mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
'Fuse' Keyword support for DGM
CostUtil.java disbanded, it's method moved closer to usage places.
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -13790,7 +13790,6 @@ src/main/java/forge/card/cost/CostTapType.java -text
|
|||||||
src/main/java/forge/card/cost/CostUnattach.java -text
|
src/main/java/forge/card/cost/CostUnattach.java -text
|
||||||
src/main/java/forge/card/cost/CostUntap.java -text
|
src/main/java/forge/card/cost/CostUntap.java -text
|
||||||
src/main/java/forge/card/cost/CostUntapType.java -text
|
src/main/java/forge/card/cost/CostUntapType.java -text
|
||||||
src/main/java/forge/card/cost/CostUtil.java -text
|
|
||||||
src/main/java/forge/card/cost/InputPayCostBase.java -text
|
src/main/java/forge/card/cost/InputPayCostBase.java -text
|
||||||
src/main/java/forge/card/cost/PaymentDecision.java -text
|
src/main/java/forge/card/cost/PaymentDecision.java -text
|
||||||
src/main/java/forge/card/cost/package-info.java svneol=native#text/plain
|
src/main/java/forge/card/cost/package-info.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -9177,6 +9177,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( sa.getSourceCard().hasKeyword("Fuse") ) // it's ok that such card won't change its side
|
||||||
|
return;
|
||||||
|
|
||||||
throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + this);
|
throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,44 @@ import forge.util.FileSection;
|
|||||||
*/
|
*/
|
||||||
public final class AbilityFactory {
|
public final class AbilityFactory {
|
||||||
|
|
||||||
|
public enum AbilityRecordType {
|
||||||
|
Ability("AB"),
|
||||||
|
Spell("SP"),
|
||||||
|
SubAbility("DB");
|
||||||
|
|
||||||
|
private final String prefix;
|
||||||
|
private AbilityRecordType(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
public String getPrefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpellAbility buildSpellAbility(ApiType api, Card hostCard, Cost abCost, Target abTgt, Map<String, String> mapParams ) {
|
||||||
|
switch(this) {
|
||||||
|
case Ability: return new AbilityApiBased(api, hostCard, abCost, abTgt, mapParams);
|
||||||
|
case Spell: return new SpellApiBased(api, hostCard, abCost, abTgt, mapParams);
|
||||||
|
case SubAbility: return new AbilitySub(api, hostCard, abTgt, mapParams);
|
||||||
|
}
|
||||||
|
return null; // exception here would be fine!
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiType getApiTypeOf(Map<String, String> abParams) {
|
||||||
|
return ApiType.smartValueOf(abParams.get(this.getPrefix()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbilityRecordType getRecordType(Map<String, String> abParams) {
|
||||||
|
if (abParams.containsKey(AbilityRecordType.Ability.getPrefix())) {
|
||||||
|
return AbilityRecordType.Ability;
|
||||||
|
} else if (abParams.containsKey(AbilityRecordType.Spell.getPrefix())) {
|
||||||
|
return AbilityRecordType.Spell;
|
||||||
|
} else if (abParams.containsKey(AbilityRecordType.SubAbility.getPrefix())) {
|
||||||
|
return AbilityRecordType.SubAbility;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* getAbility.
|
* getAbility.
|
||||||
@@ -54,11 +92,6 @@ public final class AbilityFactory {
|
|||||||
*/
|
*/
|
||||||
public static final SpellAbility getAbility(final String abString, final Card hostCard) {
|
public static final SpellAbility getAbility(final String abString, final Card hostCard) {
|
||||||
|
|
||||||
SpellAbility spellAbility = null;
|
|
||||||
|
|
||||||
boolean isAb = false;
|
|
||||||
boolean isSp = false;
|
|
||||||
boolean isDb = false;
|
|
||||||
|
|
||||||
Map<String, String> mapParams;
|
Map<String, String> mapParams;
|
||||||
try {
|
try {
|
||||||
@@ -69,34 +102,28 @@ public final class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse universal parameters
|
// parse universal parameters
|
||||||
|
AbilityRecordType type = AbilityRecordType.getRecordType(mapParams);
|
||||||
ApiType api = null;
|
if( null == type )
|
||||||
if (mapParams.containsKey("AB")) {
|
|
||||||
isAb = true;
|
|
||||||
api = ApiType.smartValueOf(mapParams.get("AB"));
|
|
||||||
} else if (mapParams.containsKey("SP")) {
|
|
||||||
isSp = true;
|
|
||||||
api = ApiType.smartValueOf(mapParams.get("SP"));
|
|
||||||
} else if (mapParams.containsKey("DB")) {
|
|
||||||
isDb = true;
|
|
||||||
api = ApiType.smartValueOf(mapParams.get("DB"));
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("AbilityFactory : getAbility -- no API in " + hostCard.getName());
|
throw new RuntimeException("AbilityFactory : getAbility -- no API in " + hostCard.getName());
|
||||||
|
|
||||||
|
return getAbility(type, type.getApiTypeOf(mapParams), mapParams, parseAbilityCost(hostCard, mapParams, type), hostCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Cost parseAbilityCost(final Card hostCard, Map<String, String> mapParams, AbilityRecordType type) {
|
||||||
Cost abCost = null;
|
Cost abCost = null;
|
||||||
if (!isDb) {
|
if (type != AbilityRecordType.SubAbility) {
|
||||||
if (!mapParams.containsKey("Cost")) {
|
if (!mapParams.containsKey("Cost")) {
|
||||||
throw new RuntimeException("AbilityFactory : getAbility -- no Cost in " + hostCard.getName());
|
throw new RuntimeException("AbilityFactory : getAbility -- no Cost in " + hostCard.getName());
|
||||||
}
|
}
|
||||||
abCost = new Cost(hostCard, mapParams.get("Cost"), isAb);
|
abCost = new Cost(hostCard, mapParams.get("Cost"), type == AbilityRecordType.Ability);
|
||||||
|
}
|
||||||
|
return abCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target abTgt = mapParams.containsKey("ValidTgts") ? readTarget(hostCard, mapParams) : null;
|
public static final SpellAbility getAbility(AbilityRecordType type, ApiType api, Map<String, String> mapParams, Cost abCost, Card hostCard) {
|
||||||
|
|
||||||
// ***********************************
|
|
||||||
// Match API keywords. These are listed in alphabetical order.
|
Target abTgt = mapParams.containsKey("ValidTgts") ? readTarget(hostCard, mapParams) : null;
|
||||||
|
|
||||||
|
|
||||||
if (api == ApiType.CopySpellAbility) {
|
if (api == ApiType.CopySpellAbility) {
|
||||||
@@ -119,20 +146,13 @@ public final class AbilityFactory {
|
|||||||
else if (api == ApiType.PermanentCreature || api == ApiType.PermanentNoncreature) {
|
else if (api == ApiType.PermanentCreature || api == ApiType.PermanentNoncreature) {
|
||||||
// If API is a permanent type, and creating AF Spell
|
// If API is a permanent type, and creating AF Spell
|
||||||
// Clear out the auto created SpellPemanent spell
|
// Clear out the auto created SpellPemanent spell
|
||||||
if (isSp) {
|
if (type == AbilityRecordType.Spell) {
|
||||||
hostCard.clearFirstSpell();
|
hostCard.clearFirstSpell();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isAb) {
|
SpellAbility spellAbility = type.buildSpellAbility(api, hostCard, abCost, abTgt, mapParams);
|
||||||
spellAbility = new AbilityApiBased(api, hostCard, abCost, abTgt, mapParams);
|
|
||||||
} else if (isSp) {
|
|
||||||
spellAbility = new SpellApiBased(api, hostCard, abCost, abTgt, mapParams);
|
|
||||||
} else if (isDb) {
|
|
||||||
spellAbility = new AbilitySub(api, hostCard, abTgt, mapParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (spellAbility == null) {
|
if (spellAbility == null) {
|
||||||
@@ -163,7 +183,7 @@ public final class AbilityFactory {
|
|||||||
} else if (mapParams.containsKey("SpellDescription")) {
|
} else if (mapParams.containsKey("SpellDescription")) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
if (!isDb) { // SubAbilities don't have Costs or Cost
|
if (type != AbilityRecordType.SubAbility) { // SubAbilities don't have Costs or Cost
|
||||||
// descriptors
|
// descriptors
|
||||||
if (mapParams.containsKey("PrecostDesc")) {
|
if (mapParams.containsKey("PrecostDesc")) {
|
||||||
sb.append(mapParams.get("PrecostDesc")).append(" ");
|
sb.append(mapParams.get("PrecostDesc")).append(" ");
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import forge.Singletons;
|
|||||||
import forge.card.ability.AbilityUtils;
|
import forge.card.ability.AbilityUtils;
|
||||||
import forge.card.ability.SpellAbilityAi;
|
import forge.card.ability.SpellAbilityAi;
|
||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.cost.CostUtil;
|
import forge.card.cost.CostPart;
|
||||||
|
import forge.card.cost.CostTapType;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.SpellAbilityRestriction;
|
import forge.card.spellability.SpellAbilityRestriction;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
@@ -29,6 +30,19 @@ import forge.game.zone.ZoneType;
|
|||||||
|
|
||||||
public class PumpAi extends PumpAiBase {
|
public class PumpAi extends PumpAiBase {
|
||||||
|
|
||||||
|
private static boolean hasTapCost(final Cost cost, final Card source) {
|
||||||
|
if (cost == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (final CostPart part : cost.getCostParts()) {
|
||||||
|
if (part instanceof CostTapType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
*/
|
*/
|
||||||
@@ -56,7 +70,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Singletons.getModel().getGame().getStack().isEmpty() && CostUtil.hasTapCost(cost, sa.getSourceCard())) {
|
if (Singletons.getModel().getGame().getStack().isEmpty() && hasTapCost(cost, sa.getSourceCard())) {
|
||||||
if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && ph.isPlayerTurn(ai)) {
|
if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && ph.isPlayerTurn(ai)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,6 +292,7 @@ public class CardFactory {
|
|||||||
if ( state == CardCharacteristicName.LeftSplit || state == CardCharacteristicName.RightSplit )
|
if ( state == CardCharacteristicName.LeftSplit || state == CardCharacteristicName.RightSplit )
|
||||||
{
|
{
|
||||||
card.getState(CardCharacteristicName.Original).getSpellAbility().addAll(card.getCharacteristics().getSpellAbility());
|
card.getState(CardCharacteristicName.Original).getSpellAbility().addAll(card.getCharacteristics().getSpellAbility());
|
||||||
|
card.getState(CardCharacteristicName.Original).getIntrinsicKeyword().addAll(card.getIntrinsicKeyword()); // Copy 'Fuse' to original side
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2371,7 +2371,29 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
card.addSpellAbility(sa);
|
card.addSpellAbility(sa);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final SpellAbility buildFusedAbility(final Card card) {
|
||||||
|
if(!card.isSplitCard())
|
||||||
|
throw new IllegalStateException("Fuse ability may be built only on split cards");
|
||||||
|
|
||||||
|
final String strLeftAbility = card.getState(CardCharacteristicName.LeftSplit).getIntrinsicAbility().get(0);
|
||||||
|
Map<String, String> leftMap = AbilityFactory.getMapParams(strLeftAbility);
|
||||||
|
AbilityFactory.AbilityRecordType leftType = AbilityFactory.AbilityRecordType.getRecordType(leftMap);
|
||||||
|
Cost leftCost = AbilityFactory.parseAbilityCost(card, leftMap, leftType);
|
||||||
|
ApiType leftApi = leftType.getApiTypeOf(leftMap);
|
||||||
|
|
||||||
|
final String strRightAbility = card.getState(CardCharacteristicName.RightSplit).getIntrinsicAbility().get(0);
|
||||||
|
Map<String, String> rightMap = AbilityFactory.getMapParams(strRightAbility);
|
||||||
|
AbilityFactory.AbilityRecordType rightType = AbilityFactory.AbilityRecordType.getRecordType(leftMap);
|
||||||
|
Cost rightCost = AbilityFactory.parseAbilityCost(card, rightMap, rightType);
|
||||||
|
ApiType rightApi = leftType.getApiTypeOf(rightMap);
|
||||||
|
|
||||||
|
Cost joinedCost = Cost.combine(rightCost, leftCost);
|
||||||
|
final SpellAbility left = AbilityFactory.getAbility(leftType, leftApi, leftMap, joinedCost, card);
|
||||||
|
final AbilitySub right = (AbilitySub) AbilityFactory.getAbility(AbilityFactory.AbilityRecordType.SubAbility, rightApi, rightMap, null, card);
|
||||||
|
left.appendSubAbility(right);
|
||||||
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2418,6 +2440,10 @@ public class CardFactoryUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(CardFactoryUtil.hasKeyword(card, "Fuse") != -1) {
|
||||||
|
card.getState(CardCharacteristicName.Original).getSpellAbility().add(buildFusedAbility(card));
|
||||||
|
}
|
||||||
|
|
||||||
final int evokePos = CardFactoryUtil.hasKeyword(card, "Evoke");
|
final int evokePos = CardFactoryUtil.hasKeyword(card, "Evoke");
|
||||||
if (evokePos != -1) {
|
if (evokePos != -1) {
|
||||||
card.addSpellAbility(makeEvokeSpell(card, card.getKeyword().get(evokePos)));
|
card.addSpellAbility(makeEvokeSpell(card, card.getKeyword().get(evokePos)));
|
||||||
@@ -3197,12 +3223,7 @@ public class CardFactoryUtil {
|
|||||||
|
|
||||||
private static final Map<String,String> emptyMap = new TreeMap<String,String>();
|
private static final Map<String,String> emptyMap = new TreeMap<String,String>();
|
||||||
public static void setupETBReplacementAbility(SpellAbility sa) {
|
public static void setupETBReplacementAbility(SpellAbility sa) {
|
||||||
SpellAbility tailend = sa;
|
sa.appendSubAbility(new AbilitySub(ApiType.InternalEtbReplacement, sa.getSourceCard(), null, emptyMap));
|
||||||
while (tailend.getSubAbility() != null) {
|
|
||||||
tailend = tailend.getSubAbility();
|
|
||||||
}
|
|
||||||
|
|
||||||
tailend.setSubAbility(new AbilitySub(ApiType.InternalEtbReplacement, sa.getSourceCard(), null, emptyMap));
|
|
||||||
// ETBReplacementMove(sa.getSourceCard(), null));
|
// ETBReplacementMove(sa.getSourceCard(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import forge.card.mana.ManaCostBeingPaid;
|
|||||||
import forge.card.mana.ManaCostParser;
|
import forge.card.mana.ManaCostParser;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.gui.GuiChoose;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -647,4 +648,42 @@ public class Cost {
|
|||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Cost combine(Cost cost1, Cost cost2) {
|
||||||
|
if (cost1 == null) return cost2;
|
||||||
|
if (cost2 == null) return cost1;
|
||||||
|
|
||||||
|
CostPartMana costPart2 = cost2.getCostMana();
|
||||||
|
for (final CostPart part : cost1.getCostParts()) {
|
||||||
|
if (part instanceof CostPartMana && costPart2 != null) {
|
||||||
|
ManaCostBeingPaid oldManaCost = new ManaCostBeingPaid(((CostPartMana) part).getMana());
|
||||||
|
boolean xCanBe0 = ((CostPartMana) part).canXbe0() && costPart2.canXbe0();
|
||||||
|
oldManaCost.combineManaCost(costPart2.getMana());
|
||||||
|
String r2 = costPart2.getRestiction();
|
||||||
|
String r1 = ((CostPartMana) part).getRestiction();
|
||||||
|
String r = r1 == null ? r2 : ( r2 == null ? r1 : r1+"."+r2);
|
||||||
|
cost2.getCostParts().remove(costPart2);
|
||||||
|
cost2.getCostParts().add(0, new CostPartMana(oldManaCost.toManaCost(), r, !xCanBe0));
|
||||||
|
} else {
|
||||||
|
cost2.getCostParts().add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cost2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int chooseXValue(final Card card, final SpellAbility sa, final int maxValue) {
|
||||||
|
/*final String chosen = sa.getSVar("ChosenX");
|
||||||
|
if (chosen.length() > 0) {
|
||||||
|
return AbilityFactory.calculateAmount(card, "ChosenX", null);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
final Integer[] choiceArray = new Integer[maxValue + 1];
|
||||||
|
for (int i = 0; i < choiceArray.length; i++) {
|
||||||
|
choiceArray[i] = i;
|
||||||
|
}
|
||||||
|
final Integer chosenX = GuiChoose.one(card.toString() + " - Choose a Value for X", choiceArray);
|
||||||
|
sa.setSVar("ChosenX", Integer.toString(chosenX));
|
||||||
|
card.setSVar("ChosenX", Integer.toString(chosenX));
|
||||||
|
return chosenX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class CostDamage extends CostPart {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, life);
|
c = Cost.chooseXValue(source, ability, life);
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ public class CostDiscard extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, handList.size());
|
c = Cost.chooseXValue(source, ability, handList.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ public class CostDiscard extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, handList.size());
|
c = Cost.chooseXValue(source, ability, handList.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ public class CostExile extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, list.size());
|
c = Cost.chooseXValue(source, ability, list.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ public class CostGainLife extends CostPart {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, life);
|
c = Cost.chooseXValue(source, ability, life);
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class CostMill extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, this.getList().size());
|
c = Cost.chooseXValue(source, ability, this.getList().size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ public class CostPayLife extends CostPart {
|
|||||||
limit = AbilityUtils.calculateAmount(source, sVar.split("LimitMax.")[1], ability);
|
limit = AbilityUtils.calculateAmount(source, sVar.split("LimitMax.")[1], ability);
|
||||||
}
|
}
|
||||||
int maxLifePayment = limit < life ? limit : life;
|
int maxLifePayment = limit < life ? limit : life;
|
||||||
c = CostUtil.chooseXValue(source, ability, maxLifePayment);
|
c = Cost.chooseXValue(source, ability, maxLifePayment);
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ public class CostRemoveCounter extends CostPartWithList {
|
|||||||
if (amount.equals("All"))
|
if (amount.equals("All"))
|
||||||
cntRemoved = maxCounters;
|
cntRemoved = maxCounters;
|
||||||
else if ( c == null && "XChoice".equals(sVarAmount)) {
|
else if ( c == null && "XChoice".equals(sVarAmount)) {
|
||||||
cntRemoved = CostUtil.chooseXValue(source, ability, maxCounters);
|
cntRemoved = Cost.chooseXValue(source, ability, maxCounters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxCounters < cntRemoved)
|
if (maxCounters < cntRemoved)
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ public class CostReturn extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, list.size());
|
c = Cost.chooseXValue(source, ability, list.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ public class CostReveal extends CostPartWithList {
|
|||||||
if (num == null) {
|
if (num == null) {
|
||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
num = CostUtil.chooseXValue(source, ability, handList.size());
|
num = Cost.chooseXValue(source, ability, handList.size());
|
||||||
} else {
|
} else {
|
||||||
num = AbilityUtils.calculateAmount(source, amount, ability);
|
num = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public class CostSacrifice extends CostPartWithList {
|
|||||||
if (c == null) {
|
if (c == null) {
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (ability.getSVar(amount).equals("XChoice")) {
|
if (ability.getSVar(amount).equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, list.size());
|
c = Cost.chooseXValue(source, ability, list.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public class CostTapType extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, typeList.size());
|
c = Cost.chooseXValue(source, ability, typeList.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ public class CostUntapType extends CostPartWithList {
|
|||||||
final String sVar = ability.getSVar(amount);
|
final String sVar = ability.getSVar(amount);
|
||||||
// Generalize this
|
// Generalize this
|
||||||
if (sVar.equals("XChoice")) {
|
if (sVar.equals("XChoice")) {
|
||||||
c = CostUtil.chooseXValue(source, ability, typeList.size());
|
c = Cost.chooseXValue(source, ability, typeList.size());
|
||||||
} else {
|
} else {
|
||||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.card.cost;
|
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.card.mana.ManaCostBeingPaid;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
|
||||||
import forge.gui.GuiChoose;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Class CostUtil.
|
|
||||||
*/
|
|
||||||
public class CostUtil {
|
|
||||||
/**
|
|
||||||
* Checks for discard hand cost.
|
|
||||||
*
|
|
||||||
* @param cost
|
|
||||||
* the cost
|
|
||||||
* @return true, if successful
|
|
||||||
*/
|
|
||||||
public static boolean hasDiscardHandCost(final Cost cost) {
|
|
||||||
if (cost == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (final CostPart part : cost.getCostParts()) {
|
|
||||||
if (part instanceof CostDiscard) {
|
|
||||||
final CostDiscard disc = (CostDiscard) part;
|
|
||||||
if (disc.getType().equals("Hand")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* hasTapCost.
|
|
||||||
*
|
|
||||||
* @param cost
|
|
||||||
* the cost
|
|
||||||
* @param source
|
|
||||||
* the source
|
|
||||||
* @return true, if successful
|
|
||||||
*/
|
|
||||||
public static boolean hasTapCost(final Cost cost, final Card source) {
|
|
||||||
if (cost == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (final CostPart part : cost.getCostParts()) {
|
|
||||||
if (part instanceof CostTapType) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Choose x value.
|
|
||||||
*
|
|
||||||
* @param card
|
|
||||||
* the card
|
|
||||||
* @param sa
|
|
||||||
* the SpellAbility
|
|
||||||
* @param maxValue
|
|
||||||
* the max value
|
|
||||||
* @return the int
|
|
||||||
*/
|
|
||||||
public static int chooseXValue(final Card card, final SpellAbility sa, final int maxValue) {
|
|
||||||
/*final String chosen = sa.getSVar("ChosenX");
|
|
||||||
if (chosen.length() > 0) {
|
|
||||||
return AbilityFactory.calculateAmount(card, "ChosenX", null);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
final Integer[] choiceArray = new Integer[maxValue + 1];
|
|
||||||
for (int i = 0; i < choiceArray.length; i++) {
|
|
||||||
choiceArray[i] = i;
|
|
||||||
}
|
|
||||||
final Integer chosenX = GuiChoose.one(card.toString() + " - Choose a Value for X", choiceArray);
|
|
||||||
sa.setSVar("ChosenX", Integer.toString(chosenX));
|
|
||||||
card.setSVar("ChosenX", Integer.toString(chosenX));
|
|
||||||
|
|
||||||
return chosenX;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static Cost combineCosts(Cost cost1, Cost cost2) {
|
|
||||||
if (cost1 == null) return cost2;
|
|
||||||
if (cost2 == null) return cost1;
|
|
||||||
|
|
||||||
CostPartMana costPart2 = cost2.getCostMana();
|
|
||||||
for (final CostPart part : cost1.getCostParts()) {
|
|
||||||
if (part instanceof CostPartMana && costPart2 != null) {
|
|
||||||
ManaCostBeingPaid oldManaCost = new ManaCostBeingPaid(((CostPartMana) part).getMana());
|
|
||||||
boolean xCanBe0 = ((CostPartMana) part).canXbe0() && costPart2.canXbe0();
|
|
||||||
oldManaCost.combineManaCost(costPart2.getMana());
|
|
||||||
String r2 = costPart2.getRestiction();
|
|
||||||
String r1 = ((CostPartMana) part).getRestiction();
|
|
||||||
String r = r1 == null ? r2 : ( r2 == null ? r1 : r1+"."+r2);
|
|
||||||
cost2.getCostParts().remove(costPart2);
|
|
||||||
cost2.getCostParts().add(0, new CostPartMana(oldManaCost.toManaCost(), r, !xCanBe0));
|
|
||||||
} else {
|
|
||||||
cost2.getCostParts().add(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cost2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -959,6 +959,15 @@ public abstract class SpellAbility implements ISpellAbility {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void appendSubAbility(final AbilitySub toAdd) {
|
||||||
|
SpellAbility tailend = this;
|
||||||
|
while (tailend.getSubAbility() != null) {
|
||||||
|
tailend = tailend.getSubAbility();
|
||||||
|
}
|
||||||
|
tailend.setSubAbility(toAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Setter for the field <code>subAbility</code>.
|
* Setter for the field <code>subAbility</code>.
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ import forge.card.cost.CostReturn;
|
|||||||
import forge.card.cost.CostReveal;
|
import forge.card.cost.CostReveal;
|
||||||
import forge.card.cost.CostSacrifice;
|
import forge.card.cost.CostSacrifice;
|
||||||
import forge.card.cost.CostTapType;
|
import forge.card.cost.CostTapType;
|
||||||
import forge.card.cost.CostUtil;
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.spellability.Ability;
|
import forge.card.spellability.Ability;
|
||||||
import forge.card.spellability.AbilityManaPart;
|
import forge.card.spellability.AbilityManaPart;
|
||||||
@@ -1250,10 +1249,8 @@ public final class GameActionUtil {
|
|||||||
return alternatives;
|
return alternatives;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Cost combineCosts(SpellAbility sa, String additionalCost) {
|
private static Cost combineCosts(SpellAbility sa, String additionalCost) {
|
||||||
final Cost newCost = new Cost(sa.getSourceCard(), additionalCost, false);
|
return Cost.combine(sa.getPayCosts(), new Cost(sa.getSourceCard(), additionalCost, false));
|
||||||
Cost oldCost = sa.getPayCosts();
|
|
||||||
return CostUtil.combineCosts(oldCost, newCost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ import forge.card.ability.ApiType;
|
|||||||
import forge.card.ability.effects.CharmEffect;
|
import forge.card.ability.effects.CharmEffect;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.cost.CostDiscard;
|
||||||
|
import forge.card.cost.CostPart;
|
||||||
import forge.card.cost.CostPayment;
|
import forge.card.cost.CostPayment;
|
||||||
import forge.card.cost.CostUtil;
|
|
||||||
import forge.card.spellability.AbilityStatic;
|
import forge.card.spellability.AbilityStatic;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
@@ -124,6 +125,21 @@ public class ComputerUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static boolean hasDiscardHandCost(final Cost cost) {
|
||||||
|
if (cost == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (final CostPart part : cost.getCostParts()) {
|
||||||
|
if (part instanceof CostDiscard) {
|
||||||
|
final CostDiscard disc = (CostDiscard) part;
|
||||||
|
if (disc.getType().equals("Hand")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* counterSpellRestriction.
|
* counterSpellRestriction.
|
||||||
@@ -149,7 +165,7 @@ public class ComputerUtil {
|
|||||||
// String totalMana = source.getSVar("PayX"); // + cost.getCMC()
|
// String totalMana = source.getSVar("PayX"); // + cost.getCMC()
|
||||||
|
|
||||||
// Consider the costs here for relative "scoring"
|
// Consider the costs here for relative "scoring"
|
||||||
if (CostUtil.hasDiscardHandCost(cost)) {
|
if (hasDiscardHandCost(cost)) {
|
||||||
// Null Brooch aid
|
// Null Brooch aid
|
||||||
restrict -= (ai.getCardsIn(ZoneType.Hand).size() * 20);
|
restrict -= (ai.getCardsIn(ZoneType.Hand).size() * 20);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import forge.card.CardType;
|
|||||||
import forge.card.ability.ApiType;
|
import forge.card.ability.ApiType;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
import forge.card.cost.CostUtil;
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.spellability.Ability;
|
import forge.card.spellability.Ability;
|
||||||
import forge.card.spellability.AbilityStatic;
|
import forge.card.spellability.AbilityStatic;
|
||||||
@@ -1131,7 +1130,7 @@ public class CombatUtil {
|
|||||||
final ArrayList<StaticAbility> staticAbilities = card.getStaticAbilities();
|
final ArrayList<StaticAbility> staticAbilities = card.getStaticAbilities();
|
||||||
for (final StaticAbility stAb : staticAbilities) {
|
for (final StaticAbility stAb : staticAbilities) {
|
||||||
Cost additionalCost = stAb.getCostAbility("CantAttackUnless", c, game.getCombat().getDefenderByAttacker(c));
|
Cost additionalCost = stAb.getCostAbility("CantAttackUnless", c, game.getCombat().getDefenderByAttacker(c));
|
||||||
attackCost = CostUtil.combineCosts(attackCost, additionalCost);
|
attackCost = Cost.combine(attackCost, additionalCost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attackCost.toSimpleString().equals("")) {
|
if (attackCost.toSimpleString().equals("")) {
|
||||||
|
|||||||
Reference in New Issue
Block a user