Check in the tool for folding Section 9 COND bits into YAML.
authorEric S. Raymond <esr@thyrsus.com>
Thu, 22 Jun 2017 13:46:09 +0000 (09:46 -0400)
committerEric S. Raymond <esr@thyrsus.com>
Thu, 22 Jun 2017 13:46:09 +0000 (09:46 -0400)
Needs to be in the repo history for reference, though it won't
be manifest after the conversion.

We shouldn't actually apply this until the murk around FORCED has been
dispelled.

locbit.py [new file with mode: 0755]

diff --git a/locbit.py b/locbit.py
new file mode 100755 (executable)
index 0000000..b50c7ef
--- /dev/null
+++ b/locbit.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python3
+#
+# Enhance adventure.yaml entries with explicit properties based on Section 9
+# of adventure.text and the kludgy macro definitions in advent.h.
+#
+# This script is meant to be gotten right, used once, and then discarded.
+# We'll leave a copy in the repository history for reference 
+#
+# When in doubt, make the code dumber and the data smarter.
+#
+# It bothers me that I don't know why FORCED is checking the fluid bit.
+#
+import sys, yaml
+
+# This is the original location-attribute data from section 9 of adventure.text
+# Bit indices are the first element of each tuple; the remaining numbers are
+# indices of locations with that bit set.
+section12 = (
+    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+    (0, 100, 115, 116, 126, 145, 146, 147, 148, 149, 150),
+    (0, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160),
+    (0, 161, 162, 163, 164, 165, 166, 167),
+    (1, 24),
+    (2, 1, 3, 4, 7, 38, 95, 113, 24, 168, 169),
+    (3, 46, 47, 48, 54, 56, 58, 82, 85, 86),
+    (3, 122, 123, 124, 125, 126, 127, 128, 129, 130),
+    (4, 6, 145, 146, 147, 148, 149, 150, 151, 152),
+    (4, 153, 154, 155, 156, 157, 158, 159, 160, 161),
+    (4, 162, 163, 164, 165, 166, 42, 43, 44, 45),
+    (4, 49, 50, 51, 52, 53, 55, 57, 80, 83),
+    (4, 84, 87, 107, 112, 131, 132, 133, 134, 135),
+    (4, 136, 137, 138, 139, 108),
+    (11, 8),
+    (12, 13),
+    (13, 19),
+    (14, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51),
+    (14, 52, 53, 54, 55, 56, 80, 81, 82, 86, 87),
+    (15, 99, 100, 101),
+    (16, 108),
+    (17, 6),
+    (18, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154),
+    (18, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164),
+    (18, 165, 166),
+    (19, 143),
+    (20, 8, 15, 64, 109, 126),
+)
+
+# Names for attribute bits
+attrnames = (
+    "LIT",     # 0
+    "OILY",    # 1
+    "FLUID",   # 2
+    "NOARRR",  # 3
+    "NOBACK",  # 4
+    "FORCED",  # 5     # New
+    "FOREST",  # 6     # New
+    "ABOVE",   # 7     # New
+    "DEEP",    # 8     # New
+    "",                # 9
+    "HBASE",   # 10
+    "HCAVE",   # 11
+    "HBIRD",   # 12
+    "HSNAKE",  # 13
+    "HMAZE",   # 14
+    "HDARK",   # 15
+    "HWITT",   # 16
+    "HCLIFF",  # 17
+    "HWOODS",  # 18
+    "HOGRE",   # 19
+    "HJADE",   # 20
+)
+
+nlocs = 184
+grate = 8
+misthall = 15
+sapphireloc = 167
+
+# For reference from advent.h:
+#
+# define FORCED(LOC)   (COND[LOC] == 2)
+# define FOREST(LOC)   ((LOC) >= LOC_FOREST1 && (LOC) <= LOC_FOREST22)
+#
+#/*  The following two functions were added to fix a bug (game.clock1 decremented
+# *  while in forest).  They should probably be replaced by using another
+# *  "cond" bit.  For now, however, a quick fix...  OUTSID(LOC) is true if
+# *  LOC is outside, INDEEP(LOC) is true if LOC is "deep" in the cave (hall
+# *  of mists or deeper).  Note special kludges for "Foof!" locs. */
+# define OUTSID(LOC)   ((LOC) <= LOC_GRATE || FOREST(LOC) || (LOC) == PLAC[SAPPH] || (LOC) == LOC_FOOF2 || (LOC) == LOC_FOOF4)
+# define INDEEP(LOC)   ((LOC) >= LOC_MISTHALL && !OUTSID(LOC) && (LOC) != LOC_FOOF1)
+
+def genline(loc):
+    attrs = []
+    name = locnames[loc]
+    for props in section12:
+        if loc in props[1:]:
+            if props[0] not in attrs:
+                attrs.append(props[0])
+    # Adod new attributes.  These are computed the same way as the
+    # INDEEP(), OUTSID(), and FORCED macros in advent.h.
+    # FORCED is on only if COND == 2
+    if attrs == [2]:
+        attrs.append(5)        # FORCED
+    if "FOREST" in name:
+        attrs.append(6)        # FOREST
+    # 167 is the sapphire's start location
+    if loc in range(1, grate+1) or name in ("FOOF2", "FOOF4") or name == sapphireloc:
+        attrs.append(7)        # ABOVE
+    if not loc in range(0, misthall+1) and name != "FOOF1" and 6 not in attrs:
+        attrs.append(8)        # DEEP
+    names = str([attrnames[n] for n in attrs]).replace("'", "")
+    return "    conditions: %s\n" % (names,)
+
+if __name__ == "__main__":
+    with open("adventure.yaml", "r") as fp:
+        db = yaml.load(fp)
+        fp.seek(0)
+        locnames = [el[0] for el in db["locations"]]
+        ln = -1
+        while True:
+            line = fp.readline()
+            if not line:
+                break
+            if line.startswith("- LOC"):
+                if ln > -1:
+                    sys.stdout.write(genline(ln))
+                ln += 1
+            sys.stdout.write(line)
+
+# end