diff --git a/INSTALL.adoc b/INSTALL.adoc index fb93b7d..5184d6b 100644 --- a/INSTALL.adoc +++ b/INSTALL.adoc @@ -23,5 +23,3 @@ You can also use pip to install PyYAML: `pip3 install PyYAML`. 5. Run `./advent` to play. 6. If you want to buld the documentation you will need asciidoctor. - -7. Running the regression tests requires batchspell diff --git a/Makefile b/Makefile index e4e31cb..a7acbd8 100644 --- a/Makefile +++ b/Makefile @@ -67,17 +67,14 @@ cheat: $(CHEAT_OBJS) dungeon.o CSUPPRESSIONS = --suppress=missingIncludeSystem --suppress=invalidscanf cppcheck: - @-cppcheck -I. --quiet --template gcc -UOBJECT_SET_SEEN --enable=all $(CSUPPRESSIONS) *.[ch] + @-cppcheck -I. --quiet --template gcc -UPROP_SET_SEEN --enable=all $(CSUPPRESSIONS) *.[ch] pylint: @-pylint --score=n *.py */*.py -check: advent cheat pylint cppcheck spellcheck +check: advent cheat pylint cppcheck cd tests; $(MAKE) --quiet -spellcheck: - @batchspell adventure.yaml advent.adoc - reflow: @clang-format --style="{IndentWidth: 8, UseTab: ForIndentation}" -i $$(find . -name "*.[ch]") @black --quiet *.py diff --git a/NEWS.adoc b/NEWS.adoc index 0140574..2d0dcee 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -2,9 +2,6 @@ // SPDX-FileCopyrightText: (C) Eric S. Raymond // SPDX-License-Identifier: CC-BY-4.0 -1.20: 2024-09-23:: - Make oldstyle correctly suppress line editing. - 1.19: 2024-06-27:: Ensore that the KNIVES_VANISH message can't issue twice. diff --git a/actions.c b/actions.c index 469e92f..31a09c8 100644 --- a/actions.c +++ b/actions.c @@ -246,7 +246,7 @@ static phase_codes_t bigwords(vocab_t id) { static void blast(void) { /* Blast. No effect unless you've got dynamite, which is a neat trick! */ - if (OBJECT_IS_NOTFOUND(ROD2) || !game.closed) { + if (PROP_IS_NOTFOUND(ROD2) || !game.closed) { rspeak(REQUIRES_DYNAMITE); } else { if (HERE(ROD2)) { @@ -329,8 +329,8 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) { if (game.objects[obj].fixed != IS_FREE) { switch (obj) { case PLANT: - rspeak((game.objects[PLANT].prop == PLANT_THIRSTY || - OBJECT_IS_STASHED(PLANT)) + /* Next guard tests whether plant is tiny or stashed */ + rspeak(game.objects[PLANT].prop <= PLANT_THIRSTY ? DEEP_ROOTS : YOU_JOKING); break; @@ -389,7 +389,7 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) { } if (obj == BIRD && game.objects[BIRD].prop != BIRD_CAGED && - !OBJECT_IS_STASHED(BIRD)) { + !PROP_IS_STASHED(BIRD)) { if (game.objects[BIRD].prop == BIRD_FOREST_UNCAGED) { DESTROY(BIRD); rspeak(BIRD_CRAP); @@ -406,7 +406,8 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) { game.objects[BIRD].prop = BIRD_CAGED; } if ((obj == BIRD || obj == CAGE) && - OBJECT_STATE_EQUALS(BIRD, BIRD_CAGED)) { + (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); } @@ -417,8 +418,8 @@ static phase_codes_t vcarry(verb_t verb, obj_t obj) { game.objects[LIQUID()].place = CARRIED; } - if (GSTONE(obj) && !OBJECT_IS_FOUND(obj)) { - OBJECT_SET_FOUND(obj); + if (GSTONE(obj) && !PROP_IS_FOUND(obj)) { + PROP_SET_FOUND(obj); game.objects[CAVITY].prop = CAVITY_EMPTY; } rspeak(OK_MAN); @@ -676,7 +677,7 @@ static phase_codes_t extinguish(verb_t verb, obj_t obj) { break; case LAMP: state_change(LAMP, LAMP_DARK); - rspeak(IS_DARK_HERE() ? PITCH_DARK : NO_MESSAGE); + rspeak(DARK(game.loc) ? PITCH_DARK : NO_MESSAGE); break; case DRAGON: case VOLCANO: @@ -970,7 +971,7 @@ static phase_codes_t listen(void) { } for (obj_t i = 1; i <= NOBJECTS; i++) { if (!HERE(i) || objects[i].sounds[0] == NULL || - OBJECT_IS_STASHED(i) || OBJECT_IS_NOTFOUND(i)) { + PROP_IS_STASHED_OR_UNSEEN(i)) { continue; } int mi = game.objects[i].prop; @@ -1150,17 +1151,17 @@ static phase_codes_t read(command_t command) command.obj = NO_OBJECT; for (int i = 1; i <= NOBJECTS; i++) { if (HERE(i) && objects[i].texts[0] != NULL && - !OBJECT_IS_STASHED(i)) { + !PROP_IS_STASHED(i)) { command.obj = command.obj * NOBJECTS + i; } } if (command.obj > NOBJECTS || command.obj == NO_OBJECT || - IS_DARK_HERE()) { + DARK(game.loc)) { return GO_UNKNOWN; } } - if (IS_DARK_HERE()) { + if (DARK(game.loc)) { sspeak(NO_SEE, command.word[0].raw); } else if (command.obj == OYSTER) { if (!TOTING(OYSTER) || !game.closed) { @@ -1174,7 +1175,7 @@ static phase_codes_t read(command_t command) 1); // Not really a sound, but oh well. } } else if (objects[command.obj].texts[0] == NULL || - OBJECT_IS_NOTFOUND(command.obj)) { + PROP_IS_NOTFOUND(command.obj)) { speak(actions[command.verb].message); } else { pspeak(command.obj, study, true, @@ -1350,9 +1351,9 @@ static phase_codes_t wave(verb_t verb, obj_t obj) { } if (game.objects[BIRD].prop == BIRD_UNCAGED && - game.loc == game.objects[STEPS].place && OBJECT_IS_NOTFOUND(JADE)) { + game.loc == game.objects[STEPS].place && PROP_IS_NOTFOUND(JADE)) { drop(JADE, game.loc); - OBJECT_SET_FOUND(JADE); + PROP_SET_FOUND(JADE); --game.tally; rspeak(NECKLACE_FLY); return GO_CLEAROBJ; diff --git a/advent.adoc b/advent.adoc index a064d1a..f132b0c 100644 --- a/advent.adoc +++ b/advent.adoc @@ -3,9 +3,6 @@ // SPDX-FileCopyrightText: (C) Eric S. Raymond // SPDX-License-Identifier: CC-BY-4.0 -// batchspell: add advent logfile savefile roleplaying Gillogly PDP Ctrl-D -// batchspell: add EOF autosave endianness wumpus zork nethack - == NAME == advent - Colossal Cave Adventure diff --git a/advent.h b/advent.h index fa0767b..21a521f 100644 --- a/advent.h +++ b/advent.h @@ -47,6 +47,7 @@ #define IS_FIXED -1 #define IS_FREE 0 +#ifndef FOUNDBOOL /* (ESR) It is fitting that translation of the original ADVENT should * have left us a maze of twisty little conditionals that resists all * understanding. Setting and use of what is now the per-object state @@ -60,49 +61,71 @@ * STATE_NOTFOUND is only set on treasures. Non-treasures start the * game in STATE_FOUND. * - * PROP_STASHIFY is supposed to map a state property value to a + * PROP_STASHED is supposed to map a state property value to a * negative range, where the object cannot be picked up but the value * can be recovered later. Various objects get this property when * the cave starts to close. Only seems to be significant for the bird * and readable objects, notably the clam/oyster - but the code around * those tests is difficult to read. - * - * All tests of the prop member are done with either these macros or ==. */ -#define OBJECT_IS_NOTFOUND(obj) (game.objects[obj].prop == STATE_NOTFOUND) -#define OBJECT_IS_FOUND(obj) (game.objects[obj].prop == STATE_FOUND) -#define OBJECT_SET_FOUND(obj) (game.objects[obj].prop = STATE_FOUND) -#define OBJECT_SET_NOT_FOUND(obj) (game.objects[obj].prop = STATE_NOTFOUND) -#define OBJECT_IS_NOTFOUND2(g, o) (g.objects[o].prop == STATE_NOTFOUND) -#define PROP_IS_INVALID(val) (val < -MAX_STATE - 1 || val > MAX_STATE) #define PROP_STASHIFY(n) (-1 - (n)) -#define OBJECT_STASHIFY(obj, pval) game.objects[obj].prop = PROP_STASHIFY(pval) -#define OBJECT_IS_STASHED(obj) (game.objects[obj].prop < STATE_NOTFOUND) -#define OBJECT_STATE_EQUALS(obj, pval) \ - ((game.objects[obj].prop == pval) || \ - (game.objects[obj].prop == PROP_STASHIFY(pval))) +#define PROP_IS_STASHED(obj) (game.objects[obj].prop < STATE_NOTFOUND) +#define PROP_IS_NOTFOUND(obj) (game.objects[obj].prop == STATE_NOTFOUND) +#define PROP_IS_FOUND(obj) (game.objects[obj].prop == STATE_FOUND) +#define PROP_IS_STASHED_OR_UNSEEN(obj) (game.objects[obj].prop < 0) +#define PROP_SET_FOUND(obj) (game.objects[obj].prop = STATE_FOUND) +#define PROP_SET_NOT_FOUND(obj) (game.objects[obj].prop = STATE_NOTFOUND) +#define PROP_IS_NOTFOUND2(g, o) (g.objects[o].prop == STATE_NOTFOUND) +#define PROP_IS_INVALID(val) (val < -MAX_STATE - 1 || val > MAX_STATE) +#else +/* (ESR) Only the boldest of adventurers will explore here. This + * alternate set of definitions for the macros above was an attempt to + * break out of the state encoding a per-object "found" member + * telling whether or not the player has seen the object. + * + * What's broken when you try to use thus is + * PROP_IS_STASHED_OR_UNSEEN. The symptom is game.tally getting + * decremented on non-treasures. + */ +#define PROP_STASHIFY(n) (-(n)) +#define PROP_IS_STASHED(obj) (game.objects[obj].prop < 0) +#define PROP_IS_NOTFOUND(obj) (!game.objects[obj].found) +#define PROP_IS_FOUND(obj) \ + (game.objects[obj].found && game.objects[obj].prop == 0) +#define PROP_IS_STASHED_OR_UNSEEN(obj) \ + (!game.objects[obj].found || game.objects[obj].prop < 0) +#define PROP_SET_FOUND(obj) \ + do { \ + game.objects[obj].found = true; \ + game.objects[obj].prop = STATE_FOUND; \ + } while (0) +#define PROP_SET_NOT_FOUND(obj) game.objects[obj].found = false +#define PROP_IS_NOTFOUND2(g, o) (!g.objects[o].found) +#define PROP_IS_INVALID(val) (val < -MAX_STATE || val > MAX_STATE) +#define PROP_SET_SEEN(obj) game.objects[object].found = true +#endif +#define PROP_STASHED(obj) PROP_STASHIFY(game.objects[obj].prop) #define PROMPT "> " /* - * DESTROY(N) = Get rid of an item by putting it in LOC_NOWHERE - * MOD(N,M) = Arithmetic modulus - * TOTING(OBJ) = true if the OBJ is being carried - * AT(OBJ) = true if on either side of two-placed object - * HERE(OBJ) = true if the OBJ is at "LOC" (or is being carried) - * CNDBIT(L,N) = true if COND(L) has bit n set (bit 0 is units bit) - * LIQUID() = object number of liquid in bottle - * LIQLOC(LOC) = object number of liquid (if any) at LOC - * FORCED(LOC) = true if LOC moves without asking for input (COND=2) - * IS_DARK_HERE() = true if location "LOC" is dark - * PCT(N) = true N% of the time (N integer from 0 to 100) - * GSTONE(OBJ) = true if OBJ is a gemstone - * FOREST(LOC) = true if LOC is part of the forest - * OUTSIDE(LOC) = true if location not in the cave - * INSIDE(LOC) = true if location is in the cave or the building at the - * beginning of the game - * INDEEP(LOC) = true if location is in the Hall of Mists or deeper - * BUG(X) = report bug and exit + * DESTROY(N) = Get rid of an item by putting it in LOC_NOWHERE + * MOD(N,M) = Arithmetic modulus + * TOTING(OBJ) = true if the OBJ is being carried + * AT(OBJ) = true if on either side of two-placed object + * HERE(OBJ) = true if the OBJ is at "LOC" (or is being carried) + * CNDBIT(L,N) = true if COND(L) has bit n set (bit 0 is units bit) + * LIQUID() = object number of liquid in bottle + * LIQLOC(LOC) = object number of liquid (if any) at LOC + * FORCED(LOC) = true if LOC moves without asking for input (COND=2) + * DARK(LOC) = true if location "LOC" is dark + * PCT(N) = true N% of the time (N integer from 0 to 100) + * GSTONE(OBJ) = true if OBJ is a gemstone + * FOREST(LOC) = true if LOC is part of the forest + * OUTSID(LOC) = true if location not in the cave + * INSIDE(LOC) = true if location is in the cave or the building at the + * beginning of the game INDEEP(LOC) = true if location is in the Hall of Mists + * or deeper BUG(X) = report bug and exit */ #define DESTROY(N) move(N, LOC_NOWHERE) #define MOD(N, M) ((N) % (M)) @@ -120,15 +143,15 @@ (CNDBIT((LOC), COND_FLUID) ? CNDBIT((LOC), COND_OILY) ? OIL : WATER \ : NO_OBJECT) #define FORCED(LOC) CNDBIT(LOC, COND_FORCED) -#define IS_DARK_HERE() \ +#define DARK(DUMMY) \ (!CNDBIT(game.loc, COND_LIT) && \ (game.objects[LAMP].prop == LAMP_DARK || !HERE(LAMP))) #define PCT(N) (randrange(100) < (N)) #define GSTONE(OBJ) \ ((OBJ) == EMERALD || (OBJ) == RUBY || (OBJ) == AMBER || (OBJ) == SAPPH) #define FOREST(LOC) CNDBIT(LOC, COND_FOREST) -#define OUTSIDE(LOC) (CNDBIT(LOC, COND_ABOVE) || FOREST(LOC)) -#define INSIDE(LOC) (!OUTSIDE(LOC) || LOC == LOC_BUILDING) +#define OUTSID(LOC) (CNDBIT(LOC, COND_ABOVE) || FOREST(LOC)) +#define INSIDE(LOC) (!OUTSID(LOC) || LOC == LOC_BUILDING) #define INDEEP(LOC) CNDBIT((LOC), COND_DEEP) #define BUG(x) bug(x, #x) @@ -234,8 +257,11 @@ struct game_t { loc_t oldloc; // prior loc of each dwarf, initially garbage } dwarves[NDWARVES + 1]; struct { +#ifdef FOUNDBOOL + bool32_t found; // has the location of this object been found? +#endif loc_t fixed; // fixed location of object (if not IS_FREE) - int32_t prop; // object state + int32_t prop; // object state */ loc_t place; // location of object } objects[NOBJECTS + 1]; struct { diff --git a/adventure.yaml b/adventure.yaml index 141ffb7..31988de 100644 --- a/adventure.yaml +++ b/adventure.yaml @@ -1,10 +1,6 @@ # SPDX-FileCopyrightText: (C) Eric S. Raymond # SPDX-License-Identifier: BSD-2-Clause # -# batchspell: add XYZZY Twopit Bedquilt ne se sw nw dwarves dwarvish gouts -# batchspell: add Crowther add axe pinin Har har meself Hmmm Adventuredom -# batchspell: add Tsk gameplay bugfixes -# # This YAML file gets processed into a collection of data structures and # variable initializers describing Colossal Cave. It replaces an ad-hoc # text database shipped with Adventure versions up to 2.5. The format @@ -14,7 +10,7 @@ # We define a bunch of YAML structures: # # motions: Motion words, grouped into synonyms. The 'oldstyle' -# attribute, if false, means that single-letter synonyms should not be +# attribute, if false, means that single-letter synonyms should be # accepted in oldstyle mode; it defaults to true. # # actions: Action words, grouped into synonyms, and their corresponding @@ -3436,7 +3432,7 @@ objects: !!omap - 'There are a few recent issues of "Spelunker Today" magazine here.' texts: - |- - I'm afraid the magazine is written in dwarvish. But penciled on one + I'm afraid the magazine is written in dwarvish. But pencilled on one cover you see, "Please leave the magazines at the construction site." - DWARF: words: ['dwarf', 'dwarv'] @@ -3944,13 +3940,11 @@ obituaries: Oh dear, you seem to have gotten yourself killed. I might be able to help you out, but I've never really done this before. Do you want me to try to reincarnate you? - # batchspell: add wr yes_response: |- All right. But don't blame me if something goes wr...... --- POOF!! --- You are engulfed in a cloud of orange smoke. Coughing and gasping, you emerge from the smoke and find.... - # batchspell: remove wr - query: |- You clumsy oaf, you've done it again! I don't know how long I can keep this up. Do you want me to try reincarnating you again? @@ -4232,7 +4226,7 @@ actions: !!omap message: |- There is a puff of orange smoke; within it, fiery runes spell out: - Open Adventure %V - http://www.catb.org/esr/open-adventure/ + \tOpen Adventure %V - http://www.catb.org/esr/open-adventure/ words: ['versi'] noaction: true diff --git a/init.c b/init.c index 372e494..e413fff 100644 --- a/init.c +++ b/init.c @@ -1,7 +1,7 @@ /* * Initialisation * - * SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods + * SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woodsm * SPDX-License-Identifier: BSD-2-Clause */ @@ -76,18 +76,13 @@ int initialise(void) { /* Treasure props are initially STATE_NOTFOUND, and are set to * STATE_FOUND the first time they are described. game.tally * keeps track of how many are not yet found, so we know when to - * close the cave. - * (ESR) Non-treasures are set to STATE_FOUND explicitly so we - * don't rely on the value of uninitialized storage. This is to - * make translation to future languages easier. */ - for (int object = 1; object <= NOBJECTS; object++) { - if (objects[object].is_treasure) { + * close the cave. */ + for (int treasure = 1; treasure <= NOBJECTS; treasure++) { + if (objects[treasure].is_treasure) { ++game.tally; - if (objects[object].inventory != NULL) { - OBJECT_SET_NOT_FOUND(object); + if (objects[treasure].inventory != 0) { + PROP_SET_NOT_FOUND(treasure); } - } else { - OBJECT_SET_FOUND(object); } } game.conds = setbit(COND_HBASE); diff --git a/main.c b/main.c index 835fc1b..6d904f2 100644 --- a/main.c +++ b/main.c @@ -81,7 +81,7 @@ char *myreadline(const char *prompt) { } } - if (isatty(fileno(settings.scriptfp)) && !settings.oldstyle) { + if (isatty(fileno(settings.scriptfp))) { free(buf); // LCOV_EXCL_LINE return readline(prompt); // LCOV_EXCL_LINE } else { @@ -152,8 +152,8 @@ static void checkhints(void) { game.hints[hint].lc = 0; return; case 4: /* dark */ - if (!OBJECT_IS_NOTFOUND(EMERALD) && - OBJECT_IS_NOTFOUND(PYRAMID)) { + if (!PROP_IS_NOTFOUND(EMERALD) && + PROP_IS_NOTFOUND(PYRAMID)) { break; } game.hints[hint].lc = 0; @@ -188,8 +188,7 @@ static void checkhints(void) { return; case 9: /* jade */ if (game.tally == 1 && - (OBJECT_IS_STASHED(JADE) || - OBJECT_IS_NOTFOUND(JADE))) { + PROP_IS_STASHED_OR_UNSEEN(JADE)) { break; } game.hints[hint].lc = 0; @@ -232,8 +231,8 @@ static bool spotted_by_pirate(int i) { * tally=1 for an unseen chest, let the pirate be spotted. Note * 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 - * OBJECT_IS_FOUND(CHEST) == true. */ - if (game.loc == game.chloc || !OBJECT_IS_NOTFOUND(CHEST)) { + * PROP_IS_FOUND(CHEST) == true. */ + if (game.loc == game.chloc || !PROP_IS_NOTFOUND(CHEST)) { return true; } int snarfed = 0; @@ -534,7 +533,7 @@ static void describe_location(void) { msg = locations[game.loc].description.big; } - if (!FORCED(game.loc) && IS_DARK_HERE()) { + if (!FORCED(game.loc) && DARK(game.loc)) { msg = arbitrary_messages[PITCH_DARK]; } @@ -640,7 +639,7 @@ static void playermove(int motion) { } else if (motion == CAVE) { /* Cave. Different messages depending on whether above ground. */ - rspeak((OUTSIDE(game.loc) && game.loc != LOC_GRATE) + rspeak((OUTSID(game.loc) && game.loc != LOC_GRATE) ? FOLLOW_STREAM : NEED_DETAIL); return; @@ -1047,7 +1046,7 @@ 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 (!IS_DARK_HERE()) { + if (!DARK(game.loc)) { ++game.locs[game.loc].abbrev; for (int i = game.locs[game.loc].atloc; i != 0; i = game.link[i]) { @@ -1062,11 +1061,11 @@ static void listobjects(void) { * running this code only on objects with the treasure * property set. Nope. There is mystery here. */ - if (OBJECT_IS_STASHED(i) || OBJECT_IS_NOTFOUND(obj)) { + if (PROP_IS_STASHED_OR_UNSEEN(obj)) { if (game.closed) { continue; } - OBJECT_SET_FOUND(obj); + PROP_SET_FOUND(obj); if (obj == RUG) { game.objects[RUG].prop = RUG_DRAGON; } @@ -1193,7 +1192,7 @@ static bool preprocess_command(command_t *command) { 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 (OUTSIDE(game.newloc) && game.newloc != 0 && game.closng) { + if (OUTSID(game.newloc) && game.newloc != 0 && game.closng) { rspeak(EXIT_CLOSED); game.newloc = game.loc; if (!game.panic) { @@ -1229,7 +1228,7 @@ static bool do_move(void) { /* The easiest way to get killed is to fall into a pit in * pitch darkness. */ - if (!FORCED(game.loc) && IS_DARK_HERE() && game.wzdark && + if (!FORCED(game.loc) && DARK(game.loc) && game.wzdark && PCT(PIT_KILL_PROB)) { rspeak(PIT_FALL); game.oldlc2 = game.loc; @@ -1267,27 +1266,26 @@ static bool do_command(void) { * way objects won't be described until they've * been picked up and put down separate from * their respective piles. */ - if ((OBJECT_IS_NOTFOUND(OYSTER) || - OBJECT_IS_STASHED(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) && - (OBJECT_IS_NOTFOUND(i) || - OBJECT_IS_STASHED(i))) { - OBJECT_STASHIFY( - i, game.objects[i].prop); + if (TOTING(i) && (PROP_IS_NOTFOUND(i) || + PROP_IS_STASHED(i))) { + game.objects[i].prop = + PROP_STASHED(i); } } } /* Check to see if the room is dark. */ - game.wzdark = IS_DARK_HERE(); - + game.wzdark = DARK(game.loc); + /* If the knife is not here it permanently disappears. - * Possibly this should fire if the knife is here but - * the room is dark? */ + * Possibly this should fire if the knife is here but + * the room is dark? */ if (game.knfloc > LOC_NOWHERE && game.knfloc != game.loc) { game.knfloc = LOC_NOWHERE; diff --git a/misc.c b/misc.c index b28949e..9e90d05 100644 --- a/misc.c +++ b/misc.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -496,8 +495,8 @@ static void tokenize(char *raw, command_t *cmd) { memset(&cmd->word[1].raw, '\0', sizeof(cmd->word[1].raw)); /* Bound prefix on the %s would be needed to prevent buffer - * overflow. We shortstop this more simply by making each - * raw-input buffer as long as the entire input buffer. */ + * overflow. but we shortstop this more simply by making each + * raw-input buffer as int as the entire input buffer. */ sscanf(raw, "%s%s", cmd->word[0].raw, cmd->word[1].raw); /* (ESR) In oldstyle mode, simulate the uppercasing and truncating @@ -513,14 +512,10 @@ static void tokenize(char *raw, command_t *cmd) { * in their tools. On the other, not simulating this misbehavior * goes against the goal of making oldstyle as accurate as * possible an emulation of the original UI. - * - * The definition of TRUNCLEN is dubious. It accurately reflects the - * FORTRAN, but it's possible that was a bug and the proper definition - * is (TOKLEN). */ -#define TRUNCLEN (TOKLEN + TOKLEN) if (settings.oldstyle) { - cmd->word[0].raw[TRUNCLEN] = cmd->word[1].raw[TRUNCLEN] = '\0'; + cmd->word[0].raw[TOKLEN + TOKLEN] = + cmd->word[1].raw[TOKLEN + TOKLEN] = '\0'; for (size_t i = 0; i < strlen(cmd->word[0].raw); i++) { cmd->word[0].raw[i] = toupper(cmd->word[0].raw[i]); } @@ -622,12 +617,14 @@ void move(obj_t object, loc_t where) { } void put(obj_t object, loc_t where, int pval) { - /* put() is the same as move(), except the object is stashed and - * can no longer be picked up. */ + /* put() is the same as move(), except it returns a value used to set + * up the negated game.prop values for the repository objects. */ move(object, where); - OBJECT_STASHIFY(object, pval); -#ifdef OBJECT_SET_SEEN - OBJECT_SET_SEEN(object); + /* (ESR) Read this in combination with the macro defintions in advebt.h. + */ + game.objects[object].prop = PROP_STASHIFY(pval); +#ifdef PROP_SET_SEEN + PROP_SET_SEEN(object); #endif } diff --git a/notes.adoc b/notes.adoc index a247e49..833682c 100644 --- a/notes.adoc +++ b/notes.adoc @@ -16,8 +16,8 @@ of Peje Nilsson in restructuring some particularly grotty gotos is gratefully acknowledged. Petr Voropaev contributed fuzz testing and code cleanups. Aaron Traas did a lot of painstaking work to improve test coverage, and factored out the last handful of gotos. Ryan -Sarson nudged us into fixing a longstanding minor bug in the -handling of incorrect magic-word sequences, +Sarson nudged us into fixing a longstannding minor bug in the +handling of incorrect magic-word sequebcesm, == Nomenclature == @@ -75,8 +75,7 @@ Bug fixes: * A few minor typos have been corrected: absence of capitalization on "Swiss" and "Persian", inconsistent spelling of "imbedded" vs. "embedded", - "eying" for "eyeing", "thresholds" for "threshholds", "pencilled" - for "penciled". + "eying" for "eyeing", "thresholds" for "threshholds". * Under odd circumstances (dropping rug or vase outdoors) the game could formerly say "floor" when it should say "ground" (or "dirt", or diff --git a/saveresume.c b/saveresume.c index 1c778ef..100c925 100644 --- a/saveresume.c +++ b/saveresume.c @@ -230,7 +230,7 @@ bool is_valid(struct game_t valgame) { int temp_tally = 0; for (int treasure = 1; treasure <= NOBJECTS; treasure++) { if (objects[treasure].is_treasure) { - if (OBJECT_IS_NOTFOUND2(valgame, treasure)) { + if (PROP_IS_NOTFOUND2(valgame, treasure)) { ++temp_tally; } } diff --git a/score.c b/score.c index ad1c00a..1d84c79 100644 --- a/score.c +++ b/score.c @@ -49,11 +49,11 @@ int score(enum termination mode) { if (i > CHEST) { k = 16; } - if (!OBJECT_IS_STASHED(i) && !OBJECT_IS_NOTFOUND(i)) { + if (!PROP_IS_STASHED(i) && !PROP_IS_NOTFOUND(i)) { score += 2; } if (game.objects[i].place == LOC_BUILDING && - OBJECT_IS_FOUND(i)) { + PROP_IS_FOUND(i)) { score += k - 2; } mxscor += k;