/* program TURN.C */ #include #include #include "advent.h" #include "advdec.h" _PROTOTYPE(void descitem, (void)); _PROTOTYPE(void domove, (void)); _PROTOTYPE(void goback, (void)); _PROTOTYPE(void copytrv, (struct trav *, struct trav *)); _PROTOTYPE(void dotrav, (void)); _PROTOTYPE(void badmove, (void)); _PROTOTYPE(void spcmove, (int)); _PROTOTYPE(void death, (void)); _PROTOTYPE(void dwarves, (void)); _PROTOTYPE(void dopirate, (void)); _PROTOTYPE(int stimer, (void)); _PROTOTYPE(void do_hint, (int)); /* Routine to take 1 turn */ void turn() { int i, hint; static int waste = 0; if (newtravel) { /* If closing, then he can't leave except via the main office. */ if (outside(g.newloc) && g.newloc != 0 && g.closing) { rspeak(130); g.newloc = g.loc; if (!g.panic) g.clock2 = 15; g.panic = TRUE; } /* See if a dwarf has seen him and has come from where he wants to go. */ if (g.newloc != g.loc && !forced(g.loc) && g.loc_attrib[g.loc] & NOPIRAT == 0) for (i = 1; i < (DWARFMAX - 1); ++i) if (g.odloc[i] == g.newloc && g.dseen[i]) { g.newloc = g.loc; rspeak(2); break; } g.loc = g.newloc; dwarves(); /* & special dwarf(pirate who steals) */ /* Check for death */ if (g.loc == 0) { death(); return; } /* Check for forced move */ if (forced(g.loc)) { desclg(g.loc); ++g.visited[g.loc]; domove(); return; } /* Check for wandering in dark */ if (g.wzdark && dark() && pct(35)) { rspeak(23); g.oldloc2 = g.loc; death(); return; } /* see if he is wasting his batteies out in the open */ if (outside(g.loc) && g.prop[LAMP]) { waste++; if (waste > 11) { rspeak(324); waste = 0; } } else waste = 0; /* If wumpus is chasing stooge, see if wumpus gets him */ if (g.chase) { g.chase++; g.prop[WUMPUS] = g.chase / 2; move(WUMPUS, g.loc); if (g.chase >= 10) { if (dark()) rspeak(270); pspeak(WUMPUS, 5); death(); return; } } /* check for radiation poisoning. */ g.health += (outside(g.loc)) ? 3 : 1; if (g.health > 100) g.health = 100; if (here(RADIUM) && (g.place[RADIUM] != -SHIELD || ajar(SHIELD))) g.health -= 7; if (g.health < 60) { rspeak(391 + (60 - g.health) / 10); if (g.health < 0) { death(); return; } } if ((g.oldloc == 188) && (g.loc != 188 && g.loc != 189) && (g.prop[BOOTH] == 1)) { move(GNOME, 0); g.prop[BOOTH] = 0; } /* Describe his situation */ describe(); if (!blind()) { ++g.visited[g.loc]; descitem(); } } /* end of newtravel start for second entry point */ /* Check if this location is eligible for any hints. If been here long enough, branch to help section. Ignore "hints" < HNTMIN (special stuff, see database notes. */ for (hint = HNTMIN; hint <= HNTMAX; hint++) { if (g.hinted[hint]) continue; if (g.loc_attrib[g.loc] / 256 != hint - 6) g.hintlc[hint] = -1; g.hintlc[hint]++; if (g.hintlc[hint] >= g.hints[hint][1]) do_hint(hint); } if (g.closed) { if (g.prop[OYSTER] < 0 && toting(OYSTER)) pspeak(OYSTER, 1); for (i = 1; i < MAXOBJ; ++i) if (toting(i) && g.prop[i] < 0) g.prop[i] = -1 - g.prop[i]; } g.wzdark = dark(); if (g.knfloc > 0 && g.knfloc != g.loc) g.knfloc = 0; ++g.turns; i = rand(); if (stimer()) /* as the grains of sand slip by */ return; while (!english()) /* retrieve player instructions */ ; vrbx = 1; objx = objs[1] ? 1 : 0; iobx = iobjs[1] ? 1 : 0; verb = VAL(verbs[vrbx]); do { object = objx ? objs[objx] : 0; iobj = iobx ? iobjs[iobx] : 0; if (object && (objs[2] || iobjs[2])) { pspeak(object, -1); printf(" "); } switch (CLASS(verbs[vrbx])) { case MOTION: motion = verb; domove(); break; case NOUN: bug(22); case ACTION: if (object || iobj) trverb(); else itverb(); break; case MISC: rspeak(verb); if (verb == 51) g.hinted[1] = TRUE; break; default: bug(22); } if (objx) { objx++; if (objs[objx] == 0) objx = 0; } if ((!objx || !objs[objx]) && iobx) { iobx++; if (iobjs[iobx] == 0) iobx = 0; if (iobx && iobjs[1]) objx = 1; } } while (objx || iobx); return; } /* Routine to describe current location */ void describe() { if (toting(BEAR)) rspeak(141); if (dark()) rspeak(16); else if ((g.terse && verb != LOOK) || g.visited[g.loc] % g.abbnum) descsh(g.loc); else desclg(g.loc); if (g.loc == 33 && pct(25) && !g.closing) rspeak(8); if (g.loc == 147 && !g.visited[g.loc]) rspeak(216); return; } /* Routine to describe visible items */ void descitem() { int i, state; for (i = 1; i < MAXOBJ; ++i) { if (at(i)) { if (i == STEPS && toting(NUGGET)) continue; if (g.prop[i] < 0) { if (g.closed) continue; else { g.prop[i] = 0; if (i == RUG || i == CHAIN || i == SWORD || i == CASK) g.prop[i] = 1; if (i == CLOAK || i == RING) g.prop[i] = 2; --g.tally; } } if (i == STEPS && g.loc == g.fixed[STEPS]) state = 1; else state = g.prop[i] % 8; pspeak(i, state); lookin(i); } } /* If remaining treasures too elusive, zap his lamp */ if (g.tally == g.tally2 && g.tally != 0 && g.limit > 35) g.limit = 35; return; } /* Routine to handle player's demise via waking up the dwarves... */ void dwarfend() { rspeak(136); normend(); return; } /* normal end of game */ void normend() { score(FALSE); gaveup = TRUE; return; } /* Routine to handle the passing on of one of the player's incarnations... */ void death() { int yea, j; if (!g.closing) { if (g.limit < 0) { rspeak(185); normend(); return; } yea = yes(81 + g.numdie * 2, 82 + g.numdie * 2, 54); if (++g.numdie >= MAXDIE || !yea) normend(); if (g.chase) { g.chase = FALSE; g.prop[WUMPUS] = 0; move(WUMPUS, 174); } if (toting(LAMP)) g.prop[LAMP] = 0; for (j = 1; j < MAXOBJ; ++j) { if (toting(j)) drop(j, j == LAMP ? 1 : g.oldloc2); if (wearng(j)) { g.prop[j] = 0; bitoff(j, WEARBT); } } g.newloc = 3; g.oldloc = g.loc; g.health = 100; return; } /* Closing -- no resurrection... */ rspeak(131); ++g.numdie; normend(); return; } /* dwarf stuff. */ void dwarves() { int i, j, k, attack, stick, dtotal; /* See if dwarves allowed here */ if (g.newloc == 0 || forced(g.newloc) || g.loc_attrib[g.newloc] & NOPIRAT) return; /* See if dwarves are active. */ if (!g.dflag) { if (inside(g.newloc)) ++g.dflag; return; } /* If first close encounter (of 3rd kind) */ if (g.dflag == 1) { if (!inside(g.newloc) || pct(85)) return; ++g.dflag; /* kill 0, 1 or 2 of the dwarfs */ for (i = 1; i < 3; ++i) if (pct(50)) g.dloc[(ranz(DWARFMAX - 1)) + 1] = 0; /* If any of the survivors is at location, use alternate choise */ for (i = 1; i <= DWARFMAX; ++i) { if (g.dloc[i] == g.newloc) g.dloc[i] = g.daltloc; g.odloc[i] = g.dloc[i]; } rspeak(3); drop(AXE, g.newloc); return; } /* Things are in full swing. Move each dwarf at random, except if he's seen us then he sticks with us. Dwarfs never go to locations outside or meet the bear or following him into dead end in maze. And of couse, dead dwarves don't do much of anything. */ dtotal = attack = stick = 0; for (i = 1; i <= DWARFMAX; ++i) { if (g.dloc[i] == 0) continue; /* Move a dwarf at random. we don't have a matrix around to do it as in the original version... */ do j = ranz(106) + 15; /* allowed area */ while (j == g.odloc[i] || j == g.dloc[i] || g.loc_attrib[j] & NOPIRAT); if (j == 0) bug(36); g.odloc[i] = g.dloc[i]; g.dloc[i] = j; g.dseen[i] = ((g.dseen[i] && inside(g.newloc)) || g.dloc[i] == g.newloc || g.odloc[i] == g.newloc); if (g.dseen[i]) { g.dloc[i] = g.newloc; if (i == DWARFMAX) dopirate(); else { ++dtotal; if (g.odloc[i] == g.dloc[i]) { ++attack; if (g.knfloc >= 0) g.knfloc = g.newloc; if (ranz(1000) < (45 * (g.dflag - 2))) ++stick; } } } } /* Now we know shat's happing, let's tell the poor sucker about it */ if (dtotal == 0) return; if (dtotal > 1) printf("There are %d threatening little dwarves in the room with you!\n", dtotal); else rspeak(4); if (attack == 0) return; if (g.dflag == 2) ++g.dflag; if (attack > 1) { printf("%d of them throw knives at you!!\n", attack); k = 6; } else { rspeak(5); k = 52; } if (stick <= 1) { rspeak(stick + k); if (stick == 0) return; } else printf("%d of them get you !!!\n", stick); g.oldloc2 = g.newloc; death(); return; } /* pirate stuff */ void dopirate() { int j; boolean k; if (g.newloc == g.chloc || g.prop[CHEST] >= 0) return; k = FALSE; /* Pirate won't take pyramid from plover room or dark room (too easy! ) */ for (j = 1; j < MAXOBJ; ++j) if (treasr(j) && !(j == CASK && liq(CASK) == WINE) && !(j == PYRAMID && (g.newloc == g.place[PYRAMID] || g.newloc == g.place[EMERALD]))) { if (toting(j) && athand(j)) goto stealit; if (here(j)) k = TRUE; } if (g.tally == g.tally2 + 1 && k == FALSE && g.place[CHEST] == 0 && athand(LAMP) && g.prop[LAMP] == 1) { rspeak(186); move(CHEST, g.chloc); move(MESSAGE, g.chloc2); g.dloc[DWARFMAX] = g.chloc; g.odloc[DWARFMAX] = g.chloc; g.dseen[DWARFMAX] = 0; return; } if (g.odloc[DWARFMAX] != g.dloc[DWARFMAX] && pct(30)) rspeak(127); return; stealit: rspeak(128); /* don't steal chest back from troll! */ if (g.place[MESSAGE] == 0) move(CHEST, g.chloc); move(MESSAGE, g.chloc2); for (j = 1; j < MAXOBJ; ++j) { if (!treasr(j) || !athand(j) || (j == PYRAMID && (g.newloc == plac[PYRAMID] || g.newloc == plac[EMERALD])) || (j == CASK && (liq(CASK) != WINE))) continue; if (enclosed(j)) extract(j); if (wearng(j)) { g.prop[j] = 0; bitoff(j, WEARBT); } insert(j, CHEST); } g.dloc[DWARFMAX] = g.chloc; g.odloc[DWARFMAX] = g.chloc; g.dseen[DWARFMAX] = FALSE; return; } /* special time limit stuff... */ int stimer() { int i, spk; static int clock3; g.foobar = g.foobar > 0 ? -g.foobar : 0; g.combo = g.combo > 0 ? -g.combo : 0; if (g.turns > 310 && g.abbnum != 10000 && !g.terse) rspeak(273); /* Bump all the right clocks for reconning battery life and closing */ if (g.closed) { clock3--; if (clock3 == 0) { g.prop[PHONE] = 0; g.prop[BOOTH] = 0; rspeak(284); } else if (clock3 < -7) { rspeak(254); normend(); return (TRUE); } } if (g.tally == 0 && inside(g.loc) && g.loc != Y2) --g.clock; if (g.clock == 0) { /* Start closing the cave */ g.prop[GRATE] = 0; biton(GRATE, LOCKBT); bitoff(GRATE, OPENBT); g.prop[FISSURE] = 0; g.prop[TDOOR] = 0; biton(TDOOR, LOCKBT); bitoff(TDOOR, OPENBT); g.prop[TDOOR2] = 0; biton(TDOOR2, LOCKBT); bitoff(TDOOR2, OPENBT); for (i = 1; i <= DWARFMAX; ++i) { g.dseen[i] = FALSE; g.dloc[i] = 0; } move(TROLL, 0); move((TROLL + MAXOBJ), 0); move(TROLL2, plac[TROLL]); move((TROLL2 + MAXOBJ), fixd[TROLL]); juggle(CHASM); if (g.prop[BEAR] != 3) destroy(BEAR); g.prop[CHAIN] = 0; g.fixed[CHAIN] = 0; g.prop[AXE] = 0; g.fixed[AXE] = 0; rspeak(129); g.clock = -1; g.closing = TRUE; return (FALSE); } if (g.clock < 0) --g.clock2; if (g.clock2 == 0) { /* Set up storage room... and close the cave... */ g.prop[BOTTLE] = put(BOTTLE, 115, 8); g.holder[BOTTLE] = WATER; g.place[WATER] = -BOTTLE; g.hlink[WATER] = 0; bitoff(BOTTLE, OPENBT); g.prop[PLANT] = put(PLANT, 115, 0); g.prop[OYSTER] = put(OYSTER, 115, 0); g.prop[LAMP] = put(LAMP, 115, 0); g.prop[ROD] = put(ROD, 115, 0); g.prop[DWARF] = put(DWARF, 115, 0); g.loc = 115; g.oldloc = 115; g.newloc = 115; /* Leave the grate with normal (non-negative property). */ put(GRATE, 116, 0); biton(GRATE, LOCKBT); bitoff(GRATE, OPENBT); g.prop[SNAKE] = put(SNAKE, 116, 1); g.prop[BIRD] = put(BIRD, 116, 1); g.prop[CAGE] = put(CAGE, 116, 0); g.prop[ROD2] = put(ROD2, 116, 0); g.prop[PILLOW] = put(PILLOW, 116, 0); g.prop[BOOTH] = put(BOOTH, 116, -3); g.fixed[BOOTH] = 115; g.prop[PHONE] = put(PHONE, 212, -4); g.prop[MIRROR] = put(MIRROR, 115, 0); g.fixed[MIRROR] = 116; g.prop[BOOK2] = put(BOOK2, 115, 0); for (i = 1; i < MAXOBJ; ++i) { if (toting(i) && enclosed(i)) extract(i); if (toting(i)) destroy(i); } rspeak(132); g.closed = TRUE; clock3 = 20 + ranz(20); newtravel = TRUE; return (TRUE); } if (g.prop[LAMP] == 1) --g.limit; if (g.limit == 0) { --g.limit; g.prop[LAMP] = 0; if (here(LAMP)) rspeak(184); return (FALSE); } if (g.limit < 0 && outside(g.loc)) { rspeak(185); normend(); return (TRUE); } if (g.limit <= 40) { if (g.lmwarn || !here(LAMP)) return (FALSE); g.lmwarn = TRUE; spk = 187; if (g.prop[BATTERIES] == 1) spk = 323; if (g.place[BATTERIES] == 0) spk = 183; if (g.prop[VEND] == 1) spk = 189; rspeak(spk); return (FALSE); } return (FALSE); } /* HINTS come here if he's been long enough at required location(s) for some unused hint, hint number is in variable "hint". Branch to quick test for additional conditions, then do neet stuff. If conditions are met and we want to offer hint. Clear hintlc if no action is taken. */ #define MASE 1 #define DARK 2 #define WITT 3 #define H_SWORD 4 #define SLIDE 5 #define H_GRATE 6 #define H_BIRD 7 #define H_ELFIN 8 #define RNBOW 9 #define STYX 10 #define H_SNAKE 11 #define CASTLE 12 void do_hint(hint) int hint; { g.hintlc[hint] = 0; switch (hint + 1 - HNTMIN) { case MASE: if (!at(g.loc) && !at(g.oldloc) && !at(g.loc) && burden(0) > 1) break; else return; case DARK: if (g.prop[EMERALD] != -1 && g.prop[PYRAMID] == -1) break; else return; case WITT: break; case H_SWORD: if ((g.prop[SWORD] == 1 || g.prop[SWORD] == 5) && !toting(CROWN)) break; else return; case SLIDE: break; case H_GRATE: if (g.prop[GRATE] == 0 && !athand(KEYS)) break; else return; case H_BIRD: if (here(BIRD) && athand(ROD) && object == BIRD) break; else return; case H_ELFIN: if (!g.visited[159]) break; else return; case RNBOW: if (!toting(SHOES) || g.visited[205]) break; else return; case STYX: if (!athand(LYRE) && g.prop[DOG] != 1) break; else return; case H_SNAKE: if (here(SNAKE) && !here(BIRD)) break; else return; case CASTLE: break; default: printf(" TRYING TO PRINT HINT # %d\n", hint); bug(27); } if (!yes(g.hints[hint][3], 0, 54)) return; printf("\nI am prepared to give you a hint,"); printf(" but it will cost you %2d points\n", g.hints[hint][2]); g.hinted[hint] = yes(175, g.hints[hint][4], 54); if (g.hinted[hint] && g.limit > 30) g.limit += 30 * g.hints[hint][2]; return; }