-#define LINESIZE 1024
-#define NDWARVES 6 // number of dwarves
-#define PIRATE NDWARVES // must be NDWARVES-1 when zero-origin
-#define DALTLC LOC_NUGGET // alternate dwarf location
-#define INVLIMIT 7 // inverntory limit (# of objects)
-#define INTRANSITIVE -1 // illegal object number
-#define SPECIALBASE 300 // base number of special rooms
-#define GAMELIMIT 330 // base limit of turns
-#define NOVICELIMIT 1000 // limit of turns for novice
-#define WARNTIME 30 // late game starts at game.limit-this
-#define FLASHTIME 50 // turns from first warning till blinding flash
-#define PANICTIME 15 // time left after closing
-#define BATTERYLIFE 2500 // turn limit increment from batteries
-#define WORD_NOT_FOUND -1 // "Word not found" flag value for the vocab hash functions.
-#define CARRIED -1 // Player is toting it
-#define READ_MODE "rb" // b is not needed for POSIX but harmless
-#define WRITE_MODE "wb" // b is not needed for POSIX but harmless
+/* LCG PRNG parameters tested against
+ * Knuth vol. 2. by the original authors */
+#define LCG_A 1093L
+#define LCG_C 221587L
+#define LCG_M 1048576L
+
+#define LINESIZE 1024
+#define TOKLEN 5 // # outputting characters in a token */
+#define PIRATE NDWARVES // must be NDWARVES-1 when zero-origin
+#define DALTLC LOC_NUGGET // alternate dwarf location
+#define INVLIMIT 7 // inventory limit (# of objects)
+#define INTRANSITIVE -1 // illegal object number
+#define GAMELIMIT 330 // base limit of turns
+#define NOVICELIMIT 1000 // limit of turns for novice
+#define WARNTIME 30 // late game starts at game.limit-this
+#define FLASHTIME 50 // turns from first warning till blinding flash
+#define PANICTIME 15 // time left after closing
+#define BATTERYLIFE 2500 // turn limit increment from batteries
+#define WORD_NOT_FOUND \
+ -1 // "Word not found" flag value for the vocab hash functions.
+#define WORD_EMPTY 0 // "Word empty" flag value for the vocab hash functions
+#define PIT_KILL_PROB 35 // Percentage probability of dying from fall in pit.
+#define CARRIED -1 // Player is toting it
+#define READ_MODE "rb" // b is not needed for POSIX but harmless
+#define WRITE_MODE "wb" // b is not needed for POSIX but harmless
+
+/* Special object-state values - integers > 0 are object-specific */
+#define STATE_NOTFOUND -1 // 'Not found" state of treasures
+#define STATE_FOUND 0 // After discovered, before messed with
+#define STATE_IN_CAVITY 1 // State value common to all gemstones
+
+/* Special fixed object-state values - integers > 0 are location */
+#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
+ * member (which used to be an array of its own) is our mystery. This
+ * state tangles together information about whether the object is a
+ * treasure, whether the player has seen it yet, and its activation
+ * state.
+ *
+ * Things we think we know:
+ *
+ * STATE_NOTFOUND is only set on treasures. Non-treasures start the
+ * game in STATE_FOUND.
+ *
+ * OBJECT_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.
+ */
+#define PROP_STASHIFY(n) (-1 - (n))
+#define PROP_IS_INVALID(val) (val < -MAX_STATE - 1 || val > MAX_STATE)
+#define OBJECT_IS_STASHED(obj) (game.objects[obj].prop < STATE_NOTFOUND)
+#define OBJECT_IS_NOTFOUND(obj) (game.objects[obj].prop == STATE_NOTFOUND)
+#define OBJECT_IS_FOUND(obj) (game.objects[obj].prop == STATE_FOUND)
+#define OBJECT_IS_STASHED_OR_UNSEEN(obj) (game.objects[obj].prop < 0)
+#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)
+#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.
+ */
+#define PROP_STASHIFY(n) (-(n))
+#define PROP_IS_INVALID(val) (val < -MAX_STATE || val > MAX_STATE)
+#define OBJECT_IS_STASHED(obj) (game.objects[obj].prop < 0)
+#define OBJECT_IS_NOTFOUND(obj) (!game.objects[obj].found)
+#define OBJECT_IS_FOUND(obj) \
+ (game.objects[obj].found && game.objects[obj].prop == 0)
+#define OBJECT_IS_STASHED_OR_UNSEEN(obj) \
+ (!game.objects[obj].found || game.objects[obj].prop < 0)
+#define OBJECT_SET_FOUND(obj) \
+ do { \
+ game.objects[obj].found = true; \
+ game.objects[obj].prop = STATE_FOUND; \
+ } while (0)
+#define OBJECT_SET_NOT_FOUND(obj) game.objects[obj].found = false
+#define OBJECT_IS_NOTFOUND2(g, o) (!g.objects[o].found)
+#define OBJECT_SET_SEEN(obj) game.objects[object].found = true
+#endif
+#define OBJECT_STASHED(obj) PROP_STASHIFY(game.objects[obj].prop)
+
+#define PROMPT "> "