From 6a19ec48df390a0d8efc4572e7091bb044e0a7c9 Mon Sep 17 00:00:00 2001 From: Grath <1895280+Grath@users.noreply.github.com> Date: Sat, 31 Aug 2024 16:42:24 -0400 Subject: [PATCH] Add tests for Camellia, refactor SacrificedPermanentBatchEvent. (#12769) Added SacrificedPermanentEvent, to be used in SacrificedPermanentBatchEvent to prevent adding incorrect GameEvents. --- .../single/blb/CamelliaTheSeedmiserTest.java | 90 +++++++++++++++++++ Mage/src/main/java/mage/game/GameState.java | 6 +- .../events/SacrificedPermanentBatchEvent.java | 6 +- .../game/events/SacrificedPermanentEvent.java | 14 +++ .../mage/game/permanent/PermanentImpl.java | 6 +- 5 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/blb/CamelliaTheSeedmiserTest.java create mode 100644 Mage/src/main/java/mage/game/events/SacrificedPermanentEvent.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/CamelliaTheSeedmiserTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/CamelliaTheSeedmiserTest.java new file mode 100644 index 00000000000..e080756ddfc --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/CamelliaTheSeedmiserTest.java @@ -0,0 +1,90 @@ + +package org.mage.test.cards.single.blb; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author Grath + */ +public class CamelliaTheSeedmiserTest extends CardTestPlayerBase { + + @Test + public void TestTokensAreCreated() { + addCard(Zone.BATTLEFIELD, playerA, "Camellia, the Seedmiser", 1); + addCard(Zone.BATTLEFIELD, playerA, "Witch's Oven", 1); + addCard(Zone.BATTLEFIELD, playerA, "Cauldron Familiar", 1); + + // Sacrifice cat to oven + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice"); + setChoice(playerA, "Cauldron Familiar"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // Sacrifice food to cat + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice a Food"); + setChoice(playerA, "Food Token"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + // One food sacrificed, one squirrel made. + assertPermanentCount(playerA, "Squirrel Token", 1); + } + + @Test + public void TestTokensAreCreatedForGildedGoose() { + addCard(Zone.BATTLEFIELD, playerA, "Camellia, the Seedmiser", 1); + addCard(Zone.BATTLEFIELD, playerA, "Witch's Oven", 1); + addCard(Zone.BATTLEFIELD, playerA, "Cauldron Familiar", 1); + addCard(Zone.BATTLEFIELD, playerA, "Sorin, Ravenous Neonate", 1); + addCard(Zone.BATTLEFIELD, playerA, "Gilded Goose", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + + // Sacrifice cat to oven + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice"); + setChoice(playerA, "Cauldron Familiar"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // Make a food with Sorin + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+2"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + activateAbility(3, PhaseStep.UPKEEP, playerA, "{2}, {T}, Sacrifice this artifact: You gain 3 life"); + + setStopAt(3, PhaseStep.BEGIN_COMBAT); + execute(); + + // Activating Gilded Goose happens first, then other costs are paid including sacrificing the other Food. + // So two Squirrels are made. + assertPermanentCount(playerA, "Squirrel Token", 2); + } + + @Test + public void TestOneTokenForSimultaneousFoodSacrifice() { + addCard(Zone.BATTLEFIELD, playerA, "Camellia, the Seedmiser", 1); + addCard(Zone.BATTLEFIELD, playerA, "Sorin, Ravenous Neonate", 1); + addCard(Zone.BATTLEFIELD, playerA, "Sai, Master Thopterist", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + // Make two food with Sorin + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+2"); + activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "+2"); + + // Sacrifice both food to Sai + activateAbility(5, PhaseStep.UPKEEP, playerA, "{1}{U}, Sacrifice two artifacts: Draw a card."); + + setStopAt(5, PhaseStep.BEGIN_COMBAT); + execute(); + + // One squirrel made because both foods were sacrificed at the same time. + assertPermanentCount(playerA, "Squirrel Token", 1); + } +} diff --git a/Mage/src/main/java/mage/game/GameState.java b/Mage/src/main/java/mage/game/GameState.java index b8f2f55caa6..13499c2fb69 100644 --- a/Mage/src/main/java/mage/game/GameState.java +++ b/Mage/src/main/java/mage/game/GameState.java @@ -930,21 +930,21 @@ public class GameState implements Serializable, Copyable { } } - public void addSimultaneousSacrificedPermanentToBatch(GameEvent sacrificedEvent, Game game) { + public void addSimultaneousSacrificedPermanentToBatch(SacrificedPermanentEvent sacrificedPermanentEvent, Game game) { // Combine multiple sacrificed permanent events in the single event (batch) // existing batch boolean isBatchUsed = false; for (GameEvent event : simultaneousEvents) { if (event instanceof SacrificedPermanentBatchEvent) { - ((SacrificedPermanentBatchEvent) event).addEvent(sacrificedEvent); + ((SacrificedPermanentBatchEvent) event).addEvent(sacrificedPermanentEvent); isBatchUsed = true; } } // new batch if (!isBatchUsed) { - addSimultaneousEvent(new SacrificedPermanentBatchEvent(sacrificedEvent), game); + addSimultaneousEvent(new SacrificedPermanentBatchEvent(sacrificedPermanentEvent), game); } } diff --git a/Mage/src/main/java/mage/game/events/SacrificedPermanentBatchEvent.java b/Mage/src/main/java/mage/game/events/SacrificedPermanentBatchEvent.java index 7740256f76a..6befd3dc008 100644 --- a/Mage/src/main/java/mage/game/events/SacrificedPermanentBatchEvent.java +++ b/Mage/src/main/java/mage/game/events/SacrificedPermanentBatchEvent.java @@ -1,8 +1,8 @@ package mage.game.events; -public class SacrificedPermanentBatchEvent extends BatchEvent { +public class SacrificedPermanentBatchEvent extends BatchEvent { - public SacrificedPermanentBatchEvent(GameEvent sacrificedEvent) { - super(EventType.SACRIFICED_PERMANENT_BATCH, false, false, false, sacrificedEvent); + public SacrificedPermanentBatchEvent(SacrificedPermanentEvent sacrificedPermanentEvent) { + super(EventType.SACRIFICED_PERMANENT_BATCH, false, false, false, sacrificedPermanentEvent); } } diff --git a/Mage/src/main/java/mage/game/events/SacrificedPermanentEvent.java b/Mage/src/main/java/mage/game/events/SacrificedPermanentEvent.java new file mode 100644 index 00000000000..70b189206fb --- /dev/null +++ b/Mage/src/main/java/mage/game/events/SacrificedPermanentEvent.java @@ -0,0 +1,14 @@ +package mage.game.events; + +import mage.abilities.Ability; + +import java.util.UUID; + +/** + * @author Grath + */ +public class SacrificedPermanentEvent extends GameEvent { + public SacrificedPermanentEvent(UUID targetId, Ability source, UUID playerId) { + super(EventType.SACRIFICED_PERMANENT, targetId, source, playerId); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 1d985b38f8f..ab9258fb39e 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -1421,9 +1421,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { if (player != null) { game.informPlayers(player.getLogName() + " sacrificed " + this.getLogName() + CardUtil.getSourceLogName(game, source)); } - GameEvent sacrificedEvent = GameEvent.getEvent(GameEvent.EventType.SACRIFICED_PERMANENT, objectId, source, controllerId); - game.fireEvent(sacrificedEvent); - game.getState().addSimultaneousSacrificedPermanentToBatch(sacrificedEvent, game); + SacrificedPermanentEvent sacrificedPermanentEvent = new SacrificedPermanentEvent(objectId, source, controllerId); + game.fireEvent(sacrificedPermanentEvent); + game.getState().addSimultaneousSacrificedPermanentToBatch(sacrificedPermanentEvent, game); return true; } return false;