X-Git-Url: https://jxself.org/git/?p=open-adventure.git;a=blobdiff_plain;f=newdungeon.py;h=d1ea21c8f04c696429960ddb3ccd74107885f624;hp=6f95bb4232277da9b650112c761fa31184dd8529;hb=a4de450bfaf2c600dccd9a5b3625c5a3ca279e7c;hpb=d53bc1c54ceb161850d560c4802daeccd86a4714 diff --git a/newdungeon.py b/newdungeon.py index 6f95bb4..d1ea21c 100755 --- a/newdungeon.py +++ b/newdungeon.py @@ -8,7 +8,7 @@ # movement rules to the travel array that's actually used by # playermove(). This program first compiles the YAML to a form # identical to the data in section 3 of the old adventure.text file, -# then a second stage packs that data into the travel array. +# then a second stage unpacks that data into the travel array. # # Here are the rules of the intermediate form: # @@ -85,12 +85,19 @@ h_template = """/* Generated from adventure.yaml - do not hand-hack! */ #define COND_HJADE 20 /* Found all treasures except jade */ typedef struct {{ + const char** strs; + const int n; +}} string_group_t; + +typedef struct {{ + const string_group_t words; const char* inventory; int plac, fixd; bool is_treasure; - const char** longs; + const char** descriptions; const char** sounds; const char** texts; + const char** changes; }} object_t; typedef struct {{ @@ -129,14 +136,32 @@ typedef struct {{ }} hint_t; typedef struct {{ - const char** words; + const string_group_t words; }} motion_t; typedef struct {{ - const char** words; + const string_group_t words; const long message; }} action_t; +typedef struct {{ + const long motion; + const long dest; + const bool stop; +}} travelop_t; + +/* Abstract out the encoding of words in the travel array. Gives us + * some hope of getting to a less cryptic representation than we + * inherited from FORTRAN, someday. To understand these, read the + * encoding description for travel. + */ +#define T_DESTINATION(entry) MOD((entry).dest, 1000) +#define T_CONDITION(entry) ((entry).dest / 1000) +#define T_NODWARVES(entry) (T_CONDITION(entry) == 100) +#define T_HIGH(entry) ((entry).dest) +#define T_TERMINATE(entry) ((entry).motion == 1) +#define L_SPEAK(loc) ((loc) - 500) + extern const location_t locations[]; extern const object_t objects[]; extern const char* arbitrary_messages[]; @@ -147,7 +172,8 @@ extern const hint_t hints[]; extern long conditions[]; extern const motion_t motions[]; extern const action_t actions[]; -extern const long travel[]; +extern const action_t specials[]; +extern const travelop_t travel[]; extern const long tkey[]; #define NLOCATIONS {} @@ -156,7 +182,9 @@ extern const long tkey[]; #define NCLASSES {} #define NDEATHS {} #define NTHRESHOLDS {} +#define NMOTIONS {} #define NACTIONS {} +#define NSPECIALS {} #define NTRAVEL {} #define NKEYS {} @@ -180,6 +208,10 @@ enum action_refs {{ {} }}; +enum special_refs {{ +{} +}}; + /* State definitions */ {} @@ -231,9 +263,15 @@ const action_t actions[] = {{ {} }}; +const action_t specials[] = {{ +{} +}}; + {} +const travelop_t travel[] = {{ {} +}}; /* end */ """ @@ -257,6 +295,19 @@ def get_refs(l): ref_str = ref_str[:-1] # trim trailing newline return ref_str +def get_string_group(strings): + template = """{{ + .strs = {}, + .n = {}, + }}""" + if strings == []: + strs = "NULL" + else: + strs = "(const char* []) {" + ", ".join([make_c_string(s) for s in strings]) + "}" + n = len(strings) + sg_str = template.format(strs, n) + return sg_str + def get_arbitrary_messages(arb): template = """ {}, """ @@ -318,17 +369,21 @@ def get_locations(loc): def get_objects(obj): template = """ {{ // {} + .words = {}, .inventory = {}, .plac = {}, .fixd = {}, .is_treasure = {}, - .longs = (const char* []) {{ + .descriptions = (const char* []) {{ {} }}, .sounds = (const char* []) {{ {} }}, .texts = (const char* []) {{ +{} + }}, + .changes = (const char* []) {{ {} }}, }}, @@ -336,18 +391,22 @@ def get_objects(obj): obj_str = "" for (i, item) in enumerate(obj): attr = item[1] + try: + words_str = get_string_group(attr["words"]) + except KeyError: + words_str = get_string_group([]) i_msg = make_c_string(attr["inventory"]) - longs_str = "" - if attr["longs"] == None: - longs_str = " " * 12 + "NULL," + descriptions_str = "" + if attr["descriptions"] == None: + descriptions_str = " " * 12 + "NULL," else: labels = [] - for l_msg in attr["longs"]: + for l_msg in attr["descriptions"]: 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 + descriptions_str += " " * 12 + make_c_string(l_msg) + ",\n" + descriptions_str = descriptions_str[:-1] # trim trailing newline if labels: global statedefines statedefines += "/* States for %s */\n" % item[0] @@ -370,6 +429,13 @@ def get_objects(obj): for l_msg in attr["texts"]: texts_str += " " * 12 + make_c_string(l_msg) + ",\n" texts_str = texts_str[:-1] # trim trailing newline + changes_str = "" + if attr.get("changes") == None: + changes_str = " " * 12 + "NULL," + else: + for l_msg in attr["changes"]: + changes_str += " " * 12 + make_c_string(l_msg) + ",\n" + changes_str = changes_str[:-1] # trim trailing newline locs = attr.get("locations", ["LOC_NOWHERE", "LOC_NOWHERE"]) immovable = attr.get("immovable", False) try: @@ -381,7 +447,7 @@ def get_objects(obj): sys.stderr.write("dungeon: unknown object location in %s\n" % locs) sys.exit(1) treasure = "true" if attr.get("treasure") else "false" - obj_str += template.format(i, i_msg, locs[0], locs[1], treasure, longs_str, sounds_str, texts_str) + obj_str += template.format(i, words_str, i_msg, locs[0], locs[1], treasure, descriptions_str, sounds_str, texts_str, changes_str) obj_str = obj_str[:-1] # trim trailing newline return obj_str @@ -462,10 +528,9 @@ def get_motions(motions): for motion in motions: contents = motion[1] if contents["words"] == None: - mot_str += template.format("NULL") - continue - c_words = [make_c_string(s) for s in contents["words"]] - words_str = "(const char* []) {" + ", ".join(c_words) + "}" + words_str = get_string_group([]) + else: + words_str = get_string_group(contents["words"]) mot_str += template.format(words_str) return mot_str @@ -480,10 +545,9 @@ def get_actions(actions): contents = action[1] if contents["words"] == None: - words_str = "NULL" + words_str = get_string_group([]) else: - c_words = [make_c_string(s) for s in contents["words"]] - words_str = "(const char* []) {" + ", ".join(c_words) + "}" + words_str = get_string_group(contents["words"]) if contents["message"] == None: message = "NO_MESSAGE" @@ -548,7 +612,19 @@ def buildtravel(locs, objs, voc): elif cond[0] == "not": # FIXME: Allow named as well as numbered states try: - return 300 + objnames.index(cond[1]) + 100 * cond[2] + obj = objnames.index(cond[1]) + if type(cond[2]) == int: + state = cond[2] + else: + for (i, stateclause) in enumerate(objs[obj][1]["descriptions"]): + if type(stateclause) == list: + if stateclause[0] == cond[2]: + state = i + break + else: + sys.stderr.write("dungeon: unmatched state symbol %s in not clause of %s\n" % (cond[2], name)) + sys.exit(0); + return 300 + obj + 100 * state except ValueError: sys.stderr.write("dungeon: unknown object name %s in not clause of %s\n" % (cond[1], name)) sys.exit(1) @@ -588,7 +664,10 @@ def buildtravel(locs, objs, voc): # } # TRAVEL[TRVS - 1] = -TRAVEL[TRVS - 1]; # } - travel = [0] + # + # In order to de-crypticize the runtime code, we're going to break these + # magic numbers up into a struct. + travel = [[0, 0, False]] tkey = [0] oldloc = 0 while ltravel: @@ -598,13 +677,26 @@ def buildtravel(locs, objs, voc): if loc != oldloc: tkey.append(len(travel)) oldloc = loc - if travel: - travel[-1] *= -1 + elif travel: + travel[-1][2] = not travel[-1][2] while rule: - travel.append(rule.pop(0) + newloc * 1000) - travel[-1] *= -1 + travel.append([rule.pop(0), newloc, False]) + travel[-1][2] = True return (travel, tkey) +def get_travel(travel): + template = """ {{ + .motion = {}, + .dest = {}, + .stop = {}, + }}, +""" + out = "" + for entry in travel: + out += template.format(entry[0], entry[1], entry[2]).lower() + out = out[:-1] # trim trailing newline + return out + if __name__ == "__main__": with open(yaml_name, "r") as f: db = yaml.load(f) @@ -629,8 +721,9 @@ if __name__ == "__main__": get_condbits(db["locations"]), get_motions(db["motions"]), get_actions(db["actions"]), + get_actions(db["specials"]), "const long tkey[] = {%s};" % bigdump(tkey), - "const long travel[] = {%s};" % bigdump(travel), + get_travel(travel), ) h = h_template.format( @@ -640,7 +733,9 @@ if __name__ == "__main__": len(db["classes"])-1, len(db["obituaries"]), len(db["turn_thresholds"]), + len(db["motions"]), len(db["actions"]), + len(db["specials"]), len(travel), len(tkey), get_refs(db["arbitrary_messages"]), @@ -648,6 +743,7 @@ if __name__ == "__main__": get_refs(db["objects"]), get_refs(db["motions"]), get_refs(db["actions"]), + get_refs(db["specials"]), statedefines, )