diff options
-rw-r--r-- | backend/Dungeon.h | 2 | ||||
-rw-r--r-- | backend/List.h | 42 | ||||
-rw-r--r-- | backend/List.hpp | 110 | ||||
-rw-r--r-- | backend/ListIterator.h | 38 | ||||
-rw-r--r-- | backend/ListIterator.hpp | 41 | ||||
-rw-r--r-- | backend/Location.cpp | 5 | ||||
-rw-r--r-- | backend/Location.h | 4 | ||||
-rw-r--r-- | backend/Object.cpp | 3 | ||||
-rw-r--r-- | backend/Object.h | 1 | ||||
-rw-r--r-- | frontend/CMakeLists.txt | 2 | ||||
-rw-r--r-- | frontend/DB.cpp | 30 | ||||
-rw-r--r-- | frontend/DB.h | 18 | ||||
-rw-r--r-- | frontend/GameData.cpp | 15 | ||||
-rw-r--r-- | frontend/GameData.h | 18 | ||||
-rw-r--r-- | frontend/cmd/query.cpp | 33 | ||||
-rw-r--r-- | frontend/generate_dungeon.cpp | 42 | ||||
-rw-r--r-- | frontend/load_dungeon.cpp | 17 |
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); } } |