f8ef9571abd0bc897aa2145041c3d3f646e49f2c
[open-adventure.git] / newdungeon.py
1 #!/usr/bin/python3
2
3 # This is the new open-adventure dungeon generator. It'll eventually replace the existing dungeon.c It currently outputs a .h and .c pair for C code.
4
5 import yaml
6
7 yaml_name = "adventure.yaml"
8 h_name = "newdb.h"
9 c_name = "newdb.c"
10
11 h_template = """#include <stdio.h>
12
13 typedef struct {{
14   const char* inventory;
15   const char** longs;
16 }} object_description_t;
17
18 typedef struct {{
19   const char* small;
20   const char* big;
21 }} descriptions_t;
22
23 typedef struct {{
24   descriptions_t description;
25 }} location_t;
26
27 typedef struct {{
28   const char* query;
29   const char* yes_response;
30 }} obituary_t;
31
32 typedef struct {{
33   const int threshold;
34   const int point_loss;
35   const char* message;
36 }} turn_threshold_t;
37
38 typedef struct {{
39   const int threshold;
40   const char* message;
41 }} class_t;
42
43 extern location_t locations[];
44 extern object_description_t object_descriptions[];
45 extern const char* arbitrary_messages[];
46 extern const class_t classes[];
47 extern turn_threshold_t turn_thresholds[];
48 extern obituary_t obituaries[];
49
50 extern size_t CLSSES;
51 extern int maximum_deaths;
52 extern int turn_threshold_count;
53
54 enum arbitrary_messages_refs {{
55 {}
56 }};
57
58 enum locations_refs {{
59 {}
60 }};
61
62 enum object_descriptions_refs {{
63 {}
64 }};
65 """
66
67 c_template = """#include "{}"
68
69 const char* arbitrary_messages[] = {{
70 {}
71 }};
72
73 const class_t classes[] = {{
74 {}
75 }};
76
77 turn_threshold_t turn_thresholds[] = {{
78 {}
79 }};
80
81 location_t locations[] = {{
82 {}
83 }};
84
85 object_description_t object_descriptions[] = {{
86 {}
87 }};
88
89 obituary_t obituaries[] = {{
90 {}
91 }};
92
93 size_t CLSSES = {};
94 int maximum_deaths = {};
95 int turn_threshold_count = {};
96 """
97
98 def make_c_string(string):
99     """Render a Python string into C string literal format."""
100     if string == None:
101         return "NULL"
102     string = string.replace("\n", "\\n")
103     string = string.replace("\t", "\\t")
104     string = string.replace('"', '\\"')
105     string = string.replace("'", "\\'")
106     string = '"' + string + '"'
107     return string
108
109 def get_refs(l):
110     reflist = [x[0] for x in l]
111     ref_str = ""
112     for ref in reflist:
113         ref_str += "    {},\n".format(ref)
114     ref_str = ref_str[:-1] # trim trailing newline
115     return ref_str
116
117 def get_arbitrary_messages(arb):
118     template = """    {},
119 """
120     arb_str = ""
121     for item in arb:
122         arb_str += template.format(make_c_string(item[1]))
123     arb_str = arb_str[:-1] # trim trailing newline
124     return arb_str
125
126 def get_class_messages(cls):
127     template = """    {{
128         .threshold = {},
129         .message = {},
130     }},
131 """
132     cls_str = ""
133     for item in cls:
134         threshold = item["threshold"]
135         message = make_c_string(item["message"])
136         cls_str += template.format(threshold, message)
137     cls_str = cls_str[:-1] # trim trailing newline
138     return cls_str
139
140 def get_turn_thresholds(trn):
141     template = """    {{
142         .threshold = {},
143         .point_loss = {},
144         .message = {},
145     }},
146 """
147     trn_str = ""
148     for item in trn:
149         threshold = item["threshold"]
150         point_loss = item["point_loss"]
151         message = make_c_string(item["message"])
152         trn_str += template.format(threshold, point_loss, message)
153     trn_str = trn_str[:-1] # trim trailing newline
154     return trn_str
155
156 def get_locations(loc):
157     template = """    {{
158         .description = {{
159             .small = {},
160             .big = {},
161         }},
162     }},
163 """
164     loc_str = ""
165     for item in loc:
166         short_d = make_c_string(item[1]["description"]["short"])
167         long_d = make_c_string(item[1]["description"]["long"])
168         loc_str += template.format(short_d, long_d)
169     loc_str = loc_str[:-1] # trim trailing newline
170     return loc_str
171
172 def get_object_descriptions(obj):
173     template = """    {{
174         .inventory = {},
175         .longs = (const char* []) {{
176 {}
177         }},
178     }},
179 """
180     obj_str = ""
181     for item in obj:
182         i_msg = make_c_string(item[1]["inventory"])
183         longs_str = ""
184         if item[1]["longs"] == None:
185             longs_str = " " * 12 + "NULL,"
186         else:
187             for l_msg in item[1]["longs"]:
188                 longs_str += " " * 12 + make_c_string(l_msg) + ",\n"
189             longs_str = longs_str[:-1] # trim trailing newline
190         obj_str += template.format(i_msg, longs_str)
191     obj_str = obj_str[:-1] # trim trailing newline
192     return obj_str
193
194 def get_obituaries(obit):
195     template = """    {{
196         .query = {},
197         .yes_response = {},
198     }},
199 """
200     obit_str = ""
201     for o in obit:
202         query = make_c_string(o["query"])
203         yes = make_c_string(o["yes_response"])
204         obit_str += template.format(query, yes)
205     obit_str = obit_str[:-1] # trim trailing newline
206     return obit_str
207
208 with open(yaml_name, "r") as f:
209     db = yaml.load(f)
210
211 h = h_template.format(
212     get_refs(db["arbitrary_messages"]),
213     get_refs(db["locations"]),
214     get_refs(db["object_descriptions"]),
215 )
216
217 c = c_template.format(
218     h_name,
219     get_arbitrary_messages(db["arbitrary_messages"]),
220     get_class_messages(db["classes"]),
221     get_turn_thresholds(db["turn_thresholds"]),
222     get_locations(db["locations"]),
223     get_object_descriptions(db["object_descriptions"]),
224     get_obituaries(db["obituaries"]),
225     len(db["classes"]),
226     len(db["obituaries"]),
227     len(db["turn_thresholds"]),
228 )
229
230 with open(h_name, "w") as hf:
231     hf.write(h)
232
233 with open(c_name, "w") as cf:
234     cf.write(c)