* AI: fixed rollback errors with copy spell abilities;

Tests: added copy spell support for test player;
This commit is contained in:
Oleg Agafonov 2019-12-23 21:47:01 +04:00
parent c0df1d6e8a
commit fac7ea1388
3 changed files with 137 additions and 73 deletions

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.triggers;
import mage.abilities.keyword.TrampleAbility;
@ -8,7 +7,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ZadaHedronGrinderTest extends CardTestPlayerBase {
@ -43,7 +41,70 @@ public class ZadaHedronGrinderTest extends CardTestPlayerBase {
assertAbility(playerA, "Zada, Hedron Grinder", TrampleAbility.getInstance(), true);
assertPowerToughness(playerA, "Silvercoat Lion", 4, 2);
assertAbility(playerA, "Silvercoat Lion", TrampleAbility.getInstance(), true);
}
@Test
public void testTargetsByTestPlayer() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder, copy that spell for
// each other creature you control that the spell could target. Each copy targets a different one of those creatures.
addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1); // 3/3
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
//
// Put a +1/+1 counter on target creature. That creature gains reach until end of turn.
addCard(Zone.HAND, playerA, "Arbor Armament", 1); // {G}
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
// cast
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Arbor Armament", "Zada, Hedron Grinder");
addTarget(playerA, "Balduvian Bears^Silvercoat Lion");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Arbor Armament", 1);
assertPowerToughness(playerA, "Zada, Hedron Grinder", 3 + 1, 3 + 1);
assertPowerToughness(playerA, "Silvercoat Lion", 2 + 1, 2 + 1);
assertPowerToughness(playerA, "Balduvian Bears", 2 + 1, 2 + 1);
}
@Test
public void testTargetsByAI() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder, copy that spell for
// each other creature you control that the spell could target. Each copy targets a different one of those creatures.
addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1); // 3/3
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
//
// Put a +1/+1 counter on target creature. That creature gains reach until end of turn.
addCard(Zone.HAND, playerA, "Arbor Armament", 1); // {G}
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
// cast
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Arbor Armament", "Zada, Hedron Grinder");
//addTarget(playerA, "Balduvian Bears^Silvercoat Lion");
//setStrictChooseMode(true); // no strict mode for AI
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Arbor Armament", 1);
assertPowerToughness(playerA, "Zada, Hedron Grinder", 3 + 1, 3 + 1);
assertPowerToughness(playerA, "Silvercoat Lion", 2 + 1, 2 + 1);
assertPowerToughness(playerA, "Balduvian Bears", 2 + 1, 2 + 1);
}
}

View file

