X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=actions.c;h=2b432f371470eb0645532951774149d7ce2d3925;hb=0e540429b017c950702aee6644f17058f6f338fb;hp=5689ad2c41d8862c8cf4525ae1b35d84304971e2;hpb=e46cbdf194bf086ea4d4b091746cb81dd469a443;p=open-adventure.git diff --git a/actions.c b/actions.c index 5689ad2..2b432f3 100644 --- a/actions.c +++ b/actions.c @@ -6,12 +6,6 @@ static int fill(token_t, token_t); -static void state_change(long obj, long state) -{ - game.prop[obj] = state; - pspeak(obj, change, state, true); -} - static int attack(struct command_t *command) /* Attack. Assume target if unambiguous. "Throw" also links here. * Attackable objects fall into two categories: enemies (snake, @@ -184,46 +178,51 @@ static int attack(struct command_t *command) return GO_CLEAROBJ; } -static int bigwords(token_t foo) +static int bigwords(long id) /* 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). */ { - char word[TOKLEN + 1]; - packed_to_token(foo, word); - int k = (int) get_special_vocab_id(word); - if (game.foobar != 1 - k) { - if (game.foobar != 0 && game.loc == LOC_GIANTROOM) { - rspeak( START_OVER); - } else { - rspeak(NOTHING_HAPPENS); - } - return GO_CLEAROBJ; - } else { - game.foobar = k; - if (k != 4) { - rspeak(OK_MAN); - return GO_CLEAROBJ; - } - game.foobar = 0; - if (game.place[EGGS] == objects[EGGS].plac || - (TOTING(EGGS) && game.loc == objects[EGGS].plac)) { - rspeak(NOTHING_HAPPENS); - return GO_CLEAROBJ; - } 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; - k = EGGS_DONE; - if (HERE(EGGS)) - k = EGGS_VANISHED; - if (game.loc == objects[EGGS].plac) - k = EGGS_HERE; - move(EGGS, objects[EGGS].plac); - pspeak(EGGS, look, k, true); - return GO_CLEAROBJ; - } + if ((game.foobar == WORD_EMPTY && id == ACTION_WORD(FEE)) || + (game.foobar == ACTION_WORD(FEE) && id == ACTION_WORD(FIE)) || + (game.foobar == ACTION_WORD(FIE) && id == ACTION_WORD(FOE)) || + (game.foobar == ACTION_WORD(FOE) && id == ACTION_WORD(FOO)) || + (game.foobar == ACTION_WORD(FOE) && id == ACTION_WORD(FUM))) + { + game.foobar = id; + if ((id != ACTION_WORD(FOO)) && (id != ACTION_WORD(FUM))) { + rspeak(OK_MAN); + return GO_CLEAROBJ; + } + game.foobar = WORD_EMPTY; + if (game.place[EGGS] == objects[EGGS].plac || + (TOTING(EGGS) && game.loc == objects[EGGS].plac)) { + rspeak(NOTHING_HAPPENS); + return GO_CLEAROBJ; + } 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; + int k = EGGS_DONE; + if (HERE(EGGS)) + k = EGGS_VANISHED; + if (game.loc == objects[EGGS].plac) + k = EGGS_HERE; + move(EGGS, objects[EGGS].plac); + pspeak(EGGS, look, k, true); + return GO_CLEAROBJ; + } + } + else + { + if (game.loc == LOC_GIANTROOM) { + rspeak( START_OVER); + } else { + rspeak(NOTHING_HAPPENS); + } + game.foobar = WORD_EMPTY; + return GO_CLEAROBJ; } } @@ -260,7 +259,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); @@ -301,8 +300,9 @@ static int vcarry(token_t verb, token_t obj) return GO_CLEAROBJ; } - if (game.fixed[obj] != 0) { - if (obj == PLANT && game.prop[PLANT] <= 0) { + 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; } @@ -337,7 +337,7 @@ static int vcarry(token_t verb, token_t obj) rspeak(YOU_JOKING); return GO_CLEAROBJ; } - int spk; + if (obj == WATER || obj == OIL) { if (!HERE(BOTTLE) || @@ -355,39 +355,38 @@ static int vcarry(token_t verb, token_t obj) 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() != 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); @@ -407,16 +406,16 @@ static int chain(token_t verb) 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; switch (game.prop[BEAR]) { case BEAR_DEAD: - game.fixed[BEAR] = -1; + game.fixed[BEAR] = IS_FIXED; break; default: - game.fixed[BEAR] = 0; + game.fixed[BEAR] = IS_FREE; } rspeak(CHAIN_UNLOCKED); return GO_CLEAROBJ; @@ -435,7 +434,7 @@ static int chain(token_t verb) if (TOTING(CHAIN)) drop(CHAIN, game.loc); - game.fixed[CHAIN] = -1; + game.fixed[CHAIN] = IS_FIXED; rspeak(CHAIN_LOCKED); return GO_CLEAROBJ; @@ -446,12 +445,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)) { @@ -464,11 +462,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) @@ -476,9 +474,9 @@ static int discard(token_t verb, token_t obj, bool just_do_it) rspeak(spk); if (spk != RUG_WIGGLES) { /* FIXME: Arithmetic on state numbers */ - int k = 2 - game.prop[RUG]; + int k = (game.prop[RUG] == RUG_HOVER) ? RUG_FLOOR : RUG_HOVER; game.prop[RUG] = k; - if (k == 2) + if (k == RUG_HOVER) k = objects[SAPPH].plac; move(RUG + NOBJECTS, k); } @@ -503,18 +501,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); @@ -548,9 +545,8 @@ static int drink(token_t verb, token_t obj) return GO_CLEAROBJ; } if (LIQUID() == WATER && HERE(BOTTLE)) { - game.prop[BOTTLE] = EMPTY_BOTTLE; game.place[WATER] = LOC_NOWHERE; - rspeak(BOTTLE_EMPTY); + state_change(BOTTLE, EMPTY_BOTTLE); return GO_CLEAROBJ; } @@ -633,46 +629,59 @@ static int feed(token_t verb, token_t obj) /* Feed. If bird, no seed. Snake, dragon, troll: quip. If dwarf, make him * mad. Bear, special. */ { - int spk = actions[verb].message; - if (obj == BIRD) { + switch (obj) { + case BIRD: rspeak(BIRD_PINING); - return GO_CLEAROBJ; - } else if (obj == SNAKE || - obj == DRAGON || - obj == TROLL) { - spk = NOTHING_EDIBLE; - if (obj == DRAGON && game.prop[DRAGON] != DRAGON_BARS) - spk = RIDICULOUS_ATTEMPT; - if (obj == TROLL) - spk = TROLL_VICES; - if (obj == SNAKE && !game.closed && HERE(BIRD)) { + break; + case DRAGON: + if (game.prop[DRAGON] != DRAGON_BARS) + rspeak(RIDICULOUS_ATTEMPT); + else + rspeak(NOTHING_EDIBLE); + break; + case SNAKE: + if (!game.closed && HERE(BIRD)) { DESTROY(BIRD); - spk = BIRD_DEVOURED; - } - } else if (obj == DWARF) { + rspeak(BIRD_DEVOURED); + } else + rspeak(NOTHING_EDIBLE); + break; + case TROLL: + rspeak(TROLL_VICES); + break; + case DWARF: if (HERE(FOOD)) { game.dflag += 2; - spk = REALLY_MAD; + rspeak(REALLY_MAD); + } else + rspeak(actions[verb].message); + break; + case BEAR: + if (game.prop[BEAR] == BEAR_DEAD) { + rspeak(RIDICULOUS_ATTEMPT); + break; } - } else if (obj == BEAR) { - if (game.prop[BEAR] == UNTAMED_BEAR) - spk = NOTHING_EDIBLE; - if (game.prop[BEAR] == BEAR_DEAD) - spk = RIDICULOUS_ATTEMPT; - if (HERE(FOOD)) { - DESTROY(FOOD); - game.prop[BEAR] = SITTING_BEAR; - game.fixed[AXE] = 0; - game.prop[AXE] = 0; - spk = BEAR_TAMED; + if (game.prop[BEAR] == UNTAMED_BEAR) { + if (HERE(FOOD)) { + DESTROY(FOOD); + game.fixed[AXE] = IS_FREE; + game.prop[AXE] = AXE_HERE; + state_change(BEAR, SITTING_BEAR); + } else + rspeak(NOTHING_EDIBLE); + break; } - } else if (obj == OGRE) { + rspeak(actions[verb].message); + break; + case OGRE: if (HERE(FOOD)) - spk = OGRE_FULL; - } else { - spk = AM_GAME; + rspeak(OGRE_FULL); + else + rspeak(actions[verb].message); + break; + default: + rspeak(AM_GAME); } - rspeak(spk); return GO_CLEAROBJ; } @@ -691,8 +700,8 @@ int fill(token_t verb, token_t obj) } rspeak(SHATTER_VASE); game.prop[VASE] = VASE_BROKEN; - game.fixed[VASE] = -1; - return (discard(verb, obj, true)); + game.fixed[VASE] = IS_FIXED; + return (discard(verb, VASE, true)); } if (obj == URN) { @@ -743,13 +752,11 @@ int fill(token_t verb, token_t obj) return GO_CLEAROBJ; } - game.prop[BOTTLE] = (LIQLOC(game.loc) == OIL) ? OIL_BOTTLE : WATER_BOTTLE; + state_change(BOTTLE, (LIQLOC(game.loc) == OIL) + ? OIL_BOTTLE + : WATER_BOTTLE); if (TOTING(BOTTLE)) game.place[LIQUID()] = CARRIED; - if (LIQUID() == OIL) - rspeak(BOTTLED_OIL); - else - rspeak(BOTTLED_WATER); return GO_CLEAROBJ; } @@ -807,10 +814,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; } @@ -873,7 +880,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) { @@ -893,8 +900,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; } @@ -1111,11 +1117,14 @@ 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) || - wd == ACTION_WORD(GIANTWORDS) || + wd == ACTION_WORD(FEE) || + wd == ACTION_WORD(FIE) || + wd == ACTION_WORD(FOE) || + wd == ACTION_WORD(FOO) || + wd == ACTION_WORD(FUM) || wd == ACTION_WORD(PART)) { /* FIXME: scribbles on the interpreter's command block */ wordclear(&command->wd2); @@ -1138,8 +1147,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; @@ -1173,7 +1180,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; @@ -1225,7 +1232,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; @@ -1378,8 +1385,12 @@ int action(struct command_t *command) case SCORE: score(scoregame); return GO_CLEAROBJ; - case GIANTWORDS: - return bigwords(command->wd1); + case FEE: + case FIE: + case FOE: + case FOO: + case FUM: + return bigwords(command->id1); case BRIEF: return brief(); case READ: @@ -1466,7 +1477,11 @@ int action(struct command_t *command) rspeak(actions[command->verb].message); return GO_CLEAROBJ; } - case GIANTWORDS: { + case FEE: + case FIE: + case FOE: + case FOO: + case FUM: { rspeak(actions[command->verb].message); return GO_CLEAROBJ; }