other: reworked target selection (now it use same logic and methods in all places), fixed AI and selection freezes in some use cases (related to #13606, #11285)

This commit is contained in:
Oleg Agafonov 2025-05-07 17:34:36 +04:00
parent 62aa310a4f
commit a53eb66b58
10 changed files with 133 additions and 53 deletions

View file

@ -15,6 +15,11 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*/
public class SaddleTest extends CardTestPlayerBase {
/**
* Whenever Quilled Charger attacks while saddled, it gets +1/+2 and gains menace until end of turn.
* <p>
* Saddle 2
*/
private static final String charger = "Quilled Charger";
private static final String bear = "Grizzly Bears";
@ -47,29 +52,35 @@ public class SaddleTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, charger);
addCard(Zone.BATTLEFIELD, playerA, bear);
setChoice(playerA, bear);
// turn 1 - saddle and trigger on attack
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Saddle");
setChoice(playerA, bear);
attack(1, playerA, charger, playerB);
runCode("on saddle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, (info, player, game) -> {
assertTapped(bear, true);
assertTapped(charger, true);
assertSaddled(charger, true);
assertAbility(playerA, charger, new MenaceAbility(false), true);
assertLife(playerB, 20 - 4 - 1);
});
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertTapped(bear, true);
assertTapped(charger, true);
assertSaddled(charger, true);
assertAbility(playerA, charger, new MenaceAbility(false), true);
assertLife(playerB, 20 - 4 - 1);
setStopAt(2, PhaseStep.UPKEEP);
execute();
// turn 2 - saddle ends
assertSaddled(charger, false);
}
/**
* Whenever Rambling Possum attacks while saddled, it gains +1/+2 until end of turn. Then you may return any number
* of creatures that saddled it this turn to their owner's hand.
* <p>
* Saddle 1
*/
private static final String possum = "Rambling Possum";
private static final String lion = "Silvercoat Lion";
private static final String elf = "Arbor Elf";
@Test
public void testSaddledThisTurn() {
@ -77,11 +88,11 @@ public class SaddleTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, bear);
addCard(Zone.BATTLEFIELD, playerA, lion);
setChoice(playerA, bear);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Saddle");
setChoice(playerA, bear); // to saddle cost
attack(1, playerA, possum, playerB);
setChoice(playerA, bear);
setChoice(playerA, bear); // to return
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
@ -100,19 +111,17 @@ public class SaddleTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, possum);
addCard(Zone.BATTLEFIELD, playerA, bear);
addCard(Zone.BATTLEFIELD, playerA, lion);
addCard(Zone.BATTLEFIELD, playerA, elf);
setChoice(playerA, bear);
// turn 1 - saddle x2 and trigger on attack
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Saddle");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
setChoice(playerA, bear + "^" + lion);
attack(1, playerA, possum, playerB);
setChoice(playerA, lion);
setChoice(playerA, elf); // to return (try to choose a wrong creature, so game must not allow to choose it)
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
// TODO: test framework must have tools to check targeting (as workaround try to check it by look at test command error)
try {
execute();
@ -123,7 +132,8 @@ public class SaddleTest extends CardTestPlayerBase {
}
assertTapped(bear, true);
assertTapped(lion, false);
assertTapped(lion, true);
assertTapped(elf, false);
assertTapped(possum, true);
assertSaddled(possum, true);
}

View file

@ -136,6 +136,8 @@ public class SearchNameExileTests extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "fused Ready // Willing");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Test of Talents", "Ready // Willing", "Ready // Willing");
// TODO: a non strict cause a good AI choice test - make strict and duplicate as really AI test?
// in non strict mode AI must choose as much as possible in good "up to" target and half in bad target
setStrictChooseMode(false);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

View file

@ -144,7 +144,9 @@ public class SacredGroundTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Molten Rain", "Caves of Koilos");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Surgical Extraction", "Caves of Koilos");
setChoice(playerA, true); // Pay 2 life instead of {B}
//setStrictChooseMode(true); TODO: good example of AI choices, so add new AI test instead non strict here
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

View file

@ -2335,12 +2335,17 @@ public class TestPlayer implements Player {
}
}
if (!targetFound) {
//failOnLastBadChoice(game, source, target, choiceRecord, "unknown or can't target");
}
try {
if (target.isChosen(game)) {
return true;
} else {
// TODO: move check above and fix all fail tests (not after target.isChosen)
if (!targetFound) {
failOnLastBadChoice(game, source, target, choiceRecord, "unknown or can't target");
failOnLastBadChoice(game, source, target, choiceRecord, "selected, but not all required targets");
}
}
} finally {