From a829dc72bcce2f710d3fb2d6e6049b663fdb2988 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Sat, 17 Feb 2018 15:25:51 +0100 Subject: [PATCH] CardFactoryUtil: make CantBeBlockedBy into new StaticAbility --- .../src/main/java/forge/game/card/Card.java | 115 +----------------- .../java/forge/game/card/CardFactoryUtil.java | 114 +++++++++++++++++ .../java/forge/game/combat/CombatUtil.java | 28 ----- 3 files changed, 117 insertions(+), 140 deletions(-) diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 73192aa9796..9d160f25d16 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -18,7 +18,6 @@ package forge.game.card; import com.esotericsoftware.minlog.Log; -import com.google.common.base.Function; import com.google.common.collect.*; import forge.GameCommand; import forge.ImageKeys; @@ -1537,6 +1536,7 @@ public class Card extends GameEntity implements Comparable { sbLong.append(keyword).append("\r\n"); } else if (keyword.startsWith("Strive") || keyword.startsWith("Escalate") || keyword.startsWith("ETBReplacement") + || keyword.startsWith("CantBeBlockedBy ") || keyword.equals("CARDNAME enters the battlefield tapped.") || keyword.startsWith("UpkeepCost")) { } else if (keyword.startsWith("Provoke") || keyword.startsWith("Ingest") || keyword.equals("Unleash") @@ -1595,12 +1595,9 @@ public class Card extends GameEntity implements Comparable { || keyword.startsWith("Amplify") || keyword.startsWith("Ninjutsu") || keyword.startsWith("Cycling") || keyword.startsWith("TypeCycling")) { // keyword parsing takes care of adding a proper description - } else if (keyword.startsWith("CantBeBlockedBy")) { + } else if (keyword.startsWith("CantBeBlockedByAmount")) { sbLong.append(getName()).append(" can't be blocked "); - if (keyword.startsWith("CantBeBlockedByAmount")) - sbLong.append(getTextForKwCantBeBlockedByAmount(keyword)); - else - sbLong.append(getTextForKwCantBeBlockedByType(keyword)); + sbLong.append(getTextForKwCantBeBlockedByAmount(keyword)); } else if (keyword.startsWith("CantBlock")) { sbLong.append(getName()).append(" can't block "); if (keyword.contains("CardUID")) { @@ -1657,112 +1654,6 @@ public class Card extends GameEntity implements Comparable { return byClause + Lang.nounWithNumeral(cnt, isLT ? "or more creature" : "creature"); } - private static String getTextForKwCantBeBlockedByType(final String keyword) { - boolean negative = true; - final List subs = Lists.newArrayList(TextUtil.split(keyword.split(" ", 2)[1], ',')); - final List> subsAnd = Lists.newArrayList(); - final List orClauses = Lists.newArrayList(); - for (final String expession : subs) { - final List parts = Lists.newArrayList(expession.split("[.+]")); - for (int p = 0; p < parts.size(); p++) { - final String part = parts.get(p); - if (part.equalsIgnoreCase("creature")) { - parts.remove(p--); - continue; - } - // based on suppossition that each expression has at least 1 predicate except 'creature' - negative &= part.contains("non") || part.contains("without"); - } - subsAnd.add(parts); - } - - final boolean allNegative = negative; - final String byClause = allNegative ? "except by " : "by "; - - final Function, String> withToString = new Function, String>() { - @Override - public String apply(Pair inp) { - boolean useNon = inp.getKey() == allNegative; - return (useNon ? "*NO* " : "") + inp.getRight(); - } - }; - - for (final List andOperands : subsAnd) { - final List> prependedAdjectives = Lists.newArrayList(); - final List> postponedAdjectives = Lists.newArrayList(); - String creatures = null; - - for (String part : andOperands) { - boolean positive = true; - if (part.startsWith("non")) { - part = part.substring(3); - positive = false; - } - if (part.startsWith("with")) { - positive = !part.startsWith("without"); - postponedAdjectives.add(Pair.of(positive, part.substring(positive ? 4 : 7))); - } else if (part.startsWith("powerLEX")) {// Kraken of the Straits - postponedAdjectives.add(Pair.of(true, "power less than the number of islands you control")); - } else if (part.startsWith("power")) { - int kwLength = 5; - String opName = Expressions.operatorName(part.substring(kwLength, kwLength + 2)); - String operand = part.substring(kwLength + 2); - postponedAdjectives.add(Pair.of(true, "power" + opName + operand)); - } else if (CardType.isACreatureType(part)) { - if (creatures != null && CardType.isACreatureType(creatures)) { // e.g. Kor Castigator - creatures = StringUtils.capitalize(Lang.getPlural(part)) + creatures; - } else { - creatures = StringUtils.capitalize(Lang.getPlural(part)) + (creatures == null ? "" : " or " + creatures); - } - // Kor Castigator and other similar creatures with composite subtype Eldrazi Scion in their text - creatures = TextUtil.fastReplace(creatures, "Scions or Eldrazis", "Eldrazi Scions"); - } else { - prependedAdjectives.add(Pair.of(positive, part.toLowerCase())); - } - } - - StringBuilder sbShort = new StringBuilder(); - if (allNegative) { - boolean isFirst = true; - for (Pair pre : prependedAdjectives) { - if (isFirst) isFirst = false; - else sbShort.append(" and/or "); - - boolean useNon = pre.getKey() == allNegative; - if (useNon) sbShort.append("non-"); - sbShort.append(pre.getValue()).append(" ").append(creatures == null ? "creatures" : creatures); - } - if (prependedAdjectives.isEmpty()) - sbShort.append(creatures == null ? "creatures" : creatures); - - if (!postponedAdjectives.isEmpty()) { - if (!prependedAdjectives.isEmpty()) { - sbShort.append(" and/or creatures"); - } - - sbShort.append(" with "); - sbShort.append(Lang.joinHomogenous(postponedAdjectives, withToString, allNegative ? "or" : "and")); - } - - } else { - for (Pair pre : prependedAdjectives) { - boolean useNon = pre.getKey() == allNegative; - if (useNon) sbShort.append("non-"); - sbShort.append(pre.getValue()).append(" "); - } - sbShort.append(creatures == null ? "creatures" : creatures); - - if (!postponedAdjectives.isEmpty()) { - sbShort.append(" with "); - sbShort.append(Lang.joinHomogenous(postponedAdjectives, withToString, allNegative ? "or" : "and")); - } - - } - orClauses.add(sbShort.toString()); - } - return byClause + StringUtils.join(orClauses, " or ") + "."; - } - // get the text of the abilities of a card public String getAbilityText() { return getAbilityText(currentState); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 5c1a576ff06..3a5d9418b3f 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -17,6 +17,7 @@ */ package forge.game.card; +import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; @@ -51,10 +52,12 @@ import forge.game.trigger.TriggerHandler; import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.util.Aggregates; +import forge.util.Expressions; import forge.util.Lang; import forge.util.TextUtil; import forge.util.collect.FCollectionView; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import java.util.*; import java.util.Map.Entry; @@ -4226,6 +4229,11 @@ public class CardFactoryUtil { } else if (keyword.equals("Undaunted")) { effect = "Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Secondary$ True" + "| Amount$ Undaunted | EffectZone$ All | Description$ Undaunted (" + inst.getReminderText() + ")"; + } else if (keyword.startsWith("CantBeBlockedBy ")) { + final String[] k = keyword.split(" ", 2); + + effect = "Mode$ CantBlockBy | ValidAttacker$ Creature.Self | ValidBlocker$ " + k[1] + + " | Description$ CARDNAME can't be blocked " + getTextForKwCantBeBlockedByType(keyword); } if (effect != null) { @@ -4277,4 +4285,110 @@ public class CardFactoryUtil { return as; // ETBReplacementMove(sa.getHostCard(), null)); } + + private static String getTextForKwCantBeBlockedByType(final String keyword) { + boolean negative = true; + final List subs = Lists.newArrayList(TextUtil.split(keyword.split(" ", 2)[1], ',')); + final List> subsAnd = Lists.newArrayList(); + final List orClauses = Lists.newArrayList(); + for (final String expession : subs) { + final List parts = Lists.newArrayList(expession.split("[.+]")); + for (int p = 0; p < parts.size(); p++) { + final String part = parts.get(p); + if (part.equalsIgnoreCase("creature")) { + parts.remove(p--); + continue; + } + // based on suppossition that each expression has at least 1 predicate except 'creature' + negative &= part.contains("non") || part.contains("without"); + } + subsAnd.add(parts); + } + + final boolean allNegative = negative; + final String byClause = allNegative ? "except by " : "by "; + + final Function, String> withToString = new Function, String>() { + @Override + public String apply(Pair inp) { + boolean useNon = inp.getKey() == allNegative; + return (useNon ? "*NO* " : "") + inp.getRight(); + } + }; + + for (final List andOperands : subsAnd) { + final List> prependedAdjectives = Lists.newArrayList(); + final List> postponedAdjectives = Lists.newArrayList(); + String creatures = null; + + for (String part : andOperands) { + boolean positive = true; + if (part.startsWith("non")) { + part = part.substring(3); + positive = false; + } + if (part.startsWith("with")) { + positive = !part.startsWith("without"); + postponedAdjectives.add(Pair.of(positive, part.substring(positive ? 4 : 7))); + } else if (part.startsWith("powerLEX")) {// Kraken of the Straits + postponedAdjectives.add(Pair.of(true, "power less than the number of islands you control")); + } else if (part.startsWith("power")) { + int kwLength = 5; + String opName = Expressions.operatorName(part.substring(kwLength, kwLength + 2)); + String operand = part.substring(kwLength + 2); + postponedAdjectives.add(Pair.of(true, "power" + opName + operand)); + } else if (CardType.isACreatureType(part)) { + if (creatures != null && CardType.isACreatureType(creatures)) { // e.g. Kor Castigator + creatures = StringUtils.capitalize(Lang.getPlural(part)) + creatures; + } else { + creatures = StringUtils.capitalize(Lang.getPlural(part)) + (creatures == null ? "" : " or " + creatures); + } + // Kor Castigator and other similar creatures with composite subtype Eldrazi Scion in their text + creatures = TextUtil.fastReplace(creatures, "Scions or Eldrazis", "Eldrazi Scions"); + } else { + prependedAdjectives.add(Pair.of(positive, part.toLowerCase())); + } + } + + StringBuilder sbShort = new StringBuilder(); + if (allNegative) { + boolean isFirst = true; + for (Pair pre : prependedAdjectives) { + if (isFirst) isFirst = false; + else sbShort.append(" and/or "); + + boolean useNon = pre.getKey() == allNegative; + if (useNon) sbShort.append("non-"); + sbShort.append(pre.getValue()).append(" ").append(creatures == null ? "creatures" : creatures); + } + if (prependedAdjectives.isEmpty()) + sbShort.append(creatures == null ? "creatures" : creatures); + + if (!postponedAdjectives.isEmpty()) { + if (!prependedAdjectives.isEmpty()) { + sbShort.append(" and/or creatures"); + } + + sbShort.append(" with "); + sbShort.append(Lang.joinHomogenous(postponedAdjectives, withToString, allNegative ? "or" : "and")); + } + + } else { + for (Pair pre : prependedAdjectives) { + boolean useNon = pre.getKey() == allNegative; + if (useNon) sbShort.append("non-"); + sbShort.append(pre.getValue()).append(" "); + } + sbShort.append(creatures == null ? "creatures" : creatures); + + if (!postponedAdjectives.isEmpty()) { + sbShort.append(" with "); + sbShort.append(Lang.joinHomogenous(postponedAdjectives, withToString, allNegative ? "or" : "and")); + } + + } + orClauses.add(sbShort.toString()); + } + return byClause + StringUtils.join(orClauses, " or ") + "."; + } } diff --git a/forge-game/src/main/java/forge/game/combat/CombatUtil.java b/forge-game/src/main/java/forge/game/combat/CombatUtil.java index 6c41d4fd021..91533392b28 100644 --- a/forge-game/src/main/java/forge/game/combat/CombatUtil.java +++ b/forge-game/src/main/java/forge/game/combat/CombatUtil.java @@ -1005,34 +1005,6 @@ public class CombatUtil { } } - // TODO remove it later to replace it with CantBlockBy above - for (KeywordInterface inst1 : attacker.getKeywords()) { - String k = inst1.getOriginal(); - if (k.startsWith("CantBeBlockedBy ")) { - final String[] n = k.split(" ", 2); - final String[] restrictions = n[1].split(","); - if (blocker.isValid(restrictions, attacker.getController(), attacker, null)) { - boolean stillblock = false; - //Dragon Hunter check - if (n[1].contains("withoutReach") && blocker.hasStartOfKeyword("IfReach")) { - for (KeywordInterface inst2 : blocker.getKeywords()) { - String k2 = inst2.getOriginal(); - if (k2.startsWith("IfReach")) { - String n2[] = k2.split(":"); - if (attacker.getType().hasCreatureType(n2[1])) { - stillblock = true; - break; - } - } - } - } - if (!stillblock) { - return false; - } - } - } - } - for (KeywordInterface inst : blocker.getKeywords()) { String keyword = inst.getOriginal(); if (keyword.startsWith("CantBlockCardUID")) {