New dungeon compiler to gradually replace the existing one.
[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 json
6 import collections
7
8 json_name = "adventure.json"
9 h_name = "newdb.h"
10 c_name = "newdb.c"
11
12 def c_escape(string):
13     """Add C escape sequences to a string."""
14     string = string.replace("\n", "\\n")
15     string = string.replace("\t", "\\t")
16     string = string.replace('"', '\\"')
17     string = string.replace("'", "\\'")
18     return string
19
20 def write_regular_messages(name, h, c):
21
22     h += "enum {}_refs {{\n".format(name)
23     c += "char* {}[] = {{\n".format(name)
24     
25     index = 0
26     for key, text in dungeon[name].items():
27         h += "  {},\n".format(key)
28         if text == None:
29             c += "  NULL,\n"
30         else:
31             text = c_escape(text)
32             c += "  \"{}\",\n".format(text)
33         
34         index += 1
35         
36     h += "};\n\n"
37     c += "};\n\n"
38     
39     return (h, c)
40
41 with open(json_name, "r") as f:
42     dungeon = json.load(f, object_pairs_hook = collections.OrderedDict)
43
44 h = """#include <stdio.h>
45
46 typedef struct {
47   char* inventory;
48   char** longs;
49 } object_description_t;
50
51 extern char* long_location_descriptions[];
52 extern char* short_location_descriptions[];
53 extern object_description_t object_descriptions[];
54 extern char* arbitrary_messages[];
55 extern char* class_messages[];
56 extern char* turn_threshold_messages[];
57
58 extern size_t CLSSES;
59
60 """
61
62 c = """#include "{}"
63
64 """.format(h_name)
65
66 for name in [
67         "arbitrary_messages",
68         "long_location_descriptions",
69         "short_location_descriptions",
70         "class_messages",
71         "turn_threshold_messages",
72 ]:
73     h, c = write_regular_messages(name, h, c)
74
75 h += "enum object_descriptions_refs {\n"
76 c += "object_description_t object_descriptions[] = {\n"
77 for key, data in dungeon["object_descriptions"].items():
78     try:
79         data["inventory"] = "\"{}\"".format(c_escape(data["inventory"]))
80     except AttributeError:
81         data["inventory"] = "NULL"
82     h += "  {},\n".format(key)
83     c += "  {\n"
84     c += "    .inventory = {},\n".format(data["inventory"])
85     try:
86         data["longs"][0]
87         c += "    .longs = (char* []) {\n"
88         for l in data["longs"]:
89             l = c_escape(l)
90             c += "      \"{}\"\n".format(l)
91         c += "    },\n"
92     except (TypeError, IndexError):
93         c += "    .longs = NULL,\n"
94     c += "  },\n"
95 h += "};"
96 c += "};"
97
98 d = {
99     h_name: h,
100     c_name: c,
101 }
102 for filename, string in d.items():
103     with open(filename, "w") as f:
104         f.write(string)
105