package magic.model.target;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import magic.model.MagicAbility;
import magic.model.MagicCard;
import magic.model.MagicColor;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.MagicSubType;
import magic.model.MagicType;
import magic.model.event.MagicEvent;
public abstract class MagicCardFilterImpl implements MagicTargetFilter<MagicCard> {
public List<MagicCard> filter(final MagicSource source) {
return filter(source, source.getController(), MagicTargetHint.None);
}
public List<MagicCard> filter(final MagicPlayer player) {
return filter(MagicSource.NONE, player, MagicTargetHint.None);
}
public List<MagicCard> filter(final MagicEvent event) {
return filter(event.getSource(), event.getPlayer(), MagicTargetHint.None);
}
public List<MagicCard> filter(final MagicSource source, final MagicPlayer player, final MagicTargetHint targetHint) {
final List<MagicCard> targets = new ArrayList<MagicCard>();
// Cards in graveyard
if (acceptType(MagicTargetType.Graveyard)) {
add(source, player, player.getGraveyard(), targets, false);
}
// Cards in opponent's graveyard
if (acceptType(MagicTargetType.OpponentsGraveyard)) {
add(source, player, player.getOpponent().getGraveyard(), targets, false);
}
// Cards in hand
if (acceptType(MagicTargetType.Hand)) {
add(source, player, player.getHand(), targets, false);
}
// Cards in library
if (acceptType(MagicTargetType.Library)) {
// only consider unique cards, possible as cards in library will not be counted
add(source, player, player.getLibrary(), targets, true);
}
return targets;
}
private void add(final MagicSource source, final MagicPlayer player, final List<MagicCard> cards, final List<MagicCard> targets, final boolean library) {
final Set<Long> added = new HashSet<Long>();
for (final MagicCard card : cards) {
final boolean old = card.isGameKnown();
if (library) {
card.setGameKnown(true);
}
if (card.isKnown() && accept(source,player,card) && (library == false || added.contains(card.getStateId()) == false)) {
targets.add(card);
added.add(card.getStateId());
}
if (library) {
card.setGameKnown(old);
}
}
}
@Override
public boolean acceptType(final MagicTargetType targetType) {
return false;
}
public MagicCardFilterImpl or(final MagicType type) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) || target.hasType(type);
}
};
}
public MagicCardFilterImpl or(final MagicSubType subType) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) || target.hasSubType(subType);
}
};
}
public MagicCardFilterImpl or(final MagicColor color) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) || target.hasColor(color);
}
};
}
public MagicCardFilterImpl or(final MagicAbility ability) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) || target.hasAbility(ability);
}
};
}
public MagicCardFilterImpl and(final MagicType type) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.hasType(type);
}
};
}
public MagicCardFilterImpl and(final MagicSubType subType) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.hasSubType(subType);
}
};
}
public MagicCardFilterImpl and(final MagicColor color) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.hasColor(color);
}
};
}
public MagicCardFilterImpl and(final MagicAbility ability) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.hasAbility(ability);
}
};
}
public MagicCardFilterImpl permanent() {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.isPermanentCard();
}
};
}
public MagicCardFilterImpl cmcLEQ(final int n) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.getConvertedCost() <= n;
}
};
}
public MagicCardFilterImpl powerLEQ(final int n) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target) && target.getPower() <= n;
}
};
}
public MagicCardFilterImpl from(final MagicTargetType location) {
final MagicCardFilterImpl curr = this;
return new MagicCardFilterImpl() {
public boolean accept(final MagicSource source,final MagicPlayer player,final MagicCard target) {
return curr.accept(source, player, target);
}
public boolean acceptType(final MagicTargetType targetType) {
return curr.acceptType(targetType) || targetType == location;
}
};
}
public MagicCardFilterImpl except(final MagicCard invalid) {
return new MagicOtherCardTargetFilter(this, invalid);
}
}