* Reworked non mana costs with variable amount. The values have now to be announced before targeting. Fixed some wrong implementations (Firestorm, Myr Battlesphere, Skeletal Scrying).

This commit is contained in:
LevelX2 2014-03-09 19:47:31 +01:00
parent 2d9f260b1e
commit 7ebb8a9cbe
46 changed files with 1176 additions and 1187 deletions

View file

@ -28,33 +28,43 @@
package mage.abilities;
import mage.constants.AbilityType;
import mage.constants.EffectType;
import mage.constants.Outcome;
import mage.constants.Zone;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.costs.*;
import mage.abilities.costs.AdjustingSourceCosts;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.AlternativeSourceCosts;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.CostsImpl;
import mage.abilities.costs.OptionalAdditionalSourceCosts;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.effects.*;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PostResolveEffect;
import mage.abilities.mana.ManaAbility;
import mage.cards.Card;
import mage.choices.Choice;
import mage.choices.Choices;
import mage.constants.AbilityType;
import mage.constants.EffectType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.command.Emblem;
import mage.game.permanent.PermanentCard;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.game.command.Emblem;
/**
*
* @author BetaSteward_at_googlemail.com
@ -72,7 +82,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
protected ManaCosts<ManaCost> manaCosts;
protected ManaCosts<ManaCost> manaCostsToPay;
protected Costs<Cost> costs;
protected ArrayList<AlternativeCost> alternativeCosts = new ArrayList<AlternativeCost>();
protected ArrayList<AlternativeCost> alternativeCosts = new ArrayList<>();
protected Costs<Cost> optionalCosts;
protected Modes modes;
protected Zone zone;
@ -89,10 +99,10 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
this.originalId = id;
this.abilityType = abilityType;
this.zone = zone;
this.manaCosts = new ManaCostsImpl<ManaCost>();
this.manaCostsToPay = new ManaCostsImpl<ManaCost>();
this.costs = new CostsImpl<Cost>();
this.optionalCosts = new CostsImpl<Cost>();
this.manaCosts = new ManaCostsImpl<>();
this.manaCostsToPay = new ManaCostsImpl<>();
this.costs = new CostsImpl<>();
this.optionalCosts = new CostsImpl<>();
this.modes = new Modes();
}
@ -222,7 +232,8 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
// 20121001 - 601.2b
// If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
// its mana cost; see rule 107.3), the player announces the value of that variable.
VariableManaCost variableManaCost = handleXCosts(game, noMana);
VariableManaCost variableManaCost = handleManaXCosts(game, noMana);
String announceString = handleOtherXCosts(game);
for (UUID modeId :this.getModes().getSelectedModes()) {
this.getModes().setMode(this.getModes().get(modeId));
@ -247,8 +258,11 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
card.adjustTargets(this, game);
}
if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) {
if (variableManaCost != null) {
game.informPlayers(new StringBuilder(card != null ? card.getName(): "").append(": no valid targets with this value of X").toString());
if (variableManaCost != null || announceString != null) {
Player controller = game.getPlayer(this.getControllerId());
if (controller != null) {
game.informPlayer(controller, new StringBuilder(card != null ? card.getName(): "").append(": no valid targets with this value of X").toString());
}
} else {
logger.debug("activate failed - target");
}
@ -305,21 +319,52 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
return false;
}
// inform about x costs now, so canceled announcements are not shown in the log
if (announceString != null) {
game.informPlayers(announceString);
}
if (variableManaCost != null) {
int xValue = getManaCostsToPay().getX();
game.informPlayers(new StringBuilder(game.getPlayer(this.controllerId).getName()).append(" announced a value of ").append(xValue).append(" for ").append(variableManaCost.getText()).toString());
game.informPlayers(new StringBuilder(game.getPlayer(this.controllerId).getName()).append(" announces a value of ").append(xValue).append(" for ").append(variableManaCost.getText()).toString());
}
return true;
}
/**
* Handles the announcement of X mana costs and sets manaCostsToPay.
* Handles the setting of non mana X costs
*
* @param game
* @return announce message
*
*/
protected String handleOtherXCosts(Game game) {
String announceString = null;
for (VariableCost variableCost : this.costs.getVariableCosts()) {
if (!(variableCost instanceof VariableManaCost)) {
int xValue = variableCost.announceXValue(this, game);
costs.add(variableCost.getFixedCostsFromAnnouncedValue(xValue));
// set the xcosts to paid
variableCost.setAmount(xValue);
((Cost) variableCost).setPaid();
String message = new StringBuilder(game.getPlayer(this.controllerId).getName())
.append(" announces a value of ").append(xValue).append(" (").append(variableCost.getActionText()).append(")").toString();
if (announceString == null) {
announceString = message;
} else {
announceString = new StringBuilder(announceString).append(" ").append(message).toString();
}
}
}
return announceString;
}
/**
* Handles X mana costs and sets manaCostsToPay.
*
* @param game
* @param noMana
* @return variableManaCost for late check
* @return variableManaCost for posting to log later
*/
protected VariableManaCost handleXCosts(Game game, boolean noMana) {
protected VariableManaCost handleManaXCosts(Game game, boolean noMana) {
// 20121001 - 601.2b
// If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
// its mana cost; see rule 107.3), the player announces the value of that variable.

View file

@ -213,8 +213,8 @@ public abstract class ActivatedAbilityImpl<T extends ActivatedAbilityImpl<T>> ex
return "";
}
MageObject object = game.getObject(this.sourceId);
return new StringBuilder(" activates ")
.append(object != null ? this.getRule(object.getName()) :this.getRule())
return new StringBuilder(" activates: ")
.append(object != null ? this.formatRule(modes.getText(), object.getName()) :modes.getText())
.append(" from ")
.append(getMessageText(game)).toString();
}

