X-Git-Url: https://jxself.org/git/?p=open-adventure.git;a=blobdiff_plain;f=actions.c;h=06da68805481e1526c7a24687b09c9224188b6b1;hp=f4633f58d617b9ab0fb4a3358a3daab618419005;hb=7be7ac9406512644886fbf4a99d16e1b4f7cefc3;hpb=ffd08893dd14ee435e4fdb1df5fae6189de72c1f diff --git a/actions.c b/actions.c index f4633f5..06da688 100644 --- a/actions.c +++ b/actions.c @@ -7,6 +7,7 @@ static int fill(token_t, token_t); static void state_change(long obj, long state) +/* Object must have a change-message list for this to be useful; only some do */ { game.prop[obj] = state; pspeak(obj, change, state, true); @@ -21,7 +22,6 @@ static int attack(struct command_t *command) vocab_t verb = command->verb; vocab_t obj = command->obj; - long spk = actions[verb].message; if (obj == NO_OBJECT || obj == INTRANSITIVE) { int changes = 0; @@ -69,69 +69,41 @@ static int attack(struct command_t *command) } if (changes >= 2) return GO_UNKNOWN; - } + if (obj == BIRD) { if (game.closed) { rspeak(UNHAPPY_BIRD); - return GO_CLEAROBJ; + } else { + DESTROY(BIRD); + rspeak(BIRD_DEAD); } - DESTROY(BIRD); - spk = BIRD_DEAD; - } else if (obj == VEND) { + return GO_CLEAROBJ; + } + if (obj == VEND) { state_change(VEND, game.prop[VEND] == VEND_BLOCKS ? VEND_UNBLOCKS : VEND_BLOCKS); return GO_CLEAROBJ; } - if (obj == NO_OBJECT) - spk = NO_TARGET; - if (obj == CLAM || - obj == OYSTER) - spk = SHELL_IMPERVIOUS; - if (obj == SNAKE) - spk = SNAKE_WARNING; - if (obj == DWARF) - spk = BARE_HANDS_QUERY; - if (obj == DWARF && game.closed) - return GO_DWARFWAKE; - if (obj == DRAGON) - spk = ALREADY_DEAD; - if (obj == TROLL) - spk = ROCKY_TROLL; - if (obj == OGRE) - spk = OGRE_DODGE; - if (obj == OGRE && atdwrf(game.loc) > 0) { - rspeak(spk); - rspeak(KNIFE_THROWN); - DESTROY(OGRE); - int dwarves = 0; - for (int i = 1; i < PIRATE; i++) { - if (game.dloc[i] == game.loc) { - ++dwarves; - game.dloc[i] = LOC_LONGWEST; - game.dseen[i] = false; - } - } - spk = (dwarves > 1) ? - OGRE_PANIC1 : - OGRE_PANIC2; - } else if (obj == BEAR) { + if (obj == BEAR) { switch (game.prop[BEAR]) { case UNTAMED_BEAR: - spk = BEAR_HANDS; + rspeak(BEAR_HANDS); break; case SITTING_BEAR: - spk = BEAR_CONFUSED; + rspeak(BEAR_CONFUSED); break; case CONTENTED_BEAR: - spk = BEAR_CONFUSED; + rspeak(BEAR_CONFUSED); break; case BEAR_DEAD: - spk = ALREADY_DEAD; + rspeak(ALREADY_DEAD); break; } - } else if (obj == DRAGON && game.prop[DRAGON] == DRAGON_BARS) { + return GO_CLEAROBJ; + } + if (obj == DRAGON && game.prop[DRAGON] == DRAGON_BARS) { /* Fun stuff for dragon. If he insists on attacking it, win! * Set game.prop to dead, move dragon to central loc (still * fixed), move rug there (not fixed), and move him there, @@ -163,7 +135,53 @@ static int attack(struct command_t *command) return GO_MOVE; } - rspeak(spk); + if (obj == OGRE) { + rspeak(OGRE_DODGE); + if (atdwrf(game.loc) == 0) + return GO_CLEAROBJ; + + rspeak(KNIFE_THROWN); + DESTROY(OGRE); + int dwarves = 0; + for (int i = 1; i < PIRATE; i++) { + if (game.dloc[i] == game.loc) { + ++dwarves; + game.dloc[i] = LOC_LONGWEST; + game.dseen[i] = false; + } + } + rspeak((dwarves > 1) ? + OGRE_PANIC1 : + OGRE_PANIC2); + return GO_CLEAROBJ; + } + + switch (obj) { + case NO_OBJECT: + rspeak(NO_TARGET); + break; + case CLAM: + case OYSTER: + rspeak(SHELL_IMPERVIOUS); + break; + case SNAKE: + rspeak(SNAKE_WARNING); + break; + case DWARF: + if (game.closed) { + return GO_DWARFWAKE; + } + rspeak(BARE_HANDS_QUERY); + break; + case DRAGON: + rspeak(ALREADY_DEAD); + break; + case TROLL: + rspeak(ROCKY_TROLL); + break; + default: + rspeak(actions[verb].message); + } return GO_CLEAROBJ; } @@ -210,38 +228,6 @@ static int bigwords(token_t foo) } } -static int bivalve(token_t verb, token_t obj) -/* Clam/oyster actions */ -{ - bool is_oyster = (obj == OYSTER); - if (verb == LOCK) { - rspeak(HUH_MAN); - return GO_CLEAROBJ; - } - if (!TOTING(TRIDENT)) { - rspeak(is_oyster ? - OYSTER_OPENER : - CLAM_OPENER); - return GO_CLEAROBJ; - } - if (TOTING(obj)) { - rspeak( is_oyster ? - DROP_OYSTER : - DROP_CLAM); - return GO_CLEAROBJ; - } - - if (!is_oyster) { - DESTROY(CLAM); - drop(OYSTER, game.loc); - drop(PEARL, LOC_CULDESAC); - } - rspeak(is_oyster ? - OYSTER_OPENS : - PEARL_FALLS); - return GO_CLEAROBJ; -} - static void blast(void) /* Blast. No effect unless you've got dynamite, which is a neat trick! */ { @@ -275,7 +261,7 @@ static int vbreak(token_t verb, token_t obj) if (TOTING(VASE)) drop(VASE, game.loc); state_change(VASE, VASE_BROKEN); - game.fixed[VASE] = -1; + game.fixed[VASE] = IS_FIXED; return GO_CLEAROBJ; } rspeak(actions[verb].message); @@ -296,7 +282,6 @@ static int vcarry(token_t verb, token_t obj) * take one without the other). Liquids also special, since they depend on * status of bottle. Also various side effects, etc. */ { - int spk; if (obj == INTRANSITIVE) { /* Carry, no object given yet. OK if only one object present. */ if (game.atloc[game.loc] == 0 || @@ -310,82 +295,100 @@ static int vcarry(token_t verb, token_t obj) rspeak(ALREADY_CARRYING); return GO_CLEAROBJ; } - spk = YOU_JOKING; - if (obj == PLANT && game.prop[PLANT] <= 0) - spk = DEEP_ROOTS; - if (obj == BEAR && game.prop[BEAR] == SITTING_BEAR) - spk = BEAR_CHAINED; - if (obj == CHAIN && game.prop[BEAR] != UNTAMED_BEAR) - spk = STILL_LOCKED; - if (obj == URN) - spk = URN_NOBUDGE; - if (obj == CAVITY) - spk = DOUGHNUT_HOLES; - if (obj == BLOOD) - spk = FEW_DROPS; - if (obj == RUG && game.prop[RUG] == RUG_HOVER) - spk = RUG_HOVERS; - if (obj == SIGN) - spk = HAND_PASSTHROUGH; + if (obj == MESSAG) { rspeak(REMOVE_MESSAGE); DESTROY(MESSAG); return GO_CLEAROBJ; } - if (game.fixed[obj] != 0) { - rspeak(spk); + + if (game.fixed[obj] != IS_FREE) { + /* Next guard tests whether plant is tiny or stashed */ + if (obj == PLANT && game.prop[PLANT] <= PLANT_THIRSTY) { + rspeak(DEEP_ROOTS); + return GO_CLEAROBJ; + } + if (obj == BEAR && game.prop[BEAR] == SITTING_BEAR) { + rspeak(BEAR_CHAINED); + return GO_CLEAROBJ; + } + if (obj == CHAIN && game.prop[BEAR] != UNTAMED_BEAR) { + rspeak(STILL_LOCKED); + return GO_CLEAROBJ; + } + if (obj == URN) { + rspeak(URN_NOBUDGE); + return GO_CLEAROBJ; + } + if (obj == CAVITY) { + rspeak(DOUGHNUT_HOLES); + return GO_CLEAROBJ; + } + if (obj == BLOOD) { + rspeak(FEW_DROPS); + return GO_CLEAROBJ; + } + if (obj == RUG && game.prop[RUG] == RUG_HOVER) { + rspeak(RUG_HOVERS); + return GO_CLEAROBJ; + } + if (obj == SIGN) { + rspeak(HAND_PASSTHROUGH); + return GO_CLEAROBJ; + } + rspeak(YOU_JOKING); return GO_CLEAROBJ; } + if (obj == WATER || obj == OIL) { if (!HERE(BOTTLE) || LIQUID() != obj) { - if (TOTING(BOTTLE) && game.prop[BOTTLE] == EMPTY_BOTTLE) - return (fill(verb, BOTTLE)); - else { - if (game.prop[BOTTLE] != EMPTY_BOTTLE) - spk = BOTTLE_FULL; - if (!TOTING(BOTTLE)) - spk = NO_CONTAINER; - rspeak(spk); + if (TOTING(BOTTLE)) { + if (game.prop[BOTTLE] == EMPTY_BOTTLE) { + return (fill(verb, BOTTLE)); + } else if (game.prop[BOTTLE] != EMPTY_BOTTLE) + rspeak(BOTTLE_FULL); return GO_CLEAROBJ; } + rspeak(NO_CONTAINER); + return GO_CLEAROBJ; } obj = BOTTLE; } - spk = CARRY_LIMIT; if (game.holdng >= INVLIMIT) { - rspeak(spk); + rspeak(CARRY_LIMIT); return GO_CLEAROBJ; - } else if (obj == BIRD && game.prop[BIRD] != BIRD_CAGED && -1 - game.prop[BIRD] != BIRD_CAGED) { + + } + + if (obj == BIRD && game.prop[BIRD] != BIRD_CAGED && STASHED(BIRD) != BIRD_CAGED) { if (game.prop[BIRD] == BIRD_FOREST_UNCAGED) { DESTROY(BIRD); rspeak(BIRD_CRAP); return GO_CLEAROBJ; } - if (!TOTING(CAGE)) - spk = CANNOT_CARRY; - if (TOTING(ROD)) - spk = BIRD_EVADES; - if (spk == CANNOT_CARRY || - spk == BIRD_EVADES) { - rspeak(spk); + if (!TOTING(CAGE)) { + rspeak(CANNOT_CARRY); + return GO_CLEAROBJ; + } + if (TOTING(ROD)) { + rspeak(BIRD_EVADES); return GO_CLEAROBJ; } game.prop[BIRD] = BIRD_CAGED; } - /* FIXME: Arithmetic on state numbers */ if ((obj == BIRD || obj == CAGE) && - (game.prop[BIRD] == BIRD_CAGED || - -1 - game.prop[BIRD] == 1)) + (game.prop[BIRD] == BIRD_CAGED || STASHED(BIRD) == BIRD_CAGED)) + /* expression maps BIRD to CAGE and CAGE to BIRD */ carry(BIRD + CAGE - obj, game.loc); carry(obj, game.loc); - if (obj == BOTTLE && LIQUID() != 0) + if (obj == BOTTLE && LIQUID() != NO_OBJECT) game.place[LIQUID()] = CARRIED; - if (GSTONE(obj) && game.prop[obj] != 0) { - game.prop[obj] = STATE_GROUND; + if (GSTONE(obj) && game.prop[obj] != STATE_FOUND) { + game.prop[obj] = STATE_FOUND; game.prop[CAVITY] = CAVITY_EMPTY; } rspeak(OK_MAN); @@ -395,39 +398,47 @@ static int vcarry(token_t verb, token_t obj) static int chain(token_t verb) /* Do something to the bear's chain */ { - int spk; if (verb != LOCK) { - spk = CHAIN_UNLOCKED; - if (game.prop[BEAR] == UNTAMED_BEAR) - spk = BEAR_BLOCKS; - if (game.prop[CHAIN] == CHAIN_HEAP) - spk = ALREADY_UNLOCKED; - if (spk != CHAIN_UNLOCKED) { - rspeak(spk); + if (game.prop[BEAR] == UNTAMED_BEAR) { + rspeak(BEAR_BLOCKS); + return GO_CLEAROBJ; + } + if (game.prop[CHAIN] == CHAIN_HEAP) { + rspeak(ALREADY_UNLOCKED); return GO_CLEAROBJ; } game.prop[CHAIN] = CHAIN_HEAP; - game.fixed[CHAIN] = CHAIN_HEAP; + game.fixed[CHAIN] = IS_FREE; if (game.prop[BEAR] != BEAR_DEAD) game.prop[BEAR] = CONTENTED_BEAR; - /* FIXME: Arithmetic on state numbers */ - game.fixed[BEAR] = 2 - game.prop[BEAR]; - } else { - spk = CHAIN_LOCKED; - if (game.prop[CHAIN] != CHAIN_HEAP) - spk = ALREADY_LOCKED; - if (game.loc != objects[CHAIN].plac) - spk = NO_LOCKSITE; - if (spk != CHAIN_LOCKED) { - rspeak(spk); - return GO_CLEAROBJ; + + switch (game.prop[BEAR]) { + case BEAR_DEAD: + game.fixed[BEAR] = IS_FIXED; + break; + default: + game.fixed[BEAR] = IS_FREE; } - game.prop[CHAIN] = CHAIN_FIXED; - if (TOTING(CHAIN)) - drop(CHAIN, game.loc); - game.fixed[CHAIN] = -1; + rspeak(CHAIN_UNLOCKED); + return GO_CLEAROBJ; } - rspeak(spk); + + if (game.prop[CHAIN] != CHAIN_HEAP) { + rspeak(ALREADY_LOCKED); + return GO_CLEAROBJ; + } + if (game.loc != objects[CHAIN].plac) { + rspeak(NO_LOCKSITE); + return GO_CLEAROBJ; + } + + game.prop[CHAIN] = CHAIN_FIXED; + + if (TOTING(CHAIN)) + drop(CHAIN, game.loc); + game.fixed[CHAIN] = IS_FIXED; + + rspeak(CHAIN_LOCKED); return GO_CLEAROBJ; } @@ -436,12 +447,11 @@ static int discard(token_t verb, token_t obj, bool just_do_it) * bird (might attack snake or dragon) and cage (might contain bird) and vase. * Drop coins at vending machine for extra batteries. */ { - int spk = actions[verb].message; if (!just_do_it) { if (TOTING(ROD2) && obj == ROD && !TOTING(ROD)) obj = ROD2; if (!TOTING(obj)) { - rspeak(spk); + rspeak(actions[verb].message); return GO_CLEAROBJ; } if (obj == BIRD && HERE(SNAKE)) { @@ -454,11 +464,11 @@ static int discard(token_t verb, token_t obj, bool just_do_it) } else if ((GSTONE(obj) && AT(CAVITY) && game.prop[CAVITY] != CAVITY_FULL)) { rspeak(GEM_FITS); - game.prop[obj] = 1; + game.prop[obj] = STATE_IN_CAVITY; game.prop[CAVITY] = CAVITY_FULL; if (HERE(RUG) && ((obj == EMERALD && game.prop[RUG] != RUG_HOVER) || (obj == RUBY && game.prop[RUG] == RUG_HOVER))) { - spk = RUG_RISES; + int spk = RUG_RISES; if (TOTING(RUG)) spk = RUG_WIGGLES; if (obj == RUBY) @@ -468,7 +478,7 @@ static int discard(token_t verb, token_t obj, bool just_do_it) /* FIXME: Arithmetic on state numbers */ int k = 2 - game.prop[RUG]; game.prop[RUG] = k; - if (k == 2) + if (k == RUG_HOVER) k = objects[SAPPH].plac; move(RUG + NOBJECTS, k); } @@ -493,18 +503,17 @@ static int discard(token_t verb, token_t obj, bool just_do_it) game.loc == objects[PILLOW].plac) { rspeak(OK_MAN); } else { - game.prop[VASE] = VASE_BROKEN; - if (AT(PILLOW)) - game.prop[VASE] = VASE_WHOLE; - pspeak(VASE, look, game.prop[VASE] + 1, true); + state_change(VASE, AT(PILLOW) + ? VASE_WHOLE + : VASE_DROPPED); if (game.prop[VASE] != VASE_WHOLE) - game.fixed[VASE] = -1; + game.fixed[VASE] = IS_FIXED; } } int k = LIQUID(); if (k == obj) obj = BOTTLE; - if (obj == BOTTLE && k != 0) + if (obj == BOTTLE && k != NO_OBJECT) game.place[k] = LOC_NOWHERE; if (obj == CAGE && game.prop[BIRD] == BIRD_CAGED) drop(BIRD, game.loc); @@ -521,24 +530,29 @@ static int drink(token_t verb, token_t obj) /* Drink. If no object, assume water and look for it here. If water is in * the bottle, drink that, else must be at a water loc, so drink stream. */ { - if (obj == NO_OBJECT && LIQLOC(game.loc) != WATER && (LIQUID() != WATER || - !HERE(BOTTLE))) + if (obj == NO_OBJECT && LIQLOC(game.loc) != WATER && + (LIQUID() != WATER || !HERE(BOTTLE))) { return GO_UNKNOWN; - if (obj != BLOOD) { - if (obj != NO_OBJECT && obj != WATER) { - rspeak(RIDICULOUS_ATTEMPT); - } else if (LIQUID() == WATER && HERE(BOTTLE)) { - game.prop[BOTTLE] = EMPTY_BOTTLE; - game.place[WATER] = LOC_NOWHERE; - rspeak(BOTTLE_EMPTY); - } else { - rspeak(actions[verb].message); - } - } else { + } + + if (obj == BLOOD) { DESTROY(BLOOD); state_change(DRAGON, DRAGON_BLOODLESS); game.blooded = true; + return GO_CLEAROBJ; + } + + if (obj != NO_OBJECT && obj != WATER) { + rspeak(RIDICULOUS_ATTEMPT); + return GO_CLEAROBJ; + } + if (LIQUID() == WATER && HERE(BOTTLE)) { + game.place[WATER] = LOC_NOWHERE; + state_change(BOTTLE, EMPTY_BOTTLE); + return GO_CLEAROBJ; } + + rspeak(actions[verb].message); return GO_CLEAROBJ; } @@ -582,9 +596,7 @@ static int extinguish(token_t verb, int obj) obj = LAMP; if (HERE(URN) && game.prop[URN] == URN_LIT) obj = URN; - if (obj == INTRANSITIVE || - (HERE(LAMP) && game.prop[LAMP] == LAMP_BRIGHT && - HERE(URN) && game.prop[URN] == URN_LIT)) + if (obj == INTRANSITIVE) return GO_UNKNOWN; } @@ -594,20 +606,24 @@ static int extinguish(token_t verb, int obj) } else { pspeak(URN, change, URN_DARK, true); } + return GO_CLEAROBJ; + } - } else if (obj == LAMP) { + if (obj == LAMP) { state_change(LAMP, LAMP_DARK); rspeak(DARK(game.loc) ? PITCH_DARK : NO_MESSAGE); + return GO_CLEAROBJ; + } - } else if (obj == DRAGON || - obj == VOLCANO) { + if (obj == DRAGON || + obj == VOLCANO) { rspeak(BEYOND_POWER); - - } else { - rspeak(actions[verb].message); + return GO_CLEAROBJ; } + + rspeak(actions[verb].message); return GO_CLEAROBJ; } @@ -644,8 +660,8 @@ static int feed(token_t verb, token_t obj) if (HERE(FOOD)) { DESTROY(FOOD); game.prop[BEAR] = SITTING_BEAR; - game.fixed[AXE] = 0; - game.prop[AXE] = 0; + game.fixed[AXE] = IS_FREE; + game.prop[AXE] = AXE_HERE; spk = BEAR_TAMED; } } else if (obj == OGRE) { @@ -662,80 +678,100 @@ int fill(token_t verb, token_t obj) /* Fill. Bottle or urn must be empty, and liquid available. (Vase * is nasty.) */ { - int k; - int spk = actions[verb].message; if (obj == VASE) { - spk = ARENT_CARRYING; - if (LIQLOC(game.loc) == 0) - spk = FILL_INVALID; - if (LIQLOC(game.loc) == 0 || - !TOTING(VASE)) { - rspeak(spk); + if (LIQLOC(game.loc) == NO_OBJECT) { + rspeak(FILL_INVALID); + return GO_CLEAROBJ; + } + if (!TOTING(VASE)) { + rspeak(ARENT_CARRYING); return GO_CLEAROBJ; } rspeak(SHATTER_VASE); game.prop[VASE] = VASE_BROKEN; - game.fixed[VASE] = -1; - return (discard(verb, obj, true)); - } else if (obj == URN) { - spk = FULL_URN; + game.fixed[VASE] = IS_FIXED; + return (discard(verb, VASE, true)); + } + + if (obj == URN) { if (game.prop[URN] != URN_EMPTY) { - rspeak(spk); + rspeak(FULL_URN); return GO_CLEAROBJ; } - spk = FILL_INVALID; - k = LIQUID(); - if (k == 0 || - !HERE(BOTTLE)) { - rspeak(spk); + if (!HERE(BOTTLE)) { + rspeak(FILL_INVALID); return GO_CLEAROBJ; } - game.place[k] = LOC_NOWHERE; - game.prop[BOTTLE] = EMPTY_BOTTLE; - if (k == OIL) + int k = LIQUID(); + switch (k) { + case WATER: + game.prop[BOTTLE] = EMPTY_BOTTLE; + rspeak(WATER_URN); + break; + case OIL: game.prop[URN] = URN_DARK; - spk = WATER_URN + game.prop[URN]; - rspeak(spk); + game.prop[BOTTLE] = EMPTY_BOTTLE; + rspeak(OIL_URN); + break; + case NO_OBJECT: + default: + rspeak(FILL_INVALID); + return GO_CLEAROBJ; + } + game.place[k] = LOC_NOWHERE; return GO_CLEAROBJ; - } else if (obj != NO_OBJECT && obj != BOTTLE) { - rspeak(spk); + } + if (obj != NO_OBJECT && obj != BOTTLE) { + rspeak(actions[verb].message); return GO_CLEAROBJ; - } else if (obj == NO_OBJECT && !HERE(BOTTLE)) + } + if (obj == NO_OBJECT && !HERE(BOTTLE)) return GO_UNKNOWN; - spk = BOTTLED_WATER; - if (LIQLOC(game.loc) == 0) - spk = NO_LIQUID; - if (HERE(URN) && game.prop[URN] != URN_EMPTY) - spk = URN_NOPOUR; - if (LIQUID() != 0) - spk = BOTTLE_FULL; - if (spk == BOTTLED_WATER) { - /* FIXME: Arithmetic on property values */ - game.prop[BOTTLE] = MOD(conditions[game.loc], 4) / 2 * 2; - k = LIQUID(); - if (TOTING(BOTTLE)) - game.place[k] = CARRIED; - if (k == OIL) - spk = BOTTLED_OIL; + + if (HERE(URN) && game.prop[URN] != URN_EMPTY) { + rspeak(URN_NOPOUR); + return GO_CLEAROBJ; } - rspeak(spk); + if (LIQUID() != NO_OBJECT) { + rspeak(BOTTLE_FULL); + return GO_CLEAROBJ; + } + if (LIQLOC(game.loc) == NO_OBJECT) { + rspeak(NO_LIQUID); + return GO_CLEAROBJ; + } + + state_change(BOTTLE, (LIQLOC(game.loc) == OIL) + ? OIL_BOTTLE + : WATER_BOTTLE); + if (TOTING(BOTTLE)) + game.place[LIQUID()] = CARRIED; return GO_CLEAROBJ; } static int find(token_t verb, token_t obj) /* Find. Might be carrying it, or it might be here. Else give caveat. */ { - int spk = actions[verb].message; + if (TOTING(obj)) { + rspeak(ALREADY_CARRYING); + return GO_CLEAROBJ; + } + + if (game.closed) { + rspeak(NEEDED_NEARBY); + return GO_CLEAROBJ; + } + if (AT(obj) || (LIQUID() == obj && AT(BOTTLE)) || obj == LIQLOC(game.loc) || - (obj == DWARF && atdwrf(game.loc) > 0)) - spk = YOU_HAVEIT; - if (game.closed) - spk = NEEDED_NEARBY; - if (TOTING(obj)) - spk = ALREADY_CARRYING; - rspeak(spk); + (obj == DWARF && atdwrf(game.loc) > 0)) { + rspeak(YOU_HAVEIT); + return GO_CLEAROBJ; + } + + + rspeak(actions[verb].message); return GO_CLEAROBJ; } @@ -767,10 +803,10 @@ static int fly(token_t verb, token_t obj) /* FIXME: Arithmetic on location values */ game.newloc = game.place[RUG] + game.fixed[RUG] - game.loc; - if (game.prop[SAPPH] >= 0) { - rspeak(RUG_RETURNS); - } else { + if (game.prop[SAPPH] == STATE_NOTFOUND) { rspeak(RUG_GOES); + } else { + rspeak(RUG_RETURNS); } return GO_TERMINATE; } @@ -833,7 +869,7 @@ static int light(token_t verb, token_t obj) } static int listen(void) -/* Listen. Intransitive only. Print stuff based on objsnd/locsnd. */ +/* Listen. Intransitive only. Print stuff based on object sound proprties. */ { long sound = locations[game.loc].sound; if (sound != SILENT) { @@ -853,8 +889,7 @@ static int listen(void) long packed_zzword = token_to_packed(game.zzword); pspeak(i, hear, mi, true, packed_zzword); rspeak(NO_MESSAGE); - /* FIXME: Magic number, sensitive to bird state logic */ - if (i == BIRD && game.prop[i] == 5) + if (i == BIRD && mi == BIRD_ENDSTATE) DESTROY(BIRD); return GO_CLEAROBJ; } @@ -908,8 +943,24 @@ static int lock(token_t verb, token_t obj) switch (obj) { case CLAM: + if (verb == LOCK) + rspeak(HUH_MAN); + else if (!TOTING(TRIDENT)) + rspeak(OYSTER_OPENER); + else { + DESTROY(CLAM); + drop(OYSTER, game.loc); + drop(PEARL, LOC_CULDESAC); + rspeak(PEARL_FALLS); + } + return GO_CLEAROBJ; case OYSTER: - return bivalve(verb, obj); + if (verb == LOCK) + rspeak(HUH_MAN); + else + rspeak(OYSTER_OPENER); + + return GO_CLEAROBJ; case DOOR: rspeak((game.prop[DOOR] == DOOR_UNRUSTED) ? OK_MAN : RUSTY_DOOR); break; @@ -955,14 +1006,14 @@ static int pour(token_t verb, token_t obj) } if (!AT(DOOR)) { if (obj == WATER) { - /* cycle through the three plant states */ - state_change(PLANT, MOD(game.prop[PLANT] + 1, 3)); - game.prop[PLANT2] = game.prop[PLANT]; - return GO_MOVE; + /* cycle through the three plant states */ + state_change(PLANT, MOD(game.prop[PLANT] + 1, 3)); + game.prop[PLANT2] = game.prop[PLANT]; + return GO_MOVE; } else { rspeak(SHAKING_LEAVES); return GO_CLEAROBJ; - } + } } else { state_change(DOOR, (obj == OIL) ? DOOR_UNRUSTED : @@ -1014,9 +1065,8 @@ static int reservoir(void) rspeak(NOTHING_HAPPENS); return GO_CLEAROBJ; } else { - /* FIXME: Arithmetic on state numbers */ - pspeak(RESER, look, game.prop[RESER] + 1, true); - game.prop[RESER] = 1 - game.prop[RESER]; + state_change(RESER, + game.prop[RESER] == WATERS_PARTED ? WATERS_UNPARTED : WATERS_PARTED); if (AT(RESER)) return GO_CLEAROBJ; else { @@ -1056,7 +1106,6 @@ static int say(struct command_t *command) char word1[TOKLEN + 1]; packed_to_token(command->wd1, word1); int wd = (int) get_vocab_id(word1); - /* FIXME: magic numbers */ if (wd == MOTION_WORD(XYZZY) || wd == MOTION_WORD(PLUGH) || wd == MOTION_WORD(PLOVER) || @@ -1083,8 +1132,6 @@ static int throw (struct command_t *command) * (Only way to do so!) Axe also special for dragon, bear, and * troll. Treasures special for troll. */ { - if (TOTING(ROD2) && command->obj == ROD && !TOTING(ROD)) - command->obj = ROD2; if (!TOTING(command->obj)) { rspeak(actions[command->verb].message); return GO_CLEAROBJ; @@ -1118,7 +1165,7 @@ static int throw (struct command_t *command) else if (HERE(BEAR) && game.prop[BEAR] == UNTAMED_BEAR) { /* This'll teach him to throw the axe at the bear! */ drop(AXE, game.loc); - game.fixed[AXE] = -1; + game.fixed[AXE] = IS_FIXED; juggle(BEAR); state_change(AXE, AXE_LOST); return GO_CLEAROBJ; @@ -1170,7 +1217,7 @@ static int wave(token_t verb, token_t obj) if (game.prop[BIRD] == BIRD_UNCAGED && game.loc == game.place[STEPS] && game.prop[JADE] < 0) { drop(JADE, game.loc); - game.prop[JADE] = 0; + game.prop[JADE] = STATE_FOUND; --game.tally; rspeak(NECKLACE_FLY); return GO_CLEAROBJ; @@ -1193,9 +1240,8 @@ static int wave(token_t verb, token_t obj) CAGE_FLY : FREE_FLY); - /* FIXME: Arithemetic on property values */ - game.prop[FISSURE] = 1 - game.prop[FISSURE]; - pspeak(FISSURE, look, 2 - game.prop[FISSURE], true); + state_change(FISSURE, + game.prop[FISSURE] == BRIDGED ? UNBRIDGED : BRIDGED); return GO_CLEAROBJ; } } @@ -1266,7 +1312,7 @@ int action(struct command_t *command) return GO_WORD2; if (command->verb == SAY) command->obj = command->wd2; - if (command->obj == 0 || + if (command->obj == NO_OBJECT || command->obj == INTRANSITIVE) { /* Analyse an intransitive verb (ie, no object given yet). */ switch (command->verb) {