Files
pokemon-battle-engine/POKEMON_TABLE_README.md
2025-08-20 16:00:00 +09:00

6.4 KiB

Pokemon Table Implementation

This document describes the high-performance Pokemon data table implementation for the Pokemon Battle Simulator.

Overview

The Pokemon Table is a high-performance data structure that provides O(1) lookup access to all Pokemon species data. It loads Pokemon data from JSON files and stores them in memory for fast runtime access.

Features

  • O(1) ID-based lookup: Access any Pokemon by its ID in constant time
  • O(1) Name-based lookup: Access any Pokemon by its name using a hash map
  • Automatic data loading: Loads all Pokemon data from JSON files at startup
  • Memory efficient: Uses contiguous memory storage for optimal cache performance
  • Type safety: Strongly typed with comprehensive error handling
  • Validation: Built-in data validation to ensure integrity

Architecture

Core Classes

PokemonTable

The main class that manages the Pokemon data table.

Key Methods:

  • loadFromDataDirectory(): Loads Pokemon data from the standard data directory
  • loadFromFiles(): Loads Pokemon data from specific JSON files
  • getPokemon(uint16_t id): O(1) lookup by Pokemon ID
  • getPokemonByName(std::string_view name): O(1) lookup by Pokemon name
  • hasPokemon(uint16_t id): Check if a Pokemon ID exists
  • size(): Get the total number of loaded Pokemon
  • validate(): Validate the integrity of loaded data

PokemonSpecies

Struct containing all the data for a single Pokemon species.

Fields:

  • id: Pokemon ID (1-based)
  • name: Pokemon name
  • base_stats: Base stats (HP, Attack, Defense, SpAttack, SpDefense, Speed)
  • types: Primary and secondary types

Global Access

The implementation provides a global Pokemon table instance for convenient access:

#include "core/pokemon_table.h"

// Initialize the global table (call once at startup)
bool success = PokEng::initializePokemonTable();

// Use the global table
const auto* bulbasaur = PokEng::g_pokemonTable->getPokemon(1);
const auto* charizard = PokEng::g_pokemonTable->getPokemonByName("charizard");

// Clean up (call at shutdown)
PokEng::shutdownPokemonTable();

Performance

Benchmarks

Based on the example program, the Pokemon table demonstrates excellent performance:

  • Initialization: ~89ms to load 1025 Pokemon species
  • ID Lookups: ~33,333 lookups per millisecond (100,000 lookups in 3ms)
  • Memory Usage: Minimal memory footprint with contiguous storage

Storage Strategy

The table uses a hybrid storage approach for optimal performance:

  1. Vector storage: Pokemon species are stored in a std::vector<PokemonSpecies> indexed by ID
  2. Hash map: Name-to-ID mapping using std::unordered_map for fast name lookups
  3. Index 0 unused: Vector index 0 is unused, so Pokemon with ID 1 is at index 1

This approach provides:

  • O(1) ID lookups via direct vector indexing
  • O(1) average case name lookups via hash table
  • Excellent cache locality for ID-based access patterns

Usage Examples

Basic Usage

#include "core/pokemon_table.h"

int main() {
    // Initialize the Pokemon table
    if (!PokEng::initializePokemonTable()) {
        std::cerr << "Failed to load Pokemon data!" << std::endl;
        return 1;
    }

    // Look up Pokemon by ID
    const auto* pikachu = PokEng::g_pokemonTable->getPokemon(25);
    if (pikachu) {
        std::cout << "Pikachu's speed: " << pikachu->base_stats.speed << std::endl;
        std::cout << "Pikachu's type: " << PokEng::TypeUtils::typeToString(pikachu->types.getPrimary()) << std::endl;
    }

    // Look up Pokemon by name
    const auto* charizard = PokEng::g_pokemonTable->getPokemonByName("charizard");
    if (charizard) {
        std::cout << "Charizard ID: " << charizard->id << std::endl;
    }

    // Clean up
    PokEng::shutdownPokemonTable();
    return 0;
}

Advanced Usage

// Check if Pokemon exists
if (PokEng::g_pokemonTable->hasPokemon(150)) {
    const auto* mewtwo = PokEng::g_pokemonTable->getPokemon(150);
    // Use mewtwo data...
}

// Iterate through all Pokemon
for (uint16_t id = 1; id <= PokEng::g_pokemonTable->getMaxId(); ++id) {
    const auto* pokemon = PokEng::g_pokemonTable->getPokemon(id);
    if (pokemon) {
        // Process pokemon...
    }
}

// Get all Pokemon at once (for bulk operations)
const auto& allPokemon = PokEng::g_pokemonTable->getAllPokemon();
for (const auto& pokemon : allPokemon) {
    if (pokemon.id != 0) { // Skip empty entries
        // Process pokemon...
    }
}

Data Loading

The Pokemon table automatically loads data from JSON files in the data/pokemon/ directory:

  • generation-i.json through generation-ix.json
  • Each file contains Pokemon from a specific generation
  • Data is validated during loading

JSON Format

Each Pokemon entry in the JSON files has the following structure:

{
  "id": 1,
  "name": "bulbasaur",
  "height": 7,
  "weight": 69,
  "base_experience": 64,
  "types": ["grass", "poison"],
  "stats": {
    "hp": 45,
    "attack": 49,
    "defense": 49,
    "special-attack": 65,
    "special-defense": 65,
    "speed": 45
  },
  "abilities": [...],
  "species": {...}
}

Error Handling

The implementation includes comprehensive error handling:

  • File loading errors: Graceful handling of missing or corrupted JSON files
  • JSON parsing errors: Detailed error messages for malformed JSON
  • Data validation: Built-in validation to ensure data integrity
  • Memory safety: Proper resource management with RAII

Testing

The implementation includes comprehensive unit tests covering:

  • Data loading and initialization
  • ID-based and name-based lookups
  • Error handling for invalid inputs
  • Performance validation
  • Data integrity validation

Run tests with:

cd build
make test

Integration

The Pokemon table is designed to integrate seamlessly with other components:

  • Pokemon creation: Use table data to create Pokemon instances
  • Battle calculations: Fast access to base stats and types
  • Type effectiveness: Integration with type system for damage calculations
  • Stat calculations: Base stats for battle stat computations

Future Enhancements

Potential improvements for the Pokemon table:

  1. Lazy loading: Load Pokemon data on-demand to reduce startup time
  2. Compressed storage: Use compression to reduce memory footprint
  3. Multi-threading: Parallel loading of Pokemon data
  4. Caching: Implement LRU cache for frequently accessed Pokemon
  5. Serialization: Save/load compiled Pokemon data for faster startup