View file

@ -28,16 +28,61 @@
package mage.abilities.costs;
import mage.filter.FilterMana;
import mage.abilities.Ability;
import mage.game.Game;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public interface VariableCost {
/**
* Returns the variable amount if alreaady set
*
* @return
*/
int getAmount();
/**
* Sets the variable amount
*
* @param amount
*/
void setAmount(int amount);
void setFilter(FilterMana filter);
FilterMana getFilter();
/**
* returns the action text (e.g. "creature cards to exile from your hand", "life to pay")
*
* @return
*/
String getActionText();
/**
* Return a min value to announce
*
* @param source
* @param game
* @return
*/
int getMinValue(Ability source, Game game);
/**
* Returns a max value to announce
*
* @param source
* @param game
* @return
*/
int getMaxValue(Ability source, Game game);
/**
* Asks the controller to announce the variable value
* @param source
* @param game
* @return
*/
int announceXValue(Ability source, Game game);
/**
* Returns a fixed cost with the announced variabke value
*
* @param xValue
* @return
*/
Cost getFixedCostsFromAnnouncedValue(int xValue);
}

View file

@ -0,0 +1,166 @@
/*
* 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.UUID;
import mage.abilities.Ability;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
/**
*
* @author LevelX2
* @param <T> variable cost type
*/
public abstract class VariableCostImpl<T extends VariableCostImpl<T>> implements Cost, VariableCost {
protected UUID id;
protected String text;
protected boolean paid;
protected Targets targets;
protected int amountPaid;
protected String xText;
protected String actionText;
@Override
public abstract T copy();
public VariableCostImpl(String actionText) {
this("X", actionText);
}
/**
*
* @param xText string for the defined value
* @param actionText what happens with the value (e.g. "to tap", "to exile from your graveyard")
*/
public VariableCostImpl(String xText, String actionText) {
id = UUID.randomUUID();
paid = false;
targets = new Targets();
amountPaid = 0;
this.xText = xText;
this.actionText = actionText;
}
public VariableCostImpl(final VariableCostImpl cost) {
this.id = cost.id;
this.text = cost.text;
this.paid = cost.paid;
this.targets = cost.targets.copy();
this.xText = cost.xText;
this.actionText = cost.actionText;
}
@Override
public String getText() {
return text;
}
@Override
public String getActionText() {
return actionText;
}
public void addTarget(Target target) {
if (target != null) {
this.targets.add(target);
}
}
@Override
public Targets getTargets() {
return this.targets;
}
@Override
public boolean isPaid() {
return paid;
}
@Override
public void clearPaid() {
paid = false;
amountPaid = 0;
}
@Override
public void setPaid() {
paid = true;
}
@Override
public UUID getId() {
return this.id;
}
@Override
public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
return true; /* not used */
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
return true; /* not used */
}
@Override
public int getAmount() {
return amountPaid;
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
}
@Override
public int getMinValue(Ability source, Game game) {
return 0;
}
@Override
public int getMaxValue(Ability source, Game game) {
return Integer.MAX_VALUE;
}
@Override
public int announceXValue(Ability source, Game game) {
int xValue = 0;
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
xValue = controller.announceXCost(0, getMaxValue(source, game),
new StringBuilder("Announce the number of ").append(actionText).toString(),
game, source, this);
}
return xValue;
}
}

View file

@ -0,0 +1,84 @@
/*
* 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 mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
/**
*
* @author LevelX2
*/
public class DiscardXTargetCost extends VariableCostImpl<DiscardXTargetCost> {
protected FilterCard filter;
public DiscardXTargetCost(FilterCard filter) {
this(filter, false);
}
public DiscardXTargetCost(FilterCard filter, boolean additionalCostText) {
super(new StringBuilder(filter.getMessage()).append(" to discard").toString());
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, discard ":"Discard ")
.append(xText).append(" ").append(filter.getMessage()).toString();
this.filter = filter;
}
public DiscardXTargetCost(final DiscardXTargetCost cost) {
super(cost);
this.filter = cost.filter;
}
@Override
public DiscardXTargetCost copy() {
return new DiscardXTargetCost(this);
}
@Override
public int getMaxValue(Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
return controller.getHand().count(filter, game);
}
return 0;
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
TargetCardInHand target = new TargetCardInHand(xValue, filter);
target.setRequired(true);
return new DiscardTargetCost(target);
}
}

View file

