From 41197902ab1a55a81f0d2acdf2cb61dc003447c6 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 18 Jun 2022 10:19:22 +0200 Subject: [PATCH] GameAction: better handle etb counter + doubler + same time --- .../src/main/java/forge/game/GameAction.java | 2 +- .../forge/game/GameEntityCounterTable.java | 10 +- .../java/forge/game/ability/AbilityKey.java | 1 + .../game/replacement/ReplaceAddCounter.java | 19 ++++ .../ai/simulation/GameSimulationTest.java | 101 ++++++++++++++++++ 5 files changed, 131 insertions(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 6b6844288da..dd71ad57ed0 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -591,7 +591,7 @@ public class GameAction { } } - table.replaceCounterEffect(game, null, true); + table.replaceCounterEffect(game, null, true, true, params); // Need to apply any static effects to produce correct triggers checkStaticAbilities(); diff --git a/forge-game/src/main/java/forge/game/GameEntityCounterTable.java b/forge-game/src/main/java/forge/game/GameEntityCounterTable.java index 2f42eb4db4b..1e81b78a21b 100644 --- a/forge-game/src/main/java/forge/game/GameEntityCounterTable.java +++ b/forge-game/src/main/java/forge/game/GameEntityCounterTable.java @@ -122,8 +122,12 @@ public class GameEntityCounterTable extends ForwardingTable, Ga game.getTriggerHandler().runTrigger(TriggerType.CounterAddedAll, runParams, false); } - @SuppressWarnings("unchecked") public void replaceCounterEffect(final Game game, final SpellAbility cause, final boolean effect) { + replaceCounterEffect(game, cause, effect, false, null); + } + + @SuppressWarnings("unchecked") + public void replaceCounterEffect(final Game game, final SpellAbility cause, final boolean effect, final boolean etb, Map params) { if (isEmpty()) { return; } @@ -135,6 +139,10 @@ public class GameEntityCounterTable extends ForwardingTable, Ga repParams.put(AbilityKey.Cause, cause); repParams.put(AbilityKey.EffectOnly, effect); repParams.put(AbilityKey.CounterMap, values); + repParams.put(AbilityKey.ETB, etb); + if (params != null) { + repParams.putAll(params); + } switch (game.getReplacementHandler().run(ReplacementType.AddCounter, repParams)) { case NotReplaced: diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index a3a2ff3681c..896bcc3268f 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -67,6 +67,7 @@ public enum AbilityKey { Explorer("Explorer"), ExtraTurn("ExtraTurn"), Event("Event"), + ETB("ETB"), Fighter("Fighter"), Fighters("Fighters"), FirstTime("FirstTime"), diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java b/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java index 82747d2c755..c60ef67722b 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceAddCounter.java @@ -8,9 +8,11 @@ import com.google.common.base.Optional; import forge.game.ability.AbilityKey; import forge.game.card.Card; +import forge.game.card.CardCollectionView; import forge.game.card.CounterType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; /** * TODO: Write javadoc for this type. @@ -58,6 +60,23 @@ public class ReplaceAddCounter extends ReplacementEffect { return false; } + if (runParams.containsKey(AbilityKey.ETB)) { + // if Card does affect something other than itself + if (!getParam("ValidCard").equals("Card.Self")) { + // and it self is entering, skip + if (getHostCard().equals(runParams.get(AbilityKey.Affected))) { + return false; + } + // and it wasn't already on the field, skip + if (getActiveZone().contains(ZoneType.Battlefield) && runParams.containsKey(AbilityKey.LastStateBattlefield)) { + CardCollectionView lastBattlefield = (CardCollectionView) runParams.get(AbilityKey.LastStateBattlefield); + if (!lastBattlefield.contains(getHostCard())) { + return false; + } + } + } + } + return true; } diff --git a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java index bf86600cb0c..bd4dad3a7f8 100644 --- a/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java +++ b/forge-gui-desktop/src/test/java/forge/ai/simulation/GameSimulationTest.java @@ -2394,4 +2394,105 @@ public class GameSimulationTest extends SimulationTest { AssertJUnit.assertEquals(20, simGame.getPlayers().get(0).getLife()); AssertJUnit.assertEquals(2, simGame.getPlayers().get(1).getLife()); } + + @Test + public void testETBCounterMowu() { + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + //Player p2 = game.getPlayers().get(1); + + String grumName = "Grumgully, the Generous"; + String mowuName = "Mowu, Loyal Companion"; + + addCard(grumName, p); + Card mowu = addCardToZone(mowuName, p, ZoneType.Hand); + + for (int i = 0; i < 7; ++i) { + addCard("Forest", p); + } + SpellAbility mowuSA = mowu.getFirstSpellAbility(); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + game.getAction().checkStateEffects(true); + + GameSimulator sim = createSimulator(game, p); + sim.simulateSpellAbility(mowuSA); + Game simGame = sim.getSimulatedGameState(); + + Card simMowu = findCardWithName(simGame, mowuName); + + AssertJUnit.assertNotNull(simMowu); + AssertJUnit.assertEquals(2, simMowu.getCounters(CounterEnumType.P1P1)); + } + + @Test + public void testETBCounterCorpsejack() { + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + //Player p2 = game.getPlayers().get(1); + + String grumName = "Grumgully, the Generous"; + String corpsejackName = "Corpsejack Menace"; + + addCard(grumName, p); + Card corpsejack = addCardToZone(corpsejackName, p, ZoneType.Hand); + + for (int i = 0; i < 7; ++i) { + addCard("Forest", p); + addCard("Swamp", p); + } + SpellAbility corpsejackSA = corpsejack.getFirstSpellAbility(); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + game.getAction().checkStateEffects(true); + + GameSimulator sim = createSimulator(game, p); + sim.simulateSpellAbility(corpsejackSA); + Game simGame = sim.getSimulatedGameState(); + + Card simCorpsejack = findCardWithName(simGame, corpsejackName); + + AssertJUnit.assertNotNull(simCorpsejack); + AssertJUnit.assertEquals(1, simCorpsejack.getCounters(CounterEnumType.P1P1)); + } + + @Test + public void testETBCounterCorpsejackMentor() { + Game game = initAndCreateGame(); + Player p = game.getPlayers().get(0); + //Player p2 = game.getPlayers().get(1); + + String grumName = "Grumgully, the Generous"; + String corpsejackName = "Corpsejack Menace"; + String mentorName = "Conclave Mentor"; + String everAfterName = "Ever After"; + + addCard(grumName, p); + Card corpsejack = addCardToZone(corpsejackName, p, ZoneType.Graveyard); + Card mentor = addCardToZone(mentorName, p, ZoneType.Graveyard); + + Card everAfter = addCardToZone(everAfterName, p, ZoneType.Hand); + + for (int i = 0; i < 7; ++i) { + addCard("Swamp", p); + } + SpellAbility everSA = everAfter.getFirstSpellAbility(); + everSA.getTargets().add(corpsejack); + everSA.getTargets().add(mentor); + + game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p); + game.getAction().checkStateEffects(true); + + GameSimulator sim = createSimulator(game, p); + sim.simulateSpellAbility(everSA); + Game simGame = sim.getSimulatedGameState(); + + Card simCorpsejack = findCardWithName(simGame, corpsejackName); + Card simMentor = findCardWithName(simGame, mentorName); + + AssertJUnit.assertNotNull(simCorpsejack); + AssertJUnit.assertEquals(1, simCorpsejack.getCounters(CounterEnumType.P1P1)); + AssertJUnit.assertNotNull(simMentor); + AssertJUnit.assertEquals(1, simMentor.getCounters(CounterEnumType.P1P1)); + } }