
              +--------------------------------------+
              | HOW TO WRITE GOOD TEXTUAL ADVENTURES | 
              +--------------------------------------+
              |     (supported with C routines)      |
              +--------------------------------------+

by	ELDER GoDS SHRiNE, thatis

		The Lands of Torment PBeM
 +.oO -------------------------------------------------------------- Oo. +
 |      vkrstul@public.srce.hr                  Chthon                   |
 |                                          the GameMaster of            |
 |  http://jagor.srce.hr/~vkrstul              the Lands of Torment      |
 |                                                  PBeM game            |
 |                                                                       |
 |  .!! Eight years of Interactive Fiction gaming experience !!.         |
 +.oO -------------------------------------------------------------- Oo. +


---------------------------------------------------------------------------
---------------------------------------------------------------------------
This text is about overall coding, but with examples in C. To understand
it one must know programming either in Basic, or in Pascal or C. ASM is cool
too, but I don't know anyone who wrote an IF in assembler. :)
If anybody writes a decent textual adventure, please send me a copy! 
All the code here is either pseudo code or C, but understandable to non-C
programmers.

CONTENTS:
        1. ABOUT GAME STRUCTURE AND OBJECT CODING
        2. MOVING IN THE GAME
        3. HANDLING OBJECTS IN THE GAME 
        4. HANDLING CHARACTERS
        5. READING PLAYER'S INPUT LINE
        6. HOW TO MAKE A SAVEGAME
        7. A GOOD STORY


Who remembers these adventures now??
We all know of DOOM and FRP games, who is talking about textual adventures? 
Well, although today ALL the games include graphics, some of us (including
even me) have started with ATARI or SPECTRUM and well remember textual 
adventures in those days. Some of us still love this kind of game, so though
nobody is coding them, we would like to learn programming it.

Another thing.....many of you will rather use Inform or TADS utility to make
an IF game. That's c00l! But can you make MUDs in these two programs? I don't
think so. And you can't include any eventual graphics in your Inform or TADS
code, as far as I know...

*****************************************************************************
1.      ABOUT GAME STRUCTURE AND OBJECT CODING
*****************************************************************************

  If you want to write a good adventure, you must first have the scenario 
prepared and all the maps etc... When you have scenario and maps worked out
the next step is to prepare the game to be converted into code. This
includes making a list of all variables used in the game, and a list of 
functions that work out the game. So make the PSEUDO CODE first!
The best language for making these kind of games is C.
It supports object programming, e.g structures 'player', 'monster'
that contain all data that describe the player or monster etc. like it's
health, strenght, ... , and here is the example:

struct Player
{
        char[15] Name;   // Player's name
        char Strenght,   // Player's strenght, max. 255
             Health,     // Player's health, max. 255
             Magic,      // Player's magic, max. 255
             Inv;        // Player's inventory 
        char *Inventory[5]; // Array of objects in player's inventory
        int  Gp;         // Gold pieces, max. 65535
        ...
}

To have a good control over the program's source code, you must use objects
as structures or classes (classes only in C++). e.g it is good that all the
humans (monsters, orcs, demons ...) are represented by structures. If you 
present it with class, it is good to define the functions that manipulate
with that class, but I suggest you use structures rather than classes. It does
the same thing like classes, and is much more easier to handle and write!

Beside the humans (monsters, orcs, demons...) you can use structures on 
other things, even on the doors:

struct Door
{
        int  Room;      // In which room ?
        char Status;    // Opened? Closed? Destroyed?
        char Color;     // Red? Green? 
        char Material;  // Wooden? Iron?
        ...
}

NOTE: Use the structures only on objects that are defined with more than one
value. So you won't use structure on object (e.g tree) UNLESS you want to do
something with that tree. If you need ONLY STATUS of that tree you can use one
variable e.g. char TreeStatus which can be for example: (flag)
1 for cut
2 for burnt
3 for sold and so on
You can also use array of TreeStatus which has status of several trees:

TreeStatus[1] e.g. the tree in the backyard
TreeStatus[2] e.g. the tree behind the castle
TreeStatus[3] e.g. the tree in the center of the forest ...

BUT IF YOUR TREE speaks, and has it's name, and there are more trees like this
create a structure:

struct Tree
{
        char Name[10];
        char Health;
        ...
        char *LifeStory= "I was born....My mother......";
        char MagickLevel;
	...
}

I supposed no comments needed here...

  After all the objects in game are defined, it is good to write their
