diff options
| -rw-r--r-- | backend/ArmorObject.h | 2 | ||||
| -rw-r--r-- | backend/ConsumableObject.h | 2 | ||||
| -rw-r--r-- | backend/Enemy.h | 4 | ||||
| -rw-r--r-- | backend/GoldObject.h | 2 | ||||
| -rw-r--r-- | backend/Location.cpp | 10 | ||||
| -rw-r--r-- | backend/Location.h | 5 | ||||
| -rw-r--r-- | backend/LocationFactory.h | 2 | ||||
| -rw-r--r-- | backend/ObjectFactory.cpp | 19 | ||||
| -rw-r--r-- | backend/ObjectFactory.h | 10 | ||||
| -rw-r--r-- | backend/WeaponObject.h | 2 | ||||
| -rw-r--r-- | frontend/DB.cpp | 50 | ||||
| -rw-r--r-- | frontend/DB.h | 26 | ||||
| -rw-r--r-- | frontend/GameData.cpp | 26 | ||||
| -rw-r--r-- | frontend/GameData.h | 8 | ||||
| -rw-r--r-- | frontend/Player.cpp | 4 | ||||
| -rw-r--r-- | frontend/load_dungeon.cpp | 34 | ||||
| -rw-r--r-- | frontend/main.cpp | 4 | ||||
| -rw-r--r-- | frontend/strings.cpp | 24 | ||||
| -rw-r--r-- | frontend/strings.h | 9 | 
19 files changed, 207 insertions, 36 deletions
diff --git a/backend/ArmorObject.h b/backend/ArmorObject.h index e9c02d2..112997b 100644 --- a/backend/ArmorObject.h +++ b/backend/ArmorObject.h @@ -3,6 +3,8 @@  #include "Object.h"  class ArmorObject : public Object { +	using Object::Object; +  private:  	int protection = 0; diff --git a/backend/ConsumableObject.h b/backend/ConsumableObject.h index 0e98674..3b4a2ce 100644 --- a/backend/ConsumableObject.h +++ b/backend/ConsumableObject.h @@ -3,5 +3,7 @@  #include "Object.h"  class ConsumableObject : public Object { +	using Object::Object; +  }; diff --git a/backend/Enemy.h b/backend/Enemy.h index dd33090..fb04472 100644 --- a/backend/Enemy.h +++ b/backend/Enemy.h @@ -1,5 +1,9 @@  #pragma once  class Enemy { +private: +	Enemy() = default; +	virtual ~Enemy() = default; +	friend class EnemyFactory;  }; diff --git a/backend/GoldObject.h b/backend/GoldObject.h index f37b7d9..6f65c1d 100644 --- a/backend/GoldObject.h +++ b/backend/GoldObject.h @@ -3,6 +3,8 @@  #include "Object.h"  class GoldObject : public Object { +	using Object::Object; +  private:  	int count = 0;  }; diff --git a/backend/Location.cpp b/backend/Location.cpp index 96d06ca..a26d530 100644 --- a/backend/Location.cpp +++ b/backend/Location.cpp @@ -37,7 +37,17 @@ Location * Location::get_exit(Direction dir) {  	return this->edges[dir];  } +void Location::add_object(Object * object) { +	this->objects.push_back(object); +}  ListRange<Object *> Location::get_objects() {  	return this->objects.range();  } +void Location::add_enemy(Enemy * enemy) { +	this->enemies.push_back(enemy); +} +ListRange<Enemy *> Location::get_enemies() { +	return this->enemies.range(); +} + diff --git a/backend/Location.h b/backend/Location.h index 8b600bb..4ce2349 100644 --- a/backend/Location.h +++ b/backend/Location.h @@ -22,9 +22,12 @@ public:  	const char * get_description();  	void set_exit(Direction dir, Location * location = nullptr);  	Location * get_exit(Direction dir); +	void add_object(Object *);  	ListRange<Object *> get_objects(); +	void add_enemy(Enemy *); +	ListRange<Enemy *> get_enemies(); -protected: +private:  	Location(const char * name = "", const char * description = "");  	virtual ~Location();  	friend class LocationFactory; diff --git a/backend/LocationFactory.h b/backend/LocationFactory.h index a12bb0e..ba34ff3 100644 --- a/backend/LocationFactory.h +++ b/backend/LocationFactory.h @@ -4,6 +4,6 @@  class LocationFactory {  public: -	Location * create_location(const char * name, const char * description); +	static Location * create_location(const char * name, const char * description);  }; diff --git a/backend/ObjectFactory.cpp b/backend/ObjectFactory.cpp index efb7742..4a0642b 100644 --- a/backend/ObjectFactory.cpp +++ b/backend/ObjectFactory.cpp @@ -1,6 +1,21 @@  #include "ObjectFactory.h" -Object * ObjectFactory::create_object() { -	return new Object(); +#include "ArmorObject.h" +#include "ConsumableObject.h" +#include "GoldObject.h" +#include "WeaponObject.h" + +Object * ObjectFactory::create_object(ObjectType type, const char * name, const char * description) { +	switch (type) { +		case ARMOR: return new ArmorObject(name, description); +		case CONSUMABLE: return new ConsumableObject(name, description); +		case GOLD: return new GoldObject(name, description); +		case WEAPON: return new WeaponObject(name, description); +	} +	return ObjectFactory::create_object(name, description); +} + +Object * ObjectFactory::create_object(const char * name, const char * description) { +	return new Object(name, description);  } diff --git a/backend/ObjectFactory.h b/backend/ObjectFactory.h index f9a7301..adf960b 100644 --- a/backend/ObjectFactory.h +++ b/backend/ObjectFactory.h @@ -2,9 +2,17 @@  #include "Object.h" +enum ObjectType { +	ARMOR, +	CONSUMABLE, +	GOLD, +	WEAPON, +}; +  class ObjectFactory {  public: -	static Object * create_object(); +	static Object * create_object(ObjectType type, const char * name = "", const char * description = ""); +	static Object * create_object(const char * name = "", const char * description = "");  private:  	ObjectFactory() = delete; diff --git a/backend/WeaponObject.h b/backend/WeaponObject.h index e9ce261..8b1bc58 100644 --- a/backend/WeaponObject.h +++ b/backend/WeaponObject.h @@ -3,6 +3,8 @@  #include "Object.h"  class WeaponObject : public Object { +	using Object::Object; +  private:  	int damage_min;  	int damage_max; diff --git a/frontend/DB.cpp b/frontend/DB.cpp index 82933b8..d51601e 100644 --- a/frontend/DB.cpp +++ b/frontend/DB.cpp @@ -1,9 +1,11 @@  #include "DB.h"  #include "Exception.h" -DB::DB(const std::string & path) { +using namespace std; + +DB::DB(const string & path) {  	sqlite3 * db = NULL; -	int ret = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READONLY, NULL); +	int ret = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READWRITE, NULL);  	this->db = {  		db,  		[] (sqlite3 * db) { @@ -11,20 +13,52 @@ DB::DB(const std::string & path) {  		},  	};  	if (ret != SQLITE_OK) -		throw Exception("sqlite3_open_v2"); +		throw Exception("sqlite3_open_v2: %d", ret); +} + +DBStatement DB::prepare(const string & query) { +	return DBStatement(*this, query);  } -DB::unique_sqlite3_stmt DB::prepare(const std::string & query) { +DBStatement::DBStatement(DB & db, const string & query) : db(db) {  	sqlite3_stmt * stmt = NULL; -	int ret = sqlite3_prepare_v2(this->db.get(), query.c_str(), query.size(), &stmt, NULL); -	unique_sqlite3_stmt uniq_stmt = { +	int ret = sqlite3_prepare_v2(this->db.db.get(), query.c_str(), query.size(), &stmt, NULL); +	this->stmt = {  		stmt,  		[] (sqlite3_stmt * stmt) {  			sqlite3_finalize(stmt);  		},  	};  	if (ret != SQLITE_OK) -		throw Exception("sqlite3_prepare_v2"); -	return uniq_stmt; +		throw Exception("sqlite3_prepare_v2: %d", ret); +} + +DBStatement & DBStatement::bind(const string & text) { +	int ret = sqlite3_bind_text(this->stmt.get(), this->param_index, text.data(), text.size(), NULL); +	if (ret != SQLITE_OK) +		throw Exception("sqlite3_bind_text: %d", ret); + +	this->param_index++; +	return *this; +} + +DBStatement & DBStatement::bind(const int & number) { +	int ret = sqlite3_bind_int(this->stmt.get(), this->param_index, number); +	if (ret != SQLITE_OK) +		throw Exception("sqlite3_bind_int: %d", ret); + +	this->param_index++; +	return *this; +} + +DBStatement & DBStatement::unbind() { +	this->param_index = 1; +	return *this; +} + +void DBStatement::execute() { +	int ret = sqlite3_step(this->stmt.get()); +	if (ret != SQLITE_DONE) +		throw Exception("sqlite3_step: %d", ret);  } diff --git a/frontend/DB.h b/frontend/DB.h index b464f9f..5c88940 100644 --- a/frontend/DB.h +++ b/frontend/DB.h @@ -4,15 +4,33 @@  #include <functional>  #include <sqlite3.h> +class DB; + +class DBStatement { +	std::unique_ptr<sqlite3_stmt, std::function<void(sqlite3_stmt*)>> stmt; +public: +	DBStatement(DB &, const std::string & query); + +public: +	DBStatement & unbind(); +	DBStatement & bind(const std::string & text); +	DBStatement & bind(const int & number); +public: +	void execute(); + +private: +	int param_index = 1; +	DB & db; +}; +  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; +	friend class DBStatement;  public:  	DB(const std::string & path); -	unique_sqlite3_stmt prepare(const std::string & query); +	DBStatement prepare(const std::string & query);  private: -	unique_sqlite3 db = NULL; +	std::unique_ptr<sqlite3, std::function<void(sqlite3*)>> db = NULL;  }; diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp index ad22aa0..0cf6a1d 100644 --- a/frontend/GameData.cpp +++ b/frontend/GameData.cpp @@ -1,5 +1,10 @@  #include <memory> +#include "backend/Enemy.h" +#include "backend/EnemyFactory.h" +#include "backend/Object.h" +#include "backend/ObjectFactory.h" +  #include "GameData.h"  using namespace std; @@ -13,3 +18,24 @@ GameData::GameData() {  	this->db = make_unique<DB>("kerkersendraken.db");  } +Enemy * GameData::create_enemy(const string & name) { +	Enemy * enemy = EnemyFactory::create_enemy(); +	return enemy; +} + +Object * GameData::create_object(const string & name) { +	DBStatement query = this->db->prepare("select type from Objecten where naam = ?"); +	query.bind(name); +	// TODO: uhhhhhhhhh data ophalen + +	Object * object = ObjectFactory::create_object(); +	return object; +} + +void GameData::leaderbord_add(const string & name, unsigned int gold) { +	this->db->prepare("insert into Leaderboard (naam, goudstukken) values (?, ?)") +		.bind(name) +		.bind(gold) +		.execute(); +} + diff --git a/frontend/GameData.h b/frontend/GameData.h index d4c3712..383de00 100644 --- a/frontend/GameData.h +++ b/frontend/GameData.h @@ -4,10 +4,18 @@  #include "DB.h" +class Enemy; +class Object; +  class GameData {  public:  	static GameData & get_instance(); +public: +	Enemy * create_enemy(const std::string & name); +	Object * create_object(const std::string & name); +	void leaderbord_add(const std::string & name, unsigned int gold); +  private:  	GameData();  	virtual ~GameData() = default; diff --git a/frontend/Player.cpp b/frontend/Player.cpp index 9ecbd08..d9974f7 100644 --- a/frontend/Player.cpp +++ b/frontend/Player.cpp @@ -43,12 +43,12 @@ void Player::cmdset_death() {  FollowupAction Player::cmd(Argv argv) {  	if (argv.size() == 0) return FollowupAction::NONE; -	string cmd = argv_pop(argv); +	string cmd = str_title(argv_pop(argv));  	if (this->cmds.contains(cmd))  		return (this->*cmds.at(cmd))(argv); -	print_string(strings::UNKNOWN_CMD); +	str_print(strings::UNKNOWN_CMD);  	return FollowupAction::NONE;  } diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp index ff68109..41c7fc4 100644 --- a/frontend/load_dungeon.cpp +++ b/frontend/load_dungeon.cpp @@ -10,6 +10,8 @@  #include "load_dungeon.h"  #include "Exception.h" +#include "GameData.h" +#include "backend/Object.h"  #include "strings.h"  using namespace std; @@ -37,28 +39,46 @@ unique_ptr<Dungeon> load_dungeon(const string & filename) {  	if (!locations)  		throw Exception("XML-bestand mist een <locaties> tag"); -	LocationFactory factory; +	GameData & gamedata = GameData::get_instance(); +  	struct TempData {  		Location * location;  		unsigned edges[4];  	};  	map<unsigned, TempData> temp_map; +  	for (xml_node & tag : locations) {  		const char * name = tag.text().as_string();  		const char * description = tag.child("beschrijving").text().as_string(); -		// vector<string> objects_hidden = split_string(tag.attribute("objectenverborgen").as_string(), ";"); -		// vector<string> objects_visible = split_string(tag.attribute("objectenzichtbaar").as_string(), ";"); -		// vector<string> enemies = split_string(tag.attribute("vijand").as_string(), ";"); +		Location * location = LocationFactory::create_location(name, description); -		Location * location = factory.create_location(name, description); +		vector<string> objects_hidden = str_split(tag.attribute("objectenverborgen").as_string(), ";"); +		for (string & name : objects_hidden) { +			Object * object = gamedata.create_object(name); +			object->set_hidden(true); +			location->add_object(object); +		} +		vector<string> objects_visible = str_split(tag.attribute("objectenzichtbaar").as_string(), ";"); +		for (string & name : objects_visible) { +			Object * object = gamedata.create_object(name); +			object->set_hidden(false); +			location->add_object(object); +		} +	 +		vector<string> 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::EAST]  = tag.attribute("oost").as_uint(0),  				[Direction::SOUTH] = tag.attribute("zuid").as_uint(0), -				[Direction::WEST] = tag.attribute("west").as_uint(0), +				[Direction::WEST]  = tag.attribute("west").as_uint(0),  			},  		};  		dungeon->add_location(location); diff --git a/frontend/main.cpp b/frontend/main.cpp index a5514bd..deacdc5 100644 --- a/frontend/main.cpp +++ b/frontend/main.cpp @@ -16,7 +16,7 @@ using namespace std;  static unique_ptr<Dungeon> make_dungeon() noexcept {  	while (1) { -		print_string(strings::INTRO); +		str_print(strings::INTRO);  		string filename = rl();  		try {  			if (filename.size() == 0) { @@ -37,7 +37,7 @@ FollowupAction game_main() {  	while (1) {  		string line = rl();  		if (line.length() == 0) continue; -		vector<string> argv = split_string(line, " "); +		vector<string> argv = str_split(line, " ");  		FollowupAction action = player.cmd(argv);  		switch (action) { diff --git a/frontend/strings.cpp b/frontend/strings.cpp index bb4a419..70fed85 100644 --- a/frontend/strings.cpp +++ b/frontend/strings.cpp @@ -1,13 +1,15 @@ +#include <algorithm> +  #include "strings.h"  #include "print.h"  using namespace std; -void print_string(const char * str) { -	lprtf("%s\n", wrap_string(str).c_str()); +void str_print(const char * str) { +	lprtf("%s\n", str_wrap(str).c_str());  } -string wrap_string(const char * str) { +string str_wrap(const char * str) {  	string out;  	for (; *str != '\0'; str++) { @@ -27,7 +29,8 @@ string wrap_string(const char * str) {  	return out;  } -vector<string> split_string(const string & src, const string & delim) { +vector<string> str_split(const string & src, const string & delim) { +	if (src.size() == 0) return {};  	vector<string> out;  	size_t start = 0;  	size_t end = src.find(delim); @@ -42,3 +45,16 @@ vector<string> split_string(const string & src, const string & delim) {  	return out;  } +string str_lower(const string & input) { +	string out = input; +	transform(out.begin(), out.end(), out.begin(), [](unsigned char c){ return tolower(c); }); +	return out; +} + +string str_title(const string & input) { +	if (input.size() == 0) return ""; +	string out = str_lower(input); +	out[0] = toupper(out[0]); +	return out; +} + diff --git a/frontend/strings.h b/frontend/strings.h index 678667e..affc835 100644 --- a/frontend/strings.h +++ b/frontend/strings.h @@ -15,9 +15,10 @@ bestaande acties te zien.)";  } -void print_string(const char *); +void str_print(const char *); -std::string wrap_string(const char *); - -std::vector<std::string> split_string(const std::string & src, const std::string & delim); +std::string str_wrap(const char *); +std::vector<std::string> str_split(const std::string & src, const std::string & delim); +std::string str_lower(const std::string & input); +std::string str_title(const std::string & input);  |