turn.c

Go to the documentation of this file.
00001 /*      program TURN.C                                          */
00002 
00003 
00004 #include        <stdio.h>
00005 #include        <stdlib.h>
00006 #include        "advent.h"
00007 #include        "advdec.h"
00008 
00009 _PROTOTYPE(void descitem, (void));
00010 _PROTOTYPE(void domove, (void));
00011 _PROTOTYPE(void goback, (void));
00012 _PROTOTYPE(void copytrv, (struct trav *, struct trav *));
00013 _PROTOTYPE(void dotrav, (void));
00014 _PROTOTYPE(void badmove, (void));
00015 _PROTOTYPE(void spcmove, (int));
00016 _PROTOTYPE(void death, (void));
00017 _PROTOTYPE(void dwarves, (void));
00018 _PROTOTYPE(void dopirate, (void));
00019 _PROTOTYPE(int stimer, (void));
00020 _PROTOTYPE(void do_hint, (int));
00021 
00022 
00023 /*
00024   Routine to take 1 turn
00025 */
00026 void turn()
00027 {
00028     int i, hint;
00029     static int waste = 0;
00030 
00031     if (newtravel) {
00032         /* If closing, then he can't leave except via the main office. */
00033         if (outside(g.newloc) && g.newloc != 0 && g.closing) {
00034             rspeak(130);
00035             g.newloc = g.loc;
00036             if (!g.panic)
00037                 g.clock2 = 15;
00038             g.panic = TRUE;
00039         }
00040         /* See if a dwarf has seen him and has come from where he wants
00041            to go. */
00042         if (g.newloc != g.loc && !forced(g.loc) && g.loc_attrib[g.loc] & NOPIRAT == 0)
00043             for (i = 1; i < (DWARFMAX - 1); ++i)
00044                 if (g.odloc[i] == g.newloc && g.dseen[i]) {
00045                     g.newloc = g.loc;
00046                     rspeak(2);
00047                     break;
00048                 }
00049 
00050         g.loc = g.newloc;
00051         dwarves();                      /* & special dwarf(pirate who
00052                                            steals)       */
00053 
00054         /* Check for death */
00055         if (g.loc == 0) {
00056             death();
00057             return;
00058         }
00059         /* Check for forced move */
00060         if (forced(g.loc)) {
00061             desclg(g.loc);
00062             ++g.visited[g.loc];
00063             domove();
00064             return;
00065         }
00066         /* Check for wandering in dark */
00067         if (g.wzdark && dark() && pct(35)) {
00068             rspeak(23);
00069             g.oldloc2 = g.loc;
00070             death();
00071             return;
00072         }
00073         /* see if he is wasting his batteies out in the open */
00074         if (outside(g.loc) && g.prop[LAMP]) {
00075             waste++;
00076             if (waste > 11) {
00077                 rspeak(324);
00078                 waste = 0;
00079             }
00080         } else
00081             waste = 0;
00082 
00083         /* If wumpus is chasing stooge, see if wumpus gets him */
00084         if (g.chase) {
00085             g.chase++;
00086             g.prop[WUMPUS] = g.chase / 2;
00087             move(WUMPUS, g.loc);
00088             if (g.chase >= 10) {
00089                 if (dark())
00090                     rspeak(270);
00091                 pspeak(WUMPUS, 5);
00092                 death();
00093                 return;
00094             }
00095         }
00096         /* check for radiation poisoning. */
00097         g.health += (outside(g.loc)) ? 3 : 1;
00098         if (g.health > 100)
00099             g.health = 100;
00100         if (here(RADIUM) && (g.place[RADIUM] != -SHIELD || ajar(SHIELD)))
00101             g.health -= 7;
00102         if (g.health < 60) {
00103             rspeak(391 + (60 - g.health) / 10);
00104             if (g.health < 0) {
00105                 death();
00106                 return;
00107             }
00108         }
00109         if ((g.oldloc == 188) && (g.loc != 188 && g.loc != 189)
00110             && (g.prop[BOOTH] == 1)) {
00111             move(GNOME, 0);
00112             g.prop[BOOTH] = 0;
00113         }
00114         /* Describe his situation */
00115         describe();
00116         if (!blind()) {
00117             ++g.visited[g.loc];
00118             descitem();
00119         }
00120     }                                   /* end of newtravel start for
00121                                            second entry point */
00122     /* Check if this location is eligible for any hints.  If been here
00123        long enough, branch to help section. Ignore "hints" < HNTMIN
00124        (special stuff, see database notes. */
00125     for (hint = HNTMIN; hint <= HNTMAX; hint++) {
00126         if (g.hinted[hint])
00127             continue;
00128         if (g.loc_attrib[g.loc] / 256 != hint - 6)
00129             g.hintlc[hint] = -1;
00130         g.hintlc[hint]++;
00131         if (g.hintlc[hint] >= g.hints[hint][1])
00132             do_hint(hint);
00133     }
00134 
00135     if (g.closed) {
00136         if (g.prop[OYSTER] < 0 && toting(OYSTER))
00137             pspeak(OYSTER, 1);
00138         for (i = 1; i < MAXOBJ; ++i)
00139             if (toting(i) && g.prop[i] < 0)
00140                 g.prop[i] = -1 - g.prop[i];
00141     }
00142     g.wzdark = dark();
00143     if (g.knfloc > 0 && g.knfloc != g.loc)
00144         g.knfloc = 0;
00145     ++g.turns;
00146     i = rand();
00147 
00148     if (stimer())                       /* as the grains of sand slip
00149                                            by */
00150         return;
00151 
00152     while (!english())                  /* retrieve player instructions  */
00153         ;
00154 
00155     vrbx = 1;
00156     objx = objs[1] ? 1 : 0;
00157     iobx = iobjs[1] ? 1 : 0;
00158     verb = VAL(verbs[vrbx]);
00159     do {
00160         object = objx ? objs[objx] : 0;
00161         iobj = iobx ? iobjs[iobx] : 0;
00162         if (object && (objs[2] || iobjs[2])) {
00163             pspeak(object, -1);
00164             printf("      ");
00165         }
00166         switch (CLASS(verbs[vrbx])) {
00167         case MOTION:
00168             motion = verb;
00169             domove();
00170             break;
00171         case NOUN:
00172             bug(22);
00173         case ACTION:
00174             if (object || iobj)
00175                 trverb();
00176             else
00177                 itverb();
00178             break;
00179         case MISC:
00180             rspeak(verb);
00181             if (verb == 51)
00182                 g.hinted[1] = TRUE;
00183             break;
00184         default:
00185             bug(22);
00186         }
00187         if (objx) {
00188             objx++;
00189             if (objs[objx] == 0)
00190                 objx = 0;
00191         }
00192         if ((!objx || !objs[objx]) && iobx) {
00193             iobx++;
00194             if (iobjs[iobx] == 0)
00195                 iobx = 0;
00196             if (iobx && iobjs[1])
00197                 objx = 1;
00198         }
00199     } while (objx || iobx);
00200     return;
00201 }
00202 
00203 /*
00204   Routine to describe current location
00205 */
00206 void describe()
00207 {
00208     if (toting(BEAR))
00209         rspeak(141);
00210     if (dark())
00211         rspeak(16);
00212     else if ((g.terse && verb != LOOK) || g.visited[g.loc] % g.abbnum)
00213         descsh(g.loc);
00214     else
00215         desclg(g.loc);
00216     if (g.loc == 33 && pct(25) && !g.closing)
00217         rspeak(8);
00218     if (g.loc == 147 && !g.visited[g.loc])
00219         rspeak(216);
00220     return;
00221 }
00222 
00223 /*
00224   Routine to describe visible items
00225 */
00226 void descitem()
00227 {
00228     int i, state;
00229 
00230     for (i = 1; i < MAXOBJ; ++i) {
00231         if (at(i)) {
00232             if (i == STEPS && toting(NUGGET))
00233                 continue;
00234             if (g.prop[i] < 0) {
00235                 if (g.closed)
00236                     continue;
00237                 else {
00238                     g.prop[i] = 0;
00239                     if (i == RUG || i == CHAIN
00240                         || i == SWORD || i == CASK)
00241                         g.prop[i] = 1;
00242                     if (i == CLOAK || i == RING)
00243                         g.prop[i] = 2;
00244                     --g.tally;
00245                 }
00246             }
00247             if (i == STEPS && g.loc == g.fixed[STEPS])
00248                 state = 1;
00249             else
00250                 state = g.prop[i] % 8;
00251             pspeak(i, state);
00252             lookin(i);
00253         }
00254     }
00255     /* If remaining treasures too elusive, zap his lamp */
00256     if (g.tally == g.tally2 && g.tally != 0 && g.limit > 35)
00257         g.limit = 35;
00258     return;
00259 }
00260 
00261 /*
00262   Routine to handle player's demise via
00263   waking up the dwarves...
00264 */
00265 void dwarfend()
00266 {
00267     rspeak(136);
00268     normend();
00269     return;
00270 }
00271 
00272 /*
00273   normal end of game
00274 */
00275 void normend()
00276 {
00277     score(FALSE);
00278     gaveup = TRUE;
00279     return;
00280 }
00281 
00282 /*
00283   Routine to handle the passing on of one
00284   of the player's incarnations...
00285 */
00286 void death()
00287 {
00288     int yea, j;
00289 
00290     if (!g.closing) {
00291         if (g.limit < 0) {
00292             rspeak(185);
00293             normend();
00294             return;
00295         }
00296         yea = yes(81 + g.numdie * 2, 82 + g.numdie * 2, 54);
00297         if (++g.numdie >= MAXDIE || !yea)
00298             normend();
00299         if (g.chase) {
00300             g.chase = FALSE;
00301             g.prop[WUMPUS] = 0;
00302             move(WUMPUS, 174);
00303         }
00304         if (toting(LAMP))
00305             g.prop[LAMP] = 0;
00306         for (j = 1; j < MAXOBJ; ++j) {
00307             if (toting(j))
00308                 drop(j, j == LAMP ? 1 : g.oldloc2);
00309             if (wearng(j)) {
00310                 g.prop[j] = 0;
00311                 bitoff(j, WEARBT);
00312             }
00313         }
00314         g.newloc = 3;
00315         g.oldloc = g.loc;
00316         g.health = 100;
00317         return;
00318     }
00319     /* Closing -- no resurrection... */
00320     rspeak(131);
00321     ++g.numdie;
00322     normend();
00323     return;
00324 }
00325 
00326 /*
00327   dwarf stuff.
00328 */
00329 void dwarves()
00330 {
00331     int i, j, k, attack, stick, dtotal;
00332 
00333     /* See if dwarves allowed here */
00334     if (g.newloc == 0 || forced(g.newloc) || g.loc_attrib[g.newloc] & NOPIRAT)
00335         return;
00336 
00337     /* See if dwarves are active. */
00338     if (!g.dflag) {
00339         if (inside(g.newloc))
00340             ++g.dflag;
00341         return;
00342     }
00343     /* If first close encounter (of 3rd kind) */
00344     if (g.dflag == 1) {
00345         if (!inside(g.newloc) || pct(85))
00346             return;
00347         ++g.dflag;
00348 
00349         /* kill 0, 1 or 2 of the dwarfs */
00350         for (i = 1; i < 3; ++i)
00351             if (pct(50))
00352                 g.dloc[(ranz(DWARFMAX - 1)) + 1] = 0;
00353 
00354         /* If any of the survivors is at location, use alternate choise */
00355         for (i = 1; i <= DWARFMAX; ++i) {
00356             if (g.dloc[i] == g.newloc)
00357                 g.dloc[i] = g.daltloc;
00358             g.odloc[i] = g.dloc[i];
00359         }
00360         rspeak(3);
00361         drop(AXE, g.newloc);
00362         return;
00363     }
00364     /* Things are in full swing.  Move each dwarf at random, except if
00365        he's seen us then he sticks with us.  Dwarfs never go to
00366        locations outside or meet the bear or following him into dead
00367        end in maze.  And of couse, dead dwarves don't do much of
00368        anything.  */
00369 
00370     dtotal = attack = stick = 0;
00371     for (i = 1; i <= DWARFMAX; ++i) {
00372         if (g.dloc[i] == 0)
00373             continue;
00374         /* Move a dwarf at random.  we don't have a matrix around to do
00375            it as in the original version... */
00376         do
00377             j = ranz(106) + 15;
00378         /* allowed area */
00379         while (j == g.odloc[i] || j == g.dloc[i]
00380                || g.loc_attrib[j] & NOPIRAT);
00381 
00382         if (j == 0)
00383             bug(36);
00384         g.odloc[i] = g.dloc[i];
00385         g.dloc[i] = j;
00386 
00387         g.dseen[i] = ((g.dseen[i] && inside(g.newloc))
00388                       || g.dloc[i] == g.newloc
00389                       || g.odloc[i] == g.newloc);
00390 
00391         if (g.dseen[i]) {
00392             g.dloc[i] = g.newloc;
00393             if (i == DWARFMAX)
00394                 dopirate();
00395             else {
00396                 ++dtotal;
00397                 if (g.odloc[i] == g.dloc[i]) {
00398                     ++attack;
00399                     if (g.knfloc >= 0)
00400                         g.knfloc = g.newloc;
00401                     if (ranz(1000) < (45 * (g.dflag - 2)))
00402                         ++stick;
00403                 }
00404             }
00405         }
00406     }
00407 
00408     /* Now we know shat's happing, let's tell the poor sucker about it */
00409     if (dtotal == 0)
00410         return;
00411     if (dtotal > 1)
00412         printf("There are %d threatening little dwarves in the room with you!\n", dtotal);
00413     else
00414         rspeak(4);
00415     if (attack == 0)
00416         return;
00417     if (g.dflag == 2)
00418         ++g.dflag;
00419     if (attack > 1) {
00420         printf("%d of them throw knives at you!!\n", attack);
00421         k = 6;
00422     } else {
00423         rspeak(5);
00424         k = 52;
00425     }
00426     if (stick <= 1) {
00427         rspeak(stick + k);
00428         if (stick == 0)
00429             return;
00430     } else
00431         printf("%d of them get you !!!\n", stick);
00432     g.oldloc2 = g.newloc;
00433     death();
00434     return;
00435 }
00436 
00437 /*
00438   pirate stuff
00439 */
00440 void dopirate()
00441 {
00442     int j;
00443     boolean k;
00444 
00445     if (g.newloc == g.chloc || g.prop[CHEST] >= 0)
00446         return;
00447     k = FALSE;
00448     /* Pirate won't take pyramid from plover room or dark room  (too
00449        easy! ) */
00450     for (j = 1; j < MAXOBJ; ++j)
00451         if (treasr(j) && !(j == CASK && liq(CASK) == WINE)
00452             && !(j == PYRAMID && (g.newloc == g.place[PYRAMID]
00453                                   || g.newloc == g.place[EMERALD]))) {
00454             if (toting(j) && athand(j))
00455                 goto stealit;
00456             if (here(j))
00457                 k = TRUE;
00458         }
00459     if (g.tally == g.tally2 + 1 && k == FALSE && g.place[CHEST] == 0 &&
00460         athand(LAMP) && g.prop[LAMP] == 1) {
00461         rspeak(186);
00462         move(CHEST, g.chloc);
00463         move(MESSAGE, g.chloc2);
00464         g.dloc[DWARFMAX] = g.chloc;
00465         g.odloc[DWARFMAX] = g.chloc;
00466         g.dseen[DWARFMAX] = 0;
00467         return;
00468     }
00469     if (g.odloc[DWARFMAX] != g.dloc[DWARFMAX] && pct(30))
00470         rspeak(127);
00471     return;
00472 
00473 stealit:
00474 
00475     rspeak(128);
00476     /* don't steal chest back from troll! */
00477     if (g.place[MESSAGE] == 0)
00478         move(CHEST, g.chloc);
00479     move(MESSAGE, g.chloc2);
00480     for (j = 1; j < MAXOBJ; ++j) {
00481         if (!treasr(j) || !athand(j)
00482             || (j == PYRAMID &&
00483              (g.newloc == plac[PYRAMID] || g.newloc == plac[EMERALD]))
00484             || (j == CASK && (liq(CASK) != WINE)))
00485             continue;
00486         if (enclosed(j))
00487             extract(j);
00488         if (wearng(j)) {
00489             g.prop[j] = 0;
00490             bitoff(j, WEARBT);
00491         }
00492         insert(j, CHEST);
00493     }
00494     g.dloc[DWARFMAX] = g.chloc;
00495     g.odloc[DWARFMAX] = g.chloc;
00496     g.dseen[DWARFMAX] = FALSE;
00497     return;
00498 }
00499 
00500 /*
00501   special time limit stuff...
00502 */
00503 int stimer()
00504 {
00505     int i, spk;
00506     static int clock3;
00507 
00508     g.foobar = g.foobar > 0 ? -g.foobar : 0;
00509     g.combo = g.combo > 0 ? -g.combo : 0;
00510     if (g.turns > 310 && g.abbnum != 10000 && !g.terse)
00511         rspeak(273);
00512 
00513     /* Bump all the right clocks for reconning battery life and closing */
00514     if (g.closed) {
00515         clock3--;
00516         if (clock3 == 0) {
00517             g.prop[PHONE] = 0;
00518             g.prop[BOOTH] = 0;
00519             rspeak(284);
00520         } else if (clock3 < -7) {
00521             rspeak(254);
00522             normend();
00523             return (TRUE);
00524         }
00525     }
00526     if (g.tally == 0 && inside(g.loc) && g.loc != Y2)
00527         --g.clock;
00528     if (g.clock == 0) {
00529         /* Start closing the cave */
00530         g.prop[GRATE] = 0;
00531         biton(GRATE, LOCKBT);
00532         bitoff(GRATE, OPENBT);
00533         g.prop[FISSURE] = 0;
00534         g.prop[TDOOR] = 0;
00535         biton(TDOOR, LOCKBT);
00536         bitoff(TDOOR, OPENBT);
00537         g.prop[TDOOR2] = 0;
00538         biton(TDOOR2, LOCKBT);
00539         bitoff(TDOOR2, OPENBT);
00540         for (i = 1; i <= DWARFMAX; ++i) {
00541             g.dseen[i] = FALSE;
00542             g.dloc[i] = 0;
00543         }
00544         move(TROLL, 0);
00545         move((TROLL + MAXOBJ), 0);
00546         move(TROLL2, plac[TROLL]);
00547         move((TROLL2 + MAXOBJ), fixd[TROLL]);
00548         juggle(CHASM);
00549         if (g.prop[BEAR] != 3)
00550             destroy(BEAR);
00551         g.prop[CHAIN] = 0;
00552         g.fixed[CHAIN] = 0;
00553         g.prop[AXE] = 0;
00554         g.fixed[AXE] = 0;
00555         rspeak(129);
00556         g.clock = -1;
00557         g.closing = TRUE;
00558         return (FALSE);
00559     }
00560     if (g.clock < 0)
00561         --g.clock2;
00562     if (g.clock2 == 0) {
00563         /* Set up storage room... and close the cave... */
00564         g.prop[BOTTLE] = put(BOTTLE, 115, 8);
00565         g.holder[BOTTLE] = WATER;
00566         g.place[WATER] = -BOTTLE;
00567         g.hlink[WATER] = 0;
00568         bitoff(BOTTLE, OPENBT);
00569         g.prop[PLANT] = put(PLANT, 115, 0);
00570         g.prop[OYSTER] = put(OYSTER, 115, 0);
00571         g.prop[LAMP] = put(LAMP, 115, 0);
00572         g.prop[ROD] = put(ROD, 115, 0);
00573         g.prop[DWARF] = put(DWARF, 115, 0);
00574         g.loc = 115;
00575         g.oldloc = 115;
00576         g.newloc = 115;
00577         /* Leave the grate with normal (non-negative property). */
00578         put(GRATE, 116, 0);
00579         biton(GRATE, LOCKBT);
00580         bitoff(GRATE, OPENBT);
00581         g.prop[SNAKE] = put(SNAKE, 116, 1);
00582         g.prop[BIRD] = put(BIRD, 116, 1);
00583         g.prop[CAGE] = put(CAGE, 116, 0);
00584         g.prop[ROD2] = put(ROD2, 116, 0);
00585         g.prop[PILLOW] = put(PILLOW, 116, 0);
00586 
00587         g.prop[BOOTH] = put(BOOTH, 116, -3);
00588         g.fixed[BOOTH] = 115;
00589         g.prop[PHONE] = put(PHONE, 212, -4);
00590 
00591         g.prop[MIRROR] = put(MIRROR, 115, 0);
00592         g.fixed[MIRROR] = 116;
00593         g.prop[BOOK2] = put(BOOK2, 115, 0);
00594 
00595         for (i = 1; i < MAXOBJ; ++i) {
00596             if (toting(i) && enclosed(i))
00597                 extract(i);
00598             if (toting(i))
00599                 destroy(i);
00600         }
00601         rspeak(132);
00602         g.closed = TRUE;
00603         clock3 = 20 + ranz(20);
00604         newtravel = TRUE;
00605         return (TRUE);
00606     }
00607     if (g.prop[LAMP] == 1)
00608         --g.limit;
00609     if (g.limit == 0) {
00610         --g.limit;
00611         g.prop[LAMP] = 0;
00612         if (here(LAMP))
00613             rspeak(184);
00614         return (FALSE);
00615     }
00616     if (g.limit < 0 && outside(g.loc)) {
00617         rspeak(185);
00618         normend();
00619         return (TRUE);
00620     }
00621     if (g.limit <= 40) {
00622         if (g.lmwarn || !here(LAMP))
00623             return (FALSE);
00624         g.lmwarn = TRUE;
00625         spk = 187;
00626         if (g.prop[BATTERIES] == 1)
00627             spk = 323;
00628         if (g.place[BATTERIES] == 0)
00629             spk = 183;
00630         if (g.prop[VEND] == 1)
00631             spk = 189;
00632         rspeak(spk);
00633         return (FALSE);
00634     }
00635     return (FALSE);
00636 }
00637 
00638 /* HINTS
00639    come here if he's been long enough at required location(s)
00640    for some unused hint,  hint number is in variable "hint".
00641    Branch to quick test for additional conditions, then
00642    do neet stuff. If conditions are met and we want to offer
00643    hint.  Clear hintlc if no action is taken.
00644  */
00645 
00646 #define MASE 1
00647 #define DARK 2
00648 #define WITT 3
00649 #define H_SWORD 4
00650 #define SLIDE 5
00651 #define H_GRATE 6
00652 #define H_BIRD 7
00653 #define H_ELFIN 8
00654 #define RNBOW 9
00655 #define STYX  10
00656 #define H_SNAKE 11
00657 #define CASTLE 12
00658 
00659 void do_hint(hint)
00660 int hint;
00661 {
00662     g.hintlc[hint] = 0;
00663     switch (hint + 1 - HNTMIN) {
00664     case MASE:
00665         if (!at(g.loc) && !at(g.oldloc)
00666             && !at(g.loc) && burden(0) > 1)
00667             break;
00668         else
00669             return;
00670     case DARK:
00671         if (g.prop[EMERALD] != -1 && g.prop[PYRAMID] == -1)
00672             break;
00673         else
00674             return;
00675     case WITT:
00676         break;
00677     case H_SWORD:
00678         if ((g.prop[SWORD] == 1 || g.prop[SWORD] == 5)
00679             && !toting(CROWN))
00680             break;
00681         else
00682             return;
00683     case SLIDE:
00684         break;
00685     case H_GRATE:
00686         if (g.prop[GRATE] == 0 && !athand(KEYS))
00687             break;
00688         else
00689             return;
00690     case H_BIRD:
00691         if (here(BIRD) && athand(ROD) && object == BIRD)
00692             break;
00693         else
00694             return;
00695     case H_ELFIN:
00696         if (!g.visited[159])
00697             break;
00698         else
00699             return;
00700     case RNBOW:
00701         if (!toting(SHOES) || g.visited[205])
00702             break;
00703         else
00704             return;
00705     case STYX:
00706         if (!athand(LYRE) && g.prop[DOG] != 1)
00707             break;
00708         else
00709             return;
00710     case H_SNAKE:
00711         if (here(SNAKE) && !here(BIRD))
00712             break;
00713         else
00714             return;
00715     case CASTLE:
00716         break;
00717     default:
00718         printf("  TRYING TO PRINT HINT # %d\n", hint);
00719         bug(27);
00720     }
00721     if (!yes(g.hints[hint][3], 0, 54))
00722         return;
00723     printf("\nI am prepared to give you a hint,");
00724     printf(" but it will cost you %2d points\n", g.hints[hint][2]);
00725     g.hinted[hint] = yes(175, g.hints[hint][4], 54);
00726     if (g.hinted[hint] && g.limit > 30)
00727         g.limit += 30 * g.hints[hint][2];
00728     return;
00729 }

Generated on Fri Apr 14 22:56:39 2006 for minix by  doxygen 1.4.6