# Pokemon Battle System Architecture Analysis ## Overview The Pokemon Emerald battle system is a complex, state-driven architecture that orchestrates combat between multiple Pokemon. Rather than being a single monolithic system, it's composed of several interconnected subsystems that handle different aspects of battle functionality. ## High-Level Architecture ### Core Components 1. **Battle State Machine** (`battle_main.c`) 2. **Battle Controllers** (`battle_controller_*.c` files) 3. **Animation System** (`battle_anim*.c` files) 4. **Script Engine** (`battle_script_commands.c`) 5. **User Interface** (`battle_interface.c`) 6. **Data Management** (Pokemon storage and battle state) ## 1. Battle State Management ### Main Battle Loop The battle system is built around a main function pointer (`gBattleMainFunc`) that controls the overall battle flow: ```c // Central battle state function pointer void (*gBattleMainFunc)(void); ``` ### Key State Variables - `gBattleStruct` - Central battle state container - `gBattleMons[MAX_BATTLERS_COUNT]` - Active Pokemon data - `gBattlerPositions[]` - Battler position tracking - `gBattleTypeFlags` - Battle mode flags (wild, trainer, double, etc.) gBattleStruct definition: ```c struct BattleStruct { u8 turnEffectsTracker; u8 turnEffectsBattlerId; u8 unused_0; u8 turnCountersTracker; u8 wrappedMove[MAX_BATTLERS_COUNT * 2]; // Leftover from Ruby's ewram access. u8 moveTarget[MAX_BATTLERS_COUNT]; u8 expGetterMonId; u8 unused_1; u8 wildVictorySong; u8 dynamicMoveType; u8 wrappedBy[MAX_BATTLERS_COUNT]; u16 assistPossibleMoves[PARTY_SIZE * MAX_MON_MOVES]; // Each of mons can know max 4 moves. u8 focusPunchBattlerId; u8 battlerPreventingSwitchout; u8 moneyMultiplier; u8 savedTurnActionNumber; u8 switchInAbilitiesCounter; u8 faintedActionsState; u8 faintedActionsBattlerId; u16 expValue; u8 scriptPartyIdx; // for printing the nickname u8 sentInPokes; bool8 selectionScriptFinished[MAX_BATTLERS_COUNT]; u8 battlerPartyIndexes[MAX_BATTLERS_COUNT]; u8 monToSwitchIntoId[MAX_BATTLERS_COUNT]; u8 battlerPartyOrders[MAX_BATTLERS_COUNT][PARTY_SIZE / 2]; u8 runTries; u8 caughtMonNick[POKEMON_NAME_LENGTH + 1]; u8 unused_2; u8 safariGoNearCounter; u8 safariPkblThrowCounter; u8 safariEscapeFactor; u8 safariCatchFactor; u8 linkBattleVsSpriteId_V; // The letter "V" u8 linkBattleVsSpriteId_S; // The letter "S" u8 formToChangeInto; u8 chosenMovePositions[MAX_BATTLERS_COUNT]; u8 stateIdAfterSelScript[MAX_BATTLERS_COUNT]; u8 unused_3[3]; u8 prevSelectedPartySlot; u8 unused_4[2]; u8 stringMoveType; u8 expGetterBattlerId; u8 unused_5; u8 absentBattlerFlags; u8 palaceFlags; // First 4 bits are "is <= 50% HP and not asleep" for each battler, last 4 bits are selected moves to pass to AI u8 field_93; // related to choosing pokemon? u8 wallyBattleState; u8 wallyMovesState; u8 wallyWaitFrames; u8 wallyMoveFrames; u8 lastTakenMove[MAX_BATTLERS_COUNT * 2 * 2]; // Last move that a battler was hit with. This field seems to erroneously take 16 bytes instead of 8. u16 hpOnSwitchout[NUM_BATTLE_SIDES]; u32 savedBattleTypeFlags; u8 abilityPreventingSwitchout; u8 hpScale; u8 synchronizeMoveEffect; bool8 anyMonHasTransformed; void (*savedCallback)(void); u16 usedHeldItems[MAX_BATTLERS_COUNT]; u8 chosenItem[MAX_BATTLERS_COUNT]; // why is this an u8? u8 AI_itemType[2]; u8 AI_itemFlags[2]; u16 choicedMove[MAX_BATTLERS_COUNT]; u16 changedItems[MAX_BATTLERS_COUNT]; u8 intimidateBattler; u8 switchInItemsCounter; u8 arenaTurnCounter; u8 turnSideTracker; u8 unused_6[3]; u8 givenExpMons; // Bits for enemy party's Pokémon that gave exp to player's party. u8 lastTakenMoveFrom[MAX_BATTLERS_COUNT * MAX_BATTLERS_COUNT * 2]; // a 3-D array [target][attacker][byte] u16 castformPalette[NUM_CASTFORM_FORMS][16]; union { struct LinkBattlerHeader linkBattlerHeader; u32 battleVideo[2]; } multiBuffer; u8 wishPerishSongState; u8 wishPerishSongBattlerId; bool8 overworldWeatherDone; u8 atkCancellerTracker; struct BattleTvMovePoints tvMovePoints; struct BattleTv tv; u8 unused_7[0x28]; u8 AI_monToSwitchIntoId[MAX_BATTLERS_COUNT]; s8 arenaMindPoints[2]; s8 arenaSkillPoints[2]; u16 arenaStartHp[2]; u8 arenaLostPlayerMons; // Bits for party member, lost as in referee's decision, not by fainting. u8 arenaLostOpponentMons; u8 alreadyStatusedMoveAttempt; // As bits for battlers; For example when using Thunder Wave on an already paralyzed Pokémon. }; ``` ### Battle Flow States The battle progresses through distinct phases: 1. **Initialization** - Setup battlers, load graphics 2. **Turn Selection** - Player/AI choose actions 3. **Action Resolution** - Execute moves in priority order 4. **Turn Cleanup** - Apply end-of-turn effects 5. **Battle End** - Victory/defeat/capture resolution ## 2. Controller Architecture ### Battler Controllers Each battler (player, opponent, partner, etc.) has its own controller that handles: - Input processing - Animation requests - Data updates - UI management ```c // Controller function pointer array void (*gBattlerControllerFuncs[MAX_BATTLERS_COUNT])(void); ``` ### Controller Types - **Player Controller** (`battle_controller_player.c`) - Human input - **Opponent Controller** (`battle_controller_opponent.c`) - AI decisions - **Link Controllers** - Network battlers - **Special Controllers** - Safari Zone, Wally, etc. ### Command System Controllers communicate via command buffers: ```c // Controller commands (simplified) CONTROLLER_GETMONDATA // Request Pokemon data CONTROLLER_CHOOSEACTION // Select battle action CONTROLLER_MOVEANIMATION // Play move animation CONTROLLER_HEALTHBARUPDATE // Update HP display ``` ## 3. Animation System ### Animation Pipeline Animations are script-driven and hierarchical: 1. **Move Animation Selection** - Choose appropriate animation 2. **Script Execution** - Run animation script commands 3. **Sprite Management** - Create/animate visual elements 4. **Audio Synchronization** - Play sound effects 5. **Cleanup** - Remove temporary sprites ### Animation Scripts Each move has an associated animation script: ```c const u8 *const gBattleAnims_Moves[]; ``` ### Animation Commands Scripts use specialized commands: - `loadspritegfx` - Load sprite graphics - `createsprite` - Create animated sprite - `playse` - Play sound effect - `delay` - Wait specified frames - `monbg` - Modify Pokemon background ### Visual Task System Complex animations use visual tasks for frame-by-frame control: ```c u8 gAnimVisualTaskCount; // Active visual task counter ``` ## 4. Pokemon Data Storage and Retrieval ### Battle Pokemon Structure Active Pokemon are stored in `gBattleMons[]`: ```c struct BattlePokemon { u16 species; u16 attack; u16 defense; u16 speed; u16 spAttack; u16 spDefense; u16 moves[MAX_MON_MOVES]; u32 hp; u8 level; u8 pp[MAX_MON_MOVES]; // ... status, abilities, etc. }; ``` ### Data Synchronization The system maintains consistency between: - **Party Data** - Full Pokemon in party array - **Battle Data** - Reduced battle-specific data - **Display Data** - UI representation ### Data Flow 1. **Load Phase** - Copy party data to battle structure 2. **Battle Phase** - Modify battle data only 3. **Update Phase** - Sync changes back to party ## 5. Menu Systems and Input Handling ### Action Selection Menu The main battle menu uses a state-driven approach: ```c static void PlayerHandleChooseAction(void) { // Present: Fight, Pokemon, Bag, Run options // Handle input and set action type } ``` ### Move Selection Interface Move selection involves: 1. **Display Moves** - Show available moves with PP 2. **Input Handling** - Process directional input 3. **Move Info** - Display type, power, accuracy 4. **Target Selection** - Choose targets for multi-target moves ### Menu State Management - Cursor position tracking - Input validation - Visual feedback (highlighting, animations) - Transition between menu levels ## 6. Action Processing and Effect Application ### Turn Order Resolution Actions are sorted by priority: 1. **Switch Pokemon** (highest priority) 2. **Use Items** 3. **Use Moves** (sorted by speed/priority) 4. **Flee** ### Move Execution Pipeline When a move is used: 1. **Validation** - Check if move can be used 2. **Target Selection** - Determine valid targets 3. **Script Execution** - Run move's battle script 4. **Animation** - Play visual/audio effects 5. **Damage Calculation** - Apply damage formulas 6. **Effect Application** - Apply status effects, stat changes 7. **Cleanup** - Update battle state ### Battle Script System Moves use script commands for effects: ```c static void Cmd_attackstring(void); // Display attack message static void Cmd_attackanimation(void); // Play attack animation static void Cmd_damagecalc(void); // Calculate damage static void Cmd_healthbarupdate(void); // Update HP bar ``` ### Gradual Information Delivery The system delivers information to players progressively: 1. **Action Announcement** - "Pokemon used Move!" 2. **Animation Phase** - Visual move animation 3. **Result Messages** - Effectiveness, critical hits 4. **Damage Application** - Gradual HP bar drain 5. **Status Updates** - Additional effects 6. **Turn Cleanup** - End-of-turn effects ## 7. Key Programming Patterns ### State Machine Architecture The battle system extensively uses function pointers for state management: ```c void (*gBattleMainFunc)(void); // Main battle state void (*gBattlerControllerFuncs[])(void); // Controller states void (*gAnimScriptCallback)(void); // Animation states ``` ### Command-Driven Controllers Controllers process commands via lookup tables: ```c static void (*const sPlayerBufferCommands[])(void) = { [CONTROLLER_GETMONDATA] = PlayerHandleGetMonData, [CONTROLLER_CHOOSEACTION] = PlayerHandleChooseAction, // ... }; ``` ### Script-Based Effects Both animations and move effects use bytecode scripts for flexibility: - Animation scripts control visual presentation - Battle scripts control game logic and effects ### Asynchronous Processing The system handles multiple concurrent operations: - Animations can run while processing user input - Multiple battlers can be in different states - Background tasks handle gradual effects (HP drain, etc.) ## 8. Memory Management ### Battle Resources Structure ```c struct BattleResources { struct SecretBase *secretBase; struct ResourceFlags *flags; struct BattleScriptsStack *battleScriptsStack; struct AI_ThinkingStruct *ai; struct BattleHistory *battleHistory; }; ``` ### Dynamic Allocation - Battle resources are allocated at battle start - Freed when battle ends - Sprites and animations use temporary allocation ## 9. Extension Points The architecture provides several extension mechanisms: - **New Move Effects** - Add scripts to move effect table - **Custom Animations** - Create new animation scripts - **Battle Types** - Add flags and specialized controllers - **AI Behaviors** - Extend AI decision trees ## Summary The Pokemon battle system demonstrates sophisticated game architecture through: 1. **Separation of Concerns** - Controllers, animations, scripts, and UI are distinct 2. **Data-Driven Design** - Moves, animations, and effects defined in data tables 3. **State Management** - Clear state machines for battle flow and individual components 4. **Asynchronous Processing** - Multiple concurrent operations with proper coordination 5. **Extensibility** - Modular design allows for easy addition of new content This architecture allows complex battle interactions while maintaining code organization and enabling the rich, interactive experience that defines Pokemon battles.