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