refactor: TargetCreatureOrPlayer inheritance (#13199)

* update TargetCreatureOrPlayer to be a subclass of TargetPermanentOrPlayer

closes #11161

* fix usages
This commit is contained in:
xenohedron 2025-01-08 22:47:36 -05:00 committed by GitHub
parent 41b9c95be9
commit 9c5c394c75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 10 additions and 340 deletions

View file

@ -311,37 +311,6 @@ public class ComputerPlayer extends PlayerImpl {
} }
} }
if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer origTarget = (TargetCreatureOrPlayer) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (target.canTarget(abilityControllerId, permanent.getId(), null, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
}
}
}
if (outcome.isGood()) {
if (target.canTarget(abilityControllerId, abilityControllerId, null, game)) {
target.add(abilityControllerId, game);
return true;
}
} else if (target.canTarget(abilityControllerId, randomOpponentId, null, game)) {
target.add(randomOpponentId, game);
return true;
}
if (!required) {
return false;
}
}
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) { if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
List<Permanent> targets; List<Permanent> targets;
TargetPermanentOrPlayer origTarget = (TargetPermanentOrPlayer) target.getOriginalTarget(); TargetPermanentOrPlayer origTarget = (TargetPermanentOrPlayer) target.getOriginalTarget();
@ -752,48 +721,6 @@ public class ComputerPlayer extends PlayerImpl {
return target.isChosen(game); return target.isChosen(game);
} }
if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
List<Permanent> targets;
TargetCreatureOrPlayer origTarget = ((TargetCreatureOrPlayer) target.getOriginalTarget());
if (outcome.isGood()) {
targets = threats(abilityControllerId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
if (outcome.isGood()) {
if (target.canTarget(abilityControllerId, abilityControllerId, source, game)) {
return tryAddTarget(target, abilityControllerId, source, game);
}
} else if (target.canTarget(abilityControllerId, randomOpponentId, source, game)) {
return tryAddTarget(target, randomOpponentId, source, game);
}
}
if (targets.isEmpty() && target.isRequired(source)) {
targets = game.getBattlefield().getActivePermanents(((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), playerId, game);
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
return tryAddTarget(target, permanent.getId(), source, game);
}
}
}
if (outcome.isGood()) {
if (target.canTarget(abilityControllerId, abilityControllerId, source, game)) {
return tryAddTarget(target, abilityControllerId, source, game);
}
} else if (target.canTarget(abilityControllerId, randomOpponentId, source, game)) {
return tryAddTarget(target, randomOpponentId, source, game);
}
return false;
}
if (target.getOriginalTarget() instanceof TargetAnyTarget) { if (target.getOriginalTarget() instanceof TargetAnyTarget) {
List<Permanent> targets; List<Permanent> targets;
TargetAnyTarget origTarget = ((TargetAnyTarget) target.getOriginalTarget()); TargetAnyTarget origTarget = ((TargetAnyTarget) target.getOriginalTarget());

View file

@ -1,7 +1,5 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -14,7 +12,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.common.FilterCreatureOrPlayer;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
@ -22,8 +19,9 @@ import mage.game.permanent.token.TIEFighterToken;
import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreatureOrPlayer;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author Styxo * @author Styxo
*/ */
public final class StarDestroyer extends CardImpl { public final class StarDestroyer extends CardImpl {
@ -33,7 +31,7 @@ public final class StarDestroyer extends CardImpl {
static { static {
filter1.add(CardType.ARTIFACT.getPredicate()); filter1.add(CardType.ARTIFACT.getPredicate());
filter3.getCreatureFilter().add(Predicates.not(SubType.STARSHIP.getPredicate())); filter3.getPermanentFilter().add(Predicates.not(SubType.STARSHIP.getPredicate()));
} }
public StarDestroyer(UUID ownerId, CardSetInfo setInfo) { public StarDestroyer(UUID ownerId, CardSetInfo setInfo) {

View file

@ -1,6 +1,5 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.SacrificeSourceCost;
@ -10,24 +9,22 @@ import mage.abilities.keyword.SpaceflightAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.common.FilterCreatureOrPlayer;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetCreatureOrPlayer;
import java.util.UUID;
/** /**
*
* @author NinthWorld * @author NinthWorld
*/ */
public final class ThermalDetonator extends CardImpl { public final class ThermalDetonator extends CardImpl {
private static final FilterCreatureOrPlayer filter = new FilterCreatureOrPlayer("creature without spaceflight or target player"); private static final FilterCreatureOrPlayer filter = new FilterCreatureOrPlayer("creature without spaceflight or target player");
private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent();
static { static {
filter.getCreatureFilter().add(Predicates.not(new AbilityPredicate(SpaceflightAbility.class))); filter.getPermanentFilter().add(Predicates.not(new AbilityPredicate(SpaceflightAbility.class)));
} }
public ThermalDetonator(UUID ownerId, CardSetInfo setInfo) { public ThermalDetonator(UUID ownerId, CardSetInfo setInfo) {

View file

@ -2286,13 +2286,10 @@ public class TestPlayer implements Player {
// TODO: Allow to choose a player with TargetPermanentOrPlayer // TODO: Allow to choose a player with TargetPermanentOrPlayer
if ((target.getOriginalTarget() instanceof TargetPermanent) if ((target.getOriginalTarget() instanceof TargetPermanent)
|| (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) // player target not implemented yet
|| (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)) { // player target not implemented yet || (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)) { // player target not implemented yet
FilterPermanent filterPermanent; FilterPermanent filterPermanent;
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) { if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
filterPermanent = ((TargetPermanentOrPlayer) target.getOriginalTarget()).getFilterPermanent(); filterPermanent = ((TargetPermanentOrPlayer) target.getOriginalTarget()).getFilterPermanent();
} else if (target.getOriginalTarget() instanceof TargetCreatureOrPlayer) {
filterPermanent = ((TargetCreatureOrPlayer) target.getOriginalTarget()).getFilterCreature();
} else { } else {
filterPermanent = ((TargetPermanent) target.getOriginalTarget()).getFilter(); filterPermanent = ((TargetPermanent) target.getOriginalTarget()).getFilter();
} }
@ -2516,8 +2513,6 @@ public class TestPlayer implements Player {
// player // player
if (target.getOriginalTarget() instanceof TargetPlayer if (target.getOriginalTarget() instanceof TargetPlayer
|| target.getOriginalTarget() instanceof TargetAnyTarget
|| target.getOriginalTarget() instanceof TargetCreatureOrPlayer
|| target.getOriginalTarget() instanceof TargetPermanentOrPlayer) { || target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
for (String targetDefinition : targets.stream().limit(takeMaxTargetsPerChoose).collect(Collectors.toList())) { for (String targetDefinition : targets.stream().limit(takeMaxTargetsPerChoose).collect(Collectors.toList())) {
if (!targetDefinition.startsWith("targetPlayer=")) { if (!targetDefinition.startsWith("targetPlayer=")) {
@ -2539,8 +2534,6 @@ public class TestPlayer implements Player {
// permanent in battlefield // permanent in battlefield
if ((target.getOriginalTarget() instanceof TargetPermanent) if ((target.getOriginalTarget() instanceof TargetPermanent)
|| (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) || (target.getOriginalTarget() instanceof TargetPermanentOrPlayer)
|| (target.getOriginalTarget() instanceof TargetAnyTarget)
|| (target.getOriginalTarget() instanceof TargetCreatureOrPlayer)
|| (target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard)) { || (target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard)) {
for (String targetDefinition : targets.stream().limit(takeMaxTargetsPerChoose).collect(Collectors.toList())) { for (String targetDefinition : targets.stream().limit(takeMaxTargetsPerChoose).collect(Collectors.toList())) {
if (targetDefinition.startsWith("targetPlayer=")) { if (targetDefinition.startsWith("targetPlayer=")) {
@ -2564,9 +2557,6 @@ public class TestPlayer implements Player {
} }
} }
Filter filter = target.getOriginalTarget().getFilter(); Filter filter = target.getOriginalTarget().getFilter();
if (filter instanceof FilterCreatureOrPlayer) {
filter = ((FilterCreatureOrPlayer) filter).getCreatureFilter();
}
if (filter instanceof FilterPermanentOrPlayer) { if (filter instanceof FilterPermanentOrPlayer) {
filter = ((FilterPermanentOrPlayer) filter).getPermanentFilter(); filter = ((FilterPermanentOrPlayer) filter).getPermanentFilter();
} }

View file

@ -1,79 +1,22 @@
package mage.filter.common; package mage.filter.common;
import mage.MageItem;
import mage.abilities.Ability;
import mage.filter.FilterImpl;
import mage.filter.FilterInPlay;
import mage.filter.FilterPlayer; import mage.filter.FilterPlayer;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class FilterCreatureOrPlayer extends FilterImpl<MageItem> implements FilterInPlay<MageItem> { public class FilterCreatureOrPlayer extends FilterPermanentOrPlayer {
protected FilterCreaturePermanent creatureFilter;
protected final FilterPlayer playerFilter;
public FilterCreatureOrPlayer() { public FilterCreatureOrPlayer() {
this("creature or player"); this("creature or player");
} }
public FilterCreatureOrPlayer(String name) { public FilterCreatureOrPlayer(String name) {
super(name); super(name, new FilterCreaturePermanent(), new FilterPlayer());
creatureFilter = new FilterCreaturePermanent();
playerFilter = new FilterPlayer();
} }
protected FilterCreatureOrPlayer(final FilterCreatureOrPlayer filter) { protected FilterCreatureOrPlayer(final FilterCreatureOrPlayer filter) {
super(filter); super(filter);
this.creatureFilter = filter.creatureFilter.copy();
this.playerFilter = filter.playerFilter.copy();
}
@Override
public boolean checkObjectClass(Object object) {
return true;
}
@Override
public boolean match(MageItem o, Game game) {
if (super.match(o, game)) {
if (o instanceof Player) {
return playerFilter.match((Player) o, game);
} else if (o instanceof Permanent) {
return creatureFilter.match((Permanent) o, game);
}
}
return false;
}
@Override
public boolean match(MageItem o, UUID playerId, Ability source, Game game) {
if (super.match(o, game)) { // process predicates
if (o instanceof Player) {
return playerFilter.match((Player) o, playerId, source, game);
} else if (o instanceof Permanent) {
return creatureFilter.match((Permanent) o, playerId, source, game);
}
}
return false;
}
public FilterCreaturePermanent getCreatureFilter() {
return this.creatureFilter;
}
public FilterPlayer getPlayerFilter() {
return this.playerFilter;
}
public void setCreatureFilter(FilterCreaturePermanent creatureFilter) {
this.creatureFilter = creatureFilter;
} }
@Override @Override

View file

@ -1,26 +1,11 @@
package mage.target.common; package mage.target.common;
import mage.MageObject;
import mage.abilities.Ability;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.common.FilterCreatureOrPlayer;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetImpl;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class TargetCreatureOrPlayer extends TargetImpl { public class TargetCreatureOrPlayer extends TargetPermanentOrPlayer {
protected FilterCreatureOrPlayer filter;
public TargetCreatureOrPlayer() { public TargetCreatureOrPlayer() {
this(1, 1, new FilterCreatureOrPlayer()); this(1, 1, new FilterCreatureOrPlayer());
@ -31,178 +16,11 @@ public class TargetCreatureOrPlayer extends TargetImpl {
} }
public TargetCreatureOrPlayer(int minNumTargets, int maxNumTargets, FilterCreatureOrPlayer filter) { public TargetCreatureOrPlayer(int minNumTargets, int maxNumTargets, FilterCreatureOrPlayer filter) {
this.minNumberOfTargets = minNumTargets; super(minNumTargets, maxNumTargets, filter, false);
this.maxNumberOfTargets = maxNumTargets;
this.zone = Zone.ALL;
this.filter = filter;
this.targetName = filter.getMessage();
} }
protected TargetCreatureOrPlayer(final TargetCreatureOrPlayer target) { protected TargetCreatureOrPlayer(final TargetCreatureOrPlayer target) {
super(target); super(target);
this.filter = target.filter.copy();
}
@Override
public Filter getFilter() {
return this.filter;
}
@Override
public boolean canTarget(UUID id, Game game) {
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
return filter.match(permanent, game);
}
Player player = game.getPlayer(id);
return filter.match(player, game);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
return canTarget(source.getControllerId(), id, source, game);
}
@Override
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
Permanent permanent = game.getPermanent(id);
Player player = game.getPlayer(id);
if (source != null) {
MageObject targetSource = game.getObject(source);
if (permanent != null) {
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), source, game) && filter.match(permanent, source.getControllerId(), source, game);
}
if (player != null) {
return player.canBeTargetedBy(targetSource, source.getControllerId(), source, game) && filter.match(player, game);
}
}
if (permanent != null) {
return filter.match(permanent, game);
}
return filter.match(player, game);
}
/**
* Checks if there are enough {@link Permanent} or {@link Player} that can
* be chosen. Should only be used for Ability targets since this checks for
* protection, shroud etc.
*
* @param sourceControllerId - controller of the target event source
* @param source
* @param game
* @return - true if enough valid {@link Permanent} or {@link Player} exist
*/
@Override
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
int count = 0;
MageObject targetSource = game.getObject(source);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(player, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
return false;
}
/**
* Checks if there are enough {@link Permanent} or {@link Player} that can
* be selected. Should not be used for Ability targets since this does not
* check for protection, shroud etc.
*
* @param sourceControllerId - controller of the select event
* @param game
* @return - true if enough valid {@link Permanent} or {@link Player} exist
*/
@Override
public boolean canChoose(UUID sourceControllerId, Game game) {
int count = 0;
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (filter.match(player, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
if (filter.match(permanent, sourceControllerId, null, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
return false;
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
MageObject targetSource = game.getObject(source);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null
&& player.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& filter.getPlayerFilter().match(player, sourceControllerId, source, game)) {
possibleTargets.add(playerId);
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& filter.getCreatureFilter().match(permanent, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId());
}
}
return possibleTargets;
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && filter.getPlayerFilter().match(player, game)) {
possibleTargets.add(playerId);
}
}
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
if (filter.getCreatureFilter().match(permanent, sourceControllerId, null, game)) {
possibleTargets.add(permanent.getId());
}
}
return possibleTargets;
}
@Override
public String getTargetedName(Game game) {
StringBuilder sb = new StringBuilder();
for (UUID targetId : getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent != null) {
sb.append(permanent.getLogName()).append(' ');
} else {
Player player = game.getPlayer(targetId);
if (player != null) {
sb.append(player.getLogName()).append(' ');
}
}
}
return sb.toString().trim();
} }
@Override @Override
@ -210,7 +28,4 @@ public class TargetCreatureOrPlayer extends TargetImpl {
return new TargetCreatureOrPlayer(this); return new TargetCreatureOrPlayer(this);
} }
public FilterCreaturePermanent getFilterCreature() {
return filter.getCreatureFilter().copy();
}
} }