diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index acf3f1d17b0..4735bc78dc6 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -1271,13 +1271,16 @@ public class PlayerControllerAi extends PlayerController { } @Override - public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title) { + public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title, boolean isOptional) { CardCollection choices = new CardCollection(); for (String mapKey: validMap.keySet()) { CardCollection cc = validMap.get(mapKey); cc.removeAll(choices); - choices.add(ComputerUtilCard.getBestAI(cc)); // TODO: should the AI limit itself here with the max number of cards in hand? + Card chosen = ComputerUtilCard.getBestAI(cc); + if (chosen != null) { + choices.add(chosen); + } } return choices; diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java index dfeccc06ade..f4eb10f558c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java @@ -10,6 +10,7 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardCollection; +import forge.game.card.CardCollectionView; import forge.game.card.CardLists; import forge.game.card.CardZoneTable; import forge.game.player.Player; @@ -22,7 +23,6 @@ public class DigMultipleEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { - // TODO Auto-generated method stub final Card host = sa.getHostCard(); final Player player = sa.getActivatingPlayer(); final Game game = player.getGame(); @@ -37,6 +37,7 @@ public class DigMultipleEffect extends SpellAbilityEffect { final int libraryPosition2 = sa.hasParam("LibraryPosition2") ? Integer.parseInt(sa.getParam("LibraryPosition2")) : -1; String changeValid = sa.hasParam("ChangeValid") ? sa.getParam("ChangeValid") : ""; + boolean chooseOptional = sa.hasParam("Optional"); CardZoneTable table = new CardZoneTable(); for (final Player p : getTargetPlayers(sa)) { @@ -79,12 +80,33 @@ public class DigMultipleEffect extends SpellAbilityEffect { continue; } - CardCollection chosen = chooser.getController().chooseCardsForEffectMultiple(validMap, sa, Localizer.getInstance().getMessage("lblChooseCards")); + CardCollection chosen = chooser.getController().chooseCardsForEffectMultiple(validMap, sa, Localizer.getInstance().getMessage("lblChooseCards"), chooseOptional); if (!chosen.isEmpty()) { game.getAction().reveal(chosen, chooser, true, Localizer.getInstance().getMessage("lblPlayerPickedCardFrom", chooser.getName())); } + if (sa.hasParam("ChooseAmount") || sa.hasParam("ChosenZone")) { + int amount = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("ChooseAmount", "1"), sa); + final ZoneType chosenZone = sa.hasParam("ChosenZone") ? ZoneType.smartValueOf(sa.getParam("ChosenZone")) : ZoneType.Battlefield; + + CardCollectionView extraChosen = chooser.getController().chooseCardsForEffect(chosen, sa, Localizer.getInstance().getMessage("lblChooseCards"), amount, amount, false); + if (!extraChosen.isEmpty()) { + game.getAction().reveal(extraChosen, chooser, true, Localizer.getInstance().getMessage("lblPlayerPickedCardFrom", chooser.getName())); + } + + for (Card c : extraChosen) { + final ZoneType origin = c.getZone().getZoneType(); + final PlayerZone zone = c.getOwner().getZone(chosenZone); + chosen.remove(c); + rest.remove(c); + c = game.getAction().moveTo(zone, c, sa); + if (!origin.equals(c.getZone().getZoneType())) { + table.put(origin, c.getZone().getZoneType(), c); + } + } + } + for (Card c : chosen) { final ZoneType origin = c.getZone().getZoneType(); final PlayerZone zone = c.getOwner().getZone(destZone1); diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index ec79ece50b7..81a022dc51f 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -274,5 +274,5 @@ public abstract class PlayerController { public abstract boolean confirmMulliganScry(final Player p); public abstract CardCollection chooseCardsForEffectMultiple(Map validMap, - SpellAbility sa, String title); + SpellAbility sa, String title, boolean isOptional); } diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index 921b860fc40..2ecb8fceaff 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -698,7 +698,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title) { + public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title, boolean isOptional) { // TODO Auto-generated method stub return new CardCollection(); } diff --git a/forge-gui/res/cardsfolder/b/benefaction_of_rhonas.txt b/forge-gui/res/cardsfolder/b/benefaction_of_rhonas.txt index 9241011976b..c7e8891df88 100644 --- a/forge-gui/res/cardsfolder/b/benefaction_of_rhonas.txt +++ b/forge-gui/res/cardsfolder/b/benefaction_of_rhonas.txt @@ -1,6 +1,5 @@ Name:Benefaction of Rhonas ManaCost:2 G Types:Sorcery -A:SP$ DigMultiple | Cost$ 2 G | DigNum$ 5 | Reveal$ True | ChangeValid$ Creature,Enchantment | DestinationZone2$ Graveyard | SpellDescription$ Reveal the top five cards of your library. You may put a creature card and/or an enchantment card from among them into your hand. Put the rest into your graveyard. -SVar:Picture:http://www.wizards.com/global/images/magic/general/benefaction_of_rhonas.jpg +A:SP$ DigMultiple | Cost$ 2 G | DigNum$ 5 | Reveal$ True | ChangeValid$ Creature,Enchantment | DestinationZone2$ Graveyard | Optional$ True | SpellDescription$ Reveal the top five cards of your library. You may put a creature card and/or an enchantment card from among them into your hand. Put the rest into your graveyard. Oracle:Reveal the top five cards of your library. You may put a creature card and/or an enchantment card from among them into your hand. Put the rest into your graveyard. diff --git a/forge-gui/res/cardsfolder/g/gift_of_the_gargantuan.txt b/forge-gui/res/cardsfolder/g/gift_of_the_gargantuan.txt index 3e1caceb1d7..b5a92704cd7 100644 --- a/forge-gui/res/cardsfolder/g/gift_of_the_gargantuan.txt +++ b/forge-gui/res/cardsfolder/g/gift_of_the_gargantuan.txt @@ -1,6 +1,5 @@ Name:Gift of the Gargantuan ManaCost:2 G Types:Sorcery -A:SP$ DigMultiple | Cost$ 2 G | DigNum$ 4 | ChangeValid$ Creature,Land | SpellDescription$ Look at the top four cards of your library. You may reveal a creature card and/or a land card from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in any order. -SVar:Picture:http://www.wizards.com/global/images/magic/general/gift_of_the_gargantuan.jpg +A:SP$ DigMultiple | Cost$ 2 G | DigNum$ 4 | ChangeValid$ Creature,Land | Optional$ True | SpellDescription$ Look at the top four cards of your library. You may reveal a creature card and/or a land card from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in any order. Oracle:Look at the top four cards of your library. You may reveal a creature card and/or a land card from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in any order. diff --git a/forge-gui/res/cardsfolder/k/kaalia_zenith_seeker.txt b/forge-gui/res/cardsfolder/k/kaalia_zenith_seeker.txt index 1e63c75d05b..e96324a73e2 100644 --- a/forge-gui/res/cardsfolder/k/kaalia_zenith_seeker.txt +++ b/forge-gui/res/cardsfolder/k/kaalia_zenith_seeker.txt @@ -5,5 +5,5 @@ PT:3/3 K:Flying K:Vigilance T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDigMulti | TriggerDescription$ When CARDNAME enters the battlefield, look at the top six cards of your library. You may reveal an Angel card, a Demon card, and/or a Dragon card from among them and put them into your hand. Put the rest on the bottom of your library in a random order. -SVar:TrigDigMulti:DB$ DigMultiple | DigNum$ 6 | ChangeValid$ Card.Angel,Card.Demon,Card.Dragon | SourceZone$ Library | DestinationZone$ Hand | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True +SVar:TrigDigMulti:DB$ DigMultiple | DigNum$ 6 | ChangeValid$ Card.Angel,Card.Demon,Card.Dragon | SourceZone$ Library | DestinationZone$ Hand | DestinationZone2$ Library | LibraryPosition$ -1 | RestRandomOrder$ True | Optional$ True Oracle:Flying, vigilance\nWhen Kaalia, Zenith Seeker enters the battlefield, look at the top six cards of your library. You may reveal an Angel card, a Demon card, and/or a Dragon card from among them and put them into your hand. Put the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/r/relentless_pursuit.txt b/forge-gui/res/cardsfolder/r/relentless_pursuit.txt index e165ce44519..d6353ee3873 100644 --- a/forge-gui/res/cardsfolder/r/relentless_pursuit.txt +++ b/forge-gui/res/cardsfolder/r/relentless_pursuit.txt @@ -1,5 +1,5 @@ Name:Relentless Pursuit ManaCost:2 G Types:Sorcery -A:SP$ DigMultiple | Cost$ 2 G | DigNum$ 4 | Reveal$ True | ChangeValid$ Creature,Land | DestinationZone2$ Graveyard | SpellDescription$ Reveal the top four cards of your library. You may put a creature card and/or land card from among them into your hand. Put the rest into your graveyard. +A:SP$ DigMultiple | Cost$ 2 G | DigNum$ 4 | Reveal$ True | ChangeValid$ Creature,Land | DestinationZone2$ Graveyard | Optional$ True | SpellDescription$ Reveal the top four cards of your library. You may put a creature card and/or land card from among them into your hand. Put the rest into your graveyard. Oracle:Reveal the top four cards of your library. You may put a creature card and/or land card from among them into your hand. Put the rest into your graveyard. diff --git a/forge-gui/res/cardsfolder/s/selective_adaptation.txt b/forge-gui/res/cardsfolder/s/selective_adaptation.txt index f1ae1776edc..f2f19b01477 100755 --- a/forge-gui/res/cardsfolder/s/selective_adaptation.txt +++ b/forge-gui/res/cardsfolder/s/selective_adaptation.txt @@ -1,22 +1,5 @@ Name:Selective Adaptation ManaCost:4 G G Types:Sorcery -A:SP$ Dig | Cost$ 4 G G | DigNum$ 7 | ChangeNum$ All | Reveal$ True | Imprint$ True | DestinationZone$ Library | LibraryPosition$ 0 | SubAbility$ Flying | StackDescription$ SpellDescription | SpellDescription$ Reveal the top seven cards of your library. Choose from among them a card with flying, a card with first strike, and so on for double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, reach, trample, and vigilance. Put one of the chosen cards onto the battlefield, the other chosen cards into your hand, and the rest into your graveyard. -SVar:Flying:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withFlying | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with flying | StackDescription$ None | SubAbility$ FirstStrike -SVar:FirstStrike:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withFirst Strike | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with first strike | StackDescription$ None | SubAbility$ DoubleStrike -SVar:DoubleStrike:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withDouble Strike | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with double strike | StackDescription$ None | SubAbility$ Deathtouch -SVar:Deathtouch:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withDeathtouch | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with deathtouch | StackDescription$ None | SubAbility$ Haste -SVar:Haste:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withHaste | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with haste | StackDescription$ None | SubAbility$ Hexproof -SVar:Hexproof:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withHexproof | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with hexproof | StackDescription$ None | SubAbility$ Indestructible -SVar:Indestructible:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withIndestructible | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with indestructible | StackDescription$ None | SubAbility$ Lifelink -SVar:Lifelink:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withLifelink | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with lifelink | StackDescription$ None | SubAbility$ Menace -SVar:Menace:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withMenace | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with menace | StackDescription$ None | SubAbility$ Reach -SVar:Reach:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withReach | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with reach | StackDescription$ None | SubAbility$ Trample -SVar:Trample:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withTrample | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with trample | StackDescription$ None | SubAbility$ Vigilance -SVar:Vigilance:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsImprinted+withVigilance | ChoiceZone$ Library | RememberChosen$ True | Mandatory$ True | ChoiceTitle$ Choose a card with vigilance | StackDescription$ None | SubAbility$ OneBattlefield -SVar:OneBattlefield:DB$ ChooseCard | Amount$ 1 | Choices$ Card.IsRemembered | ChoiceZone$ Library | Mandatory$ True | ChoiceTitle$ Choose one card to put onto the battlefield | StackDescription$ None | SubAbility$ DBChangeZone -SVar:DBChangeZone:DB$ ChangeZone | Defined$ ChosenCard | ForgetChanged$ True | Origin$ Library | Destination$ Battlefield | ChangeNum$ 1 | ChangeType$ Card.IsRemembered | StackDescription$ None | SubAbility$ OthersHand -SVar:OthersHand:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand | StackDescription$ None | SubAbility$ RestGraveyard -SVar:RestGraveyard:DB$ ChangeZoneAll | ChangeType$ Card.IsImprinted+inZoneLibrary | Origin$ Library | Destination$ Graveyard | StackDescription$ None | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True | ClearChosenCard$ True +A:SP$ DigMultiple | Cost$ 4 G G | DigNum$ 7 | Reveal$ True | ChangeValid$ Card.withFlying,Card.withFirst Strike,Card.withDeathtouch,Card.withHaste,Card.withHexproof,Card.withIndestructible,Card.withLifelink,Card.withMenace,Card.withReach,Card.withTrample,Card.withVigilance | SourceZone$ Library | ChooseAmount$ 1 | ChosenZone$ Battlefield | DestinationZone$ Hand | DestinationZone2$ Graveyard | StackDescription$ SpellDescription | SpellDescription$ Reveal the top seven cards of your library. Choose from among them a card with flying, a card with first strike, and so on for double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, reach, trample, and vigilance. Put one of the chosen cards onto the battlefield, the other chosen cards into your hand, and the rest into your graveyard. Oracle:Reveal the top seven cards of your library. Choose from among them a card with flying, a card with first strike, and so on for double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, reach, trample, and vigilance. Put one of the chosen cards onto the battlefield, the other chosen cards into your hand, and the rest into your graveyard. diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 2cdae5587e3..9e94b7609f9 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -2934,10 +2934,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } @Override - public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title) { + public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title, boolean isOptional) { CardCollection result = new CardCollection(); for (Map.Entry e : validMap.entrySet()) { - result.addAll(chooseCardsForEffect(e.getValue(), sa, title + " " + e.getKey(), 0, 1, true)); + result.addAll(chooseCardsForEffect(e.getValue(), sa, title + " " + e.getKey(), 0, 1, isOptional)); } return result; }