#include #include #include #include #include #include "backend/Location.h" #include "backend/LocationFactory.h" #include "backend/Exception.h" #include "backend/Dungeon.h" #include "load_dungeon.h" #include "GameData.h" #include "backend/Object.h" #include "strings.h" using namespace std; using namespace pugi; unique_ptr load_dungeon(const string & filename) { unique_ptr dungeon = make_unique(); 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 (%s)", filename.c_str()); } 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 tag"); GameData & gamedata = GameData::get_instance(); struct TempData { Location * location; unsigned edges[4]; }; map temp_map; for (xml_node & tag : locations) { Location * location = LocationFactory::create_location( tag.text().as_string(), tag.child("beschrijving").text().as_string() ); vector 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 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 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; }