Test coverage -- 100% cheat for real this time
[open-adventure.git] / newdungeon.py
index 52c34e5ff5913e70135fb1a94f07831696c0acea..60625997f907ddc4976fd39b1ce406f5d546637f 100755 (executable)
@@ -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:
 #
@@ -137,6 +137,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,7 +164,7 @@ extern const hint_t hints[];
 extern long conditions[];
 extern const motion_t motions[];
 extern const action_t actions[];
-extern const long travel[];
+extern const travelop_t travel[];
 extern const long tkey[];
 
 #define NLOCATIONS     {}
@@ -233,7 +250,9 @@ const action_t actions[] = {{
 
 {}
 
+const travelop_t travel[] = {{
 {}
+}};
 
 /* end */
 """
@@ -548,7 +567,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]["longs"]):
+                        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 +619,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:
@@ -599,12 +633,25 @@ def buildtravel(locs, objs, voc):
             tkey.append(len(travel))
             oldloc = loc 
         elif travel:
-            travel[-1] *= -1
+            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)
@@ -630,7 +677,7 @@ if __name__ == "__main__":
         get_motions(db["motions"]),
         get_actions(db["actions"]),
         "const long tkey[] = {%s};" % bigdump(tkey),
-        "const long travel[] = {%s};" % bigdump(travel), 
+        get_travel(travel), 
     )
 
     h = h_template.format(