description before coding. After this is done you can begin coding it.
  
*****************************************************************************
2.      MOVING IN THE GAME
*****************************************************************************

  Now we are facing the problem of how to move through the rooms of our 
adventure...
Someone says "O.K. So what? I will code each room for itself!". And then he
writes the whole program for each room, each room has own orders and own
variables...That's fine. But suppose you have 100 rooms. Will you code each 
room for itself like:

BedRoom:
        ...
        if (direction == NORTH)
                printf ("You can't go that way.");
        if (direction == SOUTH)
                goto Kitchen;
        
        ...

goto BedRoom;
Kitchen:
        ...
        if (direction == NORTH)
                goto BedRoom;

        ...

goto Kitchen;

This assumes that you have all the stuff written in each the room. In this case
your program will have a billion lines if you have for example 100 rooms, 50
verbs, 100 nouns, etc. 
You will die after one room coded, and now imagine 100 rooms. 
THIS METHOD IS WRONG !!! You have to code it like you have only one room and 
move within variable 'position' which says in which room you
are. Let's say this are all the rooms in the game:

                        North
        
                  _____________________
                  |1        |2        |
                  | Kitchen | Bedroom |
    West          |---------+---------|         East
                  |3        |4        |
                  | Hall    | Garden  |
                  |-------------------|  

                        South

The rooms are presented BY NUMBERS 1, 2, 3, 4. If you are in the kitchen, 
the variable 'position' is 1 (position = 1). How to move from one room to 
another? Simple. Define a structure 'Direction':

struct Direction  // Make it all chars if you have max. 255 rooms
{
        char n; // north
        char s; // south
        char e; // east
        char w; // west

// You can put even northeast, northwest... up, down...

}

