using SlaySharp.Core.Catalogs; using SlaySharp.Core.Combat; using SlaySharp.Core.Enums; using SlaySharp.Core.Models; using Xunit; namespace SlaySharp.Tests; public class CombatEngineTests { [Fact] public void CombatEngine_InitializesDeckAndDraws5Cards() { var player = new Player("Senior Dev", 70, maxEnergy: 3, seed: 42); player.MasterDeck.AddRange(StarterDecks.CreateCsharpArchitectDeck()); var engine = new CombatEngine(); var enemy = new NullReferenceExceptionEnemy(); engine.StartCombat(player, new List { enemy }); Assert.Equal(CombatPhase.PlayerTurn, engine.Phase); Assert.Equal(3, player.CurrentEnergy); Assert.Equal(5, player.Hand.Count); Assert.Equal(7, player.DrawPile.Count); Assert.Empty(player.DiscardPile); } [Fact] public void PlayCard_DealsDamage_AndConsumesEnergy() { var player = new Player("Senior Dev", 70, maxEnergy: 3); var card = new ConsoleWriteLineCard(); // Cost 1, dmg 6 var enemy = new NullReferenceExceptionEnemy(); // 45 HP var engine = new CombatEngine(); engine.StartCombat(player, new List { enemy }); // Force hand player.Hand.Clear(); player.Hand.Add(card); player.CurrentEnergy = 3; var success = engine.PlayCard(card, enemy); Assert.True(success); Assert.Equal(2, player.CurrentEnergy); Assert.Equal(39, enemy.CurrentHp); Assert.Contains(card, player.DiscardPile); } [Fact] public void SpanSliceCard_PiercesThroughShield() { var player = new Player("Senior Dev", 70, maxEnergy: 3); var card = new SpanSliceCard(); // 8 piercing dmg var enemy = new NullReferenceExceptionEnemy(); // 45 HP var engine = new CombatEngine(); engine.StartCombat(player, new List { enemy }); enemy.GainShield(10); player.Hand.Clear(); player.Hand.Add(card); player.CurrentEnergy = 3; var success = engine.PlayCard(card, enemy); Assert.True(success); Assert.Equal(10, enemy.Shield); // Shield remains 10! Assert.Equal(37, enemy.CurrentHp); // 45 - 8 = 37 } [Fact] public void StatusEffects_StrengthAndVulnerable_MultiplyDamage() { var player = new Player("Senior Dev", 70, maxEnergy: 3); var enemy = new NullReferenceExceptionEnemy(); // 45 HP var card = new ConsoleWriteLineCard(); // 6 dmg var engine = new CombatEngine(); engine.StartCombat(player, new List { enemy }); player.Statuses.Add(StatusType.Strength, 2); // Base 6 + 2 = 8 enemy.Statuses.Add(StatusType.Vulnerable, 1); // 8 * 1.5 = 12 player.Hand.Clear(); player.Hand.Add(card); player.CurrentEnergy = 3; engine.PlayCard(card, enemy); Assert.Equal(33, enemy.CurrentHp); // 45 - 12 = 33 } [Fact] public void DiscardPile_Reshuffles_WhenDrawPileEmpty() { var player = new Player("Senior Dev", 70, maxEnergy: 3, seed: 123); // Only 3 cards in master deck player.MasterDeck.Add(new ConsoleWriteLineCard()); player.MasterDeck.Add(new TryCatchCard()); player.MasterDeck.Add(new LinqWhereCard()); var engine = new CombatEngine(); var enemy = new OffByOneBugEnemy(); engine.StartCombat(player, new List { enemy }); // All 3 cards drawn to hand, draw pile empty Assert.Equal(3, player.Hand.Count); Assert.Empty(player.DrawPile); // Discard 2 cards player.DiscardPile.Add(player.Hand[0]); player.DiscardPile.Add(player.Hand[1]); player.Hand.RemoveRange(0, 2); // Request drawing 2 cards player.DrawCards(2, engine.Log); Assert.Equal(3, player.Hand.Count); Assert.Empty(player.DiscardPile); } [Fact] public void KillingAllEnemies_TriggersVictory() { var player = new Player("Senior Dev", 70, maxEnergy: 3); var card = new ThrowExceptionCard(); // 16 dmg var enemy = new OffByOneBugEnemy(); // 22 HP var engine = new CombatEngine(); engine.StartCombat(player, new List { enemy }); enemy.CurrentHp = 10; // low HP player.Hand.Clear(); player.Hand.Add(card); player.CurrentEnergy = 2; engine.PlayCard(card, enemy); Assert.Equal(CombatPhase.Victory, engine.Phase); Assert.Empty(engine.Enemies); } }