tests: fixed random fails in RadiateTest (wrong MOR predicate code, #9550)

This commit is contained in:
Oleg Agafonov 2023-09-15 06:29:51 +04:00
parent e92031a3bb
commit 6f12d62882
5 changed files with 32 additions and 10 deletions

View file

@ -122,7 +122,9 @@ class RadiateEffect extends CopySpellForEachItCouldTargetEffect {
@Override @Override
protected List<MageObjectReferencePredicate> prepareCopiesWithTargets(StackObject stackObject, Player player, Ability source, Game game) { protected List<MageObjectReferencePredicate> prepareCopiesWithTargets(StackObject stackObject, Player player, Ability source, Game game) {
List<MageObjectReferencePredicate> predicates = new ArrayList<>(); List<MageObjectReferencePredicate> predicates = new ArrayList<>();
UUID targeted = ((Spell) stackObject)
// spell must be with single target already (see filter for choose)
UUID ignoreTargeted = ((Spell) stackObject)
.getSpellAbilities() .getSpellAbilities()
.stream() .stream()
.map(AbilityImpl::getTargets) .map(AbilityImpl::getTargets)
@ -132,24 +134,29 @@ class RadiateEffect extends CopySpellForEachItCouldTargetEffect {
.filter(Objects::nonNull) .filter(Objects::nonNull)
.findAny() .findAny()
.orElse(null); .orElse(null);
// possible permanents
game.getBattlefield() game.getBattlefield()
.getActivePermanents( .getActivePermanents(
StaticFilters.FILTER_PERMANENT, player.getId(), source, game StaticFilters.FILTER_PERMANENT, player.getId(), source, game
).stream() ).stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(p -> !p.equals(game.getPermanent(targeted))) .filter(p -> !p.equals(game.getPermanent(ignoreTargeted)))
.filter(p -> stackObject.canTarget(game, p.getId())) .filter(p -> stackObject.canTarget(game, p.getId()))
.map(p -> new MageObjectReference(p, game)) .map(p -> new MageObjectReference(p, game))
.map(MageObjectReferencePredicate::new) .map(MageObjectReferencePredicate::new)
.forEach(predicates::add); .forEach(predicates::add);
// possible players
game.getState() game.getState()
.getPlayersInRange(source.getControllerId(), game) .getPlayersInRange(source.getControllerId(), game)
.stream() .stream()
.filter(uuid -> !uuid.equals(targeted)) .filter(uuid -> !uuid.equals(ignoreTargeted))
.filter(uuid -> stackObject.canTarget(game, uuid)) .filter(uuid -> stackObject.canTarget(game, uuid))
.map(MageObjectReference::new) .map(MageObjectReference::new)
.map(MageObjectReferencePredicate::new) .map(MageObjectReferencePredicate::new)
.forEach(predicates::add); .forEach(predicates::add);
return predicates; return predicates;
} }

View file

@ -26,10 +26,10 @@ public class RadiateTest extends CardTestPlayerBaseWithAIHelps {
addCard(Zone.BATTLEFIELD, playerB, "Kitesail Corsair", 2); addCard(Zone.BATTLEFIELD, playerB, "Kitesail Corsair", 2);
// cast bolt and copy spell for each another target // cast bolt and copy spell for each another target
setChoice(playerA, TestPlayer.CHOICE_SKIP); // skip stack order
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Radiate", "Lightning Bolt", "Lightning Bolt"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Radiate", "Lightning Bolt", "Lightning Bolt");
checkStackSize("before radiate", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2); checkStackSize("before radiate", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2);
setChoice(playerA, TestPlayer.CHOICE_SKIP); // skip stack order for copies
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true);
// must have: 2x for corsairs, 2x for bears, 1x for A // must have: 2x for corsairs, 2x for bears, 1x for A
checkStackSize("after radiate", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 1 + 5); checkStackSize("after radiate", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 1 + 5);
@ -46,8 +46,6 @@ public class RadiateTest extends CardTestPlayerBaseWithAIHelps {
@Test @Test
public void test_Play_AI() { public void test_Play_AI() {
// This test has trouble now but the manual version works
// Choose target instant or sorcery spell that targets only a single permanent or player. Copy that spell // Choose target instant or sorcery spell that targets only a single permanent or player. Copy that spell
// for each other permanent or player the spell could target. Each copy targets a different one of those // for each other permanent or player the spell could target. Each copy targets a different one of those
// permanents and players. // permanents and players.

View file

@ -36,6 +36,11 @@ public interface MageObject extends MageItem, Serializable, Copyable<MageObject>
String getName(); String getName();
/**
* Warning, don't use it as a key - multiple objects can have same parts of the id in rare use cases
*
* @return
*/
String getIdName(); String getIdName();
String getLogName(); String getLogName();

View file

@ -111,7 +111,7 @@ public class MageObjectReference implements Comparable<MageObjectReference>, Ser
@Override @Override
public int compareTo(MageObjectReference o) { public int compareTo(MageObjectReference o) {
if (o.getSourceId() == null || this.sourceId == null || Objects.equals(o.getSourceId(), this.sourceId)) { if (o.getSourceId() == null || this.sourceId == null || Objects.equals(o.getSourceId(), this.sourceId)) {
return o.getZoneChangeCounter() - this.zoneChangeCounter; return Integer.compare(o.getZoneChangeCounter(), this.zoneChangeCounter);
} }
return o.getSourceId().compareTo(sourceId); return o.getSourceId().compareTo(sourceId);
} }

View file

@ -38,15 +38,27 @@ public class MageObjectReferencePredicate implements Predicate<MageItem> {
} }
public String getName(Game game) { public String getName(Game game) {
UUID id = null;
String name = null;
Permanent permanent = mor.getPermanent(game); Permanent permanent = mor.getPermanent(game);
if (permanent != null) { if (permanent != null) {
return permanent.getIdName(); id = permanent.getId();
name = permanent.getName();
} }
Player player = game.getPlayer(mor.getSourceId()); Player player = game.getPlayer(mor.getSourceId());
if (player != null) { if (player != null) {
return player.getName(); id = player.getId();
name = player.getName();
}
// workaround to use unique keys for choose dialog (getIdName can't be used here)
if (id != null) {
return String.format("%s [%s]", name, id);
} else {
return null;
} }
return null;
} }
@Override @Override