X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=actions.c;h=fed70b9099531db585b436d51984d6d13f81628f;hb=c11938aed5e261ac40a562781325996628663610;hp=4c2fcdbad111c600cfe745544de3898eb95c09f4;hpb=b125fe7b2ad09754364f8bef1f3d72a5837c7b82;p=open-adventure.git diff --git a/actions.c b/actions.c index 4c2fcdb..fed70b9 100644 --- a/actions.c +++ b/actions.c @@ -1,26 +1,24 @@ /* * Actions for the dungeon-running code. * - * Copyright (c) 1977, 2005 by Will Crowther and Don Woods - * Copyright (c) 2017 by Eric S. Raymond - * SPDX-License-Identifier: BSD-2-clause + * SPDX-FileCopyrightText: (C) 1977, 2005 Will Crowther and Don Woods + * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include -#include "advent.h" -#include "dungeon.h" #include +#include "advent.h" + static phase_codes_t fill(verb_t, obj_t); -static phase_codes_t attack(command_t command) +static phase_codes_t attack(command_t command) { /* Attack. Assume target if unambiguous. "Throw" also links here. * Attackable objects fall into two categories: enemies (snake, * dwarf, etc.) and others (bird, clam, machine). Ambiguous if 2 * enemies, or no enemies but 2 others. */ -{ verb_t verb = command.verb; obj_t obj = command.obj; @@ -34,7 +32,7 @@ static phase_codes_t attack(command_t command) obj = SNAKE; ++changes; } - if (AT(DRAGON) && game.prop[DRAGON] == DRAGON_BARS) { + if (AT(DRAGON) && game.objects[DRAGON].prop == DRAGON_BARS) { obj = DRAGON; ++changes; } @@ -46,7 +44,7 @@ static phase_codes_t attack(command_t command) obj = OGRE; ++changes; } - if (HERE(BEAR) && game.prop[BEAR] == UNTAMED_BEAR) { + if (HERE(BEAR) && game.objects[BEAR].prop == UNTAMED_BEAR) { obj = BEAR; ++changes; } @@ -83,13 +81,13 @@ static phase_codes_t attack(command_t command) } if (obj == VEND) { state_change(VEND, - game.prop[VEND] == VEND_BLOCKS ? VEND_UNBLOCKS : VEND_BLOCKS); + game.objects[VEND].prop == VEND_BLOCKS ? VEND_UNBLOCKS : VEND_BLOCKS); return GO_CLEAROBJ; } if (obj == BEAR) { - switch (game.prop[BEAR]) { + switch (game.objects[BEAR].prop) { case UNTAMED_BEAR: rspeak(BEAR_HANDS); break; @@ -105,7 +103,7 @@ static phase_codes_t attack(command_t command) } return GO_CLEAROBJ; } - if (obj == DRAGON && game.prop[DRAGON] == DRAGON_BARS) { + if (obj == DRAGON && game.objects[DRAGON].prop == 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, @@ -116,7 +114,7 @@ static phase_codes_t attack(command_t command) return GO_MOVE; } state_change(DRAGON, DRAGON_DEAD); - game.prop[RUG] = RUG_FLOOR; + game.objects[RUG].prop = RUG_FLOOR; /* Hardcoding LOC_SECRET5 as the dragon's death location is ugly. * The way it was computed before was worse; it depended on the * two dragon locations being LOC_SECRET4 and LOC_SECRET6 and @@ -128,8 +126,8 @@ static phase_codes_t attack(command_t command) move(RUG, LOC_SECRET5); drop(BLOOD, LOC_SECRET5); for (obj_t i = 1; i <= NOBJECTS; i++) { - if (game.place[i] == objects[DRAGON].plac || - game.place[i] == objects[DRAGON].fixd) + if (game.objects[i].place == objects[DRAGON].plac || + game.objects[i].place == objects[DRAGON].fixd) move(i, LOC_SECRET5); } game.loc = LOC_SECRET5; @@ -138,17 +136,17 @@ static phase_codes_t attack(command_t command) if (obj == OGRE) { rspeak(OGRE_DODGE); - if (atdwrf(game.loc) == 0) + 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) { + if (game.dwarves[i].loc == game.loc) { ++dwarves; - game.dloc[i] = LOC_LONGWEST; - game.dseen[i] = false; + game.dwarves[i].loc = LOC_LONGWEST; + game.dwarves[i].seen = false; } } rspeak((dwarves > 1) ? @@ -186,65 +184,65 @@ static phase_codes_t attack(command_t command) return GO_CLEAROBJ; } -static phase_codes_t bigwords(vocab_t id) +static phase_codes_t bigwords(vocab_t id) { /* Only called on FEE FIE FOE FOO (AND FUM). Advance to next state if given * in proper order. Look up foo in special section of vocab to determine which * word we've got. Last word zips the eggs back to the giant room (unless * already there). */ -{ int foobar = abs(game.foobar); + /* Only FEE can start a magic-word sequence. */ + if ((foobar == WORD_EMPTY) && (id == FIE || id == FOE || id == FOO || id == FUM)) { + rspeak(NOTHING_HAPPENS); + return GO_CLEAROBJ; + } + if ((foobar == WORD_EMPTY && id == FEE) || (foobar == FEE && id == FIE) || (foobar == FIE && id == FOE) || - (foobar == FOE && id == FOO) || - (foobar == FOE && id == FUM)) { + (foobar == FOE && id == FOO)) { game.foobar = id; - if ((id != FOO) && (id != FUM)) { + if (id != FOO) { rspeak(OK_MAN); return GO_CLEAROBJ; } game.foobar = WORD_EMPTY; - if (game.place[EGGS] == objects[EGGS].plac || + if (game.objects[EGGS].place == objects[EGGS].plac || (TOTING(EGGS) && game.loc == objects[EGGS].plac)) { rspeak(NOTHING_HAPPENS); return GO_CLEAROBJ; - } else if (id == FUM) { - goto fum; } else { /* Bring back troll if we steal the eggs back from him before * crossing. */ - if (game.place[EGGS] == LOC_NOWHERE && game.place[TROLL] == LOC_NOWHERE && game.prop[TROLL] == TROLL_UNPAID) - game.prop[TROLL] = TROLL_PAIDONCE; - if (HERE(EGGS)) + if (game.objects[EGGS].place == LOC_NOWHERE && game.objects[TROLL].place == LOC_NOWHERE + && game.objects[TROLL].prop == TROLL_UNPAID) + game.objects[TROLL].prop = TROLL_PAIDONCE; + if (HERE(EGGS)) { pspeak(EGGS, look, true, EGGS_VANISHED); - else if (game.loc == objects[EGGS].plac) + } else if (game.loc == objects[EGGS].plac) { pspeak(EGGS, look, true, EGGS_HERE); - else + } else { pspeak(EGGS, look, true, EGGS_DONE); + } move(EGGS, objects[EGGS].plac); return GO_CLEAROBJ; } } else { -fum: - if (game.loc == LOC_GIANTROOM || settings.oldstyle) { - rspeak(START_OVER); - } else { - /* This is new behavior in Open Adventure - sounds better when - * player isn't in the Giant Room. */ - rspeak(NOTHING_HAPPENS); - } + /* Magic-word sequence was started but is incorrect */ + if (settings.oldstyle || game.seenbigwords) { + rspeak(START_OVER); + } else { + rspeak(WELL_POINTLESS); + } game.foobar = WORD_EMPTY; return GO_CLEAROBJ; } } -static void blast(void) +static void blast(void) { /* Blast. No effect unless you've got dynamite, which is a neat trick! */ -{ - if (game.prop[ROD2] == STATE_NOTFOUND || - !game.closed) + if (PROP_IS_NOTFOUND(ROD2) || !game.closed) rspeak(REQUIRES_DYNAMITE); else { if (HERE(ROD2)) { @@ -261,9 +259,8 @@ static void blast(void) } } -static phase_codes_t vbreak(verb_t verb, obj_t obj) +static phase_codes_t vbreak(verb_t verb, obj_t obj) { /* Break. Only works for mirror in repository and, of course, the vase. */ -{ switch (obj) { case MIRROR: if (game.closed) { @@ -274,11 +271,11 @@ static phase_codes_t vbreak(verb_t verb, obj_t obj) break; } case VASE: - if (game.prop[VASE] == VASE_WHOLE) { + if (game.objects[VASE].prop == VASE_WHOLE) { if (TOTING(VASE)) drop(VASE, game.loc); state_change(VASE, VASE_BROKEN); - game.fixed[VASE] = IS_FIXED; + game.objects[VASE].fixed = IS_FIXED; break; } /* FALLTHRU */ @@ -288,27 +285,26 @@ static phase_codes_t vbreak(verb_t verb, obj_t obj) return (GO_CLEAROBJ); } -static phase_codes_t brief(void) +static phase_codes_t brief(void) { /* Brief. Intransitive only. Suppress full descriptions after first time. */ -{ game.abbnum = 10000; game.detail = 3; rspeak(BRIEF_CONFIRM); return GO_CLEAROBJ; } -static phase_codes_t vcarry(verb_t verb, obj_t obj) +static phase_codes_t vcarry(verb_t verb, obj_t obj) { /* Carry an object. Special cases for bird and cage (if bird in cage, can't * take one without the other). Liquids also special, since they depend on * status of bottle. Also various side effects, etc. */ -{ if (obj == INTRANSITIVE) { /* Carry, no object given yet. OK if only one object present. */ - if (game.atloc[game.loc] == NO_OBJECT || - game.link[game.atloc[game.loc]] != 0 || - atdwrf(game.loc) > 0) + if (game.locs[game.loc].atloc == NO_OBJECT || + game.link[game.locs[game.loc].atloc] != 0 || + atdwrf(game.loc) > 0) { return GO_UNKNOWN; - obj = game.atloc[game.loc]; + } + obj = game.locs[game.loc].atloc; } if (TOTING(obj)) { @@ -322,20 +318,20 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) return GO_CLEAROBJ; } - if (game.fixed[obj] != IS_FREE) { + if (game.objects[obj].fixed != IS_FREE) { switch (obj) { case PLANT: /* Next guard tests whether plant is tiny or stashed */ - rspeak(game.prop[PLANT] <= PLANT_THIRSTY ? DEEP_ROOTS : YOU_JOKING); + rspeak(game.objects[PLANT].prop <= PLANT_THIRSTY ? DEEP_ROOTS : YOU_JOKING); break; case BEAR: - rspeak( game.prop[BEAR] == SITTING_BEAR ? BEAR_CHAINED : YOU_JOKING); + rspeak( game.objects[BEAR].prop == SITTING_BEAR ? BEAR_CHAINED : YOU_JOKING); break; case CHAIN: - rspeak( game.prop[BEAR] != UNTAMED_BEAR ? STILL_LOCKED : YOU_JOKING); + rspeak( game.objects[BEAR].prop != UNTAMED_BEAR ? STILL_LOCKED : YOU_JOKING); break; case RUG: - rspeak(game.prop[RUG] == RUG_HOVER ? RUG_HOVERS : YOU_JOKING); + rspeak(game.objects[RUG].prop == RUG_HOVER ? RUG_HOVERS : YOU_JOKING); break; case URN: rspeak(URN_NOBUDGE); @@ -355,18 +351,17 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) return GO_CLEAROBJ; } - if (obj == WATER || - obj == OIL) { - if (!HERE(BOTTLE) || - LIQUID() != obj) { + if (obj == WATER || obj == OIL) { + if (!HERE(BOTTLE) || LIQUID() != obj) { if (!TOTING(BOTTLE)) { rspeak(NO_CONTAINER); return GO_CLEAROBJ; } - if (game.prop[BOTTLE] == EMPTY_BOTTLE) { + if (game.objects[BOTTLE].prop == EMPTY_BOTTLE) { return (fill(verb, BOTTLE)); - } else + } else { rspeak(BOTTLE_FULL); + } return GO_CLEAROBJ; } obj = BOTTLE; @@ -378,8 +373,8 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) } - if (obj == BIRD && game.prop[BIRD] != BIRD_CAGED && STASHED(BIRD) != BIRD_CAGED) { - if (game.prop[BIRD] == BIRD_FOREST_UNCAGED) { + if (obj == BIRD && game.objects[BIRD].prop != BIRD_CAGED && !PROP_IS_STASHED(BIRD)) { + if (game.objects[BIRD].prop == BIRD_FOREST_UNCAGED) { DESTROY(BIRD); rspeak(BIRD_CRAP); return GO_CLEAROBJ; @@ -392,62 +387,61 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) rspeak(BIRD_EVADES); return GO_CLEAROBJ; } - game.prop[BIRD] = BIRD_CAGED; + game.objects[BIRD].prop = BIRD_CAGED; } - if ((obj == BIRD || - obj == CAGE) && - (game.prop[BIRD] == BIRD_CAGED || STASHED(BIRD) == BIRD_CAGED)) { + if ((obj == BIRD || obj == CAGE) && + (game.objects[BIRD].prop == BIRD_CAGED || PROP_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() != NO_OBJECT) - game.place[LIQUID()] = CARRIED; + if (obj == BOTTLE && LIQUID() != NO_OBJECT) { + game.objects[LIQUID()].place = CARRIED; + } - if (GSTONE(obj) && game.prop[obj] != STATE_FOUND) { - game.prop[obj] = STATE_FOUND; - game.prop[CAVITY] = CAVITY_EMPTY; + if (GSTONE(obj) && !PROP_IS_FOUND(obj)) { + PROP_SET_FOUND(obj); + game.objects[CAVITY].prop = CAVITY_EMPTY; } rspeak(OK_MAN); return GO_CLEAROBJ; } -static int chain(verb_t verb) +static int chain(verb_t verb) { /* Do something to the bear's chain */ -{ if (verb != LOCK) { - if (game.prop[BEAR] == UNTAMED_BEAR) { + if (game.objects[BEAR].prop == UNTAMED_BEAR) { rspeak(BEAR_BLOCKS); return GO_CLEAROBJ; } - if (game.prop[CHAIN] == CHAIN_HEAP) { + if (game.objects[CHAIN].prop == CHAIN_HEAP) { rspeak(ALREADY_UNLOCKED); return GO_CLEAROBJ; } - game.prop[CHAIN] = CHAIN_HEAP; - game.fixed[CHAIN] = IS_FREE; - if (game.prop[BEAR] != BEAR_DEAD) - game.prop[BEAR] = CONTENTED_BEAR; + game.objects[CHAIN].prop = CHAIN_HEAP; + game.objects[CHAIN].fixed = IS_FREE; + if (game.objects[BEAR].prop != BEAR_DEAD) + game.objects[BEAR].prop = CONTENTED_BEAR; - switch (game.prop[BEAR]) { + switch (game.objects[BEAR].prop) { // LCOV_EXCL_START case BEAR_DEAD: /* Can't be reached until the bear can die in some way other * than a bridge collapse. Leave in in case this changes, but * exclude from coverage testing. */ - game.fixed[BEAR] = IS_FIXED; + game.objects[BEAR].fixed = IS_FIXED; break; // LCOV_EXCL_STOP default: - game.fixed[BEAR] = IS_FREE; + game.objects[BEAR].fixed = IS_FREE; } rspeak(CHAIN_UNLOCKED); return GO_CLEAROBJ; } - if (game.prop[CHAIN] != CHAIN_HEAP) { + if (game.objects[CHAIN].prop != CHAIN_HEAP) { rspeak(ALREADY_LOCKED); return GO_CLEAROBJ; } @@ -456,21 +450,20 @@ static int chain(verb_t verb) return GO_CLEAROBJ; } - game.prop[CHAIN] = CHAIN_FIXED; + game.objects[CHAIN].prop = CHAIN_FIXED; if (TOTING(CHAIN)) drop(CHAIN, game.loc); - game.fixed[CHAIN] = IS_FIXED; + game.objects[CHAIN].fixed = IS_FIXED; rspeak(CHAIN_LOCKED); return GO_CLEAROBJ; } -static phase_codes_t discard(verb_t verb, obj_t obj) +static phase_codes_t discard(verb_t verb, obj_t obj) { /* Discard object. "Throw" also comes here for most objects. Special cases for * bird (might attack snake or dragon) and cage (might contain bird) and vase. * Drop coins at vending machine for extra batteries. */ -{ if (obj == ROD && !TOTING(ROD) && TOTING(ROD2)) { obj = ROD2; } @@ -480,23 +473,25 @@ static phase_codes_t discard(verb_t verb, obj_t obj) return GO_CLEAROBJ; } - if (GSTONE(obj) && AT(CAVITY) && game.prop[CAVITY] != CAVITY_FULL) { + if (GSTONE(obj) && AT(CAVITY) && game.objects[CAVITY].prop != CAVITY_FULL) { rspeak(GEM_FITS); - 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))) { - if (obj == RUBY) - rspeak(RUG_SETTLES); - else if (TOTING(RUG)) - rspeak(RUG_WIGGLES); - else - rspeak(RUG_RISES); + game.objects[obj].prop = STATE_IN_CAVITY; + game.objects[CAVITY].prop = CAVITY_FULL; + if (HERE(RUG) && ((obj == EMERALD && game.objects[RUG].prop != RUG_HOVER) || + (obj == RUBY && game.objects[RUG].prop == RUG_HOVER))) { + if (obj == RUBY) { + rspeak(RUG_SETTLES); + } else if (TOTING(RUG)) { + rspeak(RUG_WIGGLES); + } else { + rspeak(RUG_RISES); + } if (!TOTING(RUG) || obj == RUBY) { - int k = (game.prop[RUG] == RUG_HOVER) ? RUG_FLOOR : RUG_HOVER; - game.prop[RUG] = k; - if (k == RUG_HOVER) + int k = (game.objects[RUG].prop == RUG_HOVER) ? RUG_FLOOR : RUG_HOVER; + game.objects[RUG].prop = k; + if (k == RUG_HOVER) { k = objects[SAPPH].plac; + } move(RUG + NOBJECTS, k); } } @@ -511,10 +506,11 @@ static phase_codes_t discard(verb_t verb, obj_t obj) return GO_CLEAROBJ; } - if (LIQUID() == obj) + if (LIQUID() == obj) { obj = BOTTLE; + } if (obj == BOTTLE && LIQUID() != NO_OBJECT) { - game.place[LIQUID()] = LOC_NOWHERE; + game.objects[LIQUID()].place = LOC_NOWHERE; } if (obj == BEAR && AT(TROLL)) { @@ -533,34 +529,37 @@ static phase_codes_t discard(verb_t verb, obj_t obj) state_change(VASE, AT(PILLOW) ? VASE_WHOLE : VASE_DROPPED); - if (game.prop[VASE] != VASE_WHOLE) - game.fixed[VASE] = IS_FIXED; + if (game.objects[VASE].prop != VASE_WHOLE) { + game.objects[VASE].fixed = IS_FIXED; + } drop(obj, game.loc); return GO_CLEAROBJ; } } - if (obj == CAGE && game.prop[BIRD] == BIRD_CAGED) { + if (obj == CAGE && game.objects[BIRD].prop == BIRD_CAGED) { drop(BIRD, game.loc); } if (obj == BIRD) { - if (AT(DRAGON) && game.prop[DRAGON] == DRAGON_BARS) { + if (AT(DRAGON) && game.objects[DRAGON].prop == DRAGON_BARS) { rspeak(BIRD_BURNT); DESTROY(BIRD); return GO_CLEAROBJ; } if (HERE(SNAKE)) { rspeak(BIRD_ATTACKS); - if (game.closed) + if (game.closed) { return GO_DWARFWAKE; + } DESTROY(SNAKE); /* Set game.prop for use by travel options */ - game.prop[SNAKE] = SNAKE_CHASED; - } else + game.objects[SNAKE].prop = SNAKE_CHASED; + } else { rspeak(OK_MAN); + } - game.prop[BIRD] = FOREST(game.loc) ? BIRD_FOREST_UNCAGED : BIRD_UNCAGED; + game.objects[BIRD].prop = FOREST(game.loc) ? BIRD_FOREST_UNCAGED : BIRD_UNCAGED; drop(obj, game.loc); return GO_CLEAROBJ; } @@ -570,10 +569,9 @@ static phase_codes_t discard(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t drink(verb_t verb, obj_t obj) +static phase_codes_t drink(verb_t verb, obj_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 == INTRANSITIVE && LIQLOC(game.loc) != WATER && (LIQUID() != WATER || !HERE(BOTTLE))) { return GO_UNKNOWN; @@ -591,7 +589,7 @@ static phase_codes_t drink(verb_t verb, obj_t obj) return GO_CLEAROBJ; } if (LIQUID() == WATER && HERE(BOTTLE)) { - game.place[WATER] = LOC_NOWHERE; + game.objects[WATER].place = LOC_NOWHERE; state_change(BOTTLE, EMPTY_BOTTLE); return GO_CLEAROBJ; } @@ -600,10 +598,9 @@ static phase_codes_t drink(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t eat(verb_t verb, obj_t obj) +static phase_codes_t eat(verb_t verb, obj_t obj) { /* Eat. Intransitive: assume food if present, else ask what. Transitive: food * ok, some things lose appetite, rest are ridiculous. */ -{ switch (obj) { case INTRANSITIVE: if (!HERE(FOOD)) @@ -630,21 +627,23 @@ static phase_codes_t eat(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t extinguish(verb_t verb, obj_t obj) +static phase_codes_t extinguish(verb_t verb, obj_t obj) { /* Extinguish. Lamp, urn, dragon/volcano (nice try). */ -{ if (obj == INTRANSITIVE) { - if (HERE(LAMP) && game.prop[LAMP] == LAMP_BRIGHT) - obj = LAMP; - if (HERE(URN) && game.prop[URN] == URN_LIT) - obj = URN; - if (obj == INTRANSITIVE) - return GO_UNKNOWN; + if (HERE(LAMP) && game.objects[LAMP].prop == LAMP_BRIGHT) { + obj = LAMP; + } + if (HERE(URN) && game.objects[URN].prop == URN_LIT) { + obj = URN; + } + if (obj == INTRANSITIVE) { + return GO_UNKNOWN; + } } switch (obj) { case URN: - if (game.prop[URN] != URN_EMPTY) { + if (game.objects[URN].prop != URN_EMPTY) { state_change(URN, URN_DARK); } else { pspeak(URN, change, true, URN_DARK); @@ -666,26 +665,27 @@ static phase_codes_t extinguish(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t feed(verb_t verb, obj_t obj) +static phase_codes_t feed(verb_t verb, obj_t obj) { /* Feed. If bird, no seed. Snake, dragon, troll: quip. If dwarf, make him * mad. Bear, special. */ -{ switch (obj) { case BIRD: rspeak(BIRD_PINING); break; case DRAGON: - if (game.prop[DRAGON] != DRAGON_BARS) - rspeak(RIDICULOUS_ATTEMPT); - else - rspeak(NOTHING_EDIBLE); + if (game.objects[DRAGON].prop != DRAGON_BARS) { + rspeak(RIDICULOUS_ATTEMPT); + } else { + rspeak(NOTHING_EDIBLE); + } break; case SNAKE: if (!game.closed && HERE(BIRD)) { DESTROY(BIRD); rspeak(BIRD_DEVOURED); - } else + } else { rspeak(NOTHING_EDIBLE); + } break; case TROLL: rspeak(TROLL_VICES); @@ -694,31 +694,34 @@ static phase_codes_t feed(verb_t verb, obj_t obj) if (HERE(FOOD)) { game.dflag += 2; rspeak(REALLY_MAD); - } else + } else { speak(actions[verb].message); + } break; case BEAR: - if (game.prop[BEAR] == BEAR_DEAD) { + if (game.objects[BEAR].prop == BEAR_DEAD) { rspeak(RIDICULOUS_ATTEMPT); break; } - if (game.prop[BEAR] == UNTAMED_BEAR) { + if (game.objects[BEAR].prop == UNTAMED_BEAR) { if (HERE(FOOD)) { DESTROY(FOOD); - game.fixed[AXE] = IS_FREE; - game.prop[AXE] = AXE_HERE; + game.objects[AXE].fixed = IS_FREE; + game.objects[AXE].prop = AXE_HERE; state_change(BEAR, SITTING_BEAR); - } else + } else { rspeak(NOTHING_EDIBLE); + } break; } speak(actions[verb].message); break; case OGRE: - if (HERE(FOOD)) - rspeak(OGRE_FULL); - else - speak(actions[verb].message); + if (HERE(FOOD)) { + rspeak(OGRE_FULL); + } else { + speak(actions[verb].message); + } break; default: rspeak(AM_GAME); @@ -726,10 +729,9 @@ static phase_codes_t feed(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -phase_codes_t fill(verb_t verb, obj_t obj) +phase_codes_t fill(verb_t verb, obj_t obj) { /* Fill. Bottle or urn must be empty, and liquid available. (Vase * is nasty.) */ -{ if (obj == VASE) { if (LIQLOC(game.loc) == NO_OBJECT) { rspeak(FILL_INVALID); @@ -740,14 +742,14 @@ phase_codes_t fill(verb_t verb, obj_t obj) return GO_CLEAROBJ; } rspeak(SHATTER_VASE); - game.prop[VASE] = VASE_BROKEN; - game.fixed[VASE] = IS_FIXED; + game.objects[VASE].prop = VASE_BROKEN; + game.objects[VASE].fixed = IS_FIXED; drop(VASE, game.loc); return GO_CLEAROBJ; } if (obj == URN) { - if (game.prop[URN] != URN_EMPTY) { + if (game.objects[URN].prop != URN_EMPTY) { rspeak(FULL_URN); return GO_CLEAROBJ; } @@ -758,12 +760,12 @@ phase_codes_t fill(verb_t verb, obj_t obj) int k = LIQUID(); switch (k) { case WATER: - game.prop[BOTTLE] = EMPTY_BOTTLE; + game.objects[BOTTLE].prop = EMPTY_BOTTLE; rspeak(WATER_URN); break; case OIL: - game.prop[URN] = URN_DARK; - game.prop[BOTTLE] = EMPTY_BOTTLE; + game.objects[URN].prop = URN_DARK; + game.objects[BOTTLE].prop = EMPTY_BOTTLE; rspeak(OIL_URN); break; case NO_OBJECT: @@ -771,7 +773,7 @@ phase_codes_t fill(verb_t verb, obj_t obj) rspeak(FILL_INVALID); return GO_CLEAROBJ; } - game.place[k] = LOC_NOWHERE; + game.objects[k].place = LOC_NOWHERE; return GO_CLEAROBJ; } if (obj != INTRANSITIVE && obj != BOTTLE) { @@ -781,7 +783,7 @@ phase_codes_t fill(verb_t verb, obj_t obj) if (obj == INTRANSITIVE && !HERE(BOTTLE)) return GO_UNKNOWN; - if (HERE(URN) && game.prop[URN] != URN_EMPTY) { + if (HERE(URN) && game.objects[URN].prop != URN_EMPTY) { rspeak(URN_NOPOUR); return GO_CLEAROBJ; } @@ -797,14 +799,14 @@ phase_codes_t fill(verb_t verb, obj_t obj) state_change(BOTTLE, (LIQLOC(game.loc) == OIL) ? OIL_BOTTLE : WATER_BOTTLE); - if (TOTING(BOTTLE)) - game.place[LIQUID()] = CARRIED; + if (TOTING(BOTTLE)) { + game.objects[LIQUID()].place = CARRIED; + } return GO_CLEAROBJ; } -static phase_codes_t find(verb_t verb, obj_t obj) +static phase_codes_t find(verb_t verb, obj_t obj) { /* Find. Might be carrying it, or it might be here. Else give caveat. */ -{ if (TOTING(obj)) { rspeak(ALREADY_CARRYING); return GO_CLEAROBJ; @@ -815,10 +817,8 @@ static phase_codes_t find(verb_t verb, obj_t obj) return GO_CLEAROBJ; } - if (AT(obj) || - (LIQUID() == obj && AT(BOTTLE)) || - obj == LIQLOC(game.loc) || - (obj == DWARF && atdwrf(game.loc) > 0)) { + if (AT(obj) || (LIQUID() == obj && AT(BOTTLE)) || + obj == LIQLOC(game.loc) || (obj == DWARF && atdwrf(game.loc) > 0)) { rspeak(YOU_HAVEIT); return GO_CLEAROBJ; } @@ -828,15 +828,14 @@ static phase_codes_t find(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t fly(verb_t verb, obj_t obj) +static phase_codes_t fly(verb_t verb, obj_t obj) { /* Fly. Snide remarks unless hovering rug is here. */ -{ if (obj == INTRANSITIVE) { if (!HERE(RUG)) { rspeak(FLAP_ARMS); return GO_CLEAROBJ; } - if (game.prop[RUG] != RUG_HOVER) { + if (game.objects[RUG].prop != RUG_HOVER) { rspeak(RUG_NOTHING2); return GO_CLEAROBJ; } @@ -847,7 +846,7 @@ static phase_codes_t fly(verb_t verb, obj_t obj) speak(actions[verb].message); return GO_CLEAROBJ; } - if (game.prop[RUG] != RUG_HOVER) { + if (game.objects[RUG].prop != RUG_HOVER) { rspeak(RUG_NOTHING1); return GO_CLEAROBJ; } @@ -871,13 +870,11 @@ static phase_codes_t fly(verb_t verb, obj_t obj) return GO_TERMINATE; } -static phase_codes_t inven(void) +static phase_codes_t inven(void) { /* Inventory. If object, treat same as find. Else report on current burden. */ -{ bool empty = true; for (obj_t i = 1; i <= NOBJECTS; i++) { - if (i == BEAR || - !TOTING(i)) + if (i == BEAR || !TOTING(i)) continue; if (empty) { rspeak(NOW_HOLDING); @@ -892,16 +889,15 @@ static phase_codes_t inven(void) return GO_CLEAROBJ; } -static phase_codes_t light(verb_t verb, obj_t obj) +static phase_codes_t light(verb_t verb, obj_t obj) { /* Light. Applicable only to lamp and urn. */ -{ if (obj == INTRANSITIVE) { int selects = 0; - if (HERE(LAMP) && game.prop[LAMP] == LAMP_DARK && game.limit >= 0) { + if (HERE(LAMP) && game.objects[LAMP].prop == LAMP_DARK && game.limit >= 0) { obj = LAMP; selects++; } - if (HERE(URN) && game.prop[URN] == URN_DARK) { + if (HERE(URN) && game.objects[URN].prop == URN_DARK) { obj = URN; selects++; } @@ -911,7 +907,7 @@ static phase_codes_t light(verb_t verb, obj_t obj) switch (obj) { case URN: - state_change(URN, game.prop[URN] == URN_EMPTY ? + state_change(URN, game.objects[URN].prop == URN_EMPTY ? URN_EMPTY : URN_LIT); break; @@ -921,8 +917,9 @@ static phase_codes_t light(verb_t verb, obj_t obj) break; } state_change(LAMP, LAMP_BRIGHT); - if (game.wzdark) + if (game.wzdark) { return GO_TOP; + } break; default: speak(actions[verb].message); @@ -930,55 +927,61 @@ static phase_codes_t light(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t listen(void) +static phase_codes_t listen(void) { /* Listen. Intransitive only. Print stuff based on object sound properties. */ -{ bool soundlatch = false; vocab_t sound = locations[game.loc].sound; if (sound != SILENT) { rspeak(sound); - if (!locations[game.loc].loud) + if (!locations[game.loc].loud) { rspeak(NO_MESSAGE); + } soundlatch = true; } for (obj_t i = 1; i <= NOBJECTS; i++) { - if (!HERE(i) || - objects[i].sounds[0] == NULL || - game.prop[i] < 0) - continue; - int mi = game.prop[i]; + if (!HERE(i) || objects[i].sounds[0] == NULL || PROP_IS_STASHED_OR_UNSEEN(i)) { + continue; + } + int mi = game.objects[i].prop; /* (ESR) Some unpleasant magic on object states here. Ideally * we'd have liked the bird to be a normal object that we can * use state_change() on; can't do it, because there are * actually two different series of per-state birdsounds * depending on whether player has drunk dragon's blood. */ - if (i == BIRD) + if (i == BIRD) { mi += 3 * game.blooded; + } pspeak(i, hear, true, mi, game.zzword); rspeak(NO_MESSAGE); - if (i == BIRD && mi == BIRD_ENDSTATE) + if (i == BIRD && mi == BIRD_ENDSTATE) { DESTROY(BIRD); + } soundlatch = true; } - if (!soundlatch) + if (!soundlatch) { rspeak(ALL_SILENT); + } return GO_CLEAROBJ; } -static phase_codes_t lock(verb_t verb, obj_t obj) +static phase_codes_t lock(verb_t verb, obj_t obj) { /* Lock, unlock, no object given. Assume various things if present. */ -{ if (obj == INTRANSITIVE) { - if (HERE(CLAM)) - obj = CLAM; - if (HERE(OYSTER)) - obj = OYSTER; - if (AT(DOOR)) - obj = DOOR; - if (AT(GRATE)) - obj = GRATE; - if (HERE(CHAIN)) - obj = CHAIN; + if (HERE(CLAM)) { + obj = CLAM; + } + if (HERE(OYSTER)) { + obj = OYSTER; + } + if (AT(DOOR)) { + obj = DOOR; + } + if (AT(GRATE)) { + obj = GRATE; + } + if (HERE(CHAIN)) { + obj = CHAIN; + } if (obj == INTRANSITIVE) { rspeak(NOTHING_LOCKED); return GO_CLEAROBJ; @@ -992,32 +995,35 @@ static phase_codes_t lock(verb_t verb, obj_t obj) case CHAIN: if (HERE(KEYS)) { return chain(verb); - } else + } else { rspeak(NO_KEYS); + } break; case GRATE: if (HERE(KEYS)) { if (game.closng) { rspeak(EXIT_CLOSED); - if (!game.panic) + if (!game.panic) { game.clock2 = PANICTIME; + } game.panic = true; } else { state_change(GRATE, (verb == LOCK) ? GRATE_CLOSED : GRATE_OPEN); } - } else + } else { rspeak(NO_KEYS); + } break; case CLAM: - if (verb == LOCK) - rspeak(HUH_MAN); - else if (TOTING(CLAM)) - rspeak(DROP_CLAM); - else if (!TOTING(TRIDENT)) - rspeak(CLAM_OPENER); - else { + if (verb == LOCK) { + rspeak(HUH_MAN); + } else if (TOTING(CLAM)) { + rspeak(DROP_CLAM); + } else if (!TOTING(TRIDENT)) { + rspeak(CLAM_OPENER); + } else { DESTROY(CLAM); drop(OYSTER, game.loc); drop(PEARL, LOC_CULDESAC); @@ -1025,17 +1031,18 @@ static phase_codes_t lock(verb_t verb, obj_t obj) } break; case OYSTER: - if (verb == LOCK) - rspeak(HUH_MAN); - else if (TOTING(OYSTER)) - rspeak(DROP_OYSTER); - else if (!TOTING(TRIDENT)) - rspeak(OYSTER_OPENER); - else - rspeak(OYSTER_OPENS); + if (verb == LOCK) { + rspeak(HUH_MAN); + } else if (TOTING(OYSTER)) { + rspeak(DROP_OYSTER); + } else if (!TOTING(TRIDENT)) { + rspeak(OYSTER_OPENER); + } else { + rspeak(OYSTER_OPENS); + } break; case DOOR: - rspeak((game.prop[DOOR] == DOOR_UNRUSTED) ? OK_MAN : RUSTY_DOOR); + rspeak((game.objects[DOOR].prop == DOOR_UNRUSTED) ? OK_MAN : RUSTY_DOOR); break; case CAGE: rspeak( NO_LOCK); @@ -1050,15 +1057,15 @@ static phase_codes_t lock(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t pour(verb_t verb, obj_t obj) +static phase_codes_t pour(verb_t verb, obj_t obj) { /* Pour. If no object, or object is bottle, assume contents of bottle. * special tests for pouring water or oil on plant or rusty door. */ -{ - if (obj == BOTTLE || - obj == INTRANSITIVE) - obj = LIQUID(); - if (obj == NO_OBJECT) - return GO_UNKNOWN; + if (obj == BOTTLE || obj == INTRANSITIVE) { + obj = LIQUID(); + } + if (obj == NO_OBJECT) { + return GO_UNKNOWN; + } if (!TOTING(obj)) { speak(actions[verb].message); return GO_CLEAROBJ; @@ -1068,20 +1075,20 @@ static phase_codes_t pour(verb_t verb, obj_t obj) rspeak(CANT_POUR); return GO_CLEAROBJ; } - if (HERE(URN) && game.prop[URN] == URN_EMPTY) + if (HERE(URN) && game.objects[URN].prop == URN_EMPTY) { return fill(verb, URN); - game.prop[BOTTLE] = EMPTY_BOTTLE; - game.place[obj] = LOC_NOWHERE; - if (!(AT(PLANT) || - AT(DOOR))) { + } + game.objects[BOTTLE].prop = EMPTY_BOTTLE; + game.objects[obj].place = LOC_NOWHERE; + if (!(AT(PLANT) || AT(DOOR))) { rspeak(GROUND_WET); return GO_CLEAROBJ; } 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]; + state_change(PLANT, MOD(game.objects[PLANT].prop + 1, 3)); + game.objects[PLANT2].prop = game.objects[PLANT].prop; return GO_MOVE; } else { rspeak(SHAKING_LEAVES); @@ -1095,11 +1102,11 @@ static phase_codes_t pour(verb_t verb, obj_t obj) } } -static phase_codes_t quit(void) +static phase_codes_t quit(void) { /* Quit. Intransitive only. Verify intent and exit if that's what he wants. */ -{ - if (yes_or_no(arbitrary_messages[REALLY_QUIT], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN])) - terminate(quitgame); + if (yes_or_no(arbitrary_messages[REALLY_QUIT], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN])) { + terminate(quitgame); + } return GO_CLEAROBJ; } @@ -1109,13 +1116,13 @@ static phase_codes_t read(command_t command) if (command.obj == INTRANSITIVE) { command.obj = NO_OBJECT; for (int i = 1; i <= NOBJECTS; i++) { - if (HERE(i) && objects[i].texts[0] != NULL && game.prop[i] >= 0) - command.obj = command.obj * NOBJECTS + i; + if (HERE(i) && objects[i].texts[0] != NULL && !PROP_IS_STASHED(i)) { + command.obj = command.obj * NOBJECTS + i; + } } - if (command.obj > NOBJECTS || - command.obj == NO_OBJECT || - DARK(game.loc)) + if (command.obj > NOBJECTS || command.obj == NO_OBJECT || DARK(game.loc)) { return GO_UNKNOWN; + } } if (DARK(game.loc)) { @@ -1128,23 +1135,22 @@ static phase_codes_t read(command_t command) } else { pspeak(OYSTER, hear, true, 1); // Not really a sound, but oh well. } - } else if (objects[command.obj].texts[0] == NULL || - game.prop[command.obj] == STATE_NOTFOUND) { + } else if (objects[command.obj].texts[0] == NULL || PROP_IS_NOTFOUND(command.obj)) { speak(actions[command.verb].message); - } else - pspeak(command.obj, study, true, game.prop[command.obj]); + } else { + pspeak(command.obj, study, true, game.objects[command.obj].prop); + } return GO_CLEAROBJ; } -static phase_codes_t reservoir(void) +static phase_codes_t reservoir(void) { /* Z'ZZZ (word gets recomputed at startup; different each game). */ -{ if (!AT(RESER) && game.loc != LOC_RESBOTTOM) { rspeak(NOTHING_HAPPENS); return GO_CLEAROBJ; } else { state_change(RESER, - game.prop[RESER] == WATERS_PARTED ? WATERS_UNPARTED : WATERS_PARTED); + game.objects[RESER].prop == WATERS_PARTED ? WATERS_UNPARTED : WATERS_PARTED); if (AT(RESER)) return GO_CLEAROBJ; else { @@ -1156,13 +1162,12 @@ static phase_codes_t reservoir(void) } } -static phase_codes_t rub(verb_t verb, obj_t obj) +static phase_codes_t rub(verb_t verb, obj_t obj) { /* Rub. Yields various snide remarks except for lit urn. */ -{ - if (obj == URN && game.prop[URN] == URN_LIT) { + if (obj == URN && game.objects[URN].prop == URN_LIT) { DESTROY(URN); drop(AMBER, game.loc); - game.prop[AMBER] = AMBER_IN_ROCK; + game.objects[AMBER].prop = AMBER_IN_ROCK; --game.tally; drop(CAVITY, game.loc); rspeak(URN_GENIES); @@ -1174,17 +1179,17 @@ static phase_codes_t rub(verb_t verb, obj_t obj) return GO_CLEAROBJ; } -static phase_codes_t say(command_t command) +static phase_codes_t say(command_t command) { /* Say. Echo WD2. Magic words override. */ -{ if (command.word[1].type == MOTION && (command.word[1].id == XYZZY || command.word[1].id == PLUGH || command.word[1].id == PLOVER)) { return GO_WORD2; } - if (command.word[1].type == ACTION && command.word[1].id == PART) + if (command.word[1].type == ACTION && command.word[1].id == PART) { return reservoir(); + } if (command.word[1].type == ACTION && (command.word[1].id == FEE || @@ -1206,12 +1211,11 @@ static phase_codes_t throw_support(vocab_t spk) return GO_MOVE; } -static phase_codes_t throwit(command_t command) +static phase_codes_t throwit(command_t command) { /* Throw. Same as discard unless axe. Then same as attack except * ignore bird, and if dwarf is present then one might be killed. * (Only way to do so!) Axe also special for dragon, bear, and * troll. Treasures special for troll. */ -{ if (!TOTING(command.obj)) { speak(actions[command.verb].message); return GO_CLEAROBJ; @@ -1232,20 +1236,22 @@ static phase_codes_t throwit(command_t command) command.obj = BEAR; return (feed(command.verb, command.obj)); } - if (command.obj != AXE) + if (command.obj != AXE) { return (discard(command.verb, command.obj)); - else { + } else { if (atdwrf(game.loc) <= 0) { - if (AT(DRAGON) && game.prop[DRAGON] == DRAGON_BARS) + if (AT(DRAGON) && game.objects[DRAGON].prop == DRAGON_BARS) return throw_support(DRAGON_SCALES); - if (AT(TROLL)) - return throw_support(TROLL_RETURNS); - if (AT(OGRE)) + if (AT(TROLL)) { + return throw_support(TROLL_RETURNS); + } + if (AT(OGRE)) { return throw_support(OGRE_DODGE); - if (HERE(BEAR) && game.prop[BEAR] == UNTAMED_BEAR) { + } + if (HERE(BEAR) && game.objects[BEAR].prop == UNTAMED_BEAR) { /* This'll teach him to throw the axe at the bear! */ drop(AXE, game.loc); - game.fixed[AXE] = IS_FIXED; + game.objects[AXE].fixed = IS_FIXED; juggle(BEAR); state_change(AXE, AXE_LOST); return GO_CLEAROBJ; @@ -1258,8 +1264,8 @@ static phase_codes_t throwit(command_t command) return throw_support(DWARF_DODGES); } else { int i = atdwrf(game.loc); - game.dseen[i] = false; - game.dloc[i] = LOC_NOWHERE; + game.dwarves[i].seen = false; + game.dwarves[i].loc = LOC_NOWHERE; return throw_support((++game.dkill == 1) ? DWARF_SMOKE : KILLED_DWARF); @@ -1267,11 +1273,9 @@ static phase_codes_t throwit(command_t command) } } -static phase_codes_t wake(verb_t verb, obj_t obj) +static phase_codes_t wake(verb_t verb, obj_t obj) { /* Wake. Only use is to disturb the dwarves. */ -{ - if (obj != DWARF || - !game.closed) { + if (obj != DWARF || !game.closed) { speak(actions[verb].message); return GO_CLEAROBJ; } else { @@ -1280,9 +1284,8 @@ static phase_codes_t wake(verb_t verb, obj_t obj) } } -static phase_codes_t seed(verb_t verb, const char *arg) +static phase_codes_t seed(verb_t verb, const char *arg) { /* Set seed */ -{ int32_t seed = strtol(arg, NULL, 10); speak(actions[verb].message, seed); set_seed(seed); @@ -1290,22 +1293,16 @@ static phase_codes_t seed(verb_t verb, const char *arg) return GO_TOP; } -static phase_codes_t waste(verb_t verb, turn_t turns) +static phase_codes_t waste(verb_t verb, turn_t turns) { /* Burn turns */ -{ game.limit -= turns; speak(actions[verb].message, (int)game.limit); return GO_TOP; } -static phase_codes_t wave(verb_t verb, obj_t obj) +static phase_codes_t wave(verb_t verb, obj_t obj) { /* Wave. No effect unless waving rod at fissure or at bird. */ -{ - if (obj != ROD || - !TOTING(obj) || - (!HERE(BIRD) && - (game.closng || - !AT(FISSURE)))) { + if (obj != ROD || !TOTING(obj) || (!HERE(BIRD) && (game.closng || !AT(FISSURE)))) { speak(((!TOTING(obj)) && (obj != ROD || !TOTING(ROD2))) ? arbitrary_messages[ARENT_CARRYING] : @@ -1313,42 +1310,41 @@ static phase_codes_t wave(verb_t verb, obj_t obj) return GO_CLEAROBJ; } - if (game.prop[BIRD] == BIRD_UNCAGED && game.loc == game.place[STEPS] && game.prop[JADE] == STATE_NOTFOUND) { + if (game.objects[BIRD].prop == BIRD_UNCAGED && game.loc == game.objects[STEPS].place + && PROP_IS_NOTFOUND(JADE)) { drop(JADE, game.loc); - game.prop[JADE] = STATE_FOUND; + PROP_SET_FOUND(JADE); --game.tally; rspeak(NECKLACE_FLY); return GO_CLEAROBJ; } else { if (game.closed) { - rspeak((game.prop[BIRD] == BIRD_CAGED) ? + rspeak((game.objects[BIRD].prop == BIRD_CAGED) ? CAGE_FLY : FREE_FLY); return GO_DWARFWAKE; } - if (game.closng || - !AT(FISSURE)) { - rspeak((game.prop[BIRD] == BIRD_CAGED) ? + if (game.closng || !AT(FISSURE)) { + rspeak((game.objects[BIRD].prop == BIRD_CAGED) ? CAGE_FLY : FREE_FLY); return GO_CLEAROBJ; } if (HERE(BIRD)) - rspeak((game.prop[BIRD] == BIRD_CAGED) ? + rspeak((game.objects[BIRD].prop == BIRD_CAGED) ? CAGE_FLY : FREE_FLY); state_change(FISSURE, - game.prop[FISSURE] == BRIDGED ? UNBRIDGED : BRIDGED); + game.objects[FISSURE].prop == BRIDGED ? UNBRIDGED : BRIDGED); return GO_CLEAROBJ; } } -phase_codes_t action(command_t command) +phase_codes_t action(command_t command) { /* Analyse a verb. Remember what it was, go back for object if second word * unless verb is "say", which snarfs arbitrary second word. */ -{ /* Previously, actions that result in a message, but don't do anything * further were called "specials". Now they're handled here as normal * actions. If noaction is true, then we spit out the message and return */ @@ -1365,17 +1361,17 @@ phase_codes_t action(command_t command) * they are never actually dropped at any location, but might * be here inside the bottle or urn or as a feature of the * location. */ - if (HERE(command.obj)) - /* FALL THROUGH */; - else if (command.obj == DWARF && atdwrf(game.loc) > 0) - /* FALL THROUGH */; - else if (!game.closed && ((LIQUID() == command.obj && HERE(BOTTLE)) || - command.obj == LIQLOC(game.loc))) - /* FALL THROUGH */; - else if (command.obj == OIL && HERE(URN) && game.prop[URN] != URN_EMPTY) { + if (HERE(command.obj)) { + /* FALL THROUGH */; + } else if (command.obj == DWARF && atdwrf(game.loc) > 0) { + /* FALL THROUGH */; + } else if (!game.closed && ((LIQUID() == command.obj && HERE(BOTTLE)) || + command.obj == LIQLOC(game.loc))) { + /* FALL THROUGH */; + } else if (command.obj == OIL && HERE(URN) && game.objects[URN].prop != URN_EMPTY) { command.obj = URN; /* FALL THROUGH */; - } else if (command.obj == PLANT && AT(PLANT2) && game.prop[PLANT2] != PLANT_THIRSTY) { + } else if (command.obj == PLANT && AT(PLANT2) && game.objects[PLANT2].prop != PLANT_THIRSTY) { command.obj = PLANT2; /* FALL THROUGH */; } else if (command.obj == KNIFE && game.knfloc == game.loc) { @@ -1386,28 +1382,30 @@ phase_codes_t action(command_t command) command.obj = ROD2; /* FALL THROUGH */; } else if ((command.verb == FIND || - command.verb == INVENTORY) && (command.word[1].id == WORD_EMPTY || command.word[1].id == WORD_NOT_FOUND)) + command.verb == INVENTORY) && (command.word[1].id == WORD_EMPTY || command.word[1].id == WORD_NOT_FOUND)) { /* FALL THROUGH */; - else { + } else { sspeak(NO_SEE, command.word[0].raw); return GO_CLEAROBJ; } - if (command.verb != 0) + if (command.verb != 0) { command.part = transitive; + } } switch (command.part) { case intransitive: - if (command.word[1].raw[0] != '\0' && command.verb != SAY) - return GO_WORD2; - if (command.verb == SAY) - /* KEYS is not special, anything not NO_OBJECT or INTRANSITIVE - * will do here. We're preventing interpretation as an intransitive - * verb when the word is unknown. */ - command.obj = command.word[1].raw[0] != '\0' ? KEYS : NO_OBJECT; - if (command.obj == NO_OBJECT || - command.obj == INTRANSITIVE) { + if (command.word[1].raw[0] != '\0' && command.verb != SAY) { + return GO_WORD2; + } + if (command.verb == SAY) { + /* KEYS is not special, anything not NO_OBJECT or INTRANSITIVE + * will do here. We're preventing interpretation as an intransitive + * verb when the word is unknown. */ + command.obj = command.word[1].raw[0] != '\0' ? KEYS : NO_OBJECT; + } + if (command.obj == NO_OBJECT || command.obj == INTRANSITIVE) { /* Analyse an intransitive verb (ie, no object given yet). */ switch (command.verb) { case CARRY: @@ -1542,10 +1540,9 @@ phase_codes_t action(command_t command) return rub(command.verb, command.obj); case THROW: return throwit(command); - case QUIT: { + case QUIT: speak(actions[command.verb].message); return GO_CLEAROBJ; - } case FIND: return find(command.verb, command.obj); case INVENTORY: @@ -1557,42 +1554,36 @@ phase_codes_t action(command_t command) case BLAST: blast(); return GO_CLEAROBJ; - case SCORE: { + case SCORE: speak(actions[command.verb].message); return GO_CLEAROBJ; - } case FEE: case FIE: case FOE: case FOO: - case FUM: { + case FUM: speak(actions[command.verb].message); return GO_CLEAROBJ; - } - case BRIEF: { + case BRIEF: speak(actions[command.verb].message); return GO_CLEAROBJ; - } case READ: return read(command); case BREAK: return vbreak(command.verb, command.obj); case WAKE: return wake(command.verb, command.obj); - case SAVE: { + case SAVE: speak(actions[command.verb].message); return GO_CLEAROBJ; - } - case RESUME: { + case RESUME: speak(actions[command.verb].message); return GO_CLEAROBJ; - } case FLY: return fly(command.verb, command.obj); - case LISTEN: { + case LISTEN: speak(actions[command.verb].message); return GO_CLEAROBJ; - } // LCOV_EXCL_START // This case should never happen - here only as placeholder case PART: @@ -1613,3 +1604,5 @@ phase_codes_t action(command_t command) BUG(SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN); // LCOV_EXCL_LINE } } + +// end