aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/Dungeon.h2
-rw-r--r--backend/List.h42
-rw-r--r--backend/List.hpp110
-rw-r--r--backend/ListIterator.h38
-rw-r--r--backend/ListIterator.hpp41
-rw-r--r--backend/Location.cpp5
-rw-r--r--backend/Location.h4
-rw-r--r--backend/Object.cpp3
-rw-r--r--backend/Object.h1
-rw-r--r--frontend/CMakeLists.txt2
-rw-r--r--frontend/DB.cpp30
-rw-r--r--frontend/DB.h18
-rw-r--r--frontend/GameData.cpp15
-rw-r--r--frontend/GameData.h18
-rw-r--r--frontend/cmd/query.cpp33
-rw-r--r--frontend/generate_dungeon.cpp42
-rw-r--r--frontend/load_dungeon.cpp17
17 files changed, 310 insertions, 111 deletions
diff --git a/backend/Dungeon.h b/backend/Dungeon.h
index 2d5fa61..5740eb6 100644
--- a/backend/Dungeon.h
+++ b/backend/Dungeon.h
@@ -1,6 +1,6 @@
#pragma once
-#include "List.hpp"
+#include "List.h"
class Location;
diff --git a/backend/List.h b/backend/List.h
new file mode 100644
index 0000000..2d3d6b1
--- /dev/null
+++ b/backend/List.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <stdlib.h>
+
+template <typename T>
+class ListRange;
+
+template <typename T>
+class ListIterator;
+
+template <typename T>
+struct ListLink {
+ ListLink<T> * prev;
+ ListLink<T> * next;
+ T value;
+};
+
+template<typename T>
+class List {
+public:
+ size_t size();
+
+ void push_back(T el);
+
+ void pop_back();
+
+ void clear();
+
+ T & operator [] (size_t index);
+
+ ListIterator<T> begin();
+ ListIterator<T> end();
+ ListRange<T> range();
+
+private:
+ ListLink<T> * head = nullptr;
+ ListLink<T> * tail = nullptr;
+ size_t length = 0;
+};
+
+#include "List.hpp"
+
diff --git a/backend/List.hpp b/backend/List.hpp
index d6c7738..df075f9 100644
--- a/backend/List.hpp
+++ b/backend/List.hpp
@@ -1,66 +1,72 @@
#pragma once
-#include <stdlib.h>
+#include "List.h"
template <typename T>
-struct ListLink {
- ListLink<T> * prev;
- ListLink<T> * next;
- T value;
-};
+size_t List<T>::size() {
+ return this->length;
+}
-template<typename T>
-class List {
-public:
- size_t size() { return this->length; }
+template <typename T>
+void List<T>::push_back(T el) {
+ ListLink<T> * link = static_cast<ListLink<T> *>(malloc(sizeof(ListLink<T>)));
+ link->prev = this->head;
+ link->next = nullptr;
+ link->value = el;
+ if (this->head != nullptr) this->head->next = link;
+ if (this->head == nullptr) this->tail = link;
+ this->head = link;
+ this->length++;
+}
- void push_back(T el) {
- ListLink<T> * link = static_cast<ListLink<T> *>(malloc(sizeof(ListLink<T>)));
- link->prev = this->head;
- link->next = nullptr;
- link->value = el;
- if (this->head != nullptr) this->head->next = link;
- if (this->head == nullptr) this->tail = link;
- this->head = link;
- this->length++;
- }
+template <typename T>
+void List<T>::pop_back() {
+ if (this->head == nullptr) return; // empty list
- void pop_back() {
- if (this->head == nullptr) return; // empty list
+ ListLink<T> * secondlast = this->head->prev;
+ if (secondlast != nullptr)
+ secondlast->next = nullptr;
+ free(this->head);
+ if (this->tail == this->head)
+ this->tail = nullptr;
+ this->head = secondlast;
- ListLink<T> * secondlast = this->head->prev;
- if (secondlast != nullptr)
- secondlast->next = nullptr;
- free(this->head);
- if (this->tail == this->head)
- this->tail = nullptr;
- this->head = secondlast;
+ this->length--;
+}
- this->length--;
+template <typename T>
+void List<T>::clear() {
+ ListLink<T> * link = this->tail;
+ while (link != nullptr) {
+ ListLink<T> * next = link->next;
+ free(link);
+ link = next;
}
+ this->head = nullptr;
+ this->tail = nullptr;
+ this->length = 0;
+}
- void clear() {
- ListLink<T> * link = this->tail;
- while (link != nullptr) {
- ListLink<T> * next = link->next;
- free(link);
- link = next;
- }
- this->head = nullptr;
- this->tail = nullptr;
- this->length = 0;
- }
+template <typename T>
+T & List<T>::operator [] (size_t index) {
+ ListLink<T> * link = this->tail;
+ for (size_t i = 0; i < index; i++)
+ link = link->next;
+ return link->value;
+}
- T & operator [] (size_t index) {
- ListLink<T> * link = this->tail;
- for (size_t i = 0; i < index; i++)
- link = link->next;
- return link->value;
- }
+template <typename T>
+ListRange<T> List<T>::range() {
+ return { *this };
+}
-private:
- ListLink<T> * head = nullptr;
- ListLink<T> * tail = nullptr;
- size_t length = 0;
-};
+template <typename T>
+ListIterator<T> List<T>::begin() {
+ return this->range().begin();
+}
+
+template <typename T>
+ListIterator<T> List<T>::end() {
+ return this->range().end();
+}
diff --git a/backend/ListIterator.h b/backend/ListIterator.h
new file mode 100644
index 0000000..aa78931
--- /dev/null
+++ b/backend/ListIterator.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "backend/List.h"
+#include <cstddef>
+
+template <typename T>
+class List;
+
+template <typename T>
+class ListIterator {
+public:
+ ListIterator(List<T> & list, size_t index);
+
+public:
+ T operator * () const;
+ ListIterator<T> & operator ++ ();
+ bool operator != (const ListIterator<T> &) const;
+
+private:
+ List<T> & list;
+ size_t index;
+};
+
+template <typename T>
+class ListRange {
+public:
+ ListRange(List<T> & list);
+
+public:
+ ListIterator<T> begin() const;
+ ListIterator<T> end() const;
+ size_t size() const;
+
+private:
+ List<T> & list;
+};
+
+#include "ListIterator.hpp"
diff --git a/backend/ListIterator.hpp b/backend/ListIterator.hpp
new file mode 100644
index 0000000..5e4ea91
--- /dev/null
+++ b/backend/ListIterator.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "ListIterator.h"
+
+template <typename T>
+ListRange<T>::ListRange(List<T> & list) : list(list) { }
+
+template <typename T>
+ListIterator<T> ListRange<T>::begin() const {
+ return { this->list, 0 };
+}
+
+template <typename T>
+ListIterator<T> ListRange<T>::end() const {
+ return { this->list, this->list.size() };
+}
+
+template <typename T>
+size_t ListRange<T>::size() const {
+ return this->list.size();
+}
+
+template <typename T>
+ListIterator<T>::ListIterator(List<T> & list, size_t index) : list(list), index(index) { }
+
+template <typename T>
+T ListIterator<T>::operator * () const {
+ return this->list[this->index];
+}
+
+template <typename T>
+ListIterator<T> & ListIterator<T>::operator ++ () {
+ this->index++;
+ return *this;
+}
+
+template <typename T>
+bool ListIterator<T>::operator != (const ListIterator<T> & rhs) const {
+ return this->index < rhs.index;
+}
+
diff --git a/backend/Location.cpp b/backend/Location.cpp
index 8a79af5..96d06ca 100644
--- a/backend/Location.cpp
+++ b/backend/Location.cpp
@@ -1,6 +1,7 @@
#include <string.h>
#include "Location.h"
+#include "ListIterator.h"
#include "util.h"
Location::Location(const char * name, const char * description) {
@@ -36,3 +37,7 @@ Location * Location::get_exit(Direction dir) {
return this->edges[dir];
}
+ListRange<Object *> Location::get_objects() {
+ return this->objects.range();
+}
+
diff --git a/backend/Location.h b/backend/Location.h
index f102728..8b600bb 100644
--- a/backend/Location.h
+++ b/backend/Location.h
@@ -1,6 +1,7 @@
#pragma once
-#include "List.hpp"
+#include "List.h"
+#include "ListIterator.h"
class Enemy;
class Object;
@@ -21,6 +22,7 @@ public:
const char * get_description();
void set_exit(Direction dir, Location * location = nullptr);
Location * get_exit(Direction dir);
+ ListRange<Object *> get_objects();
protected:
Location(const char * name = "", const char * description = "");
diff --git a/backend/Object.cpp b/backend/Object.cpp
index e14c780..ed8bc46 100644
--- a/backend/Object.cpp
+++ b/backend/Object.cpp
@@ -22,6 +22,9 @@ void Object::set_name(const char * name) {
const char * Object::get_name() {
return this->name;
}
+const char * Object::get_displayname() {
+ return this->get_name();
+}
void Object::set_description(const char * description) {
safe_free(this->description);
diff --git a/backend/Object.h b/backend/Object.h
index 92652c4..cb2c209 100644
--- a/backend/Object.h
+++ b/backend/Object.h
@@ -8,6 +8,7 @@ private:
public:
void set_name(const char * name);
const char * get_name();
+ virtual const char * get_displayname();
void set_description(const char * description);
const char * get_description();
void set_hidden(bool hidden);
diff --git a/frontend/CMakeLists.txt b/frontend/CMakeLists.txt
index 60b830c..d60b44f 100644
--- a/frontend/CMakeLists.txt
+++ b/frontend/CMakeLists.txt
@@ -7,6 +7,8 @@ target_sources(main PUBLIC
load_dungeon.cpp
generate_dungeon.cpp
Exception.cpp
+ DB.cpp
+ GameData.cpp
)
add_subdirectory(cmd)
diff --git a/frontend/DB.cpp b/frontend/DB.cpp
new file mode 100644
index 0000000..82933b8
--- /dev/null
+++ b/frontend/DB.cpp
@@ -0,0 +1,30 @@
+#include "DB.h"
+#include "Exception.h"
+
+DB::DB(const std::string & path) {
+ sqlite3 * db = NULL;
+ int ret = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READONLY, NULL);
+ this->db = {
+ db,
+ [] (sqlite3 * db) {
+ sqlite3_close_v2(db);
+ },
+ };
+ if (ret != SQLITE_OK)
+ throw Exception("sqlite3_open_v2");
+}
+
+DB::unique_sqlite3_stmt DB::prepare(const std::string & query) {
+ sqlite3_stmt * stmt = NULL;
+ int ret = sqlite3_prepare_v2(this->db.get(), query.c_str(), query.size(), &stmt, NULL);
+ unique_sqlite3_stmt uniq_stmt = {
+ stmt,
+ [] (sqlite3_stmt * stmt) {
+ sqlite3_finalize(stmt);
+ },
+ };
+ if (ret != SQLITE_OK)
+ throw Exception("sqlite3_prepare_v2");
+ return uniq_stmt;
+}
+
diff --git a/frontend/DB.h b/frontend/DB.h
new file mode 100644
index 0000000..b464f9f
--- /dev/null
+++ b/frontend/DB.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <memory>
+#include <functional>
+#include <sqlite3.h>
+
+class DB {
+ typedef std::unique_ptr<sqlite3, std::function<void(sqlite3*)>> unique_sqlite3;
+ typedef std::unique_ptr<sqlite3_stmt, std::function<void(sqlite3_stmt*)>> unique_sqlite3_stmt;
+
+public:
+ DB(const std::string & path);
+ unique_sqlite3_stmt prepare(const std::string & query);
+
+private:
+ unique_sqlite3 db = NULL;
+};
+
diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp
new file mode 100644
index 0000000..ad22aa0
--- /dev/null
+++ b/frontend/GameData.cpp
@@ -0,0 +1,15 @@
+#include <memory>
+
+#include "GameData.h"
+
+using namespace std;
+
+GameData & GameData::get_instance() {
+ static GameData instance;
+ return instance;
+}
+
+GameData::GameData() {
+ this->db = make_unique<DB>("kerkersendraken.db");
+}
+
diff --git a/frontend/GameData.h b/frontend/GameData.h
new file mode 100644
index 0000000..d4c3712
--- /dev/null
+++ b/frontend/GameData.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <memory>
+
+#include "DB.h"
+
+class GameData {
+public:
+ static GameData & get_instance();
+
+private:
+ GameData();
+ virtual ~GameData() = default;
+
+private:
+ std::unique_ptr<DB> db = nullptr;
+};
+
diff --git a/frontend/cmd/query.cpp b/frontend/cmd/query.cpp
index 367d6cd..3a26e9c 100644
--- a/frontend/cmd/query.cpp
+++ b/frontend/cmd/query.cpp
@@ -1,4 +1,5 @@
#include "backend/Location.h"
+#include "backend/Object.h"
#include "../Player.h"
#include "../print.h"
@@ -16,17 +17,31 @@ FollowupAction Player::cmd_query(Argv argv) {
lprtf("Je staat bij de locatie %s.\n", this->location.get_name());
lprtf("%s\n", this->location.get_description());
- // TODO: visible objects
+ {
+ lprtf("Zichtbare objecten: ");
+ size_t objects = 0;
+ for (Object * obj : this->location.get_objects()) {
+ if (obj->get_hidden() == true) continue;
+ if (objects > 0) lprtf(", ");
+ lprtf("%s", obj->get_displayname());
+ objects++;
+ }
+ if (objects == 0)
+ lprtf("(geen)");
+ lprtf("\n");
+ }
- lprtf("Uitgangen: ");
- bool first = true;
- for (Direction direction : DIRECTIONS) {
- if (this->location.get_exit(direction) == nullptr) continue;
- if (!first) lprtf(", ");
- lprtf("%s", direction_map.at(direction).c_str());
- first = false;
+ {
+ lprtf("Uitgangen: ");
+ bool first = true;
+ for (Direction direction : DIRECTIONS) {
+ if (this->location.get_exit(direction) == nullptr) continue;
+ if (!first) lprtf(", ");
+ lprtf("%s", direction_map.at(direction).c_str());
+ first = false;
+ }
+ lprtf("\n");
}
- lprtf("\n");
// TODO: enemies
diff --git a/frontend/generate_dungeon.cpp b/frontend/generate_dungeon.cpp
index c6ddcbf..e2a7c74 100644
--- a/frontend/generate_dungeon.cpp
+++ b/frontend/generate_dungeon.cpp
@@ -1,54 +1,16 @@
#include <memory>
-#include <functional>
-#include <sqlite3.h>
#include "backend/Dungeon.h"
#include "generate_dungeon.h"
-#include "Exception.h"
+#include "GameData.h"
using namespace std;
-class DB {
- typedef unique_ptr<sqlite3, function<void(sqlite3*)>> unique_sqlite3;
- typedef unique_ptr<sqlite3_stmt, function<void(sqlite3_stmt*)>> unique_sqlite3_stmt;
-
-public:
- DB(const string & path) {
- sqlite3 * db = NULL;
- int ret = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READONLY, NULL);
- this->db = {
- db,
- [] (sqlite3 * db) {
- sqlite3_close_v2(db);
- },
- };
- if (ret != SQLITE_OK)
- throw Exception("sqlite3_open_v2");
- }
-
- unique_sqlite3_stmt prepare(const string & query) {
- sqlite3_stmt * stmt = NULL;
- int ret = sqlite3_prepare_v2(this->db.get(), query.c_str(), query.size(), &stmt, NULL);
- unique_sqlite3_stmt uniq_stmt = {
- stmt,
- [] (sqlite3_stmt * stmt) {
- sqlite3_finalize(stmt);
- },
- };
- if (ret != SQLITE_OK)
- throw Exception("sqlite3_prepare_v2");
- return uniq_stmt;
- }
-
-private:
- unique_sqlite3 db = NULL;
-};
-
unique_ptr<Dungeon> generate_dungeon() {
unique_ptr<Dungeon> dungeon = make_unique<Dungeon>();
- DB db { "kerkersendraken.db" };
+ GameData & gd = GameData::get_instance();
return dungeon;
}
diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp
index e94cbcb..b60a7b9 100644
--- a/frontend/load_dungeon.cpp
+++ b/frontend/load_dungeon.cpp
@@ -1,3 +1,4 @@
+#include <csignal>
#include <memory>
#include <filesystem>
#include <pugixml.hpp>
@@ -54,22 +55,22 @@ unique_ptr<Dungeon> load_dungeon(const string & filename) {
temp_map[tag.attribute("id").as_uint()] = {
.location = location,
.edges = {
- tag.attribute("noord").as_uint(0),
- tag.attribute("oost").as_uint(0),
- tag.attribute("zuid").as_uint(0),
- tag.attribute("west").as_uint(0),
+ [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 & [here, temp] : temp_map) {
+ for (auto & [_, temp] : temp_map) {
for (Direction direction : DIRECTIONS) {
- unsigned there = temp.edges[direction];
+ unsigned id = temp.edges[direction];
if (temp.edges[direction] == 0) continue;
- if (!temp_map.contains(there)) continue;
- temp.location->set_exit(direction, temp_map[there].location);
+ if (!temp_map.contains(id)) continue;
+ temp.location->set_exit(direction, temp_map[id].location);
}
}