@ -76,14 +76,18 @@ public class ExileFromGraveCost extends CostImpl<ExileFromGraveCost> {
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
if (targets.choose(Outcome.Exile, controllerId, sourceId, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) {
return false;
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.Exile, controllerId, sourceId, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) {
return false;
}
paid |= controller.moveCardToExileWithInfo(card, null, null, sourceId, game, Zone.GRAVEYARD);
}
paid |= card.moveToZone(Zone.EXILED, sourceId, game, false);
}
}
return paid;
}

View file

@ -0,0 +1,86 @@
/*
* 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 mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author LevelX2
*/
public class ExileXFromYourGraveCost extends VariableCostImpl<ExileXFromYourGraveCost> {
protected FilterCard filter;
public ExileXFromYourGraveCost(FilterCard filter) {
this(filter, false);
}
public ExileXFromYourGraveCost(FilterCard filter, boolean additionalCostText) {
super(new StringBuilder(filter.getMessage()).append(" to exile").toString());
this.filter = filter;
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, exile ":"Exile ")
.append(xText).append(" ").append(filter.getMessage()).toString();
}
public ExileXFromYourGraveCost(final ExileXFromYourGraveCost cost) {
super(cost);
this.amountPaid = cost.amountPaid;
this.filter = cost.filter;
}
@Override
public ExileXFromYourGraveCost copy() {
return new ExileXFromYourGraveCost(this);
}
@Override
public int getMaxValue(Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
return controller.getGraveyard().count(filter, game);
}
return 0;
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(xValue, filter);
target.setRequired(true);
return new ExileFromGraveCost(target);
}
}

View file

@ -28,11 +28,9 @@
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.VariableCost;
import mage.filter.FilterMana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.game.Game;
import mage.players.Player;
@ -41,70 +39,20 @@ import mage.players.Player;
* @author LevelX2
*/
public class PayVariableLifeCost extends CostImpl<PayVariableLifeCost> implements VariableCost {
protected int amountPaid = 0;
public class PayVariableLifeCost extends VariableCostImpl<PayVariableLifeCost> {
public PayVariableLifeCost() {
this.text = "pay X life";
this(false);
}
public PayVariableLifeCost(boolean additionalCostText) {
super("life to pay");
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, pay ":"Pay ")
.append(xText).append(" ").append("life").toString();
}
public PayVariableLifeCost(final PayVariableLifeCost cost) {
super(cost);
this.amountPaid = cost.amountPaid;
}
@Override
public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
return controller != null && controller.getLife() > 0;
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
this.amountPaid = controller.getAmount(0, controller.getLife(), "Choose X (life to pay)", game);
if (this.amountPaid> 0) {
controller.loseLife(amountPaid, game);
}
game.informPlayers(new StringBuilder(controller.getName()).append(" pays ").append(amountPaid).append(" life.").toString());
this.paid = true;
}
return paid;
}
@Override
public void clearPaid() {
paid = false;
amountPaid = 0;
}
@Override
public int getAmount() {
return amountPaid;
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
}
/**
* Not Supported
* @param filter
*/
@Override
public void setFilter(FilterMana filter) {
}
/**
* Not supported
* @return
*/
@Override
public FilterMana getFilter() {
return new FilterMana();
}
@Override
@ -112,4 +60,19 @@ public class PayVariableLifeCost extends CostImpl<PayVariableLifeCost> implement
return new PayVariableLifeCost(this);
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
return new PayLifeCost(xValue);
}
@Override
public int getMaxValue(Ability source, Game game) {
int maxValue = 0;
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
maxValue = controller.getLife();
}
return maxValue;
}
}

View file

@ -28,91 +28,46 @@
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.counters.CounterType;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class PayVariableLoyaltyCost extends CostImpl<PayVariableLoyaltyCost> implements VariableCost {
protected int amountPaid = 0;
public class PayVariableLoyaltyCost extends VariableCostImpl<PayVariableLoyaltyCost> {
public PayVariableLoyaltyCost() {
super("loyality counters to remove");
this.text = "-X";
}
public PayVariableLoyaltyCost(final PayVariableLoyaltyCost cost) {
super(cost);
this.amountPaid = cost.amountPaid;
}
@Override
public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
Permanent planeswalker = game.getPermanent(sourceId);
return !planeswalker.isLoyaltyUsed();
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
Permanent planeswalker = game.getPermanent(sourceId);
Player player = game.getPlayer(planeswalker.getControllerId());
this.amountPaid = player.getAmount(0, planeswalker.getCounters().getCount(CounterType.LOYALTY), "Choose X", game);
if (this.amountPaid> 0) {
planeswalker.getCounters().removeCounter(CounterType.LOYALTY, this.amountPaid);
} else if (this.amountPaid < 0) {
planeswalker.getCounters().addCounter(CounterType.LOYALTY.createInstance(Math.abs(this.amountPaid)));
}
planeswalker.setLoyaltyUsed(true);
this.paid = true;
return paid;
}
@Override
public void clearPaid() {
paid = false;
amountPaid = 0;
}
@Override
public int getAmount() {
return amountPaid;
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
}
/**
* Not Supported
* @param filter
*/
@Override
public void setFilter(FilterMana filter) {
}
/**
* Not supported
* @return
*/
@Override
public FilterMana getFilter() {
return new FilterMana();
}
@Override
public PayVariableLoyaltyCost copy() {
return new PayVariableLoyaltyCost(this);
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
return new PayLoyaltyCost(xValue);
}
@Override
public int getMaxValue(Ability source, Game game) {
int maxValue = 0;
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
maxValue = permanent.getCounters().getCount(CounterType.LOYALTY.getName());
}
return maxValue;
}
}

