mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
- Basic AI for Drain Life (will only go for opponent's face for 3+ damage for now, to be improved later). Soul Burn currently doesn't work with this logic due to complex xColorManaPaid which I'm not sure how to set properly for the AI.
This commit is contained in:
@@ -4,32 +4,40 @@ import com.google.common.base.Predicate;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.ai.*;
|
import forge.ai.*;
|
||||||
|
import forge.card.mana.ManaCost;
|
||||||
|
import forge.card.mana.ManaCostParser;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
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.Cost;
|
||||||
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
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;
|
||||||
|
import forge.game.player.PlayerPredicates;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetChoices;
|
import forge.game.spellability.TargetChoices;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class DamageDealAi extends DamageAiBase {
|
public class DamageDealAi extends DamageAiBase {
|
||||||
@Override
|
@Override
|
||||||
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||||
final String damage = sa.getParam("NumDmg");
|
final String damage = sa.getParam("NumDmg");
|
||||||
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
|
int dmg = AbilityUtils.calculateAmount(sa.getHostCard(), damage, sa);
|
||||||
|
final String logic = sa.getParam("AILogic");
|
||||||
|
|
||||||
Card source = sa.getHostCard();
|
Card source = sa.getHostCard();
|
||||||
|
|
||||||
@@ -58,6 +66,11 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
// Set PayX here to maximum value.
|
// Set PayX here to maximum value.
|
||||||
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
|
dmg = ComputerUtilMana.determineLeftoverMana(sa, ai);
|
||||||
source.setSVar("PayX", Integer.toString(dmg));
|
source.setSVar("PayX", Integer.toString(dmg));
|
||||||
|
|
||||||
|
// Life Drain
|
||||||
|
if ("XLifeDrain".equals(logic)) {
|
||||||
|
return doXLifeDrainLogic(ai, sa, dmg);
|
||||||
|
}
|
||||||
} else if (sa.getSVar(damage).equals("Count$CardsInYourHand") && source.getZone().is(ZoneType.Hand)) {
|
} else if (sa.getSVar(damage).equals("Count$CardsInYourHand") && source.getZone().is(ZoneType.Hand)) {
|
||||||
dmg--; // the card will be spent casting the spell, so actual damage is 1 less
|
dmg--; // the card will be spent casting the spell, so actual damage is 1 less
|
||||||
}
|
}
|
||||||
@@ -694,4 +707,26 @@ public class DamageDealAi extends DamageAiBase {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean doXLifeDrainLogic(Player ai, SpellAbility sa, int origDmg) {
|
||||||
|
Card source = sa.getHostCard();
|
||||||
|
int dmg = origDmg - source.getCMC(); // otherwise AI incorrectly calculates mana it can afford
|
||||||
|
|
||||||
|
// detect the top ability that actually targets in Drain Life and Soul Burn scripts
|
||||||
|
SpellAbility saTgt = sa;
|
||||||
|
while (saTgt.getParent() != null) {
|
||||||
|
saTgt = saTgt.getParent();
|
||||||
|
}
|
||||||
|
saTgt.resetTargets();
|
||||||
|
saTgt.getTargets().add(ai.getOpponents().min(PlayerPredicates.compareByLife()));
|
||||||
|
|
||||||
|
// TODO: this currently does not work for Soul Burn because of xColorManaPaid (B/R) which the AI doesn't set
|
||||||
|
if (dmg >= 3) {
|
||||||
|
source.setSVar("PayX", Integer.toString(dmg));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: improve to make it also target creatures
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ ManaCost:X 1 B
|
|||||||
Types:Sorcery
|
Types:Sorcery
|
||||||
A:SP$ StoreSVar | Cost$ X 1 B | XColor$ B | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player | SVar$ Limit | Type$ Targeted | Expression$ CardToughness | SubAbility$ StoreTgtP | ConditionDefined$ Targeted | ConditionPresent$ Card.Creature | ConditionCompare$ GE1 | SpellDescription$ Spend only black mana on X. CARDNAME deals X damage to target creature or player. You gain life equal to the damage dealt, but not more life than the player's life total before CARDNAME dealt damage or the creature's toughness.
|
A:SP$ StoreSVar | Cost$ X 1 B | XColor$ B | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player | SVar$ Limit | Type$ Targeted | Expression$ CardToughness | SubAbility$ StoreTgtP | ConditionDefined$ Targeted | ConditionPresent$ Card.Creature | ConditionCompare$ GE1 | SpellDescription$ Spend only black mana on X. CARDNAME deals X damage to target creature or player. You gain life equal to the damage dealt, but not more life than the player's life total before CARDNAME dealt damage or the creature's toughness.
|
||||||
SVar:StoreTgtP:DB$ StoreSVar | SVar$ Limit | Type$ Count | Expression$ TargetedLifeTotal | SubAbility$ DBDamage | ConditionDefined$ Targeted | ConditionPresent$ Card.Creature | ConditionCompare$ EQ0
|
SVar:StoreTgtP:DB$ StoreSVar | SVar$ Limit | Type$ Count | Expression$ TargetedLifeTotal | SubAbility$ DBDamage | ConditionDefined$ Targeted | ConditionPresent$ Card.Creature | ConditionCompare$ EQ0
|
||||||
SVar:DBDamage:DB$ DealDamage | Defined$ Targeted | NumDmg$ X | SubAbility$ DBGainLife | References$ X
|
SVar:DBDamage:DB$ DealDamage | Defined$ Targeted | NumDmg$ X | SubAbility$ DBGainLife | AILogic$ XLifeDrain | References$ X
|
||||||
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ DrainedLifeCard | References$ DrainedLifeCard
|
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ DrainedLifeCard | References$ DrainedLifeCard
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
SVar:DrainedLifeCard:SVar$X/LimitMax.Limit
|
SVar:DrainedLifeCard:SVar$X/LimitMax.Limit
|
||||||
SVar:Limit:Count$xPaid
|
SVar:Limit:Count$xPaid
|
||||||
SVar:RemAIDeck:True
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/drain_life.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/drain_life.jpg
|
||||||
Oracle:Spend only black mana on X.\nDrain Life deals X damage to target creature or player. You gain life equal to the damage dealt, but not more life than the player's life total before Drain Life dealt damage or the creature's toughness.
|
Oracle:Spend only black mana on X.\nDrain Life deals X damage to target creature or player. You gain life equal to the damage dealt, but not more life than the player's life total before Drain Life dealt damage or the creature's toughness.
|
||||||
|
|||||||
Reference in New Issue
Block a user