CostAdjustment: add new Adjustment class for raising non-mana costs

should somehow merged with ManaCostAdjustment later
This commit is contained in:
Hanmac
2016-07-25 10:39:49 +00:00
parent 153b14446f
commit f24d6cb86b
4 changed files with 266 additions and 5 deletions

1
.gitattributes vendored
View File

@@ -490,6 +490,7 @@ forge-game/src/main/java/forge/game/combat/CombatView.java -text
forge-game/src/main/java/forge/game/combat/GlobalAttackRestrictions.java -text
forge-game/src/main/java/forge/game/cost/Cost.java svneol=native#text/plain
forge-game/src/main/java/forge/game/cost/CostAddMana.java -text
forge-game/src/main/java/forge/game/cost/CostAdjustment.java -text
forge-game/src/main/java/forge/game/cost/CostChooseCreatureType.java -text
forge-game/src/main/java/forge/game/cost/CostDamage.java -text
forge-game/src/main/java/forge/game/cost/CostDecisionMakerBase.java -text

View File

@@ -0,0 +1,255 @@
package forge.game.cost;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import forge.card.CardStateName;
import forge.card.mana.ManaAtom;
import forge.card.mana.ManaCostShard;
import forge.game.Game;
import forge.game.GameObject;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardFactoryUtil;
import forge.game.card.CardLists;
import forge.game.player.Player;
import forge.game.spellability.AbilityActivated;
import forge.game.spellability.Spell;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetChoices;
import forge.game.spellability.TargetRestrictions;
import forge.game.staticability.StaticAbility;
import forge.game.zone.ZoneType;
public class CostAdjustment {
public static Cost adjust(final Cost cost, final SpellAbility sa) {
final Player player = sa.getActivatingPlayer();
final Card host = sa.getHostCard();
final Game game = player.getGame();
if (sa.isTrigger()) {
return cost;
}
boolean isStateChangeToFaceDown = false;
if (sa.isSpell() && ((Spell) sa).isCastFaceDown()) {
// Turn face down to apply cost modifiers correctly
host.setState(CardStateName.FaceDown, false);
isStateChangeToFaceDown = true;
} // isSpell
CardCollection cardsOnBattlefield = new CardCollection(game.getCardsIn(ZoneType.Battlefield));
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack));
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command));
if (!cardsOnBattlefield.contains(host)) {
cardsOnBattlefield.add(host);
}
final List<StaticAbility> raiseAbilities = new ArrayList<StaticAbility>();
// Sort abilities to apply them in proper order
for (Card c : cardsOnBattlefield) {
for (final StaticAbility stAb : c.getStaticAbilities()) {
if (stAb.getMapParams().get("Mode").equals("RaiseCost2")) {
raiseAbilities.add(stAb);
}
}
}
// Raise cost
for (final StaticAbility stAb : raiseAbilities) {
applyRaise(cost, sa, stAb);
}
// Reset card state (if changed)
if (isStateChangeToFaceDown) {
host.setState(CardStateName.Original, false);
}
return cost;
}
private static void applyRaise(final Cost cost, final SpellAbility sa, final StaticAbility st) {
final Map<String, String> params = st.getMapParams();
final Card hostCard = st.getHostCard();
final Card card = sa.getHostCard();
if (!checkRequirement(sa, st)) {
return;
}
Cost part = new Cost(params.get("Cost"), sa.isAbility());
int count = 0;
if (params.containsKey("ForEachShard")) {
CostPartMana mc = cost.getCostMana();
if (mc != null) {
byte atom = ManaAtom.fromName(params.get("ForEachShard").toLowerCase());
for (ManaCostShard shard : mc.getManaCostFor(sa)) {
if ((shard.getColorMask() & atom) != 0) {
++count;
}
}
}
} else if (params.containsKey("Amount")) {
String amount = params.get("Amount");
if ("Escalate".equals(amount)) {
SpellAbility sub = sa;
while(sub != null) {
if (!sub.getSVar("CharmOrder").equals("")) {
count++;
}
sub = sub.getSubAbility();
}
} else if ("Strive".equals(amount)) {
for (TargetChoices tc : sa.getAllTargetChoices()) {
count += tc.getNumTargeted();
}
--count;
} else {
if (StringUtils.isNumeric(amount)) {
count = Integer.parseInt(amount);
} else {
if (params.containsKey("AffectedAmount")) {
count = CardFactoryUtil.xCount(card, hostCard.getSVar(amount));
} else {
count = AbilityUtils.calculateAmount(hostCard, amount, sa);
}
}
}
} else {
// Amount 1 as default
count = 1;
}
for(int i = 0; i < count; ++i) {
cost.add(part);
}
}
private static boolean checkRequirement(final SpellAbility sa, final StaticAbility st) {
if (st.isSuppressed() || !st.checkConditions()) {
return false;
}
final Map<String, String> params = st.getMapParams();
final Card hostCard = st.getHostCard();
final Player activator = sa.getActivatingPlayer();
final Card card = sa.getHostCard();
if (params.containsKey("Type")) {
final String type = params.get("Type");
if (type.equals("Spell")) {
if (!sa.isSpell()) {
return false;
}
if (params.containsKey("OnlyFirstSpell")) {
if (activator == null ) {
return false;
}
CardCollection list = CardLists.filterControlledBy(activator.getGame().getStack().getSpellsCastThisTurn(), activator);
if (params.containsKey("ValidCard")) {
list = CardLists.getValidCards(list, params.get("ValidCard"), hostCard.getController(), hostCard);
}
if (list.size() > 0) {
return false;
}
}
} else if (type.equals("Ability")) {
if (!(sa instanceof AbilityActivated) || sa.isReplacementAbility()) {
return false;
}
} else if (type.equals("NonManaAbility")) {
if (!(sa instanceof AbilityActivated) || sa.isManaAbility() || sa.isReplacementAbility()) {
return false;
}
} else if (type.equals("Buyback")) {
if (!sa.isBuyBackAbility()) {
return false;
}
} else if (type.equals("Cycling")) {
if (!sa.isCycling()) {
return false;
}
} else if (type.equals("Dash")) {
if (!sa.isDash()) {
return false;
}
} else if (type.equals("Equip")) {
if (!(sa instanceof AbilityActivated) || !sa.hasParam("Equip")) {
return false;
}
} else if (type.equals("Flashback")) {
if (!sa.isFlashBackAbility()) {
return false;
}
} else if (type.equals("MorphUp")) {
if (!sa.isMorphUp()) {
return false;
}
} else if (type.equals("MorphDown")) {
if (!sa.isSpell() || !((Spell) sa).isCastFaceDown()) {
return false;
}
} else if (type.equals("SelfMonstrosity")) {
if (!(sa instanceof AbilityActivated) || !sa.hasParam("Monstrosity") || sa.isTemporary()) {
// Nemesis of Mortals
return false;
}
} else if (type.equals("SelfIntrinsicAbility")) {
if (!(sa instanceof AbilityActivated) || sa.isReplacementAbility() || sa.isTemporary()) {
return false;
}
}
}
if (params.containsKey("AffectedZone")) {
List<ZoneType> zones = ZoneType.listValueOf(params.get("AffectedZone"));
boolean found = false;
for(ZoneType zt : zones) {
if(card.isInZone(zt))
{
found = true;
break;
}
}
if(!found) {
return false;
}
}
if (params.containsKey("ValidTarget")) {
TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
return false;
}
boolean targetValid = false;
for (GameObject target : sa.getTargets().getTargets()) {
if (target.isValid(params.get("ValidTarget").split(","), hostCard.getController(), hostCard, sa)) {
targetValid = true;
}
}
if (!targetValid) {
return false;
}
}
if (params.containsKey("ValidSpellTarget")) {
TargetRestrictions tgt = sa.getTargetRestrictions();
if (tgt == null) {
return false;
}
boolean targetValid = false;
for (SpellAbility target : sa.getTargets().getTargetSpells()) {
Card targetCard = target.getHostCard();
if (targetCard.isValid(params.get("ValidSpellTarget").split(","), hostCard.getController(), hostCard, sa)) {
targetValid = true;
break;
}
}
if (!targetValid) {
return false;
}
}
return true;
}
}