@ -453,9 +453,9 @@ public class TestPlayer implements Player {
if (currentTarget.getNumberOfTargets() == 1) {
currentTarget.clearChosen();
}
if (currentTarget instanceof TargetCreaturePermanentAmount) {
if (currentTarget.getOriginalTarget() instanceof TargetCreaturePermanentAmount) {
// supports only to set the complete amount to one target
TargetCreaturePermanentAmount targetAmount = (TargetCreaturePermanentAmount) currentTarget;
TargetCreaturePermanentAmount targetAmount = (TargetCreaturePermanentAmount) currentTarget.getOriginalTarget();
targetAmount.setAmount(ability, game);
int amount = targetAmount.getAmountRemaining();
targetAmount.addTarget(id, amount, ability, game);
@ -1540,12 +1540,13 @@ public class TestPlayer implements Player {
source = stackObject.getStackAbility();
}
if ((target instanceof TargetPermanent) || (target instanceof TargetPermanentOrPlayer)) { // player target not implemted yet
if ((target.getOriginalTarget() instanceof TargetPermanent)
|| (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)) { // player target not implemted yet
FilterPermanent filterPermanent;
if (target instanceof TargetPermanentOrPlayer) {
filterPermanent = ((TargetPermanentOrPlayer) target).getFilterPermanent();
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
filterPermanent = ((TargetPermanentOrPlayer) target.getOriginalTarget()).getFilterPermanent();
} else {
filterPermanent = ((TargetPermanent) target).getFilter();
filterPermanent = ((TargetPermanent) target.getOriginalTarget()).getFilter();
}
for (String choose2 : choices) {
String[] targetList = choose2.split("\\^");
@ -1608,7 +1609,7 @@ public class TestPlayer implements Player {
}
// TODO: add same choices fixes for other target types (one choice must uses only one time for one target)
if (target instanceof TargetCard) {
if (target.getOriginalTarget() instanceof TargetCard) {
// one choice per target
// only unique targets
//TargetCard targetFull = ((TargetCard) target);
@ -1674,9 +1675,9 @@ public class TestPlayer implements Player {
}
}
if (target instanceof TargetSource) {
if (target.getOriginalTarget() instanceof TargetSource) {
Set<UUID> possibleTargets;
TargetSource t = ((TargetSource) target);
TargetSource t = ((TargetSource) target.getOriginalTarget());
possibleTargets = t.possibleTargets(sourceId, abilityControllerId, game);
for (String choose2 : choices) {
String[] targetList = choose2.split("\\^");
@ -1760,11 +1761,11 @@ public class TestPlayer implements Player {
}
// player
if (target instanceof TargetPlayer
|| target instanceof TargetAnyTarget
|| target instanceof TargetCreatureOrPlayer
|| target instanceof TargetPermanentOrPlayer
|| target instanceof TargetDefender) {
if (target.getOriginalTarget() instanceof TargetPlayer
|| target.getOriginalTarget() instanceof TargetAnyTarget
|| target.getOriginalTarget() instanceof TargetCreatureOrPlayer
|| target.getOriginalTarget() instanceof TargetPermanentOrPlayer
|| target.getOriginalTarget() instanceof TargetDefender) {
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "=");
if (targetDefinition.startsWith("targetPlayer=")) {
@ -1779,15 +1780,14 @@ public class TestPlayer implements Player {
}
}
}
}
// permanent in battlefield
if ((target instanceof TargetPermanent)
|| (target instanceof TargetPermanentOrPlayer)
|| (target instanceof TargetAnyTarget)
|| (target instanceof TargetCreatureOrPlayer)
|| (target instanceof TargetDefender)) {
if ((target.getOriginalTarget() instanceof TargetPermanent)
|| (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)
|| (target.getOriginalTarget() instanceof TargetAnyTarget)
|| (target.getOriginalTarget() instanceof TargetCreatureOrPlayer)
|| (target.getOriginalTarget() instanceof TargetDefender)) {
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^[]");
String[] targetList = targetDefinition.split("\\^");
@ -1805,7 +1805,7 @@ public class TestPlayer implements Player {
targetName = targetName.substring(0, targetName.length() - 11);
}
}
Filter filter = target.getFilter();
Filter filter = target.getOriginalTarget().getFilter();
if (filter instanceof FilterCreatureOrPlayer) {
filter = ((FilterCreatureOrPlayer) filter).getCreatureFilter();
}
@ -1824,12 +1824,11 @@ public class TestPlayer implements Player {
if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
target.add(permanent.getId(), game);
targetFound = true;
break;
break; // return to for (String targetName
}
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
@ -1839,18 +1838,18 @@ public class TestPlayer implements Player {
}
// card in hand
if (target instanceof TargetCardInHand) {
if (target.getOriginalTarget() instanceof TargetCardInHand) {
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (Card card : computerPlayer.getHand().getCards(((TargetCardInHand) target).getFilter(), game)) {
for (Card card : computerPlayer.getHand().getCards(((TargetCardInHand) target.getOriginalTarget()).getFilter(), game)) {
if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
target.add(card.getId(), game);
targetFound = true;
break;
break; // return to for (String targetName
}
}
}
@ -1863,8 +1862,8 @@ public class TestPlayer implements Player {
}
// card in exile
if (target instanceof TargetCardInExile) {
TargetCardInExile targetFull = (TargetCardInExile) target;
if (target.getOriginalTarget() instanceof TargetCardInExile) {
TargetCardInExile targetFull = (TargetCardInExile) target.getOriginalTarget();
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
@ -1872,10 +1871,10 @@ public class TestPlayer implements Player {
for (String targetName : targetList) {
for (Card card : game.getExile().getCards(targetFull.getFilter(), game)) {
if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !targetFull.getTargets().contains(card.getId())) {
targetFull.add(card.getId(), game);
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
target.add(card.getId(), game);
targetFound = true;
break;
break; // return to for (String targetName
}
}
}
@ -1900,7 +1899,7 @@ public class TestPlayer implements Player {
if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !targetFull.getTargets().contains(card.getId())) {
targetFull.add(card.getId(), game);
targetFound = true;
break;
break; // return to for (String targetName
}
}
}
@ -1914,22 +1913,22 @@ public class TestPlayer implements Player {
// card in graveyard
if (target instanceof TargetCardInOpponentsGraveyard
|| target instanceof TargetCardInYourGraveyard
|| target instanceof TargetCardInGraveyard
|| target instanceof TargetCardInGraveyardOrBattlefield) {
TargetCard targetFull = (TargetCard) target;
if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard
|| target.getOriginalTarget() instanceof TargetCardInYourGraveyard
|| target.getOriginalTarget() instanceof TargetCardInGraveyard
|| target.getOriginalTarget() instanceof TargetCardInGraveyardOrBattlefield) {
TargetCard targetFull = (TargetCard) target.getOriginalTarget();
List<UUID> needPlayers = game.getState().getPlayersInRange(getId(), game).toList();
// fix for opponent graveyard
if (target instanceof TargetCardInOpponentsGraveyard) {
if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard) {
// current player remove
Assert.assertTrue(needPlayers.contains(getId()));
needPlayers.remove(getId());
Assert.assertFalse(needPlayers.contains(getId()));
}
// fix for your graveyard
if (target instanceof TargetCardInYourGraveyard) {
if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard) {
// only current player
Assert.assertTrue(needPlayers.contains(getId()));
needPlayers.clear();
@ -1948,17 +1947,16 @@ public class TestPlayer implements Player {
Player player = game.getPlayer(playerId);
for (Card card : player.getGraveyard().getCards(targetFull.getFilter(), game)) {
if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
target.add(card.getId(), game);
targetFound = true;
break IterateGraveyards;
break IterateGraveyards; // return to for (String targetName
}
}
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
@ -1968,7 +1966,7 @@ public class TestPlayer implements Player {
}
// stack
if (target instanceof TargetSpell) {
if (target.getOriginalTarget() instanceof TargetSpell) {
for (String targetDefinition : targets) {
checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
@ -1976,9 +1974,11 @@ public class TestPlayer implements Player {
for (String targetName : targetList) {
for (StackObject stackObject : game.getStack()) {
if (stackObject.getName().equals(targetName)) {
target.add(stackObject.getId(), game);
targetFound = true;
break;
if (target.canTarget(abilityControllerId, stackObject.getId(), source, game) && !target.getTargets().contains(stackObject.getId())) {
target.add(stackObject.getId(), game);
targetFound = true;
break; // return to for (String targetName
}
}
}
}