From 99315174a8b8dee2f279185ecf803ed01bf54580 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Tue, 29 Oct 2019 11:19:25 +0100 Subject: [PATCH] Initial support for setting battle choices. --- src/Battling/Models/Battle.cpp | 16 +++++ src/Battling/Models/Battle.hpp | 4 ++ src/Battling/Models/BattleSide.cpp | 34 ++++++++++ src/Battling/Models/BattleSide.hpp | 18 +++++ src/Battling/Models/Creature.cpp | 14 ++++ src/Battling/Models/Creature.hpp | 7 ++ src/Battling/TurnChoices/AttackTurnChoice.hpp | 20 ++++++ src/Battling/TurnChoices/BaseTurnChoice.hpp | 21 ++++++ src/Battling/TurnChoices/PassTurnChoice.hpp | 17 +++++ src/Battling/TurnChoices/TurnChoiceKind.hpp | 15 ++++ tests/BattleTests/ChoiceSetTests.cpp | 68 +++++++++++++++++++ tests/TestLibrary/TestLibrary.cpp | 5 -- 12 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 src/Battling/TurnChoices/AttackTurnChoice.hpp create mode 100644 src/Battling/TurnChoices/BaseTurnChoice.hpp create mode 100644 src/Battling/TurnChoices/PassTurnChoice.hpp create mode 100644 src/Battling/TurnChoices/TurnChoiceKind.hpp create mode 100644 tests/BattleTests/ChoiceSetTests.cpp diff --git a/src/Battling/Models/Battle.cpp b/src/Battling/Models/Battle.cpp index 3116133..a5c37d3 100644 --- a/src/Battling/Models/Battle.cpp +++ b/src/Battling/Models/Battle.cpp @@ -1,5 +1,21 @@ #include "Battle.hpp" +#include "../TurnChoices/AttackTurnChoice.hpp" const CreatureLib::Battling::BattleLibrary *CreatureLib::Battling::Battle::GetLibrary() const { return _library; } + +bool CreatureLib::Battling::Battle::CanUse(CreatureLib::Battling::BaseTurnChoice *choice) { + if (choice->GetKind() == TurnChoiceKind::Attack) + //HOOK: change number of uses needed. + return static_cast(choice)->GetAttack()->GetRemainingUses() > 1; + } + return true; +} + +bool CreatureLib::Battling::Battle::TrySetChoice(CreatureLib::Battling::BaseTurnChoice *choice) { + if (!CanUse(choice)) + return false; + choice->GetUser()->GetBattleSide()->SetChoice(choice); + return true; +} diff --git a/src/Battling/Models/Battle.hpp b/src/Battling/Models/Battle.hpp index e33cfcf..03ff862 100644 --- a/src/Battling/Models/Battle.hpp +++ b/src/Battling/Models/Battle.hpp @@ -4,6 +4,7 @@ #include #include "BattleSide.hpp" #include "../Library/BattleLibrary.hpp" +#include "../TurnChoices/BaseTurnChoice.hpp" namespace CreatureLib::Battling { class Battle { @@ -11,6 +12,9 @@ namespace CreatureLib::Battling { std::vector _sides; public: const BattleLibrary* GetLibrary() const; + + virtual bool CanUse(BaseTurnChoice* choice); + virtual bool TrySetChoice(BaseTurnChoice* choice); }; } diff --git a/src/Battling/Models/BattleSide.cpp b/src/Battling/Models/BattleSide.cpp index a53c5bb..aae4eba 100644 --- a/src/Battling/Models/BattleSide.cpp +++ b/src/Battling/Models/BattleSide.cpp @@ -1 +1,35 @@ #include "BattleSide.hpp" +#include + +using namespace CreatureLib::Battling; + +bool BattleSide::AllChoicesSet() const { + for (uint8_t i = 0; i < _creaturesPerSide; i++){ + if (_choices[i] == nullptr){ + return false; + } + } + return true; +} + +void BattleSide::ResetChoices() { + for (uint8_t i = 0; i < _creaturesPerSide; i++){ + _choices[i] = nullptr; + } +} + +const std::vector& BattleSide::GetChoices() const{ + return _choices; +} + +void BattleSide::SetChoice(const BaseTurnChoice *choice) { + auto find = std::find(_creatures.begin(), _creatures.end(), choice->GetUser()); + if (find ==_creatures.end()) + throw "User not found"; + uint8_t index = std::distance(_creatures.begin(),find); + _choices[index] = choice; +} + +void BattleSide::SetCreature(Creature *creature, uint8_t index) { + _creatures[index] = creature; +} diff --git a/src/Battling/Models/BattleSide.hpp b/src/Battling/Models/BattleSide.hpp index 26a1fa8..ac0f31c 100644 --- a/src/Battling/Models/BattleSide.hpp +++ b/src/Battling/Models/BattleSide.hpp @@ -3,10 +3,28 @@ #include #include "Creature.hpp" +#include "../TurnChoices/BaseTurnChoice.hpp" namespace CreatureLib::Battling{ class BattleSide { + uint8_t _creaturesPerSide; std::vector _creatures; + std::vector _choices; + public: + BattleSide(uint8_t creaturesPerSide) + : _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), _choices(creaturesPerSide) + { + ResetChoices(); + } + + [[nodiscard]] bool AllChoicesSet() const; + [[nodiscard]] const std::vector& GetChoices() const; + + void SetChoice(const BaseTurnChoice* choice); + void ResetChoices(); + + void SetCreature(Creature* creature, uint8_t index); + }; } diff --git a/src/Battling/Models/Creature.cpp b/src/Battling/Models/Creature.cpp index 57e3fb1..4469a09 100644 --- a/src/Battling/Models/Creature.cpp +++ b/src/Battling/Models/Creature.cpp @@ -49,6 +49,11 @@ const std::string &Battling::Creature::GetTalent() const { return __Variant->GetTalent(_talentIndex); } +void Battling::Creature::SetBattleData(Battling::Battle *battle, Battling::BattleSide *side) { + _battle = battle; + _side = side; +} + //region Stat APIs void Battling::Creature::ChangeStatBoost(Core::Statistic stat, int8_t diffAmount){ @@ -98,4 +103,13 @@ void Battling::Creature::RecalculateBoostedStat(Core::Statistic stat) { this->_boostedStats.SetStat(stat, s); } +Battling::Battle *Battling::Creature::GetBattle() const{ + return _battle; +} + +Battling::BattleSide *Battling::Creature::GetBattleSide() const { + return _side; +} + + //endregion diff --git a/src/Battling/Models/Creature.hpp b/src/Battling/Models/Creature.hpp index 09e407d..dfefec0 100644 --- a/src/Battling/Models/Creature.hpp +++ b/src/Battling/Models/Creature.hpp @@ -8,6 +8,7 @@ namespace CreatureLib::Battling{ // Forward declare battle class class Battle; + class BattleSide; class Creature { GetProperty(const Library::CreatureSpecies*, Species); @@ -29,6 +30,7 @@ namespace CreatureLib::Battling{ Core::StatisticSet _boostedStats; Battle* _battle; + BattleSide* _side; BattleLibrary* _library; std::string _nickname = ""; @@ -46,6 +48,11 @@ namespace CreatureLib::Battling{ void ChangeLevel(int8_t amount); + void SetBattleData(Battle* battle, BattleSide* side); + + Battle* GetBattle() const; + BattleSide* GetBattleSide() const; + //region Stat APIs void SetBattle(Battle* battle); diff --git a/src/Battling/TurnChoices/AttackTurnChoice.hpp b/src/Battling/TurnChoices/AttackTurnChoice.hpp new file mode 100644 index 0000000..87d46ca --- /dev/null +++ b/src/Battling/TurnChoices/AttackTurnChoice.hpp @@ -0,0 +1,20 @@ +#ifndef CREATURELIB_ATTACKTURNCHOICE_HPP +#define CREATURELIB_ATTACKTURNCHOICE_HPP + +#include "BaseTurnChoice.hpp" +#include "../Models/LearnedAttack.hpp" + +namespace CreatureLib::Battling{ + class AttackTurnChoice : public BaseTurnChoice { + LearnedAttack* _attack; + public: + AttackTurnChoice(Creature* c) : BaseTurnChoice(c){} + + inline LearnedAttack* GetAttack() const{ + return _attack; + } + }; +} + + +#endif //CREATURELIB_ATTACKTURNCHOICE_HPP diff --git a/src/Battling/TurnChoices/BaseTurnChoice.hpp b/src/Battling/TurnChoices/BaseTurnChoice.hpp new file mode 100644 index 0000000..9dfbe1b --- /dev/null +++ b/src/Battling/TurnChoices/BaseTurnChoice.hpp @@ -0,0 +1,21 @@ +#ifndef CREATURELIB_BASETURNCHOICE_HPP +#define CREATURELIB_BASETURNCHOICE_HPP + +#include "TurnChoiceKind.hpp" + +namespace CreatureLib::Battling{ + class BaseTurnChoice { + Creature* _user; + protected: + BaseTurnChoice(Creature* user) : _user(user){}; + public: + virtual ~BaseTurnChoice() = default; + [[nodiscard]] virtual TurnChoiceKind GetKind() const = 0; + [[nodiscard]] inline Creature* GetUser() const{ + return _user; + } + }; +} + + +#endif //CREATURELIB_BASETURNCHOICE_HPP diff --git a/src/Battling/TurnChoices/PassTurnChoice.hpp b/src/Battling/TurnChoices/PassTurnChoice.hpp new file mode 100644 index 0000000..ce2013d --- /dev/null +++ b/src/Battling/TurnChoices/PassTurnChoice.hpp @@ -0,0 +1,17 @@ +#ifndef CREATURELIB_PASSTURNCHOICE_HPP +#define CREATURELIB_PASSTURNCHOICE_HPP + +#include "BaseTurnChoice.hpp" + +namespace CreatureLib::Battling { + class PassTurnChoice : public BaseTurnChoice{ + public: + PassTurnChoice(Creature* c) : BaseTurnChoice(c){} + + TurnChoiceKind GetKind() const override { + return TurnChoiceKind ::Pass; + } + }; +} + +#endif //CREATURELIB_PASSTURNCHOICE_HPP diff --git a/src/Battling/TurnChoices/TurnChoiceKind.hpp b/src/Battling/TurnChoices/TurnChoiceKind.hpp new file mode 100644 index 0000000..8299a20 --- /dev/null +++ b/src/Battling/TurnChoices/TurnChoiceKind.hpp @@ -0,0 +1,15 @@ +#ifndef CREATURELIB_TURNCHOICEKIND_HPP +#define CREATURELIB_TURNCHOICEKIND_HPP + +#include + +namespace CreatureLib::Battling { + enum class TurnChoiceKind : uint8_t { + Pass, + Attack, + Item, + Switch, + RunAway + }; +} +#endif //CREATURELIB_TURNCHOICEKIND_HPP diff --git a/tests/BattleTests/ChoiceSetTests.cpp b/tests/BattleTests/ChoiceSetTests.cpp new file mode 100644 index 0000000..fdb09bf --- /dev/null +++ b/tests/BattleTests/ChoiceSetTests.cpp @@ -0,0 +1,68 @@ +#ifdef TESTS_BUILD + +#include "../TestLibrary/TestLibrary.cpp" +#include "../../src/Battling/Models/BattleSide.hpp" +#include "../../src/Battling/Models/CreateCreature.hpp" +#include "../../src/Battling/TurnChoices/PassTurnChoice.hpp" + +using namespace CreatureLib::Battling; + +TEST_CASE( "Set Choice one-sized side", "[Battling]" ) { + auto side = BattleSide(1); + auto c = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); + side.SetCreature(c, 0); + auto choice = new PassTurnChoice(c); + side.SetChoice(choice); + delete choice; + delete c; +} + +TEST_CASE( "Set Choice one-sized side, validate all choices set", "[Battling]" ) { + auto side = BattleSide(1); + auto c = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); + side.SetCreature(c, 0); + auto choice = new PassTurnChoice(c); + REQUIRE_FALSE(side.AllChoicesSet()); + side.SetChoice(choice); + REQUIRE(side.AllChoicesSet()); + delete choice; + delete c; +} + +TEST_CASE( "Set Choice two-sized side", "[Battling]" ) { + auto side = BattleSide(2); + auto c1 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); + auto c2 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); + side.SetCreature(c1, 0); + side.SetCreature(c2, 1); + auto choice1 = new PassTurnChoice(c1); + auto choice2 = new PassTurnChoice(c2); + side.SetChoice(choice1); + side.SetChoice(choice2); + delete choice1; + delete choice2; + delete c1; + delete c2; +} + +TEST_CASE( "Set Choice two-sized side, validate all choices set", "[Battling]" ) { + auto side = BattleSide(2); + auto c1 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); + auto c2 = CreateCreature(GetLibrary(), "testSpecies1", 5).Create(); + side.SetCreature(c1, 0); + side.SetCreature(c2, 1); + auto choice1 = new PassTurnChoice(c1); + auto choice2 = new PassTurnChoice(c2); + REQUIRE_FALSE(side.AllChoicesSet()); + side.SetChoice(choice1); + REQUIRE_FALSE(side.AllChoicesSet()); + side.SetChoice(choice2); + REQUIRE(side.AllChoicesSet()); + delete choice1; + delete choice2; + delete c1; + delete c2; +} + + +#endif \ No newline at end of file diff --git a/tests/TestLibrary/TestLibrary.cpp b/tests/TestLibrary/TestLibrary.cpp index f320211..95bb5f8 100644 --- a/tests/TestLibrary/TestLibrary.cpp +++ b/tests/TestLibrary/TestLibrary.cpp @@ -1,11 +1,6 @@ #ifdef TESTS_BUILD #include "../../extern/catch.hpp" #include "../../src/Battling/Library/BattleLibrary.hpp" -#include "../../src/Library/SpeciesLibrary.hpp" -#include "../../src/Library/AttackLibrary.hpp" -#include "../../src/Library/ItemLibrary.hpp" -#include "../../src/Library/GrowthRates/GrowthRateLibrary.hpp" -#include "../../src/Library/DataLibrary.hpp" using namespace CreatureLib::Core; using namespace CreatureLib::Library;