diff --git a/Mage/src/mage/abilities/Ability.java b/Mage/src/mage/abilities/Ability.java index 96cc4e297f..b59fe07750 100644 --- a/Mage/src/mage/abilities/Ability.java +++ b/Mage/src/mage/abilities/Ability.java @@ -29,16 +29,19 @@ package mage.abilities; import java.io.Serializable; +import java.util.List; import java.util.UUID; import mage.Constants.Zone; +import mage.abilities.costs.AlternativeCost; 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.effects.Effect; import mage.abilities.effects.Effects; import mage.choices.Choice; import mage.choices.Choices; import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.Target; import mage.target.Targets; @@ -49,6 +52,10 @@ public interface Ability extends Serializable { public UUID getSourceId(); public Costs getCosts(); public void addCost(Cost cost); + public ManaCosts getManaCosts(); + public void addManaCost(ManaCost cost); + public List getAlternativeCosts(); + public void addAlternativeCost(AlternativeCost cost); public Effects getEffects(); public void addEffect(Effect effect); public Targets getTargets(); @@ -63,7 +70,6 @@ public interface Ability extends Serializable { public void setEnabled(boolean enabled); public boolean activate(Game game, boolean noMana); public boolean resolve(Game game); - public void handleEvent(GameEvent event, Game game); public void setControllerId(UUID controllerId); public void setSourceId(UUID sourceID); diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index e0393bbc5f..afca491484 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -29,11 +29,18 @@ package mage.abilities; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; +import mage.Constants.Outcome; import mage.Constants.Zone; +import mage.abilities.costs.AlternativeCost; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.mana.ManaCost; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; @@ -41,7 +48,6 @@ import mage.abilities.effects.OneShotEffect; import mage.choices.Choice; import mage.choices.Choices; import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.Target; import mage.target.Targets; import mage.util.Copier; @@ -57,7 +63,9 @@ public abstract class AbilityImpl implements Ability, Serializable { protected UUID id; protected UUID controllerId; protected UUID sourceId; + protected ManaCosts manaCosts = new ManaCosts(this); protected Costs costs = new CostsImpl(this); + protected List alternativeCosts = new ArrayList(); protected Targets targets = new Targets(this); protected Choices choices = new Choices(this); protected Effects effects = new Effects(this); @@ -88,7 +96,7 @@ public abstract class AbilityImpl implements Ability, Serializable { result &= effect.apply(game); } else { - game.addEffect((ContinuousEffectImpl) effect); + game.addEffect((ContinuousEffect) effect); } } } @@ -101,7 +109,21 @@ public abstract class AbilityImpl implements Ability, Serializable { return false; if (targets.size() > 0 && targets.choose(effects.get(0).getOutcome(), game) == false) return false; - return getCosts().pay(game, noMana); + if (!useAlternativeCost(game)) { + if (!manaCosts.pay(game, noMana)) + return false; + } + return costs.pay(game, noMana); + } + + protected boolean useAlternativeCost(Game game) { + for (AlternativeCost cost: alternativeCosts) { + if (cost.isAvailable(game)) { + if (game.getPlayer(this.controllerId).chooseUse(Outcome.Neutral, "Use alternative cost " + cost.getName(), game)) + return cost.pay(game, false); + } + } + return false; } @Override @@ -130,6 +152,16 @@ public abstract class AbilityImpl implements Ability, Serializable { return costs; } + @Override + public ManaCosts getManaCosts() { + return manaCosts; + } + + @Override + public List getAlternativeCosts() { + return alternativeCosts; + } + @Override public Effects getEffects() { return effects; @@ -150,10 +182,25 @@ public abstract class AbilityImpl implements Ability, Serializable { StringBuilder sbRule = new StringBuilder(); if (!(this instanceof SpellAbility)) { - if (!costs.getText().equals("")) { - sbRule.append(costs.getText()).append(": "); + if (manaCosts.size() > 0) { + sbRule.append(manaCosts.getText()); + } + if (costs.size() > 0) { + if (sbRule.length() > 0) { + sbRule.append(","); + } + sbRule.append(costs.getText()); + } + if (sbRule.length() > 0) { + sbRule.append(": "); } } + else if (this.alternativeCosts.size() > 0) { + for (AlternativeCost cost: alternativeCosts) { + sbRule.append(cost.getText()).append("\n"); + } + } + sbRule.append(effects.getText()); return sbRule.toString(); @@ -174,11 +221,6 @@ public abstract class AbilityImpl implements Ability, Serializable { this.enabled = enabled; } - @Override - public void handleEvent(GameEvent event, Game game) { - - } - @Override public void addCost(Cost cost) { if (cost != null) { @@ -187,6 +229,22 @@ public abstract class AbilityImpl implements Ability, Serializable { } } + @Override + public void addManaCost(ManaCost cost) { + if (cost != null) { + cost.setAbility(this); + this.manaCosts.add(cost); + } + } + + @Override + public void addAlternativeCost(AlternativeCost cost) { + if (cost != null) { + cost.setAbility(this); + this.alternativeCosts.add(cost); + } + } + @Override public void addEffect(Effect effect) { if (effect != null) { diff --git a/Mage/src/mage/abilities/ActivatedAbility.java b/Mage/src/mage/abilities/ActivatedAbility.java index c7eca46274..f6379bdd22 100644 --- a/Mage/src/mage/abilities/ActivatedAbility.java +++ b/Mage/src/mage/abilities/ActivatedAbility.java @@ -38,7 +38,6 @@ import mage.game.Game; public interface ActivatedAbility extends Ability { public boolean canActivate(UUID playerId, Game game); - public boolean isActivated(Game game); public String getActivatedMessage(Game game); } diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index dac656a982..b1700bcfde 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -32,6 +32,8 @@ import java.util.UUID; import mage.Constants.TimingRule; import mage.Constants.Zone; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.mana.ManaCosts; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.cards.Card; @@ -45,33 +47,82 @@ import mage.target.Target; public abstract class ActivatedAbilityImpl extends AbilityImpl implements ActivatedAbility { protected TimingRule timing = TimingRule.INSTANT; - protected UUID effectId; - public ActivatedAbilityImpl(Zone zone, Cost cost) { + public ActivatedAbilityImpl(Zone zone) { super(zone); + } + + public ActivatedAbilityImpl(Zone zone, Effect effect) { + super(zone); + if (effect != null) { + this.addEffect(effect); + } + } + + public ActivatedAbilityImpl(Zone zone, Effect effect, ManaCosts cost) { + super(zone); + if (effect != null) { + this.addEffect(effect); + } if (cost != null) - this.addCost(cost); + this.addManaCost(cost); + } + + public ActivatedAbilityImpl(Zone zone, Effects effects, ManaCosts cost) { + super(zone); + if (effects != null) { + for (Effect effect: effects) { + this.addEffect(effect); + } + } + if (cost != null) + this.addManaCost(cost); } public ActivatedAbilityImpl(Zone zone, Effect effect, Cost cost) { super(zone); if (effect != null) { this.addEffect(effect); - effectId = effect.getId(); } if (cost != null) this.addCost(cost); } + public ActivatedAbilityImpl(Zone zone, Effect effect, Costs costs) { + super(zone); + if (effect != null) { + this.addEffect(effect); + } + if (costs != null) { + for (Cost cost: costs) { + this.addCost(cost); + } + } + } + public ActivatedAbilityImpl(Zone zone, Effects effects, Cost cost) { + super(zone); + if (effects != null) { + for (Effect effect: effects) { + this.addEffect(effect); + } + } + if (cost != null) + this.addCost(cost); + } + + public ActivatedAbilityImpl(Zone zone, Effects effects, Costs costs) { super(zone); for (Effect effect: effects) { if (effect != null) { this.addEffect(effect); } } - if (cost != null) - this.addCost(cost); + if (costs != null) { + for (Cost cost: costs) { + this.addCost(cost); + } + } } @Override @@ -80,25 +131,12 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa if (!controlsAbility(playerId, game)) return false; //20091005 - 602.5d/602.5e - if (timing == TimingRule.INSTANT || (game.isMainPhase() && - game.getStack().isEmpty() && - game.getActivePlayerId().equals(playerId)) && - costs.canPay(playerId, game) && - targets.canChoose(sourceId, game) - ) { + if ((timing == TimingRule.INSTANT || game.canPlaySorcery(playerId)) && costs.canPay(playerId, game) && targets.canChoose(sourceId, game)) { return true; } return false; } - @Override - public boolean isActivated(Game game) { - - if (effectId != null) - return game.getContinuousEffects().effectExists(this.id); - return false; - } - protected boolean controlsAbility(UUID playerId, Game game) { if (this.controllerId != null && this.controllerId.equals(playerId)) return true; diff --git a/Mage/src/mage/abilities/PlayLandAbility.java b/Mage/src/mage/abilities/PlayLandAbility.java index 09c6a10ef0..346c5c763b 100644 --- a/Mage/src/mage/abilities/PlayLandAbility.java +++ b/Mage/src/mage/abilities/PlayLandAbility.java @@ -48,7 +48,7 @@ public class PlayLandAbility extends ActivatedAbilityImpl { if (!controlsAbility(playerId, game)) return false; //20091005 - 114.2a - if (game.getActivePlayerId().equals(playerId) && game.getStack().isEmpty() && game.isMainPhase()) { + if (game.canPlaySorcery(playerId)) { return game.getPlayer(playerId).canPlayLand(); } return false; diff --git a/Mage/src/mage/abilities/SpellAbility.java b/Mage/src/mage/abilities/SpellAbility.java index de385f7f24..d831b618ad 100644 --- a/Mage/src/mage/abilities/SpellAbility.java +++ b/Mage/src/mage/abilities/SpellAbility.java @@ -31,7 +31,7 @@ package mage.abilities; import java.util.UUID; import mage.Constants.CardType; import mage.Constants.Zone; -import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.ManaCost; import mage.game.Game; /** @@ -40,20 +40,18 @@ import mage.game.Game; */ public class SpellAbility extends ActivatedAbilityImpl { - public SpellAbility(Cost cost) { - super(Zone.HAND, cost); + public SpellAbility(ManaCost cost) { + super(Zone.HAND); + this.addManaCost(cost); this.name = "Cast"; } @Override public boolean canActivate(UUID playerId, Game game) { - if (game.getObject(sourceId).getCardType().contains(CardType.INSTANT) || - (game.isMainPhase() && - game.getStack().isEmpty() && - game.getActivePlayerId().equals(playerId)) && - costs.canPay(playerId, game) && - targets.canChoose(sourceId, game)) + if ((game.getObject(sourceId).getCardType().contains(CardType.INSTANT) || game.canPlaySorcery(playerId)) && + costs.canPay(playerId, game) && targets.canChoose(sourceId, game)) { return true; + } return false; } @@ -62,4 +60,11 @@ public class SpellAbility extends ActivatedAbilityImpl { return " casts " + getMessageText(game); } + public void clear() { + this.choices.clearChosen(); + this.targets.clearChosen(); + this.manaCosts.clearPaid(); + this.costs.clearPaid(); + } + } diff --git a/Mage/src/mage/abilities/TriggeredAbilities.java b/Mage/src/mage/abilities/TriggeredAbilities.java index c5ca3e6030..e324b69791 100644 --- a/Mage/src/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/mage/abilities/TriggeredAbilities.java @@ -29,6 +29,8 @@ package mage.abilities; import java.util.ArrayList; +import java.util.Iterator; +import java.util.UUID; import mage.game.Game; import mage.game.events.GameEvent; @@ -40,18 +42,28 @@ public class TriggeredAbilities extends ArrayList { public void handleEvent(GameEvent event, Game game) { for(TriggeredAbility ability: this) { - ability.handleEvent(event, game); + ability.checkTrigger(event, game); } } - public boolean check(Game game) { - boolean played = false; +// public boolean check(Game game) { +// boolean played = false; +// Iterator it = this.iterator(); +// while(it.hasNext()) { +// TriggeredAbility ability = it.next(); +// it.remove(); +// played |= game.getPlayer(ability.getControllerId()).triggerAbility(ability, game); +// } +// return played; +// } + + public TriggeredAbilities getControlledBy(UUID controllerId) { + TriggeredAbilities controlledBy = new TriggeredAbilities(); for (TriggeredAbility ability: this) { - played |= game.getPlayer(ability.getControllerId()).triggerAbility(ability, game); + if (ability.getControllerId().equals(controllerId)) + controlledBy.add(ability); } - clear(); - return played; + return controlledBy; } - } diff --git a/Mage/src/mage/abilities/TriggeredAbility.java b/Mage/src/mage/abilities/TriggeredAbility.java index b9304febd2..e5e77ba93d 100644 --- a/Mage/src/mage/abilities/TriggeredAbility.java +++ b/Mage/src/mage/abilities/TriggeredAbility.java @@ -30,6 +30,7 @@ package mage.abilities; import java.util.UUID; import mage.game.Game; +import mage.game.events.GameEvent; /** * @@ -38,5 +39,7 @@ import mage.game.Game; public interface TriggeredAbility extends Ability { public void trigger(Game game, UUID controllerId); - + public void checkTrigger(GameEvent event, Game game); + public boolean checkIfClause(Game game); + } diff --git a/Mage/src/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/mage/abilities/TriggeredAbilityImpl.java index 7f34a8907d..6de639bd64 100644 --- a/Mage/src/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/mage/abilities/TriggeredAbilityImpl.java @@ -29,7 +29,6 @@ package mage.abilities; import java.util.UUID; -import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.effects.Effect; import mage.game.Game; @@ -57,8 +56,16 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge @Override public void trigger(Game game, UUID controllerId) { - this.controllerId = controllerId; - game.addTriggeredAbility(this); + //20091005 - 603.4 + if (checkIfClause(game)) { + this.controllerId = controllerId; + game.addTriggeredAbility(this); + } + } + + @Override + public boolean checkIfClause(Game game) { + return true; } @Override @@ -70,6 +77,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge return false; } } - return super.resolve(game); + //20091005 - 603.4 + if (checkIfClause(game)) + return super.resolve(game); + return false; } } diff --git a/Mage/src/mage/abilities/common/ActivateOncePerTurnActivatedAbility.java b/Mage/src/mage/abilities/common/ActivateOncePerTurnActivatedAbility.java index a9761f4579..337d48f1ee 100644 --- a/Mage/src/mage/abilities/common/ActivateOncePerTurnActivatedAbility.java +++ b/Mage/src/mage/abilities/common/ActivateOncePerTurnActivatedAbility.java @@ -32,6 +32,7 @@ import java.util.UUID; import mage.Constants.Zone; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; import mage.abilities.effects.Effect; import mage.game.Game; @@ -41,13 +42,17 @@ import mage.game.Game; */ public class ActivateOncePerTurnActivatedAbility extends ActivatedAbilityImpl { + protected UUID effectId; + public ActivateOncePerTurnActivatedAbility(Zone zone, Effect effect, Cost cost) { super(zone, effect, cost); + effectId = effect.getId(); } @Override public boolean canActivate(UUID playerId, Game game) { - if (isActivated(game)) + //assumes that ability creates a continuous effect + if (game.getContinuousEffects().effectExists(this.id)) return false; return super.canActivate(playerId, game); } diff --git a/Mage/src/mage/abilities/common/AsRequiredTriggeredAbility.java b/Mage/src/mage/abilities/common/AsRequiredTriggeredAbility.java index 0c5d1124ac..3bce6ad4ca 100644 --- a/Mage/src/mage/abilities/common/AsRequiredTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/AsRequiredTriggeredAbility.java @@ -1,50 +1,50 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - -package mage.abilities.common; - -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.game.Game; -import mage.game.events.GameEvent; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class AsRequiredTriggeredAbility extends TriggeredAbilityImpl { - - public AsRequiredTriggeredAbility(Effect effect) { - super(null, effect); - - } - - @Override - public void handleEvent(GameEvent event, Game game) { - } -} +///* +//* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +//* +//* Redistribution and use in source and binary forms, with or without modification, are +//* permitted provided that the following conditions are met: +//* +//* 1. Redistributions of source code must retain the above copyright notice, this list of +//* conditions and the following disclaimer. +//* +//* 2. Redistributions in binary form must reproduce the above copyright notice, this list +//* of conditions and the following disclaimer in the documentation and/or other materials +//* provided with the distribution. +//* +//* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +//* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +//* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +//* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +//* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +//* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//* +//* The views and conclusions contained in the software and documentation are those of the +//* authors and should not be interpreted as representing official policies, either expressed +//* or implied, of BetaSteward_at_googlemail.com. +//*/ +// +//package mage.abilities.common; +// +//import mage.abilities.TriggeredAbilityImpl; +//import mage.abilities.effects.Effect; +//import mage.game.Game; +//import mage.game.events.GameEvent; +// +///** +// * +// * @author BetaSteward_at_googlemail.com +// */ +//public class AsRequiredTriggeredAbility extends TriggeredAbilityImpl { +// +// public AsRequiredTriggeredAbility(Effect effect) { +// super(null, effect); +// +// } +// +// @Override +// public void handleEvent(GameEvent event, Game game) { +// } +//} diff --git a/Mage/src/mage/abilities/common/AttacksTriggeredAbility.java b/Mage/src/mage/abilities/common/AttacksTriggeredAbility.java index 24032b5a59..d2f47dd6d5 100644 --- a/Mage/src/mage/abilities/common/AttacksTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/AttacksTriggeredAbility.java @@ -46,7 +46,7 @@ public class AttacksTriggeredAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId()) ) { trigger(game, this.controllerId); } diff --git a/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java index 3abc862fe6..5b3547e8a7 100644 --- a/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/EntersBattlefieldTriggeredAbility.java @@ -47,7 +47,7 @@ public class EntersBattlefieldTriggeredAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId()) ) { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getToZone() == Zone.BATTLEFIELD) diff --git a/Mage/src/mage/abilities/common/LandfallAbility.java b/Mage/src/mage/abilities/common/LandfallAbility.java index 141b241a6e..6d576fef23 100644 --- a/Mage/src/mage/abilities/common/LandfallAbility.java +++ b/Mage/src/mage/abilities/common/LandfallAbility.java @@ -49,7 +49,7 @@ public class LandfallAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).getToZone() == Zone.BATTLEFIELD) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null && permanent.getCardType().contains(CardType.LAND) && permanent.getControllerId().equals(this.controllerId)) diff --git a/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java index 70b0106bfc..113f44b86a 100644 --- a/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/LeavesBattlefieldTriggeredAbility.java @@ -47,7 +47,7 @@ public class LeavesBattlefieldTriggeredAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId()) ) { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getFromZone() == Zone.BATTLEFIELD) diff --git a/Mage/src/mage/abilities/common/OnEventTriggeredAbility.java b/Mage/src/mage/abilities/common/OnEventTriggeredAbility.java index b795fa1d60..e2687d95ef 100644 --- a/Mage/src/mage/abilities/common/OnEventTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/OnEventTriggeredAbility.java @@ -59,7 +59,7 @@ public class OnEventTriggeredAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == eventType) { if (allPlayers || event.getPlayerId().equals(this.controllerId) ) { trigger(game, this.controllerId); diff --git a/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java index 0ac52019d3..7b12e5e0f4 100644 --- a/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/PutIntoGraveFromBattlefieldTriggeredAbility.java @@ -47,7 +47,7 @@ public class PutIntoGraveFromBattlefieldTriggeredAbility extends TriggeredAbilit } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId()) ) { ZoneChangeEvent zEvent = (ZoneChangeEvent)event; if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) diff --git a/Mage/src/mage/abilities/common/SimpleActivatedAbility.java b/Mage/src/mage/abilities/common/SimpleActivatedAbility.java index add350c1ca..a0b262680d 100644 --- a/Mage/src/mage/abilities/common/SimpleActivatedAbility.java +++ b/Mage/src/mage/abilities/common/SimpleActivatedAbility.java @@ -31,6 +31,8 @@ package mage.abilities.common; import mage.Constants.Zone; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.mana.ManaCosts; import mage.abilities.effects.Effect; /** @@ -39,8 +41,16 @@ import mage.abilities.effects.Effect; */ public class SimpleActivatedAbility extends ActivatedAbilityImpl { + public SimpleActivatedAbility(Zone zone, Effect effect, ManaCosts cost) { + super(zone, effect, cost); + } + + public SimpleActivatedAbility(Zone zone, Effect effect, Costs costs) { + super(zone, effect, costs); + } + public SimpleActivatedAbility(Zone zone, Effect effect, Cost cost) { super(zone, effect, cost); } - + } diff --git a/Mage/src/mage/abilities/common/SimpleTriggeredAbility.java b/Mage/src/mage/abilities/common/SimpleTriggeredAbility.java index 977d4e5028..bb722456b9 100644 --- a/Mage/src/mage/abilities/common/SimpleTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/SimpleTriggeredAbility.java @@ -49,7 +49,7 @@ public class SimpleTriggeredAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == eventType) { trigger(game, event.getPlayerId()); } diff --git a/Mage/src/mage/abilities/costs/AbilityCosts.java b/Mage/src/mage/abilities/costs/AbilityCosts.java new file mode 100644 index 0000000000..ed65d6d275 --- /dev/null +++ b/Mage/src/mage/abilities/costs/AbilityCosts.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.costs; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import mage.abilities.costs.mana.ManaCosts; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class AbilityCosts implements Serializable { + + + +} diff --git a/Mage/src/mage/abilities/costs/AbstractCosts.java b/Mage/src/mage/abilities/costs/AbstractCosts.java deleted file mode 100644 index 6be8cf9078..0000000000 --- a/Mage/src/mage/abilities/costs/AbstractCosts.java +++ /dev/null @@ -1,135 +0,0 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - -package mage.abilities.costs; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.costs.mana.ManaCosts; -import mage.game.Game; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public abstract class AbstractCosts extends ArrayList implements Costs { - - private Ability ability; - - public AbstractCosts(Ability ability) { - this.ability = ability; - } - - @Override - public String getText() { - if (this.size() == 0) - return ""; - - StringBuilder sbText = new StringBuilder(); - for (T cost: this) { - sbText.append(cost.getText()).append(", "); - } - sbText.setLength(sbText.length() - 2); - return sbText.toString(); - } - - @Override - public boolean canPay(UUID playerId, Game game) { - for (Cost cost: this) { - if (!cost.canPay(playerId, game)) - return false; - } - return true; - } - - @Override - public boolean pay(Game game, boolean noMana) { - if (this.size() > 0) { - while (!isPaid()) { - Cost cost = getFirstUnpaid(); - if (!cost.pay(game, noMana)) - return false; - } - } - return true; - } - - @Override - public boolean isPaid() { - for (T cost: this) { - if (!cost.isPaid()) - return false; - } - return true; - } - - @Override - public void clearPaid() { - for (T cost: this) { - cost.clearPaid(); - } - } - - @Override - public Ability getAbility() { - return ability; - } - - @Override - public void setAbility(Ability ability) { - this.ability = ability; - for (T cost: this) { - cost.setAbility(ability); - } - } - - @Override - public boolean add(T cost) { - cost.setAbility(ability); - return super.add(cost); - } - - @Override - public List getUnpaid() { - List unpaid = new ArrayList(); - for (T cost: this) { - if (!cost.isPaid()) - unpaid.add(cost); - } - return unpaid; - } - - protected T getFirstUnpaid() { - if (this.size() > 0) { - return this.get(0); - } - return null; - } -} diff --git a/Mage/src/mage/abilities/costs/AlternativeCost.java b/Mage/src/mage/abilities/costs/AlternativeCost.java new file mode 100644 index 0000000000..f8076f33d5 --- /dev/null +++ b/Mage/src/mage/abilities/costs/AlternativeCost.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.costs; + +import mage.game.Game; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class AlternativeCost extends CostsImpl { + + protected String name; + + public AlternativeCost(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public boolean isAvailable(Game game) { + return true; + } +} diff --git a/Mage/src/mage/abilities/costs/Costs.java b/Mage/src/mage/abilities/costs/Costs.java index 6e1b3e3b19..ab09196617 100644 --- a/Mage/src/mage/abilities/costs/Costs.java +++ b/Mage/src/mage/abilities/costs/Costs.java @@ -29,15 +29,11 @@ package mage.abilities.costs; import java.util.List; -import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.costs.mana.VariableManaCost; public interface Costs extends List, Cost { @Override public boolean add(T cost); public List getUnpaid(); - public List getVariableCosts(); - public ManaCosts getManaCosts(); } diff --git a/Mage/src/mage/abilities/costs/CostsImpl.java b/Mage/src/mage/abilities/costs/CostsImpl.java index 5e23d07894..3b77756f01 100644 --- a/Mage/src/mage/abilities/costs/CostsImpl.java +++ b/Mage/src/mage/abilities/costs/CostsImpl.java @@ -29,11 +29,8 @@ package mage.abilities.costs; import java.util.ArrayList; -import java.util.List; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.costs.mana.ManaCost; -import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.VariableManaCost; import mage.game.Game; @@ -145,23 +142,23 @@ public class CostsImpl extends ArrayList implements Costs return null; } - @Override - public ManaCosts getManaCosts() { - ManaCosts manaCosts = new ManaCosts(ability); - for (T cost: this) { - if (cost instanceof ManaCost) - manaCosts.add((ManaCost)cost); - } - return manaCosts; - } - - @Override - public List getVariableCosts() { - List variableCosts = new ArrayList(); - for (T cost: this) { - if (cost instanceof ManaCosts) - variableCosts.addAll(((ManaCosts)cost).getVariableCosts()); - } - return variableCosts; - } +// @Override +// public ManaCosts getManaCosts() { +// ManaCosts manaCosts = new ManaCosts(ability); +// for (T cost: this) { +// if (cost instanceof ManaCost) +// manaCosts.add((ManaCost)cost); +// } +// return manaCosts; +// } +// +// @Override +// public List getVariableCosts() { +// List variableCosts = new ArrayList(); +// for (T cost: this) { +// if (cost instanceof ManaCosts) +// variableCosts.addAll(((ManaCosts)cost).getVariableCosts()); +// } +// return variableCosts; +// } } diff --git a/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java b/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java new file mode 100644 index 0000000000..b4d7530d01 --- /dev/null +++ b/Mage/src/mage/abilities/costs/common/DiscardSourceCost.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.costs.common; + +import java.util.UUID; +import mage.abilities.costs.CostImpl; +import mage.cards.Card; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DiscardSourceCost extends CostImpl { + + @Override + public boolean canPay(UUID playerId, Game game) { + return game.getPlayer(playerId).getHand().containsKey(this.ability.getSourceId()); + } + + @Override + public boolean pay(Game game, boolean noMana) { + Player player = game.getPlayer(this.ability.getControllerId()); + Card card = player.getHand().get(this.ability.getSourceId()); + return player.discard(card, game); + } + + @Override + public String getText() { + return "Discard {this}"; + } +} diff --git a/Mage/src/mage/abilities/costs/common/PayLifeCost.java b/Mage/src/mage/abilities/costs/common/PayLifeCost.java index 6b5754bc68..e5201ff094 100644 --- a/Mage/src/mage/abilities/costs/common/PayLifeCost.java +++ b/Mage/src/mage/abilities/costs/common/PayLifeCost.java @@ -41,17 +41,18 @@ public class PayLifeCost extends CostImpl { private int amount; public PayLifeCost(int amount) { -// super(ability); this.amount = amount; this.text = "Pay " + Integer.toString(amount) + " life"; } + @Override public boolean canPay(UUID playerId, Game game) { if (ability.getControllerId().equals(playerId)) return game.getPlayer(playerId).getLife() >= amount; return false; } + @Override public boolean pay(Game game, boolean noMana) { this.paid = game.getPlayer(ability.getControllerId()).loseLife(amount, game) == amount; return paid; diff --git a/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java b/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java new file mode 100644 index 0000000000..5c5b88d113 --- /dev/null +++ b/Mage/src/mage/abilities/costs/common/RemoveCountersSourceCost.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.costs.common; + +import java.util.UUID; +import mage.abilities.costs.CostImpl; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class RemoveCountersSourceCost extends CostImpl { + + private int amount; + private String name; + + public RemoveCountersSourceCost(String name, int amount) { + this.amount = amount; + this.name = name; + this.text = "Remove " + amount + " " + name + " counters from {this}"; + } + + @Override + public boolean canPay(UUID playerId, Game game) { + Permanent source = game.getPermanent(this.ability.getSourceId()); + if (source.getCounters().getCount(name) >= amount) + return true; + return false; + } + + @Override + public boolean pay(Game game, boolean noMana) { + Permanent source = game.getPermanent(this.ability.getSourceId()); + if (source.getCounters().getCount(name) >= amount) { + source.getCounters().removeCounter(name, amount); + this.paid = true; + } + return paid; + } +} diff --git a/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java b/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java index 4d6c892e56..c96c47facb 100644 --- a/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/SacrificeSourceCost.java @@ -52,6 +52,7 @@ public class SacrificeSourceCost extends CostImpl { return paid; } + @Override public boolean canPay(UUID playerId, Game game) { Permanent source = game.getPermanent(ability.getSourceId()); if (source != null) { diff --git a/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java new file mode 100644 index 0000000000..3a0f6d75c5 --- /dev/null +++ b/Mage/src/mage/abilities/costs/common/SacrificeTargetCost.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.costs.common; + +import java.util.UUID; +import mage.Constants.Outcome; +import mage.abilities.costs.CostImpl; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class SacrificeTargetCost extends CostImpl { + + public Target target; + + public SacrificeTargetCost(Target target) { + this.target = target; + this.text = "Sacrifice " + target.getTargetName(); + } + + @Override + public boolean pay(Game game, boolean noMana) { + target.setAbility(ability); + if (target.choose(Outcome.Sacrifice, game)) { + Permanent source = game.getPermanent(target.getFirstTarget()); + if (source != null) { + paid = source.sacrifice(this.ability.getSourceId(), game); + } + } + return paid; + } + + @Override + public boolean canPay(UUID playerId, Game game) { + return target.canChoose(playerId, game); + } + +} diff --git a/Mage/src/mage/abilities/costs/common/TapSourceCost.java b/Mage/src/mage/abilities/costs/common/TapSourceCost.java index ba8b43c276..4ee099a0e3 100644 --- a/Mage/src/mage/abilities/costs/common/TapSourceCost.java +++ b/Mage/src/mage/abilities/costs/common/TapSourceCost.java @@ -29,7 +29,6 @@ package mage.abilities.costs.common; import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.game.Game; @@ -54,6 +53,7 @@ public class TapSourceCost extends CostImpl { return paid; } + @Override public boolean canPay(UUID playerId, Game game) { Permanent source = game.getPermanent(ability.getSourceId()); if (source != null) { @@ -62,9 +62,4 @@ public class TapSourceCost extends CostImpl { return false; } - @Override - public void setAbility(Ability ability) { - this.ability = ability; - } - } diff --git a/Mage/src/mage/abilities/costs/mana/ManaCosts.java b/Mage/src/mage/abilities/costs/mana/ManaCosts.java index 78d57c1507..6563f003d3 100644 --- a/Mage/src/mage/abilities/costs/mana/ManaCosts.java +++ b/Mage/src/mage/abilities/costs/mana/ManaCosts.java @@ -59,6 +59,19 @@ public class ManaCosts extends CostsImpl implements Costs, M load(mana); } + @Override + public boolean add(ManaCost cost) { + if (cost instanceof ManaCosts) { + for (ManaCost manaCost: (ManaCosts)cost) { + super.add(manaCost); + } + return true; + } + else { + return super.add(cost); + } + } + @Override public int convertedManaCost() { int total = 0; @@ -79,7 +92,7 @@ public class ManaCosts extends CostsImpl implements Costs, M @Override public boolean pay(Game game, boolean noMana) { - if (noMana) { + if (this.size() == 0 || noMana) { setPaid(); return true; } @@ -122,7 +135,6 @@ public class ManaCosts extends CostsImpl implements Costs, M return unpaid; } - @Override public List getVariableCosts() { List variableCosts = new ArrayList(); for (ManaCost cost: this) { @@ -135,6 +147,7 @@ public class ManaCosts extends CostsImpl implements Costs, M @Override public void assignPayment(ManaPool pool) { //attempt to pay colored costs first + for (ManaCost cost: this) { if (!cost.isPaid() && cost instanceof ColoredManaCost) { cost.assignPayment(pool); @@ -217,6 +230,7 @@ public class ManaCosts extends CostsImpl implements Costs, M return sbText.toString(); } + @Override public ManaOptions getOptions() { ManaOptions options = new ManaOptions(); for (ManaCost cost: this) { @@ -225,6 +239,7 @@ public class ManaCosts extends CostsImpl implements Costs, M return options; } + @Override public boolean testPay(Mana testMana) { for (ManaCost cost: this) { if (cost.testPay(testMana)) diff --git a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java index 7249a417bd..66d8d75029 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffectImpl.java @@ -71,16 +71,6 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu return false; } -// @Override -// public Layer getLayer() { -// return layer; -// } -// -// @Override -// public SubLayer getSubLayer() { -// return sublayer; -// } - @Override public Date getTimestamp() { return timestamp; diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index f7479418aa..5175d6cb64 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -67,7 +67,7 @@ public class ContinuousEffects implements Serializable { public void removeInactiveEffects(Game game) { for (Iterator i = effects.iterator(); i.hasNext();) { ContinuousEffect entry = i.next(); - if (entry.getDuration() == Duration.WhileInPlay) { + if (entry.getDuration() == Duration.WhileOnBattlefield) { Permanent permanent = (Permanent)game.getPermanent(entry.getSource().getSourceId()); if (permanent == null || !permanent.isPhasedIn()) i.remove(); diff --git a/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java b/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java index c87beb4044..6c447c600c 100644 --- a/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java +++ b/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java @@ -47,7 +47,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl { protected Effects baseEffects = new Effects(null); public EntersBattlefieldEffect(Effect baseEffect) { - super(Duration.OneShot, baseEffect.getOutcome()); + super(Duration.WhileOnBattlefield, baseEffect.getOutcome()); this.baseEffects.add(baseEffect); } diff --git a/Mage/src/mage/abilities/effects/PreventionEffectImpl.java b/Mage/src/mage/abilities/effects/PreventionEffectImpl.java new file mode 100644 index 0000000000..bd79b2d0e6 --- /dev/null +++ b/Mage/src/mage/abilities/effects/PreventionEffectImpl.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects; + +import mage.Constants.Duration; +import mage.Constants.Outcome; +import mage.game.Game; +import mage.game.events.GameEvent; + + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public abstract class PreventionEffectImpl extends ReplacementEffectImpl { + + + public PreventionEffectImpl(Duration duration) { + super(duration, Outcome.PreventDamage); + } + + @Override + public boolean applies(GameEvent event, Game game) { + switch (event.getType()) { + case DAMAGE_CREATURE: + case DAMAGE_PLAYER: + case DAMAGE_PLANESWALKER: + return true; + default: + return false; + } + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/AddCountersSourceEffect.java b/Mage/src/mage/abilities/effects/common/AddCountersSourceEffect.java new file mode 100644 index 0000000000..81d156d2b5 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/AddCountersSourceEffect.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.effects.OneShotEffect; +import mage.counters.Counter; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class AddCountersSourceEffect extends OneShotEffect { + + private int amount; + private String name; + + public AddCountersSourceEffect(String name, int amount) { + super(Outcome.Benefit); + this.name = name; + this.amount = amount; + } + + @Override + public boolean apply(Game game) { + Permanent permanent = game.getPermanent(this.source.getSourceId()); + if (permanent != null) { + Counter counter = new Counter(name); + counter.add(amount); + permanent.getCounters().addCounter(counter); + } + return true; + } + + @Override + public String getText() { + if (amount > 1) { + StringBuilder sb = new StringBuilder(); + sb.append("put ").append(Integer.toString(amount)).append(" ").append(name).append("counters on {this}"); + return sb.toString(); + } + else + return "put a " + name + " counter on {this}"; + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java new file mode 100644 index 0000000000..6257388e5b --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/AddManaOfAnyColorEffect.java @@ -0,0 +1,87 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.Mana; +import mage.abilities.effects.OneShotEffect; +import mage.choices.ChoiceColor; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class AddManaOfAnyColorEffect extends OneShotEffect { + + int amount; + + public AddManaOfAnyColorEffect(int amount) { + super(Outcome.PutManaInPool); + this.amount = amount; + } + + @Override + public boolean apply(Game game) { + ChoiceColor choice = (ChoiceColor) this.source.getChoices().get(0); + Player player = game.getPlayer(this.source.getControllerId()); + if (choice.getColor().isBlack()) { + player.getManaPool().changeMana(Mana.BlackMana); + return true; + } + else if (choice.getColor().isBlue()) { + player.getManaPool().changeMana(Mana.BlueMana); + return true; + } + else if (choice.getColor().isRed()) { + player.getManaPool().changeMana(Mana.RedMana); + return true; + } + else if (choice.getColor().isGreen()) { + player.getManaPool().changeMana(Mana.GreenMana); + return true; + } + else if (choice.getColor().isWhite()) { + player.getManaPool().changeMana(Mana.WhiteMana); + return true; + } + return false; + } + + @Override + public String getText() { + if (amount > 1) + return "add " + Integer.toString(amount) + " mana of any color to your mana pool"; + else + return "add one mana of any color to your mana pool"; + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/BoostControlledEOTEffect.java b/Mage/src/mage/abilities/effects/common/BoostControlledEOTEffect.java deleted file mode 100644 index 4df23af89c..0000000000 --- a/Mage/src/mage/abilities/effects/common/BoostControlledEOTEffect.java +++ /dev/null @@ -1,69 +0,0 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - -package mage.abilities.effects.common; - -import mage.Constants.CardType; -import mage.Constants.Duration; -import mage.Constants.Layer; -import mage.Constants.Outcome; -import mage.Constants.SubLayer; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class BoostControlledEOTEffect extends ContinuousEffectImpl { - - private int power; - private int toughness; - - public BoostControlledEOTEffect(int power, int toughness) { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - this.power = power; - this.toughness = toughness; - } - - @Override - public boolean apply(Game game) { - for (Permanent perm: game.getBattlefield().getActivePermanents(this.source.getControllerId(), CardType.CREATURE)) { - perm.addPower(power); - perm.addToughness(toughness); - } - return true; - } - - @Override - public String getText() { - return "Creatures you control get " + String.format("%1$+d/%2$+d", power, toughness) + " until end of turn."; - } - -} diff --git a/Mage/src/mage/abilities/effects/common/BoostControlledEffect.java b/Mage/src/mage/abilities/effects/common/BoostControlledEffect.java index 247b1784ca..c37db12885 100644 --- a/Mage/src/mage/abilities/effects/common/BoostControlledEffect.java +++ b/Mage/src/mage/abilities/effects/common/BoostControlledEffect.java @@ -49,7 +49,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl { protected FilterCreaturePermanent filter; public BoostControlledEffect(int power, int toughness, Duration duration) { - this(power, toughness, duration, null); + this(power, toughness, duration, new FilterCreaturePermanent()); } public BoostControlledEffect(int power, int toughness, Duration duration, FilterCreaturePermanent filter) { @@ -61,19 +61,11 @@ public class BoostControlledEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game) { - if (filter != null) { - filter.getControllerId().clear(); - filter.getControllerId().add(this.source.getControllerId()); - for (Permanent perm: game.getBattlefield().getActivePermanents(filter)) { - perm.addPower(power); - perm.addToughness(toughness); - } - } - else { - for (Permanent perm: game.getBattlefield().getActivePermanents(this.source.getControllerId(), CardType.CREATURE)) { - perm.addPower(power); - perm.addToughness(toughness); - } + filter.getControllerId().clear(); + filter.getControllerId().add(this.source.getControllerId()); + for (Permanent perm: game.getBattlefield().getActivePermanents(filter)) { + perm.addPower(power); + perm.addToughness(toughness); } return true; } @@ -81,10 +73,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl { @Override public String getText() { StringBuilder sb = new StringBuilder(); - if (filter == null) - sb.append("Creatures"); - else - sb.append(filter.getMessage()); + sb.append(filter.getMessage()); sb.append(" you control get ").append(String.format("%1$+d/%2$+d", power, toughness)); sb.append((duration==Duration.EndOfTurn?" until end of turn":"")); return sb.toString(); diff --git a/Mage/src/mage/abilities/effects/common/BoostEquippedEffect.java b/Mage/src/mage/abilities/effects/common/BoostEquippedEffect.java new file mode 100644 index 0000000000..ccb728e005 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/BoostEquippedEffect.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.CardType; +import mage.Constants.Duration; +import mage.Constants.Layer; +import mage.Constants.Outcome; +import mage.Constants.SubLayer; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class BoostEquippedEffect extends ContinuousEffectImpl { + + private int power; + private int toughness; + + public BoostEquippedEffect(int power, int toughness) { + super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); + this.power = power; + this.toughness = toughness; + } + + @Override + public boolean apply(Game game) { + Permanent equipment = game.getPermanent(this.source.getSourceId()); + if (equipment.getAttachedTo() != null) { + Permanent creature = game.getPermanent(equipment.getAttachedTo()); + if (creature != null) { + creature.addPower(power); + creature.addToughness(toughness); + } + } + return true; + } + + @Override + public String getText() { + return "Equipped creatures gets " + String.format("%1$+d/%2$+d", power, toughness); + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/BoostSourceEOTEffect.java b/Mage/src/mage/abilities/effects/common/BoostSourceEffect.java similarity index 90% rename from Mage/src/mage/abilities/effects/common/BoostSourceEOTEffect.java rename to Mage/src/mage/abilities/effects/common/BoostSourceEffect.java index ea2298453f..ad3bf92068 100644 --- a/Mage/src/mage/abilities/effects/common/BoostSourceEOTEffect.java +++ b/Mage/src/mage/abilities/effects/common/BoostSourceEffect.java @@ -40,13 +40,13 @@ import mage.game.permanent.Permanent; * * @author BetaSteward_at_googlemail.com */ -public class BoostSourceEOTEffect extends ContinuousEffectImpl { +public class BoostSourceEffect extends ContinuousEffectImpl { private int power; private int toughness; - public BoostSourceEOTEffect(int power, int toughness) { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); + public BoostSourceEffect(int power, int toughness, Duration duration) { + super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); this.power = power; this.toughness = toughness; } @@ -64,7 +64,7 @@ public class BoostSourceEOTEffect extends ContinuousEffectImpl { @Override public String getText() { - return "{this} gets " + String.format("%1$+d/%2$+d", power, toughness) + " until end of turn"; + return "{this} gets " + String.format("%1$+d/%2$+d", power, toughness) + " " + duration.toString(); } } diff --git a/Mage/src/mage/abilities/effects/common/BoostSourceWhileControlsEffect.java b/Mage/src/mage/abilities/effects/common/BoostSourceWhileControlsEffect.java index 4b6c6d1963..a4f2ee87c9 100644 --- a/Mage/src/mage/abilities/effects/common/BoostSourceWhileControlsEffect.java +++ b/Mage/src/mage/abilities/effects/common/BoostSourceWhileControlsEffect.java @@ -47,7 +47,7 @@ public class BoostSourceWhileControlsEffect extends WhileControlsContinuousEffec private int toughness; public BoostSourceWhileControlsEffect(FilterPermanent filter, int power, int toughness) { - super(Duration.WhileInPlay, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, filter, Outcome.BoostCreature); + super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, filter, Outcome.BoostCreature); this.power = power; this.toughness = toughness; } diff --git a/Mage/src/mage/abilities/effects/common/BoostTargetEffect.java b/Mage/src/mage/abilities/effects/common/BoostTargetEffect.java new file mode 100644 index 0000000000..6826122d8b --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/BoostTargetEffect.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Duration; +import mage.Constants.Layer; +import mage.Constants.Outcome; +import mage.Constants.SubLayer; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class BoostTargetEffect extends ContinuousEffectImpl { + + private int power; + private int toughness; + + public BoostTargetEffect(int power, int toughness, Duration duration) { + super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); + this.power = power; + this.toughness = toughness; + } + + @Override + public boolean apply(Game game) { + Permanent target = (Permanent) game.getPermanent(this.source.getFirstTarget()); + if (target != null) { + target.addPower(power); + target.addToughness(toughness); + return true; + } + return false; + } + + @Override + public String getText() { + StringBuilder sb = new StringBuilder(); + sb.append("target ").append(this.source.getTargets().get(0).getTargetName()).append(" gets "); + sb.append(String.format("%1$+d/%2$+d", power, toughness)).append(" ").append(duration.toString()); + return sb.toString(); + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java b/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java index 2e1a317902..930bb5b7b6 100644 --- a/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantCounterControlledEffect.java @@ -47,7 +47,7 @@ public class CantCounterControlledEffect extends ReplacementEffectImpl { private FilterSpell filter; public CantCounterControlledEffect(FilterSpell filter) { - super(Duration.OneShot, Outcome.Benefit); + super(Duration.WhileOnStack, Outcome.Benefit); this.filter = filter; } diff --git a/Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java b/Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java index 92c270ee85..41f6fdb99a 100644 --- a/Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantCounterSourceEffect.java @@ -42,17 +42,20 @@ import mage.game.events.GameEvent.EventType; public class CantCounterSourceEffect extends ReplacementEffectImpl { public CantCounterSourceEffect() { - super(Duration.OneShot, Outcome.Benefit); + super(Duration.WhileOnStack, Outcome.Benefit); } + @Override public boolean apply(Game game) { return true; } + @Override public boolean replaceEvent(GameEvent event, Game game) { return true; } + @Override public boolean applies(GameEvent event, Game game) { if (event.getType() == EventType.COUNTER && event.getTargetId().equals(source.getSourceId())) return true; diff --git a/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java b/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java index 3cdd33f472..b45fbd6b0c 100644 --- a/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java @@ -42,6 +42,7 @@ public class CounterTargetEffect extends OneShotEffect { super(Outcome.Detriment); } + @Override public boolean apply(Game game) { return game.getStack().counter(this.source.getFirstTarget(), source.getSourceId(), game); } diff --git a/Mage/src/mage/abilities/effects/common/DrawCardAllEffect.java b/Mage/src/mage/abilities/effects/common/DrawCardAllEffect.java new file mode 100644 index 0000000000..75ba0f7c23 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/DrawCardAllEffect.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DrawCardAllEffect extends OneShotEffect { + + protected int amount; + + public DrawCardAllEffect(int amount) { + super(Outcome.DrawCard); + this.amount = amount; + } + + @Override + public boolean apply(Game game) { + + for (Player player: game.getPlayers().values()) { + player.drawCards(amount, game); + } + return true; + } + + @Override + public String getText() { + return "Each player draws " + Integer.toString(amount) + " card" + (amount == 1?"":"s"); + } + +} diff --git a/Mage/src/mage/abilities/effects/common/DrawCardTargetEffect.java b/Mage/src/mage/abilities/effects/common/DrawCardTargetEffect.java new file mode 100644 index 0000000000..41b9f2eca8 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/DrawCardTargetEffect.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DrawCardTargetEffect extends OneShotEffect { + + protected int amount; + + public DrawCardTargetEffect(int amount) { + super(Outcome.DrawCard); + this.amount = amount; + } + + @Override + public boolean apply(Game game) { + Player player = game.getPlayer(this.source.getFirstTarget()); + if (player != null) { + player.drawCards(amount, game); + return true; + } + return false; + } + + @Override + public String getText() { + return "Target player draws " + Integer.toString(amount) + " card" + (amount == 1?"":"s"); + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/GainAbilityControlledEOTEffect.java b/Mage/src/mage/abilities/effects/common/GainAbilityControlledEffect.java similarity index 72% rename from Mage/src/mage/abilities/effects/common/GainAbilityControlledEOTEffect.java rename to Mage/src/mage/abilities/effects/common/GainAbilityControlledEffect.java index 2812388ac8..574557f855 100644 --- a/Mage/src/mage/abilities/effects/common/GainAbilityControlledEOTEffect.java +++ b/Mage/src/mage/abilities/effects/common/GainAbilityControlledEffect.java @@ -28,13 +28,13 @@ package mage.abilities.effects.common; -import mage.Constants.CardType; import mage.Constants.Duration; import mage.Constants.Layer; import mage.Constants.Outcome; import mage.Constants.SubLayer; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; +import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -42,18 +42,26 @@ import mage.game.permanent.Permanent; * * @author BetaSteward_at_googlemail.com */ -public class GainAbilityControlledEOTEffect extends ContinuousEffectImpl { +public class GainAbilityControlledEffect extends ContinuousEffectImpl { protected Ability ability; + protected FilterPermanent permanentFilter; - public GainAbilityControlledEOTEffect(Ability ability) { - super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + public GainAbilityControlledEffect(Ability ability, Duration duration) { + this(ability, duration, new FilterPermanent()); + } + + public GainAbilityControlledEffect(Ability ability, Duration duration, FilterPermanent filter) { + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.ability = ability; + this.permanentFilter = filter; } @Override public boolean apply(Game game) { - for (Permanent perm: game.getBattlefield().getActivePermanents(this.source.getControllerId(), CardType.CREATURE)) { + permanentFilter.getControllerId().clear(); + permanentFilter.getControllerId().add(this.source.getControllerId()); + for (Permanent perm: game.getBattlefield().getActivePermanents(permanentFilter)) { perm.addAbility(ability); } return true; @@ -61,7 +69,10 @@ public class GainAbilityControlledEOTEffect extends ContinuousEffectImpl { @Override public String getText() { - return "Creatures you control gain " + ability.getRule() + " until end of turn"; + StringBuilder sb = new StringBuilder(); + sb.append(permanentFilter.getMessage()).append(" you control gain ").append(ability.getRule()); + sb.append(" ").append(duration.toString()); + return sb.toString(); } } diff --git a/Mage/src/mage/abilities/effects/common/GainAbilityEquippedEffect.java b/Mage/src/mage/abilities/effects/common/GainAbilityEquippedEffect.java index 67fea85a92..f69fc15023 100644 --- a/Mage/src/mage/abilities/effects/common/GainAbilityEquippedEffect.java +++ b/Mage/src/mage/abilities/effects/common/GainAbilityEquippedEffect.java @@ -28,7 +28,6 @@ package mage.abilities.effects.common; -import mage.Constants.CardType; import mage.Constants.Duration; import mage.Constants.Layer; import mage.Constants.Outcome; @@ -47,7 +46,7 @@ public class GainAbilityEquippedEffect extends ContinuousEffectImpl { protected Ability ability; public GainAbilityEquippedEffect(Ability ability) { - super(Duration.WhileInPlay, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.ability = ability; } diff --git a/Mage/src/mage/abilities/effects/common/GainAbilitySourceEffect.java b/Mage/src/mage/abilities/effects/common/GainAbilitySourceEffect.java new file mode 100644 index 0000000000..7d064e8eea --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/GainAbilitySourceEffect.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Duration; +import mage.Constants.Layer; +import mage.Constants.Outcome; +import mage.Constants.SubLayer; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GainAbilitySourceEffect extends ContinuousEffectImpl { + + protected Ability ability; + + public GainAbilitySourceEffect(Ability ability, Duration duration) { + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.ability = ability; + } + + @Override + public boolean apply(Game game) { + Permanent permanent = game.getPermanent(this.source.getSourceId()); + if (permanent != null) { + permanent.addAbility(ability); + return true; + } + return false; + } + + @Override + public String getText() { + StringBuilder sb = new StringBuilder(); + sb.append("{this} gains ").append(ability.getRule()).append(" ").append(duration.toString()); + return sb.toString(); + } + + +} diff --git a/Mage/src/mage/abilities/effects/common/GainAbilityTargetEOTEffect.java b/Mage/src/mage/abilities/effects/common/GainAbilityTargetEffect.java similarity index 82% rename from Mage/src/mage/abilities/effects/common/GainAbilityTargetEOTEffect.java rename to Mage/src/mage/abilities/effects/common/GainAbilityTargetEffect.java index 06feec5cee..ae8f246be6 100644 --- a/Mage/src/mage/abilities/effects/common/GainAbilityTargetEOTEffect.java +++ b/Mage/src/mage/abilities/effects/common/GainAbilityTargetEffect.java @@ -28,7 +28,6 @@ package mage.abilities.effects.common; -import mage.Constants.CardType; import mage.Constants.Duration; import mage.Constants.Layer; import mage.Constants.Outcome; @@ -42,12 +41,12 @@ import mage.game.permanent.Permanent; * * @author BetaSteward_at_googlemail.com */ -public class GainAbilityTargetEOTEffect extends ContinuousEffectImpl { +public class GainAbilityTargetEffect extends ContinuousEffectImpl { - private Ability ability; + protected Ability ability; - public GainAbilityTargetEOTEffect(Ability ability) { - super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + public GainAbilityTargetEffect(Ability ability, Duration duration) { + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); this.ability = ability; } @@ -63,7 +62,10 @@ public class GainAbilityTargetEOTEffect extends ContinuousEffectImpl { @Override public String getText() { - return "Target creature gains " + ability.getRule() + " until end of turn"; + StringBuilder sb = new StringBuilder(); + sb.append("Target ").append(this.source.getTargets().get(0).getTargetName()).append(" gains "); + sb.append(ability.getRule()).append(" ").append(duration.toString()); + return sb.toString(); } } \ No newline at end of file diff --git a/Mage/src/mage/abilities/effects/common/GainControlTargetEOTEffect.java b/Mage/src/mage/abilities/effects/common/GainControlTargetEOTEffect.java index 8063966973..c54a364f4d 100644 --- a/Mage/src/mage/abilities/effects/common/GainControlTargetEOTEffect.java +++ b/Mage/src/mage/abilities/effects/common/GainControlTargetEOTEffect.java @@ -46,6 +46,7 @@ public class GainControlTargetEOTEffect extends ContinuousEffectImpl { super(Duration.EndOfTurn, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); } + @Override public boolean apply(Game game) { Permanent permanent = game.getPermanent(this.source.getFirstTarget()); if (permanent != null) { diff --git a/Mage/src/mage/abilities/effects/common/GainProtectionFromColorTargetEOTEffect.java b/Mage/src/mage/abilities/effects/common/GainProtectionFromColorTargetEOTEffect.java new file mode 100644 index 0000000000..2d4d073e07 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/GainProtectionFromColorTargetEOTEffect.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Duration; +import mage.abilities.keyword.ProtectionAbility; +import mage.choices.ChoiceColor; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GainProtectionFromColorTargetEOTEffect extends GainAbilityTargetEffect { + + FilterCard protectionFilter; + + public GainProtectionFromColorTargetEOTEffect() { + super(new ProtectionAbility(new FilterCard()), Duration.EndOfTurn); + protectionFilter = (FilterCard)((ProtectionAbility)ability).getFilter(); + protectionFilter.setUseColor(true); + } + + @Override + public boolean apply(Game game) { + ChoiceColor choice = (ChoiceColor) this.source.getChoices().get(0); + protectionFilter.setColor(choice.getColor()); + protectionFilter.setMessage(choice.getChoice()); + Permanent creature = game.getPermanent(source.getFirstTarget()); + creature.addAbility(ability); + return true; + } + + @Override + public String getText() { + return "target creature you control gains protection from the color of your choice until end of turn"; + } + +} diff --git a/Mage/src/mage/abilities/effects/common/PlayTargetWithoutPayingManaEffect.java b/Mage/src/mage/abilities/effects/common/PlayTargetWithoutPayingManaEffect.java index 807c267e66..493822ecd5 100644 --- a/Mage/src/mage/abilities/effects/common/PlayTargetWithoutPayingManaEffect.java +++ b/Mage/src/mage/abilities/effects/common/PlayTargetWithoutPayingManaEffect.java @@ -40,8 +40,6 @@ import mage.players.Player; */ public class PlayTargetWithoutPayingManaEffect extends OneShotEffect { - private Card target; - public PlayTargetWithoutPayingManaEffect() { super(Outcome.GainControl); } @@ -49,10 +47,12 @@ public class PlayTargetWithoutPayingManaEffect extends OneShotEffect { @Override public boolean apply(Game game) { Player controller = game.getPlayer(this.source.getControllerId()); + Card target = (Card) game.getObject(this.source.getFirstTarget()); return controller.cast(target, game, true); } - public void setTarget(Card card) { - this.target = card; + @Override + public String getText() { + return "you may put " + this.getSource().getTargets().get(0).getTargetName() + " from you hand onto the battlefield"; } } diff --git a/Mage/src/mage/abilities/effects/common/PreventAllCombatDamageEffect.java b/Mage/src/mage/abilities/effects/common/PreventAllCombatDamageEffect.java new file mode 100644 index 0000000000..5685663b7d --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/PreventAllCombatDamageEffect.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Duration; +import mage.Constants.PhaseStep; +import mage.abilities.effects.PreventionEffectImpl; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PreventAllCombatDamageEffect extends PreventionEffectImpl { + + public PreventAllCombatDamageEffect(Duration duration) { + super(duration); + } + + @Override + public boolean apply(Game game) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Game game) { + event.setAmount(0); + return false; + } + + @Override + public boolean applies(GameEvent event, Game game) { + if (game.getTurn().getStep() == PhaseStep.COMBAT_DAMAGE) + return super.applies(event, game); + return false; + } + + @Override + public String getText() { + return "Prevent all combat damage " + duration.toString(); + } +} diff --git a/Mage/src/mage/abilities/effects/common/PreventAllDamageToEffect.java b/Mage/src/mage/abilities/effects/common/PreventAllDamageToEffect.java new file mode 100644 index 0000000000..9b51331402 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/PreventAllDamageToEffect.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Duration; +import mage.abilities.effects.PreventionEffectImpl; +import mage.filter.Filter; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PreventAllDamageToEffect extends PreventionEffectImpl { + + protected Filter filter; + + public PreventAllDamageToEffect(Duration duration, Filter filter) { + super(duration); + this.filter = filter; + } + + @Override + public boolean apply(Game game) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Game game) { + event.setAmount(0); + return false; + } + + @Override + public boolean applies(GameEvent event, Game game) { + if (super.applies(event, game)) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent != null) { + if (filter.match(permanent)) + return true; + } + else { + Player player = game.getPlayer(event.getTargetId()); + if (player != null && filter.match(player)) + return true; + } + } + return false; + } + + @Override + public String getText() { + return "Prevent all damage that would be dealt to " + filter.getMessage() + " " + duration.toString(); + } + +} diff --git a/Mage/src/mage/abilities/effects/common/PreventDamageTargetEffect.java b/Mage/src/mage/abilities/effects/common/PreventDamageTargetEffect.java new file mode 100644 index 0000000000..06e62f1254 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/PreventDamageTargetEffect.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Duration; +import mage.abilities.effects.PreventionEffectImpl; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PreventDamageTargetEffect extends PreventionEffectImpl { + + private int amount; + + public PreventDamageTargetEffect(Duration duration, int amount) { + super(duration); + this.amount = amount; + } + + @Override + public boolean apply(Game game) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Game game) { + if (event.getAmount() >= this.amount) { + event.setAmount(event.getAmount() - amount); + this.used = true; + } else { + int damage = event.getAmount(); + event.setAmount(0); + amount -= damage; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Game game) { + if (!this.used && super.applies(event, game) && event.getTargetId().equals(this.getSource().getFirstTarget())) { + return true; + } + return false; + } + +} diff --git a/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java new file mode 100644 index 0000000000..5b2b0970a1 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PutLibraryIntoGraveTargetEffect extends OneShotEffect { + + private int amount; + + public PutLibraryIntoGraveTargetEffect(int amount) { + super(Outcome.Detriment); + this.amount = amount; + } + + @Override + public boolean apply(Game game) { + Player player = game.getPlayer(this.source.getFirstTarget()); + Card card; + for (int i = 0; i < amount; i++) { + card = player.getLibrary().removeFromTop(game); + if (card != null) + player.getGraveyard().add(card); + else + break; + } + return true; + } + + @Override + public String getText() { + StringBuilder sb = new StringBuilder(); + sb.append("Target ").append(this.getSource().getTargets().get(0).getTargetName()); + sb.append(" puts the top ").append(amount).append("cards of his or her library into his or her graveyard."); + return sb.toString(); + } + +} diff --git a/Mage/src/mage/abilities/effects/common/SearchLibraryPutInPlayEffect.java b/Mage/src/mage/abilities/effects/common/SearchLibraryPutInPlayEffect.java index 288c95a357..e8acb53a31 100644 --- a/Mage/src/mage/abilities/effects/common/SearchLibraryPutInPlayEffect.java +++ b/Mage/src/mage/abilities/effects/common/SearchLibraryPutInPlayEffect.java @@ -94,6 +94,8 @@ public class SearchLibraryPutInPlayEffect extends OneShotEffect { else { sb.append("a ").append(target.getTargetName()).append(", and put it onto the battlefield"); } + if (tapped) + sb.append(" tapped"); sb.append(". Then shuffle your library"); return sb.toString(); } diff --git a/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java b/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java index ce82588e30..db745627f7 100644 --- a/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/SkipNextUntapTargetEffect.java @@ -46,21 +46,25 @@ public class SkipNextUntapTargetEffect extends ReplacementEffectImpl { super(Duration.OneUse, Outcome.Detriment); } + @Override public boolean apply(Game game) { return false; } + @Override public boolean replaceEvent(GameEvent event, Game game) { + used = true; return true; } + @Override public boolean applies(GameEvent event, Game game) { - if (game.getStep() == PhaseStep.UNTAP && + if (game.getTurn().getStep() == PhaseStep.UNTAP && event.getType() == EventType.UNTAP && - event.getSourceId().equals(source.getFirstTarget())) { - used = true; + event.getTargetId().equals(source.getFirstTarget())) { + return true; } - return used; + return false; } @Override diff --git a/Mage/src/mage/abilities/keyword/CascadeAbility.java b/Mage/src/mage/abilities/keyword/CascadeAbility.java index 97860f0e85..a906c4fec4 100644 --- a/Mage/src/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/mage/abilities/keyword/CascadeAbility.java @@ -33,7 +33,6 @@ import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.PlayTargetWithoutPayingManaEffect; import mage.cards.Card; import mage.game.ExileZone; import mage.game.Game; @@ -53,7 +52,7 @@ public class CascadeAbility extends TriggeredAbilityImpl { } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTrigger(GameEvent event, Game game) { if (event.getType() == EventType.SPELL_CAST && event.getTargetId().equals(this.getSourceId()) ) { trigger(game, event.getPlayerId()); } @@ -71,6 +70,7 @@ class CascadeEffect extends OneShotEffect { super(Outcome.PutCardInPlay); } + @Override public boolean apply(Game game) { Card card; Player player = game.getPlayer(this.getSource().getControllerId()); @@ -85,10 +85,7 @@ class CascadeEffect extends OneShotEffect { if (card != null) { if (player.chooseUse(outcome, "Use cascade effect on " + card.getName() + "?", game)) { - PlayTargetWithoutPayingManaEffect playEffect = new PlayTargetWithoutPayingManaEffect(); - playEffect.setSource(source); - playEffect.setTarget(card); - playEffect.apply(game); + player.cast(card, game, true); exile.remove(card.getId()); } } diff --git a/Mage/src/mage/abilities/keyword/CyclingAbility.java b/Mage/src/mage/abilities/keyword/CyclingAbility.java new file mode 100644 index 0000000000..efd2f08c1c --- /dev/null +++ b/Mage/src/mage/abilities/keyword/CyclingAbility.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.keyword; + +import mage.Constants.Outcome; +import mage.Constants.Zone; +import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.costs.common.DiscardSourceCost; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.players.Player; + + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CyclingAbility extends ActivatedAbilityImpl { + + public CyclingAbility(ManaCosts costs) { + super(Zone.HAND, new CycleEffect(), costs); + this.addCost(new DiscardSourceCost()); + } + + @Override + public String getRule() { + return "Cycling " + super.getRule(); + } + +} + +class CycleEffect extends OneShotEffect { + + public CycleEffect() { + super(Outcome.DrawCard); + } + + @Override + public boolean apply(Game game) { + Player player = game.getPlayer(this.source.getControllerId()); + player.drawCards(1, game); + return true; + } + + @Override + public String getText() { + return "Draw a card"; + } + +} \ No newline at end of file diff --git a/Mage/src/mage/abilities/keyword/ExaltedAbility.java b/Mage/src/mage/abilities/keyword/ExaltedAbility.java index 530d23068f..11c61b9a03 100644 --- a/Mage/src/mage/abilities/keyword/ExaltedAbility.java +++ b/Mage/src/mage/abilities/keyword/ExaltedAbility.java @@ -29,18 +29,12 @@ package mage.abilities.keyword; import mage.Constants.Duration; -import mage.Constants.Layer; -import mage.Constants.Outcome; -import mage.Constants.SubLayer; import mage.Constants.Zone; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.BoostTargetEffect; import mage.game.Game; -import mage.game.combat.Combat; -import mage.game.combat.CombatGroup; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -50,22 +44,16 @@ import mage.target.common.TargetCreaturePermanent; public class ExaltedAbility extends TriggeredAbilityImpl { public ExaltedAbility() { - super(Zone.BATTLEFIELD, new ExaltedEffect()); + super(Zone.BATTLEFIELD, new BoostTargetEffect(1, 1, Duration.EndOfTurn)); } @Override - public void handleEvent(GameEvent event, Game game) { - if (event.getType() == EventType.DECLARED_ATTACKERS ) { - Combat combat = game.getCombat(); - if (combat.getGroups().size() == 1) { - CombatGroup group = combat.getGroups().get(0); - if (group.getAttackers().size() == 1) { - if (game.getPermanent(group.getAttackers().get(0)).getControllerId().equals(this.controllerId)) { - this.targets.add(new TargetCreaturePermanent()); - this.targets.get(0).getTargets().add(group.getAttackers().get(0)); - trigger(game, event.getPlayerId()); - } - } + public void checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.DECLARED_ATTACKERS && game.getActivePlayerId().equals(this.controllerId) ) { + if (game.getCombat().attacksAlone()) { + this.targets.add(new TargetCreaturePermanent()); + this.targets.get(0).getTargets().add(game.getCombat().getAttackers().get(0)); + trigger(game, event.getPlayerId()); } } } @@ -76,22 +64,3 @@ public class ExaltedAbility extends TriggeredAbilityImpl { } } - -class ExaltedEffect extends ContinuousEffectImpl { - - public ExaltedEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - } - - @Override - public boolean apply(Game game) { - Permanent permanent = game.getPermanent(this.source.getFirstTarget()); - if (permanent != null) { - permanent.addPower(1); - permanent.addToughness(1); - return true; - } - return false; - } - -} \ No newline at end of file diff --git a/Mage/src/mage/abilities/keyword/IndestructableAbility.java b/Mage/src/mage/abilities/keyword/IndestructableAbility.java new file mode 100644 index 0000000000..c7ca7836ed --- /dev/null +++ b/Mage/src/mage/abilities/keyword/IndestructableAbility.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.abilities.keyword; + +import java.io.ObjectStreamException; +import mage.Constants.Zone; +import mage.abilities.StaticAbility; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class IndestructableAbility extends StaticAbility { + + private static final IndestructableAbility fINSTANCE = new IndestructableAbility(); + + private Object readResolve() throws ObjectStreamException { + return fINSTANCE; + } + + public static IndestructableAbility getInstance() { + return fINSTANCE; + } + + private IndestructableAbility() { + super(Zone.BATTLEFIELD, null); + } + + @Override + public String getRule() { + return "Indestructable"; + } + +} diff --git a/Mage/src/mage/abilities/keyword/UnblockableAbility.java b/Mage/src/mage/abilities/keyword/UnblockableAbility.java index 9b26565518..06c41cede3 100644 --- a/Mage/src/mage/abilities/keyword/UnblockableAbility.java +++ b/Mage/src/mage/abilities/keyword/UnblockableAbility.java @@ -58,7 +58,7 @@ public class UnblockableAbility extends EvasionAbilityImpl { @Override public String getRule() { - return "{this} is unblockable"; + return "Unblockable"; } } diff --git a/Mage/src/mage/abilities/mana/ManaAbility.java b/Mage/src/mage/abilities/mana/ManaAbility.java index 973cf2efa8..45ad0bb3d5 100644 --- a/Mage/src/mage/abilities/mana/ManaAbility.java +++ b/Mage/src/mage/abilities/mana/ManaAbility.java @@ -33,6 +33,7 @@ import mage.Constants.Zone; import mage.Mana; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; import mage.abilities.effects.common.ManaEffect; import mage.game.Game; diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java index c5e3c0286c..6009550b50 100644 --- a/Mage/src/mage/cards/Card.java +++ b/Mage/src/mage/cards/Card.java @@ -36,6 +36,7 @@ import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.game.Game; import mage.game.events.GameEvent; +import mage.watchers.Watchers; public interface Card extends MageObject { @@ -46,8 +47,10 @@ public interface Card extends MageObject { public void addAbility(Ability ability); public SpellAbility getSpellAbility(); public List getRules(); + public Watchers getWatchers(); public Card copy(); + public UUID getExpansionSetId(); - public void handleEvent(Zone zone, GameEvent event, Game game); + public void checkTriggers(Zone zone, GameEvent event, Game game); } diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 233e8942c9..1a4de31e3e 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -40,6 +40,7 @@ import mage.abilities.TriggeredAbility; import mage.game.Game; import mage.game.events.GameEvent; import mage.util.Copier; +import mage.watchers.Watchers; public abstract class CardImpl extends MageObjectImpl implements Card { @@ -47,6 +48,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card { protected UUID ownerId; protected String art = ""; + protected Watchers watchers = new Watchers(); + protected UUID expansionSetId; public CardImpl(UUID ownerId, String name, CardType[] cardTypes, String costs) { this.ownerId = ownerId; @@ -116,9 +119,19 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } @Override - public void handleEvent(Zone zone, GameEvent event, Game game) { + public Watchers getWatchers() { + return watchers; + } + + @Override + public void checkTriggers(Zone zone, GameEvent event, Game game) { for (TriggeredAbility ability: abilities.getTriggeredAbilities(zone)) { - ability.handleEvent(event, game); + ability.checkTrigger(event, game); } } + + @Override + public UUID getExpansionSetId() { + return expansionSetId; + } } diff --git a/Mage/src/mage/cards/Cards.java b/Mage/src/mage/cards/Cards.java index 1e7d5f3237..9c764c3bdd 100644 --- a/Mage/src/mage/cards/Cards.java +++ b/Mage/src/mage/cards/Cards.java @@ -41,9 +41,10 @@ public interface Cards extends Map, Serializable { public void add(Card card); public void remove(Card card); public void setOwner(UUID ownerId); - public void handleEvent(GameEvent event, Game game); public void addAll(List createCards); public List getCards(FilterCard filter); public Card getRandom(); + public int count(FilterCard filter); + public void checkTriggers(GameEvent event, Game game); } diff --git a/Mage/src/mage/cards/CardsImpl.java b/Mage/src/mage/cards/CardsImpl.java index f9bfad53cd..f9aa4e0bed 100644 --- a/Mage/src/mage/cards/CardsImpl.java +++ b/Mage/src/mage/cards/CardsImpl.java @@ -85,9 +85,19 @@ public class CardsImpl extends LinkedHashMap implements Cards, Seria } @Override - public void handleEvent(GameEvent event, Game game) { + public int count(FilterCard filter) { + int result = 0; for (Card card: this.values()) { - card.handleEvent(zone, event, game); + if (filter.match(card)) + result++; + } + return result; + } + + @Override + public void checkTriggers(GameEvent event, Game game) { + for (Card card: this.values()) { + card.checkTriggers(zone, event, game); } } diff --git a/Mage/src/mage/cards/ExpansionSet.java b/Mage/src/mage/cards/ExpansionSet.java index 207945e1cc..b78d4b8111 100644 --- a/Mage/src/mage/cards/ExpansionSet.java +++ b/Mage/src/mage/cards/ExpansionSet.java @@ -44,11 +44,16 @@ public class ExpansionSet implements Serializable { protected String name; protected List cards = new ArrayList(); + protected UUID id = UUID.randomUUID(); public List getCards() { return cards; } + public UUID getId() { + return id; + } + public String getName() { return name; } @@ -71,4 +76,8 @@ public class ExpansionSet implements Serializable { return created; } + @Override + public String toString() { + return name; + } } diff --git a/Mage/src/mage/cards/decks/DeckValidator.java b/Mage/src/mage/cards/decks/DeckValidator.java index ffdd77a817..f0c0bb656f 100644 --- a/Mage/src/mage/cards/decks/DeckValidator.java +++ b/Mage/src/mage/cards/decks/DeckValidator.java @@ -36,6 +36,7 @@ import java.io.Serializable; */ public interface DeckValidator extends Serializable { + public String getName(); public boolean validate(Deck deck); } diff --git a/Mage/src/mage/cards/decks/DeckValidatorConstructed.java b/Mage/src/mage/cards/decks/DeckValidatorConstructed.java deleted file mode 100644 index 1fa47a39f3..0000000000 --- a/Mage/src/mage/cards/decks/DeckValidatorConstructed.java +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - -package mage.cards.decks; - -import java.io.Serializable; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class DeckValidatorConstructed implements DeckValidator, Serializable { - - public boolean validate(Deck deck) { - return true; - } - -} diff --git a/Mage/src/mage/cards/decks/DeckValidatorFactory.java b/Mage/src/mage/cards/decks/DeckValidatorFactory.java deleted file mode 100644 index a0f3e48e55..0000000000 --- a/Mage/src/mage/cards/decks/DeckValidatorFactory.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - -package mage.cards.decks; - -import java.util.logging.Logger; -import mage.Constants; -import mage.util.Logging; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class DeckValidatorFactory { - - private final static DeckValidatorFactory INSTANCE = new DeckValidatorFactory(); - private final static Logger logger = Logging.getLogger(DeckValidatorFactory.class.getName()); - - public static DeckValidatorFactory getInstance() { - return INSTANCE; - } - - private DeckValidatorFactory() {} - - public DeckValidator createDeckValidator(Constants.DeckType deckType) { - - switch (deckType) { - case CONSTRUCTED_STANDARD: - - break; - case CONSTRUCTED_EXTENDED: - - break; - default: - - break; - } - return new DeckValidatorConstructed(); - } -} diff --git a/Mage/src/mage/cards/decks/DeckValidatorImpl.java b/Mage/src/mage/cards/decks/DeckValidatorImpl.java new file mode 100644 index 0000000000..16fa9e8bb0 --- /dev/null +++ b/Mage/src/mage/cards/decks/DeckValidatorImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.cards.decks; + +import java.util.Collection; +import java.util.Map; +import mage.cards.Card; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public abstract class DeckValidatorImpl implements DeckValidator { + + protected String name; + + public DeckValidatorImpl(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + protected void countCards(Map counts, Collection cards) { + for (Card card: cards) { + if (counts.containsKey(card.getName())) { + counts.put(card.getName(), counts.get(card.getName()) + 1); + } + else { + counts.put(card.getName(), 1); + } + } + } +} diff --git a/Mage/src/mage/counters/PlusOneCounter.java b/Mage/src/mage/counters/PlusOneCounter.java index becfb59218..0fe6304012 100644 --- a/Mage/src/mage/counters/PlusOneCounter.java +++ b/Mage/src/mage/counters/PlusOneCounter.java @@ -35,7 +35,7 @@ package mage.counters; public class PlusOneCounter extends BoostCounter { public PlusOneCounter() { - super(1, 1); + this(1); } public PlusOneCounter(int amount) { diff --git a/Mage/src/mage/filter/FilterCard.java b/Mage/src/mage/filter/FilterCard.java index ab7c1b4e69..6f448b105f 100644 --- a/Mage/src/mage/filter/FilterCard.java +++ b/Mage/src/mage/filter/FilterCard.java @@ -41,6 +41,8 @@ public class FilterCard extends FilterObject { protected List ownerId = new ArrayList(); protected boolean notOwner = false; + protected List expansionSetId = new ArrayList(); + protected boolean notExpansionSetId = false; public FilterCard() { super("card"); @@ -58,6 +60,9 @@ public class FilterCard extends FilterObject { if (ownerId.size() > 0 && ownerId.contains(card.getOwnerId()) == notOwner) return false; + if (expansionSetId.size() > 0 && expansionSetId.contains(card.getExpansionSetId()) == notExpansionSetId) + return false; + return true; } @@ -69,6 +74,14 @@ public class FilterCard extends FilterObject { this.notOwner = notOwner; } + public List getExpansionSetId() { + return expansionSetId; + } + + public void setNotExpansionSetId(boolean notExpansionSetId) { + this.notExpansionSetId = notExpansionSetId; + } + public boolean matchOwner(UUID testOwnerId) { if (ownerId.size() > 0 && ownerId.contains(testOwnerId) == notOwner) return false; diff --git a/Mage/src/mage/filter/common/FilterCreatureOrPlayer.java b/Mage/src/mage/filter/common/FilterCreatureOrPlayer.java index 877fd5c0eb..eb1f6f926b 100644 --- a/Mage/src/mage/filter/common/FilterCreatureOrPlayer.java +++ b/Mage/src/mage/filter/common/FilterCreatureOrPlayer.java @@ -28,6 +28,7 @@ package mage.filter.common; +import java.util.UUID; import mage.filter.Filter; import mage.filter.FilterImpl; import mage.filter.FilterPlayer; @@ -47,6 +48,12 @@ public class FilterCreatureOrPlayer extends FilterImpl implements Filter this("player or creature"); } + public FilterCreatureOrPlayer(String name, UUID controllerId) { + this(name); + creatureFilter.getControllerId().add(controllerId); + playerFilter.getPlayerId().add(controllerId); + } + public FilterCreatureOrPlayer(String name) { super(name); creatureFilter = new FilterCreaturePermanent(); diff --git a/Mage/src/mage/filter/common/FilterLegendaryPermanent.java b/Mage/src/mage/filter/common/FilterLegendaryPermanent.java new file mode 100644 index 0000000000..9db69f0a03 --- /dev/null +++ b/Mage/src/mage/filter/common/FilterLegendaryPermanent.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.filter.common; + +import mage.filter.FilterPermanent; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class FilterLegendaryPermanent extends FilterPermanent { + + public FilterLegendaryPermanent() { + this("legend"); + } + + + public FilterLegendaryPermanent(String name) { + super(name); + this.supertype.add("Legendary"); + } + +} diff --git a/Mage/src/mage/filter/common/FilterPlaneswalkerPermanent.java b/Mage/src/mage/filter/common/FilterPlaneswalkerPermanent.java index 15aee14c3b..912ff38896 100644 --- a/Mage/src/mage/filter/common/FilterPlaneswalkerPermanent.java +++ b/Mage/src/mage/filter/common/FilterPlaneswalkerPermanent.java @@ -30,7 +30,6 @@ package mage.filter.common; import mage.Constants.CardType; import mage.filter.FilterPermanent; -import mage.game.permanent.Permanent; /** * @@ -48,12 +47,4 @@ public class FilterPlaneswalkerPermanent extends FilterPermanent { cardType.add(CardType.PLANESWALKER); } - @Override - public boolean match(Permanent permanent) { - if (!super.match(permanent)) - return false; - - return true; - } - } diff --git a/Mage/src/mage/game/Exile.java b/Mage/src/mage/game/Exile.java index 48208968da..ae18d91bda 100644 --- a/Mage/src/mage/game/Exile.java +++ b/Mage/src/mage/game/Exile.java @@ -73,9 +73,9 @@ public class Exile implements Serializable { return exileZones.get(id); } - void handleEvent(GameEvent event, Game game) { + void checkTriggers(GameEvent event, Game game) { for (ExileZone exile: exileZones.values()) { - exile.handleEvent(event, game); + exile.checkTriggers(event, game); } } } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 200c4d2caf..eeb30c4af1 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -34,10 +34,9 @@ import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.UUID; -import mage.Constants.PhaseStep; -import mage.Constants.TurnPhase; import mage.MageItem; import mage.abilities.ActivatedAbility; +import mage.abilities.TriggeredAbilities; import mage.abilities.TriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; @@ -50,6 +49,7 @@ import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; import mage.game.permanent.Battlefield; import mage.game.permanent.Permanent; +import mage.game.turn.Turn; import mage.players.Player; import mage.players.PlayerList; import mage.players.Players; @@ -68,10 +68,10 @@ public interface Game extends MageItem, Serializable { public Players getPlayers(); public PlayerList getPlayerList(UUID playerId); public List getOpponents(UUID controllerId); - public TurnPhase getPhase(); - public PhaseStep getStep(); + public Turn getTurn(); public int getTurnNum(); public boolean isMainPhase(); + public boolean canPlaySorcery(UUID playerId); public UUID getActivePlayerId(); public UUID getPriorityPlayerId(); public boolean isGameOver(); @@ -91,6 +91,7 @@ public interface Game extends MageItem, Serializable { public void fireChooseEvent(UUID playerId, Choice choice); public void fireSelectTargetEvent(UUID playerId, String message, boolean required); public void fireSelectTargetEvent(UUID playerId, String message, Cards cards, boolean required); + public void fireSelectTargetEvent(UUID playerId, String message, TriggeredAbilities abilities, boolean required); public void fireSelectEvent(UUID playerId, String message); public void firePriorityEvent(UUID playerId); public void firePlayManaEvent(UUID playerId, String message); @@ -117,19 +118,19 @@ public interface Game extends MageItem, Serializable { public void applyEffects(); // public boolean checkStateAndTriggered(); // public boolean checkStateBasedActions(); - public void playPriority(); - public void playUntapStep(); - public void playUpkeepStep(); - public void playDrawStep(); - public void playPreCombatMainStep(); - public void playBeginCombatStep(); - public void playDeclareAttackersStep(); - public void playDeclareBlockersStep(); - public void playCombatDamageStep(boolean first); - public void playEndCombatStep(); - public void playPostMainStep(); - public void playEndStep(); - public void playCleanupStep(); + public void playPriority(UUID activePlayerId); + public boolean playUntapStep(UUID activePlayerId); + public boolean playUpkeepStep(UUID activePlayerId); + public boolean playDrawStep(UUID activePlayerId); + public boolean playPreCombatMainStep(UUID activePlayerId); + public boolean playBeginCombatStep(UUID activePlayerId); + public boolean playDeclareAttackersStep(UUID activePlayerId); + public boolean playDeclareBlockersStep(UUID activePlayerId); + public boolean playCombatDamageStep(UUID activePlayerId, boolean first); + public boolean playEndCombatStep(UUID activePlayerId); + public boolean playPostMainStep(UUID activePlayerId); + public boolean playEndStep(UUID activePlayerId); + public boolean playCleanupStep(UUID activePlayerId); //game transaction methods public void saveState(); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 40242a9df8..e5c6bce989 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -30,6 +30,7 @@ package mage.game; import mage.game.stack.SpellStack; import java.io.Serializable; +import java.net.URLClassLoader; import java.util.Collection; import java.util.Random; import java.util.Stack; @@ -38,10 +39,10 @@ import mage.Constants; import mage.Constants.CardType; import mage.Constants.Outcome; import mage.Constants.PhaseStep; -import mage.Constants.TurnPhase; import mage.Constants.Zone; import mage.MageObject; import mage.abilities.ActivatedAbility; +import mage.abilities.TriggeredAbilities; import mage.abilities.TriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; @@ -50,6 +51,7 @@ import mage.choices.Choice; import mage.filter.Filter.ComparisonScope; import mage.filter.common.FilterEquipment; import mage.filter.common.FilterFortification; +import mage.filter.common.FilterLegendaryPermanent; import mage.filter.common.FilterPlaneswalkerPermanent; import mage.game.combat.Combat; import mage.game.combat.CombatGroup; @@ -63,6 +65,7 @@ import mage.game.events.PlayerQueryEvent; import mage.game.events.PlayerQueryEventSource; import mage.game.permanent.Battlefield; import mage.game.permanent.Permanent; +import mage.game.turn.Turn; import mage.players.PlayerList; import mage.players.Players; import mage.target.TargetPlayer; @@ -76,14 +79,16 @@ public abstract class GameImpl implements Game, Serializable { protected TableEventSource tableEventSource = new TableEventSource(); protected PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource(); - protected GameState state = new GameState(); + protected GameState state; protected UUID startingPlayerId; protected UUID choosingPlayerId; protected String winner; - protected GameStates gameStates = new GameStates(); + protected GameStates gameStates; public GameImpl() { id = UUID.randomUUID(); + state = new GameState(); + gameStates = new GameStates(); } @Override @@ -152,7 +157,7 @@ public abstract class GameImpl implements Game, Serializable { @Override public void bookmarkState() { - savedStates.push(gameStates.getStates().size()); + savedStates.push(gameStates.getSize()); } @Override @@ -168,7 +173,7 @@ public abstract class GameImpl implements Game, Serializable { @Override public void start() { for (Player player: state.getPlayers().values()) { - player.init(); + player.init(this); } fireInformEvent("game has started"); saveState(); @@ -212,6 +217,7 @@ public abstract class GameImpl implements Game, Serializable { state.setTurnNum(state.getTurnNum() + 1); fireInformEvent("Turn " + Integer.toString(state.getTurnNum())); for (Player player: state.getPlayerList(startingPlayerId)) { + state.setActivePlayerId(player.getId()); state.getTurn().play(this, player.getId()); if (isGameOver()) break; @@ -235,6 +241,7 @@ public abstract class GameImpl implements Game, Serializable { for (Player player: getPlayers().values()) { player.endOfTurn(this); } + state.getWatchers().reset(); } protected UUID pickChoosingPlayer() { @@ -289,13 +296,13 @@ public abstract class GameImpl implements Game, Serializable { } @Override - public void playPriority() { + public void playPriority(UUID activePlayerId) { while (!isGameOver()) { while (!isGameOver()) { int stackSize = state.getStack().size(); state.getPlayers().resetPriority(); - for (Player player: getPlayerList(state.getTurn().getActivePlayerId())) { - state.getTurn().setPriorityPlayerId(player.getId()); + for (Player player: getPlayerList(activePlayerId)) { + state.setPriorityPlayerId(player.getId()); while (!player.isPassed() && !isGameOver()) { checkStateAndTriggered(); if (isGameOver()) @@ -313,6 +320,7 @@ public abstract class GameImpl implements Game, Serializable { } if (isGameOver() || state.getStack().isEmpty()) break; + //20091005 - 115.4 state.getStack().resolve(this); applyEffects(); saveState(); @@ -340,14 +348,15 @@ public abstract class GameImpl implements Game, Serializable { @Override public void addTriggeredAbility(TriggeredAbility ability) { - state.addTriggeredAbility(ability); + state.addTriggeredAbility((TriggeredAbility) ability.copy()); } protected boolean checkStateAndTriggered() { boolean somethingHappened = false; + //20091005 - 115.5 while (true) { if (!checkStateBasedActions() ) { - if (!state.getTriggered().check(this)) { + if (!checkTriggered()) { break; } } @@ -356,12 +365,33 @@ public abstract class GameImpl implements Game, Serializable { return somethingHappened; } + public boolean checkTriggered() { + boolean played = false; + for (Player player: getPlayerList(state.getActivePlayerId())) { + while (true) { + TriggeredAbilities abilities = state.getTriggered().getControlledBy(player.getId()); + if (abilities.size() == 0) + break; + if (abilities.size() == 1) { + state.getTriggered().remove(abilities.get(0)); + played |= player.triggerAbility(abilities.get(0), this); + } + else { + TriggeredAbility ability = player.chooseTriggeredAbility(abilities, this); + state.getTriggered().remove(ability); + played |= player.triggerAbility(ability, this); + } + } + } + return played; + } + protected boolean checkStateBasedActions() { boolean somethingHappened = false; //20091005 - 704.5a/704.5b/704.5c for (Player player: state.getPlayers().values()) { - if (player.getLife() <= 0 || player.isEmptyDraw() || player.getCounters().getCount("Poison") >= 10) { + if (!player.hasLost() && (player.getLife() <= 0 || player.isEmptyDraw() || player.getCounters().getCount("Poison") >= 10)) { player.lost(this); somethingHappened = true; } @@ -378,21 +408,6 @@ public abstract class GameImpl implements Game, Serializable { somethingHappened = true; } } - //20091005 - 704.5j - FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent(); - if (getBattlefield().count(filter) > 1) { //don't bother checking if less than 2 planeswalkers in play - for (String planeswalkerType: Constants.PlaneswalkerTypes) { - filter.getSubtype().clear(); - filter.getSubtype().add(planeswalkerType); - filter.setScopeSubtype(ComparisonScope.Any); - if (getBattlefield().count(filter) > 1) { - for (Permanent perm: getBattlefield().getActivePermanents(filter)) { - perm.moveToZone(Zone.GRAVEYARD, this, false); - somethingHappened = true; - } - } - } - } //20091005 - 704.5i for (Permanent perm: getBattlefield().getActivePermanents(CardType.PLANESWALKER)) { if (perm.getLoyalty().getValue() == 0) { @@ -400,6 +415,35 @@ public abstract class GameImpl implements Game, Serializable { return true; } } + //20091005 - 704.5j + FilterPlaneswalkerPermanent filterPlaneswalker = new FilterPlaneswalkerPermanent(); + if (getBattlefield().count(filterPlaneswalker) > 1) { //don't bother checking if less than 2 planeswalkers in play + for (String planeswalkerType: Constants.PlaneswalkerTypes) { + filterPlaneswalker.getSubtype().clear(); + filterPlaneswalker.getSubtype().add(planeswalkerType); + filterPlaneswalker.setScopeSubtype(ComparisonScope.Any); + if (getBattlefield().count(filterPlaneswalker) > 1) { + for (Permanent perm: getBattlefield().getActivePermanents(filterPlaneswalker)) { + perm.moveToZone(Zone.GRAVEYARD, this, false); + } + somethingHappened = true; + } + } + } + //20091005 - 704.5k + FilterLegendaryPermanent filterLegendary = new FilterLegendaryPermanent(); + if (getBattlefield().count(filterPlaneswalker) > 1) { //don't bother checking if less than 2 legends in play + for (Permanent legend: getBattlefield().getActivePermanents(filterLegendary)) { + FilterLegendaryPermanent filterLegendName = new FilterLegendaryPermanent(); + filterLegendName.getName().add(legend.getName()); + if (getBattlefield().count(filterLegendName) > 1) { + for (Permanent dupLegend: getBattlefield().getActivePermanents(filterLegendName)) { + dupLegend.moveToZone(Zone.GRAVEYARD, this, false); + } + return true; + } + } + } //20091005 - 704.5p for (Permanent perm: getBattlefield().getActivePermanents(new FilterEquipment())) { if (perm.getAttachedTo() != null) { @@ -446,8 +490,7 @@ public abstract class GameImpl implements Game, Serializable { } @Override - public void playUntapStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playUntapStep(UUID activePlayerId) { fireEvent(new GameEvent(GameEvent.EventType.BEGINNING_PHASE_PRE, null, null, activePlayerId)); if (!replaceEvent(new GameEvent(GameEvent.EventType.UNTAP_STEP, null, null, activePlayerId))) { //20091005 - 502.1/703.4a @@ -456,128 +499,138 @@ public abstract class GameImpl implements Game, Serializable { getPlayer(activePlayerId).untap(this); fireEvent(new GameEvent(GameEvent.EventType.UNTAP_STEP_PRE, null, null, activePlayerId)); fireEvent(new GameEvent(GameEvent.EventType.UNTAP_STEP_POST, null, null, activePlayerId)); + return true; } - + return false; } @Override - public void playUpkeepStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playUpkeepStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.UPKEEP_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.UPKEEP_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.UPKEEP_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playDrawStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playDrawStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.DRAW_STEP, null, null, activePlayerId))) { //20091005 - 504.1/703.4c getPlayer(activePlayerId).drawCards(1, this); fireEvent(new GameEvent(GameEvent.EventType.DRAW_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.DRAW_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playPreCombatMainStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playPreCombatMainStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.PRECOMBAT_MAIN_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.PRECOMBAT_MAIN_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.PRECOMBAT_MAIN_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playBeginCombatStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playBeginCombatStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.BEGIN_COMBAT_STEP, null, null, activePlayerId))) { //20091005 - 507.1 state.getCombat().clear(); state.getCombat().setAttacker(activePlayerId); for (Player player: state.getPlayers().values()) { - if (!player.getId().equals(state.getTurn().getActivePlayerId())) + if (!player.getId().equals(state.getActivePlayerId())) state.getCombat().getDefenders().add(player.getId()); } fireEvent(new GameEvent(GameEvent.EventType.BEGIN_COMBAT_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.PRECOMBAT_MAIN_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playDeclareAttackersStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playDeclareAttackersStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP, null, null, activePlayerId))) { state.getCombat().selectAttackers(this); fireEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.DECLARE_ATTACKERS_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playDeclareBlockersStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playDeclareBlockersStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP, null, null, activePlayerId))) { state.getCombat().selectBlockers(this); fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.DECLARE_BLOCKERS_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playCombatDamageStep(boolean first) { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playCombatDamageStep(UUID activePlayerId, boolean first) { if (!replaceEvent(new GameEvent(GameEvent.EventType.COMBAT_DAMAGE_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.COMBAT_DAMAGE_STEP_PRE, null, null, activePlayerId)); for (CombatGroup group: getCombat().getGroups()) { group.assignDamage(first, this); } - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.COMBAT_DAMAGE_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override - public void playEndCombatStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playEndCombatStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.END_COMBAT_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.END_COMBAT_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.END_COMBAT_STEP_POST, null, null, activePlayerId)); removeCreaturesFromCombat(); + return true; } + return false; } @Override - public void playPostMainStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playPostMainStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.POSTCOMBAT_MAIN_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.POSTCOMBAT_MAIN_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.POSTCOMBAT_MAIN_STEP_POST, null, null, activePlayerId)); - } + return true; + } + return false; } @Override - public void playEndStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playEndStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.END_TURN_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.END_TURN_STEP_PRE, null, null, activePlayerId)); - playPriority(); + playPriority(activePlayerId); fireEvent(new GameEvent(GameEvent.EventType.END_TURN_STEP_POST, null, null, activePlayerId)); - } + return true; + } + return false; } @Override - public void playCleanupStep() { - UUID activePlayerId = state.getTurn().getActivePlayerId(); + public boolean playCleanupStep(UUID activePlayerId) { if (!replaceEvent(new GameEvent(GameEvent.EventType.CLEANUP_STEP, null, null, activePlayerId))) { fireEvent(new GameEvent(GameEvent.EventType.CLEANUP_STEP_PRE, null, null, activePlayerId)); //20091005 - 514.1 @@ -586,11 +639,13 @@ public abstract class GameImpl implements Game, Serializable { state.getBattlefield().endOfTurn(activePlayerId, this); state.removeEotEffects(this); if (checkStateAndTriggered()) { - playPriority(); - playCleanupStep(); + playPriority(activePlayerId); + playCleanupStep(activePlayerId); } fireEvent(new GameEvent(GameEvent.EventType.CLEANUP_STEP_POST, null, null, activePlayerId)); + return true; } + return false; } @Override @@ -600,8 +655,8 @@ public abstract class GameImpl implements Game, Serializable { @Override public void firePriorityEvent(UUID playerId) { - String message = this.getStep().toString(); - if (this.getActivePlayerId().equals(playerId) && this.getStack().isEmpty() && this.isMainPhase()) + String message = this.state.getTurn().getStep().toString(); + if (this.canPlaySorcery(playerId)) message += " - play spells and sorceries."; else message += " - play instants and activated abilites."; @@ -644,6 +699,11 @@ public abstract class GameImpl implements Game, Serializable { playerQueryEventSource.target(playerId, message, cards, required); } + @Override + public void fireSelectTargetEvent(UUID playerId, String message, TriggeredAbilities abilities, boolean required) { + playerQueryEventSource.target(playerId, message, abilities, required); + } + @Override public void fireGetAmountEvent(UUID playerId, String message, int min, int max) { playerQueryEventSource.amount(playerId, message, min, max); @@ -681,14 +741,19 @@ public abstract class GameImpl implements Game, Serializable { } @Override - public TurnPhase getPhase() { - return state.getPhase(); + public Turn getTurn() { + return state.getTurn(); } - @Override - public PhaseStep getStep() { - return state.getStep(); - } +// @Override +// public TurnPhase getPhase() { +// return state.getPhase(); +// } +// +// @Override +// public PhaseStep getStep() { +// return state.getStep(); +// } @Override public Battlefield getBattlefield() { @@ -717,18 +782,22 @@ public abstract class GameImpl implements Game, Serializable { @Override public boolean isMainPhase() { - return state.getStep() == PhaseStep.PRECOMBAT_MAIN || state.getStep() == PhaseStep.POSTCOMBAT_MAIN; + return state.getTurn().getStep() == PhaseStep.PRECOMBAT_MAIN || state.getTurn().getStep() == PhaseStep.POSTCOMBAT_MAIN; } + @Override + public boolean canPlaySorcery(UUID playerId) { + return getActivePlayerId().equals(playerId) && getStack().isEmpty() && isMainPhase(); + } @Override public UUID getActivePlayerId() { - return state.getTurn().getActivePlayerId(); + return state.getActivePlayerId(); } @Override public UUID getPriorityPlayerId() { - return state.getTurn().getPriorityPlayerId(); + return state.getPriorityPlayerId(); } @Override diff --git a/Mage/src/mage/game/GameReplay.java b/Mage/src/mage/game/GameReplay.java index 394d527017..e9c2037c3f 100644 --- a/Mage/src/mage/game/GameReplay.java +++ b/Mage/src/mage/game/GameReplay.java @@ -46,15 +46,15 @@ public class GameReplay { } public GameState next() { - if (this.stateIndex < savedGame.getStates().size()) { - return savedGame.getStates().get(stateIndex++); + if (this.stateIndex < savedGame.getSize()) { + return savedGame.get(stateIndex++); } return null; } public GameState previous() { if (this.stateIndex > 0) { - return savedGame.getStates().get(--stateIndex); + return savedGame.get(--stateIndex); } return null; } diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 55a9bea7dc..04e385a5de 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -36,8 +36,6 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import mage.Constants.PhaseStep; -import mage.Constants.TurnPhase; import mage.Constants.Zone; import mage.MageObject; import mage.abilities.TriggeredAbilities; @@ -47,10 +45,12 @@ import mage.game.combat.Combat; import mage.game.permanent.Battlefield; import mage.game.permanent.Permanent; import mage.game.turn.Turn; +import mage.game.turn.TurnMods; import mage.players.Player; import mage.players.PlayerList; import mage.players.Players; import mage.util.Copier; +import mage.watchers.Watchers; /** * @@ -66,6 +66,8 @@ public class GameState implements Serializable { private static final transient Copier copier = new Copier(); private Players players = new Players(); + private UUID activePlayerId; + private UUID priorityPlayerId; private Turn turn = new Turn(); private SpellStack stack = new SpellStack(); private Exile exile = new Exile(); @@ -76,6 +78,8 @@ public class GameState implements Serializable { private ContinuousEffects effects = new ContinuousEffects(); private TriggeredAbilities triggers = new TriggeredAbilities(); private Combat combat = new Combat(); + private TurnMods turnMods = new TurnMods(); + private Watchers watchers = new Watchers(); public void addPlayer(Player player) { players.put(player.getId(), player); @@ -89,12 +93,20 @@ public class GameState implements Serializable { return players.get(playerId); } - public TurnPhase getPhase() { - return turn.getPhase(); + public UUID getActivePlayerId() { + return activePlayerId; } - public PhaseStep getStep() { - return turn.getStep(); + public void setActivePlayerId(UUID activePlayerId) { + this.activePlayerId = activePlayerId; + } + + public UUID getPriorityPlayerId() { + return priorityPlayerId; + } + + public void setPriorityPlayerId(UUID priorityPlayerId) { + this.priorityPlayerId = priorityPlayerId; } public Battlefield getBattlefield() { @@ -129,6 +141,14 @@ public class GameState implements Serializable { return this.gameOver; } + public TurnMods getTurnMods() { + return this.turnMods; + } + + public Watchers getWatchers() { + return this.watchers; + } + public void endGame() { this.gameOver = true; } @@ -150,10 +170,6 @@ public class GameState implements Serializable { effects.addEffect(effect); } -// public boolean effectExists(UUID effectId) { -// return effects.effectExists(effectId); -// } - public void addMessage(String message) { this.messages.add(message); } @@ -239,12 +255,13 @@ public class GameState implements Serializable { public void handleEvent(GameEvent event, Game game) { if (!replaceEvent(event, game)) { for (Player player: players.values()) { - player.handleEvent(event, game); + player.checkTriggers(event, game); } } - battlefield.handleEvent(event, game); - stack.handleEvent(event, game); - exile.handleEvent(event, game); + battlefield.checkTriggers(event, game); + stack.checkTriggers(event, game); + exile.checkTriggers(event, game); + watchers.watch(event, game); } public boolean replaceEvent(GameEvent event, Game game) { @@ -260,7 +277,7 @@ public class GameState implements Serializable { return this.triggers; } - ContinuousEffects getContinuousEffects() { + public ContinuousEffects getContinuousEffects() { return effects; } diff --git a/Mage/src/mage/game/GameStates.java b/Mage/src/mage/game/GameStates.java index 57e37f71f5..e179544192 100644 --- a/Mage/src/mage/game/GameStates.java +++ b/Mage/src/mage/game/GameStates.java @@ -43,8 +43,8 @@ public class GameStates { states.add(gameState.copy()); } - public List getStates() { - return states; + public int getSize() { + return states.size(); } public GameState rollback(int index) { @@ -53,4 +53,10 @@ public class GameStates { } return states.get(index - 1); } + + public GameState get(int index) { + if (index <= states.size()) + return states.get(index); + return null; + } } diff --git a/Mage/src/mage/game/Table.java b/Mage/src/mage/game/Table.java index 0720fa8e3b..27b6da9064 100644 --- a/Mage/src/mage/game/Table.java +++ b/Mage/src/mage/game/Table.java @@ -31,11 +31,9 @@ package mage.game; import java.io.Serializable; import java.util.List; import java.util.UUID; -import mage.Constants.DeckType; import mage.Constants.TableState; import mage.MageItem; import mage.cards.decks.DeckValidator; -import mage.cards.decks.DeckValidatorFactory; import mage.players.Player; /** @@ -47,19 +45,19 @@ public class Table implements MageItem, Serializable { private UUID tableId; private String name; private Game game; - private DeckType deckType; +// private String deckType; private Seat[] seats; private int numSeats; private DeckValidator validator; private TableState state = TableState.WAITING; - public Table(Game game, DeckType deckType, List playerTypes) { + public Table(Game game, DeckValidator validator, List playerTypes) { tableId = UUID.randomUUID(); this.numSeats = game.getNumPlayers(); this.game = game; - this.deckType = deckType; createSeats(playerTypes); - this.validator = DeckValidatorFactory.getInstance().createDeckValidator(deckType); + this.validator = validator; +// this.validator = DeckValidatorFactory.getInstance().createDeckValidator(deckType); } private void createSeats(List playerTypes) { @@ -87,9 +85,9 @@ public class Table implements MageItem, Serializable { state = TableState.DUELING; } - public void replayGame() { - - } +// public void replayGame() { +// +// } public void endGame() { state = TableState.FINISHED; @@ -99,8 +97,8 @@ public class Table implements MageItem, Serializable { return game.getGameType(); } - public DeckType getDeckType() { - return deckType; + public String getDeckType() { + return validator.getName(); } public UUID joinTable(Player player, int seatNum) throws GameException { diff --git a/Mage/src/mage/game/combat/Combat.java b/Mage/src/mage/game/combat/Combat.java index 8ec7b34ba6..730c54e8e7 100644 --- a/Mage/src/mage/game/combat/Combat.java +++ b/Mage/src/mage/game/combat/Combat.java @@ -159,4 +159,15 @@ public class Combat implements Serializable { return total; } + public boolean attacksAlone() { + return (groups.size() == 1 && groups.get(0).getAttackers().size() == 1); + } + + public boolean noAttackers() { + if (groups.size() == 0 || getAttackers().size() == 0) + return true; + return false; + } + + } diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index a7c9c5e393..f241735302 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -45,19 +45,23 @@ public class GameEvent { public enum EventType { //Turn-based events - BEGINNING_PHASE_PRE, BEGINNING_PHASE_POST, + CHANGE_PHASE, PHASE_CHANGED, + CHANGE_STEP, STEP_CHANGED, + BEGINNING_PHASE, BEGINNING_PHASE_PRE, BEGINNING_PHASE_POST, UNTAP_STEP_PRE, UNTAP_STEP, UNTAP_STEP_POST, UPKEEP_STEP_PRE, UPKEEP_STEP, UPKEEP_STEP_POST, DRAW_STEP_PRE, DRAW_STEP, DRAW_STEP_POST, + PRECOMBAT_MAIN_PHASE, PRECOMBAT_MAIN_PHASE_PRE, PRECOMBAT_MAIN_PHASE_POST, PRECOMBAT_MAIN_STEP_PRE, PRECOMBAT_MAIN_STEP, PRECOMBAT_MAIN_STEP_POST, - COMBAT_PHASE_PRE, COMBAT_PHASE_POST, + COMBAT_PHASE, COMBAT_PHASE_PRE, COMBAT_PHASE_POST, BEGIN_COMBAT_STEP_PRE, BEGIN_COMBAT_STEP, BEGIN_COMBAT_STEP_POST, DECLARE_ATTACKERS_STEP_PRE, DECLARE_ATTACKERS_STEP, DECLARE_ATTACKERS_STEP_POST, DECLARE_BLOCKERS_STEP_PRE, DECLARE_BLOCKERS_STEP, DECLARE_BLOCKERS_STEP_POST, COMBAT_DAMAGE_STEP_PRE, COMBAT_DAMAGE_STEP, COMBAT_DAMAGE_STEP_POST, END_COMBAT_STEP_PRE, END_COMBAT_STEP, END_COMBAT_STEP_POST, + POSTCOMBAT_MAIN_PHASE, POSTCOMBAT_MAIN_PHASE_PRE, POSTCOMBAT_MAIN_PHASE_POST, POSTCOMBAT_MAIN_STEP_PRE, POSTCOMBAT_MAIN_STEP, POSTCOMBAT_MAIN_STEP_POST, - END_PHASE_PRE, END_PHASE_POST, + END_PHASE, END_PHASE_PRE, END_PHASE_POST, END_TURN_STEP_PRE, END_TURN_STEP, END_TURN_STEP_POST, CLEANUP_STEP_PRE, CLEANUP_STEP, CLEANUP_STEP_POST, @@ -68,6 +72,7 @@ public class GameEvent { ZONE_CHANGE, DRAW_CARD, DREW_CARD, DISCARD_CARD, DISCARDED_CARD, + CYCLE_CARD, CYCLED_CARD, DAMAGE_PLAYER, DAMAGED_PLAYER, PLAYER_LIFE_CHANGE, PLAY_LAND, LAND_PLAYED, @@ -80,6 +85,7 @@ public class GameEvent { DECLARE_ATTACKER, ATTACKER_DECLARED, DECLARING_BLOCKERS, DECLARED_BLOCKERS, DECLARE_BLOCKER, BLOCKER_DECLARED, + SEARCH_LIBRARY, LIBRARY_SEARCHED, //permanent events TAP, TAPPED, @@ -147,4 +153,8 @@ public class GameEvent { return amount; } + public void setAmount(int amount) { + this.amount = amount; + } + } diff --git a/Mage/src/mage/game/events/PlayerQueryEvent.java b/Mage/src/mage/game/events/PlayerQueryEvent.java index 597b2b9705..140671c5f8 100644 --- a/Mage/src/mage/game/events/PlayerQueryEvent.java +++ b/Mage/src/mage/game/events/PlayerQueryEvent.java @@ -32,7 +32,9 @@ import java.io.Serializable; import java.util.Collection; import java.util.EventObject; import java.util.UUID; +import mage.abilities.Ability; import mage.abilities.ActivatedAbility; +import mage.abilities.TriggeredAbilities; import mage.cards.Cards; /** @@ -42,11 +44,11 @@ import mage.cards.Cards; public class PlayerQueryEvent extends EventObject implements ExternalEvent, Serializable { public enum QueryType { - ASK, CHOOSE, CHOOSE_ABILITY, PICK_TARGET, SELECT, PLAY_MANA, PLAY_X_MANA, AMOUNT + ASK, CHOOSE, CHOOSE_ABILITY, PICK_TARGET, PICK_ABILITY, SELECT, PLAY_MANA, PLAY_X_MANA, AMOUNT } private String message; - private Collection abilities; + private Collection abilities; private String[] choices; private Cards cards; private QueryType queryType; @@ -55,7 +57,7 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri private int min; private int max; - private PlayerQueryEvent(UUID playerId, String message, Collection abilities, String[] choices, Cards cards, QueryType queryType, int min, int max, boolean required) { + private PlayerQueryEvent(UUID playerId, String message, Collection abilities, String[] choices, Cards cards, QueryType queryType, int min, int max, boolean required) { super(playerId); this.queryType = queryType; this.message = message; @@ -87,6 +89,10 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return new PlayerQueryEvent(playerId, message, null, null, cards, QueryType.PICK_TARGET, 0, 0, required); } + public static PlayerQueryEvent targetEvent(UUID playerId, String message, TriggeredAbilities abilities, boolean required) { + return new PlayerQueryEvent(playerId, message, abilities, null, null, QueryType.PICK_ABILITY, 0, 0, required); + } + public static PlayerQueryEvent selectEvent(UUID playerId, String message) { return new PlayerQueryEvent(playerId, message, null, null, null, QueryType.SELECT, 0, 0, false); } @@ -111,7 +117,7 @@ public class PlayerQueryEvent extends EventObject implements ExternalEvent, Seri return queryType; } - public Collection getAbilities() { + public Collection getAbilities() { return abilities; } diff --git a/Mage/src/mage/game/events/PlayerQueryEventSource.java b/Mage/src/mage/game/events/PlayerQueryEventSource.java index d40aa14543..1b07b22031 100644 --- a/Mage/src/mage/game/events/PlayerQueryEventSource.java +++ b/Mage/src/mage/game/events/PlayerQueryEventSource.java @@ -33,6 +33,7 @@ import java.util.Collection; import java.util.List; import java.util.UUID; import mage.abilities.ActivatedAbility; +import mage.abilities.TriggeredAbilities; import mage.cards.Cards; /** @@ -43,6 +44,7 @@ public class PlayerQueryEventSource implements EventSource, Se protected final EventDispatcher dispatcher = new EventDispatcher() {}; + @Override public void addListener(Listener listener) { dispatcher.addListener(listener); } @@ -67,6 +69,10 @@ public class PlayerQueryEventSource implements EventSource, Se dispatcher.fireEvent(PlayerQueryEvent.targetEvent(playerId, message, cards, required)); } + public void target(UUID playerId, String message, TriggeredAbilities abilities, boolean required) { + dispatcher.fireEvent(PlayerQueryEvent.targetEvent(playerId, message, abilities, required)); + } + public void playMana(UUID playerId, String message) { dispatcher.fireEvent(PlayerQueryEvent.playManaEvent(playerId, message)); } diff --git a/Mage/src/mage/game/permanent/Battlefield.java b/Mage/src/mage/game/permanent/Battlefield.java index e64a8dff8d..8853eaa4ea 100644 --- a/Mage/src/mage/game/permanent/Battlefield.java +++ b/Mage/src/mage/game/permanent/Battlefield.java @@ -86,10 +86,10 @@ public class Battlefield implements Serializable { return field.containsKey(key); } - public void handleEvent(GameEvent event, Game game) { + public void checkTriggers(GameEvent event, Game game) { for (Permanent perm: field.values()) { if (perm.isPhasedIn()) - perm.handleEvent(event, game); + perm.checkTriggers(event, game); } } diff --git a/Mage/src/mage/game/permanent/Permanent.java b/Mage/src/mage/game/permanent/Permanent.java index d068923fec..8bdede4048 100644 --- a/Mage/src/mage/game/permanent/Permanent.java +++ b/Mage/src/mage/game/permanent/Permanent.java @@ -84,7 +84,7 @@ public interface Permanent extends Card { public boolean isLoyaltyUsed(); public void endOfTurn(Game game); - public void handleEvent(GameEvent event, Game game); + public void checkTriggers(GameEvent event, Game game); public int getTurnsOnBattlefield(); public void addPower(int power); diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index 0edb49a74d..9d740d4d97 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -37,11 +37,13 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.EvasionAbility; import mage.abilities.StaticAbility; +import mage.abilities.TriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.IndestructableAbility; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.ProtectionAbility; import mage.abilities.keyword.ShroudAbility; @@ -111,11 +113,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent } @Override - public void handleEvent(GameEvent event, Game game) { + public void checkTriggers(GameEvent event, Game game) { if (event.getType() == EventType.BEGINNING_PHASE_PRE && game.getActivePlayerId().equals(controllerId)) this.controlledFromStartOfTurn = true; - for (Ability ability: abilities.getTriggeredAbilities(Zone.BATTLEFIELD)) { - ability.handleEvent(event, game); + for (TriggeredAbility ability: abilities.getTriggeredAbilities(Zone.BATTLEFIELD)) { + ability.checkTrigger(event, game); } } @@ -423,9 +425,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent //20091005 - 701.6 //TODO: handle noRegen if (!game.replaceEvent(GameEvent.getEvent(EventType.DESTROY_PERMANENT, objectId, sourceId, controllerId))) { - if (moveToZone(Zone.GRAVEYARD, game, false)) { - game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId)); - return true; + if (!this.getAbilities().containsKey(IndestructableAbility.getInstance().getId())) { + if (moveToZone(Zone.GRAVEYARD, game, false)) { + game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId)); + return true; + } } } return false; diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 0c0cd67490..f11b210741 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -45,6 +45,7 @@ import mage.cards.Card; import mage.game.events.GameEvent; import mage.players.Player; import mage.util.Copier; +import mage.watchers.Watchers; /** * @@ -60,6 +61,7 @@ public class Spell implements StackObject, Card { this.controllerId = controllerId; } + @Override public boolean resolve(Game game) { boolean result = false; if (card.getCardType().contains(CardType.INSTANT) || card.getCardType().contains(CardType.SORCERY)) { @@ -93,108 +95,144 @@ public class Spell implements StackObject, Card { } } + @Override public void counter(Game game) { game.getPlayers().get(controllerId).putInGraveyard(card, game, false); } + @Override public UUID getSourceId() { return card.getId(); } + @Override public UUID getControllerId() { return this.controllerId; } + @Override public String getName() { return card.getName(); } + @Override public List getCardType() { return card.getCardType(); } + @Override public List getSubtype() { return card.getSubtype(); } + @Override public List getSupertype() { return card.getSupertype(); } + @Override public Abilities getAbilities() { return card.getAbilities(); } + @Override public ObjectColor getColor() { return card.getColor(); } + @Override public ManaCosts getManaCost() { return card.getManaCost(); } + @Override public MageInt getPower() { return card.getPower(); } + @Override public MageInt getToughness() { return card.getToughness(); } + @Override public MageInt getLoyalty() { return card.getLoyalty(); } + @Override public Zone getZone() { return Zone.STACK; } + @Override public void setZone(Zone zone) { } + @Override public UUID getId() { return card.getId(); } + @Override public UUID getOwnerId() { return card.getOwnerId(); } + @Override public String getArt() { return card.getArt(); } + @Override public void addAbility(Ability ability) { } + @Override public SpellAbility getSpellAbility() { return card.getSpellAbility(); } + @Override public void setControllerId(UUID controllerId) { this.controllerId = controllerId; } + @Override public void setOwnerId(UUID controllerId) { } + @Override public Card copy() { return new Copier().copy(this); } - public void handleEvent(GameEvent event, Game game) { - handleEvent(Zone.STACK, event, game); + @Override + public void checkTriggers(GameEvent event, Game game) { + checkTriggers(Zone.STACK, event, game); } - public void handleEvent(Zone zone, GameEvent event, Game game) { - card.handleEvent(zone, event, game); + @Override + public void checkTriggers(Zone zone, GameEvent event, Game game) { + card.checkTriggers(zone, event, game); } + @Override public List getRules() { return card.getRules(); } + @Override + public Watchers getWatchers() { + return card.getWatchers(); + } + + @Override + public UUID getExpansionSetId() { + return card.getExpansionSetId(); + } + } diff --git a/Mage/src/mage/game/stack/SpellStack.java b/Mage/src/mage/game/stack/SpellStack.java index 680f826f64..20a75aeea5 100644 --- a/Mage/src/mage/game/stack/SpellStack.java +++ b/Mage/src/mage/game/stack/SpellStack.java @@ -53,9 +53,9 @@ public class SpellStack extends Stack { this.remove(top); } - public void handleEvent(GameEvent event, Game game) { + public void checkTriggers(GameEvent event, Game game) { for (StackObject stackObject: this) { - stackObject.handleEvent(event, game); + stackObject.checkTriggers(event, game); } } diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index 676cf12c47..9f2984e852 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -29,8 +29,10 @@ package mage.game.stack; import java.util.ArrayList; +import mage.abilities.costs.AlternativeCost; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.choices.Choice; @@ -81,6 +83,7 @@ public class StackAbility implements StackObject, Ability { return false; } + @Override public void counter(Game game) { } @@ -192,11 +195,6 @@ public class StackAbility implements StackObject, Ability { @Override public void addCost(Cost cost) {} - @Override - public void handleEvent(GameEvent event, Game game) { - ability.handleEvent(event, game); - } - @Override public void addEffect(Effect effect) {} @@ -232,4 +230,23 @@ public class StackAbility implements StackObject, Ability { throw new UnsupportedOperationException("Not supported yet."); } + @Override + public List getAlternativeCosts() { + return ability.getAlternativeCosts(); + } + + @Override + public void addAlternativeCost(AlternativeCost cost) { } + + @Override + public ManaCosts getManaCosts() { + return ability.getManaCosts(); + } + + @Override + public void addManaCost(ManaCost cost) { } + + @Override + public void checkTriggers(GameEvent event, Game game) { } + } diff --git a/Mage/src/mage/game/stack/StackObject.java b/Mage/src/mage/game/stack/StackObject.java index 9ce7b703c1..95f95bacf0 100644 --- a/Mage/src/mage/game/stack/StackObject.java +++ b/Mage/src/mage/game/stack/StackObject.java @@ -39,7 +39,7 @@ public interface StackObject extends MageObject { public boolean resolve(Game game); public UUID getSourceId(); public UUID getControllerId(); - public void handleEvent(GameEvent event, Game game); + public void checkTriggers(GameEvent event, Game game); public void counter(Game game); } diff --git a/Mage/src/mage/game/turn/BeginningPhase.java b/Mage/src/mage/game/turn/BeginningPhase.java new file mode 100644 index 0000000000..915e714049 --- /dev/null +++ b/Mage/src/mage/game/turn/BeginningPhase.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class BeginningPhase extends Phase { + + public BeginningPhase() { + this.type = TurnPhase.BEGINNING; + this.event = EventType.BEGINNING_PHASE; + this.preEvent = EventType.BEGINNING_PHASE_PRE; + this.postEvent = EventType.BEGINNING_PHASE_POST; + this.steps.add(new Step(PhaseStep.UNTAP)); + this.steps.add(new Step(PhaseStep.UPKEEP)); + this.steps.add(new Step(PhaseStep.DRAW)); + } + +} diff --git a/Mage/src/mage/game/turn/CombatPhase.java b/Mage/src/mage/game/turn/CombatPhase.java new file mode 100644 index 0000000000..15121effab --- /dev/null +++ b/Mage/src/mage/game/turn/CombatPhase.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CombatPhase extends Phase { + + public CombatPhase() { + this.type = TurnPhase.COMBAT; + this.event = EventType.COMBAT_PHASE; + this.preEvent = EventType.COMBAT_PHASE_PRE; + this.postEvent = EventType.COMBAT_PHASE_POST; + this.steps.add(new Step(PhaseStep.BEGIN_COMBAT)); + this.steps.add(new Step(PhaseStep.DECLARE_ATTACKERS)); + this.steps.add(new Step(PhaseStep.DECLARE_BLOCKERS)); + this.steps.add(new Step(PhaseStep.FIRST_COMBAT_DAMAGE)); + this.steps.add(new Step(PhaseStep.COMBAT_DAMAGE)); + this.steps.add(new Step(PhaseStep.END_COMBAT)); + } + +} diff --git a/Mage/src/mage/game/turn/EndPhase.java b/Mage/src/mage/game/turn/EndPhase.java new file mode 100644 index 0000000000..0a45055092 --- /dev/null +++ b/Mage/src/mage/game/turn/EndPhase.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class EndPhase extends Phase { + + public EndPhase() { + this.type = TurnPhase.END; + this.event = EventType.END_PHASE; + this.preEvent = EventType.END_PHASE_PRE; + this.postEvent = EventType.END_PHASE_POST; + this.steps.add(new Step(PhaseStep.END_TURN)); + this.steps.add(new Step(PhaseStep.CLEANUP)); + } + +} diff --git a/Mage/src/mage/game/turn/Phase.java b/Mage/src/mage/game/turn/Phase.java new file mode 100644 index 0000000000..a3de5dee82 --- /dev/null +++ b/Mage/src/mage/game/turn/Phase.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public abstract class Phase implements Serializable { + + protected TurnPhase type; + protected List steps = new ArrayList(); + protected EventType event; + protected EventType preEvent; + protected EventType postEvent; + + protected UUID activePlayerId; + protected Step currentStep; + protected int count; + + public TurnPhase getType() { + return type; + } + + public PhaseStep getStep() { + if (currentStep != null) + return currentStep.getType(); + return null; + } + + public void resetCount() { + count = 0; + } + + public int getCount() { + return count; + } + + public boolean play(Game game, UUID activePlayerId) { + if (game.isGameOver()) + return false; + + this.activePlayerId = activePlayerId; + + if (!game.replaceEvent(new GameEvent(event, null, null, activePlayerId))) { + game.fireEvent(new GameEvent(preEvent, null, null, activePlayerId)); + + for (Step step: steps) { + if (game.isGameOver()) + return false; + currentStep = step; + if (step.play(game, activePlayerId)) { + //20091005 - 500.4/703.4n + game.emptyManaPools(); + game.saveState(); + //20091005 - 500.9 + playExtraSteps(game, step.getType()); + } + } + count++; + game.fireEvent(new GameEvent(postEvent, null, null, activePlayerId)); + return true; + } + return false; + } + + private void playExtraSteps(Game game, PhaseStep afterStep) { + while (true) { + PhaseStep extraStep = game.getState().getTurnMods().extraStep(activePlayerId, afterStep); + if (extraStep == null) + return; + Step step = new Step(extraStep); + currentStep = step; + step.play(game, activePlayerId); + } + } + +} diff --git a/Mage/src/mage/game/turn/PostCombatMainPhase.java b/Mage/src/mage/game/turn/PostCombatMainPhase.java new file mode 100644 index 0000000000..9aa63d452d --- /dev/null +++ b/Mage/src/mage/game/turn/PostCombatMainPhase.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PostCombatMainPhase extends Phase { + + public PostCombatMainPhase() { + this.type = TurnPhase.POSTCOMBAT_MAIN; + this.event = EventType.POSTCOMBAT_MAIN_PHASE; + this.preEvent = EventType.POSTCOMBAT_MAIN_PHASE_PRE; + this.postEvent = EventType.POSTCOMBAT_MAIN_STEP_POST; + this.steps.add(new Step(PhaseStep.POSTCOMBAT_MAIN)); + } + +} diff --git a/Mage/src/mage/game/turn/PreCombatMainPhase.java b/Mage/src/mage/game/turn/PreCombatMainPhase.java new file mode 100644 index 0000000000..390f224935 --- /dev/null +++ b/Mage/src/mage/game/turn/PreCombatMainPhase.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; +import mage.game.events.GameEvent.EventType; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PreCombatMainPhase extends Phase { + + public PreCombatMainPhase() { + this.type = TurnPhase.PRECOMBAT_MAIN; + this.event = EventType.PRECOMBAT_MAIN_PHASE; + this.preEvent = EventType.PRECOMBAT_MAIN_PHASE_PRE; + this.postEvent = EventType.PRECOMBAT_MAIN_PHASE_POST; + this.steps.add(new Step(PhaseStep.PRECOMBAT_MAIN)); + } + +} diff --git a/Mage/src/mage/game/turn/Step.java b/Mage/src/mage/game/turn/Step.java new file mode 100644 index 0000000000..1b53115c2d --- /dev/null +++ b/Mage/src/mage/game/turn/Step.java @@ -0,0 +1,90 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import java.io.Serializable; +import java.util.UUID; +import mage.Constants.PhaseStep; +import mage.game.Game; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Step implements Serializable { + + private PhaseStep type; + + public Step(PhaseStep type) { + this.type = type; + } + + public PhaseStep getType() { + return type; + } + + public boolean play(Game game, UUID activePlayerId) { + switch(type) { + case UNTAP: + return game.playUntapStep(activePlayerId); + case UPKEEP: + return game.playUpkeepStep(activePlayerId); + case DRAW: + return game.playDrawStep(activePlayerId); + case PRECOMBAT_MAIN: + return game.playPreCombatMainStep(activePlayerId); + case BEGIN_COMBAT: + return game.playBeginCombatStep(activePlayerId); + case DECLARE_ATTACKERS: + return game.playDeclareAttackersStep(activePlayerId); + case DECLARE_BLOCKERS: + if (!game.getCombat().noAttackers()) + return game.playDeclareBlockersStep(activePlayerId); + return false; + case FIRST_COMBAT_DAMAGE: + if (!game.getCombat().noAttackers() && game.getCombat().hasFirstOrDoubleStrike(game)) + return game.playCombatDamageStep(activePlayerId, true); + return false; + case COMBAT_DAMAGE: + if (!game.getCombat().noAttackers()) + return game.playCombatDamageStep(activePlayerId, false); + return false; + case END_COMBAT: + return game.playEndCombatStep(activePlayerId); + case POSTCOMBAT_MAIN: + return game.playPostMainStep(activePlayerId); + case END_TURN: + return game.playEndStep(activePlayerId); + case CLEANUP: + return game.playCleanupStep(activePlayerId); + } + return false; + } + +} diff --git a/Mage/src/mage/game/turn/Turn.java b/Mage/src/mage/game/turn/Turn.java index b3ae325c75..936341019d 100644 --- a/Mage/src/mage/game/turn/Turn.java +++ b/Mage/src/mage/game/turn/Turn.java @@ -29,6 +29,8 @@ package mage.game.turn; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.Constants.PhaseStep; import mage.Constants.TurnPhase; @@ -40,159 +42,97 @@ import mage.game.Game; */ public class Turn implements Serializable { - private TurnPhase phase; - private PhaseStep step; + private Phase currentPhase; private UUID activePlayerId; - private UUID priorityPlayerId; + private List phases = new ArrayList(); + + public Turn() { + phases.add(new BeginningPhase()); + phases.add(new PreCombatMainPhase()); + phases.add(new CombatPhase()); + phases.add(new PostCombatMainPhase()); + phases.add(new EndPhase()); + } public TurnPhase getPhase() { - return phase; + if (currentPhase != null) + return currentPhase.getType(); + return null; + } + + public Phase getPhase(TurnPhase turnPhase) { + for (Phase phase: phases) { + if (phase.getType() == turnPhase) { + return phase; + } + } + return null; } public PhaseStep getStep() { - return step; - } - - public UUID getActivePlayerId() { - return activePlayerId; - } - - public void setActivePlayerId(UUID activePlayerId) { - this.activePlayerId = activePlayerId; - } - - public UUID getPriorityPlayerId() { - return priorityPlayerId; - } - - public void setPriorityPlayerId(UUID priorityPlayerId) { - this.priorityPlayerId = priorityPlayerId; - } - - private boolean nextStep(Game game) { - if (step == null) { - phase = TurnPhase.BEGINNING; - step = PhaseStep.UNTAP; - return true; - } - switch(step) { - case UNTAP: - step = PhaseStep.UPKEEP; - return true; - case UPKEEP: - step = PhaseStep.DRAW; - return true; - case DRAW: - phase = TurnPhase.PRECOMBAT_MAIN; - step = PhaseStep.PRECOMBAT_MAIN; - return true; - case PRECOMBAT_MAIN: - phase = TurnPhase.COMBAT; - step = PhaseStep.BEGIN_COMBAT; - return true; - case BEGIN_COMBAT: - step = PhaseStep.DECLARE_ATTACKERS; - return true; - case DECLARE_ATTACKERS: - //20091005 - 508.6 - if (game.getCombat().getGroups().size() > 0) - step = PhaseStep.DECLARE_BLOCKERS; - else - step = PhaseStep.END_COMBAT; - return true; - case DECLARE_BLOCKERS: - //20091005 - 510.5 - if (game.getCombat().hasFirstOrDoubleStrike(game)) - step = PhaseStep.FIRST_COMBAT_DAMAGE; - else - step = PhaseStep.COMBAT_DAMAGE; - return true; - case FIRST_COMBAT_DAMAGE: - step = PhaseStep.COMBAT_DAMAGE; - return true; - case COMBAT_DAMAGE: - step = PhaseStep.END_COMBAT; - return true; - case END_COMBAT: - phase = TurnPhase.POSTCOMBAT_MAIN; - step = PhaseStep.POSTCOMBAT_MAIN; - return true; - case POSTCOMBAT_MAIN: - phase = TurnPhase.END; - step = PhaseStep.END_TURN; - return true; - case END_TURN: - step = PhaseStep.CLEANUP; - return true; - case CLEANUP: - return false; - } - - return false; + if (currentPhase != null) + return currentPhase.getStep(); + return null; } public void play(Game game, UUID activePlayerId) { if (game.isGameOver()) return; - phase = null; - step = null; this.activePlayerId = activePlayerId; + resetCounts(); game.getPlayer(activePlayerId).beginTurn(); - while (nextStep(game)) { - playStep(game); - game.saveState(); + for (Phase phase: phases) { + if (game.isGameOver()) + return; + currentPhase = phase; + if (phase.play(game, activePlayerId)) { + //20091005 - 500.4/703.4n + game.emptyManaPools(); + game.saveState(); + //20091005 - 500.8 + playExtraPhases(game, phase.getType()); + } + } + //20091005 - 500.7 + playExtraTurns(game); + } + + private void resetCounts() { + for (Phase phase: phases) { + phase.resetCount(); } } - private void playStep(Game game) { - if (game.isGameOver()) + private void playExtraPhases(Game game, TurnPhase afterPhase) { + TurnPhase extraPhase = game.getState().getTurnMods().extraPhase(activePlayerId, afterPhase); + if (extraPhase == null) return; - - switch(step) { - case UNTAP: - game.playUntapStep(); - break; - case UPKEEP: - game.playUpkeepStep(); - break; - case DRAW: - game.playDrawStep(); + Phase phase; + switch(extraPhase) { + case BEGINNING: + phase = new BeginningPhase(); break; case PRECOMBAT_MAIN: - game.playPreCombatMainStep(); + phase = new PreCombatMainPhase(); break; - case BEGIN_COMBAT: - game.playBeginCombatStep(); - break; - case DECLARE_ATTACKERS: - game.playDeclareAttackersStep(); - break; - case DECLARE_BLOCKERS: - game.playDeclareBlockersStep(); - break; - case FIRST_COMBAT_DAMAGE: - game.playCombatDamageStep(true); - break; - case COMBAT_DAMAGE: - game.playCombatDamageStep(false); - break; - case END_COMBAT: - game.playEndCombatStep(); + case COMBAT: + phase = new CombatPhase(); break; case POSTCOMBAT_MAIN: - game.playPostMainStep(); - break; - case END_TURN: - game.playEndStep(); - break; - case CLEANUP: - game.playCleanupStep(); + phase = new PostCombatMainPhase(); break; + default: + phase = new EndPhase(); } - //20091005 - 500.4/703.4n - game.emptyManaPools(); + currentPhase = phase; + phase.play(game, activePlayerId); } + private void playExtraTurns(Game game) { + while (game.getState().getTurnMods().extraTurn(activePlayerId)) { + this.play(game, activePlayerId); + } + } } diff --git a/Mage/src/mage/game/turn/TurnMod.java b/Mage/src/mage/game/turn/TurnMod.java new file mode 100644 index 0000000000..6d68eb911f --- /dev/null +++ b/Mage/src/mage/game/turn/TurnMod.java @@ -0,0 +1,103 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import java.io.Serializable; +import java.util.UUID; +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; + +/** + * stores extra turns, phases or steps + * + * @author BetaSteward_at_googlemail.com + */ +public class TurnMod implements Serializable { + + private UUID playerId; + private boolean extraTurn; + private TurnPhase extraPhase; + private PhaseStep extraStep; + private TurnPhase afterPhase; + private PhaseStep afterStep; + + public TurnMod(UUID playerId) { + this.playerId = playerId; + this.extraTurn = true; + } + + /** + * + * @param playerId + * @param extraPhase + * @param afterPhase - set to null if extraPhase is after the next phase + */ + public TurnMod(UUID playerId, TurnPhase extraPhase, TurnPhase afterPhase) { + this.playerId = playerId; + this.extraPhase = extraPhase; + this.afterPhase = afterPhase; + } + + /** + * + * @param playerId + * @param extraStep + * @param afterStep - set to null if extraStep is after the next step + */ + public TurnMod(UUID playerId, PhaseStep extraStep, PhaseStep afterStep) { + this.playerId = playerId; + this.extraStep = extraStep; + this.afterStep = afterStep; + } + + public UUID getPlayerId() { + return playerId; + } + + public boolean isExtraTurn() { + return extraTurn; + } + + public TurnPhase getExtraPhase() { + return extraPhase; + } + + public PhaseStep getExtraStep() { + return extraStep; + } + + public TurnPhase getAfterPhase() { + return afterPhase; + } + + public PhaseStep getAfterStep() { + return afterStep; + } + +} diff --git a/Mage/src/mage/game/turn/TurnMods.java b/Mage/src/mage/game/turn/TurnMods.java new file mode 100644 index 0000000000..26ba2efe9a --- /dev/null +++ b/Mage/src/mage/game/turn/TurnMods.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game.turn; + +import java.util.ArrayList; +import java.util.ListIterator; +import java.util.UUID; +import mage.Constants.PhaseStep; +import mage.Constants.TurnPhase; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TurnMods extends ArrayList { + + public boolean extraTurn(UUID playerId) { + ListIterator it = this.listIterator(this.size()); + while (it.hasPrevious()) { + TurnMod turnMod = it.previous(); + if (turnMod.isExtraTurn() == true && turnMod.getPlayerId().equals(playerId)) { + it.remove(); + return true; + } + } + return false; + } + + public PhaseStep extraStep(UUID playerId, PhaseStep afterStep) { + ListIterator it = this.listIterator(this.size()); + while (it.hasPrevious()) { + TurnMod turnMod = it.previous(); + if (turnMod.getExtraStep() != null && turnMod.getPlayerId().equals(playerId) && (turnMod.getAfterStep() == null || turnMod.getAfterStep() == afterStep)) { + it.remove(); + return turnMod.getExtraStep(); + } + } + return null; + } + + public TurnPhase extraPhase(UUID playerId, TurnPhase afterPhase) { + ListIterator it = this.listIterator(this.size()); + while (it.hasPrevious()) { + TurnMod turnMod = it.previous(); + if (turnMod.getExtraPhase() != null && turnMod.getPlayerId().equals(playerId) && turnMod.getExtraPhase() != null && (turnMod.getAfterPhase() == null || turnMod.getAfterPhase() == afterPhase)) { + it.remove(); + return turnMod.getExtraPhase(); + } + } + return null; + } + +} diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 5daa36e30b..13efff23b6 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -35,6 +35,7 @@ import mage.MageItem; import mage.MageObject; import mage.abilities.Abilities; import mage.abilities.ActivatedAbility; +import mage.abilities.TriggeredAbilities; import mage.abilities.TriggeredAbility; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.VariableManaCost; @@ -58,6 +59,7 @@ import mage.target.common.TargetCardInLibrary; */ public interface Player extends MageItem { + public boolean isHuman(); public Deck getDeck(); public void setDeck(Deck deck); public String getName(); @@ -79,7 +81,7 @@ public interface Player extends MageItem { public boolean hasLeft(); public ManaPool getManaPool(); - public void init(); + public void init(Game game); public void reset(); public void shuffleLibrary(Game game); public int drawCards(int num, Game game); @@ -97,9 +99,10 @@ public interface Player extends MageItem { public boolean activateAbility(ActivatedAbility ability, Game game); public boolean triggerAbility(TriggeredAbility ability, Game game); public boolean canTarget(MageObject source); - public void handleEvent(GameEvent event, Game game); + public void checkTriggers(GameEvent event, Game game); public void discard(int amount, Game game); public void discardToMax(Game game); + public boolean discard(Card card, Game game); public void lost(Game game); public void won(Game game); public void leaveGame(); @@ -125,6 +128,7 @@ public interface Player extends MageItem { public abstract boolean playXMana(VariableManaCost cost, Game game); public abstract boolean searchCards(Cards cards, TargetCard target, Game game); public abstract int chooseEffect(List rEffects, Game game); + public abstract TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game); public abstract void selectAttackers(Game game); public abstract void selectBlockers(Game game); public abstract void assignDamage(int damage, List targets, UUID sourceId, Game game); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 23fec1efa4..befb8eb350 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -1,10 +1,10 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * -* Redistribution and use in source and binary forms, with or without modification, are +* Redistribution and use in ability and binary forms, with or without modification, are * permitted provided that the following conditions are met: * -* 1. Redistributions of source code must retain the above copyright notice, this list of +* 1. Redistributions of ability code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list @@ -71,6 +71,7 @@ public abstract class PlayerImpl implements Player, Serializable { protected UUID playerId; protected String name; + protected boolean human; protected int life; protected boolean wins; protected boolean loses; @@ -95,7 +96,7 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public void init() { + public void init(Game game) { this.hand.clear(); this.graveyard.clear(); this.abilities.clear(); @@ -106,6 +107,9 @@ public abstract class PlayerImpl implements Player, Serializable { this.passed = false; this.passedTurn = false; library.addAll(deck.getCards()); + for (Card card: deck.getCards().values()) { + game.getState().getWatchers().addAll(card.getWatchers()); + } } @Override @@ -131,9 +135,9 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public void handleEvent(GameEvent event, Game game) { - hand.handleEvent(event, game); - graveyard.handleEvent(event, game); + public void checkTriggers(GameEvent event, Game game) { + hand.checkTriggers(event, game); + graveyard.checkTriggers(event, game); } @Override @@ -220,13 +224,16 @@ public abstract class PlayerImpl implements Player, Serializable { game.fireInformEvent(name + " discards " + Integer.toString(amount) + " card" + (amount > 1?"s":"")); } - protected void discard(Card card, Game game) { + @Override + public boolean discard(Card card, Game game) { //20091005 - 701.1 if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD, playerId, playerId))) { removeFromHand(card, game); putInGraveyard(card, game, false); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, playerId, playerId)); + return true; } + return false; } @Override @@ -278,10 +285,12 @@ public abstract class PlayerImpl implements Player, Serializable { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, card.getId(), playerId))) { game.bookmarkState(); removeFromHand(card, game); + game.getStack().push(new Spell(card, playerId)); + card.getSpellAbility().clear(); if (card.getSpellAbility().activate(game, noMana)) { for (KickerAbility ability: card.getAbilities().getKickerAbilities()) { - ability.activate(game, false); + ability.copy().activate(game, false); } game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, card.getId(), playerId)); game.removeLastBookmark(); @@ -301,6 +310,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (putOntoBattlefield(card, game)) { landsPlayed++; game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), playerId)); + game.fireInformEvent(name + " plays " + card.getName()); game.removeLastBookmark(); return true; } @@ -327,6 +337,7 @@ public abstract class PlayerImpl implements Player, Serializable { game.getStack().push(new StackAbility(ability, playerId)); if (ability.activate(game, false)) { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATED_ABILITY, ability.getId(), playerId)); + game.fireInformEvent(name + ability.getActivatedMessage(game)); game.removeLastBookmark(); return true; } @@ -345,26 +356,30 @@ public abstract class PlayerImpl implements Player, Serializable { result = playLand(hand.get(ability.getSourceId()), game); } else if (ability instanceof ManaAbility) { - result = playManaAbility((ManaAbility)ability, game); + result = playManaAbility((ManaAbility)ability.copy(), game); } else if (ability instanceof SpellAbility) { result = cast(hand.get(ability.getSourceId()), game, false); } else { - result = playAbility(ability, game); + result = playAbility((ActivatedAbility)ability.copy(), game); } - if (result && !(ability instanceof ManaAbility)) - game.fireInformEvent(name + ability.getActivatedMessage(game)); return result; } @Override - public boolean triggerAbility(TriggeredAbility ability, Game game) { + public boolean triggerAbility(TriggeredAbility source, Game game) { + //20091005 - 603.3c, 603.3d + game.saveState(); + game.bookmarkState(); + TriggeredAbility ability = (TriggeredAbility) source.copy(); + game.getStack().push(new StackAbility(ability, playerId)); if (ability.activate(game, false)) { - game.getStack().push(new StackAbility(ability, playerId)); + game.removeLastBookmark(); return true; } + game.restoreState(); return false; } @@ -452,6 +467,11 @@ public abstract class PlayerImpl implements Player, Serializable { return name; } + @Override + public boolean isHuman() { + return human; + } + @Override public Library getLibrary() { return library; @@ -627,14 +647,18 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean searchLibrary(TargetCardInLibrary target, Game game) { //20091005 - 701.14c - if (library.count(target.getFilter()) < target.getNumberOfTargets()) { - TargetCardInLibrary newTarget = new TargetCardInLibrary(library.count(target.getFilter()), target.getMaxNumberOfTargets(), target.getFilter()); - searchCards(new CardsImpl(Zone.LIBRARY, getLibrary().getCards()), newTarget, game); + if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.SEARCH_LIBRARY, playerId, playerId))) { + if (library.count(target.getFilter()) < target.getNumberOfTargets()) { + TargetCardInLibrary newTarget = new TargetCardInLibrary(library.count(target.getFilter()), target.getMaxNumberOfTargets(), target.getFilter()); + searchCards(new CardsImpl(Zone.LIBRARY, getLibrary().getCards()), newTarget, game); + } + else { + searchCards(new CardsImpl(Zone.LIBRARY, getLibrary().getCards()), target, game); + } + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SEARCHED, playerId, playerId)); + return true; } - else { - searchCards(new CardsImpl(Zone.LIBRARY, getLibrary().getCards()), target, game); - } - return true; + return false; } } diff --git a/Mage/src/mage/target/Target.java b/Mage/src/mage/target/Target.java index 42d286fd3d..eaac193d9a 100644 --- a/Mage/src/mage/target/Target.java +++ b/Mage/src/mage/target/Target.java @@ -31,6 +31,7 @@ package mage.target; import java.io.Serializable; import java.util.List; import java.util.UUID; +import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.Ability; import mage.filter.Filter; @@ -46,6 +47,7 @@ public interface Target extends Serializable { public boolean doneChosing(); public void clearChosen(); public boolean canChoose(UUID sourceId, Game game); + public boolean choose(Outcome outcome, Game game); public String getMessage(); public String getTargetName(); public String getTargetedName(Game game); diff --git a/Mage/src/mage/target/TargetImpl.java b/Mage/src/mage/target/TargetImpl.java index 0c3bb87002..1fe13aa953 100644 --- a/Mage/src/mage/target/TargetImpl.java +++ b/Mage/src/mage/target/TargetImpl.java @@ -31,11 +31,13 @@ package mage.target; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import mage.Constants.Outcome; import mage.Constants.Zone; import mage.abilities.Ability; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.players.Player; /** * @@ -51,6 +53,7 @@ public abstract class TargetImpl implements Target { protected int minNumberOfTargets; protected boolean required = false; protected Ability source; + protected boolean chosen = false; @Override public int getNumberOfTargets() { @@ -89,7 +92,7 @@ public abstract class TargetImpl implements Target { @Override public boolean isChosen() { - return targets.size() >= minNumberOfTargets; + return chosen; } @Override @@ -100,6 +103,7 @@ public abstract class TargetImpl implements Target { @Override public void clearChosen() { targets.clear(); + chosen = false; } /** @@ -121,6 +125,25 @@ public abstract class TargetImpl implements Target { } } + @Override + public boolean choose(Outcome outcome, Game game) { + Player player = game.getPlayer(this.source.getControllerId()); + while (!isChosen()) { + chosen = targets.size() >= minNumberOfTargets; + if (!player.chooseTarget(outcome, this, game)) { + return chosen; + } + chosen = targets.size() >= minNumberOfTargets; + } + while (!doneChosing()) { + if (!player.chooseTarget(outcome, this, game)) { + break; + } + } + return true; + } + + @Override public boolean isLegal(Game game) { for (UUID targetId: targets) { diff --git a/Mage/src/mage/target/TargetObject.java b/Mage/src/mage/target/TargetObject.java index 411b39c8ac..b4e1397fce 100644 --- a/Mage/src/mage/target/TargetObject.java +++ b/Mage/src/mage/target/TargetObject.java @@ -32,7 +32,6 @@ import java.util.UUID; import mage.Constants.Zone; import mage.MageObject; import mage.game.Game; -import mage.players.Player; /** * diff --git a/Mage/src/mage/target/Targets.java b/Mage/src/mage/target/Targets.java index f35d7efd1c..0d8bed3c67 100644 --- a/Mage/src/mage/target/Targets.java +++ b/Mage/src/mage/target/Targets.java @@ -83,10 +83,9 @@ public class Targets extends ArrayList { public boolean choose(Outcome outcome, Game game) { if (this.size() > 0) { - Player player = game.getPlayer(this.source.getControllerId()); while (!isChosen()) { Target target = this.getUnchosen().get(0); - if (!player.chooseTarget(outcome, target, game)) + if (!target.choose(outcome, game)) return false; } } diff --git a/Mage/src/mage/target/common/TargetCardInGraveyard.java b/Mage/src/mage/target/common/TargetCardInGraveyard.java index 4cce1bffdb..9f64dc8143 100644 --- a/Mage/src/mage/target/common/TargetCardInGraveyard.java +++ b/Mage/src/mage/target/common/TargetCardInGraveyard.java @@ -55,12 +55,12 @@ public class TargetCardInGraveyard extends TargetCard { public TargetCardInGraveyard(int minNumTargets, int maxNumTargets, FilterCard filter) { super(minNumTargets, maxNumTargets, Zone.HAND, filter); - this.targetName = "card in graveyard"; + this.targetName = filter.getMessage(); } @Override public boolean canTarget(UUID id, Game game) { - Card card = game.getPlayer(this.source.getControllerId()).getHand().get(id); + Card card = game.getPlayer(this.source.getControllerId()).getGraveyard().get(id); if (card != null) return filter.match(card); return false; diff --git a/Mage/src/mage/target/common/TargetCardInHand.java b/Mage/src/mage/target/common/TargetCardInHand.java index 7412106b66..ad4e91b21e 100644 --- a/Mage/src/mage/target/common/TargetCardInHand.java +++ b/Mage/src/mage/target/common/TargetCardInHand.java @@ -41,29 +41,26 @@ import mage.target.TargetCard; */ public class TargetCardInHand extends TargetCard { - protected UUID playerId; - - public TargetCardInHand(UUID playerId) { - this(1, 1, new FilterCard(), playerId); + public TargetCardInHand() { + this(1, 1, new FilterCard()); } - public TargetCardInHand(FilterCard filter, UUID playerId) { - this(1, 1, filter, playerId); + public TargetCardInHand(FilterCard filter) { + this(1, 1, filter); } - public TargetCardInHand(int numTargets, FilterCard filter, UUID playerId) { - this(numTargets, numTargets, filter, playerId); + public TargetCardInHand(int numTargets, FilterCard filter) { + this(numTargets, numTargets, filter); } - public TargetCardInHand(int minNumTargets, int maxNumTargets, FilterCard filter, UUID playerId) { + public TargetCardInHand(int minNumTargets, int maxNumTargets, FilterCard filter) { super(minNumTargets, maxNumTargets, Zone.HAND, filter); - this.targetName = "card in hand"; - this.playerId = playerId; + this.targetName = filter.getMessage(); } @Override public boolean canTarget(UUID id, Game game) { - Card card = game.getPlayer(playerId).getHand().get(id); + Card card = game.getPlayer(this.source.getControllerId()).getHand().get(id); if (card != null) return filter.match(card); return false; diff --git a/Mage/src/mage/target/common/TargetCardInLibrary.java b/Mage/src/mage/target/common/TargetCardInLibrary.java index 647af6cc33..07ee3fe0f1 100644 --- a/Mage/src/mage/target/common/TargetCardInLibrary.java +++ b/Mage/src/mage/target/common/TargetCardInLibrary.java @@ -31,7 +31,6 @@ package mage.target.common; import java.util.UUID; import mage.Constants.Zone; import mage.cards.Card; -import mage.cards.Cards; import mage.filter.FilterCard; import mage.game.Game; import mage.target.TargetCard; diff --git a/Mage/src/mage/target/common/TargetDiscard.java b/Mage/src/mage/target/common/TargetDiscard.java index d0dfda5d2c..62a396109d 100644 --- a/Mage/src/mage/target/common/TargetDiscard.java +++ b/Mage/src/mage/target/common/TargetDiscard.java @@ -29,18 +29,46 @@ package mage.target.common; import java.util.UUID; +import mage.Constants.Zone; +import mage.cards.Card; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.target.TargetCard; /** * * @author BetaSteward_at_googlemail.com */ -public class TargetDiscard extends TargetCardInHand { +public class TargetDiscard extends TargetCard { + + private UUID playerId; public TargetDiscard(UUID playerId) { - super(playerId); - filter.getOwnerId().add(playerId); + this(1, 1, new FilterCard(), playerId); + } + + public TargetDiscard(FilterCard filter, UUID playerId) { + this(1, 1, filter, playerId); + } + + public TargetDiscard(int numTargets, FilterCard filter, UUID playerId) { + this(numTargets, numTargets, filter, playerId); + } + + public TargetDiscard(int minNumTargets, int maxNumTargets, FilterCard filter, UUID playerId) { + super(minNumTargets, maxNumTargets, Zone.HAND, filter); + this.filter.getOwnerId().add(playerId); + this.playerId = playerId; this.required = true; this.targetName = "card to discard"; } + @Override + public boolean canTarget(UUID id, Game game) { + Card card = game.getPlayer(playerId).getHand().get(id); + if (card != null) + return filter.match(card); + return false; + } + } diff --git a/Mage/src/mage/target/common/TargetLandPermanent.java b/Mage/src/mage/target/common/TargetLandPermanent.java index 64bb2dabfb..ef935720b8 100644 --- a/Mage/src/mage/target/common/TargetLandPermanent.java +++ b/Mage/src/mage/target/common/TargetLandPermanent.java @@ -28,7 +28,6 @@ package mage.target.common; -import mage.Constants.CardType; import mage.Constants.TargetController; import mage.filter.common.FilterLandPermanent; import mage.target.TargetPermanent; diff --git a/Mage/src/mage/target/common/TargetNonBasicLandPermanent.java b/Mage/src/mage/target/common/TargetNonBasicLandPermanent.java index f44d06c650..66bf972bde 100644 --- a/Mage/src/mage/target/common/TargetNonBasicLandPermanent.java +++ b/Mage/src/mage/target/common/TargetNonBasicLandPermanent.java @@ -41,6 +41,7 @@ public class TargetNonBasicLandPermanent extends TargetLandPermanent { filter.getName().add("Mountain"); filter.getName().add("Swamp"); filter.getName().add("Plains"); + this.targetName = "nonbasic land"; } } diff --git a/Mage/src/mage/target/common/TargetOpponent.java b/Mage/src/mage/target/common/TargetOpponent.java new file mode 100644 index 0000000000..6b3802406d --- /dev/null +++ b/Mage/src/mage/target/common/TargetOpponent.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.target.common; + +import java.util.UUID; +import mage.game.Game; +import mage.target.TargetPlayer; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TargetOpponent extends TargetPlayer { + + public TargetOpponent() { + super(); + this.targetName = "opponent"; + } + + @Override + public boolean canChoose(UUID sourceId, Game game) { + filter.getPlayerId().clear(); + filter.getPlayerId().addAll(game.getOpponents(this.getAbility().getControllerId())); + return super.canChoose(sourceId, game); + } + + @Override + public boolean canTarget(UUID id, Game game) { + filter.getPlayerId().clear(); + filter.getPlayerId().addAll(game.getOpponents(this.getAbility().getControllerId())); + return super.canTarget(id, game); + } + +} diff --git a/Mage/src/mage/util/Copier.java b/Mage/src/mage/util/Copier.java index 662eccc4ac..524ef3451c 100644 --- a/Mage/src/mage/util/Copier.java +++ b/Mage/src/mage/util/Copier.java @@ -28,9 +28,13 @@ package mage.util; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.net.URLClassLoader; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; /** * @@ -38,6 +42,12 @@ import java.io.ObjectOutputStream; */ public class Copier { + private static ClassLoader loader; + + public static void setLoader(ClassLoader loader) { + Copier.loader = loader; + } + public T copy(T obj) { T copy = null; try { @@ -51,7 +61,7 @@ public class Copier { // Retrieve an input stream from the byte array and read // a copy of the object back in. - ObjectInputStream in = new ObjectInputStream(fbos.getInputStream()); + ObjectInputStream in = new CopierObjectInputStream(loader, fbos.getInputStream()); copy = (T) in.readObject(); } catch(IOException e) { @@ -63,4 +73,39 @@ public class Copier { return copy; } + + public byte[] copyCompressed(T obj) { + try { + FastByteArrayOutputStream fbos = new FastByteArrayOutputStream(); + ObjectOutputStream out= new ObjectOutputStream(new GZIPOutputStream(fbos)); + + // Write the object out to a byte array + out.writeObject(obj); + out.flush(); + out.close(); + + byte[] copy = new byte[fbos.getSize()]; + System.arraycopy(fbos.getByteArray(), 0, copy, 0, fbos.getSize()); + return copy; + } + catch(IOException e) { + e.printStackTrace(); + } + return null; + } + + public T uncompressCopy(byte[] buffer) { + T copy = null; + try { + ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new ByteArrayInputStream(buffer))); + copy = (T) in.readObject(); + } + catch(IOException e) { + e.printStackTrace(); + } + catch(ClassNotFoundException cnfe) { + cnfe.printStackTrace(); + } + return copy; + } } diff --git a/Mage/src/mage/util/CopierObjectInputStream.java b/Mage/src/mage/util/CopierObjectInputStream.java new file mode 100644 index 0000000000..5482ba31a1 --- /dev/null +++ b/Mage/src/mage/util/CopierObjectInputStream.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.io.StreamCorruptedException; +import java.net.URLClassLoader; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CopierObjectInputStream extends ObjectInputStream { + ClassLoader myLoader = null; + + public CopierObjectInputStream(ClassLoader newLoader, InputStream theStream) throws IOException, StreamCorruptedException { + super(theStream); + myLoader = newLoader; + } + + @Override + protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException + { + Class theClass = null; + + try { + theClass = Class.forName(osc.getName(), true, myLoader); + } + catch (Exception e) { + e.printStackTrace(); + } + + return theClass; + } + +} diff --git a/Mage/src/mage/util/FastByteArrayInputStream.java b/Mage/src/mage/util/FastByteArrayInputStream.java index 6308e30665..6e540f3040 100644 --- a/Mage/src/mage/util/FastByteArrayInputStream.java +++ b/Mage/src/mage/util/FastByteArrayInputStream.java @@ -59,6 +59,7 @@ public class FastByteArrayInputStream extends InputStream { return count - pos; } + @Override public final int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1; } diff --git a/Mage/src/mage/util/FastByteArrayOutputStream.java b/Mage/src/mage/util/FastByteArrayOutputStream.java index 6ceaf56295..98a33e185e 100644 --- a/Mage/src/mage/util/FastByteArrayOutputStream.java +++ b/Mage/src/mage/util/FastByteArrayOutputStream.java @@ -96,6 +96,7 @@ public class FastByteArrayOutputStream extends OutputStream { size += len; } + @Override public final void write(int b) { verifyBufferSize(size + 1); buf[size++] = (byte) b;