The Pokémon Showdown battle engine is split into two clearly separated concerns: state and presentation.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/smogon/pokemon-showdown-client/llms.txt
Use this file to discover all available pages before exploring further.
Battle (in battle.ts) is a pure state machine that ingests pipe-delimited protocol messages and maintains a model of the current game. BattleScene (in battle-animations.ts) reads that model and renders animations, sprites, and effects to the DOM. This split means Battle can run headlessly in the replay viewer, automated tests, or any context without a DOM, simply by substituting BattleSceneStub for the real renderer.
Licensing note: The
battle-*.ts files are individually licensed MIT, while the full Pokémon Showdown client is AGPLv3. The MIT boundary means you can embed just the battle replay engine in other projects without the copyleft requirement applying to your whole codebase.Battle: the state machine
Constructing a Battle
undefined for $frame and $logFrame to get a headless battle with BattleSceneStub — useful for unit testing or server-side rendering.
BattleScene: the animation renderer
BattleScene implements the BattleSceneStub interface and renders everything visible in a battle: sprites, HP bars, weather effects, move animations, and the message bar.
animating
When
false, the scene skips all animation timers and renders frames instantly. Used during seeking/scrubbing.acceleration
Multiplier applied to animation durations. Set higher when fast-forwarding through a long replay.
gen
Controls which sprite sheet and background art is used. Independently of the actual battle’s generation.
mod
Identifies the mod (e.g.
'digimon') for mod-specific sprite overrides.How a battle message flows end-to-end
Server sends a protocol message
The game server sends a newline-delimited block prefixed with the room ID:
PSConnection routes it to PS.receive()
PS.receive() strips the room prefix and dispatches each line to the appropriate PSRoom via room.receiveLine(args).BattleRoom passes lines to Battle
BattleRoom (a subclass of ChatRoom) holds a Battle instance. Protocol lines are added to battle.stepQueue.Battle updates its state model
As the queue plays,
Battle updates turn, weather, sides, pokemon, etc. It calls methods on this.scene to trigger animations at the right moment.BattleTextParser
BattleTextParser (in battle-text-parser.ts) converts raw pipe-delimited protocol lines into typed Args tuples that the rest of the engine operates on.
Protocol line examples
KWArgs are keyword arguments appended after the positional args in the form [from] move name, [of] pokemon, etc. BattleTextParser separates these for you.
BattleChoiceBuilder
When a player receives a request from the server,BattleChoiceBuilder helps build the response string incrementally — one Pokémon’s choice at a time.
Request types
Building a move choice
BattleSound and BattleBGM
Audio in battles is managed by two collaborating objects:BattleSound (a singleton that owns the audio cache and the active BGM list) and BattleBGM (a per-battle object representing one music track).
When multiple battle tabs are open, only the first
BattleBGM in BattleSound.bgm that isPlaying is isActuallyPlaying. The others are silenced but keep their play state, so they resume correctly when the first battle is closed or paused.BGM lifecycle
BattleSound.currentBgm() returns false if BGM is muted or volume is zero, null if nothing is playing, or the active BattleBGM instance.
BattleTooltips
BattleTooltips (in battle-tooltips.ts) generates the HTML content for the hover tooltips shown over Pokémon sprites and move buttons during a live battle or replay.
battle-dex.ts.