diff --git a/Mage.Common/src/mage/view/CardsView.java b/Mage.Common/src/mage/view/CardsView.java index 63d079a7194..0d350ab4fc7 100644 --- a/Mage.Common/src/mage/view/CardsView.java +++ b/Mage.Common/src/mage/view/CardsView.java @@ -36,6 +36,7 @@ import mage.abilities.Ability; import mage.cards.Card; import mage.game.Game; import mage.game.GameState; +import mage.game.permanent.Permanent; /** * @@ -63,7 +64,7 @@ public class CardsView extends HashMap { case BATTLEFIELD: sourceCard = game.getPermanent(ability.getSourceId()); if (sourceCard == null) - sourceCard = game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD); + sourceCard = (Permanent)game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD); break; } if (sourceCard != null) { diff --git a/Mage.Common/src/mage/view/GameClientMessage.java b/Mage.Common/src/mage/view/GameClientMessage.java index 0bf124e68ce..7cc3b809d37 100644 --- a/Mage.Common/src/mage/view/GameClientMessage.java +++ b/Mage.Common/src/mage/view/GameClientMessage.java @@ -46,6 +46,7 @@ public class GameClientMessage implements Serializable { private String message; private AbilityPickerView abilityView; private boolean flag; + private boolean cancel; private String[] strings; private Set targets; private int min; diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index fa7df354354..16dba337ad6 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -216,6 +216,72 @@ public class ComputerPlayer> extends PlayerImpl i return true; } } + if (target instanceof TargetCreatureOrPlayer) { + List targets; + TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer)target); + if (outcome.isGood()) { + targets = threats(playerId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game, target.getTargets()); + } + else { + targets = threats(opponentId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game, target.getTargets()); + } + for (Permanent permanent : targets) { + List alreadyTargetted = target.getTargets(); + if (t.canTarget(playerId, permanent.getId(), null, game)) { + if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) { + target.add(permanent.getId(), game); + return true; + } + } + } + if (outcome.isGood()) { + if (target.canTarget(playerId, null, game)) { + target.add(playerId, game); + return true; + } + } + else { + if (target.canTarget(opponentId, null, game)) { + target.add(opponentId, game); + return true; + } + } + if (!target.isRequired()) + return false; + } + if (target instanceof TargetPermanentOrPlayer) { + List targets; + TargetPermanentOrPlayer t = ((TargetPermanentOrPlayer)target); + if (outcome.isGood()) { + targets = threats(playerId, ((FilterPermanentOrPlayer)t.getFilter()).getPermanentFilter(), game, target.getTargets()); + } + else { + targets = threats(opponentId, ((FilterPermanentOrPlayer)t.getFilter()).getPermanentFilter(), game, target.getTargets()); + } + for (Permanent permanent : targets) { + List alreadyTargetted = target.getTargets(); + if (t.canTarget(permanent.getId(), game)) { + if (alreadyTargetted != null && !alreadyTargetted.contains(permanent.getId())) { + target.add(permanent.getId(), game); + return true; + } + } + } + if (outcome.isGood()) { + if (target.canTarget(playerId, null, game)) { + target.add(playerId, game); + return true; + } + } + else { + if (target.canTarget(opponentId, null, game)) { + target.add(opponentId, game); + return true; + } + } + if (!target.isRequired()) + return false; + } return false; } diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java index fe2fcc52da7..5e84a065dd5 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java @@ -60,7 +60,7 @@ public class ComputerPlayerMCTS extends ComputerPlayer imple private static final int THINK_MIN_RATIO = 40; private static final int THINK_MAX_RATIO = 100; private static final double THINK_TIME_MULTIPLIER = 2.0; - private static final boolean USE_MULTIPLE_THREADS = false; + private static final boolean USE_MULTIPLE_THREADS = true; protected transient MCTSNode root; protected int maxThinkTime; diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java index 0b4fb0a73e4..0a4eadab0af 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSNode.java @@ -118,9 +118,9 @@ public class MCTSNode { double uct; if (node.visits > 0) if (isTarget) - uct = (node.wins / (node.visits + 1.0)) + (selectionCoefficient * Math.sqrt(Math.log(visits + 1.0) / (node.visits + 1.0))); + uct = (node.wins / (node.visits)) + (selectionCoefficient * Math.sqrt(Math.log(visits) / (node.visits))); else - uct = ((node.visits - node.wins) / (node.visits + 1.0)) + (selectionCoefficient * Math.sqrt(Math.log(visits + 1.0) / (node.visits + 1.0))); + uct = ((node.visits - node.wins) / (node.visits)) + (selectionCoefficient * Math.sqrt(Math.log(visits) / (node.visits))); else // ensure that a random unvisited node is played first uct = 10000 + 1000 * Math.random(); diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java index 66ab3381d42..2d994495779 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java @@ -130,8 +130,10 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { } if (ability.getManaCosts().getVariableCosts().size() > 0) { int amount = getAvailableManaProducers(game).size() - ability.getManaCosts().convertedManaCost(); - if (amount > 0) + if (amount > 0) { + ability = ability.copy(); ability.getManaCostsToPay().add(new GenericManaCost(rnd.nextInt(amount))); + } } // check if ability kills player, if not then it's ok to play // if (ability.isUsesStack()) { diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 928761f7cb0..3703d1642ae 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -6,7 +6,7 @@ - + diff --git a/Mage.Server/plugins/mage-player-ai-ma.jar b/Mage.Server/plugins/mage-player-ai-ma.jar index cc217100107..d8b70d9a0da 100644 Binary files a/Mage.Server/plugins/mage-player-ai-ma.jar and b/Mage.Server/plugins/mage-player-ai-ma.jar differ diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar index 97350a037ac..cf196b3c470 100644 Binary files a/Mage.Server/plugins/mage-player-ai.jar and b/Mage.Server/plugins/mage-player-ai.jar differ diff --git a/Mage.Server/plugins/mage-player-aimcts.jar b/Mage.Server/plugins/mage-player-aimcts.jar index ea7c63dd723..d8845a2f6e8 100644 Binary files a/Mage.Server/plugins/mage-player-aimcts.jar and b/Mage.Server/plugins/mage-player-aimcts.jar differ diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index 380c682b720..7cfdbe3e828 100644 Binary files a/Mage.Server/plugins/mage-player-aiminimax.jar and b/Mage.Server/plugins/mage-player-aiminimax.jar differ diff --git a/Mage.Server/plugins/mage-player-human.jar b/Mage.Server/plugins/mage-player-human.jar index 382b3443e1e..9d56fb86dcf 100644 Binary files a/Mage.Server/plugins/mage-player-human.jar and b/Mage.Server/plugins/mage-player-human.jar differ diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java b/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java index 70f9bf5e623..16165e839c1 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/FloatingDreamZubera.java @@ -35,6 +35,7 @@ import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.WatcherScope; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; @@ -96,7 +97,7 @@ class ZuberasDiedWatcher extends WatcherImpl { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { - Card card = game.getLastKnownInformation(event.getTargetId(), Constants.Zone.BATTLEFIELD); + MageObject card = game.getLastKnownInformation(event.getTargetId(), Constants.Zone.BATTLEFIELD); if (card != null && card.hasSubtype("Zubera")) { zuberasDiedThisTurn++; } diff --git a/Mage.Sets/src/mage/sets/innistrad/GutterGrime.java b/Mage.Sets/src/mage/sets/innistrad/GutterGrime.java index 8ade483eb45..226940a1391 100644 --- a/Mage.Sets/src/mage/sets/innistrad/GutterGrime.java +++ b/Mage.Sets/src/mage/sets/innistrad/GutterGrime.java @@ -36,6 +36,7 @@ import mage.Constants.Rarity; import mage.Constants.SubLayer; import mage.Constants.Zone; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; @@ -103,7 +104,7 @@ class GutterGrimeTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean apply(Game game, Ability source) { - Card card = game.getLastKnownInformation(source.getFirstTarget(), Constants.Zone.BATTLEFIELD); - if (card != null) { + MageObject card = game.getLastKnownInformation(source.getFirstTarget(), Constants.Zone.BATTLEFIELD); + if (card != null) { int cost = card.getManaCost().get(0).convertedManaCost(); Player player = game.getPlayer(source.getControllerId()); if (player != null) { player.gainLife(cost, game); } - } + } return true; } diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/Mirrorworks.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/Mirrorworks.java index 5cd575e7275..92e2f4a7eac 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/Mirrorworks.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/Mirrorworks.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.Constants; import mage.Constants.CardType; import mage.Constants.Rarity; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.Cost; @@ -134,10 +135,10 @@ class MirrorworksEffect extends OneShotEffect { if (cost.pay(source, game, source.getId(), source.getControllerId(), false)) { UUID targetId = targetPointer.getFirst(source); if (targetId != null) { - Card target = game.getLastKnownInformation(targetId, Constants.Zone.BATTLEFIELD); - if (target != null) { + MageObject target = game.getLastKnownInformation(targetId, Constants.Zone.BATTLEFIELD); + if (target != null && target instanceof Permanent) { EmptyToken token = new EmptyToken(); - CardUtil.copyTo(token).from(target); + CardUtil.copyTo(token).from((Permanent)target); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); return true; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/FreshMeat.java b/Mage.Sets/src/mage/sets/newphyrexia/FreshMeat.java index 0c7326d0ea9..5f934b29f0d 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/FreshMeat.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/FreshMeat.java @@ -32,6 +32,7 @@ import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.WatcherScope; import mage.Constants.Zone; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.common.CreateTokenEffect; @@ -96,8 +97,8 @@ class FreshMeatWatcher extends WatcherImpl { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { - Card card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (card != null && card.getOwnerId().equals(this.controllerId) && card.getCardType().contains(CardType.CREATURE)) { + MageObject card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); + if (card != null && ((Card)card).getOwnerId().equals(this.controllerId) && card.getCardType().contains(CardType.CREATURE)) { creaturesCount++; } } diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/PawnOfUlamog.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/PawnOfUlamog.java index 0ddfebbb8a6..eceef182207 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/PawnOfUlamog.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/PawnOfUlamog.java @@ -32,6 +32,7 @@ import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; import mage.MageInt; +import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.Card; @@ -92,7 +93,7 @@ class PawnOfUlamogTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Card c = game.getLastKnownInformation(targetPointer.getFirst(source), Constants.Zone.BATTLEFIELD); + MageObject c = game.getLastKnownInformation(targetPointer.getFirst(source), Constants.Zone.BATTLEFIELD); if (c != null && controller != null) { controller.gainLife(c.getPower().getValue(), game); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/FleshAllergy.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/FleshAllergy.java index 0a2581ae557..be87145a7e0 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/FleshAllergy.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/FleshAllergy.java @@ -35,6 +35,7 @@ import mage.Constants.Outcome; import mage.Constants.Rarity; import mage.Constants.WatcherScope; import mage.Constants.Zone; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.effects.OneShotEffect; @@ -99,7 +100,7 @@ class FleshAllergyWatcher extends WatcherImpl { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) { - Card card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); + MageObject card = game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); if (card != null && card.getCardType().contains(CardType.CREATURE)) { creaturesDiedThisTurn++; } @@ -133,7 +134,7 @@ class FleshAllergyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { FleshAllergyWatcher watcher = (FleshAllergyWatcher) game.getState().getWatchers().get("CreaturesDied"); - Card card = game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); + MageObject card = game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); if (card != null && watcher != null) { Player player = game.getPlayer(((Permanent)card).getControllerId()); if (player != null) { diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrPropagator.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrPropagator.java index c1ca9ba7d6b..43ad234c23e 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrPropagator.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/MyrPropagator.java @@ -44,6 +44,7 @@ import mage.sets.tokens.EmptyToken; import mage.util.CardUtil; import java.util.UUID; +import mage.MageObject; /** * @@ -93,10 +94,10 @@ class MyrPropagatorCreateTokenEffect extends OneShotEffect { if (player != null) { Card card = player.getGraveyard().get(source.getFirstTarget(), game); if (card == null) { - card = game.getLastKnownInformation(source.getFirstTarget(), Zone.GRAVEYARD); + card = (Card)game.getLastKnownInformation(source.getFirstTarget(), Zone.GRAVEYARD); } if (card != null) { player.gainLife(card.getManaCost().convertedManaCost(), game); diff --git a/Mage.Tests/plugins/mage-player-ai-ma.jar b/Mage.Tests/plugins/mage-player-ai-ma.jar index 256949fc8d6..88614c6e2ad 100644 Binary files a/Mage.Tests/plugins/mage-player-ai-ma.jar and b/Mage.Tests/plugins/mage-player-ai-ma.jar differ diff --git a/Mage.Tests/plugins/mage-player-ai.jar b/Mage.Tests/plugins/mage-player-ai.jar index e66864a702b..387174114dd 100644 Binary files a/Mage.Tests/plugins/mage-player-ai.jar and b/Mage.Tests/plugins/mage-player-ai.jar differ diff --git a/Mage/src/mage/abilities/common/DiesAndDealtDamageThisTurnTriggeredAbility.java b/Mage/src/mage/abilities/common/DiesAndDealtDamageThisTurnTriggeredAbility.java index ebe91530c09..9decb38e546 100644 --- a/Mage/src/mage/abilities/common/DiesAndDealtDamageThisTurnTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DiesAndDealtDamageThisTurnTriggeredAbility.java @@ -1,6 +1,7 @@ package mage.abilities.common; import mage.Constants; +import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.cards.Card; @@ -31,8 +32,8 @@ public class DiesAndDealtDamageThisTurnTriggeredAbility extends TriggeredAbility @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) { - Card card = game.getLastKnownInformation(event.getTargetId(), Constants.Zone.BATTLEFIELD); - if (card instanceof Permanent && ((Permanent)card).getDealtDamageByThisTurn().contains(this.sourceId)) { + MageObject object = game.getLastKnownInformation(event.getTargetId(), Constants.Zone.BATTLEFIELD); + if (object instanceof Permanent && ((Permanent)object).getDealtDamageByThisTurn().contains(this.sourceId)) { return true; } } diff --git a/Mage/src/mage/abilities/common/DiesTriggeredAbility.java b/Mage/src/mage/abilities/common/DiesTriggeredAbility.java index 67829e77694..b0798164e6c 100644 --- a/Mage/src/mage/abilities/common/DiesTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DiesTriggeredAbility.java @@ -32,6 +32,7 @@ import java.util.UUID; import mage.Constants; import mage.Constants.Zone; +import mage.MageObject; import mage.abilities.effects.Effect; import mage.cards.Card; import mage.game.Game; @@ -60,7 +61,7 @@ public class DiesTriggeredAbility extends ZoneChangeTriggeredAbility> implements Game, Serializa protected transient PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource(); protected Map gameCards = new HashMap(); - protected Map lki = new HashMap(); + protected Map lki = new HashMap(); protected GameState state; protected Date startTime; @@ -1206,13 +1206,13 @@ public abstract class GameImpl> implements Game, Serializa * @return */ @Override - public Card getLastKnownInformation(UUID objectId, Zone zone) { + public MageObject getLastKnownInformation(UUID objectId, Zone zone) { /*if (!lki.containsKey(objectId)) { return getCard(objectId); }*/ - Card card = lki.get(objectId); - if (card != null) { - return card.copy(); + MageObject object = lki.get(objectId); + if (object != null) { + return object.copy(); } return null; } @@ -1225,9 +1225,11 @@ public abstract class GameImpl> implements Game, Serializa * @param card */ @Override - public void rememberLKI(UUID objectId, Zone zone, Card card) { - Card copy = card.copy(); - lki.put(objectId, copy); + public void rememberLKI(UUID objectId, Zone zone, MageObject object) { + if (object instanceof Permanent || object instanceof StackObject) { + MageObject copy = object.copy(); + lki.put(objectId, copy); + } } /** diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index ed6eecb77d2..97c9f810392 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -71,6 +71,8 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.stack.StackAbility; import mage.players.net.UserData; +import mage.target.Target; +import mage.target.TargetAmount; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetDiscard; import mage.watchers.common.BloodthirstWatcher; @@ -1278,15 +1280,25 @@ public abstract class PlayerImpl> implements Player, Ser } private void addTargetOptions(List options, Ability option, int targetNum, Game game) { - for (UUID targetId: option.getTargets().getUnchosen().get(targetNum).possibleTargets(option.getSourceId(), playerId, game)) { - Ability newOption = option.copy(); - newOption.getTargets().get(targetNum).addTarget(targetId, option, game, true); - if (targetNum < option.getTargets().size() - 2) { + for (Target target: option.getTargets().getUnchosen().get(targetNum).getTargetOptions(option, game)) { + Ability newOption = option.copy(); + if (target instanceof TargetAmount) { + for (UUID targetId: target.getTargets()) { + int amount = target.getTargetAmount(targetId); + newOption.getTargets().get(targetNum).addTarget(targetId, amount, newOption, game, true); + } + } + else { + for (UUID targetId: target.getTargets()) { + newOption.getTargets().get(targetNum).addTarget(targetId, newOption, game, true); + } + } + if (targetNum < option.getTargets().size() - 2) { //addTargetOptions(options, newOption, targetNum + 1, game); // ayrat: bug fix addTargetOptions(options, newOption, targetNum + 1, game); } - else { + else { if (option.getChoices().size() > 0) addChoiceOptions(options, newOption, 0, game); else if (option.getCosts().getTargets().size() > 0) diff --git a/Mage/src/mage/target/Target.java b/Mage/src/mage/target/Target.java index 9d10d04bd16..073ee3f3d53 100644 --- a/Mage/src/mage/target/Target.java +++ b/Mage/src/mage/target/Target.java @@ -61,6 +61,7 @@ public interface Target extends Serializable { public boolean canTarget(UUID id, Game game); public boolean canTarget(UUID id, Ability source, Game game); public boolean isLegal(Ability source, Game game); + public List getTargetOptions(Ability source, Game game); //methods for non-targets public boolean canChoose(UUID sourceControllerId, Game game); diff --git a/Mage/src/mage/target/TargetAmount.java b/Mage/src/mage/target/TargetAmount.java index 079cb430688..c260dcccb67 100644 --- a/Mage/src/mage/target/TargetAmount.java +++ b/Mage/src/mage/target/TargetAmount.java @@ -28,7 +28,7 @@ package mage.target; -import java.util.UUID; +import java.util.*; import mage.Constants.Outcome; import mage.abilities.Ability; import mage.game.Game; @@ -95,5 +95,36 @@ public abstract class TargetAmount> extends TargetImpl } return chosen = true; } + + @Override + public List getTargetOptions(Ability source, Game game) { + List options = new ArrayList(); + Set possibleTargets = possibleTargets(source.getSourceId(), source.getControllerId(), game); + + addTargets(this, possibleTargets, options, source, game); + + return options; + } + protected void addTargets(TargetAmount target, Set targets, List options, Ability source, Game game) { + for (UUID targetId: targets) { + for (int n = 1; n <= target.remainingAmount; n++) { + T t = target.copy(); + t.addTarget(targetId, n, source, game, true); + if (t.remainingAmount > 0) { + if (targets.size() > 1) { + Set newTargets = new HashSet(); + for (UUID newTarget: targets) { + if (!newTarget.equals(targetId)) + newTargets.add(newTarget); + } + addTargets(t, newTargets, options, source, game); + } + } + else { + options.add(t); + } + } + } + } } diff --git a/Mage/src/mage/target/TargetImpl.java b/Mage/src/mage/target/TargetImpl.java index 7eaec494faa..f6d0a7b9a74 100644 --- a/Mage/src/mage/target/TargetImpl.java +++ b/Mage/src/mage/target/TargetImpl.java @@ -28,12 +28,8 @@ package mage.target; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.UUID; import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.Ability; @@ -260,6 +256,30 @@ public abstract class TargetImpl> implements Target { return true; } + @Override + public List getTargetOptions(Ability source, Game game) { + List options = new ArrayList(); + Set possibleTargets = possibleTargets(source.getSourceId(), source.getControllerId(), game); + possibleTargets.removeAll(getTargets()); + Iterator it = possibleTargets.iterator(); + while (it.hasNext()) { + UUID targetId = it.next(); + T target = this.copy(); + target.clearChosen(); + target.addTarget(targetId, source, game, true); + if (!target.isChosen()) { + Iterator it2 = possibleTargets.iterator(); + while (it2.hasNext()&& !target.isChosen()) { + UUID nextTargetId = it2.next(); + target.addTarget(nextTargetId, source, game, true); + } + } + if (target.isChosen()) + options.add(target); + } + return options; + } + @Override public List getTargets() { return new ArrayList(targets.keySet());