Final Project, CS257

Due Thurs May 6, 1999
(but early submissions will be appreciated)
Beware of mathematicians and all those who make empty prophecies. The danger already exists that the mathematicians have made covenant with the devil to darken the spirit and to confine man in the bonds of hell.
-St. Augustine
Your final project is to write the ``guts'' of an adventure game. The interface between your innards and the user will be handled by code we provide, but you are responsible for the fun part.

Sample Interaction

Here is a sample interaction of a player with the system, with player input in boldface.

player: invent

You are holding
 1. a bucket of water
 2. an intricate key
 3. a portable thermonuclear warhead

player: look

You are in a tall room with high doors to the east and north.  At the
front of the room a small bald professor is using an enormous laptop
computer.

You could pick up:
 1. a textbook
 2. an orange

player: get 2

Got it.

player: invent

You are holding
 1. a bucket of water
 2. an intricate key
 3. a portable thermonuclear warhead
 4. an orange

player: use 4

Mmm that hit the spot.

player: use 1

Glug glug glug.

player: invent

You are holding
 1. an intricate key
 2. a portable thermonuclear warhead
 3. an empty bucket

player: north

You are now in ....

Behind the scenes

The way the system works is primarily through an object called the ``current state'' of the game. State-changing actions occur via messages being sent to this object, and its returning a ``new state.'' The object-system interface uses the function bsend as defined in the file bsend.scm, which is the same object system used in class for complex numbers and such, except renamed bsend so as not to step on the MzScheme object system's native send macro.

You are to provide a file adventure.scm which defines a global variable initial-state. This is the state the game starts out in. Each time the player types something, messages are sent to the ``current state'' whose meaning is defined below.

You should load adventure-io to get the adventure-playing shell that talks to your code.

moving and looking around

These are the messages related to basic motion and looking around.

(bsend state 'look), sent to the current state, returns a description of the current situation, eg a view of the room the player is in. This can be either a long string (including carriage returns) or a list of words or a list of lists of words, which will be printed as sentences one per line.

(bsend state 'lookg), returns a ``graphic object'' which is a picture of the current room. Aim for 300x300 in size. The picture should sit above and to the right of the initial drawing point. (bsend state 'go direction), returns the world state resulting from the player having tried to move in direction direction. (The possible directions should normally be obvious from ``look''ing at the current state. You can overload this by handling directions that are not really directions, eg bathroom which doesn't actually go anywhere but makes the room smelly, or pull for pulling a lever set into the floor.

(bsend state 'message), returns a string or list of words or list of etc, which should be given to the user after his last action. (Or #f for no message.)

movable objects

The following all have to do with picking stuff up and putting it down and looking at it.

(bsend state 'pick-up-able), returns a list of ``movable objects'' which the player could potentially try to pick up right now.

(bsend state 'inventory), returns a list of ``movable objects'' which the player is currently carrying.

(bsend state 'pickup movable-object), This returns a new state, which is the state resulting after the player tries to pick up the given object in the current state.

(bsend state 'drop movable-object), This returns a new state, which is the state resulting after the player tries to drop the given object in the current state.

(bsend state 'use movable-object), returns the new world state resulting from the player using the given object in the current state. (The user interface will only let the object to be used be something the player is carrying, but you can use go messages for other kinds of actions.)

The ``movable object'' things refered to above themselves obey a protocol.

(bsend movable-object 'name), returns a brief description of an object, eg "An orange"

(bsend movable-object 'graphic), returns a picture of the object, as a graphic thingie. Aim for a size of about 75x75. The picture should sit above and to the right of the initial drawing point.

Some examples

(bsend (bsend initial-state 'use thermonuclear-bomb) 'message) might return "Boom!"

(bsend (bsend initial-state 'use thermonuclear-bomb) 'look) might return "You are in a devastated post-nuclear wasteland. You see an eerie green glow on the southern horizon."

Caveats

Do not use side effects in your code, no matter how tempting. For one thing, they would break the save/restore commands.

If you do not have your graphics stuff working,
(set! adventure-enable-graphics #f)
will disable graphic objects in the I/O shell.

Hints

It might be useful for your objects to accept messages not described above. For instance, if you want to prevent the player from picking up too much stuff, you might want the movable objects to take a weight message.

If you have lots of objects in lots of rooms, an association list mapping rooms to lists of objects currently in them might be useful.

You might want to define other kinds of objects for your own internal use, eg rooms which respond to some messages, like maybe each knowing a association list mapping ``go'' actions to destination.

After the user does an illegal action (like moving in an impossible direction) you'll want to make sure the resulting world state has a cogent response to the message message, like "You can't use the kitten" or "You can't scramble up the cliff" or (cannot go blibbledy).

Don't get caught up in formatting output messages. Better to improve the game itself, your players won't mind if the descriptions are formatted strangely. Concentrate on the play itself.

Careful use of delegation, and careful system design prior to implementation, and sitting back every once in a while to see if you should rewrite or rething parts of what you have can buy you a lot.

Don't be afraid to ask the TAs for help, escpecially in getting started.

You are strongly encouraged to work in teams! Trust me on this one, it'll be a lot more fun!

Driver and Sample Games

The driver that your code is the back end to is adventure-io.scm. To test your code, first load bsend.scm, then adventure-io.scm, then your own file, then evaluate (adventure).

Some sample games are available here. If you come up with some particularly clever technique which you'd like to share with others, I'd be happy to put more code samples here.
adventure-cyanide.scm
adventure-recurse.scm
adventure-workday.scm
adventure-workday2.scm
adventure-workday3.scm
Other files:
adventure-io.scm
bsend.scm
no-plumber.scm

Size

Basically, we are aiming for a measure of complexity and coolness and effort here. Roughly, you should have at least
20 rooms
10 objects
lots of fun
but if some aspects of your adventure game are more complicated, you can skimp on others. Eg as a degenerate case, if you have super-cool places and actions, you could have no movable objects at all.

Team projects should be proportionally cooler, not just in gross measures like the above but also in internal complexity and cleverness.

Submission

Turn this in using the usual handin program. (Obviously there is no test suite.)
Barak Pearlmutter <bap@cs.unm.edu>