calculateDamage
Calculate battle damage between Pokémon by analyzing stats, abilities, items, moves, and field conditions for strategic planning.
Instructions
Calculates the battle damage between an attacking and a defending Pokémon, considering their stats, abilities, items, and field conditions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| attacker | Yes | ||
| defender | Yes | ||
| move | Yes | ||
| field | Yes |
Implementation Reference
- src/calculator.ts:97-139 (handler)Core handler function implementing the calculateDamage tool logic using the @smogon/calc library to compute damage ranges, KO chances, and descriptions.export function calculateDamage(request: CalculateDamageRequest): CalculateDamageResponse { try { // Validate required fields if (!request.attacker?.species) { throw new Error("Attacker species is required"); } if (!request.defender?.species) { throw new Error("Defender species is required"); } if (!request.move?.name) { throw new Error("Move name is required"); } const attacker = createSmogonPokemon(request.attacker); const defender = createSmogonPokemon(request.defender); const move = createSmogonMove(request.move); const field = createSmogonField(request.field); const result = calculate(gen, attacker, defender, move, field); let damageRange: [number, number]; if (result.damage) { if (Array.isArray(result.damage)) { const damageArray = result.damage as number[]; damageRange = [damageArray[0], damageArray[damageArray.length - 1]]; } else { const singleDamage = result.damage as number; damageRange = [singleDamage, singleDamage]; } } else { damageRange = [0, 0]; } return { description: result.fullDesc(), damage: damageRange, koChance: result.kochance().text, fullResult: result }; } catch (error) { throw new Error(`Calculation failed: ${error instanceof Error ? error.message : String(error)}`); } }
- src/index.ts:168-178 (registration)MCP server registration of the calculateDamage tool in the listTools request handler, including name, description, and input schema.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'calculateDamage', description: 'Calculates the battle damage between an attacking and a defending Pokémon, considering their stats, abilities, items, and field conditions.', inputSchema: CALCULATE_DAMAGE_SCHEMA, }, ], }; });
- src/index.ts:184-195 (handler)Dispatch handler in the MCP callTool request that invokes the calculateDamage function with parsed arguments and formats the response.if (name === 'calculateDamage') { try { const result = calculateDamage(args as unknown as CalculateDamageRequest); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) {
- src/types.ts:57-69 (schema)TypeScript type definitions for the input (CalculateDamageRequest) and output (CalculateDamageResponse) of the calculateDamage tool.export interface CalculateDamageRequest { attacker: Pokemon; defender: Pokemon; field: Field; move: Move; } export interface CalculateDamageResponse { description: string; damage: [number, number]; koChance: string; fullResult?: any; }
- src/index.ts:26-165 (schema)JSON schema definition for the calculateDamage tool input used in MCP tool registration. Note: excerpt abbreviated; full schema spans detailed properties for Pokemon stats, moves, and field conditions.const CALCULATE_DAMAGE_SCHEMA = { type: 'object', properties: { attacker: { type: 'object', properties: { species: { type: 'string', description: 'Name of the Pokémon species (e.g., \'Pikachu\').' }, level: { type: 'number', default: 50 }, ability: { type: 'string', description: 'The Pokémon\'s ability (e.g., \'Lightning Rod\').' }, item: { type: 'string', description: 'The Pokémon\'s held item (e.g., \'Light Ball\').' }, nature: { type: 'string', description: 'The Pokémon\'s nature (e.g., \'Timid\').' }, status: { type: 'string', enum: ['', 'psn', 'brn', 'frz', 'par', 'slp'], description: 'e.g., \'brn\' for Burned.' }, evs: { type: 'object', properties: { hp: { type: 'number' }, atk: { type: 'number' }, def: { type: 'number' }, spa: { type: 'number' }, spd: { type: 'number' }, spe: { type: 'number' } } }, ivs: { type: 'object', properties: { hp: { type: 'number' }, atk: { type: 'number' }, def: { type: 'number' }, spa: { type: 'number' }, spd: { type: 'number' }, spe: { type: 'number' } } }, boosts: { type: 'object', properties: { atk: { type: 'number' }, def: { type: 'number' }, spa: { type: 'number' }, spd: { type: 'number' }, spe: { type: 'number' } } } }, required: ['species'] }, defender: { type: 'object', properties: { species: { type: 'string', description: 'Name of the Pokémon species (e.g., \'Pikachu\').' }, level: { type: 'number', default: 50 }, ability: { type: 'string', description: 'The Pokémon\'s ability (e.g., \'Lightning Rod\').' }, item: { type: 'string', description: 'The Pokémon\'s held item (e.g., \'Light Ball\').' }, nature: { type: 'string', description: 'The Pokémon\'s nature (e.g., \'Timid\').' }, status: { type: 'string', enum: ['', 'psn', 'brn', 'frz', 'par', 'slp'], description: 'e.g., \'brn\' for Burned.' }, evs: { type: 'object', properties: { hp: { type: 'number' }, atk: { type: 'number' }, def: { type: 'number' }, spa: { type: 'number' }, spd: { type: 'number' }, spe: { type: 'number' } } }, ivs: { type: 'object', properties: { hp: { type: 'number' }, atk: { type: 'number' }, def: { type: 'number' }, spa: { type: 'number' }, spd: { type: 'number' }, spe: { type: 'number' } } }, boosts: { type: 'object', properties: { atk: { type: 'number' }, def: { type: 'number' }, spa: { type: 'number' }, spd: { type: 'number' }, spe: { type: 'number' } } } }, required: ['species'] }, move: { type: 'object', properties: { name: { type: 'string', description: 'Name of the move being used (e.g., \'Thunderbolt\').' }, isCrit: { type: 'boolean', default: false, description: 'Whether the move is a guaranteed critical hit.' } }, required: ['name'] }, field: { type: 'object', properties: { gameType: { type: 'string', enum: ['Singles', 'Doubles'], default: 'Singles' }, weather: { type: 'string', enum: ['', 'Sun', 'Rain', 'Sand', 'Snow'] }, terrain: { type: 'string', enum: ['', 'Electric', 'Grassy', 'Misty', 'Psychic'] }, isBeadsOfRuin: { type: 'boolean', default: false }, isTabletsOfRuin: { type: 'boolean', default: false }, isSwordOfRuin: { type: 'boolean', default: false }, isVesselOfRuin: { type: 'boolean', default: false }, attackerSide: { type: 'object', properties: { isSR: { type: 'boolean', default: false, description: 'Stealth Rock is active.' }, spikes: { type: 'number', enum: [0, 1, 2, 3], default: 0 }, isLightScreen: { type: 'boolean', default: false }, isReflect: { type: 'boolean', default: false } } }, defenderSide: { type: 'object', properties: { isSR: { type: 'boolean', default: false, description: 'Stealth Rock is active.' }, spikes: { type: 'number', enum: [0, 1, 2, 3], default: 0 }, isLightScreen: { type: 'boolean', default: false }, isReflect: { type: 'boolean', default: false } } } } } }, required: ['attacker', 'defender', 'field', 'move'] } as const;