mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Use current shard when trying to pay with combo mana (#3130)
* Use current shard when trying to pay with combo mana
This commit is contained in:
@@ -1507,7 +1507,7 @@ public class AiAttackController {
|
|||||||
}
|
}
|
||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
sa.setActivatingPlayer(c.getController(), true);
|
sa.setActivatingPlayer(c.getController(), true);
|
||||||
List<Card> validTargets = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
List<Card> validTargets = CardUtil.getValidCardsToTarget(sa);
|
||||||
if (validTargets.isEmpty()) {
|
if (validTargets.isEmpty()) {
|
||||||
missTarget = true;
|
missTarget = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -644,7 +644,6 @@ public class AiController {
|
|||||||
public SpellAbility predictSpellToCastInMain2(ApiType exceptSA) {
|
public SpellAbility predictSpellToCastInMain2(ApiType exceptSA) {
|
||||||
return predictSpellToCastInMain2(exceptSA, true);
|
return predictSpellToCastInMain2(exceptSA, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpellAbility predictSpellToCastInMain2(ApiType exceptSA, boolean handOnly) {
|
private SpellAbility predictSpellToCastInMain2(ApiType exceptSA, boolean handOnly) {
|
||||||
if (!getBooleanProperty(AiProps.PREDICT_SPELLS_FOR_MAIN2)) {
|
if (!getBooleanProperty(AiProps.PREDICT_SPELLS_FOR_MAIN2)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -684,15 +683,12 @@ public class AiController {
|
|||||||
public boolean reserveManaSourcesForNextSpell(SpellAbility sa, SpellAbility exceptForSa) {
|
public boolean reserveManaSourcesForNextSpell(SpellAbility sa, SpellAbility exceptForSa) {
|
||||||
return reserveManaSources(sa, null, false, true, exceptForSa);
|
return reserveManaSources(sa, null, false, true, exceptForSa);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reserveManaSources(SpellAbility sa) {
|
public boolean reserveManaSources(SpellAbility sa) {
|
||||||
return reserveManaSources(sa, PhaseType.MAIN2, false, false, null);
|
return reserveManaSources(sa, PhaseType.MAIN2, false, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) {
|
public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) {
|
||||||
return reserveManaSources(sa, phaseType, enemy, true, null);
|
return reserveManaSources(sa, phaseType, enemy, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy, boolean forNextSpell, SpellAbility exceptForThisSa) {
|
public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy, boolean forNextSpell, SpellAbility exceptForThisSa) {
|
||||||
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, true, 0);
|
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, true, 0);
|
||||||
CardCollection manaSources = ComputerUtilMana.getManaSourcesToPayCost(cost, sa, player);
|
CardCollection manaSources = ComputerUtilMana.getManaSourcesToPayCost(cost, sa, player);
|
||||||
|
|||||||
@@ -868,7 +868,7 @@ public class ComputerUtilCost {
|
|||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
// if announce is used as min targets, check what the max possible number would be
|
// if announce is used as min targets, check what the max possible number would be
|
||||||
if ("X".equals(sa.getTargetRestrictions().getMinTargets())) {
|
if ("X".equals(sa.getTargetRestrictions().getMinTargets())) {
|
||||||
val = ObjectUtils.min(val, CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa).size());
|
val = ObjectUtils.min(val, CardUtil.getValidCardsToTarget(sa).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sa.hasParam("AIMaxTgtsCount")) {
|
if (sa.hasParam("AIMaxTgtsCount")) {
|
||||||
|
|||||||
@@ -962,6 +962,7 @@ public class ComputerUtilMana {
|
|||||||
ManaCostShard toPay, SpellAbility saPayment) {
|
ManaCostShard toPay, SpellAbility saPayment) {
|
||||||
AbilityManaPart m = saPayment.getManaPart();
|
AbilityManaPart m = saPayment.getManaPart();
|
||||||
if (m.isComboMana()) {
|
if (m.isComboMana()) {
|
||||||
|
m.setExpressChoice(ColorSet.fromMask(toPay.getColorMask()));
|
||||||
getComboManaChoice(ai, saPayment, sa, cost);
|
getComboManaChoice(ai, saPayment, sa, cost);
|
||||||
}
|
}
|
||||||
else if (saPayment.getApi() == ApiType.ManaReflected) {
|
else if (saPayment.getApi() == ApiType.ManaReflected) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class SpecialAiLogic {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Card> targetable = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
List<Card> targetable = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
CardCollection listOpp = CardLists.filterControlledBy(targetable, ai.getOpponents());
|
CardCollection listOpp = CardLists.filterControlledBy(targetable, ai.getOpponents());
|
||||||
if (isDestroy) {
|
if (isDestroy) {
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
} else if (sa.usesTargeting() && mandatory) {
|
} else if (sa.usesTargeting() && mandatory) {
|
||||||
// fallback if animate is mandatory
|
// fallback if animate is mandatory
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,8 +123,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Chained to the Rocks")) {
|
if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Chained to the Rocks")) {
|
||||||
final SpellAbility effectExile = AbilityFactory.getAbility(source.getSVar("TrigExile"), source);
|
final SpellAbility effectExile = AbilityFactory.getAbility(source.getSVar("TrigExile"), source);
|
||||||
effectExile.setActivatingPlayer(ai, true);
|
effectExile.setActivatingPlayer(ai, true);
|
||||||
final TargetRestrictions exile_tgt = effectExile.getTargetRestrictions();
|
final List<Card> targets = CardUtil.getValidCardsToTarget(effectExile);
|
||||||
final List<Card> targets = CardUtil.getValidCardsToTarget(exile_tgt, effectExile);
|
|
||||||
return !targets.isEmpty();
|
return !targets.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1328,11 +1327,9 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
|
||||||
|
|
||||||
// Is a SA that moves target attachment
|
// Is a SA that moves target attachment
|
||||||
if ("MoveTgtAura".equals(sa.getParam("AILogic"))) {
|
if ("MoveTgtAura".equals(sa.getParam("AILogic"))) {
|
||||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(tgt, sa), Predicates.or(CardPredicates.isControlledByAnyOf(aiPlayer.getOpponents()), new Predicate<Card>() {
|
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(sa), Predicates.or(CardPredicates.isControlledByAnyOf(aiPlayer.getOpponents()), new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card card) {
|
public boolean apply(final Card card) {
|
||||||
return ComputerUtilCard.isUselessCreature(aiPlayer, card.getAttachedTo());
|
return ComputerUtilCard.isUselessCreature(aiPlayer, card.getAttachedTo());
|
||||||
@@ -1341,7 +1338,7 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
return !list.isEmpty() ? ComputerUtilCard.getBestAI(list) : null;
|
return !list.isEmpty() ? ComputerUtilCard.getBestAI(list) : null;
|
||||||
} else if ("Unenchanted".equals(sa.getParam("AILogic"))) {
|
} else if ("Unenchanted".equals(sa.getParam("AILogic"))) {
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
CardCollection preferred = CardLists.filter(list, new Predicate<Card>() {
|
CardCollection preferred = CardLists.filter(list, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card card) {
|
public boolean apply(final Card card) {
|
||||||
@@ -1358,10 +1355,10 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Card> list = null;
|
List<Card> list = null;
|
||||||
if (tgt == null) {
|
if (sa.usesTargeting()) {
|
||||||
list = AbilityUtils.getDefinedCards(attachSource, sa.getParam("Defined"), sa);
|
list = CardUtil.getValidCardsToTarget(sa);
|
||||||
} else {
|
} else {
|
||||||
list = CardUtil.getValidCardsToTarget(tgt, sa);
|
list = AbilityUtils.getDefinedCards(attachSource, sa.getParam("Defined"), sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
|||||||
@@ -1432,7 +1432,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
final ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
|
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
|||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
//Nothing to target
|
//Nothing to target
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ public class DebuffAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
private boolean debuffMandatoryTarget(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
private boolean debuffMandatoryTarget(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ public class EffectAi extends SpellAbilityAi {
|
|||||||
} else if (logic.equals("Fight")) {
|
} else if (logic.equals("Fight")) {
|
||||||
return FightAi.canFightAi(ai, sa, 0, 0);
|
return FightAi.canFightAi(ai, sa, 0, 0);
|
||||||
} else if (logic.equals("Pump")) {
|
} else if (logic.equals("Pump")) {
|
||||||
List<Card> options = CardUtil.getValidCardsToTarget(sa.getTargetRestrictions(), sa);
|
List<Card> options = CardUtil.getValidCardsToTarget(sa);
|
||||||
options = CardLists.filterControlledBy(options, ai);
|
options = CardLists.filterControlledBy(options, ai);
|
||||||
if (sa.getPayCosts().hasTapCost()) {
|
if (sa.getPayCosts().hasTapCost()) {
|
||||||
options.remove(sa.getHostCard());
|
options.remove(sa.getHostCard());
|
||||||
|
|||||||
@@ -213,11 +213,10 @@ public class PlayAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
private static List<Card> getPlayableCards(SpellAbility sa, Player ai) {
|
private static List<Card> getPlayableCards(SpellAbility sa, Player ai) {
|
||||||
List<Card> cards = null;
|
List<Card> cards = null;
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
if (tgt != null) {
|
if (sa.usesTargeting()) {
|
||||||
cards = CardUtil.getValidCardsToTarget(tgt, sa);
|
cards = CardUtil.getValidCardsToTarget(sa);
|
||||||
} else if (!sa.hasParam("Valid")) {
|
} else if (!sa.hasParam("Valid")) {
|
||||||
cards = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
cards = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ public class ProtectAi extends SpellAbilityAi {
|
|||||||
private static boolean protectMandatoryTarget(final Player ai, final SpellAbility sa) {
|
private static boolean protectMandatoryTarget(final Player ai, final SpellAbility sa) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
final List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
final List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
if (list.size() < tgt.getMinTargets(source, sa)) {
|
if (list.size() < tgt.getMinTargets(source, sa)) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ public class PumpAi extends PumpAiBase {
|
|||||||
|
|
||||||
private boolean pumpMandatoryTarget(final Player ai, final SpellAbility sa) {
|
private boolean pumpMandatoryTarget(final Player ai, final SpellAbility sa) {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
public class SetStateAi extends SpellAbilityAi {
|
public class SetStateAi extends SpellAbilityAi {
|
||||||
@@ -79,11 +78,10 @@ public class SetStateAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
return shouldTransformCard(source, ai, ph) || "Always".equals(logic);
|
return shouldTransformCard(source, ai, ph) || "Always".equals(logic);
|
||||||
} else {
|
} else {
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
// select only the ones that can transform
|
// select only the ones that can transform
|
||||||
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(tgt, sa), CardPredicates.Presets.CREATURES, new Predicate<Card>() {
|
CardCollection list = CardLists.filter(CardUtil.getValidCardsToTarget(sa), CardPredicates.Presets.CREATURES, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Card c) {
|
public boolean apply(Card c) {
|
||||||
return c.canTransform(sa);
|
return c.canTransform(sa);
|
||||||
@@ -106,17 +104,10 @@ public class SetStateAi extends SpellAbilityAi {
|
|||||||
return sa.isMinTargetChosen();
|
return sa.isMinTargetChosen();
|
||||||
}
|
}
|
||||||
} else if ("TurnFace".equals(mode)) {
|
} else if ("TurnFace".equals(mode)) {
|
||||||
if (!sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
CardCollection list = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return shouldTurnFace(list.get(0), ai, ph) || "Always".equals(logic);
|
|
||||||
} else {
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
|
||||||
sa.resetTargets();
|
sa.resetTargets();
|
||||||
|
|
||||||
List<Card> list = CardUtil.getValidCardsToTarget(tgt, sa);
|
List<Card> list = CardUtil.getValidCardsToTarget(sa);
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -132,6 +123,12 @@ public class SetStateAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sa.isTargetNumberValid();
|
return sa.isTargetNumberValid();
|
||||||
|
} else {
|
||||||
|
CardCollection list = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return shouldTurnFace(list.get(0), ai, ph) || "Always".equals(logic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -544,7 +544,8 @@ public final class CardUtil {
|
|||||||
// parameters for target selection.
|
// parameters for target selection.
|
||||||
// however, due to the changes necessary for SA_Requirements this is much
|
// however, due to the changes necessary for SA_Requirements this is much
|
||||||
// different than the original
|
// different than the original
|
||||||
public static List<Card> getValidCardsToTarget(TargetRestrictions tgt, SpellAbility ability) {
|
public static List<Card> getValidCardsToTarget(final SpellAbility ability) {
|
||||||
|
final TargetRestrictions tgt = ability.getTargetRestrictions();
|
||||||
final Card activatingCard = ability.getHostCard();
|
final Card activatingCard = ability.getHostCard();
|
||||||
final Game game = ability.getActivatingPlayer().getGame();
|
final Game game = ability.getActivatingPlayer().getGame();
|
||||||
final List<ZoneType> zone = tgt.getZone();
|
final List<ZoneType> zone = tgt.getZone();
|
||||||
|
|||||||
@@ -460,7 +460,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
if (ability.usesTargeting()) {
|
if (ability.usesTargeting()) {
|
||||||
// if announce is used as min targets, check what the max possible number would be
|
// if announce is used as min targets, check what the max possible number would be
|
||||||
if (announce.equals(ability.getTargetRestrictions().getMinTargets())) {
|
if (announce.equals(ability.getTargetRestrictions().getMinTargets())) {
|
||||||
max = Math.min(max, CardUtil.getValidCardsToTarget(ability.getTargetRestrictions(), ability).size());
|
max = Math.min(max, CardUtil.getValidCardsToTarget(ability).size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (min > max) {
|
if (min > max) {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class TargetSelection {
|
|||||||
return ability.getTargets().addAll(choices);
|
return ability.getTargets().addAll(choices);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Card> validTargets = CardUtil.getValidCardsToTarget(tgt, ability);
|
List<Card> validTargets = CardUtil.getValidCardsToTarget(ability);
|
||||||
boolean mustTargetFiltered = false;
|
boolean mustTargetFiltered = false;
|
||||||
if (canFilterMustTarget) {
|
if (canFilterMustTarget) {
|
||||||
mustTargetFiltered = StaticAbilityMustTarget.filterMustTargetCards(controller.getPlayer(), validTargets, ability);
|
mustTargetFiltered = StaticAbilityMustTarget.filterMustTargetCards(controller.getPlayer(), validTargets, ability);
|
||||||
|
|||||||
Reference in New Issue
Block a user