counters: united calls using multipliers and ignoring them,

removed useless setCounter wrapper
This commit is contained in:
Maxmtg
2012-11-23 21:51:30 +00:00
parent 4f49ba3ac7
commit 2c0e938d4b
18 changed files with 124 additions and 209 deletions

View File

@@ -1230,58 +1230,11 @@ public class Card extends GameEntity implements Comparable<Card> {
return true;
}
// for costs (like Planeswalker abilities) Doubling Season gets ignored.
/**
* <p>
* addCounterFromNonEffect.
* </p>
*
* @param counterName
* a {@link forge.CounterType} object.
* @param n
* a int.
*/
public final void addCounterFromNonEffect(final CounterType counterName, final int n) {
if (!this.canHaveCountersPlacedOnIt(counterName)) {
return;
}
if (this.counters.containsKey(counterName)) {
final Integer aux = this.counters.get(counterName) + n;
this.counters.put(counterName, aux);
} else {
this.counters.put(counterName, Integer.valueOf(n));
}
// Run triggers
final Map<String, Object> runParams = new TreeMap<String, Object>();
runParams.put("Card", this);
runParams.put("CounterType", counterName);
for (int i = 0; i < n; i++) {
Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterAdded, runParams);
}
// play the Add Counter sound
Singletons.getModel().getGame().getEvents().post(new AddCounterEvent(n));
this.updateObservers();
}
/**
* <p>
* addCounter.
* </p>
*
* @param counterType
* a {@link forge.CounterType} object.
* @param n
* a int.
*/
public final void addCounter(final CounterType counterType, final int n) {
public final void addCounter(final CounterType counterType, final int n, final boolean applyMultiplier) {
if (!this.canHaveCountersPlacedOnIt(counterType)) {
return;
}
final int multiplier = this.getController().getCounterDoublersMagnitude(counterType);
final int multiplier = applyMultiplier ? this.getController().getCounterDoublersMagnitude(counterType) : 1;
final int addAmount = (multiplier * n);
Integer oldValue = this.counters.get(counterType);
@@ -1313,69 +1266,74 @@ public class Card extends GameEntity implements Comparable<Card> {
* a int.
*/
public final void subtractCounter(final CounterType counterName, final int n) {
if (this.counters.containsKey(counterName)) {
Integer aux = this.counters.get(counterName) - n;
if (aux < 0) {
aux = 0;
}
this.counters.put(counterName, aux);
Integer oldValue = this.counters.get(counterName);
int newValue = oldValue == null ? 0 : Math.max(oldValue.intValue() - n, 0);
// Run triggers
final Map<String, Object> runParams = new TreeMap<String, Object>();
runParams.put("Card", this);
runParams.put("CounterType", counterName);
for (int i = 0; i < n; i++) {
Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams);
final int delta = ( oldValue == null ? 0 : oldValue.intValue() ) - newValue;
if ( delta == 0 ) return;
if ( newValue > 0 )
this.counters.put(counterName, Integer.valueOf(newValue));
else
this.counters.remove(counterName);
// Run triggers
final Map<String, Object> runParams = new TreeMap<String, Object>();
runParams.put("Card", this);
runParams.put("CounterType", counterName);
for (int i = 0; i < delta; i++) {
Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.CounterRemoved, runParams);
}
if (counterName.equals(CounterType.TIME) && (newValue == 0)) {
final boolean hasVanish = CardFactoryUtil.hasKeyword(this, "Vanishing") != -1;
if (hasVanish && this.isInPlay()) {
Singletons.getModel().getGame().getAction().sacrifice(this, null);
}
if (counterName.equals(CounterType.TIME) && (aux == 0)) {
final boolean hasVanish = CardFactoryUtil.hasKeyword(this, "Vanishing") != -1;
if (this.hasSuspend() && Singletons.getModel().getGame().isCardExiled(this)) {
playFromSuspend();
}
}
if (hasVanish && this.isInPlay()) {
Singletons.getModel().getGame().getAction().sacrifice(this, null);
}
// Play the Subtract Counter sound
Singletons.getModel().getGame().getEvents().post(new RemoveCounterEvent(delta));
if (this.hasSuspend() && Singletons.getModel().getGame().isCardExiled(this)) {
final Card c = this;
this.updateObservers();
}
private void playFromSuspend() {
final Card c = this;
c.setSuspendCast(true);
// set activating player for base spell ability
c.getSpellAbility()[0].setActivatingPlayer(c.getOwner());
// Any trigger should cause the phase not to skip
for (Player p : Singletons.getModel().getGame().getPlayers()) {
p.getController().autoPassCancel();
c.setSuspendCast(true);
// set activating player for base spell ability
c.getSpellAbility()[0].setActivatingPlayer(c.getOwner());
// Any trigger should cause the phase not to skip
for (Player p : Singletons.getModel().getGame().getPlayers()) {
p.getController().autoPassCancel();
}
if (c.getOwner().isHuman()) {
Singletons.getModel().getGame().getAction().playCardWithoutManaCost(c);
} else {
final List<SpellAbility> choices = this.getBasicSpells();
for (final SpellAbility sa : choices) {
//Spells
if (sa instanceof Spell) {
Spell spell = (Spell) sa;
if (!spell.canPlayFromEffectAI(true, true)) {
continue;
}
if (c.getOwner().isHuman()) {
Singletons.getModel().getGame().getAction().playCardWithoutManaCost(c);
} else {
final List<SpellAbility> choices = this.getBasicSpells();
for (final SpellAbility sa : choices) {
//Spells
if (sa instanceof Spell) {
Spell spell = (Spell) sa;
if (!spell.canPlayFromEffectAI(true, true)) {
continue;
}
} else {
if (!sa.canPlayAI()) {
continue;
}
}
ComputerUtil.playSpellAbilityWithoutPayingManaCost(c.getOwner(), sa);
break;
}
} else {
if (!sa.canPlayAI()) {
continue;
}
}
ComputerUtil.playSpellAbilityWithoutPayingManaCost(c.getOwner(), sa);
break;
}
// Play the Subtract Counter sound
if (n > 0) {
Singletons.getModel().getGame().getEvents().post(new RemoveCounterEvent(n));
}
this.updateObservers();
}
}
@@ -1389,10 +1347,8 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a int.
*/
public final int getCounters(final CounterType counterName) {
if (this.counters.containsKey(counterName)) {
return this.counters.get(counterName);
}
return 0;
Integer value = this.counters.get(counterName);
return value == null ? 0 : value.intValue();
}
// get all counters from a card
@@ -1416,7 +1372,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a boolean.
*/
public final boolean hasCounters() {
return this.counters.size() > 0;
return !this.counters.isEmpty();
}
/**
@@ -1433,37 +1389,6 @@ public class Card extends GameEntity implements Comparable<Card> {
return number;
}
/**
* <p>
* setCounter.
* </p>
*
* @param counterName
* a {@link forge.CounterType} object.
* @param n
* a int.
* @param bSetValue
* a boolean.
*/
public final void setCounter(final CounterType counterName, final int n, final boolean bSetValue) {
if (!this.canHaveCountersPlacedOnIt(counterName)) {
return;
}
// sometimes you just need to set the value without being affected by
// DoublingSeason
if (bSetValue) {
this.counters.put(counterName, Integer.valueOf(n));
} else {
final int num = this.getCounters(counterName);
// if counters on card is less than the setting value, addCounters
if (num < n) {
this.addCounter(counterName, n - num);
} else {
this.subtractCounter(counterName, num - n);
}
}
this.updateObservers();
}
// get all counters from a card
/**
@@ -8325,7 +8250,7 @@ public class Card extends GameEntity implements Comparable<Card> {
GameActionUtil.executeDamageToCreatureEffects(source, this, damageToAdd);
if (this.isInPlay() && wither) {
this.addCounter(CounterType.M1M1, damageToAdd);
this.addCounter(CounterType.M1M1, damageToAdd, true);
}
if (source.hasKeyword("Deathtouch") && this.isCreature()) {
Singletons.getModel().getGame().getAction().destroy(this);

View File

@@ -836,22 +836,6 @@ public class GameAction {
game.getStack().add(activate);
}
/**
* <p>
* discardPutIntoPlayInstead.
* </p>
*
* @param c
* a {@link forge.Card} object.
*/
public final void discardPutIntoPlayInstead(final Card c) {
this.moveToPlay(c);
if (c.getName().equals("Dodecapod")) {
c.setCounter(CounterType.P1P1, 2, false);
}
}
/**
* <p>
* discardMadness.
@@ -1494,7 +1478,7 @@ public class GameAction {
if (game.getZoneOf(persistCard).is(ZoneType.Graveyard)) {
final PlayerZone ownerPlay = persistCard.getOwner().getZone(ZoneType.Battlefield);
final Card card = GameAction.this.moveTo(ownerPlay, persistCard);
card.addCounter(CounterType.M1M1, 1);
card.addCounter(CounterType.M1M1, 1, true);
}
}
};
@@ -1514,7 +1498,7 @@ public class GameAction {
if (game.getZoneOf(undyingCard).is(ZoneType.Graveyard)) {
final PlayerZone ownerPlay = undyingCard.getOwner().getZone(ZoneType.Battlefield);
final Card card = GameAction.this.moveTo(ownerPlay, undyingCard);
card.addCounter(CounterType.P1P1, 1);
card.addCounter(CounterType.P1P1, 1, true);
}
}
};

View File

@@ -434,7 +434,7 @@ public final class GameActionUtil {
if (showYesNoDialog(source, "Do you want to put " + amount + " " + counterType.getName()
+ " counter" + plural + " on " + source + "?")) {
if (source.canHaveCountersPlacedOnIt(counterType)) {
source.addCounterFromNonEffect(counterType, amount);
source.addCounter(counterType, amount, false);
} else {
hasPaid = false;
Singletons.getModel().getGame().getGameLog().add("ResolveStack", "Trying to pay upkeep for " + source + " but it can't have "
@@ -729,7 +729,7 @@ public final class GameActionUtil {
counter = CounterType.P2P2;
}
if (thisCard.isInPlay()) {
thisCard.addCounter(counter, 1);
thisCard.addCounter(counter, 1, true);
}
}
}; // ability2

View File

@@ -745,7 +745,7 @@ public class ChangeZoneAi extends SpellAiLogic {
aiPermanents = CardLists.filter(aiPermanents, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
if (c.getNumberOfCounters() > 0) {
if (c.hasCounters()) {
return false; // don't blink something with
}
// counters TODO check good and

View File

@@ -75,7 +75,7 @@ public class CountersMoveEffect extends SpellEffect {
if (!dest.hasKeyword("CARDNAME can't have counters placed on it.")
&& !(dest.hasKeyword("CARDNAME can't have -1/-1 counters placed on it.") && cType
.equals(CounterType.M1M1))) {
dest.addCounter(cType, amount);
dest.addCounter(cType, amount, true);
source.subtractCounter(cType, amount);
}
}

View File

@@ -77,9 +77,8 @@ public class CountersProliferateEffect extends SpellEffect {
}
}
if (choices.size() > 0) {
card.addCounter(
CounterType.getType((choices.size() == 1 ? choices.get(0) : GuiChoose.one(
"Select counter type", choices).toString())), 1);
card.addCounter(CounterType.getType((choices.size() == 1 ? choices.get(0) : GuiChoose.one(
"Select counter type", choices).toString())), 1, true);
}
}
@@ -153,12 +152,12 @@ public class CountersProliferateEffect extends SpellEffect {
for (final Entry<CounterType, Integer> c1 : c.getCounters().entrySet()) {
if (CardFactoryUtil.isNegativeCounter(c1.getKey()) && enemies.contains(c.getController()))
{
c.addCounter(c1.getKey(), 1);
c.addCounter(c1.getKey(), 1, true);
break;
}
if (!CardFactoryUtil.isNegativeCounter(c1.getKey()) && allies.contains(c.getController()))
{
c.addCounter(c1.getKey(), 1);
c.addCounter(c1.getKey(), 1, true);
break;
}
}

View File

@@ -55,10 +55,10 @@ public class CountersPutAllEffect extends SpellEffect {
for (final Card tgtCard : cards) {
if (Singletons.getModel().getGame().getZoneOf(tgtCard).is(ZoneType.Battlefield)) {
tgtCard.addCounter(CounterType.valueOf(type), counterAmount);
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, true);
} else {
// adding counters to something like re-suspend cards
tgtCard.addCounterFromNonEffect(CounterType.valueOf(type), counterAmount);
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, false);
}
}
}

View File

@@ -92,10 +92,10 @@ public class CountersPutEffect extends SpellEffect {
if (zone == null) {
// Do nothing, token disappeared
} else if (zone.is(ZoneType.Battlefield) || zone.is(ZoneType.Stack)) {
tgtCard.addCounter(CounterType.valueOf(type), counterAmount);
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, true);
} else {
// adding counters to something like re-suspend cards
tgtCard.addCounterFromNonEffect(CounterType.valueOf(type), counterAmount);
tgtCard.addCounter(CounterType.valueOf(type), counterAmount, false);
}
}
}

View File

@@ -77,7 +77,7 @@ public class CountersRemoveEffect extends SpellEffect {
}
if (type.matches("Any")) {
while (counterAmount > 0 && tgtCard.getNumberOfCounters() > 0) {
while (counterAmount > 0 && tgtCard.hasCounters()) {
final Map<CounterType, Integer> tgtCounters = tgtCard.getCounters();
CounterType chosenType = null;
int chosenAmount;

View File

@@ -309,7 +309,7 @@ class CardFactoryArtifacts {
@Override
public void execute() {
card.addCounter(CounterType.CHARGE, card.getMultiKickerMagnitude());
card.addCounter(CounterType.CHARGE, card.getMultiKickerMagnitude(), true);
card.setMultiKickerMagnitude(0);
}
};

View File

@@ -18,7 +18,10 @@
package forge.card.cardfactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JOptionPane;
@@ -94,7 +97,7 @@ public class CardFactoryCreatures {
// zerker clean up:
for (final CounterType c1 : CounterType.values()) {
if (c.getCounters(c1) > 0) {
c.addCounter(c1, c.getCounters(c1));
c.addCounter(c1, c.getCounters(c1), true);
}
}
}
@@ -151,7 +154,7 @@ public class CardFactoryCreatures {
if (artifacts.size() != 0) {
final Card c = GuiChoose.one("Select an artifact put a phylactery counter on", artifacts);
if (c != null) {
c.addCounter(CounterType.PHYLACTERY, 1);
c.addCounter(CounterType.PHYLACTERY, 1, true);
}
}
@@ -171,7 +174,7 @@ public class CardFactoryCreatures {
chosen = artifacts.get(0);
}
if (chosen != null) {
chosen.addCounter(CounterType.PHYLACTERY, 1);
chosen.addCounter(CounterType.PHYLACTERY, 1, true);
}
} // else
} // execute()
@@ -506,7 +509,7 @@ public class CardFactoryCreatures {
if (xCounters >= 5) {
xCounters = 2 * xCounters;
}
c.addCounter(CounterType.P1P1, xCounters);
c.addCounter(CounterType.P1P1, xCounters, true);
}
};
spell.setIsXCost(true);
@@ -520,7 +523,7 @@ public class CardFactoryCreatures {
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
card.addCounter(CounterType.P1P1, this.countKithkin());
card.addCounter(CounterType.P1P1, this.countKithkin(), true);
// System.out.println("all counters: "
// +card.sumAllCounters());
} // resolve()
@@ -590,7 +593,7 @@ public class CardFactoryCreatures {
final AbilityStatic ability = new AbilityStatic(card, "0") {
@Override
public void resolve() {
card.addCounter(CounterType.P1P1, card.getMultiKickerMagnitude());
card.addCounter(CounterType.P1P1, card.getMultiKickerMagnitude(), true);
card.setMultiKickerMagnitude(0);
}
};
@@ -671,10 +674,10 @@ public class CardFactoryCreatures {
@Override
public void resolve() {
final Card c = this.getTargetCard();
for (final CounterType counter : CounterType.values()) {
if (c.getCounters(counter) > 0) {
c.setCounter(counter, 0, false);
}
// need a copy to avoid exception caused by modification of Iterable being enumerated
Map<CounterType, Integer> copy = new HashMap<CounterType, Integer>(c.getCounters());
for (final Entry<CounterType, Integer> counter : copy.entrySet()) {
c.subtractCounter(counter.getKey(), counter.getValue());
}
}
}
@@ -1166,7 +1169,7 @@ public class CardFactoryCreatures {
@Override
public void resolve() {
card.addCounter(CounterType.LEVEL, 1);
card.addCounter(CounterType.LEVEL, 1, true);
}
@Override

View File

@@ -178,7 +178,7 @@ class CardFactoryLands {
this.inPlay.clear();
this.inPlay.addAll(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield));
for (final Card targ : CardLists.filter(this.inPlay, targets)) {
targ.addCounter(CounterType.P1P1, 1);
targ.addCounter(CounterType.P1P1, 1, true);
}
}
}

View File

@@ -1124,7 +1124,7 @@ public class CardFactoryUtil {
final Card c = Singletons.getModel().getGame().getAction().exile(sourceCard);
int counters = AbilityFactory.calculateAmount(c, timeCounters, this);
c.addCounter(CounterType.TIME, counters);
c.addCounter(CounterType.TIME, counters, true);
StringBuilder sb = new StringBuilder();
sb.append(this.getActivatingPlayer()).append(" has suspended ");
@@ -1165,7 +1165,7 @@ public class CardFactoryUtil {
@Override
public void execute() {
c.addCounter(type, n);
c.addCounter(type, n, true);
}
};
return addCounters;
@@ -4446,9 +4446,9 @@ public class CardFactoryUtil {
@Override
public void execute() {
if (card.isCreature()) {
card.addCounter(CounterType.P1P1, card.getSunburstValue());
card.addCounter(CounterType.P1P1, card.getSunburstValue(), true);
} else {
card.addCounter(CounterType.CHARGE, card.getSunburstValue());
card.addCounter(CounterType.CHARGE, card.getSunburstValue(), true);
}
}
@@ -4594,7 +4594,7 @@ public class CardFactoryUtil {
: Integer.parseInt(magnitude);
final int totalCounters = numCreatures[0] * multiplier;
card.addCounter(CounterType.P1P1, totalCounters);
card.addCounter(CounterType.P1P1, totalCounters, true);
}
};
@@ -4617,7 +4617,7 @@ public class CardFactoryUtil {
@Override
public void resolve() {
final Card card2 = this.getTargetCard();
card2.addCounter(CounterType.P1P1, this.getSourceCard().getCounters(CounterType.P1P1));
card2.addCounter(CounterType.P1P1, this.getSourceCard().getCounters(CounterType.P1P1), true);
} // resolve()
};

View File

@@ -162,11 +162,11 @@ public class CostPutCounter extends CostPartWithList {
}
if (this.getThis()) {
source.addCounterFromNonEffect(this.getCounter(), c);
source.addCounter(this.getCounter(), c, false);
} else {
// Put counter on chosen card
for (final Card card : this.getList()) {
card.addCounterFromNonEffect(this.getCounter(), 1);
card.addCounter(this.getCounter(), 1, false);
}
}
}
@@ -186,7 +186,7 @@ public class CostPutCounter extends CostPartWithList {
}
if (this.getThis()) {
source.addCounterFromNonEffect(this.getCounter(), c);
source.addCounter(this.getCounter(), c, false);
payment.setPaidManaPart(this);
this.addToList(source);
return true;
@@ -285,7 +285,7 @@ public class CostPutCounter extends CostPartWithList {
if (this.typeList.contains(card)) {
this.nPut++;
costPutCounter.addToList(card);
card.addCounterFromNonEffect(costPutCounter.getCounter(), 1);
card.addCounter(costPutCounter.getCounter(), 1, false);
if (nNeeded == this.nPut) {
this.done();

View File

@@ -144,7 +144,7 @@ public class CostRemoveCounter extends CostPartWithList {
@Override
public final void refund(final Card source) {
for (final Card c : this.getList()) {
c.addCounterFromNonEffect(this.counter, this.lastPaidAmount);
c.addCounter(this.counter, this.lastPaidAmount, false);
}
}

View File

@@ -139,7 +139,7 @@ public class Upkeep extends Phase {
final Ability upkeepAbility = new Ability(c, "0") {
@Override
public void resolve() {
c.addCounter(CounterType.AGE, 1);
c.addCounter(CounterType.AGE, 1, true);
StringBuilder rs = new StringBuilder("R");
for(int ageCounters = c.getCounters(CounterType.AGE); ageCounters > 1; ageCounters-- )
rs.append(" R");
@@ -337,7 +337,7 @@ public class Upkeep extends Phase {
if (ability.startsWith("Cumulative upkeep")) {
final String[] k = ability.split(":");
c.addCounter(CounterType.AGE, 1);
c.addCounter(CounterType.AGE, 1, true);
cost = CardFactoryUtil.multiplyCost(k[1], c.getCounters(CounterType.AGE));
sb.append("Cumulative upkeep for ").append(c).append("\n");
}
@@ -1691,7 +1691,7 @@ public class Upkeep extends Phase {
this.revealTopCard(title);
}
if (wantCounter) {
k.addCounter(CounterType.P1P1, 1);
k.addCounter(CounterType.P1P1, 1, true);
}
} // resolve()

View File

@@ -1610,15 +1610,19 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
}*/
game.getAction().discardMadness(c);
if ((c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, "
+ "put it onto the battlefield instead of putting it into your graveyard.")
|| c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, "
+ "put it onto the battlefield with two +1/+1 counters on it "
+ "instead of putting it into your graveyard."))
&& (null != sa) && !c.getController().equals(sa.getSourceCard().getController())) {
game.getAction().discardPutIntoPlayInstead(c);
boolean hasPutIntoPlayInsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you " +
"to discard CARDNAME, put it onto the battlefield instead of putting it into your graveyard.");
boolean hasPutIntoPlayWith2xP1P1InsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, "
+ "put it onto the battlefield with two +1/+1 counters on it instead of putting it into your graveyard.");
if ( ( hasPutIntoPlayInsteadOfDiscard || hasPutIntoPlayWith2xP1P1InsteadOfDiscard )
&& null != sa && sa.getSourceCard().getController().isHostileTo(c.getController())) {
game.getAction().moveToPlay(c);
if (hasPutIntoPlayWith2xP1P1InsteadOfDiscard) {
c.addCounter(CounterType.P1P1, 2, false);
}
// Play the corresponding Put into Play sound
game.getEvents().post(new SpellResolvedEvent(c, sa));
} else {

View File

@@ -599,7 +599,7 @@ public final class GuiDisplayUtil {
} else if (info.startsWith("Counters:")) {
final String[] counterStrings = info.substring(info.indexOf(':') + 1).split(",");
for (final String counter : counterStrings) {
c.addCounter(CounterType.valueOf(counter), 1);
c.addCounter(CounterType.valueOf(counter), 1, true);
}
} else if (info.equalsIgnoreCase("SummonSick:True")) {
c.setSickness(true);
@@ -661,7 +661,7 @@ public final class GuiDisplayUtil {
if (null == i) {
return;
} else {
c.addCounterFromNonEffect(counter, i);
c.addCounter(counter, i, false);
}
}
}