about summary refs log tree commit diff stats
path: root/src/game_data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game_data.cpp')
-rw-r--r--src/game_data.cpp604
1 files changed, 326 insertions, 278 deletions
diff --git a/src/game_data.cpp b/src/game_data.cpp index e15847e..8c6dd26 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -5,6 +5,8 @@
5 5
6#include <iostream> 6#include <iostream>
7 7
8namespace {
9
8LingoColor GetColorForString(const std::string &str) { 10LingoColor GetColorForString(const std::string &str) {
9 if (str == "black") { 11 if (str == "black") {
10 return LingoColor::kBlack; 12 return LingoColor::kBlack;
@@ -30,377 +32,423 @@ LingoColor GetColorForString(const std::string &str) {
30 } 32 }
31} 33}
32 34
33GameData::GameData() { 35struct GameData {
34 YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml"); 36 std::vector<Room> rooms_;
35 YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml"); 37 std::vector<Door> doors_;
38 std::vector<Panel> panels_;
39 std::vector<MapArea> map_areas_;
36 40
37 rooms_.reserve(lingo_config.size() * 2); 41 std::map<std::string, int> room_by_id_;
42 std::map<std::string, int> door_by_id_;
43 std::map<std::string, int> panel_by_id_;
44 std::map<std::string, int> area_by_id_;
38 45
39 for (const auto &room_it : lingo_config) { 46 std::map<std::string, int> room_by_painting_;
40 int room_id = AddOrGetRoom(room_it.first.as<std::string>());
41 Room &room_obj = rooms_[room_id];
42 47
43 for (const auto &entrance_it : room_it.second["entrances"]) { 48 std::vector<int> achievement_panels_;
44 int from_room_id = AddOrGetRoom(entrance_it.first.as<std::string>());
45 Room &from_room_obj = rooms_[from_room_id];
46 49
47 switch (entrance_it.second.Type()) { 50 GameData() {
48 case YAML::NodeType::Scalar: { 51 YAML::Node lingo_config = YAML::LoadFile("assets/LL1.yaml");
49 // This is just "true". 52 YAML::Node areas_config = YAML::LoadFile("assets/areas.yaml");
50 from_room_obj.exits.push_back({.destination_room = room_id});
51 break;
52 }
53 case YAML::NodeType::Map: {
54 Exit exit_obj;
55 exit_obj.destination_room = room_id;
56
57 if (entrance_it.second["door"]) {
58 std::string door_room = room_obj.name;
59 if (entrance_it.second["room"]) {
60 door_room = entrance_it.second["room"].as<std::string>();
61 }
62 exit_obj.door = AddOrGetDoor(
63 door_room, entrance_it.second["door"].as<std::string>());
64 }
65 53
66 if (entrance_it.second["painting"]) { 54 rooms_.reserve(lingo_config.size() * 2);
67 exit_obj.painting = entrance_it.second["painting"].as<bool>();
68 }
69 55
70 from_room_obj.exits.push_back(exit_obj); 56 for (const auto &room_it : lingo_config) {
71 break; 57 int room_id = AddOrGetRoom(room_it.first.as<std::string>());
72 } 58 Room &room_obj = rooms_[room_id];
73 case YAML::NodeType::Sequence: { 59
74 for (const auto &option : entrance_it.second) { 60 for (const auto &entrance_it : room_it.second["entrances"]) {
61 int from_room_id = AddOrGetRoom(entrance_it.first.as<std::string>());
62 Room &from_room_obj = rooms_[from_room_id];
63
64 switch (entrance_it.second.Type()) {
65 case YAML::NodeType::Scalar: {
66 // This is just "true".
67 from_room_obj.exits.push_back({.destination_room = room_id});
68 break;
69 }
70 case YAML::NodeType::Map: {
75 Exit exit_obj; 71 Exit exit_obj;
76 exit_obj.destination_room = room_id; 72 exit_obj.destination_room = room_id;
77 73
78 std::string door_room = room_obj.name; 74 if (entrance_it.second["door"]) {
79 if (option["room"]) { 75 std::string door_room = room_obj.name;
80 door_room = option["room"].as<std::string>(); 76 if (entrance_it.second["room"]) {
77 door_room = entrance_it.second["room"].as<std::string>();
78 }
79 exit_obj.door = AddOrGetDoor(
80 door_room, entrance_it.second["door"].as<std::string>());
81 } 81 }
82 exit_obj.door =
83 AddOrGetDoor(door_room, option["door"].as<std::string>());
84 82
85 if (option["painting"]) { 83 if (entrance_it.second["painting"]) {
86 exit_obj.painting = option["painting"].as<bool>(); 84 exit_obj.painting = entrance_it.second["painting"].as<bool>();
87 } 85 }
88 86
89 from_room_obj.exits.push_back(exit_obj); 87 from_room_obj.exits.push_back(exit_obj);
88 break;
90 } 89 }
90 case YAML::NodeType::Sequence: {
91 for (const auto &option : entrance_it.second) {
92 Exit exit_obj;
93 exit_obj.destination_room = room_id;
94
95 std::string door_room = room_obj.name;
96 if (option["room"]) {
97 door_room = option["room"].as<std::string>();
98 }
99 exit_obj.door =
100 AddOrGetDoor(door_room, option["door"].as<std::string>());
91 101
92 break; 102 if (option["painting"]) {
93 } 103 exit_obj.painting = option["painting"].as<bool>();
94 default: { 104 }
95 // This shouldn't happen.
96 std::cout << "Error reading game data: " << entrance_it << std::endl;
97 break;
98 }
99 }
100 }
101 105
102 if (room_it.second["panels"]) { 106 from_room_obj.exits.push_back(exit_obj);
103 for (const auto &panel_it : room_it.second["panels"]) {
104 int panel_id =
105 AddOrGetPanel(room_obj.name, panel_it.first.as<std::string>());
106 Panel &panel_obj = panels_[panel_id];
107
108 if (panel_it.second["colors"]) {
109 if (panel_it.second["colors"].IsScalar()) {
110 panel_obj.colors.push_back(
111 GetColorForString(panel_it.second["colors"].as<std::string>()));
112 } else {
113 for (const auto &color_node : panel_it.second["colors"]) {
114 panel_obj.colors.push_back(
115 GetColorForString(color_node.as<std::string>()));
116 } 107 }
108
109 break;
110 }
111 default: {
112 // This shouldn't happen.
113 std::cout << "Error reading game data: " << entrance_it
114 << std::endl;
115 break;
117 } 116 }
118 } 117 }
118 }
119 119
120 if (panel_it.second["required_room"]) { 120 if (room_it.second["panels"]) {
121 if (panel_it.second["required_room"].IsScalar()) { 121 for (const auto &panel_it : room_it.second["panels"]) {
122 panel_obj.required_rooms.push_back(AddOrGetRoom( 122 int panel_id =
123 panel_it.second["required_room"].as<std::string>())); 123 AddOrGetPanel(room_obj.name, panel_it.first.as<std::string>());
124 } else { 124 Panel &panel_obj = panels_[panel_id];
125 for (const auto &rr_node : panel_it.second["required_room"]) { 125
126 panel_obj.required_rooms.push_back( 126 if (panel_it.second["colors"]) {
127 AddOrGetRoom(rr_node.as<std::string>())); 127 if (panel_it.second["colors"].IsScalar()) {
128 panel_obj.colors.push_back(GetColorForString(
129 panel_it.second["colors"].as<std::string>()));
130 } else {
131 for (const auto &color_node : panel_it.second["colors"]) {
132 panel_obj.colors.push_back(
133 GetColorForString(color_node.as<std::string>()));
134 }
128 } 135 }
129 } 136 }
130 }
131 137
132 if (panel_it.second["required_door"]) { 138 if (panel_it.second["required_room"]) {
133 if (panel_it.second["required_door"].IsMap()) { 139 if (panel_it.second["required_room"].IsScalar()) {
134 std::string rd_room = room_obj.name; 140 panel_obj.required_rooms.push_back(AddOrGetRoom(
135 if (panel_it.second["required_door"]["room"]) { 141 panel_it.second["required_room"].as<std::string>()));
136 rd_room = 142 } else {
137 panel_it.second["required_door"]["room"].as<std::string>(); 143 for (const auto &rr_node : panel_it.second["required_room"]) {
144 panel_obj.required_rooms.push_back(
145 AddOrGetRoom(rr_node.as<std::string>()));
146 }
138 } 147 }
148 }
139 149
140 panel_obj.required_doors.push_back(AddOrGetDoor( 150 if (panel_it.second["required_door"]) {
141 rd_room, 151 if (panel_it.second["required_door"].IsMap()) {
142 panel_it.second["required_door"]["door"].as<std::string>()));
143 } else {
144 for (const auto &rr_node : panel_it.second["required_door"]) {
145 std::string rd_room = room_obj.name; 152 std::string rd_room = room_obj.name;
146 if (rr_node["room"]) { 153 if (panel_it.second["required_door"]["room"]) {
147 rd_room = rr_node["room"].as<std::string>(); 154 rd_room =
155 panel_it.second["required_door"]["room"].as<std::string>();
148 } 156 }
149 157
150 panel_obj.required_doors.push_back( 158 panel_obj.required_doors.push_back(AddOrGetDoor(
151 AddOrGetDoor(rd_room, rr_node["door"].as<std::string>())); 159 rd_room,
160 panel_it.second["required_door"]["door"].as<std::string>()));
161 } else {
162 for (const auto &rr_node : panel_it.second["required_door"]) {
163 std::string rd_room = room_obj.name;
164 if (rr_node["room"]) {
165 rd_room = rr_node["room"].as<std::string>();
166 }
167
168 panel_obj.required_doors.push_back(
169 AddOrGetDoor(rd_room, rr_node["door"].as<std::string>()));
170 }
152 } 171 }
153 } 172 }
154 }
155 173
156 if (panel_it.second["check"]) { 174 if (panel_it.second["check"]) {
157 panel_obj.check = panel_it.second["check"].as<bool>(); 175 panel_obj.check = panel_it.second["check"].as<bool>();
158 } 176 }
159 177
160 if (panel_it.second["achievement"]) { 178 if (panel_it.second["achievement"]) {
161 panel_obj.achievement = panel_it.second["achievement"].as<bool>(); 179 panel_obj.achievement = panel_it.second["achievement"].as<bool>();
162 180
163 if (panel_obj.achievement) { 181 if (panel_obj.achievement) {
164 achievement_panels_.push_back(panel_id); 182 achievement_panels_.push_back(panel_id);
183 }
165 } 184 }
166 }
167 185
168 if (panel_it.second["exclude_reduce"]) { 186 if (panel_it.second["exclude_reduce"]) {
169 panel_obj.exclude_reduce = 187 panel_obj.exclude_reduce =
170 panel_it.second["exclude_reduce"].as<bool>(); 188 panel_it.second["exclude_reduce"].as<bool>();
189 }
171 } 190 }
172 } 191 }
173 }
174 192
175 if (room_it.second["doors"]) { 193 if (room_it.second["doors"]) {
176 for (const auto &door_it : room_it.second["doors"]) { 194 for (const auto &door_it : room_it.second["doors"]) {
177 int door_id = 195 int door_id =
178 AddOrGetDoor(room_obj.name, door_it.first.as<std::string>()); 196 AddOrGetDoor(room_obj.name, door_it.first.as<std::string>());
179 Door &door_obj = doors_[door_id]; 197 Door &door_obj = doors_[door_id];
180 198
181 bool has_external_panels = false; 199 bool has_external_panels = false;
182 std::vector<std::string> panel_names; 200 std::vector<std::string> panel_names;
183 201
184 for (const auto &panel_node : door_it.second["panels"]) { 202 for (const auto &panel_node : door_it.second["panels"]) {
185 if (panel_node.IsScalar()) { 203 if (panel_node.IsScalar()) {
186 panel_names.push_back(panel_node.as<std::string>()); 204 panel_names.push_back(panel_node.as<std::string>());
187 door_obj.panels.push_back( 205 door_obj.panels.push_back(
188 AddOrGetPanel(room_obj.name, panel_node.as<std::string>())); 206 AddOrGetPanel(room_obj.name, panel_node.as<std::string>()));
189 } else { 207 } else {
190 has_external_panels = true; 208 has_external_panels = true;
191 panel_names.push_back(panel_node["panel"].as<std::string>()); 209 panel_names.push_back(panel_node["panel"].as<std::string>());
192 door_obj.panels.push_back( 210 door_obj.panels.push_back(
193 AddOrGetPanel(panel_node["room"].as<std::string>(), 211 AddOrGetPanel(panel_node["room"].as<std::string>(),
194 panel_node["panel"].as<std::string>())); 212 panel_node["panel"].as<std::string>()));
213 }
195 } 214 }
196 }
197 215
198 if (door_it.second["skip_location"]) { 216 if (door_it.second["skip_location"]) {
199 door_obj.skip_location = door_it.second["skip_location"].as<bool>(); 217 door_obj.skip_location = door_it.second["skip_location"].as<bool>();
200 } 218 }
201 219
202 if (door_it.second["skip_item"]) { 220 if (door_it.second["skip_item"]) {
203 door_obj.skip_item = door_it.second["skip_item"].as<bool>(); 221 door_obj.skip_item = door_it.second["skip_item"].as<bool>();
204 } 222 }
205 223
206 if (door_it.second["event"]) { 224 if (door_it.second["event"]) {
207 door_obj.skip_location = door_it.second["event"].as<bool>(); 225 door_obj.skip_location = door_it.second["event"].as<bool>();
208 door_obj.skip_item = door_it.second["event"].as<bool>(); 226 door_obj.skip_item = door_it.second["event"].as<bool>();
209 } 227 }
210 228
211 if (door_it.second["item_name"]) { 229 if (door_it.second["item_name"]) {
212 door_obj.item_name = door_it.second["item_name"].as<std::string>(); 230 door_obj.item_name = door_it.second["item_name"].as<std::string>();
213 } else if (!door_it.second["skip_item"] && !door_it.second["event"]) { 231 } else if (!door_it.second["skip_item"] && !door_it.second["event"]) {
214 door_obj.item_name = room_obj.name + " - " + door_obj.name; 232 door_obj.item_name = room_obj.name + " - " + door_obj.name;
215 } 233 }
216 234
217 if (door_it.second["group"]) { 235 if (door_it.second["group"]) {
218 door_obj.group_name = door_it.second["group"].as<std::string>(); 236 door_obj.group_name = door_it.second["group"].as<std::string>();
219 } 237 }
238
239 if (door_it.second["location_name"]) {
240 door_obj.location_name =
241 door_it.second["location_name"].as<std::string>();
242 } else if (!door_it.second["skip_location"] &&
243 !door_it.second["event"]) {
244 if (has_external_panels) {
245 std::cout
246 << room_obj.name << " - " << door_obj.name
247 << " has panels from other rooms but does not have an "
248 "explicit "
249 "location name and is not marked skip_location or event"
250 << std::endl;
251 }
220 252
221 if (door_it.second["location_name"]) { 253 door_obj.location_name =
222 door_obj.location_name = 254 room_obj.name + " - " + hatkirby::implode(panel_names, ", ");
223 door_it.second["location_name"].as<std::string>();
224 } else if (!door_it.second["skip_location"] &&
225 !door_it.second["event"]) {
226 if (has_external_panels) {
227 std::cout
228 << room_obj.name << " - " << door_obj.name
229 << " has panels from other rooms but does not have an explicit "
230 "location name and is not marked skip_location or event"
231 << std::endl;
232 } 255 }
233 256
234 door_obj.location_name = 257 if (door_it.second["include_reduce"]) {
235 room_obj.name + " - " + hatkirby::implode(panel_names, ", "); 258 door_obj.exclude_reduce =
259 !door_it.second["include_reduce"].as<bool>();
260 }
236 } 261 }
262 }
237 263
238 if (door_it.second["include_reduce"]) { 264 if (room_it.second["paintings"]) {
239 door_obj.exclude_reduce = 265 for (const auto &painting : room_it.second["paintings"]) {
240 !door_it.second["include_reduce"].as<bool>(); 266 std::string painting_id = painting["id"].as<std::string>();
267 room_by_painting_[painting_id] = room_id;
268
269 if (!painting["exit_only"] || !painting["exit_only"].as<bool>()) {
270 PaintingExit painting_exit;
271 painting_exit.id = painting_id;
272
273 if (painting["required_door"]) {
274 std::string rd_room = room_obj.name;
275 if (painting["required_door"]["room"]) {
276 rd_room = painting["required_door"]["room"].as<std::string>();
277 }
278
279 painting_exit.door = AddOrGetDoor(
280 rd_room, painting["required_door"]["door"].as<std::string>());
281 }
282
283 room_obj.paintings.push_back(painting_exit);
284 }
241 } 285 }
242 } 286 }
243 }
244 287
245 if (room_it.second["paintings"]) { 288 if (room_it.second["progression"]) {
246 for (const auto &painting : room_it.second["paintings"]) { 289 for (const auto &progression_it : room_it.second["progression"]) {
247 std::string painting_id = painting["id"].as<std::string>(); 290 std::string progressive_item_name =
248 room_by_painting_[painting_id] = room_id; 291 progression_it.first.as<std::string>();
249 292
250 if (!painting["exit_only"] || !painting["exit_only"].as<bool>()) { 293 int index = 1;
251 PaintingExit painting_exit; 294 for (const auto &stage : progression_it.second) {
252 painting_exit.id = painting_id; 295 int door_id = -1;
253 296
254 if (painting["required_door"]) { 297 if (stage.IsScalar()) {
255 std::string rd_room = room_obj.name; 298 door_id = AddOrGetDoor(room_obj.name, stage.as<std::string>());
256 if (painting["required_door"]["room"]) { 299 } else {
257 rd_room = painting["required_door"]["room"].as<std::string>(); 300 door_id = AddOrGetDoor(stage["room"].as<std::string>(),
301 stage["door"].as<std::string>());
258 } 302 }
259 303
260 painting_exit.door = AddOrGetDoor( 304 doors_[door_id].progressives.push_back(
261 rd_room, painting["required_door"]["door"].as<std::string>()); 305 {.item_name = progressive_item_name, .quantity = index});
306 index++;
262 } 307 }
263
264 room_obj.paintings.push_back(painting_exit);
265 } 308 }
266 } 309 }
267 } 310 }
268 311
269 if (room_it.second["progression"]) { 312 map_areas_.reserve(areas_config.size());
270 for (const auto &progression_it : room_it.second["progression"]) { 313
271 std::string progressive_item_name = 314 std::map<std::string, int> fold_areas;
272 progression_it.first.as<std::string>(); 315 for (const auto &area_it : areas_config) {
316 if (area_it.second["map"]) {
317 int area_id = AddOrGetArea(area_it.first.as<std::string>());
318 MapArea &area_obj = map_areas_[area_id];
319 area_obj.map_x = area_it.second["map"][0].as<int>();
320 area_obj.map_y = area_it.second["map"][1].as<int>();
321 } else if (area_it.second["fold_into"]) {
322 fold_areas[area_it.first.as<std::string>()] =
323 AddOrGetArea(area_it.second["fold_into"].as<std::string>());
324 }
325 }
273 326
274 int index = 1; 327 for (const Panel &panel : panels_) {
275 for (const auto &stage : progression_it.second) { 328 if (panel.check) {
276 int door_id = -1; 329 int room_id = panel.room;
330 std::string room_name = rooms_[room_id].name;
277 331
278 if (stage.IsScalar()) { 332 std::string area_name = room_name;
279 door_id = AddOrGetDoor(room_obj.name, stage.as<std::string>()); 333 if (fold_areas.count(room_name)) {
280 } else { 334 int fold_area_id = fold_areas[room_name];
281 door_id = AddOrGetDoor(stage["room"].as<std::string>(), 335 area_name = map_areas_[fold_area_id].name;
282 stage["door"].as<std::string>()); 336 }
283 } 337
338 int area_id = AddOrGetArea(area_name);
339 MapArea &map_area = map_areas_[area_id];
340 // room field should be the original room ID
341 map_area.locations.push_back(
342 {.name = panel.name,
343 .ap_location_name = room_name + " - " + panel.name,
344 .room = panel.room,
345 .panels = {panel.id}});
346 }
347 }
348
349 for (const Door &door : doors_) {
350 if (!door.skip_location) {
351 int room_id = door.room;
352 std::string area_name = rooms_[room_id].name;
353 std::string section_name;
354
355 size_t divider_pos = door.location_name.find(" - ");
356 if (divider_pos == std::string::npos) {
357 section_name = door.location_name;
358 } else {
359 area_name = door.location_name.substr(0, divider_pos);
360 section_name = door.location_name.substr(divider_pos + 3);
361 }
284 362
285 doors_[door_id].progressives.push_back( 363 if (fold_areas.count(area_name)) {
286 {.item_name = progressive_item_name, .quantity = index}); 364 int fold_area_id = fold_areas[area_name];
287 index++; 365 area_name = map_areas_[fold_area_id].name;
288 } 366 }
367
368 int area_id = AddOrGetArea(area_name);
369 MapArea &map_area = map_areas_[area_id];
370 // room field should be the original room ID
371 map_area.locations.push_back({.name = section_name,
372 .ap_location_name = door.location_name,
373 .room = door.room,
374 .panels = door.panels});
289 } 375 }
290 } 376 }
291 } 377 }
292 378
293 map_areas_.reserve(areas_config.size()); 379 int AddOrGetRoom(std::string room) {
294 380 if (!room_by_id_.count(room)) {
295 std::map<std::string, int> fold_areas; 381 room_by_id_[room] = rooms_.size();
296 for (const auto &area_it : areas_config) { 382 rooms_.push_back({.name = room});
297 if (area_it.second["map"]) {
298 int area_id = AddOrGetArea(area_it.first.as<std::string>());
299 MapArea &area_obj = map_areas_[area_id];
300 area_obj.map_x = area_it.second["map"][0].as<int>();
301 area_obj.map_y = area_it.second["map"][1].as<int>();
302 } else if (area_it.second["fold_into"]) {
303 fold_areas[area_it.first.as<std::string>()] =
304 AddOrGetArea(area_it.second["fold_into"].as<std::string>());
305 } 383 }
306 }
307 384
308 for (const Panel &panel : panels_) { 385 return room_by_id_[room];
309 if (panel.check) { 386 }
310 int room_id = panel.room;
311 std::string room_name = rooms_[room_id].name;
312 387
313 std::string area_name = room_name; 388 int AddOrGetDoor(std::string room, std::string door) {
314 if (fold_areas.count(room_name)) { 389 std::string full_name = room + " - " + door;
315 int fold_area_id = fold_areas[room_name];
316 area_name = map_areas_[fold_area_id].name;
317 }
318 390
319 int area_id = AddOrGetArea(area_name); 391 if (!door_by_id_.count(full_name)) {
320 MapArea &map_area = map_areas_[area_id]; 392 door_by_id_[full_name] = doors_.size();
321 // room field should be the original room ID 393 doors_.push_back({.room = AddOrGetRoom(room), .name = door});
322 map_area.locations.push_back(
323 {.name = panel.name,
324 .ap_location_name = room_name + " - " + panel.name,
325 .room = panel.room,
326 .panels = {panel.id}});
327 } 394 }
328 }
329 395
330 for (const Door &door : doors_) { 396 return door_by_id_[full_name];
331 if (!door.skip_location) { 397 }
332 int room_id = door.room;
333 std::string area_name = rooms_[room_id].name;
334 std::string section_name;
335
336 size_t divider_pos = door.location_name.find(" - ");
337 if (divider_pos == std::string::npos) {
338 section_name = door.location_name;
339 } else {
340 area_name = door.location_name.substr(0, divider_pos);
341 section_name = door.location_name.substr(divider_pos + 3);
342 }
343 398
344 if (fold_areas.count(area_name)) { 399 int AddOrGetPanel(std::string room, std::string panel) {
345 int fold_area_id = fold_areas[area_name]; 400 std::string full_name = room + " - " + panel;
346 area_name = map_areas_[fold_area_id].name;
347 }
348 401
349 int area_id = AddOrGetArea(area_name); 402 if (!panel_by_id_.count(full_name)) {
350 MapArea &map_area = map_areas_[area_id]; 403 int panel_id = panels_.size();
351 // room field should be the original room ID 404 panel_by_id_[full_name] = panel_id;
352 map_area.locations.push_back({.name = section_name, 405 panels_.push_back(
353 .ap_location_name = door.location_name, 406 {.id = panel_id, .room = AddOrGetRoom(room), .name = panel});
354 .room = door.room,
355 .panels = door.panels});
356 } 407 }
408
409 return panel_by_id_[full_name];
357 } 410 }
358}
359 411
360int GameData::AddOrGetRoom(std::string room) { 412 int AddOrGetArea(std::string area) {
361 if (!room_by_id_.count(room)) { 413 if (!area_by_id_.count(area)) {
362 room_by_id_[room] = rooms_.size(); 414 int area_id = map_areas_.size();
363 rooms_.push_back({.name = room}); 415 area_by_id_[area] = area_id;
416 map_areas_.push_back({.id = area_id, .name = area});
417 }
418
419 return area_by_id_[area];
364 } 420 }
421};
365 422
366 return room_by_id_[room]; 423GameData &GetState() {
424 static GameData *instance = new GameData();
425 return *instance;
367} 426}
368 427
369int GameData::AddOrGetDoor(std::string room, std::string door) { 428} // namespace
370 std::string full_name = room + " - " + door;
371 429
372 if (!door_by_id_.count(full_name)) { 430const std::vector<MapArea> &GD_GetMapAreas() { return GetState().map_areas_; }
373 door_by_id_[full_name] = doors_.size(); 431
374 doors_.push_back({.room = AddOrGetRoom(room), .name = door}); 432const MapArea &GD_GetMapArea(int id) { return GetState().map_areas_.at(id); }
375 }
376 433
377 return door_by_id_[full_name]; 434int GD_GetRoomByName(const std::string &name) {
435 return GetState().room_by_id_.at(name);
378} 436}
379 437
380int GameData::AddOrGetPanel(std::string room, std::string panel) { 438const Room &GD_GetRoom(int room_id) { return GetState().rooms_.at(room_id); }
381 std::string full_name = room + " - " + panel;
382 439
383 if (!panel_by_id_.count(full_name)) { 440const std::vector<Door> &GD_GetDoors() { return GetState().doors_; }
384 int panel_id = panels_.size();
385 panel_by_id_[full_name] = panel_id;
386 panels_.push_back(
387 {.id = panel_id, .room = AddOrGetRoom(room), .name = panel});
388 }
389 441
390 return panel_by_id_[full_name]; 442const Door &GD_GetDoor(int door_id) { return GetState().doors_.at(door_id); }
391}
392 443
393int GameData::AddOrGetArea(std::string area) { 444const Panel &GD_GetPanel(int panel_id) {
394 if (!area_by_id_.count(area)) { 445 return GetState().panels_.at(panel_id);
395 int area_id = map_areas_.size(); 446}
396 area_by_id_[area] = area_id;
397 map_areas_.push_back({.id = area_id, .name = area});
398 }
399 447
400 return area_by_id_[area]; 448int GD_GetRoomForPainting(const std::string &painting_id) {
449 return GetState().room_by_painting_.at(painting_id);
401} 450}
402 451
403const GameData &GetGameData() { 452const std::vector<int> &GD_GetAchievementPanels() {
404 static GameData *instance = new GameData(); 453 return GetState().achievement_panels_;
405 return *instance;
406} 454}