[CMR] implemented Opposition Agent and other changes:

* You may play cards and you may spend mana of any color - refactored cards to use same code;
* Library search event allows to change searching controller (gives full game control for another player);
* Library searched event allows to remove founded cards from result;
* Improved library searching effects with Panglacial Wurm's effects;
* Little changes to test framework;
This commit is contained in:
Oleg Agafonov 2020-11-24 23:49:19 +04:00
parent 13fa98ec44
commit c2a636e2b2
22 changed files with 806 additions and 721 deletions

View file

@ -120,6 +120,10 @@ public class SpendOtherManaTest extends CardTestPlayerBase {
// You may cast that card as long as it remains exiled, and you may spend mana as though it were mana of any type to cast that spell.
addCard(Zone.HAND, playerA, "Hostage Taker"); // {2}{U}{B}
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}.");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}.");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}.");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}.");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hostage Taker");
addTarget(playerA, "Silvercoat Lion");

View file

@ -0,0 +1,254 @@
package org.mage.test.cards.control;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.replacement.YouControlYourOpponentsWhileSearchingReplacementEffect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author JayDi85
*/
public class TakeControlWhileSearchingLibraryTest extends CardTestPlayerBase {
@Test
public void test_SimpleSearchingLibrary_Normal() {
removeAllCardsFromLibrary(playerA);
removeAllCardsFromLibrary(playerB);
addCard(Zone.LIBRARY, playerA, "Balduvian Bears", 1);
addCard(Zone.LIBRARY, playerB, "Kitesail Corsair", 1);
//
// Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
addCard(Zone.HAND, playerA, "Buried Alive", 1); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
// before
checkGraveyardCount("before a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkGraveyardCount("before b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
// search as normal
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Buried Alive");
addTarget(playerA, "Balduvian Bears");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// after
checkGraveyardCount("after a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
checkGraveyardCount("after b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
}
@Test
public void test_SimpleSearchingLibrary_TakeControl() {
removeAllCardsFromLibrary(playerA);
removeAllCardsFromLibrary(playerB);
addCard(Zone.LIBRARY, playerA, "Balduvian Bears", 1);
addCard(Zone.LIBRARY, playerB, "Kitesail Corsair", 1);
//
// Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
addCard(Zone.HAND, playerA, "Buried Alive", 1); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
//
// You control your opponents while theyre searching their libraries.
addCustomCardWithAbility("control", playerB, new SimpleStaticAbility(
new YouControlYourOpponentsWhileSearchingReplacementEffect())
);
//
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// before
checkGraveyardCount("before a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkGraveyardCount("before b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
// search under control of B
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Buried Alive");
setChoice(playerB, "Yes"); // continue
addTarget(playerB, "Balduvian Bears"); // player B must take control for searching
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// after
checkGraveyardCount("after a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
checkGraveyardCount("after b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
// check that control returned
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt");
addTarget(playerA, playerB);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
}
@Test
public void test_CastCardWhileSearchingLibrary_Normal() {
removeAllCardsFromLibrary(playerA);
removeAllCardsFromLibrary(playerB);
addCard(Zone.LIBRARY, playerA, "Balduvian Bears", 1);
addCard(Zone.LIBRARY, playerB, "Kitesail Corsair", 1);
//
// While you're searching your library, you may cast Panglacial Wurm from your library.
addCard(Zone.LIBRARY, playerA, "Panglacial Wurm", 1); // {5}{G}{G}
addCard(Zone.BATTLEFIELD, playerA, "Panglacial Wurm", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 7);
//
// Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
addCard(Zone.HAND, playerA, "Buried Alive", 1); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
//
// before
checkGraveyardCount("before a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkGraveyardCount("before b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
// search as normal and cast
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Buried Alive");
setChoice(playerA, "Yes"); // yes, try to cast a creature card from lib
setChoice(playerA, "Panglacial Wurm"); // try to cast
addTarget(playerA, "Balduvian Bears"); // choice for searching
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// after
checkGraveyardCount("after a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
checkGraveyardCount("after b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
checkPermanentCount("must cast Panglacial Wurm", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Panglacial Wurm", 2);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
}
@Test
@Ignore // unsupported by unit tests, see test_UnderControlMustUseTestCommandsCorrectrly
public void test_CastCardWhileSearchingLibrary_TakeControl() {
/*
[test control manually]
// use case: login by p1 and p2 clients, cast Buried Alive -> control under p2 -> try cast Panglacial Wurm and search for Balduvian Bears
library:p1:Balduvian Bears:1
library:p2:Kitesail Corsair:1
library:p1:Panglacial Wurm:1
battlefield:p1:Panglacial Wurm:1
battlefield:p1:Forest:7
hand:p1:Buried Alive:1
battlefield:p1:Swamp:3
battlefield:p2:Opposition Agent:1
*/
removeAllCardsFromLibrary(playerA);
removeAllCardsFromLibrary(playerB);
addCard(Zone.LIBRARY, playerA, "Balduvian Bears", 1);
addCard(Zone.LIBRARY, playerB, "Kitesail Corsair", 1);
//
// While you're searching your library, you may cast Panglacial Wurm from your library.
addCard(Zone.LIBRARY, playerA, "Panglacial Wurm", 1); // {5}{G}{G}
addCard(Zone.BATTLEFIELD, playerA, "Panglacial Wurm", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 7);
//
// Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
addCard(Zone.HAND, playerA, "Buried Alive", 1); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
// before
checkGraveyardCount("before a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkGraveyardCount("before b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
// search under control of B and cast under B too
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Buried Alive");
setChoice(playerB, "Yes"); // continue
setChoice(playerB, "Yes"); // yes, try to cast a creature card from lib
setChoice(playerB, "Panglacial Wurm"); // try to cast
addTarget(playerB, "Balduvian Bears"); // choice for searching
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// after
checkGraveyardCount("after a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
checkGraveyardCount("after b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Kitesail Corsair", 0);
checkPermanentCount("must cast Panglacial Wurm", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Panglacial Wurm", 2);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
}
@Test
@Ignore
// TODO: current "take player under control" implemented in GameController and HumanPlayer,
// not "game part" - so tests and AI ignore it and must be tested manually
// see another problems with control in HumanPlayer.priority(Game game) and https://github.com/magefree/mage/issues/2088
public void test_UnderControlMustUseTestCommandsCorrectrly() {
// {4}, {T}, Sacrifice Mindslaver: You control target player during that player's next turn.
addCard(Zone.BATTLEFIELD, playerA, "Mindslaver", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
//
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
// activate and take control
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}, {T}");
addTarget(playerA, playerB);
// check control
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt");
addTarget(playerA, playerB);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
}
@Test
public void test_OppositionAgent() {
// You control your opponents while theyre searching their libraries.
// While an opponent is searching their library, they exile each card they find. You may play those cards
// for as long as they remain exiled, and you may spend mana as though it were mana of any color to cast them.
addCard(Zone.BATTLEFIELD, playerB, "Opposition Agent", 1);
//
// Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
addCard(Zone.HAND, playerA, "Buried Alive", 1); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
//
addCard(Zone.LIBRARY, playerA, "Balduvian Bears", 1); // {1}{G}
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2); // B can cast green bear for red mana
// before
checkPermanentCount("before a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkPermanentCount("before b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Balduvian Bears", 0);
// start searching under B (bears must go to exile instead graveyard)
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Buried Alive");
setChoice(playerB, "Yes"); // continue after new control
addTarget(playerB, "Balduvian Bears");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkGraveyardCount("after grave a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkGraveyardCount("after grave b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Balduvian Bears", 0);
checkExileCount("after exile a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
checkExileCount("after exile b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Balduvian Bears", 0);
// B can cast green bear for red mana
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Balduvian Bears");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerB, "Balduvian Bears", 1);
}
}

View file

@ -1302,7 +1302,7 @@ public class TestPlayer implements Player {
printStart("Permanents of " + player.getName());
printPermanents(game, game.getBattlefield().getAllActivePermanents(player.getId()));
printEnd();
Assert.fail(action.getActionName() + " - permanent " + permanentName + " must exists in " + count + " instances");
Assert.fail(action.getActionName() + " - permanent " + permanentName + " must exists in " + count + " instances, but founded " + foundedCount);
}
}
@ -2526,7 +2526,8 @@ public class TestPlayer implements Player {
this.chooseStrictModeFailed("choice", game, getInfo(source, game)
+ "\nMessage: " + message
+ "\nChoices: " + (trueText != null ? trueText : "Yes") + " - " + (falseText != null ? falseText : "No"));
+ "\nChoices: " + (trueText != null ? trueText : "Yes") + " - " + (falseText != null ? falseText : "No")
+ ((trueText != null || falseText != null) ? "\nUse Yes/No in unit tests for text choices." : ""));
return computerPlayer.chooseUse(outcome, message, secondMessage, trueText, falseText, source, game);
}