mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- Better logic for Desecration Demon: only sac creatures to it if in critical condition to lose to it and have no active flying/reach blockers that are useful.
This commit is contained in:
@@ -668,7 +668,7 @@ public class ComputerUtil {
|
|||||||
return returnList;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CardCollection choosePermanentsToSacrifice(final Player ai, final CardCollectionView cardlist, final int amount, SpellAbility source,
|
public static CardCollection choosePermanentsToSacrifice(final Player ai, final CardCollectionView cardlist, final int amount, final SpellAbility source,
|
||||||
final boolean destroy, final boolean isOptional) {
|
final boolean destroy, final boolean isOptional) {
|
||||||
CardCollection remaining = new CardCollection(cardlist);
|
CardCollection remaining = new CardCollection(cardlist);
|
||||||
final CardCollection sacrificed = new CardCollection();
|
final CardCollection sacrificed = new CardCollection();
|
||||||
@@ -680,6 +680,10 @@ public class ComputerUtil {
|
|||||||
if(!source.getActivatingPlayer().isOpponentOf(ai)) {
|
if(!source.getActivatingPlayer().isOpponentOf(ai)) {
|
||||||
return sacrificed; // sacrifice none
|
return sacrificed; // sacrifice none
|
||||||
}
|
}
|
||||||
|
} else if ("DesecrationDemon".equals(source.getParam("AILogic"))) {
|
||||||
|
if (!SpecialCardAi.DesecrationDemon.considerSacrificingCreature(ai, source)) {
|
||||||
|
return sacrificed; // don't sacrifice unless in special conditions specified by DesecrationDemon AI
|
||||||
|
}
|
||||||
} else if (isOptional && source.getActivatingPlayer().isOpponentOf(ai)) {
|
} else if (isOptional && source.getActivatingPlayer().isOpponentOf(ai)) {
|
||||||
if ("Pillar Tombs of Aku".equals(host.getName())) {
|
if ("Pillar Tombs of Aku".equals(host.getName())) {
|
||||||
if (!ai.canLoseLife() || ai.cantLose()) {
|
if (!ai.canLoseLife() || ai.cantLose()) {
|
||||||
@@ -715,7 +719,15 @@ public class ComputerUtil {
|
|||||||
remaining = CardLists.filter(remaining, new Predicate<Card>() {
|
remaining = CardLists.filter(remaining, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
if (c.hasSVar("SacMe") || ComputerUtilCard.evaluateCreature(c) < (considerSacThreshold != -1 ? considerSacThreshold : 190)) {
|
int sacThreshold = 190;
|
||||||
|
|
||||||
|
if ("DesecrationDemon".equals(source.getParam("AILogic"))) {
|
||||||
|
sacThreshold = SpecialCardAi.DesecrationDemon.getSacThreshold();
|
||||||
|
} else if (considerSacLogic) {
|
||||||
|
sacThreshold = considerSacThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.hasSVar("SacMe") || ComputerUtilCard.evaluateCreature(c) < sacThreshold) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package forge.ai;
|
package forge.ai;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
@@ -107,6 +108,32 @@ public class SpecialCardAi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Desecration Demon
|
||||||
|
public static class DesecrationDemon {
|
||||||
|
private static final int demonSacThreshold = Integer.MAX_VALUE; // if we're in dire conditions, sac everything from worst to best hoping to find an answer
|
||||||
|
|
||||||
|
public static boolean considerSacrificingCreature(Player ai, SpellAbility sa) {
|
||||||
|
CardCollection flyingCreatures = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), Predicates.and(CardPredicates.Presets.UNTAPPED, Predicates.or(CardPredicates.hasKeyword("Flying"), CardPredicates.hasKeyword("Reach"))));
|
||||||
|
boolean hasUsefulBlocker = false;
|
||||||
|
|
||||||
|
for (Card c : flyingCreatures) {
|
||||||
|
if (!ComputerUtilCard.isUselessCreature(ai, c)) {
|
||||||
|
hasUsefulBlocker = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ai.getLife() <= sa.getHostCard().getNetPower() && !hasUsefulBlocker) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getSacThreshold() {
|
||||||
|
return demonSacThreshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Donate
|
// Donate
|
||||||
public static class Donate {
|
public static class Donate {
|
||||||
public static boolean considerTargetingOpponent(Player ai, SpellAbility sa) {
|
public static boolean considerTargetingOpponent(Player ai, SpellAbility sa) {
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ Types:Creature Demon
|
|||||||
PT:6/6
|
PT:6/6
|
||||||
K:Flying
|
K:Flying
|
||||||
T:Mode$ Phase | Phase$ BeginCombat | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ At the beginning of each combat, any opponent may sacrifice a creature. If a player does, tap CARDNAME and put a +1/+1 counter on it.
|
T:Mode$ Phase | Phase$ BeginCombat | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ At the beginning of each combat, any opponent may sacrifice a creature. If a player does, tap CARDNAME and put a +1/+1 counter on it.
|
||||||
SVar:TrigSac:AB$ Sacrifice | Cost$ 0 | Defined$ Opponent | Amount$ 1 | SacValid$ Creature | RememberSacrificed$ True | Optional$ True | AILogic$ ConsiderSac | SubAbility$ DBSacSelf
|
SVar:TrigSac:AB$ Sacrifice | Cost$ 0 | Defined$ Opponent | Amount$ 1 | SacValid$ Creature | RememberSacrificed$ True | Optional$ True | AILogic$ DesecrationDemon | SubAbility$ DBSacSelf
|
||||||
SVar:DBSacSelf:DB$ Tap | Cost$ 0 | Defined$ Self | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X | SubAbility$ DBPutCounter
|
SVar:DBSacSelf:DB$ Tap | Cost$ 0 | Defined$ Self | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X | SubAbility$ DBPutCounter
|
||||||
SVar:DBPutCounter:DB$ PutCounter | Cost$ 0 | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X | SubAbility$ DBCleanup
|
SVar:DBPutCounter:DB$ PutCounter | Cost$ 0 | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | References$ X | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:X:Remembered$Amount
|
SVar:X:Remembered$Amount
|
||||||
SVar:AIPreferenceParams:CreatureEvalThreshold$ 150
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/desecration_demon.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/desecration_demon.jpg
|
||||||
Oracle:Flying\nAt the beginning of each combat, any opponent may sacrifice a creature. If a player does, tap Desecration Demon and put a +1/+1 counter on it.
|
Oracle:Flying\nAt the beginning of each combat, any opponent may sacrifice a creature. If a player does, tap Desecration Demon and put a +1/+1 counter on it.
|
||||||
|
|||||||
Reference in New Issue
Block a user