eris2010

Documentation: http://frombelow.net/projects/eris2010/
Clone: git clone https://git.frombelow.net/eris2010.git
Log | Files | Refs | README | LICENSE

adventure.c (22959B)


      1 /*
      2  * Source: https://github.com/jefftranter/6502
      3  *
      4  * Minor changes by Gerd Beuster (gerd@frombelow.net) in order to get
      5  * it to work on Eris 2010.
      6  *
      7  * The Abandoned Farm House Adventure
      8  *
      9  * Jeff Tranter <tranter@pobox.com>
     10  *
     11  * Written in standard C but designed to run on the Apple Replica 1
     12  * or Apple II using the CC65 6502 assembler.
     13  *
     14  * Copyright 2012-2015 Jeff Tranter
     15  *
     16  * Licensed under the Apache License, Version 2.0 (the "License");
     17  * you may not use this file except in compliance with the License.
     18  * You may obtain a copy of the License at
     19  *
     20  *     http://www.apache.org/licenses/LICENSE-2.0
     21  *
     22  * Unless required by applicable law or agreed to in writing, software
     23  * distributed under the License is distributed on an "AS IS" BASIS,
     24  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     25  * See the License for the specific language governing permissions and
     26  * limitations under the License.
     27  *
     28  * Revision History:
     29  *
     30  * Version  Date         Comments
     31  * -------  ----         --------
     32  * 0.0      13 Mar 2012  First alpha version
     33  * 0.1      18 Mar 2012  First beta version
     34  * 0.9      19 Mar 2012  First public release
     35  * 1.0      06 Sep 2015  Lower case and other Apple II improvements.
     36  *
     37  */
     38 
     39 #include <ctype.h>
     40 #include <stdlib.h>
     41 #include <string.h>
     42 #ifdef __CC65__
     43 #include <conio.h>
     44 #endif
     45 
     46 /* CONSTANTS */
     47 
     48 /* Maximum number of items user can carry */
     49 #define MAXITEMS 5
     50 
     51 /* Number of locations */
     52 #define NUMLOCATIONS 32
     53 
     54 /* TYPES */
     55 
     56 /* To optimize for code size and speed, most numbers are 8-bit chars when compiling for CC65. */
     57 #ifdef __CC65__
     58 typedef char number;
     59 #else
     60 typedef int number;
     61 #endif
     62 
     63 /* Directions */
     64 typedef enum {
     65     North,
     66     South,
     67     East,
     68     West,
     69     Up,
     70     Down
     71 } Direction_t;
     72 
     73 /* Items */
     74 typedef enum {
     75     NoItem,
     76     Key,
     77     Pitchfork,
     78     Flashlight,
     79     Lamp,
     80     Oil,
     81     Candybar,
     82     Bottle,
     83     Doll,
     84     ToyCar,
     85     Matches,
     86     GoldCoin,
     87     SilverCoin,
     88     StaleMeat,
     89     Book,
     90     Cheese,
     91     OldRadio,
     92     LastItem=OldRadio
     93 } Item_t;
     94 
     95 /* Locations */
     96 typedef enum {
     97     NoLocation,
     98     Driveway1,
     99     Driveway2,
    100     Driveway3,
    101     Driveway4,
    102     Driveway5,
    103     Garage,
    104     WorkRoom,
    105     Hayloft,
    106     Kitchen,
    107     DiningRoom,
    108     BottomStairs,
    109     DrawingRoom,
    110     Study,
    111     TopStairs,
    112     BoysBedroom,
    113     GirlsBedroom,
    114     MasterBedroom,
    115     ServantsQuarters,
    116     LaundryRoom,
    117     FurnaceRoom,
    118     VacantRoom,
    119     Cistern,
    120     Tunnel,
    121     Woods24,
    122     Woods25,
    123     Woods26,
    124     WolfTree,
    125     Woods28,
    126     Woods29,
    127     Woods30,
    128     Woods31,
    129 } Location_t;
    130 
    131 /* TABLES */
    132 
    133 /* Names of directions */
    134 char *DescriptionOfDirection[] = {
    135     "north", "south", "east", "west", "up", "down"
    136 };
    137 
    138 /* Names of items */
    139 char *DescriptionOfItem[LastItem+1] = {
    140     "",
    141     "key",
    142     "pitchfork",
    143     "flashlight",
    144     "lamp",
    145     "oil",
    146     "candybar",
    147     "bottle",
    148     "doll",
    149     "toy car",
    150     "matches",
    151     "gold coin",
    152     "silver coin",
    153     "stale meat",
    154     "book",
    155     "cheese",
    156     "old radio",
    157 };
    158 
    159 /* Names of locations */
    160 char *DescriptionOfLocation[NUMLOCATIONS] = {
    161     "",
    162     "in the driveway near your car",
    163     "in the driveway",
    164     "in front of the garage",
    165     "in front of the barn",
    166     "at the door to the house",
    167     "in the garage",
    168     "in the workroom of the barn",
    169     "in the hayloft of the barn",
    170     "in the kitchen",
    171     "in the dining room",
    172     "at the bottom of the stairs",
    173     "in the drawing room",
    174     "in the study",
    175     "at the top of the stairs",
    176     "in a boy's bedroom",
    177     "in a girl's bedroom",
    178     "in the master bedroom next to\r\na bookcase",
    179     "in the servant's quarters",
    180     "in the basement laundry room",
    181     "in the furnace room",
    182     "in a vacant room next to a\r\nlocked door",
    183     "in the cistern",
    184     "in an underground tunnel. There are rats here",
    185     "in the woods near a trapdoor",
    186     "in the woods",
    187     "in the woods",
    188     "in the woods next to a tree",
    189     "in the woods",
    190     "in the woods",
    191     "in the woods",
    192     "in the woods",
    193 };
    194 
    195 /* DATA */
    196 
    197 /* Inventory of what player is carrying */
    198 Item_t Inventory[MAXITEMS];
    199 
    200 /* Location of each item. Index is the item number, returns the location. 0 if item is gone */
    201 Location_t locationOfItem[LastItem+1];
    202 
    203 /* Map. Given a location and a direction to move, returns the location it connects to, or 0 if not a valid move. Map can change during game play. */
    204 Direction_t Move[NUMLOCATIONS][6] = {
    205     /* N  S  E  W  U  D */
    206     {  0, 0, 0, 0, 0, 0 }, /* 0 */
    207     {  2, 0, 0, 0, 0, 0 }, /* 1 */
    208     {  4, 1, 3, 5, 0, 0 }, /* 2 */
    209     {  0, 0, 6, 2, 0, 0 }, /* 3 */
    210     {  7, 2, 0, 0, 0, 0 }, /* 4 */
    211     {  0, 0, 2, 9, 0, 0 }, /* 5 */
    212     {  0, 0, 0, 3, 0, 0 }, /* 6 */
    213     {  0, 4, 0, 0, 8, 0 }, /* 7 */
    214     {  0, 0, 0, 0, 0, 7 }, /* 8 */
    215     {  0,10, 5, 0, 0,19 }, /* 9 */
    216     {  9, 0, 0,11, 0, 0 }, /* 10 */
    217     {  0, 0,10,12,14, 0 }, /* 11 */
    218     { 13, 0,11, 0, 0, 0 }, /* 12 */
    219     {  0,12, 0, 0, 0, 0 }, /* 13 */
    220     { 16, 0,15,17, 0,11 }, /* 14 */
    221     {  0, 0, 0,14, 0, 0 }, /* 15 */
    222     {  0,14, 0, 0, 0, 0 }, /* 16 */
    223     {  0, 0,14, 0, 0, 0 }, /* 17 */
    224     {  0, 0, 0, 0, 0,13 }, /* 18 */
    225     {  0, 0, 0,20, 9, 0 }, /* 19 */
    226     { 21, 0,19, 0, 0, 0 }, /* 20 */
    227     {  0,20, 0,22, 0, 0 }, /* 21 */
    228     {  0, 0,21, 0, 0, 0 }, /* 22 */
    229     { 24,21, 0, 0, 0, 0 }, /* 23 */
    230     { 29,23, 0,26, 0, 0 }, /* 24 */
    231     { 26, 0,24, 0, 0, 0 }, /* 25 */
    232     { 27,25,29, 0, 0, 0 }, /* 26 */
    233     {  0,26,28, 0, 0, 0 }, /* 27 */
    234     {  0,29,31,27, 0, 0 }, /* 28 */
    235     { 28,24,30,26, 0, 0 }, /* 29 */
    236     { 31, 0, 0,29, 0, 0 }, /* 30 */
    237     {  0,30, 0,29, 0, 0 }, /* 31 */
    238 };
    239 
    240 /* Current location */
    241 number currentLocation;
    242 
    243 /* Number of turns played in game */
    244 int turnsPlayed;
    245 
    246 /* True if player has lit the lamp. */
    247 number lampLit;
    248 
    249 /* True if lamp filled with oil. */
    250 number lampFilled;
    251 
    252 /* True if player ate food. */
    253 number ateFood;
    254 
    255 /* True if player drank water. */
    256 number drankWater;
    257 
    258 /* Incremented each turn you are in the tunnel. */
    259 number ratAttack;
    260 
    261 /* Tracks state of wolf attack */
    262 number wolfState;
    263 
    264 /* Set when game is over */
    265 number gameOver;
    266 
    267 const char *introText = "     Abandoned Farmhouse Adventure\r\n           By Jeff Tranter\r\n\r\nYour three-year-old grandson has gone\r\nmissing and was last seen headed in the\r\ndirection of the abandoned family farm.\r\nIt's a dangerous place to play. You\r\nhave to find him before he gets hurt,\r\nand it will be getting dark soon...\r\n";
    268 
    269 const char *helpString = "Valid commands:\r\ngo east/west/north/south/up/down \r\nlook\r\nuse <object>\r\nexamine <object>\r\ntake <object>\r\ndrop <object>\r\ninventory\r\nhelp\r\nquit\r\nYou can abbreviate commands and\r\ndirections to the first letter.\r\nType just the first letter of\r\na direction to move.\r\n";
    270 
    271 /* Line of user input */
    272 char buffer[40];
    273 
    274 // gb: Not available in conio, therefore added.
    275 void gets(char *s) {
    276   char c;
    277   while ((c = cgetc()) != '\r') {
    278     cputc(c);
    279     *s = c;
    280     s++;
    281   }
    282   *s = '\0';
    283   cputs("\r\n");
    284 };
    285 
    286 /* Clear the screen */
    287 void clearScreen()
    288 {
    289 #if defined(__APPLE2__)
    290     clrscr();
    291 #else
    292     number i;
    293     for (i = 0; i < 24; ++i)
    294         cprintf("\r\n");
    295 #endif
    296 }
    297 
    298 /* Return 1 if carrying an item */
    299 number carryingItem(char *item)
    300 {
    301     number i;
    302 
    303     for (i = 0; i < MAXITEMS; i++) {
    304         if ((Inventory[i] != 0) && (!strcasecmp(DescriptionOfItem[Inventory[i]], item)))
    305             return 1;
    306     }
    307     return 0;
    308 }
    309 
    310 /* Return 1 if item it at current location (not carried) */
    311 number itemIsHere(char *item)
    312 {
    313     number i;
    314 
    315     /* Find number of the item. */
    316     for (i = 1; i <= LastItem; i++) {
    317         if (!strcasecmp(item, DescriptionOfItem[i])) {
    318             /* Found it, but is it here? */
    319             if (locationOfItem[i] == currentLocation) {
    320                 return 1;
    321             } else {
    322                 return 0;
    323             }
    324         }
    325     }
    326     return 0;
    327 }
    328 
    329 /* Inventory command */
    330 void doInventory()
    331 {
    332     number i;
    333     int found = 0;
    334 
    335     cprintf("%s", "You are carrying:\r\n");
    336     for (i = 0; i < MAXITEMS; i++) {
    337         if (Inventory[i] != 0) {
    338             cprintf("  %s\r\n", DescriptionOfItem[Inventory[i]]);
    339             found = 1;
    340         }
    341     }
    342     if (!found)
    343         cprintf("  nothing\r\n");
    344 }
    345 
    346 /* Help command */
    347 void doHelp()
    348 {
    349     cprintf("%s", helpString);
    350 }
    351 
    352 /* Look command */
    353 void doLook()
    354 {
    355     number i, loc, seen;
    356 
    357     cprintf("You are %s.\r\n", DescriptionOfLocation[currentLocation]);
    358 
    359     seen = 0;
    360     cprintf("You see:\r\n");
    361     for (i = 1; i <= LastItem; i++) {
    362         if (locationOfItem[i] == currentLocation) {
    363             cprintf("  %s\r\n", DescriptionOfItem[i]);
    364             seen = 1;
    365         }
    366     }
    367     if (!seen)
    368         cprintf("  nothing special\r\n");
    369 
    370     cprintf("You can go:");
    371 
    372     for (i = North; i <= Down; i++) {
    373         loc = Move[currentLocation][i];
    374         if (loc != 0) {
    375             cprintf(" %s", DescriptionOfDirection[i]);
    376         }
    377     }
    378     cprintf("\r\n");
    379 }
    380 
    381 /* Quit command */
    382 void doQuit()
    383 {
    384     cprintf("%s", "Are you sure you want to quit (y/n)? ");
    385     gets(buffer);
    386     if (tolower(buffer[0]) == 'y') {
    387         gameOver = 1;
    388     }
    389 }
    390 
    391 /* Drop command */
    392 void doDrop()
    393 {
    394     number i;
    395     char *sp;
    396     char *item;
    397 
    398     /* Command line should be like "D[ROP] ITEM" Item name will be after after first space. */
    399     sp = strchr(buffer, ' ');
    400     if (sp == NULL) {
    401         cprintf("Drop what?\r\n");
    402         return;
    403     }
    404 
    405     item = sp + 1;
    406 
    407     /* See if we have this item */
    408     for (i = 0; i < MAXITEMS; i++) {
    409         if ((Inventory[i] != 0) && (!strcasecmp(DescriptionOfItem[Inventory[i]], item))) {
    410             /* We have it. Add to location. */
    411             locationOfItem[Inventory[i]] = currentLocation;
    412             /* And remove from inventory */
    413             Inventory[i] = 0;
    414             cprintf("Dropped %s.\r\n", item);
    415             ++turnsPlayed;
    416             return;
    417         }
    418     }
    419     /* If here, don't have it. */
    420     cprintf("Not carrying %s.\r\n", item);
    421 }
    422 
    423 /* Take command */
    424 void doTake()
    425 {
    426     number i, j;
    427     char *sp;
    428     char *item;
    429 
    430     /* Command line should be like "T[AKE] ITEM" Item name will be after after first space. */
    431     sp = strchr(buffer, ' ');
    432     if (sp == NULL) {
    433         cprintf("Take what?\r\n");
    434         return;
    435     }
    436 
    437     item = sp + 1;
    438 
    439     if (carryingItem(item)) {
    440         cprintf("Already carrying it.\r\n");
    441         return;
    442     }
    443 
    444     /* Find number of the item. */
    445     for (i = 1; i <= LastItem; i++) {
    446         if (!strcasecmp(item, DescriptionOfItem[i])) {
    447             /* Found it, but is it here? */
    448             if (locationOfItem[i] == currentLocation) {
    449             /* It is here. Add to inventory. */
    450             for (j = 0; j < MAXITEMS; j++) {
    451                 if (Inventory[j] == 0) {
    452                     Inventory[j] = i;
    453                     /* And remove from location. */
    454                     locationOfItem[i] = 0;
    455                     cprintf("Took %s.\r\n", item);
    456                     ++turnsPlayed;
    457                     return;
    458                 }
    459             }
    460 
    461             /* Reached maximum number of items to carry */
    462             cprintf("You can't carry any more. Drop something.\r\n");
    463             return;
    464             }
    465         }
    466     }
    467 
    468     /* If here, don't see it. */
    469     cprintf("I see no %s here.\r\n", item);
    470 }
    471 
    472 /* Go command */
    473 void doGo()
    474 {
    475     char *sp;
    476     char dirChar;
    477     Direction_t dir;
    478 
    479     /* Command line should be like "G[O] N[ORTH]" Direction will be
    480        the first letter after a space. Or just a single letter
    481        direction N S E W U D or full directon NORTH etc. */
    482 
    483     sp = strrchr(buffer, ' ');
    484     if (sp != NULL) {
    485         dirChar = *(sp+1);
    486     } else {
    487         dirChar = buffer[0];
    488     }
    489     dirChar = tolower(dirChar);
    490 
    491     if (dirChar == 'n') {
    492         dir = North;
    493     } else if (dirChar == 's') {
    494         dir = South;
    495     } else if (dirChar == 'e') {
    496         dir = East;
    497     } else if (dirChar == 'w') {
    498         dir = West;
    499     } else if (dirChar == 'u') {
    500         dir = Up;
    501     } else if (dirChar == 'd') {
    502         dir = Down;
    503     } else {
    504         cprintf("Go where?\r\n");
    505         return;
    506     }
    507 
    508     if (Move[currentLocation][dir] == 0) {
    509         cprintf("You can't go %s from here.\r\n", DescriptionOfDirection[dir]);
    510         return;
    511     }
    512 
    513     /* We can move */
    514     currentLocation = Move[currentLocation][dir];
    515     cprintf("You are %s.\r\n", DescriptionOfLocation[currentLocation]);
    516     ++turnsPlayed;
    517 }
    518 
    519 /* Examine command */
    520 void doExamine()
    521 {
    522     char *sp;
    523     char *item;
    524 
    525     /* Command line should be like "E[XAMINE] ITEM" Item name will be after after first space. */
    526     sp = strchr(buffer, ' ');
    527     if (sp == NULL) {
    528         cprintf("Examine what?\r\n");
    529         return;
    530     }
    531 
    532     item = sp + 1;
    533     ++turnsPlayed;
    534 
    535     /* Examine bookcase - not an object */
    536     if (!strcasecmp(item, "bookcase")) {
    537         cprintf("You pull back a book and the bookcase\r\nopens up to reveal a secret room.\r\n");
    538         Move[17][North] = 18;
    539         return;
    540     }
    541 
    542     /* Make sure item is being carried or is in the current location */
    543     if (!carryingItem(item) && !itemIsHere(item)) {
    544         cprintf("I don't see it here.\r\n");
    545         return;
    546     }
    547 
    548     /* Examine Book */
    549     if (!strcasecmp(item, "book")) {
    550         cprintf("It is a very old book entitled\r\n\"Apple 1 operation manual\".\r\n");
    551         return;
    552     }
    553 
    554     /* Examine Flashlight */
    555     if (!strcasecmp(item, "flashlight")) {
    556         cprintf("It doesn't have any batteries.\r\n");
    557         return;
    558     }
    559 
    560     /* Examine toy car */
    561     if (!strcasecmp(item, "toy car")) {
    562         cprintf("It is a nice toy car.\r\nYour grandson Matthew would like it.\r\n");
    563         return;
    564     }
    565 
    566     /* Examine old radio */
    567     if (!strcasecmp(item, "old radio")) {
    568         cprintf("It is a 1940 Zenith 8-S-563 console\r\nwith an 8A02 chassis. You'd turn it on\r\nbut the electricity is off.\r\n");
    569         return;
    570     }
    571 
    572    /* Nothing special about this item */
    573    cprintf("You see nothing special about it.\r\n");
    574 }
    575 
    576 /* Use command */
    577 void doUse()
    578 {
    579     char *sp;
    580     char *item;
    581 
    582     /* Command line should be like "U[SE] ITEM" Item name will be after after first space. */
    583     sp = strchr(buffer, ' ');
    584     if (sp == NULL) {
    585         cprintf("Use what?\r\n");
    586         return;
    587     }
    588 
    589     item = sp + 1;
    590 
    591     /* Make sure item is being carried or is in the current location */
    592     if (!carryingItem(item) && !itemIsHere(item)) {
    593         cprintf("I don't see it here.\r\n");
    594         return;
    595     }
    596 
    597     ++turnsPlayed;
    598 
    599     /* Use key */
    600     if (!strcasecmp(item, "key") && (currentLocation == VacantRoom)) {
    601         cprintf("You insert the key in the door and it\r\nopens, revealing a tunnel.\r\n");
    602         Move[21][North] = 23;
    603         return;
    604     }
    605 
    606     /* Use pitchfork */
    607     if (!strcasecmp(item, "pitchfork") && (currentLocation == WolfTree) && (wolfState == 0)) {
    608         cprintf("You jab the wolf with the pitchfork.\r\nIt howls and runs away.\r\n");
    609         wolfState = 1;
    610         return;
    611     }
    612 
    613     /* Use toy car */
    614     if (!strcasecmp(item, "toy car") && (currentLocation == WolfTree && wolfState == 1)) {
    615         cprintf("You show Matthew the toy car and he\r\ncomes down to take it. You take Matthew\r\nin your arms and carry him home.\r\n");
    616         wolfState = 2;
    617         return;
    618     }
    619 
    620     /* Use oil */
    621     if (!strcasecmp(item, "oil")) {
    622         if (carryingItem("lamp")) {
    623             cprintf("You fill the lamp with oil.\r\n");
    624             lampFilled = 1;
    625             return;
    626         } else {
    627             cprintf("You don't have anything to use it with.\r\n");
    628             return;
    629         }
    630     }
    631 
    632     /* Use matches */
    633     if (!strcasecmp(item, "matches")) {
    634         if (carryingItem("lamp")) {
    635             if (lampFilled) {
    636                 cprintf("You light the lamp. You can see!\r\n");
    637                 lampLit = 1;
    638                 return;
    639             } else {
    640                 cprintf("You can't light the lamp. It needs oil.\r\n");
    641                 return;
    642             }
    643         } else {
    644             cprintf("Nothing here to light\r\n");
    645         }
    646     }
    647 
    648     /* Use candybar */
    649     if (!strcasecmp(item, "candybar")) {
    650         cprintf("That hit the spot. You no longer feel\r\nhungry.\r\n");
    651         ateFood = 1;
    652         return;
    653     }
    654 
    655     /* Use bottle */
    656     if (!strcasecmp(item, "bottle")) {
    657         if (currentLocation == Cistern) {
    658             cprintf("You fill the bottle with water from the\r\ncistern and take a drink. You no longer\r\nfeel thirsty.\r\n");
    659             drankWater = 1;
    660             return;
    661         } else {
    662             cprintf("The bottle is empty. If only you had\r\nsome water to fill it!\r\n");
    663             return;
    664         }
    665     }
    666 
    667     /* Use stale meat */
    668     if (!strcasecmp(item, "stale meat")) {
    669         cprintf("The meat looked and tasted bad. You\r\nfeel very sick and pass out.\r\n");
    670         gameOver = 1;
    671         return;
    672     }
    673 
    674     /* Default */
    675     cprintf("Nothing happens\r\n");
    676 }
    677 
    678 /* Prompt user and get a line of input */
    679 void prompt()
    680 {
    681     cprintf("? ");
    682     gets(buffer);
    683 
    684     /* Remove trailing newline */
    685     // gb: Already removed
    686     // buffer[strlen(buffer)-1] = '\0';
    687 }
    688 
    689 /* Do special things unrelated to command typed. */
    690 void doActions()
    691 {
    692     if ((turnsPlayed == 10) && !lampLit) {
    693         cprintf("It will be getting dark soon. You need\r\nsome kind of light or soon you won't\r\nbe able to see.\r\n");
    694     }
    695 
    696     if ((turnsPlayed >= 60) && (!lampLit || (!itemIsHere("lamp") && !carryingItem("lamp")))) {
    697         cprintf("It is dark out and you have no light.\r\nYou stumble around for a while and\r\nthen fall, hit your head, and pass out.\r\n");
    698         gameOver = 1;
    699         return;
    700     }
    701 
    702     if ((turnsPlayed == 20) && !drankWater) {
    703         cprintf("You are getting very thirsty.\r\nYou need to get a drink soon.\r\n");
    704     }
    705 
    706     if ((turnsPlayed == 30) && !ateFood) {
    707         cprintf("You are getting very hungry.\r\nYou need to find something to eat.\r\n");
    708     }
    709 
    710     if ((turnsPlayed == 50) && !drankWater) {
    711         cprintf("You pass out due to thirst.\r\n");
    712         gameOver = 1;
    713         return;
    714     }
    715 
    716     if ((turnsPlayed == 40) && !ateFood) {
    717         cprintf("You pass out from hunger.\r\n");
    718         gameOver = 1;
    719         return;
    720     }
    721 
    722     if (currentLocation == Tunnel) {
    723         if (itemIsHere("cheese")) {
    724             cprintf("The rats go after the cheese.\r\n");
    725         } else {
    726             if (ratAttack < 3) {
    727                 cprintf("The rats are coming towards you!\r\n");
    728                 ++ratAttack;
    729             } else {
    730                 cprintf("The rats attack and you pass out.\r\n");
    731                 gameOver = 1;
    732                 return;
    733             }
    734         }
    735     }
    736 
    737     /* wolfState values:  0 - wolf attacking 1 - wolf gone, Matthew in tree. 2 - Matthew safe, you won. Game over. */
    738     if (currentLocation == WolfTree) {
    739         switch (wolfState) {
    740             case 0:
    741                 cprintf("A wolf is circling around the tree.\r\nMatthew is up in the tree. You have to\r\nsave him! If only you had some kind of\r\nweapon!\r\n");
    742                 break;
    743             case 1:
    744                 cprintf("Matthew is afraid to come\r\ndown from the tree. If only you had\r\nsomething to coax him with.\r\n");
    745                 break;
    746             case 2:
    747                 cprintf("Congratulations! You succeeded and won\r\nthe game. I hope you had as much fun\r\nplaying the game as I did creating it.\r\n- Jeff Tranter <tranter@pobox.com>\r\n");
    748                 gameOver = 1;
    749                 return;
    750                 break;
    751             }
    752     }
    753 }
    754 
    755 /* Set variables to values for start of game */
    756 void initialize()
    757 {
    758     currentLocation = Driveway1;
    759     lampFilled = 0;
    760     lampLit = 0;
    761     ateFood = 0;
    762     drankWater = 0;
    763     ratAttack = 0;
    764     wolfState = 0;
    765     turnsPlayed = 0;
    766     gameOver= 0;
    767 
    768     /* These doors can get changed during game and may need to be reset O*/
    769     Move[17][North] = 0;
    770     Move[21][North] = 0;
    771 
    772     /* Set inventory to default */
    773     memset(Inventory, 0, sizeof(Inventory[0])*MAXITEMS);
    774     Inventory[0] = Flashlight;
    775 
    776     /* Put items in their default locations */
    777     locationOfItem[0]  = 0;                /* NoItem */
    778     locationOfItem[1]  = Driveway1;        /* Key */
    779     locationOfItem[2]  = Hayloft;          /* Pitchfork */
    780     locationOfItem[3]  = 0;                /* Flashlight */
    781     locationOfItem[4]  = WorkRoom;         /* Lamp */
    782     locationOfItem[5]  = Garage;           /* Oil */
    783     locationOfItem[6]  = Kitchen;          /* Candybar */
    784     locationOfItem[7]  = Driveway2;        /* Bottle */
    785     locationOfItem[8]  = GirlsBedroom;     /* Doll */
    786     locationOfItem[9]  = BoysBedroom;      /* ToyCar */
    787     locationOfItem[10] = ServantsQuarters; /* Matches */
    788     locationOfItem[11] = Woods25;          /* GoldCoin */
    789     locationOfItem[12] = Woods29;          /* SilverCoin */
    790     locationOfItem[13] = DiningRoom;       /* StaleMeat */
    791     locationOfItem[14] = DrawingRoom;      /* Book */
    792     locationOfItem[15] = LaundryRoom;      /* Cheese */
    793     locationOfItem[16] = MasterBedroom;    /* OldRadio */
    794 }
    795 
    796 /* Main program (obviously) */
    797 int main(void)
    798 {
    799     while (1) {
    800         initialize();
    801         clearScreen();
    802         cprintf("%s", introText);
    803 
    804         while (!gameOver) {
    805             prompt();
    806             if (buffer[0] == '\0') {
    807             } else if (tolower(buffer[0]) == 'h') {
    808                 doHelp();
    809             } else if (tolower(buffer[0]) == 'i') {
    810                 doInventory();
    811             } else if ((tolower(buffer[0]) == 'g')
    812                        || !strcasecmp(buffer, "n") || !strcasecmp(buffer, "s")
    813                        || !strcasecmp(buffer, "e") || !strcasecmp(buffer, "w")
    814                        || !strcasecmp(buffer, "u") || !strcasecmp(buffer, "d")
    815                        || !strcasecmp(buffer, "north") || !strcasecmp(buffer, "south")
    816                        || !strcasecmp(buffer, "east") || !strcasecmp(buffer, "west")
    817                        || !strcasecmp(buffer, "up") || !strcasecmp(buffer, "down")) {
    818                 doGo();
    819             } else if (tolower(buffer[0]) == 'l') {
    820                 doLook();
    821             } else if (tolower(buffer[0]) == 't') {
    822                 doTake();
    823             } else if (tolower(buffer[0]) == 'e') {
    824                 doExamine();
    825             } else if (tolower(buffer[0]) == 'u') {
    826                 doUse();
    827             } else if (tolower(buffer[0]) == 'd') {
    828                 doDrop();
    829             } else if (tolower(buffer[0]) == 'q') {
    830                 doQuit();
    831             } else if (!strcasecmp(buffer, "xyzzy")) {
    832                 cprintf("Nice try, but that won't work here.\r\n");
    833             } else {
    834                 cprintf("I don't understand. Try 'help'.\r\n");
    835             }
    836 
    837             /* Handle special actions. */
    838             doActions();
    839         }
    840 
    841         cprintf("Game over after %d turns.\r\n", turnsPlayed);
    842         cprintf("%s", "Do you want to play again (y/n)? ");
    843         gets(buffer);
    844         if (tolower(buffer[0]) == 'n') {
    845             break;
    846         }
    847     }
    848     return 0;
    849 }