prevent direct access of Player->counters ; some cleanup on counter removal effects ; implement [MH3] Izzet Generatorium (#12314)

This commit is contained in:
Susucre 2024-05-29 22:34:54 +02:00 committed by GitHub
parent 8d02ff14ff
commit 20b7a115da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
110 changed files with 895 additions and 646 deletions

View file

@ -13,6 +13,10 @@ import mage.constants.Zone;
*/
public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
public ActivateIfConditionActivatedAbility(Effect effect, Cost cost, Condition condition) {
this(Zone.BATTLEFIELD, effect, cost, condition, TimingRule.INSTANT);
}
public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) {
this(zone, effect, cost, condition, TimingRule.INSTANT);
}

View file

@ -11,7 +11,7 @@ import java.util.Objects;
/**
* A condition which checks whether any players being attacked are poisoned
* (have one or more poison counters on them)
*
*
* @author alexander-novo
*/
public enum AttackedPlayersPoisonedCondition implements Condition {
@ -27,7 +27,7 @@ public enum AttackedPlayersPoisonedCondition implements Condition {
.distinct()
.map(game::getPlayer)
.filter(Objects::nonNull)
.anyMatch(player -> player.getCounters().containsKey(CounterType.POISON));
.anyMatch(player -> player.getCountersCount(CounterType.POISON) > 0);
}
@Override

View file

@ -6,7 +6,6 @@ import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.counters.CounterType;
import mage.game.Game;
import mage.players.Player;
import java.util.Objects;
@ -24,8 +23,7 @@ public enum CorruptedCondition implements Condition {
.stream()
.map(game::getPlayer)
.filter(Objects::nonNull)
.map(Player::getCounters)
.anyMatch(counters -> counters.getCount(CounterType.POISON) >= 3);
.anyMatch(player -> player.getCountersCount(CounterType.POISON) >= 3);
}
@Override

View file

@ -11,6 +11,8 @@ import mage.util.CardUtil;
import java.util.UUID;
import java.util.UUID;
/**
* @author emerald000
*/
@ -31,14 +33,14 @@ public class PayEnergyCost extends CostImpl {
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
Player player = game.getPlayer(controllerId);
return player != null && player.getCounters().getCount(CounterType.ENERGY) >= amount;
return player != null && player.getCountersCount(CounterType.ENERGY) >= amount;
}
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Player player = game.getPlayer(controllerId);
if (player != null && player.getCounters().getCount(CounterType.ENERGY) >= amount) {
player.getCounters().removeCounter(CounterType.ENERGY, amount);
if (player != null && player.getCountersCount(CounterType.ENERGY) >= amount) {
player.loseCounters(CounterType.ENERGY.getName(), amount, source, game);
paid = true;
}
return paid;

View file

@ -38,10 +38,7 @@ public class RemoveAllCountersSourceCost extends CostImpl {
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Permanent permanent = game.getPermanent(ability.getSourceId());
if (permanent != null) {
this.removedCounters = permanent.getCounters(game).getCount(counterType);
if (this.removedCounters > 0) {
permanent.removeCounters(counterType.createInstance(this.removedCounters), source, game);
}
this.removedCounters = permanent.removeAllCounters(counterType.getName(), source, game);
}
this.paid = true;
return true;

View file

@ -20,7 +20,7 @@ public enum OpponentsPoisonCountersCount implements DynamicValue {
for (UUID playerUUID : playerList) {
Player player = game.getPlayer(playerUUID);
if (player != null) {
amount += player.getCounters().getCount(CounterType.POISON);
amount += player.getCountersCount(CounterType.POISON);
}
}
return amount;

View file

@ -32,7 +32,7 @@ public enum SourceControllerCountersCount implements DynamicValue {
int amount = 0;
Player player = game.getPlayer(sourceAbility.getControllerId());
if (player != null) {
amount = player.getCounters().getCount(counterType);
amount = player.getCountersCount(counterType);
}
return amount;
}

View file

@ -35,8 +35,7 @@ public class RemoveAllCountersSourceEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
int count = sourcePermanent.getCounters(game).getCount(counterType);
sourcePermanent.removeCounters(counterType.getName(), count, source, game);
sourcePermanent.removeAllCounters(counterType.getName(), source, game);
return true;
}
return false;

View file

@ -76,7 +76,8 @@ public class ProliferateEffect extends OneShotEffect {
if (player == null) {
continue;
}
for (Counter counter : player.getCounters().values()) {
for (Counter counter : player.getCountersAsCopy().values()) {
// TODO: this does not work with ability counters that are not explicitly in CounterType. Like the Hexproof from XXX counters from Indominus Rex, Alpha
Counter newCounter = CounterType.findByName(counter.getName()).createInstance();
if (player.addCounters(newCounter, source.getControllerId(), source, game)) {
game.informPlayers(player.getLogName() + " had " + newCounter.getDescription() + " added to them.");

View file

@ -0,0 +1,53 @@
package mage.abilities.effects.common.counter;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* Removes all counters (optionally of a given counter type) from the target permanent.
*
* @author MTGfan
*/
public class RemoveAllCountersPermanentTargetEffect extends OneShotEffect {
private final CounterType counterType; // If not null, remove counters of that type only.
public RemoveAllCountersPermanentTargetEffect() {
this((CounterType) null);
}
public RemoveAllCountersPermanentTargetEffect(CounterType counterType) {
super(Outcome.Neutral);
this.counterType = counterType;
staticText = "remove all " + (counterType == null ? "" : counterType.getName() + " ") + "counters from it.";
}
public RemoveAllCountersPermanentTargetEffect(RemoveAllCountersPermanentTargetEffect effect) {
super(effect);
this.counterType = effect.counterType;
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
if (counterType == null) {
permanent.removeAllCounters(source, game);
} else {
permanent.removeAllCounters(counterType.getName(), source, game);
}
return true;
}
return false;
}
@Override
public RemoveAllCountersPermanentTargetEffect copy() {
return new RemoveAllCountersPermanentTargetEffect(this);
}
}

View file

@ -1,45 +0,0 @@
package mage.abilities.effects.common.counter;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
*
* @author MTGfan
*/
public class RemoveAllCountersTargetEffect extends OneShotEffect {
private final CounterType counterType;
public RemoveAllCountersTargetEffect(CounterType counterType) {
super(Outcome.Neutral);
this.counterType = counterType;
staticText = "remove all " + counterType.getName() + " counters from it.";
}
public RemoveAllCountersTargetEffect(RemoveAllCountersTargetEffect effect) {
super(effect);
this.counterType = effect.counterType;
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if(permanent != null) {
int count = permanent.getCounters(game).getCount(counterType);
permanent.removeCounters(counterType.getName(), count, source, game);
return true;
}
return false;
}
@Override
public RemoveAllCountersTargetEffect copy() {
return new RemoveAllCountersTargetEffect(this);
}
}

View file

@ -88,11 +88,13 @@ public interface Card extends MageObject, Ownerable {
/**
* Is this an extra deck card? (such as contraptions and attractions)
*
* @return true if this is an extra deck card, false otherwise
*/
default boolean isExtraDeckCard() {
return false;
}
void assignNewId();
void addInfo(String key, String value, Game game);
@ -168,17 +170,64 @@ public interface Card extends MageObject, Ownerable {
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters);
default void removeCounters(String name, int amount, Ability source, Game game){
removeCounters(name, amount, source, game, false);
/**
* Remove {@param amount} counters of the specified kind.
*/
default void removeCounters(String counterName, int amount, Ability source, Game game) {
removeCounters(counterName, amount, source, game, false);
}
void removeCounters(String name, int amount, Ability source, Game game, boolean damage);
/**
* Remove {@param amount} counters of the specified kind.
*
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
*/
void removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage);
default void removeCounters(Counter counter, Ability source, Game game) {
removeCounters(counter, source, game, false);
}
void removeCounters(Counter counter, Ability source, Game game, boolean damage);
/**
* Remove all counters of any kind.
*
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
*/
void removeCounters(Counter counter, Ability source, Game game, boolean isDamage);
/**
* Remove all counters of any kind.
*
* @return the amount of counters removed this way.
*/
default int removeAllCounters(Ability source, Game game) {
return removeAllCounters(source, game, false);
}
/**
* Remove all counters of any kind.
*
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
* @return the amount of counters removed this way.
*/
int removeAllCounters(Ability source, Game game, boolean isDamage);
/**
* Remove all counters of a specific kind. Return the amount of counters removed this way.
*
* @return the amount of counters removed this way.
*/
default int removeAllCounters(String counterName, Ability source, Game game) {
return removeAllCounters(counterName, source, game, false);
}
/**
* Remove all counters of a specific kind. Return the amount of counters removed this way.
*
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
* @return the amount of counters removed this way.
*/
int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage);
@Override
Card copy();

View file

@ -803,39 +803,40 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
}
@Override
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
public void removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage) {
if (amount <= 0){
if (amount <= 0) {
return;
}
if (getCounters(game).getCount(name) <= 0){
if (getCounters(game).getCount(counterName) <= 0) {
return;
}
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, isDamage);
if (game.replaceEvent(removeCountersEvent)){
GameEvent removeCountersEvent = new RemoveCountersEvent(counterName, this, source, amount, isDamage);
if (game.replaceEvent(removeCountersEvent)) {
return;
}
int finalAmount = 0;
for (int i = 0; i < removeCountersEvent.getAmount(); i++) {
GameEvent event = new RemoveCounterEvent(name, this, source, isDamage);
if (game.replaceEvent(event)){
GameEvent event = new RemoveCounterEvent(counterName, this, source, isDamage);
if (game.replaceEvent(event)) {
continue;
}
if (!getCounters(game).removeCounter(name, 1)) {
if (!getCounters(game).removeCounter(counterName, 1)) {
break;
}
event = new CounterRemovedEvent(name, this, source, isDamage);
event = new CounterRemovedEvent(counterName, this, source, isDamage);
game.fireEvent(event);
finalAmount++;
}
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, isDamage);
GameEvent event = new CountersRemovedEvent(counterName, this, source, finalAmount, isDamage);
game.fireEvent(event);
}
@ -846,6 +847,24 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
}
}
@Override
public int removeAllCounters(Ability source, Game game, boolean isDamage) {
int amountBefore = getCounters(game).getTotalCount();
for (Counter counter : getCounters(game).copy().values()) {
removeCounters(counter.getName(), counter.getCount(), source, game, isDamage);
}
int amountAfter = getCounters(game).getTotalCount();
return Math.max(0, amountBefore - amountAfter);
}
@Override
public int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage) {
int amountBefore = getCounters(game).getCount(counterName);
removeCounters(counterName, amountBefore, source, game, isDamage);
int amountAfter = getCounters(game).getCount(counterName);
return Math.max(0, amountBefore - amountAfter);
}
@Override
public String getLogName() {
if (name.isEmpty()) {

View file

@ -223,8 +223,8 @@ public abstract class ModalDoubleFacedCard extends CardImpl implements CardWithH
}
@Override
public void removeCounters(String name, int amount, Ability source, Game game) {
leftHalfCard.removeCounters(name, amount, source, game);
public void removeCounters(String counterName, int amount, Ability source, Game game) {
leftHalfCard.removeCounters(counterName, amount, source, game);
}
@Override

View file

@ -27,35 +27,17 @@ public class Counters extends HashMap<String, Counter> implements Serializable,
return new Counters(this);
}
public Counters addCounter(String name, int amount) {
putIfAbsent(name, new Counter(name));
this.get(name).add(amount);
return this;
}
public Counters addCounter(Counter counter) {
if (!containsKey(counter.name)) {
put(counter.name, counter);
} else {
get(counter.name).add(counter.getCount());
}
return this;
}
public boolean removeCounter(String name) {
return removeCounter(name, 1);
}
public boolean removeCounter(CounterType counterType, int amount) {
if (this.containsKey(counterType.getName())) {
get(counterType.getName()).remove(amount);
if (get(counterType.getName()).count == 0) {
this.remove(counterType.getName());
}
return true;
}
return false;
return removeCounter(counterType.getName(), amount);
}
public boolean removeCounter(String name, int amount) {
@ -69,17 +51,6 @@ public class Counters extends HashMap<String, Counter> implements Serializable,
return false;
}
public void removeAllCounters(CounterType counterType) {
removeAllCounters(counterType.getName());
}
public void removeAllCounters(String name) {
if (this.containsKey(name)) {
this.remove(name);
}
}
public int getCount(String name) {
if (this.containsKey(name)) {
return this.get(name).getCount();
@ -91,6 +62,10 @@ public class Counters extends HashMap<String, Counter> implements Serializable,
return getCount(counterType) > 0;
}
public int getTotalCount() {
return this.values().stream().mapToInt(Counter::getCount).sum();
}
public int getCount(CounterType type) {
if (this.containsKey(type.getName())) {
return this.get(type.getName()).getCount();

View file

@ -29,7 +29,7 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer
public boolean match(MageItem o, Game game) {
if (super.match(o, game)) {
if (o instanceof Player) {
return !((Player) o).getCounters().isEmpty();
return ((Player) o).getCountersTotalCount() > 0;
} else if (o instanceof Permanent) {
return !((Permanent) o).getCounters(game).isEmpty();
}
@ -41,7 +41,7 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer
public boolean match(MageItem o, UUID playerId, Ability source, Game game) {
if (super.match(o, playerId, source, game)) { // same as parent class, so can call with full params
if (o instanceof Player) {
return !((Player) o).getCounters().isEmpty();
return ((Player) o).getCountersTotalCount() > 0;
} else if (o instanceof Permanent) {
return !((Permanent) o).getCounters(game).isEmpty();
}

View file

@ -2195,7 +2195,7 @@ public abstract class GameImpl implements Game {
public UUID fireReflexiveTriggeredAbility(ReflexiveTriggeredAbility reflexiveAbility, Ability source) {
return fireReflexiveTriggeredAbility(reflexiveAbility, source, false);
}
@Override
public UUID fireReflexiveTriggeredAbility(ReflexiveTriggeredAbility reflexiveAbility, Ability source, boolean fireAsSimultaneousEvent) {
UUID uuid = this.addDelayedTriggeredAbility(reflexiveAbility, source);
@ -2300,7 +2300,7 @@ public abstract class GameImpl implements Game {
if (!player.hasLost()
&& ((player.getLife() <= 0 && player.canLoseByZeroOrLessLife())
|| player.getLibrary().isEmptyDraw()
|| player.getCounters().getCount(CounterType.POISON) >= 10)) {
|| player.getCountersCount(CounterType.POISON) >= 10)) {
player.lost(this);
}
}

View file

@ -66,7 +66,7 @@ enum RadiationCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
return player != null && player.getCounters().getCount(CounterType.RAD) > 0;
return player != null && player.getCountersCount(CounterType.RAD) > 0;
}
}
@ -102,13 +102,13 @@ class RadiationEffect extends OneShotEffect {
if (player == null) {
return false;
}
int amount = player.getCounters().getCount(CounterType.RAD);
int amount = player.getCountersCount(CounterType.RAD);
Cards milled = player.millCards(amount, source, game);
int countNonLand = milled.count(StaticFilters.FILTER_CARD_NON_LAND, player.getId(), source, game);
if (countNonLand > 0) {
// TODO: support gaining life instead with [[Strong, the Brutish Thespian]]
player.loseLife(countNonLand, game, source, false);
player.removeCounters(CounterType.RAD.getName(), countNonLand, source, game);
player.loseCounters(CounterType.RAD.getName(), countNonLand, source, game);
}
return true;
}

View file

@ -548,8 +548,8 @@ public class GameEvent implements Serializable {
amount number of counters being removed
data name of the counter(s) being removed
*/
REMOVE_COUNTER, REMOVE_COUNTERS,
COUNTER_REMOVED, COUNTERS_REMOVED,
REMOVE_COUNTER, COUNTER_REMOVED,
REMOVE_COUNTERS, COUNTERS_REMOVED,
LOSE_CONTROL,
/* LOST_CONTROL
targetId id of the creature that lost control

View file

@ -65,7 +65,7 @@ class DaxosSpiritSetPTEffect extends ContinuousEffectImpl {
return false;
}
int amount = controller.getCounters().getCount(CounterType.EXPERIENCE);
int amount = controller.getCountersCount(CounterType.EXPERIENCE);
permanent.getPower().setModifiedBaseValue(amount);
permanent.getToughness().setModifiedBaseValue(amount);
return true;

View file

@ -1090,8 +1090,8 @@ public class Spell extends StackObjectImpl implements Card {
}
@Override
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
card.removeCounters(name, amount, source, game, isDamage);
public void removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage) {
card.removeCounters(counterName, amount, source, game, isDamage);
}
@Override
@ -1099,6 +1099,16 @@ public class Spell extends StackObjectImpl implements Card {
card.removeCounters(counter, source, game, isDamage);
}
@Override
public int removeAllCounters(Ability source, Game game, boolean isDamage) {
return card.removeAllCounters(source, game, isDamage);
}
@Override
public int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage) {
return card.removeAllCounters(counterName, source, game, isDamage);
}
public Card getCard() {
return card;
}

View file

@ -372,7 +372,7 @@ public class Turn implements Serializable {
int delimiter = game.getPlayers().size() - 1;
for (Player gamePlayer : game.getPlayers().values()) {
sb.append(gamePlayer.getLife());
int poison = gamePlayer.getCounters().getCount(CounterType.POISON);
int poison = gamePlayer.getCountersCount(CounterType.POISON);
if (poison > 0) {
sb.append("[P:").append(poison).append(']');
}

View file

@ -15,6 +15,7 @@ import mage.cards.decks.Deck;
import mage.choices.Choice;
import mage.constants.*;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.counters.Counters;
import mage.designations.Designation;
import mage.designations.DesignationType;
@ -105,7 +106,11 @@ public interface Player extends MageItem, Copyable<Player> {
void addAbility(Ability ability);
Counters getCounters();
/**
* The counters should be manipulated (adding or removing counters) with the appropriate addCounters/removeCounters/getCounterCount methods.
* This returns a copy for specific usage, to make sure the Player's counters are not altered from there.
*/
Counters getCountersAsCopy();
int getLife();
@ -832,9 +837,44 @@ public interface Player extends MageItem, Copyable<Player> {
Map<UUID, ActivatedAbility> getPlayableActivatedAbilities(MageObject object, Zone zone, Game originalGame);
/**
* add counter to the player (action verb is `get`, but not using that one to avoid ambiguity with getters)
*/
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game);
void removeCounters(String name, int amount, Ability source, Game game);
/**
* lose {@param amount} counters of the specified kind.
*/
void loseCounters(String counterName, int amount, Ability source, Game game);
/**
* lose all counters of any kind.
*
* @return the amount of counters removed this way.
*/
int loseAllCounters(Ability source, Game game);
/**
* lose all counters of a specific kind.
*
* @return the amount of counters removed this way.
*/
int loseAllCounters(String counterName, Ability source, Game game);
/**
* @return the amount of counters of the specified kind the player has
*/
int getCountersCount(CounterType counterType);
/**
* @return the amount of counters of the specified kind the player has
*/
int getCountersCount(String counterName);
/**
* @return the amount of counters in total of any kind the player has
*/
int getCountersTotalCount();
List<UUID> getAttachments();

View file

@ -337,7 +337,7 @@ public abstract class PlayerImpl implements Player, Serializable {
this.commandersIds = new HashSet<>(player.getCommandersIds());
this.abilities = player.getAbilities().copy();
this.counters = player.getCounters().copy();
this.counters = player.getCountersAsCopy();
this.landsPlayed = player.getLandsPlayed();
this.landsPerTurn = player.getLandsPerTurn();
@ -531,8 +531,8 @@ public abstract class PlayerImpl implements Player, Serializable {
}
@Override
public Counters getCounters() {
return counters;
public Counters getCountersAsCopy() {
return counters.copy();
}
@Override
@ -2369,7 +2369,7 @@ public abstract class PlayerImpl implements Player, Serializable {
);
addingOneEvent.setFlag(isEffectFlag);
if (!game.replaceEvent(addingOneEvent)) {
getCounters().addCounter(eventCounter);
counters.addCounter(eventCounter);
GameEvent addedOneEvent = GameEvent.getEvent(
GameEvent.EventType.COUNTER_ADDED, playerId, source,
playerAddingCounters, counter.getName(), 1
@ -2396,9 +2396,9 @@ public abstract class PlayerImpl implements Player, Serializable {
}
@Override
public void removeCounters(String name, int amount, Ability source, Game game) {
public void loseCounters(String counterName, int amount, Ability source, Game game) {
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, false);
GameEvent removeCountersEvent = new RemoveCountersEvent(counterName, this, source, amount, false);
if (game.replaceEvent(removeCountersEvent)) {
return;
}
@ -2406,22 +2406,56 @@ public abstract class PlayerImpl implements Player, Serializable {
int finalAmount = 0;
for (int i = 0; i < amount; i++) {
GameEvent event = new RemoveCounterEvent(name, this, source, false);
GameEvent event = new RemoveCounterEvent(counterName, this, source, false);
if (game.replaceEvent(event)) {
continue;
}
if (!counters.removeCounter(name, 1)) {
if (!counters.removeCounter(counterName, 1)) {
break;
}
event = new CounterRemovedEvent(name, this, source, false);
event = new CounterRemovedEvent(counterName, this, source, false);
game.fireEvent(event);
finalAmount++;
}
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, false);
GameEvent event = new CountersRemovedEvent(counterName, this, source, finalAmount, false);
game.fireEvent(event);
}
@Override
public int loseAllCounters(Ability source, Game game) {
int amountBefore = getCountersTotalCount();
for (Counter counter : getCountersAsCopy().values()) {
loseCounters(counter.getName(), counter.getCount(), source, game);
}
int amountAfter = getCountersTotalCount();
return Math.max(0, amountBefore - amountAfter);
}
@Override
public int loseAllCounters(String counterName, Ability source, Game game) {
int amountBefore = getCountersCount(counterName);
loseCounters(counterName, amountBefore, source, game);
int amountAfter = getCountersCount(counterName);
return Math.max(0, amountBefore - amountAfter);
}
@Override
public int getCountersCount(CounterType counterType) {
return counters.getCount(counterType);
}
@Override
public int getCountersCount(String counterName) {
return counters.getCount(counterName);
}
@Override
public int getCountersTotalCount() {
return counters.getTotalCount();
}
@Override
public Abilities<Ability> getAbilities() {
return this.abilities;

View file

@ -16,7 +16,7 @@ public class CountersTest {
@Test
public void testCopyCounter() {
// given
counters.addCounter("test", 4);
counters.addCounter(new Counter("test", 5));
// when
Counters copy = counters.copy();
@ -29,8 +29,8 @@ public class CountersTest {
@Test
public void testRemoveCounter() {
// given
counters.addCounter("test1", 5);
counters.addCounter("test2", 5);
counters.addCounter(new Counter("test1", 5));
counters.addCounter(new Counter("test2", 5));
// when
@ -45,35 +45,23 @@ public class CountersTest {
@Test
public void testAddCounterWithNewCounter() {
// given
counters.addCounter("test1", 5);
counters.addCounter(new Counter("test1", 5));
// when
counters.addCounter("test1", 10);
counters.addCounter("test2", 5);
counters.addCounter(new Counter("test1", 10));
counters.addCounter(new Counter("test2", 5));
// then
assertNotEquals(15, counters.getCount("test1"));
assertEquals(16, counters.getCount("test1"));
assertTrue(counters.containsKey("test1"));
assertEquals(15, counters.getCount("test1"));
assertTrue(counters.containsKey("test2"));
assertEquals(6, counters.getCount("test2"));
}
@Test
public void testRemoveAllCounter() {
// given
counters.addCounter("test", 10);
// when
counters.removeAllCounters("test");
// then
assertFalse(counters.containsKey("test"));
assertEquals(5, counters.getCount("test2"));
}
@Test
public void testGetCount() {
// given
counters.addCounter("test1", 5);
counters.addCounter(new Counter("test1", 5));
// when
int count1 = counters.getCount("test1");
@ -81,13 +69,13 @@ public class CountersTest {
// then
assertEquals(0, count2);
assertEquals(6, count1);
assertEquals(5, count1);
}
@Test
public void testContainsKey() {
// given
counters.addCounter("test1", 5);
counters.addCounter(new Counter("test1", 5));
// when