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