mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
Bunch of fixes (#2706)
* Fix Tawnos's Coffin not using ETB counters * Cost fix * Saga tweaks --------- Co-authored-by: tool4EvEr <tool4EvEr@192.168.0.59>
This commit is contained in:
@@ -355,6 +355,31 @@ public class AiController {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (final Trigger tr : card.getTriggers()) {
|
||||
if (!card.hasStartOfKeyword("Saga") && !card.hasStartOfKeyword("Read ahead")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (tr.getMode() != TriggerType.CounterAdded) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SpellAbility exSA = tr.ensureAbility().copy(activator);
|
||||
|
||||
if (api != null && exSA.getApi() == api) {
|
||||
rightapi = true;
|
||||
}
|
||||
|
||||
if (exSA instanceof AbilitySub && !doTrigger(exSA, false)) {
|
||||
// AI would not run this chapter if given the chance
|
||||
// TODO eventually we'll want to consider playing it anyway, especially if Read ahead would still allow an immediate benefit
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (api != null && !rightapi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
// TODO Determine exile from same zone for AI
|
||||
return null;
|
||||
} else {
|
||||
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c, ability);
|
||||
CardCollectionView chosen = ComputerUtil.chooseExileFrom(player, cost, source, c, ability);
|
||||
return null == chosen ? null : PaymentDecision.card(chosen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostExile;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPayment;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
@@ -641,9 +642,14 @@ public class ComputerUtil {
|
||||
return sacList;
|
||||
}
|
||||
|
||||
public static CardCollection chooseExileFrom(final Player ai, final ZoneType zone, final String type, final Card activate,
|
||||
final Card target, final int amount, SpellAbility sa) {
|
||||
CardCollection typeList = CardLists.getValidCards(ai.getCardsIn(zone), type.split(";"), activate.getController(), activate, sa);
|
||||
public static CardCollection chooseExileFrom(final Player ai, CostExile cost, final Card activate, final int amount, SpellAbility sa) {
|
||||
CardCollection typeList;
|
||||
if (cost.zoneRestriction != 1) {
|
||||
typeList = new CardCollection(ai.getGame().getCardsIn(cost.from));
|
||||
} else {
|
||||
typeList = new CardCollection(ai.getCardsIn(cost.from));
|
||||
}
|
||||
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), activate.getController(), activate, sa);
|
||||
|
||||
// don't exile the card we're pumping
|
||||
typeList = ComputerUtilCost.paymentChoicesWithoutTargets(typeList, sa, ai);
|
||||
|
||||
@@ -2410,7 +2410,6 @@ public class ComputerUtilCombat {
|
||||
// (currently looks for the creature with maximum raw power since that's what the AI usually judges by when
|
||||
// deciding whether the creature is worth blocking).
|
||||
// If the creature doesn't change into anything, returns the original creature.
|
||||
if (attacker == null) { return null; }
|
||||
Card attackerAfterTrigs = attacker;
|
||||
|
||||
// Test for some special triggers that can change the creature in combat
|
||||
|
||||
@@ -1412,7 +1412,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
// avoid randomly moving the equipment back and forth between several creatures in one turn
|
||||
if (AiCardMemory.isRememberedCard(aiPlayer, sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN) && !mandatory) {
|
||||
if (AiCardMemory.isRememberedCard(aiPlayer, attachSource, AiCardMemory.MemorySet.ATTACHED_THIS_TURN) && !mandatory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1423,7 +1423,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
}
|
||||
|
||||
AiCardMemory.rememberCard(aiPlayer, sa.getHostCard(), AiCardMemory.MemorySet.ATTACHED_THIS_TURN);
|
||||
AiCardMemory.rememberCard(aiPlayer, attachSource, AiCardMemory.MemorySet.ATTACHED_THIS_TURN);
|
||||
|
||||
if (c == null && mandatory) {
|
||||
CardLists.shuffle(list);
|
||||
@@ -1674,12 +1674,6 @@ public class AttachAi extends SpellAbilityAi {
|
||||
if (c == null) {
|
||||
return false;
|
||||
}
|
||||
if (sa.getHostCard() == null) {
|
||||
// FIXME: Not sure what should the resolution be if a SpellAbility has no host card. This should
|
||||
// not happen normally. Possibly remove this block altogether? (if it's an impossible condition).
|
||||
System.out.println("AttachAi: isUsefulAttachAction unexpectedly called with SpellAbility with no host card. Assuming it's a determined useful action.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// useless to equip a creature that can't attack or block.
|
||||
return !sa.getHostCard().isEquipment() || !ComputerUtilCard.isUselessCreature(ai, c);
|
||||
|
||||
@@ -69,7 +69,6 @@ public class CloneAi extends SpellAbilityAi {
|
||||
bFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!bFlag) { // All of the defined stuff is cloned, not very useful
|
||||
|
||||
@@ -1221,4 +1221,12 @@ public class CountersPutAi extends CountersAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int chooseNumber(Player player, SpellAbility sa, int min, int max, Map<String, Object> params) {
|
||||
if (sa.hasParam("ReadAhead")) {
|
||||
return 1;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user