NOW define an ARRAY 'Rooms'. You have 4 rooms and 4 directions to go, you don't
have 0th room so you define it as 5 rooms because 0th does not exist but IS
a member of array Rooms (That's the way it is!).

//                          n, s, e, w

struct Direction Rooms[]= { 0, 0, 0, 0,  // 0th room    
                            0, 3, 2, 0,  // 1st is kitchen
                            0, 4, 0, 1,  // 2nd is bedroom
                            1, 0, 4, 0,  // 3rd is hall
                            2, 0, 0, 3   // 4th is garden
                          };

UNDERSTAND ????? NO ???????? Then write to my e-mail address....

As you have seen if you are in kitchen (1) and you go east, you come into room
2 and that is the bedroom. Got it now ?? "And what now?" you ask. Well now
you must convert this into code (C): 

position = 1; // You are in kitchen

... // The player has entered a line, e.g '> Go north' or '> n'

The variable DIR has to be set to 1 (north): 

(PSEUDO CODE)
if ( Rooms[DIR] == 0 ) 
        then print "You can't go there"
else
        position = Rooms[DIR];
Endif

Got it now ??? No ??? Contact me...

To make the code easier to understand you can have functions for each direction.
For example direction north has function n_() and if player wishes to go
north call the function n_();
(about converting lines like 'get the key' into language understandable to 
computer, we will discuss later!)

var 'position' is the current position in the game, player wants to go north so
the prog called func n_():

(C CODE)
void n_()
{
        if ( Rooms[ position ].n == 0)
        {
                printf ("You can't go that way");
                return;
        }
        
        ...

        position = Rooms[ position ].n; // new position
}

Make the same for the other directions.
Now you call a function e.g. Events() to see if anything happens if player
comes to this room. This way you can have thousands of rooms and your code will
not increase much. 

*****************************************************************************
3.      HANDLING OBJECTS IN THE GAME
*****************************************************************************

  By 'objects' we assume all the objects that player can take or do something
else with them. Let's say that we have house with ten rooms and all kinds of
objects all over the house. The objects are numbered just as rooms are and
also have their description:

char objects[]= {"", "a golden key", "a sword", ...};

How do we know where are the objects?

char object_pos[]= {0, 1, 5, ...};

In this case the key is in room 1, and the sword in room 5. And that is it.
Other positions like in pocket, or in chest can be numbered as room, but
with numbers that you define, e.g if a key is in a chest, it would be:

char object_pos[]= {0, 255, 5, ...};

Here a chest is defined as 255, a pocket can be defined as 254 and so on. When
the player is carrying the object, it's position can be 0, or -1...
If you like you can use structures, which is recommended:

struct object
{
        char Name[15]; // e.g "a golden key"
        char Desc[];   // e.g "A golden key looks like a knife"
        int  Pos;      // it's position, can be also char if you have max. 
                          255 rooms
        char Weight;   // it's weight
        ...
}

and then

struct object Object[10]; // Let's suppose you have 10 objects in that house

WARNING: Watch out if the object is in the room or in the player's possesion 
         when handling it!

See chapter 5. to see about recognising objects...

*****************************************************************************
4.      HANDLING CHARACTERS
*****************************************************************************

  The characters can be handled like objects with no difference: with arrays
or with structures in the same way as objects. 

See chapter 1. for more details and chapter 5. for recognising characters


*****************************************************************************
5.      READING PLAYER'S INPUT LINE
*****************************************************************************

   Reading player's input line and converting it to computer understandable 
language is difficult. You have to parse the line into separate words so you
can define which word is noun, verb, adjective... When player inputs a line it
MUST have the structure like this:

   VERB ARTICLE ADJECTIVE NOUN     ( Get the golden key )
or VERB ARTICLE NOUN               ( Get the key )
or VERB NOUN                       ( Get key )
or VERB ADJECTIVE NOUN             ( Get golden key )

 As you see, the verb is at first place so this would be no problem. But the 
program must also be aware of difference between e.g. 'look' and 'look the key'
becouse first gives description of the room, and second of the key. The program
must also accept lines like 'look the room' or 'look around' as one and the
same order.
 The game will be good if you program it to recognise complicated lines like
'get the golden sword and kill the monster'. The best way to solve it would be
to seperate the line in two lines as independent and execute them one by one. 
In this case the program has to execute first line ( get the sword ) and then
second (kill the monster), and then continue with the program which includes
checking if anything happens when player kills the monster. Of course to 
execute the first and second line all conditions must be fulfilled as in this
case they are: the sword must be in the room or in player's inventory, the
monster must be in the room, and eventualy the player must have needed 
strenght to swing the sword and so on...
  How to recognise the words? First the line must be parsed into words (there
is a routine for that at end of the chapter). So we have an array of words:

> get the key

words[1]= get
words[2]= the
words[3]= key
 
Now we must check each word to see what is verb, noun, adjective... As we 
already know, the verb MUST be first, so words[1] is always a verb. The
question is which is noun, adjective... Here are the four possible positions
of the words, within the player's sentence:

   VERB ARTICLE ADJECTIVE NOUN     ( Get the golden key )
or VERB ARTICLE NOUN               ( Get the key )
or VERB NOUN                       ( Get key )
pr VERB ADJECTIVE NOUN             ( Get golden key )

You can also have adverbs and prepositions that you must include in your
word scanner.

   ( Put the golden key on the desk )
   ( Put the golden key on desk )
   ( Put the golden key on the wooden desk )
   ( Put the golden key on desk )
   ( Put the key on desk )
    
      etc...

If we have complicated line like get the key AND unlock the door, AND is just
a limit of first line and begginig of second, and this will be parsed like:

          1   2   3     
1. line> get the key

           1     2   3 
2. line> unlock the door

So we scan the words like this, WITHOUT THE ADVERBS AND PREPOSITIONS:

1st. word is verb.
2nd. word: is it article| (yes): word 2 is article
                        | (no):  is it adjective| (yes): word 2 is adjective
                                               | (no): is it noun| (yes): word 2
                                                                       is noun
                                                                | (no):  cannot
                                                                   recognise
                                                                   the word!
3rd. word: if (word 2 is article)
             then is it adjective| (yes): word 3 is adjective
                                 | (no): is it noun| (yes): word 3 is noun
                                                   | (no):  cannot recognise
                                                            the word!
                  is it noun| (yes): then word 3 is noun
                            | (no): then cannot recognise the word !

4. word: if it is not the noun then cannot recognise the word!
                
If a word cannot be recognised there are several reasons for that. First one
is that the word does not exist in the game, so the message would be
"I don't understand you!". Other reason is that player did  enter the sentence
like "get the golden". Here we have a verb, article and adjective but no noun,
so the message would be "Please be more specific!" If there is no verb there is
no use to check other words. The message here is clear. 
   The parser at the end of this chapter returns array of words cut out from
the line, so the line can be "    get      the  golden         key", and the
routine will return the array like this:

words[1]= "get"
words[2]= "the"
words[3]= "golden"
words[4]= "key"


   Now when we have defined which word is what, we must convert it to program
understandable language. We will convert the words into numbers while scanning
which word is what. Suppose we have an array of verbs:

char Verb[]= {"", "GET", "PUT", ... };

While scanning which word is what, when we recognise a verb we compare it with
the array like this:
        
        for (i= 0; i< number_of_verbs; i++)
                if (words[1] == Verb[i])
                        verb_number= i;
        
So if the word is "put" the verb_number would be 2 ! We do the same to the 
nouns, articles, adjectives, adverbs, prepositions and so on...                         
And further in the program, in function e.g. get() which is called if the
verb is 'get' we will work with noun by numbers!

NOTE: To make it easier, order of the nouns must be the same as the order of
      the objects, so we can write for example:
                
                object_pos[ noun_number ] = 0;

when player wants to get something;     

----------------------------
A ROUTINE FOR PARSING WORDS:

A routine for parsing words is enargv( string ) which calls routine
word_parse() that is of no interest to us. Parameter 'string' is a line that
player has entered, for example: 

char *string;

gets ( string );
enargv ( string );

There MUST BE also DECLARED two global variables:

char *globargv[];   // array of words     (words[])
int globargc;       // number of elements in globargv

THE ROUTINE:

void enargv (char *buf);
char *word_parse (char *line, char *word, int delim);

void enargv( char *buf )
{
        char *bufptr;
        char pbuf[50];
        globargc=0;
        bufptr=buf;
        while (  bufptr=word_parse( bufptr,pbuf,0)  )
        {
                globargv[ globargc ]= malloc( strlen(pbuf)+1 );
                strcpy ( globargv[ globargc++ ],pbuf );
        }
        globargv[ globargc ]=NULL;
}
char *word_parse( char *line, char *word, int delim )
{
        int quot=0;
        while ( *line && (isspace (*line) || *line==delim) )
                line++;
        if ( *line=='\n' )
                line++;
        if ( !*line )
        {
                *word='\0';
                return ( 0 );
        }
        while ( *line )
        {
                if ( !quot && (*line=='\"' || *line=='\'') )
                        quot=*line++;
                if ( (isspace(*line) || *line==delim) && !quot )
                        break;
                else
                        if ( quot && *line==quot )
                        {
                                quot=0;
                                line++;
                        }
                        else
                                *word++=*line++;
        }
        *word='\0';
return ( line );
}




*****************************************************************************
6.      HOW TO MAKE A SAVEGAME
*****************************************************************************

 Very easy. Open a file ( e.g "save001.dat" ) and put these variables in it:

position,
structures of player and other characters,
all other structures or variables that are changeable through the game except
the game controling variables like last word entered, ...

*****************************************************************************
7.      A GOOD STORY
*****************************************************************************

  Making a good story is question of your creating abilities. It is like 
writing a book, a book where the player is the main character (an interactive
book). It can happen anywhere and anytime, from the very beggining of the world
to late year 1201938 a.c ... When making a story be sure not to use too many
traps because the player would become frustrated. On the other hand not too
easy because the player would become boring. Make it NONLINEAR which means that
there are several ways to finish the game. For example the player can kill the
evil magician with sword, or making a trap for him, or paying somebody
else to kill it, which depends on player's intelligence. The game needs to
have a whole palette of possible ways to finish it, from the way which needs
small intelligence to ways that expect hot brains. 
  Make the messages interesting, make several of them for one thing and choose
them randomly, for example the player wants to open a locked gate, choose one
of theese messages:

        "You pull, push, hit and yell on it, but the gate seems to be locked."
        "You examine the gate from all sides finding it locked."
        "The gate suddenly speaks: I am locked you cretin!"

instead of the "It is locked.". When a glass falls on the floor don't type
"The glass has broken." but use something like "Touching the ground the glass
breaks into millions of pieces...". I have seen a very good story in a game 
called

        "The Guild of Thieves" (c)

which is very nonlinear and interesting. 

REMEMBER: The more words you use the game is more interesting, and that 
          is also for the events. Make it that ALL the objects in the game
          can be moved or breaked, even the walls. Make it that if player
          uses a hand grenade, it can destroy almost everything...Yeah,
	  this asks for intensive coding for a whole month! So what? I used
	  to write my games for a whole year!

At the end of this file, I wish you good luck, but you MUST send me a copy
of what you have done....


                "For he who slayeth the dragon shall win the sword"

						Chthon.....