View file

@ -32,17 +32,18 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.Outcome;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.util.CardUtil;
/**
*
@ -53,69 +54,96 @@ public class RemoveCounterCost extends CostImpl<RemoveCounterCost> {
private TargetPermanent target;
private String name;
private CounterType counterTypeToRemove;
private int countersToRemove;
public RemoveCounterCost(TargetPermanent target) {
this(target, null);
}
public RemoveCounterCost(TargetPermanent target, CounterType counterTypeToRemove) {
this(target, counterTypeToRemove, 1);
}
public RemoveCounterCost(TargetPermanent target, CounterType counterTypeToRemove, int countersToRemove) {
this.target = target;
this.counterTypeToRemove = counterTypeToRemove;
text = setText();
this.countersToRemove = countersToRemove;
this.text = setText();
}
public RemoveCounterCost(final RemoveCounterCost cost) {
super(cost);
this.target = cost.target.copy();
this.name = cost.name;
this.countersToRemove = cost.countersToRemove;
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
paid = false;
int countersRemoved = 0;
Player controller = game.getPlayer(controllerId);
if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) {
for (UUID targetId: (List<UUID>)target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
if (permanent.getCounters().size() > 0 && (counterTypeToRemove == null || permanent.getCounters().containsKey(counterTypeToRemove))) {
String counterName = null;
if (counterTypeToRemove != null) {
counterName = counterTypeToRemove.getName();
} else {
if (permanent.getCounters().size() > 1 && counterTypeToRemove == null) {
Choice choice = new ChoiceImpl(true);
Set<String> choices = new HashSet<String>();
for (Counter counter : permanent.getCounters().values()) {
if (permanent.getCounters().getCount(counter.getName()) > 0) {
choices.add(counter.getName());
}
}
choice.setChoices(choices);
choice.setMessage("Choose a counter to remove from " + permanent.getName());
controller.choose(Outcome.UnboostCreature, choice, game);
counterName = choice.getChoice();
if (controller != null) {
target.clearChosen();
if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) {
for (UUID targetId: (List<UUID>)target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
if (permanent.getCounters().size() > 0 && (counterTypeToRemove == null || permanent.getCounters().containsKey(counterTypeToRemove))) {
String counterName = null;
if (counterTypeToRemove != null) {
counterName = counterTypeToRemove.getName();
} else {
for (Counter counter : permanent.getCounters().values()) {
if (counter.getCount() > 0) {
counterName = counter.getName();
if (permanent.getCounters().size() > 1 && counterTypeToRemove == null) {
Choice choice = new ChoiceImpl(true);
Set<String> choices = new HashSet<>();
for (Counter counter : permanent.getCounters().values()) {
if (permanent.getCounters().getCount(counter.getName()) > 0) {
choices.add(counter.getName());
}
}
choice.setChoices(choices);
choice.setMessage("Choose a counter to remove from " + permanent.getName());
controller.choose(Outcome.UnboostCreature, choice, game);
counterName = choice.getChoice();
} else {
for (Counter counter : permanent.getCounters().values()) {
if (counter.getCount() > 0) {
counterName = counter.getName();
}
}
}
}
}
if (counterName != null) {
permanent.removeCounters(counterName, 1, game);
if (permanent.getCounters().getCount(counterName) == 0 ){
permanent.getCounters().removeCounter(counterName);
if (counterName != null) {
int countersLeft = countersToRemove - countersRemoved;
int countersOnPermanent = permanent.getCounters().getCount(counterName);
int numberOfCountersSelected = 1;
if (countersLeft > 1 && countersOnPermanent > 1) {
numberOfCountersSelected = controller.getAmount(1, Math.min(countersLeft, countersOnPermanent),
new StringBuilder("Remove how many counters from ").append(permanent.getName()).toString(), game);
}
permanent.removeCounters(counterName, numberOfCountersSelected, game);
if (permanent.getCounters().getCount(counterName) == 0 ){
permanent.getCounters().removeCounter(counterName);
}
countersRemoved += numberOfCountersSelected;
game.informPlayers(new StringBuilder(controller.getName())
.append(" removes ").append(numberOfCountersSelected == 1 ? "a":numberOfCountersSelected).append(" ")
.append(counterName).append(numberOfCountersSelected == 1 ? " counter from ":" counters from ")
.append(permanent.getName()).toString());
if (countersRemoved == countersToRemove) {
this.paid = true;
break;
}
}
this.paid = true;
game.informPlayers(new StringBuilder(controller.getName()).append(" removes a ").append(counterName).append(" counter from ").append(permanent.getName()).toString());
}
}
}
}
}
target.clearChosen();
return paid;
}
@ -125,11 +153,12 @@ public class RemoveCounterCost extends CostImpl<RemoveCounterCost> {
}
private String setText() {
StringBuilder sb = new StringBuilder("Remove a ");
StringBuilder sb = new StringBuilder("Remove ");
sb.append(CardUtil.numberToText(countersToRemove, "a")).append(" ");
if (counterTypeToRemove != null) {
sb.append(counterTypeToRemove.getName()).append(" ");
sb.append(counterTypeToRemove.getName());
}
sb.append("counter from a ").append(target.getTargetName());
sb.append(countersToRemove == 1 ? " counter from ":" counters from ").append(target.getMaxNumberOfTargets() == 1 ? "a ":"").append(target.getTargetName());
return sb.toString();
}

View file

@ -28,30 +28,27 @@
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.counters.Counter;
import mage.filter.FilterMana;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author LevelX2
*/
public class RemoveVariableCountersSourceCost extends CostImpl<RemoveVariableCountersSourceCost> implements VariableCost {
public class RemoveVariableCountersSourceCost extends VariableCostImpl<RemoveVariableCountersSourceCost> {
protected int amountPaid = 0;
protected int minimalCountersToPay = 0;
private String name;
private String counterName;
public RemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay) {
super(new StringBuilder(counter.getName()).append(" counters to remove").toString());
this.minimalCountersToPay = minimalCountersToPay;
this.name = counter.getName();
this.text = "Remove X " + name + " counters from {this}";
this.counterName = counter.getName();
this.text = new StringBuilder("Remove ").append(xText).append(" ").append(counterName).append(" counters from {this}").toString();
}
public RemoveVariableCountersSourceCost(Counter counter) {
@ -60,65 +57,8 @@ public class RemoveVariableCountersSourceCost extends CostImpl<RemoveVariableCou
public RemoveVariableCountersSourceCost(final RemoveVariableCountersSourceCost cost) {
super(cost);
this.amountPaid = cost.amountPaid;
this.minimalCountersToPay = cost.minimalCountersToPay;
this.name = cost.name;
}
@Override
public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
Permanent permanent = game.getPermanent(sourceId);
return permanent != null && permanent.getCounters().getCount(name) >= minimalCountersToPay;
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
Permanent permanent = game.getPermanent(sourceId);
if (permanent != null) {
Player player = game.getPlayer(permanent.getControllerId());
if (player != null) {
this.amountPaid = player.getAmount(minimalCountersToPay, permanent.getCounters().getCount(name), "Choose X counters to remove", game);
if (this.amountPaid >= minimalCountersToPay) {
permanent.removeCounters(name, amountPaid, game);
this.paid = true;
}
game.informPlayers(new StringBuilder(player.getName()).append(" removes ").append(this.amountPaid).append(" ").append(name).append(" counter from ").append(permanent.getName()).toString());
}
}
return paid;
}
@Override
public void clearPaid() {
paid = false;
amountPaid = 0;
}
@Override
public int getAmount() {
return amountPaid;
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
}
/**
* Not Supported
* @param filter
*/
@Override
public void setFilter(FilterMana filter) {
}
/**
* Not supported
* @return
*/
@Override
public FilterMana getFilter() {
return new FilterMana();
this.counterName = cost.counterName;
}
@Override
@ -126,5 +66,25 @@ public class RemoveVariableCountersSourceCost extends CostImpl<RemoveVariableCou
return new RemoveVariableCountersSourceCost(this);
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
return new RemoveCountersSourceCost(new Counter(counterName, xValue));
}
@Override
public int getMinValue(Ability source, Game game) {
return minimalCountersToPay;
}
@Override
public int getMaxValue(Ability source, Game game) {
int maxValue = 0;
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
maxValue = permanent.getCounters().getCount(counterName);
}
return maxValue;
}
}

