aboutsummaryrefslogtreecommitdiff
path: root/frontend/load_dungeon.cpp
blob: b60a7b923028f4fea49b985047702a46bbb5f1b1 (plain)
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
#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 "frontend/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());
	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");

	LocationFactory factory;
	struct TempData {
		Location * location;
		unsigned edges[4];
	};
	map<unsigned, TempData> temp_map;
	for (xml_node & tag : locations) {
		const char * name = tag.text().as_string();
		const char * description = tag.child("beschrijving").text().as_string();

		// vector<string> objects_hidden = split_string(tag.attribute("objectenverborgen").as_string(), ";");
		// vector<string> objects_visible = split_string(tag.attribute("objectenzichtbaar").as_string(), ";");
		// vector<string> enemies = split_string(tag.attribute("vijand").as_string(), ";");

		Location * location = factory.create_location(name, description);
		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;
}