Text adventure design.

Started by
10 comments, last by Jompe71 14 years, 7 months ago
Hi, I'm thinking on creating a remake of an old C64 "text adventure" game for 2 other platforms. User input in the old game is mostly (if not always) a 2 word command, ex: "open door", "climb up", "pull lever" etc. I was thinking of creating a dictionary for all words acceptable but my main concern is to handle the user input. Is there any "common" or smart way of mapping user command to code action. Lets say user is on a certain location in the adventure and there is an item on the floor. In this location giving the command "use item" is valid and shall respond in an action. Thus this command is only valid if it was entered after "pickup item". Next thing is how to map commands into code calls. The variation of commands only used for one purpose and at one location at a certain time responding in only one result is probably very large. I would like to avoid to create one method for each available and valid command. If any of you have valuable input or perhaps links to resources I'd be glad. Note that one of the platforms uses old Java so I seem to have to go without script support which could have made things easier. ;/
Advertisement
Well from the examples given the first word is always a command and the second a parameter.

You could simply have your game check the first word to see if it is a valid command and then if it is use the given parameter to work with it.

"In this location giving the command "use item" is valid and shall respond in an action. Thus this command is only valid if it was entered after "pickup item""

I'm not sure I understand this correctly but couldn't you just give the user an "inventory" and have it so that "use item" will only work if the item is in the user's inventory. "pickup item" could be use to add the item to the user's inventory.

I don't see why you want to avoid creating a method for each possible command. For each location you can attach a list of valid commands which are associated with a function pointer or equivalent so that your command parser can directly call the command's function.

I couldn't make a lot of sense out of your post so sorry if that is all useless to you =/
It's not a bug... it's a feature!
Dom_152 has the right approach to "use" versus "get" or "pickup."

