diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-11-02 18:46:18 +0100 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-11-02 18:46:18 +0100 |
commit | c17df7d3e28e0eeb21f7a62d1c66f525b487a5fa (patch) | |
tree | 897cc608add9682c0ae36d3b3552147706234602 | |
parent | 5e4dd0c0197f6273c61491a5b9a030c93f796a12 (diff) |
implement dungeon generation
-rw-r--r-- | backend/Location.cpp | 4 | ||||
-rw-r--r-- | backend/Location.h | 1 | ||||
-rw-r--r-- | frontend/GameData.cpp | 16 | ||||
-rw-r--r-- | frontend/GameData.h | 3 | ||||
-rw-r--r-- | frontend/generate_dungeon.cpp | 43 | ||||
-rw-r--r-- | frontend/load_dungeon.cpp | 1 | ||||
-rw-r--r-- | test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | test/direction.cpp | 11 |
8 files changed, 74 insertions, 6 deletions
diff --git a/backend/Location.cpp b/backend/Location.cpp index c036c7b..eadbef2 100644 --- a/backend/Location.cpp +++ b/backend/Location.cpp @@ -5,6 +5,10 @@ #include "Object.h" #include "util.h" +Direction operator - (const Direction & rhs) { + return static_cast<Direction>((rhs + 2) % 4); +} + Direction random_direction() { return DIRECTIONS[RNG::get().rand_int(4)]; } diff --git a/backend/Location.h b/backend/Location.h index d29c117..6f701ad 100644 --- a/backend/Location.h +++ b/backend/Location.h @@ -15,6 +15,7 @@ enum Direction { WEST = 3, }; static constexpr const Direction DIRECTIONS[] = { NORTH, EAST, SOUTH, WEST }; +Direction operator - (const Direction &); Direction random_direction(); Direction random_direction(const Location &); diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp index 6d22f8e..70a8058 100644 --- a/frontend/GameData.cpp +++ b/frontend/GameData.cpp @@ -79,7 +79,7 @@ Object * GameData::create_object(const string & name) const { .value = { row.col<int>(2), row.col<int>(3) }, .protection = row.col<int>(4), }); - } catch (...) { + } catch (Exception & e) { return ObjectFactory::create_object(name.c_str()); } } @@ -142,7 +142,7 @@ vector<string> GameData::random_names(const string & table, unsigned count) cons // (i.e. the table name in this case), which makes this function vulnerable // to SQL injection if the table argument contains user-controllable data. String query_str = String::fmt("select naam from %s order by random() limit ?", table.c_str()); - static DBStatement query = this->db.prepare(query_str.c_str()); + DBStatement query = this->db.prepare(query_str.c_str()); query.reset() .bind(count) ; @@ -169,3 +169,15 @@ vector<string> GameData::random_enemies(unsigned count) const { return this->random_names("Vijanden", count); } +string GameData::random_location() const { + return this->random_locations(1)[0]; +} + +string GameData::random_object() const { + return this->random_objects(1)[0]; +} + +string GameData::random_enemy() const { + return this->random_enemies(1)[0]; +} + diff --git a/frontend/GameData.h b/frontend/GameData.h index b0c9415..172f7d5 100644 --- a/frontend/GameData.h +++ b/frontend/GameData.h @@ -26,6 +26,9 @@ public: std::vector<std::string> random_objects(unsigned count = 1) const; std::vector<std::string> random_locations(unsigned count = 1) const; std::vector<std::string> random_enemies(unsigned count = 1) const; + std::string random_object() const; + std::string random_location() const; + std::string random_enemy() const; private: std::vector<std::string> random_names(const std::string & table, unsigned count) const; diff --git a/frontend/generate_dungeon.cpp b/frontend/generate_dungeon.cpp index 7ce1754..5484b2c 100644 --- a/frontend/generate_dungeon.cpp +++ b/frontend/generate_dungeon.cpp @@ -1,6 +1,8 @@ +#include <map> #include <memory> #include "backend/Dungeon.h" +#include "backend/RNG.h" #include "backend/print.h" #include "backend/Exception.h" @@ -26,14 +28,49 @@ unique_ptr<Dungeon> generate_dungeon() { throw Exception("meer dan 1 locatie nodig"); vector<string> locations = gd.random_locations(location_count); + struct TempData { + Location * location; + int edges[4] = { -1, -1, -1, -1 }; + }; + vector<TempData> temp_map; + temp_map.resize(location_count); + + size_t index = 0; + RNG & rng = RNG::get(); for (const string & name : locations) { Location * location = gd.create_location(name); + + if (index % 3 == 0) { + location->add_enemy(gd.create_enemy(gd.random_enemy())); + } + + for (const string & object : gd.random_objects(rng.rand_int(Range<int> { 0, 3 }))) { + location->add_visible_object(gd.create_object(object)); + } + + for (const string & object : gd.random_objects(rng.rand_int(Range<int> { 0, 2 }))) { + location->add_hidden_object(gd.create_object(object)); + } + + auto & temp = temp_map[index]; + temp.location = location; + for (Direction direction : DIRECTIONS) { + if (rng.rand_double() < 0.5) continue; + temp.edges[direction] = rng.rand_int(location_count); + temp_map[temp.edges[direction]].edges[-direction] = index; + } + dungeon->add_location(location); + index++; } - // TODO: connect locations - // TODO: optionally add enemy - // TODO: generate items + for (auto & temp : temp_map) { + for (Direction direction : DIRECTIONS) { + unsigned id = temp.edges[direction]; + if (temp.edges[direction] < 0) continue; + temp.location->set_exit(direction, temp_map[id].location); + } + } return dungeon; } diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp index e5a1e82..b19b541 100644 --- a/frontend/load_dungeon.cpp +++ b/frontend/load_dungeon.cpp @@ -1,4 +1,3 @@ -#include <csignal> #include <memory> #include <filesystem> #include <pugixml.hpp> diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 96c0e95..c219ac0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,4 +3,5 @@ target_sources(test_main PUBLIC list.cpp ptrlist.cpp util.cpp + direction.cpp ) diff --git a/test/direction.cpp b/test/direction.cpp new file mode 100644 index 0000000..8c36a94 --- /dev/null +++ b/test/direction.cpp @@ -0,0 +1,11 @@ +#include <gtest/gtest.h> + +#include "backend/Location.h" + +TEST(LocationDirection, Negate) { + ASSERT_EQ(-NORTH, SOUTH); + ASSERT_EQ(-EAST, WEST); + ASSERT_EQ(-SOUTH, NORTH); + ASSERT_EQ(-WEST, EAST); +} + |