mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
* Aminatou's Augury - Fixed that spells in exile where not shown as castable and that AI usage prevented casting of multiple spells from exile (fixes #6987).
This commit is contained in:
parent
89639f5e9b
commit
783239e79e
3 changed files with 85 additions and 10 deletions
|
@ -134,21 +134,20 @@ class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
Player player = game.getPlayer(affectedControllerId);
|
||||
EnumSet<CardType> usedCardTypes = EnumSet.noneOf(CardType.class);
|
||||
|
||||
if (game.getState().getValue(source.getSourceId().toString() + "cardTypes") != null) {
|
||||
usedCardTypes = (EnumSet<CardType>) game.getState().getValue(source.getSourceId().toString() + "cardTypes");
|
||||
}
|
||||
//TODO add code for adding additional costs to the card
|
||||
if (player != null
|
||||
&& sourceId != null
|
||||
&& sourceId.equals(getTargetPointer().getFirst(game, source))
|
||||
&& objectId != null
|
||||
&& objectId.equals(getTargetPointer().getFirst(game, source))
|
||||
&& affectedControllerId.equals(source.getControllerId())) {
|
||||
Card card = game.getCard(sourceId);
|
||||
Card card = game.getCard(objectId);
|
||||
if (card != null
|
||||
&& game.getState().getZone(sourceId) == Zone.EXILED) {
|
||||
&& game.getState().getZone(objectId) == Zone.EXILED) {
|
||||
EnumSet<CardType> unusedCardTypes = EnumSet.noneOf(CardType.class);
|
||||
for (CardType cardT : card.getCardType()) {
|
||||
if (!usedCardTypes.contains(cardT)) {
|
||||
|
@ -175,10 +174,9 @@ class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl {
|
|||
usedCardTypes.add(CardType.fromString(choice.getChoice()));
|
||||
}
|
||||
usedCardTypes.addAll(unusedCardTypes);
|
||||
player.setCastSourceIdWithAlternateMana(sourceId, null, card.getSpellAbility().getCosts());
|
||||
// TODO- This does not correctly work when you cancel the cast (has to be done by watcher I guess)
|
||||
game.getState().setValue(source.getSourceId().toString() + "cardTypes", usedCardTypes);
|
||||
}
|
||||
player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
package org.mage.test.cards.single.c18;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class AminatousAuguryTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testCastMultiple() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
|
||||
addCard(Zone.LIBRARY, playerA, "Pillarfield Ox"); // Creature (2/4)
|
||||
// As an additional cost to cast this spell, discard a card.
|
||||
// Draw two cards.
|
||||
addCard(Zone.LIBRARY, playerA, "Tormenting Voice"); // Sorcery
|
||||
// {1}: Adarkar Sentinel gets +0/+1 until end of turn.
|
||||
addCard(Zone.LIBRARY, playerA, "Adarkar Sentinel"); // Artifact Creature {5} (3/3)
|
||||
addCard(Zone.LIBRARY, playerA, "Storm Crow");
|
||||
// You have hexproof. (You can't be the target of spells or abilities your opponents control.)
|
||||
addCard(Zone.LIBRARY, playerA, "Aegis of the Gods"); // Enchantment Creature {1}{W} (2/1)
|
||||
addCard(Zone.LIBRARY, playerA, "Lightning Bolt"); // Instant
|
||||
addCard(Zone.LIBRARY, playerA, "Badlands");
|
||||
skipInitShuffling();
|
||||
// Exile the top eight cards of your library. You may put a land card from among them onto the battlefield.
|
||||
// Until end of turn, for each nonland card type, you may cast a card of that type from among the exiled cards
|
||||
// without paying its mana cost.
|
||||
addCard(Zone.HAND, playerA, "Aminatou's Augury"); // SORCERY {6}{U}{U}
|
||||
addCard(Zone.HAND, playerA, "Mountain");
|
||||
addCard(Zone.HAND, playerA, "Silvercoat Lion");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 8);
|
||||
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aminatou's Augury");
|
||||
setChoice(playerA, "Yes"); // Put a land from among the exiled cards into play?
|
||||
setChoice(playerA, "Badlands"); // Select a land card
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Adarkar Sentinel");
|
||||
setChoice(playerA, "Artifact"); // Which card type do you want to consume?
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aegis of the Gods");
|
||||
setChoice(playerA, "Enchantment"); // Which card type do you want to consume?
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Storm Crow");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tormenting Voice");
|
||||
setChoice(playerA, "Silvercoat Lion"); // Select a card (discard cost)
|
||||
|
||||
checkPlayableAbility("Cannot cast second creature from exile", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Pillarfield Ox", Boolean.FALSE); // Type Creature type is already consumed
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Aminatou's Augury", 1);
|
||||
assertPermanentCount(playerA, "Mountain", 1);
|
||||
assertPermanentCount(playerA, "Badlands", 1);
|
||||
assertPermanentCount(playerA, "Adarkar Sentinel", 1);
|
||||
assertPermanentCount(playerA, "Aegis of the Gods", 1);
|
||||
assertPermanentCount(playerA, "Storm Crow", 1);
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 17);
|
||||
|
||||
assertHandCount(playerA, 2);
|
||||
assertGraveyardCount(playerA, "Silvercoat Lion",1);
|
||||
assertExileCount(playerA, 2);
|
||||
}
|
||||
|
||||
}
|
|
@ -163,6 +163,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
for (Map.Entry<String, Object> entry : state.values.entrySet()) {
|
||||
if (entry.getValue() instanceof HashSet) {
|
||||
this.values.put(entry.getKey(), ((HashSet) entry.getValue()).clone());
|
||||
} else if (entry.getValue() instanceof EnumSet) {
|
||||
this.values.put(entry.getKey(), ((EnumSet) entry.getValue()).clone());
|
||||
} else {
|
||||
this.values.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
@ -986,7 +988,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
* object may be changed by AI simulation or rollbacks, because the Value
|
||||
* objects are not copied as the state class is copied. Mutable supported:
|
||||
* HashSet with immutable entries (e.g. HashSet< UUID > or HashSet< String
|
||||
* >)
|
||||
* > and EnumSets)
|
||||
*
|
||||
* @param valueId
|
||||
* @param value
|
||||
|
|
Loading…
Reference in a new issue