From 2848494a01db9baccf69c9a592ea5a916af84a8a Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Fri, 23 Jun 2017 14:07:44 -0400 Subject: [PATCH] Proof of cobcept for state defines. It is now possible in the YAML to declare defines for all state values associated with an object. This are visible in the C code and can be used to replace magic numbers. --- actions.c | 14 ++++++++------ adventure.yaml | 26 ++++++++++++++------------ main.c | 9 +++++---- newdungeon.py | 33 +++++++++++++++++++++++++-------- 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/actions.c b/actions.c index b6cfc33..0f7ece8 100644 --- a/actions.c +++ b/actions.c @@ -242,10 +242,11 @@ static int carry(token_t verb, token_t obj) } if (obj == WATER || obj == OIL) { if (!HERE(BOTTLE) || LIQUID() != obj) { - if (TOTING(BOTTLE) && game.prop[BOTTLE] == 1) + if (TOTING(BOTTLE) && game.prop[BOTTLE] == EMPTY_BOTTLE) return (fill(verb, BOTTLE)); else { - if (game.prop[BOTTLE] != 1)spk = BOTTLE_FULL; + if (game.prop[BOTTLE] != EMPTY_BOTTLE) + spk = BOTTLE_FULL; if (!TOTING(BOTTLE))spk = NO_CONTAINER; rspeak(spk); return GO_CLEAROBJ; @@ -356,7 +357,7 @@ static int discard(token_t verb, token_t obj, bool just_do_it) } else if (obj == COINS && HERE(VEND)) { DESTROY(COINS); DROP(BATTERY, game.loc); - pspeak(BATTERY, 0); + pspeak(BATTERY, FRESH_BATTERIES); return GO_CLEAROBJ; } else if (obj == BIRD && AT(DRAGON) && game.prop[DRAGON] == 0) { rspeak(BIRD_BURNT); @@ -402,7 +403,7 @@ static int drink(token_t verb, token_t obj) if (obj != BLOOD) { if (obj != 0 && obj != WATER)spk = RIDICULOUS_ATTEMPT; if (spk != RIDICULOUS_ATTEMPT && LIQUID() == WATER && HERE(BOTTLE)) { - game.prop[BOTTLE] = 1; + game.prop[BOTTLE] = EMPTY_BOTTLE; game.place[WATER] = LOC_NOWHERE; spk = BOTTLE_EMPTY; } @@ -534,7 +535,7 @@ int fill(token_t verb, token_t obj) return GO_CLEAROBJ; } game.place[k] = LOC_NOWHERE; - game.prop[BOTTLE] = 1; + game.prop[BOTTLE] = EMPTY_BOTTLE; if (k == OIL)game.prop[URN] = 1; spk = WATER_URN + game.prop[URN]; rspeak(spk); @@ -552,6 +553,7 @@ int fill(token_t verb, token_t obj) if (LIQUID() != 0) spk = BOTTLE_FULL; if (spk == BOTTLED_WATER) { + /* FIXME: Arithmetic on property values */ game.prop[BOTTLE] = MOD(conditions[game.loc], 4) / 2 * 2; k = LIQUID(); if (TOTING(BOTTLE)) @@ -756,7 +758,7 @@ static int pour(token_t verb, token_t obj) } if (HERE(URN) && game.prop[URN] == 0) return fill(verb, URN); - game.prop[BOTTLE] = 1; + game.prop[BOTTLE] = EMPTY_BOTTLE; game.place[obj] = LOC_NOWHERE; spk = GROUND_WET; if (!(AT(PLANT) || AT(DOOR))) { diff --git a/adventure.yaml b/adventure.yaml index 24eb206..f5df5c0 100644 --- a/adventure.yaml +++ b/adventure.yaml @@ -64,8 +64,10 @@ # # objects: Each item contains a description for use in the inventory command # and one or more messages describing the object in different states. -# If the inventory desription begins with "*" the object is dungeon -# furniture that cannot be taken or carried. +# If a state message is a tuple then the first element is made the name +# of a #define viible to the code for the associayed state, numbered +# from zero upwards. If the inventory desription begins with "*" the +# object is dungeon furniture that cannot be taken or carried. # # obituaries: Death messages and reincarnation queries. Order is # significant, they're used in succession as the player racks up @@ -1343,7 +1345,7 @@ arbitrary_messages: !!omap - PIRATE_SPOTTED: 'There are faint rustling noises from the darkness behind you. As you\nturn toward them, the beam of your lamp falls across a bearded pirate.\nHe is carrying a large chest. "Shiver me timbers!" he cries, "I''ve\nbeen spotted! I''d best hie meself off to the maze to hide me chest!"\nWith that, he vanishes into the gloom.' - GET_BATTERIES: 'Your lamp is getting dim. You''d best go back for those batteries.' - REPLACE_BATTERIES: 'Your lamp is getting dim. I''m taking the liberty of replacing the\nbatteries.' -- MISSING_BATTERYIES: 'Your lamp is getting dim, and you''re out of spare batteries. You''d\nbest start wrapping this up.' +- MISSING_BATTERIES: 'Your lamp is getting dim, and you''re out of spare batteries. You''d\nbest start wrapping this up.' - REMOVE_MESSAGE: 'You sift your fingers through the dust, but succeed only in\nobliterating the cryptic message.' - OGRE_QUERY: 'Do you need help dealing with the ogre?' - CLUE_QUERY: 'Hmmm, this looks like a clue, which means it''ll cost you 10 points to\nread it. Should I go ahead and read it anyway?' @@ -1574,9 +1576,9 @@ object_descriptions: !!omap - OBJ_20: inventory: 'Small bottle' longs: - - 'There is a bottle of water here.' - - 'There is an empty bottle here.' - - 'There is a bottle of oil here.' + - [WATER_BOTTLE, 'There is a bottle of water here.'] + - [EMPTY_BOTTLE, 'There is an empty bottle here.'] + - [OIL_BOTTLE, 'There is a bottle of oil here.'] - OBJ_21: inventory: 'Water in the bottle' longs: !!null @@ -1676,8 +1678,8 @@ object_descriptions: !!omap - OBJ_39: inventory: 'Batteries' longs: - - 'There are fresh batteries here.' - - 'Some worn-out batteries have been discarded nearby.' + - [FRESH_BATTERIES, 'There are fresh batteries here.'] + - [DEAD_BATTERIES, 'Some worn-out batteries have been discarded nearby.'] - OBJ_40: inventory: '*carpet and/or moss and/or curtains' longs: !!null @@ -1764,10 +1766,10 @@ object_descriptions: !!omap - OBJ_58: inventory: 'Ming vase' longs: - - 'There is a delicate, precious, ming vase here!' - - 'The vase is now resting, delicately, on a velvet pillow.' - - 'The floor is littered with worthless shards of pottery.' - - 'The ming vase drops with a delicate crash.' + - [VASE_WHOLE, 'There is a delicate, precious, ming vase here!'] + - [VASE_RESTING, 'The vase is now resting, delicately, on a velvet pillow.'] + - [VASE_BROKEN, 'The floor is littered with worthless shards of pottery.'] + - [VASE_DROPS, 'The ming vase drops with a delicate crash.'] - OBJ_59: inventory: 'Egg-sized emerald' longs: diff --git a/main.c b/main.c index 90665c7..3c4c034 100644 --- a/main.c +++ b/main.c @@ -799,7 +799,7 @@ static bool closecheck(void) * objects he might be carrying (lest he have some which * could cause trouble, such as the keys). We describe the * flash of light and trundle back. */ - game.prop[BOTTLE] = PUT(BOTTLE, LOC_NE, 1); + game.prop[BOTTLE] = PUT(BOTTLE, LOC_NE, EMPTY_BOTTLE); game.prop[PLANT] = PUT(PLANT, LOC_NE, 0); game.prop[OYSTER] = PUT(OYSTER, LOC_NE, 0); OBJTXT[OYSTER] = 3; @@ -848,9 +848,9 @@ static void lampcheck(void) * here, in which case we replace the batteries and continue. * Second is for other cases of lamp dying. Eve after it goes * out, he can explore outside for a while if desired. */ - if (game.limit <= WARNTIME && HERE(BATTERY) && game.prop[BATTERY] == 0 && HERE(LAMP)) { + if (game.limit <= WARNTIME && HERE(BATTERY) && game.prop[BATTERY] == FRESH_BATTERIES && HERE(LAMP)) { rspeak(REPLACE_BATTERIES); - game.prop[BATTERY] = 1; + game.prop[BATTERY] = DEAD_BATTERIES; if (TOTING(BATTERY)) DROP(BATTERY, game.loc); game.limit += BATTERYLIFE; @@ -865,7 +865,8 @@ static void lampcheck(void) game.lmwarn = true; int spk = GET_BATTERIES; if (game.place[BATTERY] == LOC_NOWHERE)spk = LAMP_DIM; - if (game.prop[BATTERY] == 1)spk = MISSING_BATTERYIES; + if (game.prop[BATTERY] == DEAD_BATTERIES) + spk = MISSING_BATTERIES; rspeak(spk); } } diff --git a/newdungeon.py b/newdungeon.py index 873990c..a981a1d 100755 --- a/newdungeon.py +++ b/newdungeon.py @@ -8,6 +8,8 @@ yaml_name = "adventure.yaml" h_name = "newdb.h" c_name = "newdb.c" +statedefines = "" + h_template = """/* Generated from adventure.yaml - do not hand-hack! */ #ifndef NEWDB_H #define NEWDB_H @@ -65,7 +67,6 @@ extern turn_threshold_t turn_thresholds[]; extern obituary_t obituaries[]; extern hint_t hints[]; extern long conditions[]; - extern const size_t CLSSES; extern const int maximum_deaths; extern const int turn_threshold_count; @@ -83,6 +84,9 @@ enum object_descriptions_refs {{ {} }}; +/* State definitions */ + +{} #endif /* end NEWDB_H */ """ @@ -223,9 +227,21 @@ def get_object_descriptions(obj): if item[1]["longs"] == None: longs_str = " " * 12 + "NULL," else: + labels = [] for l_msg in item[1]["longs"]: + if not isinstance(l_msg, str): + labels.append(l_msg) + l_msg = l_msg[1] longs_str += " " * 12 + make_c_string(l_msg) + ",\n" longs_str = longs_str[:-1] # trim trailing newline + if labels: + global statedefines + statedefines += "/* States for %s */\n" % item[0] + for (i, (label, message)) in enumerate(labels): + if len(message) >= 45: + message = message[:45] + "..." + statedefines += "#define %s\t%d /* %s */\n" % (label, i, message) + statedefines += "\n" obj_str += template.format(i_msg, longs_str) obj_str = obj_str[:-1] # trim trailing newline return obj_str @@ -290,13 +306,6 @@ if __name__ == "__main__": with open(yaml_name, "r") as f: db = yaml.load(f) - h = h_template.format( - len(db["hints"]), - get_refs(db["arbitrary_messages"]), - get_refs(db["locations"]), - get_refs(db["object_descriptions"]), - ) - c = c_template.format( h_name, get_arbitrary_messages(db["arbitrary_messages"]), @@ -312,6 +321,14 @@ if __name__ == "__main__": len(db["turn_thresholds"]), ) + h = h_template.format( + len(db["hints"]), + get_refs(db["arbitrary_messages"]), + get_refs(db["locations"]), + get_refs(db["object_descriptions"]), + statedefines, + ) + with open(h_name, "w") as hf: hf.write(h) -- 2.31.1