mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
test framework improves:
- now game logs will show stack ability on push and on resolve (before any choices); - now game logs will show used choices made by cast/activate, setChoice, setMode and addTarget commands (not work for AI tests, part of #13832); - improved choice logic for modes and yes/not dialogs (now it's use a more strictly checks, use TestPlayer.MODE_SKIP to stop mode selection); - improved error logs and testable dialogs menu in cheat mode;
This commit is contained in:
parent
a7a6ffd6f3
commit
e866707912
17 changed files with 553 additions and 410 deletions
|
|
@ -405,13 +405,13 @@ public class ComputerPlayer6 extends ComputerPlayer {
|
|||
if (effect != null
|
||||
&& stackObject.getControllerId().equals(playerId)) {
|
||||
Target target = effect.getTarget();
|
||||
if (!target.isChoiceCompleted(getId(), (StackAbility) stackObject, game)) {
|
||||
if (!target.isChoiceCompleted(getId(), (StackAbility) stackObject, game, null)) {
|
||||
for (UUID targetId : target.possibleTargets(stackObject.getControllerId(), stackObject.getStackAbility(), game)) {
|
||||
Game sim = game.createSimulationForAI();
|
||||
StackAbility newAbility = (StackAbility) stackObject.copy();
|
||||
SearchEffect newEffect = getSearchEffect(newAbility);
|
||||
newEffect.getTarget().addTarget(targetId, newAbility, sim);
|
||||
sim.getStack().push(newAbility);
|
||||
sim.getStack().push(sim, newAbility);
|
||||
SimulationNode2 newNode = new SimulationNode2(node, sim, depth, stackObject.getControllerId());
|
||||
node.children.add(newNode);
|
||||
newNode.getTargets().add(targetId);
|
||||
|
|
@ -886,10 +886,10 @@ public class ComputerPlayer6 extends ComputerPlayer {
|
|||
}
|
||||
|
||||
UUID abilityControllerId = target.getAffectedAbilityControllerId(getId());
|
||||
if (!target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (!target.isChoiceCompleted(abilityControllerId, source, game, cards)) {
|
||||
for (UUID targetId : targets) {
|
||||
target.addTarget(targetId, source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, cards)) {
|
||||
targets.clear();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -906,10 +906,10 @@ public class ComputerPlayer6 extends ComputerPlayer {
|
|||
}
|
||||
|
||||
UUID abilityControllerId = target.getAffectedAbilityControllerId(getId());
|
||||
if (!target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (!target.isChoiceCompleted(abilityControllerId, source, game, cards)) {
|
||||
for (UUID targetId : targets) {
|
||||
target.add(targetId, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, cards)) {
|
||||
targets.clear();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public final class SimulatedPlayer2 extends ComputerPlayer {
|
|||
return list;
|
||||
}
|
||||
|
||||
protected void simulateOptions(Game game) {
|
||||
private void simulateOptions(Game game) {
|
||||
List<ActivatedAbility> playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer);
|
||||
for (ActivatedAbility ability : playables) {
|
||||
if (ability.isManaAbility()) {
|
||||
|
|
@ -176,6 +176,10 @@ public final class SimulatedPlayer2 extends ComputerPlayer {
|
|||
return options;
|
||||
}
|
||||
|
||||
// remove invalid targets
|
||||
// TODO: is it useless cause it already filtered before?
|
||||
options.removeIf(option -> !option.getTargets().isChosen(game));
|
||||
|
||||
if (AI_SIMULATE_ALL_BAD_AND_GOOD_TARGETS) {
|
||||
return options;
|
||||
}
|
||||
|
|
@ -315,7 +319,7 @@ public final class SimulatedPlayer2 extends ComputerPlayer {
|
|||
List<Ability> options = getPlayableOptions(ability, game);
|
||||
if (options.isEmpty()) {
|
||||
logger.debug("simulating -- triggered ability:" + ability);
|
||||
game.getStack().push(new StackAbility(ability, playerId));
|
||||
game.getStack().push(game, new StackAbility(ability, playerId));
|
||||
if (ability.activate(game, false) && ability.isUsesStack()) {
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId()));
|
||||
}
|
||||
|
|
@ -337,9 +341,9 @@ public final class SimulatedPlayer2 extends ComputerPlayer {
|
|||
|
||||
protected void addAbilityNode(SimulationNode2 parent, Ability ability, int depth, Game game) {
|
||||
Game sim = game.createSimulationForAI();
|
||||
sim.getStack().push(new StackAbility(ability, playerId));
|
||||
sim.getStack().push(sim, new StackAbility(ability, playerId));
|
||||
if (ability.activate(sim, false) && ability.isUsesStack()) {
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId()));
|
||||
sim.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId()));
|
||||
}
|
||||
sim.applyEffects();
|
||||
SimulationNode2 newNode = new SimulationNode2(parent, sim, depth, playerId);
|
||||
|
|
|
|||
|
|
@ -142,17 +142,27 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
UUID abilityControllerId = target.getAffectedAbilityControllerId(getId());
|
||||
|
||||
// nothing to choose, e.g. X=0
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, fromCards)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// default logic for any targets
|
||||
PossibleTargetsSelector possibleTargetsSelector = new PossibleTargetsSelector(outcome, target, abilityControllerId, source, game);
|
||||
possibleTargetsSelector.findNewTargets(fromCards);
|
||||
|
||||
// nothing to choose, e.g. no valid targets
|
||||
if (!possibleTargetsSelector.hasAnyTargets()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// can't choose
|
||||
if (!possibleTargetsSelector.hasMinNumberOfTargets()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// good targets -- choose as much as possible
|
||||
for (MageItem item : possibleTargetsSelector.getGoodTargets()) {
|
||||
target.add(item.getId(), game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, fromCards)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -226,7 +236,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
UUID abilityControllerId = target.getAffectedAbilityControllerId(getId());
|
||||
|
||||
// nothing to choose, e.g. X=0
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +248,11 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
// can't choose
|
||||
if (!possibleTargetsSelector.hasMinNumberOfTargets()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// KILL PRIORITY
|
||||
if (outcome == Outcome.Damage) {
|
||||
// opponent first
|
||||
|
|
@ -251,7 +266,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
int leftLife = PossibleTargetsComparator.getLifeForDamage(item, game);
|
||||
if (leftLife > 0 && leftLife <= target.getAmountRemaining()) {
|
||||
target.addTarget(item.getId(), leftLife, source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -268,7 +283,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
int leftLife = PossibleTargetsComparator.getLifeForDamage(item, game);
|
||||
if (leftLife > 0 && leftLife <= target.getAmountRemaining()) {
|
||||
target.addTarget(item.getId(), leftLife, source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -283,7 +298,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
continue;
|
||||
}
|
||||
target.addTarget(item.getId(), target.getAmountRemaining(), source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +318,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
int leftLife = PossibleTargetsComparator.getLifeForDamage(item, game);
|
||||
if (leftLife > 1) {
|
||||
target.addTarget(item.getId(), Math.min(leftLife - 1, target.getAmountRemaining()), source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -322,7 +337,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
return !target.getTargets().isEmpty();
|
||||
}
|
||||
target.addTarget(item.getId(), target.getAmountRemaining(), source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -339,7 +354,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
continue;
|
||||
}
|
||||
target.addTarget(item.getId(), target.getAmountRemaining(), source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -355,7 +370,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
return !target.getTargets().isEmpty();
|
||||
}
|
||||
target.addTarget(item.getId(), target.getAmountRemaining(), source, game);
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game)) {
|
||||
if (target.isChoiceCompleted(abilityControllerId, source, game, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ public class PossibleTargetsSelector {
|
|||
// collect new valid targets
|
||||
List<MageItem> found = target.possibleTargets(abilityControllerId, source, game, fromTargetsList).stream()
|
||||
.filter(id -> !target.contains(id))
|
||||
.filter(id -> target.canTarget(abilityControllerId, id, source, game))
|
||||
.map(id -> {
|
||||
Player player = game.getPlayer(id);
|
||||
if (player != null) {
|
||||
|
|
@ -137,6 +136,10 @@ public class PossibleTargetsSelector {
|
|||
}
|
||||
}
|
||||
|
||||
public List<MageItem> getAny() {
|
||||
return this.any;
|
||||
}
|
||||
|
||||
public static boolean isMyItem(UUID abilityControllerId, MageItem item) {
|
||||
if (item instanceof Player) {
|
||||
return item.getId().equals(abilityControllerId);
|
||||
|
|
@ -181,7 +184,12 @@ public class PossibleTargetsSelector {
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean hasAnyTargets() {
|
||||
public boolean hasAnyTargets() {
|
||||
return !this.any.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasMinNumberOfTargets() {
|
||||
return this.target.getMinNumberOfTargets() == 0
|
||||
|| this.any.size() >= this.target.getMinNumberOfTargets();
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
}
|
||||
}
|
||||
if (ability.isUsesStack()) {
|
||||
game.getStack().push(new StackAbility(ability, playerId));
|
||||
game.getStack().push(game, new StackAbility(ability, playerId));
|
||||
if (ability.activate(game, false)) {
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId()));
|
||||
actionCount++;
|
||||
|
|
@ -187,8 +187,8 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
abort = true;
|
||||
}
|
||||
|
||||
protected boolean chooseRandom(Target target, Game game) {
|
||||
Set<UUID> possibleTargets = target.possibleTargets(playerId, game);
|
||||
private boolean chooseRandom(Target target, Ability source, Game game) {
|
||||
Set<UUID> possibleTargets = target.possibleTargets(playerId, source, game);
|
||||
if (possibleTargets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -233,7 +233,7 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
@Override
|
||||
public boolean choose(Outcome outcome, Target target, Ability source, Game game) {
|
||||
if (this.isHuman()) {
|
||||
return chooseRandom(target, game);
|
||||
return chooseRandom(target, source, game);
|
||||
}
|
||||
return super.choose(outcome, target, source, game);
|
||||
}
|
||||
|
|
@ -241,7 +241,7 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
@Override
|
||||
public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map<String, Serializable> options) {
|
||||
if (this.isHuman()) {
|
||||
return chooseRandom(target, game);
|
||||
return chooseRandom(target, source, game);
|
||||
}
|
||||
return super.choose(outcome, target, source, game, options);
|
||||
}
|
||||
|
|
@ -252,7 +252,7 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Set<UUID> possibleTargets = target.possibleTargets(playerId, cards, source, game);
|
||||
Set<UUID> possibleTargets = target.possibleTargets(playerId, source, game, cards);
|
||||
if (possibleTargets.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue