package magic.model; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import magic.data.EnglishToInt; import magic.data.RomanToInt; import magic.model.action.MagicPlayMod; import magic.model.event.MagicEvent; import magic.model.stack.MagicItemOnStack; import magic.model.target.MagicTarget; import magic.model.target.MagicTargetFilter; import magic.model.target.MagicTargetFilterFactory; import magic.model.target.MagicTargetHint; public class ARG { public static final String COLON = "\\s*:\\s*"; public static final String CHOICE = "(?(a|an|another|target) [^\\.]+?)"; public static final String TARGET_CONTROLS = "(?[^\\.]* (?target (player|opponent)) controls)"; public static final String CARD = "(?[^\\.]* card [^\\.]+?)"; public static final String THING = "(permanent|creature|artifact|land|spell or ability|spell|ability)"; public static final String PLAYER = "(player|opponent)"; public static final String EVENQUOTES = "(?=([^\"]*'[^\"]*')*[^\"]*$)"; public static final String CARDTYPE = "(?(creature|artifact|land|enchantment|conspiracy|instant|phenomenon|plane|planeswalker|scheme|sorcery|tribal|vanguard))"; public static final String ENERGY = "(?(\\{E\\})+)"; public static int energy(final Matcher m) { return m.group("energy").length() / 3; } public static final String NUMBER = "(?[0-9]+)"; public static int number(final Matcher m) { if (m.group("number") == null) { return 1; } else { return Integer.parseInt(m.group("number")); } } public static final String NUMBER2 = "(?[0-9]+)"; public static int number2(final Matcher m) { if (m.group("number2") == null) { return 1; } else { return Integer.parseInt(m.group("number2")); } } public static final String AMOUNT = "(?(a|an|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|twenty|x|[0-9]+))"; public static int amount(final Matcher m) { return EnglishToInt.convert(m.group("amount")); } public static MagicAmount amountObj(final Matcher m) { return MagicAmountParser.build(m.group("amount")); } public static MagicType cardType(final Matcher m) { return MagicType.getType(m.group("cardtype")); } public static final String AMOUNT2 = "(?[^ ]+?)"; public static int amount2(final Matcher m) { return EnglishToInt.convert(m.group("amount2")); } public static MagicAmount amount2Obj(final Matcher m) { return MagicAmountParser.build(m.group("amount2")); } 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)); } public static final String COST = "(?.+)"; public static final String MAY_COST = "(?(?!search|draw|exile).+)"; public static String cost(final Matcher m) { return m.group("cost"); } public static final String COLOR = "(?[^ ]+)"; public static MagicColor color(final Matcher m) { return MagicColor.getColor(m.group("color")); } public static final String EFFECT = "(?.+)"; public static String effect(final Matcher m) { return m.group("effect"); } public static final String ANY = "(?.+)"; public static String any(final Matcher m) { return m.group("any"); } public static final String MANA = "(?[^\\.]+)"; public static String mana(final Matcher m) { return m.group("mana"); } public static final String MANACOST = "(?(\\{[A-Z\\d/]+\\})+)"; public static String manacost(final Matcher m) { return m.group("manacost"); } public static final String WORD1 = "(?[^ ]+)"; public static String word1(final Matcher m) { return m.group("word1"); } public static final String WORD2 = "(?[^ ]+)"; public static String word2(final Matcher m) { return m.group("word2"); } public static final String WORDRUN = "(?[^\\.\"]+?)"; public static String wordrun(final Matcher m) { return m.group("wordrun"); } public static final String WORDRUN2 = "(?[^\\.\"]+?)"; public static String wordrun2(final Matcher m) { return m.group("wordrun2"); } public static final String COND = "(?[^,\\.\"]+)"; public static String cond(final Matcher m) { return m.group("cond"); } public static final String PT = "(?[+-][0-9]+/[+-][0-9]+)"; public static final String XPT = "(?[+-][X0]+/[+-][X0]+)"; 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])}; } public static String[] ptStr(final Matcher m) { return m.group("pt").replace("+","").split("/"); } 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])); } public static final String MODS = "(\\.|,)?( )?(?.+?)??"; public static List mods(final Matcher m) { return MagicPlayMod.build(m.group("mods")); } public static final String IT = "((?rn)|(?sn))"; public static MagicPermanent itPermanent(final MagicEvent event, final Matcher m) { if (m.group("rn") != null) { return event.getRefPermanent(); } else { return event.getPermanent(); } } public static MagicSource itSource(final MagicEvent event, final Matcher m) { if (m.group("rn") != null) { return event.getRefSource(); } else { return event.getSource(); } } public static final String YOU = "((?(rn))|(?(pn||you)))"; 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(); } } private static final String TNC = "(that [^ ]+'s|its) controller( or that player)?"; public static final String PLAYERS = "((?rn's controller)|(?" + TNC + ")|(?rn)|(?(pn||you))|" + CHOICE + "|(?[^\\.]+?))"; public static List players(final MagicEvent event, final Matcher m, final MagicTargetFilter filter) { if (m.group("rnc") != null) { return Collections.singletonList(event.getRefObject().getController()); } else if (m.group("tnc") != null) { return event.listTargetController(); } else if (m.group("rn") != null) { return Collections.singletonList(event.getRefPlayer()); } else if (m.group("pn") != null) { return Collections.singletonList(event.getPlayer()); } else if (m.group("choice") != null) { return event.listTargetPlayer(); } else { return filter.filter(event); } } public static MagicTargetFilter playersParse(final Matcher m) { if (m.group("group") != null) { return MagicTargetFilterFactory.Player(m.group("group")); } else { return MagicTargetFilterFactory.PLAYER; } } public static final String PERMANENTS = "((?rn)|(?sn)|" + CHOICE + "|" + TARGET_CONTROLS + "|(?[^\\.]+?))"; public static List permanents(final MagicEvent event, final Matcher m, final MagicTargetFilter filter) { if (m.group("rn") != null) { return Collections.singletonList(event.getRefPermanent()); } else if (m.group("sn") != null) { return Collections.singletonList(event.getPermanent()); } else if (m.group("choice") != null) { return event.listTargetPermanent(); } else if (m.group("tpchoice") != null) { return filter.filter(event.getSource(), event.listTargetPlayer().get(0), MagicTargetHint.None); } else { return filter.filter(event); } } public static MagicTargetFilter permanentsParse(final Matcher m) { if (m.group("group") != null) { return MagicTargetFilterFactory.Permanent(m.group("group")); } else if (m.group("tpgroup") != null) { return MagicTargetFilterFactory.Permanent(m.group("tpgroup").replaceFirst("target (player|opponent) controls", "you control")); } else { return MagicTargetFilterFactory.ANY; } } public static final String TARGETS = "((?rn's controller)|(?" + TNC + ")|(?rn)|(?sn)|(?(pn||you))|" + CHOICE + "|(?[^\\.]+?))"; public static List targets(final MagicEvent event, final Matcher m, final MagicTargetFilter filter) { if (m.group("rnc1") != null) { return Collections.singletonList(event.getRefObject().getController()); } else if (m.group("tnc1") != null) { return event.listTargetController(); } else if (m.group("rn1") != null) { return Collections.singletonList(event.getRefTarget()); } else if (m.group("pn1") != null) { return Collections.singletonList(event.getPlayer()); } else if (m.group("sn1") != null) { return Collections.singletonList(event.getPermanent()); } else if (m.group("choice") != null) { return event.listTarget(); } else { return filter.filter(event); } } public static MagicTargetFilter targetsParse(final Matcher m) { if (m.group("group1") != null) { return MagicTargetFilterFactory.Target(m.group("group1")); } else { return MagicTargetFilterFactory.ONE; } } public static final String TARGETS2 = "((?" + TNC + ")|(?rn)|(?sn)|(?(pn||you))|(?[^\\.]+?))"; public static List targets2(final MagicEvent event, final Matcher m, final MagicTargetFilter filter) { if (m.group("tnc2") != null) { return event.listTargetController(); } else if (m.group("rn2") != null) { 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 targets2Parse(final Matcher m) { if (m.group("group2") != null) { return MagicTargetFilterFactory.Target(m.group("group2")); } else { return MagicTargetFilterFactory.ONE; } } public static final String GRAVEYARD_CARDS = "((?[^\\.]* card [^\\.]+? graveyard)|(?[^\\.]* cards [^\\.]+? graveyard))"; public static final String CARDS = "((?[^\\.]* card [^\\.]+?)|(?[^\\.]* cards [^\\.]+?))"; public static String cards(final Matcher m) { if (m.group("choice") != null) { return m.group("choice"); } else { return m.group("group"); } } public static List cards(final MagicEvent event, final Matcher m, final MagicTargetFilter filter) { if (m.group("choice") != null) { return event.listTargetCard(); } else { return filter.filter(event); } } public static MagicTargetFilter cardsParse(final Matcher m) { if (m.group("group") != null) { return MagicTargetFilterFactory.Card(m.group("group")); } else { return MagicTargetFilterFactory.CARD_FROM_HAND; } } public static final String ITEMS = "((?rn)|(?sn)|" + CHOICE + "|(?[^\\.]+?))"; public static List items(final MagicEvent event, final Matcher m, final MagicTargetFilter 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); } } public static MagicTargetFilter itemsParse(final Matcher m) { if (m.group("group") != null) { return MagicTargetFilterFactory.ItemOnStack(m.group("group")); } else { return MagicTargetFilterFactory.SPELL_OR_ABILITY; } } public static final String 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(); } }