(WIP) Replacing blocking/blocked by predicates (#8729)

* replaced blocking/blocked by predicates

* added test for knight of dusk (currently fails)

* added source parameter to filters and everything else that needs it

* some changes to various predicates

* test fix

* small changes to filter code

* merge fix

* fixed a test failure

* small change to Karn, Scion of Urza

* removed sourceId from filter methods and other similar places

* added new getobject method to fix some test failures

* a few more fixes

* fixed merge conflicts

* merge fix
This commit is contained in:
Evan Kranzler 2022-03-23 18:45:02 -04:00 committed by GitHub
parent 53877424a0
commit 80e11b2052
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1719 changed files with 3384 additions and 3325 deletions

View file

@ -396,7 +396,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
&& stackObject.getControllerId().equals(playerId)) {
Target target = effect.getTarget();
if (!target.doneChosing()) {
for (UUID targetId : target.possibleTargets(stackObject.getSourceId(), stackObject.getControllerId(), game)) {
for (UUID targetId : target.possibleTargets(stackObject.getControllerId(), stackObject.getStackAbility(), game)) {
Game sim = game.copy();
StackAbility newAbility = (StackAbility) stackObject.copy();
SearchEffect newEffect = getSearchEffect(newAbility);

View file

@ -122,12 +122,12 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
return choose(outcome, target, sourceId, game, null);
public boolean choose(Outcome outcome, Target target, Ability source, Game game) {
return choose(outcome, target, source, game, null);
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map<String, Serializable> options) {
if (log.isDebugEnabled()) {
log.debug("choose: " + outcome.toString() + ':' + target.toString());
@ -143,9 +143,10 @@ public class ComputerPlayer extends PlayerImpl implements Player {
&& target.getAbilityController() != null) {
abilityControllerId = target.getAbilityController();
}
UUID sourceId = source != null ? source.getSourceId() : null;
boolean required = target.isRequired(sourceId, game);
Set<UUID> possibleTargets = target.possibleTargets(sourceId, abilityControllerId, game);
Set<UUID> possibleTargets = target.possibleTargets(abilityControllerId, source, game);
if (possibleTargets.isEmpty() || target.getTargets().size() >= target.getNumberOfTargets()) {
required = false;
}
@ -160,7 +161,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (target.getOriginalTarget() instanceof TargetPlayer) {
return setTargetPlayer(outcome, target, null, sourceId, abilityControllerId, randomOpponentId, game, required);
return setTargetPlayer(outcome, target, null, abilityControllerId, randomOpponentId, game, required);
}
if (target.getOriginalTarget() instanceof TargetDiscard) {
@ -191,12 +192,12 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetControlledPermanent) {
List<Permanent> targets;
TargetControlledPermanent origTarget = (TargetControlledPermanent) target.getOriginalTarget();
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, origTarget.getFilter(), game, target.getTargets());
if (!outcome.isGood()) {
Collections.reverse(targets);
}
for (Permanent permanent : targets) {
if (origTarget.canTarget(abilityControllerId, permanent.getId(), sourceId, game, false) && !target.getTargets().contains(permanent.getId())) {
if (origTarget.canTarget(abilityControllerId, permanent.getId(), source, game, false) && !target.getTargets().contains(permanent.getId())) {
target.add(permanent.getId(), game);
return true;
}
@ -217,18 +218,18 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
if (outcome.isCanTargetAll()) {
targets = threats(null, sourceId, filter, game, target.getTargets());
targets = threats(null, source, filter, game, target.getTargets());
} else {
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, filter, game, target.getTargets());
targets = threats(abilityControllerId, source, filter, game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, filter, game, target.getTargets());
targets = threats(randomOpponentId, source, filter, game, target.getTargets());
}
if (targets.isEmpty() && target.isRequired()) {
if (!outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, filter, game, target.getTargets());
targets = threats(abilityControllerId, source, filter, game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, filter, game, target.getTargets());
targets = threats(randomOpponentId, source, filter, game, target.getTargets());
}
}
}
@ -257,7 +258,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetCardInHand
|| (target.getZone() == Zone.HAND && (target.getOriginalTarget() instanceof TargetCard))) {
List<Card> cards = new ArrayList<>();
for (UUID cardId : target.possibleTargets(sourceId, this.getId(), game)) {
for (UUID cardId : target.possibleTargets(this.getId(), source, game)) {
Card card = game.getCard(cardId);
if (card != null) {
cards.add(card);
@ -278,9 +279,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
TargetAnyTarget origTarget = (TargetAnyTarget) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargetted = target.getTargets();
@ -309,9 +310,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
TargetCreatureOrPlayer origTarget = (TargetCreatureOrPlayer) target.getOriginalTarget();
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
for (Permanent permanent : targets) {
List<UUID> alreadyTargeted = target.getTargets();
@ -339,8 +340,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
List<Permanent> targets;
TargetPermanentOrPlayer origTarget = (TargetPermanentOrPlayer) target.getOriginalTarget();
List<Permanent> ownedTargets = threats(abilityControllerId, sourceId, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> opponentTargets = threats(randomOpponentId, sourceId, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> ownedTargets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
List<Permanent> opponentTargets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
if (outcome.isGood()) {
targets = ownedTargets;
} else {
@ -463,7 +464,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetSource) {
Set<UUID> targets;
targets = target.possibleTargets(sourceId, abilityControllerId, game);
targets = target.possibleTargets(abilityControllerId, source, game);
for (UUID targetId : targets) {
MageObject targetObject = game.getObject(targetId);
if (targetObject != null) {
@ -517,7 +518,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
boolean required = target.isRequired(sourceId, game);
Set<UUID> possibleTargets = target.possibleTargets(sourceId, abilityControllerId, game);
Set<UUID> possibleTargets = target.possibleTargets(abilityControllerId, source, game);
if (possibleTargets.isEmpty() || target.getTargets().size() >= target.getNumberOfTargets()) {
required = false;
}
@ -537,7 +538,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
if (target.getOriginalTarget() instanceof TargetPlayer) {
return setTargetPlayer(outcome, target, source, sourceId, abilityControllerId, randomOpponentId, game, required);
return setTargetPlayer(outcome, target, source, abilityControllerId, randomOpponentId, game, required);
}
// Angel of Serenity trigger
@ -642,7 +643,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetControlledPermanent) {
TargetControlledPermanent origTarget = (TargetControlledPermanent) target.getOriginalTarget();
List<Permanent> targets;
targets = threats(abilityControllerId, sourceId, origTarget.getFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, origTarget.getFilter(), game, target.getTargets());
if (!outcome.isGood()) {
Collections.reverse(targets);
}
@ -671,7 +672,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
+ target.getOriginalTarget().getClass().getCanonicalName());
}
findBestPermanentTargets(outcome, abilityControllerId, sourceId, filter,
findBestPermanentTargets(outcome, abilityControllerId, sourceId, source, filter,
game, target, goodList, badList, allList);
// use good list all the time and add maximum targets
@ -700,9 +701,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
TargetCreatureOrPlayer origTarget = ((TargetCreatureOrPlayer) target.getOriginalTarget());
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, ((FilterCreatureOrPlayer) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -742,9 +743,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
TargetAnyTarget origTarget = ((TargetAnyTarget) target.getOriginalTarget());
if (outcome.isGood()) {
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -785,9 +786,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target.getOriginalTarget());
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty()) {
@ -823,9 +824,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
// normal cycle (good for you, bad for opponents)
// possible good/bad permanents
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
}
// possible good/bad players
@ -930,12 +931,12 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<Permanent> targets;
boolean outcomeTargets = true;
if (outcome.isGood()) {
targets = threats(abilityControllerId, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
targets = threats(abilityControllerId, source, origTarget.getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
targets = threats(randomOpponentId, source, origTarget.getPermanentFilter(), game, target.getTargets());
}
if (targets.isEmpty() && required) {
targets = threats(null, source == null ? null : source.getSourceId(), origTarget.getPermanentFilter(), game, target.getTargets());
targets = threats(null, source, origTarget.getPermanentFilter(), game, target.getTargets());
Collections.reverse(targets);
outcomeTargets = false;
}
@ -1008,7 +1009,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
List<Card> cards = new ArrayList<>();
for (UUID uuid : target.possibleTargets(source.getSourceId(), source.getControllerId(), game)) {
for (UUID uuid : target.possibleTargets(source.getControllerId(), source, game)) {
Card card = game.getCard(uuid);
if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) {
cards.add(card);
@ -1026,7 +1027,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetActivatedAbility) {
List<StackObject> stackObjects = new ArrayList<>();
for (UUID uuid : target.possibleTargets(source.getSourceId(), source.getControllerId(), game)) {
for (UUID uuid : target.possibleTargets(source.getControllerId(), source, game)) {
StackObject stackObject = game.getStack().getStackObject(uuid);
if (stackObject != null) {
stackObjects.add(stackObject);
@ -1129,7 +1130,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
// permanents kill
for (UUID opponentId : opponents) {
targets = threats(opponentId, sourceId, StaticFilters.FILTER_PERMANENT_CREATURE_OR_PLANESWALKER_A, game, target.getTargets());
targets = threats(opponentId, source, StaticFilters.FILTER_PERMANENT_CREATURE_OR_PLANESWALKER_A, game, target.getTargets());
// planeswalker kill
for (Permanent permanent : targets) {
@ -1156,9 +1157,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
// own permanents will be checked multiple times... that's ok
for (UUID opponentId : opponents) {
if (outcome.isGood()) {
targets = threats(getId(), sourceId, StaticFilters.FILTER_PERMANENT, game, target.getTargets());
targets = threats(getId(), source, StaticFilters.FILTER_PERMANENT, game, target.getTargets());
} else {
targets = threats(opponentId, sourceId, StaticFilters.FILTER_PERMANENT, game, target.getTargets());
targets = threats(opponentId, source, StaticFilters.FILTER_PERMANENT, game, target.getTargets());
}
// planeswalkers
@ -1192,9 +1193,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
for (UUID opponentId : opponents) {
if (!outcome.isGood()) {
// bad on yourself, uses weakest targets
targets = threats(getId(), sourceId, StaticFilters.FILTER_PERMANENT, game, target.getTargets(), false);
targets = threats(getId(), source, StaticFilters.FILTER_PERMANENT, game, target.getTargets(), false);
} else {
targets = threats(opponentId, sourceId, StaticFilters.FILTER_PERMANENT, game, target.getTargets(), false);
targets = threats(opponentId, source, StaticFilters.FILTER_PERMANENT, game, target.getTargets(), false);
}
// creatures - non killable (TODO: add extra skill checks like undestructeable)
@ -1989,7 +1990,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
// we still use playerId when getting cards even if they don't control the search
List<Card> cardChoices = new ArrayList<>(cards.getCards(target.getFilter(), source != null ? source.getSourceId() : null, playerId, game));
List<Card> cardChoices = new ArrayList<>(cards.getCards(target.getFilter(), playerId, source, game));
while (!target.doneChosing()) {
Card card = pickTarget(abilityControllerId, cardChoices, outcome, target, source, game);
if (card != null) {
@ -2109,7 +2110,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
continue AvailableMode;
}
}
if (mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and where targets are available
if (mode.getTargets().canChoose(source.getControllerId(), source, game)) { // and where targets are available
return mode;
}
}
@ -2694,7 +2695,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return worst;
}
protected void findBestPermanentTargets(Outcome outcome, UUID abilityControllerId, UUID sourceId, FilterPermanent filter, Game game, Target target,
protected void findBestPermanentTargets(Outcome outcome, UUID abilityControllerId, UUID sourceId, Ability source, FilterPermanent filter, Game game, Target target,
List<Permanent> goodList, List<Permanent> badList, List<Permanent> allList) {
// searching for most valuable/powerfull permanents
goodList.clear();
@ -2703,7 +2704,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
List<UUID> usedTargets = target.getTargets();
// search all
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, abilityControllerId, sourceId, game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, abilityControllerId, source, game)) {
if (usedTargets.contains(permanent.getId())) {
continue;
}
@ -2751,19 +2752,19 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
protected List<Permanent> threats(UUID playerId, UUID sourceId, FilterPermanent filter, Game game, List<UUID> targets) {
return threats(playerId, sourceId, filter, game, targets, true);
protected List<Permanent> threats(UUID playerId, Ability source, FilterPermanent filter, Game game, List<UUID> targets) {
return threats(playerId, source, filter, game, targets, true);
}
protected List<Permanent> threats(UUID playerId, UUID sourceId, FilterPermanent filter, Game game, List<UUID> targets, boolean mostValueableGoFirst) {
protected List<Permanent> threats(UUID playerId, Ability source, FilterPermanent filter, Game game, List<UUID> targets, boolean mostValueableGoFirst) {
// most valuable/powerfull permanents goes at first
List<Permanent> threats;
if (playerId == null) {
threats = game.getBattlefield().getActivePermanents(filter, this.getId(), sourceId, game); // all permanents within the range of the player
threats = game.getBattlefield().getActivePermanents(filter, this.getId(), source, game); // all permanents within the range of the player
} else {
FilterPermanent filterCopy = filter.copy();
filterCopy.add(new ControllerIdPredicate(playerId));
threats = game.getBattlefield().getActivePermanents(filter, this.getId(), sourceId, game);
threats = game.getBattlefield().getActivePermanents(filter, this.getId(), source, game);
}
Iterator<Permanent> it = threats.iterator();
while (it.hasNext()) { // remove permanents already targeted
@ -2881,7 +2882,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
*
* @param source null on choose and non-null on chooseTarget
*/
private boolean setTargetPlayer(Outcome outcome, Target target, Ability source, UUID sourceId, UUID abilityControllerId, UUID randomOpponentId, Game game, boolean required) {
private boolean setTargetPlayer(Outcome outcome, Target target, Ability source, UUID abilityControllerId, UUID randomOpponentId, Game game, boolean required) {
Outcome affectedOutcome;
if (abilityControllerId == this.playerId) {
// selects for itself
@ -2915,6 +2916,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return false;
}
UUID sourceId = source != null ? source.getSourceId() : null;
if (target.getOriginalTarget() instanceof TargetPlayer) {
if (affectedOutcome.isGood()) {
if (source == null) {

View file

@ -221,7 +221,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
}
protected boolean chooseRandomTarget(Target target, Ability source, Game game) {
Set<UUID> possibleTargets = target.possibleTargets(source == null ? null : source.getSourceId(), playerId, game);
Set<UUID> possibleTargets = target.possibleTargets(playerId, source, game);
if (possibleTargets.isEmpty()) {
return false;
}
@ -245,19 +245,19 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
public boolean choose(Outcome outcome, Target target, Ability source, Game game) {
if (this.isHuman()) {
return chooseRandom(target, game);
}
return super.choose(outcome, target, sourceId, game);
return super.choose(outcome, target, source, game);
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map<String, Serializable> options) {
if (this.isHuman()) {
return chooseRandom(target, game);
}
return super.choose(outcome, target, sourceId, game, options);
return super.choose(outcome, target, source, game, options);
}
@Override
@ -302,7 +302,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
@Override
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
Set<UUID> possibleTargets = target.possibleTargets(source == null ? null : source.getSourceId(), playerId, game);
Set<UUID> possibleTargets = target.possibleTargets(playerId, source, game);
if (possibleTargets.isEmpty()) {
return !target.isRequired(source);
}

View file

@ -235,7 +235,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements Player {
if (effect != null && ability.getControllerId().equals(playerId)) {
Target target = effect.getTarget();
if (!target.doneChosing()) {
for (UUID targetId: target.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) {
for (UUID targetId: target.possibleTargets(ability.getControllerId(), ability.getStackAbility(), game)) {
Game sim = game.copy();
StackAbility newAbility = (StackAbility) ability.copy();
SearchEffect newEffect = getSearchEffect((StackAbility) newAbility);

View file

@ -498,12 +498,12 @@ public class HumanPlayer extends PlayerImpl {
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
return choose(outcome, target, sourceId, game, null);
public boolean choose(Outcome outcome, Target target, Ability source, Game game) {
return choose(outcome, target, source, game, null);
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map<String, Serializable> options) {
if (gameInCheckPlayableState(game)) {
return true;
}
@ -519,12 +519,12 @@ public class HumanPlayer extends PlayerImpl {
}
while (canRespond()) {
Set<UUID> targetIds = target.possibleTargets(sourceId, abilityControllerId, game);
Set<UUID> targetIds = target.possibleTargets(abilityControllerId, source, game);
if (targetIds == null || targetIds.isEmpty()) {
return target.getTargets().size() >= target.getNumberOfTargets();
}
boolean required = target.isRequired(sourceId, game);
boolean required = target.isRequired(source != null ? source.getSourceId() : null, game);
if (target.getTargets().size() >= target.getNumberOfTargets()) {
required = false;
}
@ -535,7 +535,7 @@ public class HumanPlayer extends PlayerImpl {
updateGameStatePriority("choose(5)", game);
prepareForResponse(game);
if (!isExecutingMacro()) {
game.fireSelectTargetEvent(getId(), new MessageToClient(target.getMessage(), getRelatedObjectName(sourceId, game)), targetIds, required, getOptions(target, options));
game.fireSelectTargetEvent(getId(), new MessageToClient(target.getMessage(), getRelatedObjectName(source.getSourceId(), game)), targetIds, required, getOptions(target, options));
}
waitForResponse(game);
@ -554,14 +554,14 @@ public class HumanPlayer extends PlayerImpl {
}
if (target instanceof TargetPermanent) {
if (((TargetPermanent) target).canTarget(abilityControllerId, responseId, sourceId, game, false)) {
if (((TargetPermanent) target).canTarget(abilityControllerId, responseId, source, game, false)) {
target.add(responseId, game);
if (target.doneChosing()) {
return true;
}
}
} else {
MageObject object = game.getObject(sourceId);
MageObject object = game.getObject(source);
if (object instanceof Ability) {
if (target.canTarget(responseId, (Ability) object, game)) {
if (target.getTargets().contains(responseId)) { // if already included remove it with
@ -617,7 +617,7 @@ public class HumanPlayer extends PlayerImpl {
Map<String, Serializable> options = new HashMap<>();
while (canRespond()) {
Set<UUID> possibleTargets = target.possibleTargets(source == null ? null : source.getSourceId(), abilityControllerId, game);
Set<UUID> possibleTargets = target.possibleTargets(abilityControllerId, source, game);
boolean required = target.isRequired(source != null ? source.getSourceId() : null, game);
if (possibleTargets.isEmpty()
|| target.getTargets().size() >= target.getNumberOfTargets()) {
@ -845,7 +845,7 @@ public class HumanPlayer extends PlayerImpl {
// 1. Select targets
while (canRespond()) {
Set<UUID> possibleTargets = target.possibleTargets(source == null ? null : source.getSourceId(), abilityControllerId, game);
Set<UUID> possibleTargets = target.possibleTargets(abilityControllerId, source, game);
boolean required = target.isRequired(source != null ? source.getSourceId() : null, game);
if (possibleTargets.isEmpty()
|| target.getSize() >= target.getNumberOfTargets()) {
@ -979,7 +979,7 @@ public class HumanPlayer extends PlayerImpl {
FilterCreatureForCombatBlock filter = filterCreatureForCombatBlock.copy();
filter.add(new ControllerIdPredicate(playerId));
// stop skip on any/zero permanents available
int possibleBlockersCount = game.getBattlefield().count(filter, null, playerId, game);
int possibleBlockersCount = game.getBattlefield().count(filter, playerId, null, game);
boolean canStopOnAny = possibleBlockersCount != 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithAnyPermanents();
boolean canStopOnZero = possibleBlockersCount == 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithZeroPermanents();
quickStop = canStopOnAny || canStopOnZero;
@ -1605,9 +1605,9 @@ public class HumanPlayer extends PlayerImpl {
} else if (responseId != null) {
Permanent attacker = game.getPermanent(responseId);
if (attacker != null) {
if (filterCreatureForCombat.match(attacker, null, playerId, game)) {
if (filterCreatureForCombat.match(attacker, playerId, null, game)) {
selectDefender(game.getCombat().getDefenders(), attacker.getId(), game);
} else if (filterAttack.match(attacker, null, playerId, game) && game.getStack().isEmpty()) {
} else if (filterAttack.match(attacker, playerId, null, game) && game.getStack().isEmpty()) {
removeAttackerIfPossible(game, attacker);
}
}
@ -1772,7 +1772,7 @@ public class HumanPlayer extends PlayerImpl {
filter.add(new ControllerIdPredicate(defendingPlayerId));
// stop skip on any/zero permanents available
int possibleBlockersCount = game.getBattlefield().count(filter, null, playerId, game);
int possibleBlockersCount = game.getBattlefield().count(filter, playerId, source, game);
boolean canStopOnAny = possibleBlockersCount != 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithAnyPermanents();
boolean canStopOnZero = possibleBlockersCount == 0 && getControllingPlayersUserData(game).getUserSkipPrioritySteps().isStopOnDeclareBlockersWithZeroPermanents();
@ -1810,9 +1810,9 @@ public class HumanPlayer extends PlayerImpl {
if (blocker != null) {
boolean removeBlocker = false;
// does not block yet and can block or can block more attackers
if (filter.match(blocker, null, playerId, game)) {
if (filter.match(blocker, playerId, source, game)) {
selectCombatGroup(defendingPlayerId, blocker.getId(), game);
} else if (filterBlock.match(blocker, null, playerId, game)
} else if (filterBlock.match(blocker, playerId, source, game)
&& game.getStack().isEmpty()) {
removeBlocker = true;
}
@ -1892,7 +1892,7 @@ public class HumanPlayer extends PlayerImpl {
prepareForResponse(game);
if (!isExecutingMacro()) {
// possible attackers to block
Set<UUID> attackers = target.possibleTargets(null, playerId, game);
Set<UUID> attackers = target.possibleTargets(playerId, null, game);
Permanent blocker = game.getPermanent(blockerId);
Set<UUID> possibleTargets = new HashSet<>();
for (UUID attackerId : attackers) {
@ -1932,7 +1932,7 @@ public class HumanPlayer extends PlayerImpl {
if (singleTargetName != null) {
target.setTargetName(singleTargetName);
}
choose(Outcome.Damage, target, source.getSourceId(), game);
choose(Outcome.Damage, target, source, game);
if (targets.isEmpty() || targets.contains(target.getFirstTarget())) {
int damageAmount = getAmount(0, remainingDamage, "Select amount", game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
@ -2222,7 +2222,7 @@ public class HumanPlayer extends PlayerImpl {
if (modes.size() > 1) {
// done option for up to choices
boolean canEndChoice = modes.getSelectedModes().size() >= modes.getMinModes() || modes.isMayChooseNone();
MageObject obj = game.getObject(source.getSourceId());
MageObject obj = game.getObject(source);
Map<UUID, String> modeMap = new LinkedHashMap<>();
int modeIndex = 0;
AvailableModes:
@ -2242,7 +2242,7 @@ public class HumanPlayer extends PlayerImpl {
}
}
if (mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and needed targets have to be available
if (mode.getTargets().canChoose(source.getControllerId(), source, game)) { // and needed targets have to be available
String modeText = mode.getEffects().getText(mode);
if (obj != null) {
modeText = modeText.replace("{this}", obj.getName());

View file

@ -68,7 +68,7 @@ class AbeyanceEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
return "You can't cast instant or sorcery spells or activate abilities "
+ "that aren't mana abilities this turn (" + mageObject.getIdName() + ").";

View file

@ -1,7 +1,5 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
@ -9,28 +7,31 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.BlockedByIdPredicate;
import mage.filter.predicate.permanent.BlockingAttackerIdPredicate;
import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate;
import java.util.UUID;
/**
*
* @author MarcoMarin
*/
public final class AbuJafar extends CardImpl {
private static final FilterPermanent filter
= new FilterCreaturePermanent("creatures blocking or blocked by it");
static {
filter.add(BlockingOrBlockedBySourcePredicate.EITHER);
}
public AbuJafar(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(0);
this.toughness = new MageInt(1);
FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures blocking or blocked by it");
filter.add(Predicates.or(new BlockedByIdPredicate(this.getId()),
new BlockingAttackerIdPredicate(this.getId())));
// When Abu Ja'far dies, destroy all creatures blocking or blocked by it. They can't be regenerated.
// When Abu Ja'far dies, destroy all creatures blocking or blocked by it. They can't be regenerated.
this.addAbility(new DiesSourceTriggeredAbility(new DestroyAllEffect(filter, true), false));
}

View file

@ -64,7 +64,7 @@ class AbundanceReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(event.getPlayerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (controller != null && sourceObject != null) {
FilterCard filter = new FilterCard();
if (controller.chooseUse(Outcome.Detriment, "Choose card type:",
@ -79,7 +79,7 @@ class AbundanceReplacementEffect extends ReplacementEffectImpl {
Card selectedCard = null;
for (Card card : controller.getLibrary().getCards(game)) {
toReveal.add(card);
if (filter.match(card, source.getSourceId(), source.getControllerId(), game)) {
if (filter.match(card, source.getControllerId(), source, game)) {
selectedCard = card;
break;
}

View file

@ -73,7 +73,7 @@ class AcademyResearchersEffect extends OneShotEffect {
if (controller != null && academyResearchers != null) {
filterCardInHand.add(new AuraCardCanAttachToPermanentId(academyResearchers.getId()));
TargetCardInHand target = new TargetCardInHand(0, 1, filterCardInHand);
if (controller.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) {
if (controller.choose(Outcome.PutCardInPlay, target, source, game)) {
Card auraInHand = game.getCard(target.getFirstTarget());
if (auraInHand != null) {
game.getState().setValue("attachTo:" + auraInHand.getId(), academyResearchers);

View file

@ -103,7 +103,7 @@ class AcererakTheArchlichEffect extends OneShotEffect {
}
TargetPermanent target = new TargetControlledCreaturePermanent(0, 1);
target.setNotTarget(true);
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
player.choose(Outcome.Sacrifice, target, source, game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null && permanent.sacrifice(source, game)) {
tokens--;

View file

@ -50,7 +50,7 @@ class AcidicSoilEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source.getSourceId(), game);
List<Permanent> permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LAND, source.getControllerId(), source, game);
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {

View file

@ -73,7 +73,7 @@ class AcolyteOfAfflictionEffect extends OneShotEffect {
}
player.moveCards(player.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
TargetCard target = new TargetCardInYourGraveyard(0, 1, filter, true);
if (!player.choose(Outcome.ReturnToHand, target, source.getSourceId(), game)) {
if (!player.choose(Outcome.ReturnToHand, target, source, game)) {
return true;
}
Card card = game.getCard(target.getFirstTarget());

View file

@ -63,7 +63,7 @@ class AdviceFromTheFaeEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (controller != null && mageObject != null) {
Set<Card> topCards = controller.getLibrary().getTopCards(game, 5);
Cards cardsFromLibrary = new CardsImpl();

View file

@ -79,10 +79,10 @@ enum AerialSurveyorCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
return game.getBattlefield().count(
filter, source.getSourceId(), source.getControllerId(), game
filter, source.getControllerId(), source, game
) > game.getBattlefield().count(
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND,
source.getSourceId(), source.getControllerId(), game
source.getControllerId(), source, game
);
}
}
@ -96,7 +96,7 @@ enum AerialSurveyorHint implements Hint {
.getActivePermanents(
StaticFilters.FILTER_LAND,
ability.getControllerId(),
ability.getSourceId(), game
ability, game
).stream()
.map(Controllable::getControllerId)
.filter(game.getOpponents(ability.getControllerId())::contains)

View file

@ -90,7 +90,7 @@ class AetherVialEffect extends OneShotEffect {
}
TargetCardInHand target = new TargetCardInHand(filter);
if (controller.choose(this.outcome, target, source.getSourceId(), game)) {
if (controller.choose(this.outcome, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
return controller.moveCards(card, Zone.BATTLEFIELD, source, game);

View file

@ -78,12 +78,12 @@ class AetherbornMarauderEffect extends OneShotEffect {
filter.add(AnotherPredicate.instance);
filter.add(CounterType.P1P1.getPredicate());
boolean firstRun = true;
while (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) {
while (game.getBattlefield().count(filter, source.getControllerId(), source, game) > 0) {
if (controller.chooseUse(outcome, "Move " + (firstRun ? "any" : "more") + " +1/+1 counters from other permanents you control to " + sourceObject.getLogName() + '?', source, game)) {
firstRun = false;
TargetControlledPermanent target = new TargetControlledPermanent(filter);
target.setNotTarget(true);
if (target.choose(Outcome.Neutral, source.getControllerId(), source.getSourceId(), game)) {
if (target.choose(Outcome.Neutral, source.getControllerId(), source.getSourceId(), source, game)) {
Permanent fromPermanent = game.getPermanent(target.getFirstTarget());
if (fromPermanent != null) {
int numberOfCounters = fromPermanent.getCounters(game).getCount(CounterType.P1P1);

View file

@ -60,7 +60,7 @@ class AethermagesTouchEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (controller != null && sourceObject != null) {
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 4));
if (!cards.isEmpty()) {

View file

@ -67,7 +67,7 @@ class AetherplasmEffect extends OneShotEffect {
}
if (player.chooseUse(Outcome.PutCardInPlay, "Put a creature card from your hand onto the battlefield?", source, game)) {
TargetCardInHand target = new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A);
if (player.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) {
if (player.choose(Outcome.PutCardInPlay, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
Permanent blockedCreature = game.getPermanent(getTargetPointer().getFirst(game, source));

View file

@ -81,7 +81,7 @@ class AetherspoutsEffect extends OneShotEffect {
do {
List<Permanent> permanentsToTop = new ArrayList<>();
List<Permanent> permanentsToBottom = new ArrayList<>();
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(new FilterAttackingCreature(), player.getId(), source, game)) {
if (permanent.isOwnedBy(player.getId())) {
if (player.chooseUse(outcome, "Put " + permanent.getLogName() + " to the top? (else it goes to bottom)", source, game)) {
permanentsToTop.add(permanent);

View file

@ -81,8 +81,8 @@ class AgadeemOccultistEffect extends OneShotEffect {
TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(1, 1, filter);
if (controller != null) {
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)
&& controller.choose(Outcome.GainControl, target, source.getSourceId(), game)) {
if (target.canChoose(source.getControllerId(), source, game)
&& controller.choose(Outcome.GainControl, target, source, game)) {
if (!target.getTargets().isEmpty()) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {

View file

@ -100,8 +100,8 @@ class AgadeemsAwakeningTarget extends TargetCardInYourGraveyard {
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, source, game);
Set<Integer> cmcs = this.getTargets()
.stream()
.map(game::getCard)

View file

@ -86,7 +86,7 @@ class AgitatorAntEffect extends OneShotEffect {
}
TargetPermanent targetPermanent = new TargetControlledCreaturePermanent(0, 1);
targetPermanent.setNotTarget(true);
player.choose(Outcome.BoostCreature, targetPermanent, source.getSourceId(), game);
player.choose(Outcome.BoostCreature, targetPermanent, source, game);
Permanent permanent = game.getPermanent(targetPermanent.getFirstTarget());
if (permanent == null || !permanent.addCounters(CounterType.P1P1.createInstance(2), player.getId(), source, game)) {
continue;

View file

@ -65,7 +65,7 @@ class AidFromTheCowlEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (controller == null || sourceObject == null) {
return false;
}

View file

@ -142,11 +142,11 @@ class AkiriFearlessVoyagerEffect extends OneShotEffect {
return false;
}
TargetPermanent target = new TargetPermanent(1, 1, filter, true);
if (!target.canChoose(source.getSourceId(), source.getControllerId(), game)
if (!target.canChoose(source.getControllerId(), source, game)
|| !player.chooseUse(outcome, "Unnattach an equipment from a creature you control?", source, game)) {
return false;
}
player.choose(outcome, target, source.getSourceId(), game);
player.choose(outcome, target, source, game);
Permanent equipment = game.getPermanent(target.getFirstTarget());
if (equipment == null) {
return false;

View file

@ -104,7 +104,7 @@ class AkromaVisionOfIxidorEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE,
source.getControllerId(), source.getSourceId(), game
source.getControllerId(), source, game
)) {
Abilities<Ability> abilities = permanent.getAbilities(game);
int count = classes

View file

@ -138,7 +138,7 @@ class AlhammarretHighArbiterCantCastEffect extends ContinuousRuleModifyingEffect
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
return "You may not cast a card named " + cardName + " (" + mageObject.getIdName() + ").";
}

View file

@ -91,7 +91,7 @@ class AlibouAncientWitnessEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int xValue = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
int xValue = game.getBattlefield().count(filter, source.getControllerId(), source, game);
if (xValue < 1) {
return false;
}

View file

@ -77,7 +77,7 @@ class AlignedHedronNetworkExileEffect extends OneShotEffect {
// If Whale leaves the battlefield before its triggered ability resolves,
// the target creature won't be exiled.
Set<Card> toExile = new LinkedHashSet<>(game.getBattlefield().getActivePermanents(filter, controller.getId(), source.getSourceId(), game));
Set<Card> toExile = new LinkedHashSet<>(game.getBattlefield().getActivePermanents(filter, controller.getId(), source, game));
if (toExile.isEmpty()) { return false; }
controller.moveCardsToExile(toExile, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName());

View file

@ -66,7 +66,7 @@ class WellEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
int life = 2 * game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
int life = 2 * game.getBattlefield().count(filter, source.getControllerId(), source, game);
player.gainLife(life, game, source);
}
return true;

View file

@ -69,7 +69,7 @@ class AllureOfTheUnknownEffect extends OneShotEffect {
return player.moveCards(cards, Zone.HAND, source, game);
}
TargetOpponent targetOpponent = new TargetOpponent(true);
if (!player.choose(outcome, targetOpponent, source.getSourceId(), game)) {
if (!player.choose(outcome, targetOpponent, source, game)) {
return false;
}
Player opponent = game.getPlayer(targetOpponent.getFirstTarget());

View file

@ -105,7 +105,7 @@ class AminatouPlusEffect extends OneShotEffect {
private boolean putOnLibrary(Player player, Ability source, Game game) {
TargetCardInHand target = new TargetCardInHand();
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
if (target.canChoose(player.getId(), source, game)) {
player.chooseTarget(Outcome.ReturnToHand, target, source, game);
Card card = player.getHand().get(target.getFirstTarget(), game);
if (card != null) {

View file

@ -82,7 +82,7 @@ class AmuletOfSafekeepingTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
StackObject stackObject = game.getStack().getStackObject(event.getSourceId());
if (event.getTargetId().equals(getControllerId())
&& filter.match(stackObject, getSourceId(), getControllerId(), game)) {
&& filter.match(stackObject, getControllerId(), this, game)) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(stackObject.getId(), game));
}

View file

@ -68,7 +68,7 @@ class AnHavvaConstableEffect extends ContinuousEffectImpl {
FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures");
filter.add(new ColorPredicate(ObjectColor.GREEN));
int numberOfGreenCreatures = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
int numberOfGreenCreatures = game.getBattlefield().count(filter, source.getSourceId(), source, game);
mageObject.getToughness().setValue(1 + numberOfGreenCreatures);

View file

@ -59,7 +59,7 @@ class AnHavvaInnEffect extends OneShotEffect {
if (player != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent("green creatures");
filter.add(new ColorPredicate(ObjectColor.GREEN));
int greenCreatures = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
int greenCreatures = game.getBattlefield().count(filter, source.getControllerId(), source, game);
player.gainLife(greenCreatures+1, game, source);
}
return true;

View file

@ -63,8 +63,8 @@ enum AnathemancerCount implements DynamicValue {
}
return game.getBattlefield().count(
StaticFilters.FILTER_LANDS_NONBASIC,
sourceAbility.getFirstTarget(),
sourceAbility.getControllerId(), game
sourceAbility.getControllerId(),
sourceAbility, game
);
}

View file

@ -72,7 +72,7 @@ class AngelOfGlorysRiseEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Set<Card> toExile = new HashSet<>(game.getBattlefield()
.getActivePermanents(new FilterCreaturePermanent(SubType.ZOMBIE, "Zombie"), source.getControllerId(), source.getSourceId(), game));
.getActivePermanents(new FilterCreaturePermanent(SubType.ZOMBIE, "Zombie"), source.getControllerId(), source, game));
controller.moveCards(toExile, Zone.EXILED, source, game);
FilterCreatureCard filterHuman = new FilterCreatureCard();
filterHuman.add(SubType.HUMAN.getPredicate());

View file

@ -57,7 +57,7 @@ class AnimalMagnetismEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (sourceObject != null && controller != null) {
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 5));
if (!cards.isEmpty()) {

View file

@ -56,7 +56,7 @@ class AnimistsAwakeningEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (controller == null || sourceObject == null) {
return false;
}
@ -66,7 +66,7 @@ class AnimistsAwakeningEffect extends OneShotEffect {
if (!cards.isEmpty()) {
controller.revealCards(sourceObject.getIdName(), cards, game);
Set<Card> toBattlefield = new LinkedHashSet<>();
for (Card card : cards.getCards(new FilterLandCard(), source.getSourceId(), source.getControllerId(), game)) {
for (Card card : cards.getCards(new FilterLandCard(), source.getControllerId(), source, game)) {
cards.remove(card);
toBattlefield.add(card);
}

View file

@ -69,7 +69,7 @@ class AnuridScavengerCost extends CostImpl {
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.Removal, controllerId, source.getSourceId(), game)) {
if (targets.choose(Outcome.Removal, controllerId, source.getSourceId(), source, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || game.getState().getZone(targetId) != Zone.GRAVEYARD) {
@ -85,7 +85,7 @@ class AnuridScavengerCost extends CostImpl {
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
return targets.canChoose(source.getSourceId(), controllerId, game);
return targets.canChoose(controllerId, source, game);
}
@Override

View file

@ -82,7 +82,7 @@ class ArashinWarBeastTriggeredAbility extends TriggeredAbilityImpl {
((DamagedEvent) event).isCombatDamage() &&
!usedForCombatDamageStep) {
Permanent creature = game.getPermanentOrLKIBattlefield(event.getTargetId());
if (creature == null || !filter.match(creature, getSourceId(), getControllerId(), game)) {
if (creature == null || !filter.match(creature, getControllerId(), this, game)) {
return false;
}
// trigger only once per combat damage step

View file

@ -96,7 +96,7 @@ class AraumiOfTheDeadTideCost extends CostImpl {
int oppCount = game.getOpponents(controllerId).size();
TargetCard target = new TargetCardInYourGraveyard(oppCount, StaticFilters.FILTER_CARD);
target.setNotTarget(true);
player.choose(Outcome.Exile, target, source.getSourceId(), game);
player.choose(Outcome.Exile, target, source, game);
Cards cards = new CardsImpl(target.getTargets());
if (cards.size() < oppCount) {
return paid;

View file

@ -130,7 +130,7 @@ class ArcbondEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
int damage = (Integer) this.getValue("damage");
UUID sourceId = (UUID) this.getValue("sourceId");
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (sourceObject != null && damage > 0 && sourceId != null) {
Permanent targetObject = game.getPermanentOrLKIBattlefield(sourceId);
if (targetObject != null) {

View file

@ -72,10 +72,10 @@ enum ArchaeomancersMapCondition implements Condition {
UUID playerId = (UUID) source.getEffects().get(0).getValue("permanentEnteringControllerId");
return playerId != null && game.getBattlefield().count(
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND,
source.getSourceId(), playerId, game
playerId, source, game
) > game.getBattlefield().count(
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND,
source.getSourceId(), source.getControllerId(), game
source.getControllerId(), source, game
);
}
}

View file

@ -84,8 +84,8 @@ public final class ArchdemonOfGreed extends CardImpl {
if (player != null) {
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, false);
// if they can pay the cost, then they must pay
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
if (target.canChoose(player.getId(), source, game)) {
player.choose(Outcome.Sacrifice, target, source, game);
Permanent humanSacrifice = game.getPermanent(target.getFirstTarget());
if (humanSacrifice != null) {
// sacrifice the chosen card

View file

@ -73,7 +73,7 @@ class ArchfiendOfDepravityEffect extends OneShotEffect {
List<Permanent> creaturesToSacrifice = new ArrayList<>();
TargetControlledPermanent target = new TargetControlledPermanent(0, 2, new FilterControlledCreaturePermanent("creatures to keep"), true);
if (opponent.chooseTarget(outcome, target, source, game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), opponent.getId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), opponent.getId(), source, game)) {
if (permanent != null && !target.getTargets().contains(permanent.getId())) {
creaturesToSacrifice.add(permanent);
}

View file

@ -68,6 +68,6 @@ enum ArcticFoxesCondition implements Condition {
if (defenderId == null) {
return false;
}
return game.getBattlefield().contains(filter, source.getSourceId(), defenderId, game, 1);
return game.getBattlefield().contains(filter, source.getSourceId(), defenderId, source, game, 1);
}
}

View file

@ -88,7 +88,7 @@ class ArdennIntrepidArchaeologistEffect extends OneShotEffect {
return false;
}
TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true);
controller.choose(outcome, target, source.getSourceId(), game);
controller.choose(outcome, target, source, game);
for (UUID targetId : target.getTargets()) {
if (player != null) {
player.addAttachment(targetId, source, game);

View file

@ -79,7 +79,7 @@ class ArdentDustspeakerCost extends CostImpl {
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
return targets.canChoose(source.getSourceId(), controllerId, game);
return targets.canChoose(controllerId, source, game);
}
@Override

View file

@ -108,12 +108,12 @@ class ArmedAndArmoredEquipEffect extends OneShotEffect {
if (!dwarves.isEmpty() && !equipment.isEmpty()) {
TargetPermanent target = new TargetPermanent(0, 1, dwarfFilter, true);
target.withChooseHint("dwarf to be equipped");
controller.choose(outcome, target, source.getId(), game);
controller.choose(outcome, target, source, game);
Permanent dwarf = game.getPermanent(target.getFirstTarget());
if (dwarf != null) {
target = new TargetPermanent(0, Integer.MAX_VALUE, equipmentFilter, true);
target.withChooseHint("equip to " + dwarf.getLogName());
controller.choose(outcome, target, source.getId(), game);
controller.choose(outcome, target, source, game);
for (UUID targetId : target.getTargets()) {
dwarf.addAttachment(targetId, source, game);
game.informPlayers(game.getPermanent(targetId).getLogName() + " was attached to " + dwarf.getLogName());

View file

@ -100,7 +100,7 @@ class ArmoredSkyhunterEffect extends OneShotEffect {
}
TargetPermanent targetPermanent = new TargetControlledCreaturePermanent(0, 1);
targetCard.setNotTarget(true);
player.choose(outcome, targetPermanent, source.getSourceId(), game);
player.choose(outcome, targetPermanent, source, game);
Permanent permanent = game.getPermanent(targetPermanent.getFirstTarget());
if (permanent != null) {
permanent.addAttachment(equipment.getId(), source, game);

View file

@ -88,7 +88,7 @@ class ArmoryAutomatonEffect extends OneShotEffect {
while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.Benefit, "Select and attach a target Equipment?", source, game)) {
Target targetEquipment = new TargetPermanent(currentFilter);
targetEquipment.setRequired(false);
if (player.choose(Outcome.Benefit, targetEquipment, source.getSourceId(), game) && targetEquipment.getFirstTarget() != null) {
if (player.choose(Outcome.Benefit, targetEquipment, source, game) && targetEquipment.getFirstTarget() != null) {
currentFilter.add(Predicates.not(new PermanentIdPredicate(targetEquipment.getFirstTarget()))); // exclude selected for next time
Permanent aura = game.getPermanent(targetEquipment.getFirstTarget());

View file

@ -69,7 +69,7 @@ class ArniBrokenbrowEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (controller == null || mageObject == null) {
return false;
}

View file

@ -14,7 +14,7 @@ import mage.constants.Outcome;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.common.FilterArtifactCard;
import mage.filter.predicate.mageobject.AnotherCardPredicate;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -75,12 +75,12 @@ class ArsenalThresherEffect extends OneShotEffect {
}
Permanent arsenalThresher = game.getPermanentEntering(source.getSourceId());
FilterArtifactCard filter = new FilterArtifactCard();
filter.add(new AnotherCardPredicate());
filter.add(AnotherPredicate.instance);
if (controller.chooseUse(Outcome.Benefit, "Reveal other artifacts in your hand?", source, game)) {
Cards cards = new CardsImpl();
if (controller.getHand().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) {
if (controller.getHand().count(filter, source.getControllerId(), source, game) > 0) {
TargetCardInHand target = new TargetCardInHand(0, Integer.MAX_VALUE, filter);
if (controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) {
if (controller.choose(Outcome.Benefit, target, source, game)) {
for (UUID uuid : target.getTargets()) {
cards.add(controller.getHand().get(uuid, game));
}

View file

@ -74,7 +74,7 @@ class ArterialAlchemyEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(
filter, source.getControllerId(), source.getSourceId(), game
filter, source.getControllerId(), source, game
)) {
switch (layer) {
case TypeChangingEffects_4:

View file

@ -95,7 +95,7 @@ class AryelTapXTargetCost extends VariableCostImpl {
@Override
public int getMaxValue(Ability source, Game game) {
return game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
return game.getBattlefield().count(filter, source.getControllerId(), source, game);
}
@Override

View file

@ -69,7 +69,7 @@ class SpellWithManaCostLessThanOrEqualToCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
MageObject object = game.getObject(source.getSourceId());
MageObject object = game.getObject(source);
return object != null
&& !object.isLand(game)
&& object.getManaValue() <= counters;

View file

@ -71,7 +71,7 @@ enum AscendantAcolyteValue implements DynamicValue {
.getActivePermanents(
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE,
sourceAbility.getControllerId(),
sourceAbility.getSourceId(), game
sourceAbility, game
).stream()
.mapToInt(permanent -> permanent.getCounters(game).getCount(CounterType.P1P1))
.sum();

View file

@ -87,10 +87,10 @@ class AscentOfTheWorthyEffect extends OneShotEffect {
}
TargetPermanent target = new TargetControlledCreaturePermanent();
target.setNotTarget(true);
if (!target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
if (!target.canChoose(source.getControllerId(), source, game)) {
return false;
}
player.choose(outcome, target, source.getControllerId(), game);
player.choose(outcome, target, source, game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent == null) {
return false;

View file

@ -77,7 +77,7 @@ class AshayaSoulOfTheWildEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(
filter, source.getControllerId(), source.getSourceId(), game
filter, source.getControllerId(), source, game
)) {
if (!permanent.isLand(game)) {
permanent.addCardType(game, CardType.LAND);

View file

@ -73,7 +73,7 @@ class AshiokDreamRenderEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
return "You can't search libraries (" + mageObject.getLogName() + " in play).";
}

View file

@ -120,7 +120,7 @@ class AshiokNightmareWeaverPutIntoPlayEffect extends OneShotEffect {
Target target = new TargetCardInExile(filter, CardUtil.getExileZoneId(game, source));
if (!target.canChoose(source.getSourceId(), controller.getId(), game)) {
if (!target.canChoose(controller.getId(), source, game)) {
return false;
}
controller.chooseTarget(Outcome.PutCreatureInPlay, target, source, game);

View file

@ -66,7 +66,7 @@ enum AspectOfWolfValue implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
int forestCount = game.getBattlefield().count(
filter, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game
filter, sourceAbility.getControllerId(), sourceAbility, game
);
return forestCount / 2 + (up ? forestCount % 2 : 0);
}

View file

@ -70,7 +70,7 @@ class AssemblyHallEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (controller == null || controller.getHand().isEmpty() || sourceObject == null) {
return false;
}

View file

@ -82,7 +82,7 @@ class AtarkaWorldRenderEffect extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
Permanent attacker = game.getPermanent(event.getSourceId());
if (attacker != null
&& filter.match(attacker, sourceId, controllerId, game)) {
&& filter.match(attacker, controllerId, this, game)) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(attacker.getId(), game));
}

View file

@ -144,7 +144,7 @@ class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
if (!zEvent.isDiesEvent()) {
return false;
}
if (zEvent.getTarget() == null || !filter.match(zEvent.getTarget(), sourceId, controllerId, game)) {
if (zEvent.getTarget() == null || !filter.match(zEvent.getTarget(), controllerId, this, game)) {
return false;
}
for (Effect effect : this.getEffects()) {

View file

@ -72,18 +72,18 @@ class AugurOfBolasEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (controller != null && sourceObject != null) {
Cards topCards = new CardsImpl();
topCards.addAll(controller.getLibrary().getTopCards(game, 3));
if (!topCards.isEmpty()) {
controller.lookAtCards(sourceObject.getIdName(), topCards, game);
int number = topCards.count(new FilterInstantOrSorceryCard(), source.getSourceId(), source.getControllerId(), game);
int number = topCards.count(new FilterInstantOrSorceryCard(), source.getControllerId(), source, game);
if (number > 0) {
if (controller.chooseUse(outcome, "Reveal an instant or sorcery card from the looked at cards and put it into your hand?", source, game)) {
Card card = null;
if (number == 1) {
Set<Card> cards = topCards.getCards(new FilterInstantOrSorceryCard(), source.getSourceId(), source.getControllerId(), game);
Set<Card> cards = topCards.getCards(new FilterInstantOrSorceryCard(), source.getControllerId(), source, game);
if (!cards.isEmpty()) {
card = cards.iterator().next();
}

View file

@ -18,7 +18,6 @@ import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
/**
@ -83,7 +82,7 @@ class AuntiesSnitchTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event;
Permanent p = game.getPermanent(event.getSourceId());
return damageEvent.isCombatDamage() && filter.match(p, getSourceId(), getControllerId(), game);
return damageEvent.isCombatDamage() && filter.match(p, getControllerId(), this, game);
}
@Override

View file

@ -54,7 +54,7 @@ public final class AuraBarbs extends CardImpl {
FilterPermanent filterEnchantments = new FilterPermanent();
filterEnchantments.add(CardType.ENCHANTMENT.getPredicate());
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterEnchantments, source.getControllerId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterEnchantments, source.getControllerId(), source, game)) {
Player controller = game.getPlayer(permanent.getControllerId());
if (controller != null) {
controller.damage(2, permanent.getId(), source, game);
@ -63,7 +63,7 @@ public final class AuraBarbs extends CardImpl {
}
filterEnchantments.add(SubType.AURA.getPredicate());
for (Permanent auraEnchantment : game.getBattlefield().getActivePermanents(filterEnchantments, source.getControllerId(), source.getSourceId(), game)) {
for (Permanent auraEnchantment : game.getBattlefield().getActivePermanents(filterEnchantments, source.getControllerId(), source, game)) {
if (auraEnchantment.getAttachedTo() != null) {
Permanent attachedToCreature = game.getPermanent(auraEnchantment.getAttachedTo());
if (attachedToCreature != null && attachedToCreature.isCreature(game)) {

View file

@ -123,8 +123,8 @@ class MoveTargetAuraEffect extends OneShotEffect {
filter.add(new PermanentCanBeAttachedToPredicate(enchantment));
Target target = new TargetPermanent(filter);
target.setNotTarget(true);
if (target.canChoose(oldAttachment.getId(), controller.getId(), game)
&& controller.choose(outcome, target, oldAttachment.getId(), game)) {
if (target.canChoose(controller.getId(), source, game)
&& controller.choose(outcome, target, source, game)) {
Permanent newAttachment = game.getPermanent(target.getFirstTarget());
if (newAttachment != null
&& oldAttachment.removeAttachment(enchantment.getId(), source, game)) {

View file

@ -71,7 +71,7 @@ class AuraThiefDiesTriggeredEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
boolean ret = false;
for(Permanent enchantment : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_ENCHANTMENT, source.getControllerId(), source.getControllerId(), game)) {
for(Permanent enchantment : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_ENCHANTMENT, source.getControllerId(), source, game)) {
ContinuousEffect gainControl = new GainControlTargetEffect(Duration.EndOfGame);
gainControl.setTargetPointer(new FixedTarget(enchantment.getId(), game));
game.addEffect(gainControl, source);

View file

@ -140,7 +140,7 @@ class AureliasFuryCantCastEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
return "You can't cast noncreature spells this turn (you were dealt damage by " + mageObject.getLogName() + ')';
}

View file

@ -111,7 +111,7 @@ class SacrificeAllEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getId(), game);
List<Permanent> permanents = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game);
for (Permanent p : permanents) {
p.sacrifice(source, game);
}

View file

@ -90,7 +90,7 @@ class AvenShrineEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int count = 0;
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if(mageObject != null) {
Spell spell = (Spell) game.getState().getValue("avenShrine" + mageObject);
if (spell != null) {

View file

@ -81,7 +81,7 @@ class AvenSoulgazerLookFaceDownEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (player == null || mageObject == null) {
return false;
}

View file

@ -113,7 +113,7 @@ class AzorTheLawbringerCantCastEffect extends ContinuousRuleModifyingEffectImpl
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
return "You can't cast instant or sorcery spells this turn (" + mageObject.getIdName() + ").";
}

View file

@ -80,7 +80,7 @@ class AzoriusAEthermageAbility extends TriggeredAbilityImpl {
return false;
}
return StaticFilters.FILTER_PERMANENT_CREATURE.match(permanentThatMoved, sourceId, controllerId, game);
return StaticFilters.FILTER_PERMANENT_CREATURE.match(permanentThatMoved, controllerId, this, game);
}
@Override

View file

@ -87,7 +87,7 @@ class AzorsGatewayEffect extends OneShotEffect {
controller.drawCards(1, source, game);
TargetCardInHand target = new TargetCardInHand();
controller.choose(outcome, target, source.getSourceId(), game);
controller.choose(outcome, target, source, game);
Card cardToExile = game.getCard(target.getFirstTarget());
if (cardToExile != null) {
controller.moveCardsToExile(cardToExile, source, game, true, exileId, sourceObject.getIdName());

View file

@ -75,7 +75,7 @@ class AzraBladeseekerEffect extends OneShotEffect {
continue;
}
Target target = new TargetDiscard(playerId);
if (target.choose(Outcome.DrawCard, playerId, source.getSourceId(), game)) {
if (target.choose(Outcome.DrawCard, playerId, source.getSourceId(), source, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
playerCardList.add(new PlayerCard(player, card));

View file

@ -82,7 +82,7 @@ class AzraOddsmakerEffect extends OneShotEffect {
Permanent permanent = null;
TargetCreaturePermanent target = new TargetCreaturePermanent();
target.setNotTarget(true);
if (player.choose(Outcome.DrawCard, target, source.getSourceId(), game)) {
if (player.choose(Outcome.DrawCard, target, source, game)) {
permanent = game.getPermanent(target.getFirstTarget());
}
if (permanent == null) {

View file

@ -83,7 +83,7 @@ class BingoEffect extends OneShotEffect {
if (spell.getManaValue() > 9) {
return true;
}
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (mageObject != null) {
Map<Integer, Integer> chipCounters = new HashMap<>(); // Map<number, amount of counters>
if (game.getState().getValue(mageObject.getId() + "_chip") != null) {

View file

@ -67,12 +67,12 @@ class BackFromTheBrinkCost extends CostImpl {
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
return targets.canChoose(source.getSourceId(), controllerId, game);
return targets.canChoose(controllerId, source, game);
}
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
if (targets.choose(Outcome.Exile, controllerId, source.getSourceId(), game)) {
if (targets.choose(Outcome.Exile, controllerId, source.getSourceId(), source, game)) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
Card card = controller.getGraveyard().get(targets.getFirstTarget(), game);

View file

@ -113,7 +113,7 @@ class BagOfDevouringEffect extends OneShotEffect {
CardUtil.getExileZoneId(game, source)
);
target.setNotTarget(true);
player.choose(outcome, target, source.getSourceId(), game);
player.choose(outcome, target, source, game);
player.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game);
return true;
}

View file

@ -55,7 +55,7 @@ class BakisCurseEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source, game)) {
int count = 0;
List<UUID> attachments = creature.getAttachments();
for (UUID attachmentId : attachments) {

View file

@ -64,7 +64,7 @@ class BalancingActEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
int count = game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source.getSourceId(), game).size();
int count = game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source, game).size();
if (count < minPermanent) {
minPermanent = count;
}
@ -75,8 +75,8 @@ class BalancingActEffect extends OneShotEffect {
Player player = game.getPlayer(playerId);
if (player != null) {
TargetControlledPermanent target = new TargetControlledPermanent(minPermanent, minPermanent, new FilterControlledPermanent(), true);
if (target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source.getSourceId(), game)) {
if (target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), source, game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source, game)) {
if (permanent != null && !target.getTargets().contains(permanent.getId())) {
permanent.sacrifice(source, game);
}
@ -101,7 +101,7 @@ class BalancingActEffect extends OneShotEffect {
Player player = game.getPlayer(playerId);
if (player != null) {
TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard());
if (target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game)) {
if (target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), source, game)) {
Cards cards = player.getHand().copy();
cards.removeIf(target.getTargets()::contains);
player.discard(cards, false, source, game);

View file

@ -115,8 +115,8 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect {
FilterAttackingCreature filter = new FilterAttackingCreature("creature attacking " + targetsController.getLogName());
filter.add(new PermanentInListPredicate(list));
TargetAttackingCreature target = new TargetAttackingCreature(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(source.getSourceId(), controller.getId(), game) && controller.canRespond()) {
if (target.canChoose(controller.getId(), source, game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), source, game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
} else {

View file

@ -89,7 +89,7 @@ class BalthorTheDefiledEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
cardsToReturn.addAll(player.getGraveyard().getCards(filter, source.getSourceId(), source.getControllerId(), game));
cardsToReturn.addAll(player.getGraveyard().getCards(filter, source.getControllerId(), source, game));
}
}
controller.moveCards(cardsToReturn.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null);

View file

@ -70,7 +70,7 @@ class BaneOfProgressEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int destroyedPermanents = 0;
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) {
if (permanent.destroy(source, game, false)) {
destroyedPermanents++;
}

View file

@ -1,7 +1,6 @@
package mage.cards.b;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.effects.common.LoseLifeTargetControllerEffect;
@ -12,18 +11,10 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.WatcherScope;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
import java.util.*;
import java.util.UUID;
/**
* @author TheElk801
@ -31,11 +22,9 @@ import java.util.*;
public final class BaneclawMarauder extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
private static final FilterPermanent filter2 = new FilterCreaturePermanent("a creature blocking {this}");
static {
filter.add(BlockingOrBlockedBySourcePredicate.BLOCKING);
filter2.add(BaneclawMarauderPredicate.instance);
}
public BaneclawMarauder(UUID ownerId, CardSetInfo setInfo) {
@ -56,8 +45,8 @@ public final class BaneclawMarauder extends CardImpl {
this.addAbility(new DiesCreatureTriggeredAbility(
new LoseLifeTargetControllerEffect(1)
.setText("that creature's controller loses 1 life"),
false, filter2, true
), new BaneclawMarauderWatcher());
false, filter, true
));
// Nightbound
this.addAbility(new NightboundAbility());
@ -72,55 +61,3 @@ public final class BaneclawMarauder extends CardImpl {
return new BaneclawMarauder(this);
}
}
enum BaneclawMarauderPredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
return BaneclawMarauderWatcher.check(input.getSourceId(), input.getObject(), game);
}
}
class BaneclawMarauderWatcher extends Watcher {
private final Map<MageObjectReference, Set<MageObjectReference>> blockerMap = new HashMap<>();
BaneclawMarauderWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
switch (event.getType()) {
case BLOCKER_DECLARED:
blockerMap
.computeIfAbsent(new MageObjectReference(event.getTargetId(), game), x -> new HashSet<>())
.add(new MageObjectReference(event.getSourceId(), game));
return;
case END_COMBAT_STEP_POST:
blockerMap.clear();
return;
case REMOVED_FROM_COMBAT:
blockerMap
.values()
.stream()
.forEach(set -> set.removeIf(mor -> mor.refersTo(event.getTargetId(), game)));
}
}
@Override
public void reset() {
super.reset();
blockerMap.clear();
}
static boolean check(UUID sourceId, Permanent blocker, Game game) {
return game.getState()
.getWatcher(BaneclawMarauderWatcher.class)
.blockerMap
.getOrDefault(new MageObjectReference(sourceId, game), Collections.emptySet())
.stream()
.anyMatch(mor -> mor.refersTo(blocker, game));
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
@ -13,30 +11,37 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.BlockingAttackerIdPredicate;
import mage.target.common.TargetCreaturePermanent;
import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
*
* @author LoneFox
*/
public final class BarbedBackWurm extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("green creature blocking {this}");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(BlockingOrBlockedBySourcePredicate.BLOCKING);
}
public BarbedBackWurm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.WURM);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// {B}: Target green creature blocking Barbed-Back Wurm gets -1/-1 until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(-1, -1, Duration.EndOfTurn), new ManaCostsImpl("{B}"));
FilterCreaturePermanent filter = new FilterCreaturePermanent("green creature blocking {this}");
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(new BlockingAttackerIdPredicate(this.getId()));
ability.addTarget(new TargetCreaturePermanent(filter));
Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(
-1, -1, Duration.EndOfTurn
), new ManaCostsImpl<>("{B}"));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}

View file

@ -76,7 +76,7 @@ class BaronVonCountPutCounterEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getPermanentEntering(source.getSourceId());
if (mageObject == null) {
mageObject = game.getObject(source.getSourceId());
mageObject = game.getObject(source);
}
if (controller != null && mageObject != null) {
Integer doomNumber = 5;
@ -172,7 +172,7 @@ class BaronVonCountMoveDoomCounterEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (controller != null && sourcePermanent != null && mageObject != null) {
if (game.getState().getValue(mageObject.getId() + "_doom") == null) {
return false;
@ -249,7 +249,7 @@ class BaronVonCountDestroyPlayerEffect extends OneShotEffect {
targetPlayer.lost(game); // double checks canLose, but seems more future-proof than lostForced
}
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
MageObject mageObject = game.getObject(source.getSourceId());
MageObject mageObject = game.getObject(source);
if (sourcePermanent != null && mageObject != null) {
if (game.getState().getValue(mageObject.getId() + "_doom") == null) {
return false;

View file

@ -75,7 +75,7 @@ enum BaseCampCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
MageObject object = game.getObject(source.getSourceId());
MageObject object = game.getObject(source);
return object != null && (
object.hasSubtype(SubType.CLERIC, game)
|| object.hasSubtype(SubType.ROGUE, game)

View file

@ -87,7 +87,7 @@ class BatheInLightEffect extends OneShotEffect {
ContinuousEffect effect = new ProtectionChosenColorTargetEffect();
game.addEffect(effect, source);
ObjectColor color = target.getColor(game);
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)) {
if (!permanent.getId().equals(target.getId()) && permanent.getColor(game).shares(color)) {
game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor());
effect.setTargetPointer(new FixedTarget(permanent, game));

View file

@ -89,7 +89,7 @@ class BattleForBretagardEffect extends OneShotEffect {
return false;
}
TargetPermanent target = new BattleForBretagardTarget();
player.choose(outcome, target, source.getSourceId(), game);
player.choose(outcome, target, source, game);
for (UUID targetId : target.getTargets()) {
new CreateTokenCopyTargetEffect()
.setTargetPointer(new FixedTarget(targetId, game))
@ -145,8 +145,8 @@ class BattleForBretagardTarget extends TargetPermanent {
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = super.possibleTargets(sourceId, sourceControllerId, game);
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, source, game);
Set<String> names = this.getTargets()
.stream()
.map(game::getPermanent)

View file

@ -68,7 +68,7 @@ class BattlefieldScroungerCost extends CostImpl {
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.Removal, controllerId, source.getSourceId(), game)) {
if (targets.choose(Outcome.Removal, controllerId, source.getSourceId(), source, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || game.getState().getZone(targetId) != Zone.GRAVEYARD) {
@ -84,7 +84,7 @@ class BattlefieldScroungerCost extends CostImpl {
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
return targets.canChoose(source.getSourceId(), controllerId, game);
return targets.canChoose(controllerId, source, game);
}
@Override

View file

@ -99,7 +99,7 @@ class BattlefieldThaumaturgeSpellsCostReductionEffect extends CostModificationEf
if (target.isNotTarget()) {
continue;
}
Set<UUID> possibleList = target.possibleTargets(ability.getSourceId(), ability.getControllerId(), game);
Set<UUID> possibleList = target.possibleTargets(ability.getControllerId(), ability, game);
possibleList.removeIf(id -> {
Permanent permanent = game.getPermanent(id);
return permanent == null || !permanent.isCreature(game);

View file

@ -71,7 +71,7 @@ class BeaconOfDestinyEffect extends RedirectionEffect {
@Override
public void init(Ability source, Game game) {
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), source, game);
super.init(source, game);
}

View file

@ -112,7 +112,7 @@ class BeamsplitterMageTriggeredAbility extends TriggeredAbilityImpl {
}
return game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_CREATURE,
getControllerId(), getSourceId(), game
getControllerId(), this, game
).stream()
.filter(Objects::nonNull)
.filter(permanent -> permanent.isCreature(game))
@ -165,7 +165,7 @@ class BeamsplitterMageEffect extends OneShotEffect {
filter.add(new BeamsplitterMagePredicate(spell));
TargetPermanent target = new TargetPermanent(filter);
target.setNotTarget(true);
player.choose(outcome, target, source.getSourceId(), game);
player.choose(outcome, target, source, game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent == null) {
return false;

View file

@ -14,7 +14,6 @@ import mage.constants.SpellAbilityType;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.BirdToken;
@ -65,7 +64,7 @@ class BeckTriggeredAbility extends DelayedTriggeredAbility {
public boolean checkTrigger(GameEvent event, Game game) {
UUID targetId = event.getTargetId();
Permanent permanent = game.getPermanent(targetId);
return filter.match(permanent, getSourceId(), getControllerId(), game);
return filter.match(permanent, getControllerId(), this, game);
}
@Override

View file

@ -96,7 +96,7 @@ class BendOrBreakEffect extends OneShotEffect {
List<Permanent> secondPile = new ArrayList<>();
FilterControlledLandPermanent filter = new FilterControlledLandPermanent("lands you control to assign to the first pile (lands not chosen will be assigned to the second pile)");
TargetPermanent target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true);
if (!target.canChoose(source.getSourceId(), currentPlayer.getId(), game)) { continue; }
if (!target.canChoose(currentPlayer.getId(), source, game)) { continue; }
// TODO: add support for AI (50/50), need AI hints mechanic here
currentPlayer.chooseTarget(Outcome.Neutral, target, source, game);

View file

@ -61,7 +61,7 @@ class BenefactionOfRhonasEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
MageObject sourceObject = game.getObject(source);
if (sourceObject != null && controller != null) {
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 5));
boolean creatureCardFound = false;

Some files were not shown because too many files have changed in this diff Show more