aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-02 18:46:18 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-02 18:46:18 +0100
commitc17df7d3e28e0eeb21f7a62d1c66f525b487a5fa (patch)
tree897cc608add9682c0ae36d3b3552147706234602
parent5e4dd0c0197f6273c61491a5b9a030c93f796a12 (diff)
implement dungeon generation
-rw-r--r--backend/Location.cpp4
-rw-r--r--backend/Location.h1
-rw-r--r--frontend/GameData.cpp16
-rw-r--r--frontend/GameData.h3
-rw-r--r--frontend/generate_dungeon.cpp43
-rw-r--r--frontend/load_dungeon.cpp1
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/direction.cpp11
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);
+}
+