mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
Added additional test for prevent damage effects, improved 3358e2da80
(#6915)
This commit is contained in:
parent
3358e2da80
commit
2eeefd91ef
9 changed files with 137 additions and 64 deletions
|
@ -1,16 +1,16 @@
|
||||||
package mage.cards.b;
|
package mage.cards.b;
|
||||||
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.BecomesTargetTriggeredAbility;
|
import mage.abilities.common.BecomesTargetTriggeredAbility;
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
|
||||||
import mage.abilities.effects.common.DamageTargetEffect;
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.DamageCantBePreventedEffect;
|
||||||
import mage.cards.AdventureCard;
|
import mage.cards.AdventureCard;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.target.common.TargetAnyTarget;
|
import mage.target.common.TargetAnyTarget;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -34,7 +34,7 @@ public final class BonecrusherGiant extends AdventureCard {
|
||||||
|
|
||||||
// Stomp
|
// Stomp
|
||||||
// Damage can’t be prevented this turn. Stomp deals 2 damage to any target.
|
// Damage can’t be prevented this turn. Stomp deals 2 damage to any target.
|
||||||
this.getSpellCard().getSpellAbility().addEffect(new StompEffect());
|
this.getSpellCard().getSpellAbility().addEffect(new DamageCantBePreventedEffect(Duration.EndOfTurn, "Damage can't be prevented this turn", false, false));
|
||||||
this.getSpellCard().getSpellAbility().addEffect(new DamageTargetEffect(2));
|
this.getSpellCard().getSpellAbility().addEffect(new DamageTargetEffect(2));
|
||||||
this.getSpellCard().getSpellAbility().addTarget(new TargetAnyTarget());
|
this.getSpellCard().getSpellAbility().addTarget(new TargetAnyTarget());
|
||||||
}
|
}
|
||||||
|
@ -47,36 +47,4 @@ public final class BonecrusherGiant extends AdventureCard {
|
||||||
public BonecrusherGiant copy() {
|
public BonecrusherGiant copy() {
|
||||||
return new BonecrusherGiant(this);
|
return new BonecrusherGiant(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StompEffect extends ReplacementEffectImpl {
|
|
||||||
|
|
||||||
StompEffect() {
|
|
||||||
super(Duration.EndOfTurn, Outcome.Benefit);
|
|
||||||
staticText = "Damage can't be prevented this turn.";
|
|
||||||
}
|
|
||||||
|
|
||||||
private StompEffect(final StompEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StompEffect copy() {
|
|
||||||
return new StompEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.PREVENT_DAMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -82,7 +82,7 @@ class QuestingBeastPreventionEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
QuestingBeastPreventionEffect() {
|
QuestingBeastPreventionEffect() {
|
||||||
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||||
staticText = "Combat damage that would be dealt by creatures you control can't be prevented.";
|
staticText = "Combat damage that would be dealt by creatures you control can't be prevented";
|
||||||
}
|
}
|
||||||
|
|
||||||
private QuestingBeastPreventionEffect(final QuestingBeastPreventionEffect effect) {
|
private QuestingBeastPreventionEffect(final QuestingBeastPreventionEffect effect) {
|
||||||
|
|
|
@ -80,8 +80,9 @@ class StormwildCapridorEffect extends PreventionEffectImpl {
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
permanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source, game);
|
permanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source, game);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return preventionEffectData.isReplaced();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,11 +91,8 @@ class StormwildCapridorEffect extends PreventionEffectImpl {
|
||||||
|| !super.applies(event, source, game)) {
|
|| !super.applies(event, source, game)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getSourceId(), source.getControllerId()))) {
|
DamageCreatureEvent damageEvent = (DamageCreatureEvent) event;
|
||||||
DamageCreatureEvent damageEvent = (DamageCreatureEvent) event;
|
return !damageEvent.isCombatDamage();
|
||||||
return !damageEvent.isCombatDamage();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class ConditionalPreventionTest extends CardTestPlayerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_PrentableCombatDamage() {
|
public void test_PreventableCombatDamage() {
|
||||||
// Prevent all damage that would be dealt to creatures.
|
// Prevent all damage that would be dealt to creatures.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Bubble Matrix", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Bubble Matrix", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||||
|
@ -190,4 +190,77 @@ public class ConditionalPreventionTest extends CardTestPlayerBase {
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 20 - 2);
|
assertLife(playerB, 20 - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PreventSomeDamage_Normal() {
|
||||||
|
// Kicker-Sacrifice a land.
|
||||||
|
// Prevent the next 3 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose.
|
||||||
|
// If Pollen Remedy was kicked, prevent the next 6 damage this way instead.
|
||||||
|
addCard(Zone.HAND, playerA, "Pollen Remedy", 1); // {W}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Swamp", 1); // for kicker
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
|
||||||
|
// add shield for 3 damage
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pollen Remedy");
|
||||||
|
setChoice(playerA, "No"); // no kicker
|
||||||
|
addTargetAmount(playerA, "Balduvian Bears", 3);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("shield", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pollen Remedy", 1);
|
||||||
|
|
||||||
|
// 6 damage to die (if no shield then can cast only 1 bolt)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
checkGraveyardCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 2);
|
||||||
|
checkGraveyardCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PreventSomeDamage_Kicked() {
|
||||||
|
// Kicker-Sacrifice a land.
|
||||||
|
// Prevent the next 3 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose.
|
||||||
|
// If Pollen Remedy was kicked, prevent the next 6 damage this way instead.
|
||||||
|
addCard(Zone.HAND, playerA, "Pollen Remedy", 1); // {W}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); // for kicker
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
|
||||||
|
// add shield for 6 damage
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pollen Remedy");
|
||||||
|
setChoice(playerA, "Yes"); // use kicker
|
||||||
|
setChoice(playerA, "Swamp"); // kicker cost
|
||||||
|
addTargetAmount(playerA, "Balduvian Bears", 6);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("shield", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pollen Remedy", 1);
|
||||||
|
|
||||||
|
// 9 damage to die (if no shield then can cast only 1 bolt)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
checkGraveyardCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 3);
|
||||||
|
checkGraveyardCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,4 +650,43 @@ public class AdventureCardsTest extends CardTestPlayerBase {
|
||||||
execute();
|
execute();
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_BonecrusherGiant_Stopm() {
|
||||||
|
// bug with non working stopm: https://github.com/magefree/mage/issues/6915
|
||||||
|
|
||||||
|
// If noncombat damage would be dealt to Stormwild Capridor, prevent that damage.
|
||||||
|
// Put a +1/+1 counter on Stormwild Capridor for each 1 damage prevented this way.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Stormwild Capridor@storm", 2); // 1/3
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||||
|
//
|
||||||
|
// Stomp {1}{R}
|
||||||
|
// Damage can’t be prevented this turn. Stomp deals 2 damage to any target.
|
||||||
|
addCard(Zone.HAND, playerA, "Bonecrusher Giant", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||||
|
|
||||||
|
// prevent
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@storm.1");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("prevent", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
|
||||||
|
checkGraveyardCount("prevent", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "@storm.1", 0);
|
||||||
|
|
||||||
|
// prepare protect by stomp
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stomp");
|
||||||
|
addTarget(playerA, playerB);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// can't prevent
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@storm.2");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("can't prevent", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 2);
|
||||||
|
checkGraveyardCount("can't prevent", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "@storm.2", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2450,7 +2450,7 @@ public class TestPlayer implements Player {
|
||||||
//Assert.fail("Wrong target");
|
//Assert.fail("Wrong target");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chooseStrictModeFailed("target", game, getInfo(source, game) + "; " + getInfo(target));
|
this.chooseStrictModeFailed("target", game, getInfo(source, game) + "\n" + getInfo(target));
|
||||||
return computerPlayer.chooseTarget(outcome, cards, target, source, game);
|
return computerPlayer.chooseTarget(outcome, cards, target, source, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3760,7 +3760,7 @@ public class TestPlayer implements Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chooseStrictModeFailed("target", game, getInfo(source, game) + "; " + getInfo(target));
|
this.chooseStrictModeFailed("target", game, getInfo(source, game) + "\n" + getInfo(target));
|
||||||
return computerPlayer.chooseTargetAmount(outcome, target, source, game);
|
return computerPlayer.chooseTargetAmount(outcome, target, source, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,7 +287,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Assert.assertFalse("Wrong stop command on " + this.stopOnTurn + " / " + this.stopAtStep + " (" + this.stopAtStep.getIndex() + ")"
|
Assert.assertFalse("Wrong stop command on " + this.stopOnTurn + " / " + this.stopAtStep + " (" + this.stopAtStep.getIndex() + ")"
|
||||||
+ " (found actions after stop on " + maxTurn + " / " + maxPhase + ")",
|
+ " (found actions after stop on " + maxTurn + " / " + maxPhase + ")",
|
||||||
(maxTurn > this.stopOnTurn) || (maxTurn == this.stopOnTurn && maxPhase > this.stopAtStep.getIndex()));
|
(maxTurn > this.stopOnTurn) || (maxTurn == this.stopOnTurn && maxPhase > this.stopAtStep.getIndex()));
|
||||||
|
|
||||||
if (!currentGame.isPaused()) {
|
if (!currentGame.isPaused()) {
|
||||||
|
@ -916,7 +916,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
||||||
}
|
}
|
||||||
Assert.assertNotNull("There is no such permanent under player's control, player=" + player.getName()
|
Assert.assertNotNull("There is no such permanent under player's control, player=" + player.getName()
|
||||||
+ ", cardName=" + cardName, found);
|
+ ", cardName=" + cardName, found);
|
||||||
|
|
||||||
Assert.assertEquals(amount, found.getAbilities(currentGame).stream()
|
Assert.assertEquals(amount, found.getAbilities(currentGame).stream()
|
||||||
.filter(a -> searchedAbility.isAssignableFrom(a.getClass())).collect(Collectors.toList()).size());
|
.filter(a -> searchedAbility.isAssignableFrom(a.getClass())).collect(Collectors.toList()).size());
|
||||||
}
|
}
|
||||||
|
@ -1619,9 +1619,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
||||||
* @param step
|
* @param step
|
||||||
* @param player
|
* @param player
|
||||||
* @param cardName
|
* @param cardName
|
||||||
* @param targetName for modes you can add "mode=3" before target name,
|
* @param targetName for modes you can add "mode=3" before target name;
|
||||||
* multiple targets can be seperated by ^, not target
|
* multiple targets can be seperated by ^;
|
||||||
* marks as TestPlayer.NO_TARGET
|
* no target marks as TestPlayer.NO_TARGET;
|
||||||
|
* warning, do not support cards with target adjusters - use addTarget instead
|
||||||
*/
|
*/
|
||||||
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName) {
|
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName) {
|
||||||
//Assert.assertNotEquals("", cardName);
|
//Assert.assertNotEquals("", cardName);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
public class DamageCantBePreventedEffect extends ContinuousRuleModifyingEffectImpl {
|
public class DamageCantBePreventedEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
public DamageCantBePreventedEffect(Duration duration, String staticText, boolean messageToUser, boolean messageToLog) {
|
public DamageCantBePreventedEffect(Duration duration, String staticText, boolean messageToUser, boolean messageToLog) {
|
||||||
super(duration, Outcome.Benefit, messageToUser, messageToLog);
|
super(duration, Outcome.Benefit, messageToUser, messageToLog);
|
||||||
this.staticText = staticText;
|
this.staticText = staticText;
|
||||||
|
|
|
@ -12,14 +12,7 @@ import mage.game.events.GameEvent.EventType;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
@ -112,9 +105,9 @@ public abstract class TargetImpl implements Target {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Select ").append(targetName);
|
sb.append("Select ").append(targetName);
|
||||||
if (getMaxNumberOfTargets() > 0 && getMaxNumberOfTargets() != Integer.MAX_VALUE) {
|
if (getMaxNumberOfTargets() > 0 && getMaxNumberOfTargets() != Integer.MAX_VALUE) {
|
||||||
sb.append(" (").append(targets.size()).append('/').append(getMaxNumberOfTargets()).append(')');
|
sb.append(" (selected ").append(targets.size()).append(" of ").append(getMaxNumberOfTargets()).append(')');
|
||||||
} else {
|
} else {
|
||||||
sb.append(" (").append(targets.size()).append(')');
|
sb.append(" (selected ").append(targets.size()).append(')');
|
||||||
}
|
}
|
||||||
sb.append(suffix);
|
sb.append(suffix);
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|
Loading…
Reference in a new issue