home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Game Programming Gurus / Tricks of the Windows Game Programming Gurus (SAMS)(2000).iso / Articles / T3DCHAP15BONUS / Shadow.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-01  |  62.4 KB  |  2,255 lines

  1.  
  2. // Compile as a CONSOLE application or straight DOS16/32 application
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <fcntl.h>
  12. #include <memory.h>
  13. #include <malloc.h>
  14. #include <math.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17.  
  18. // D E F I N E S /////////////////////////////////////////////////////////////
  19.  
  20. // size of universe in blocks
  21.  
  22. #define NUM_ROWS               32
  23. #define NUM_COLUMNS            32
  24.  
  25. // id's for objects and geometry in universe
  26.  
  27. #define EMPTY_ID               ' '
  28. #define WALL_ID                '*'
  29.  
  30. #define LAMP_ID                'l'
  31. #define SANDWICH_ID            's'
  32. #define KEYS_ID                'k'
  33.  
  34. // general directions
  35.  
  36. #define EAST                   0
  37. #define WEST                   1
  38. #define NORTH                  2
  39. #define SOUTH                  3
  40.  
  41. // language details
  42.  
  43. #define MAX_TOKENS             64
  44. #define NUM_TOKENS             28
  45.  
  46. #define FIRST_WORD             0
  47. #define SECOND_WORD            1
  48. #define THIRD_WORD             2
  49. #define FOURTH_WORD            3
  50. #define FIFTH_WORD             4
  51.  
  52. #define OBJECT_START           50
  53.  
  54. #define OBJECT_LAMP            50
  55. #define OBJECT_SANDWICH        51
  56. #define OBJECT_KEYS            52
  57.  
  58. #define OBJECT_END             52
  59.  
  60. // directions (adjectives)
  61.  
  62. #define DIR_1_START            100
  63.  
  64. #define DIR_1_EAST             100
  65. #define DIR_1_WEST             101
  66. #define DIR_1_NORTH            102
  67. #define DIR_1_SOUTH            103
  68.  
  69. #define DIR_1_END              103
  70.  
  71.  
  72.  
  73. #define DIR_2_START            150
  74.  
  75. #define DIR_2_FORWARD          150
  76. #define DIR_2_BACKWARD         151
  77. #define DIR_2_RIGHT            152
  78. #define DIR_2_LEFT             153
  79.  
  80. #define DIR_2_END              153
  81.  
  82.  
  83. // define actions (verbs)
  84.  
  85. #define ACTION_START           200
  86.  
  87. #define ACTION_MOVE            200
  88. #define ACTION_TURN            201
  89. #define ACTION_SMELL           202
  90. #define ACTION_LOOK            203
  91. #define ACTION_LISTEN          204
  92. #define ACTION_PUT             205
  93. #define ACTION_GET             206
  94. #define ACTION_EAT             207
  95. #define ACTION_INVENTORY       208
  96. #define ACTION_WHERE           209
  97. #define ACTION_EXIT            210
  98.  
  99. #define ACTION_END             210
  100.  
  101. // articles
  102.  
  103. #define ART_START              300
  104.  
  105. #define ART_THE                300
  106.  
  107. #define ART_END                300
  108.  
  109. // prepositions
  110.  
  111. #define PREP_START             325
  112.  
  113. #define PREP_IN                325
  114. #define PREP_ON                326
  115. #define PREP_TO                327
  116. #define PREP_DOWN              328
  117.  
  118. #define PREP_END               328
  119.  
  120. // the phrases that add meaning to us, but not to the computer
  121.  
  122. #define PHRASE_TO              0
  123. #define PHRASE_THE             1
  124. #define PHRASE_TO_THE          2
  125. #define PHRASE_DOWN            3
  126. #define PHRASE_DOWN_THE        4
  127.  
  128. // S T R U C T U R E S ///////////////////////////////////////////////////////
  129.  
  130. // this is the structure for a single token
  131.  
  132. typedef struct token_typ
  133.         {
  134.  
  135.         char symbol[16];   // the string that represents the token
  136.         int value;         // the integer value of the token
  137.  
  138.         } token, *token_ptr;
  139.  
  140. // this is the structure used to hold a single string that is used to
  141. // describe something in the game like a smell, sight, sound...
  142.  
  143. typedef struct info_string_typ
  144.         {
  145.         char type;        // the type of info string i.e. what does it describe
  146.         char string[100]; // the actual description string
  147.  
  148.         } info_string, *info_string_ptr;
  149.  
  150. // this structure holds everything pertaining to the player
  151.  
  152. typedef struct player_typ
  153.         {
  154.         char name[16];   // name of player
  155.         int x,y;         // postion of player
  156.         int direction;   // direction of player, east,west north,south
  157.  
  158.         char inventory[8]; // objects player is holding (like pockets)
  159.         int num_objects;   // number of objects player is holding
  160.  
  161.         } player, *player_ptr;
  162.  
  163. // this structure holds an object
  164.  
  165. typedef struct object_typ
  166.         {
  167.         char thing;     // the actual object
  168.         int x,y;        // position of object in universe
  169.  
  170.         } object, *object_ptr;
  171.  
  172. // P R O T O T Y P E S //////////////////////////////////////////////////////
  173.  
  174. void Introduction();
  175.  
  176. int Vision_System(int depth,
  177.                   int direction,
  178.                   object *stuff,
  179.                   int *num_objects);
  180.  
  181. int Check_For_Phrase(int phrase,int index);
  182.  
  183. void Print_Info_Strings(info_string strings[],char where);
  184.  
  185. char *Get_Line(char *buffer);
  186.  
  187. int Get_Token(char *input,char *output,int *current_pos);
  188.  
  189. int Extract_Tokens(char *string);
  190.  
  191. void Verb_Parser(void);
  192.  
  193. int Verb_MOVE(void);
  194.  
  195. int Verb_TURN(void);
  196.  
  197. int Verb_SMELL(void);
  198.  
  199. int Verb_LOOK(void);
  200.  
  201. int Verb_LISTEN(void);
  202.  
  203. int Verb_PUT(void);
  204.  
  205. int Verb_GET(void);
  206.  
  207. int Verb_EAT(void);
  208.  
  209. int Verb_INVENTORY(void);
  210.  
  211. int Verb_EXIT(void);
  212.  
  213. int Verb_WHERE(void);
  214.  
  215. // G L O B A L S //////////////////////////////////////////////////////////////
  216.  
  217. // this is the entire "language" of the language.
  218.  
  219. token language[MAX_TOKENS] = {
  220.  
  221.  {"LAMP",      OBJECT_LAMP     },
  222.  {"SANDWICH",  OBJECT_SANDWICH },
  223.  {"KEYS",      OBJECT_KEYS     },
  224.  {"EAST",      DIR_1_EAST      },
  225.  {"WEST",      DIR_1_WEST      },
  226.  {"NORTH",     DIR_1_NORTH     },
  227.  {"SOUTH",     DIR_1_SOUTH     },
  228.  {"FORWARD",   DIR_2_FORWARD   },
  229.  {"BACKWARD",  DIR_2_BACKWARD  },
  230.  {"RIGHT",     DIR_2_RIGHT     },
  231.  {"LEFT",      DIR_2_LEFT      },
  232.  {"MOVE",      ACTION_MOVE     },
  233.  {"TURN",      ACTION_TURN     },
  234.  {"SMELL",     ACTION_SMELL    },
  235.  {"LOOK",      ACTION_LOOK     },
  236.  {"LISTEN",    ACTION_LISTEN   },
  237.  {"PUT",       ACTION_PUT      },
  238.  {"GET",       ACTION_GET      },
  239.  {"EAT",       ACTION_EAT      },
  240.  {"INVENTORY", ACTION_INVENTORY},
  241.  {"WHERE",     ACTION_WHERE    },
  242.  {"EXIT",      ACTION_EXIT     },
  243.  {"THE",       ART_THE         },
  244.  {"IN",        PREP_IN         },
  245.  {"ON",        PREP_ON         },
  246.  {"TO",        PREP_TO         },
  247.  {"DOWN",      PREP_DOWN       },
  248.  
  249. };
  250.  
  251. // now for the definition of the universe and the objects within it
  252.  
  253. // this array holds the geometry of the universe
  254.  
  255. // l - living room
  256. // b - bedroom
  257. // k - kitchen
  258. // w - washroom
  259. // h - hall way
  260. // r - restroom
  261. // e - entry way
  262. // o - office
  263.  
  264. //           ^
  265. //         NORTH
  266. //
  267. // < WEST           EAST >
  268. //
  269. //         SOUTH
  270. //           v
  271.  
  272. char *universe_geometry[NUM_ROWS]={"********************************",
  273.                                    "*lllllllll*bbbbbbbbbbbbbbbbbbbb*",
  274.                                    "*llllllllll*bbbbbbbbbbbbbbbbbbb*",
  275.                                    "*lllllllllll*bbbbbbbbbbbbbbbbbb*",
  276.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  277.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  278.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  279.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  280.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  281.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  282.                                    "*llllllllllll*bbbbbbbbbbbbbbbbb*",
  283.                                    "*llllllllllll*bbbb*rrr**********",
  284.                                    "*lllllllllllhhhhhh*rrrrrrrrrrrr*",
  285.                                    "*lllllllllllhhhhhh*rrrrrrrrrrrr*",
  286.                                    "*lllllllllhhh******rrrrrrrrrrrr*",
  287.                                    "*********hhhh*rrrrrrrrrrrrrrrrr*",
  288.                                    "*kkkkkkk*hhhh*rrrrrrrrrrrrrrrrr*",
  289.                                    "*kkkkkkk*hhhh*rrrrrrrrrrrrrrrrr*",
  290.                                    "*kkkkkkk*hhhh*rrrrrrrrrrrrrrrrr*",
  291.                                    "*kkkkkkkhhhhh*******************",
  292.                                    "*kkkkkkkhhhhhhhhhhhwwwwwwwwwwww*",
  293.                                    "*kkkkkkkhhhhhhhhhhhwwwwwwwwwwww*",
  294.                                    "*kkkkkkk*hhhhhhhhhhwwwwwwwwwwww*",
  295.                                    "*kkkkkkk*hhhh*ooooo*************",
  296.                                    "*kkkkkkk*hhhh*ooooooooooooooooo*",
  297.                                    "*kkkkkkk*hhhh*ooooooooooooooooo*",
  298.                                    "*kkkkkk*hhhhh*ooooooooooooooooo*",
  299.                                    "*******hhhhhh*ooooooooooooooooo*",
  300.                                    "*eeeeeeeeeeee*ooooooooooooooooo*",
  301.                                    "*eeeeeeeeeeee*ooooooooooooooooo*",
  302.                                    "*eeeeeeeeeeee*ooooooooooooooooo*",
  303.                                    "********************************",};
  304.  
  305. // this array holds the objects within the universe
  306.  
  307. // l - lamp
  308. // s - sandwich
  309. // k - keys
  310.  
  311. //           ^
  312. //         NORTH
  313. //
  314. // < WEST           EAST >
  315. //
  316. //         SOUTH
  317. //           v
  318.  
  319. char *universe_objects[NUM_ROWS]={"                                ",
  320.                                   " l                            k ",
  321.                                   "                                ",
  322.                                   "                                ",
  323.                                   "                                ",
  324.                                   "                                ",
  325.                                   "                                ",
  326.                                   "                                ",
  327.                                   "                                ",
  328.                                   " l                              ",
  329.                                   "                                ",
  330.                                   "                                ",
  331.                                   "                                ",
  332.                                   "                                ",
  333.                                   "                                ",
  334.                                   "                                ",
  335.                                   "                                ",
  336.                                   "                                ",
  337.                                   "                                ",
  338.                                   "                                ",
  339.                                   "                                ",
  340.                                   "                                ",
  341.                                   "                                ",
  342.                                   "  s                             ",
  343.                                   "                                ",
  344.                                   "                                ",
  345.                                   "                                ",
  346.                                   "                                ",
  347.                                   "          s                     ",
  348.                                   "                             l  ",
  349.                                   "                                ",
  350.                                   "                                ",};
  351.  
  352. // these info strings hold the views in each room
  353.  
  354. info_string views[]={
  355.  
  356. {'l',"You see an expansive white room with a vaulted ceiling. The walls are adorned "},
  357. {'l',"with medieval art.  To the North, is a plate glass window through which colored"},
  358. {'l',"strands of light pierce. They reflect off the carpeted floor and create a     "},
  359. {'l',"silhouette of the towering pines just outdside. In the Northeast corner of    "},
  360. {'l',"the room, you see a fire place with a half burnt log in it. Finally, against  "},
  361. {'l',"the West wall there's a white leather couch and in each corner of the room    "},
  362. {'l',"are large green palms potted in hexogonal black pots.                         "},
  363.  
  364. {'b',"You see a black lacquer bedroom set surrounding a king size platform bed."},
  365. {'b',"On the walls, you see pictures of mystical landscapes and underwater cities.   "},
  366. {'b',"To the North there is a window thru which you see a group of large trees just  "},
  367. {'b',"beyond a small pond. On the floor of the room you see black silk stockings     "},
  368. {'b',"and lingerie thrown with abandon about the area.                               "},
  369.  
  370. {'k',"You are surrounded by stone washed granite counters. On the counters are the"},
  371. {'k',"normal appliances found in a kitchen. To the West there is a large glass    "},
  372. {'k',"door refrigerator with a varitable plethora of food. Against the South wall"},
  373. {'k',"there is a small nook with a white refuge container. Above your head dangle"},
  374. {'k',"down many cooking utensils and exotic pans suspended from a anodized        "},
  375. {'k',"aluminum structure.                                                         "},
  376.  
  377. {'w',"There is a large vanity mirror and a black porcellin wash basin. To the East"},
  378. {'w',"is a rack of black and white towels hung on brass rails. On the counter     "},
  379. {'w',"surrounding the walls there are small spherically shaped soap balls in a    "},
  380. {'w',"myriad of colors set in cyrstal dishes. The floor is made of black and white"},
  381. {'w',"marble with a hint of grey running thru it.                                 "},
  382.  
  383. {'h',"You see an ordinary hallway with track lighting above head. "},
  384.  
  385. {'r',"You see a large wash area with two basins. To the West through a glass  "},
  386. {'r',"enclosure you see the outline of a young woman apperantly bathing... To "},
  387. {'r',"the East you see a second smaller room with many plants hanging from the"},
  388. {'r',"celing along with the shadow of a dark,muscular man moving around. On   "},
  389. {'r',"the floor below you are plush tapestries of Egyption origin.            "},
  390.  
  391. {'e',"To the West you see a small opening into what appears to be a kitchen.        "},
  392. {'e',"The lights are low and you can't make out much more in this direction.        "},
  393. {'e',"Under your feet is a large black rectangular cut of carpet. Lastly, leading to"},
  394. {'e',"the East and North are hallways to the remainder of the house.                "},
  395.  
  396. {'o',"You are astounded by the amount of computer equipment in every corner of the "},
  397. {'o',"room. To the South is a Silicon Graphics OYNX Super Computer, the screen of  "},
  398. {'o',"which seems to displaying a mesmorizing array of mathematical equations. To  "},
  399. {'o',"the North you are faced with literally hundreds of books on every topic from "},
  400. {'o',"quantum mechanics to molecular bio-chemistry. Against the East wall there    "},
  401. {'o',"is a full collection of electrical engineering equipment with a oscilloscope "},
  402. {'o',"displaying a curious waveform apparently an input from a black box resting on"},
  403. {'o',"the floor. As you look around the walls of the room, you see schematics of   "},
  404. {'o',"digital hardware and paintings of great scientific pioneers such as Einstein,"},
  405. {'o',"Newton and Maxwell. Strewn about the floor are small electronic              "},
  406. {'o',"components and pieces of paper with scribbles upon them.                     "},
  407. {'X',""},  // terminate
  408.  
  409. };
  410.  
  411. // these info strings hold the smells in each room
  412.  
  413. info_string smells[]={
  414.  
  415. {'l',"You smell the sweet odor of Jasmine with an undertone of potpourri. "},
  416.  
  417. {'b',"The sweet smell of perfume dances within your nostrils...Realities possibly. "},
  418.  
  419. {'k',"You take a deep breath and your senses are tantallized with the smell of"},
  420. {'k',"tender breasts of chicken marinating in a garlic sauce. Also, there is "},
  421. {'k',"a sweet berry smell emanating from the oven.                          "},
  422.  
  423. {'w',"You are almost overwhelmed by the smell of bathing fragrance as you"},
  424. {'w',"inhale.                                                              "},
  425.  
  426. {'h',"You smell nothing to make note of. "},
  427.  
  428. {'r',"Your nose is filled with steam and the smell of baby oil... "},
  429.  
  430. {'e',"You smell pine possibly from the air coming thru a small orifice near"},
  431. {'e',"the front door.                                                            "},
  432.  
  433. {'o',"You are greeted with the familiar odor of burning electronics. As you inhale"},
  434. {'o',"a second time, you can almost taste the rustic smell of aging books.        "},
  435. {'X',""}, // terminate
  436.  
  437. };
  438.  
  439. // these info strings hold the sounds in each room
  440.  
  441. info_string sounds[]={
  442.  
  443. {'l',"You hear the faint sounds of Enigma playing in the background along with"},
  444. {'l',"the wind howling against the exterior of the room.                      "},
  445.  
  446. {'b',"You hear the wind rubbing against the window making a sound similar to"},
  447. {'b',"sheets being pulled off a bed.                                        "},
  448.  
  449. {'k',"You hear expansion of the hot ovens along with the relaxing sounds produced"},
  450. {'k',"by the cooling fans.                                                       "},
  451.  
  452. {'w',"You hear nothing but a slight echo in the heating ducts."},
  453.  
  454. {'h',"You hear the sounds of music, but you can't make out any of the words or"},
  455. {'h',"melodies.                                                               "},
  456.  
  457. {'r',"You hear the sound of driping water and the whispers of a femal voice"},
  458. {'r',"ever so faintly in the background.                                   "},
  459.  
  460. {'e',"You hear the noises of the outside world muffled by the closed door to the"},
  461. {'e',"South.                                                                    "},
  462.  
  463. {'o',"You hear nothing but the perpetual hum of all the cooling fans within the"},
  464. {'o',"electronic equipment.                                                    "},
  465. {'X',""},
  466.  
  467. };
  468.  
  469. int sentence[8];               // this array holds the current sentence
  470. int num_tokens;                // number of words in current sentecne
  471.  
  472. // this is the player
  473.  
  474. player you={"Andre'",10,29,NORTH,{' ',' ',' ',' ',' ',' ',' ',' '},0};
  475.  
  476. int global_exit=0;             // global exit flag
  477.  
  478. char global_input[128],        // input string
  479.      global_output[128];       // output string
  480.  
  481. // F U N C T I O N S //////////////////////////////////////////////////////////
  482.  
  483. char *Get_Line(char *buffer)
  484. {
  485. // this function gets a single line of input and tolerates white space
  486.  
  487. int c,index=0;
  488.  
  489. // loop while user hasn't hit return
  490.  
  491. while((c=getch())!=13)
  492.      {
  493.  
  494. // implement backspace
  495.  
  496.      if (c==8 && index>0)
  497.         {
  498.  
  499.         buffer[--index] = ' ';
  500.         printf("%c %c",8,8);
  501.  
  502.         } // end if backspace
  503.      else
  504.      if (c>=32 && c<=122)
  505.         {
  506.         buffer[index++] = c;
  507.         printf("%c",c);
  508.  
  509.         } // end if in printable range
  510.  
  511.      } // end while
  512.  
  513. // terminate string
  514.  
  515. buffer[index] = 0;
  516.  
  517. // return pointer to buffer or NULL
  518.  
  519. if (strlen(buffer)==0)
  520.    return(NULL);
  521. else
  522. return(buffer);
  523.  
  524. } // end Get_Line
  525.  
  526. ////////////////////////////////////////////////////////////////////////////////
  527.  
  528. int Get_Token(char *input,char *output,int *current_pos)
  529. {
  530.  
  531. int index,   // loop index and working index
  532.     start,   // points to start of token
  533.     end;     // points to end of token
  534.  
  535. // set current positions
  536.  
  537. index=start=end=*current_pos;
  538.  
  539. // eat white space
  540.  
  541. while(isspace(input[index]) || ispunct(input[index]))
  542.      {
  543.  
  544.      index++;
  545.  
  546.      } // end while
  547.  
  548. // test if end of string found
  549.  
  550. if (input[index]==NULL)
  551.    {
  552.    // emit nothing
  553.  
  554.    strcpy(output,"");
  555.    return(0);
  556.  
  557.    } // end if no more tokens
  558.  
  559. // at this point, we must have a token of some kind, so find the end of it
  560.  
  561. start = index; // mark front of it
  562. end   = index;
  563.  
  564. // find end of Token
  565.  
  566. while(!isspace(input[end]) && !ispunct(input[end]) && input[end]!=NULL)
  567.      {
  568.  
  569.      end++;
  570.  
  571.      } // end while
  572.  
  573. // build up output string
  574.  
  575. for (index=start; index<end; index++)
  576.     {
  577.  
  578.     output[index-start] = toupper(input[index]);
  579.  
  580.     } // end copy string
  581.  
  582. // place terminator
  583.  
  584. output[index-start] = 0;
  585.  
  586. // update current string position
  587.  
  588. *current_pos  = end;
  589.  
  590. return(end);
  591.  
  592. } // end Get_Token
  593.  
  594. ///////////////////////////////////////////////////////////////////////////////
  595.  
  596. int Extract_Tokens(char *string)
  597. {
  598. // this function breaks the input string down into tokens and fills up
  599. // the global sentence array with the tokens so that it can be processed
  600.  
  601. int curr_pos=0,      // current position in string
  602.     curr_token=0,    // current token number
  603.     found,           // used to flag if the token is valid in language
  604.     index;           // loop index
  605.  
  606. char output[16];
  607.  
  608. // reset number of tokens and clear the sentence out
  609.  
  610. num_tokens=0;
  611.  
  612. for (index=0; index<8; index++)
  613.     sentence[index]=0;
  614.  
  615. // extract all the words in the sentence (tokens)
  616.  
  617. while(Get_Token(string,output,&curr_pos))
  618.      {
  619.  
  620.      // test to see if this is a valid token
  621.  
  622.      for (index=0,found=0; index<NUM_TOKENS; index++)
  623.          {
  624.  
  625.          // do we have a match?
  626.  
  627.          if (strcmp(output,language[index].symbol)==0)
  628.             {
  629.             // set found flag
  630.  
  631.             found=1;
  632.  
  633.             // enter token into sentence
  634.  
  635.             sentence[curr_token++] = language[index].value;
  636.         //    printf("\nEntering %s, %d in sentence",
  637.         //                               output,language[index].value);
  638.  
  639.             break;
  640.  
  641.             } // end if
  642.  
  643.          } // end for index
  644.  
  645.          // test if token was part of language (grammar)
  646.  
  647.          if (!found)
  648.             {
  649.             printf("\n%s, I don't know what \"%s\" means.",you.name
  650.                                                           ,output);
  651.  
  652.             // failure
  653.  
  654.             return(0);
  655.  
  656.             } // end if not found
  657.  
  658.          // else
  659.  
  660.          num_tokens++;
  661.  
  662.      } // end while
  663.  
  664. return(1);
  665.  
  666. } // end Extract_Tokens
  667.  
  668. ///////////////////////////////////////////////////////////////////////////////
  669.  
  670. void Verb_Parser(void)
  671. {
  672. // this function breaks down the sentence and based on the verb calls the
  673. // appropriate "method" or function to apply that verb
  674. // note: syntactic analysis could be done here, but I decided to place it
  675. // in the action verb functions, so that you can see the way the errors are
  676. // detected for each verb (even though there is a a lot of redundancy)
  677.  
  678. // what is the verb?
  679.  
  680. switch(sentence[FIRST_WORD])
  681.       {
  682.  
  683.       case ACTION_MOVE:
  684.            {
  685.            // call the appropriate function
  686.  
  687.            Verb_MOVE();
  688.  
  689.            } break;
  690.  
  691.       case ACTION_TURN:
  692.            {
  693.            // call the appropriate function
  694.  
  695.            Verb_TURN();
  696.  
  697.            } break;
  698.  
  699.       case ACTION_SMELL:
  700.            {
  701.            // call the appropriate function
  702.  
  703.            Verb_SMELL();
  704.  
  705.            } break;
  706.  
  707.       case ACTION_LOOK:
  708.            {
  709.            // call the appropriate function
  710.  
  711.            Verb_LOOK();
  712.  
  713.            } break;
  714.  
  715.       case ACTION_LISTEN:
  716.            {
  717.            // call the appropriate function
  718.  
  719.            Verb_LISTEN();
  720.  
  721.            } break;
  722.  
  723.       case ACTION_PUT:
  724.            {
  725.            // call the appropriate function
  726.  
  727.            Verb_PUT();
  728.  
  729.            } break;
  730.  
  731.       case ACTION_GET:
  732.            {
  733.            // call the appropriate function
  734.  
  735.            Verb_GET();
  736.  
  737.            } break;
  738.  
  739.       case ACTION_EAT:
  740.            {
  741.            // call the appropriate function
  742.  
  743.            Verb_EAT();
  744.  
  745.            } break;
  746.  
  747.       case ACTION_WHERE:
  748.            {
  749.            // call the appropriate function
  750.  
  751.            Verb_WHERE();
  752.  
  753.            } break;
  754.  
  755.       case ACTION_INVENTORY:
  756.            {
  757.            // call the appropriate function
  758.  
  759.            Verb_INVENTORY();
  760.  
  761.            } break;
  762.  
  763.       case ACTION_EXIT:
  764.            {
  765.            // call the appropriate function
  766.  
  767.            Verb_EXIT();
  768.  
  769.            } break;
  770.  
  771.       default:
  772.              {
  773.              printf("\n%s, you must start a sentence with an action verb!",
  774.                     you.name);
  775.  
  776.              return;
  777.  
  778.              } break;
  779.  
  780.       } // end switch
  781.  
  782. } // end Verb_Parser
  783.  
  784. // THE ACTION VERBS ///////////////////////////////////////////////////////////
  785.  
  786. int Verb_MOVE(void)
  787. {
  788. // this function will figure out which way the player wants to move,
  789. // then move the player and test for syntax errors
  790.  
  791. int token_index,   // current token being processed
  792.     dx,dy;         // ised to hold translation factors
  793.  
  794. // these look up tables are used to compute the translation factors
  795. // needed to move the player in the requested direction based on the
  796. // current direction, the problem occurs since the directives are not
  797. // absolute directions, they are relative to the direction the player
  798. // is facing
  799.  
  800. static int forward_x[]={1,-1,0,0};
  801. static int forward_y[]={0,0,-1,1};
  802.  
  803. static int backward_x[]={-1,1,0,0};
  804. static int backward_y[]={0,0,1,-1};
  805.  
  806. static int left_x[]={0, 0,-1,1};
  807. static int left_y[]={-1,1,0,0};
  808.  
  809. static int right_x[]={0,0,1,-1};
  810. static int right_y[]={1,-1,0,0};
  811.  
  812. // test if player didn't say which way, if so just move forward
  813. // this functionality was added after the fact so is a slight cludge
  814. // it is accomplished by synthetically inserting the direction "forward" into
  815. // the sentence
  816.  
  817. if (num_tokens==1)
  818.    {
  819.    // no direction given so assume forward
  820.  
  821.    sentence[SECOND_WORD] = DIR_2_FORWARD;
  822.  
  823.    num_tokens++;
  824.  
  825.    } // end if no direction
  826.  
  827.    // begin further processing to figure out direction
  828.  
  829.    // check if the next word is a direction and if so move in that
  830.    // direction
  831.  
  832.    // first test if the words 'to' or 'to the' are inserted bewteen action
  833.    // verb and noun (object).  In this case the phrase "move to the right"
  834.    // sounds ok and should be passed, but "move to the forward" will also
  835.    // be passed even though it is grammatically incorrent, but that's life
  836.  
  837.    token_index=1;
  838.  
  839.    if (Check_For_Phrase(PHRASE_TO_THE,token_index))
  840.       {
  841.       // consume preposition since it has to bearing on the final
  842.       // meaning sentence
  843.  
  844.       // index token scan to directon
  845.  
  846.       token_index=3;
  847.  
  848.       } // end if prep and article
  849.    else
  850.    if (Check_For_Phrase(PHRASE_TO,token_index))
  851.       {
  852.       // consume preposition since it has to bearing on the final
  853.       // meaning sentence
  854.  
  855.       // index token scan to directon
  856.  
  857.       token_index=2;
  858.  
  859.       } // end if prep
  860.  
  861.    // at this point the token_index is pointing to the direction
  862.  
  863.    if (sentence[token_index] >= DIR_2_START &&
  864.        sentence[token_index] <= DIR_2_END)
  865.       {
  866.       // at this point we finally know what the user is asking for, so
  867.       // let's do it
  868.  
  869.       // based on direction asked for do movement and collision detection
  870.       // note: the use of look up tables to decrease the complexity of the
  871.       // conditional logic
  872.  
  873.       dx=dy=0;
  874.  
  875.       switch(sentence[token_index])
  876.             {
  877.  
  878.             case DIR_2_FORWARD:  // move player forward
  879.                  {
  880.                  // compute translation factors using look up tables
  881.  
  882.                  dx = forward_x[you.direction];
  883.                  dy = forward_y[you.direction];
  884.  
  885.                  } break;
  886.  
  887.             case DIR_2_BACKWARD: // move player backward
  888.                  {
  889.                  // compute translation factors using look up tables
  890.  
  891.                  dx = backward_x[you.direction];
  892.                  dy = backward_y[you.direction];
  893.  
  894.                  } break;
  895.  
  896.             case DIR_2_RIGHT:    // parry right
  897.                  {
  898.                  // compute translation factors using look up tables
  899.  
  900.                  dx = right_x[you.direction];
  901.                  dy = right_y[you.direction];
  902.  
  903.                  } break;
  904.  
  905.             case DIR_2_LEFT:     // parry left
  906.                  {
  907.                  // compute translation factors using look up tables
  908.  
  909.                  dx = left_x[you.direction];
  910.                  dy = left_y[you.direction];
  911.  
  912.                  } break;
  913.  
  914.             } // end switch direction of motion
  915.  
  916.       // based on the translation factors move the player
  917.  
  918.       you.x+=dx;
  919.       you.y+=dy;
  920.  
  921.       // test for collision with a wall
  922.  
  923.       if (universe_geometry[you.y][you.x]==WALL_ID)
  924.          {
  925.          // let' user know he hit a wall
  926.          printf("\nOuch! that hurt. Can't you see this wall %s?\n",you.name);
  927.  
  928.          // back player up
  929.  
  930.          you.x-=dx;
  931.          you.y-=dy;
  932.  
  933.          } // end collision detection
  934.       else
  935.          {
  936.          printf("\nYou take a few steps.\n");
  937.  
  938.          } // end else ok
  939.  
  940.       return(1);
  941.  
  942.       } // end if direction is valid
  943.    else
  944.       {
  945.       printf("\n%\"%s\" is an invalid sentence.",global_input);
  946.       printf("\nI don't understand the direction you wish me to move in?");
  947.       return(0);
  948.  
  949.       } // end else invalid direction
  950.  
  951. } // end Verb_MOVE
  952.  
  953. ////////////////////////////////////////////////////////////////////////////////
  954.  
  955. int Verb_TURN(void)
  956. {
  957. // this function will figure out which way the player wants to turn,
  958. // then turn the player and test for syntax errors
  959.  
  960. int token_index;
  961.  
  962. // if the player look in general then give him the full view, otherwise
  963. // look for walls and objects
  964.  
  965. token_index=0;
  966.  
  967. // first test for a direction
  968.  
  969. if (num_tokens==1)
  970.    {
  971.    // no direction, so tell user to give one next time
  972.  
  973.    printf("\n%s, I don't know which way to turn?\n",you.name);
  974.    return(0);
  975.  
  976.    } // end if only turn
  977. else
  978.    {
  979.    // check if the next word is a direction and if so turn in that
  980.    // direction
  981.  
  982.    // first test if the words 'to' or 'to the' are inserted bewteen action
  983.    // verb and noun (object)
  984.  
  985.    token_index=1;
  986.  
  987.    if (Check_For_Phrase(PHRASE_TO_THE,token_index))
  988.       {
  989.       // consume preposition since it has to bearing on the final
  990.       // meaning sentence
  991.  
  992.       // index token scan to directon
  993.  
  994.       token_index=3;
  995.  
  996.       } // end if prep and article
  997.    else
  998.    if (Check_For_Phrase(PHRASE_TO,token_index))
  999.       {
  1000.       // consume preposition since it has to bearing on the final
  1001.       // meaning sentence
  1002.  
  1003.       // index token scan to directon
  1004.  
  1005.       token_index=2;
  1006.  
  1007.       } // end if prep
  1008.  
  1009.    // at this point the token_index is pointing to the direction
  1010.  
  1011.    if (sentence[token_index] >= DIR_1_START &&
  1012.        sentence[token_index] <= DIR_1_END)
  1013.       {
  1014.       // at this point we finally know what the user is asking for, so
  1015.       // let's do it
  1016.  
  1017.       // update the players direction based on new direction
  1018.  
  1019.       you.direction = sentence[token_index]-DIR_1_START;
  1020.  
  1021.       printf("\nYou turn...");
  1022.  
  1023.       return(1);
  1024.  
  1025.       } // end if direction is valid
  1026.    else
  1027.       {
  1028.       printf("\n%\"%s\" is an invalid sentence.",global_input);
  1029.       printf("\nI don't understand the direction you wish me to turn to?");
  1030.       return(0);
  1031.       } // end else invalid direction
  1032.  
  1033.    } // end else
  1034.  
  1035. } // end Verb_TURN
  1036.  
  1037. ////////////////////////////////////////////////////////////////////////////////
  1038.  
  1039. int Verb_SMELL(void)
  1040. {
  1041. // this function will just smell without paying attention to the rest
  1042. // of the sentence
  1043.  
  1044. if (num_tokens==1)
  1045.    {
  1046.  
  1047.    Print_Info_Strings(smells,universe_geometry[you.y][you.x]);
  1048.    return(1);
  1049.    } // end if smell
  1050. else
  1051.    {
  1052.  
  1053.    printf("\n%\"%s\" is an invalid sentence.",global_input);
  1054.    printf("\nI don't understand what you want me to smell?");
  1055.    return(0);
  1056.    } // end else invalid
  1057.  
  1058. } // end Verb_SMELL
  1059.  
  1060. ////////////////////////////////////////////////////////////////////////////////
  1061.  
  1062. int Verb_LOOK(void)
  1063. {
  1064. // this function will look in the direction commanded to
  1065.  
  1066. int token_index,   // current word being processed
  1067.     direction,     // direction player wants to look
  1068.     num_items,     // number of objects seen during vision scan
  1069.     index;         // used as look index
  1070.  
  1071. object objects[8]; // holds the objects
  1072.  
  1073. // if the player look in general then give him the full view, otherwise
  1074. // look for walls and objects
  1075.  
  1076. token_index=0;
  1077.  
  1078. // first test for a direction
  1079.  
  1080. if (num_tokens==1)
  1081.    {
  1082.    // no direction, so give long version
  1083.  
  1084.    Print_Info_Strings(views,universe_geometry[you.y][you.x]);
  1085.    return(1);
  1086.    } // end if only look
  1087. else
  1088.    {
  1089.    // check if the next word is a direction and if so look in that
  1090.    // direction
  1091.  
  1092.    // first test if the words 'to' or 'to the' are inserted bewteen action
  1093.    // verb and noun (object)
  1094.  
  1095.    token_index=1;
  1096.  
  1097.    if (Check_For_Phrase(PHRASE_TO_THE,token_index))
  1098.       {
  1099.       // consume preposition since it has to bearing on the final
  1100.       // meaning sentence
  1101.  
  1102.       // index token scan to directon
  1103.  
  1104.       token_index=3;
  1105.  
  1106.       } // end if prep and article
  1107.    else
  1108.    if (Check_For_Phrase(PHRASE_TO,token_index))
  1109.       {
  1110.       // consume preposition since it has to bearing on the final
  1111.       // meaning sentence
  1112.  
  1113.       // index token scan to directon
  1114.  
  1115.       token_index=2;
  1116.  
  1117.       } // end if prep
  1118.  
  1119.    // at this point the token_index is pointing to the direction
  1120.  
  1121.    if (sentence[token_index] >= DIR_1_START &&
  1122.        sentence[token_index] <= DIR_1_END)
  1123.       {
  1124.       // at this point we finally know what the user is asking for, so
  1125.       // let's do it
  1126.  
  1127.       printf("\nYou see walls");
  1128.  
  1129.       // compute direction
  1130.  
  1131.       direction = sentence[token_index] - DIR_1_START;
  1132.  
  1133.       // test if there are any objects in sight
  1134.  
  1135.       if (Vision_System(24,direction,objects,&num_items))
  1136.          {
  1137.  
  1138.          // print out what was seen
  1139.  
  1140.          printf(" and,");
  1141.  
  1142.          for (index=0; index<num_items; index++)
  1143.              {
  1144.  
  1145.              // print out the correct description
  1146.  
  1147.              switch(objects[index].thing)
  1148.                    {
  1149.  
  1150.                    case LAMP_ID:
  1151.                         {
  1152.                         printf("\na torch lamp.");
  1153.                         } break;
  1154.  
  1155.                    case KEYS_ID:
  1156.                         {
  1157.                         printf("\na set of car keys.");
  1158.                         } break;
  1159.  
  1160.                    case SANDWICH_ID:
  1161.                         {
  1162.                         printf("\na turkey sandwich.");
  1163.                         } break;
  1164.  
  1165.                    default:break;
  1166.  
  1167.                    } // end switch
  1168.  
  1169.              } // end for index
  1170.  
  1171.          } // end if we saw something
  1172.  
  1173.       return(1);
  1174.  
  1175.       } // end if direction is valid
  1176.    else
  1177.       {
  1178.       printf("\n%\"%s\" is an invalid sentence.",global_input);
  1179.       printf("\nI don't understand the direction you wish me to look in?");
  1180.       return(0);
  1181.       } // end else invalid direction
  1182.  
  1183.    } // end else
  1184.  
  1185. } // end Verb_LOOK
  1186.  
  1187. ////////////////////////////////////////////////////////////////////////////////
  1188.  
  1189. int Verb_LISTEN(void)
  1190. {
  1191. // this function will just listen without paying attention to the rest of
  1192. // the sentence
  1193.  
  1194.  
  1195. if (num_tokens==1)
  1196.    {
  1197.  
  1198.    Print_Info_Strings(sounds,universe_geometry[you.y][you.x]);
  1199.    return(1);
  1200.    } // end if sound
  1201. else
  1202.    {
  1203.  
  1204.    printf("\n%\"%s\" is an invalid sentence.",global_input);
  1205.    printf("\nI don't understand what you want me to listen to?");
  1206.    return(0);
  1207.    } // end else invalid
  1208.  
  1209. } // end Verb_LISTEN
  1210.  
  1211. ////////////////////////////////////////////////////////////////////////////////
  1212.  
  1213. int Verb_PUT(void)
  1214. {
  1215. // this function will put down the object requested
  1216.  
  1217. // this look up table is used to convert object token numbers into object id's
  1218.  
  1219. static char object_to_id[]={'l','s','k'};
  1220.  
  1221. int token_index, // current toek nbeing precessed
  1222.           index; // loop index
  1223.  
  1224. char object;     // object we are currently looking at
  1225.  
  1226. token_index=0;
  1227.  
  1228. // first test for a object
  1229.  
  1230. if (num_tokens==1)
  1231.    {
  1232.    // no object, so tell user to give one next time
  1233.  
  1234.    printf("\n%s, I don't know what you want me to put down?\n",you.name);
  1235.    return(0);
  1236.  
  1237.    } // end if only put
  1238. else
  1239.    {
  1240.    // check if the next word is an object, if so put is down
  1241.    // direction
  1242.  
  1243.    // first test if the words 'down' or 'down the' are inserted bewteen action
  1244.    // verb and noun (object)
  1245.  
  1246.    token_index=1;
  1247.  
  1248.    if (Check_For_Phrase(PHRASE_DOWN_THE,token_index))
  1249.       {
  1250.       // consume preposition since it has to bearing on the final
  1251.       // meaning sentence
  1252.  
  1253.       // index token scan to object
  1254.  
  1255.       token_index=3;
  1256.  
  1257.       } // end if prep and article
  1258.    else
  1259.    if (Check_For_Phrase(PHRASE_DOWN,token_index))
  1260.       {
  1261.       // consume preposition since it has to bearing on the final
  1262.       // meaning sentence
  1263.  
  1264.       // index token scan to object
  1265.  
  1266.       token_index=2;
  1267.  
  1268.       } // end if prep
  1269.  
  1270.    // at this point the token_index is pointing to the object
  1271.  
  1272.    if (sentence[token_index] >= OBJECT_START &&
  1273.        sentence[token_index] <= OBJECT_END)
  1274.       {
  1275.       // at this point we finally know what the user is asking for, so
  1276.       // let's do it
  1277.  
  1278.       // check to see if object is in inventory..if so then put it down
  1279.       // in the current square
  1280.  
  1281.       // first convert object token to object id
  1282.  
  1283.       object = object_to_id[sentence[token_index]-OBJECT_START];
  1284.  
  1285.       // do scan in pockets
  1286.  
  1287.       for (index=0; index<you.num_objects; index++)
  1288.           {
  1289.           // test if this pocket has the object we are looking for
  1290.  
  1291.           if (you.inventory[index]==object)
  1292.              {
  1293.              // take object out of pocket
  1294.  
  1295.              you.inventory[index] = EMPTY_ID;
  1296.  
  1297.              // decrement number of objects
  1298.  
  1299.              you.num_objects--;
  1300.  
  1301.              // place the object back into object universe
  1302.  
  1303.              universe_objects[you.y][you.x] = object;
  1304.  
  1305.              // say something
  1306.  
  1307.              printf("\nPutting down the ");
  1308.  
  1309.              switch(object)
  1310.                    {
  1311.                    case LAMP_ID:
  1312.                         {printf("torch lamp.\n");}break;
  1313.  
  1314.                    case SANDWICH_ID:
  1315.                         {printf("sandwich.\n");}break;
  1316.  
  1317.                    case KEYS_ID:
  1318.                         {printf("keys.\n");}break;
  1319.  
  1320.                    default:break;
  1321.  
  1322.                    } // end switch
  1323.  
  1324.              // **************************************************************
  1325.              // if the player puts the keys in the kitchen where they should be
  1326.              // then he will win! Test that condition here
  1327.  
  1328.              if (object==KEYS_ID && universe_geometry[you.y][you.x]=='k')
  1329.                 {
  1330.  
  1331.                 printf("\nCongratulation %s! You have solved the game.\n",you.name);
  1332.  
  1333.                 } // end if win
  1334.  
  1335.              // **************************************************************
  1336.  
  1337.              return(1);
  1338.  
  1339.              } // end if found object
  1340.  
  1341.           } // end for index
  1342.  
  1343.       // if we get this far then the player wasn't carrying the requested
  1344.       // object to be dropped
  1345.  
  1346.       printf("\n%s, you don't have that to drop!\n",you.name);
  1347.  
  1348.       return(1);
  1349.  
  1350.       } // end if object is valid
  1351.    else
  1352.       {
  1353.       printf("\n%\"%s\" is an invalid sentence.",global_input);
  1354.       printf("\nI don't understand the object you wish me to put down?");
  1355.       return(0);
  1356.       } // end else invalid object
  1357.  
  1358.    } // end else
  1359.  
  1360. } // end Verb_PUT
  1361.  
  1362. ////////////////////////////////////////////////////////////////////////////////
  1363.  
  1364. int Verb_GET(void)
  1365. {
  1366. // this function will get the object in the current square
  1367.  
  1368. object objects[8];  // the objects within reaching distance of player
  1369.  
  1370. // this look up table is used to convert object token numbers into object id's
  1371.  
  1372. static char object_to_id[]={'l','s','k'};
  1373.  
  1374. int token_index=0,   // current token being processed
  1375.           index,     // loop index
  1376.           index_2,   // loop index
  1377.           num_items; // number of items found during vision scan
  1378.  
  1379. char object;       // item we are currently looking at
  1380.  
  1381. // first test for a object
  1382.  
  1383. if (num_tokens==1)
  1384.    {
  1385.    // no object, so ask what get
  1386.  
  1387.    printf("\n%s, what do you want me to pick up?\n",you.name);
  1388.  
  1389.    return(1);
  1390.  
  1391.    } // end if only get
  1392. else
  1393.    {
  1394.    // check if the next word is an object
  1395.  
  1396.    // first test if the word 'the' is inserted bewteen action
  1397.    // verb and noun (object)
  1398.  
  1399.    token_index=1;
  1400.  
  1401.    if (Check_For_Phrase(PHRASE_THE,token_index))
  1402.       {
  1403.       // consume article since it has to bearing on the final
  1404.       // meaning sentence
  1405.  
  1406.       // index token scan to directon
  1407.  
  1408.       token_index=2;
  1409.  
  1410.       } // end if article
  1411.  
  1412.    // at this point the token_index is pointing to the object to pick up
  1413.  
  1414.    if (sentence[token_index] >= OBJECT_START &&
  1415.        sentence[token_index] <= OBJECT_END)
  1416.       {
  1417.       // at this point we finally know what the user is asking for, so
  1418.       // let's do it
  1419.  
  1420.       // using vision system scan forward a depth of 2 units this will simulate
  1421.       // the player reaching for the object within a reasonable radius
  1422.  
  1423.       // convert object to id
  1424.  
  1425.       object = object = object_to_id[sentence[token_index]-OBJECT_START];
  1426.  
  1427.        // do forward radial scan
  1428.  
  1429.       if (Vision_System(3,you.direction,objects,&num_items))
  1430.          {
  1431.  
  1432.          // test if the object we desire to pick up is within the objects array
  1433.  
  1434.          for (index=0; index<num_items; index++)
  1435.              {
  1436.              // is this what player wants to pick up?
  1437.  
  1438.              if (object==objects[index].thing)
  1439.                 {
  1440.  
  1441.                 // remove object from universe
  1442.  
  1443.                 universe_objects[objects[index].y][objects[index].x] = EMPTY_ID;
  1444.  
  1445.                 // update players inventory (find an empty pocket and place
  1446.                 // object in it)
  1447.  
  1448.                 for (index_2=0; index_2<8; index_2++)
  1449.                     {
  1450.                     if (you.inventory[index_2]==EMPTY_ID)
  1451.                        {
  1452.                        // put it in pocket
  1453.  
  1454.                        you.inventory[index_2]=object;
  1455.  
  1456.                        you.num_objects++;
  1457.  
  1458.                        break;
  1459.  
  1460.                        } // end if an open spot was found
  1461.  
  1462.                     } // end for index_2
  1463.  
  1464.                 // let user know it was picked up
  1465.  
  1466.                 printf("\nGot it!\n");
  1467.  
  1468.                 return(1);
  1469.  
  1470.                 } // end if object found
  1471.  
  1472.              } // end for index
  1473.  
  1474.          } // end if any objects within reach
  1475.       else
  1476.          {
  1477.  
  1478.          printf("\nYou are too far from it!\n");
  1479.          return(0);
  1480.  
  1481.          } // end else can't reach
  1482.  
  1483.       } // end if object is valid
  1484.    else
  1485.       {
  1486.       printf("\nI don't understand what you want me to pick up?");
  1487.       return(0);
  1488.  
  1489.       } // end else invalid object
  1490.  
  1491.    } // end else
  1492.  
  1493. return(0);
  1494.  
  1495. } // end Verb_GET
  1496.  
  1497. ////////////////////////////////////////////////////////////////////////////////
  1498.  
  1499. int Verb_EAT(void)
  1500. {
  1501. // the function will eat the object it is directed to
  1502.  
  1503. // this look up table is used to convert object token numbers into object id's
  1504.  
  1505. static char object_to_id[]={'l','s','k'};
  1506.  
  1507. int token_index=0, // current token being processed
  1508.           index;   // loop index
  1509.  
  1510. char object;       // object we are currently looking at
  1511.  
  1512. // first test for a direction
  1513.  
  1514. if (num_tokens==1)
  1515.    {
  1516.    // no object, so ask what to eat
  1517.  
  1518.    printf("\n%s, what do you want me to eat?\n",you.name);
  1519.  
  1520.    return(1);
  1521.  
  1522.    } // end if only eat
  1523. else
  1524.    {
  1525.    // check if the next word is an object
  1526.  
  1527.    // first test if the word 'the' is inserted bewteen action
  1528.    // verb and noun (object)
  1529.  
  1530.    token_index=1;
  1531.  
  1532.    if (Check_For_Phrase(PHRASE_THE,token_index))
  1533.       {
  1534.       // consume article since it has to bearing on the final
  1535.       // meaning sentence
  1536.  
  1537.       // index token scan to directon
  1538.  
  1539.       token_index=2;
  1540.  
  1541.       } // end if article
  1542.  
  1543.    // at this point the token_index is pointing to the object to eat
  1544.  
  1545.    if (sentence[token_index] >= OBJECT_START &&
  1546.        sentence[token_index] <= OBJECT_END)
  1547.       {
  1548.       // at this point we finally know what the user is asking for, so
  1549.       // let's do it
  1550.  
  1551.       // scan thru the inventory and test if the player is carrying the
  1552.       // object.  Actually, the only thing he can eat is the sandwich, but
  1553.       // we need a little comedy relief and this is a good place for it
  1554.  
  1555.       for (index=0; index<8; index++)
  1556.           {
  1557.  
  1558.           // test if this pocket has object we are interested in
  1559.  
  1560.  
  1561.           // first convert object token to object id
  1562.  
  1563.           object = object_to_id[sentence[token_index]-OBJECT_START];
  1564.  
  1565.           if (you.inventory[index]==object)
  1566.           {
  1567.  
  1568.           switch(you.inventory[index])
  1569.                 {
  1570.  
  1571.                 case LAMP_ID:
  1572.                      {
  1573.                      printf("\nI don't think I can fit this 6 foot long lamp in my mouth!\n");
  1574.                      return(1);
  1575.                      } break;
  1576.  
  1577.                 case KEYS_ID:
  1578.                      {
  1579.                      printf("\nIf you say so...gulp\n");
  1580.  
  1581.                      // extract keys from pocket
  1582.  
  1583.                      you.inventory[index]= EMPTY_ID;
  1584.  
  1585.                      // decrement number of objects on player
  1586.  
  1587.                      you.num_objects--;
  1588.  
  1589.                      return(1);
  1590.  
  1591.                      } break;
  1592.  
  1593.                 case SANDWICH_ID:
  1594.                      {
  1595.                      printf("\nThat was good, but it needed more mustard.\n");
  1596.  
  1597.                      // extract sanwich from pocket
  1598.  
  1599.                      you.inventory[index]= EMPTY_ID;
  1600.  
  1601.                      // decrement number of objects on player
  1602.  
  1603.                      you.num_objects--;
  1604.  
  1605.                      return(1);
  1606.  
  1607.                      } break;
  1608.  
  1609.                 } // end switch pockets
  1610.  
  1611.           } // end if this is the object
  1612.  
  1613.           } // end for index
  1614.  
  1615.       // didn't find the object
  1616.  
  1617.       printf("\nI would really like to eat that, but you don't seem to have one.\n");
  1618.  
  1619.       return(1);
  1620.  
  1621.       } // end if object is valid
  1622.    else
  1623.       {
  1624.       printf("\nI don't understand what you want me to eat?");
  1625.       return(0);
  1626.  
  1627.       } // end else invalid object
  1628.  
  1629.    } // end else
  1630.  
  1631. } // end Verb_EAT
  1632.  
  1633. ////////////////////////////////////////////////////////////////////////////////
  1634.  
  1635. int Verb_WHERE(void)
  1636. {
  1637. // the function tells the player where he is
  1638.  
  1639. // based on the tile the player is standing on in the geometry array
  1640. // indicate where he is
  1641.  
  1642. if (num_tokens==1)
  1643.     {
  1644.     // what room is player in
  1645.  
  1646.     switch(universe_geometry[you.y][you.x])
  1647.           {
  1648.  
  1649.           case 'l': //- living room
  1650.              {
  1651.              printf("\n\nYou are in the living room");
  1652.              } break;
  1653.  
  1654.           case 'b': //- bedroom
  1655.              {
  1656.              printf("\n\nYou are in the bedroom");
  1657.              } break;
  1658.  
  1659.           case 'k': //- kitchen
  1660.              {
  1661.              printf("\n\nYou are in the kitchen");
  1662.              } break;
  1663.  
  1664.           case 'w': //- washroom
  1665.              {
  1666.              printf("\n\nYou are in the washroom");
  1667.              } break;
  1668.  
  1669.           case 'h': //- hall way
  1670.              {
  1671.              printf("\n\nYou are in the hallway");
  1672.              } break;
  1673.  
  1674.           case 'r': //- restroom
  1675.              {
  1676.              printf("\n\nYou are in the master bathroom");
  1677.              } break;
  1678.  
  1679.           case 'e': //- entry way
  1680.              {
  1681.              printf("\n\nYou are in the entry way");
  1682.              } break;
  1683.  
  1684.           case 'o': //- office
  1685.              {
  1686.              printf("\n\nYou are in the computer office");
  1687.              } break;
  1688.  
  1689.           default:break;
  1690.  
  1691.           } // end switch
  1692.  
  1693.  
  1694.     // now state the direction
  1695.  
  1696.     switch(you.direction)
  1697.           {
  1698.  
  1699.           case EAST:
  1700.                {
  1701.                printf(" facing East.\n");
  1702.                } break;
  1703.  
  1704.           case WEST:
  1705.                {
  1706.                printf(" facing West.\n");
  1707.                } break;
  1708.  
  1709.           case NORTH:
  1710.                {
  1711.                printf(" facing North.\n");
  1712.                } break;
  1713.  
  1714.           case SOUTH:
  1715.                {
  1716.                printf(" facing South.\n");
  1717.                } break;
  1718.  
  1719.           default:break;
  1720.  
  1721.           } // end switch
  1722.     return(1);
  1723.     } // end if a valid sentence structure
  1724. else
  1725.    {
  1726.  
  1727.    printf("\n%\"%s\" is an invalid sentence.",global_input);
  1728.    printf("\n%s, I just don't get it?",you.name);
  1729.    return(0);
  1730.    } // end else invalid
  1731.  
  1732. } // end Verb_WHERE
  1733.  
  1734. ////////////////////////////////////////////////////////////////////////////////
  1735.  
  1736. int Verb_INVENTORY(void)
  1737. {
  1738. // this function will print out the current inventory
  1739.  
  1740. int index; // loop index
  1741.  
  1742.  
  1743. // print out the inventory and then test if the player typed too many words
  1744. // if so complain a little
  1745.  
  1746. printf("\nYou have the following items within your possesion.\n");
  1747.  
  1748. // scan thru inventory array and print out the objects that the player is
  1749. // holding
  1750.  
  1751. for (index=0; index<8; index++)
  1752.     {
  1753.  
  1754.     // test if this "pocket" has an object in it
  1755.  
  1756.     switch(you.inventory[index])
  1757.           {
  1758.  
  1759.           case LAMP_ID:
  1760.                {
  1761.                printf("\nA torch lamp.");
  1762.                } break;
  1763.  
  1764.           case KEYS_ID:
  1765.                {
  1766.                printf("\nA set of car keys.");
  1767.                } break;
  1768.  
  1769.           case SANDWICH_ID:
  1770.                {
  1771.                printf("\nA turkey sandwich.");
  1772.                } break;
  1773.  
  1774.           default:break;
  1775.  
  1776.           } // end switch
  1777.  
  1778.     } // end for index
  1779.  
  1780. // test if player has nothing on him
  1781.  
  1782. if (you.num_objects==0)
  1783.    printf("\nYour pockets are empty %s.",you.name);
  1784.  
  1785. // test if there are too many words
  1786.  
  1787. if (num_tokens>1)
  1788.    printf("\n%s, all you hade to say was \"Inventory!\"",you.name);
  1789.  
  1790. return(1);
  1791.  
  1792. } // end Verb_INVENTORY
  1793.  
  1794. ////////////////////////////////////////////////////////////////////////////////
  1795.  
  1796. int Verb_EXIT(void)
  1797. {
  1798. // this function sets the global exit and terminates the game
  1799.  
  1800. global_exit=1;
  1801.  
  1802. return(1);
  1803.  
  1804. } // end Verb_EXIT
  1805.  
  1806. ////////////////////////////////////////////////////////////////////////////////
  1807.  
  1808. int Vision_System(int depth,         // depth of scan
  1809.                   int direction,     // direction of scan N,E,S,W
  1810.                   object *stuff,     // objects seen in scan
  1811.                   int *num_objects)  // number of objects seen in scan
  1812.  
  1813. {
  1814. // this function is rather complex. It is responsible for the vision of
  1815. // the player. It works by scanning a upside down pryamid of squares in
  1816. // front of the player.  The objects within this vision window will be
  1817. // returned in the objects array along withe the number of them.
  1818. // the vision window is built up by consequtively scanning rows of blocks
  1819. // in the geometry universe along with testing the objects universe for
  1820. // instances of objects. It is sort of like ray casting, but the distance
  1821. // is irrelevant and only four directions are used.  For example if the
  1822. // player was looking north and a depth of 3 was sent for the scan then the
  1823. // scan pattern would look like:
  1824. //
  1825. //       .....
  1826. //        ...
  1827. //         P
  1828. // where 'P' is the position of player and the '.' is a scanned block
  1829. // similary a scan of depth 5 to the east would like like
  1830. //      .
  1831. //      ..
  1832. //      ...
  1833. //      ....
  1834. //      ....P
  1835. //      ....
  1836. //      ...
  1837. //      ..
  1838. //      .
  1839. // note: the field of view (FOV) will always be 90 degrees
  1840. // anyway the function is basically used for the "LOOK" verb and the "GET"
  1841. // verb and I admit that the code is redundant for each case, but to merge
  1842. // it all would make it too hard to follow!
  1843.  
  1844. int x,y,           // used to hold current universe cell location
  1845.     index,         // loop index
  1846.     scan_level;    // current level or iteration of the scan
  1847.  
  1848. *num_objects=0;
  1849.  
  1850. // which direction is vision requested in?
  1851.  
  1852. switch(direction)
  1853.       {
  1854.  
  1855.       case NORTH:
  1856.            {
  1857.            // scan like this
  1858.            //  .....
  1859.            //   ...
  1860.            //    P
  1861.  
  1862.            for (y=you.y,scan_level=0; y>=(you.y-depth); y--,scan_level++)
  1863.                {
  1864.                for (x=you.x-scan_level; x<=you.x+scan_level; x++)
  1865.                    {
  1866.                    // x,y is test point, make sure it is within the universe
  1867.                    // boundaries and within the same room
  1868.  
  1869.                    if (x>=1 && x<NUM_COLUMNS-1 &&
  1870.                        y>=1 && x<NUM_ROWS-1 &&
  1871.                        universe_geometry[y][x]==universe_geometry[you.y][you.x])
  1872.  
  1873.  
  1874.                       {
  1875.                       // test to see if square has an object in it
  1876.  
  1877.                       if (universe_objects[y][x]!=' ')
  1878.                          {
  1879.                          // insert the object into object list
  1880.  
  1881.                          stuff[*num_objects].thing = universe_objects[y][x];
  1882.                          stuff[*num_objects].x     = x;
  1883.                          stuff[*num_objects].y     = y;
  1884.  
  1885.                          // increment the number of objects
  1886.  
  1887.                          (*num_objects)++;
  1888.  
  1889.                          } // end if an object was found
  1890.  
  1891.                       } // end if in boundaries
  1892.  
  1893.                    } // end for x
  1894.  
  1895.                } // end for y
  1896.  
  1897.            // return number of objects found
  1898.  
  1899.            return(*num_objects);
  1900.  
  1901.            } break;
  1902.  
  1903.       case SOUTH:
  1904.            {
  1905.            // scan like this
  1906.            //  P
  1907.            // ...
  1908.            //.....
  1909.  
  1910.            for (y=you.y,scan_level=0; y<=(you.y+depth); y++,scan_level++)
  1911.                {
  1912.                for (x=you.x-scan_level; x<=you.x+scan_level; x++)
  1913.                    {
  1914.                    // x,y is test point, make sure it is within the universe
  1915.                    // boundaries
  1916.  
  1917.                    if (x>=1 && x<NUM_COLUMNS-1 &&
  1918.                        y>=1 && x<NUM_ROWS-1 &&
  1919.                        universe_geometry[y][x]==universe_geometry[you.y][you.x])
  1920.                       {
  1921.                       // test to see if square has an object in it
  1922.  
  1923.                       if (universe_objects[y][x]!=' ')
  1924.                          {
  1925.                          // insert the object into object list
  1926.  
  1927.                          stuff[*num_objects].thing = universe_objects[y][x];
  1928.                          stuff[*num_objects].x     = x;
  1929.                          stuff[*num_objects].y     = y;
  1930.  
  1931.                          // increment the number of objects
  1932.  
  1933.                          (*num_objects)++;
  1934.  
  1935.                          } // end if an object was found
  1936.  
  1937.                       } // end if in boundaries
  1938.  
  1939.                    } // end for x
  1940.  
  1941.                } // end for y
  1942.  
  1943.            // return number of objects found
  1944.  
  1945.            return(*num_objects);
  1946.  
  1947.            } break;
  1948.  
  1949.  
  1950.       case EAST:
  1951.            {
  1952.            // scan like this
  1953.            //   .
  1954.            //  ..
  1955.            // P..
  1956.            //  ..
  1957.            //   .
  1958.  
  1959.            for (x=you.x,scan_level=0; x<=(you.x+depth); x++,scan_level++)
  1960.                {
  1961.                for (y=you.y-scan_level; y<=you.y+scan_level; y++)
  1962.                    {
  1963.                    // x,y is test point, make sure it is within the universe
  1964.                    // boundaries
  1965.  
  1966.                    if (x>=1 && x<NUM_COLUMNS-1 &&
  1967.                        y>=1 && x<NUM_ROWS-1 &&
  1968.                        universe_geometry[y][x]==universe_geometry[you.y][you.x])
  1969.                       {
  1970.                       // test to see if square has an object in it
  1971.  
  1972.                       if (universe_objects[y][x]!=' ')
  1973.                          {
  1974.                          // insert the object into object list
  1975.  
  1976.                          stuff[*num_objects].thing = universe_objects[y][x];
  1977.                          stuff[*num_objects].x     = x;
  1978.                          stuff[*num_objects].y     = y;
  1979.  
  1980.                          // increment the number of objects
  1981.  
  1982.                          (*num_objects)++;
  1983.  
  1984.                          } // end if an object was found
  1985.  
  1986.                       } // end if in boundaries
  1987.  
  1988.                    } // end for y
  1989.  
  1990.                } // end for x
  1991.  
  1992.            // return number of objects found
  1993.  
  1994.            return(*num_objects);
  1995.  
  1996.            } break;
  1997.  
  1998.       case WEST:
  1999.            {
  2000.            // scan like this
  2001.            // .
  2002.            // ..
  2003.            // ..P
  2004.            // ..
  2005.            // .
  2006.            //
  2007.  
  2008.            for (x=you.x,scan_level=0; x>=(you.x-depth); x--,scan_level++)
  2009.                {
  2010.                for (y=you.y-scan_level; y<=you.y+scan_level; y++)
  2011.                    {
  2012.                    // x,y is test point, make sure it is within the universe
  2013.                    // boundaries
  2014.  
  2015.                    if (x>=1 && x<NUM_COLUMNS-1 &&
  2016.                        y>=1 && x<NUM_ROWS-1 &&
  2017.                        universe_geometry[y][x]==universe_geometry[you.y][you.x])
  2018.                       {
  2019.                       // test to see if square has an object in it
  2020.  
  2021.                       if (universe_objects[y][x]!=' ')
  2022.                          {
  2023.                          // insert the object into object list
  2024.  
  2025.                          stuff[*num_objects].thing = universe_objects[y][x];
  2026.                          stuff[*num_objects].x     = x;
  2027.                          stuff[*num_objects].y     = y;
  2028.  
  2029.                          // increment the number of objects
  2030.  
  2031.                          (*num_objects)++;
  2032.  
  2033.                          } // end if an object was found
  2034.  
  2035.                       } // end if in boundaries
  2036.  
  2037.                    } // end for y
  2038.  
  2039.                } // end for x
  2040.  
  2041.            // return number of objects found
  2042.  
  2043.            return(*num_objects);
  2044.  
  2045.            } break;
  2046.  
  2047.       } // end switch direction
  2048.  
  2049. return(0);
  2050.  
  2051. } // end Vision_System
  2052.  
  2053. ////////////////////////////////////////////////////////////////////////////////
  2054.  
  2055. int Check_For_Phrase(int phrase,int index)
  2056. {
  2057. // this function is used to test for small phrases that when extracted don't
  2058. // change the measning of a sentence for example:"look to the west" and
  2059. // "loo west" and "look to west" all mean the same thing.
  2060.  
  2061. // test which phrase is to be checked
  2062.  
  2063. switch(phrase)
  2064.       {
  2065.       case PHRASE_TO: // have we found the prep. "to"
  2066.            {
  2067.  
  2068.            if (sentence[index]==PREP_TO)
  2069.               return(1);
  2070.  
  2071.            } break;
  2072.  
  2073.       case PHRASE_THE: // have we found the article "the"
  2074.            {
  2075.  
  2076.            if (sentence[index]==ART_THE)
  2077.               return(1);
  2078.  
  2079.            } break;
  2080.  
  2081.  
  2082.      case PHRASE_DOWN: // have we found the prep/adj "down"
  2083.           {
  2084.  
  2085.           if (sentence[index]==PREP_DOWN)
  2086.              return(1);
  2087.  
  2088.           } break;
  2089.  
  2090.       case PHRASE_TO_THE: // have we found the prep. phrase "to the"
  2091.            {
  2092.  
  2093.            if (sentence[index]==PREP_TO)
  2094.               {
  2095.               if (sentence[index+1]==ART_THE)
  2096.                   return(1);
  2097.               else
  2098.                   return(0);
  2099.               } // end if got "to the"
  2100.            } break;
  2101.  
  2102.       case PHRASE_DOWN_THE: // have we found the prep. phrase "down the"
  2103.            {
  2104.  
  2105.            if (sentence[index]==PREP_DOWN)
  2106.               {
  2107.               if (sentence[index+1]==ART_THE)
  2108.                   return(1);
  2109.               else
  2110.                   return(0);
  2111.               } // end if got "down the"
  2112.            } break;
  2113.  
  2114.  
  2115.       default:break; // there is a serious problem!
  2116.  
  2117.       } // end switch
  2118.  
  2119. // we have failed
  2120.  
  2121. return(0);
  2122.  
  2123. } // end Check_For_Phrase
  2124.  
  2125. ///////////////////////////////////////////////////////////////////////////////
  2126.  
  2127. void Print_Info_Strings(info_string strings[],char where)
  2128. {
  2129. // this function will print the info strings out of the sent array based
  2130. // on the the current location of the player i.e. bedroom, kitchen etc.
  2131.  
  2132. int index=0;
  2133.  
  2134. printf("\n");
  2135.  
  2136. // traverse list and print all string relating to this room
  2137.  
  2138. while(strings[index].type!='X')
  2139.      {
  2140.  
  2141.      // should this string be printed
  2142.  
  2143.      if (strings[index].type==where)
  2144.         {
  2145.  
  2146.         printf("\n%s",strings[index].string);
  2147.  
  2148.         } // end if this is a relevant string
  2149.  
  2150.      // next string
  2151.  
  2152.      index++;
  2153.  
  2154.      } // end while
  2155.  
  2156. printf("\n");
  2157.  
  2158. } // end Print_Info_Strings
  2159.  
  2160. ///////////////////////////////////////////////////////////////////////////////
  2161.  
  2162. void Introduction(void)
  2163. {
  2164.  
  2165. int index;
  2166.  
  2167. for (index=0; index<50; index++,printf("\n"));
  2168.  
  2169. // make the screen blue with white characters
  2170. // only works with ansi driver
  2171.  
  2172. printf("%c%c37;44m",27,91);
  2173.  
  2174. printf("\n     SSSSSSSSSS  H      H  AAAAAAAA  DDDDD     OOOOOOOO  W       W");
  2175. printf("\n     S           H      H  A      A  D    D    O      O  W       W");
  2176. printf("\n     S           H      H  A      A  D     D   O      O  W       W");
  2177. printf("\n     S           H      H  A      A  D      D  O      O  W       W");
  2178. printf("\n     S           H      H  A      A  D      D  O      O  W       W");
  2179. printf("\n     SSSSSSSSSS  HHHHHHHH  AAAAAAAA  D      D  O      O  W       W");
  2180. printf("\n              S  H      H  A      A  D      D  O      O  W       W");
  2181. printf("\n              S  H      H  A      A  D      D  O      O  W   W   W");
  2182. printf("\n              S  H      H  A      A  D      D  O      O  W   W   W");
  2183. printf("\n              S  H      H  A      A  D     D   O      O  W   W   W");
  2184. printf("\n              S  H      H  A      A  D    D    O      O  W   W   W");
  2185. printf("\n     SSSSSSSSSS  H      H  A      A  DDDDD     OOOOOOOO  WWWWWWWWW");
  2186. printf("\n                                                                  ");
  2187. printf("\n     L         AAAAAAA  NNNNNNN  DDDDDD                           ");
  2188. printf("\n     L         A     A  N     N  D     D                          ");
  2189. printf("\n     L         A     A  N     N  D      D                         ");
  2190. printf("\n     L         A     A  N     N  D      D                         ");
  2191. printf("\n     L         AAAAAAA  N     N  D      D                         ");
  2192. printf("\n     L         A     A  N     N  D      D                         ");
  2193. printf("\n     L         A     A  N     N  D     D                          ");
  2194. printf("\n     L         A     A  N     N  D    D                           ");
  2195. printf("\n     LLLLLLL   A     A  N     N  DDDDD                            ");
  2196. printf("\n                                                                  ");
  2197. printf("\n     By Andre' LaMothe                                            ");
  2198.  
  2199.  
  2200. while(!kbhit());
  2201.  
  2202. for (index=0; index<50; index++,printf("\n"));
  2203.  
  2204. } // end Introduction
  2205.  
  2206. // M A I N /////////////////////////////////////////////////////////////////////
  2207.  
  2208. void main(void)
  2209. {
  2210.  
  2211. // call up intro
  2212.  
  2213. Introduction();
  2214.  
  2215. printf("\n\nWelcome to the world of  S H A D O W  L A N D...\n\n\n");
  2216.  
  2217. // obtain users name to make game more personal
  2218.  
  2219. printf("\nWhat is your first name?");
  2220. scanf("%s",you.name);
  2221.  
  2222. // main event loop,note: it is NOT real-time
  2223.  
  2224. while(!global_exit)
  2225.      {
  2226.      // put up an input notice to user
  2227.  
  2228.      printf("\n\nWhat do you want to do?");
  2229.  
  2230.      // get the line of text
  2231.  
  2232.      Get_Line(global_input);
  2233.  
  2234.      printf("\n");
  2235.  
  2236.      // break the text down into tokens and build up a sentence
  2237.  
  2238.      Extract_Tokens(global_input);
  2239.  
  2240.      // parse the verb and execute the command
  2241.  
  2242.      Verb_Parser();
  2243.  
  2244.      } // end main event loop
  2245.  
  2246. printf("\n\nExiting the universe of S H A D O W  L A N D...see you later %s.\n",you.name);
  2247.  
  2248. // restore screen color
  2249.  
  2250. printf("%c%c37;40m",27,91);
  2251.  
  2252. } // end main
  2253.  
  2254.  
  2255.