+/* 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
+
+/* (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.
+ *
+ * PROP_STASHIFY 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 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
+ */
+#define DESTROY(N) move(N, LOC_NOWHERE)
+#define MOD(N, M) ((N) % (M))
+#define TOTING(OBJ) (game.objects[OBJ].place == CARRIED)
+#define AT(OBJ) \
+ (game.objects[OBJ].place == game.loc || \
+ game.objects[OBJ].fixed == game.loc)
+#define HERE(OBJ) (AT(OBJ) || TOTING(OBJ))
+#define CNDBIT(L, N) (tstbit(conditions[L], N))
+#define LIQUID() \
+ (game.objects[BOTTLE].prop == WATER_BOTTLE ? WATER \
+ : game.objects[BOTTLE].prop == OIL_BOTTLE ? OIL \
+ : NO_OBJECT)
+#define LIQLOC(LOC) \
+ (CNDBIT((LOC), COND_FLUID) ? CNDBIT((LOC), COND_OILY) ? OIL : WATER \
+ : NO_OBJECT)
+#define FORCED(LOC) CNDBIT(LOC, COND_FORCED)
+#define IS_DARK_HERE() \
+ (!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 INDEEP(LOC) CNDBIT((LOC), COND_DEEP)
+#define BUG(x) bug(x, #x)
+
+enum bugtype {
+ SPECIAL_TRAVEL_500_GT_L_GT_300_EXCEEDS_GOTO_LIST,
+ VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3,
+ INTRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST,
+ TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST,
+ CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION,
+ LOCATION_HAS_NO_TRAVEL_ENTRIES,
+ HINT_NUMBER_EXCEEDS_GOTO_LIST,
+ SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN,
+ ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH,
+};
+
+enum speaktype { touch, look, hear, study, change };
+
+enum termination { endgame, quitgame, scoregame };
+
+enum speechpart { unknown, intransitive, transitive };
+
+typedef enum { NO_WORD_TYPE, MOTION, OBJECT, ACTION, NUMERIC } word_type_t;
+
+typedef enum scorebonus { none, splatter, defeat, victory } score_t;
+
+/* Phase codes for action returns.
+ * These were at one time FORTRAN line numbers.
+ */
+typedef enum {
+ GO_TERMINATE,
+ GO_MOVE,
+ GO_TOP,
+ GO_CLEAROBJ,
+ GO_CHECKHINT,
+ GO_WORD2,
+ GO_UNKNOWN,
+ GO_DWARFWAKE,
+} phase_codes_t;