mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
* game: now all playable calculations done in game simulation, outside real game (no more freeze and ruined games by wrong Nyxbloom Ancient and other cards with wrong replacement dialog); * game: fixed multiple problems with triggers (wrong order, duplicated calls or "too many mana" bugs, see #8426, #12087); * tests: added data integrity checks for game's triggers (3 enabled and 3 disabled due current game engine logic);
This commit is contained in:
parent
f68e435fc4
commit
e8e2f23284
23 changed files with 362 additions and 120 deletions
|
|
@ -53,9 +53,10 @@ public class TappedForManaFromMultipleEffects extends CardTestPlayerBase {
|
|||
// cast nyx 2
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nyxbloom Ancient");
|
||||
// TODO: TAPPED_FOR_MANA replace event called from checkTappedForManaReplacement and start to choose replace events (is that problem?)
|
||||
// TODO: yes, it's a problem, cause playable calc must not use dialogs!!!
|
||||
// use case (that test): comment one 1-2 choices to fail in 1-2 calls
|
||||
setChoice(playerA, "Nyxbloom Ancient"); // getPlayable... checkTappedForManaReplacement... chooseReplacementEffect
|
||||
setChoice(playerA, "Nyxbloom Ancient"); // playManaAbility... resolve... checkToFirePossibleEvents... chooseReplacementEffect
|
||||
setChoice(playerA, "Nyxbloom Ancient"); // x2 replacement effects from x2 nyx
|
||||
//setChoice(playerA, "Nyxbloom Ancient"); // wrongly choice from playable calc - no need after bug fix
|
||||
|
||||
// cast chloro
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Chlorophant");
|
||||
|
|
|
|||
|
|
@ -11,15 +11,48 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
import static org.mage.test.utils.ManaOptionsTestUtils.assertManaOptions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_SasayasEssence_SimpleManaCalculation() {
|
||||
addCard(Zone.HAND, playerA, "Plains", 7);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
|
||||
// Reveal your hand: If you have seven or more land cards in your hand, flip Sasaya, Orochi Ascendant.
|
||||
// Sasaya's Essence: Legendary Enchantment
|
||||
// Whenever a land you control is tapped for mana, for each other land you control with the same name, add one mana of any type that land produced.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Sasaya, Orochi Ascendant", 1);
|
||||
//
|
||||
// Mana pools don't empty as steps and phases end.
|
||||
addCard(Zone.HAND, playerA, "Upwelling", 1); // Enchantment {3}{G}
|
||||
//
|
||||
// At the beginning of your upkeep, you gain 1 life.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Fountain of Renewal", 1);
|
||||
|
||||
// prepare Sasaya's Essence
|
||||
checkPermanentCount("before prepare", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sasaya's Essence", 0);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reveal your hand: If you have seven or more land cards in your hand, flip");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after prepare", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sasaya's Essence", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
// possible error: additional triggers from neutral card can break mana triggers and will calc wrong mana
|
||||
// reason: random triggers order on triggers iterator, can be fixed by linked map usage
|
||||
// x3 forest + x2 for each other forest
|
||||
ManaOptions manaOptions = playerA.getManaAvailable(currentGame);
|
||||
assertManaOptions("{G}{G}{G}" + "{G}{G}" + "{G}{G}" + "{G}{G}", manaOptions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSasayasEssence() {
|
||||
addCard(Zone.HAND, playerA, "Plains", 7);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Fountain of Renewal", 5);
|
||||
|
||||
// Reveal your hand: If you have seven or more land cards in your hand, flip Sasaya, Orochi Ascendant.
|
||||
// Sasaya's Essence: Legendary Enchantment
|
||||
|
|
@ -123,7 +156,7 @@ public class SasayaOrochiAscendantTest extends CardTestPlayerBase {
|
|||
assertManaOptions("{R}{R}{R}{R}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{R}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
assertManaOptions("{R}{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public class ValkiGodOfLiesTest extends CardTestPlayerBase {
|
|||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+2: Exile the top card of each player's library.");
|
||||
playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Plains");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Ephemerate", "Grizzly Bears");
|
||||
setChoice(playerA, "Emblem Tibalt");
|
||||
//setChoice(playerA, "Emblem Tibalt"); // wrongly x2 replacement effects - no need after bug fix
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
|
||||
/**
|
||||
* 3BG Legendary Creature - Frog Horror Deathtouch
|
||||
*
|
||||
* <p>
|
||||
* At the beginning of your upkeep, sacrifice The Gitrog Monster unless you
|
||||
* sacrifice a land.
|
||||
*
|
||||
* <p>
|
||||
* You may play an additional land on each of your turns.
|
||||
*
|
||||
* <p>
|
||||
* Whenever one or more land cards are put into your graveyard from anywhere,
|
||||
* draw a card.
|
||||
*
|
||||
|
|
@ -35,6 +35,7 @@ public class TheGitrogMonsterTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "The Gitrog Monster");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Armageddon");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.DRAW);
|
||||
execute();
|
||||
|
||||
|
|
@ -58,10 +59,10 @@ public class TheGitrogMonsterTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "The Gitrog Monster");
|
||||
// on 3rd turn during upkeep opt to sacrifice a land
|
||||
// TODO: I don't know how to get these choices to work, let the choices go automatically
|
||||
// addTarget(playerA, "Swamp");
|
||||
// setChoice(playerA, true);
|
||||
setChoice(playerA, true); // sac land
|
||||
setChoice(playerA, "Swamp"); // sac land
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.DRAW);
|
||||
execute();
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ public class TheGitrogMonsterTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "The Gitrog Monster");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Planar Outburst");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.DRAW);
|
||||
execute();
|
||||
|
||||
|
|
@ -98,7 +100,7 @@ public class TheGitrogMonsterTest extends CardTestPlayerBase {
|
|||
/**
|
||||
* NOTE: As of 05/05/2017 this test is failing due to a bug in code. See
|
||||
* issue #3251
|
||||
*
|
||||
* <p>
|
||||
* I took control of a Gitrog Monster, while the Gitrog Monster's owner
|
||||
* controlled a Dryad Arbor and cast Toxic Deluge for 6.
|
||||
*/
|
||||
|
|
@ -125,10 +127,13 @@ public class TheGitrogMonsterTest extends CardTestPlayerBase {
|
|||
addCard(Zone.GRAVEYARD, playerB, "Rags // Riches", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 7);
|
||||
|
||||
// first land
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swamp");
|
||||
// cast gitrog and second land
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "The Gitrog Monster");
|
||||
playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Dryad Arbor");
|
||||
|
||||
// change control to B, so no additional land for A
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Riches");
|
||||
setChoice(playerA, "The Gitrog Monster");
|
||||
|
||||
|
|
@ -137,6 +142,7 @@ public class TheGitrogMonsterTest extends CardTestPlayerBase {
|
|||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Toxic Deluge");
|
||||
setChoice(playerA, "X=6");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import mage.player.ai.ComputerPlayerMCTS;
|
|||
import mage.players.ManaPool;
|
||||
import mage.players.Player;
|
||||
import mage.server.game.GameSessionPlayer;
|
||||
import mage.util.ThreadUtils;
|
||||
import mage.utils.SystemUtil;
|
||||
import mage.util.CardUtil;
|
||||
import mage.view.GameView;
|
||||
|
|
@ -236,6 +237,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
throw new IllegalStateException("Game is not initialized. Use load method to load a test case and initialize a game.");
|
||||
}
|
||||
|
||||
ThreadUtils.ensureRunInGameThread();
|
||||
|
||||
// check stop command
|
||||
int maxTurn = 1;
|
||||
int maxPhase = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue