1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
#include <csignal>
#include <memory>
#include <filesystem>
#include <pugixml.hpp>
#include <map>
#include "backend/Location.h"
#include "backend/LocationFactory.h"
#include "backend/Dungeon.h"
#include "load_dungeon.h"
#include "Exception.h"
#include "GameData.h"
#include "backend/Object.h"
#include "strings.h"
using namespace std;
using namespace pugi;
unique_ptr<Dungeon> load_dungeon(const string & filename) {
unique_ptr<Dungeon> dungeon = make_unique<Dungeon>();
xml_document doc;
string canonical = filename;
if (canonical.starts_with("~/"))
canonical = getenv("HOME") + canonical.substr(1);
try {
canonical = filesystem::canonical(canonical);
} catch (...) {
throw Exception("Kon bestand niet vinden");
}
xml_parse_result result = doc.load_file(canonical.c_str(), parse_default, encoding_latin1);
if (!result)
throw Exception("Kon XML-bestand niet lezen");
xml_node locations = doc.child("locaties");
if (!locations)
throw Exception("XML-bestand mist een <locaties> tag");
GameData & gamedata = GameData::get_instance();
struct TempData {
Location * location;
unsigned edges[4];
};
map<unsigned, TempData> temp_map;
for (xml_node & tag : locations) {
Location * location = LocationFactory::create_location(
tag.text().as_string(),
tag.child("beschrijving").text().as_string()
);
vector<string> objects_hidden = str_split(tag.attribute("objectenverborgen").as_string(), ";");
for (string & name : objects_hidden) {
Object * object = gamedata.create_object(name);
location->add_hidden_object(object);
}
vector<string> objects_visible = str_split(tag.attribute("objectenzichtbaar").as_string(), ";");
for (string & name : objects_visible) {
Object * object = gamedata.create_object(name);
location->add_visible_object(object);
}
vector<string> enemies = str_split(tag.attribute("vijand").as_string(), ";");
for (string & name : enemies) {
Enemy * enemy = gamedata.create_enemy(name);
location->add_enemy(enemy);
}
temp_map[tag.attribute("id").as_uint()] = {
.location = location,
.edges = {
[Direction::NORTH] = tag.attribute("noord").as_uint(0),
[Direction::EAST] = tag.attribute("oost").as_uint(0),
[Direction::SOUTH] = tag.attribute("zuid").as_uint(0),
[Direction::WEST] = tag.attribute("west").as_uint(0),
},
};
dungeon->add_location(location);
}
// connect edges after creating all locations
for (auto & [_, temp] : temp_map) {
for (Direction direction : DIRECTIONS) {
unsigned id = temp.edges[direction];
if (temp.edges[direction] == 0) continue;
if (!temp_map.contains(id)) continue;
temp.location->set_exit(direction, temp_map[id].location);
}
}
return dungeon;
}
|