/** * Test for the complete Tempest Wraith example from the design document * This demonstrates all advanced features working together */ import { describe, it, expect } from 'vitest'; import { BattleEngine } from './BattleEngine'; import { PicletDefinition } from './types'; import { PicletType, AttackType } from './types'; describe('Complete Tempest Wraith Implementation', () => { it('should handle the complete Tempest Wraith from design document', () => { const tempestWraith: PicletDefinition = { name: "Tempest Wraith", description: "A ghostly creature born from violent storms, wielding cosmic energy and shadowy illusions", tier: 'high', primaryType: PicletType.SPACE, secondaryType: PicletType.CULTURE, baseStats: { hp: 75, attack: 95, defense: 45, speed: 85 }, nature: "timid", specialAbility: { name: "Storm Caller", description: "When HP drops below 25%, gains immunity to status effects and +50% speed", triggers: [ { event: 'onLowHP', effects: [ { type: 'mechanicOverride', mechanic: 'statusImmunity', value: ['burn', 'freeze', 'paralyze', 'poison', 'sleep', 'confuse'] }, { type: 'modifyStats', target: 'self', stats: { speed: 'greatly_increase' } } ] }, { event: 'onSwitchIn', condition: 'ifWeather:storm', effects: [ { type: 'modifyStats', target: 'self', stats: { attack: 'increase' } } ] } ] }, movepool: [ { name: "Shadow Pulse", type: AttackType.CULTURE, power: 70, accuracy: 100, pp: 15, priority: 0, flags: [], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' }, { type: 'applyStatus', target: 'opponent', status: 'confuse' } ] }, { name: "Cosmic Strike", type: AttackType.SPACE, power: 85, accuracy: 90, pp: 10, priority: 0, flags: [], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' }, { type: 'applyStatus', target: 'opponent', status: 'paralyze' } ] }, { name: "Spectral Drain", type: AttackType.CULTURE, power: 60, accuracy: 95, pp: 12, priority: 0, flags: ['draining'], effects: [ { type: 'damage', target: 'opponent', formula: 'drain', value: 0.5 } ] }, { name: "Void Sacrifice", type: AttackType.SPACE, power: 130, accuracy: 85, pp: 1, priority: 0, flags: ['sacrifice', 'explosive'], effects: [ { type: 'damage', target: 'all', formula: 'standard', multiplier: 1.2 }, { type: 'damage', target: 'self', formula: 'percentage', value: 75 }, { type: 'fieldEffect', effect: 'voidStorm', target: 'field', stackable: false } ] } ] }; const opponent: PicletDefinition = { name: "Standard Fighter", description: "A basic opponent", tier: 'medium', primaryType: PicletType.BEAST, baseStats: { hp: 100, attack: 80, defense: 70, speed: 60 }, nature: "Hardy", specialAbility: { name: "None", description: "No ability" }, movepool: [{ name: "Tackle", type: AttackType.NORMAL, power: 40, accuracy: 100, pp: 35, priority: 0, flags: [], effects: [{ type: 'damage', target: 'opponent', amount: 'normal' }] }] }; const engine = new BattleEngine(tempestWraith, opponent); // Test 1: Verify Tempest Wraith is properly initialized const state = engine.getState(); expect(state.playerPiclet.definition.name).toBe("Tempest Wraith"); expect(state.playerPiclet.definition.primaryType).toBe(PicletType.SPACE); expect(state.playerPiclet.definition.secondaryType).toBe(PicletType.CULTURE); expect(state.playerPiclet.moves).toHaveLength(4); // Test 2: Verify special ability structure const ability = tempestWraith.specialAbility; expect(ability.name).toBe("Storm Caller"); expect(ability.triggers).toHaveLength(2); expect(ability.triggers![0].event).toBe('onLowHP'); expect(ability.triggers![1].event).toBe('onSwitchIn'); // Test 3: Test Shadow Pulse (dual effect move) engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 0 }, // Shadow Pulse { type: 'move', piclet: 'opponent', moveIndex: 0 } ); let log = engine.getLog(); expect(log.some(msg => msg.includes('used Shadow Pulse'))).toBe(true); // Test 4: Test Spectral Drain (drain move) if (!engine.isGameOver()) { // Damage the player to test healing engine['state'].playerPiclet.currentHp = 30; engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 2 }, // Spectral Drain { type: 'move', piclet: 'opponent', moveIndex: 0 } ); log = engine.getLog(); expect(log.some(msg => msg.includes('recovered') && msg.includes('HP from draining'))).toBe(true); } // Test 5: Test Void Sacrifice (ultimate move) if (!engine.isGameOver()) { const preVoidHp = engine.getState().playerPiclet.currentHp; engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 3 }, // Void Sacrifice { type: 'move', piclet: 'opponent', moveIndex: 0 } ); log = engine.getLog(); expect(log.some(msg => msg.includes('used Void Sacrifice'))).toBe(true); // Just verify that some field effect message exists const hasFieldEffect = log.some(msg => msg.includes('applied') || msg.includes('effect')); expect(hasFieldEffect).toBe(true); // Should have taken massive self-damage const postVoidHp = engine.getState().playerPiclet.currentHp; expect(postVoidHp).toBeLessThan(preVoidHp); } }); it('should demonstrate strategic depth with different movesets', () => { const tempestWraith: PicletDefinition = { name: "Tempest Wraith", description: "A ghostly creature born from violent storms", tier: 'high', primaryType: PicletType.SPACE, secondaryType: PicletType.CULTURE, baseStats: { hp: 75, attack: 95, defense: 45, speed: 85 }, nature: "timid", specialAbility: { name: "Storm Caller", description: "Complex multi-trigger ability", triggers: [ { event: 'onLowHP', effects: [ { type: 'mechanicOverride', mechanic: 'statusImmunity', value: ['burn', 'freeze', 'paralyze', 'poison', 'sleep', 'confuse'] } ] } ] }, movepool: [ { name: "Berserker's End", type: AttackType.BEAST, power: 80, accuracy: 95, pp: 10, priority: 0, flags: ['contact', 'reckless'], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' }, { type: 'damage', target: 'opponent', amount: 'strong', condition: 'ifLowHp' }, { type: 'mechanicOverride', target: 'self', mechanic: 'healingBlocked', value: true } ] }, { name: "Cursed Gambit", type: AttackType.CULTURE, power: 0, accuracy: 100, pp: 1, priority: 0, flags: ['gambling'], effects: [ { type: 'heal', target: 'self', formula: 'percentage', value: 100, condition: 'ifLucky50' }, { type: 'damage', target: 'self', formula: 'fixed', value: 9999, condition: 'ifUnlucky50' } ] } ] }; const engine = new BattleEngine(tempestWraith, { name: "Opponent", description: "Test opponent", tier: 'medium', primaryType: PicletType.BEAST, baseStats: { hp: 100, attack: 80, defense: 70, speed: 60 }, nature: "Hardy", specialAbility: { name: "None", description: "No ability" }, movepool: [{ name: "Tackle", type: AttackType.NORMAL, power: 40, accuracy: 100, pp: 35, priority: 0, flags: [], effects: [{ type: 'damage', target: 'opponent', amount: 'normal' }] }] }); // Test the moveset variety const state = engine.getState(); expect(state.playerPiclet.moves[0].move.name).toBe("Berserker's End"); expect(state.playerPiclet.moves[1].move.name).toBe("Cursed Gambit"); // Test Berserker's End effects const berserkersEnd = state.playerPiclet.moves[0].move; expect(berserkersEnd.effects).toHaveLength(3); expect(berserkersEnd.effects[1].condition).toBe('ifLowHp'); // Test Cursed Gambit effects const cursedGambit = state.playerPiclet.moves[1].move; expect(cursedGambit.effects).toHaveLength(2); expect(cursedGambit.effects[0].condition).toBe('ifLucky50'); expect(cursedGambit.effects[1].condition).toBe('ifUnlucky50'); }); it('should handle complete battle with advanced mechanics', () => { const advancedPiclet: PicletDefinition = { name: "Master of All Trades", description: "Demonstrates every major battle system feature", tier: 'legendary', primaryType: PicletType.SPACE, secondaryType: PicletType.CULTURE, baseStats: { hp: 100, attack: 100, defense: 80, speed: 90 }, nature: "Adaptive", specialAbility: { name: "Omni-Adaptation", description: "Multiple triggers for different situations", effects: [ { type: 'mechanicOverride', mechanic: 'criticalHits', value: 'double' } ], triggers: [ { event: 'onDamageTaken', effects: [ { type: 'modifyStats', target: 'self', stats: { attack: 'increase' } } ] }, { event: 'onSwitchIn', effects: [ { type: 'removeStatus', target: 'self', status: 'poison' } ] }, { event: 'endOfTurn', condition: 'ifStatus:burn', effects: [ { type: 'heal', target: 'self', formula: 'percentage', value: 10 } ] } ] }, movepool: [ { name: "Adaptive Strike", type: AttackType.NORMAL, power: 70, accuracy: 100, pp: 20, priority: 0, flags: ['contact'], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' }, { type: 'damage', target: 'opponent', amount: 'strong', condition: 'ifStatus:burn' } ] }, { name: "Field Manipulator", type: AttackType.SPACE, power: 0, accuracy: 100, pp: 10, priority: 1, flags: ['priority'], effects: [ { type: 'fieldEffect', effect: 'gravityField', target: 'field', stackable: false }, { type: 'modifyStats', target: 'opponent', stats: { speed: 'decrease' } } ] }, { name: "Status Cleanse", type: AttackType.NORMAL, power: 0, accuracy: 100, pp: 15, priority: 0, flags: [], effects: [ { type: 'removeStatus', target: 'self', status: 'poison' }, { type: 'removeStatus', target: 'self', status: 'burn' }, { type: 'heal', target: 'self', amount: 'medium' } ] }, { name: "Counter Protocol", type: AttackType.NORMAL, power: 0, accuracy: 100, pp: 10, priority: -5, flags: ['lowPriority'], effects: [ { type: 'counter', strength: 'strong' } ] } ] }; const engine = new BattleEngine(advancedPiclet, { name: "Test Opponent", description: "Basic opponent", tier: 'medium', primaryType: PicletType.BEAST, baseStats: { hp: 80, attack: 70, defense: 60, speed: 50 }, nature: "Hardy", specialAbility: { name: "None", description: "No ability" }, movepool: [{ name: "Tackle", type: AttackType.NORMAL, power: 40, accuracy: 100, pp: 35, priority: 0, flags: [], effects: [{ type: 'damage', target: 'opponent', amount: 'normal' }] }] }); // Test complex special ability const ability = advancedPiclet.specialAbility; expect(ability.effects).toHaveLength(1); expect(ability.triggers).toHaveLength(3); expect(ability.triggers![0].event).toBe('onDamageTaken'); expect(ability.triggers![2].condition).toBe('ifStatus:burn'); // Test diverse moveset const moves = advancedPiclet.movepool; expect(moves).toHaveLength(4); expect(moves[1].priority).toBe(1); // Priority move expect(moves[3].priority).toBe(-5); // Low priority counter expect(moves[2].effects).toHaveLength(3); // Multi-effect move // Test battle execution engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 1 }, // Field Manipulator { type: 'move', piclet: 'opponent', moveIndex: 0 } ); const log = engine.getLog(); const hasFieldEffect = log.some(msg => msg.includes('applied') || msg.includes('effect')); expect(hasFieldEffect).toBe(true); expect(log.some(msg => msg.includes('speed fell'))).toBe(true); }); });