The Game Theory of Competitive Pokémon

Strategic Element 4: Probability ManagementURL copied

Simulated Damage DistributionURL copied

The turn_resolution.py script in this folder computes the exact distribution empirically. Core logic:

"""
Competitive Pokemon: damage roll simulation.

Demonstrates the 16-value damage range that makes
every KO threshold a probabilistic, not deterministic, fact.
"""

import random
from collections import Counter


def damage(base_power: int, attack: int, defense: int, level: int = 50) -> int:
    """Apply the core damage formula with a random roll in [85, 100]."""
    roll = random.randint(85, 100)
    raw = ((2 * level // 5 + 2) * base_power * attack // defense) // 50 + 2
    return int(raw * roll / 100)


def roll_distribution(base_power: int, attack: int, defense: int,
                      trials: int = 100_000) -> dict[int, float]:
    counts: Counter[int] = Counter(
        damage(base_power, attack, defense) for _ in range(trials)
    )
    total = sum(counts.values())
    return {v: round(c / total * 100, 2) for v, c in sorted(counts.items())}


def ko_probability(base_power: int, attack: int, defense: int,
                   target_hp: int, trials: int = 100_000) -> float:
    """P(one-hit KO) for given target_hp."""
    kos = sum(
        1 for _ in range(trials)
        if damage(base_power, attack, defense) >= target_hp
    )
    return round(kos / trials * 100, 2)