mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Merge branch 'gameCacheRework' into 'master'
Human Play: try to remove usage of game.getCard See merge request core-developers/forge!2804
This commit is contained in:
@@ -769,7 +769,7 @@ public class AiController {
|
|||||||
return AiPlayDecision.CantPlayAi;
|
return AiPlayDecision.CantPlayAi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sa.getPayCosts() != null){
|
else {
|
||||||
Cost payCosts = sa.getPayCosts();
|
Cost payCosts = sa.getPayCosts();
|
||||||
ManaCost mana = payCosts.getTotalMana();
|
ManaCost mana = payCosts.getTotalMana();
|
||||||
if (mana != null) {
|
if (mana != null) {
|
||||||
@@ -858,7 +858,7 @@ public class AiController {
|
|||||||
int neededMana = 0;
|
int neededMana = 0;
|
||||||
boolean dangerousRecurringCost = false;
|
boolean dangerousRecurringCost = false;
|
||||||
|
|
||||||
Cost costWithBuyback = sa.getPayCosts() != null ? sa.getPayCosts().copy() : Cost.Zero;
|
Cost costWithBuyback = sa.getPayCosts().copy();
|
||||||
for (OptionalCostValue opt : GameActionUtil.getOptionalCostValues(sa)) {
|
for (OptionalCostValue opt : GameActionUtil.getOptionalCostValues(sa)) {
|
||||||
if (opt.getType() == OptionalCost.Buyback) {
|
if (opt.getType() == OptionalCost.Buyback) {
|
||||||
costWithBuyback.add(opt.getCost());
|
costWithBuyback.add(opt.getCost());
|
||||||
@@ -907,8 +907,8 @@ public class AiController {
|
|||||||
public int compare(final SpellAbility a, final SpellAbility b) {
|
public int compare(final SpellAbility a, final SpellAbility b) {
|
||||||
// sort from highest cost to lowest
|
// sort from highest cost to lowest
|
||||||
// we want the highest costs first
|
// we want the highest costs first
|
||||||
int a1 = a.getPayCosts() == null ? 0 : a.getPayCosts().getTotalMana().getCMC();
|
int a1 = a.getPayCosts().getTotalMana().getCMC();
|
||||||
int b1 = b.getPayCosts() == null ? 0 : b.getPayCosts().getTotalMana().getCMC();
|
int b1 = b.getPayCosts().getTotalMana().getCMC();
|
||||||
|
|
||||||
// deprioritize SAs explicitly marked as preferred to be activated last compared to all other SAs
|
// deprioritize SAs explicitly marked as preferred to be activated last compared to all other SAs
|
||||||
if (a.hasParam("AIActivateLast") && !b.hasParam("AIActivateLast")) {
|
if (a.hasParam("AIActivateLast") && !b.hasParam("AIActivateLast")) {
|
||||||
@@ -927,12 +927,12 @@ public class AiController {
|
|||||||
// deprioritize pump spells with pure energy cost (can be activated last,
|
// deprioritize pump spells with pure energy cost (can be activated last,
|
||||||
// since energy is generally scarce, plus can benefit e.g. Electrostatic Pummeler)
|
// since energy is generally scarce, plus can benefit e.g. Electrostatic Pummeler)
|
||||||
int a2 = 0, b2 = 0;
|
int a2 = 0, b2 = 0;
|
||||||
if (a.getApi() == ApiType.Pump && a.getPayCosts() != null && a.getPayCosts().getCostEnergy() != null) {
|
if (a.getApi() == ApiType.Pump && a.getPayCosts().getCostEnergy() != null) {
|
||||||
if (a.getPayCosts().hasOnlySpecificCostType(CostPayEnergy.class)) {
|
if (a.getPayCosts().hasOnlySpecificCostType(CostPayEnergy.class)) {
|
||||||
a2 = a.getPayCosts().getCostEnergy().convertAmount();
|
a2 = a.getPayCosts().getCostEnergy().convertAmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (b.getApi() == ApiType.Pump && b.getPayCosts() != null && b.getPayCosts().getCostEnergy() != null) {
|
if (b.getApi() == ApiType.Pump && b.getPayCosts().getCostEnergy() != null) {
|
||||||
if (b.getPayCosts().hasOnlySpecificCostType(CostPayEnergy.class)) {
|
if (b.getPayCosts().hasOnlySpecificCostType(CostPayEnergy.class)) {
|
||||||
b2 = b.getPayCosts().getCostEnergy().convertAmount();
|
b2 = b.getPayCosts().getCostEnergy().convertAmount();
|
||||||
}
|
}
|
||||||
@@ -956,8 +956,7 @@ public class AiController {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.getHostCard().equals(b.getHostCard()) && a.getApi() == b.getApi()
|
if (a.getHostCard().equals(b.getHostCard()) && a.getApi() == b.getApi()) {
|
||||||
&& a.getPayCosts() != null && b.getPayCosts() != null) {
|
|
||||||
// Cheaper Spectacle costs should be preferred
|
// Cheaper Spectacle costs should be preferred
|
||||||
// FIXME: Any better way to identify that these are the same ability, one with Spectacle and one not?
|
// FIXME: Any better way to identify that these are the same ability, one with Spectacle and one not?
|
||||||
// (looks like it's not a full-fledged alternative cost as such, and is not processed with other alt costs)
|
// (looks like it's not a full-fledged alternative cost as such, and is not processed with other alt costs)
|
||||||
@@ -1479,7 +1478,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (SpellAbility sa : card.getSpellAbilities()) {
|
for (SpellAbility sa : card.getSpellAbilities()) {
|
||||||
if (sa.getPayCosts() != null && sa.isAbility()
|
if (sa.isAbility()
|
||||||
&& sa.getPayCosts().getCostMana() != null
|
&& sa.getPayCosts().getCostMana() != null
|
||||||
&& sa.getPayCosts().getCostMana().getMana().getCMC() > 0
|
&& sa.getPayCosts().getCostMana().getMana().getCMC() > 0
|
||||||
&& (!sa.getPayCosts().hasTapCost() || !isTapLand)
|
&& (!sa.getPayCosts().hasTapCost() || !isTapLand)
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
|||||||
@Override
|
@Override
|
||||||
public boolean apply(Card card) {
|
public boolean apply(Card card) {
|
||||||
for (final SpellAbility sa : card.getSpellAbilities()) {
|
for (final SpellAbility sa : card.getSpellAbilities()) {
|
||||||
if (sa.isManaAbility() && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.isManaAbility() && sa.getPayCosts().hasTapCost()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,9 +113,7 @@ public class ComputerUtilAbility {
|
|||||||
List<SpellAbility> priorityAltSa = Lists.newArrayList();
|
List<SpellAbility> priorityAltSa = Lists.newArrayList();
|
||||||
List<SpellAbility> otherAltSa = Lists.newArrayList();
|
List<SpellAbility> otherAltSa = Lists.newArrayList();
|
||||||
for (SpellAbility altSa : saAltCosts) {
|
for (SpellAbility altSa : saAltCosts) {
|
||||||
if (altSa.getPayCosts() == null || sa.getPayCosts() == null) {
|
if (sa.getPayCosts().isOnlyManaCost()
|
||||||
otherAltSa.add(altSa);
|
|
||||||
} else if (sa.getPayCosts().isOnlyManaCost()
|
|
||||||
&& altSa.getPayCosts().isOnlyManaCost() && sa.getPayCosts().getTotalMana().compareTo(altSa.getPayCosts().getTotalMana()) == 1) {
|
&& altSa.getPayCosts().isOnlyManaCost() && sa.getPayCosts().getTotalMana().compareTo(altSa.getPayCosts().getTotalMana()) == 1) {
|
||||||
// the alternative cost is strictly cheaper, so why not? (e.g. Omniscience etc.)
|
// the alternative cost is strictly cheaper, so why not? (e.g. Omniscience etc.)
|
||||||
priorityAltSa.add(altSa);
|
priorityAltSa.add(altSa);
|
||||||
|
|||||||
@@ -1474,7 +1474,7 @@ public class ComputerUtilCard {
|
|||||||
if (totalPowerUnblocked >= opp.getLife()) {
|
if (totalPowerUnblocked >= opp.getLife()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (totalPowerUnblocked > dmg && sa.getHostCard() != null && sa.getHostCard().isInPlay()) {
|
} else if (totalPowerUnblocked > dmg && sa.getHostCard() != null && sa.getHostCard().isInPlay()) {
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().hasNoManaCost()) {
|
if (sa.getPayCosts().hasNoManaCost()) {
|
||||||
return true; // always activate abilities which cost no mana and which can increase unblocked damage
|
return true; // always activate abilities which cost no mana and which can increase unblocked damage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1785,10 +1785,6 @@ public class ComputerUtilCard {
|
|||||||
|
|
||||||
for (Card c : otb) {
|
for (Card c : otb) {
|
||||||
for (SpellAbility sa : c.getSpellAbilities()) {
|
for (SpellAbility sa : c.getSpellAbilities()) {
|
||||||
if (sa.getPayCosts() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CostPayEnergy energyCost = sa.getPayCosts().getCostEnergy();
|
CostPayEnergy energyCost = sa.getPayCosts().getCostEnergy();
|
||||||
if (energyCost != null) {
|
if (energyCost != null) {
|
||||||
int amount = energyCost.convertAmount();
|
int amount = energyCost.convertAmount();
|
||||||
|
|||||||
@@ -1028,7 +1028,7 @@ public class ComputerUtilCombat {
|
|||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
for (SpellAbility ability : blocker.getAllSpellAbilities()) {
|
for (SpellAbility ability : blocker.getAllSpellAbilities()) {
|
||||||
if (!(ability instanceof AbilityActivated) || ability.getPayCosts() == null) {
|
if (!(ability instanceof AbilityActivated)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ability.hasParam("ActivationPhases") || ability.hasParam("SorcerySpeed") || ability.hasParam("ActivationZone")) {
|
if (ability.hasParam("ActivationPhases") || ability.hasParam("SorcerySpeed") || ability.hasParam("ActivationZone")) {
|
||||||
@@ -1203,7 +1203,7 @@ public class ComputerUtilCombat {
|
|||||||
return toughness;
|
return toughness;
|
||||||
}
|
}
|
||||||
for (SpellAbility ability : blocker.getAllSpellAbilities()) {
|
for (SpellAbility ability : blocker.getAllSpellAbilities()) {
|
||||||
if (!(ability instanceof AbilityActivated) || ability.getPayCosts() == null) {
|
if (!(ability instanceof AbilityActivated)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1426,7 +1426,7 @@ public class ComputerUtilCombat {
|
|||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
for (SpellAbility ability : attacker.getAllSpellAbilities()) {
|
for (SpellAbility ability : attacker.getAllSpellAbilities()) {
|
||||||
if (!(ability instanceof AbilityActivated) || ability.getPayCosts() == null) {
|
if (!(ability instanceof AbilityActivated)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ability.hasParam("ActivationPhases") || ability.hasParam("SorcerySpeed") || ability.hasParam("ActivationZone")) {
|
if (ability.hasParam("ActivationPhases") || ability.hasParam("SorcerySpeed") || ability.hasParam("ActivationZone")) {
|
||||||
@@ -1662,7 +1662,7 @@ public class ComputerUtilCombat {
|
|||||||
return toughness;
|
return toughness;
|
||||||
}
|
}
|
||||||
for (SpellAbility ability : attacker.getAllSpellAbilities()) {
|
for (SpellAbility ability : attacker.getAllSpellAbilities()) {
|
||||||
if (!(ability instanceof AbilityActivated) || ability.getPayCosts() == null) {
|
if (!(ability instanceof AbilityActivated)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2517,7 +2517,7 @@ public class ComputerUtilCombat {
|
|||||||
final Player controller = combatant.getController();
|
final Player controller = combatant.getController();
|
||||||
for (Card c : controller.getCardsIn(ZoneType.Battlefield)) {
|
for (Card c : controller.getCardsIn(ZoneType.Battlefield)) {
|
||||||
for (SpellAbility ability : c.getAllSpellAbilities()) {
|
for (SpellAbility ability : c.getAllSpellAbilities()) {
|
||||||
if (!(ability instanceof AbilityActivated) || ability.getPayCosts() == null) {
|
if (!(ability instanceof AbilityActivated)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ability.getApi() != ApiType.Pump) {
|
if (ability.getApi() != ApiType.Pump) {
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ public class ComputerUtilCost {
|
|||||||
public boolean apply(Card card) {
|
public boolean apply(Card card) {
|
||||||
boolean hasManaSa = false;
|
boolean hasManaSa = false;
|
||||||
for (final SpellAbility sa : card.getSpellAbilities()) {
|
for (final SpellAbility sa : card.getSpellAbilities()) {
|
||||||
if (sa.isManaAbility() && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.isManaAbility() && sa.getPayCosts().hasTapCost()) {
|
||||||
hasManaSa = true;
|
hasManaSa = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -507,16 +507,10 @@ public class ComputerUtilMana {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (saPayment.getPayCosts() != null) {
|
final CostPayment pay = new CostPayment(saPayment.getPayCosts(), saPayment);
|
||||||
final CostPayment pay = new CostPayment(saPayment.getPayCosts(), saPayment);
|
if (!pay.payComputerCosts(new AiCostDecision(ai, saPayment))) {
|
||||||
if (!pay.payComputerCosts(new AiCostDecision(ai, saPayment))) {
|
saList.remove(saPayment);
|
||||||
saList.remove(saPayment);
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
System.err.println("Ability " + saPayment + " from " + saPayment.getHostCard() + " had NULL as payCost");
|
|
||||||
saPayment.getHostCard().tap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ai.getGame().getStack().addAndUnfreeze(saPayment);
|
ai.getGame().getStack().addAndUnfreeze(saPayment);
|
||||||
@@ -837,10 +831,9 @@ public class ComputerUtilMana {
|
|||||||
if (checkCosts) {
|
if (checkCosts) {
|
||||||
// Check if AI can still play this mana ability
|
// Check if AI can still play this mana ability
|
||||||
ma.setActivatingPlayer(ai);
|
ma.setActivatingPlayer(ai);
|
||||||
if (ma.getPayCosts() != null) { // if the AI can't pay the additional costs skip the mana ability
|
// if the AI can't pay the additional costs skip the mana ability
|
||||||
if (!CostPayment.canPayAdditionalCosts(ma.getPayCosts(), ma)) {
|
if (!CostPayment.canPayAdditionalCosts(ma.getPayCosts(), ma)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (sourceCard.isTapped()) {
|
else if (sourceCard.isTapped()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1144,7 +1137,7 @@ public class ComputerUtilMana {
|
|||||||
ManaCostBeingPaid cost = new ManaCostBeingPaid(mana, restriction);
|
ManaCostBeingPaid cost = new ManaCostBeingPaid(mana, restriction);
|
||||||
|
|
||||||
// Tack xMana Payments into mana here if X is a set value
|
// Tack xMana Payments into mana here if X is a set value
|
||||||
if (sa.getPayCosts() != null && (cost.getXcounter() > 0 || extraMana > 0)) {
|
if (cost.getXcounter() > 0 || extraMana > 0) {
|
||||||
int manaToAdd = 0;
|
int manaToAdd = 0;
|
||||||
if (test && extraMana > 0) {
|
if (test && extraMana > 0) {
|
||||||
final int multiplicator = Math.max(cost.getXcounter(), 1);
|
final int multiplicator = Math.max(cost.getXcounter(), 1);
|
||||||
@@ -1218,7 +1211,7 @@ public class ComputerUtilMana {
|
|||||||
for (SpellAbility ma : src.getManaAbilities()) {
|
for (SpellAbility ma : src.getManaAbilities()) {
|
||||||
ma.setActivatingPlayer(p);
|
ma.setActivatingPlayer(p);
|
||||||
if (!checkPlayable || ma.canPlay()) {
|
if (!checkPlayable || ma.canPlay()) {
|
||||||
int costsToActivate = ma.getPayCosts() != null && ma.getPayCosts().getCostMana() != null ? ma.getPayCosts().getCostMana().convertAmount() : 0;
|
int costsToActivate = ma.getPayCosts().getCostMana() != null ? ma.getPayCosts().getCostMana().convertAmount() : 0;
|
||||||
int producedMana = ma.getParamOrDefault("Produced", "").split(" ").length;
|
int producedMana = ma.getParamOrDefault("Produced", "").split(" ").length;
|
||||||
int producedAmount = AbilityUtils.calculateAmount(src, ma.getParamOrDefault("Amount", "1"), ma);
|
int producedAmount = AbilityUtils.calculateAmount(src, ma.getParamOrDefault("Amount", "1"), ma);
|
||||||
|
|
||||||
@@ -1594,7 +1587,7 @@ public class ComputerUtilMana {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int determineMaxAffordableX(Player ai, SpellAbility sa) {
|
public static int determineMaxAffordableX(Player ai, SpellAbility sa) {
|
||||||
if (sa.getPayCosts() == null || sa.getPayCosts().getCostMana() == null) {
|
if (sa.getPayCosts().getCostMana() == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ public class CreatureEvaluator implements Function<Card, Integer> {
|
|||||||
&& "+X".equals(sa.getParam("NumDef"))
|
&& "+X".equals(sa.getParam("NumDef"))
|
||||||
&& !sa.usesTargeting()
|
&& !sa.usesTargeting()
|
||||||
&& (!sa.hasParam("Defined") || "Self".equals(sa.getParam("Defined")))) {
|
&& (!sa.hasParam("Defined") || "Self".equals(sa.getParam("Defined")))) {
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().hasOnlySpecificCostType(CostPayEnergy.class)) {
|
if (sa.getPayCosts().hasOnlySpecificCostType(CostPayEnergy.class)) {
|
||||||
// Electrostatic Pummeler, can be expanded for similar cards
|
// Electrostatic Pummeler, can be expanded for similar cards
|
||||||
int initPower = getEffectivePower(sa.getHostCard());
|
int initPower = getEffectivePower(sa.getHostCard());
|
||||||
int pumpedPower = initPower;
|
int pumpedPower = initPower;
|
||||||
|
|||||||
@@ -1216,7 +1216,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
public List<OptionalCostValue> chooseOptionalCosts(SpellAbility chosen,
|
public List<OptionalCostValue> chooseOptionalCosts(SpellAbility chosen,
|
||||||
List<OptionalCostValue> optionalCostValues) {
|
List<OptionalCostValue> optionalCostValues) {
|
||||||
List<OptionalCostValue> chosenOptCosts = Lists.newArrayList();
|
List<OptionalCostValue> chosenOptCosts = Lists.newArrayList();
|
||||||
Cost costSoFar = chosen.getPayCosts() != null ? chosen.getPayCosts().copy() : Cost.Zero;
|
Cost costSoFar = chosen.getPayCosts().copy();
|
||||||
|
|
||||||
for (OptionalCostValue opt : optionalCostValues) {
|
for (OptionalCostValue opt : optionalCostValues) {
|
||||||
// Choose the optional cost if it can be paid (to be improved later, check for playability and other conditions perhaps)
|
// Choose the optional cost if it can be paid (to be improved later, check for playability and other conditions perhaps)
|
||||||
@@ -1255,7 +1255,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
// TODO: improve the logic depending on the keyword and the playability of the cost-modified SA (enough targets present etc.)
|
// TODO: improve the logic depending on the keyword and the playability of the cost-modified SA (enough targets present etc.)
|
||||||
int chosenAmount = 0;
|
int chosenAmount = 0;
|
||||||
|
|
||||||
Cost costSoFar = sa.getPayCosts() != null ? sa.getPayCosts().copy() : Cost.Zero;
|
Cost costSoFar = sa.getPayCosts().copy();
|
||||||
|
|
||||||
for (int i = 0; i < max; i++) {
|
for (int i = 0; i < max; i++) {
|
||||||
costSoFar.add(cost);
|
costSoFar.add(cost);
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ public abstract class SpellAbilityAi {
|
|||||||
|
|
||||||
// TODO probably also consider if winter orb or similar are out
|
// TODO probably also consider if winter orb or similar are out
|
||||||
|
|
||||||
if (sa.getPayCosts() == null || sa instanceof AbilitySub) {
|
if (sa instanceof AbilitySub) {
|
||||||
return true; // This is only true for Drawbacks and triggers
|
return true; // This is only true for Drawbacks and triggers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -247,7 +247,6 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
final Player ai = sa.getActivatingPlayer();
|
final Player ai = sa.getActivatingPlayer();
|
||||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||||
final boolean alwaysActivatePWAbility = sa.hasParam("Planeswalker")
|
final boolean alwaysActivatePWAbility = sa.hasParam("Planeswalker")
|
||||||
&& sa.getPayCosts() != null
|
|
||||||
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class)
|
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class)
|
||||||
&& sa.getTargetRestrictions() != null
|
&& sa.getTargetRestrictions() != null
|
||||||
&& sa.getTargetRestrictions().getMinTargets(sa.getHostCard(), sa) == 0;
|
&& sa.getTargetRestrictions().getMinTargets(sa.getHostCard(), sa) == 0;
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
if (!c.isCreature() && !c.getType().hasSubtype("Vehicle") && !c.isTapped()) {
|
if (!c.isCreature() && !c.getType().hasSubtype("Vehicle") && !c.isTapped()) {
|
||||||
// try to identify if this thing can actually tap
|
// try to identify if this thing can actually tap
|
||||||
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
||||||
if (ab.getPayCosts() != null && ab.getPayCosts().hasTapCost()) {
|
if (ab.getPayCosts().hasTapCost()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -560,7 +560,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
for (final SpellAbility sa : c.getSpellAbilities()) {
|
for (final SpellAbility sa : c.getSpellAbilities()) {
|
||||||
if (sa.isAbility() && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.isAbility() && sa.getPayCosts().hasTapCost()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1065,8 +1065,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
if (destination.equals(ZoneType.Exile) || origin.contains(ZoneType.Battlefield)) {
|
if (destination.equals(ZoneType.Exile) || origin.contains(ZoneType.Battlefield)) {
|
||||||
|
|
||||||
// don't rush bouncing stuff when not going to attack
|
// don't rush bouncing stuff when not going to attack
|
||||||
if (!immediately && sa.getPayCosts() != null
|
if (!immediately && game.getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
|
||||||
&& game.getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
|
|
||||||
&& game.getPhaseHandler().isPlayerTurn(ai)
|
&& game.getPhaseHandler().isPlayerTurn(ai)
|
||||||
&& ai.getCreaturesInPlay().isEmpty()) {
|
&& ai.getCreaturesInPlay().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1103,8 +1102,8 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean doWithoutTarget = sa.hasParam("Planeswalker") && sa.getTargetRestrictions() != null
|
boolean doWithoutTarget = sa.hasParam("Planeswalker") && sa.usesTargeting()
|
||||||
&& sa.getTargetRestrictions().getMinTargets(source, sa) == 0 && sa.getPayCosts() != null
|
&& sa.getTargetRestrictions().getMinTargets(source, sa) == 0
|
||||||
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class);
|
&& sa.getPayCosts().hasSpecificCostType(CostPutCounter.class);
|
||||||
|
|
||||||
if (list.isEmpty() && !doWithoutTarget) {
|
if (list.isEmpty() && !doWithoutTarget) {
|
||||||
@@ -1790,6 +1789,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean doReturnCommanderLogic(SpellAbility sa, Player aiPlayer) {
|
public boolean doReturnCommanderLogic(SpellAbility sa, Player aiPlayer) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>)sa.getReplacingObject(AbilityKey.OriginalParams);
|
Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>)sa.getReplacingObject(AbilityKey.OriginalParams);
|
||||||
SpellAbility causeSa = (SpellAbility)originalParams.get(AbilityKey.Cause);
|
SpellAbility causeSa = (SpellAbility)originalParams.get(AbilityKey.Cause);
|
||||||
SpellAbility causeSub = null;
|
SpellAbility causeSub = null;
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (SpellAbility sa : c.getAllSpellAbilities()) {
|
for (SpellAbility sa : c.getAllSpellAbilities()) {
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.getPayCosts().hasTapCost()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public class CopySpellAbilityAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
final SpellAbility top = game.getStack().peekAbility();
|
final SpellAbility top = game.getStack().peekAbility();
|
||||||
if (top != null
|
if (top != null
|
||||||
&& top.getPayCosts() != null && top.getPayCosts().getCostMana() != null
|
&& top.getPayCosts().getCostMana() != null
|
||||||
&& sa.getPayCosts() != null && sa.getPayCosts().getCostMana() != null
|
&& sa.getPayCosts().getCostMana() != null
|
||||||
&& top.getPayCosts().getCostMana().getMana().getCMC() >= sa.getPayCosts().getCostMana().getMana().getCMC() + diff) {
|
&& top.getPayCosts().getCostMana().getMana().getCMC() >= sa.getPayCosts().getCostMana().getMana().getCMC() + diff) {
|
||||||
// The copied spell has a significantly higher CMC than the copy spell, consider copying
|
// The copied spell has a significantly higher CMC than the copy spell, consider copying
|
||||||
chance = 100;
|
chance = 100;
|
||||||
|
|||||||
@@ -454,7 +454,6 @@ public class CountersPutAi extends SpellAbilityAi {
|
|||||||
// but try to do it in Main 2 then so that the AI has a chance to play creatures first.
|
// but try to do it in Main 2 then so that the AI has a chance to play creatures first.
|
||||||
if (list.isEmpty()
|
if (list.isEmpty()
|
||||||
&& sa.hasParam("Planeswalker")
|
&& sa.hasParam("Planeswalker")
|
||||||
&& sa.getPayCosts() != null
|
|
||||||
&& sa.getPayCosts().hasOnlySpecificCostType(CostPutCounter.class)
|
&& sa.getPayCosts().hasOnlySpecificCostType(CostPutCounter.class)
|
||||||
&& sa.isTargetNumberValid()
|
&& sa.isTargetNumberValid()
|
||||||
&& sa.getTargets().getNumTargeted() == 0
|
&& sa.getTargets().getNumTargeted() == 0
|
||||||
@@ -706,7 +705,7 @@ public class CountersPutAi extends SpellAbilityAi {
|
|||||||
SpellAbility testSa = sa;
|
SpellAbility testSa = sa;
|
||||||
int countX = 0;
|
int countX = 0;
|
||||||
int nonXGlyphs = 0;
|
int nonXGlyphs = 0;
|
||||||
while (testSa != null && testSa.getPayCosts() != null && countX == 0) {
|
while (testSa != null && countX == 0) {
|
||||||
countX = testSa.getPayCosts().getTotalMana().countX();
|
countX = testSa.getPayCosts().getTotalMana().countX();
|
||||||
nonXGlyphs = testSa.getPayCosts().getTotalMana().getGlyphCount() - countX;
|
nonXGlyphs = testSa.getPayCosts().getTotalMana().getGlyphCount() - countX;
|
||||||
testSa = testSa.getSubAbility();
|
testSa = testSa.getSubAbility();
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ public class CountersPutAllAi extends SpellAbilityAi {
|
|||||||
//Check for cards that could profit from the ability
|
//Check for cards that could profit from the ability
|
||||||
PhaseHandler phase = ai.getGame().getPhaseHandler();
|
PhaseHandler phase = ai.getGame().getPhaseHandler();
|
||||||
if (type.equals("P1P1") && sa.isAbility() && source.isCreature()
|
if (type.equals("P1P1") && sa.isAbility() && source.isCreature()
|
||||||
&& sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()
|
&& sa.getPayCosts().hasTapCost()
|
||||||
&& sa instanceof AbilitySub
|
&& sa instanceof AbilitySub
|
||||||
&& (!phase.getNextTurn().equals(ai)
|
&& (!phase.getNextTurn().equals(ai)
|
||||||
|| phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
|
|| phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) {
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ public class DamageAllAi extends SpellAbilityAi {
|
|||||||
x = source.getCounters(CounterType.LOYALTY);
|
x = source.getCounters(CounterType.LOYALTY);
|
||||||
}
|
}
|
||||||
if (x == -1) {
|
if (x == -1) {
|
||||||
Player bestOpp = determineOppToKill(ai, sa, source, dmg);
|
|
||||||
if (determineOppToKill(ai, sa, source, dmg) != null) {
|
if (determineOppToKill(ai, sa, source, dmg) != null) {
|
||||||
// we already know we can kill a player, so go for it
|
// we already know we can kill a player, so go for it
|
||||||
return true;
|
return true;
|
||||||
@@ -138,7 +137,7 @@ public class DamageAllAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int minGain = 200; // The minimum gain in destroyed creatures
|
int minGain = 200; // The minimum gain in destroyed creatures
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().isReusuableResource()) {
|
if (sa.getPayCosts().isReusuableResource()) {
|
||||||
if (computerList.isEmpty()) {
|
if (computerList.isEmpty()) {
|
||||||
minGain = 10; // nothing to lose
|
minGain = 10; // nothing to lose
|
||||||
// no creatures to lose and player can be damaged
|
// no creatures to lose and player can be damaged
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("XCountersDamage".equals(logic) && sa.getPayCosts() != null) {
|
if ("XCountersDamage".equals(logic)) {
|
||||||
// Check to ensure that we have enough counters to remove per the defined PayX
|
// Check to ensure that we have enough counters to remove per the defined PayX
|
||||||
for (CostPart part : sa.getPayCosts().getCostParts()) {
|
for (CostPart part : sa.getPayCosts().getCostParts()) {
|
||||||
if (part instanceof CostRemoveCounter) {
|
if (part instanceof CostRemoveCounter) {
|
||||||
@@ -449,7 +449,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
int pwScore = curLoyalty * 10;
|
int pwScore = curLoyalty * 10;
|
||||||
|
|
||||||
for (SpellAbility sa : pw.getSpellAbilities()) {
|
for (SpellAbility sa : pw.getSpellAbilities()) {
|
||||||
if (sa.hasParam("Ultimate") && sa.getPayCosts() != null) {
|
if (sa.hasParam("Ultimate")) {
|
||||||
Integer loyaltyCost = 0;
|
Integer loyaltyCost = 0;
|
||||||
CostRemoveCounter remLoyalty = sa.getPayCosts().getCostPartByType(CostRemoveCounter.class);
|
CostRemoveCounter remLoyalty = sa.getPayCosts().getCostPartByType(CostRemoveCounter.class);
|
||||||
if (remLoyalty != null) {
|
if (remLoyalty != null) {
|
||||||
@@ -794,8 +794,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
if (((phase.is(PhaseType.END_OF_TURN) && phase.getNextTurn().equals(ai))
|
if (((phase.is(PhaseType.END_OF_TURN) && phase.getNextTurn().equals(ai))
|
||||||
|| (SpellAbilityAi.isSorcerySpeed(sa) && phase.is(PhaseType.MAIN2))
|
|| (SpellAbilityAi.isSorcerySpeed(sa) && phase.is(PhaseType.MAIN2))
|
||||||
|| ("PingAfterAttack".equals(logic) && phase.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) && phase.isPlayerTurn(ai))
|
|| ("PingAfterAttack".equals(logic) && phase.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) && phase.isPlayerTurn(ai))
|
||||||
|| sa.getPayCosts() == null || immediately
|
|| immediately || shouldTgtP(ai, sa, dmg, noPrevention)) &&
|
||||||
|| this.shouldTgtP(ai, sa, dmg, noPrevention)) &&
|
|
||||||
(!avoidTargetP(ai, sa))) {
|
(!avoidTargetP(ai, sa))) {
|
||||||
tcs.add(enemy);
|
tcs.add(enemy);
|
||||||
if (divided) {
|
if (divided) {
|
||||||
@@ -1126,8 +1125,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// currently works only with cards that don't have additional costs (only mana is supported)
|
// currently works only with cards that don't have additional costs (only mana is supported)
|
||||||
if (ab.getPayCosts() != null
|
if (ab.getPayCosts().hasNoManaCost() || ab.getPayCosts().hasOnlySpecificCostType(CostPartMana.class)) {
|
||||||
&& (ab.getPayCosts().hasNoManaCost() || ab.getPayCosts().hasOnlySpecificCostType(CostPartMana.class))) {
|
|
||||||
String dmgDef = "0";
|
String dmgDef = "0";
|
||||||
if (ab.getApi() == ApiType.DealDamage) {
|
if (ab.getApi() == ApiType.DealDamage) {
|
||||||
dmgDef = ab.getParamOrDefault("NumDmg", "0");
|
dmgDef = ab.getParamOrDefault("NumDmg", "0");
|
||||||
@@ -1151,7 +1149,7 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: should it also check restrictions for targeting players?
|
// FIXME: should it also check restrictions for targeting players?
|
||||||
ManaCost costSa = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : ManaCost.NO_COST;
|
ManaCost costSa = sa.getPayCosts().getTotalMana();
|
||||||
ManaCost costAb = ab.getPayCosts().getTotalMana(); // checked for null above
|
ManaCost costAb = ab.getPayCosts().getTotalMana(); // checked for null above
|
||||||
ManaCost total = ManaCost.combine(costSa, costAb);
|
ManaCost total = ManaCost.combine(costSa, costAb);
|
||||||
SpellAbility combinedAb = ab.copyWithDefinedCost(new Cost(total, false));
|
SpellAbility combinedAb = ab.copyWithDefinedCost(new Cost(total, false));
|
||||||
|
|||||||
@@ -262,22 +262,20 @@ public class DrawAi extends SpellAbilityAi {
|
|||||||
// Draw up to max hand size but leave at least 3 in library
|
// Draw up to max hand size but leave at least 3 in library
|
||||||
numCards = Math.min(computerMaxHandSize - computerHandSize, computerLibrarySize - 3);
|
numCards = Math.min(computerMaxHandSize - computerHandSize, computerLibrarySize - 3);
|
||||||
|
|
||||||
if (sa.getPayCosts() != null) {
|
if (sa.getPayCosts().hasSpecificCostType(CostPayLife.class)) {
|
||||||
if (sa.getPayCosts().hasSpecificCostType(CostPayLife.class)) {
|
// [Necrologia, Pay X Life : Draw X Cards]
|
||||||
// [Necrologia, Pay X Life : Draw X Cards]
|
// Don't draw more than what's "safe" and don't risk a near death experience
|
||||||
// Don't draw more than what's "safe" and don't risk a near death experience
|
// Maybe would be better to check for "serious danger" and take more risk?
|
||||||
// Maybe would be better to check for "serious danger" and take more risk?
|
while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) {
|
||||||
while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) {
|
numCards--;
|
||||||
numCards--;
|
}
|
||||||
}
|
} else if (sa.getPayCosts().hasSpecificCostType(CostSacrifice.class)) {
|
||||||
} else if (sa.getPayCosts().hasSpecificCostType(CostSacrifice.class)) {
|
// [e.g. Krav, the Unredeemed and other cases which say "Sacrifice X creatures: draw X cards]
|
||||||
// [e.g. Krav, the Unredeemed and other cases which say "Sacrifice X creatures: draw X cards]
|
// TODO: Add special logic to limit/otherwise modify the ChosenX value here
|
||||||
// TODO: Add special logic to limit/otherwise modify the ChosenX value here
|
|
||||||
|
|
||||||
// Skip this ability if nothing is to be chosen for sacrifice
|
// Skip this ability if nothing is to be chosen for sacrifice
|
||||||
if (numCards <= 0) {
|
if (numCards <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class EffectAi extends SpellAbilityAi {
|
|||||||
} else if (logic.equals("SpellCopy")) {
|
} else if (logic.equals("SpellCopy")) {
|
||||||
// fetch Instant or Sorcery and AI has reason to play this turn
|
// fetch Instant or Sorcery and AI has reason to play this turn
|
||||||
// does not try to get itself
|
// does not try to get itself
|
||||||
final ManaCost costSa = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : ManaCost.NO_COST;
|
final ManaCost costSa = sa.getPayCosts().getTotalMana();
|
||||||
final int count = CardLists.count(ai.getCardsIn(ZoneType.Hand), new Predicate<Card>() {
|
final int count = CardLists.count(ai.getCardsIn(ZoneType.Hand), new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
@@ -135,7 +135,7 @@ public class EffectAi extends SpellAbilityAi {
|
|||||||
AiPlayDecision decision = ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(ab);
|
AiPlayDecision decision = ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(ab);
|
||||||
// see if we can pay both for this spell and for the Effect spell we're considering
|
// see if we can pay both for this spell and for the Effect spell we're considering
|
||||||
if (decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2) {
|
if (decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2) {
|
||||||
ManaCost costAb = ab.getPayCosts() != null ? ab.getPayCosts().getTotalMana() : ManaCost.NO_COST;
|
ManaCost costAb = ab.getPayCosts().getTotalMana();
|
||||||
ManaCost total = ManaCost.combine(costSa, costAb);
|
ManaCost total = ManaCost.combine(costSa, costAb);
|
||||||
SpellAbility combinedAb = ab.copyWithDefinedCost(new Cost(total, false));
|
SpellAbility combinedAb = ab.copyWithDefinedCost(new Cost(total, false));
|
||||||
// can we pay both costs?
|
// can we pay both costs?
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ public class LifeGainAi extends SpellAbilityAi {
|
|||||||
if (lifeCritical
|
if (lifeCritical
|
||||||
&& sa.isAbility()
|
&& sa.isAbility()
|
||||||
&& sa.getHostCard() != null && sa.getHostCard().isCreature()
|
&& sa.getHostCard() != null && sa.getHostCard().isCreature()
|
||||||
&& sa.getPayCosts() != null
|
|
||||||
&& (sa.getPayCosts().hasSpecificCostType(CostRemoveCounter.class) || sa.getPayCosts().hasSpecificCostType(CostSacrifice.class))) {
|
&& (sa.getPayCosts().hasSpecificCostType(CostRemoveCounter.class) || sa.getPayCosts().hasSpecificCostType(CostSacrifice.class))) {
|
||||||
if (!game.getStack().isEmpty()) {
|
if (!game.getStack().isEmpty()) {
|
||||||
SpellAbility saTop = game.getStack().peekAbility();
|
SpellAbility saTop = game.getStack().peekAbility();
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class ManaEffectAi extends SpellAbilityAi {
|
|||||||
return true; // handled elsewhere, does not meet the standard requirements
|
return true; // handled elsewhere, does not meet the standard requirements
|
||||||
}
|
}
|
||||||
|
|
||||||
return sa.getPayCosts() != null && sa.getPayCosts().hasNoManaCost() && sa.getPayCosts().isReusuableResource()
|
return sa.getPayCosts().hasNoManaCost() && sa.getPayCosts().isReusuableResource()
|
||||||
&& sa.getSubAbility() == null && ComputerUtil.playImmediately(ai, sa);
|
&& sa.getSubAbility() == null && ComputerUtil.playImmediately(ai, sa);
|
||||||
// return super.checkApiLogic(ai, sa);
|
// return super.checkApiLogic(ai, sa);
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ public class ManaEffectAi extends SpellAbilityAi {
|
|||||||
int numCounters = 0;
|
int numCounters = 0;
|
||||||
int manaSurplus = 0;
|
int manaSurplus = 0;
|
||||||
if ("XChoice".equals(host.getSVar("X"))
|
if ("XChoice".equals(host.getSVar("X"))
|
||||||
&& sa.getPayCosts() != null && sa.getPayCosts().hasSpecificCostType(CostRemoveCounter.class)) {
|
&& sa.getPayCosts().hasSpecificCostType(CostRemoveCounter.class)) {
|
||||||
CounterType ctrType = CounterType.KI; // Petalmane Baku
|
CounterType ctrType = CounterType.KI; // Petalmane Baku
|
||||||
for (CostPart part : sa.getPayCosts().getCostParts()) {
|
for (CostPart part : sa.getPayCosts().getCostParts()) {
|
||||||
if (part instanceof CostRemoveCounter) {
|
if (part instanceof CostRemoveCounter) {
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ public class PlayAi extends SpellAbilityAi {
|
|||||||
return ComputerUtil.targetPlayableSpellCard(ai, cards, sa, sa.hasParam("WithoutManaCost"));
|
return ComputerUtil.targetPlayableSpellCard(ai, cards, sa, sa.hasParam("WithoutManaCost"));
|
||||||
} else if (logic.startsWith("NeedsChosenCard")) {
|
} else if (logic.startsWith("NeedsChosenCard")) {
|
||||||
int minCMC = 0;
|
int minCMC = 0;
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().getCostMana() != null) {
|
if (sa.getPayCosts().getCostMana() != null) {
|
||||||
minCMC = sa.getPayCosts().getCostMana().getMana().getCMC();
|
minCMC = sa.getPayCosts().getTotalMana().getCMC();
|
||||||
}
|
}
|
||||||
validOpts = CardLists.filter(validOpts, CardPredicates.greaterCMC(minCMC));
|
validOpts = CardLists.filter(validOpts, CardPredicates.greaterCMC(minCMC));
|
||||||
return chooseSingleCard(ai, sa, validOpts, sa.hasParam("Optional"), null) != null;
|
return chooseSingleCard(ai, sa, validOpts, sa.hasParam("Optional"), null) != null;
|
||||||
@@ -156,9 +156,7 @@ public class PlayAi extends SpellAbilityAi {
|
|||||||
if (sa.hasParam("WithoutManaCost")) {
|
if (sa.hasParam("WithoutManaCost")) {
|
||||||
// Try to avoid casting instants and sorceries with X in their cost, since X will be assumed to be 0.
|
// Try to avoid casting instants and sorceries with X in their cost, since X will be assumed to be 0.
|
||||||
if (!(spell instanceof SpellPermanent)) {
|
if (!(spell instanceof SpellPermanent)) {
|
||||||
if (spell.getPayCosts() != null
|
if (spell.getPayCosts().getTotalMana().countX() > 0) {
|
||||||
&& spell.getPayCosts().getCostMana() != null
|
|
||||||
&& spell.getPayCosts().getCostMana().getMana().countX() > 0) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ public class ProtectAi extends SpellAbilityAi {
|
|||||||
if (game.getStack().isEmpty()) {
|
if (game.getStack().isEmpty()) {
|
||||||
// If the cost is tapping, don't activate before declare
|
// If the cost is tapping, don't activate before declare
|
||||||
// attack/block
|
// attack/block
|
||||||
if ((sa.getPayCosts() != null) && sa.getPayCosts().hasTapCost()) {
|
if (sa.getPayCosts().hasTapCost()) {
|
||||||
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||||
&& game.getPhaseHandler().isPlayerTurn(ai)) {
|
&& game.getPhaseHandler().isPlayerTurn(ai)) {
|
||||||
list.remove(sa.getHostCard());
|
list.remove(sa.getHostCard());
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
if (game.getStack().isEmpty()) {
|
if (game.getStack().isEmpty()) {
|
||||||
// If the cost is tapping, don't activate before declare
|
// If the cost is tapping, don't activate before declare
|
||||||
// attack/block
|
// attack/block
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.getPayCosts().hasTapCost()) {
|
||||||
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
|
||||||
&& game.getPhaseHandler().isPlayerTurn(ai)) {
|
&& game.getPhaseHandler().isPlayerTurn(ai)) {
|
||||||
list.remove(sa.getHostCard());
|
list.remove(sa.getHostCard());
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
List<Card> attackers = CardLists.filter(ai.getCreaturesInPlay(), new Predicate<Card>() {
|
List<Card> attackers = CardLists.filter(ai.getCreaturesInPlay(), new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
if (c.equals(sa.getHostCard()) && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()
|
if (c.equals(sa.getHostCard()) && sa.getPayCosts().hasTapCost()
|
||||||
&& (combat == null || !combat.isAttacking(c))) {
|
&& (combat == null || !combat.isAttacking(c))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
List<Card> attackers = CardLists.filter(ai.getCreaturesInPlay(), new Predicate<Card>() {
|
List<Card> attackers = CardLists.filter(ai.getCreaturesInPlay(), new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
if (c.equals(sa.getHostCard()) && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()
|
if (c.equals(sa.getHostCard()) && sa.getPayCosts().hasTapCost()
|
||||||
&& (combat == null || !combat.isAttacking(c))) {
|
&& (combat == null || !combat.isAttacking(c))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class RearrangeTopOfLibraryAi extends SpellAbilityAi {
|
|||||||
final PhaseHandler ph = aiPlayer.getGame().getPhaseHandler();
|
final PhaseHandler ph = aiPlayer.getGame().getPhaseHandler();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
if (source.isPermanent() && sa.getRestrictions().isInstantSpeed() && sa.getPayCosts() != null
|
if (source.isPermanent() && sa.getRestrictions().isInstantSpeed()
|
||||||
&& (sa.getPayCosts().hasTapCost() || sa.getPayCosts().hasManaCost())) {
|
&& (sa.getPayCosts().hasTapCost() || sa.getPayCosts().hasManaCost())) {
|
||||||
// If it has an associated cost, try to only do this before own turn
|
// If it has an associated cost, try to only do this before own turn
|
||||||
if (!(ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == aiPlayer)) {
|
if (!(ph.is(PhaseType.END_OF_TURN) && ph.getNextTurn() == aiPlayer)) {
|
||||||
|
|||||||
@@ -46,12 +46,10 @@ public class ScryAi extends SpellAbilityAi {
|
|||||||
// and right before the beginning of AI's turn, if possible, to avoid mana locking the AI and also to
|
// and right before the beginning of AI's turn, if possible, to avoid mana locking the AI and also to
|
||||||
// try to scry right before drawing a card. Also, avoid tapping creatures in the AI's turn, if possible,
|
// try to scry right before drawing a card. Also, avoid tapping creatures in the AI's turn, if possible,
|
||||||
// even if there's no mana cost.
|
// even if there's no mana cost.
|
||||||
if (sa.getPayCosts() != null) {
|
if (sa.getPayCosts().hasTapCost()
|
||||||
if (sa.getPayCosts().hasTapCost()
|
&& (sa.getPayCosts().hasManaCost() || (sa.getHostCard() != null && sa.getHostCard().isCreature()))
|
||||||
&& (sa.getPayCosts().hasManaCost() || (sa.getHostCard() != null && sa.getHostCard().isCreature()))
|
&& !SpellAbilityAi.isSorcerySpeed(sa)) {
|
||||||
&& !SpellAbilityAi.isSorcerySpeed(sa)) {
|
return ph.getNextTurn() == ai && ph.is(PhaseType.END_OF_TURN);
|
||||||
return ph.getNextTurn() == ai && ph.is(PhaseType.END_OF_TURN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI logic to scry in Main 1 if there is no better option, otherwise scry at opponent's EOT
|
// AI logic to scry in Main 1 if there is no better option, otherwise scry at opponent's EOT
|
||||||
@@ -76,8 +74,7 @@ public class ScryAi extends SpellAbilityAi {
|
|||||||
boolean hasSomethingElse = false;
|
boolean hasSomethingElse = false;
|
||||||
for (Card c : CardLists.filter(ai.getCardsIn(ZoneType.Hand), Predicates.not(CardPredicates.Presets.LANDS))) {
|
for (Card c : CardLists.filter(ai.getCardsIn(ZoneType.Hand), Predicates.not(CardPredicates.Presets.LANDS))) {
|
||||||
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
||||||
if (ab.getPayCosts() != null
|
if (ab.getPayCosts().hasManaCost()
|
||||||
&& ab.getPayCosts().hasManaCost()
|
|
||||||
&& ComputerUtilMana.hasEnoughManaSourcesToCast(ab, ai)) {
|
&& ComputerUtilMana.hasEnoughManaSourcesToCast(ab, ai)) {
|
||||||
// TODO: currently looks for non-Scry cards, can most certainly be made smarter.
|
// TODO: currently looks for non-Scry cards, can most certainly be made smarter.
|
||||||
if (ab.getApi() != ApiType.Scry) {
|
if (ab.getApi() != ApiType.Scry) {
|
||||||
|
|||||||
@@ -47,12 +47,10 @@ public class SurveilAi extends SpellAbilityAi {
|
|||||||
// and right before the beginning of AI's turn, if possible, to avoid mana locking the AI and also to
|
// and right before the beginning of AI's turn, if possible, to avoid mana locking the AI and also to
|
||||||
// try to scry right before drawing a card. Also, avoid tapping creatures in the AI's turn, if possible,
|
// try to scry right before drawing a card. Also, avoid tapping creatures in the AI's turn, if possible,
|
||||||
// even if there's no mana cost.
|
// even if there's no mana cost.
|
||||||
if (sa.getPayCosts() != null) {
|
if (sa.getPayCosts().hasTapCost()
|
||||||
if (sa.getPayCosts().hasTapCost()
|
&& (sa.getPayCosts().hasManaCost() || (sa.getHostCard() != null && sa.getHostCard().isCreature()))
|
||||||
&& (sa.getPayCosts().hasManaCost() || (sa.getHostCard() != null && sa.getHostCard().isCreature()))
|
&& !SpellAbilityAi.isSorcerySpeed(sa)) {
|
||||||
&& !SpellAbilityAi.isSorcerySpeed(sa)) {
|
return ph.getNextTurn() == ai && ph.is(PhaseType.END_OF_TURN);
|
||||||
return ph.getNextTurn() == ai && ph.is(PhaseType.END_OF_TURN);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// in the player's turn Surveil should only be done in Main1 or in Upkeep if able
|
// in the player's turn Surveil should only be done in Main1 or in Upkeep if able
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final SpellAbility sa : c.getSpellAbilities()) {
|
for (final SpellAbility sa : c.getSpellAbilities()) {
|
||||||
if (sa.isAbility() && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.isAbility() && sa.getPayCosts().hasTapCost()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final SpellAbility sa : c.getSpellAbilities()) {
|
for (final SpellAbility sa : c.getSpellAbilities()) {
|
||||||
if (sa.isAbility() && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost()) {
|
if (sa.isAbility() && sa.getPayCosts().hasTapCost()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,12 +153,11 @@ public class UntapAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
// Try to avoid potential infinite recursion,
|
// Try to avoid potential infinite recursion,
|
||||||
// e.g. Kiora's Follower untapping another Kiora's Follower and repeating infinitely
|
// e.g. Kiora's Follower untapping another Kiora's Follower and repeating infinitely
|
||||||
if (sa.getPayCosts() != null && sa.getPayCosts().hasOnlySpecificCostType(CostTap.class)) {
|
if (sa.getPayCosts().hasOnlySpecificCostType(CostTap.class)) {
|
||||||
CardCollection toRemove = new CardCollection();
|
CardCollection toRemove = new CardCollection();
|
||||||
for (Card c : untapList) {
|
for (Card c : untapList) {
|
||||||
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
for (SpellAbility ab : c.getAllSpellAbilities()) {
|
||||||
if (ab.getApi() == ApiType.Untap
|
if (ab.getApi() == ApiType.Untap
|
||||||
&& ab.getPayCosts() != null
|
|
||||||
&& ab.getPayCosts().hasOnlySpecificCostType(CostTap.class)
|
&& ab.getPayCosts().hasOnlySpecificCostType(CostTap.class)
|
||||||
&& ab.canTarget(source)) {
|
&& ab.canTarget(source)) {
|
||||||
toRemove.add(c);
|
toRemove.add(c);
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public class ForgeScript {
|
|||||||
return !cardState.getTypeWithChanges().hasSubtype(subType);
|
return !cardState.getTypeWithChanges().hasSubtype(subType);
|
||||||
} else if (property.equals("hasActivatedAbilityWithTapCost")) {
|
} else if (property.equals("hasActivatedAbilityWithTapCost")) {
|
||||||
for (final SpellAbility sa : cardState.getSpellAbilities()) {
|
for (final SpellAbility sa : cardState.getSpellAbilities()) {
|
||||||
if (sa.isAbility() && (sa.getPayCosts() != null) && sa.getPayCosts().hasTapCost()) {
|
if (sa.isAbility() && sa.getPayCosts().hasTapCost()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -79,7 +79,7 @@ public class Game {
|
|||||||
private final GameLog gameLog = new GameLog();
|
private final GameLog gameLog = new GameLog();
|
||||||
|
|
||||||
private final Zone stackZone = new Zone(ZoneType.Stack, this);
|
private final Zone stackZone = new Zone(ZoneType.Stack, this);
|
||||||
|
|
||||||
private CardCollection lastStateBattlefield = new CardCollection();
|
private CardCollection lastStateBattlefield = new CardCollection();
|
||||||
private CardCollection lastStateGraveyard = new CardCollection();
|
private CardCollection lastStateGraveyard = new CardCollection();
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ public class Game {
|
|||||||
private GameStage age = GameStage.BeforeMulligan;
|
private GameStage age = GameStage.BeforeMulligan;
|
||||||
private GameOutcome outcome;
|
private GameOutcome outcome;
|
||||||
|
|
||||||
private final GameView view;
|
private final GameView view;
|
||||||
private final Tracker tracker = new Tracker();
|
private final Tracker tracker = new Tracker();
|
||||||
|
|
||||||
public Player getMonarch() {
|
public Player getMonarch() {
|
||||||
@@ -177,19 +177,6 @@ public class Game {
|
|||||||
playerCache.put(Integer.valueOf(id), player);
|
playerCache.put(Integer.valueOf(id), player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final GameEntityCache<Card, CardView> cardCache = new GameEntityCache<>();
|
|
||||||
public Card getCard(CardView cardView) {
|
|
||||||
return cardCache.get(cardView);
|
|
||||||
}
|
|
||||||
public void addCard(int id, Card card) {
|
|
||||||
cardCache.put(Integer.valueOf(id), card);
|
|
||||||
}
|
|
||||||
public CardCollection getCardList(Iterable<CardView> cardViews) {
|
|
||||||
CardCollection list = new CardCollection();
|
|
||||||
cardCache.addToList(cardViews, list);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
// methods that deal with saving, retrieving and clearing LKI information about cards on zone change
|
// methods that deal with saving, retrieving and clearing LKI information about cards on zone change
|
||||||
private final HashMap<Integer, Card> changeZoneLKIInfo = new HashMap<>();
|
private final HashMap<Integer, Card> changeZoneLKIInfo = new HashMap<>();
|
||||||
public final void addChangeZoneLKIInfo(Card c) {
|
public final void addChangeZoneLKIInfo(Card c) {
|
||||||
@@ -385,7 +372,7 @@ public class Game {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Direction in which the turn order of this Game currently proceeds.
|
* The Direction in which the turn order of this Game currently proceeds.
|
||||||
*/
|
*/
|
||||||
@@ -537,6 +524,33 @@ public class Game {
|
|||||||
return visit.getFound(notFound);
|
return visit.getFound(notFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class CardIdVisitor extends Visitor<Card> {
|
||||||
|
Card found = null;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
private CardIdVisitor(final int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(Card object) {
|
||||||
|
if (this.id == object.getId()) {
|
||||||
|
found = object;
|
||||||
|
}
|
||||||
|
return found == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Card getFound() {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Card findById(int id) {
|
||||||
|
CardIdVisitor visit = new CardIdVisitor(id);
|
||||||
|
this.forEachCardInGame(visit);
|
||||||
|
return visit.getFound();
|
||||||
|
}
|
||||||
|
|
||||||
// Allows visiting cards in game without allocating a temporary list.
|
// Allows visiting cards in game without allocating a temporary list.
|
||||||
public void forEachCardInGame(Visitor<Card> visitor) {
|
public void forEachCardInGame(Visitor<Card> visitor) {
|
||||||
for (final Player player : getPlayers()) {
|
for (final Player player : getPlayers()) {
|
||||||
@@ -771,11 +785,11 @@ public class Game {
|
|||||||
|
|
||||||
public Multimap<Player, Card> chooseCardsForAnte(final boolean matchRarity) {
|
public Multimap<Player, Card> chooseCardsForAnte(final boolean matchRarity) {
|
||||||
Multimap<Player, Card> anteed = ArrayListMultimap.create();
|
Multimap<Player, Card> anteed = ArrayListMultimap.create();
|
||||||
|
|
||||||
if (matchRarity) {
|
if (matchRarity) {
|
||||||
|
|
||||||
boolean onePlayerHasTimeShifted = false;
|
boolean onePlayerHasTimeShifted = false;
|
||||||
|
|
||||||
List<CardRarity> validRarities = new ArrayList<>(Arrays.asList(CardRarity.values()));
|
List<CardRarity> validRarities = new ArrayList<>(Arrays.asList(CardRarity.values()));
|
||||||
for (final Player player : getPlayers()) {
|
for (final Player player : getPlayers()) {
|
||||||
final Set<CardRarity> playerRarity = getValidRarities(player.getCardsIn(ZoneType.Library));
|
final Set<CardRarity> playerRarity = getValidRarities(player.getCardsIn(ZoneType.Library));
|
||||||
@@ -791,24 +805,24 @@ public class Game {
|
|||||||
}
|
}
|
||||||
return anteed;
|
return anteed;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If possible, don't ante basic lands
|
//If possible, don't ante basic lands
|
||||||
if (validRarities.size() > 1) {
|
if (validRarities.size() > 1) {
|
||||||
validRarities.remove(CardRarity.BasicLand);
|
validRarities.remove(CardRarity.BasicLand);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validRarities.contains(CardRarity.Special)) {
|
if (validRarities.contains(CardRarity.Special)) {
|
||||||
onePlayerHasTimeShifted = false;
|
onePlayerHasTimeShifted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CardRarity anteRarity = validRarities.get(MyRandom.getRandom().nextInt(validRarities.size()));
|
CardRarity anteRarity = validRarities.get(MyRandom.getRandom().nextInt(validRarities.size()));
|
||||||
|
|
||||||
System.out.println("Rarity chosen for ante: " + anteRarity.name());
|
System.out.println("Rarity chosen for ante: " + anteRarity.name());
|
||||||
|
|
||||||
for (final Player player : getPlayers()) {
|
for (final Player player : getPlayers()) {
|
||||||
CardCollection library = new CardCollection(player.getCardsIn(ZoneType.Library));
|
CardCollection library = new CardCollection(player.getCardsIn(ZoneType.Library));
|
||||||
CardCollection toRemove = new CardCollection();
|
CardCollection toRemove = new CardCollection();
|
||||||
|
|
||||||
//Remove all cards that aren't of the chosen rarity
|
//Remove all cards that aren't of the chosen rarity
|
||||||
for (Card card : library) {
|
for (Card card : library) {
|
||||||
if (onePlayerHasTimeShifted && card.getRarity() == CardRarity.Special) {
|
if (onePlayerHasTimeShifted && card.getRarity() == CardRarity.Special) {
|
||||||
@@ -827,16 +841,16 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
library.removeAll(toRemove);
|
library.removeAll(toRemove);
|
||||||
|
|
||||||
if (library.size() > 0) { //Make sure that matches were found. If not, use the original method to choose antes
|
if (library.size() > 0) { //Make sure that matches were found. If not, use the original method to choose antes
|
||||||
Card ante = library.get(MyRandom.getRandom().nextInt(library.size()));
|
Card ante = library.get(MyRandom.getRandom().nextInt(library.size()));
|
||||||
anteed.put(player, ante);
|
anteed.put(player, ante);
|
||||||
} else {
|
} else {
|
||||||
chooseRandomCardsForAnte(player, anteed);
|
chooseRandomCardsForAnte(player, anteed);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -874,7 +888,6 @@ public class Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clearCaches() {
|
public void clearCaches() {
|
||||||
cardCache.clear();
|
|
||||||
|
|
||||||
lastStateBattlefield.clear();
|
lastStateBattlefield.clear();
|
||||||
lastStateGraveyard.clear();
|
lastStateGraveyard.clear();
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ public class GameEntityCache<Entity extends IIdentifiable, View extends Trackabl
|
|||||||
public void put(Integer id, Entity entity) {
|
public void put(Integer id, Entity entity) {
|
||||||
entityCache.put(id, entity);
|
entityCache.put(id, entity);
|
||||||
}
|
}
|
||||||
|
public void putAll(Iterable<Entity> entities) {
|
||||||
|
for (Entity e : entities) {
|
||||||
|
put(e.getId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void remove(Integer id) {
|
public void remove(Integer id) {
|
||||||
entityCache.remove(id);
|
entityCache.remove(id);
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ public abstract class GameEntityView extends TrackableObject {
|
|||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T extends GameEntity, V extends GameEntityView> GameEntityViewMap<T, V> getMap(Iterable<T> spabs) {
|
||||||
|
GameEntityViewMap<T, V> gameViewCache = new GameEntityViewMap<T, V>();
|
||||||
|
gameViewCache.putAll(spabs);
|
||||||
|
return gameViewCache;
|
||||||
|
}
|
||||||
|
|
||||||
protected GameEntityView(final int id0, final Tracker tracker) {
|
protected GameEntityView(final int id0, final Tracker tracker) {
|
||||||
super(id0, tracker);
|
super(id0, tracker);
|
||||||
}
|
}
|
||||||
|
|||||||
52
forge-game/src/main/java/forge/game/GameEntityViewMap.java
Normal file
52
forge-game/src/main/java/forge/game/GameEntityViewMap.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package forge.game;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.ForwardingMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import forge.trackable.TrackableCollection;
|
||||||
|
|
||||||
|
public class GameEntityViewMap<Entity extends GameEntity, View extends GameEntityView> extends ForwardingMap<View, Entity> {
|
||||||
|
private Map<View, Entity> dataMap = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<View, Entity> delegate() {
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void put(Entity e) {
|
||||||
|
this.put((View) e.getView(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putAll(Iterable<Entity> entities) {
|
||||||
|
for (Entity e : entities) {
|
||||||
|
put(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Entity e) {
|
||||||
|
this.remove(e.getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAll(Iterable<Entity> entities) {
|
||||||
|
for (Entity e : entities) {
|
||||||
|
remove(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToList(Iterable<View> views, List<Entity> list) {
|
||||||
|
for (View view : views) {
|
||||||
|
Entity entity = get(view);
|
||||||
|
if (entity != null) {
|
||||||
|
list.add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackableCollection<View> getTrackableKeys() {
|
||||||
|
return new TrackableCollection<View>(this.keySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1344,7 +1344,7 @@ public class AbilityUtils {
|
|||||||
Player pl = sa.getActivatingPlayer();
|
Player pl = sa.getActivatingPlayer();
|
||||||
final Game game = pl.getGame();
|
final Game game = pl.getGame();
|
||||||
|
|
||||||
if (sa.isTrigger() && sa.getParent() == null && sa.getPayCosts() != null) {
|
if (sa.isTrigger() && sa.getParent() == null) {
|
||||||
// when trigger cost are paid before the effect does resolve, need to clean the trigger
|
// when trigger cost are paid before the effect does resolve, need to clean the trigger
|
||||||
game.getTriggerHandler().resetActiveTriggers();
|
game.getTriggerHandler().resetActiveTriggers();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* @param id0 the unique id of the new card.
|
* @param id0 the unique id of the new card.
|
||||||
*/
|
*/
|
||||||
public Card(final int id0, final Game game0) {
|
public Card(final int id0, final Game game0) {
|
||||||
this(id0, null, true, game0);
|
this(id0, null, game0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -307,15 +307,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* @see IPaperCard
|
* @see IPaperCard
|
||||||
*/
|
*/
|
||||||
public Card(final int id0, final IPaperCard paperCard0, final Game game0) {
|
public Card(final int id0, final IPaperCard paperCard0, final Game game0) {
|
||||||
this(id0, paperCard0, true, game0);
|
|
||||||
}
|
|
||||||
public Card(final int id0, final IPaperCard paperCard0, final boolean allowCache, final Game game0) {
|
|
||||||
super(id0);
|
super(id0);
|
||||||
|
|
||||||
game = game0;
|
game = game0;
|
||||||
if (id0 >= 0 && allowCache && game != null) {
|
|
||||||
game.addCard(id0, this);
|
|
||||||
}
|
|
||||||
paperCard = paperCard0;
|
paperCard = paperCard0;
|
||||||
view = new CardView(id0, game == null ? null : game.getTracker());
|
view = new CardView(id0, game == null ? null : game.getTracker());
|
||||||
currentState = new CardState(view.getCurrentState(), this);
|
currentState = new CardState(view.getCurrentState(), this);
|
||||||
@@ -2083,9 +2077,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
if (sa.isAdventure() && state.getView().getState().equals(CardStateName.Original)) {
|
if (sa.isAdventure() && state.getView().getState().equals(CardStateName.Original)) {
|
||||||
StringBuilder sbSA = new StringBuilder();
|
StringBuilder sbSA = new StringBuilder();
|
||||||
sbSA.append("Adventure — ").append(getState(CardStateName.Adventure).getName());
|
sbSA.append("Adventure — ").append(getState(CardStateName.Adventure).getName());
|
||||||
if (sa.getPayCosts() != null) {
|
sbSA.append(" ").append(sa.getPayCosts().toSimpleString());
|
||||||
sbSA.append(" ").append(sa.getPayCosts().toSimpleString());
|
|
||||||
}
|
|
||||||
sbSA.append(": ");
|
sbSA.append(": ");
|
||||||
sbSA.append(sAbility);
|
sbSA.append(sAbility);
|
||||||
sAbility = sbSA.toString();
|
sAbility = sbSA.toString();
|
||||||
|
|||||||
@@ -118,39 +118,6 @@ public class CardFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* copyCardWithChangedStats
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* This method copies the card together with certain temporarily changed stats of the card
|
|
||||||
* (namely, changed color, changed types, changed keywords).
|
|
||||||
*
|
|
||||||
* copyCardWithChangedStats must NOT be used for ordinary card copy operations because
|
|
||||||
* according to MTG rules the changed text (including keywords, types) is not copied over
|
|
||||||
* to cards cloned by another card. However, this method is useful, for example, for certain
|
|
||||||
* triggers that demand the latest information about the changes to the card which is lost
|
|
||||||
* when the card changes its zone after GameAction::changeZone is called.
|
|
||||||
*
|
|
||||||
* @param in
|
|
||||||
* a {@link forge.game.card.Card} object.
|
|
||||||
* @param assignNewId
|
|
||||||
* a boolean
|
|
||||||
* @return a {@link forge.game.card.Card} object.
|
|
||||||
*/
|
|
||||||
public static final Card copyCardWithChangedStats(final Card in, boolean assignNewId) {
|
|
||||||
Card out = copyCard(in, assignNewId);
|
|
||||||
|
|
||||||
// Copy changed color, type, keyword arrays (useful for some triggers that require
|
|
||||||
// information about the latest state of the card as it left the battlefield)
|
|
||||||
out.setChangedCardColors(in.getChangedCardColors());
|
|
||||||
out.setChangedCardKeywords(in.getChangedCardKeywords());
|
|
||||||
out.setChangedCardTypes(in.getChangedCardTypesMap());
|
|
||||||
out.setChangedCardNames(in.getChangedCardNames());
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* copySpellHost.
|
* copySpellHost.
|
||||||
@@ -471,23 +438,6 @@ public class CardFactory {
|
|||||||
CardFactoryUtil.addAbilityFactoryAbilities(c, face.getAbilities());
|
CardFactoryUtil.addAbilityFactoryAbilities(c, face.getAbilities());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a copy of a card, including its copiable characteristics (but not
|
|
||||||
* abilities).
|
|
||||||
* @param from
|
|
||||||
* @param newOwner
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static Card copyCopiableCharacteristics(final Card from, final Player newOwner) {
|
|
||||||
int id = newOwner == null ? 0 : newOwner.getGame().nextCardId();
|
|
||||||
final Card c = new Card(id, from.getPaperCard(), from.getGame());
|
|
||||||
c.setOwner(newOwner);
|
|
||||||
c.setSetCode(from.getSetCode());
|
|
||||||
|
|
||||||
copyCopiableCharacteristics(from, c);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy the copiable characteristics of one card to another, taking the
|
* Copy the copiable characteristics of one card to another, taking the
|
||||||
* states of both cards into account.
|
* states of both cards into account.
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ public final class CardUtil {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
final Card newCopy = new Card(in.getId(), in.getPaperCard(), false, in.getGame());
|
final Card newCopy = new Card(in.getId(), in.getPaperCard(), in.getGame());
|
||||||
newCopy.setSetCode(in.getSetCode());
|
newCopy.setSetCode(in.getSetCode());
|
||||||
newCopy.setOwner(in.getOwner());
|
newCopy.setOwner(in.getOwner());
|
||||||
newCopy.setController(in.getController(), 0);
|
newCopy.setController(in.getController(), 0);
|
||||||
|
|||||||
@@ -3067,7 +3067,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public void createMonarchEffect() {
|
public void createMonarchEffect() {
|
||||||
final PlayerZone com = getZone(ZoneType.Command);
|
final PlayerZone com = getZone(ZoneType.Command);
|
||||||
if (monarchEffect == null) {
|
if (monarchEffect == null) {
|
||||||
monarchEffect = new Card(game.nextCardId(), null, false, game);
|
monarchEffect = new Card(game.nextCardId(), null, game);
|
||||||
monarchEffect.setOwner(this);
|
monarchEffect.setOwner(this);
|
||||||
monarchEffect.setImageKey("t:monarch");
|
monarchEffect.setImageKey("t:monarch");
|
||||||
monarchEffect.setName("The Monarch");
|
monarchEffect.setName("The Monarch");
|
||||||
@@ -3163,7 +3163,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
final PlayerZone com = getZone(ZoneType.Command);
|
final PlayerZone com = getZone(ZoneType.Command);
|
||||||
|
|
||||||
if(bless) {
|
if(bless) {
|
||||||
blessingEffect = new Card(game.nextCardId(), null, false, game);
|
blessingEffect = new Card(game.nextCardId(), null, game);
|
||||||
blessingEffect.setOwner(this);
|
blessingEffect.setOwner(this);
|
||||||
blessingEffect.setImageKey("t:blessing");
|
blessingEffect.setImageKey("t:blessing");
|
||||||
blessingEffect.setName("City's Blessing");
|
blessingEffect.setName("City's Blessing");
|
||||||
@@ -3257,7 +3257,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
final PlayerZone com = getZone(ZoneType.Command);
|
final PlayerZone com = getZone(ZoneType.Command);
|
||||||
|
|
||||||
keywordEffect = new Card(game.nextCardId(), null, false, game);
|
keywordEffect = new Card(game.nextCardId(), null, game);
|
||||||
keywordEffect.setImmutable(true);
|
keywordEffect.setImmutable(true);
|
||||||
keywordEffect.setOwner(this);
|
keywordEffect.setOwner(this);
|
||||||
keywordEffect.setName("Keyword Effects");
|
keywordEffect.setName("Keyword Effects");
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class ReplaceProduceMana extends ReplacementEffect {
|
|||||||
//Check for tapping
|
//Check for tapping
|
||||||
if (!hasParam("NoTapCheck")) {
|
if (!hasParam("NoTapCheck")) {
|
||||||
final SpellAbility manaAbility = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
|
final SpellAbility manaAbility = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
|
||||||
if (manaAbility == null || manaAbility.getRootAbility().getPayCosts() == null || !manaAbility.getRootAbility().getPayCosts().hasTapCost()) {
|
if (manaAbility == null || !manaAbility.getRootAbility().getPayCosts().hasTapCost()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,10 +145,8 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getPayCosts() != null) {
|
if (!CostPayment.canPayAdditionalCosts(this.getPayCosts(), this)) {
|
||||||
if (!CostPayment.canPayAdditionalCosts(this.getPayCosts(), this)) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkOtherRestrictions(card);
|
return checkOtherRestrictions(card);
|
||||||
|
|||||||
@@ -442,16 +442,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean costHasX() {
|
public boolean costHasX() {
|
||||||
if (getPayCosts() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return getPayCosts().hasXInAnyCostPart();
|
return getPayCosts().hasXInAnyCostPart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean costHasManaX() {
|
public boolean costHasManaX() {
|
||||||
if (getPayCosts() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getPayCosts().hasNoManaCost()) {
|
if (getPayCosts().hasNoManaCost()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -890,9 +884,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
|
|
||||||
clone.triggeringObjects = AbilityKey.newMap(this.triggeringObjects);
|
clone.triggeringObjects = AbilityKey.newMap(this.triggeringObjects);
|
||||||
|
|
||||||
if (getPayCosts() != null) {
|
clone.setPayCosts(getPayCosts().copy());
|
||||||
clone.setPayCosts(getPayCosts().copy());
|
|
||||||
}
|
|
||||||
if (manaPart != null) {
|
if (manaPart != null) {
|
||||||
clone.manaPart = new AbilityManaPart(host, mapParams);
|
clone.manaPart = new AbilityManaPart(host, mapParams);
|
||||||
}
|
}
|
||||||
@@ -1422,16 +1414,15 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
int maxTargets = getTargetRestrictions().getMaxTargets(hostCard, this);
|
int maxTargets = getTargetRestrictions().getMaxTargets(hostCard, this);
|
||||||
int numTargets = getTargets().getNumTargeted();
|
int numTargets = getTargets().getNumTargeted();
|
||||||
|
|
||||||
if (maxTargets == 0 && this.getPayCosts() != null
|
if (maxTargets == 0 && getPayCosts().hasSpecificCostType(CostRemoveCounter.class)
|
||||||
&& this.getPayCosts().hasSpecificCostType(CostRemoveCounter.class)
|
&& hasSVar(getParam("TargetMax"))
|
||||||
&& this.hasSVar(this.getParam("TargetMax"))
|
&& getSVar(getParam("TargetMax")).startsWith("Count$CardCounters")
|
||||||
&& this.getSVar(this.getParam("TargetMax")).startsWith("Count$CardCounters")
|
&& getHostCard() != null && getHostCard().hasSVar("CostCountersRemoved")) {
|
||||||
&& this.getHostCard() != null && this.getHostCard().hasSVar("CostCountersRemoved")) {
|
|
||||||
// TODO: Current AI implementation removes the counters during payment before the
|
// TODO: Current AI implementation removes the counters during payment before the
|
||||||
// ability is added to stack, resulting in maxTargets=0 at this point. We are
|
// ability is added to stack, resulting in maxTargets=0 at this point. We are
|
||||||
// assuming here that the AI logic specified a legal number, and that number ended
|
// assuming here that the AI logic specified a legal number, and that number ended
|
||||||
// up being in CostCountersRemoved that is created on the card during payment.
|
// up being in CostCountersRemoved that is created on the card during payment.
|
||||||
maxTargets = Integer.parseInt(this.getHostCard().getSVar("CostCountersRemoved"));
|
maxTargets = Integer.parseInt(getHostCard().getSVar("CostCountersRemoved"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return minTargets <= numTargets && maxTargets >= numTargets;
|
return minTargets <= numTargets && maxTargets >= numTargets;
|
||||||
@@ -1775,9 +1766,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
targetRestrictions.applyTargetTextChanges(this);
|
targetRestrictions.applyTargetTextChanges(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPayCosts() != null) {
|
getPayCosts().applyTextChangeEffects(this);
|
||||||
getPayCosts().applyTextChangeEffects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
stackDescription = AbilityUtils.applyDescriptionTextChangeEffects(originalStackDescription, this);
|
stackDescription = AbilityUtils.applyDescriptionTextChangeEffects(originalStackDescription, this);
|
||||||
description = AbilityUtils.applyDescriptionTextChangeEffects(originalDescription, this);
|
description = AbilityUtils.applyDescriptionTextChangeEffects(originalDescription, this);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class TriggerTapsForMana extends Trigger {
|
|||||||
//Check for tapping
|
//Check for tapping
|
||||||
if (!hasParam("NoTapCheck")) {
|
if (!hasParam("NoTapCheck")) {
|
||||||
final SpellAbility manaAbility = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
|
final SpellAbility manaAbility = (SpellAbility) runParams.get(AbilityKey.AbilityMana);
|
||||||
if (manaAbility == null || manaAbility.getRootAbility().getPayCosts() == null || !manaAbility.getRootAbility().getPayCosts().hasTapCost()) {
|
if (manaAbility == null || !manaAbility.getRootAbility().getPayCosts().hasTapCost()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,161 +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.match.input;
|
|
||||||
|
|
||||||
import forge.card.mana.ManaAtom;
|
|
||||||
import forge.card.mana.ManaCost;
|
|
||||||
import forge.card.mana.ManaCostShard;
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.model.FModel;
|
|
||||||
import forge.player.PlayerControllerHuman;
|
|
||||||
import forge.properties.ForgePreferences;
|
|
||||||
import forge.util.ITriggerEvent;
|
|
||||||
import forge.util.Localizer;
|
|
||||||
|
|
||||||
//pays the cost of a card played from the player's hand
|
|
||||||
//the card is removed from the players hand if the cost is paid
|
|
||||||
//CANNOT be used for ABILITIES
|
|
||||||
public class InputPayManaSimple extends InputPayMana {
|
|
||||||
// anything that uses this should be converted to Ability_Cost
|
|
||||||
/** Constant <code>serialVersionUID=3467312982164195091L</code>. */
|
|
||||||
private static final long serialVersionUID = 3467312982164195091L;
|
|
||||||
|
|
||||||
private final Card originalCard;
|
|
||||||
private final ManaCost originalManaCost;
|
|
||||||
|
|
||||||
public InputPayManaSimple(final PlayerControllerHuman controller, final Game game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) {
|
|
||||||
super(controller, sa, sa.getActivatingPlayer());
|
|
||||||
this.originalManaCost = manaCostToPay.toManaCost();
|
|
||||||
this.originalCard = sa.getHostCard();
|
|
||||||
|
|
||||||
if (sa.getHostCard().isCopiedSpell() && sa.isSpell()) {
|
|
||||||
this.manaCost = new ManaCostBeingPaid(ManaCost.ZERO);
|
|
||||||
game.getStack().add(this.saPaidFor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.manaCost = manaCostToPay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onManaAbilityPaid() {
|
|
||||||
if (this.manaCost.isPaid()) {
|
|
||||||
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(final Player selected, final ITriggerEvent triggerEvent) {
|
|
||||||
if (player == selected) {
|
|
||||||
if (player.canPayLife(this.phyLifeToLose + 2)) {
|
|
||||||
if (manaCost.payPhyrexian()) {
|
|
||||||
this.phyLifeToLose += 2;
|
|
||||||
} else {
|
|
||||||
if (player.hasKeyword("PayLifeInsteadOf:B") && manaCost.hasAnyKind(ManaAtom.BLACK)) {
|
|
||||||
manaCost.decreaseShard(ManaCostShard.BLACK, 1);
|
|
||||||
this.phyLifeToLose += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* done.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void done() {
|
|
||||||
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
|
|
||||||
|
|
||||||
if (this.phyLifeToLose > 0) {
|
|
||||||
player.payLife(this.phyLifeToLose, this.originalCard);
|
|
||||||
}
|
|
||||||
if (!this.saPaidFor.getHostCard().isCopiedSpell()) {
|
|
||||||
if (this.saPaidFor.isSpell()) {
|
|
||||||
this.saPaidFor.setHostCard(game.getAction().moveToStack(this.originalCard, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
player.getManaPool().refundManaPaid(this.saPaidFor);
|
|
||||||
// Update UI
|
|
||||||
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void showMessage() {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
|
|
||||||
updateButtons();
|
|
||||||
|
|
||||||
if (this.manaCost.isPaid() && !new ManaCostBeingPaid(this.originalManaCost).isPaid()) {
|
|
||||||
this.done();
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
updateMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.control.input.InputPayManaBase#updateMessage()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected String getMessage() {
|
|
||||||
final StringBuilder msg = new StringBuilder();
|
|
||||||
final Localizer localizer = Localizer.getInstance();
|
|
||||||
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT)) {
|
|
||||||
msg.append(saPaidFor.getStackDescription().replace("(Targeting ERROR)", "")).append("\n\n");
|
|
||||||
}
|
|
||||||
msg.append(localizer.getMessage("lblPayManaCost")).append(" ").append(this.manaCost.toString(false, player.getManaPool()));
|
|
||||||
if (this.phyLifeToLose > 0) {
|
|
||||||
msg.append(" ").append(String.format(localizer.getMessage("lblLifePaidForPhyrexianMana"), this.phyLifeToLose));
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isLifeInsteadBlack = player.hasKeyword("PayLifeInsteadOf:B") && manaCost.hasAnyKind(ManaAtom.BLACK);
|
|
||||||
|
|
||||||
if (manaCost.containsPhyrexianMana() || isLifeInsteadBlack) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (manaCost.containsPhyrexianMana() && !isLifeInsteadBlack) {
|
|
||||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianMana"));
|
|
||||||
} else if (!manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
|
|
||||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForBlackMana"));
|
|
||||||
} else if (manaCost.containsPhyrexianMana() && isLifeInsteadBlack) {
|
|
||||||
sb.append(localizer.getMessage("lblClickOnYourLifeTotalToPayLifeForPhyrexianOrBlackMana"));
|
|
||||||
}
|
|
||||||
msg.append("\n(").append(sb).append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
// has its own variant of checkIfPaid
|
|
||||||
return msg.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -110,7 +110,7 @@ public class InputProxy implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Card getCard(final CardView cardView) {
|
private Card getCard(final CardView cardView) {
|
||||||
return controller.getGame().getCard(cardView);
|
return controller.getCard(cardView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getActivateAction(final CardView cardView) {
|
public final String getActivateAction(final CardView cardView) {
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import com.google.common.collect.Lists;
|
|||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityView;
|
||||||
|
import forge.game.GameEntityViewMap;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
@@ -35,6 +37,7 @@ import forge.match.input.InputSelectManyBase;
|
|||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
|
import forge.util.gui.SGuiChoose;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import forge.util.CardTranslation;
|
import forge.util.CardTranslation;
|
||||||
@@ -310,11 +313,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
if (nNeeded == 0) {
|
if (nNeeded == 0) {
|
||||||
return PaymentDecision.number(0);
|
return PaymentDecision.number(0);
|
||||||
}
|
}
|
||||||
final Game game = controller.getGame();
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(payableZone);
|
||||||
final Player p = game.getPlayer(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileFromWhoseZone", cost.getFrom().getTranslatedName()), PlayerView.getCollection(payableZone)));
|
final PlayerView pv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileFromWhoseZone", cost.getFrom().getTranslatedName()), gameCachePlayer.getTrackableKeys());
|
||||||
if (p == null) {
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
final Player p = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final CardCollection typeList = CardLists.filter(list, CardPredicates.isOwner(p));
|
final CardCollection typeList = CardLists.filter(list, CardPredicates.isOwner(p));
|
||||||
final int count = typeList.size();
|
final int count = typeList.size();
|
||||||
@@ -322,8 +326,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardCollection toExile = game.getCardList(controller.getGui().many(Localizer.getInstance().getMessage("lblExileFromZone", cost.getFrom().getTranslatedName()), Localizer.getInstance().getMessage("lblToBeExiled"), nNeeded, CardView.getCollection(typeList), null));
|
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(typeList);
|
||||||
return PaymentDecision.card(toExile);
|
List<CardView> views = controller.getGui().many(
|
||||||
|
Localizer.getInstance().getMessage("lblExileFromZone", cost.getFrom().getTranslatedName()),
|
||||||
|
Localizer.getInstance().getMessage("lblToBeExiled"), nNeeded, gameCacheExile.getTrackableKeys(), null);
|
||||||
|
List<Card> result = Lists.newArrayList();
|
||||||
|
gameCacheExile.addToList(views, result);
|
||||||
|
return PaymentDecision.card(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -395,20 +404,17 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
return PaymentDecision.card(list);
|
return PaymentDecision.card(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Card getCard(final CardView cardView) {
|
|
||||||
return controller.getGame().getCard(cardView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PaymentDecision exileFromMiscZone(final CostExile cost, final SpellAbility sa, final int nNeeded, final CardCollection typeList) {
|
private PaymentDecision exileFromMiscZone(final CostExile cost, final SpellAbility sa, final int nNeeded, final CardCollection typeList) {
|
||||||
if (typeList.size() < nNeeded) { return null; }
|
if (typeList.size() < nNeeded) { return null; }
|
||||||
|
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheCard = GameEntityView.getMap(typeList);
|
||||||
|
|
||||||
final CardCollection exiled = new CardCollection();
|
final CardCollection exiled = new CardCollection();
|
||||||
for (int i = 0; i < nNeeded; i++) {
|
for (int i = 0; i < nNeeded; i++) {
|
||||||
final Card c = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileProgressFromZone", String.valueOf(i + 1), String.valueOf(nNeeded), cost.getFrom().getTranslatedName()), CardView.getCollection(typeList)));
|
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileProgressFromZone", String.valueOf(i + 1), String.valueOf(nNeeded), cost.getFrom().getTranslatedName()), gameCacheCard.getTrackableKeys());
|
||||||
if (c == null) { return null; }
|
if (cv == null || !gameCacheCard.containsKey(cv)) { return null; }
|
||||||
|
|
||||||
typeList.remove(c);
|
exiled.add(gameCacheCard.remove(cv));
|
||||||
exiled.add(c);
|
|
||||||
}
|
}
|
||||||
return PaymentDecision.card(exiled);
|
return PaymentDecision.card(exiled);
|
||||||
}
|
}
|
||||||
@@ -438,12 +444,17 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
if (ability.isOptionalTrigger()) {
|
if (ability.isOptionalTrigger()) {
|
||||||
min = 0;
|
min = 0;
|
||||||
}
|
}
|
||||||
final CardCollection choice = controller.getGame().getCardList(controller.getGui().many(Localizer.getInstance().getMessage("lblChooseAnExiledCardPutIntoGraveyard"), Localizer.getInstance().getMessage("lblToGraveyard"), min, c, CardView.getCollection(list), CardView.get(source)));
|
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(list);
|
||||||
|
List<CardView> views = controller.getGui().many(
|
||||||
if (choice == null || choice.size() < c) {
|
Localizer.getInstance().getMessage("lblChooseAnExiledCardPutIntoGraveyard"),
|
||||||
|
Localizer.getInstance().getMessage("lblToGraveyard"), min, c, CardView.getCollection(list), CardView.get(source));
|
||||||
|
|
||||||
|
if (views == null || views.size() < c) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return PaymentDecision.card(choice);
|
List<Card> result = Lists.newArrayList();
|
||||||
|
gameCacheExile.addToList(views, result);
|
||||||
|
return PaymentDecision.card(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -555,11 +566,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
return PaymentDecision.players(oppsThatCanGainLife);
|
return PaymentDecision.players(oppsThatCanGainLife);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player chosenToGain = controller.getGame().getPlayer(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblCardChooseAnOpponentToGainNLife", CardTranslation.getTranslatedName(source.getName()), String.valueOf(c)), PlayerView.getCollection(oppsThatCanGainLife)));
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(oppsThatCanGainLife);
|
||||||
if (chosenToGain == null) {
|
final PlayerView pv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblCardChooseAnOpponentToGainNLife", CardTranslation.getTranslatedName(source.getName()), String.valueOf(c)), gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return PaymentDecision.players(Lists.newArrayList(chosenToGain));
|
return PaymentDecision.players(Lists.newArrayList(gameCachePlayer.get(pv)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -694,13 +706,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final CardCollection chosen = new CardCollection();
|
final CardCollection chosen = new CardCollection();
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheCard = GameEntityView.getMap(typeList);
|
||||||
for (int i = 0; i < nNeeded; i++) {
|
for (int i = 0; i < nNeeded; i++) {
|
||||||
final Card c = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblFromZonePutToLibrary", fromZone.getTranslatedName()), CardView.getCollection(typeList)));
|
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblFromZonePutToLibrary", fromZone.getTranslatedName()), gameCacheCard.getTrackableKeys());
|
||||||
if (c == null) {
|
if (cv == null || !gameCacheCard.containsKey(cv)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
typeList.remove(c);
|
chosen.add(gameCacheCard.remove(cv));
|
||||||
chosen.add(c);
|
|
||||||
}
|
}
|
||||||
return PaymentDecision.card(chosen);
|
return PaymentDecision.card(chosen);
|
||||||
}
|
}
|
||||||
@@ -710,10 +722,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
return PaymentDecision.number(0);
|
return PaymentDecision.number(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player p = controller.getGame().getPlayer(controller.getGui().oneOrNone(TextUtil.concatNoSpace(Localizer.getInstance().getMessage("lblPutCardsFromWhoseZone"), fromZone.getTranslatedName()), PlayerView.getCollection(payableZone)));
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(payableZone);
|
||||||
if (p == null) {
|
PlayerView pv = SGuiChoose.oneOrNone(TextUtil.concatNoSpace(Localizer.getInstance().getMessage("lblPutCardsFromWhoseZone"), fromZone.getTranslatedName()), gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Player p = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final CardCollection typeList = CardLists.filter(list, CardPredicates.isOwner(p));
|
final CardCollection typeList = CardLists.filter(list, CardPredicates.isOwner(p));
|
||||||
if (typeList.size() < nNeeded) {
|
if (typeList.size() < nNeeded) {
|
||||||
@@ -721,13 +735,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final CardCollection chosen = new CardCollection();
|
final CardCollection chosen = new CardCollection();
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheCard = GameEntityView.getMap(typeList);
|
||||||
for (int i = 0; i < nNeeded; i++) {
|
for (int i = 0; i < nNeeded; i++) {
|
||||||
final Card c = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblPutZoneCardsToLibrary", fromZone.getTranslatedName()), CardView.getCollection(typeList)));
|
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblPutZoneCardsToLibrary", fromZone.getTranslatedName()), gameCacheCard.getTrackableKeys());
|
||||||
if (c == null) {
|
if (cv == null || !gameCacheCard.containsKey(cv)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
typeList.remove(c);
|
chosen.add(gameCacheCard.remove(cv));
|
||||||
chosen.add(c);
|
|
||||||
}
|
}
|
||||||
return PaymentDecision.card(chosen);
|
return PaymentDecision.card(chosen);
|
||||||
}
|
}
|
||||||
@@ -1068,15 +1082,14 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rift Elemental only - always removes 1 counter, so there will be no code for N counters.
|
// Rift Elemental only - always removes 1 counter, so there will be no code for N counters.
|
||||||
final List<CardView> suspended = Lists.newArrayList();
|
GameEntityViewMap<Card, CardView> gameCacheSuspended = GameEntityView.getMap(CardLists.filter(validCards, CardPredicates.hasCounter(cost.counter)));
|
||||||
for (final Card crd : validCards) {
|
|
||||||
if (crd.getCounters(cost.counter) > 0) {
|
final CardView cv = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblRemoveCountersFromAInZoneCard", cost.zone.getTranslatedName()), gameCacheSuspended.getTrackableKeys());
|
||||||
suspended.add(CardView.get(crd));
|
if (cv == null || !gameCacheSuspended.containsKey(cv)) {
|
||||||
}
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Card card = getCard(controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblRemoveCountersFromAInZoneCard", cost.zone.getTranslatedName()), suspended));
|
return PaymentDecision.card(gameCacheSuspended.get(cv), c);
|
||||||
return null == card ? null : PaymentDecision.card(card, c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import forge.FThreads;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
|
import forge.game.GameEntityView;
|
||||||
|
import forge.game.GameEntityViewMap;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.CharmEffect;
|
import forge.game.ability.effects.CharmEffect;
|
||||||
@@ -23,7 +25,6 @@ import forge.game.trigger.TriggerType;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.match.input.InputPayMana;
|
import forge.match.input.InputPayMana;
|
||||||
import forge.match.input.InputPayManaOfCostPayment;
|
import forge.match.input.InputPayManaOfCostPayment;
|
||||||
import forge.match.input.InputPayManaSimple;
|
|
||||||
import forge.match.input.InputSelectCardsFromList;
|
import forge.match.input.InputSelectCardsFromList;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
@@ -46,7 +47,7 @@ public class HumanPlay {
|
|||||||
* <p>
|
* <p>
|
||||||
* playSpellAbility.
|
* playSpellAbility.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param sa
|
* @param sa
|
||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
* a {@link forge.game.spellability.SpellAbility} object.
|
||||||
*/
|
*/
|
||||||
@@ -94,34 +95,9 @@ public class HumanPlay {
|
|||||||
source.animateBestow();
|
source.animateBestow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to check PayCosts, and Ability + All SubAbilities for Target
|
|
||||||
boolean newAbility = sa.getPayCosts() != null;
|
|
||||||
SpellAbility ability = sa;
|
|
||||||
while ((ability != null) && !newAbility) {
|
|
||||||
final TargetRestrictions tgt = ability.getTargetRestrictions();
|
|
||||||
|
|
||||||
newAbility |= tgt != null;
|
|
||||||
ability = ability.getSubAbility();
|
|
||||||
}
|
|
||||||
|
|
||||||
// System.out.println("Playing:" + sa.getDescription() + " of " + sa.getHostCard() + " new = " + newAbility);
|
// System.out.println("Playing:" + sa.getDescription() + " of " + sa.getHostCard() + " new = " + newAbility);
|
||||||
if (newAbility) {
|
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
||||||
|
if (!req.playAbility(true, false, false)) {
|
||||||
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
|
||||||
if (!req.playAbility(true, false, false)) {
|
|
||||||
if (flippedToCast && !castFaceDown) {
|
|
||||||
source.turnFaceDown(true);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (payManaCostIfNeeded(controller, p, sa)) {
|
|
||||||
if (sa.isSpell() && !source.isCopiedSpell()) {
|
|
||||||
sa.setHostCard(p.getGame().getAction().moveToStack(source, sa));
|
|
||||||
}
|
|
||||||
|
|
||||||
p.getGame().getStack().add(sa);
|
|
||||||
} else {
|
|
||||||
// Failed to pay costs, revert to original state
|
|
||||||
if (flippedToCast && !castFaceDown) {
|
if (flippedToCast && !castFaceDown) {
|
||||||
source.turnFaceDown(true);
|
source.turnFaceDown(true);
|
||||||
}
|
}
|
||||||
@@ -133,7 +109,7 @@ public class HumanPlay {
|
|||||||
/**
|
/**
|
||||||
* choose optional additional costs. For HUMAN only
|
* choose optional additional costs. For HUMAN only
|
||||||
* @param p
|
* @param p
|
||||||
*
|
*
|
||||||
* @param original
|
* @param original
|
||||||
* the original sa
|
* the original sa
|
||||||
* @return an ArrayList<SpellAbility>.
|
* @return an ArrayList<SpellAbility>.
|
||||||
@@ -159,31 +135,11 @@ public class HumanPlay {
|
|||||||
//final List<SpellAbility> abilities = GameActionUtil.getOptionalCosts(original);
|
//final List<SpellAbility> abilities = GameActionUtil.getOptionalCosts(original);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean payManaCostIfNeeded(final PlayerControllerHuman controller, final Player p, final SpellAbility sa) {
|
|
||||||
final ManaCostBeingPaid manaCost;
|
|
||||||
if (sa.getHostCard().isCopiedSpell() && sa.isSpell()) {
|
|
||||||
manaCost = new ManaCostBeingPaid(ManaCost.ZERO);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
manaCost = new ManaCostBeingPaid(sa.getPayCosts().getTotalMana());
|
|
||||||
CostAdjustment.adjust(manaCost, sa, null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isPaid = manaCost.isPaid();
|
|
||||||
|
|
||||||
if (!isPaid) {
|
|
||||||
InputPayManaSimple inputPay = new InputPayManaSimple(controller, p.getGame(), sa, manaCost);
|
|
||||||
inputPay.showAndWait();
|
|
||||||
isPaid = inputPay.isPaid();
|
|
||||||
}
|
|
||||||
return isPaid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* playSpellAbilityForFree.
|
* playSpellAbilityForFree.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param sa
|
* @param sa
|
||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
* a {@link forge.game.spellability.SpellAbility} object.
|
||||||
*/
|
*/
|
||||||
@@ -193,33 +149,22 @@ public class HumanPlay {
|
|||||||
|
|
||||||
source.setSplitStateToPlayAbility(sa);
|
source.setSplitStateToPlayAbility(sa);
|
||||||
|
|
||||||
if (sa.getPayCosts() != null) {
|
if (!sa.isCopied()) {
|
||||||
if (!sa.isCopied()) {
|
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
||||||
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
|
CharmEffect.makeChoices(sa);
|
||||||
CharmEffect.makeChoices(sa);
|
|
||||||
}
|
|
||||||
sa = AbilityUtils.addSpliceEffects(sa);
|
|
||||||
}
|
}
|
||||||
|
sa = AbilityUtils.addSpliceEffects(sa);
|
||||||
|
}
|
||||||
|
|
||||||
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
||||||
req.playAbility(mayChooseNewTargets, true, false);
|
req.playAbility(mayChooseNewTargets, true, false);
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (sa.isSpell()) {
|
|
||||||
final Card c = sa.getHostCard();
|
|
||||||
if (!c.isCopiedSpell()) {
|
|
||||||
sa.setHostCard(game.getAction().moveToStack(c, sa));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
game.getStack().add(sa);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* playSpellAbility_NoStack.
|
* playSpellAbility_NoStack.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param sa
|
* @param sa
|
||||||
* a {@link forge.game.spellability.SpellAbility} object.
|
* a {@link forge.game.spellability.SpellAbility} object.
|
||||||
*/
|
*/
|
||||||
@@ -230,14 +175,8 @@ public class HumanPlay {
|
|||||||
public final static void playSpellAbilityNoStack(final PlayerControllerHuman controller, final Player player, final SpellAbility sa, boolean useOldTargets) {
|
public final static void playSpellAbilityNoStack(final PlayerControllerHuman controller, final Player player, final SpellAbility sa, boolean useOldTargets) {
|
||||||
sa.setActivatingPlayer(player);
|
sa.setActivatingPlayer(player);
|
||||||
|
|
||||||
if (sa.getPayCosts() != null) {
|
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
||||||
final HumanPlaySpellAbility req = new HumanPlaySpellAbility(controller, sa);
|
req.playAbility(!useOldTargets, false, true);
|
||||||
|
|
||||||
req.playAbility(!useOldTargets, false, true);
|
|
||||||
}
|
|
||||||
else if (payManaCostIfNeeded(controller, player, sa)) {
|
|
||||||
AbilityUtils.resolve(sa);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@@ -506,14 +445,13 @@ public class HumanPlay {
|
|||||||
} else {
|
} else {
|
||||||
// replace this with input
|
// replace this with input
|
||||||
CardCollection newList = new CardCollection();
|
CardCollection newList = new CardCollection();
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheList = GameEntityView.getMap(list);
|
||||||
for (int i = 0; i < nNeeded; i++) {
|
for (int i = 0; i < nNeeded; i++) {
|
||||||
final Card c = p.getGame().getCard(SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblExileFromZone", from.getTranslatedName()), CardView.getCollection(list)));
|
final CardView cv = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblExileFromZone", from.getTranslatedName()), gameCacheList.getTrackableKeys());
|
||||||
if (c == null) {
|
if (cv == null || !gameCacheList.containsKey(cv)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
newList.add(gameCacheList.remove(cv));
|
||||||
list.remove(c);
|
|
||||||
newList.add(c);
|
|
||||||
}
|
}
|
||||||
costExile.payAsDecided(p, PaymentDecision.card(newList), sourceAbility);
|
costExile.payAsDecided(p, PaymentDecision.card(newList), sourceAbility);
|
||||||
}
|
}
|
||||||
@@ -543,27 +481,28 @@ public class HumanPlay {
|
|||||||
payableZone.add(player);
|
payableZone.add(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Player chosen = controller.getGame().getPlayer(SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardFromWhoseZone", from.getTranslatedName()), PlayerView.getCollection(payableZone)));
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(payableZone);
|
||||||
if (chosen == null) {
|
PlayerView pv = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardFromWhoseZone", from.getTranslatedName()), gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Player chosen = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
List<Card> typeList = CardLists.filter(list, CardPredicates.isOwner(chosen));
|
List<Card> typeList = CardLists.filter(list, CardPredicates.isOwner(chosen));
|
||||||
|
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheTypeList = GameEntityView.getMap(typeList);
|
||||||
for (int i = 0; i < amount; i++) {
|
for (int i = 0; i < amount; i++) {
|
||||||
if (typeList.isEmpty()) {
|
if (gameCacheTypeList.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
final CardView cv = SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardToLibrary"), gameCacheTypeList.getTrackableKeys());
|
||||||
final Card c = p.getGame().getCard(SGuiChoose.oneOrNone(Localizer.getInstance().getMessage("lblPutCardToLibrary"), CardView.getCollection(typeList)));
|
if (cv == null || !gameCacheTypeList.containsKey(cv)) {
|
||||||
|
|
||||||
if (c != null) {
|
|
||||||
typeList.remove(c);
|
|
||||||
p.getGame().getAction().moveToLibrary(c, Integer.parseInt(((CostPutCardToLib) part).getLibPos()), null);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
final Card c = gameCacheTypeList.get(cv);
|
||||||
|
|
||||||
|
gameCacheTypeList.remove(c);
|
||||||
|
p.getGame().getAction().moveToLibrary(c, Integer.parseInt(((CostPutCardToLib) part).getLibPos()), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // Tainted Specter, Gurzigost, etc.
|
else { // Tainted Specter, Gurzigost, etc.
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class HumanPlaySpellAbility {
|
|||||||
|
|
||||||
ability = GameActionUtil.addExtraKeywordCost(ability);
|
ability = GameActionUtil.addExtraKeywordCost(ability);
|
||||||
|
|
||||||
Cost abCost = ability.getPayCosts() == null ? new Cost("0", ability.isAbility()) : ability.getPayCosts();
|
Cost abCost = ability.getPayCosts();
|
||||||
CostPayment payment = new CostPayment(abCost, ability);
|
CostPayment payment = new CostPayment(abCost, ability);
|
||||||
|
|
||||||
// TODO Apply this to the SAStackInstance instead of the Player
|
// TODO Apply this to the SAStackInstance instead of the Player
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
private final Localizer localizer = Localizer.getInstance();
|
private final Localizer localizer = Localizer.getInstance();
|
||||||
|
|
||||||
protected Map<SpellAbilityView, SpellAbility> spellViewCache = null;
|
protected Map<SpellAbilityView, SpellAbility> spellViewCache = null;
|
||||||
|
protected GameEntityViewMap<Card, CardView> gameCache = new GameEntityViewMap<>();
|
||||||
|
|
||||||
public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp) {
|
public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp) {
|
||||||
super(game0, p, lp);
|
super(game0, p, lp);
|
||||||
@@ -151,7 +152,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if (t instanceof Card) {
|
if (t instanceof Card) {
|
||||||
tempShowCard((Card) t);
|
tempShowCard((Card) t);
|
||||||
} else if (t instanceof CardView) {
|
} else if (t instanceof CardView) {
|
||||||
tempShowCard(game.getCard((CardView) t));
|
tempShowCard(getCard((CardView) t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,14 +288,16 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
|
if (defender != null && assignDamageAsIfNotBlocked(attacker)) {
|
||||||
map.put(null, damageDealt);
|
map.put(null, damageDealt);
|
||||||
} else {
|
} else {
|
||||||
final List<CardView> vBlockers = CardView.getCollection(blockers);
|
|
||||||
if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1)) {
|
if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1)) {
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(blockers);
|
||||||
final CardView vAttacker = CardView.get(attacker);
|
final CardView vAttacker = CardView.get(attacker);
|
||||||
final GameEntityView vDefender = GameEntityView.get(defender);
|
final GameEntityView vDefender = GameEntityView.get(defender);
|
||||||
final Map<CardView, Integer> result = getGui().assignCombatDamage(vAttacker, vBlockers, damageDealt,
|
final Map<CardView, Integer> result = getGui().assignCombatDamage(vAttacker, gameCacheBlockers.getTrackableKeys(), damageDealt,
|
||||||
vDefender, overrideOrder);
|
vDefender, overrideOrder);
|
||||||
for (final Entry<CardView, Integer> e : result.entrySet()) {
|
for (final Entry<CardView, Integer> e : result.entrySet()) {
|
||||||
map.put(game.getCard(e.getKey()), e.getValue());
|
if (gameCacheBlockers.containsKey(e.getKey())) {
|
||||||
|
map.put(gameCacheBlockers.get(e.getKey()), e.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
map.put(blockers.get(0), damageDealt);
|
map.put(blockers.get(0), damageDealt);
|
||||||
@@ -377,9 +380,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
final boolean useUiPointAtCard =
|
final boolean useUiPointAtCard =
|
||||||
(FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) && (!GuiBase.getInterface().isLibgdxPort())) ?
|
(FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) && (!GuiBase.getInterface().isLibgdxPort())) ?
|
||||||
(cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) ||
|
(cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) ||
|
||||||
cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Command)) :
|
cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Command)) :
|
||||||
(cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield));
|
(cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield));
|
||||||
if (!useUiPointAtCard) {
|
if (!useUiPointAtCard) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -412,23 +415,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
tempShowCards(sourceList);
|
tempShowCards(sourceList);
|
||||||
final CardCollection choices = getGame().getCardList(getGui().many(title, localizer.getMessage("lblChosenCards"), min, max,
|
GameEntityViewMap<Card, CardView> gameCachechoose = GameEntityView.getMap(sourceList);
|
||||||
CardView.getCollection(sourceList), CardView.get(sa.getHostCard())));
|
List<CardView> views = getGui().many(title, localizer.getMessage("lblChosenCards"), min, max,
|
||||||
|
gameCachechoose.getTrackableKeys(), CardView.get(sa.getHostCard()));
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
|
final CardCollection choices = new CardCollection();
|
||||||
|
gameCachechoose.addToList(views, choices);
|
||||||
return choices;
|
return choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pfps there should be a better way
|
|
||||||
private GameEntity convertToEntity(final GameEntityView view) {
|
|
||||||
if (view instanceof CardView) {
|
|
||||||
return game.getCard((CardView) view);
|
|
||||||
} else if (view instanceof PlayerView) {
|
|
||||||
return game.getPlayer((PlayerView) view);
|
|
||||||
} else return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends GameEntity> T chooseSingleEntityForEffect(final FCollectionView<T> optionList,
|
public <T extends GameEntity> T chooseSingleEntityForEffect(final FCollectionView<T> optionList,
|
||||||
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final boolean isOptional,
|
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final boolean isOptional,
|
||||||
@@ -454,6 +449,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
tempShow(delayedReveal.getCards());
|
tempShow(delayedReveal.getCards());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameEntityViewMap<T, GameEntityView> gameCacheChoose = GameEntityView.getMap(optionList);
|
||||||
|
|
||||||
if (useSelectCardsInput(optionList)) {
|
if (useSelectCardsInput(optionList)) {
|
||||||
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, isOptional ? 0 : 1, 1,
|
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, isOptional ? 0 : 1, 1,
|
||||||
optionList, sa);
|
optionList, sa);
|
||||||
@@ -465,21 +463,25 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
final GameEntityView result = getGui().chooseSingleEntityForEffect(title,
|
final GameEntityView result = getGui().chooseSingleEntityForEffect(title,
|
||||||
GameEntityView.getEntityCollection(optionList), delayedReveal, isOptional);
|
gameCacheChoose.getTrackableKeys(), delayedReveal, isOptional);
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
return (T) convertToEntity(result);
|
if (result != null || !gameCacheChoose.containsKey(result)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return gameCacheChoose.get(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min, final int max,
|
public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min,
|
||||||
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer) {
|
final int max, final DelayedReveal delayedReveal, final SpellAbility sa, final String title,
|
||||||
|
final Player targetedPlayer) {
|
||||||
|
|
||||||
// useful details for debugging problems with the mass select logic
|
// useful details for debugging problems with the mass select logic
|
||||||
Sentry.getContext().addExtra("Card", sa.getCardView().toString());
|
Sentry.getContext().addExtra("Card", sa.getCardView().toString());
|
||||||
Sentry.getContext().addExtra("SpellAbility", sa.toString());
|
Sentry.getContext().addExtra("SpellAbility", sa.toString());
|
||||||
|
|
||||||
// Human is supposed to read the message and understand from it what to // choose
|
// Human is supposed to read the message and understand from it what to //
|
||||||
|
// choose
|
||||||
if (optionList.isEmpty()) {
|
if (optionList.isEmpty()) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(),
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(),
|
||||||
@@ -494,29 +496,24 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
tempShow(optionList);
|
tempShow(optionList);
|
||||||
if (useSelectCardsInput(optionList)) {
|
if (useSelectCardsInput(optionList)) {
|
||||||
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, min, max,
|
final InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<>(this, min, max, optionList,
|
||||||
optionList, sa);
|
sa);
|
||||||
input.setCancelAllowed(min == 0);
|
input.setCancelAllowed(min == 0);
|
||||||
input.setMessage(MessageUtil.formatMessage(title, player, targetedPlayer));
|
input.setMessage(MessageUtil.formatMessage(title, player, targetedPlayer));
|
||||||
input.showAndWait();
|
input.showAndWait();
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
return (List<T>) input.getSelected();
|
return (List<T>) input.getSelected();
|
||||||
}
|
|
||||||
final List<GameEntityView> chosen = getGui().chooseEntitiesForEffect(title,
|
|
||||||
GameEntityView.getEntityCollection(optionList), min, max, delayedReveal);
|
|
||||||
endTempShowCards();
|
|
||||||
|
|
||||||
List<T> results = new ArrayList<>(); //pfps I'm not sure that the chosens should be modified this way
|
|
||||||
if (chosen instanceof List && chosen.size() > 0) {
|
|
||||||
for (GameEntityView entry: chosen) {
|
|
||||||
if (entry instanceof CardView) {
|
|
||||||
results.add((T)game.getCard((CardView) entry));
|
|
||||||
}
|
|
||||||
if (entry instanceof PlayerView) {
|
|
||||||
results.add((T)game.getPlayer((PlayerView) entry));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
GameEntityViewMap<T, GameEntityView> gameCacheEntity = GameEntityView.getMap(optionList);
|
||||||
|
final List<GameEntityView> views = getGui().chooseEntitiesForEffect(title, gameCacheEntity.getTrackableKeys(), min, max, delayedReveal);
|
||||||
|
endTempShowCards();
|
||||||
|
|
||||||
|
List<T> results = Lists.newArrayList();
|
||||||
|
|
||||||
|
if (views != null) {
|
||||||
|
gameCacheEntity.addToList(views, results);
|
||||||
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +556,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see
|
* @see
|
||||||
* forge.game.player.PlayerController#confirmAction(forge.card.spellability.
|
* forge.game.player.PlayerController#confirmAction(forge.card.spellability.
|
||||||
* SpellAbility, java.lang.String, java.lang.String)
|
* SpellAbility, java.lang.String, java.lang.String)
|
||||||
@@ -686,43 +683,50 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollection orderBlockers(final Card attacker, final CardCollection blockers) {
|
public CardCollection orderBlockers(final Card attacker, final CardCollection blockers) {
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(blockers);
|
||||||
final CardView vAttacker = CardView.get(attacker);
|
final CardView vAttacker = CardView.get(attacker);
|
||||||
getGui().setPanelSelection(vAttacker);
|
getGui().setPanelSelection(vAttacker);
|
||||||
return game.getCardList(getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vAttacker.getName())), localizer.getMessage("lblDamagedFirst"),
|
List<CardView> chosen = getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vAttacker.getName())), localizer.getMessage("lblDamagedFirst"),
|
||||||
CardView.getCollection(blockers), vAttacker));
|
gameCacheBlockers.getTrackableKeys(), vAttacker);
|
||||||
|
CardCollection chosenCards = new CardCollection();
|
||||||
|
gameCacheBlockers.addToList(chosen, chosenCards);
|
||||||
|
return chosenCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Card> exertAttackers(List<Card> attackers) {
|
public List<Card> exertAttackers(List<Card> attackers) {
|
||||||
HashMap<CardView, Card> mapCVtoC = new HashMap<>();
|
GameEntityViewMap<Card, CardView> gameCacheExert = GameEntityView.getMap(attackers);
|
||||||
for (Card card : attackers) {
|
List<CardView> chosen = getGui().order(localizer.getMessage("lblExertAttackersConfirm"), localizer.getMessage("lblExerted"),
|
||||||
mapCVtoC.put(card.getView(), card);
|
0, gameCacheExert.size(), gameCacheExert.getTrackableKeys(), null, null, false);
|
||||||
}
|
|
||||||
List<CardView> chosen;
|
List<Card> chosenCards = new CardCollection();
|
||||||
List<CardView> choices = new ArrayList<>(mapCVtoC.keySet());
|
gameCacheExert.addToList(chosen, chosenCards);
|
||||||
chosen = getGui().order(localizer.getMessage("lblExertAttackersConfirm"), localizer.getMessage("lblExerted"), 0, choices.size(), choices, null, null, false);
|
|
||||||
List<Card> chosenCards = new ArrayList<>();
|
|
||||||
for (CardView cardView : chosen) {
|
|
||||||
chosenCards.add(mapCVtoC.get(cardView));
|
|
||||||
}
|
|
||||||
return chosenCards;
|
return chosenCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollection orderBlocker(final Card attacker, final Card blocker, final CardCollection oldBlockers) {
|
public CardCollection orderBlocker(final Card attacker, final Card blocker, final CardCollection oldBlockers) {
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(oldBlockers);
|
||||||
final CardView vAttacker = CardView.get(attacker);
|
final CardView vAttacker = CardView.get(attacker);
|
||||||
getGui().setPanelSelection(vAttacker);
|
getGui().setPanelSelection(vAttacker);
|
||||||
return game.getCardList(getGui().insertInList(
|
List<CardView> chosen = getGui().insertInList(
|
||||||
localizer.getMessage("lblChooseBlockerAfterWhichToPlaceAttackert", CardTranslation.getTranslatedName(vAttacker.getName())),
|
localizer.getMessage("lblChooseBlockerAfterWhichToPlaceAttackert", CardTranslation.getTranslatedName(vAttacker.getName())),
|
||||||
CardView.get(blocker), CardView.getCollection(oldBlockers)));
|
CardView.get(blocker), CardView.getCollection(oldBlockers));
|
||||||
|
CardCollection chosenCards = new CardCollection();
|
||||||
|
gameCacheBlockers.addToList(chosen, chosenCards);
|
||||||
|
return chosenCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollection orderAttackers(final Card blocker, final CardCollection attackers) {
|
public CardCollection orderAttackers(final Card blocker, final CardCollection attackers) {
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheAttackers = GameEntityView.getMap(attackers);
|
||||||
final CardView vBlocker = CardView.get(blocker);
|
final CardView vBlocker = CardView.get(blocker);
|
||||||
getGui().setPanelSelection(vBlocker);
|
getGui().setPanelSelection(vBlocker);
|
||||||
return game.getCardList(getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vBlocker.getName())), localizer.getMessage("lblDamagedFirst"),
|
List<CardView> chosen = getGui().order(localizer.getMessage("lblChooseDamageOrderFor", CardTranslation.getTranslatedName(vBlocker.getName())), localizer.getMessage("lblDamagedFirst"),
|
||||||
CardView.getCollection(attackers), vBlocker));
|
CardView.getCollection(attackers), vBlocker);
|
||||||
|
CardCollection chosenCards = new CardCollection();
|
||||||
|
gameCacheAttackers.addToList(chosen, chosenCards);
|
||||||
|
return chosenCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -739,7 +743,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
final String fm = MessageUtil.formatMessage(message, getLocalPlayerView(), owner);
|
final String fm = MessageUtil.formatMessage(message, getLocalPlayerView(), owner);
|
||||||
if (!cards.isEmpty()) {
|
if (!cards.isEmpty()) {
|
||||||
tempShowCards(game.getCardList(cards));
|
tempShowCards(getCardList(cards));
|
||||||
getGui().reveal(fm, cards);
|
getGui().reveal(fm, cards);
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
} else {
|
} else {
|
||||||
@@ -749,23 +753,27 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Card> manipulateCardList(final String title, final Iterable<Card> cards, final Iterable<Card> manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) {
|
public List<Card> manipulateCardList(final String title, final Iterable<Card> cards, final Iterable<Card> manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) {
|
||||||
Iterable<CardView> result = getGui().manipulateCardList(title, CardView.getCollection(cards), CardView.getCollection(manipulable), toTop, toBottom, toAnywhere);
|
GameEntityViewMap<Card, CardView> gameCacheManipulate = GameEntityView.getMap(cards);
|
||||||
return game.getCardList(result);
|
gameCacheManipulate.putAll(manipulable);
|
||||||
|
List<CardView> views = getGui().manipulateCardList(title, CardView.getCollection(cards), CardView.getCollection(manipulable), toTop, toBottom, toAnywhere);
|
||||||
|
List<Card> result = new CardCollection();
|
||||||
|
gameCacheManipulate.addToList(views, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImmutablePair<CardCollection, CardCollection> arrangeForMove(final String title, final FCollectionView<Card> cards, final List<Card> manipulable, final boolean topOK, final boolean bottomOK) {
|
public ImmutablePair<CardCollection, CardCollection> arrangeForMove(final String title, final FCollectionView<Card> cards, final List<Card> manipulable, final boolean topOK, final boolean bottomOK) {
|
||||||
List<Card> result = manipulateCardList(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cards, manipulable, topOK, bottomOK, false);
|
List<Card> result = manipulateCardList(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cards, manipulable, topOK, bottomOK, false);
|
||||||
CardCollection toBottom = new CardCollection();
|
CardCollection toBottom = new CardCollection();
|
||||||
CardCollection toTop = new CardCollection();
|
CardCollection toTop = new CardCollection();
|
||||||
for (int i = 0; i<cards.size() && manipulable.contains(result.get(i)) ; i++ ) {
|
for (int i = 0; i<cards.size() && manipulable.contains(result.get(i)) ; i++ ) {
|
||||||
toTop.add(result.get(i));
|
toTop.add(result.get(i));
|
||||||
}
|
|
||||||
if (toTop.size() < cards.size()) { // the top isn't everything
|
|
||||||
for (int i = result.size()-1; i>=0 && manipulable.contains(result.get(i)); i-- ) {
|
|
||||||
toBottom.add(result.get(i));
|
|
||||||
}
|
}
|
||||||
}
|
if (toTop.size() < cards.size()) { // the top isn't everything
|
||||||
return ImmutablePair.of(toTop,toBottom);
|
for (int i = result.size()-1; i>=0 && manipulable.contains(result.get(i)); i-- ) {
|
||||||
|
toBottom.add(result.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ImmutablePair.of(toTop,toBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -789,16 +797,24 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
toBottom = topN;
|
toBottom = topN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toBottom = game.getCardList(getGui().many(localizer.getMessage("lblSelectCardsToBeOutOnTheBottomOfYourLibrary"),
|
GameEntityViewMap<Card, CardView> cardCacheScry = GameEntityView.getMap(topN);
|
||||||
localizer.getMessage("lblCardsToPutOnTheBottom"), -1, CardView.getCollection(topN), null));
|
|
||||||
|
toBottom = new CardCollection();
|
||||||
|
List<CardView> views = getGui().many(localizer.getMessage("lblSelectCardsToBeOutOnTheBottomOfYourLibrary"),
|
||||||
|
localizer.getMessage("lblCardsToPutOnTheBottom"), -1, cardCacheScry.getTrackableKeys(), null);
|
||||||
|
cardCacheScry.addToList(views, toBottom);
|
||||||
|
|
||||||
topN.removeAll(toBottom);
|
topN.removeAll(toBottom);
|
||||||
if (topN.isEmpty()) {
|
if (topN.isEmpty()) {
|
||||||
toTop = null;
|
toTop = null;
|
||||||
} else if (topN.size() == 1) {
|
} else if (topN.size() == 1) {
|
||||||
toTop = topN;
|
toTop = topN;
|
||||||
} else {
|
} else {
|
||||||
toTop = game.getCardList(getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
|
GameEntityViewMap<Card, CardView> cardCacheOrder = GameEntityView.getMap(topN);
|
||||||
localizer.getMessage("lblTopOfLibrary"), CardView.getCollection(topN), null));
|
toTop = new CardCollection();
|
||||||
|
views = getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
|
||||||
|
localizer.getMessage("lblTopOfLibrary"), cardCacheOrder.getTrackableKeys(), null);
|
||||||
|
cardCacheOrder.addToList(views, toTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -827,16 +843,22 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
toGrave = topN;
|
toGrave = topN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toGrave = game.getCardList(getGui().many(localizer.getMessage("lblSelectCardsToBePutIntoTheGraveyard"),
|
GameEntityViewMap<Card, CardView> gameCacheSurveil = GameEntityView.getMap(topN);
|
||||||
localizer.getMessage("lblCardsToPutInTheGraveyard"), -1, CardView.getCollection(topN), null));
|
toGrave = new CardCollection();
|
||||||
|
List<CardView> views = getGui().many(localizer.getMessage("lblSelectCardsToBePutIntoTheGraveyard"),
|
||||||
|
localizer.getMessage("lblCardsToPutInTheGraveyard"), -1, gameCacheSurveil.getTrackableKeys(), null);
|
||||||
|
gameCacheSurveil.addToList(views, toGrave);
|
||||||
topN.removeAll(toGrave);
|
topN.removeAll(toGrave);
|
||||||
if (topN.isEmpty()) {
|
if (topN.isEmpty()) {
|
||||||
toTop = null;
|
toTop = null;
|
||||||
} else if (topN.size() == 1) {
|
} else if (topN.size() == 1) {
|
||||||
toTop = topN;
|
toTop = topN;
|
||||||
} else {
|
} else {
|
||||||
toTop = game.getCardList(getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
|
GameEntityViewMap<Card, CardView> cardCacheOrder = GameEntityView.getMap(topN);
|
||||||
localizer.getMessage("lblTopOfLibrary"), CardView.getCollection(topN), null));
|
toTop = new CardCollection();
|
||||||
|
views = getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
|
||||||
|
localizer.getMessage("lblTopOfLibrary"), cardCacheOrder.getTrackableKeys(), null);
|
||||||
|
cardCacheOrder.addToList(views, toTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
@@ -882,32 +904,28 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<CardView> choices;
|
|
||||||
tempShowCards(cards);
|
tempShowCards(cards);
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheMove = GameEntityView.getMap(cards);
|
||||||
|
List<CardView> choices = gameCacheMove.getTrackableKeys();
|
||||||
|
|
||||||
switch (destinationZone) {
|
switch (destinationZone) {
|
||||||
case Library:
|
case Library:
|
||||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage("lblClosestToTop"),
|
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage("lblClosestToTop"), choices, null);
|
||||||
CardView.getCollection(cards), null);
|
|
||||||
break;
|
break;
|
||||||
case Battlefield:
|
case Battlefield:
|
||||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"),
|
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"), choices, null);
|
||||||
CardView.getCollection(cards), null);
|
|
||||||
break;
|
break;
|
||||||
case Graveyard:
|
case Graveyard:
|
||||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"),
|
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"), choices, null);
|
||||||
CardView.getCollection(cards), null);
|
|
||||||
break;
|
break;
|
||||||
case PlanarDeck:
|
case PlanarDeck:
|
||||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"),
|
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"), choices, null);
|
||||||
CardView.getCollection(cards), null);
|
|
||||||
break;
|
break;
|
||||||
case SchemeDeck:
|
case SchemeDeck:
|
||||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"),
|
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"), choices, null);
|
||||||
CardView.getCollection(cards), null);
|
|
||||||
break;
|
break;
|
||||||
case Stack:
|
case Stack:
|
||||||
choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), CardView.getCollection(cards),
|
choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), choices, null);
|
||||||
null);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
System.out.println("ZoneType " + destinationZone + " - Not Ordered");
|
System.out.println("ZoneType " + destinationZone + " - Not Ordered");
|
||||||
@@ -915,7 +933,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
return game.getCardList(choices);
|
CardCollection result = new CardCollection();
|
||||||
|
gameCacheMove.addToList(choices, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -923,10 +943,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
final CardCollection valid, final int min, final int max) {
|
final CardCollection valid, final int min, final int max) {
|
||||||
if (p != player) {
|
if (p != player) {
|
||||||
tempShowCards(valid);
|
tempShowCards(valid);
|
||||||
final CardCollection choices = game
|
GameEntityViewMap<Card, CardView> gameCacheDiscard = GameEntityView.getMap(valid);
|
||||||
.getCardList(getGui().many(String.format(localizer.getMessage("lblChooseMinCardToDiscard"), min),
|
List<CardView> views = getGui().many(String.format(localizer.getMessage("lblChooseMinCardToDiscard"), min),
|
||||||
localizer.getMessage("lblDiscarded"), min, min, CardView.getCollection(valid), null));
|
localizer.getMessage("lblDiscarded"), min, min, gameCacheDiscard.getTrackableKeys(), null);
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
|
final CardCollection choices = new CardCollection();
|
||||||
|
gameCacheDiscard.addToList(views, choices);
|
||||||
return choices;
|
return choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,25 +971,26 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
cntChoice.add(Integer.valueOf(i));
|
cntChoice.add(Integer.valueOf(i));
|
||||||
}
|
}
|
||||||
final int chosenAmount = getGui().one(localizer.getMessage("lblDelveHowManyCards"), cntChoice.build()).intValue();
|
final int chosenAmount = getGui().one(localizer.getMessage("lblDelveHowManyCards"), cntChoice.build()).intValue();
|
||||||
for (int i = 0; i < chosenAmount; i++) {
|
|
||||||
final CardView nowChosen = getGui().oneOrNone(localizer.getMessage("lblExileWhichCard", String.valueOf(i + 1), String.valueOf(chosenAmount)), CardView.getCollection(grave));
|
|
||||||
|
|
||||||
if (nowChosen == null) {
|
GameEntityViewMap<Card, CardView> gameCacheGrave = GameEntityView.getMap(grave);
|
||||||
|
for (int i = 0; i < chosenAmount; i++) {
|
||||||
|
String title = localizer.getMessage("lblExileWhichCard", String.valueOf(i + 1), String.valueOf(chosenAmount));
|
||||||
|
final CardView nowChosen = getGui().oneOrNone(title, gameCacheGrave.getTrackableKeys());
|
||||||
|
|
||||||
|
if (nowChosen == null || !gameCacheGrave.containsKey(nowChosen)) {
|
||||||
// User canceled,abort delving.
|
// User canceled,abort delving.
|
||||||
toExile.clear();
|
toExile.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Card card = game.getCard(nowChosen);
|
toExile.add(gameCacheGrave.remove(nowChosen));
|
||||||
grave.remove(card);
|
|
||||||
toExile.add(card);
|
|
||||||
}
|
}
|
||||||
return toExile;
|
return toExile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see
|
* @see
|
||||||
* forge.game.player.PlayerController#chooseTargets(forge.card.spellability.
|
* forge.game.player.PlayerController#chooseTargets(forge.card.spellability.
|
||||||
* SpellAbility, forge.card.spellability.SpellAbilityStackInstance)
|
* SpellAbility, forge.card.spellability.SpellAbilityStackInstance)
|
||||||
@@ -991,7 +1014,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see
|
* @see
|
||||||
* forge.game.player.PlayerController#chooseCardsToDiscardUnlessType(int,
|
* forge.game.player.PlayerController#chooseCardsToDiscardUnlessType(int,
|
||||||
* java.lang.String, forge.card.spellability.SpellAbility)
|
* java.lang.String, forge.card.spellability.SpellAbility)
|
||||||
@@ -1020,7 +1043,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see
|
* @see
|
||||||
* forge.game.player.PlayerController#chooseManaFromPool(java.util.List)
|
* forge.game.player.PlayerController#chooseManaFromPool(java.util.List)
|
||||||
*/
|
*/
|
||||||
@@ -1038,7 +1061,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.game.player.PlayerController#chooseSomeType(java.lang.String,
|
* @see forge.game.player.PlayerController#chooseSomeType(java.lang.String,
|
||||||
* java.lang.String, java.util.List, java.util.List, java.lang.String)
|
* java.lang.String, java.util.List, java.util.List, java.lang.String)
|
||||||
*/
|
*/
|
||||||
@@ -1185,7 +1208,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see
|
* @see
|
||||||
* forge.game.player.PlayerController#confirmReplacementEffect(forge.card.
|
* forge.game.player.PlayerController#confirmReplacementEffect(forge.card.
|
||||||
* replacement.ReplacementEffect, forge.card.spellability.SpellAbility,
|
* replacement.ReplacementEffect, forge.card.spellability.SpellAbility,
|
||||||
@@ -1355,6 +1378,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SpellAbility> chooseSaToActivateFromOpeningHand(final List<SpellAbility> usableFromOpeningHand) {
|
public List<SpellAbility> chooseSaToActivateFromOpeningHand(final List<SpellAbility> usableFromOpeningHand) {
|
||||||
|
|
||||||
|
|
||||||
final CardCollection srcCards = new CardCollection();
|
final CardCollection srcCards = new CardCollection();
|
||||||
for (final SpellAbility sa : usableFromOpeningHand) {
|
for (final SpellAbility sa : usableFromOpeningHand) {
|
||||||
srcCards.add(sa.getHostCard());
|
srcCards.add(sa.getHostCard());
|
||||||
@@ -1363,10 +1388,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if (srcCards.isEmpty()) {
|
if (srcCards.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheOpenHand = GameEntityView.getMap(srcCards);
|
||||||
|
|
||||||
final List<CardView> chosen = getGui().many(localizer.getMessage("lblChooseCardsActivateOpeningHandandOrder"),
|
final List<CardView> chosen = getGui().many(localizer.getMessage("lblChooseCardsActivateOpeningHandandOrder"),
|
||||||
localizer.getMessage("lblActivateFirst"), -1, CardView.getCollection(srcCards), null);
|
localizer.getMessage("lblActivateFirst"), -1, CardView.getCollection(srcCards), null);
|
||||||
for (final CardView view : chosen) {
|
for (final CardView view : chosen) {
|
||||||
final Card c = game.getCard(view);
|
if (!gameCacheOpenHand.containsKey(view)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final Card c = gameCacheOpenHand.get(view);
|
||||||
for (final SpellAbility sa : usableFromOpeningHand) {
|
for (final SpellAbility sa : usableFromOpeningHand) {
|
||||||
if (sa.getHostCard() == c) {
|
if (sa.getHostCard() == c) {
|
||||||
result.add(sa);
|
result.add(sa);
|
||||||
@@ -1474,7 +1504,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.
|
* @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.
|
||||||
* spellability.SpellAbility, java.util.List, int, int)
|
* spellability.SpellAbility, java.util.List, int, int)
|
||||||
*/
|
*/
|
||||||
@@ -1983,7 +2013,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#setCanPlayUnlimitedLands(boolean)
|
* @see forge.player.IDevModeCheats#setCanPlayUnlimitedLands(boolean)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -1994,7 +2024,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#setViewAllCards(boolean)
|
* @see forge.player.IDevModeCheats#setViewAllCards(boolean)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2007,7 +2037,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#generateMana()
|
* @see forge.player.IDevModeCheats#generateMana()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2042,7 +2072,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#dumpGameState()
|
* @see forge.player.IDevModeCheats#dumpGameState()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2069,7 +2099,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#setupGameState()
|
* @see forge.player.IDevModeCheats#setupGameState()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2109,7 +2139,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#tutorForCard()
|
* @see forge.player.IDevModeCheats#tutorForCard()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2140,7 +2170,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#addCountersToPermanent()
|
* @see forge.player.IDevModeCheats#addCountersToPermanent()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2160,12 +2190,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
public void modifyCountersOnPermanent(boolean subtract) {
|
public void modifyCountersOnPermanent(boolean subtract) {
|
||||||
final String titleMsg = subtract ? localizer.getMessage("lblRemoveCountersFromWhichCard") : localizer.getMessage("lblAddCountersToWhichCard");
|
final String titleMsg = subtract ? localizer.getMessage("lblRemoveCountersFromWhichCard") : localizer.getMessage("lblAddCountersToWhichCard");
|
||||||
final CardCollectionView cards = game.getCardsIn(ZoneType.Battlefield);
|
|
||||||
final Card card = game
|
GameEntityViewMap<Card, CardView> gameCacheCounters = GameEntityView.getMap(game.getCardsIn(ZoneType.Battlefield));
|
||||||
.getCard(getGui().oneOrNone(titleMsg, CardView.getCollection(cards)));
|
|
||||||
if (card == null) {
|
final CardView cv = getGui().oneOrNone(titleMsg, gameCacheCounters.getTrackableKeys());
|
||||||
|
if (cv == null || !gameCacheCounters.containsKey(cv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final Card card = gameCacheCounters.get(cv);
|
||||||
|
|
||||||
final ImmutableList<CounterType> counters = subtract ? ImmutableList.copyOf(card.getCounters().keySet())
|
final ImmutableList<CounterType> counters = subtract ? ImmutableList.copyOf(card.getCounters().keySet())
|
||||||
: CounterType.values;
|
: CounterType.values;
|
||||||
@@ -2190,7 +2222,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#tapPermanents()
|
* @see forge.player.IDevModeCheats#tapPermanents()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2216,7 +2248,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#untapPermanents()
|
* @see forge.player.IDevModeCheats#untapPermanents()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2242,16 +2274,19 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#setPlayerLife()
|
* @see forge.player.IDevModeCheats#setPlayerLife()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setPlayerLife() {
|
public void setPlayerLife() {
|
||||||
final Player player = game.getPlayer(
|
|
||||||
getGui().oneOrNone(localizer.getMessage("lblSetLifeforWhichPlayer"), PlayerView.getCollection(game.getPlayers())));
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
|
||||||
if (player == null) {
|
|
||||||
|
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblSetLifeforWhichPlayer"), gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final Player player = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final Integer life = getGui().getInteger(localizer.getMessage("lblSetLifetoWhat"), 0);
|
final Integer life = getGui().getInteger(localizer.getMessage("lblSetLifetoWhat"), 0);
|
||||||
if (life == null) {
|
if (life == null) {
|
||||||
@@ -2263,7 +2298,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#winGame()
|
* @see forge.player.IDevModeCheats#winGame()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2289,7 +2324,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#addCardToHand()
|
* @see forge.player.IDevModeCheats#addCardToHand()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2375,12 +2410,21 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player p = repeatLast ? lastAddedPlayer
|
Player pOld = lastAddedPlayer;
|
||||||
: game.getPlayer(getGui().oneOrNone(message,
|
if (repeatLast) {
|
||||||
PlayerView.getCollection(game.getPlayers())));
|
if (pOld == null) {
|
||||||
if (p == null) {
|
return;
|
||||||
return;
|
}
|
||||||
|
} else {
|
||||||
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
|
||||||
|
PlayerView pv = getGui().oneOrNone(message, gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pOld = gameCachePlayer.get(pv);
|
||||||
}
|
}
|
||||||
|
final Player p = pOld;
|
||||||
|
|
||||||
|
|
||||||
final CardDb carddb = FModel.getMagicDb().getCommonCards();
|
final CardDb carddb = FModel.getMagicDb().getCommonCards();
|
||||||
final List<ICardFace> faces = Lists.newArrayList(carddb.getAllFaces());
|
final List<ICardFace> faces = Lists.newArrayList(carddb.getAllFaces());
|
||||||
@@ -2478,70 +2522,76 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#exileCardsFromHand()
|
* @see forge.player.IDevModeCheats#exileCardsFromHand()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void exileCardsFromHand() {
|
public void exileCardsFromHand() {
|
||||||
final Player p = game.getPlayer(getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerHandConfirm"),
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
|
||||||
PlayerView.getCollection(game.getPlayers())));
|
|
||||||
if (p == null) {
|
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerHandConfirm"),
|
||||||
|
gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Player p = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final CardCollection selection;
|
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(p.getCardsIn(ZoneType.Hand));
|
||||||
|
|
||||||
CardCollectionView cardsInHand = p.getCardsIn(ZoneType.Hand);
|
List<CardView> views = getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
|
||||||
selection = game.getCardList(getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
|
gameCacheExile.getTrackableKeys(), null);
|
||||||
CardView.getCollection(cardsInHand), null));
|
|
||||||
|
|
||||||
if (selection != null && selection.size() > 0) {
|
final CardCollection selection = new CardCollection();
|
||||||
for (Card c : selection) {
|
gameCacheExile.addToList(views, selection);
|
||||||
if (c == null) {
|
|
||||||
continue;
|
for (Card c : selection) {
|
||||||
}
|
if (c == null) {
|
||||||
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
|
continue;
|
||||||
StringBuilder sb = new StringBuilder();
|
}
|
||||||
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
|
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
|
||||||
game.getGameLog().add(GameLogEntryType.DISCARD, sb.toString());
|
StringBuilder sb = new StringBuilder();
|
||||||
} else {
|
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
|
||||||
game.getGameLog().add(GameLogEntryType.INFORMATION, "DISCARD CHEAT ERROR");
|
game.getGameLog().add(GameLogEntryType.DISCARD, sb.toString());
|
||||||
}
|
} else {
|
||||||
|
game.getGameLog().add(GameLogEntryType.INFORMATION, "DISCARD CHEAT ERROR");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#exileCardsFromBattlefield()
|
* @see forge.player.IDevModeCheats#exileCardsFromBattlefield()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void exileCardsFromBattlefield() {
|
public void exileCardsFromBattlefield() {
|
||||||
final Player p = game.getPlayer(getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerBattlefieldConfirm"),
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
|
||||||
PlayerView.getCollection(game.getPlayers())));
|
|
||||||
if (p == null) {
|
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblExileCardsFromPlayerBattlefieldConfirm"),
|
||||||
|
gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Player p = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final CardCollection selection;
|
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(p.getCardsIn(ZoneType.Battlefield));
|
||||||
|
|
||||||
CardCollectionView cardsInPlay = p.getCardsIn(ZoneType.Battlefield);
|
List<CardView> views = getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
|
||||||
selection = game.getCardList(getGui().many(localizer.getMessage("lblChooseCardsExile"), localizer.getMessage("lblDiscarded"), 0, -1,
|
gameCacheExile.getTrackableKeys(), null);
|
||||||
CardView.getCollection(cardsInPlay), null));
|
|
||||||
|
|
||||||
if (selection != null && selection.size() > 0) {
|
final CardCollection selection = new CardCollection();
|
||||||
for (Card c : selection) {
|
gameCacheExile.addToList(views, selection);
|
||||||
if (c == null) {
|
|
||||||
continue;
|
for (Card c : selection) {
|
||||||
}
|
if (c == null) {
|
||||||
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
|
continue;
|
||||||
StringBuilder sb = new StringBuilder();
|
}
|
||||||
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
|
if (game.getAction().moveTo(ZoneType.Exile, c, null) != null) {
|
||||||
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
|
StringBuilder sb = new StringBuilder();
|
||||||
} else {
|
sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats.");
|
||||||
game.getGameLog().add(GameLogEntryType.INFORMATION, "EXILE FROM PLAY CHEAT ERROR");
|
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
|
||||||
}
|
} else {
|
||||||
|
game.getGameLog().add(GameLogEntryType.INFORMATION, "EXILE FROM PLAY CHEAT ERROR");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2553,48 +2603,53 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void removeCardsFromGame() {
|
public void removeCardsFromGame() {
|
||||||
final Player p = game.getPlayer(getGui().oneOrNone(localizer.getMessage("lblRemoveCardBelongingWitchPlayer"),
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
|
||||||
PlayerView.getCollection(game.getPlayers())));
|
|
||||||
if (p == null) {
|
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblRemoveCardBelongingWitchPlayer"),
|
||||||
|
gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Player p = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final String zone = getGui().one(localizer.getMessage("lblRemoveCardFromWhichZone"),
|
final String zone = getGui().one(localizer.getMessage("lblRemoveCardFromWhichZone"),
|
||||||
Arrays.asList("Hand", "Battlefield", "Library", "Graveyard", "Exile"));
|
Arrays.asList("Hand", "Battlefield", "Library", "Graveyard", "Exile"));
|
||||||
|
|
||||||
final CardCollection selection;
|
|
||||||
|
|
||||||
CardCollectionView cards = p.getCardsIn(ZoneType.smartValueOf(zone));
|
CardCollectionView cards = p.getCardsIn(ZoneType.smartValueOf(zone));
|
||||||
selection = game.getCardList(getGui().many(localizer.getMessage("lblChooseCardsRemoveFromGame"), localizer.getMessage("lblRemoved"), 0, -1,
|
GameEntityViewMap<Card, CardView> gameCacheExile = GameEntityView.getMap(cards);
|
||||||
CardView.getCollection(cards), null));
|
List<CardView> views = getGui().many(localizer.getMessage("lblChooseCardsRemoveFromGame"), localizer.getMessage("lblRemoved"), 0, -1,
|
||||||
|
gameCacheExile.getTrackableKeys(), null);
|
||||||
|
|
||||||
if (selection != null && selection.size() > 0) {
|
final CardCollection selection = new CardCollection();
|
||||||
for (Card c : selection) {
|
gameCacheExile.addToList(views, selection);
|
||||||
if (c == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
c.getZone().remove(c);
|
|
||||||
c.ceaseToExist();
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
for (Card c : selection) {
|
||||||
sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats.");
|
if (c == null) {
|
||||||
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
|
continue;
|
||||||
}
|
}
|
||||||
|
c.getZone().remove(c);
|
||||||
|
c.ceaseToExist();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats.");
|
||||||
|
game.getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#riggedPlanarRoll()
|
* @see forge.player.IDevModeCheats#riggedPlanarRoll()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void riggedPlanarRoll() {
|
public void riggedPlanarRoll() {
|
||||||
final Player player = game.getPlayer(
|
GameEntityViewMap<Player, PlayerView> gameCachePlayer = GameEntityView.getMap(game.getPlayers());
|
||||||
getGui().oneOrNone(localizer.getMessage("lblWhichPlayerShouldRoll"), PlayerView.getCollection(game.getPlayers())));
|
|
||||||
if (player == null) {
|
final PlayerView pv = getGui().oneOrNone(localizer.getMessage("lblWhichPlayerShouldRoll"), gameCachePlayer.getTrackableKeys());
|
||||||
|
if (pv == null || !gameCachePlayer.containsKey(pv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final Player player = gameCachePlayer.get(pv);
|
||||||
|
|
||||||
final PlanarDice res = getGui().oneOrNone(localizer.getMessage("lblChooseResult"), PlanarDice.values);
|
final PlanarDice res = getGui().oneOrNone(localizer.getMessage("lblChooseResult"), PlanarDice.values);
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
@@ -2613,7 +2668,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.player.IDevModeCheats#planeswalkTo()
|
* @see forge.player.IDevModeCheats#planeswalkTo()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -2868,7 +2923,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
@Override
|
@Override
|
||||||
public void reorderHand(final CardView card, final int index) {
|
public void reorderHand(final CardView card, final int index) {
|
||||||
final PlayerZone hand = player.getZone(ZoneType.Hand);
|
final PlayerZone hand = player.getZone(ZoneType.Hand);
|
||||||
hand.reorder(game.getCard(card), index);
|
hand.reorder(getCard(card), index);
|
||||||
player.updateZoneForView(hand);
|
player.updateZoneForView(hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2880,30 +2935,25 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Card> chooseCardsForSplice(SpellAbility sa, List<Card> cards) {
|
public List<Card> chooseCardsForSplice(SpellAbility sa, List<Card> cards) {
|
||||||
HashMap<CardView, Card> mapCVtoC = new HashMap<>();
|
GameEntityViewMap<Card, CardView> gameCacheSplice = GameEntityView.getMap(cards);
|
||||||
for (Card card : cards) {
|
|
||||||
mapCVtoC.put(card.getView(), card);
|
List<CardView> chosen = getGui().many(
|
||||||
}
|
|
||||||
List<CardView> choices = new ArrayList<>(mapCVtoC.keySet());
|
|
||||||
List<CardView> chosen;
|
|
||||||
chosen = getGui().many(
|
|
||||||
localizer.getMessage("lblChooseCardstoSpliceonto"),
|
localizer.getMessage("lblChooseCardstoSpliceonto"),
|
||||||
localizer.getMessage("lblChosenCards"),
|
localizer.getMessage("lblChosenCards"),
|
||||||
0,
|
0,
|
||||||
choices.size(),
|
gameCacheSplice.size(),
|
||||||
choices,
|
gameCacheSplice.getTrackableKeys(),
|
||||||
sa.getHostCard().getView()
|
sa.getHostCard().getView()
|
||||||
);
|
);
|
||||||
List<Card> chosenCards = new ArrayList<>();
|
|
||||||
for (CardView cardView : chosen) {
|
List<Card> chosenCards = new CardCollection();
|
||||||
chosenCards.add(mapCVtoC.get(cardView));
|
gameCacheSplice.addToList(chosen, chosenCards);
|
||||||
}
|
|
||||||
return chosenCards;
|
return chosenCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
* @see forge.game.player.PlayerController#chooseOptionalCosts(forge.game.
|
* @see forge.game.player.PlayerController#chooseOptionalCosts(forge.game.
|
||||||
* spellability.SpellAbility, java.util.List)
|
* spellability.SpellAbility, java.util.List)
|
||||||
*/
|
*/
|
||||||
@@ -2942,5 +2992,25 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Card getCard(final CardView cardView) {
|
||||||
|
if (gameCache.containsKey(cardView)) {
|
||||||
|
return gameCache.get(cardView);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Card c = getGame().findById(cardView.getId());
|
||||||
|
gameCache.put(cardView, c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CardCollection getCardList(Iterable<CardView> cardViews) {
|
||||||
|
CardCollection result = new CardCollection();
|
||||||
|
for(CardView cardView : cardViews){
|
||||||
|
final Card c = this.getCard(cardView);
|
||||||
|
if (c != null) {
|
||||||
|
result.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -21,6 +21,8 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityView;
|
||||||
|
import forge.game.GameEntityViewMap;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
@@ -44,7 +46,7 @@ import java.util.Map;
|
|||||||
* <p>
|
* <p>
|
||||||
* Target_Selection class.
|
* Target_Selection class.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id: TargetSelection.java 25148 2014-03-12 08:28:52Z swordshine $
|
* @version $Id: TargetSelection.java 25148 2014-03-12 08:28:52Z swordshine $
|
||||||
*/
|
*/
|
||||||
@@ -69,8 +71,8 @@ public class TargetSelection {
|
|||||||
if (!canTarget) {
|
if (!canTarget) {
|
||||||
throw new RuntimeException("TargetSelection.chooseTargets called for ability that does not target - " + ability);
|
throw new RuntimeException("TargetSelection.chooseTargets called for ability that does not target - " + ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of targets is explicitly set only if spell is being redirected (ex. Swerve or Redirect)
|
// Number of targets is explicitly set only if spell is being redirected (ex. Swerve or Redirect)
|
||||||
final int minTargets = numTargets != null ? numTargets.intValue() : tgt.getMinTargets(ability.getHostCard(), ability);
|
final int minTargets = numTargets != null ? numTargets.intValue() : tgt.getMinTargets(ability.getHostCard(), ability);
|
||||||
final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getHostCard(), ability);
|
final int maxTargets = numTargets != null ? numTargets.intValue() : tgt.getMaxTargets(ability.getHostCard(), ability);
|
||||||
//final int maxTotalCMC = tgt.getMaxTotalCMC(ability.getHostCard(), ability);
|
//final int maxTotalCMC = tgt.getMaxTotalCMC(ability.getHostCard(), ability);
|
||||||
@@ -99,10 +101,10 @@ public class TargetSelection {
|
|||||||
// Mandatory target selection, that has no candidates but enough targets (Min == 0, but no choices)
|
// Mandatory target selection, that has no candidates but enough targets (Min == 0, but no choices)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<ZoneType> zones = tgt.getZone();
|
final List<ZoneType> zones = tgt.getZone();
|
||||||
final boolean mandatory = tgt.getMandatory() && hasCandidates;
|
final boolean mandatory = tgt.getMandatory() && hasCandidates;
|
||||||
|
|
||||||
final boolean choiceResult;
|
final boolean choiceResult;
|
||||||
final boolean random = tgt.isRandomTarget();
|
final boolean random = tgt.isRandomTarget();
|
||||||
if (random) {
|
if (random) {
|
||||||
@@ -167,7 +169,7 @@ public class TargetSelection {
|
|||||||
choiceResult = this.chooseCardFromList(validTargets, true, mandatory);
|
choiceResult = this.chooseCardFromList(validTargets, true, mandatory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// some inputs choose cards one-by-one and need to be called again
|
// some inputs choose cards one-by-one and need to be called again
|
||||||
return choiceResult && chooseTargets(numTargets);
|
return choiceResult && chooseTargets(numTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +177,8 @@ public class TargetSelection {
|
|||||||
// Send in a list of valid cards, and popup a choice box to target
|
// Send in a list of valid cards, and popup a choice box to target
|
||||||
final Game game = ability.getActivatingPlayer().getGame();
|
final Game game = ability.getActivatingPlayer().getGame();
|
||||||
|
|
||||||
|
GameEntityViewMap<Card, CardView> gameCacheChooseCard = GameEntityView.getMap(choices);
|
||||||
|
|
||||||
final List<CardView> crdsBattle = Lists.newArrayList();
|
final List<CardView> crdsBattle = Lists.newArrayList();
|
||||||
final List<CardView> crdsExile = Lists.newArrayList();
|
final List<CardView> crdsExile = Lists.newArrayList();
|
||||||
final List<CardView> crdsGrave = Lists.newArrayList();
|
final List<CardView> crdsGrave = Lists.newArrayList();
|
||||||
@@ -228,7 +232,7 @@ public class TargetSelection {
|
|||||||
// is there a more elegant way of doing this?
|
// is there a more elegant way of doing this?
|
||||||
choicesFiltered.add(msgDone);
|
choicesFiltered.add(msgDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object chosen = null;
|
Object chosen = null;
|
||||||
if (!choices.isEmpty() && mandatory) {
|
if (!choices.isEmpty() && mandatory) {
|
||||||
chosen = controller.getGui().one(getTgt().getVTSelection(), choicesFiltered);
|
chosen = controller.getGui().one(getTgt().getVTSelection(), choicesFiltered);
|
||||||
@@ -245,7 +249,10 @@ public class TargetSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (chosen instanceof CardView) {
|
if (chosen instanceof CardView) {
|
||||||
ability.getTargets().add(game.getCard((CardView) chosen));
|
if (!gameCacheChooseCard.containsKey(chosen)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ability.getTargets().add(gameCacheChooseCard.get((CardView) chosen));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -292,7 +299,7 @@ public class TargetSelection {
|
|||||||
if (madeChoice instanceof StackItemView) {
|
if (madeChoice instanceof StackItemView) {
|
||||||
ability.getTargets().add(stackItemViewCache.get(madeChoice).getSpellAbility(true));
|
ability.getTargets().add(stackItemViewCache.get(madeChoice).getSpellAbility(true));
|
||||||
}
|
}
|
||||||
else {// 'FINISH TARGETING' chosen
|
else {// 'FINISH TARGETING' chosen
|
||||||
bTargetingDone = true;
|
bTargetingDone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user