#include "LearnableAttacks.hpp" namespace CreatureLib::Library { struct LearnableAttacks::impl { private: ArbUt::Dictionary>> _learnedByLevel; ArbUt::List> _distinctLevelAttacks; public: explicit impl(level_int_t levelAttackCapacity) : _learnedByLevel(ArbUt::Dictionary>>( levelAttackCapacity)) {} ~impl() = default; void AddLevelAttack(level_int_t level, const ArbUt::BorrowedPtr& attack) { if (_learnedByLevel.Has(level)) { _learnedByLevel[level].Append(attack); } else { _learnedByLevel.Insert(level, {attack}); } if (!_distinctLevelAttacks.Contains(attack)) { _distinctLevelAttacks.Append(attack); } } inline bool HasAttacksForLevel(level_int_t level) const noexcept { return _learnedByLevel.Has(level); } inline const ArbUt::List>& GetAttacksForLevel(level_int_t level) const { if (!_learnedByLevel.Has(level)) { THROW("No attacks found for level " << (uint32_t)level << "."); } return _learnedByLevel.Get(level); } inline const ArbUt::List>& GetDistinctLevelAttacks() const noexcept { return _distinctLevelAttacks; } std::optional> GetRandomAttack(ArbUt::Random& rand) const { if (_distinctLevelAttacks.Count() == 0) { return {}; } auto val = rand.Get(_distinctLevelAttacks.Count()); auto it = _distinctLevelAttacks.begin(); std::advance(it, val); return *it; } }; LearnableAttacks::LearnableAttacks(level_int_t levelAttackCapacity) : _impl(new impl(levelAttackCapacity)) {} LearnableAttacks::~LearnableAttacks() = default; void LearnableAttacks::AddLevelAttack(level_int_t level, ArbUt::BorrowedPtr attack) { _impl->AddLevelAttack(level, attack); } bool LearnableAttacks::HasAttacksForLevel(level_int_t level) const noexcept { return _impl->HasAttacksForLevel(level); } const ArbUt::List>& LearnableAttacks::GetAttacksForLevel(level_int_t level) const { return _impl->GetAttacksForLevel(level); } const ArbUt::List>& LearnableAttacks::GetDistinctLevelAttacks() const noexcept { return _impl->GetDistinctLevelAttacks(); } std::optional> LearnableAttacks::GetRandomAttack(ArbUt::Random& rand) const { return _impl->GetRandomAttack(rand); } }