/* program VERB.C */ #include "stdio.h" #include "advent.h" #include "advdec.h" /* Initialize default verb messages */ static _CONST int actmsg[56] = { 0, 24, 29, 0, 33, 0, 33, 38, 38, 42, 14, 43, 110, 29, 110, 73, 75, 29, 13, 59, 59, 174, 313, 67, 13, 147, 155, 369, 146, 110, 13, 13, 24, 25, 110, 262, 14, 29, 271, 14, 14, 24, 29, 38, 24, 331, 24, 109, 332, 0, 0, 348, 358, 0, 364, 0}; _PROTOTYPE(static int ck_obj, (void)); _PROTOTYPE(void von, (void)); _PROTOTYPE(void voff, (void)); _PROTOTYPE(void vwave, (void)); _PROTOTYPE(void veat, (void)); _PROTOTYPE(void vthrow, (void)); _PROTOTYPE(void vfind, (void)); _PROTOTYPE(void vfill, (void)); _PROTOTYPE(void vfeed, (void)); _PROTOTYPE(void vbreak, (void)); _PROTOTYPE(void vwake, (void)); _PROTOTYPE(void vdrop, (void)); _PROTOTYPE(void vpour, (void)); _PROTOTYPE(void vput, (void)); _PROTOTYPE(void vread, (void)); _PROTOTYPE(void vinsert, (void)); _PROTOTYPE(void vextract, (void)); _PROTOTYPE(static boolean do_battle, (int *)); _PROTOTYPE(void vhit, (void)); _PROTOTYPE(void vanswer, (void)); _PROTOTYPE(void vblow, (void)); _PROTOTYPE(void vdial, (void)); _PROTOTYPE(void vplay, (void)); _PROTOTYPE(void vpick, (void)); _PROTOTYPE(void vput, (void)); _PROTOTYPE(void vturn, (void)); _PROTOTYPE(void vget, (void)); _PROTOTYPE(void vlook, (void)); /* Routine to process a transitive verb */ void trverb() { newtravel = FALSE; switch (verb) { case NOTHING: case CALM: case WALK: case QUIT: case SCORE: case FOO: case SUSPEND: break; case TAKE: vtake(); break; case DROP: vdrop(); break; case SAY: bug(34); break; case OPEN: vopen(); break; case CLOSE: vclose(); break; case LOCK: vlock(); break; case UNLOCK: vunlock(); break; case ON: von(); break; case OFF: voff(); break; case WAVE: vwave(); break; case KILL: vkill(); break; case POUR: vpour(); break; case EAT: veat(); break; case DRINK: vdrink(); break; case RUB: if (object != LAMP) rspeak(76); else actspk(RUB); break; case THROW: if (prep == PREPDN) vput(); else vthrow(); break; case FEED: vfeed(); break; case FIND: case INVENTORY: vfind(); break; case FILL: vfill(); break; case BLAST: ivblast(); break; case READ: vread(); break; case BREAK: vbreak(); break; case WAKE: vwake(); break; case REMOVE: vextract(); break; case YANK: vyank(); break; case WEAR: vwear(); break; case HIT: vhit(); break; case ANSWER: vanswer(); break; case BLOW: vblow(); break; case DIAL: vdial(); break; case PLAY: vplay(); break; case PICK: vpick(); break; case PUT: vput(); break; case TURN: vturn(); break; case GET: vget(); break; case INSRT: vinsert(); break; case LOOK: vlook(); break; default: printf("This verb is not implemented yet.\n"); } return; } /* Routine to speak default verb message */ void actspk(verb) int verb; { int i; if (verb < 1 || verb > 55) bug(39); i = actmsg[verb]; if (i) rspeak(i); return; } /* CARRY TAKE etc. */ void vtake() { int msg; msg = 0; if (object == BIRD && !g.closed && athand(BIRD) && g.place[BIRD] != g.loc) { rspeak(407); return; } if (prep == PREPOF) { if (object && iobj) { rspeak(confuz()); return; } else if (!object) { object = iobj; iobj = 0; vdrop(); return; } } msg = 24; if (object == BOAT) msg = 281; if (plural(object)) msg = 297; if (holding(object)) { rspeak(msg); return; } /* Special case objects and fixed objects */ msg = ck_obj(); if (g.fixed[object]) { rspeak(msg); return; } if (prep == PREPIN) { vinsert(); return; } /* Special case for liquids */ if (object == WATER || object == OIL || object == WINE) { if (here(BOTTLE) && here(CASK)) { rspeak(315); return; } iobj = object; if (here(BOTTLE)) { object = BOTTLE; if (holding(BOTTLE)) vfill(); else rspeak(312); return; } else if (here(CASK)) { object = CASK; if (holding(CASK)) vfill(); else rspeak(312); return; } else { rspeak(312); return; } } if (object != BEAR && ((burden(0) + burden(object)) > 15)) { if (wearng(object)) { g.prop[object] = 0; bitoff(object, WEARBT); } rspeak(92); return; } if (prep == PREPFR || enclosed(object)) { vextract(); return; } msg = 343; /* Poster: hides wall safe */ if (object == POSTER && g.place[SAFE] == 0) { g.prop[POSTER] = 1; msg = 362; /* Move safe and wall containing safe into view */ drop(SAFE, g.loc); drop(WALL2, g.loc); } /* Boat: need the pole to push it */ if (object == BOAT) { if (!toting(POLE) && g.place[POLE] != -BOAT) { rspeak(218); return; } else { g.prop[BOAT] = 1; msg = 221; } } /* Special case for bird. */ if (object == BIRD && g.prop[BIRD] <= 0) { if (athand(ROD)) { rspeak(26); return; } if (!holding(CAGE)) { rspeak(27); return; } if (!ajar(CAGE)) { rspeak(358); return; } insert(BIRD, CAGE); bitoff(CAGE, OPENBT); pspeak(object, -1); rspeak(54); return; } /* SWORD If in anvil, need crown & must yank */ if (object == SWORD && g.prop[SWORD] != 0) { if (iobj && iobj != ANVIL) { rspeak(noway()); return; } if (verb != YANK) if (!yes(215, 0, 54)) return; if (!wearng(CROWN)) { g.fixed[SWORD] = -1; g.prop[SWORD] = 3; pspeak(SWORD, 2); return; } } carry(object, g.loc); if (object == POLE || object == SKEY || object == SWORD || ((object == CLOAK || object == RING) && !wearng(object)) ) g.prop[object] = 0; if (verb == YANK || object == SWORD) msg = 204; rspeak(msg); return; } static int ck_obj() { int msg; msg = noway(); if (object == PLANT && g.prop[PLANT] <= 0) msg = 115; if (object == BEAR && g.prop[BEAR] == 1) msg = 169; if (object == CHAIN && g.prop[BEAR] != 0) msg = 170; if (object == SWORD && g.prop[SWORD] == 5) msg = 208; if (object == CLOAK && g.prop[CLOAK] == 2) msg = 242; if (object == AXE && g.prop[AXE] == 2) msg = 246; if (object == PHONE) msg = 251; if (object == BEES || object == HIVE) msg = 295; if (object == STICKS) msg = 296; return (msg); } /* DROP etc. */ void vdrop() { int msg; /* Check for dynamite */ if (holding(ROD2) && object == ROD && !holding(ROD)) object = ROD2; if (plural(object)) msg = 105; else msg = 29; if (object == liq(BOTTLE)) object = BOTTLE; else if (object == liq(CASK)) object = CASK; if (!toting(object)) { rspeak(msg); return; } if (prep == PREPIN) { vinsert(); return; } /* Snake and bird */ if (object == BIRD && here(SNAKE)) { rspeak(30); if (g.closed) { dwarfend(); return; } extract(BIRD); destroy(SNAKE); /* Set snake prop for use by travel options */ g.prop[SNAKE] = 1; drop(BIRD, g.loc); return; } msg = 344; if (verb == LEAVE) msg = 353; if (verb == THROW) msg = 352; if (verb == TAKE) msg = 54; if (object == POLE && holding(BOAT)) { rspeak(280); return; } /* Coins and vending machine */ if (object == COINS && here(VEND)) { destroy(COINS); drop(BATTERIES, g.loc); pspeak(BATTERIES, 0); return; } /* Bird and dragon (ouch!!) */ if (object == BIRD && at(DRAGON) && g.prop[DRAGON] == 0) { rspeak(154); extract(BIRD); destroy(BIRD); if (g.place[SNAKE] == plac[SNAKE]) g.tally2++; return; } /* Bear and troll */ if (object == BEAR && at(TROLL)) { msg = 163; destroy(TROLL); destroy(TROLL + MAXOBJ); move(TROLL2, plac[TROLL]); move((TROLL2 + MAXOBJ), fixd[TROLL]); juggle(CHASM); g.prop[TROLL] = 2; } /* Vase */ else if (object == VASE) { if (g.loc == plac[PILLOW]) msg = 54; else { g.prop[VASE] = at(PILLOW) ? 0 : 2; pspeak(VASE, g.prop[VASE] + 1); if (g.prop[VASE] != 0) g.fixed[VASE] = -1; } } else { if (worn(object) || object == POLE || object == BOAT) g.prop[object] = 0; if (worn(object)) bitoff(object, WEARBT); if (object == POLE) g.prop[BOAT] = 0; } if (enclosed(object)) extract(object); drop(object, g.loc); rspeak(msg); return; } /* OPEN. special stuff for opening clam/oyster. The following can be opened without a key: clam/oyster, door, pdoor, bottle, cask, cage */ void vopen() { int msg, oyclam; if (!hinged(object)) msg = noway(); else if (object == PDOOR && g.prop[PDOOR] == 1) msg = 253; else if (ajar(object)) msg = 336; else if (locks(object) || iobj == KEYS || iobj == SKEY) { vunlock(); return; } else if (locked(object)) if (object == DOOR) msg = 111; else msg = 337; else if (object == CLAM || object == OYSTER) { oyclam = (object == OYSTER ? 1 : 0); msg = oyclam + holding(object) ? 120 : 124; if (!athand(TRIDENT)) msg = 122 + oyclam; if (iobj != 0 && iobj != TRIDENT) msg = 376 + oyclam; if (msg == 124) { destroy(CLAM); drop(OYSTER, g.loc); drop(PEARL, 105); } } else { msg = 54; biton(object, OPENBT); } rspeak(msg); return; } /* close, shut the following can be closed without keys: door, pdoor, bottle, cask, cage */ void vclose() { if (!hinged(object)) rspeak(noway()); else if (!ajar(object)) rspeak(338); else if (locks(object)) vlock(); else { rspeak(54); bitoff(object, OPENBT); } } /* Lamp ON. */ void von() { if (!athand(LAMP)) actspk(verb); else if (g.limit < 0) rspeak(184); else if (g.prop[LAMP] == 1) rspeak(321); else { g.prop[LAMP] = 1; if (g.loc == 200) rspeak(108); else rspeak(39); if (g.wzdark) { g.wzdark = 0; describe(); descitem(); } } return; } /* Lamp OFF. */ void voff() { if (!athand(LAMP)) actspk(verb); else if (g.prop[LAMP] == 0) rspeak(322); else { g.prop[LAMP] = 0; rspeak(40); if (dark()) rspeak(16); } return; } /* WAVE. no effect unless waving rod at fissure. */ void vwave() { if (!holding(object) && (object != ROD || !holding(ROD2))) rspeak(29); else if (object != ROD || !at(FISSURE) || !holding(object) || g.closing) actspk(verb); else if (iobj != 0 && iobj != FISSURE) actspk(verb); else { g.prop[FISSURE] = 1 - g.prop[FISSURE]; pspeak(FISSURE, 2 - g.prop[FISSURE]); if (g.chase == 0 || g.prop[FISSURE] != 0) return; if ((g.loc == 17 && g.oldloc != 27) || (g.loc == 27 && g.oldloc != 17)) return; /* Demise of the Wumpus. Champ must have just crossed bridge */ rspeak(244); g.chase = 0; drop(RING, 209); g.prop[WUMPUS] = 6; move(WUMPUS, 209); biton(WUMPUS, DEADBT); if (g.place[AXE] != plac[WUMPUS]) return; g.fixed[AXE] = 0; g.prop[AXE] = 0; } return; } /* ATTACK, KILL etc. */ void vkill() { int msg, i, k; boolean survival; survival = TRUE; switch (object) { case BIRD: if (g.closed) msg = 137; else { destroy(BIRD); g.prop[BIRD] = 0; if (g.place[SNAKE] == plac[SNAKE]) g.tally2++; msg = 45; } break; case DWARF: if (g.closed) { dwarfend(); return; } survival = do_battle(&msg); break; case 0: msg = 44; break; case CLAM: case OYSTER: msg = 150; break; case DOG: if (g.prop[DOG] == 1) msg = 291; else if (iobj == AXE) { object = AXE; iobj = DOG; vthrow(); return; } else msg = 110; break; case SNAKE: msg = 46; break; case TROLL: if (iobj == AXE) msg = 158; else msg = 110; break; case BEAR: msg = 165 + (g.prop[BEAR] + 1) / 2; break; case WUMPUS: if (g.prop[WUMPUS] == 6) msg = 167; else if (iobj == AXE) { object = AXE; iobj = WUMPUS; vthrow(); return; } else msg = 110; break; case GNOME: msg = 320; break; case DRAGON: if (g.prop[DRAGON] != 0) { msg = 167; break; } if (!yes(49, 0, 0)) break; pspeak(DRAGON, 1); biton(DRAGON, DEADBT); g.prop[DRAGON] = 2; g.prop[RUG] = 0; k = (plac[DRAGON] + fixd[DRAGON]) / 2; move((DRAGON + MAXOBJ), -1); move((RUG + MAXOBJ), 0); move(DRAGON, k); move(RUG, k); for (i = 1; i < MAXOBJ; i++) if (g.place[i] == plac[DRAGON] || g.place[i] == fixd[DRAGON] || holding(i)) move(i, k); g.loc = k; g.newloc = k; return; default: actspk(verb); return; } rspeak(msg); if (!survival) { g.oldloc2 = g.loc; death(); } return; } static boolean do_battle(msg_ptr) int *msg_ptr; { boolean survival; int temp; survival = TRUE; if (iobj == 0) *msg_ptr = 49; else if (iobj != AXE && iobj != SWORD) { *msg_ptr = 355; survival = FALSE; } else if (pct(25)) { temp = iobj; iobj = object; object = temp; vthrow(); return (TRUE); } else if (pct(25)) { *msg_ptr = 355; survival = FALSE; } else if (pct(36)) *msg_ptr = 354; else { rspeak(356); if (pct(61)) *msg_ptr = 52; else { *msg_ptr = 53; survival = FALSE; } } return (survival); } /* POUR */ void vpour() { int msg; if (object == BOTTLE || object == CASK) { iobj = object; object = liq(iobj); if (object == 0) { rspeak(316); return; } } else { if (object < WATER || object > (WINE + 1)) { rspeak(78); return; } } if (!holding(BOTTLE) && !holding(CASK)) { rspeak(29); return; } if (holding(BOTTLE) && liq(BOTTLE) == object) iobj = BOTTLE; if (holding(CASK) && liq(CASK) == object) iobj = CASK; if (iobj == 0) { rspeak(29); return; } if (!ajar(iobj)) { rspeak(335); return; } if (iobj == CASK) object++; g.prop[iobj] = 1; extract(object); g.place[object] = 0; msg = 77; if (iobj == CASK) { object--; msg = 104; } if (at(PLANT) || at(DOOR) || (at(SWORD) && g.prop[SWORD] != 0)) { if (at(DOOR)) { g.prop[DOOR] = 0; if (object == OIL) { g.prop[DOOR] = 1; bitoff(DOOR, LOCKBT); biton(DOOR, OPENBT); } msg = 113 + g.prop[DOOR]; } else if (at(SWORD)) { /* If sword is alread oily, don't let him clean it. No soap. */ if (g.prop[SWORD] != 5) { g.prop[SWORD] = 4; if (object == OIL) { g.prop[SWORD] = 5; g.fixed[SWORD] = -1; } msg = 206 + g.prop[SWORD] - 4; } } else { msg = 112; if (object == WATER) { if (g.prop[PLANT] < 0) g.prop[PLANT] = -g.prop[PLANT] - 1; pspeak(PLANT, g.prop[PLANT] + 1); g.prop[PLANT] = (g.prop[PLANT] + 2) % 6; g.prop[PLANT2] = g.prop[PLANT] / 2; newtravel = TRUE; return; } } } rspeak(msg); return; } /* EAT If he ate the right thing and is in the right place, move him to the other place with all his junk. Otherwise, narky message. */ void veat() { int msg, i, k, ll, kk; switch (object) { case HONEY: g.tally2++; case FOOD: destroy(object); msg = 72; break; case BIRD: case SNAKE: case CLAM: case OYSTER: case FLOWER: msg = 301; break; case DWARF: case DRAGON: case TROLL: case DOG: case WUMPUS: case BEAR: case GNOME: msg = 250; break; case MUSHRM: case CAKES: k = object - MUSHRM; ll = 229 + k; k = 159 - k; kk = SKEY; if (object == MUSHRM) { kk = TDOOR; if (g.loc != 158) g.tally2++; } destroy(object); msg = 228; if (!(here(kk) || g.fixed[kk] == g.loc)) break; msg = ll; /* If he hasn't taken tiny key off shelf, don't let him get it for free! */ for (i = 1; i < MAXOBJ; i++) { if (i == SKEY && g.prop[SKEY] == 1) continue; if (g.place[i] == plac[kk] && g.fixed[i] == 0) move(i, k); } if (g.loc == plac[SKEY] && g.place[SKEY] == plac[SKEY]) g.tally2++; g.loc = k; g.newloc = k; newtravel = TRUE; break; default: actspk(verb); return; } rspeak(msg); return; } /* DRINK */ void vdrink() { int msg, k, j; if (object == 0 && (iobj == BOTTLE || iobj == CASK)) object = liq(iobj); msg = 110; if (object == OIL) msg = 301; if (object != WATER && object != WINE) { rspeak(msg); return; } if (iobj == 0) { if (object == liqloc(g.loc)) iobj = -1; if (athand(CASK) && object == liq(CASK)) iobj = CASK; if (athand(BOTTLE) && object == liq(BOTTLE)) iobj = BOTTLE; } msg = 73; if (iobj != -1) { if (iobj == CASK) object++; extract(object); g.place[object] = 0; g.prop[iobj] = 1; msg = (iobj == CASK) ? 299 : 74; } if (object == WATER || object == (WATER + 1)) { rspeak(msg); return; } /* UH-OH. He's a wino. Let him reap the rewards of incontinence. He'll wander around for awhile, then wake up somewhere or other, having dropped most of his stuff. */ rspeak(300); if (g.prop[LAMP] == 1) g.limit -= ranz(g.limit) / 2; if (g.limit < 10) g.limit = 25; k = 0; if (pct(15)) k = 49; if (k == 0 && pct(15)) k = 53; if (k == 0 && pct(25)) k = 132; if (k == 0) k = 175; if (outside(g.loc)) k = 5; if (k == g.loc) { rspeak(msg); return; } if (holding(AXE)) move(AXE, k); if (holding(LAMP)) move(LAMP, k); for (j = 1; j < MAXOBJ; j++) { if (wearng(j)) bitoff(j, WEARBT); if (holding(j)) drop(j, g.loc); } g.loc = k; g.newloc = k; } /* THROW etc. */ void vthrow() { int msg, i, k, dwarfn; if (holding(ROD2) && object == ROD && !holding(ROD)) object = ROD2; if (!holding(object)) { actspk(verb); return; } if (object == BOAT || object == BEAR) { rspeak(noway()); return; } dwarfn = dcheck(); if (iobj == 0) { /* No indirect object was specified. If a dwarf is present, assume it is the object. If not, look for other living thing. If no living things present, treat 'THROW' as 'DROP'. */ if (dwarfn) iobj = DWARF; else { /* No dwarves present; figure out pausible object. */ k = 0; for (i = 1; i < MAXOBJ; i++) { if (at(i) && living(i)) { iobj = i; k++; } } if (k == 0) { vdrop(); return; } /* It is a beastie of some sort. Is there more than one? Don't kill the bird by default. */ if (k > 1) { rspeak(43); return; } else { if (iobj == BIRD) { vdrop(); return; } if (treasr(object) && at(TROLL)) iobj = TROLL; } } } if (object == SWORD || object == BOTTLE) { vbreak(); return; } if (object == FLOWER && iobj == HIVE) iobj = BEES; if (edible(object) && living(iobj)) { vfeed(); return; } /* If not axe, same as drop... */ if (object != AXE && iobj != TROLL) { vdrop(); return; } /* AXE is THROWN */ msg = 48; switch (iobj) { case DRAGON: if (g.prop[DRAGON] == 0) msg = 152; break; case DWARF: /* At a dwarf... */ if (pct(75)) { g.dseen[dwarfn] = g.dloc[dwarfn] = 0; msg = 47; ++g.dkill; if (g.dkill == 1) msg = 149; } break; case BEAR: /* This'll teach him to throw axe at the bear */ if (g.prop[BEAR] == 0) { msg = 164; drop(AXE, g.loc); g.fixed[AXE] = -1; g.prop[AXE] = 1; juggle(BEAR); } rspeak(msg); return; case WUMPUS: /* Or the WUMPUS! */ if (g.prop[WUMPUS] == 6) { vdrop(); return; } else { msg = 245; g.prop[AXE] = 2; if (g.prop[WUMPUS] == 0) { drop(AXE, g.loc); g.fixed[AXE] = -1; juggle(iobj); } else { msg = 243; destroy(AXE); } } rspeak(msg); return; case DOG: /* Or the nice doggie! */ if (g.prop[DOG] != 1) { msg = 248; g.prop[AXE] = 3; drop(AXE, g.loc); g.fixed[AXE] = -1; juggle(iobj); } rspeak(msg); return; case TROLL: /* Snarf a treasure for the troll */ if (object == AXE) { msg = 158; } else if (!treasr(object) || (object == CASK && (liq(CASK) != WINE))) { vdrop(); return; } else { msg = 159; drop(object, 0); if (object == CASK) g.place[WINE + 1] = 0; move(TROLL, 0); move((TROLL + MAXOBJ), 0); drop(TROLL2, plac[TROLL]); drop((TROLL2 + MAXOBJ), fixd[TROLL]); juggle(CHASM); rspeak(msg); return; } break; default: /* Otherwise it is an attack */ verb = KILL; object = iobj; iobj = objs[objx]; vkill(); return; } rspeak(msg); drop(AXE, g.loc); g.newloc = g.loc; describe(); } /* FIND might be carrying it, or it might be here. else give caveat. */ void vfind() { int msg; if (at(object) || (liq(BOTTLE) == object && at(BOTTLE)) || object == liqloc(g.loc)) msg = 94; else if (dcheck() && g.dflag >= 2 && object == DWARF) msg = 94; else if (g.closed) msg = 138; else if (at(object)) msg = 24; else { actspk(verb); return; } rspeak(msg); return; } /* FEED */ void vfeed() { int msg; if (iobj == 0 || !living(iobj)) { int i, k, kk; if (object == BIRD) { rspeak(100); return; } if (!living(object)) { rspeak(noway()); return; } /* See if there is anything edible around here. */ kk = 0; k = 0; for (i = 1; i < MAXOBJ; i++) if (here(i) && edible(i)) { k++; kk = i; } iobj = object; object = kk; if (k != 1 && !dead(iobj)) { printf("What do you want to feed the %s\n", otxt[objx]); objs[1] = 0; objx = 0; return; } } /* Feed object ot indirect object */ msg = 102; switch (iobj) { case DRAGON: if (g.prop[DRAGON] != 0) msg = noway(); break; case TROLL: msg = 182; break; case SNAKE: if (object == BIRD && !g.closed) { msg = 101; destroy(BIRD); g.prop[BIRD] = 0; g.tally2++; } break; case DWARF: msg = 103; g.dflag++; break; case BEAR: if (g.prop[BEAR] == 3) msg = noway(); if (g.prop[BEAR] == 1 || g.prop[BEAR] == 2) msg = 264; if (object == FOOD) msg = 278; if (object == HONEY) { g.prop[BEAR] = 1; g.fixed[AXE] = 0; destroy(HONEY); msg = 168; } break; case DOG: msg = 291; if (object == FOOD && g.prop[DOG] != 1) { msg = 249; destroy(FOOD); } break; case WUMPUS: if (g.prop[WUMPUS] == 6) msg = 326; if (g.prop[WUMPUS] == 0) msg = 327; if (object == FOOD) msg = 240; break; case BEES: if (object == FLOWER) { if (enclosed(FLOWER)) extract(FLOWER); drop(FLOWER, g.loc); g.fixed[FLOWER] = -1; g.prop[FLOWER] = 1; drop(HONEY, g.loc); juggle(HONEY); msg = 267; g.prop[HIVE] = 1; } } rspeak(msg); return; } /* FILL. object with iobj */ void vfill() { int msg, k; if (!vessel(object)) msg = 313; else { if (iobj == 0) iobj = liqloc(g.loc); if (object == BOTTLE || object == CASK) { k = (object == CASK) ? 1 : 0; msg = 0; if (iobj == 0) msg = 304 + k; if (liq(object) != 0) msg = 302 + k; if (msg != 0) { rspeak(msg); return; } msg = 306 + k; if (iobj == OIL) msg = 308 + k; if (iobj == WINE) msg = 310 + k; g.prop[object] = (int) g.loc_attrib[g.loc] & 14; g.place[iobj + k] = -1; insert(iobj + k, object); } else if (object == VASE) { if (iobj == 0 || !holding(VASE)) { rspeak(144); return; } msg = 145; g.prop[VASE] = 2; g.fixed[VASE] = -1; if (enclosed(object)) extract(object); drop(object, g.loc); } else if (object == GRAIL) msg = 298; else msg = 339; } rspeak(msg); } /* READ. Magazine in dwarvish, message we've seen, and ... oyster? */ void vread() { int msg; if (blind()) { actspk(verb); return; } if (object && iobj) { rspeak(confuz()); return; } msg = confuz(); if (!object) object = iobj; switch (object) { case BOOK: case BOOK2: msg = 142; break; case BILLBD: msg = 361; break; case CARVNG: msg = 372; break; case MAGAZINE: msg = 190; break; case MESSAGE: msg = 191; break; case POSTER: msg = 370; break; case TABLET: msg = 196; break; case OYSTER: if (g.hinted[2] && holding(OYSTER)) msg = 194; if (!g.hinted[2] && holding(OYSTER) && g.closed) { g.hinted[2] = yes(192, 193, 54); return; } break; } rspeak(msg); return; } /* BREAK. works for mirror in repository and, of course the vase and bottle. Also the sword is more brittle than it appears. */ void vbreak() { int msg, k; boolean it_broke; it_broke = FALSE; msg = 146; switch (object) { case MIRROR: msg = 148; if (g.closed) { rspeak(197); dwarfend(); return; } break; case VASE: if (g.prop[VASE] == 0) { it_broke = TRUE; msg = 198; g.prop[VASE] = 2; } break; case BOTTLE: if (g.prop[BOTTLE] != 3) { it_broke = TRUE; k = liq(BOTTLE); msg = 231; g.prop[BOTTLE] = 3; if (k) { extract(k); g.place[k] = 0; } } break; case SWORD: msg = 29; if (holding(SWORD)) { msg = 279; g.prop[SWORD] = 4; it_broke = TRUE; } break; } if (it_broke) { if (enclosed(object)) extract(object); if (holding(object)) drop(object, g.loc); g.fixed[object] = -1; } rspeak(msg); return; } /* WAKE. only use is to disturb the dwarves or the Wumpus. Other wumpus-wakers link here. */ void vwake() { int msg; msg = actmsg[verb]; if (at(WUMPUS)) { g.chase = TRUE; g.prop[WUMPUS] = 1; msg = 276; } if (at(DOG) && g.prop[DOG] == 1) msg = 291; if (object == DWARF && g.closed) { rspeak(199); dwarfend(); return; } rspeak(msg); return; } /* YANK. A variant of 'CARRY'. In general, not a good idea. At most, it gets the cloak or a couple of snide comments. */ void vyank() { if (toting(object)) vdrop(); else if (object == BEAR && g.prop[CHAIN]) rspeak(205); else if (object == CLOAK && g.prop[CLOAK] == 2) { /* Cloak. big trouble ahead. */ g.prop[ROCKS] = 1; g.prop[CLOAK] = 0; g.fixed[CLOAK] = 0; carry(CLOAK, g.loc); rspeak(241); if (at(WUMPUS) && g.prop[WUMPUS] == 0) { g.chase = 1; g.prop[WUMPUS] = 1; rspeak(276); } } else vtake(); return; } /* WEAR. Only good for jewels, ruby slippers, cloak & crown. But he might try the sword. Anything else is ridiculous. Another variant of 'CARRY'. */ void vwear() { int msg; if (object == SWORD && g.prop[SWORD] != 3) msg = 209; else if (worn(object)) { if (object == CLOAK && g.prop[CLOAK] == 2) msg = 242; else if (wearng(object)) msg = (object == SHOES) ? 227 : 210; else { g.prop[object] = 1; biton(object, WEARBT); if (enclosed(object)) extract(object); if (holding(object)) msg = 54; else { vtake(); return; } } } else { printf("Just exactly how does one wear a %s\n", otxt[objx]); return; } rspeak(msg); return; } /* HIT. If not punching out telephone, assume attack. */ void vhit() { if (at(WUMPUS) && g.prop[WUMPUS] == 0) { vwake(); return; } if (object != PHONE) { vkill(); return; } else { if (g.closed) { rspeak(282); dwarfend(); return; } if (g.prop[PHONE] == 2) rspeak(256); else { drop(SLUGS, g.loc); g.prop[PHONE] = 2; g.prop[BOOTH] = 2; rspeak(257); } } return; } /* ANSWER (telephone). Smartass for anything else. */ void vanswer() { int msg; switch (object) { case DWARF: case WUMPUS: case SNAKE: case BEAR: case DRAGON: msg = 259; break; case TROLL: msg = 258; break; case BIRD: msg = 260; break; case PHONE: if (g.prop[PHONE] != 0) msg = 269; else if (g.closed) { rspeak(283); normend(); return; } else { msg = 261; g.prop[PHONE] = 1; g.prop[BOOTH] = 2; } break; default: msg = actmsg[verb]; break; } rspeak(msg); return; } /* BLOW. Joshua fit de battle of Jericho, and de walls ... */ void vblow() { int msg, i, k; msg = actmsg[verb]; if (object != 0 && iobj != 0) { rspeak(msg); return; } if (object == 0) object = iobj; iobj = 0; if (object == 0) msg = 268; if (object == HORN) { msg = outside(g.loc) ? 277 : 266; if (at(WUMPUS)) { rspeak(msg); if (g.prop[WUMPUS] == 0) vwake(); return; } else if (g.prop[WALL] != 1 && (g.loc == 102 || g.loc == 194)) { k = g.loc == 194 ? 195 : 196; msg = 265; g.prop[WALL] = 1; for (i = 1; i < MAXOBJ; i++) if (g.place[i] == g.loc || g.fixed[i] == g.loc) move(i, k); g.newloc = k; } } rspeak(msg); return; } /* DIAL. No effect unless at phone. */ void vdial() { if (object != PHONE) actspk(verb); else if (g.closed) { rspeak(283); normend(); } else rspeak(271); return; } /* PLAY. Only for horn or lyre. */ void vplay() { int msg; msg = actmsg[verb]; if (object != 0 && iobj != 0) { rspeak(confuz()); return; } if (object == 0) object = iobj; if (object == HORN) { vblow(); return; } if (object == LYRE) { msg = 287; if (here(DOG) && !dead(DOG)) { g.prop[DOG] = 1; biton(DOG, DEADBT); g.fixed[AXE] = 0; g.prop[AXE] = 0; msg = 288; } } rspeak(msg); return; } /* PICK/ PICK UP. Can pick flower & mushrooms, But must 'PICK UP' everything else. */ void vpick() { if (object == 0) object = iobj; iobj = 0; if (object == FLOWER || object == MUSHRM || prep != 0) vtake(); else rspeak(confuz()); return; } /* PUT DOWN: equivalent to drop PUT IN: if liquid, means fill PUT ON: wear of drop */ void vput() { if (prep == 0) { printf("Where do you want to put the %s\n", otxt[objx]); return; } if (prep == PREPIN) vinsert(); else { /* PUT ON: wear or put object on iobj */ if (prep == PREPON) { if (object == 0) { object = iobj; otxt[objx] = iotxt[iobx]; iobj = 0; } if (worn(object) || object == 0) vwear(); else vdrop(); } else { /* PUT DOWN: "drop" */ if (object == 0 && iobj == 0) { if (object == 0) object = iobj; iobj = 0; vdrop(); } else rspeak(noway()); } } return; } /* turn on/off */ void vturn() { if (!prep) rspeak(confuz()); else { if (!object && iobj == LAMP) object = LAMP; if (object != LAMP) rspeak(noway()); else if (prep == PREPON) von(); else voff(); } return; } /* GET (no prep): "take" GET IN: "enter" GET OUT: "leave" */ void vget() { if (prep == 0 || prep == PREPFR) vtake(); else if (object == 0) { object = iobj; iobj = 0; prep = 0; vtake(); } return; } /* INSERT/PUT IN */ void vinsert() { int msg; if (iobj == 0) { printf("Where do you want to %s it?\n", vtxt[vrbx]); return; } msg = noway(); if (object == SWORD && iobj == ANVIL && g.prop[SWORD] == 0) msg = 350; if (!vessel(iobj)) { rspeak(msg); return; } msg = ck_obj(); if (g.fixed[object]) { rspeak(msg); return; } if (object == iobj) { rspeak(252); return; } if (iobj == BOTTLE || iobj == CASK || iobj == VASE || iobj == GRAIL || (object >= WATER && object <= WINE + 1)) { object = iobj; iobj = objs[objx]; vfill(); return; } if (!ajar(iobj)) { rspeak(358); return; } if (iobj == CHEST) { if (object == BOAT) msg = noway(); else { if (wearng(object)) bitoff(object, WEARBT); if (worn(object)) g.prop[object] = 0; if (enclosed(object)) extract(object); insert(object, iobj); msg = 54; } rspeak(msg); return; } /* Bird goes into cage and only cage */ if (object == BIRD && iobj != CAGE) { rspeak(351); return; } if (object != BIRD && iobj == CAGE) { rspeak(329); return; } if (object == BIRD) { prep = 0; vtake(); return; } /* Bar vase & pillow from safe, to force putting down on florr */ if ((object == VASE || object == PILLOW) && iobj == SAFE) { rspeak(329); return; } if (object != RADIUM && iobj == SHIELD) { rspeak(329); return; } if (iobj == PHONE) { if (object == COINS || object == SLUGS) { destroy(object); msg = 330; } else msg = 329; rspeak(msg); return; } if (iobj == VEND) { if (object == COINS || object == SLUGS) { destroy(object); move(BATTERIES, g.loc); if (g.prop[BATTERIES] == 1) { rspeak(317); g.prop[VEND] = 1; } g.prop[BATTERIES] = 0; pspeak(BATTERIES, 0); } else rspeak(noway()); return; } /* Put batteries in lamp. There is a glitch here, in that if he tries to get a third set of batteries before the second set has been inserted, the second set disappears! ***fix this some time *** */ if (iobj == LAMP) { if (object != BATTERIES || g.prop[BATTERIES] != 0) msg = noway(); else { g.prop[BATTERIES] = 1; if (enclosed(BATTERIES)) extract(BATTERIES); if (holding(BATTERIES)) drop(BATTERIES, g.loc); g.limit = 400; g.prop[LAMP] = 1; g.lmwarn = FALSE; msg = 188; } rspeak(msg); return; } if (!small(object)) msg = 329; else { if (wearng(object)) bitoff(object, WEARBT); if (worn(object)) g.prop[object] = 0; if (enclosed(object)) extract(object); insert(object, iobj); msg = 54; } rspeak(msg); return; } /* Remove or take from */ void vextract() { int msg; if (object == RING && g.prop[RING] == 2) { prep = 0; iobj = 0; vtake(); return; } msg = 343; if (iobj == 0) { if (!enclosed(object)) msg = 340; iobj = -g.place[object]; } if (g.place[object] != -iobj) msg = 341; if (!ajar(iobj)) msg = 335; if (object == WATER || object == OIL || object == WINE) msg = 342; if (!toting(object) && ((burden(0) + burden(object)) > 15)) msg = 92; if (msg == 343) { if (object == BIRD) { vdrop(); return; } extract(object); } rspeak(msg); return; } /* lock. chain, grate, chest, elfin door Here are the current lock/unlock messages & numbers: 31 you have no keys. 32 it has no lock. 34 it's already locked. 35 the grate is now locked. 36 the grate is now unlocked. 37 it was allready unlocked. 55 you can't unlock the keys. 171 The chain is now unlocked. 172 The chain is now locked. 173 There is nothing here to which the chain can be locked. 224 Your keys are all too large. 234 The wrought-iron door is now locked. 235 The tiny door is now locked. 236 The wrought-iron door is now unlocked. 237 The tiny door is now unlocked. 375 You don't have the right key. 333 the chest is now locked. 334 the chest is now unlocked. 367 The safe's door swings shut. */ void vlock() { int msg, k; if (!hinged(object)) { printf("I don't know how to lock or unlock the %s\n", otxt[objx]); return; } else if (!locks(object)) msg = 32; else if (locked(object)) msg = 34; else if (!athand(KEYS) && !athand(SKEY) && object != SAFE) msg = 31; else { msg = 375; switch (object) { case CHAIN: if (!athand(KEYS)) break; msg = 173; if (g.loc != plac[CHAIN]) break; msg = 172; g.prop[CHAIN] = 2; if (enclosed(CHAIN)) extract(CHAIN); if (holding(CHAIN)) drop(CHAIN, g.loc); g.fixed[CHAIN] = -1; biton(CHAIN, LOCKBT); bitoff(CHAIN, OPENBT); break; case CHEST: if (!athand(KEYS)) break; msg = 334; biton(CHEST, LOCKBT); bitoff(CHEST, OPENBT); break; case TDOOR: case TDOOR2: msg = 224; if (!toting(SKEY)) break; g.prop[TDOOR] = 0; g.prop[TDOOR2] = 0; msg = 234 + (TDOOR2 - object); k = TDOOR + TDOOR2 - object; biton(k, LOCKBT); bitoff(k, OPENBT); biton(object, LOCKBT); bitoff(object, OPENBT); break; case GRATE: if (!athand(KEYS)) break; g.prop[GRATE] = 0; msg = 35; biton(GRATE, LOCKBT); bitoff(GRATE, OPENBT); break; case SAFE: g.prop[SAFE] = 0; msg = 367; biton(SAFE, LOCKBT); bitoff(SAFE, OPENBT); break; } } rspeak(msg); } /* UNLOCK. chain, grate, chest, elfin door. */ void vunlock() { int msg, k; if (object == KEYS || object == SKEY) msg = 55; else if (!hinged(object)) { printf("I don't know how to lock or unlock the %s\n", otxt[objx]); return; } else if (!locked(object)) msg = 37; else if (!locks(object)) msg = 32; else if (object == SAFE) { if (iobj == KEYS || iobj == SKEY) msg = 368; else msg = 342; } else if (!athand(KEYS) && !athand(SKEY)) msg = 31; else { msg = 375; switch (object) { case CHAIN: if (!athand(KEYS)) break; if (g.prop[BEAR] == 0) msg = 41; else { msg = 171; g.prop[CHAIN] = 0; g.fixed[CHAIN] = 0; if (g.prop[BEAR] != 3) g.prop[BEAR] = 2; g.fixed[BEAR] = 2 - g.prop[BEAR]; bitoff(CHAIN, LOCKBT); biton(CHAIN, OPENBT); } break; case CHEST: if (athand(KEYS)) { msg = 333; bitoff(CHEST, LOCKBT); biton(CHEST, OPENBT); } break; case TDOOR: case TDOOR2: /* Elvin door stuff to lock/unlock tiny door w/special key. the damn thing is really at four places, and we want the right messages if he only has 'BIG'keys (or no keys). Also, he can unlock it either while he is big or small. */ msg = 224; if (!athand(SKEY)) break; if (g.closing) { msg = 130; if (!g.panic) g.clock2 = 15; g.panic = TRUE; } else { g.prop[TDOOR] = 1; g.prop[TDOOR2] = 1; msg = 234 + 2 + (TDOOR2 - object); k = TDOOR + (TDOOR2 - object); bitoff(k, LOCKBT); biton(k, OPENBT); bitoff(object, LOCKBT); biton(object, OPENBT); } break; case GRATE: if (!athand(KEYS)) break; if (g.closing) { msg = 130; if (!g.panic) g.clock2 = 15; g.panic = TRUE; } else { g.prop[GRATE] = 1; msg = 36; bitoff(GRATE, LOCKBT); biton(GRATE, OPENBT); } break; default: msg = 33; } } rspeak(msg); } /* LOOK. */ void vlook() { int sloc; if (object != 0) { rspeak(confuz()); return; } /* Look into something (a container). */ if (vessel(iobj)) { if (!ajar(iobj) && opaque(iobj)) rspeak(actmsg[verb]); else if (g.holder[iobj] == 0) rspeak(359); else { putchar(' '); lookin(iobj); } /* Look at something. If written, read it. */ } else if (printed(iobj)) { object = iobj; iobj = 0; vread(); } else if (iobj == SPHERE) { if (!inside(g.loc) || athand(SAPPHIRE)) rspeak(42); else { rspeak(400); printf(" "); sloc = g.place[SAPPHIRE]; if ((g.loc_attrib[sloc] % 2 == 0 || enclosed(SAPPHIRE)) && sloc != 200 && !g.place[LAMP] == sloc && g.prop[LAMP] != 0) rspeak(401); else desclg(sloc); if (sloc == 239 && !g.flg239) { rspeak(403); g.flg239 = TRUE; } printf(" "); rspeak(402); } } else printf("I see nothing special about the %s?\n", iotxt[iobx]); return; }