mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
- Some logic update for Krav. Somewhat better handling of CostSacrifice inside DrawAi.
This commit is contained in:
@@ -514,14 +514,18 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
|||||||
Integer c = cost.convertAmount();
|
Integer c = cost.convertAmount();
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
if (ability.getSVar(cost.getAmount()).equals("XChoice")) {
|
if (ability.getSVar(cost.getAmount()).equals("XChoice")) {
|
||||||
if ("SacToReduceCost".equals(ability.getParam("AILogic"))) {
|
String logic = ability.getParamOrDefault("AILogic", "");
|
||||||
|
if ("SacToReduceCost".equals(logic)) {
|
||||||
// e.g. Torgaar, Famine Incarnate
|
// e.g. Torgaar, Famine Incarnate
|
||||||
// TODO: currently returns an empty list, so the AI doesn't sacrifice anything. Trying to make
|
// TODO: currently returns an empty list, so the AI doesn't sacrifice anything. Trying to make
|
||||||
// the AI decide on creatures to sac makes the AI sacrifice them, but the cost is not reduced and the
|
// the AI decide on creatures to sac makes the AI sacrifice them, but the cost is not reduced and the
|
||||||
// AI pays the full mana cost anyway (despite sacrificing creatures).
|
// AI pays the full mana cost anyway (despite sacrificing creatures).
|
||||||
return PaymentDecision.card(new CardCollection());
|
return PaymentDecision.card(new CardCollection());
|
||||||
} else if ("AsChosen".equals(ability.getParam("AILogic"))) {
|
} else if (!logic.isEmpty() && !logic.equals("Never")) {
|
||||||
// Honor the ChosenX value set earlier by the AI ability processing code.
|
// If at least some other AI logic is specified, assume that the AI for that API knows how
|
||||||
|
// to define ChosenX and thus honor that value.
|
||||||
|
// Cards which have no special logic for this yet but which do work in a simple/suboptimal way
|
||||||
|
// are currently conventionally flagged with AILogic$ DoSacrifice.
|
||||||
c = AbilityUtils.calculateAmount(source, source.getSVar("ChosenX"), null);
|
c = AbilityUtils.calculateAmount(source, source.getSVar("ChosenX"), null);
|
||||||
} else {
|
} else {
|
||||||
// Other cards are assumed to be flagged RemAIDeck for now
|
// Other cards are assumed to be flagged RemAIDeck for now
|
||||||
|
|||||||
@@ -26,10 +26,7 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.*;
|
||||||
import forge.game.cost.CostDiscard;
|
|
||||||
import forge.game.cost.CostPart;
|
|
||||||
import forge.game.cost.PaymentDecision;
|
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -252,22 +249,32 @@ public class DrawAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (num != null && num.equals("ChosenX")) {
|
if (num != null && num.equals("ChosenX")) {
|
||||||
// Necrologia, Pay X Life : Draw X Cards
|
|
||||||
if (sa.getSVar("X").equals("XChoice")) {
|
if (sa.getSVar("X").equals("XChoice")) {
|
||||||
// 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);
|
||||||
// But no more than what's "safe" and doesn't risk a near death experience
|
|
||||||
// Maybe would be better to check for "serious danger" and take more risk?
|
if (sa.getPayCosts() != null) {
|
||||||
while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) {
|
if (sa.getPayCosts().hasSpecificCostType(CostPayLife.class)) {
|
||||||
numCards--;
|
// [Necrologia, Pay X Life : Draw X Cards]
|
||||||
|
// 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?
|
||||||
|
while ((ComputerUtil.aiLifeInDanger(ai, false, numCards) && (numCards > 0))) {
|
||||||
|
numCards--;
|
||||||
|
}
|
||||||
|
} else if (sa.getPayCosts().hasSpecificCostType(CostSacrifice.class)) {
|
||||||
|
// [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
|
||||||
|
|
||||||
|
// Skip this ability if nothing is to be chosen for sacrifice
|
||||||
|
if (numCards <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sa.setSVar("ChosenX", Integer.toString(numCards));
|
sa.setSVar("ChosenX", Integer.toString(numCards));
|
||||||
source.setSVar("ChosenX", Integer.toString(numCards));
|
source.setSVar("ChosenX", Integer.toString(numCards));
|
||||||
|
|
||||||
// If the logic is set to AsChosen, then skip the ability if nothing is to be chosen
|
|
||||||
if ("AsChosen".equals(sa.getParam("AILogic")) && numCards <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Logic for cards that require special handling
|
// Logic for cards that require special handling
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ ManaCost:4 B
|
|||||||
Types:Legendary Creature Demon
|
Types:Legendary Creature Demon
|
||||||
PT:3/3
|
PT:3/3
|
||||||
K:Partner:Regna, the Redeemer:Regna
|
K:Partner:Regna, the Redeemer:Regna
|
||||||
A:AB$Draw | Cost$ B Sac<X/Creature/creatures> | NumCards$ ChosenX | ValidTgts$ Player | TgtPrompt$ Choose a player | References$ X | SubAbility$ DBGainLife | AILogic$ AsChosen | SpellDescription$ Target player draws X cards and gains X life. Put X +1/+1 counters on CARDNAME.
|
# TODO: AILogic$ DoSacrifice is a placeholder which signals AiCostDecision that the API knows how to properly determine
|
||||||
|
# the number of creatures to sacrifice. Currently DrawAi doesn't handle it too optimally and this can be improved.
|
||||||
|
A:AB$Draw | Cost$ B Sac<X/Creature/creatures> | NumCards$ ChosenX | ValidTgts$ Player | TgtPrompt$ Choose a player | References$ X | SubAbility$ DBGainLife | AILogic$ DoSacrifice | SpellDescription$ Target player draws X cards and gains X life. Put X +1/+1 counters on CARDNAME.
|
||||||
SVar:DBGainLife:DB$GainLife | Defined$ Targeted | LifeAmount$ ChosenX | SubAbility$ DBPutCounter
|
SVar:DBGainLife:DB$GainLife | Defined$ Targeted | LifeAmount$ ChosenX | SubAbility$ DBPutCounter
|
||||||
SVar:DBPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ ChosenX
|
SVar:DBPutCounter:DB$PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ ChosenX
|
||||||
SVar:X:XChoice
|
SVar:X:XChoice
|
||||||
|
|||||||
Reference in New Issue
Block a user