This commit is contained in:
BetaSteward 2010-04-11 19:52:34 +00:00
parent 058af9a48e
commit cbb37e7933
126 changed files with 3253 additions and 911 deletions

View file

@ -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<Cost> getCosts();
public void addCost(Cost cost);
public ManaCosts getManaCosts();
public void addManaCost(ManaCost cost);
public List<AlternativeCost> 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);

View file

@ -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<Cost> costs = new CostsImpl<Cost>(this);
protected List<AlternativeCost> alternativeCosts = new ArrayList<AlternativeCost>();
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<AlternativeCost> 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) {

View file

@ -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);
}

View file

@ -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<Cost> 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<Cost> 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;

View file

@ -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;

View file

@ -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();
}
}

View file

@ -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<TriggeredAbility> {
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<TriggeredAbility> 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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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) {
// }
//}

View file

@ -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);
}

View file

@ -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)

View file

@ -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))

View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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());
}

View file

@ -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 {
}

View file

@ -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<T extends Cost> extends ArrayList<T> implements Costs<T> {
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<T> getUnpaid() {
List<T> unpaid = new ArrayList<T>();
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;
}
}

View file

@ -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<Cost> {
protected String name;
public AlternativeCost(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isAvailable(Game game) {
return true;
}
}

View file

@ -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<T extends Cost> extends List<T>, Cost {
@Override
public boolean add(T cost);
public List<T> getUnpaid();
public List<VariableManaCost> getVariableCosts();
public ManaCosts getManaCosts();
}

View file

@ -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<T extends Cost> extends ArrayList<T> implements Costs<T>
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<VariableManaCost> getVariableCosts() {
List<VariableManaCost> variableCosts = new ArrayList<VariableManaCost>();
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<VariableManaCost> getVariableCosts() {
// List<VariableManaCost> variableCosts = new ArrayList<VariableManaCost>();
// for (T cost: this) {
// if (cost instanceof ManaCosts)
// variableCosts.addAll(((ManaCosts)cost).getVariableCosts());
// }
// return variableCosts;
// }
}

View file

@ -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}";
}
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -59,6 +59,19 @@ public class ManaCosts extends CostsImpl<ManaCost> implements Costs<ManaCost>, 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<ManaCost> implements Costs<ManaCost>, 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<ManaCost> implements Costs<ManaCost>, M
return unpaid;
}
@Override
public List<VariableManaCost> getVariableCosts() {
List<VariableManaCost> variableCosts = new ArrayList<VariableManaCost>();
for (ManaCost cost: this) {
@ -135,6 +147,7 @@ public class ManaCosts extends CostsImpl<ManaCost> implements Costs<ManaCost>, 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<ManaCost> implements Costs<ManaCost>, 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<ManaCost> implements Costs<ManaCost>, M
return options;
}
@Override
public boolean testPay(Mana testMana) {
for (ManaCost cost: this) {
if (cost.testPay(testMana))

View file

@ -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;

View file

@ -67,7 +67,7 @@ public class ContinuousEffects implements Serializable {
public void removeInactiveEffects(Game game) {
for (Iterator<ContinuousEffect> 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();

View file

@ -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);
}

View file

@ -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;
}
}
}

View file

@ -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}";
}
}

View file

@ -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";
}
}

View file

@ -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.";
}
}

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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");
}
}

View file

@ -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");
}
}

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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) {

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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();
}

View file

@ -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

View file

@ -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());
}
}

View file

@ -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";
}
}

View file

@ -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;
}
}

View file

@ -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";
}
}

View file

@ -58,7 +58,7 @@ public class UnblockableAbility extends EvasionAbilityImpl {
@Override
public String getRule() {
return "{this} is unblockable";
return "Unblockable";
}
}

View file

@ -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;

View file

@ -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<String> 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);
}

View file

@ -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;
}
}

View file

@ -41,9 +41,10 @@ public interface Cards extends Map<UUID, Card>, 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<Card> createCards);
public List<Card> getCards(FilterCard filter);
public Card getRandom();
public int count(FilterCard filter);
public void checkTriggers(GameEvent event, Game game);
}

View file

@ -85,9 +85,19 @@ public class CardsImpl extends LinkedHashMap<UUID, Card> 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);
}
}

View file

@ -44,11 +44,16 @@ public class ExpansionSet implements Serializable {
protected String name;
protected List<Class> cards = new ArrayList<Class>();
protected UUID id = UUID.randomUUID();
public List<Class> 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;
}
}

View file

@ -36,6 +36,7 @@ import java.io.Serializable;
*/
public interface DeckValidator extends Serializable {
public String getName();
public boolean validate(Deck deck);
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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<String, Integer> counts, Collection<Card> 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);
}
}
}
}

View file

@ -35,7 +35,7 @@ package mage.counters;
public class PlusOneCounter extends BoostCounter {
public PlusOneCounter() {
super(1, 1);
this(1);
}
public PlusOneCounter(int amount) {

View file

@ -41,6 +41,8 @@ public class FilterCard extends FilterObject<Card> {
protected List<UUID> ownerId = new ArrayList<UUID>();
protected boolean notOwner = false;
protected List<UUID> expansionSetId = new ArrayList<UUID>();
protected boolean notExpansionSetId = false;
public FilterCard() {
super("card");
@ -58,6 +60,9 @@ public class FilterCard extends FilterObject<Card> {
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<Card> {
this.notOwner = notOwner;
}
public List<UUID> 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;

View file

@ -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<Object> 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();

View file

@ -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");
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -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<UUID> 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();

View file

@ -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

View file

@ -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;
}

View file

@ -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<GameState> copier = new Copier<GameState>();
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;
}

View file

@ -43,8 +43,8 @@ public class GameStates {
states.add(gameState.copy());
}
public List<GameState> 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;
}
}

View file

@ -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<String> playerTypes) {
public Table(Game game, DeckValidator validator, List<String> 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<String> 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 {

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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<? extends ActivatedAbility> abilities;
private Collection<? extends Ability> 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<? extends ActivatedAbility> abilities, String[] choices, Cards cards, QueryType queryType, int min, int max, boolean required) {
private PlayerQueryEvent(UUID playerId, String message, Collection<? extends Ability> 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<? extends ActivatedAbility> getAbilities() {
public Collection<? extends Ability> getAbilities() {
return abilities;
}

View file

@ -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<PlayerQueryEvent>, Se
protected final EventDispatcher<PlayerQueryEvent> dispatcher = new EventDispatcher<PlayerQueryEvent>() {};
@Override
public void addListener(Listener<PlayerQueryEvent> listener) {
dispatcher.addListener(listener);
}
@ -67,6 +69,10 @@ public class PlayerQueryEventSource implements EventSource<PlayerQueryEvent>, 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));
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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<CardType> getCardType() {
return card.getCardType();
}
@Override
public List<String> getSubtype() {
return card.getSubtype();
}
@Override
public List<String> 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<Spell>().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<String> getRules() {
return card.getRules();
}
@Override
public Watchers getWatchers() {
return card.getWatchers();
}
@Override
public UUID getExpansionSetId() {
return card.getExpansionSetId();
}
}

View file

@ -53,9 +53,9 @@ public class SpellStack extends Stack<StackObject> {
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);
}
}

View file

@ -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<AlternativeCost> 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) { }
}

View file

@ -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);
}

View file

@ -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));
}
}

Some files were not shown because too many files have changed in this diff Show more