use of mage.abilities.effects.RestrictionUntapNotMoreThanEffect in project mage by magefree.
the class PlayerImpl method untap.
@Override
public void untap(Game game) {
// create list of all "notMoreThan" effects to track which one are consumed
Map<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffectsUsage = new HashMap<>();
for (Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>> restrictionEffect : game.getContinuousEffects().getApplicableRestrictionUntapNotMoreThanEffects(this, game).entrySet()) {
notMoreThanEffectsUsage.put(restrictionEffect, restrictionEffect.getKey().getNumber());
}
if (!notMoreThanEffectsUsage.isEmpty()) {
// create list of all permanents that can be untapped generally
List<Permanent> canBeUntapped = new ArrayList<>();
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
boolean untap = true;
for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).keySet()) {
untap &= effect.canBeUntapped(permanent, null, game, true);
}
if (untap) {
canBeUntapped.add(permanent);
}
}
// selected permanents to untap
List<Permanent> selectedToUntap = new ArrayList<>();
// player can cancel the selection of an effect to use a preferred order of restriction effects
boolean playerCanceledSelection;
do {
playerCanceledSelection = false;
// select permanents to untap to consume the "notMoreThan" effects
for (Map.Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> handledEntry : notMoreThanEffectsUsage.entrySet()) {
// select a permanent to untap for this entry
int numberToUntap = handledEntry.getValue();
if (numberToUntap > 0) {
List<Permanent> leftForUntap = getPermanentsThatCanBeUntapped(game, canBeUntapped, handledEntry.getKey().getKey(), notMoreThanEffectsUsage);
FilterControlledPermanent filter = handledEntry.getKey().getKey().getFilter().copy();
String message = filter.getMessage();
// omit already from other untap effects selected permanents
for (Permanent permanent : selectedToUntap) {
filter.add(Predicates.not(new PermanentIdPredicate(permanent.getId())));
}
// while targets left and there is still allowed to untap
while (canRespond() && !leftForUntap.isEmpty() && numberToUntap > 0) {
// player has to select the permanent they want to untap for this restriction
Ability ability = handledEntry.getKey().getValue().iterator().next();
if (ability != null) {
StringBuilder sb = new StringBuilder(message).append(" to untap").append(" (").append(Math.min(leftForUntap.size(), numberToUntap)).append(" in total");
MageObject effectSource = game.getObject(ability.getSourceId());
if (effectSource != null) {
sb.append(" from ").append(effectSource.getLogName());
}
sb.append(')');
filter.setMessage(sb.toString());
Target target = new TargetPermanent(1, 1, filter, true);
if (!this.chooseTarget(Outcome.Untap, target, ability, game)) {
// player canceled, go on with the next effect (if no other effect available, this effect will be active again)
playerCanceledSelection = true;
break;
}
Permanent selectedPermanent = game.getPermanent(target.getFirstTarget());
if (leftForUntap.contains(selectedPermanent)) {
selectedToUntap.add(selectedPermanent);
numberToUntap--;
// don't allow to select same permanent twice
filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId())));
// reduce available untap numbers from other "UntapNotMoreThan" effects if selected permanent applies to their filter too
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
if (notMoreThanEffect.getValue() > 0 && notMoreThanEffect.getKey().getKey().getFilter().match(selectedPermanent, game)) {
notMoreThanEffect.setValue(notMoreThanEffect.getValue() - 1);
}
}
// update the left for untap list
leftForUntap = getPermanentsThatCanBeUntapped(game, canBeUntapped, handledEntry.getKey().getKey(), notMoreThanEffectsUsage);
// remove already selected permanents
for (Permanent permanent : selectedToUntap) {
leftForUntap.remove(permanent);
}
} else {
// player selected an permanent that is restricted by another effect, disallow it (so AI can select another one)
filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId())));
if (this.isHuman() && !game.isSimulation()) {
game.informPlayer(this, "This permanent can't be untapped because of other restricting effect.");
}
}
}
}
}
}
} while (canRespond() && playerCanceledSelection);
if (!game.isSimulation()) {
// show in log which permanents were selected to untap
for (Permanent permanent : selectedToUntap) {
game.informPlayers(this.getLogName() + " untapped " + permanent.getLogName());
}
}
// untap if permanent is not concerned by notMoreThan effects or is included in the selectedToUntapList
for (Permanent permanent : canBeUntapped) {
boolean doUntap = true;
if (!selectedToUntap.contains(permanent)) {
// if the permanent is covered by one of the restriction effects, don't untap it
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game)) {
doUntap = false;
break;
}
}
}
if (permanent != null && doUntap) {
permanent.untap(game);
}
}
} else {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
boolean untap = true;
for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).keySet()) {
untap &= effect.canBeUntapped(permanent, null, game, true);
}
if (untap) {
permanent.untap(game);
}
}
}
}
Aggregations