View file

@ -28,144 +28,109 @@
package mage.abilities.costs.common;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.VariableCost;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.filter.FilterMana;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
/**
*
* @author LevelX
*/
public class RemoveVariableCountersTargetCost extends CostImpl<RemoveVariableCountersTargetCost> implements VariableCost {
public class RemoveVariableCountersTargetCost extends VariableCostImpl<RemoveVariableCountersTargetCost> {
protected int amountPaid = 0;
protected TargetPermanent target;
protected String name;
protected FilterPermanent filter;
protected CounterType counterTypeToRemove;
protected int minValue;
public RemoveVariableCountersTargetCost(TargetPermanent target) {
this(target, null);
public RemoveVariableCountersTargetCost(FilterPermanent filter) {
this(filter, null);
}
public RemoveVariableCountersTargetCost(TargetPermanent target, CounterType counterTypeToRemove) {
this.target = target;
public RemoveVariableCountersTargetCost(FilterPermanent filter, CounterType counterTypeToRemove) {
this(filter, counterTypeToRemove, "X", 0);
}
public RemoveVariableCountersTargetCost(FilterPermanent filter, CounterType counterTypeToRemove, String xText, int minValue) {
super(xText, new StringBuilder(counterTypeToRemove != null ? counterTypeToRemove.getName() + " ":"").append("counters to remove").toString());
this.filter = filter;
this.counterTypeToRemove = counterTypeToRemove;
text = setText();
this.text = setText();
this.minValue = minValue;
}
public RemoveVariableCountersTargetCost(final RemoveVariableCountersTargetCost cost) {
super(cost);
this.target = cost.target.copy();
this.name = cost.name;
this.filter = cost.filter;
this.minValue = cost.minValue;
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
paid = false;
Player controller = game.getPlayer(controllerId);
if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) {
for (UUID targetId: (List<UUID>)target.getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
if (permanent.getCounters().size() > 0 && (counterTypeToRemove == null || permanent.getCounters().containsKey(counterTypeToRemove))) {
String counterName = null;
if (counterTypeToRemove != null) {
counterName = counterTypeToRemove.getName();
} else {
if (permanent.getCounters().size() > 1 && counterTypeToRemove == null) {
Choice choice = new ChoiceImpl(true);
Set<String> choices = new HashSet<String>();
for (Counter counter : permanent.getCounters().values()) {
if (permanent.getCounters().getCount(counter.getName()) > 0) {
choices.add(counter.getName());
}
}
choice.setChoices(choices);
choice.setMessage("Choose a counter to remove from " + permanent.getName());
controller.choose(Outcome.UnboostCreature, choice, game);
counterName = choice.getChoice();
} else {
for (Counter counter : permanent.getCounters().values()) {
if (counter.getCount() > 0) {
counterName = counter.getName();
}
}
}
}
if (counterName != null) {
int countersToRemove = 1;
if (permanent.getCounters().getCount(counterName) > 1) {
countersToRemove = controller.getAmount(1, permanent.getCounters().getCount(counterName),"Remove how many counters from " + permanent.getName(), game);
}
permanent.removeCounters(counterName, countersToRemove, game);
if (permanent.getCounters().getCount(counterName) == 0 ){
permanent.getCounters().removeCounter(counterName);
}
this.amountPaid += countersToRemove;
this.paid = true;
game.informPlayers(new StringBuilder(controller.getName()).append(" removes ").append(countersToRemove).append(" ").append(counterName).append(" counter from ").append(permanent.getName()).toString());
}
}
}
}
}
target.clearChosen();
// paid = false;
// Player controller = game.getPlayer(controllerId);
// if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) {
// for (UUID targetId: (List<UUID>)target.getTargets()) {
// Permanent permanent = game.getPermanent(targetId);
// if (permanent != null) {
// if (permanent.getCounters().size() > 0 && (counterTypeToRemove == null || permanent.getCounters().containsKey(counterTypeToRemove))) {
// String counterName = null;
// if (counterTypeToRemove != null) {
// counterName = counterTypeToRemove.getName();
// } else {
// if (permanent.getCounters().size() > 1 && counterTypeToRemove == null) {
// Choice choice = new ChoiceImpl(true);
// Set<String> choices = new HashSet<>();
// for (Counter counter : permanent.getCounters().values()) {
// if (permanent.getCounters().getCount(counter.getName()) > 0) {
// choices.add(counter.getName());
// }
// }
// choice.setChoices(choices);
// choice.setMessage("Choose a counter to remove from " + permanent.getName());
// controller.choose(Outcome.UnboostCreature, choice, game);
// counterName = choice.getChoice();
// } else {
// for (Counter counter : permanent.getCounters().values()) {
// if (counter.getCount() > 0) {
// counterName = counter.getName();
// }
// }
// }
// }
// if (counterName != null) {
// int countersToRemove = 1;
// if (permanent.getCounters().getCount(counterName) > 1) {
// countersToRemove = controller.getAmount(1, permanent.getCounters().getCount(counterName),"Remove how many counters from " + permanent.getName(), game);
// }
// permanent.removeCounters(counterName, countersToRemove, game);
// if (permanent.getCounters().getCount(counterName) == 0 ){
// permanent.getCounters().removeCounter(counterName);
// }
// this.amountPaid += countersToRemove;
// this.paid = true;
// game.informPlayers(new StringBuilder(controller.getName()).append(" removes ").append(countersToRemove).append(" ").append(counterName).append(" counter from ").append(permanent.getName()).toString());
// }
// }
// }
// }
// }
// target.clearChosen();
return paid;
}
@Override
public int getAmount() {
return amountPaid;
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
}
/**
* Not Supported
* @param filter
*/
@Override
public void setFilter(FilterMana filter) {
}
/**
* Not supported
* @return
*/
@Override
public FilterMana getFilter() {
return new FilterMana();
}
@Override
public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
return target.canChoose(controllerId, game);
}
private String setText() {
// Remove one or more +1/+1 counters from among creatures you control
StringBuilder sb = new StringBuilder("Remove one or more ");
StringBuilder sb = new StringBuilder("Remove ").append(xText);
if (counterTypeToRemove != null) {
sb.append(counterTypeToRemove.getName()).append(" ");
sb.append(" ").append(counterTypeToRemove.getName());
}
sb.append("counter from among ").append(target.getTargetName());
sb.append(" counters from among ").append(filter.getMessage());
return sb.toString();
}
@ -173,4 +138,25 @@ public class RemoveVariableCountersTargetCost extends CostImpl<RemoveVariableCou
public RemoveVariableCountersTargetCost copy() {
return new RemoveVariableCountersTargetCost(this);
}
@Override
public int getMaxValue(Ability source, Game game) {
int maxValue = 0;
for (Permanent permanent :game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
if (counterTypeToRemove != null) {
maxValue += permanent.getCounters().getCount(counterTypeToRemove);
} else {
for(Counter counter :permanent.getCounters().values()){
maxValue += counter.getCount();
}
}
}
return maxValue;
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
return new RemoveCounterCost(new TargetPermanent(1,Integer.MAX_VALUE, filter, true), counterTypeToRemove, xValue);
}
}

