// test/game_test.dart import 'package:flutter_test/flutter_test.dart'; import 'package:game_test/game/game_instance.dart'; import 'package:game_test/game/game_manager.dart'; import 'package:game_test/game/model/entity.dart'; import 'package:game_test/game/model/stat.dart'; import 'package:game_test/game/model/item.dart'; void main() { group('Game Core Logic Tests', () { test('Stat calculation with Modifiers', () { final strength = Stat(baseValue: 100); expect(strength.value, 100.0); // Add flat modifier strength.addModifier(Modifier(type: ModifierType.flat, value: 10)); expect(strength.value, closeTo(110.0, 0.00001)); // Add percent modifier strength.addModifier(Modifier(type: ModifierType.percent, value: 0.10)); // +10% // 110 * (1 + 0.10) = 121 expect(strength.value, closeTo(121.0, 0.00001)); // Add another flat modifier strength.addModifier(Modifier(type: ModifierType.flat, value: 20)); // (110 + 20) * (1 + 0.10) = 130 * 1.1 = 143 expect(strength.value, closeTo(143.0, 0.00001)); // Add another percent modifier strength.addModifier(Modifier(type: ModifierType.percent, value: 0.05)); // +5% // (110 + 20) * (1 + 0.10 + 0.05) = 130 * 1.15 = 149.5 expect(strength.value, closeTo(149.5, 0.00001)); // Remove a modifier final flatModifier10 = Modifier(type: ModifierType.flat, value: 10); strength.removeModifier(flatModifier10); // (100 + 20) * (1 + 0.10 + 0.05) = 120 * 1.15 = 138 expect(strength.value, closeTo(138.0, 0.00001)); final percentModifier10 = Modifier(type: ModifierType.percent, value: 0.10); strength.removeModifier(percentModifier10); // (100 + 20) * (1 + 0.05) = 120 * 1.05 = 126 expect(strength.value, closeTo(126.0, 0.00001)); }); test('LivingEntity HP and damage', () { final player = Player(id: 'p1', name: 'Test Player', baseHp: 100); expect(player.hp.value, 100.0); expect(player.isAlive, isTrue); player.takeDamage(20); expect(player.hp.value, 80.0); expect(player.isAlive, isTrue); player.takeDamage(90); // Should go to 0 expect(player.hp.value, 0.0); expect(player.isAlive, isFalse); player.heal(50); expect(player.hp.value, 50.0); expect(player.isAlive, isTrue); }); group('Player Equipment Tests', () { test('Player starts unarmed with base attack 1', () { final player = Player(id: 'p1', name: 'Test Player', baseHp: 100); expect(player.equippedWeapon?.id, 'unarmed_weapon'); expect(player.attack.value, closeTo(1.0, 0.00001)); }); test('Player equips a new weapon and attack changes', () { final player = Player(id: 'p1', name: 'Test Player', baseHp: 100); final sword = Weapon( id: 'iron_sword', name: '무쇠 검', attackModifier: Modifier(type: ModifierType.flat, value: 10), ); player.equipWeapon(sword); expect(player.equippedWeapon?.id, 'iron_sword'); expect(player.attack.value, closeTo(10.0, 0.00001)); // Base attack from sword }); test('Player unequips weapon and returns to unarmed', () { final player = Player(id: 'p1', name: 'Test Player', baseHp: 100); final sword = Weapon( id: 'iron_sword', name: '무쇠 검', attackModifier: Modifier(type: ModifierType.flat, value: 10), ); player.equipWeapon(sword); expect(player.attack.value, closeTo(10.0, 0.00001)); player.unequipWeapon(EquipmentSlot.mainHand); expect(player.equippedWeapon?.id, 'unarmed_weapon'); expect(player.attack.value, closeTo(1.0, 0.00001)); }); test('Equipping a new weapon replaces the old one', () { final player = Player(id: 'p1', name: 'Test Player', baseHp: 100); final sword = Weapon( id: 'iron_sword', name: '무쇠 검', attackModifier: Modifier(type: ModifierType.flat, value: 10), ); final axe = Weapon( id: 'steel_axe', name: '강철 도끼', attackModifier: Modifier(type: ModifierType.flat, value: 15), ); player.equipWeapon(sword); expect(player.attack.value, closeTo(10.0, 0.00001)); player.equipWeapon(axe); expect(player.equippedWeapon?.id, 'steel_axe'); expect(player.attack.value, closeTo(15.0, 0.00001)); }); }); test('GameInstance singleton and initialization', () async { final instance1 = GameInstance(); final instance2 = GameInstance(); expect(instance1, same(instance2)); // Verify singleton expect(instance1.isInitialized, isFalse); await instance1.initialize(); expect(instance1.isInitialized, isTrue); // Calling initialize again should not re-initialize await instance2.initialize(); expect(instance2.isInitialized, isTrue); }); test('GameManager initializes and player/enemies exist', () async { final gameManager = GameManager(); // Allow some time for async initialization in GameManager constructor await Future.delayed(const Duration(milliseconds: 100)); expect(gameManager.player, isNotNull); expect(gameManager.player?.name, '용감한 검투사'); expect(gameManager.currentEnemies.length, 2); }); test('GameManager player turn and enemy turn logic', () async { final gameManager = GameManager(); await Future.delayed(const Duration(milliseconds: 100)); // Ensure initialization final initialPlayerHp = gameManager.player!.hp.value; final initialEnemyCount = gameManager.currentEnemies.length; // Player attacks with medium risk (e.g., 0.6 for 60% success/damage) gameManager.playerTurn(action: 'attack', risk: 0.6); await Future.delayed(const Duration(milliseconds: 100)); // Allow enemy turn to complete // Expect player to have taken damage from enemy's turn expect(gameManager.player!.hp.value, lessThan(initialPlayerHp)); // Expect at least one enemy to have taken damage or been defeated // The current simple logic removes enemy if defeated, so check count. if (gameManager.currentEnemies.length < initialEnemyCount) { print('Enemy was defeated during playerTurn test.'); } else { final remainingEnemy = gameManager.currentEnemies.first; expect(remainingEnemy.hp.value, closeTo(49.4, 0.00001)); } }); }); }