Magazine: Ahoy! Issue No.: 55 Date: July 1988 Pages: 13-14 Transcribed by Patrick Kellum -------------------------- PROGRAMMING YOUR OWN TEXT GAMES Part II of III: Think Modules By Cleveland M. Blakemore Ingenuity lies not in further complicating definitions and concepts, but in reducing the number of contradictions and terms to the fewest possible true sets. Any given system design must begin with the sum of its parts, and then define these parts.    This is the essential theory behind "black box" system design, or modular programming. We begin by describing what we want the system to do, then breaking this down into the necessary steps to accomplish it. Whether you are pursuing a personal goal or creating a computer program, you will find that this approach is always the most effective.    Last month we published a short text adventure called Lost Dutchman's Mine. In this installment we will examine this program in detail and demonstrate how a series of modules (or subroutines) can be tied together into one cohesive system that is greater than the sum of its parts. None of the routines by themselves would constitute a game - but working in tandem, they create an interactive adventure.    If we wanted to describe the player's purpose in Lost Dutchman's Mine in one sentence, we could say:    "To move around within a network of locations, collect various objects, return them to a specific location, and win the game."    This is the simplest way to define the program's operation. In last month's column, I advised designing your adventure on three seperate pieces of paper before touching the keyboard. Page one of my scenario for Lost Dutchman's Mine read like this:    "The object of the game is to wander around within a series of caves, collecting up three treasures as you go. When you have all three objects, you return them to a specific base location, drop them, and win the game."    On page two I listed the obstacles I wanted to hamper the player's efforts:    "1. A timber woolf guards the entrance to a burial mound where one of the treasures is buried. The player must find the gun and bullets to kill the wolf.    "2. A secret word is required to pass from the base location to the caverns. (Kind of like PLUGH in Colossal Caves.) The secret word is written inside a matchbook cover.     "3. A whistling spirit guards the entrance to the caverns. The player must blow on an empty 7-UP bottle to scare the spirit away.    "4. The burial mound is submerged under water. The player must find and open a reservoir lock through which the mound room can be drained.    "5. A shovel is needed to dig up the third treasure (Dutchman's nugget).    "6. The player must also light a torch, drop enough equipment to fit through a narrow crack, and escape from the room after he opens the reservoir lock."    You may have noticed that a lot of these ideas are taken from other adventure games, many of them classic puzzles. I wanted them to be familiar enough that the game could be solved without too much trouble. I could just as easily have made the game much harder.    On the third and final page, I drew a map detailing all nine locations in the game, complete with references to the objects that would be found there, and the puzzles specific to those spots.    Using the modular approach, I broke the program down into seven discrete boxes. * Initialize arrays and variables * Read in data * Get command * Find verb in command * Find noun in command (if any) * GOSUB to appropriate subroutine pertaining to verb * Data lines    Modules 3, 4, and 5 could all be considered part of the parser, the routine that gets and analyzes player input. I define them seperately here to make clear what goes on inside the routine.    The first thing I typed in, as always, were lines 1530-1610. These lines contain descriptions of the nine locations in the game. I immediately followed with comments to accompany each, in lines 1630-1670. These commonts are specific observations in each location. For example, the gas station has a "metal plaque above a glass shelf." Then, using the third page of my notes (the map) as a guide, I typed in the data for an array of nine dimensions, each dimension having six elements. This dimension will be known as D(9,6). The six elements consist of the directions North, South, East, West, Up, and Down. This is a numerical array, and the number in each element indicates the location to which that direction connects. Any non-zero number is a pathway; otherwise there is no exit in that direction. I did not type in directions for the gas station, because it is only accessible by use of the formentioned "magic word."    In the fashion of any sensible hacker, I jumped to lines 120 through 210 and designed a data loader. Once I made sure that the arrays were dimensioned properly in line 120, I read them in a couple times in lines 190 and 210 just to make sure everything was going smoothly before I continued. This type-n-run approach is the hacking method, and it works. Trust me.    Now for the tough part. I had to figure out all the verbs and nouns that would be needed for the parser's vocabulary. In lines 1800-1850 I tried to give the program a reasonable dictionary of words to work with for player input. An advanced parser would recognize far, far more then this simple collection of words.    Again, I skipped back to the beginning and made sure these strings loaded in correctly before going on.    Lines 1870 through 1900 are detailed descriptions of the objects that can be carried in the player's inventory. Although an object might be referenced by the parser as "diamo," it will be described on the screen as a "glowing diamond." This gives character and atmosphere to the adventure.    Line 1920 is a list of numbers that tells the program where to place objects initially. The first number indicates the location, the second is the object number itself in the inventory.The -1, -1 at the end of the line signals the end of the data.    Lines 1940-1970 are end of game messages, for when the player is killed or is victorious. If the player is killed, these lines help tell him where he made his mistake.    With this, I completed the data lines, the major stumbling block of any adventure game. Although I made many changes afterwards and altered these lines considerably before finishing, these lines gave me something to work with, the meat of the text adventure.The remaining program portions manipulate the data loaded in from here in many ways, but it is in these lines that the game gets its substance.    Important variables to be defined are CL(Current Location) and the arrays O(9,8) and I(8). The former is an array that tells what objects are in what rooms, and the latter is the player's inventory array.I(8) refers directly to the eight objects listed in line 1840, the objects in the game which can be carried. Any non-zero number in element I(1), for example, would indicate that the player is carrying the torch. However, a -1 would mean the torch is burning, while a 1 would mean it is out. I also set up meaningful flag names in line 150. These flags indicate the status of certain items.    In lines 340-540, I fleshed out the parser routines.First the directions, then once the program is recognizing them correctly and responding, I introduce the other verbs. It is better to make sure that all directions are functiong correctly first before continuing, because a flaw that shows up later might take a lot of work to repair.Make certain that the directions in the game correspond indentically to your map. It is very common to make errors here. I often get East and West mixed up while typing them in.    Line 340 gets the player's input. If he enters nothing, the program checks again. Line 370 checks for a single character input (either a direction or the letter "i" for inventory) and acts accordingly. Since the six compass directions match up with the six single character commands perfectly, I just reduced any of these terms to a number between 1 and 6, subtracting 7 if necessary. I can then use this number to reference the corresponding element in direction array D(9,6). Once a match is found for the verb, the number is placed in the variable V.    The verb is the important part. We use the verb to jump to the subroutine that designates the action, so we must have a verb. The noun, on the other hand, is not always necessary for many actions, and so our parser only looks for it. If it finds one, it places the number of the noun into the variable Nbefore branching off to our routine. The subroutine can then check this variable to see if the player is referencing the correct object.For example, if the player gives the command to dig, we check the variable N to determine whether or not he wants to dig in any particular spot, as in DIG MOUND. If N=0, we simply print a standardized message that reads "YOU DIG FOR A WHILE BUT YOU DON'T FIND ANYTHING."    After the parser has both these variables, V and N, assigned with values, it drops through to lines 570-580, the branches. These lines will steer the program flow into the correct verb actions that alter program variables and the game environment.    These lines run from 700-1520, accomplishing every possible action that the player is permitted to take in our adventure.If you study them carefully, the variables are self-explanatory and it should be readily apparent that they act on values to change location inventory, specific flags (mound full-empty, wolf dead-alive, etc.), and print messages for the player's benefit.    After program flow returns from these subroutines, the main parser program executes a series of critical checks in lines 600-690. These flags count elapsed time in the current location and check on the player's status relative to certain non-player characters and events. For example, if the player is in room 4 for more than four turns with the spirit, he is going to get it good. The same goes for being in a river full of water too long or beside a hungry wolf.    The check for a win is in line 600. This line checks if a variable called WINGAME has been set yet by the drop subroutine. If the player drops all three treasures in location zero, this flag will be set upon returning from the routine, telling the main program that the player has succeeded.    With as little work as all this, an adventure game was born. We have a full-fledged story, with a plot, characters, and suspense. Next month, we'll go over the specifics of the way the parser functions, and methods we could use to upgrade the routine so that it could recognize complete sentences.    Until then, remember - stop wrestling with the program as a whole and break it down into modules. You cannot move mountains unless you do it one bucket of dirt at a time! EOF