Implement basic library class that other libraries inherit from for performance.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
a47f60cdf7
commit
d6ea16b467
|
@ -24,14 +24,14 @@ CreateCreature* CreateCreature::WithAttack(const std::string& attackName, Attack
|
|||
if (_attacks.size() >= _library->GetSettings()->GetMaximalMoves())
|
||||
throw CreatureException("You have already set the maximum amount of allowed moves.");
|
||||
|
||||
auto attackData = _library->GetAttackLibrary()->GetAttack(attackName);
|
||||
auto attackData = _library->GetAttackLibrary()->Get(attackName.c_str());
|
||||
_attacks.emplace_back(attackData, learnMethod);
|
||||
return this;
|
||||
}
|
||||
|
||||
Creature* CreateCreature::Create() {
|
||||
auto rand = Core::Random();
|
||||
auto species = this->_library->GetSpeciesLibrary()->GetSpecies(this->_species);
|
||||
auto species = this->_library->GetSpeciesLibrary()->Get(this->_species.c_str());
|
||||
auto variant = species->GetVariant(this->_variant);
|
||||
int8_t talent;
|
||||
if (this->_talent.empty()) {
|
||||
|
@ -49,7 +49,9 @@ Creature* CreateCreature::Create() {
|
|||
}
|
||||
const Library::Item* heldItem = nullptr;
|
||||
if (!this->_heldItem.empty()) {
|
||||
heldItem = _library->GetItemLibrary()->GetItem(this->_heldItem);
|
||||
if (!_library->GetItemLibrary()->TryGet(this->_heldItem.c_str(), heldItem)) {
|
||||
throw CreatureException("Invalid held item.");
|
||||
}
|
||||
}
|
||||
// FIXME: implement experience
|
||||
auto experience = 0;
|
||||
|
|
|
@ -1,37 +1 @@
|
|||
#include "AttackLibrary.hpp"
|
||||
|
||||
bool CreatureLib::Library::AttackLibrary::TryGetAttack(const std::string& name,
|
||||
const CreatureLib::Library::AttackData*& move) const {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
auto find = _attacks.find(key);
|
||||
if (find == _attacks.end()) {
|
||||
move = nullptr;
|
||||
return false;
|
||||
}
|
||||
move = find->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
const CreatureLib::Library::AttackData* CreatureLib::Library::AttackLibrary::GetAttack(const std::string& name) const {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
return this->_attacks.at(key);
|
||||
}
|
||||
|
||||
const CreatureLib::Library::AttackData* CreatureLib::Library::AttackLibrary::operator[](const std::string& name) const {
|
||||
return GetAttack(name);
|
||||
}
|
||||
|
||||
void CreatureLib::Library::AttackLibrary::LoadAttack(const std::string& name,
|
||||
const CreatureLib::Library::AttackData* attack) {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
this->_attacks.insert({key, attack});
|
||||
}
|
||||
|
||||
void CreatureLib::Library::AttackLibrary::DeleteAttack(const std::string& name) {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
this->_attacks.erase(key);
|
||||
}
|
||||
|
|
|
@ -4,31 +4,11 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "Attacks/AttackData.hpp"
|
||||
|
||||
#include "BaseLibrary.hpp"
|
||||
namespace CreatureLib::Library {
|
||||
class AttackLibrary {
|
||||
private:
|
||||
std::unordered_map<std::string, const AttackData*> _attacks;
|
||||
|
||||
class AttackLibrary : public BaseLibrary<AttackData> {
|
||||
public:
|
||||
AttackLibrary(size_t initialCapacity = 32)
|
||||
: _attacks(std::unordered_map<std::string, const AttackData*>(initialCapacity)){};
|
||||
|
||||
virtual ~AttackLibrary() {
|
||||
for (auto attack : _attacks) {
|
||||
delete attack.second;
|
||||
}
|
||||
_attacks.clear();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool TryGetAttack(const std::string& name, const AttackData*& move) const;
|
||||
[[nodiscard]] const AttackData* GetAttack(const std::string& name) const;
|
||||
[[nodiscard]] const AttackData* operator[](const std::string& name) const;
|
||||
|
||||
void LoadAttack(const std::string& name, const AttackData* attack);
|
||||
void DeleteAttack(const std::string& name);
|
||||
|
||||
const std::unordered_map<std::string, const AttackData*>& GetIterator() { return _attacks; }
|
||||
AttackLibrary(size_t initialCapacity = 32) : BaseLibrary(initialCapacity){};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "BaseLibrary.hpp"
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef CREATURELIB_BASELIBRARY_HPP
|
||||
#define CREATURELIB_BASELIBRARY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
namespace CreatureLib::Library {
|
||||
template <class T> class BaseLibrary {
|
||||
inline static constexpr char charToLower(const char c) { return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; }
|
||||
inline static uint32_t constexpr Hash(char const* input) {
|
||||
return charToLower(*input) ? static_cast<uint32_t>(charToLower(*input)) + 33 * Hash(input + 1) : 5381;
|
||||
}
|
||||
|
||||
std::unordered_map<uint32_t, const T*> _values;
|
||||
|
||||
public:
|
||||
BaseLibrary(size_t initialCapacity = 32) : _values(initialCapacity) {}
|
||||
|
||||
virtual ~BaseLibrary() {
|
||||
for (const auto& v : _values) {
|
||||
delete v.second;
|
||||
}
|
||||
_values.clear();
|
||||
}
|
||||
|
||||
inline void Insert(const char* key, const T* value) { _values.insert({Hash(key), value}); }
|
||||
|
||||
inline void Delete(const char* key) { _values.erase(Hash(key)); }
|
||||
|
||||
bool TryGet(const char* name, const T*& out) const {
|
||||
auto find = this->_values.find(Hash(name));
|
||||
if (find == this->_values.end()) {
|
||||
out = nullptr;
|
||||
return false;
|
||||
}
|
||||
out = find->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const T* Get(const char* name) const { return _values.at(Hash(name)); }
|
||||
|
||||
inline const T* operator[](const char* name) const { return Get(name); }
|
||||
|
||||
inline const std::unordered_map<uint32_t, const T*>& GetIterator() const { return _values; }
|
||||
|
||||
size_t GetCount() const { return _values.count(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CREATURELIB_BASELIBRARY_HPP
|
|
@ -1,36 +1 @@
|
|||
#include "ItemLibrary.hpp"
|
||||
|
||||
bool CreatureLib::Library::ItemLibrary::TryGetItem(const std::string& name,
|
||||
const CreatureLib::Library::Item*& item) const {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
auto find = this->_items.find(key);
|
||||
if (find == this->_items.end()) {
|
||||
item = nullptr;
|
||||
return false;
|
||||
}
|
||||
item = find->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
const CreatureLib::Library::Item* CreatureLib::Library::ItemLibrary::GetItem(const std::string& name) const {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
return this->_items.at(key);
|
||||
}
|
||||
|
||||
const CreatureLib::Library::Item* CreatureLib::Library::ItemLibrary::operator[](const std::string& name) const {
|
||||
return this->GetItem(name);
|
||||
}
|
||||
|
||||
void CreatureLib::Library::ItemLibrary::LoadItem(const std::string& name, const CreatureLib::Library::Item* item) {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
this->_items.insert({key, item});
|
||||
}
|
||||
|
||||
void CreatureLib::Library::ItemLibrary::DeleteItem(const std::string& name) {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
this->_items.erase(key);
|
||||
}
|
||||
|
|
|
@ -3,26 +3,13 @@
|
|||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "BaseLibrary.hpp"
|
||||
#include "Items/Item.hpp"
|
||||
|
||||
namespace CreatureLib::Library {
|
||||
class ItemLibrary {
|
||||
private:
|
||||
std::unordered_map<std::string, const Item*> _items;
|
||||
|
||||
class ItemLibrary : public BaseLibrary<Item> {
|
||||
public:
|
||||
ItemLibrary(size_t initialCapacity = 32)
|
||||
: _items(std::unordered_map<std::string, const Item*>(initialCapacity)){};
|
||||
virtual ~ItemLibrary() { _items.clear(); }
|
||||
|
||||
[[nodiscard]] bool TryGetItem(const std::string& name, const Item*& item) const;
|
||||
[[nodiscard]] const Item* GetItem(const std::string& name) const;
|
||||
[[nodiscard]] const Item* operator[](const std::string& name) const;
|
||||
|
||||
void LoadItem(const std::string& name, const Item* item);
|
||||
void DeleteItem(const std::string& name);
|
||||
|
||||
const std::unordered_map<std::string, const Item*>& GetIterator() { return _items; }
|
||||
ItemLibrary(size_t initialCapacity = 32) : BaseLibrary(initialCapacity){};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,39 +1 @@
|
|||
#include "SpeciesLibrary.hpp"
|
||||
|
||||
bool CreatureLib::Library::SpeciesLibrary::TryGetSpecies(
|
||||
const std::string& name, const CreatureLib::Library::CreatureSpecies*& outSpecies) const {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
auto find = _species.find(key);
|
||||
if (find == _species.end()) {
|
||||
outSpecies = nullptr;
|
||||
return false;
|
||||
}
|
||||
outSpecies = find->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
const CreatureLib::Library::CreatureSpecies*
|
||||
CreatureLib::Library::SpeciesLibrary::GetSpecies(const std::string& name) const {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
return _species.at(key);
|
||||
}
|
||||
|
||||
const CreatureLib::Library::CreatureSpecies*
|
||||
CreatureLib::Library::SpeciesLibrary::operator[](const std::string& name) const {
|
||||
return GetSpecies(name);
|
||||
}
|
||||
|
||||
void CreatureLib::Library::SpeciesLibrary::LoadSpecies(const std::string& name,
|
||||
const CreatureLib::Library::CreatureSpecies* species) {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
_species.insert({key, species});
|
||||
}
|
||||
|
||||
void CreatureLib::Library::SpeciesLibrary::DeleteSpecies(const std::string& name) {
|
||||
std::string key = name;
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
_species.erase(key);
|
||||
}
|
||||
|
|
|
@ -3,33 +3,14 @@
|
|||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "BaseLibrary.hpp"
|
||||
#include "CreatureData/CreatureSpecies.hpp"
|
||||
|
||||
namespace CreatureLib::Library {
|
||||
class SpeciesLibrary {
|
||||
class SpeciesLibrary : public BaseLibrary<CreatureSpecies> {
|
||||
private:
|
||||
std::unordered_map<std::string, const CreatureSpecies*> _species;
|
||||
|
||||
public:
|
||||
SpeciesLibrary(size_t initialCapacity = 32)
|
||||
: _species(std::unordered_map<std::string, const CreatureSpecies*>(initialCapacity)){};
|
||||
|
||||
virtual ~SpeciesLibrary() {
|
||||
for (auto s : _species)
|
||||
delete s.second;
|
||||
_species.clear();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool TryGetSpecies(const std::string& name, const CreatureSpecies*& outSpecies) const;
|
||||
[[nodiscard]] const CreatureSpecies* GetSpecies(const std::string& name) const;
|
||||
[[nodiscard]] const CreatureSpecies* operator[](const std::string& name) const;
|
||||
|
||||
void LoadSpecies(const std::string& name, const CreatureSpecies* species);
|
||||
void DeleteSpecies(const std::string& name);
|
||||
|
||||
size_t GetCount() const { return _species.size(); }
|
||||
|
||||
const std::unordered_map<std::string, const CreatureSpecies*>& GetIterator() { return _species; }
|
||||
SpeciesLibrary(size_t initialCapacity = 32) : BaseLibrary(initialCapacity){};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ TEST_CASE("Turn ordering: Attack before pass", "[Battling]") {
|
|||
|
||||
TEST_CASE("Turn ordering: High priority goes before no priority", "[Battling]") {
|
||||
auto l = TestLibrary::Get()->GetAttackLibrary();
|
||||
auto a1 = new LearnedAttack(l->GetAttack("standard"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->GetAttack("highPriority"), AttackLearnMethod::Unknown);
|
||||
auto a1 = new LearnedAttack(l->Get("standard"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->Get("highPriority"), AttackLearnMethod::Unknown);
|
||||
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0));
|
||||
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0));
|
||||
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2};
|
||||
|
@ -50,8 +50,8 @@ TEST_CASE("Turn ordering: High priority goes before no priority", "[Battling]")
|
|||
|
||||
TEST_CASE("Turn ordering: Higher priority goes before high priority", "[Battling]") {
|
||||
auto l = TestLibrary::Get()->GetAttackLibrary();
|
||||
auto a1 = new LearnedAttack(l->GetAttack("highPriority"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->GetAttack("higherPriority"), AttackLearnMethod::Unknown);
|
||||
auto a1 = new LearnedAttack(l->Get("highPriority"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->Get("higherPriority"), AttackLearnMethod::Unknown);
|
||||
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0));
|
||||
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0));
|
||||
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2};
|
||||
|
@ -72,8 +72,8 @@ TEST_CASE("Turn ordering: Higher priority goes before high priority", "[Battling
|
|||
|
||||
TEST_CASE("Turn ordering: High priority goes before low priority", "[Battling]") {
|
||||
auto l = TestLibrary::Get()->GetAttackLibrary();
|
||||
auto a1 = new LearnedAttack(l->GetAttack("lowPriority"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->GetAttack("higherPriority"), AttackLearnMethod::Unknown);
|
||||
auto a1 = new LearnedAttack(l->Get("lowPriority"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->Get("higherPriority"), AttackLearnMethod::Unknown);
|
||||
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0));
|
||||
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0));
|
||||
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2};
|
||||
|
@ -94,8 +94,8 @@ TEST_CASE("Turn ordering: High priority goes before low priority", "[Battling]")
|
|||
|
||||
TEST_CASE("Turn ordering: No priority goes before low priority", "[Battling]") {
|
||||
auto l = TestLibrary::Get()->GetAttackLibrary();
|
||||
auto a1 = new LearnedAttack(l->GetAttack("lowPriority"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->GetAttack("standard"), AttackLearnMethod::Unknown);
|
||||
auto a1 = new LearnedAttack(l->Get("lowPriority"), AttackLearnMethod::Unknown);
|
||||
auto a2 = new LearnedAttack(l->Get("standard"), AttackLearnMethod::Unknown);
|
||||
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0));
|
||||
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0));
|
||||
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2};
|
||||
|
|
|
@ -22,25 +22,25 @@ BattleLibrary* TestLibrary::Get() {
|
|||
|
||||
SpeciesLibrary* TestLibrary::BuildSpeciesLibrary() {
|
||||
auto l = new SpeciesLibrary();
|
||||
l->LoadSpecies("testSpecies1",
|
||||
new CreatureSpecies(
|
||||
0, "testSpecies1",
|
||||
new SpeciesVariant("default", 1, 1, 10, {0, 1}, StatisticSet<uint16_t>(10, 10, 10, 10, 10, 10),
|
||||
{"testTalent"}, {"testSecretTalent"}, new LearnableAttacks(100)),
|
||||
0.5f, "testGrowthRate", 5));
|
||||
l->Insert("testSpecies1",
|
||||
new CreatureSpecies(0, "testSpecies1",
|
||||
new SpeciesVariant("default", 1, 1, 10, {0, 1},
|
||||
StatisticSet<uint16_t>(10, 10, 10, 10, 10, 10), {"testTalent"},
|
||||
{"testSecretTalent"}, new LearnableAttacks(100)),
|
||||
0.5f, "testGrowthRate", 5));
|
||||
return l;
|
||||
}
|
||||
|
||||
AttackLibrary* TestLibrary::BuildAttackLibrary() {
|
||||
auto l = new AttackLibrary();
|
||||
l->LoadAttack("standard", new AttackData("standard", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, 0, {}));
|
||||
l->LoadAttack("highPriority", new AttackData("highPriority", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, 1, {}));
|
||||
l->LoadAttack("higherPriority", new AttackData("higherPriority", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, 2, {}));
|
||||
l->LoadAttack("lowPriority", new AttackData("lowPriority", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, -1, {}));
|
||||
l->Insert("standard", new AttackData("standard", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, 0, {}));
|
||||
l->Insert("highPriority", new AttackData("highPriority", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, 1, {}));
|
||||
l->Insert("higherPriority", new AttackData("higherPriority", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, 2, {}));
|
||||
l->Insert("lowPriority", new AttackData("lowPriority", 0, AttackCategory::Physical, 20, 100, 30,
|
||||
AttackTarget::AdjacentOpponent, -1, {}));
|
||||
return l;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue