Files
pokemon-battle-engine/include/types.h
2025-08-14 23:11:46 +00:00

195 lines
6.4 KiB
C++

#ifndef POKEMON_TYPES_H
#define POKEMON_TYPES_H
#include <cstdint>
#include <array>
#include <string_view>
#include <optional>
#include <vector>
namespace PokemonSim {
// Forward declarations
enum class Type : uint8_t;
struct TypeChartEntry;
// Type enumeration - ordered for optimal cache performance
enum class Type : uint8_t {
NONE = 0,
NORMAL,
FIRE,
WATER,
ELECTRIC,
GRASS,
ICE,
FIGHTING,
POISON,
GROUND,
FLYING,
PSYCHIC,
BUG,
ROCK,
GHOST,
DRAGON,
DARK, // Generation 2+
STEEL, // Generation 2+
FAIRY, // Generation 6+
TYPE_COUNT // Keep this last for array sizing
};
// Type multipliers as integers (multiply by 2 for 0.5x, 4 for 0.25x, etc.)
enum class TypeMultiplier : uint8_t {
ZERO = 0, // 0x damage (immune)
QUARTER = 1, // 0.25x damage
HALF = 2, // 0.5x damage
NEUTRAL = 4, // 1x damage (neutral)
DOUBLE = 8, // 2x damage
QUADRUPLE = 16 // 4x damage
};
// Generation support
enum class Generation : uint8_t {
GENERATION_1 = 1,
GENERATION_2 = 2,
GENERATION_3 = 3,
GENERATION_4 = 4,
GENERATION_5 = 5,
GENERATION_6 = 6,
GENERATION_7 = 7,
GENERATION_8 = 8,
GENERATION_9 = 9
};
// Compile-time type chart traits
template <Generation Gen>
struct TypeChartTraits {
static constexpr size_t TYPE_COUNT = static_cast<size_t>(Type::TYPE_COUNT);
static constexpr size_t CHART_SIZE = TYPE_COUNT * TYPE_COUNT;
// Each generation has its own type chart
static const std::array<TypeMultiplier, CHART_SIZE>& getTypeChart();
};
// Pokemon type representation
class PokemonTypes {
public:
PokemonTypes() = default;
PokemonTypes(Type primary) : primary_(primary), secondary_(Type::NONE) {}
PokemonTypes(Type primary, Type secondary) : primary_(primary), secondary_(secondary) {}
Type getPrimary() const { return primary_; }
Type getSecondary() const { return secondary_; }
bool hasSecondary() const { return secondary_ != Type::NONE; }
void setPrimary(Type type) { primary_ = type; }
void setSecondary(Type type) { secondary_ = type; }
private:
Type primary_{Type::NONE};
Type secondary_{Type::NONE};
};
// Type utility functions
class TypeUtils {
public:
// Convert string to Type enum
static std::optional<Type> stringToType(std::string_view typeStr);
// Convert Type enum to string
static std::string_view typeToString(Type type);
// Get type effectiveness multiplier
template <Generation Gen>
static TypeMultiplier getTypeEffectiveness(Type attackType, Type defendType);
// Calculate damage multiplier for dual-type Pokemon
template <Generation Gen>
static uint32_t calculateDamageMultiplier(Type attackType, const PokemonTypes& defenderTypes);
// Load type chart from JSON file
template <Generation Gen>
static bool loadTypeChartFromFile(const std::string& filename);
public:
// Type chart storage for each generation (public for template access)
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_1>::CHART_SIZE> s_gen1Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_2>::CHART_SIZE> s_gen2Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_3>::CHART_SIZE> s_gen3Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_4>::CHART_SIZE> s_gen4Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_5>::CHART_SIZE> s_gen5Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_6>::CHART_SIZE> s_gen6Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_7>::CHART_SIZE> s_gen7Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_8>::CHART_SIZE> s_gen8Chart;
static std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_9>::CHART_SIZE> s_gen9Chart;
};
// High-performance damage calculation
template <Generation Gen>
inline uint32_t calculateDamage(uint32_t baseDamage, Type attackType, const PokemonTypes& defenderTypes) {
uint32_t rawMultiplier = TypeUtils::calculateDamageMultiplier<Gen>(attackType, defenderTypes);
// Apply the multiplier: damage = (baseDamage * rawMultiplier) / 4
// Since our multipliers are: 0, 1, 2, 4, 8, 16 representing 0x, 0.25x, 0.5x, 1x, 2x, 4x
// We divide by 4 (NEUTRAL) to normalize back to actual damage multiplier
return (baseDamage * rawMultiplier) / static_cast<uint32_t>(TypeMultiplier::NEUTRAL);
}
// Template specializations for type chart access
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_1>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_1>::getTypeChart() {
return TypeUtils::s_gen1Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_2>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_2>::getTypeChart() {
return TypeUtils::s_gen2Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_3>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_3>::getTypeChart() {
return TypeUtils::s_gen3Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_4>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_4>::getTypeChart() {
return TypeUtils::s_gen4Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_5>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_5>::getTypeChart() {
return TypeUtils::s_gen5Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_6>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_6>::getTypeChart() {
return TypeUtils::s_gen6Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_7>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_7>::getTypeChart() {
return TypeUtils::s_gen7Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_8>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_8>::getTypeChart() {
return TypeUtils::s_gen8Chart;
}
template <>
inline const std::array<TypeMultiplier, TypeChartTraits<Generation::GENERATION_9>::CHART_SIZE>&
TypeChartTraits<Generation::GENERATION_9>::getTypeChart() {
return TypeUtils::s_gen9Chart;
}
} // namespace PokemonSim
#endif // POKEMON_TYPES_H