An approach that I took many years ago (don't ask how many) is to store information about each item. Then have a function for each way any item can be used and let the item decide. You can use a class for each item or (the old old way to do it), store a "use" function pointer for each item and dispatch execution to that function. An item would also have a location, either in the "map" or in the inventory.

Each item could also have attributes: useable, openable, pullable, etc. They can be set and tested as a single bit.

For instance:

"Get" item: is the item in this location? If yes, AddToInventory(item). If no, "There is no <item> here."

"Use" item: is the item in Inventory? If no, "You don't have <item>." If yes, item->UseYourself().

"Open" item: is item openable?

"Move" direction {up,down,left,right,etc.} : Check the map. Is there a <direction> here?

If you don't want to use function pointers (which gets sort of complicated), you'll probably have to use dispatch tables. And, yes, they'll be big.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Thx for the input guys, sorry for not beeing albe to express myself 100%.

Quote: "Dom_152"
I'm not sure I understand this correctly but couldn't you just give the user an "inventory" and have it so that "use item" will only work if the item is in the user's inventory

Well there might be more to it than just the inventory issue. It's all about some commands are only valid if other commands have been executed before.
Example: You cannot lit the torch if you haven't executed the command "look wall" which reveiled the feedback "There is an unlit torch attached here..." ;)

Function pointers are out since it's Java. Thus reflection could be used...
You both have good issues with having lists of stuff to pick up attached to the players inventory as well as for every room in the map. It makes pickup/drop stuff easier as well as saving game states.

Quote "Buckeye":
store a "use" function pointer for each item and dispatch execution to that function

Perhaps not bad at all. Keeps spreading logic out into classes where it belongs(might try it).

My thought at the moment is to use some kind of "command-tree" which upon executing a user command takes the current room and inventory etc as arguments.
My hope with the tree was to somehow be able to combine commands which are similar like "get item"/"pickup item"/"fetch item" etc.

I also really wanna come up with some scripting syntax which I can share for save games as well as the inital game setup as for where items are located, visibillity, directions etc. Since I'm gonna use a VM which requires a small footprint I'm thinking of JSON which goes well with Java.

Again, thx for the input and sorry for the poor english.
(Suppose this is of no interest but I'm aiming for the Android and BD-J platforms ;) )
I think a "command tree" might be a good idea in this case.

The system will start at root and iterate through the tree and checks the input against all the "activated" commands. Once a command is executed it's sub commands becomes activated so they can be used in the correct order.
It's not a bug... it's a feature!
Sorry for bringing life to such an old thread, but I need comments on my ideas.

Soon I'll be having the main engine for the text adventure up and running. using JSON as data format turned out to be more profitable than expected, beats the crap out of XML in turns of devloping process speed and general visuallity.
At the moment I have a few hundred lines of code and have the functionallity of walking, picking up stuff, dropping of, command interpeter, response handler, command aliases, rule handling etc. Extreemly flexible and reusable for other games (This one is just a C64 remake).

Next question (going ahead of development and assuming future luck in engine progress) is how to handle the memory issue using a platform which requires a small footprint.

Fact: I can't load the entire map/world into memory at once.
1st thought: Load only the current map location and always save the last visited location as a temporary serialization of it's current state to disc.

This sounds good when having autosave vs. manuall save of games in mind, just turn tmp files into regular in manual save and just save regular when auto is turned of.
Dissadvantage: Engine must ba able to query for available map directions (N, S, E, W etc.) which requires "peeking" into persisted locations i.e. disc access when loading each new location.

Fact: The game will be intended for platforms where disc access might be an issue.
1st thought: Zip! :-/

Fact: I'm new to game programming and need your expert input.
1st thought: You guys will spam me with you knowledge, even if 3D stuff is your hard-ons. My most concern is for Fact no.1

// Jompe71

I'd suggest you have a look at the Inform languge, http://www.inform-fiction.org

It is a language specialized for writing text adventures. It'll take care of all the actual handling of objects and commands.

Thx, I already did. The format looks similar to my JSON:
Snippet:
                {                    "TEXT": "YEAH RIGHT, AND ADD IT TO MY COLLECTION OF STIFFS BACK HOME?",                    "RULES": [],                    "DIRECTION": 0,                }            ],            "ERRORS": [],            "RULES": [],            "INDEX": 0        },        {            "ALIASES": [ "SEARCH BODY", "FRISK BODY", "EXAMINE BODY" ],            "RESPONSES": [                {                    "TEXT": "OK. YOU FOUND SOMETHING. WALLET.",                    "RULES": [ "$WALLET" ],                    "DIRECTION": 0                },                {                    "TEXT": "OK. YOU FOUND SOMETHING. TELEGRAM.",                    "RULES": [ "$TELEGRAM" ],                    "DIRECTION": 0                },                   {                    "TEXT": "HMMM... THE CHEAP BASTARD KEPT NOTHING ELSE USEFUL ON HIM.",                    "RULES": [],                    "DIRECTION": 0                }            ],            "ERRORS": [],            "RULES": [],            "INDEX": 0        },        {            "ALIASES": [ "DRAG BODY", "MOVE BODY", "FLIP BODY" ],            "RESPONSES": [                {                    "TEXT": "OK. THERE WAS SOMETHING UNDER IT.",


But it's not the format of the map I'm concerned about it's the interpeter. Don't know if the app is open source or what, but writing my own will serve my needs to the most I think.

Giving me the link made me more comfortable with my solution even if the Infom plaftorm might be more flexible.

One thing I could have done was to "rip" their format right off and be able to get some more solid grounds to work on. But now I already got the ball rollin' and as said if I don't know what goes on behind the sceenes of the format I'm back to square one never the less I think.

Quiz: Giving the "config" snippet above, what game am I "remaking"? ;)
Quote:Fact: I can't load the entire map/world into memory at once...
Fact: The game will be intended for platforms where disc access might be an issue.

No memory and no disk. What're you targeting, calculator watches??

Just bluesky thinking:

You might think in the direction of dividing up the map into sections (like you haven't thought of that) like an octree (if it's a 3D map) or quadtree. Load the section of the map within a certain number of nodes of the current location. That would help if the user is exploring a limited area.

If the user has to backtrack ("You forgot to pick up the framitz back in the train station, you idiot!"), it'll be sort of grueling. That would probably occur in any case. Or, design the map to limit the need for long treks between stops to explore - make it difficult to progress without having the right items or knowledge.

EDIT: If you're really serious about memory limitations, the old PDP-8 (or some DEC machine, if I remember correctly) used a text packing method. If you can limit yourself to 32 characters (5 bits) for your text, you can pack 3 characters into 16 bits, a savings of over 30% if you're using 1 byte/character. [WINK] Bit-shifting and masking are quick operations. With a text adventure, I can't imagine performance being an issue anyway.

EDIT2: If you want to use a text packing method and you need more than 31 characters (I know I said 32 but you have to have a stop character), you can also use something like RTTY (I used to be a ham radio operator). Besides 26 alphabet characters, a couple of the "extra" 5 characters can be "shift" characters - something like "change to character set 2" or "change to numbers," etc. Depends on how serious you are about considering code to be cheaper than data.



[Edited by - Buckeye on August 26, 2009 4:18:51 PM]

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I just wanted to point out that someone has written (or was writing some time ago) an Android port of a z-code interpreter (used by the Zork series). It could probably be Googled, I can't remember if its open source or not, but it may give you some platform-specific ideas (personally, I know nothing about the systems you are targeting).

Interestingly, I did write a simple rpg/text adventure game on a C64 many years ago. In basic. I don't remember the details of project, but I also don't remember even coming close to the limits of that machine. I can't imagine a platform so limited in memory that you can only have 1 'room' loaded at a time. Are you sure you need to optimize so heavily?

P.S. Reading some example source code in Inform 7 is an interesting experience. Finally, a natural language programming language! That is, until I saw the hideous source code for the fixed math extensions...

This topic is closed to new replies.

Advertisement