diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index d7c923a9417..ec0217fede2 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -95,15 +95,9 @@ public class ComputerPlayer6 extends ComputerPlayer implements this.currentScore = player.currentScore; if (player.combat != null) this.combat = player.combat.copy(); - for (Ability ability: player.actions) { - actions.add(ability); - } - for (UUID targetId: player.targets) { - targets.add(targetId); - } - for (String choice: player.choices) { - choices.add(choice); - } + this.actions.addAll(player.actions); + this.targets.addAll(player.targets); + this.choices.addAll(player.choices); } @Override @@ -773,7 +767,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements Game sim = game.copy(); for (Player copyPlayer: sim.getState().getPlayers().values()) { - Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId()); + Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId()).copy(); SimulatedPlayer2 newPlayer = new SimulatedPlayer2(copyPlayer.getId(), copyPlayer.getId().equals(playerId), suggested); newPlayer.restore(origPlayer); sim.getState().getPlayers().put(copyPlayer.getId(), newPlayer); 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 fa2d05990fd..721e26eddbd 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 @@ -180,7 +180,7 @@ public class ComputerPlayer> extends PlayerImpl i } if (target instanceof TargetControlledPermanent) { List targets; - targets = threats(playerId, ((TargetControlledPermanent)target).getFilter(), game); + targets = threats(playerId, ((TargetControlledPermanent)target).getFilter(), game, target.getTargets()); if (!outcome.isGood()) Collections.reverse(targets); for (Permanent permanent: targets) { @@ -193,10 +193,10 @@ public class ComputerPlayer> extends PlayerImpl i if (target instanceof TargetPermanent) { List targets; if (outcome.isGood()) { - targets = threats(playerId, ((TargetPermanent)target).getFilter(), game); + targets = threats(playerId, ((TargetPermanent)target).getFilter(), game, target.getTargets()); } else { - targets = threats(opponentId, ((TargetPermanent)target).getFilter(), game); + targets = threats(opponentId, ((TargetPermanent)target).getFilter(), game, target.getTargets()); } for (Permanent permanent: targets) { if (((TargetPermanent)target).canTarget(playerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) { @@ -268,7 +268,7 @@ public class ComputerPlayer> extends PlayerImpl i } if (target instanceof TargetControlledPermanent) { List targets; - targets = threats(playerId, ((TargetControlledPermanent)target).getFilter(), game); + targets = threats(playerId, ((TargetControlledPermanent)target).getFilter(), game, target.getTargets()); if (!outcome.isGood()) Collections.reverse(targets); for (Permanent permanent: targets) { @@ -282,10 +282,10 @@ public class ComputerPlayer> extends PlayerImpl i if (target instanceof TargetPermanent) { List targets; if (outcome.isGood()) { - targets = threats(playerId, ((TargetPermanent)target).getFilter(), game); + targets = threats(playerId, ((TargetPermanent)target).getFilter(), game, target.getTargets()); } else { - targets = threats(opponentId, ((TargetPermanent)target).getFilter(), game); + targets = threats(opponentId, ((TargetPermanent)target).getFilter(), game, target.getTargets()); } for (Permanent permanent: targets) { if (((TargetPermanent)target).canTarget(playerId, permanent.getId(), source, game)) { @@ -299,10 +299,10 @@ public class ComputerPlayer> extends PlayerImpl i List targets; TargetCreatureOrPlayer t = ((TargetCreatureOrPlayer)target); if (outcome.isGood()) { - targets = threats(playerId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game); + targets = threats(playerId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game, target.getTargets()); } else { - targets = threats(opponentId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game); + targets = threats(opponentId, ((FilterCreatureOrPlayer)t.getFilter()).getCreatureFilter(), game, target.getTargets()); } for (Permanent permanent: targets) { List alreadyTargetted = target.getTargets(); @@ -395,10 +395,10 @@ public class ComputerPlayer> extends PlayerImpl i } List targets; if (outcome.isGood()) { - targets = threats(playerId, new FilterCreaturePermanent(), game); + targets = threats(playerId, new FilterCreaturePermanent(), game, target.getTargets()); } else { - targets = threats(opponentId, new FilterCreaturePermanent(), game); + targets = threats(opponentId, new FilterCreaturePermanent(), game, target.getTargets()); } for (Permanent permanent: targets) { if (target.canTarget(permanent.getId(), source, game)) { @@ -1301,8 +1301,14 @@ public class ComputerPlayer> extends PlayerImpl i return worst; } - protected List threats(UUID playerId, FilterPermanent filter, Game game) { + protected List threats(UUID playerId, FilterPermanent filter, Game game, List targets) { List threats = game.getBattlefield().getAllActivePermanents(filter, playerId); + Iterator it = threats.iterator(); + while (it.hasNext()) { // remove permanents already targetted + Permanent test = it.next(); + if (targets.contains(test.getId())) + it.remove(); + } Collections.sort(threats, new PermanentComparator(game)); return threats; } diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java index 080567c5777..4a6205e574f 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java @@ -120,15 +120,9 @@ public class ComputerPlayer2 extends ComputerPlayer implements this.currentScore = player.currentScore; if (player.combat != null) this.combat = player.combat.copy(); - for (Ability ability: player.actions) { - actions.add(ability); - } - for (UUID targetId: player.targets) { - targets.add(targetId); - } - for (String choice: player.choices) { - choices.add(choice); - } + this.actions.addAll(player.actions); + this.targets.addAll(player.targets); + this.choices.addAll(player.choices); } @Override @@ -731,7 +725,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Game sim = game.copy(); for (Player copyPlayer: sim.getState().getPlayers().values()) { - Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId()); + Player origPlayer = game.getState().getPlayers().get(copyPlayer.getId()).copy(); SimulatedPlayer newPlayer = new SimulatedPlayer(copyPlayer.getId(), copyPlayer.getId().equals(playerId), maxDepth); newPlayer.restore(origPlayer); sim.getState().getPlayers().put(copyPlayer.getId(), newPlayer); diff --git a/Mage.Server/plugins/mage-player-ai-ma.jar b/Mage.Server/plugins/mage-player-ai-ma.jar index 906117badc1..14bdfcf795c 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 171bdc2d5ea..69a49e78f1e 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-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar index a88f33c3dae..056a4123475 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.Sets/src/mage/sets/Sets.java b/Mage.Sets/src/mage/sets/Sets.java index 6903c9ef431..748221cfd1c 100644 --- a/Mage.Sets/src/mage/sets/Sets.java +++ b/Mage.Sets/src/mage/sets/Sets.java @@ -113,8 +113,8 @@ public class Sets extends HashMap { private void addSet(ExpansionSet set) { this.put(set.getCode(), set); + cards.addAll(set.getCards()); for (Card card: set.getCards()) { - cards.add(card); names.add(card.getName()); if (card.getCardType().contains(CardType.CREATURE)) { for (String type : card.getSubtype()) { diff --git a/Mage/src/mage/MageObjectImpl.java b/Mage/src/mage/MageObjectImpl.java index 702c176aebc..f68e68c43d0 100644 --- a/Mage/src/mage/MageObjectImpl.java +++ b/Mage/src/mage/MageObjectImpl.java @@ -82,15 +82,9 @@ public abstract class MageObjectImpl> implements Mag power = object.power.copy(); toughness = object.toughness.copy(); abilities = object.abilities.copy(); - for (CardType cType: object.cardType) { - cardType.add(cType); - } - for (String subType: object.subtype) { - this.subtype.add(subType); - } - for (String superType: object.supertype) { - this.supertype.add(superType); - } + this.cardType.addAll(object.cardType); + this.subtype.addAll(object.subtype); + this.supertype.addAll(object.supertype); } @Override diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index 3bd30cb41e5..f52f162271b 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -34,6 +34,7 @@ import mage.Constants.TimingRule; import mage.Constants.Zone; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.PhyrexianManaCost; @@ -100,8 +101,8 @@ public abstract class ActivatedAbilityImpl> ex if (cost != null) { if (cost instanceof PhyrexianManaCost) { this.addManaCost((PhyrexianManaCost)cost); - } else if (cost instanceof ManaCostsImpl) { - this.addManaCost((ManaCostsImpl) cost); + } else if (cost instanceof ManaCost) { + this.addManaCost((ManaCost) cost); } else { this.addCost(cost); } @@ -164,7 +165,7 @@ public abstract class ActivatedAbilityImpl> ex return true; else { Card card = (Card)game.getObject(this.sourceId); - if (card != null && game.getZone(this.sourceId) != Zone.BATTLEFIELD) + if (card != null && game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) return card.getOwnerId().equals(playerId); } return false; diff --git a/Mage/src/mage/abilities/costs/common/FlashbackCost.java b/Mage/src/mage/abilities/costs/common/FlashbackCost.java index 8cafccce15b..b1d13d0fb7f 100644 --- a/Mage/src/mage/abilities/costs/common/FlashbackCost.java +++ b/Mage/src/mage/abilities/costs/common/FlashbackCost.java @@ -53,7 +53,7 @@ public class FlashbackCost extends AlternativeCostImpl { @Override public boolean isAvailable(Game game, Ability source) { - Constants.Zone zone = game.getZone(source.getSourceId()); + Constants.Zone zone = game.getState().getZone(source.getSourceId()); if (zone != null) { return zone.equals(Constants.Zone.GRAVEYARD); } diff --git a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java index b97817515cb..24c7a9ac1ea 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java @@ -77,9 +77,7 @@ public abstract class ContinuousEffectImpl> ex this.timestamp = new Date(effect.timestamp.getTime()); this.used = effect.used; this.affectedObjectsSet = effect.affectedObjectsSet; - for (UUID objectId: effect.objects) { - this.objects.add(objectId); - } + this.objects.addAll(effect.objects); } @Override diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index d26ad247977..4e0bae81f2b 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -60,13 +60,13 @@ import mage.players.Player; public class ContinuousEffects implements Serializable { //transient Continuous effects - private final List layeredEffects = new ArrayList(); - private final List replacementEffects = new ArrayList(); - private final List preventionEffects = new ArrayList(); - private final List requirementEffects = new ArrayList(); - private final List restrictionEffects = new ArrayList(); - private final List asThoughEffects = new ArrayList(); - private final List costModificationEffects = new ArrayList(); + private final ArrayList layeredEffects = new ArrayList(); + private final ArrayList replacementEffects = new ArrayList(); + private final ArrayList preventionEffects = new ArrayList(); + private final ArrayList requirementEffects = new ArrayList(); + private final ArrayList restrictionEffects = new ArrayList(); + private final ArrayList asThoughEffects = new ArrayList(); + private final ArrayList costModificationEffects = new ArrayList(); //map Abilities to Continuous effects private final Map abilityMap = new HashMap(); @@ -82,24 +82,31 @@ public class ContinuousEffects implements Serializable { public ContinuousEffects(final ContinuousEffects effect) { this.applyCounters = effect.applyCounters.copy(); this.planeswalkerRedirectionEffect = effect.planeswalkerRedirectionEffect.copy(); + layeredEffects.ensureCapacity(effect.layeredEffects.size()); for (ContinuousEffect entry: effect.layeredEffects) { layeredEffects.add((ContinuousEffect) entry.copy()); } + replacementEffects.ensureCapacity(effect.replacementEffects.size()); for (ReplacementEffect entry: effect.replacementEffects) { replacementEffects.add((ReplacementEffect)entry.copy()); } + preventionEffects.ensureCapacity(effect.preventionEffects.size()); for (PreventionEffect entry: effect.preventionEffects) { preventionEffects.add((PreventionEffect)entry.copy()); } + requirementEffects.ensureCapacity(effect.requirementEffects.size()); for (RequirementEffect entry: effect.requirementEffects) { requirementEffects.add((RequirementEffect)entry.copy()); } + restrictionEffects.ensureCapacity(effect.restrictionEffects.size()); for (RestrictionEffect entry: effect.restrictionEffects) { restrictionEffects.add((RestrictionEffect)entry.copy()); } + asThoughEffects.ensureCapacity(effect.asThoughEffects.size()); for (AsThoughEffect entry: effect.asThoughEffects) { asThoughEffects.add((AsThoughEffect)entry.copy()); } + costModificationEffects.ensureCapacity(effect.costModificationEffects.size()); for ( CostModificationEffect entry : effect.costModificationEffects ) { costModificationEffects.add(entry); } @@ -209,7 +216,7 @@ public class ContinuousEffects implements Serializable { private List getLayeredEffects(Game game) { List layerEffects = new ArrayList(layeredEffects); for (Card card: game.getCards()) { - Zone zone = game.getZone(card.getId()); + Zone zone = game.getState().getZone(card.getId()); if (zone == Zone.HAND || zone == Zone.GRAVEYARD) { for (Entry entry: card.getAbilities().getEffects(zone, EffectType.CONTINUOUS).entrySet()) { layerEffects.add((ContinuousEffect)entry.getKey()); @@ -284,7 +291,7 @@ public class ContinuousEffects implements Serializable { replaceEffects.add(planeswalkerRedirectionEffect); //get all applicable Replacement effects in each players hand and graveyard for (Card card: game.getCards()) { - Zone zone = game.getZone(card.getId()); + Zone zone = game.getState().getZone(card.getId()); if (zone == Zone.HAND || zone == Zone.GRAVEYARD) { for (Entry entry: card.getAbilities().getReplacementEffects(zone).entrySet()) { if (entry.getKey().applies(event, entry.getValue(), game)) { diff --git a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java index 482498776ae..5f74a3235bf 100644 --- a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java @@ -66,7 +66,7 @@ public class PutOnLibraryTargetEffect extends OneShotEffect> extends MageObjectImpl @Override public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { - Zone fromZone = game.getZone(objectId); + Zone fromZone = game.getState().getZone(objectId); ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone); if (!game.replaceEvent(event)) { if (event.getFromZone() != null) { @@ -243,8 +245,11 @@ public abstract class CardImpl> extends MageObjectImpl case EXILED: game.getExile().removeCard(this, game); break; + case STACK: + break; default: - //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); + logger.fatal("invalid zone for card - " + fromZone); + return false; } game.rememberLKI(objectId, event.getFromZone(), this); } @@ -278,7 +283,7 @@ public abstract class CardImpl> extends MageObjectImpl } game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return game.getZone(objectId) == toZone; + return game.getState().getZone(objectId) == toZone; } return false; } @@ -309,14 +314,14 @@ public abstract class CardImpl> extends MageObjectImpl game.getStack().push(new Spell(this, ability.copy(), controllerId)); game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return game.getZone(objectId) == Zone.STACK; + return game.getState().getZone(objectId) == Zone.STACK; } return false; } @Override public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { - Zone fromZone = game.getZone(objectId); + Zone fromZone = game.getState().getZone(objectId); ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED); if (!game.replaceEvent(event)) { if (fromZone != null) { diff --git a/Mage/src/mage/cards/CardsImpl.java b/Mage/src/mage/cards/CardsImpl.java index 055109ce10d..eb3ee73433b 100644 --- a/Mage/src/mage/cards/CardsImpl.java +++ b/Mage/src/mage/cards/CardsImpl.java @@ -61,14 +61,12 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl public CardsImpl(Zone zone, List cards) { this(zone); for (Card card: cards) { - add(card); + this.add(card.getId()); } } public CardsImpl(final CardsImpl cards) { - for (UUID cardId: cards) { - this.add(cardId); - } + this.addAll(cards); this.ownerId = cards.ownerId; this.zone = cards.zone; } @@ -163,7 +161,7 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl @Override public void addAll(List cards) { for (Card card: cards) { - add(card); + add(card.getId()); } } diff --git a/Mage/src/mage/choices/ChoiceImpl.java b/Mage/src/mage/choices/ChoiceImpl.java index eb32181e1a0..dcf1413181e 100644 --- a/Mage/src/mage/choices/ChoiceImpl.java +++ b/Mage/src/mage/choices/ChoiceImpl.java @@ -57,9 +57,7 @@ public class ChoiceImpl> implements Choice, Serializable this.chosen = choice.chosen; this.required = choice.required; this.message = choice.message; - for (String c: choice.choices) { - this.choices.add(c); - } + this.choices.addAll(choice.choices); } @Override diff --git a/Mage/src/mage/filter/FilterCard.java b/Mage/src/mage/filter/FilterCard.java index 334b2b03b10..bc204b6faa2 100644 --- a/Mage/src/mage/filter/FilterCard.java +++ b/Mage/src/mage/filter/FilterCard.java @@ -67,13 +67,9 @@ public class FilterCard> extends FilterObject filter) { super(filter); - for (UUID oId: filter.ownerId) { - this.ownerId.add(oId); - } + this.ownerId.addAll(filter.ownerId); this.notOwner = filter.notOwner; - for (String code: filter.expansionSetCode) { - this.expansionSetCode.add(code); - } + this.expansionSetCode.addAll(filter.expansionSetCode); this.notExpansionSetCode = filter.notExpansionSetCode; this.owner = filter.owner; } diff --git a/Mage/src/mage/filter/FilterObject.java b/Mage/src/mage/filter/FilterObject.java index 805cf19153b..14c66db7eda 100644 --- a/Mage/src/mage/filter/FilterObject.java +++ b/Mage/src/mage/filter/FilterObject.java @@ -91,12 +91,8 @@ public class FilterObject> ex super(filter); this.abilities = filter.abilities.copy(); this.notAbilities = filter.notAbilities; - for (CardType cType: (List)filter.cardType) { - this.cardType.add(cType); - } - for (CardType cType: (List)filter.notCardTypeList) { - this.notCardTypeList.add(cType); - } + this.cardType.addAll(filter.cardType); + this.notCardTypeList.addAll(filter.notCardTypeList); this.scopeCardType = filter.scopeCardType; this.notCardType = filter.notCardType; this.notScopeCardType = filter.notScopeCardType; @@ -106,18 +102,12 @@ public class FilterObject> ex this.color = filter.color.copy(); this.scopeColor = filter.scopeColor; this.notColor = filter.notColor; - for (String fName: (List)filter.name) { - this.name.add(fName); - } + this.name.addAll(filter.name); this.notName = filter.notName; - for (String fSubtype: (List)filter.subtype) { - this.subtype.add(fSubtype); - } + this.subtype.addAll(filter.subtype); this.scopeSubtype = filter.scopeSubtype; this.notSubtype = filter.notSubtype; - for (String fSupertype: (List)filter.supertype) { - this.supertype.add(fSupertype); - } + this.supertype.addAll(filter.supertype); this.scopeSupertype = filter.scopeSupertype; this.notSupertype = filter.notSupertype; this.convertedManaCost = filter.convertedManaCost; diff --git a/Mage/src/mage/filter/FilterPermanent.java b/Mage/src/mage/filter/FilterPermanent.java index d1fd737eb4d..ed33c34546a 100644 --- a/Mage/src/mage/filter/FilterPermanent.java +++ b/Mage/src/mage/filter/FilterPermanent.java @@ -61,13 +61,9 @@ public class FilterPermanent> extends FilterObject< public FilterPermanent(final FilterPermanent filter) { super(filter); - for (UUID oId: filter.ownerId) { - this.ownerId.add(oId); - } + this.ownerId = new ArrayList(filter.ownerId); this.notOwner = filter.notOwner; - for (UUID oId: filter.controllerId) { - this.controllerId.add(oId); - } + this.controllerId = new ArrayList(filter.controllerId); this.notController = filter.notController; this.useTapped = filter.useTapped; this.tapped = filter.tapped; diff --git a/Mage/src/mage/filter/FilterPlayer.java b/Mage/src/mage/filter/FilterPlayer.java index 7df285d135e..eed926c93a6 100644 --- a/Mage/src/mage/filter/FilterPlayer.java +++ b/Mage/src/mage/filter/FilterPlayer.java @@ -52,9 +52,7 @@ public class FilterPlayer extends FilterImpl implements Fi public FilterPlayer(FilterPlayer filter) { super(filter); - for (UUID pId: filter.playerId) { - this.playerId.add(pId); - } + this.playerId.addAll(filter.playerId); this.notPlayer = filter.notPlayer; this.playerTarget = filter.playerTarget; } diff --git a/Mage/src/mage/filter/FilterStackObject.java b/Mage/src/mage/filter/FilterStackObject.java index 117a6a2c87c..5e456e87430 100644 --- a/Mage/src/mage/filter/FilterStackObject.java +++ b/Mage/src/mage/filter/FilterStackObject.java @@ -55,9 +55,7 @@ public class FilterStackObject> extends FilterObj public FilterStackObject(final FilterStackObject filter) { super(filter); - for (UUID cId: filter.controllerId) { - this.controllerId.add(cId); - } + this.controllerId.addAll(filter.controllerId); this.notController = filter.notController; this.controller = filter.controller; } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 0f80469ae1f..062d188bf16 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -145,6 +145,8 @@ public interface Game extends MageItem, Serializable { public void start(UUID choosingPlayerId); public void start(UUID choosingPlayerId, GameOptions options); public void resume(); + public void pause(); + public boolean isPaused(); public void end(); public void mulligan(UUID playerId); public void quit(UUID playerId); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index de4f196f364..0016bbc62d6 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -77,6 +77,7 @@ public abstract class GameImpl> implements Game, Serializa private final static transient Logger logger = Logger.getLogger(GameImpl.class); private static FilterAura filterAura = new FilterAura(); + private static FilterLegendaryPermanent filterLegendary = new FilterLegendaryPermanent(); private static FilterEquipment filterEquipment = new FilterEquipment(); private static FilterFortification filterFortification = new FilterFortification(); private static Random rnd = new Random(); @@ -125,6 +126,7 @@ public abstract class GameImpl> implements Game, Serializa this.gameCards = game.gameCards; this.simulation = game.simulation; this.gameOptions = game.gameOptions; + this.lki.putAll(game.lki); } @Override @@ -355,27 +357,44 @@ public abstract class GameImpl> implements Game, Serializa @Override public void resume() { - play(state.getActivePlayerId()); - } - - protected void play(UUID nextPlayerId) { - PlayerList players = state.getPlayerList(nextPlayerId); + PlayerList players = state.getPlayerList(state.getActivePlayerId()); Player player = getPlayer(players.get()); - while (!isGameOver()) { - state.setTurnNum(state.getTurnNum() + 1); + state.resume(); + if (!isGameOver()) { if (simulation) logger.info("Turn " + Integer.toString(state.getTurnNum())); fireInformEvent("Turn " + Integer.toString(state.getTurnNum())); if (checkStopOnTurnOption()) return; - state.setActivePlayerId(player.getId()); - state.getTurn().play(this, player.getId()); - if (isGameOver()) - break; - endOfTurn(); - player = players.getNext(this); + state.getTurn().resumePlay(this); + if (!isPaused() && !isGameOver()) { + endOfTurn(); + player = players.getNext(this); + state.setTurnNum(state.getTurnNum() + 1); + } } - - winnerId = findWinnersAndLosers(); + play(player.getId()); + } + + protected void play(UUID nextPlayerId) { + if (!isPaused() && !isGameOver()) { + PlayerList players = state.getPlayerList(nextPlayerId); + Player player = getPlayer(players.get()); + while (!isPaused() && !isGameOver()) { +// if (simulation) +// logger.info("Turn " + Integer.toString(state.getTurnNum())); + fireInformEvent("Turn " + Integer.toString(state.getTurnNum())); + if (checkStopOnTurnOption()) return; + state.setActivePlayerId(player.getId()); + state.getTurn().play(this, player.getId()); + if (isPaused() || isGameOver()) + break; + endOfTurn(); + player = players.getNext(this); + state.setTurnNum(state.getTurnNum() + 1); + } + } + if (isGameOver()) + winnerId = findWinnersAndLosers(); } private boolean checkStopOnTurnOption() { @@ -501,6 +520,16 @@ public abstract class GameImpl> implements Game, Serializa return playerId; } + @Override + public void pause() { + state.pause(); + } + + @Override + public boolean isPaused() { + return state.isPaused(); + } + @Override public void end() { state.endGame(); @@ -547,25 +576,25 @@ public abstract class GameImpl> implements Game, Serializa public void playPriority(UUID activePlayerId) { int bookmark = 0; try { - while (!isGameOver()) { + while (!isPaused() && !isGameOver()) { state.getPlayers().resetPassed(); state.getPlayerList().setCurrent(activePlayerId); Player player; - while (!isGameOver()) { + while (!isPaused() && !isGameOver()) { try { if (bookmark == 0) bookmark = bookmarkState(); player = getPlayer(state.getPlayerList().get()); state.setPriorityPlayerId(player.getId()); - while (!player.isPassed() && !player.hasLost() && !player.hasLeft() && !isGameOver()) { + while (!player.isPassed() && !player.hasLost() && !player.hasLeft() && !isPaused() && !isGameOver()) { checkStateAndTriggered(); - if (isGameOver()) return; + if (isPaused() || isGameOver()) return; // resetPassed should be called if player performs any action player.priority(this); - if (isGameOver()) return; + if (isPaused() || isGameOver()) return; applyEffects(); } - if (isGameOver()) return; + if (isPaused() || isGameOver()) return; if (allPassed()) { if (!state.getStack().isEmpty()) { //20091005 - 115.4 @@ -669,9 +698,9 @@ public abstract class GameImpl> implements Game, Serializa public boolean checkStateAndTriggered() { boolean somethingHappened = false; //20091005 - 115.5 - while (!this.isGameOver()) { + while (!isPaused() && !this.isGameOver()) { if (!checkStateBasedActions() ) { - if (this.isGameOver() || !checkTriggered()) { + if (isPaused() || this.isGameOver() || !checkTriggered()) { break; } } @@ -711,28 +740,127 @@ public abstract class GameImpl> implements Game, Serializa player.lost(this); } } - for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.CREATURE)) { - //20091005 - 704.5f - if (perm.getToughness().getValue() == 0) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - somethingHappened = true; + + List planeswalkers = new ArrayList(); + List legendary = new ArrayList(); + for (Permanent perm: getBattlefield().getAllActivePermanents()) { + if (perm.getCardType().contains(CardType.CREATURE)) { + //20091005 - 704.5f + if (perm.getToughness().getValue() == 0) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) { + somethingHappened = true; + continue; + } + } + //20091005 - 704.5g/704.5h + else if (perm.getToughness().getValue() <= perm.getDamage() || perm.isDeathtouched()) { + if (perm.destroy(null, this, false)) { + somethingHappened = true; + continue; + } + } + } + if (perm.getCardType().contains(CardType.PLANESWALKER)) { + //20091005 - 704.5i + if (perm.getCounters().getCount(CounterType.LOYALTY) == 0) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) { + somethingHappened = true; + continue; + } + } + planeswalkers.add(perm); + } + if (filterAura.match(perm)) { + //20091005 - 704.5n, 702.14c + if (perm.getAttachedTo() == null) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; + } + else { + Target target = perm.getSpellAbility().getTargets().get(0); + if (target instanceof TargetPermanent) { + Permanent attachedTo = getPermanent(perm.getAttachedTo()); + if (attachedTo == null) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; + } + else { + Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter(); + if (!auraFilter.match(attachedTo) || attachedTo.hasProtectionFrom(perm)) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; + } + } + } + else if (target instanceof TargetPlayer) { + Player attachedTo = getPlayer(perm.getAttachedTo()); + if (attachedTo == null) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; + } + else { + Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter(); + if (!auraFilter.match(attachedTo) || attachedTo.hasProtectionFrom(perm)) { + if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) + somethingHappened = true; + } + } + } + } + } + if (filterLegendary.match(perm)) + legendary.add(perm); + if (filterEquipment.match(perm)) { + //20091005 - 704.5p, 702.14d + if (perm.getAttachedTo() != null) { + Permanent creature = getPermanent(perm.getAttachedTo()); + if (creature == null) { + perm.attachTo(null, this); + } + else if (!creature.getCardType().contains(CardType.CREATURE) || creature.hasProtectionFrom(perm)) { + if (creature.removeAttachment(perm.getId(), this)) + somethingHappened = true; + } + } + } + if (filterFortification.match(perm)) { + if (perm.getAttachedTo() != null) { + Permanent land = getPermanent(perm.getAttachedTo()); + if (land == null) { + perm.attachTo(null, this); + } + else if (!land.getCardType().contains(CardType.LAND) || land.hasProtectionFrom(perm)) { + if (land.removeAttachment(perm.getId(), this)) + somethingHappened = true; + } + } + } + //20091005 - 704.5q + if (perm.getAttachments().size() > 0) { + for (UUID attachmentId: perm.getAttachments()) { + Permanent attachment = getPermanent(attachmentId); + if (attachment != null && !(attachment.getSubtype().contains("Aura") || + attachment.getSubtype().contains("Equipment") || + attachment.getSubtype().contains("Fortification"))) { + if (perm.removeAttachment(attachment.getId(), this)) + somethingHappened = true; + } + } } - //20091005 - 704.5g/704.5h - else if (perm.getToughness().getValue() <= perm.getDamage() || perm.isDeathtouched()) { - if (perm.destroy(null, this, false)) - somethingHappened = true; + + //20110501 - 704.5r + if (perm.getCounters().containsKey(CounterType.P1P1) && perm.getCounters().containsKey(CounterType.M1M1)) { + int p1p1 = perm.getCounters().getCount(CounterType.P1P1); + int m1m1 = perm.getCounters().getCount(CounterType.M1M1); + int min = Math.min(p1p1, m1m1); + perm.getCounters().removeCounter(CounterType.P1P1, min); + perm.getCounters().removeCounter(CounterType.M1M1, min); } - } - //20091005 - 704.5i - for (Permanent perm: getBattlefield().getAllActivePermanents(CardType.PLANESWALKER)) { - if (perm.getCounters().getCount(CounterType.LOYALTY) == 0) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - return true; - } - } + + } //20091005 - 704.5j, 801.14 - if (getBattlefield().contains(new FilterPlaneswalkerPermanent(), 2)) { //don't bother checking if less than 2 planeswalkers in play - for (Permanent planeswalker: getBattlefield().getAllActivePermanents(CardType.PLANESWALKER)) { + if (planeswalkers.size() > 1) { //don't bother checking if less than 2 planeswalkers in play + for (Permanent planeswalker: planeswalkers) { for (String planeswalkertype: planeswalker.getSubtype()) { FilterPlaneswalkerPermanent filterPlaneswalker = new FilterPlaneswalkerPermanent(); filterPlaneswalker.getSubtype().add(planeswalkertype); @@ -746,48 +874,9 @@ public abstract class GameImpl> implements Game, Serializa } } } - //20091005 - 704.5n, 702.14c - for (Permanent perm: getBattlefield().getAllActivePermanents(filterAura)) { - if (perm.getAttachedTo() == null) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - somethingHappened = true; - } - else { - Target target = perm.getSpellAbility().getTargets().get(0); - if (target instanceof TargetPermanent) { - Permanent attachedTo = getPermanent(perm.getAttachedTo()); - if (attachedTo == null) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - somethingHappened = true; - } - else { - Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter(); - if (!auraFilter.match(attachedTo) || attachedTo.hasProtectionFrom(perm)) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - somethingHappened = true; - } - } - } - else if (target instanceof TargetPlayer) { - Player attachedTo = getPlayer(perm.getAttachedTo()); - if (attachedTo == null) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - somethingHappened = true; - } - else { - Filter auraFilter = perm.getSpellAbility().getTargets().get(0).getFilter(); - if (!auraFilter.match(attachedTo) || attachedTo.hasProtectionFrom(perm)) { - if (perm.moveToZone(Zone.GRAVEYARD, null, this, false)) - somethingHappened = true; - } - } - } - } - } - FilterLegendaryPermanent filterLegendary = new FilterLegendaryPermanent(); //20091005 - 704.5k, 801.12 - if (getBattlefield().contains(filterLegendary, 2)) { //don't bother checking if less than 2 legends in play - for (Permanent legend: getBattlefield().getAllActivePermanents(filterLegendary)) { + if (legendary.size() > 1) { //don't bother checking if less than 2 legends in play + for (Permanent legend: legendary) { FilterLegendaryPermanent filterLegendName = new FilterLegendaryPermanent(); filterLegendName.getName().add(legend.getName()); if (getBattlefield().contains(filterLegendName, legend.getControllerId(), this, 2)) { @@ -798,55 +887,6 @@ public abstract class GameImpl> implements Game, Serializa } } } - //20091005 - 704.5p, 702.14d - for (Permanent perm: getBattlefield().getAllActivePermanents(filterEquipment)) { - if (perm.getAttachedTo() != null) { - Permanent creature = getPermanent(perm.getAttachedTo()); - if (creature == null) { - perm.attachTo(null, this); - } - else if (!creature.getCardType().contains(CardType.CREATURE) || creature.hasProtectionFrom(perm)) { - if (creature.removeAttachment(perm.getId(), this)) - somethingHappened = true; - } - } - } - for (Permanent perm: getBattlefield().getAllActivePermanents(filterFortification)) { - if (perm.getAttachedTo() != null) { - Permanent land = getPermanent(perm.getAttachedTo()); - if (land == null) { - perm.attachTo(null, this); - } - else if (!land.getCardType().contains(CardType.LAND) || land.hasProtectionFrom(perm)) { - if (land.removeAttachment(perm.getId(), this)) - somethingHappened = true; - } - } - } - //20091005 - 704.5q - for (Permanent perm: getBattlefield().getAllActivePermanents()) { - if (perm.getAttachments().size() > 0) { - for (UUID attachmentId: perm.getAttachments()) { - Permanent attachment = getPermanent(attachmentId); - if (attachment != null && !(attachment.getSubtype().contains("Aura") || - attachment.getSubtype().contains("Equipment") || - attachment.getSubtype().contains("Fortification"))) { - if (perm.removeAttachment(attachment.getId(), this)) - return true; - } - } - } - } - //20110501 - 704.5r - for (Permanent perm: getBattlefield().getAllActivePermanents()) { - if (perm.getCounters().containsKey(CounterType.P1P1) && perm.getCounters().containsKey(CounterType.M1M1)) { - int p1p1 = perm.getCounters().getCount(CounterType.P1P1); - int m1m1 = perm.getCounters().getCount(CounterType.M1M1); - int min = Math.min(p1p1, m1m1); - perm.getCounters().removeCounter(CounterType.P1P1, min); - perm.getCounters().removeCounter(CounterType.M1M1, min); - } - } //TODO: implement the rest diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index c7aab310924..47db0a533cc 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -85,8 +85,9 @@ public class GameState implements Serializable, Copyable { private Revealed revealed; private Map lookedAt = new HashMap(); private Battlefield battlefield; - private int turnNum; + private int turnNum = 1; private boolean gameOver; + private boolean paused; // private List messages = new ArrayList(); private ContinuousEffects effects; private TriggeredAbilities triggers; @@ -128,9 +129,7 @@ public class GameState implements Serializable, Copyable { this.command = state.command.copy(); this.exile = state.exile.copy(); this.revealed = state.revealed.copy(); - for (Map.Entry entry: state.lookedAt.entrySet()) { - lookedAt.put(entry.getKey(), entry.getValue()); - } + this.lookedAt.putAll(state.lookedAt); this.battlefield = state.battlefield.copy(); this.turnNum = state.turnNum; this.gameOver = state.gameOver; @@ -141,13 +140,8 @@ public class GameState implements Serializable, Copyable { this.combat = state.combat.copy(); this.turnMods = state.turnMods.copy(); this.watchers = state.watchers.copy(); - for (Map.Entry entry : state.values.entrySet()) { - values.put(entry.getKey(), entry.getValue()); - //TODO: might have to change value to Copyable - } - for (Map.Entry entry: state.zones.entrySet()) { - zones.put(entry.getKey(), entry.getValue()); - } + this.values.putAll(state.values); + this.zones.putAll(state.zones); for (Map.Entry> entry: state.otherAbilities.entrySet()) { otherAbilities.put(entry.getKey(), entry.getValue().copy()); } @@ -457,4 +451,16 @@ public class GameState implements Serializable, Copyable { zones.clear(); } + public void pause() { + this.paused = true; + } + + public void resume() { + this.paused = false; + } + + public boolean isPaused() { + return this.paused; + } + } diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java index 76b57344b73..a0604c105e0 100644 --- a/Mage/src/mage/game/combat/Combat.java +++ b/Mage/src/mage/game/combat/Combat.java @@ -66,9 +66,7 @@ public class Combat implements Serializable, Copyable { for (CombatGroup group : combat.groups) { groups.add(group.copy()); } - for (UUID defenderId : combat.defenders) { - defenders.add(defenderId); - } + defenders.addAll(combat.defenders); for (Map.Entry group : combat.blockingGroups.entrySet()) { blockingGroups.put(group.getKey(), group.getValue()); } @@ -128,6 +126,8 @@ public class Combat implements Serializable, Copyable { //20101001 - 508.1d checkAttackRequirements(player, game); player.selectAttackers(game); + if (game.isPaused() || game.isGameOver()) + return; for (CombatGroup group: groups) { for (UUID attacker: group.getAttackers()) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ATTACKER_DECLARED, group.defenderId, attacker, attackerId)); @@ -169,6 +169,8 @@ public class Combat implements Serializable, Copyable { checkBlockRequirements(player, game); for (UUID defenderId : getPlayerDefenders(game)) { game.getPlayer(defenderId).selectBlockers(game); + if (game.isPaused() || game.isGameOver()) + return; game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, defenderId, defenderId)); } } diff --git a/Mage/src/mage/game/combat/CombatGroup.java b/Mage/src/mage/game/combat/CombatGroup.java index c511cd8697b..bc2dd6c1d9a 100644 --- a/Mage/src/mage/game/combat/CombatGroup.java +++ b/Mage/src/mage/game/combat/CombatGroup.java @@ -67,21 +67,11 @@ public class CombatGroup implements Serializable, Copyable { this.blocked = group.blocked; this.defenderId = group.defenderId; this.defenderIsPlaneswalker = group.defenderIsPlaneswalker; - for (UUID attackerId: group.attackers) { - this.attackers.add(attackerId); - } - for (UUID blockerId: group.blockers) { - this.blockers.add(blockerId); - } - for (UUID orderId: group.blockerOrder) { - this.blockerOrder.add(orderId); - } - for (UUID orderId: group.attackerOrder) { - this.attackerOrder.add(orderId); - } - for (Map.Entry entry : group.players.entrySet()) { - players.put(entry.getKey(), entry.getValue()); - } + this.attackers.addAll(group.attackers); + this.blockers.addAll(group.blockers); + this.blockerOrder.addAll(group.blockerOrder); + this.attackerOrder.addAll(group.attackerOrder); + this.players.putAll(group.players); } protected String getValue(Game game) { diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index 68de9720162..bc879b207a7 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -157,7 +157,7 @@ public class PermanentCard extends PermanentImpl { @Override public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { - Zone fromZone = game.getZone(objectId); + Zone fromZone = game.getState().getZone(objectId); Player controller = game.getPlayer(controllerId); if (controller != null && controller.removeFromBattlefield(this, game)) { ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone); @@ -187,7 +187,7 @@ public class PermanentCard extends PermanentImpl { } game.setZone(objectId, event.getToZone()); game.fireEvent(event); - return game.getZone(objectId) == toZone; + return game.getState().getZone(objectId) == toZone; } } } @@ -197,7 +197,7 @@ public class PermanentCard extends PermanentImpl { @Override public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { - Zone fromZone = game.getZone(objectId); + Zone fromZone = game.getState().getZone(objectId); Player controller = game.getPlayer(controllerId); if (controller != null && controller.removeFromBattlefield(this, game)) { ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED); diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index 56b52a19f66..cb95e4d4e18 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -112,20 +112,11 @@ public abstract class PermanentImpl> extends CardImpl this.loyaltyUsed = permanent.loyaltyUsed; this.deathtouched = permanent.deathtouched; this.counters = permanent.counters.copy(); - for (UUID attachmentId : permanent.attachments) { - this.attachments.add(attachmentId); - } - for (UUID imprintedId : permanent.imprinted) { - this.imprinted.add(imprintedId); - } - for (UUID connectedCardId : permanent.connectedCards) { - this.connectedCards.add(connectedCardId); - } + this.attachments.addAll(permanent.attachments); + this.imprinted.addAll(permanent.imprinted); + this.connectedCards.addAll(permanent.connectedCards); if (permanent.dealtDamageByThisTurn != null) { - dealtDamageByThisTurn = new ArrayList(); - for (UUID sourceId : permanent.dealtDamageByThisTurn) { - this.dealtDamageByThisTurn.add(sourceId); - } + dealtDamageByThisTurn = new ArrayList(permanent.dealtDamageByThisTurn); if (permanent.markedDamage != null) { markedDamage = new ArrayList(); for (Counter counter : permanent.markedDamage) { diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 7dec2195327..d925e7471fe 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -135,16 +135,18 @@ public class Spell> implements StackObject, Card { */ private void updateOptionalCosts() { Ability abilityOrig = card.getAbilities().get(ability.getId()); - for (Object object : ability.getOptionalCosts()) { - Cost cost = (Cost) object; - for (Cost costOrig : abilityOrig.getOptionalCosts()) { - if (cost.getId().equals(costOrig.getId())) { - if (cost.isPaid()) { - costOrig.setPaid(); - } else { - costOrig.clearPaid(); + if (abilityOrig != null) { + for (Object object : ability.getOptionalCosts()) { + Cost cost = (Cost) object; + for (Cost costOrig : abilityOrig.getOptionalCosts()) { + if (cost.getId().equals(costOrig.getId())) { + if (cost.isPaid()) { + costOrig.setPaid(); + } else { + costOrig.clearPaid(); + } + break; } - break; } } } diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index d05d6385003..a56c85ffff0 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -32,13 +32,12 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Stack; import java.util.UUID; import mage.Constants.Zone; import mage.abilities.Ability; -import mage.abilities.effects.Effect; import mage.abilities.effects.ReplacementEffect; -import mage.cards.Card; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; @@ -105,15 +104,9 @@ public class SpellStack extends Stack { boolean caught = false; Map rEffects = new LinkedHashMap(); for (StackObject stackObject: this) { - for (Ability ability: stackObject.getAbilities()) { - if (ability.getZone() == Zone.STACK) { - for (Effect effect: ability.getEffects()) { - if (effect instanceof ReplacementEffect) { - if (((ReplacementEffect)effect).applies(event, ability, game)) - rEffects.put((ReplacementEffect) effect, ability); - } - } - } + for (Entry entry: stackObject.getAbilities().getReplacementEffects(Zone.STACK).entrySet()) { + if (entry.getKey().applies(event, entry.getValue(), game)) + rEffects.put(entry.getKey(), entry.getValue()); } } if (rEffects.size() > 0) { diff --git a/Mage/src/mage/game/turn/EndPhase.java b/Mage/src/mage/game/turn/EndPhase.java index 3b4546b4483..3aa441ecd04 100644 --- a/Mage/src/mage/game/turn/EndPhase.java +++ b/Mage/src/mage/game/turn/EndPhase.java @@ -54,16 +54,16 @@ public class EndPhase extends Phase { } @Override - protected void playStep(Game game, UUID activePlayerId) { + protected void playStep(Game game) { if (currentStep.getType() == PhaseStep.CLEANUP) { currentStep.beginStep(game, activePlayerId); if (game.checkStateAndTriggered()) { - playStep(game, activePlayerId); + playStep(game); } currentStep.endStep(game, activePlayerId); } else - super.playStep(game, activePlayerId); + super.playStep(game); } @Override diff --git a/Mage/src/mage/game/turn/Phase.java b/Mage/src/mage/game/turn/Phase.java index eae89258630..6a14c3961e8 100644 --- a/Mage/src/mage/game/turn/Phase.java +++ b/Mage/src/mage/game/turn/Phase.java @@ -30,6 +30,7 @@ package mage.game.turn; import java.io.Serializable; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.UUID; import mage.Constants.PhaseStep; @@ -93,7 +94,7 @@ public abstract class Phase> implements Serializable { } public boolean play(Game game, UUID activePlayerId) { - if (game.isGameOver()) + if (game.isPaused() || game.isGameOver()) return false; this.activePlayerId = activePlayerId; @@ -101,12 +102,14 @@ public abstract class Phase> implements Serializable { if (beginPhase(game, activePlayerId)) { for (Step step: steps) { - if (game.isGameOver()) + if (game.isPaused() || game.isGameOver()) return false; currentStep = step; if (!game.getState().getTurnMods().skipStep(activePlayerId, currentStep.getType())) - playStep(game, activePlayerId); + playStep(game); } + if (game.isPaused() || game.isGameOver()) + return false; count++; endPhase(game, activePlayerId); return true; @@ -114,6 +117,34 @@ public abstract class Phase> implements Serializable { return false; } + public boolean resumePlay(Game game, PhaseStep stepType) { + if (game.isPaused() || game.isGameOver()) + return false; + + this.activePlayerId = game.getActivePlayerId(); + Iterator it = steps.iterator(); + Step step; + do { + step = it.next(); + currentStep = step; + } while (step.getType() != stepType); + resumeStep(game); + while (it.hasNext()) { + step = it.next(); + if (game.isPaused() || game.isGameOver()) + return false; + currentStep = step; + if (!game.getState().getTurnMods().skipStep(activePlayerId, currentStep.getType())) + playStep(game); + } + + if (game.isPaused() || game.isGameOver()) + return false; + count++; + endPhase(game, activePlayerId); + return true; + } + public boolean beginPhase(Game game, UUID activePlayerId) { if (!game.replaceEvent(new GameEvent(event, null, null, activePlayerId))) { game.fireEvent(new GameEvent(preEvent, null, null, activePlayerId)); @@ -138,21 +169,36 @@ public abstract class Phase> implements Serializable { playExtraSteps(game, currentStep.getType()); } - protected void playStep(Game game, UUID activePlayerId) { + protected void playStep(Game game) { if (!currentStep.skipStep(game, activePlayerId)) { prePriority(game, activePlayerId); - currentStep.priority(game, activePlayerId); - postPriority(game, activePlayerId); + if (!game.isPaused() && !game.isGameOver()) + currentStep.priority(game, activePlayerId); + if (!game.isPaused() && !game.isGameOver()) + postPriority(game, activePlayerId); } } + protected void resumeStep(Game game) { + switch (currentStep.getStepPart()) { + case PRE: + prePriority(game, activePlayerId); + case PRIORITY: + if (!game.isPaused() && !game.isGameOver()) + currentStep.priority(game, activePlayerId); + case POST: + if (!game.isPaused() && !game.isGameOver()) + postPriority(game, activePlayerId); + } + } + private void playExtraSteps(Game game, PhaseStep afterStep) { while (true) { Step extraStep = game.getState().getTurnMods().extraStep(activePlayerId, afterStep); if (extraStep == null) return; currentStep = extraStep; - playStep(game, activePlayerId); + playStep(game); } } diff --git a/Mage/src/mage/game/turn/Step.java b/Mage/src/mage/game/turn/Step.java index 62f7fa6ddea..9fb4d12455d 100644 --- a/Mage/src/mage/game/turn/Step.java +++ b/Mage/src/mage/game/turn/Step.java @@ -46,6 +46,11 @@ public abstract class Step> implements Serializable { protected EventType stepEvent; protected EventType preStepEvent; protected EventType postStepEvent; + protected StepPart stepPart; + + public enum StepPart { + PRE, PRIORITY, POST; + } public abstract T copy(); @@ -60,6 +65,7 @@ public abstract class Step> implements Serializable { this.stepEvent = step.stepEvent; this.preStepEvent = step.preStepEvent; this.postStepEvent = step.postStepEvent; + this.stepPart = step.stepPart; } public PhaseStep getType() { @@ -67,15 +73,19 @@ public abstract class Step> implements Serializable { } public void beginStep(Game game, UUID activePlayerId) { + stepPart = StepPart.PRE; game.fireEvent(new GameEvent(preStepEvent, null, null, activePlayerId)); } public void priority(Game game, UUID activePlayerId) { - if (hasPriority) + if (hasPriority) { + stepPart = StepPart.PRIORITY; game.playPriority(activePlayerId); + } } public void endStep(Game game, UUID activePlayerId) { + stepPart = StepPart.POST; game.fireEvent(new GameEvent(postStepEvent, null, null, activePlayerId)); } @@ -87,4 +97,8 @@ public abstract class Step> implements Serializable { return this.hasPriority; } + public StepPart getStepPart() { + return stepPart; + } + } diff --git a/Mage/src/mage/game/turn/Turn.java b/Mage/src/mage/game/turn/Turn.java index 5135d267c97..9702988235c 100644 --- a/Mage/src/mage/game/turn/Turn.java +++ b/Mage/src/mage/game/turn/Turn.java @@ -30,6 +30,7 @@ package mage.game.turn; import java.io.Serializable; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.UUID; import mage.Constants.PhaseStep; @@ -100,8 +101,8 @@ public class Turn implements Serializable { return null; } - public void play(Game game, UUID activePlayerId) { - if (game.isGameOver()) + public void play(Game game, UUID activePlayerId) { + if (game.isPaused() || game.isGameOver()) return; if (game.getState().getTurnMods().skipTurn(activePlayerId)) @@ -113,7 +114,7 @@ public class Turn implements Serializable { resetCounts(); game.getPlayer(activePlayerId).beginTurn(game); for (Phase phase: phases) { - if (game.isGameOver()) + if (game.isPaused() || game.isGameOver()) return; currentPhase = phase; if (!game.getState().getTurnMods().skipPhase(activePlayerId, currentPhase.getType())) { @@ -132,6 +133,44 @@ public class Turn implements Serializable { playExtraTurns(game); } + public void resumePlay(Game game) { + activePlayerId = game.getActivePlayerId(); + UUID priorityPlayerId = game.getPriorityPlayerId(); + TurnPhase phaseType = game.getPhase().getType(); + PhaseStep stepType = game.getStep().getType(); + + Iterator it = phases.iterator(); + Phase phase; + do { + phase = it.next(); + currentPhase = phase; + } while (phase.type != phaseType); + if (phase.resumePlay(game, stepType)) { + //20091005 - 500.4/703.4n + game.emptyManaPools(); + game.saveState(); + //20091005 - 500.8 + playExtraPhases(game, phase.getType()); + } + while (it.hasNext()) { + phase = it.next(); + if (game.isPaused() || game.isGameOver()) + return; + currentPhase = phase; + if (!game.getState().getTurnMods().skipPhase(activePlayerId, currentPhase.getType())) { + if (phase.play(game, activePlayerId)) { + //20091005 - 500.4/703.4n + game.emptyManaPools(); + game.saveState(); + //20091005 - 500.8 + playExtraPhases(game, phase.getType()); + } + } + if (!currentPhase.equals(phase)) // phase was changed from the card + break; + } + } + private void checkTurnIsControlledByOtherPlayer(Game game, UUID activePlayerId) { UUID newControllerId = game.getState().getTurnMods().controlsTurn(activePlayerId); if (newControllerId != null && !newControllerId.equals(activePlayerId)) { diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 43f08988a73..1438d5015b7 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -154,9 +154,8 @@ public abstract class PlayerImpl> implements Player, Ser this.range = player.range; this.canGainLife = player.canGainLife; this.canLoseLife = player.canLoseLife; - for (UUID id: player.inRange) { - this.inRange.add(id); - } + this.attachments.addAll(player.attachments); + this.inRange.addAll(player.inRange); this.userData = player.userData; } @@ -504,7 +503,7 @@ public abstract class PlayerImpl> implements Player, Ser if (card != null) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability.getSourceId(), playerId))) { int bookmark = game.bookmarkState(); - Zone fromZone = game.getZone(card.getId()); + Zone fromZone = game.getState().getZone(card.getId()); card.cast(game, fromZone, ability, playerId); Ability spellAbility = game.getStack().getSpell(ability.getId()).getSpellAbility(); @@ -530,7 +529,7 @@ public abstract class PlayerImpl> implements Player, Ser //20091005 - 305.1 if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), playerId))) { int bookmark = game.bookmarkState(); - Zone zone = game.getZone(card.getId()); + Zone zone = game.getState().getZone(card.getId()); switch (zone) { case HAND: removeFromHand(card, game); @@ -541,6 +540,9 @@ public abstract class PlayerImpl> implements Player, Ser case GRAVEYARD: removeFromGraveyard(card, game); break; + default: + // invalid zone for play land + return false; } if (card.putOntoBattlefield(game, zone, null, playerId)) { diff --git a/Mage/src/mage/target/TargetImpl.java b/Mage/src/mage/target/TargetImpl.java index b662bf23ff3..9b2ddcb4725 100644 --- a/Mage/src/mage/target/TargetImpl.java +++ b/Mage/src/mage/target/TargetImpl.java @@ -76,9 +76,7 @@ public abstract class TargetImpl> implements Target { this.minNumberOfTargets = target.minNumberOfTargets; this.required = target.required; this.chosen = target.chosen; - for (Entry entry: target.targets.entrySet()) { - targets.put(entry.getKey(), entry.getValue()); - } + this.targets.putAll(target.targets); } @Override diff --git a/Mage/src/mage/target/TargetObject.java b/Mage/src/mage/target/TargetObject.java index b7be81f5fc3..38a3d1e2573 100644 --- a/Mage/src/mage/target/TargetObject.java +++ b/Mage/src/mage/target/TargetObject.java @@ -74,7 +74,7 @@ public abstract class TargetObject> extends TargetImpl @Override public boolean canTarget(UUID id, Game game) { MageObject object = game.getObject(id); - if (object != null && game.getZone(id).match(zone)) + if (object != null && game.getState().getZone(id).match(zone)) return getFilter().match(object); return false; } diff --git a/Mage/src/mage/target/TargetPermanent.java b/Mage/src/mage/target/TargetPermanent.java index c98f0a89ca0..aab3c935c2c 100644 --- a/Mage/src/mage/target/TargetPermanent.java +++ b/Mage/src/mage/target/TargetPermanent.java @@ -146,7 +146,8 @@ public class TargetPermanent> extends TargetObject< int remainingTargets = this.minNumberOfTargets - targets.size(); if (remainingTargets == 0) { // if we return true, then AnowonTheRuinSage will hang for AI when no targets in play - return false; + // TODO: retest Anowon the Ruin Sage + return true; } int count = 0; for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { diff --git a/Mage/src/mage/target/common/TargetCardInExile.java b/Mage/src/mage/target/common/TargetCardInExile.java index e1fa9f04d60..38856ee942f 100644 --- a/Mage/src/mage/target/common/TargetCardInExile.java +++ b/Mage/src/mage/target/common/TargetCardInExile.java @@ -62,7 +62,7 @@ public class TargetCardInExile extends TargetCard { @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); - if (card != null && game.getZone(card.getId()) == Zone.EXILED) { + if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { ExileZone exile; if (zoneId != null) { exile = game.getExile().getExileZone(zoneId); diff --git a/Mage/src/mage/target/common/TargetCardInGraveyard.java b/Mage/src/mage/target/common/TargetCardInGraveyard.java index a72bbcfc2b9..866d11d691f 100644 --- a/Mage/src/mage/target/common/TargetCardInGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInGraveyard.java @@ -66,7 +66,7 @@ public class TargetCardInGraveyard extends TargetCard { @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); - if (card != null && game.getZone(card.getId()) == Zone.GRAVEYARD) + if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) return filter.match(card); return false; } diff --git a/Mage/src/mage/target/common/TargetCardInOpponentsGraveyard.java b/Mage/src/mage/target/common/TargetCardInOpponentsGraveyard.java index 85d1fe2446d..840f844e20e 100644 --- a/Mage/src/mage/target/common/TargetCardInOpponentsGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInOpponentsGraveyard.java @@ -28,7 +28,7 @@ public class TargetCardInOpponentsGraveyard extends TargetCard