195 lines
6.4 KiB
C++
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
|