magarena/src/magic/model/event/MagicCostEvent.java

362 lines
16 KiB
Java

package magic.model.event;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import magic.model.ARG;
import magic.model.MagicCard;
import magic.model.MagicCounterType;
import magic.model.MagicLocationType;
import magic.model.MagicManaCost;
import magic.model.MagicPermanent;
import magic.model.MagicSource;
import magic.model.choice.MagicTargetChoice;
import magic.model.target.MagicOtherCardTargetFilter;
import magic.model.target.MagicOtherPermanentTargetFilter;
import magic.model.target.MagicTargetFilter;
import magic.model.target.MagicTargetFilterFactory;
public enum MagicCostEvent {
SacrificeSelf("Sacrifice (SN|this permanent|this land)") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicSacrificeEvent((MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
},
SacrificeMultiple("Sacrifice (?<another>another )?(" + ARG.AMOUNT + " )?" + ARG.ANY) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amt = ARG.amount(arg);
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg)) + " you control";
final MagicTargetFilter<MagicPermanent> regular = MagicTargetFilterFactory.Permanent(chosen);
final MagicTargetFilter<MagicPermanent> filter = arg.group("another") != null ?
new MagicOtherPermanentTargetFilter(regular, (MagicPermanent)source) :
regular;
final MagicTargetChoice choice = new MagicTargetChoice(
filter,
("aeiou".indexOf(chosen.charAt(0)) >= 0 ? "an " : "a ") + chosen
);
return new MagicRepeatedCostEvent(source, choice, amt, MagicChainEventFactory.Sac);
}
},
BounceSelf("Return SN to its owner's hand") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicBouncePermanentEvent(source, (MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
},
BounceMultiple("Return ((?<another>another )|" + ARG.AMOUNT + " )?" + ARG.ANY + " to (their|its) owner's hand") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amt = ARG.amount(arg);
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg));
final MagicTargetFilter<MagicPermanent> regular = MagicTargetFilterFactory.Permanent(chosen);
final MagicTargetFilter<MagicPermanent> filter = arg.group("another") != null ?
new MagicOtherPermanentTargetFilter(regular, (MagicPermanent)source) :
regular;
final MagicTargetChoice choice = new MagicTargetChoice(
filter,
("aeiou".indexOf(chosen.charAt(0)) >= 0 ? "an " : "a ") + chosen
);
return new MagicRepeatedCostEvent(source, choice, amt, MagicChainEventFactory.Bounce);
}
},
DiscardAll("Discard( all the cards in)? your hand") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicDiscardHandEvent(source);
}
},
DiscardSelf("Discard SN") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicDiscardSelfEvent((MagicCard)source);
}
},
DiscardCards("Discard " + ARG.AMOUNT + " card(s)?") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amount = ARG.amount(arg);
return new MagicDiscardEvent(source, amount);
}
},
DiscardCardsRandom("Discard " + ARG.AMOUNT + " card(s)? at random") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amount = ARG.amount(arg);
return MagicDiscardEvent.Random(source, amount);
}
},
DiscardChosen("Discard " + ARG.ANY) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final String chosen = ARG.any(arg) + " from your hand";
final MagicTargetFilter<MagicCard> regular = MagicTargetFilterFactory.Card(chosen);
final MagicTargetFilter<MagicCard> filter = (source instanceof MagicCard) ? new MagicOtherCardTargetFilter(regular, (MagicCard)source) : regular;
return new MagicDiscardChosenEvent(source, new MagicTargetChoice(filter, chosen));
}
},
ExileSelf("Exile SN") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicExileEvent((MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
},
ExileCardSelf("Exile SN from your graveyard") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicExileSelfEvent((MagicCard)source, MagicLocationType.Graveyard);
}
},
ExileTopNCardsLibrary("Exile the top( " + ARG.AMOUNT + ")? card(s)? of your library") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicExileTopLibraryEvent(source, ARG.amount(arg));
}
},
ExileCards("Exile ((?<another>another )|" + ARG.AMOUNT + " )?(other )?(?<any>.*card.*)") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amt = ARG.amount(arg);
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg));
final MagicTargetFilter<MagicCard> regular = MagicTargetFilterFactory.Card(chosen);
final MagicTargetFilter<MagicCard> filter = (source instanceof MagicCard) ? new MagicOtherCardTargetFilter(regular, (MagicCard)source) : regular;
final MagicTargetChoice choice = new MagicTargetChoice(
filter,
("aeiou".indexOf(chosen.charAt(0)) >= 0 ? "an " : "a ") + chosen
);
return new MagicRepeatedCostEvent(
source,
choice,
amt,
MagicChainEventFactory.ExileCard
);
}
},
ExileMultiple("Exile ((?<another>another )|" + ARG.AMOUNT + " )?" + ARG.ANY) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amt = ARG.amount(arg);
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg));
final MagicTargetFilter<MagicPermanent> regular = MagicTargetFilterFactory.Permanent(chosen);
final MagicTargetFilter<MagicPermanent> filter = arg.group("another") != null ?
new MagicOtherPermanentTargetFilter(regular, (MagicPermanent)source) :
regular;
final MagicTargetChoice choice = new MagicTargetChoice(
filter,
("aeiou".indexOf(chosen.charAt(0)) >= 0 ? "an " : "a ") + chosen
);
return new MagicRepeatedCostEvent(source, choice, amt, MagicChainEventFactory.ExilePerm);
}
},
TapSelf("\\{T\\}") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicTapEvent((MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
},
ExertSelf("Exert SN") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicExertEvent((MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
},
UntapSelf("\\{Q\\}") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicUntapEvent((MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
},
TapMultiple("Tap (?<another>another )?(" + ARG.AMOUNT + " )?untapped " + ARG.ANY) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amt = ARG.amount(arg);
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg));
final MagicTargetFilter<MagicPermanent> untapped = MagicTargetFilterFactory.untapped(MagicTargetFilterFactory.Permanent(chosen));
final MagicTargetFilter<MagicPermanent> filter = arg.group("another") != null ?
new MagicOtherPermanentTargetFilter(untapped, (MagicPermanent)source) :
untapped;
final MagicTargetChoice choice = new MagicTargetChoice(filter, "an untapped " + chosen);
return new MagicRepeatedCostEvent(source, choice, amt, MagicChainEventFactory.Tap);
}
},
UntapMultiple("Untap (?<another>another )?(" + ARG.AMOUNT + " )?tapped " + ARG.ANY) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amt = ARG.amount(arg);
final String chosen = MagicTargetFilterFactory.toSingular(ARG.any(arg));
final MagicTargetFilter<MagicPermanent> tapped = MagicTargetFilterFactory.tapped(MagicTargetFilterFactory.Permanent(chosen));
final MagicTargetFilter<MagicPermanent> filter = arg.group("another") != null ?
new MagicOtherPermanentTargetFilter(tapped, (MagicPermanent)source) :
tapped;
final MagicTargetChoice choice = new MagicTargetChoice(filter, "a tapped " + chosen);
return new MagicRepeatedCostEvent(source, choice, amt, MagicChainEventFactory.Untap);
}
},
PayLife("Pay " + ARG.NUMBER + " life") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicPayLifeEvent(source, ARG.number(arg));
}
},
PayEnergy("Pay " + ARG.ENERGY) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicPayEnergyEvent(source, ARG.energy(arg));
}
},
RemoveCounterSelf("Remove " + ARG.AMOUNT + " " + ARG.WORD1 + " counter(s)? from SN") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amount = ARG.amount(arg);
final MagicCounterType counterType = MagicCounterType.getCounterRaw(ARG.word1(arg));
return new MagicRemoveCounterEvent((MagicPermanent)source, counterType, amount);
}
@Override
public boolean isIndependent() {
return false;
}
},
RemoveCounterChosen("Remove a " + ARG.WORD1 + " counter from a creature you control") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final MagicCounterType counterType = MagicCounterType.getCounterRaw(ARG.word1(arg));
return new MagicRemoveCounterChosenEvent(source, counterType);
}
},
AddCounterSelf("Put " + ARG.AMOUNT + " " + ARG.WORD1 + " counter(s)? on SN") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final int amount = ARG.amount(arg);
final MagicCounterType counterType = MagicCounterType.getCounterRaw(ARG.word1(arg));
return new MagicAddCounterEvent((MagicPermanent)source, counterType, amount);
}
@Override
public boolean isIndependent() {
return false;
}
},
AddCounterChosen("Put a " + ARG.WORD1 + " counter on a creature you control") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final MagicCounterType counterType = MagicCounterType.getCounterRaw(ARG.word1(arg));
return new MagicAddCounterChosenEvent(source, counterType);
}
},
PayMana("(pay )?" + ARG.MANACOST) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicPayManaCostEvent(source, MagicManaCost.create(ARG.manacost(arg)));
}
},
AltManaCost("(pay )?alt mana cost " + ARG.MANACOST) {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
final MagicManaCost origCost = MagicManaCost.create(ARG.manacost(arg));
final MagicManaCost cost = origCost == MagicManaCost.ZERO ? MagicManaCost.NONE : origCost;
return (source instanceof MagicCard) ?
MagicPayManaCostEvent.Cast((MagicCard)source, cost) :
new MagicPayManaCostEvent(source, cost);
}
},
DamageYou("SN deals " + ARG.NUMBER + " damage to you") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return MagicRuleEventAction.create(arg.group()).getEvent(source);
}
},
DoesntUntap("SN doesn't untap during your next untap step") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return MagicRuleEventAction.create(arg.group()).getEvent(source);
}
@Override
public boolean isIndependent() {
return false;
}
},
MillSelf("Put the top( " + ARG.AMOUNT + ")? card(s)? of your library into your graveyard") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicMillEvent(source, ARG.amount(arg));
}
},
Processor("Put a card an opponent owns from exile into that player's graveyard") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicProcessorEvent(source);
}
},
PutSelfOnBottomLibrary("Put SN on the bottom of its owner's library") {
@Override
public MagicEvent toEvent(final Matcher arg, final MagicSource source) {
return new MagicPutOnBottomLibraryEvent((MagicPermanent)source);
}
@Override
public boolean isIndependent() {
return false;
}
}
;
public boolean isIndependent() {
return true;
}
private final Pattern pattern;
private MagicCostEvent(final String regex) {
pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
}
public Matcher matched(final String rule) {
final Matcher matcher = pattern.matcher(rule);
final boolean matches = matcher.matches();
if (!matches) {
throw new RuntimeException("unknown cost: \"" + rule + "\"");
}
return matcher;
}
private Matcher matcher(final String rule) {
return pattern.matcher(rule);
}
public abstract MagicEvent toEvent(final Matcher arg, final MagicSource source);
public static final MagicCostEvent build(final String cost) {
for (final MagicCostEvent rule : values()) {
final Matcher arg = rule.matcher(cost);
if (arg.matches() && (arg.groupCount() == 0 || rule.toEvent(arg, MagicPermanent.NONE).isValid())) {
return rule;
}
}
throw new RuntimeException("unknown cost \"" + cost + "\"");
}
}