Revert "Added missing fields to many copy constructors. (#8957)" (#8999)

This reverts commit 82708e4273.

Some of these (AI related result in bloated memory usage, needs more investigation).
This commit is contained in:
Alex Vasile 2022-05-25 12:57:24 -06:00 committed by GitHub
parent 2f3831599d
commit 015cdf3136
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 597 additions and 811 deletions

View file

@ -76,11 +76,7 @@ public class CardDownloadData {
this.tokenDescriptor = card.tokenDescriptor;
this.tokenClassName = card.tokenClassName;
this.fileName = card.fileName;
this.splitCard = card.splitCard;
this.flipCard = card.flipCard;
this.flippedSide = card.flippedSide;
this.downloadName = card.downloadName;
this.isType2 = card.isType2;
}
@Override

View file

@ -31,7 +31,6 @@ public class MomirGame extends GameImpl {
public MomirGame(final MomirGame game) {
super(game);
this.numPlayers = game.numPlayers;
}
@Override

View file

@ -68,7 +68,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
protected Set<String> actionCache;
private static final List<TreeOptimizer> optimizers = new ArrayList<>();
protected int lastLoggedTurn;
protected int lastLoggedTurn = 0;
protected static final String BLANKS = "...............................................";
static {
@ -80,7 +80,11 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
public ComputerPlayer6(String name, RangeOfInfluence range, int skill) {
super(name, range);
maxDepth = Math.max(skill, 4);
if (skill < 4) {
maxDepth = 4;
} else {
maxDepth = skill;
}
maxThink = skill * 3;
maxNodes = Config2.maxNodes;
getSuggestedActions();
@ -90,11 +94,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
public ComputerPlayer6(final ComputerPlayer6 player) {
super(player);
this.maxDepth = player.maxDepth;
this.maxNodes = player.maxNodes;
this.maxThink = player.maxThink;
this.lastLoggedTurn = player.lastLoggedTurn;
this.currentScore = player.currentScore;
this.root = player.root;
if (player.combat != null) {
this.combat = player.combat.copy();
}
@ -102,8 +102,6 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
this.targets.addAll(player.targets);
this.choices.addAll(player.choices);
this.actionCache = player.actionCache;
this.attackersList.addAll(player.attackersList);
this.attackersToCheck.addAll(player.attackersToCheck);
}
@Override

View file

@ -58,7 +58,6 @@ public class SimulatedPlayer2 extends ComputerPlayer {
this.suggested = new ArrayList<>(player.suggested);
// this.allActions = player.allActions; // dynamic, no need to copy
this.originalPlayer = player.originalPlayer.copy();
this.forced = player.forced;
}
@Override

View file

@ -67,7 +67,7 @@ import java.util.Map.Entry;
public class ComputerPlayer extends PlayerImpl implements Player {
private static final Logger log = Logger.getLogger(ComputerPlayer.class);
private long lastThinkTime; // msecs for last AI actions calc
private long lastThinkTime = 0; // msecs for last AI actions calc
protected int PASSIVITY_PENALTY = 5; // Penalty value for doing nothing if some actions are available
@ -105,9 +105,6 @@ public class ComputerPlayer extends PlayerImpl implements Player {
public ComputerPlayer(final ComputerPlayer player) {
super(player);
this.lastThinkTime = player.lastThinkTime;
this.PASSIVITY_PENALTY = player.PASSIVITY_PENALTY;
this.COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS = player.COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS;
}
@Override

View file

@ -31,13 +31,10 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player {
private static final int THINK_MAX_RATIO = 100;
private static final double THINK_TIME_MULTIPLIER = 2.0;
private static final boolean USE_MULTIPLE_THREADS = true;
private static final Logger logger = Logger.getLogger(ComputerPlayerMCTS.class);
protected transient MCTSNode root;
protected String lastPhase = "";
protected long totalThinkTime;
protected long totalSimulations;
protected int maxThinkTime;
private static final Logger logger = Logger.getLogger(ComputerPlayerMCTS.class);
private int poolSize;
public ComputerPlayerMCTS(String name, RangeOfInfluence range, int skill) {
@ -53,11 +50,6 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player {
public ComputerPlayerMCTS(final ComputerPlayerMCTS player) {
super(player);
this.maxThinkTime = player.maxThinkTime;
this.poolSize = player.poolSize;
this.lastPhase = player.lastPhase;
this.totalSimulations = player.totalSimulations;
this.totalThinkTime = player.totalThinkTime;
}
@Override
@ -65,6 +57,8 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player {
return new ComputerPlayerMCTS(this);
}
protected String lastPhase = "";
@Override
public boolean priority(Game game) {
if (game.getStep().getType() == PhaseStep.UPKEEP) {
@ -158,6 +152,9 @@ public class ComputerPlayerMCTS extends ComputerPlayer implements Player {
MCTSNode.logHitMiss();
}
protected long totalThinkTime = 0;
protected long totalSimulations = 0;
protected void applyMCTS(final Game game, final NextAction action) {
int thinkTime = calculateThinkTime(game, action);

View file

@ -30,8 +30,8 @@ import java.util.*;
*/
public class SimulatedPlayerMCTS extends MCTSPlayer {
private final boolean isSimulatedPlayer;
private int actionCount;
private boolean isSimulatedPlayer;
private int actionCount = 0;
private static final Logger logger = Logger.getLogger(SimulatedPlayerMCTS.class);
public SimulatedPlayerMCTS(Player originalPlayer, boolean isSimulatedPlayer) {
@ -43,7 +43,6 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
public SimulatedPlayerMCTS(final SimulatedPlayerMCTS player) {
super(player);
this.isSimulatedPlayer = player.isSimulatedPlayer;
this.actionCount = player.actionCount;
}
@Override

View file

@ -40,8 +40,8 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
protected int maxDepth;
protected int maxNodes;
protected int maxThink;
protected int nodeCount;
protected long thinkTime;
protected int nodeCount = 0;
protected long thinkTime = 0;
protected transient LinkedList<Ability> actions = new LinkedList<>();
protected transient List<UUID> targets = new ArrayList<>();
protected transient List<String> choices = new ArrayList<>();
@ -59,10 +59,6 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
public ComputerPlayer2(final ComputerPlayer2 player) {
super(player);
this.maxDepth = player.maxDepth;
this.maxNodes = player.maxNodes;
this.maxThink = player.maxThink;
this.nodeCount = player.nodeCount;
this.thinkTime = player.thinkTime;
this.currentScore = player.currentScore;
if (player.combat != null) {
this.combat = player.combat.copy();

View file

@ -28,9 +28,9 @@ import java.util.concurrent.ConcurrentLinkedQueue;
public class SimulatedPlayer extends ComputerPlayer {
private static final Logger logger = Logger.getLogger(SimulatedPlayer.class);
private final boolean isSimulatedPlayer;
private boolean isSimulatedPlayer;
private transient ConcurrentLinkedQueue<Ability> allActions;
private static final PassAbility pass = new PassAbility();
private static PassAbility pass = new PassAbility();
protected int maxDepth;
public SimulatedPlayer(Player originalPlayer, boolean isSimulatedPlayer, int maxDepth) {
@ -44,7 +44,6 @@ public class SimulatedPlayer extends ComputerPlayer {
public SimulatedPlayer(final SimulatedPlayer player) {
super(player);
this.isSimulatedPlayer = player.isSimulatedPlayer;
this.maxDepth = player.maxDepth;
}
@Override

View file

@ -61,9 +61,8 @@ class CaromEffect extends RedirectionEffect {
staticText = "The next " + amount + " damage that would be dealt to target creature this turn is dealt to another target creature instead";
}
private CaromEffect(final CaromEffect effect) {
public CaromEffect(final CaromEffect effect) {
super(effect);
this.redirectToObject = effect.redirectToObject;
}
@Override

View file

@ -30,8 +30,7 @@ public final class DesecratorHag extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// When Desecrator Hag enters the battlefield, return to your hand the creature card in your graveyard with the greatest power.
// If two or more cards are tied for greatest power, you choose one of them.
// When Desecrator Hag enters the battlefield, return to your hand the creature card in your graveyard with the greatest power. If two or more cards are tied for greatest power, you choose one of them.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DesecratorHagEffect(), false));
}
@ -48,21 +47,17 @@ public final class DesecratorHag extends CardImpl {
class DesecratorHagEffect extends OneShotEffect {
int creatureGreatestPower;
int creatureGreatestPower = 0;
Cards cards = new CardsImpl();
TargetCard target = new TargetCard(Zone.GRAVEYARD, new FilterCard());
public DesecratorHagEffect() {
super(Outcome.DrawCard);
this.staticText = "return to your hand the creature card in your graveyard with the greatest power. " +
"If two or more cards are tied for greatest power, you choose one of them";
this.staticText = "return to your hand the creature card in your graveyard with the greatest power. If two or more cards are tied for greatest power, you choose one of them";
}
public DesecratorHagEffect(final DesecratorHagEffect effect) {
super(effect);
this.creatureGreatestPower = effect.creatureGreatestPower;
this.cards = effect.cards.copy();
this.target = effect.target.copy();
}
@Override
@ -73,40 +68,35 @@ class DesecratorHagEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player you = game.getPlayer(source.getControllerId());
if (you == null) {
return false;
}
for (Card card : you.getGraveyard().getCards(game)) {
if (card.isCreature(game)) {
if (card.getPower().getValue() > creatureGreatestPower) {
creatureGreatestPower = card.getPower().getValue();
cards.clear();
cards.add(card);
} else {
if (card.getPower().getValue() == creatureGreatestPower) {
if (you != null) {
for (Card card : you.getGraveyard().getCards(game)) {
if (card.isCreature(game)) {
if (card.getPower().getValue() > creatureGreatestPower) {
creatureGreatestPower = card.getPower().getValue();
cards.clear();
cards.add(card);
} else {
if (card.getPower().getValue() == creatureGreatestPower) {
cards.add(card);
}
}
}
}
}
if (cards.isEmpty()) {
return false;
} else if (cards.size() == 1) {
return you.moveCards(cards, Zone.HAND, source, game);
} else {
if (you.choose(Outcome.DrawCard, cards, target, game)) {
if (target == null) {
return false;
}
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
return you.moveCards(card, Zone.HAND, source, game);
}
if (cards.isEmpty()) {
return true;
}
if (cards.size() > 1
&& you.choose(Outcome.DrawCard, cards, target, game)) {
if (target != null) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
return you.moveCards(card, Zone.HAND, source, game);
}
}
} else {
return you.moveCards(cards, Zone.HAND, source, game);
}
return false;
}
return false;
}
}

View file

@ -33,9 +33,7 @@ public final class DesperateGambit extends CardImpl {
public DesperateGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}");
// Choose a source you control and flip a coin.
// If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead.
// If you lose the flip, the next time it would deal damage this turn, prevent that damage.
// Choose a source you control and flip a coin. If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. If you lose the flip, the next time it would deal damage this turn, prevent that damage.
this.getSpellAbility().addEffect(new DesperateGambitEffect());
}
@ -56,16 +54,13 @@ class DesperateGambitEffect extends PreventionEffectImpl {
public DesperateGambitEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "Choose a source you control and flip a coin. " +
"If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. " +
"If you lose the flip, the next time it would deal damage this turn, prevent that damage";
staticText = "Choose a source you control and flip a coin. If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. If you lose the flip, the next time it would deal damage this turn, prevent that damage";
this.target = new TargetControlledSource();
}
public DesperateGambitEffect(final DesperateGambitEffect effect) {
super(effect);
this.target = effect.target.copy();
this.wonFlip = effect.wonFlip;
}
@Override

View file

@ -80,7 +80,7 @@ class DoublingSeasonTokenEffect extends ReplacementEffectImpl {
class DoublingSeasonCounterEffect extends ReplacementEffectImpl {
private boolean landPlayed; // a played land is not an effect
private boolean landPlayed = false; // a played land is not an effect
DoublingSeasonCounterEffect() {
super(Duration.WhileOnBattlefield, Outcome.BoostCreature, false);
@ -89,7 +89,6 @@ class DoublingSeasonCounterEffect extends ReplacementEffectImpl {
private DoublingSeasonCounterEffect(final DoublingSeasonCounterEffect effect) {
super(effect);
this.landPlayed = effect.landPlayed;
}
@Override
@ -111,7 +110,8 @@ class DoublingSeasonCounterEffect extends ReplacementEffectImpl {
}
if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId());
landPlayed = (permanent != null && permanent.isLand(game)); // a played land is not an effect
landPlayed = (permanent != null
&& permanent.isLand(game)); // a played land is not an effect
}
return permanent != null
&& permanent.isControlledBy(source.getControllerId())

View file

@ -8,7 +8,6 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
import mage.abilities.effects.ContinuousEffect;
@ -102,7 +101,7 @@ class DreadWightTriggeredAbility extends TriggeredAbilityImpl {
class DreadWightEffect extends OneShotEffect {
static final String rule = "doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it.";
String rule = "doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it.";
public DreadWightEffect() {
super(Outcome.Detriment);
@ -123,42 +122,44 @@ class DreadWightEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
if (permanent == null) {
return false;
if (permanent != null) {
// add paralyzation counter
Effect effect = new AddCountersTargetEffect(CounterType.PARALYZATION.createInstance());
effect.setTargetPointer(new FixedTarget(permanent, game));
effect.apply(game, source);
// tap permanent
permanent.tap(source, game);
// does not untap while paralyzation counter is on it
ContinuousRuleModifyingEffect effect2 = new DreadWightDoNotUntapEffect(
Duration.WhileOnBattlefield,
permanent.getId());
effect2.setText("This creature doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it");
Condition condition = new DreadWightCounterCondition(permanent.getId());
ConditionalContinuousRuleModifyingEffect conditionalEffect = new ConditionalContinuousRuleModifyingEffect(
effect2,
condition);
Ability ability = new SimpleStaticAbility(
Zone.BATTLEFIELD,
conditionalEffect);
ContinuousEffect effect3 = new GainAbilityTargetEffect(
ability,
Duration.WhileOnBattlefield);
ability.setRuleVisible(true);
effect3.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect3, source);
// each gains 4: remove paralyzation counter
Ability activatedAbility = new SimpleActivatedAbility(
Zone.BATTLEFIELD,
new RemoveCounterSourceEffect(CounterType.PARALYZATION.createInstance()),
new ManaCostsImpl("{4}"));
ContinuousEffect effect4 = new GainAbilityTargetEffect(
activatedAbility,
Duration.WhileOnBattlefield);
effect4.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect4, source);
return true;
}
// add paralyzation counter
Effect effect = new AddCountersTargetEffect(CounterType.PARALYZATION.createInstance());
effect.setTargetPointer(new FixedTarget(permanent, game));
effect.apply(game, source);
// tap permanent
permanent.tap(source, game);
// does not untap while paralyzation counter is on it
ContinuousRuleModifyingEffect effect2 = new DreadWightDoNotUntapEffect(Duration.WhileOnBattlefield, permanent.getId());
effect2.setText(rule);
Condition condition = new DreadWightCounterCondition(permanent.getId());
ConditionalContinuousRuleModifyingEffect conditionalEffect = new ConditionalContinuousRuleModifyingEffect(
effect2,
condition);
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, conditionalEffect);
ContinuousEffect effect3 = new GainAbilityTargetEffect(ability, Duration.WhileOnBattlefield);
ability.setRuleVisible(true);
effect3.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect3, source);
// each gains 4: remove paralyzation counter
Ability activatedAbility = new SimpleActivatedAbility(
Zone.BATTLEFIELD,
new RemoveCounterSourceEffect(CounterType.PARALYZATION.createInstance()),
new GenericManaCost(4));
ContinuousEffect effect4 = new GainAbilityTargetEffect(activatedAbility, Duration.WhileOnBattlefield);
effect4.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect4, source);
return true;
return false;
}
}

View file

@ -97,21 +97,12 @@ class DubiousChallengeEffect extends OneShotEffect {
class DubiousChallengeMoveToBattlefieldEffect extends OneShotEffect {
private Cards cards;
private Player player;
public DubiousChallengeMoveToBattlefieldEffect() {
super(Outcome.Benefit);
}
public DubiousChallengeMoveToBattlefieldEffect(final DubiousChallengeMoveToBattlefieldEffect effect) {
super(effect);
if (effect.cards != null) {
this.cards = effect.cards.copy();
}
if (effect.player != null) {
this.player = effect.player.copy();
}
}
@Override
@ -126,10 +117,12 @@ class DubiousChallengeMoveToBattlefieldEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
if (cards == null || player == null) {
return false;
if (cards != null && player != null) {
return player.moveCards(cards, Zone.BATTLEFIELD, source, game);
}
return player.moveCards(cards, Zone.BATTLEFIELD, source, game);
return false;
}
private Cards cards;
private Player player;
}

View file

@ -61,21 +61,17 @@ class ElkinBottleExileEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
if (controller != null) {
Card card = controller.getLibrary().getFromTop(game);
if (card != null) {
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), CardUtil.createObjectRealtedWindowTitle(source, game, null));
ContinuousEffect effect = new ElkinBottleCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), game));
game.addEffect(effect, source);
}
return true;
}
Card card = controller.getLibrary().getFromTop(game);
if (card == null) {
return false;
}
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), CardUtil.createObjectRealtedWindowTitle(source, game, null));
ContinuousEffect effect = new ElkinBottleCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), game));
game.addEffect(effect, source);
return true;
return false;
}
}
@ -90,7 +86,6 @@ class ElkinBottleCastFromExileEffect extends AsThoughEffectImpl {
public ElkinBottleCastFromExileEffect(final ElkinBottleCastFromExileEffect effect) {
super(effect);
this.sameStep = effect.sameStep;
}
@Override
@ -101,9 +96,9 @@ class ElkinBottleCastFromExileEffect extends AsThoughEffectImpl {
@Override
public boolean isInactive(Ability source, Game game) {
if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) {
return !sameStep
&& game.isActivePlayer(source.getControllerId())
|| game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving();
if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
return true;
}
} else {
sameStep = false;
}

View file

@ -34,9 +34,7 @@ public final class FoodChain extends CardImpl {
public FoodChain(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
// Exile a creature you control: Add X mana of any one color,
// where X is the exiled creature's converted mana cost plus one.
// Spend this mana only to cast creature spells.
// Exile a creature you control: Add X mana of any one color, where X is the exiled creature's converted mana cost plus one. Spend this mana only to cast creature spells.
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new FoodChainManaEffect(),
new ExileTargetCost(new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_A_CREATURE, true)));
this.addAbility(ability);
@ -70,13 +68,11 @@ class FoodChainManaEffect extends ManaEffect {
ConditionalManaBuilder manaBuilder = new FoodChainManaBuilder();
FoodChainManaEffect() {
this.staticText = "Add X mana of any one color, where X is 1 plus the exiled creature's mana value. " +
"Spend this mana only to cast creature spells";
this.staticText = "Add X mana of any one color, where X is 1 plus the exiled creature's mana value. Spend this mana only to cast creature spells";
}
FoodChainManaEffect(final FoodChainManaEffect effect) {
super(effect);
this.manaBuilder = effect.manaBuilder;
}
@Override
@ -87,25 +83,21 @@ class FoodChainManaEffect extends ManaEffect {
@Override
public List<Mana> getNetMana(Game game, Ability source) {
List<Mana> netMana = new ArrayList<>();
if (game == null) {
return netMana;
}
int cmc = -1;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (permanent.isCreature(game)) {
cmc = Math.max(cmc, permanent.getManaCost().manaValue());
if (game != null) {
int cmc = -1;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (permanent.isCreature(game)) {
cmc = Math.max(cmc, permanent.getManaCost().manaValue());
}
}
if (cmc != -1) {
netMana.add(manaBuilder.setMana(Mana.BlackMana(cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.BlueMana(cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.RedMana(cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.GreenMana(cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.WhiteMana(cmc + 1), source, game).build());
}
}
if (cmc != -1) {
netMana.add(manaBuilder.setMana(Mana.BlackMana(cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.BlueMana( cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.RedMana( cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.GreenMana(cmc + 1), source, game).build());
netMana.add(manaBuilder.setMana(Mana.WhiteMana(cmc + 1), source, game).build());
}
return netMana;
}
@ -115,27 +107,24 @@ class FoodChainManaEffect extends ManaEffect {
if (game == null) {
return mana;
}
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return mana;
}
int manaCostExiled = 0;
for (Cost cost : source.getCosts()) {
if (cost.isPaid() && cost instanceof ExileTargetCost) {
for (Card card : ((ExileTargetCost) cost).getPermanents()) {
manaCostExiled += card.getManaValue();
if (controller != null) {
int manaCostExiled = 0;
for (Cost cost : source.getCosts()) {
if (cost.isPaid() && cost instanceof ExileTargetCost) {
for (Card card : ((ExileTargetCost) cost).getPermanents()) {
manaCostExiled += card.getManaValue();
}
}
}
ChoiceColor choice = new ChoiceColor();
if (!controller.choose(Outcome.PutManaInPool, choice, game)) {
return mana;
}
Mana chosen = choice.getMana(manaCostExiled + 1);
return manaBuilder.setMana(chosen, source, game).build();
}
ChoiceColor choice = new ChoiceColor();
if (!controller.choose(Outcome.PutManaInPool, choice, game)) {
return mana;
}
Mana chosen = choice.getMana(manaCostExiled + 1);
return manaBuilder.setMana(chosen, source, game).build();
return mana;
}
}

View file

@ -86,7 +86,7 @@ class FrayingSanityTriggeredAbility extends TriggeredAbilityImpl {
class FrayingSanityEffect extends OneShotEffect {
int xAmount;
int xAmount = 0;
public FrayingSanityEffect() {
super(Outcome.Detriment);
@ -95,7 +95,6 @@ class FrayingSanityEffect extends OneShotEffect {
public FrayingSanityEffect(final FrayingSanityEffect effect) {
super(effect);
this.xAmount = effect.xAmount;
}
@Override

View file

@ -33,8 +33,7 @@ public final class GabrielAngelfire extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// At the beginning of your upkeep, choose flying, first strike, trample, or rampage 3.
// Gabriel Angelfire gains that ability until your next upkeep.
// At the beginning of your upkeep, choose flying, first strike, trample, or rampage 3. Gabriel Angelfire gains that ability until your next upkeep.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GabrielAngelfireGainAbilityEffect(), TargetController.YOU, false));
}
@ -65,10 +64,9 @@ class GabrielAngelfireGainAbilityEffect extends GainAbilitySourceEffect {
staticText = "choose flying, first strike, trample, or rampage 3. {this} gains that ability until your next upkeep";
}
private GabrielAngelfireGainAbilityEffect(final GabrielAngelfireGainAbilityEffect effect) {
public GabrielAngelfireGainAbilityEffect(final GabrielAngelfireGainAbilityEffect effect) {
super(effect);
ability.newId();
this.sameStep = effect.sameStep;
}
@Override
@ -79,7 +77,9 @@ class GabrielAngelfireGainAbilityEffect extends GainAbilitySourceEffect {
@Override
public boolean isInactive(Ability source, Game game) {
if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) {
return !sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving();
if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
return true;
}
} else {
sameStep = false;
}
@ -89,32 +89,29 @@ class GabrielAngelfireGainAbilityEffect extends GainAbilitySourceEffect {
@Override
public void init(Ability source, Game game) {
super.init(source, game);
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return;
}
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose one");
choice.setChoices(choices);
if (controller.choose(outcome, choice, game)) {
switch (choice.getChoice()) {
case "First strike":
ability = FirstStrikeAbility.getInstance();
break;
case "Trample":
ability = TrampleAbility.getInstance();
break;
case "Rampage 3":
ability = new RampageAbility(3);
break;
default:
ability = FlyingAbility.getInstance();
break;
if (controller != null) {
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose one");
choice.setChoices(choices);
if (controller.choose(outcome, choice, game)) {
switch (choice.getChoice()) {
case "First strike":
ability = FirstStrikeAbility.getInstance();
break;
case "Trample":
ability = TrampleAbility.getInstance();
break;
case "Rampage 3":
ability = new RampageAbility(3);
break;
default:
ability = FlyingAbility.getInstance();
break;
}
} else {
discard();
}
} else {
discard();
}
}

View file

@ -50,10 +50,11 @@ public final class GloomwidowsFeast extends CardImpl {
class GloomwidowsFeastEffect extends OneShotEffect {
boolean applied = false;
public GloomwidowsFeastEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Destroy target creature with flying. " +
"If that creature was blue or black, create a 1/2 green Spider creature token with reach";
this.staticText = "Destroy target creature with flying. If that creature was blue or black, create a 1/2 green Spider creature token with reach";
}
public GloomwidowsFeastEffect(final GloomwidowsFeastEffect effect) {
@ -68,20 +69,15 @@ class GloomwidowsFeastEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent targetCreature = game.getPermanent(source.getFirstTarget());
if (targetCreature == null) {
return false;
}
targetCreature.destroy(source, game, false);
Permanent destroyedCreature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
if (destroyedCreature == null) {
return false;
}
if (destroyedCreature.getColor(game).isBlue() || destroyedCreature.getColor(game).isBlack()) {
SpiderToken token = new SpiderToken();
token.putOntoBattlefield(1, game, source, source.getControllerId());
return true;
if (targetCreature != null) {
targetCreature.destroy(source, game, false);
Permanent destroyedCreature = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
if (destroyedCreature.getColor(game).isBlue()
|| destroyedCreature.getColor(game).isBlack()) {
SpiderToken token = new SpiderToken();
token.putOntoBattlefield(1, game, source, source.getControllerId());
return true;
}
}
return false;
}

View file

@ -1,6 +1,5 @@
package mage.cards.g;
import javafx.event.EventType;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -56,7 +55,6 @@ class GoblinPsychopathEffect extends ReplacementEffectImpl {
public GoblinPsychopathEffect(final GoblinPsychopathEffect effect) {
super(effect);
this.wonFlip = effect.wonFlip;
}
@Override
@ -90,14 +88,10 @@ class GoblinPsychopathEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (object == null || controller == null) {
if (controller == null || object == null
|| !(this.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0)) {
return false;
}
if (!(this.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0)) {
return false;
}
DamageEvent damageEvent = (DamageEvent) event;
if (!damageEvent.isCombatDamage() || wonFlip) {
return false;

View file

@ -61,7 +61,7 @@ public final class Godsend extends CardImpl {
class GodsendTriggeredAbility extends TriggeredAbilityImpl {
private final Set<UUID> possibleTargets = new HashSet<>();
private Set<UUID> possibleTargets = new HashSet<>();
GodsendTriggeredAbility() {
super(Zone.BATTLEFIELD, new GodsendExileEffect(), true);
@ -69,7 +69,6 @@ class GodsendTriggeredAbility extends TriggeredAbilityImpl {
GodsendTriggeredAbility(final GodsendTriggeredAbility ability) {
super(ability);
this.possibleTargets.addAll(ability.possibleTargets);
}
@Override
@ -154,19 +153,13 @@ class GodsendExileEffect extends OneShotEffect {
Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (creature == null || controller == null || sourcePermanent == null) {
return false;
}
if (creature != null && controller != null && sourcePermanent != null) {
UUID exileId = CardUtil.getCardExileZoneId(game, source);
controller.moveCardToExileWithInfo(creature, exileId,
sourcePermanent.getIdName() + " (" + sourcePermanent.getZoneChangeCounter(game) + ')', source, game, Zone.BATTLEFIELD, true);
UUID exileId = CardUtil.getCardExileZoneId(game, source);
return controller.moveCardToExileWithInfo(
creature,
exileId,
sourcePermanent.getIdName() + " (" + sourcePermanent.getZoneChangeCounter(game) + ')',
source,
game,
Zone.BATTLEFIELD,
true);
}
return false;
}
}
@ -197,30 +190,19 @@ class GodsendRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() != GameEvent.EventType.CAST_SPELL) {
return false;
}
if (!game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
return false;
}
MageObject object = game.getObject(event.getSourceId());
if (object == null) {
return false;
}
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
if (exileZone == null) {
return false;
}
for (Card card : exileZone.getCards(game)) {
if ((card.getName().equals(object.getName()))) {
return true;
if (event.getType() == GameEvent.EventType.CAST_SPELL && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
MageObject object = game.getObject(event.getSourceId());
if (object != null) {
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
if ((exileZone != null)) {
for (Card card : exileZone.getCards(game)) {
if ((card.getName().equals(object.getName()))) {
return true;
}
}
}
}
}
return false;
}
}

View file

@ -102,7 +102,6 @@ class GrinningTotemMayPlayEffect extends AsThoughEffectImpl {
public GrinningTotemMayPlayEffect(final GrinningTotemMayPlayEffect effect) {
super(effect);
this.sameStep = effect.sameStep;
}
@Override
@ -113,7 +112,9 @@ class GrinningTotemMayPlayEffect extends AsThoughEffectImpl {
@Override
public boolean isInactive(Ability source, Game game) {
if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) {
return !sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving();
if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
return true;
}
} else {
sameStep = false;
}
@ -197,10 +198,10 @@ class GrinningTotemPutIntoGraveyardEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
ExileZone zone = game.getExile().getExileZone(exileZoneId);
if (controller == null || zone == null) {
return false;
if (controller != null && zone != null) {
return controller.moveCards(zone, Zone.GRAVEYARD, source, game);
}
return controller.moveCards(zone, Zone.GRAVEYARD, source, game);
return false;
}
}

View file

@ -34,9 +34,8 @@ public final class GuardDogs extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {2}{W}, {T}: Choose a permanent you control.
// Prevent all combat damage target creature would deal this turn if it shares a color with that permanent.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GuardDogsEffect(), new ManaCostsImpl<>("{2}{W}"));
// {2}{W}, {T}: Choose a permanent you control. Prevent all combat damage target creature would deal this turn if it shares a color with that permanent.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GuardDogsEffect(), new ManaCostsImpl("{2}{W}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
@ -58,14 +57,13 @@ class GuardDogsEffect extends PreventionEffectImpl {
public GuardDogsEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
this.staticText = "Choose a permanent you control. " +
"Prevent all combat damage target creature would deal this turn if it shares a color with that permanent";
this.staticText = "Choose a permanent you control. Prevent all combat damage target creature would deal this turn if it shares a color with that permanent";
}
private GuardDogsEffect(final GuardDogsEffect effect) {
public GuardDogsEffect(final GuardDogsEffect effect) {
super(effect);
this.controlledTarget = effect.controlledTarget.copy();
}
@Override
public void init(Ability source, Game game) {
@ -74,6 +72,7 @@ class GuardDogsEffect extends PreventionEffectImpl {
this.controlledTarget.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
super.init(source, game);
}
@Override
public GuardDogsEffect copy() {
@ -82,21 +81,20 @@ class GuardDogsEffect extends PreventionEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (this.used || !super.applies(event, source, game)) {
return false;
if (!this.used && super.applies(event, source, game)) {
MageObject mageObject = game.getObject(event.getSourceId());
if (mageObject != null
&& controlledTarget.getFirstTarget() != null) {
Permanent permanent = game.getPermanentOrLKIBattlefield(controlledTarget.getFirstTarget());
Permanent targetPermanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
if (permanent != null
&& targetPermanent != null
&& this.getTargetPointer().getTargets(game, source).contains(event.getSourceId())
&& permanent.getColor(game).shares(targetPermanent.getColor(game))) {
return true;
}
}
}
MageObject mageObject = game.getObject(event.getSourceId());
if (mageObject == null || controlledTarget.getFirstTarget() == null) {
return false;
}
Permanent permanent = game.getPermanentOrLKIBattlefield(controlledTarget.getFirstTarget());
Permanent targetPermanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source);
if (permanent == null || targetPermanent == null) {
return false;
}
return this.getTargetPointer().getTargets(game, source).contains(event.getSourceId())
&& permanent.getColor(game).shares(targetPermanent.getColor(game));
return false;
}
}

View file

@ -40,7 +40,7 @@ public final class HisokaMinamoSensei extends CardImpl {
this.toughness = new MageInt(3);
// {2}{U}, Discard a card: Counter target spell if it has the same converted mana cost as the discarded card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HisokaMinamoSenseiCounterEffect(), new ManaCostsImpl<>("{2}{U}"));
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HisokaMinamoSenseiCounterEffect(), new ManaCostsImpl("{2}{U}"));
ability.addTarget(new TargetSpell());
TargetCardInHand targetCard = new TargetCardInHand(new FilterCard("a card"));
ability.addCost(new HisokaMinamoSenseiDiscardTargetCost(targetCard));
@ -60,7 +60,7 @@ public final class HisokaMinamoSensei extends CardImpl {
class HisokaMinamoSenseiDiscardTargetCost extends CostImpl {
protected Card card;
protected Card card = null;
public HisokaMinamoSenseiDiscardTargetCost(TargetCardInHand target) {
this.addTarget(target);
@ -69,27 +69,23 @@ class HisokaMinamoSenseiDiscardTargetCost extends CostImpl {
public HisokaMinamoSenseiDiscardTargetCost(HisokaMinamoSenseiDiscardTargetCost cost) {
super(cost);
this.card = cost.card.copy();
}
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
if (!targets.choose(Outcome.Discard, controllerId, source.getSourceId(), source, game)) {
return paid;
}
if (targets.choose(Outcome.Discard, controllerId, source.getSourceId(), source, game)) {
Player player = game.getPlayer(controllerId);
if(player != null) {
for (UUID targetId : targets.get(0).getTargets()) {
card = player.getHand().get(targetId, game);
if (card == null) {
return false;
}
paid |= player.discard(card, true, source, game);
Player player = game.getPlayer(controllerId);
if (player == null) {
return paid;
}
for (UUID targetId : targets.get(0).getTargets()) {
card = player.getHand().get(targetId, game);
if (card != null) {
paid |= player.discard(card, true, source, game);
}
}
}
return paid;
}
@ -110,32 +106,24 @@ class HisokaMinamoSenseiDiscardTargetCost extends CostImpl {
}
class HisokaMinamoSenseiCounterEffect extends OneShotEffect {
HisokaMinamoSenseiCounterEffect() {
super(Outcome.Detriment);
staticText = "Counter target spell if it has the same mana value as the discarded card";
}
private HisokaMinamoSenseiCounterEffect(final HisokaMinamoSenseiCounterEffect effect) {
HisokaMinamoSenseiCounterEffect(final HisokaMinamoSenseiCounterEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
if (spell == null) {
return false;
if (spell != null) {
HisokaMinamoSenseiDiscardTargetCost cost = (HisokaMinamoSenseiDiscardTargetCost) source.getCosts().get(0);
if (cost != null && cost.getDiscardedCard().getManaValue() == spell.getManaValue()) {
return game.getStack().counter(targetPointer.getFirst(game, source), source, game);
}
}
HisokaMinamoSenseiDiscardTargetCost cost = (HisokaMinamoSenseiDiscardTargetCost) source.getCosts().get(0);
if (cost == null) {
return false;
}
if (cost.getDiscardedCard().getManaValue() == spell.getManaValue()) {
return game.getStack().counter(targetPointer.getFirst(game, source), source, game);
}
return false;
}

View file

@ -39,10 +39,9 @@ public final class IllusionaryPresence extends CardImpl {
this.toughness = new MageInt(2);
// Cumulative upkeep {U}
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl<>("{U}")));
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{U}")));
// At the beginning of your upkeep, choose a land type.
// Illusionary Presence gains landwalk of the chosen type until end of turn.
// At the beginning of your upkeep, choose a land type. Illusionary Presence gains landwalk of the chosen type until end of turn.
Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new ChooseBasicLandTypeEffect(Outcome.Neutral), TargetController.YOU, false);
ability.addEffect(new IllusionaryPresenceEffect());
this.addAbility(ability);
@ -61,6 +60,8 @@ public final class IllusionaryPresence extends CardImpl {
class IllusionaryPresenceEffect extends OneShotEffect {
Ability gainedAbility;
public IllusionaryPresenceEffect() {
super(Outcome.Benefit);
this.staticText = "{this} gains landwalk of the chosen type until end of turn";
@ -78,38 +79,33 @@ class IllusionaryPresenceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
MageObject mageObject = game.getObject(source);
if (mageObject == null) {
return false;
if (mageObject != null) {
SubType landTypeChoice = SubType.byDescription((String) game.getState().getValue(mageObject.getId().toString() + "BasicLandType"));
if (landTypeChoice != null) {
switch (landTypeChoice) {
case PLAINS:
gainedAbility = new PlainswalkAbility();
break;
case FOREST:
gainedAbility = new ForestwalkAbility();
break;
case SWAMP:
gainedAbility = new SwampwalkAbility();
break;
case ISLAND:
gainedAbility = new IslandwalkAbility();
break;
case MOUNTAIN:
gainedAbility = new MountainwalkAbility();
break;
}
if (gainedAbility != null) {
GainAbilitySourceEffect effect = new GainAbilitySourceEffect(gainedAbility, Duration.EndOfTurn);
game.addEffect(effect, source);
return true;
}
}
}
SubType landTypeChoice = SubType.byDescription((String) game.getState().getValue(mageObject.getId().toString() + "BasicLandType"));
if (landTypeChoice == null) {
return false;
}
Ability gainedAbility;
switch (landTypeChoice) {
case PLAINS:
gainedAbility = new PlainswalkAbility();
break;
case FOREST:
gainedAbility = new ForestwalkAbility();
break;
case SWAMP:
gainedAbility = new SwampwalkAbility();
break;
case ISLAND:
gainedAbility = new IslandwalkAbility();
break;
case MOUNTAIN:
gainedAbility = new MountainwalkAbility();
break;
default:
return false;
}
GainAbilitySourceEffect effect = new GainAbilitySourceEffect(gainedAbility, Duration.EndOfTurn);
game.addEffect(effect, source);
return true;
return false;
}
}

View file

@ -141,10 +141,8 @@ class ChooseTwoBasicLandTypesEffect extends OneShotEffect {
this.staticText = "choose two basic land types";
}
private ChooseTwoBasicLandTypesEffect(final ChooseTwoBasicLandTypesEffect effect) {
public ChooseTwoBasicLandTypesEffect(final ChooseTwoBasicLandTypesEffect effect) {
super(effect);
this.choiceOne = effect.choiceOne;
this.choiceTwo = effect.choiceTwo;
}
@Override

View file

@ -33,9 +33,7 @@ public final class ImminentDoom extends CardImpl {
// Imminent Doom enters the battlefield with a doom counter on it.
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.DOOM.createInstance(1)), "with a doom counter on it"));
// Whenever you cast a spell with converted mana cost equal to the number of doom counters on Imminent Doom,
// Imminent Doom deals that much damage to any target.
// Then put a doom counter on Imminent Doom.
// Whenever you cast a spell with converted mana cost equal to the number of doom counters on Imminent Doom, Imminent Doom deals that much damage to any target. Then put a doom counter on Imminent Doom.
Ability ability = new ImminentDoomTriggeredAbility();
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
@ -54,8 +52,7 @@ public final class ImminentDoom extends CardImpl {
class ImminentDoomTriggeredAbility extends TriggeredAbilityImpl {
private static final String rule = "Whenever you cast a spell with mana value equal to the number of doom counters on {this}, " +
"{this} deals that much damage to any target. Then put a doom counter on {this}.";
private String rule = "Whenever you cast a spell with mana value equal to the number of doom counters on {this}, {this} deals that much damage to any target. Then put a doom counter on {this}.";
public ImminentDoomTriggeredAbility() {
super(Zone.BATTLEFIELD, new ImminentDoomEffect());
@ -77,24 +74,16 @@ class ImminentDoomTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!event.getPlayerId().equals(this.getControllerId())) {
return false;
}
Permanent imminentDoom = game.getPermanent(getSourceId());
Spell spell = game.getStack().getSpell(event.getTargetId());
if (imminentDoom == null || spell == null) {
return false;
}
if (spell.getManaValue() == imminentDoom.getCounters(game).getCount(CounterType.DOOM)) {
// store its current value
game.getState().setValue(
"ImminentDoomCount" + getSourceId().toString(),
imminentDoom.getCounters(game).getCount(CounterType.DOOM)
);
return true;
}
if (event.getPlayerId().equals(this.getControllerId())) {
Permanent imminentDoom = game.getPermanent(getSourceId());
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null
&& imminentDoom != null
&& spell.getManaValue() == imminentDoom.getCounters(game).getCount(CounterType.DOOM)) {
game.getState().setValue("ImminentDoomCount" + getSourceId().toString(), imminentDoom.getCounters(game).getCount(CounterType.DOOM)); // store its current value
return true;
}
}
return false;
}
@ -122,13 +111,13 @@ class ImminentDoomEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent imminentDoom = game.getPermanent(source.getSourceId());
if (imminentDoom == null) {
return false;
if (imminentDoom != null) {
Effect effect = new DamageTargetEffect((int) game.getState().getValue("ImminentDoomCount" + source.getSourceId().toString()));
effect.apply(game, source);
imminentDoom.addCounters(CounterType.DOOM.createInstance(), source.getControllerId(), source, game);
return true;
}
Effect effect = new DamageTargetEffect((int) game.getState().getValue("ImminentDoomCount" + source.getSourceId().toString()));
effect.apply(game, source);
imminentDoom.addCounters(CounterType.DOOM.createInstance(), source.getControllerId(), source, game);
return true;
return false;
}
}

View file

@ -48,14 +48,11 @@ class ImpulsiveManeuversEffect extends PreventionEffectImpl {
public ImpulsiveManeuversEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "flip a coin. " +
"If you win the flip, the next time that creature would deal combat damage this turn, it deals double that damage instead. " +
"If you lose the flip, the next time that creature would deal combat damage this turn, prevent that damage";
staticText = "flip a coin. If you win the flip, the next time that creature would deal combat damage this turn, it deals double that damage instead. If you lose the flip, the next time that creature would deal combat damage this turn, prevent that damage";
}
public ImpulsiveManeuversEffect(final ImpulsiveManeuversEffect effect) {
super(effect);
this.wonFlip = effect.wonFlip;
}
@Override
@ -89,25 +86,21 @@ class ImpulsiveManeuversEffect extends PreventionEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller == null || object == null) {
return false;
if (controller != null && object != null) {
if (super.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) {
DamageEvent damageEvent = (DamageEvent) event;
if (damageEvent.isCombatDamage()) {
if (wonFlip) {
event.setAmount(CardUtil.overflowMultiply(event.getAmount(), 2));
this.discard();
} else {
preventDamageAction(event, source, game);
this.discard();
return true;
}
}
}
}
if (!super.applies(event, source, game)) {
return false;
}
if (!(event instanceof DamageEvent) || !((DamageEvent) event).isCombatDamage() || event.getAmount() <= 0) {
return false;
}
if (wonFlip) {
event.setAmount(CardUtil.overflowMultiply(event.getAmount(), 2));
} else {
preventDamageAction(event, source, game);
}
this.discard();
return true;
return false;
}
}

View file

@ -60,7 +60,7 @@ public final class IncubationDruid extends CardImpl {
class AnyColorLandsProduceManaEffect extends ManaEffect {
private boolean inManaTypeCalculation;
private boolean inManaTypeCalculation = false;
AnyColorLandsProduceManaEffect() {
super();
@ -70,7 +70,6 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
private AnyColorLandsProduceManaEffect(final AnyColorLandsProduceManaEffect effect) {
super(effect);
this.inManaTypeCalculation = effect.inManaTypeCalculation;
}
@Override

View file

@ -17,6 +17,7 @@ import mage.constants.CardType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterArtifactPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCardInLibrary;
@ -38,9 +39,8 @@ public final class InventorsFair extends CardImpl {
// {t}: Add {C}.
this.addAbility(new ColorlessManaAbility());
// {4}, {T}, Sacrifice Inventors' Fair: Search your library for an artifact card, reveal it,
// put it into your hand, then shuffle your library.
// Activate this ability only if you control three or more artifacts.
// {4}, {T}, Sacrifice Inventors' Fair: Search your library for an artifact card, reveal it, put it into your hand, then shuffle your library.
// Activate this ability only if you control threeor more artifacts.
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_ARTIFACT), true),
new GenericManaCost(4), MetalcraftCondition.instance);
ability.addCost(new TapSourceCost());
@ -61,6 +61,8 @@ public final class InventorsFair extends CardImpl {
class InventorsFairAbility extends TriggeredAbilityImpl {
private FilterArtifactPermanent filter = new FilterArtifactPermanent();
public InventorsFairAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(1));
}
@ -86,7 +88,7 @@ class InventorsFairAbility extends TriggeredAbilityImpl {
@Override
public boolean checkInterveningIfClause(Game game) {
return game.getBattlefield().countAll(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, this.controllerId, game) >= 3;
return game.getBattlefield().countAll(filter, this.controllerId, game) >= 3;
}
@Override

View file

@ -8,7 +8,7 @@ import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.DoubleStrikeAbility;
@ -38,7 +38,7 @@ public final class JodahsAvenger extends CardImpl {
this.toughness = new MageInt(4);
// {0}: Until end of turn, Jodah's Avenger gets -1/-1 and gains your choice of double strike, protection from red, vigilance, or shadow.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new JodahsAvengerEffect(), new GenericManaCost(0)));
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new JodahsAvengerEffect(), new ManaCostsImpl("{0}")));
}
private JodahsAvenger(final JodahsAvenger card) {
@ -70,7 +70,6 @@ class JodahsAvengerEffect extends ContinuousEffectImpl {
public JodahsAvengerEffect(final JodahsAvengerEffect effect) {
super(effect);
this.gainedAbility = effect.gainedAbility.copy();
}
@Override
@ -81,46 +80,41 @@ class JodahsAvengerEffect extends ContinuousEffectImpl {
@Override
public void init(Ability source, Game game) {
super.init(source, game);
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return;
}
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose one");
choice.setChoices(choices);
if (controller.choose(outcome, choice, game)) {
switch (choice.getChoice()) {
case "Double strike":
gainedAbility = DoubleStrikeAbility.getInstance();
break;
case "Vigilance":
gainedAbility = VigilanceAbility.getInstance();
break;
case "Shadow":
gainedAbility = ShadowAbility.getInstance();
break;
default:
gainedAbility = ProtectionAbility.from(ObjectColor.RED);
break;
if (controller != null) {
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose one");
choice.setChoices(choices);
if (controller.choose(outcome, choice, game)) {
switch (choice.getChoice()) {
case "Double strike":
gainedAbility = DoubleStrikeAbility.getInstance();
break;
case "Vigilance":
gainedAbility = VigilanceAbility.getInstance();
break;
case "Shadow":
gainedAbility = ShadowAbility.getInstance();
break;
default:
gainedAbility = ProtectionAbility.from(ObjectColor.RED);
break;
}
} else {
discard();
}
} else {
discard();
}
}
@Override
public boolean apply(Game game, Ability source) {
Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject == null) {
return false;
if (sourceObject != null) {
sourceObject.addPower(-1);
sourceObject.addToughness(-1);
game.addEffect(new GainAbilitySourceEffect(gainedAbility, Duration.EndOfTurn), source);
return true;
}
sourceObject.addPower(-1);
sourceObject.addToughness(-1);
game.addEffect(new GainAbilitySourceEffect(gainedAbility, Duration.EndOfTurn), source);
return true;
return false;
}
}

View file

@ -56,7 +56,6 @@ class JointAssaultBoostTargetEffect extends ContinuousEffectImpl {
super(effect);
this.power = effect.power;
this.toughness = effect.toughness;
this.paired = effect.paired;
}
@Override
@ -67,11 +66,12 @@ class JointAssaultBoostTargetEffect extends ContinuousEffectImpl {
@Override
public void init(Ability source, Game game) {
super.init(source, game);
UUID permanentId = targetPointer.getFirst(game, source);
Permanent target = game.getPermanent(permanentId);
if (target != null && target.getPairedCard() != null) {
this.paired = target.getPairedCard();
if (target != null) {
if (target.getPairedCard() != null) {
this.paired = target.getPairedCard();
}
}
}

View file

@ -46,8 +46,7 @@ public final class KarnLiberated extends CardImpl {
ability2.addTarget(new TargetPermanent());
this.addAbility(ability2);
// -14: Restart the game, leaving in exile all non-Aura permanent cards exiled with Karn Liberated.
// Then put those cards onto the battlefield under your control.
// -14: Restart the game, leaving in exile all non-Aura permanent cards exiled with Karn Liberated. Then put those cards onto the battlefield under your control.
this.addAbility(new LoyaltyAbility(new KarnLiberatedEffect(), -14));
}
@ -63,10 +62,11 @@ public final class KarnLiberated extends CardImpl {
class KarnLiberatedEffect extends OneShotEffect {
private UUID exileId;
public KarnLiberatedEffect() {
super(Outcome.ExtraTurn);
this.staticText = "Restart the game, leaving in exile all non-Aura permanent cards exiled with {this}. " +
"Then put those cards onto the battlefield under your control";
this.staticText = "Restart the game, leaving in exile all non-Aura permanent cards exiled with {this}. Then put those cards onto the battlefield under your control";
}
public KarnLiberatedEffect(final KarnLiberatedEffect effect) {
@ -75,7 +75,6 @@ class KarnLiberatedEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
UUID exileId = null;
MageObject sourceObject = source.getSourceObject(game);
if (sourceObject == null) {
return false;
@ -85,7 +84,8 @@ class KarnLiberatedEffect extends OneShotEffect {
exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
if (zone.getId().equals(exileId)) {
for (Card card : zone.getCards(game)) {
if (!card.hasSubtype(SubType.AURA, game) && card.isPermanent(game)) {
if (!card.hasSubtype(SubType.AURA, game)
&& card.isPermanent(game)) {
cards.add(card);
}
}

View file

@ -59,6 +59,8 @@ public final class KrovikanVampire extends CardImpl {
class KrovikanVampireEffect extends OneShotEffect {
Set<UUID> creaturesAffected = new HashSet<>();
KrovikanVampireEffect() {
super(Outcome.Neutral);
staticText = "put that card onto the battlefield under your control. Sacrifice it when you lose control of {this}";
@ -72,24 +74,25 @@ class KrovikanVampireEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent krovikanVampire = game.getPermanent(source.getSourceId());
Set<UUID> creaturesAffected = (Set<UUID>) game.getState().getValue(source.getSourceId() + "creatureToGainControl");
if (creaturesAffected == null || controller == null || krovikanVampire == null) {
return false;
creaturesAffected = (Set<UUID>) game.getState().getValue(source.getSourceId() + "creatureToGainControl");
if (creaturesAffected != null
&& controller != null
&& krovikanVampire != null) {
creaturesAffected.stream().map((creatureId) -> {
controller.moveCards(game.getCard(creatureId), Zone.BATTLEFIELD, source, game, false, false, false, null);
return creatureId;
}).map((creatureId) -> {
OneShotEffect effect = new SacrificeTargetEffect();
effect.setText("Sacrifice this if Krovikan Vampire leaves the battlefield or its current controller loses control of it.");
effect.setTargetPointer(new FixedTarget(creatureId, game));
return effect;
}).map((effect) -> new KrovikanVampireDelayedTriggeredAbility(effect, krovikanVampire.getId())).forEachOrdered((dTA) -> {
game.addDelayedTriggeredAbility(dTA, source);
});
creaturesAffected.clear();
return true;
}
creaturesAffected.stream().map((creatureId) -> {
controller.moveCards(game.getCard(creatureId), Zone.BATTLEFIELD, source, game, false, false, false, null);
return creatureId;
}).map((creatureId) -> {
OneShotEffect effect = new SacrificeTargetEffect();
effect.setText("Sacrifice this if Krovikan Vampire leaves the battlefield or its current controller loses control of it.");
effect.setTargetPointer(new FixedTarget(creatureId, game));
return effect;
}).map((effect) -> new KrovikanVampireDelayedTriggeredAbility(effect, krovikanVampire.getId())).forEachOrdered((dTA) -> {
game.addDelayedTriggeredAbility(dTA, source);
});
creaturesAffected.clear();
return true;
return false;
}
@Override
@ -106,24 +109,21 @@ class KrovikanVampireInterveningIfCondition implements Condition {
public boolean apply(Game game, Ability source) {
KrovikanVampireCreaturesDiedWatcher watcherDied = game.getState().getWatcher(KrovikanVampireCreaturesDiedWatcher.class);
KrovikanVampireCreaturesDamagedWatcher watcherDamaged = game.getState().getWatcher(KrovikanVampireCreaturesDamagedWatcher.class);
if (watcherDied == null) {
return false;
}
Set<UUID> creaturesThatDiedThisTurn = watcherDied.getDiedThisTurn();
creaturesThatDiedThisTurn.stream().filter((mor) -> (watcherDamaged != null)).forEachOrdered((mor) -> {
watcherDamaged.getDamagedBySource().stream().filter((mor2) -> (mor2 != null
&& mor == mor2)).forEachOrdered((_item) -> {
creaturesAffected.add(mor);
if (watcherDied != null) {
Set<UUID> creaturesThatDiedThisTurn = watcherDied.getDiedThisTurn();
creaturesThatDiedThisTurn.stream().filter((mor) -> (watcherDamaged != null)).forEachOrdered((mor) -> {
watcherDamaged.getDamagedBySource().stream().filter((mor2) -> (mor2 != null
&& mor == mor2)).forEachOrdered((_item) -> {
creaturesAffected.add(mor);
});
});
});
if (creaturesAffected == null || creaturesAffected.isEmpty()) {
return false;
if (creaturesAffected != null
&& creaturesAffected.size() > 0) {
game.getState().setValue(source.getSourceId() + "creatureToGainControl", creaturesAffected);
return true;
}
}
game.getState().setValue(source.getSourceId() + "creatureToGainControl", creaturesAffected);
return true;
return false;
}
@Override
@ -142,15 +142,14 @@ class KrovikanVampireCreaturesDamagedWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT || !sourceId.equals(event.getSourceId())) {
if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT
|| !sourceId.equals(event.getSourceId())) {
return;
}
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null || !permanent.isCreature(game)) {
return;
}
damagedBySource.add(event.getTargetId());
}
@ -216,10 +215,14 @@ class KrovikanVampireDelayedTriggeredAbility extends DelayedTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.LOST_CONTROL || event.getType() == GameEvent.EventType.ZONE_CHANGE) {
return event.getTargetId().equals(krovikanVampire);
if (event.getType() == GameEvent.EventType.LOST_CONTROL
&& event.getTargetId().equals(krovikanVampire)) {
return true;
}
if (event.getType() == GameEvent.EventType.ZONE_CHANGE
&& event.getTargetId().equals(krovikanVampire)) {
return true;
}
return false;
}

View file

@ -60,7 +60,6 @@ class LivingBreakthroughEffect extends ContinuousRuleModifyingEffectImpl {
private LivingBreakthroughEffect(final LivingBreakthroughEffect effect) {
super(effect);
this.manaValue = effect.manaValue;
}
@Override

View file

@ -70,7 +70,6 @@ class MarshlandBloodcasterEffect extends ContinuousEffectImpl {
public MarshlandBloodcasterEffect(final MarshlandBloodcasterEffect effect) {
super(effect);
this.spellsCast = effect.spellsCast;
}
@Override

View file

@ -6,7 +6,6 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.SearchEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -31,10 +30,8 @@ public final class MyrIncubator extends CardImpl {
public MyrIncubator(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
// {6}, {tap}, Sacrifice Myr Incubator: Search your library for any number of artifact cards, exile them,
// then put that many 1/1 colorless Myr artifact creature tokens onto the battlefield.
// Then shuffle your library.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MyrIncubatorEffect(), new GenericManaCost(6));
// {6}, {tap}, Sacrifice Myr Incubator: Search your library for any number of artifact cards, exile them, then put that many 1/1 colorless Myr artifact creature tokens onto the battlefield. Then shuffle your library.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MyrIncubatorEffect(), new ManaCostsImpl("{6}"));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
@ -59,39 +56,32 @@ class MyrIncubatorEffect extends SearchEffect {
filter.add(CardType.ARTIFACT.getPredicate());
}
int tokensToCreate;
int tokensToCreate = 0;
MyrIncubatorEffect() {
super(new TargetCardInLibrary(0, Integer.MAX_VALUE, filter), Outcome.Neutral);
staticText = "Search your library for any number of artifact cards, exile them, " +
"then create that many 1/1 colorless Myr artifact creature tokens. " +
"Then shuffle";
staticText = "Search your library for any number of artifact cards, exile them, then create that many 1/1 colorless Myr artifact creature tokens. Then shuffle";
}
MyrIncubatorEffect(final MyrIncubatorEffect effect) {
super(effect);
this.tokensToCreate = effect.tokensToCreate;
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
if (!controller.searchLibrary(target, source, game)) {
return false;
}
if (!target.getTargets().isEmpty()) {
tokensToCreate = target.getTargets().size();
controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
if (controller != null
&& controller.searchLibrary(target, source, game)) {
if (!target.getTargets().isEmpty()) {
tokensToCreate = target.getTargets().size();
controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
}
CreateTokenEffect effect = new CreateTokenEffect(new MyrToken(), tokensToCreate);
effect.apply(game, source);
controller.shuffleLibrary(source, game);
return true;
}
controller.shuffleLibrary(source, game);
return true;
return false;
}
@Override

View file

@ -55,6 +55,7 @@ public final class NaturesBlessing extends CardImpl {
class NaturesBlessingEffect extends OneShotEffect {
private static final Set<String> choices = new HashSet<>();
private Ability gainedAbility;
static {
choices.add("+1/+1 counter");
@ -81,33 +82,30 @@ class NaturesBlessingEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent targetPermanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (controller == null || targetPermanent == null) {
return false;
}
Ability gainedAbility = null;
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose one");
choice.setChoices(choices);
if (controller.choose(outcome, choice, game)) {
switch (choice.getChoice()) {
case "Banding":
gainedAbility = BandingAbility.getInstance();
break;
case "First strike":
gainedAbility = FirstStrikeAbility.getInstance();
break;
case "Trample":
gainedAbility = TrampleAbility.getInstance();
if (controller != null && targetPermanent != null) {
Choice choice = new ChoiceImpl(true);
choice.setMessage("Choose one");
choice.setChoices(choices);
if (controller.choose(outcome, choice, game)) {
switch (choice.getChoice()) {
case "Banding":
gainedAbility = BandingAbility.getInstance();
break;
case "First strike":
gainedAbility = FirstStrikeAbility.getInstance();
break;
case "Trample":
gainedAbility = TrampleAbility.getInstance();
}
}
if (gainedAbility != null) {
game.addEffect(new GainAbilityTargetEffect(gainedAbility, Duration.Custom), source);
} else {
targetPermanent.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game);
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + targetPermanent.getLogName());
}
return true;
}
if (gainedAbility != null) {
game.addEffect(new GainAbilityTargetEffect(gainedAbility, Duration.Custom), source);
} else {
targetPermanent.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game);
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + targetPermanent.getLogName());
}
return true;
return false;
}
}

View file

@ -60,7 +60,6 @@ class NecromancersStockpileDiscardTargetCost extends CostImpl {
public NecromancersStockpileDiscardTargetCost(NecromancersStockpileDiscardTargetCost cost) {
super(cost);
this.isZombieCard = cost.isZombieCard;
}
@Override

View file

@ -46,7 +46,6 @@ class PredatoryFocusEffect extends AsThoughEffectImpl {
public PredatoryFocusEffect(PredatoryFocusEffect effect) {
super(effect);
this.choseUse = effect.choseUse;
}
@Override

View file

@ -49,7 +49,6 @@ class PrimitiveEtchingsAbility extends TriggeredAbilityImpl {
PrimitiveEtchingsAbility(final PrimitiveEtchingsAbility ability) {
super(ability);
this.lastTriggeredTurn = ability.lastTriggeredTurn;
}
@Override

View file

@ -87,7 +87,6 @@ class RaziaBorosArchangelEffect extends RedirectionEffect {
public RaziaBorosArchangelEffect(final RaziaBorosArchangelEffect effect) {
super(effect);
this.redirectToObject = effect.redirectToObject;
}
@Override

View file

@ -47,9 +47,8 @@ class RowenAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, new InfoEffect(""), false);
}
private RowenAbility(final RowenAbility ability) {
RowenAbility(final RowenAbility ability) {
super(ability);
this.lastTriggeredTurn = ability.lastTriggeredTurn;
}
@Override

View file

@ -54,7 +54,7 @@ class ChooseNumberEffect extends OneShotEffect {
staticText = "choose a number";
}
private ChooseNumberEffect(final ChooseNumberEffect effect) {
public ChooseNumberEffect(final ChooseNumberEffect effect) {
super(effect);
}
@ -83,12 +83,14 @@ class ChooseNumberEffect extends OneShotEffect {
class SanctumPrelateReplacementEffect extends ContinuousRuleModifyingEffectImpl {
Integer choiceValue;
public SanctumPrelateReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
staticText = "Noncreature spells with mana value equal to the chosen number can't be cast";
}
private SanctumPrelateReplacementEffect(final SanctumPrelateReplacementEffect effect) {
public SanctumPrelateReplacementEffect(final SanctumPrelateReplacementEffect effect) {
super(effect);
}
@ -118,7 +120,7 @@ class SanctumPrelateReplacementEffect extends ContinuousRuleModifyingEffectImpl
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Integer choiceValue = (Integer) game.getState().getValue(source.getSourceId().toString());
choiceValue = (Integer) game.getState().getValue(source.getSourceId().toString());
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && !spell.isCreature(game)) {

View file

@ -12,7 +12,6 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterLandPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -46,6 +45,8 @@ public final class ScuteMob extends CardImpl {
class ScuteMobAbility extends TriggeredAbilityImpl {
private FilterLandPermanent filter = new FilterLandPermanent();
public ScuteMobAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(4)));
}
@ -71,7 +72,7 @@ class ScuteMobAbility extends TriggeredAbilityImpl {
@Override
public boolean checkInterveningIfClause(Game game) {
return game.getBattlefield().countAll(StaticFilters.FILTER_LAND, this.controllerId, game) >= 5;
return game.getBattlefield().countAll(filter, this.controllerId, game) >= 5;
}
@Override

View file

@ -31,7 +31,6 @@ public final class SlumberingTora extends CardImpl {
public SlumberingTora(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// {2}, Discard a Spirit or Arcane card: Slumbering Tora becomes an X/X Cat artifact creature until end of turn,
// where X is the discarded card's converted mana cost.
Ability ability = new SimpleActivatedAbility(new SlumberingToraEffect(), new ManaCostsImpl("{2}"));
@ -50,7 +49,7 @@ public final class SlumberingTora extends CardImpl {
private static class SlumberingToraEffect extends ContinuousEffectImpl {
private int convManaCosts;
private int convManaCosts = 0;
private SlumberingToraEffect() {
super(Duration.EndOfTurn, Outcome.BecomeCreature);
@ -60,7 +59,6 @@ public final class SlumberingTora extends CardImpl {
private SlumberingToraEffect(final SlumberingToraEffect effect) {
super(effect);
this.convManaCosts = effect.convManaCosts;
}
@Override

View file

@ -80,24 +80,13 @@ class SoulEchoOpponentsChoiceEffect extends OneShotEffect {
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
if (controller == null || opponent == null || permanent == null) {
return false;
}
String msg1 = "Have all damage dealt to " + controller.getLogName() +
" be decremented from echo counters on " + permanent.getLogName() +
" until " + controller.getLogName() + "'s next upkeep instead?";
String msg2 = "Until " + controller.getLogName() +
"'s next upkeep, for each 1 damage that would be dealt to " + controller.getLogName() +
", an echo counter from " + permanent.getLogName() + " is removed instead";
if (opponent.chooseUse(outcome, msg1, source, game)) {
game.informPlayers(msg2);
game.addEffect(new SoulEchoReplacementEffect(), source);
if (controller != null && opponent != null && permanent != null) {
if (opponent.chooseUse(outcome, "Have all damage dealt to " + controller.getLogName() + " be decremented from echo counters on " + permanent.getLogName() + " until " + controller.getLogName() + "'s next upkeep instead?", source, game)) {
game.informPlayers("Until " + controller.getLogName() + "'s next upkeep, for each 1 damage that would be dealt to " + controller.getLogName() + ", an echo counter from " + permanent.getLogName() + " is removed instead");
game.addEffect(new SoulEchoReplacementEffect(), source);
}
return true;
}
return false;
}
}
@ -110,15 +99,16 @@ class SoulEchoReplacementEffect extends ReplacementEffectImpl {
super(Duration.Custom, Outcome.PreventDamage);
}
private SoulEchoReplacementEffect(final SoulEchoReplacementEffect effect) {
SoulEchoReplacementEffect(final SoulEchoReplacementEffect effect) {
super(effect);
this.sameStep = effect.sameStep;
}
@Override
public boolean isInactive(Ability source, Game game) {
if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) {
return !sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving();
if (!sameStep && game.isActivePlayer(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
return true;
}
} else {
sameStep = false;
}
@ -127,18 +117,14 @@ class SoulEchoReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (permanent == null && controller == null) {
return false;
}
DamageEvent damageEvent = (DamageEvent) event;
int damage = damageEvent.getAmount();
permanent.removeCounters(CounterType.ECHO.createInstance(damage), source, game);
game.informPlayers(controller.getLogName() + ": " + damage + " damage replaced with " + permanent.getLogName());
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (permanent != null && controller != null) {
permanent.removeCounters(CounterType.ECHO.createInstance(damage), source, game);
game.informPlayers(controller.getLogName() + ": " + damage + " damage replaced with " + permanent.getLogName());
}
return true;
}

View file

@ -45,7 +45,7 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp
private static final FilterControlledPermanent filter = new FilterControlledPermanent();
private boolean wonAlready;
private boolean wonAlready = false;
static {
filter.add(new NamePredicate("The Cheese Stands Alone"));
@ -56,9 +56,8 @@ class CheeseStandsAloneContinuousEffect extends ContinuousRuleModifyingEffectImp
staticText = "When you control no permanents other than {this} and have no cards in hand, you win the game";
}
private CheeseStandsAloneContinuousEffect(final CheeseStandsAloneContinuousEffect effect) {
public CheeseStandsAloneContinuousEffect(final CheeseStandsAloneContinuousEffect effect) {
super(effect);
this.wonAlready = effect.wonAlready;
}
@Override

View file

@ -67,9 +67,8 @@ class UrzasAvengerEffect extends ContinuousEffectImpl {
this.staticText = "{this} gets -1/-1 and gains your choice of banding, flying, first strike, or trample until end of turn";
}
private UrzasAvengerEffect(final UrzasAvengerEffect effect) {
public UrzasAvengerEffect(final UrzasAvengerEffect effect) {
super(effect);
this.gainedAbility = effect.gainedAbility;
}
@Override

View file

@ -100,6 +100,8 @@ class VerdantSuccessionTriggeredAbility extends TriggeredAbilityImpl {
class VerdantSuccessionEffect extends OneShotEffect {
private Permanent permanent;
VerdantSuccessionEffect() {
super(Outcome.PutCardInPlay);
}
@ -116,36 +118,26 @@ class VerdantSuccessionEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
MageObject mageObject = game.getObject(source);
if (mageObject == null) {
return false;
}
Permanent permanent = (Permanent) game.getState().getValue("verdantSuccession" + mageObject);
if (permanent == null) {
return false;
}
Player controller = game.getPlayer(permanent.getControllerId());
if (controller == null) {
return false;
}
FilterCard filterCard = new FilterCard("Card named " + permanent.getName());
filterCard.add(new NamePredicate(permanent.getName()));
TargetCardInLibrary target = new TargetCardInLibrary(filterCard);
if (!controller.searchLibrary(target, source, game)) {
return false;
}
if (!target.getTargets().isEmpty()) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
if(mageObject != null) {
permanent = (Permanent) game.getState().getValue("verdantSuccession" + mageObject);
if (permanent != null) {
Player controller = game.getPlayer(permanent.getControllerId());
if (controller != null) {
FilterCard filterCard = new FilterCard("Card named " + permanent.getName());
filterCard.add(new NamePredicate(permanent.getName()));
TargetCardInLibrary target = new TargetCardInLibrary(filterCard);
controller.searchLibrary(target, source, game);
if (!target.getTargets().isEmpty()) {
Card card = game.getCard(target.getFirstTarget());
if (card != null
&& controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
controller.shuffleLibrary(source, game);
}
return true;
}
}
}
}
controller.shuffleLibrary(source, game); // Shuffle even if no card was found since it revealed the order of cards.
return true;
return false;
}
}

View file

@ -2,11 +2,8 @@
package mage.cards.w;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
@ -31,7 +28,7 @@ public final class WarCadence extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
// {X}{R}: This turn, creatures can't block unless their controller pays {X} for each blocking creature they control.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WarCadenceReplacementEffect(), new ManaCostsImpl<>("{X}{R}")));
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new WarCadenceReplacementEffect(), new ManaCostsImpl("{X}{R}")));
}
@ -56,28 +53,26 @@ class WarCadenceReplacementEffect extends ReplacementEffectImpl {
WarCadenceReplacementEffect(WarCadenceReplacementEffect effect) {
super(effect);
this.xCosts = effect.xCosts.copy();
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getPlayerId());
if (player == null) {
return false;
if (player != null) {
int amount = xCosts.calculate(game, source, this);
if (amount > 0) {
String mana = "{" + amount + '}';
ManaCostsImpl cost = new ManaCostsImpl(mana);
if (cost.canPay(source, source, event.getPlayerId(), game)
&& player.chooseUse(Outcome.Benefit, "Pay " + mana + " to declare blocker?", source, game)) {
if (cost.payOrRollback(source, game, source, event.getPlayerId())) {
return false;
}
}
return true;
}
}
int amount = xCosts.calculate(game, source, this);
if (amount <= 0) {
return false;
}
String mana = "{" + amount + '}';
ManaCostsImpl<ManaCost> cost = new ManaCostsImpl<>(mana);
if (cost.canPay(source, source, event.getPlayerId(), game)
&& player.chooseUse(Outcome.Benefit, "Pay " + mana + " to declare blocker?", source, game)) {
return !cost.payOrRollback(source, game, source, event.getPlayerId());
}
return true;
return false;
}
@Override

View file

@ -54,7 +54,6 @@ class WarTaxCantAttackUnlessPaysEffect extends PayCostToAttackBlockEffectImpl {
WarTaxCantAttackUnlessPaysEffect(WarTaxCantAttackUnlessPaysEffect effect) {
super(effect);
this.xCosts = effect.xCosts.copy();
}
@Override

View file

@ -54,6 +54,9 @@ public final class Woeleecher extends CardImpl {
class WoeleecherEffect extends OneShotEffect {
private int numberCountersOriginal = 0;
private int numberCountersAfter = 0;
public WoeleecherEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Remove a -1/-1 counter from target creature. If you do, you gain 2 life";
@ -72,19 +75,15 @@ class WoeleecherEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent target = game.getPermanent(source.getFirstTarget());
Player you = game.getPlayer(source.getControllerId());
if (target == null || you == null) {
return false;
}
int numberCountersOriginal = target.getCounters(game).getCount(CounterType.M1M1);
target.removeCounters(CounterType.M1M1.createInstance(), source, game);
int numberCountersAfter = target.getCounters(game).getCount(CounterType.M1M1);
if (numberCountersAfter < numberCountersOriginal) {
you.gainLife(2, game, source);
return true;
} else {
return false;
if (target != null && you != null) {
numberCountersOriginal = target.getCounters(game).getCount(CounterType.M1M1);
target.removeCounters(CounterType.M1M1.createInstance(), source, game);
numberCountersAfter = target.getCounters(game).getCount(CounterType.M1M1);
if (numberCountersAfter < numberCountersOriginal && you != null) {
you.gainLife(2, game, source);
return true;
}
}
return false;
}
}

View file

@ -31,7 +31,7 @@ import java.util.*;
public class RandomPlayer extends ComputerPlayer {
private final boolean isSimulatedPlayer;
private int actionCount;
private int actionCount = 0;
protected PassAbility pass = new PassAbility();
@ -43,8 +43,6 @@ public class RandomPlayer extends ComputerPlayer {
public RandomPlayer(final RandomPlayer player) {
super(player);
this.isSimulatedPlayer = player.isSimulatedPlayer;
this.actionCount = player.actionCount;
this.pass = player.pass.copy();
}
@Override

View file

@ -83,7 +83,7 @@ public class TestPlayer implements Player {
public static final String DIE_ROLL = "[die_roll]: ";
private int maxCallsWithoutAction = 400;
private int foundNoAction;
private int foundNoAction = 0;
// full playable AI, TODO: can be deleted?
private boolean AIPlayer;
@ -106,9 +106,9 @@ public class TestPlayer implements Player {
// - enable checks for wrong or missing choice commands (you must set up all choices by unit test)
// - enable inner choice dialogs accessable by set up choices
// (example: card call TestPlayer's choice, but it uses another choices, see docs in TestComputerPlayer)
private boolean strictChooseMode;
private boolean strictChooseMode = false;
private String[] groupsForTargetHandling;
private String[] groupsForTargetHandling = null;
// Tracks the initial turns (turn 0s) both players are given at the start of the game.
// Before actual turns start. Needed for checking attacker/blocker legality in the tests
@ -146,7 +146,6 @@ public class TestPlayer implements Player {
this.groupsForTargetHandling = testPlayer.groupsForTargetHandling.clone();
}
this.strictChooseMode = testPlayer.strictChooseMode;
this.maxCallsWithoutAction = testPlayer.maxCallsWithoutAction;
}
public void addChoice(String choice) {

View file

@ -23,10 +23,10 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
protected boolean optional;
protected boolean leavesTheBattlefieldTrigger;
private boolean triggersOnce;
private boolean doOnlyOnce;
private GameEvent triggerEvent;
private String triggerPhrase;
private boolean triggersOnce = false;
private boolean doOnlyOnce = false;
private GameEvent triggerEvent = null;
private String triggerPhrase = null;
public TriggeredAbilityImpl(Zone zone, Effect effect) {
this(zone, effect, false);
@ -55,7 +55,6 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
this.triggersOnce = ability.triggersOnce;
this.doOnlyOnce = ability.doOnlyOnce;
this.triggerPhrase = ability.triggerPhrase;
this.triggerEvent = ability.triggerEvent;
}
@Override

View file

@ -15,8 +15,8 @@ import mage.target.targetpointer.FixedTarget;
*/
public class BlocksAttachedTriggeredAbility extends TriggeredAbilityImpl {
private final boolean setFixedTargetPointer;
private final String attachedDescription;
private boolean setFixedTargetPointer;
private String attachedDescription;
private boolean setFixedTargetPointerToBlocked;
public BlocksAttachedTriggeredAbility(Effect effect, String attachedDescription, boolean optional) {
@ -40,7 +40,6 @@ public class BlocksAttachedTriggeredAbility extends TriggeredAbilityImpl {
super(ability);
this.setFixedTargetPointer = ability.setFixedTargetPointer;
this.attachedDescription = ability.attachedDescription;
this.setFixedTargetPointerToBlocked = ability.setFixedTargetPointerToBlocked;
}
@Override

View file

@ -16,14 +16,13 @@ import java.util.UUID;
*/
public class CyclingDiscardCost extends CostImpl {
private MageObjectReference cycledCard;
private MageObjectReference cycledCard = null;
public CyclingDiscardCost() {
}
private CyclingDiscardCost(CyclingDiscardCost cost) {
super(cost);
this.cycledCard = cost.cycledCard;
}
@Override

View file

@ -49,7 +49,6 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
this.add(cost.copy());
}
this.phyrexian = costs.phyrexian;
this.phyrexianPaid = costs.phyrexianPaid;
}
@Override

View file

@ -42,7 +42,9 @@ public abstract class EffectImpl implements Effect {
if (effect.values != null) {
values = new HashMap<>();
Map<String, Object> map = effect.values;
values.putAll(map);
for (Map.Entry<String, Object> entry : map.entrySet()) {
values.put(entry.getKey(), entry.getValue());
}
}
}

View file

@ -21,7 +21,6 @@ public class DontUntapInControllersNextUntapStepSourceEffect extends ContinuousR
public DontUntapInControllersNextUntapStepSourceEffect(final DontUntapInControllersNextUntapStepSourceEffect effect) {
super(effect);
this.validForTurnNum = effect.validForTurnNum;
}
@Override

View file

@ -17,6 +17,7 @@ import mage.util.CardUtil;
public class ExileCardsFromTopOfLibraryTargetEffect extends OneShotEffect {
int amount;
String targetName;
public ExileCardsFromTopOfLibraryTargetEffect(int amount) {
this(amount, null);

View file

@ -10,10 +10,9 @@ import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
// TODO: Remove this class? Nothing uses it.
public class ReturnCreaturesFromExileEffect extends OneShotEffect {
private final UUID exileId;
private UUID exileId;
private boolean byOwner;
public ReturnCreaturesFromExileEffect(UUID exileId, boolean byOwner, String description) {
@ -24,10 +23,9 @@ public class ReturnCreaturesFromExileEffect extends OneShotEffect {
}
private ReturnCreaturesFromExileEffect(final ReturnCreaturesFromExileEffect effect) {
public ReturnCreaturesFromExileEffect(final ReturnCreaturesFromExileEffect effect) {
super(effect);
this.exileId = effect.exileId;
this.byOwner = effect.byOwner;
}
@Override

View file

@ -29,7 +29,6 @@ public class MustBeBlockedByAllAttachedEffect extends RequirementEffect {
public MustBeBlockedByAllAttachedEffect(final MustBeBlockedByAllAttachedEffect effect) {
super(effect);
this.attachmentType = effect.attachmentType;
}
@Override

View file

@ -11,7 +11,7 @@ import mage.game.permanent.Permanent;
*/
public class BecomesCreatureIfVehicleEffect extends ContinuousEffectImpl {
private static final CardType addedType = CardType.CREATURE;
private CardType addedType = CardType.CREATURE;
public BecomesCreatureIfVehicleEffect() {
super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);

View file

@ -22,7 +22,7 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
protected boolean addStillALandText;
protected boolean loseName;
protected boolean keepAbilities;
protected boolean removeSubtypes;
protected boolean removeSubtypes = false;
public BecomesCreatureTargetEffect(Token token, boolean loseAllAbilities, boolean stillALand, Duration duration) {
@ -58,7 +58,6 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
this.addStillALandText = effect.addStillALandText;
this.loseName = effect.loseName;
this.keepAbilities = effect.keepAbilities;
this.removeSubtypes = effect.removeSubtypes;
}
@Override

View file

@ -57,7 +57,6 @@ public class GainControlTargetEffect extends ContinuousEffectImpl {
super(effect);
this.controllingPlayerId = effect.controllingPlayerId;
this.fixedControl = effect.fixedControl;
this.firstControlChange = effect.firstControlChange;
}
@Override

View file

@ -32,7 +32,7 @@ public class AmassEffect extends OneShotEffect {
}
private final DynamicValue amassNumber;
private UUID amassedCreatureId;
private UUID amassedCreatureId = null;
public AmassEffect(int amassNumber) {
this(StaticValue.get(amassNumber));
@ -53,7 +53,6 @@ public class AmassEffect extends OneShotEffect {
private AmassEffect(final AmassEffect effect) {
super(effect);
this.amassNumber = effect.amassNumber;
this.amassedCreatureId = effect.amassedCreatureId;
}
@Override

View file

@ -39,7 +39,6 @@ public class ProtectionChosenColorAttachedEffect extends ContinuousEffectImpl {
this.protectionAbility = effect.protectionAbility.copy();
}
this.notRemoveItself = effect.notRemoveItself;
this.notRemoveControlled = effect.notRemoveControlled;
}
@Override

View file

@ -135,7 +135,7 @@ class ReturnAttackerToHandTargetCost extends CostImpl {
filter.add(UnblockedPredicate.instance);
}
private UUID defendingPlayerId;
private UUID defendingPlayerId = null;
public ReturnAttackerToHandTargetCost() {
this.addTarget(new TargetControlledPermanent(filter));
@ -144,7 +144,6 @@ class ReturnAttackerToHandTargetCost extends CostImpl {
public ReturnAttackerToHandTargetCost(ReturnAttackerToHandTargetCost cost) {
super(cost);
this.defendingPlayerId = cost.defendingPlayerId;
}
@Override
@ -153,7 +152,8 @@ class ReturnAttackerToHandTargetCost extends CostImpl {
for (UUID targetId : targets.get(0).getTargets()) {
Permanent permanent = game.getPermanent(targetId);
Player controller = game.getPlayer(controllerId);
if (permanent == null || controller == null) {
if (permanent == null
|| controller == null) {
return false;
}
defendingPlayerId = game.getCombat().getDefenderId(permanent.getId());

View file

@ -12,8 +12,8 @@ import mage.util.CardUtil;
public class VanishingUpkeepAbility extends BeginningOfUpkeepTriggeredAbility {
private final int vanishingAmount;
private final String permanentType;
private int vanishingAmount;
private String permanentType;
public VanishingUpkeepAbility(int vanishingEffect) {
super(new VanishingEffect(), TargetController.YOU, false);
@ -27,10 +27,9 @@ public class VanishingUpkeepAbility extends BeginningOfUpkeepTriggeredAbility {
this.permanentType = permanentType;
}
private VanishingUpkeepAbility(final VanishingUpkeepAbility ability) {
public VanishingUpkeepAbility(final VanishingUpkeepAbility ability) {
super(ability);
this.vanishingAmount = ability.vanishingAmount;
this.permanentType = ability.permanentType;
}
@Override
@ -64,16 +63,15 @@ class VanishingEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent p = game.getPermanent(source.getSourceId());
if (p == null) {
return false;
if (p != null) {
int amount = p.getCounters(game).getCount(CounterType.TIME);
if (amount > 0) {
p.removeCounters(CounterType.TIME.createInstance(), source, game);
game.informPlayers("Removed a time counter from " + p.getLogName() + " (" + amount + " left)");
}
return true;
}
int amount = p.getCounters(game).getCount(CounterType.TIME);
if (amount > 0) {
p.removeCounters(CounterType.TIME.createInstance(), source, game);
game.informPlayers("Removed a time counter from " + p.getLogName() + " (" + amount + " left)");
}
return true;
return false;
}
@Override

View file

@ -73,7 +73,7 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
private final FilterPermanent filter;
private final boolean onlyColors; // false if mana types can be produced (also Colorless mana), if true only colors can be produced (no Colorless mana).
private boolean inManaTypeCalculation;
private boolean inManaTypeCalculation = false;
AnyColorLandsProduceManaEffect(TargetController targetController, boolean onlyColors, FilterPermanent filter) {
super();
@ -93,7 +93,6 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
super(effect);
this.filter = effect.filter.copy();
this.onlyColors = effect.onlyColors;
this.inManaTypeCalculation = effect.inManaTypeCalculation;
}
@Override

View file

@ -57,7 +57,7 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
private final FilterPermanent filter;
private final boolean onlyColors; // false if mana types can be produced (also Colorless mana), if true only colors can be produced (no Colorless mana).
private boolean inManaTypeCalculation;
private boolean inManaTypeCalculation = false;
public AnyColorPermanentTypesManaEffect(TargetController targetController, boolean onlyColors, FilterPermanent permanentTypes) {
super();
@ -72,7 +72,6 @@ class AnyColorPermanentTypesManaEffect extends ManaEffect {
super(effect);
this.filter = effect.filter.copy();
this.onlyColors = effect.onlyColors;
this.inManaTypeCalculation = effect.inManaTypeCalculation;
}
@Override

View file

@ -85,9 +85,9 @@ public class GameState implements Serializable, Copyable<GameState> {
private Exile exile;
private Battlefield battlefield;
private int turnNum = 1;
private int stepNum;
private UUID turnId;
private boolean extraTurn;
private int stepNum = 0;
private UUID turnId = null;
private boolean extraTurn = false;
private boolean legendaryRuleActive = true;
private boolean gameOver;
private boolean paused;
@ -105,8 +105,8 @@ public class GameState implements Serializable, Copyable<GameState> {
private int permanentOrderNumber;
private final Map<UUID, FilterCreaturePermanent> usePowerInsteadOfToughnessForDamageLethalityFilters = new HashMap<>();
private Set<MageObjectReference> commandersToStay = new HashSet<>(); // commanders that do not go back to command zone
private boolean manaBurn;
private boolean hasDayNight;
private boolean manaBurn = false;
private boolean hasDayNight = false;
private boolean isDaytime = true;
private int applyEffectsCounter; // Upcounting number of each applyEffects execution
@ -157,7 +157,6 @@ public class GameState implements Serializable, Copyable<GameState> {
this.battlefield = state.battlefield.copy();
this.turnNum = state.turnNum;
this.stepNum = state.stepNum;
this.turnId = state.turnId;
this.extraTurn = state.extraTurn;
this.legendaryRuleActive = state.legendaryRuleActive;
this.effects = state.effects.copy();
@ -200,7 +199,6 @@ public class GameState implements Serializable, Copyable<GameState> {
this.commandersToStay.addAll(state.commandersToStay);
this.hasDayNight = state.hasDayNight;
this.isDaytime = state.isDaytime;
this.manaBurn = state.manaBurn;
}
public void clearOnGameRestart() {

View file

@ -39,7 +39,6 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
public GameTinyLeadersImpl(final GameTinyLeadersImpl game) {
super(game);
this.alsoHand = game.alsoHand;
this.alsoLibrary = game.alsoLibrary;
this.startingPlayerSkipsDraw = game.startingPlayerSkipsDraw;
}
@ -51,37 +50,35 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
// move tiny leader to command zone
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
Player player = getPlayer(playerId);
if (player == null) {
continue;
}
String commanderName = player.getMatchPlayer().getDeck().getName();
Card commander = findCommander(this, player, commanderName);
if (commander != null) {
// already exists - just move to zone (example: game restart by Karn Liberated)
commander.moveToZone(Zone.COMMAND, null, this, true);
} else {
// create new commander
commander = getCommanderCard(commanderName, player.getId());
if (player != null) {
String commanderName = player.getMatchPlayer().getDeck().getName();
Card commander = findCommander(this, player, commanderName);
if (commander != null) {
Set<Card> cards = new HashSet<>();
cards.add(commander);
this.loadCards(cards, playerId);
player.addCommanderId(commander.getId());
// already exists - just move to zone (example: game restart by Karn Liberated)
commander.moveToZone(Zone.COMMAND, null, this, true);
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary, false, "Commander"));
ability.addEffect(new CommanderCostModification(commander));
// Commander rule #4 was removed Jan. 18, 2016
// ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander)));
CommanderInfoWatcher watcher = new CommanderInfoWatcher("Commander", commander.getId(), false);
getState().addWatcher(watcher);
watcher.addCardInfoToCommander(this);
this.getState().addAbility(ability, null);
} else {
// GameWorker.call processing errors and write it in magediag.log by defalt
// Test use case: create tiny game with random generated deck - game freezes with empty battlefield
throw new IllegalStateException("Commander card could not be created. Name: [" + player.getMatchPlayer().getDeck().getName() + ']');
// create new commander
commander = getCommanderCard(commanderName, player.getId());
if (commander != null) {
Set<Card> cards = new HashSet<>();
cards.add(commander);
this.loadCards(cards, playerId);
player.addCommanderId(commander.getId());
commander.moveToZone(Zone.COMMAND, null, this, true);
Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary, false, "Commander"));
ability.addEffect(new CommanderCostModification(commander));
// Commander rule #4 was removed Jan. 18, 2016
// ability.addEffect(new CommanderManaReplacementEffect(player.getId(), CardUtil.getColorIdentity(commander)));
CommanderInfoWatcher watcher = new CommanderInfoWatcher("Commander", commander.getId(), false);
getState().addWatcher(watcher);
watcher.addCardInfoToCommander(this);
this.getState().addAbility(ability, null);
} else {
// GameWorker.call processing errors and write it in magediag.log by defalt
// Test use case: create tiny game with random generated deck - game freezes with empty battlefield
throw new IllegalStateException("Commander card could not be created. Name: [" + player.getMatchPlayer().getDeck().getName() + ']');
}
}
}
}

View file

@ -73,9 +73,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
protected boolean morphed = false;
protected int classLevel = 1;
protected final Set<UUID> goadingPlayers = new HashSet<>();
// The UUID of the controller under who the permanent first entered the battelfield under.
protected UUID originalControllerId;
// The UUID of the current controller.
protected UUID controllerId;
protected UUID beforeResetControllerId;
protected int damage;
@ -131,7 +129,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.flipped = permanent.flipped;
this.originalControllerId = permanent.originalControllerId;
this.controllerId = permanent.controllerId;
this.beforeResetControllerId = permanent.controllerId;
this.damage = permanent.damage;
this.controlledFromStartOfControllerTurn = permanent.controlledFromStartOfControllerTurn;
this.turnsOnBattlefield = permanent.turnsOnBattlefield;
@ -144,9 +141,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.deathtouched = permanent.deathtouched;
this.markedLifelink = permanent.markedLifelink;
this.connectedCards.putAll(permanent.connectedCards);
for (Map.Entry<String, List<UUID>> entry : permanent.connectedCards.entrySet()) {
this.connectedCards.put(entry.getKey(), entry.getValue());
}
if (permanent.dealtDamageByThisTurn != null) {
this.dealtDamageByThisTurn = new HashSet<>(permanent.dealtDamageByThisTurn);
dealtDamageByThisTurn = new HashSet<>(permanent.dealtDamageByThisTurn);
}
if (permanent.markedDamage != null) {
markedDamage = new ArrayList<>();
@ -172,7 +171,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.bandedCards.addAll(permanent.bandedCards);
this.timesLoyaltyUsed = permanent.timesLoyaltyUsed;
this.transformCount = permanent.transformCount;
this.removedFromCombat = permanent.removedFromCombat;
this.morphed = permanent.morphed;
this.manifested = permanent.manifested;
@ -195,14 +193,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
abilities.setControllerId(controllerId);
}
/**
* Used to override the original controller of a permanent to be different than the player who cast the spell
* or activated the ability.
*
* E.g. Xantcha, Sleeper Agent. Who enters the battlefield directly under someone else's control.
*
* @param originalControllerId The UUID of the original controller of the permanent
*/
@Override
public void setOriginalControllerId(UUID originalControllerId) {
this.originalControllerId = originalControllerId;
@ -774,7 +764,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
@Override
public boolean checkControlChanged(Game game) {
// TODO Put a break point and see what's going on with controllerID, beforeResetControllerID, and originalControllerID
if (!controllerId.equals(beforeResetControllerId)) {
this.removeFromCombat(game);
this.controlledFromStartOfControllerTurn = false;
@ -915,7 +904,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
* @return
*/
private int doDamage(int damageAmount, UUID attackerId, Ability source, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
int damageDone;
int damageDone = 0;
if (damageAmount < 1 || !canDamage(game.getObject(attackerId), game)) {
return 0;
}
@ -1769,22 +1758,20 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
Zone fromZone = game.getState().getZone(objectId);
Player controller = game.getPlayer(controllerId);
if (controller == null) {
return false;
if (controller != null) {
ZoneChangeEvent event = new ZoneChangeEvent(this, source, controllerId, fromZone, toZone, appliedEffects);
ZoneChangeInfo zoneChangeInfo;
if (toZone == Zone.LIBRARY) {
zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */);
} else {
zoneChangeInfo = new ZoneChangeInfo(event);
}
boolean successfullyMoved = ZonesHandler.moveCard(zoneChangeInfo, game, source);
//20180810 - 701.3d
detachAllAttachments(game);
return successfullyMoved;
}
ZoneChangeEvent event = new ZoneChangeEvent(this, source, controllerId, fromZone, toZone, appliedEffects);
ZoneChangeInfo zoneChangeInfo;
if (toZone == Zone.LIBRARY) {
zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */);
} else {
zoneChangeInfo = new ZoneChangeInfo(event);
}
boolean successfullyMoved = ZonesHandler.moveCard(zoneChangeInfo, game, source);
//20180810 - 701.3d
detachAllAttachments(game);
return successfullyMoved;
return false;
}
@Override

View file

@ -81,7 +81,6 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
this.expansionSetCodeChecked = token.expansionSetCodeChecked;
this.copySourceCard = token.copySourceCard; // will never be changed
this.availableImageSetCodes = token.availableImageSetCodes;
this.tokenDescriptor = token.tokenDescriptor;
}
@Override

View file

@ -30,7 +30,6 @@ public class SpellStack extends ArrayDeque<StackObject> {
for (StackObject spell : stack) {
this.addLast(spell.copy());
}
this.dateLastAdded = stack.dateLastAdded;
}
//resolve top StackObject