Place1TBS mandatory braces.

This commit is contained in:
Eric S. Raymond 2024-01-28 07:11:21 -05:00
parent 258b7703f2
commit c11938aed5
4 changed files with 438 additions and 343 deletions

307
actions.c
View file

@ -14,12 +14,11 @@
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;
@ -137,9 +136,9 @@ 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;
@ -185,12 +184,11 @@ 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. */
@ -219,30 +217,31 @@ static phase_codes_t bigwords(vocab_t id)
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))
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 {
/* Magic-word sequence was started but is incorrect */
if (settings.oldstyle || game.seenbigwords)
if (settings.oldstyle || game.seenbigwords) {
rspeak(START_OVER);
else
} 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 (PROP_IS_NOTFOUND(ROD2) || !game.closed)
rspeak(REQUIRES_DYNAMITE);
else {
@ -260,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) {
@ -287,26 +285,25 @@ 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.locs[game.loc].atloc == NO_OBJECT ||
game.link[game.locs[game.loc].atloc] != 0 ||
atdwrf(game.loc) > 0)
atdwrf(game.loc) > 0) {
return GO_UNKNOWN;
}
obj = game.locs[game.loc].atloc;
}
@ -362,8 +359,9 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj)
}
if (game.objects[BOTTLE].prop == EMPTY_BOTTLE) {
return (fill(verb, BOTTLE));
} else
} else {
rspeak(BOTTLE_FULL);
}
return GO_CLEAROBJ;
}
obj = BOTTLE;
@ -399,8 +397,9 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj)
carry(obj, game.loc);
if (obj == BOTTLE && LIQUID() != NO_OBJECT)
if (obj == BOTTLE && LIQUID() != NO_OBJECT) {
game.objects[LIQUID()].place = CARRIED;
}
if (GSTONE(obj) && !PROP_IS_FOUND(obj)) {
PROP_SET_FOUND(obj);
@ -410,9 +409,8 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj)
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.objects[BEAR].prop == UNTAMED_BEAR) {
rspeak(BEAR_BLOCKS);
@ -462,11 +460,10 @@ static int chain(verb_t verb)
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;
}
@ -482,17 +479,19 @@ static phase_codes_t discard(verb_t verb, obj_t obj)
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)
if (obj == RUBY) {
rspeak(RUG_SETTLES);
else if (TOTING(RUG))
} else if (TOTING(RUG)) {
rspeak(RUG_WIGGLES);
else
} else {
rspeak(RUG_RISES);
}
if (!TOTING(RUG) || obj == RUBY) {
int k = (game.objects[RUG].prop == RUG_HOVER) ? RUG_FLOOR : RUG_HOVER;
game.objects[RUG].prop = k;
if (k == RUG_HOVER)
if (k == RUG_HOVER) {
k = objects[SAPPH].plac;
}
move(RUG + NOBJECTS, k);
}
}
@ -507,8 +506,9 @@ 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.objects[LIQUID()].place = LOC_NOWHERE;
}
@ -529,8 +529,9 @@ static phase_codes_t discard(verb_t verb, obj_t obj)
state_change(VASE, AT(PILLOW)
? VASE_WHOLE
: VASE_DROPPED);
if (game.objects[VASE].prop != VASE_WHOLE)
if (game.objects[VASE].prop != VASE_WHOLE) {
game.objects[VASE].fixed = IS_FIXED;
}
drop(obj, game.loc);
return GO_CLEAROBJ;
}
@ -548,13 +549,15 @@ static phase_codes_t discard(verb_t verb, obj_t obj)
}
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.objects[SNAKE].prop = SNAKE_CHASED;
} else
} else {
rspeak(OK_MAN);
}
game.objects[BIRD].prop = FOREST(game.loc) ? BIRD_FOREST_UNCAGED : BIRD_UNCAGED;
drop(obj, game.loc);
@ -566,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;
@ -596,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))
@ -626,17 +627,19 @@ 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.objects[LAMP].prop == LAMP_BRIGHT)
if (HERE(LAMP) && game.objects[LAMP].prop == LAMP_BRIGHT) {
obj = LAMP;
if (HERE(URN) && game.objects[URN].prop == URN_LIT)
}
if (HERE(URN) && game.objects[URN].prop == URN_LIT) {
obj = URN;
if (obj == INTRANSITIVE)
}
if (obj == INTRANSITIVE) {
return GO_UNKNOWN;
}
}
switch (obj) {
case URN:
@ -662,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.objects[DRAGON].prop != DRAGON_BARS)
if (game.objects[DRAGON].prop != DRAGON_BARS) {
rspeak(RIDICULOUS_ATTEMPT);
else
} 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);
@ -690,8 +694,9 @@ 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.objects[BEAR].prop == BEAR_DEAD) {
@ -704,17 +709,19 @@ static phase_codes_t feed(verb_t verb, obj_t obj)
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))
if (HERE(FOOD)) {
rspeak(OGRE_FULL);
else
} else {
speak(actions[verb].message);
}
break;
default:
rspeak(AM_GAME);
@ -722,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);
@ -793,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))
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;
@ -822,9 +828,8 @@ 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);
@ -865,9 +870,8 @@ 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))
@ -885,9 +889,8 @@ 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.objects[LAMP].prop == LAMP_DARK && game.limit >= 0) {
@ -914,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);
@ -923,53 +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 || PROP_IS_STASHED_OR_UNSEEN(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))
if (HERE(CLAM)) {
obj = CLAM;
if (HERE(OYSTER))
}
if (HERE(OYSTER)) {
obj = OYSTER;
if (AT(DOOR))
}
if (AT(DOOR)) {
obj = DOOR;
if (AT(GRATE))
}
if (AT(GRATE)) {
obj = GRATE;
if (HERE(CHAIN))
}
if (HERE(CHAIN)) {
obj = CHAIN;
}
if (obj == INTRANSITIVE) {
rspeak(NOTHING_LOCKED);
return GO_CLEAROBJ;
@ -983,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)
if (verb == LOCK) {
rspeak(HUH_MAN);
else if (TOTING(CLAM))
} else if (TOTING(CLAM)) {
rspeak(DROP_CLAM);
else if (!TOTING(TRIDENT))
} else if (!TOTING(TRIDENT)) {
rspeak(CLAM_OPENER);
else {
} else {
DESTROY(CLAM);
drop(OYSTER, game.loc);
drop(PEARL, LOC_CULDESAC);
@ -1016,14 +1031,15 @@ static phase_codes_t lock(verb_t verb, obj_t obj)
}
break;
case OYSTER:
if (verb == LOCK)
if (verb == LOCK) {
rspeak(HUH_MAN);
else if (TOTING(OYSTER))
} else if (TOTING(OYSTER)) {
rspeak(DROP_OYSTER);
else if (!TOTING(TRIDENT))
} else if (!TOTING(TRIDENT)) {
rspeak(OYSTER_OPENER);
else
} else {
rspeak(OYSTER_OPENS);
}
break;
case DOOR:
rspeak((game.objects[DOOR].prop == DOOR_UNRUSTED) ? OK_MAN : RUSTY_DOOR);
@ -1041,14 +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)
if (obj == BOTTLE || obj == INTRANSITIVE) {
obj = LIQUID();
if (obj == NO_OBJECT)
}
if (obj == NO_OBJECT) {
return GO_UNKNOWN;
}
if (!TOTING(obj)) {
speak(actions[verb].message);
return GO_CLEAROBJ;
@ -1058,8 +1075,9 @@ static phase_codes_t pour(verb_t verb, obj_t obj)
rspeak(CANT_POUR);
return GO_CLEAROBJ;
}
if (HERE(URN) && game.objects[URN].prop == URN_EMPTY)
if (HERE(URN) && game.objects[URN].prop == URN_EMPTY) {
return fill(verb, URN);
}
game.objects[BOTTLE].prop = EMPTY_BOTTLE;
game.objects[obj].place = LOC_NOWHERE;
if (!(AT(PLANT) || AT(DOOR))) {
@ -1084,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]))
if (yes_or_no(arbitrary_messages[REALLY_QUIT], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN])) {
terminate(quitgame);
}
return GO_CLEAROBJ;
}
@ -1098,12 +1116,14 @@ 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 && !PROP_IS_STASHED(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)) {
sspeak(NO_SEE, command.word[0].raw);
@ -1117,14 +1137,14 @@ static phase_codes_t read(command_t command)
}
} else if (objects[command.obj].texts[0] == NULL || PROP_IS_NOTFOUND(command.obj)) {
speak(actions[command.verb].message);
} else
} 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;
@ -1142,9 +1162,8 @@ 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.objects[URN].prop == URN_LIT) {
DESTROY(URN);
drop(AMBER, game.loc);
@ -1160,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 ||
@ -1192,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;
@ -1218,16 +1236,18 @@ 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.objects[DRAGON].prop == DRAGON_BARS)
return throw_support(DRAGON_SCALES);
if (AT(TROLL))
if (AT(TROLL)) {
return throw_support(TROLL_RETURNS);
if (AT(OGRE))
}
if (AT(OGRE)) {
return throw_support(OGRE_DODGE);
}
if (HERE(BEAR) && game.objects[BEAR].prop == UNTAMED_BEAR) {
/* This'll teach him to throw the axe at the bear! */
drop(AXE, game.loc);
@ -1253,9 +1273,8 @@ 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) {
speak(actions[verb].message);
return GO_CLEAROBJ;
@ -1265,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);
@ -1275,17 +1293,15 @@ 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)))) {
speak(((!TOTING(obj)) && (obj != ROD ||
!TOTING(ROD2))) ?
@ -1325,11 +1341,10 @@ static phase_codes_t wave(verb_t verb, obj_t obj)
}
}
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 */
@ -1346,14 +1361,14 @@ 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))
if (HERE(command.obj)) {
/* FALL THROUGH */;
else if (command.obj == DWARF && atdwrf(game.loc) > 0)
} 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)))
} 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) {
} 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.objects[PLANT2].prop != PLANT_THIRSTY) {
@ -1367,26 +1382,29 @@ 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)
if (command.word[1].raw[0] != '\0' && command.verb != SAY) {
return GO_WORD2;
if (command.verb == SAY)
}
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) {
@ -1522,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:
@ -1537,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:
@ -1593,3 +1604,5 @@ phase_codes_t action(command_t command)
BUG(SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN); // LCOV_EXCL_LINE
}
}
// end

