other: reworked target selection: (#13638)

- WIP: AI and multi targets, human and X=0 use cases, human and impossible targets use cases;
- improved stability and shared logic (related to #13606, #11134, #11666, continue from a53eb66b58, close #13617, close #13613);
- improved test logs and debug info to show more target info on errors;
- improved test framework to support multiple addTarget calls;
- improved test framework to find bad commands order for targets (related to #11666);
- fixed game freezes on auto-choice usages with disconnected or under control players (related to #11285);
- gui, game: fixed that player doesn't mark avatar as selected/green in "up to" targeting;
- gui, game: fixed small font in some popup messages on big screens (related to #969);
- gui, game: added min targets info for target selection dialog;
- for devs: added new cheat option to call and test any game dialog (define own dialogs, targets, etc in HumanDialogsTester);
- for devs: now tests require complete an any or up to target selection by addTarget + TestPlayer.TARGET_SKIP or setChoice + TestPlayer.CHOICE_SKIP (if not all max/possible targets used);
- for devs: added detail targets info for activate/trigger/cast, can be useful to debug unit tests, auto-choose or AI (see DebugUtil.GAME_SHOW_CHOOSE_TARGET_LOGS)
This commit is contained in:
Oleg Agafonov 2025-05-16 13:55:54 +04:00 committed by GitHub
parent 80d62727e1
commit 133e4fe425
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
84 changed files with 2737 additions and 743 deletions

View file

@ -28,6 +28,7 @@ import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import mage.util.MultiAmountMessage;
import mage.util.RandomUtil;
import mage.utils.testers.TestableDialogsRunner;
import java.io.File;
import java.lang.reflect.Constructor;
@ -69,6 +70,7 @@ public final class SystemUtil {
private static final String COMMAND_LANDS_ADD_TO_BATTLEFIELD = "@lands add";
private static final String COMMAND_UNDER_CONTROL_TAKE = "@under control take";
private static final String COMMAND_UNDER_CONTROL_GIVE = "@under control give";
private static final String COMMAND_SHOW_TEST_DIALOGS = "@show dialog";
private static final String COMMAND_MANA_ADD = "@mana add"; // TODO: not implemented
private static final String COMMAND_RUN_CUSTOM_CODE = "@run custom code"; // TODO: not implemented
private static final String COMMAND_SHOW_OPPONENT_HAND = "@show opponent hand";
@ -76,6 +78,7 @@ public final class SystemUtil {
private static final String COMMAND_SHOW_MY_HAND = "@show my hand";
private static final String COMMAND_SHOW_MY_LIBRARY = "@show my library";
private static final Map<String, String> supportedCommands = new HashMap<>();
private static final TestableDialogsRunner testableDialogsRunner = new TestableDialogsRunner(); // for tests
static {
// special commands names in choose dialog
@ -89,6 +92,7 @@ public final class SystemUtil {
supportedCommands.put(COMMAND_SHOW_OPPONENT_LIBRARY, "SHOW OPPONENT LIBRARY");
supportedCommands.put(COMMAND_SHOW_MY_HAND, "SHOW MY HAND");
supportedCommands.put(COMMAND_SHOW_MY_LIBRARY, "SHOW MY LIBRARY");
supportedCommands.put(COMMAND_SHOW_TEST_DIALOGS, "SHOW TEST DIALOGS");
}
private static final Pattern patternGroup = Pattern.compile("\\[(.+)\\]"); // [test new card]
@ -263,8 +267,13 @@ public final class SystemUtil {
public static void executeCheatCommands(Game game, String commandsFilePath, Player feedbackPlayer) {
// fake test ability for triggers and events
Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards"));
Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("fake ability"));
fakeSourceAbilityTemplate.setControllerId(feedbackPlayer.getId());
Card fakeSourceCard = feedbackPlayer.getLibrary().getFromTop(game);
if (fakeSourceCard != null) {
// set any existing card as source, so dialogs will show all GUI elements, including source and workable popup info
fakeSourceAbilityTemplate.setSourceId(fakeSourceCard.getId());
}
List<String> errorsList = new ArrayList<>();
try {
@ -304,8 +313,9 @@ public final class SystemUtil {
// add default commands
initLines.add(0, String.format("[%s]", COMMAND_LANDS_ADD_TO_BATTLEFIELD));
initLines.add(1, String.format("[%s]", COMMAND_CARDS_ADD_TO_HAND));
initLines.add(2, String.format("[%s]", COMMAND_UNDER_CONTROL_TAKE));
initLines.add(3, String.format("[%s]", COMMAND_UNDER_CONTROL_GIVE));
initLines.add(2, String.format("[%s]", COMMAND_SHOW_TEST_DIALOGS));
initLines.add(3, String.format("[%s]", COMMAND_UNDER_CONTROL_TAKE));
initLines.add(4, String.format("[%s]", COMMAND_UNDER_CONTROL_GIVE));
// collect all commands
CommandGroup currentGroup = null;
@ -538,6 +548,11 @@ public final class SystemUtil {
break;
}
case COMMAND_SHOW_TEST_DIALOGS: {
testableDialogsRunner.selectAndShowTestableDialog(feedbackPlayer, fakeSourceAbilityTemplate.copy(), game, opponent);
break;
}
default: {
String mes = String.format("Unknown system command: %s", runGroup.name);
errorsList.add(mes);