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 af815a53ca7..4854322a873 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 @@ -924,7 +924,7 @@ public class ComputerPlayer> extends PlayerImpl i } @Override - public TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game) { + public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { log.debug("chooseTriggeredAbility"); //TODO: improve this if (abilities.size() > 0) 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 8714801e5b8..0b305c2bb78 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 @@ -58,6 +58,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; protected transient MCTSNode root; @@ -69,7 +70,7 @@ public class ComputerPlayerMCTS extends ComputerPlayer imple public ComputerPlayerMCTS(String name, RangeOfInfluence range, int skill) { super(name, range); human = false; - maxThinkTime = (int) (skill * 1.5); + maxThinkTime = (int) (skill * THINK_TIME_MULTIPLIER); cores = Runtime.getRuntime().availableProcessors(); pool = Executors.newFixedThreadPool(cores); } 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 f1187606dc4..eb088dbc126 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 @@ -407,7 +407,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { } @Override - public TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game) { + public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { if (this.isHuman()) return abilities.get(rnd.nextInt(abilities.size())); return super.chooseTriggeredAbility(abilities, game); diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 5f7f63fc850..d2f503d6fb4 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -396,7 +396,7 @@ public class HumanPlayer extends PlayerImpl { MageObject object = game.getObject(response.getUUID()); if (object != null) { Map useableAbilities = null; - Zone zone = game.getZone(object.getId()); + Zone zone = game.getState().getZone(object.getId()); if (zone != null) { useableAbilities = getUseableActivatedAbilities(object, zone, game); if (useableAbilities != null && useableAbilities.size() > 0) { @@ -411,10 +411,10 @@ public class HumanPlayer extends PlayerImpl { } @Override - public TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game) { + public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { game.getState().setPriorityPlayerId(getId()); while (!abort) { - game.fireSelectTargetEvent(playerId, "Pick triggered ability (goes to the stack first)", abilities, true); + game.fireSelectTargetEvent(playerId, "Pick triggered ability (goes to the stack first)", abilities); waitForResponse(); if (response.getUUID() != null) { for (TriggeredAbility ability: abilities) { @@ -472,7 +472,7 @@ public class HumanPlayer extends PlayerImpl { MageObject object = game.getObject(response.getUUID()); if (object == null) return; Map useableAbilities = null; - Zone zone = game.getZone(object.getId()); + Zone zone = game.getState().getZone(object.getId()); if (zone != null) { useableAbilities = getUseableManaAbilities(object, zone, game); if (useableAbilities != null && useableAbilities.size() > 0) { @@ -496,7 +496,7 @@ public class HumanPlayer extends PlayerImpl { selectDefender(game.getCombat().getDefenders(), attacker.getId(), game); } else if (filterAttack.match(attacker, null, playerId, game) && game.getStack().isEmpty()) { - if (game.getState().getTriggered().isEmpty() && game.getState().getDelayed().isEmpty()) +// if (game.getState().getTriggered().isEmpty() && game.getState().getDelayed().isEmpty()) game.getCombat().removeAttacker(attacker.getId(), game); } } @@ -534,7 +534,7 @@ public class HumanPlayer extends PlayerImpl { selectCombatGroup(blocker.getId(), game); } else if (filterBlock.match(blocker, null, playerId, game) && game.getStack().isEmpty()) { - if (game.getState().getTriggered().isEmpty() && game.getState().getDelayed().isEmpty()) +// if (game.getState().getTriggered().isEmpty() && game.getState().getDelayed().isEmpty()) game.getCombat().removeBlocker(blocker.getId(), game); } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HisokasGuard.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HisokasGuard.java index 6acf5eba966..0be4688d8aa 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/HisokasGuard.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HisokasGuard.java @@ -163,7 +163,7 @@ class HisokasGuardGainAbilityTargetEffect extends ContinuousEffectImpl 0) { Permanent guardedCreature = game.getPermanent(hisokasGuard.getConnectedCards().get(0)); if (guardedCreature != null && hisokasGuard.isTapped()) { - guardedCreature.addAbility(ability); + guardedCreature.addAbility(ability, game); return true; } else { diff --git a/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java b/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java index 3abce506ebb..03da87f1bd3 100644 --- a/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java +++ b/Mage.Sets/src/mage/sets/innistrad/EssenceOfTheWild.java @@ -160,7 +160,7 @@ class EssenceOfTheWildCopyEffect extends ContinuousEffectImpl { @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) { UUID firstTarget = source.getFirstTarget(); if (firstTarget != null && game.getPlayer(firstTarget).getGraveyard().contains(id)) { return filter.match(card); diff --git a/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java b/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java index dc9edc81ee9..fd1f567d90d 100644 --- a/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java +++ b/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java @@ -161,19 +161,19 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { switch (layer) { case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - creature.addAbility(new ForestwalkAbility()); + creature.addAbility(new ForestwalkAbility(), game); } break; } diff --git a/Mage.Sets/src/mage/sets/magic2011/NecroticPlague.java b/Mage.Sets/src/mage/sets/magic2011/NecroticPlague.java index f05a09991e3..0625c1e11bc 100644 --- a/Mage.Sets/src/mage/sets/magic2011/NecroticPlague.java +++ b/Mage.Sets/src/mage/sets/magic2011/NecroticPlague.java @@ -112,8 +112,8 @@ class NecroticPlagueEffect extends ContinuousEffectImpl { switch (layer) { case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - creature.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new SacrificeSourceEffect())); - creature.addAbility(new DiesTriggeredAbility(new NecroticPlagueEffect2(source.getSourceId()), false)); + creature.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new SacrificeSourceEffect()), game); + creature.addAbility(new DiesTriggeredAbility(new NecroticPlagueEffect2(source.getSourceId()), false), game); } break; } diff --git a/Mage.Sets/src/mage/sets/magic2011/OverwhelmingStampede.java b/Mage.Sets/src/mage/sets/magic2011/OverwhelmingStampede.java index dc5ed5d7934..667436df138 100644 --- a/Mage.Sets/src/mage/sets/magic2011/OverwhelmingStampede.java +++ b/Mage.Sets/src/mage/sets/magic2011/OverwhelmingStampede.java @@ -99,7 +99,7 @@ class OverwhelmingStampedeEffect extends ContinuousEffectImpl { break; case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - creature.addAbility(FlyingAbility.getInstance()); + creature.addAbility(FlyingAbility.getInstance(), game); } break; } diff --git a/Mage.Sets/src/mage/sets/magic2011/ShivsEmbrace.java b/Mage.Sets/src/mage/sets/magic2011/ShivsEmbrace.java index d8c04ac3a68..e17afd8956d 100644 --- a/Mage.Sets/src/mage/sets/magic2011/ShivsEmbrace.java +++ b/Mage.Sets/src/mage/sets/magic2011/ShivsEmbrace.java @@ -114,7 +114,7 @@ class ShivsEmbraceEffect extends ContinuousEffectImpl { break; case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { - creature.addAbility(FlyingAbility.getInstance()); + creature.addAbility(FlyingAbility.getInstance(), game); } break; } diff --git a/Mage.Sets/src/mage/sets/magic2011/VolcanicStrength.java b/Mage.Sets/src/mage/sets/magic2011/VolcanicStrength.java index 3a081e3917f..3c5871ad999 100644 --- a/Mage.Sets/src/mage/sets/magic2011/VolcanicStrength.java +++ b/Mage.Sets/src/mage/sets/magic2011/VolcanicStrength.java @@ -110,7 +110,7 @@ class VolcanicStrengthEffect extends ContinuousEffectImpl permanent.reset(game); permanent.assignNewId(); permanent.getSubtype().add("Illusion"); - permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); + permanent.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), game); game.addEffect(new CopyEffect(permanent), source); diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/ConcussiveBolt.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/ConcussiveBolt.java index e3b701bdc9d..047720d34dc 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/ConcussiveBolt.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/ConcussiveBolt.java @@ -98,7 +98,7 @@ class ConcussiveBoltEffect extends ContinuousEffectImpl { if (player != null) { List permanents = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId()); for (Permanent permanent : permanents) { - permanent.addAbility(CantBlockAbility.getInstance()); + permanent.addAbility(CantBlockAbility.getInstance(), game); affectedTargets++; } } diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java index a896ae1d7e4..f7d6a1ad02b 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java @@ -95,7 +95,7 @@ class CryptoplasmTransformEffect extends ContinuousEffectImpl { case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { land.getAbilities().clear(); - land.addAbility(new BlackManaAbility()); + land.addAbility(new BlackManaAbility(), game); } break; } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/PraetorsGrasp.java b/Mage.Sets/src/mage/sets/newphyrexia/PraetorsGrasp.java index 57943774a73..05315967dfc 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/PraetorsGrasp.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/PraetorsGrasp.java @@ -144,7 +144,7 @@ class PraetorsGraspPlayEffect extends AsThoughEffectImpl { Card card = game.getCard(source.getFirstTarget()); if (card != null) { // if still in graveyard - if (game.getZone(card.getId()).equals(Zone.GRAVEYARD)) { + if (game.getState().getZone(card.getId()).equals(Zone.GRAVEYARD)) { Player player = game.getPlayer(card.getOwnerId()); if (card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getId(), source.getControllerId())) { player.getGraveyard().remove(card); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java index c34832364a5..f57bfa3e682 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java @@ -128,7 +128,7 @@ class KothOfTheHammerThirdEffect extends ContinuousEffectImpl { if (card.getCardType().contains(CardType.CREATURE)) { for (Ability ability: card.getAbilities()) { if (ability instanceof ActivatedAbility) { - perm.addAbility(ability); + perm.addAbility(ability, game); } } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java index 3167d4e9554..6615717ecf5 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/NimDeathmantle.java @@ -164,7 +164,7 @@ class NimDeathmantleEffect extends OneShotEffect { if (target != null && equipment != null) { Card card = game.getCard(target); // check if it's still in graveyard - if (card != null && game.getZone(card.getId()).equals(Constants.Zone.GRAVEYARD)) { + if (card != null && game.getState().getZone(card.getId()).equals(Constants.Zone.GRAVEYARD)) { Player owner = game.getPlayer(card.getOwnerId()); if (card.putOntoBattlefield(game, Constants.Zone.GRAVEYARD, source.getId(), source.getControllerId())) { owner.getGraveyard().remove(card); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java index 677a95b7160..f5f8aec3e60 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java @@ -106,7 +106,7 @@ public class QuicksilverGargantuan extends CardImpl { permanent.setExpansionSetCode(card.getExpansionSetCode()); permanent.getAbilities().clear(); for (Ability ability : card.getAbilities()) { - permanent.addAbility(ability); + permanent.addAbility(ability, game); } return true; diff --git a/Mage.Sets/src/mage/sets/shardsofalara/ElspethKnightErrant.java b/Mage.Sets/src/mage/sets/shardsofalara/ElspethKnightErrant.java index da2609697e2..3d5307b1afd 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/ElspethKnightErrant.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/ElspethKnightErrant.java @@ -40,8 +40,8 @@ import mage.abilities.LoyaltyAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effects; -import mage.abilities.effects.common.continious.BoostTargetEffect; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continious.BoostTargetEffect; import mage.abilities.effects.common.continious.GainAbilityTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -118,7 +118,7 @@ class ElspethKnightErrantEffect extends ContinuousEffectImpl { break; case AbilityAddingRemovingEffects_6: if (sublayer == Constants.SubLayer.NA) { - creature.addAbility(HasteAbility.getInstance()); + creature.addAbility(HasteAbility.getInstance(), game); } break; } diff --git a/Mage.Sets/src/mage/sets/zendikar/SpreadingSeas.java b/Mage.Sets/src/mage/sets/zendikar/SpreadingSeas.java index b85ba1a6faa..339a2b58339 100644 --- a/Mage.Sets/src/mage/sets/zendikar/SpreadingSeas.java +++ b/Mage.Sets/src/mage/sets/zendikar/SpreadingSeas.java @@ -114,7 +114,7 @@ class SpreadingSeasEffect extends ContinuousEffectImpl { case AbilityAddingRemovingEffects_6: if (sublayer == SubLayer.NA) { land.getAbilities().clear(); - land.addAbility(new BlueManaAbility()); + land.addAbility(new BlueManaAbility(), game); } break; } diff --git a/Mage/src/mage/Constants.java b/Mage/src/mage/Constants.java index a245704d5cc..4926f8765dd 100644 --- a/Mage/src/mage/Constants.java +++ b/Mage/src/mage/Constants.java @@ -362,9 +362,7 @@ public final class Constants { HAND, GRAVEYARD, LIBRARY, BATTLEFIELD, STACK, EXILED, ALL, OUTSIDE, PICK, COMMAND; public boolean match(Zone zone) { - if (this == zone || this == ALL || zone == ALL) - return true; - return false; + return (this == zone || this == ALL || zone == ALL); } } diff --git a/Mage/src/mage/abilities/Abilities.java b/Mage/src/mage/abilities/Abilities.java index fe90578b000..fac3f843baa 100644 --- a/Mage/src/mage/abilities/Abilities.java +++ b/Mage/src/mage/abilities/Abilities.java @@ -77,18 +77,6 @@ public interface Abilities extends List, Serializable { */ public Abilities getActivatedAbilities(Zone zone); - /** - * Retrieves all activated abilities for the given {@link Zone} that match - * the given {@link FilterAbility}. - * - * @param zone The {@link Zone} for which abilities should be retrieved. - * @param filter The {@link FilterAbility} to apply to the result. - * @return The {@link ActivatedAbility activated abilities} matching the {@link Zone} and {@link FilterAbility}. - * - * @see mage.players.PlayerImpl#getPlayable(mage.game.Game, mage.filter.FilterAbility, mage.abilities.mana.ManaOptions, boolean) - */ - public Abilities getActivatedAbilities(Zone zone, FilterAbility filter); - /** * Retrieves all {@link ManaAbility mana abilities} in the given {@link Zone}. * @@ -259,7 +247,5 @@ public interface Abilities extends List, Serializable { */ public Abilities copy(); - public Map getReplacementEffects(Zone zone); - public Map getEffects(Game game, Zone zone, EffectType effectType); public String getValue(); } diff --git a/Mage/src/mage/abilities/AbilitiesImpl.java b/Mage/src/mage/abilities/AbilitiesImpl.java index ea1aa575d5c..e2688ee77ea 100644 --- a/Mage/src/mage/abilities/AbilitiesImpl.java +++ b/Mage/src/mage/abilities/AbilitiesImpl.java @@ -30,20 +30,13 @@ package mage.abilities; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.UUID; -import mage.Constants.EffectType; import mage.Constants.Zone; import mage.abilities.common.ZoneChangeTriggeredAbility; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.Effect; -import mage.abilities.effects.ReplacementEffect; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.ProtectionAbility; import mage.abilities.mana.ManaAbility; -import mage.filter.FilterAbility; import mage.game.Game; /** @@ -88,17 +81,6 @@ public class AbilitiesImpl extends ArrayList implements Ab return zonedAbilities; } - @Override - public Abilities getActivatedAbilities(Zone zone, FilterAbility filter) { - Abilities zonedAbilities = new AbilitiesImpl(); - for (T ability: this) { - if (ability instanceof ActivatedAbility && ability.getZone().match(zone) && filter.match(ability)) { - zonedAbilities.add((ActivatedAbility)ability); - } - } - return zonedAbilities; - } - @Override public Abilities getManaAbilities(Zone zone) { Abilities abilities = new AbilitiesImpl(); @@ -161,34 +143,6 @@ public class AbilitiesImpl extends ArrayList implements Ab return zonedAbilities; } - @Override - public Map getReplacementEffects(Zone zone) { - Map effects = new HashMap(); - for (T ability: this) { - if (ability instanceof StaticAbility && ability.getZone().match(zone)) { - for (Effect effect: ability.getEffects()) { - if (effect.getEffectType() == EffectType.REPLACEMENT || effect.getEffectType() == EffectType.PREVENTION) { - effects.put((ReplacementEffect)effect, ability); - } - } - } - } - return effects; - } - - @Override - public Map getEffects(Game game, Zone zone, EffectType effectType) { - Map effects = new HashMap(); - for (T ability: this) { - if (ability instanceof StaticAbility && ability.getZone().match(zone)) { - for (Effect effect: ability.getEffects(game, effectType)) { - effects.put(effect, ability); - } - } - } - return effects; - } - @Override public Abilities getProtectionAbilities() { Abilities abilities = new AbilitiesImpl(); diff --git a/Mage/src/mage/abilities/Ability.java b/Mage/src/mage/abilities/Ability.java index c5279ef6315..6114267fc21 100644 --- a/Mage/src/mage/abilities/Ability.java +++ b/Mage/src/mage/abilities/Ability.java @@ -351,5 +351,13 @@ public interface Ability extends Serializable { public Modes getModes(); public boolean canChooseTarget(Game game); + + /** + * Returns true if this abilities source is in the zone for the ability + * + * @param game + * @return + */ + public boolean isInUseableZone(Game game); } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 617700e6361..e449db02327 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -461,6 +461,12 @@ public abstract class AbilityImpl> implements Ability { return false; } + @Override + public boolean isInUseableZone(Game game) { + Zone test = game.getState().getZone(sourceId); + return test != null && zone.match(test); + } + @Override public String toString() { return getRule(); diff --git a/Mage/src/mage/abilities/DelayedTriggeredAbilities.java b/Mage/src/mage/abilities/DelayedTriggeredAbilities.java index 62fc4bb4e55..c853621efb0 100644 --- a/Mage/src/mage/abilities/DelayedTriggeredAbilities.java +++ b/Mage/src/mage/abilities/DelayedTriggeredAbilities.java @@ -44,17 +44,6 @@ import mage.game.events.GameEvent; super(abilities); } - public void checkTriggers(GameEvent event, Game game) { - Iterator it = this.iterator(); - while (it.hasNext()) { - DelayedTriggeredAbility ability = it.next(); - if (ability.checkTrigger(event, game)) { - ability.trigger(game, ability.controllerId); - it.remove(); - } - } - } - @Override public DelayedTriggeredAbilities copy() { return new DelayedTriggeredAbilities(this); diff --git a/Mage/src/mage/abilities/TriggeredAbilities.java b/Mage/src/mage/abilities/TriggeredAbilities.java index 5e6bb8b623a..8ed7ae47dc1 100644 --- a/Mage/src/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/mage/abilities/TriggeredAbilities.java @@ -29,6 +29,11 @@ package mage.abilities; import java.util.UUID; +import mage.Constants; +import mage.Constants.Zone; +import mage.MageObject; +import mage.game.Game; +import mage.game.events.GameEvent; /** * @@ -42,15 +47,19 @@ public class TriggeredAbilities extends AbilitiesImpl { super(abilities); } - public TriggeredAbilities getControlledBy(UUID controllerId) { - TriggeredAbilities controlledBy = new TriggeredAbilities(); - for (TriggeredAbility ability: this) { - if (ability.getControllerId().equals(controllerId)) - controlledBy.add(ability); - } - return controlledBy; - } - + public void checkTriggers(GameEvent event, Game game) { + for (TriggeredAbility ability: this) { + if (ability.isInUseableZone(game)) { + MageObject object = game.getObject(ability.getSourceId()); + if (object.getAbilities().contains(ability)) { + if (ability.checkTrigger(event, game)) { + ability.trigger(game, ability.getControllerId()); + } + } + } + } + } + @Override public TriggeredAbilities copy() { return new TriggeredAbilities(this); diff --git a/Mage/src/mage/abilities/TriggeredAbility.java b/Mage/src/mage/abilities/TriggeredAbility.java index 763052272cd..c24380a8844 100644 --- a/Mage/src/mage/abilities/TriggeredAbility.java +++ b/Mage/src/mage/abilities/TriggeredAbility.java @@ -41,5 +41,7 @@ public interface TriggeredAbility extends Ability { public void trigger(Game game, UUID controllerId); public boolean checkTrigger(GameEvent event, Game game); public boolean checkInterveningIfClause(Game game); - + @Override + public TriggeredAbility copy(); + } diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index 03ee51914df..f2bbf5f166c 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -201,10 +201,11 @@ public class ContinuousEffects implements Serializable { } private boolean isInactive(ContinuousEffect effect, Game game) { + Ability ability = abilityMap.get(effect.getId()); switch(effect.getDuration()) { case WhileOnBattlefield: - Permanent permanent = game.getPermanent(abilityMap.get(effect.getId()).getSourceId()); - return (permanent == null || !permanent.isPhasedIn()); + if (game.getObject(ability.getSourceId()) == null) + return (true); case OneUse: return effect.isUsed(); case Custom: @@ -214,22 +215,13 @@ public class ContinuousEffects implements Serializable { } private List getLayeredEffects(Game game) { - List layerEffects = new ArrayList(layeredEffects); - for (Card card: game.getCards()) { - Zone zone = game.getState().getZone(card.getId()); - if (zone == Zone.HAND || zone == Zone.GRAVEYARD) { - for (Entry entry: card.getAbilities().getEffects(game, zone, EffectType.CONTINUOUS).entrySet()) { - layerEffects.add((ContinuousEffect)entry.getKey()); - abilityMap.put(entry.getKey().getId(), entry.getValue()); - } - } - } - for (Permanent permanent: game.getBattlefield().getAllPermanents()) { - for (Entry entry: permanent.getAbilities().getEffects(game, Zone.BATTLEFIELD, EffectType.CONTINUOUS).entrySet()) { - layerEffects.add((ContinuousEffect)entry.getKey()); - abilityMap.put(entry.getKey().getId(), entry.getValue()); + List layerEffects = new ArrayList(); + for (ContinuousEffect effect: layeredEffects) { + Ability ability = abilityMap.get(effect.getId()); + if (ability.isInUseableZone(game)) { + layerEffects.add(effect); } - } + } Collections.sort(layerEffects, new TimestampSorter()); return layerEffects; } @@ -256,7 +248,7 @@ public class ContinuousEffects implements Serializable { // } for (RequirementEffect effect: requirementEffects) { Ability ability = abilityMap.get(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.getZone() == game.getZone(ability.getSourceId())) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { if (effect.applies(permanent, ability, game)) effects.add(effect); } @@ -277,7 +269,7 @@ public class ContinuousEffects implements Serializable { // } for (RestrictionEffect effect: restrictionEffects) { Ability ability = abilityMap.get(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.getZone() == game.getZone(ability.getSourceId())) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { if (effect.applies(permanent, ability, game)) effects.add(effect); } @@ -328,7 +320,7 @@ public class ContinuousEffects implements Serializable { //get all applicable transient Replacement effects for (ReplacementEffect effect: replacementEffects) { Ability ability = abilityMap.get(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.getZone() == game.getZone(ability.getSourceId())) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.applies(event, ability, game)) { replaceEffects.add(effect); @@ -338,7 +330,7 @@ public class ContinuousEffects implements Serializable { } for (PreventionEffect effect: preventionEffects) { Ability ability = abilityMap.get(effect.getId()); - if (!(ability instanceof StaticAbility) || ability.getZone() == game.getZone(ability.getSourceId())) { + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game)) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.applies(event, ability, game)) { replaceEffects.add(effect); diff --git a/Mage/src/mage/abilities/effects/common/CopyEffect.java b/Mage/src/mage/abilities/effects/common/CopyEffect.java index f165ac592b0..69413b0de01 100644 --- a/Mage/src/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/mage/abilities/effects/common/CopyEffect.java @@ -78,7 +78,7 @@ public class CopyEffect extends ContinuousEffectImpl { } permanent.getAbilities().clear(); for (Ability ability: target.getAbilities()) { - permanent.addAbility(ability); + permanent.addAbility(ability, game); } permanent.getPower().setValue(target.getPower().getValue()); permanent.getToughness().setValue(target.getToughness().getValue()); diff --git a/Mage/src/mage/abilities/effects/common/CopyPermanentEffect.java b/Mage/src/mage/abilities/effects/common/CopyPermanentEffect.java index 7a31721fbc3..20cbdbf7e1c 100644 --- a/Mage/src/mage/abilities/effects/common/CopyPermanentEffect.java +++ b/Mage/src/mage/abilities/effects/common/CopyPermanentEffect.java @@ -72,6 +72,7 @@ public class CopyPermanentEffect extends OneShotEffect { Permanent perm = game.getPermanent(target.getFirstTarget()); if (perm != null) { perm = perm.copy(); + game.getState().addCard(perm); perm.reset(game); perm.assignNewId(); game.addEffect(new CopyEffect(perm), source); diff --git a/Mage/src/mage/abilities/effects/common/CopyTokenEffect.java b/Mage/src/mage/abilities/effects/common/CopyTokenEffect.java index d5b05fe3b9a..9444165f779 100644 --- a/Mage/src/mage/abilities/effects/common/CopyTokenEffect.java +++ b/Mage/src/mage/abilities/effects/common/CopyTokenEffect.java @@ -40,7 +40,7 @@ public class CopyTokenEffect extends ContinuousEffectImpl { } permanent.getAbilities().clear(); for (Ability ability: token.getAbilities()) { - permanent.addAbility(ability); + permanent.addAbility(ability, game); } permanent.getPower().setValue(token.getPower().getValue()); permanent.getToughness().setValue(token.getToughness().getValue()); diff --git a/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java b/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java index 9f01a5fd7cf..81c2691f176 100644 --- a/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureSourceEffect.java @@ -99,7 +99,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl 0) { for (Ability ability: token.getAbilities()) { - permanent.addAbility(ability); + permanent.addAbility(ability, game); } } } diff --git a/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureTargetEffect.java b/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureTargetEffect.java index 7fa3c055309..188135d5f89 100644 --- a/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/BecomesCreatureTargetEffect.java @@ -101,7 +101,7 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl 0) { for (Ability ability : token.getAbilities()) { - permanent.addAbility(ability); + permanent.addAbility(ability, game); } } } diff --git a/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java b/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java index 9b037a015c3..1f68e21bdfb 100644 --- a/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/GainAbilityAllEffect.java @@ -93,7 +93,7 @@ public class GainAbilityAllEffect extends ContinuousEffectImpl { permanent.setExpansionSetCode(card.getExpansionSetCode()); permanent.getAbilities().clear(); for (Ability ability : card.getAbilities()) { - permanent.addAbility(ability); + permanent.addAbility(ability, game); } permanent.getPower().setValue(card.getPower().getValue()); permanent.getToughness().setValue(card.getToughness().getValue()); diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java index 987d8efa9c3..d49ae516832 100644 --- a/Mage/src/mage/cards/Card.java +++ b/Mage/src/mage/cards/Card.java @@ -82,8 +82,6 @@ public interface Card extends MageObject { public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game); public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId); public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId); - public void checkTriggers(Zone zone, GameEvent event, Game game); - public List getMana(); @Override diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index b8b7caf0c79..1fbc8374ebb 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -33,27 +33,20 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; - import mage.Constants.CardType; -import mage.Constants.Outcome; import mage.Constants.Rarity; import mage.Constants.Zone; -import mage.MageException; import mage.MageObjectImpl; import mage.Mana; import mage.abilities.Ability; import mage.abilities.PlayLandAbility; import mage.abilities.SpellAbility; -import mage.abilities.TriggeredAbility; import mage.abilities.mana.ManaAbility; import mage.game.Game; -import mage.game.GameException; -import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.PermanentCard; import mage.game.stack.Spell; import mage.watchers.Watcher; -import mage.watchers.WatcherImpl; import org.apache.log4j.Logger; public abstract class CardImpl> extends MageObjectImpl implements Card { @@ -70,6 +63,7 @@ public abstract class CardImpl> extends MageObjectImpl protected boolean canTransform; protected Card secondSideCard; protected boolean nightCard; + protected SpellAbility spellAbility; public CardImpl(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { this(ownerId, name); @@ -175,11 +169,13 @@ public abstract class CardImpl> extends MageObjectImpl @Override public SpellAbility getSpellAbility() { - for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) { - if (ability instanceof SpellAbility) - return (SpellAbility) ability; + if (spellAbility == null) { + for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) { + if (ability instanceof SpellAbility) + spellAbility = (SpellAbility) ability; + } } - return null; + return spellAbility; } @Override @@ -198,15 +194,6 @@ public abstract class CardImpl> extends MageObjectImpl return watchers; } - @Override - public void checkTriggers(Zone zone, GameEvent event, Game game) { - for (TriggeredAbility ability : abilities.getTriggeredAbilities(zone)) { - if (ability.checkTrigger(event, game)) { - ability.trigger(game, ownerId); - } - } - } - @Override public String getExpansionSetCode() { return expansionSetCode; diff --git a/Mage/src/mage/cards/Cards.java b/Mage/src/mage/cards/Cards.java index a18cab22f31..593a04f871b 100644 --- a/Mage/src/mage/cards/Cards.java +++ b/Mage/src/mage/cards/Cards.java @@ -51,7 +51,5 @@ public interface Cards extends Set, Serializable { public int count(FilterCard filter, Game game); public int count(FilterCard filter, UUID playerId, Game game); - public void checkTriggers(GameEvent event, Game game); - public Cards copy(); } diff --git a/Mage/src/mage/cards/CardsImpl.java b/Mage/src/mage/cards/CardsImpl.java index 56453c65699..7259ea7d582 100644 --- a/Mage/src/mage/cards/CardsImpl.java +++ b/Mage/src/mage/cards/CardsImpl.java @@ -29,18 +29,10 @@ package mage.cards; import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.UUID; +import java.util.*; import mage.Constants.Zone; import mage.filter.FilterCard; import mage.game.Game; -import mage.game.events.GameEvent; /** * @@ -79,8 +71,6 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl @Override public void add(Card card) { this.add(card.getId()); -// if (zone != null) -// card.setZone(zone); } @Override @@ -133,13 +123,6 @@ public class CardsImpl extends LinkedHashSet implements Cards, Serializabl return result; } - @Override - public void checkTriggers(GameEvent event, Game game) { - for (UUID card: this) { - game.getCard(card).checkTriggers(zone, event, game); - } - } - @Override public Set getCards(FilterCard filter, Game game) { Set cards = new LinkedHashSet(); diff --git a/Mage/src/mage/game/Exile.java b/Mage/src/mage/game/Exile.java index 161a6b33ccd..6473d615ebc 100644 --- a/Mage/src/mage/game/Exile.java +++ b/Mage/src/mage/game/Exile.java @@ -90,12 +90,6 @@ public class Exile implements Serializable, Copyable { return exileZones.get(id); } - public void checkTriggers(GameEvent event, Game game) { - for (ExileZone exile: exileZones.values()) { - exile.checkTriggers(event, game); - } - } - public Card getCard(UUID cardId, Game game) { for (ExileZone exile: exileZones.values()) { if (exile.contains(cardId)) diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 14a90f9bcc5..4f4b150a56b 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -82,7 +82,6 @@ public interface Game extends MageItem, Serializable { public UUID getControllerId(UUID objectId); public Permanent getPermanent(UUID permanentId); public Card getCard(UUID cardId); - public Zone getZone(UUID objectId); public void setZone(UUID objectId, Zone zone); public void addPlayer(Player player, Deck deck) throws GameException; public Player getPlayer(UUID playerId); @@ -126,7 +125,7 @@ public interface Game extends MageItem, Serializable { public void fireChooseEvent(UUID playerId, Choice choice); public void fireSelectTargetEvent(UUID playerId, String message, Set targets, boolean required, Map options); public void fireSelectTargetEvent(UUID playerId, String message, Cards cards, boolean required, Map options); - public void fireSelectTargetEvent(UUID playerId, String message, TriggeredAbilities abilities, boolean required); + public void fireSelectTargetEvent(UUID playerId, String message, List abilities); public void fireSelectTargetEvent(UUID playerId, String message, List perms, boolean required); public void fireSelectEvent(UUID playerId, String message); public void fireLookAtCardsEvent(UUID playerId, String message, Cards cards); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index f683d6f5e07..3714b82d055 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -187,21 +187,7 @@ public abstract class GameImpl> implements Game, Serializa for (Card card: cards) { card.setOwnerId(ownerId); gameCards.put(card.getId(), card); - state.setZone(card.getId(), Zone.OUTSIDE); - for (Watcher watcher: card.getWatchers()) { - watcher.setControllerId(ownerId); - watcher.setSourceId(card.getId()); - state.getWatchers().add(watcher); - } - for (StaticAbility ability: card.getAbilities().getStaticAbilities(Zone.ALL)) { - for (Mode mode: ability.getModes().values()) { - for (Effect effect: mode.getEffects()) { - if (effect instanceof ContinuousEffect) { - state.addEffect((ContinuousEffect)effect, ability); - } - } - } - } + state.addCard(card); } } @@ -285,10 +271,10 @@ public abstract class GameImpl> implements Game, Serializa return gameCards.get(cardId); } - @Override - public Zone getZone(UUID objectId) { - return state.getZone(objectId); - } +// @Override +// public Zone getZone(UUID objectId) { +// return state.getZone(objectId); +// } @Override public void setZone(UUID objectId, Zone zone) { @@ -766,16 +752,16 @@ public abstract class GameImpl> implements Game, Serializa for (UUID playerId: state.getPlayerList(state.getActivePlayerId())) { Player player = getPlayer(playerId); while (true) { - TriggeredAbilities abilities = state.getTriggered().getControlledBy(player.getId()); - if (abilities.size() == 0) + List abilities = state.getTriggered(player.getId()); + if (abilities.isEmpty()) break; if (abilities.size() == 1) { - state.getTriggered().remove(abilities.get(0)); + state.removeTriggeredAbility(abilities.get(0)); played |= player.triggerAbility(abilities.get(0), this); } else { TriggeredAbility ability = player.chooseTriggeredAbility(abilities, this); - state.getTriggered().remove(ability); + state.removeTriggeredAbility(ability); played |= player.triggerAbility(ability, this); } } @@ -1011,9 +997,9 @@ public abstract class GameImpl> implements Game, Serializa } @Override - public void fireSelectTargetEvent(UUID playerId, String message, TriggeredAbilities abilities, boolean required) { + public void fireSelectTargetEvent(UUID playerId, String message, List abilities) { if (simulation) return; - playerQueryEventSource.target(playerId, message, abilities, required); + playerQueryEventSource.target(playerId, message, abilities); } @Override diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 104f7c6419e..7acd0d84abe 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -39,17 +39,10 @@ import java.util.List; import java.util.Map; import java.util.UUID; import mage.Constants.Zone; -import mage.abilities.Abilities; -import mage.abilities.AbilitiesImpl; -import mage.abilities.Ability; -import mage.abilities.ActivatedAbility; -import mage.abilities.DelayedTriggeredAbilities; -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.Mode; -import mage.abilities.SpecialActions; -import mage.abilities.TriggeredAbilities; +import mage.abilities.*; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; +import mage.abilities.effects.Effect; import mage.cards.Card; import mage.choices.Choice; import mage.game.combat.Combat; @@ -68,6 +61,7 @@ import mage.players.PlayerList; import mage.players.Players; import mage.target.Target; import mage.util.Copyable; +import mage.watchers.Watcher; import mage.watchers.Watchers; /** @@ -98,7 +92,8 @@ public class GameState implements Serializable, Copyable { private boolean paused; // private List messages = new ArrayList(); private ContinuousEffects effects; - private TriggeredAbilities triggers; + private TriggeredAbilities triggers; + private List triggered = new ArrayList(); private DelayedTriggeredAbilities delayed; private SpecialActions specialActions; private Map> otherAbilities = new HashMap>(); @@ -116,10 +111,9 @@ public class GameState implements Serializable, Copyable { command = new Command(); exile = new Exile(); revealed = new Revealed(); - lookedAt = new HashMap(); battlefield = new Battlefield(); effects = new ContinuousEffects(); - triggers = new TriggeredAbilities(); + triggers = new TriggeredAbilities(); delayed = new DelayedTriggeredAbilities(); specialActions = new SpecialActions(); combat = new Combat(); @@ -142,7 +136,10 @@ public class GameState implements Serializable, Copyable { this.turnNum = state.turnNum; this.gameOver = state.gameOver; this.effects = state.effects.copy(); - this.triggers = state.triggers.copy(); + for (TriggeredAbility trigger: state.triggered) { + this.triggered.add(trigger.copy()); + } + this.triggers = state.triggers.copy(); this.delayed = state.delayed.copy(); this.specialActions = state.specialActions.copy(); this.combat = state.combat.copy(); @@ -413,7 +410,8 @@ public class GameState implements Serializable, Copyable { this.stack = state.stack; this.command = state.command; this.effects = state.effects; - this.triggers = state.triggers; + this.triggers = state.triggers; + this.triggered = state.triggered; this.combat = state.combat; this.exile = state.exile; this.battlefield = state.battlefield; @@ -426,41 +424,49 @@ public class GameState implements Serializable, Copyable { public void handleEvent(GameEvent event, Game game) { watchers.watch(event, game); -// if (!replaceEvent(event, game)) { - //TODO: this is awkward - improve - if (event.getType() == EventType.ZONE_CHANGE) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; - if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getTarget() != null) { - if (zEvent.getTarget() instanceof PermanentCard) { - ((PermanentCard)zEvent.getTarget()).checkPermanentOnlyTriggers(zEvent, game); - } - else { - zEvent.getTarget().checkTriggers(zEvent.getFromZone(), event, game); - zEvent.getTarget().checkTriggers(zEvent.getToZone(), event, game); - } - } - } - for (Player player: players.values()) { - player.checkTriggers(event, game); - } - battlefield.checkTriggers(event, game); - stack.checkTriggers(event, game); - command.checkTriggers(event, game); - delayed.checkTriggers(event, game); - exile.checkTriggers(event, game); -// } + triggers.checkTriggers(event, game); } public boolean replaceEvent(GameEvent event, Game game) { - return stack.replaceEvent(event, game) | effects.replaceEvent(event, game); - + return effects.replaceEvent(event, game); } - public void addTriggeredAbility(TriggeredAbility ability) { - this.triggers.add(ability); + public void addCard(Card card) { + setZone(card.getId(), Zone.OUTSIDE); + for (Watcher watcher: card.getWatchers()) { + watcher.setControllerId(card.getOwnerId()); + watcher.setSourceId(card.getId()); + watchers.add(watcher); + } + for (Ability ability: card.getAbilities()) { + addAbility(ability); + } + } + + public void addAbility(Ability ability) { + if (ability instanceof StaticAbility) { + for (Mode mode: ability.getModes().values()) { + for (Effect effect: mode.getEffects()) { + if (effect instanceof ContinuousEffect) { + addEffect((ContinuousEffect)effect, ability); + } + } + } + } + else if (ability instanceof TriggeredAbility) { + triggers.add((TriggeredAbility)ability); + } } - public void addDelayedTriggeredAbility(DelayedTriggeredAbility ability) { + public void addTriggeredAbility(TriggeredAbility ability) { + this.triggered.add(ability); + } + + public void removeTriggeredAbility(TriggeredAbility ability) { + this.triggered.remove(ability); + } + + public void addDelayedTriggeredAbility(DelayedTriggeredAbility ability) { this.delayed.add(ability); } @@ -473,8 +479,13 @@ public class GameState implements Serializable, Copyable { } } - public TriggeredAbilities getTriggered() { - return this.triggers; + public List getTriggered(UUID controllerId) { + List triggereds = new ArrayList(); + for (TriggeredAbility ability: triggered) { + if (ability.getControllerId().equals(controllerId)) + triggereds.add(ability); + } + return triggereds; } public DelayedTriggeredAbilities getDelayed() { @@ -516,8 +527,9 @@ public class GameState implements Serializable, Copyable { public void clear() { battlefield.clear(); effects.clear(); - delayed.clear(); triggers.clear(); + delayed.clear(); + triggered.clear(); stack.clear(); exile.clear(); command.clear(); diff --git a/Mage/src/mage/game/command/Command.java b/Mage/src/mage/game/command/Command.java index 11b4b7250e8..1782e645b0e 100644 --- a/Mage/src/mage/game/command/Command.java +++ b/Mage/src/mage/game/command/Command.java @@ -44,11 +44,11 @@ public class Command extends ArrayList { // } - public void checkTriggers(GameEvent event, Game game) { - for (CommandObject commandObject: this) { - commandObject.checkTriggers(event, game); - } - } +// public void checkTriggers(GameEvent event, Game game) { +// for (CommandObject commandObject: this) { +// commandObject.checkTriggers(event, game); +// } +// } public Command copy() { return new Command(this); diff --git a/Mage/src/mage/game/command/CommandObject.java b/Mage/src/mage/game/command/CommandObject.java index fbc9d7d6912..ae9674b908b 100644 --- a/Mage/src/mage/game/command/CommandObject.java +++ b/Mage/src/mage/game/command/CommandObject.java @@ -28,11 +28,8 @@ package mage.game.command; -import mage.abilities.Ability; -import mage.game.*; import java.util.UUID; import mage.MageObject; -import mage.game.events.GameEvent; /** * @@ -42,7 +39,7 @@ public interface CommandObject extends MageObject { public UUID getSourceId(); public UUID getControllerId(); - public void checkTriggers(GameEvent event, Game game); +// public void checkTriggers(GameEvent event, Game game); @Override public CommandObject copy(); diff --git a/Mage/src/mage/game/command/Emblem.java b/Mage/src/mage/game/command/Emblem.java index 64bd6d3f16e..55986304da9 100644 --- a/Mage/src/mage/game/command/Emblem.java +++ b/Mage/src/mage/game/command/Emblem.java @@ -88,18 +88,18 @@ public class Emblem implements CommandObject { this.sourceId = sourceId; } - @Override - public void checkTriggers(GameEvent event, Game game) { - // we have to use Zone.BATTLEFIELD to use the same predefined abilities (like SpellCastTriggeredAbility) - // and not create duplicates - for (TriggeredAbility ability: getAbilities().getTriggeredAbilities(Constants.Zone.BATTLEFIELD)) { - ability.setControllerId(getControllerId()); - ability.setSourceId(getSourceId()); - if (ability.checkTrigger(event, game)) { - ability.trigger(game, getControllerId()); - } - } - } +// @Override +// public void checkTriggers(GameEvent event, Game game) { +// // we have to use Zone.BATTLEFIELD to use the same predefined abilities (like SpellCastTriggeredAbility) +// // and not create duplicates +// for (TriggeredAbility ability: getAbilities().getTriggeredAbilities(Constants.Zone.BATTLEFIELD)) { +// ability.setControllerId(getControllerId()); +// ability.setSourceId(getSourceId()); +// if (ability.checkTrigger(event, game)) { +// ability.trigger(game, getControllerId()); +// } +// } +// } @Override public String getName() { diff --git a/Mage/src/mage/game/events/PlayerQueryEvent.java b/Mage/src/mage/game/events/PlayerQueryEvent.java index 24312db9574..184f678ba20 100644 --- a/Mage/src/mage/game/events/PlayerQueryEvent.java +++ b/Mage/src/mage/game/events/PlayerQueryEvent.java @@ -34,6 +34,7 @@ import java.util.*; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; import mage.abilities.TriggeredAbilities; +import mage.abilities.TriggeredAbility; import mage.cards.Card; import mage.cards.Cards; import mage.game.permanent.Permanent; @@ -144,8 +145,8 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return new PlayerQueryEvent(playerId, message, null, null, null, cards, QueryType.PICK_TARGET, 0, 0, required, options); } - public static PlayerQueryEvent targetEvent(UUID playerId, String message, TriggeredAbilities abilities, boolean required) { - return new PlayerQueryEvent(playerId, message, abilities, null, null, null, QueryType.PICK_ABILITY, 0, 0, required); + public static PlayerQueryEvent targetEvent(UUID playerId, String message, List abilities) { + return new PlayerQueryEvent(playerId, message, abilities, null, null, null, QueryType.PICK_ABILITY, 0, 0, true); } public static PlayerQueryEvent targetEvent(UUID playerId, String message, List perms, boolean required) { diff --git a/Mage/src/mage/game/events/PlayerQueryEventSource.java b/Mage/src/mage/game/events/PlayerQueryEventSource.java index 6a5c902bdd2..fb345d7f532 100644 --- a/Mage/src/mage/game/events/PlayerQueryEventSource.java +++ b/Mage/src/mage/game/events/PlayerQueryEventSource.java @@ -31,10 +31,7 @@ package mage.game.events; import java.io.Serializable; import java.util.*; -import mage.abilities.ActivatedAbility; -import mage.abilities.Mode; -import mage.abilities.Modes; -import mage.abilities.TriggeredAbilities; +import mage.abilities.*; import mage.cards.Card; import mage.cards.Cards; import mage.cards.decks.Deck; @@ -85,8 +82,8 @@ public class PlayerQueryEventSource implements EventSource, Se dispatcher.fireEvent(PlayerQueryEvent.lookEvent(playerId, message, cards)); } - public void target(UUID playerId, String message, TriggeredAbilities abilities, boolean required) { - dispatcher.fireEvent(PlayerQueryEvent.targetEvent(playerId, message, abilities, required)); + public void target(UUID playerId, String message, List abilities) { + dispatcher.fireEvent(PlayerQueryEvent.targetEvent(playerId, message, abilities)); } public void target(UUID playerId, String message, List perms, boolean required) { diff --git a/Mage/src/mage/game/permanent/Battlefield.java b/Mage/src/mage/game/permanent/Battlefield.java index 37feab69092..deeeb3a004b 100644 --- a/Mage/src/mage/game/permanent/Battlefield.java +++ b/Mage/src/mage/game/permanent/Battlefield.java @@ -229,24 +229,13 @@ public class Battlefield implements Serializable { return field.containsKey(key); } - public void checkTriggers(GameEvent event, Game game) { - if (game.getRangeOfInfluence() == RangeOfInfluence.ALL) { - for (Permanent perm: field.values()) { - if (perm.isPhasedIn()) - perm.checkTriggers(event, game); - } + public void beginningOfTurn(Game game) { + for (Permanent perm: field.values()) { + perm.beginningOfTurn(game); } - else { - //20100423 - 801.7 - Set range = game.getPlayer(event.getPlayerId()).getInRange(); - for (Permanent perm: field.values()) { - if (range.contains(perm.getControllerId()) && perm.isPhasedIn()) - perm.checkTriggers(event, game); - } - } - } - - public void endOfTurn(UUID controllerId, Game game) { + } + + public void endOfTurn(UUID controllerId, Game game) { for (Permanent perm: field.values()) { perm.endOfTurn(game); } diff --git a/Mage/src/mage/game/permanent/Permanent.java b/Mage/src/mage/game/permanent/Permanent.java index a8aed74ba1d..d81391f878b 100644 --- a/Mage/src/mage/game/permanent/Permanent.java +++ b/Mage/src/mage/game/permanent/Permanent.java @@ -97,14 +97,16 @@ public interface Permanent extends Card { public void entersBattlefield(UUID sourceId, Game game); public String getValue(); - @Override - public void addAbility(Ability ability); + @Deprecated + @Override + public void addAbility(Ability ability); + public void addAbility(Ability ability, Game game); public void setLoyaltyUsed(boolean used); public boolean isLoyaltyUsed(); - public void endOfTurn(Game game); - public void checkTriggers(GameEvent event, Game game); + public void beginningOfTurn(Game game); + public void endOfTurn(Game game); public void checkControlChanged(Game game); public int getTurnsOnBattlefield(); diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index 878dae3217a..58f05c70eee 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -130,35 +130,35 @@ public class PermanentCard extends PermanentImpl { } } - public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) { - // we only want to trigger abilities that are not on the underlying card ie. have been added by another effect - // or we want to trigger abilities that only trigger on leaving the battlefield - // card abilities will get triggered later when the card hits the new zone - List triggered = new ArrayList(); - for (TriggeredAbility ability : abilities.getTriggeredAbilities(event.getFromZone())) { - if (!card.getAbilities().containsKey(ability.getId())) { - if (ability.checkTrigger(event, game)) { - triggered.add(ability.getId()); - ability.trigger(game, controllerId); - } - } else if (ability instanceof ZoneChangeTriggeredAbility && event.getFromZone() == Zone.BATTLEFIELD) { - ZoneChangeTriggeredAbility zcAbility = (ZoneChangeTriggeredAbility) ability; - if (zcAbility.getToZone() == null) { - if (ability.checkTrigger(event, game)) { - triggered.add(ability.getId()); - ability.trigger(game, controllerId); - } - } - } - } - for (TriggeredAbility ability : abilities.getTriggeredAbilities(event.getToZone())) { - if (!card.getAbilities().containsKey(ability.getId())) { - if (!triggered.contains(ability.getId()) && ability.checkTrigger(event, game)) { - ability.trigger(game, controllerId); - } - } - } - } +// public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) { +// // we only want to trigger abilities that are not on the underlying card ie. have been added by another effect +// // or we want to trigger abilities that only trigger on leaving the battlefield +// // card abilities will get triggered later when the card hits the new zone +// List triggered = new ArrayList(); +// for (TriggeredAbility ability : abilities.getTriggeredAbilities(event.getFromZone())) { +// if (!card.getAbilities().containsKey(ability.getId())) { +// if (ability.checkTrigger(event, game)) { +// triggered.add(ability.getId()); +// ability.trigger(game, controllerId); +// } +// } else if (ability instanceof ZoneChangeTriggeredAbility && event.getFromZone() == Zone.BATTLEFIELD) { +// ZoneChangeTriggeredAbility zcAbility = (ZoneChangeTriggeredAbility) ability; +// if (zcAbility.getToZone() == null) { +// if (ability.checkTrigger(event, game)) { +// triggered.add(ability.getId()); +// ability.trigger(game, controllerId); +// } +// } +// } +// } +// for (TriggeredAbility ability : abilities.getTriggeredAbilities(event.getToZone())) { +// if (!card.getAbilities().containsKey(ability.getId())) { +// if (!triggered.contains(ability.getId()) && ability.checkTrigger(event, game)) { +// ability.trigger(game, controllerId); +// } +// } +// } +// } @Override diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index 1c5785fc3c0..e41aa27f7c6 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -158,12 +158,18 @@ public abstract class PermanentImpl> extends CardImpl return sb.toString(); } + @Override + public void addAbility(Ability ability) { + throw new UnsupportedOperationException("Unsupported operation: use addAbility(Ability ability, Game game) instead"); + } + @Override - public void addAbility(Ability ability) { + public void addAbility(Ability ability, Game game) { Ability copy = ability.copy(); if (!abilities.containsKey(copy.getId())) { copy.setControllerId(controllerId); copy.setSourceId(objectId); + game.getState().addAbility(copy); abilities.add(copy); } } @@ -209,6 +215,11 @@ public abstract class PermanentImpl> extends CardImpl return turnsOnBattlefield; } + @Override + public void beginningOfTurn(Game game) { + this.controlledFromStartOfTurn = true; + } + @Override public void endOfTurn(Game game) { this.damage = 0; @@ -221,17 +232,6 @@ public abstract class PermanentImpl> extends CardImpl } } - @Override - public void checkTriggers(GameEvent event, Game game) { - if (event.getType() == EventType.BEGINNING_PHASE_PRE && game.getActivePlayerId().equals(controllerId)) - this.controlledFromStartOfTurn = true; - for (TriggeredAbility ability : abilities.getTriggeredAbilities(Zone.BATTLEFIELD)) { - if (ability.checkTrigger(event, game)) { - ability.trigger(game, controllerId); - } - } - } - @Override public void setLoyaltyUsed(boolean used) { this.loyaltyUsed = used; diff --git a/Mage/src/mage/game/permanent/token/Token.java b/Mage/src/mage/game/permanent/token/Token.java index c9970c7461a..84c06299d41 100644 --- a/Mage/src/mage/game/permanent/token/Token.java +++ b/Mage/src/mage/game/permanent/token/Token.java @@ -96,6 +96,7 @@ public class Token extends MageObjectImpl { amount = event.getAmount(); for (int i = 0; i < amount; i++) { PermanentToken permanent = new PermanentToken(this, controllerId, setCode); + game.getState().addCard(permanent); game.getBattlefield().addPermanent(permanent); this.lastAddedTokenId = permanent.getId(); permanent.entersBattlefield(sourceId, game); diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 6efc4606cf7..9b34d840a73 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -309,16 +309,6 @@ public class Spell> implements StackObject, Card { @Override public void setOwnerId(UUID controllerId) {} - @Override - public void checkTriggers(GameEvent event, Game game) { - checkTriggers(Zone.STACK, event, game); - } - - @Override - public void checkTriggers(Zone zone, GameEvent event, Game game) { - card.checkTriggers(zone, event, game); - } - @Override public List getRules() { return card.getRules(); diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index d9a245d0cf4..359ba7c3cc1 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -29,18 +29,10 @@ package mage.game.stack; import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.UUID; import mage.Constants.Zone; -import mage.abilities.Ability; -import mage.abilities.effects.ReplacementEffect; import mage.game.Game; import mage.game.events.GameEvent; -import mage.players.Player; /** * @@ -77,12 +69,6 @@ public class SpellStack extends ArrayDeque { } } - public void checkTriggers(GameEvent event, Game game) { - for (StackObject stackObject: this) { - stackObject.checkTriggers(event, game); - } - } - public boolean counter(UUID objectId, UUID sourceId, Game game) { StackObject stackObject = getStackObject(objectId); if (stackObject != null) { @@ -100,30 +86,6 @@ public class SpellStack extends ArrayDeque { return false; } - public boolean replaceEvent(GameEvent event, Game game) { - boolean caught = false; - Map rEffects = new LinkedHashMap(); - for (StackObject stackObject: this) { - 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) { - List effects = new ArrayList(rEffects.keySet()); - int index; - if (rEffects.size() == 1) { - index = 0; - } - else { - Player player = game.getPlayer(event.getPlayerId()); - index = player.chooseEffect(effects, game); - } - caught = effects.get(index).replaceEvent(event, rEffects.get(effects.get(index)), game); - } - return caught; - } - public StackObject getStackObject(UUID id) { for (StackObject stackObject: this) { UUID objectId = stackObject.getId(); diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index 30cb05a25cd..7125fd45b2b 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -265,9 +265,6 @@ public class StackAbility implements StackObject, Ability { @Override public void addManaCost(ManaCost cost) { } - @Override - public void checkTriggers(GameEvent event, Game game) { } - @Override public AbilityType getAbilityType() { return ability.getAbilityType(); @@ -330,4 +327,9 @@ public class StackAbility implements StackObject, Ability { public boolean canChooseTarget(Game game) { return ability.canChooseTarget(game); } + + @Override + public boolean isInUseableZone(Game game) { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/Mage/src/mage/game/stack/StackObject.java b/Mage/src/mage/game/stack/StackObject.java index a7daa74784f..b3336545b0b 100644 --- a/Mage/src/mage/game/stack/StackObject.java +++ b/Mage/src/mage/game/stack/StackObject.java @@ -28,11 +28,10 @@ package mage.game.stack; -import mage.abilities.Ability; -import mage.game.*; import java.util.UUID; import mage.MageObject; -import mage.game.events.GameEvent; +import mage.abilities.Ability; +import mage.game.Game; public interface StackObject extends MageObject { @@ -40,7 +39,6 @@ public interface StackObject extends MageObject { public boolean resolve(Game game); public UUID getSourceId(); public UUID getControllerId(); - public void checkTriggers(GameEvent event, Game game); public void counter(UUID sourceId, Game game); public Ability getStackAbility(); @Override diff --git a/Mage/src/mage/game/turn/BeginningPhase.java b/Mage/src/mage/game/turn/BeginningPhase.java index 47d0a7ec932..a74664ee03e 100644 --- a/Mage/src/mage/game/turn/BeginningPhase.java +++ b/Mage/src/mage/game/turn/BeginningPhase.java @@ -28,7 +28,10 @@ package mage.game.turn; +import java.util.UUID; import mage.Constants.TurnPhase; +import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; /** @@ -47,6 +50,13 @@ public class BeginningPhase extends Phase { this.steps.add(new DrawStep()); } + @Override + public boolean beginPhase(Game game, UUID activePlayerId) { + game.getBattlefield().beginningOfTurn(game); + return super.beginPhase(game, activePlayerId); + } + + public BeginningPhase(final BeginningPhase phase) { super(phase); } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index f6a4d98cfc8..334c7c19d6a 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -188,7 +188,6 @@ public interface Player extends MageItem, Copyable { public boolean canBeTargetedBy(MageObject source); public boolean hasProtectionFrom(MageObject source); public boolean flipCoin(Game game); - public void checkTriggers(GameEvent event, Game game); public void discard(int amount, Ability source, Game game); public void discardToMax(Game game); public boolean discard(Card card, Ability source, Game game); @@ -223,7 +222,7 @@ public interface Player extends MageItem, Copyable { public abstract boolean playMana(ManaCost unpaid, Game game); public abstract boolean playXMana(VariableManaCost cost, ManaCosts costs, Game game); public abstract int chooseEffect(List rEffects, Game game); - public abstract TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game); + public abstract TriggeredAbility chooseTriggeredAbility(List abilities, Game game); public abstract Mode chooseMode(Modes modes, Ability source, Game game); public abstract void selectAttackers(Game game); public abstract void selectBlockers(Game game); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index ebe342dcb20..cf7a3aad028 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -307,12 +307,6 @@ public abstract class PlayerImpl> implements Player, Ser this.passedTurn = false; } - @Override - public void checkTriggers(GameEvent event, Game game) { - hand.checkTriggers(event, game); - graveyard.checkTriggers(event, game); - } - @Override public boolean canBeTargetedBy(MageObject source) { if (this.hasLost() || this.hasLeft())