import { describe, it, expect, beforeEach } from 'vitest'; import { BattleEngine } from './BattleEngine'; import type { PicletDefinition, SpecialAbility } from './types'; import { PicletType, AttackType } from './types'; describe('Advanced Mechanic Override System', () => { describe('Critical Hit Mechanics', () => { it('should prevent critical hits with Shell Armor ability', () => { const shellArmor: SpecialAbility = { name: "Shell Armor", description: "Hard shell prevents critical hits", effects: [ { type: 'mechanicOverride', mechanic: 'criticalHits', condition: 'always', value: false } ] }; const defender: PicletDefinition = { name: "Shell Defender", description: "Protected by hard shell", tier: 'medium', primaryType: PicletType.MINERAL, baseStats: { hp: 80, attack: 60, defense: 80, speed: 40 }, nature: "Impish", specialAbility: shellArmor, movepool: [ { name: "Defense Curl", type: AttackType.NORMAL, power: 0, accuracy: 100, pp: 10, priority: 0, flags: [], effects: [ { type: 'modifyStats', target: 'self', stats: { defense: 'increase' } } ] } ] }; const attacker: PicletDefinition = { name: "High Crit Attacker", description: "Has high critical hit rate", tier: 'medium', primaryType: PicletType.BEAST, baseStats: { hp: 70, attack: 90, defense: 50, speed: 80 }, nature: "Adamant", specialAbility: { name: "No Ability", description: "" }, movepool: [ { name: "Slash", type: AttackType.BEAST, power: 70, accuracy: 100, pp: 10, priority: 0, flags: ['contact'], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' } ] } ] }; const engine = new BattleEngine(defender, attacker); // Force high crit rate for testing const originalCritRate = (engine as any).calculateCriticalChance; (engine as any).calculateCriticalChance = () => 1.0; // 100% crit rate normally let criticalHitOccurred = false; for (let i = 0; i < 10; i++) { const initialHp = engine.getState().playerPiclet.currentHp; engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 0 }, { type: 'move', piclet: 'opponent', moveIndex: 0 } ); const log = engine.getLog(); if (log.some(msg => msg.includes('critical') || msg.includes('Critical'))) { criticalHitOccurred = true; break; } if (engine.isGameOver()) break; } // Shell Armor should prevent ALL critical hits expect(criticalHitOccurred).toBe(false); // Restore original function (engine as any).calculateCriticalChance = originalCritRate; }); it('should guarantee critical hits with certain abilities', () => { const alwaysCrit: SpecialAbility = { name: "Super Luck", description: "Always lands critical hits", effects: [ { type: 'mechanicOverride', mechanic: 'criticalHits', condition: 'always', value: true } ] }; const critUser: PicletDefinition = { name: "Lucky Fighter", description: "Always gets critical hits", tier: 'medium', primaryType: PicletType.BEAST, baseStats: { hp: 70, attack: 80, defense: 60, speed: 90 }, nature: "Hasty", specialAbility: alwaysCrit, movepool: [ { name: "Strike", type: AttackType.BEAST, power: 60, accuracy: 100, pp: 10, priority: 0, flags: ['contact'], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' } ] } ] }; const opponent: PicletDefinition = { name: "Opponent", description: "Standard opponent", tier: 'medium', primaryType: PicletType.BEAST, baseStats: { hp: 80, attack: 60, defense: 60, speed: 70 }, nature: "Hardy", specialAbility: { name: "No Ability", description: "" }, movepool: [ { name: "Tackle", type: AttackType.NORMAL, power: 40, accuracy: 100, pp: 10, priority: 0, flags: ['contact'], effects: [{ type: 'damage', target: 'opponent', amount: 'normal' }] } ] }; const engine = new BattleEngine(critUser, opponent); engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 0 }, { type: 'move', piclet: 'opponent', moveIndex: 0 } ); const log = engine.getLog(); expect(log.some(msg => msg.includes('critical') || msg.includes('Critical'))).toBe(true); }); }); describe('Status Immunity', () => { it('should provide immunity to specific status effects', () => { const insomnia: SpecialAbility = { name: "Insomnia", description: "Prevents sleep status", effects: [ { type: 'mechanicOverride', mechanic: 'statusImmunity', value: ['sleep'] } ] }; const insomniac: PicletDefinition = { name: "Sleepless Fighter", description: "Cannot be put to sleep", tier: 'medium', primaryType: PicletType.CULTURE, baseStats: { hp: 70, attack: 60, defense: 60, speed: 80 }, nature: "Timid", specialAbility: insomnia, movepool: [ { name: "Tackle", type: AttackType.NORMAL, power: 40, accuracy: 100, pp: 10, priority: 0, flags: ['contact'], effects: [{ type: 'damage', target: 'opponent', amount: 'normal' }] } ] }; const sleepUser: PicletDefinition = { name: "Sleep Inducer", description: "Puts opponents to sleep", tier: 'medium', primaryType: PicletType.CULTURE, baseStats: { hp: 80, attack: 50, defense: 70, speed: 60 }, nature: "Calm", specialAbility: { name: "No Ability", description: "" }, movepool: [ { name: "Sleep Powder", type: AttackType.FLORA, power: 0, accuracy: 75, pp: 10, priority: 0, flags: [], effects: [ { type: 'applyStatus', target: 'opponent', status: 'sleep' } ] } ] }; const engine = new BattleEngine(insomniac, sleepUser); engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 0 }, { type: 'move', piclet: 'opponent', moveIndex: 0 } ); const log = engine.getLog(); expect(log.some(msg => msg.includes('immune') || msg.includes('had no effect'))).toBe(true); expect(log.some(msg => msg.includes('fell asleep'))).toBe(false); }); }); describe('Type Immunity', () => { it('should provide immunity to specific attack types', () => { const levitate: SpecialAbility = { name: "Levitate", description: "Floating ability makes ground moves miss", effects: [ { type: 'mechanicOverride', mechanic: 'typeImmunity', value: ['ground'] } ] }; const levitator: PicletDefinition = { name: "Floating Fighter", description: "Levitates above ground attacks", tier: 'medium', primaryType: PicletType.SPACE, baseStats: { hp: 75, attack: 70, defense: 60, speed: 85 }, nature: "Timid", specialAbility: levitate, movepool: [ { name: "Air Slash", type: AttackType.SPACE, power: 60, accuracy: 95, pp: 10, priority: 0, flags: [], effects: [ { type: 'damage', target: 'opponent', amount: 'normal' } ] } ] }; const groundUser: PicletDefinition = { name: "Ground Attacker", description: "Uses ground-based attacks", tier: 'medium', primaryType: PicletType.MINERAL, baseStats: { hp: 80, attack: 80, defense: 70, speed: 60 }, nature: "Adamant", specialAbility: { name: "No Ability", description: "" }, movepool: [ { name: "Earthquake", type: AttackType.MINERAL, power: 100, accuracy: 100, pp: 10, priority: 0, flags: ['ground'], effects: [ { type: 'damage', target: 'opponent', amount: 'strong' } ] } ] }; const engine = new BattleEngine(levitator, groundUser); const initialHp = engine.getState().playerPiclet.currentHp; engine.executeActions( { type: 'move', piclet: 'player', moveIndex: 0 }, { type: 'move', piclet: 'opponent', moveIndex: 0 } ); const finalHp = engine.getState().playerPiclet.currentHp; const log = engine.getLog(); // Ground move should have no effect due to Levitate expect(finalHp).toBe(initialHp); expect(log.some(msg => msg.includes('had no effect') || msg.includes('immune'))).toBe(true); }); }); });