9
init.c
View file

@ -56,10 +56,11 @@ int initialise(void)
for (int i = 1; i <= NLOCATIONS; i++) {
if (!(locations[i].description.big == 0 || tkey[i] == 0)) {
int k = tkey[i];
if (travel[k].motion == HERE)
if (travel[k].motion == HERE) {
conditions[i] |= (1 << COND_FORCED);
}
}
}
/* Set up the game.locs atloc and game.link arrays.
* We'll use the DROP subroutine, which prefaces new objects on the
@ -77,9 +78,10 @@ int initialise(void)
for (int i = 1; i <= NOBJECTS; i++) {
int k = NOBJECTS + 1 - i;
game.objects[k].fixed = objects[k].fixd;
if (objects[k].plac != 0 && objects[k].fixd <= 0)
if (objects[k].plac != 0 && objects[k].fixd <= 0) {
drop(k, objects[k].plac);
}
}
/* Treasure props are initially STATE_NOTFOUND, and are set to
* STATE_FOUND the first time they are described. game.tally
@ -88,10 +90,11 @@ int initialise(void)
for (int treasure = 1; treasure <= NOBJECTS; treasure++) {
if (objects[treasure].is_treasure) {
++game.tally;
if (objects[treasure].inventory != 0)
if (objects[treasure].inventory != 0) {
PROP_SET_NOT_FOUND(treasure);
}
}
}
game.conds = setbit(COND_HBASE);
return seedval;

265
main.c
View file

@ -38,8 +38,9 @@ static void sig_handler(int signo)
}
#if defined ADVENT_AUTOSAVE
if (signo == SIGHUP || signo == SIGTERM)
if (signo == SIGHUP || signo == SIGTERM) {
autosave();
}
#endif
exit(EXIT_FAILURE);
}
@ -71,13 +72,15 @@ char *myreadline(const char *prompt)
char *next = settings.argv[settings.optind++];
if (settings.scriptfp != NULL && feof(settings.scriptfp))
if (settings.scriptfp != NULL && feof(settings.scriptfp)) {
fclose(settings.scriptfp);
if (strcmp(next, "-") == 0)
}
if (strcmp(next, "-") == 0) {
settings.scriptfp = stdin; // LCOV_EXCL_LINE
else
} else {
settings.scriptfp = fopen(next, "r");
}
}
if (isatty(fileno(settings.scriptfp))) {
free(buf); // LCOV_EXCL_LINE
@ -102,10 +105,12 @@ static void checkhints(void)
{
if (conditions[game.loc] >= game.conds) {
for (int hint = 0; hint < NHINTS; hint++) {
if (game.hints[hint].used)
if (game.hints[hint].used) {
continue;
if (!CNDBIT(game.loc, hint + 1 + COND_HBASE))
}
if (!CNDBIT(game.loc, hint + 1 + COND_HBASE)) {
game.hints[hint].lc = -1;
}
++game.hints[hint].lc;
/* Come here if he's been int enough at required loc(s) for some
* unused hint. */
@ -115,17 +120,20 @@ static void checkhints(void)
switch (hint) {
case 0:
/* cave */
if (game.objects[GRATE].prop == GRATE_CLOSED && !HERE(KEYS))
if (game.objects[GRATE].prop == GRATE_CLOSED && !HERE(KEYS)) {
break;
}
game.hints[hint].lc = 0;
return;
case 1: /* bird */
if (game.objects[BIRD].place == game.loc && TOTING(ROD) && game.oldobj == BIRD)
if (game.objects[BIRD].place == game.loc && TOTING(ROD) && game.oldobj == BIRD) {
break;
}
return;
case 2: /* snake */
if (HERE(SNAKE) && !HERE(BIRD))
if (HERE(SNAKE) && !HERE(BIRD)) {
break;
}
game.hints[hint].lc = 0;
return;
case 3: /* maze */
@ -137,15 +145,17 @@ static void checkhints(void)
game.hints[hint].lc = 0;
return;
case 4: /* dark */
if (!PROP_IS_NOTFOUND(EMERALD) && PROP_IS_NOTFOUND(PYRAMID))
if (!PROP_IS_NOTFOUND(EMERALD) && PROP_IS_NOTFOUND(PYRAMID)) {
break;
}
game.hints[hint].lc = 0;
return;
case 5: /* witt */
break;
case 6: /* urn */
if (game.dflag == 0)
if (game.dflag == 0) {
break;
}
game.hints[hint].lc = 0;
return;
case 7: /* woods */
@ -160,12 +170,14 @@ static void checkhints(void)
game.hints[hint].lc = 0;
return;
}
if (HERE(OGRE) && i == 0)
if (HERE(OGRE) && i == 0) {
break;
}
return;
case 9: /* jade */
if (game.tally == 1 && PROP_IS_STASHED_OR_UNSEEN(JADE))
if (game.tally == 1 && PROP_IS_STASHED_OR_UNSEEN(JADE)) {
break;
}
game.hints[hint].lc = 0;
return;
default: // LCOV_EXCL_LINE
@ -175,21 +187,24 @@ static void checkhints(void)
/* Fall through to hint display */
game.hints[hint].lc = 0;
if (!yes_or_no(hints[hint].question, arbitrary_messages[NO_MESSAGE], arbitrary_messages[OK_MAN]))
if (!yes_or_no(hints[hint].question, arbitrary_messages[NO_MESSAGE], arbitrary_messages[OK_MAN])) {
return;
}
rspeak(HINT_COST, hints[hint].penalty, hints[hint].penalty);
game.hints[hint].used = yes_or_no(arbitrary_messages[WANT_HINT], hints[hint].hint, arbitrary_messages[OK_MAN]);
if (game.hints[hint].used && game.limit > WARNTIME)
if (game.hints[hint].used && game.limit > WARNTIME) {
game.limit += WARNTIME * hints[hint].penalty;
}
}
}
}
}
static bool spotted_by_pirate(int i)
{
if (i != PIRATE)
if (i != PIRATE) {
return false;
}
/* The pirate's spotted him. Pirate leaves him alone once we've
* found chest. K counts if a treasure is here. If not, and
@ -197,21 +212,24 @@ static bool spotted_by_pirate(int i)
* that game.objexts,place[CHEST] = LOC_NOWHERE might mean that he's thrown
* it to the troll, but in that case he's seen the chest
* PROP_IS_FOUND(CHEST) == true. */
if (game.loc == game.chloc || !PROP_IS_NOTFOUND(CHEST))
if (game.loc == game.chloc || !PROP_IS_NOTFOUND(CHEST)) {
return true;
}
int snarfed = 0;
bool movechest = false, robplayer = false;
for (int treasure = 1; treasure <= NOBJECTS; treasure++) {
if (!objects[treasure].is_treasure)
if (!objects[treasure].is_treasure) {
continue;
}
/* Pirate won't take pyramid from plover room or dark
* room (too easy!). */
if (treasure == PYRAMID && (game.loc == objects[PYRAMID].plac ||
game.loc == objects[EMERALD].plac)) {
continue;
}
if (TOTING(treasure) || HERE(treasure))
if (TOTING(treasure) || HERE(treasure)) {
++snarfed;
}
if (TOTING(treasure)) {
movechest = true;
robplayer = true;
@ -233,30 +251,33 @@ static bool spotted_by_pirate(int i)
} else {
/* You might get a hint of the pirate's presence even if the
* chest doesn't move... */
if (game.dwarves[PIRATE].oldloc != game.dwarves[PIRATE].loc && PCT(20))
if (game.dwarves[PIRATE].oldloc != game.dwarves[PIRATE].loc && PCT(20)) {
rspeak(PIRATE_RUSTLES);
}
}
if (robplayer) {
rspeak(PIRATE_POUNCES);
for (int treasure = 1; treasure <= NOBJECTS; treasure++) {
if (!objects[treasure].is_treasure)
if (!objects[treasure].is_treasure) {
continue;
}
if (!(treasure == PYRAMID && (game.loc == objects[PYRAMID].plac ||
game.loc == objects[EMERALD].plac))) {
if (AT(treasure) && game.objects[treasure].fixed == IS_FREE)
if (AT(treasure) && game.objects[treasure].fixed == IS_FREE) {
carry(treasure, game.loc);
if (TOTING(treasure))
}
if (TOTING(treasure)) {
drop(treasure, game.chloc);
}
}
}
}
return true;
}
static bool dwarfmove(void)
static bool dwarfmove(void) {
/* Dwarves move. Return true if player survives, false if he dies. */
{
int kk, stick, attack;
loc_t tk[21];
@ -272,8 +293,9 @@ static bool dwarfmove(void)
* steal return toll, and dwarves can't meet the bear. Also
* means dwarves won't follow him into dead end in maze, but
* c'est la vie. They'll wait for him outside the dead end. */
if (game.loc == LOC_NOWHERE || FORCED(game.loc) || CNDBIT(game.newloc, COND_NOARRR))
if (game.loc == LOC_NOWHERE || FORCED(game.loc) || CNDBIT(game.newloc, COND_NOARRR)) {
return true;
}
/* Dwarf activity level ratchets up */
if (game.dflag == 0) {
@ -287,20 +309,23 @@ static bool dwarfmove(void)
* replace him with the alternate. */
if (game.dflag == 1) {
if (!INDEEP(game.loc) ||
(PCT(95) && (!CNDBIT(game.loc, COND_NOBACK) || PCT(85))))
(PCT(95) && (!CNDBIT(game.loc, COND_NOBACK) || PCT(85)))) {
return true;
}
game.dflag = 2;
for (int i = 1; i <= 2; i++) {
int j = 1 + randrange(NDWARVES - 1);
if (PCT(50))
if (PCT(50)) {
game.dwarves[j].loc = 0;
}
}
/* Alternate initial loc for dwarf, in case one of them
* starts out on top of the adventurer. */
for (int i = 1; i <= NDWARVES - 1; i++) {
if (game.dwarves[i].loc == game.loc)
game.dwarves[i].loc = DALTLC; //
if (game.dwarves[i].loc == game.loc) {
game.dwarves[i].loc = DALTLC;
}
game.dwarves[i].oldloc = game.dwarves[i].loc;
}
rspeak(DWARF_RAN);
@ -318,8 +343,9 @@ static bool dwarfmove(void)
attack = 0;
stick = 0;
for (int i = 1; i <= NDWARVES; i++) {
if (game.dwarves[i].loc == 0)
if (game.dwarves[i].loc == 0) {
continue;
}
/* Fill tk array with all the places this dwarf might go. */
unsigned int j = 1;
kk = tkey[game.dwarves[i].loc];
@ -351,38 +377,46 @@ static bool dwarfmove(void)
} while
(!travel[kk++].stop);
tk[j] = game.dwarves[i].oldloc;
if (j >= 2)
if (j >= 2) {
--j;
}
j = 1 + randrange(j);
game.dwarves[i].oldloc = game.dwarves[i].loc;
game.dwarves[i].loc = tk[j];
game.dwarves[i].seen = (game.dwarves[i].seen && INDEEP(game.loc)) ||
(game.dwarves[i].loc == game.loc ||
game.dwarves[i].oldloc == game.loc);
if (!game.dwarves[i].seen)
if (!game.dwarves[i].seen) {
continue;
}
game.dwarves[i].loc = game.loc;
if (spotted_by_pirate(i))
if (spotted_by_pirate(i)) {
continue;
}
/* This threatening little dwarf is in the room with him! */
++game.dtotal;
if (game.dwarves[i].oldloc == game.dwarves[i].loc) {
++attack;
if (game.knfloc >= LOC_NOWHERE)
if (game.knfloc >= LOC_NOWHERE) {
game.knfloc = game.loc;
if (randrange(1000) < 95 * (game.dflag - 2))
}
if (randrange(1000) < 95 * (game.dflag - 2)) {
++stick;
}
}
}
/* Now we know what's happening. Let's tell the poor sucker about it. */
if (game.dtotal == 0)
if (game.dtotal == 0) {
return true;
}
rspeak(game.dtotal == 1 ? DWARF_SINGLE : DWARF_PACK, game.dtotal);
if (attack == 0)
if (attack == 0) {
return true;
if (game.dflag == 2)
}
if (game.dflag == 2) {
game.dflag = 3;
}
if (attack > 1) {
rspeak(THROWN_KNIVES, attack);
rspeak(stick > 1 ? MULTIPLE_HITS : (stick == 1 ? ONE_HIT : NONE_HIT), stick);
@ -390,8 +424,9 @@ static bool dwarfmove(void)
rspeak(KNIFE_THROWN);
rspeak(stick ? GETS_YOU : MISSES_YOU);
}
if (stick == 0)
if (stick == 0) {
return true;
}
game.oldlc2 = game.loc;
return false;
}
@ -415,9 +450,8 @@ static bool dwarfmove(void)
* building (and heaven help him if he tries to xyzzy back into the
* cave without the lamp!). game.oldloc is zapped so he can't just
* "retreat". */
static void croak(void)
static void croak(void) {
/* Okay, he's dead. Let's get on with it. */
{
const char* query = obituaries[game.numdie].query;
const char* yes_response = obituaries[game.numdie].yes_response;
@ -451,9 +485,8 @@ static void croak(void)
}
}
static void describe_location(void)
static void describe_location(void) {
/* Describe the location to the user */
{
const char* msg = locations[game.loc].description.small;
if (MOD(game.locs[game.loc].abbrev, game.abbnum) == 0 || msg == NO_MESSAGE)
@ -463,8 +496,9 @@ static void describe_location(void)
msg = arbitrary_messages[PITCH_DARK];
}
if (TOTING(BEAR))
if (TOTING(BEAR)) {
rspeak(TAME_BEAR);
}
speak(msg);
@ -473,9 +507,8 @@ static void describe_location(void)
}
static bool traveleq(int a, int b)
static bool traveleq(int a, int b) {
/* Are two travel entries equal for purposes of skip after failed condition? */
{
return (travel[a].condtype == travel[b].condtype)
&& (travel[a].condarg1 == travel[b].condarg1)
&& (travel[a].condarg2 == travel[b].condarg2)
@ -494,11 +527,12 @@ static void playermove(int motion)
{
int scratchloc, travel_entry = tkey[game.loc];
game.newloc = game.loc;
if (travel_entry == 0)
if (travel_entry == 0) {
BUG(LOCATION_HAS_NO_TRAVEL_ENTRIES); // LCOV_EXCL_LINE
if (motion == NUL)
}
if (motion == NUL) {
return;
else if (motion == BACK) {
} else if (motion == BACK) {
/* Handle "go back". Look for verb which goes from game.loc to
* game.oldloc, or to game.oldlc2 If game.oldloc has forced-motion.
* te_tmp saves entry -> forced loc -> previous loc. */
@ -545,8 +579,9 @@ static void playermove(int motion)
/* Look. Can't give more detail. Pretend it wasn't dark
* (though it may now be dark) so he won't fall into a
* pit while staring into the gloom. */
if (game.detail < 3)
if (game.detail < 3) {
rspeak(NO_MORE_DETAIL);
}
++game.detail;
game.wzdark = false;
game.locs[game.loc].abbrev = 0;
@ -626,8 +661,9 @@ static void playermove(int motion)
else if (TOTING(condarg1) || (condtype == cond_with && AT(condarg1)))
break;
/* else fall through to check [not OBJ STATE] */
} else if (game.objects[condarg1].prop != condarg2)
} else if (game.objects[condarg1].prop != condarg2) {
break;
}
/* We arrive here on conditional failure.
* Skip to next non-matching destination */
@ -644,8 +680,9 @@ static void playermove(int motion)
/* Found an eligible rule, now execute it */
enum desttype_t desttype = travel[travel_entry].desttype;
game.newloc = travel[travel_entry].destval;
if (desttype == dest_goto)
if (desttype == dest_goto) {
return;
}
if (desttype == dest_speak) {
/* Execute a speak rule */
@ -710,8 +747,9 @@ static void playermove(int motion)
game.newloc = objects[TROLL].plac + objects[TROLL].fixd - game.loc;
if (game.objects[TROLL].prop == TROLL_UNPAID)
game.objects[TROLL].prop = TROLL_PAIDONCE;
if (!TOTING(BEAR))
if (!TOTING(BEAR)) {
return;
}
state_change(CHASM, BRIDGE_WRECKED);
game.objects[TROLL].prop = TROLL_GONE;
drop(BEAR, game.newloc);
@ -731,11 +769,11 @@ static void playermove(int motion)
(false);
}
static void lampcheck(void)
static void lampcheck(void) {
/* Check game limit and lamp timers */
{
if (game.objects[LAMP].prop == LAMP_BRIGHT)
if (game.objects[LAMP].prop == LAMP_BRIGHT) {
--game.limit;
}
/* Another way we can force an end to things is by having the
* lamp give out. When it gets close, we come here to warn him.
@ -752,30 +790,32 @@ static void lampcheck(void)
* No tests ever passed the guard, and with the guard removed
* the game hangs when the lamp limit is reached.
*/
if (TOTING(BATTERY))
if (TOTING(BATTERY)) {
drop(BATTERY, game.loc);
}
#endif
game.limit += BATTERYLIFE;
game.lmwarn = false;
} else if (!game.lmwarn && HERE(LAMP)) {
game.lmwarn = true;
if (game.objects[BATTERY].prop == DEAD_BATTERIES)
if (game.objects[BATTERY].prop == DEAD_BATTERIES) {
rspeak(MISSING_BATTERIES);
else if (game.objects[BATTERY].place == LOC_NOWHERE)
} else if (game.objects[BATTERY].place == LOC_NOWHERE) {
rspeak(LAMP_DIM);
else
} else {
rspeak(GET_BATTERIES);
}
}
}
if (game.limit == 0) {
game.limit = -1;
game.objects[LAMP].prop = LAMP_DARK;
if (HERE(LAMP))
if (HERE(LAMP)) {
rspeak(LAMP_OUT);
}
}
}
static bool closecheck(void)
/* Handle the closing of the cave. The cave closes "clock1" turns
* after the last treasure has been located (including the pirate's
* chest, which may of course never show up). Note that the
@ -794,7 +834,7 @@ static bool closecheck(void)
* separating him from all the treasures. Most of these problems
* arise from the use of negative prop numbers to suppress the object
* descriptions until he's actually moved the objects. */
{
static bool closecheck(void) {
/* If a turn threshold has been met, apply penalties and tell
* the player about it. */
for (int i = 0; i < NTHRESHOLDS; ++i) {
@ -805,8 +845,9 @@ static bool closecheck(void)
}
/* Don't tick game.clock1 unless well into cave (and not at Y2). */
if (game.tally == 0 && INDEEP(game.loc) && game.loc != LOC_Y2)
if (game.tally == 0 && INDEEP(game.loc) && game.loc != LOC_Y2) {
--game.clock1;
}
/* When the first warning comes, we lock the grate, destroy
* the bridge, kill all the dwarves (and the pirate), remove
@ -833,8 +874,9 @@ static bool closecheck(void)
move(TROLL2, objects[TROLL].plac);
move(TROLL2 + NOBJECTS, objects[TROLL].fixd);
juggle(CHASM);
if (game.objects[BEAR].prop != BEAR_DEAD)
if (game.objects[BEAR].prop != BEAR_DEAD) {
DESTROY(BEAR);
}
game.objects[CHAIN].prop = CHAIN_HEAP;
game.objects[CHAIN].fixed = IS_FREE;
game.objects[AXE].prop = AXE_HERE;
@ -885,9 +927,10 @@ static bool closecheck(void)
game.objects[MIRROR].fixed = LOC_SW;
for (int i = 1; i <= NOBJECTS; i++) {
if (TOTING(i))
if (TOTING(i)) {
DESTROY(i);
}
}
rspeak(CAVE_CLOSED);
game.closed = true;
@ -898,7 +941,7 @@ static bool closecheck(void)
return false;
}
static void listobjects(void)
static void listobjects(void) {
/* Print out descriptions of objects at this location. If
* not closing and property value is negative, tally off
* another treasure. Rug is special case; once seen, its
@ -906,29 +949,34 @@ static void listobjects(void)
* Similarly for chain; game.prop is initially CHAINING_BEAR (locked to
* bear). These hacks are because game.prop=0 is needed to
* get full score. */
{
if (!DARK(game.loc)) {
++game.locs[game.loc].abbrev;
for (int i = game.locs[game.loc].atloc; i != 0; i = game.link[i]) {
obj_t obj = i;
if (obj > NOBJECTS)
if (obj > NOBJECTS) {
obj = obj - NOBJECTS;
if (obj == STEPS && TOTING(NUGGET))
}
if (obj == STEPS && TOTING(NUGGET)) {
continue;
}
/* (ESR) Warning: it looks like you could get away with
* running this code only on objects with the treasure
* property set. Nope. There is mystery here.
*/
if (PROP_IS_STASHED_OR_UNSEEN(obj)) {
if (game.closed)
if (game.closed) {
continue;
}
PROP_SET_FOUND(obj);
if (obj == RUG)
if (obj == RUG) {
game.objects[RUG].prop = RUG_DRAGON;
if (obj == CHAIN)
}
if (obj == CHAIN) {
game.objects[CHAIN].prop = CHAINING_BEAR;
if (obj == EGGS)
}
if (obj == EGGS) {
game.seenbigwords = true;
}
--game.tally;
/* Note: There used to be a test here to see whether the
* player had blown it so badly that he could never ever see
@ -946,16 +994,16 @@ static void listobjects(void)
* (so goes the rationalisation). */
}
int kk = game.objects[obj].prop;
if (obj == STEPS)
if (obj == STEPS) {
kk = (game.loc == game.objects[STEPS].fixed)
? STEPS_UP
: STEPS_DOWN;
}
pspeak(obj, look, true, kk);
}
}
}
static bool preprocess_command(command_t *command)
/* Pre-processes a command input to see if we need to tease out a few specific cases:
* - "enter water" or "enter stream":
* weird specific case that gets the user wet, and then kicks us back to get another command
@ -972,13 +1020,14 @@ static bool preprocess_command(command_t *command)
*
* Returns true if pre-processing is complete, and we're ready to move to the primary command
* processing, false otherwise. */
{
static bool preprocess_command(command_t *command) {
if (command->word[0].type == MOTION && command->word[0].id == ENTER
&& (command->word[1].id == STREAM || command->word[1].id == WATER)) {
if (LIQLOC(game.loc) == WATER)
if (LIQLOC(game.loc) == WATER) {
rspeak(FEET_WET);
else
} else {
rspeak(WHERE_QUERY);
}
} else {
if (command->word[0].type == OBJECT) {
/* From OV to VO form */
@ -1028,15 +1077,15 @@ static bool preprocess_command(command_t *command)
return false;
}
static bool do_move(void)
static bool do_move(void) {
/* Actually execute the move to the new location and dwarf movement */
{
/* Can't leave cave once it's closing (except by main office). */
if (OUTSID(game.newloc) && game.newloc != 0 && game.closng) {
rspeak(EXIT_CLOSED);
game.newloc = game.loc;
if (!game.panic)
if (!game.panic) {
game.clock2 = PANICTIME;
}
game.panic = true;
}
@ -1055,11 +1104,13 @@ static bool do_move(void)
}
game.loc = game.newloc;
if (!dwarfmove())
if (!dwarfmove()) {
croak();
}
if (game.loc == LOC_NOWHERE)
if (game.loc == LOC_NOWHERE) {
croak();
}
/* The easiest way to get killed is to fall into a pit in
* pitch darkness. */
@ -1073,9 +1124,8 @@ static bool do_move(void)
return true;
}
static bool do_command(void)
static bool do_command(void) {
/* Get and execute a command */
{
static command_t command;
clear_command(&command);
@ -1101,8 +1151,9 @@ static bool do_command(void)
* won't be described until they've been picked up
* and put down separate from their respective
* piles. */
if ((PROP_IS_NOTFOUND(OYSTER) || PROP_IS_STASHED(OYSTER)) && TOTING(OYSTER))
if ((PROP_IS_NOTFOUND(OYSTER) || PROP_IS_STASHED(OYSTER)) && TOTING(OYSTER)) {
pspeak(OYSTER, look, true, 1);
}
for (size_t i = 1; i <= NOBJECTS; i++) {
if (TOTING(i) && (PROP_IS_NOTFOUND(i) || PROP_IS_STASHED(i)))
game.objects[i].prop = PROP_STASHED(i);
@ -1112,8 +1163,9 @@ static bool do_command(void)
/* Check to see if the room is dark. If the knife is here,
* and it's dark, the knife permanently disappears */
game.wzdark = DARK(game.loc);
if (game.knfloc != LOC_NOWHERE && game.knfloc != game.loc)
if (game.knfloc != LOC_NOWHERE && game.knfloc != game.loc) {
game.knfloc = LOC_NOWHERE;
}
/* Check some for hints, get input from user, increment
* turn, and pre-process commands. Keep going until
@ -1122,8 +1174,9 @@ static bool do_command(void)
checkhints();
/* Get command input from user */
if (!get_command_input(&command))
if (!get_command_input(&command)) {
return false;
}
/* Every input, check "foobar" flag. If zero, nothing's going
* on. If pos, make neg. If neg, he skipped a word, so make it
@ -1136,8 +1189,9 @@ static bool do_command(void)
}
/* check if game is closed, and exit if it is */
if (closecheck() )
if (closecheck()) {
return true;
}
/* loop until all words in command are processed */
while (command.state == PREPROCESSED ) {
@ -1152,13 +1206,15 @@ static bool do_command(void)
/* Give user hints of shortcuts */
if (strncasecmp(command.word[0].raw, "west", sizeof("west")) == 0) {
if (++game.iwest == 10)
if (++game.iwest == 10) {
rspeak(W_IS_WEST);
}
}
if (strncasecmp(command.word[0].raw, "go", sizeof("go")) == 0 && command.word[1].id != WORD_EMPTY) {
if (++game.igo == 10)
if (++game.igo == 10) {
rspeak(GO_UNNEEDED);
}
}
switch (command.word[0].type) {
case MOTION:
@ -1170,10 +1226,11 @@ static bool do_command(void)
command.obj = command.word[0].id;
break;
case ACTION:
if (command.word[1].type == NUMERIC)
if (command.word[1].type == NUMERIC) {
command.part = transitive;
else
} else {
command.part = intransitive;
}
command.verb = command.word[0].id;
break;
case NUMERIC:
@ -1275,10 +1332,11 @@ int main(int argc, char *argv[])
break; // LCOV_EXCL_LINE
case 'l':
settings.logfp = fopen(optarg, "w");
if (settings.logfp == NULL)
if (settings.logfp == NULL) {
fprintf(stderr,
"advent: can't open logfile %s for write\n",
optarg);
}
signal(SIGINT, sig_handler);
break;
case 'o':
@ -1295,10 +1353,11 @@ int main(int argc, char *argv[])
#elif !defined ADVENT_NOSAVE
case 'r':
rfp = fopen(optarg, "r");
if (rfp == NULL)
if (rfp == NULL) {
fprintf(stderr,
"advent: can't open save file %s for read\n",
optarg);
}
break;
#endif
default:
@ -1331,8 +1390,9 @@ int main(int argc, char *argv[])
#if !defined ADVENT_NOSAVE
if (!rfp) {
game.novice = yes_or_no(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
if (game.novice)
if (game.novice) {
game.limit = NOVICELIMIT;
}
} else {
restore(rfp);
#if defined ADVENT_AUTOSAVE
@ -1354,19 +1414,22 @@ int main(int argc, char *argv[])
game.limit = NOVICELIMIT;
#endif
if (settings.logfp)
if (settings.logfp) {
fprintf(settings.logfp, "seed %d\n", seedval);
}
/* interpret commands until EOF or interrupt */
for (;;) {
// if we're supposed to move, move
if (!do_move())
if (!do_move()) {
continue;
}
// get command
if (!do_command())
if (!do_command()) {
break;
}
}
/* show score and exit */
terminate(quitgame);
}

60
score.c
View file

@ -10,10 +10,9 @@
static int mxscor; /* ugh..the price for having score() not exit. */
int score(enum termination mode)
int score(enum termination mode) {
/* mode is 'scoregame' if scoring, 'quitgame' if quitting, 'endgame' if died
* or won */
{
int score = 0;
/* The present scoring algorithm is as follows:
@ -39,18 +38,23 @@ int score(enum termination mode)
* Give the poor guy 2 points just for finding each treasure. */
mxscor = 0;
for (int i = 1; i <= NOBJECTS; i++) {
if (!objects[i].is_treasure)
if (!objects[i].is_treasure) {
continue;
}
if (objects[i].inventory != 0) {
int k = 12;
if (i == CHEST)
if (i == CHEST) {
k = 14;
if (i > CHEST)
}
if (i > CHEST) {
k = 16;
if (!PROP_IS_STASHED(i) && !PROP_IS_NOTFOUND(i))
}
if (!PROP_IS_STASHED(i) && !PROP_IS_NOTFOUND(i)) {
score += 2;
if (game.objects[i].place == LOC_BUILDING && PROP_IS_FOUND(i))
}
if (game.objects[i].place == LOC_BUILDING && PROP_IS_FOUND(i)) {
score += k - 2;
}
mxscor += k;
}
}
@ -63,30 +67,38 @@ int score(enum termination mode)
* mundane exits or 133, 134, 135 if he blew it (so to speak). */
score += (NDEATHS - game.numdie) * 10;
mxscor += NDEATHS * 10;
if (mode == endgame)
if (mode == endgame) {
score += 4;
}
mxscor += 4;
if (game.dflag != 0)
if (game.dflag != 0) {
score += 25;
}
mxscor += 25;
if (game.closng)
if (game.closng) {
score += 25;
}
mxscor += 25;
if (game.closed) {
if (game.bonus == none)
if (game.bonus == none) {
score += 10;
if (game.bonus == splatter)
}
if (game.bonus == splatter) {
score += 25;
if (game.bonus == defeat)
}
if (game.bonus == defeat) {
score += 30;
if (game.bonus == victory)
}
if (game.bonus == victory) {
score += 45;
}
}
mxscor += 45;
/* Did he come to Witt's End as he should? */
if (game.objects[MAGAZINE].place == LOC_WITTSEND)
if (game.objects[MAGAZINE].place == LOC_WITTSEND) {
score += 1;
}
mxscor += 1;
/* Round it off. */
@ -95,13 +107,16 @@ int score(enum termination mode)
/* Deduct for hints/turns/saves. Hints < 4 are special; see database desc. */
for (int i = 0; i < NHINTS; i++) {
if (game.hints[i].used)
if (game.hints[i].used) {
score = score - hints[i].penalty;
}
if (game.novice)
}
if (game.novice) {
score -= 5;
if (game.clshnt)
}
if (game.clshnt) {
score -= 10;
}
score = score - game.trnluz - game.saved;
/* Return to score command if that's where we came from. */
@ -112,18 +127,19 @@ int score(enum termination mode)
return score;
}
void terminate(enum termination mode)
void terminate(enum termination mode) {
/* End of game. Let's tell him all about it. */
{
int points = score(mode);
#if defined ADVENT_AUTOSAVE
autosave();
#endif
if (points + game.trnluz + 1 >= mxscor && game.trnluz != 0)
if (points + game.trnluz + 1 >= mxscor && game.trnluz != 0) {
rspeak(TOOK_LONG);
if (points + game.saved + 1 >= mxscor && game.saved != 0)
}
if (points + game.saved + 1 >= mxscor && game.saved != 0) {
rspeak(WITHOUT_SUSPENDS);
}
rspeak(TOTAL_SCORE, points, mxscor, game.turns, game.turns);
for (int i = 1; i <= (int)NCLASSES; i++) {
if (classes[i].threshold >= points) {