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.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
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 ....
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.
(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.)
(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.
(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."
If you do not have your graphics stuff working,
(set! adventure-enable-graphics #f)
will disable graphic objects in the I/O shell.
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!
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
20 roomsbut 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.
10 objects
lots of fun
Team projects should be proportionally cooler, not just in gross measures like the above but also in internal complexity and cleverness.