2014-05-05 00:14:34 -07:00
|
|
|
package magic.model;
|
|
|
|
|
2018-05-03 23:17:55 -07:00
|
|
|
import java.util.Arrays;
|
2017-04-08 03:29:49 -07:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.regex.Matcher;
|
2020-01-15 12:02:42 -08:00
|
|
|
|
2017-04-08 03:29:49 -07:00
|
|
|
import magic.data.EnglishToInt;
|
2018-05-03 23:17:55 -07:00
|
|
|
import magic.data.RomanToInt;
|
2017-04-08 03:29:49 -07:00
|
|
|
import magic.model.action.MagicPlayMod;
|
|
|
|
import magic.model.event.MagicEvent;
|
2015-12-18 17:24:55 -08:00
|
|
|
import magic.model.stack.MagicItemOnStack;
|
2015-04-06 20:30:06 -07:00
|
|
|
import magic.model.target.MagicTarget;
|
2015-12-08 18:09:53 -08:00
|
|
|
import magic.model.target.MagicTargetFilter;
|
|
|
|
import magic.model.target.MagicTargetFilterFactory;
|
2020-01-15 12:02:42 -08:00
|
|
|
import magic.model.target.MagicTargetHint;
|
2014-05-05 00:14:34 -07:00
|
|
|
|
2015-08-20 06:02:31 -07:00
|
|
|
public class ARG {
|
2015-12-10 07:14:42 -08:00
|
|
|
public static final String COLON = "\\s*:\\s*";
|
|
|
|
|
|
|
|
public static final String CHOICE = "(?<choice>(a|an|another|target) [^\\.]+?)";
|
2017-08-25 22:16:50 -07:00
|
|
|
public static final String TARGET_CONTROLS = "(?<tpgroup>[^\\.]* (?<tpchoice>target (player|opponent)) controls)";
|
2015-12-10 07:14:42 -08:00
|
|
|
public static final String CARD = "(?<choice>[^\\.]* card [^\\.]+?)";
|
2017-08-16 23:47:55 -07:00
|
|
|
public static final String THING = "(permanent|creature|artifact|land|spell or ability|spell|ability)";
|
|
|
|
public static final String PLAYER = "(player|opponent)";
|
2015-12-23 17:55:48 -08:00
|
|
|
public static final String EVENQUOTES = "(?=([^\"]*'[^\"]*')*[^\"]*$)";
|
2018-10-22 06:09:12 -07:00
|
|
|
public static final String CARDTYPE = "(?<cardtype>(creature|artifact|land|enchantment|conspiracy|instant|phenomenon|plane|planeswalker|scheme|sorcery|tribal|vanguard))";
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2016-09-18 05:20:42 -07:00
|
|
|
public static final String ENERGY = "(?<energy>(\\{E\\})+)";
|
|
|
|
public static int energy(final Matcher m) {
|
|
|
|
return m.group("energy").length() / 3;
|
|
|
|
}
|
|
|
|
|
2014-05-05 00:14:34 -07:00
|
|
|
public static final String NUMBER = "(?<number>[0-9]+)";
|
|
|
|
public static int number(final Matcher m) {
|
2017-08-09 03:00:04 -07:00
|
|
|
if (m.group("number") == null) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return Integer.parseInt(m.group("number"));
|
|
|
|
}
|
2014-05-05 00:14:34 -07:00
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2018-03-31 21:36:38 -07:00
|
|
|
public static final String NUMBER2 = "(?<number2>[0-9]+)";
|
|
|
|
public static int number2(final Matcher m) {
|
|
|
|
if (m.group("number2") == null) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return Integer.parseInt(m.group("number2"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-20 21:52:16 -07:00
|
|
|
public static final String AMOUNT = "(?<amount>(a|an|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|twenty|x|[0-9]+))";
|
2014-05-05 00:14:34 -07:00
|
|
|
public static int amount(final Matcher m) {
|
|
|
|
return EnglishToInt.convert(m.group("amount"));
|
|
|
|
}
|
2015-12-12 21:51:19 -08:00
|
|
|
public static MagicAmount amountObj(final Matcher m) {
|
|
|
|
return MagicAmountParser.build(m.group("amount"));
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2018-10-22 06:09:12 -07:00
|
|
|
public static MagicType cardType(final Matcher m) {
|
|
|
|
return MagicType.getType(m.group("cardtype"));
|
|
|
|
}
|
|
|
|
|
2015-12-20 17:54:22 -08:00
|
|
|
public static final String AMOUNT2 = "(?<amount2>[^ ]+?)";
|
2015-12-12 18:41:47 -08:00
|
|
|
public static int amount2(final Matcher m) {
|
|
|
|
return EnglishToInt.convert(m.group("amount2"));
|
|
|
|
}
|
2017-08-02 18:45:40 -07:00
|
|
|
public static MagicAmount amount2Obj(final Matcher m) {
|
|
|
|
return MagicAmountParser.build(m.group("amount2"));
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2017-08-03 19:39:07 -07:00
|
|
|
public static final String EACH = "( |, )?((for each|equal to|where X is) " + ARG.WORDRUN + ")?";
|
|
|
|
public static MagicAmount each(final Matcher m) {
|
|
|
|
return MagicAmountParser.build(ARG.wordrun(m));
|
|
|
|
}
|
|
|
|
|
2014-05-05 00:14:34 -07:00
|
|
|
public static final String COST = "(?<cost>.+)";
|
2016-05-31 20:36:56 -07:00
|
|
|
public static final String MAY_COST = "(?<cost>(?!search|draw|exile).+)";
|
2014-05-05 00:14:34 -07:00
|
|
|
public static String cost(final Matcher m) {
|
|
|
|
return m.group("cost");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
|
|
|
public static final String COLOR = "(?<color>[^ ]+)";
|
2018-03-31 21:36:38 -07:00
|
|
|
public static MagicColor color(final Matcher m) {
|
|
|
|
return MagicColor.getColor(m.group("color"));
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2014-05-05 00:14:34 -07:00
|
|
|
public static final String EFFECT = "(?<effect>.+)";
|
|
|
|
public static String effect(final Matcher m) {
|
|
|
|
return m.group("effect");
|
|
|
|
}
|
|
|
|
|
|
|
|
public static final String ANY = "(?<any>.+)";
|
|
|
|
public static String any(final Matcher m) {
|
|
|
|
return m.group("any");
|
|
|
|
}
|
|
|
|
|
|
|
|
public static final String MANA = "(?<mana>[^\\.]+)";
|
|
|
|
public static String mana(final Matcher m) {
|
|
|
|
return m.group("mana");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2014-08-22 18:56:08 -07:00
|
|
|
public static final String MANACOST = "(?<manacost>(\\{[A-Z\\d/]+\\})+)";
|
|
|
|
public static String manacost(final Matcher m) {
|
|
|
|
return m.group("manacost");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2014-05-05 00:14:34 -07:00
|
|
|
public static final String WORD1 = "(?<word1>[^ ]+)";
|
|
|
|
public static String word1(final Matcher m) {
|
|
|
|
return m.group("word1");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2014-05-05 00:14:34 -07:00
|
|
|
public static final String WORD2 = "(?<word2>[^ ]+)";
|
|
|
|
public static String word2(final Matcher m) {
|
|
|
|
return m.group("word2");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2015-04-22 22:20:05 -07:00
|
|
|
public static final String WORDRUN = "(?<wordrun>[^\\.\"]+?)";
|
2014-05-05 00:14:34 -07:00
|
|
|
public static String wordrun(final Matcher m) {
|
|
|
|
return m.group("wordrun");
|
|
|
|
}
|
|
|
|
|
2015-05-02 22:48:12 -07:00
|
|
|
public static final String WORDRUN2 = "(?<wordrun2>[^\\.\"]+?)";
|
2014-05-13 08:19:11 -07:00
|
|
|
public static String wordrun2(final Matcher m) {
|
|
|
|
return m.group("wordrun2");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2015-04-11 05:13:41 -07:00
|
|
|
public static final String COND = "(?<cond>[^,\\.\"]+)";
|
|
|
|
public static String cond(final Matcher m) {
|
|
|
|
return m.group("cond");
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2014-05-05 00:14:34 -07:00
|
|
|
public static final String PT = "(?<pt>[+-][0-9]+/[+-][0-9]+)";
|
2016-06-05 02:47:27 -07:00
|
|
|
public static final String XPT = "(?<pt>[+-][X0]+/[+-][X0]+)";
|
2015-04-13 18:47:27 -07:00
|
|
|
public static int[] pt(final Matcher m) {
|
|
|
|
final String[] pt = m.group("pt").replace("+","").split("/");
|
|
|
|
return new int[]{Integer.parseInt(pt[0]), Integer.parseInt(pt[1])};
|
|
|
|
}
|
2015-12-23 06:51:34 -08:00
|
|
|
public static String[] ptStr(final Matcher m) {
|
|
|
|
return m.group("pt").replace("+","").split("/");
|
|
|
|
}
|
2015-04-13 18:47:27 -07:00
|
|
|
public static MagicPowerToughness mpt(final Matcher m) {
|
|
|
|
final String[] pt = m.group("pt").replace("+","").split("/");
|
|
|
|
return new MagicPowerToughness(Integer.parseInt(pt[0]), Integer.parseInt(pt[1]));
|
2014-05-05 00:14:34 -07:00
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2015-12-20 18:02:31 -08:00
|
|
|
public static final String MODS = "(\\.|,)?( )?(?<mods>.+?)??";
|
2015-12-20 17:54:22 -08:00
|
|
|
public static List<MagicPlayMod> mods(final Matcher m) {
|
|
|
|
return MagicPlayMod.build(m.group("mods"));
|
|
|
|
}
|
|
|
|
|
2015-04-09 22:14:01 -07:00
|
|
|
public static final String IT = "((?<rn>rn)|(?<sn>sn))";
|
2015-04-06 20:30:06 -07:00
|
|
|
public static MagicPermanent itPermanent(final MagicEvent event, final Matcher m) {
|
2015-04-09 22:14:01 -07:00
|
|
|
if (m.group("rn") != null) {
|
2015-04-06 20:30:06 -07:00
|
|
|
return event.getRefPermanent();
|
|
|
|
} else {
|
|
|
|
return event.getPermanent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public static MagicSource itSource(final MagicEvent event, final Matcher m) {
|
2015-04-09 22:14:01 -07:00
|
|
|
if (m.group("rn") != null) {
|
2015-04-06 20:30:06 -07:00
|
|
|
return event.getRefSource();
|
|
|
|
} else {
|
|
|
|
return event.getSource();
|
|
|
|
}
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2015-04-09 22:14:01 -07:00
|
|
|
public static final String YOU = "((?<rn>(rn))|(?<pn>(pn||you)))";
|
2015-04-06 20:30:06 -07:00
|
|
|
public static MagicTarget youTarget(final MagicEvent event, final Matcher m) {
|
|
|
|
if (m.group("rn") != null) {
|
|
|
|
return event.getRefTarget();
|
|
|
|
} else {
|
|
|
|
return event.getPlayer();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public static MagicPlayer youPlayer(final MagicEvent event, final Matcher m) {
|
|
|
|
if (m.group("rn") != null) {
|
|
|
|
return event.getRefPlayer();
|
|
|
|
} else {
|
|
|
|
return event.getPlayer();
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2015-12-14 17:02:04 -08:00
|
|
|
private static final String TNC = "(that [^ ]+'s|its) controller( or that player)?";
|
|
|
|
public static final String PLAYERS = "((?<rnc>rn's controller)|(?<tnc>" + TNC + ")|(?<rn>rn)|(?<pn>(pn||you))|" + CHOICE + "|(?<group>[^\\.]+?))";
|
2015-12-08 18:09:53 -08:00
|
|
|
public static List<MagicPlayer> players(final MagicEvent event, final Matcher m, final MagicTargetFilter<MagicPlayer> filter) {
|
2015-12-13 21:02:53 -08:00
|
|
|
if (m.group("rnc") != null) {
|
|
|
|
return Collections.singletonList(event.getRefObject().getController());
|
2015-12-14 06:40:14 -08:00
|
|
|
} else if (m.group("tnc") != null) {
|
|
|
|
return event.listTargetController();
|
2015-12-13 21:02:53 -08:00
|
|
|
} else if (m.group("rn") != null) {
|
2015-12-08 18:09:53 -08:00
|
|
|
return Collections.singletonList(event.getRefPlayer());
|
|
|
|
} else if (m.group("pn") != null) {
|
|
|
|
return Collections.singletonList(event.getPlayer());
|
2015-12-11 17:03:05 -08:00
|
|
|
} else if (m.group("choice") != null) {
|
|
|
|
return event.listTargetPlayer();
|
2015-12-08 18:09:53 -08:00
|
|
|
} else {
|
|
|
|
return filter.filter(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static MagicTargetFilter<MagicPlayer> playersParse(final Matcher m) {
|
|
|
|
if (m.group("group") != null) {
|
|
|
|
return MagicTargetFilterFactory.Player(m.group("group"));
|
|
|
|
} else {
|
|
|
|
return MagicTargetFilterFactory.PLAYER;
|
|
|
|
}
|
|
|
|
}
|
2015-08-20 06:02:31 -07:00
|
|
|
|
2017-08-21 19:00:03 -07:00
|
|
|
public static final String PERMANENTS = "((?<rn>rn)|(?<sn>sn)|" + CHOICE + "|" + TARGET_CONTROLS + "|(?<group>[^\\.]+?))";
|
2015-12-09 05:31:54 -08:00
|
|
|
public static List<MagicPermanent> permanents(final MagicEvent event, final Matcher m, final MagicTargetFilter<MagicPermanent> filter) {
|
|
|
|
if (m.group("rn") != null) {
|
|
|
|
return Collections.singletonList(event.getRefPermanent());
|
2015-12-09 07:33:01 -08:00
|
|
|
} else if (m.group("sn") != null) {
|
2015-12-09 05:31:54 -08:00
|
|
|
return Collections.singletonList(event.getPermanent());
|
2015-12-10 07:14:42 -08:00
|
|
|
} else if (m.group("choice") != null) {
|
|
|
|
return event.listTargetPermanent();
|
2017-08-25 17:28:55 -07:00
|
|
|
} else if (m.group("tpchoice") != null) {
|
2017-08-21 19:00:03 -07:00
|
|
|
return filter.filter(event.getSource(), event.listTargetPlayer().get(0), MagicTargetHint.None);
|
2015-12-09 05:31:54 -08:00
|
|
|
} else {
|
|
|
|
return filter.filter(event);
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2015-12-09 05:31:54 -08:00
|
|
|
public static MagicTargetFilter<MagicPermanent> permanentsParse(final Matcher m) {
|
|
|
|
if (m.group("group") != null) {
|
|
|
|
return MagicTargetFilterFactory.Permanent(m.group("group"));
|
2017-08-25 22:16:50 -07:00
|
|
|
} else if (m.group("tpgroup") != null) {
|
|
|
|
return MagicTargetFilterFactory.Permanent(m.group("tpgroup").replaceFirst("target (player|opponent) controls", "you control"));
|
2015-12-09 05:31:54 -08:00
|
|
|
} else {
|
|
|
|
return MagicTargetFilterFactory.ANY;
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2015-12-14 17:02:04 -08:00
|
|
|
public static final String TARGETS = "((?<rnc1>rn's controller)|(?<tnc1>" + TNC + ")|(?<rn1>rn)|(?<sn1>sn)|(?<pn1>(pn||you))|" + CHOICE + "|(?<group1>[^\\.]+?))";
|
2015-12-14 06:23:22 -08:00
|
|
|
public static List<? extends MagicTarget> targets(final MagicEvent event, final Matcher m, final MagicTargetFilter<MagicTarget> filter) {
|
2015-12-13 22:59:22 -08:00
|
|
|
if (m.group("rnc1") != null) {
|
|
|
|
return Collections.singletonList(event.getRefObject().getController());
|
2015-12-14 06:23:22 -08:00
|
|
|
} else if (m.group("tnc1") != null) {
|
|
|
|
return event.listTargetController();
|
2015-12-13 22:59:22 -08:00
|
|
|
} else if (m.group("rn1") != null) {
|
2015-12-11 19:21:38 -08:00
|
|
|
return Collections.singletonList(event.getRefTarget());
|
2015-12-12 19:16:34 -08:00
|
|
|
} else if (m.group("pn1") != null) {
|
2015-12-11 19:21:38 -08:00
|
|
|
return Collections.singletonList(event.getPlayer());
|
2015-12-12 19:16:34 -08:00
|
|
|
} else if (m.group("sn1") != null) {
|
2015-12-11 19:21:38 -08:00
|
|
|
return Collections.singletonList(event.getPermanent());
|
|
|
|
} else if (m.group("choice") != null) {
|
|
|
|
return event.listTarget();
|
|
|
|
} else {
|
|
|
|
return filter.filter(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static MagicTargetFilter<MagicTarget> targetsParse(final Matcher m) {
|
2015-12-12 19:16:34 -08:00
|
|
|
if (m.group("group1") != null) {
|
|
|
|
return MagicTargetFilterFactory.Target(m.group("group1"));
|
|
|
|
} else {
|
|
|
|
return MagicTargetFilterFactory.ONE;
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2015-12-14 17:02:04 -08:00
|
|
|
public static final String TARGETS2 = "((?<tnc2>" + TNC + ")|(?<rn2>rn)|(?<sn2>sn)|(?<pn2>(pn||you))|(?<group2>[^\\.]+?))";
|
2015-12-14 06:40:14 -08:00
|
|
|
public static List<? extends MagicTarget> targets2(final MagicEvent event, final Matcher m, final MagicTargetFilter<MagicTarget> filter) {
|
|
|
|
if (m.group("tnc2") != null) {
|
|
|
|
return event.listTargetController();
|
|
|
|
} else if (m.group("rn2") != null) {
|
2015-12-12 19:16:34 -08:00
|
|
|
return Collections.singletonList(event.getRefTarget());
|
|
|
|
} else if (m.group("pn2") != null) {
|
|
|
|
return Collections.singletonList(event.getPlayer());
|
|
|
|
} else if (m.group("sn2") != null) {
|
|
|
|
return Collections.singletonList(event.getPermanent());
|
|
|
|
} else {
|
|
|
|
return filter.filter(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static MagicTargetFilter<MagicTarget> targets2Parse(final Matcher m) {
|
|
|
|
if (m.group("group2") != null) {
|
|
|
|
return MagicTargetFilterFactory.Target(m.group("group2"));
|
2015-12-11 19:21:38 -08:00
|
|
|
} else {
|
|
|
|
return MagicTargetFilterFactory.ONE;
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2017-07-19 20:06:53 -07:00
|
|
|
public static final String GRAVEYARD_CARDS = "((?<choice>[^\\.]* card [^\\.]+? graveyard)|(?<group>[^\\.]* cards [^\\.]+? graveyard))";
|
2015-12-12 19:16:34 -08:00
|
|
|
public static final String CARDS = "((?<choice>[^\\.]* card [^\\.]+?)|(?<group>[^\\.]* cards [^\\.]+?))";
|
2017-07-20 20:06:56 -07:00
|
|
|
public static String cards(final Matcher m) {
|
|
|
|
if (m.group("choice") != null) {
|
|
|
|
return m.group("choice");
|
|
|
|
} else {
|
|
|
|
return m.group("group");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-12 03:59:29 -08:00
|
|
|
public static List<MagicCard> cards(final MagicEvent event, final Matcher m, final MagicTargetFilter<MagicCard> filter) {
|
|
|
|
if (m.group("choice") != null) {
|
|
|
|
return event.listTargetCard();
|
|
|
|
} else {
|
|
|
|
return filter.filter(event);
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2015-12-12 03:59:29 -08:00
|
|
|
public static MagicTargetFilter<MagicCard> cardsParse(final Matcher m) {
|
|
|
|
if (m.group("group") != null) {
|
|
|
|
return MagicTargetFilterFactory.Card(m.group("group"));
|
|
|
|
} else {
|
|
|
|
return MagicTargetFilterFactory.CARD_FROM_HAND;
|
|
|
|
}
|
|
|
|
}
|
2015-12-18 17:24:55 -08:00
|
|
|
|
|
|
|
public static final String ITEMS = "((?<rn>rn)|(?<sn>sn)|" + CHOICE + "|(?<group>[^\\.]+?))";
|
|
|
|
public static List<MagicItemOnStack> items(final MagicEvent event, final Matcher m, final MagicTargetFilter<MagicItemOnStack> filter) {
|
|
|
|
if (m.group("rn") != null) {
|
|
|
|
return Collections.singletonList(event.getRefItemOnStack());
|
|
|
|
} else if (m.group("sn") != null) {
|
|
|
|
return Collections.singletonList(event.getItemOnStack());
|
|
|
|
} else if (m.group("choice") != null) {
|
|
|
|
return event.listTargetItem();
|
|
|
|
} else {
|
|
|
|
return filter.filter(event);
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 02:54:52 -08:00
|
|
|
|
2015-12-18 17:24:55 -08:00
|
|
|
public static MagicTargetFilter<MagicItemOnStack> itemsParse(final Matcher m) {
|
|
|
|
if (m.group("group") != null) {
|
|
|
|
return MagicTargetFilterFactory.ItemOnStack(m.group("group"));
|
|
|
|
} else {
|
|
|
|
return MagicTargetFilterFactory.SPELL_OR_ABILITY;
|
|
|
|
}
|
|
|
|
}
|
2018-05-03 23:17:55 -07:00
|
|
|
|
|
|
|
public static final String CHAPTERS = "(?<chapters>I+(, I+)*)";
|
|
|
|
public static int[] chapters(final Matcher m) {
|
|
|
|
final String[] chapters = m.group("chapters").split(", ");
|
|
|
|
return Arrays.stream(chapters).mapToInt(RomanToInt::convert).toArray();
|
|
|
|
}
|
|
|
|
|
2015-08-20 06:02:31 -07:00
|
|
|
}
|