View file

@ -0,0 +1,78 @@
/*
* 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 mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author LevelX2
*/
public class SacrificeXTargetCost extends VariableCostImpl<SacrificeXTargetCost> {
protected FilterControlledPermanent filter;
public SacrificeXTargetCost(FilterControlledPermanent filter) {
this(filter, false);
}
public SacrificeXTargetCost(FilterControlledPermanent filter, boolean additionalCostText) {
super(new StringBuilder(filter.getMessage()).append(" to sacrifice").toString());
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, sacrifice ":"Sacrifice ").append(xText).append(" ").append(filter.getMessage()).toString();
this.filter = filter;
}
public SacrificeXTargetCost(final SacrificeXTargetCost cost) {
super(cost);
this.filter = cost.filter;
}
@Override
public SacrificeXTargetCost copy() {
return new SacrificeXTargetCost(this);
}
@Override
public int getMaxValue(Ability source, Game game) {
return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
TargetControlledPermanent target = new TargetControlledPermanent(xValue, xValue, filter, true);
target.setRequired(true);
return new SacrificeTargetCost(target);
}
}

View file

@ -28,90 +28,35 @@
package mage.abilities.costs.common;
import java.util.Iterator;
import java.util.UUID;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.VariableCost;
import mage.filter.FilterMana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCostImpl;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class TapVariableTargetCost extends CostImpl<TapVariableTargetCost> implements VariableCost {
public class TapVariableTargetCost extends VariableCostImpl<TapVariableTargetCost> {
protected int amountPaid = 0;
protected TargetControlledPermanent target;
protected FilterControlledPermanent filter;
public TapVariableTargetCost(TargetControlledPermanent target) {
this.target = target;
this.text = "tap X " + target.getTargetName() + " you control";
public TapVariableTargetCost(FilterControlledPermanent filter) {
this(filter, false, "X");
}
public TapVariableTargetCost(FilterControlledPermanent filter, boolean additionalCostText, String xText) {
super(xText, new StringBuilder(filter.getMessage()).append(" to tap").toString());
this.filter = filter;
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, tap ":"Tap ")
.append(this.xText).append(" ").append(filter.getMessage()).toString();
}
public TapVariableTargetCost(final TapVariableTargetCost cost) {
super(cost);
this.target = cost.target.copy();
this.amountPaid = cost.amountPaid;
}
@Override
public boolean canPay(UUID sourceId, UUID controllerId, Game game) {
return target.canChoose(controllerId, game);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
amountPaid = 0;
target.clearChosen();
if (target.canChoose(sourceId, controllerId, game) && target.choose(Outcome.Tap, controllerId, sourceId, game)) {
for (Iterator it = target.getTargets().iterator(); it.hasNext();) {
UUID uuid = (UUID) it.next();
Permanent permanent = game.getPermanent(uuid);
if (permanent != null && permanent.tap(game)) {
amountPaid++;
}
}
}
paid = true;
return true;
}
@Override
public void clearPaid() {
paid = false;
amountPaid = 0;
}
@Override
public int getAmount() {
return amountPaid;
}
@Override
public void setAmount(int amount) {
amountPaid = amount;
}
/**
* Not Supported
* @param filter
*/
@Override
public void setFilter(FilterMana filter) {
}
/**
* Not supported
* @return
*/
@Override
public FilterMana getFilter() {
return new FilterMana();
this.filter = cost.filter.copy();
}
@Override
@ -119,4 +64,14 @@ public class TapVariableTargetCost extends CostImpl<TapVariableTargetCost> imple
return new TapVariableTargetCost(this);
}
@Override
public int getMaxValue(Ability source, Game game) {
return game.getBattlefield().countAll(filter, source.getControllerId(), game);
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
return new TapTargetCost(new TargetControlledPermanent(xValue, xValue, filter, true));
}
}

View file

@ -35,6 +35,7 @@ import mage.abilities.costs.VariableCost;
/**
*
* @author BetaSteward_at_googlemail.com
* @param <T>
*/
public interface ManaCosts<T extends ManaCost> extends List<T>, ManaCost {

View file

@ -30,6 +30,7 @@ package mage.abilities.costs.mana;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.VariableCost;
import mage.constants.ColoredManaSymbol;
import mage.filter.FilterMana;
@ -113,16 +114,6 @@ public class VariableManaCost extends ManaCostImpl<VariableManaCost> implements
return true;
}
@Override
public void setFilter(FilterMana filter) {
this.filter = filter;
}
@Override
public FilterMana getFilter() {
return filter;
}
@Override
public VariableManaCost copy() {
return new VariableManaCost(this);
@ -152,4 +143,37 @@ public class VariableManaCost extends ManaCostImpl<VariableManaCost> implements
public boolean containsColor(ColoredManaSymbol coloredManaSymbol) {
return false;
}
@Override
public int announceXValue(Ability source, Game game) {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String getActionText() {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public int getMinValue(Ability source, Game game) {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public int getMaxValue(Ability source, Game game) {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
public FilterMana getFilter() {
return filter;
}
public void setFilter(FilterMana filter) {
this.filter = filter;
}
}

View file

@ -86,6 +86,9 @@ public class ReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect<
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder();
Target target = mode.getTargets().get(0);
sb.append("Return ");

View file

@ -50,7 +50,7 @@ public class TransformSourceEffect extends OneShotEffect<TransformSourceEffect>
this(fromDayToNight, false);
}
private TransformSourceEffect(boolean fromDayToNight, boolean withoutTrigger) {
public TransformSourceEffect(boolean fromDayToNight, boolean withoutTrigger) {
super(Outcome.Transform);
this.withoutTrigger = withoutTrigger;
this.fromDayToNight = fromDayToNight;

View file

@ -33,6 +33,7 @@ import java.io.Serializable;
/**
*
* @author BetaSteward_at_googlemail.com
* @param <T>
*/
public class Counter<T extends Counter<T>> implements Serializable {

View file

@ -53,27 +53,31 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
}
public void addCounter(String name) {
if (!this.containsKey(name))
if (!this.containsKey(name)) {
this.put(name, new Counter(name));
}
this.get(name).add();
}
public void addCounter(String name, int amount) {
if (!this.containsKey(name))
if (!this.containsKey(name)) {
this.put(name, new Counter(name));
}
this.get(name).add(amount);
}
public void addCounter(Counter counter) {
if (!this.containsKey(counter.name))
if (!this.containsKey(counter.name)) {
put(counter.name, counter);
else
} else {
get(counter.name).add(counter.getCount());
}
}
public void removeCounter(String name) {
if (this.containsKey(name))
if (this.containsKey(name)) {
this.get(name).remove();
}
}
public void removeCounter(CounterType counterType, int amount) {
@ -83,13 +87,15 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
}
public void removeCounter(String name, int amount) {
if (this.containsKey(name))
if (this.containsKey(name)) {
this.get(name).remove(amount);
}
}
public int getCount(String name) {
if (this.containsKey(name))
if (this.containsKey(name)) {
return this.get(name).getCount();
}
return 0;
}
@ -98,16 +104,18 @@ public class Counters extends HashMap<String, Counter> implements Serializable {
}
public int getCount(CounterType type) {
if (this.containsKey(type.getName()))
if (this.containsKey(type.getName())) {
return this.get(type.getName()).getCount();
}
return 0;
}
public List<BoostCounter> getBoostCounters() {
List<BoostCounter> boosters = new ArrayList<BoostCounter>();
List<BoostCounter> boosters = new ArrayList<>();
for (Counter counter: this.values()) {
if (counter instanceof BoostCounter)
if (counter instanceof BoostCounter) {
boosters.add((BoostCounter)counter);
}
}
return boosters;
}

View file

@ -6,13 +6,20 @@ import mage.abilities.keyword.FlyingAbility;
import mage.constants.CardType;
public class AngelToken extends Token {
public AngelToken() {
this("M14");
}
public AngelToken(String tokenImageSetCode) {
super("Angel", "4/4 white Angel creature token with flying");
this.setOriginalExpansionSetCode(tokenImageSetCode);
cardType.add(CardType.CREATURE);
color = ObjectColor.WHITE;
subtype.add("Angel");
power = new MageInt(4);
toughness = new MageInt(4);
addAbility(FlyingAbility.getInstance());
}
}

View file

@ -4,8 +4,14 @@ import mage.MageInt;
import mage.constants.CardType;
public class MyrToken extends Token {
public MyrToken() {
this("SOM");
}
public MyrToken(String expansionSetCode) {
super("Myr", "1/1 colorless Myr artifact creature token");
this.setOriginalExpansionSetCode(expansionSetCode);
cardType.add(CardType.CREATURE);
cardType.add(CardType.ARTIFACT);
subtype.add("Myr");

View file

@ -43,6 +43,7 @@ import mage.abilities.Mode;
import mage.abilities.Modes;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.mana.ManaCost;
import mage.cards.Card;
import mage.cards.Cards;
@ -278,9 +279,12 @@ public interface Player extends MageItem, Copyable<Player> {
*/
boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder);
// set the value for X spells and abilities
// set the value for X mana spells and abilities
int announceXMana(int min, int max, String message, Game game, Ability ability);
// set the value for non mana X costs
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
int chooseEffect(List<String> rEffects, Game game);
TriggeredAbility chooseTriggeredAbility(List<TriggeredAbility> abilities, Game game);
Mode chooseMode(Modes modes, Ability source, Game game);

View file

@ -46,8 +46,8 @@ import java.util.*;
*/
public abstract class TargetImpl<T extends TargetImpl<T>> implements Target {
protected Map<UUID, Integer> targets = new LinkedHashMap<UUID, Integer>();
protected Map<UUID, Integer> zoneChangeCounters = new HashMap<UUID, Integer>();
protected Map<UUID, Integer> targets = new LinkedHashMap<>();
protected Map<UUID, Integer> zoneChangeCounters = new HashMap<>();
protected String targetName;
protected Zone zone;