X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=newdungeon.py;h=f2e801f587d91e7735d50ecfa8061cb92663e062;hb=1ed812691287700b4bdf804d782f09f4a0eee0de;hp=a4b230e80faac1cacc98725b3e2df1223e002dcf;hpb=20a645bdf42e494262e897210100d8a1f8f9dd18;p=open-adventure.git diff --git a/newdungeon.py b/newdungeon.py index a4b230e..f2e801f 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: # @@ -88,9 +88,10 @@ typedef struct {{ 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 {{ @@ -137,6 +138,23 @@ typedef struct {{ 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_NODWARVES(entry) ((entry).dest / 1000 == 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,6 +165,8 @@ extern const hint_t hints[]; extern long conditions[]; extern const motion_t motions[]; extern const action_t actions[]; +extern const travelop_t travel[]; +extern const long tkey[]; #define NLOCATIONS {} #define NOBJECTS {} @@ -156,6 +176,7 @@ extern const action_t actions[]; #define NTHRESHOLDS {} #define NACTIONS {} #define NTRAVEL {} +#define NKEYS {} enum arbitrary_messages_refs {{ {} @@ -228,6 +249,12 @@ const action_t actions[] = {{ {} }}; +{} + +const travelop_t travel[] = {{ +{} +}}; + /* end */ """ @@ -315,13 +342,16 @@ def get_objects(obj): .plac = {}, .fixd = {}, .is_treasure = {}, - .longs = (const char* []) {{ + .descriptions = (const char* []) {{ {} }}, .sounds = (const char* []) {{ {} }}, .texts = (const char* []) {{ +{} + }}, + .changes = (const char* []) {{ {} }}, }}, @@ -330,17 +360,17 @@ def get_objects(obj): for (i, item) in enumerate(obj): attr = item[1] 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] @@ -363,6 +393,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: @@ -374,7 +411,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, 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 @@ -446,6 +483,58 @@ def recompose(type_word, value): sys.stderr.write("%s is not a known word classifier\n" % attrs["type"]) sys.exit(1) +def get_motions(motions): + template = """ {{ + .words = {}, + }}, +""" + mot_str = "" + 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) + "}" + mot_str += template.format(words_str) + return mot_str + +def get_actions(actions): + template = """ {{ + .words = {}, + .message = {}, + }}, +""" + act_str = "" + for action in actions: + contents = action[1] + + if contents["words"] == None: + words_str = "NULL" + else: + c_words = [make_c_string(s) for s in contents["words"]] + words_str = "(const char* []) {" + ", ".join(c_words) + "}" + + if contents["message"] == None: + message = "NO_MESSAGE" + else: + message = contents["message"] + + act_str += template.format(words_str, message) + act_str = act_str[:-1] # trim trailing newline + return act_str + +def bigdump(arr): + out = "" + for (i, entry) in enumerate(arr): + if i % 10 == 0: + if out and out[-1] == ' ': + out = out[:-1] + out += "\n " + out += str(arr[i]) + ", " + out = out[:-2] + "\n" + return out + def buildtravel(locs, objs, voc): ltravel = [] verbmap = {} @@ -489,14 +578,26 @@ 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) else: print(cond) raise ValueError - # Much more to be done here + for (i, (name, loc)) in enumerate(locs): if "travel" in loc: for rule in loc["travel"]: @@ -507,58 +608,6 @@ def buildtravel(locs, objs, voc): if not rule["verbs"]: tt.append(1) ltravel.append(tuple(tt)) - return tuple(ltravel) - -def get_motions(motions): - template = """ {{ - .words = {}, - }}, -""" - mot_str = "" - 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) + "}" - mot_str += template.format(words_str) - return mot_str - -def get_actions(actions): - template = """ {{ - .words = {}, - .message = {}, - }}, -""" - act_str = "" - for action in actions: - contents = action[1] - - if contents["words"] == None: - words_str = "NULL" - else: - c_words = [make_c_string(s) for s in contents["words"]] - words_str = "(const char* []) {" + ", ".join(c_words) + "}" - - if contents["message"] == None: - message = "NO_MESSAGE" - else: - message = contents["message"] - - act_str += template.format(words_str, message) - act_str = act_str[:-1] # trim trailing newline - return act_str - -if __name__ == "__main__": - with open(yaml_name, "r") as f: - db = yaml.load(f) - - locnames = [x[0] for x in db["locations"]] - msgnames = [el[0] for el in db["arbitrary_messages"]] - objnames = [el[0] for el in db["objects"]] - - travel = buildtravel(db["locations"], db["objects"], db["vocabulary"]) # At this point the ltravel data is in the Section 3 # representation from the FORTRAN version. Next we perform the @@ -581,6 +630,50 @@ if __name__ == "__main__": # } # TRAVEL[TRVS - 1] = -TRAVEL[TRVS - 1]; # } + # + # 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: + rule = list(ltravel.pop(0)) + loc = rule.pop(0) + newloc = rule.pop(0) + if loc != oldloc: + tkey.append(len(travel)) + oldloc = loc + elif travel: + travel[-1][2] = not travel[-1][2] + while rule: + 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) + + locnames = [x[0] for x in db["locations"]] + msgnames = [el[0] for el in db["arbitrary_messages"]] + objnames = [el[0] for el in db["objects"]] + + (travel, tkey) = buildtravel(db["locations"], + db["objects"], + db["vocabulary"]) c = c_template.format( h_name, @@ -594,6 +687,8 @@ if __name__ == "__main__": get_condbits(db["locations"]), get_motions(db["motions"]), get_actions(db["actions"]), + "const long tkey[] = {%s};" % bigdump(tkey), + get_travel(travel), ) h = h_template.format( @@ -605,6 +700,7 @@ if __name__ == "__main__": len(db["turn_thresholds"]), len(db["actions"]), len(travel), + len(tkey), get_refs(db["arbitrary_messages"]), get_refs(db["locations"]), get_refs(db["objects"]),