View File

@@ -36,6 +36,7 @@ import java.util.Map;
*/
public class CostPayment {
private final Cost cost;
private Cost adjustedCost;
private final SpellAbility ability;
private final List<CostPart> paidCostParts = new ArrayList<CostPart>();
@@ -66,6 +67,7 @@ public class CostPayment {
*/
public CostPayment(final Cost cost, final SpellAbility abil) {
this.cost = cost;
this.adjustedCost = cost;
this.ability = abil;
}
@@ -109,7 +111,7 @@ public class CostPayment {
* @return a boolean.
*/
public final boolean isFullyPaid() {
for (final CostPart part : this.cost.getCostParts()) {
for (final CostPart part : adjustedCost.getCostParts()) {
if (!this.paidCostParts.contains(part)) {
return false;
}
@@ -136,7 +138,8 @@ public class CostPayment {
}
public boolean payCost(final CostDecisionMakerBase decisionMaker) {
final List<CostPart> costParts = this.getCost().getCostPartsWithZeroMana();
adjustedCost = CostAdjustment.adjust(cost, ability);
final List<CostPart> costParts = adjustedCost.getCostPartsWithZeroMana();
for (final CostPart part : costParts) {
// Wrap the cost and push onto the cost stack
decisionMaker.getPlayer().getGame().costPaymentStack.push(new IndividualCostPaymentInstance(part, this));
@@ -171,8 +174,9 @@ public class CostPayment {
Map<CostPart, PaymentDecision> decisions = new HashMap<CostPart, PaymentDecision>();
List<CostPart> parts = CostAdjustment.adjust(cost, ability).getCostParts();
// Set all of the decisions before attempting to pay anything
for (final CostPart part : this.cost.getCostParts()) {
for (final CostPart part : parts) {
PaymentDecision decision = part.accept(decisionMaker);
if (null == decision) return false;
@@ -187,7 +191,7 @@ public class CostPayment {
decisions.put(part, decision);
}
for (final CostPart part : this.cost.getCostParts()) {
for (final CostPart part : parts) {
// wrap the payment and push onto the cost stack
decisionMaker.getPlayer().getGame().costPaymentStack.push(new IndividualCostPaymentInstance(part, this));

View File

@@ -30,6 +30,7 @@ import forge.game.card.CardView;
import forge.game.card.CounterType;
import forge.game.cost.Cost;
import forge.game.cost.CostAddMana;
import forge.game.cost.CostAdjustment;
import forge.game.cost.CostDamage;
import forge.game.cost.CostDiscard;
import forge.game.cost.CostDraw;
@@ -281,7 +282,7 @@ public class HumanPlay {
current = Iterables.getFirst(AbilityUtils.getDefinedCards(source, sourceAbility.getParam("ShowCurrentCard"), sourceAbility), null);
}
final List<CostPart> parts = cost.getCostParts();
final List<CostPart> parts = CostAdjustment.adjust(cost, sourceAbility).getCostParts();
final List<CostPart> remainingParts = new ArrayList<CostPart>(parts);
CostPart costPart = null;
if (!parts.isEmpty()) {