From 802aca942a8da10b3fcb71c08a11868011865dcc Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 6 Jul 2020 21:06:49 +0400 Subject: [PATCH] Play card without mana cost - fixed that AI and other players can play cards without additional cost in some use cases (#6760); --- .../asthough/PlayFromNonHandZoneTest.java | 37 ++++++++++++++++++- .../main/java/mage/players/PlayerImpl.java | 5 ++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java index 80a519f382e..7a7aa3f7b91 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java @@ -3,12 +3,12 @@ package org.mage.test.cards.asthough; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Test; -import org.mage.test.serverside.base.CardTestPlayerBase; +import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps; /** * @author LevelX2 */ -public class PlayFromNonHandZoneTest extends CardTestPlayerBase { +public class PlayFromNonHandZoneTest extends CardTestPlayerBaseWithAIHelps { @Test public void testWorldheartPhoenixNormal() { @@ -148,6 +148,39 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Cathartic Reunion", 1); } + @Test + public void testNarsetEnlightenedMasterAdditionalCost_AI() { + skipInitShuffling(); + removeAllCardsFromLibrary(playerA); + + // First strike + // Hexproof + // Whenever Narset, Enlightented Master attacks, exile the top four cards of your library. Until end of turn, you may cast noncreature cards exiled with Narset this turn without paying their mana costs. + addCard(Zone.BATTLEFIELD, playerA, "Narset, Enlightened Master", 1); + // + // {1}{R} + // As an additional cost to cast this spell, discard two cards. + addCard(Zone.LIBRARY, playerA, "Swamp", 3); // 3 cards for draw effect + addCard(Zone.LIBRARY, playerA, "Cathartic Reunion", 1); // exile from lib + addCard(Zone.LIBRARY, playerA, "Plains", 3); // exile from lib + addCard(Zone.HAND, playerA, "Swamp", 1); + addCard(Zone.HAND, playerA, "Forest", 1); + + attack(1, playerA, "Narset, Enlightened Master"); + + // AI simulation to cast exiled card (possible bug: ai real cast uses cost payed status from one of the simulation and don't pay) + aiPlayPriority(1, PhaseStep.POSTCOMBAT_MAIN, playerA); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertGraveyardCount(playerA, "Swamp", 1); + assertGraveyardCount(playerA, "Forest", 1); + assertGraveyardCount(playerA, "Cathartic Reunion", 1); + } + /** * Kess, Dissident Mage and Fire/Ice - When you cast fire/ice from your * graverayr with kess it doesn't exile it self diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 697c201fe57..2076e20c3ab 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1075,9 +1075,10 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts, Costs costs) { + // cost must be copied for data consistence between game simulations castSourceIdWithAlternateMana.add(sourceId); - castSourceIdManaCosts.put(sourceId, manaCosts); - castSourceIdCosts.put(sourceId, costs); + castSourceIdManaCosts.put(sourceId, manaCosts != null ? manaCosts.copy() : null); + castSourceIdCosts.put(sourceId, costs != null ? costs.copy() : null); } @Override