- Some crash prevention in ChangeTargetsAi, the AI needs further improvement here if we're to teach it to retarget spells with multiple targets.

- Generalized ChangeTargetsAi not to mention Spellskite by name (so other creatures can gain its ability and be correctly used by the AI) and also not to use AI Logic and detect the ability via DefinedMagnet instead.
- Marking Muck Drubb as AI playable.
This commit is contained in:
Agetian
2017-01-22 05:56:30 +00:00
parent 13793ecf6f
commit 2c39506879
4 changed files with 20 additions and 13 deletions

View File

@@ -6,6 +6,7 @@ import forge.ai.ComputerUtilMana;
import forge.ai.SpellAbilityAi;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser;
import forge.card.mana.ManaCostShard;
import forge.game.Game;
import forge.game.mana.ManaCostBeingPaid;
import forge.game.player.Player;
@@ -26,10 +27,8 @@ public class ChangeTargetsAi extends SpellAbilityAi {
final Game game = sa.getHostCard().getGame();
final SpellAbility topSa = game.getStack().isEmpty() ? null : ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa);
if (sa.hasParam("AILogic")) {
if ("SpellMagnet".equals(sa.getParam("AILogic"))) {
return doSpellMagnet(sa, topSa, aiPlayer);
}
if ("Self".equals(sa.getParam("DefinedMagnet"))) {
return doSpellMagnet(sa, topSa, aiPlayer);
}
// The AI can't otherwise play this ability, but should at least not miss mandatory activations (e.g. triggers).
@@ -41,10 +40,8 @@ public class ChangeTargetsAi extends SpellAbilityAi {
final Game game = sa.getHostCard().getGame();
final SpellAbility topSa = game.getStack().isEmpty() ? null : ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa);
if (sa.hasParam("AILogic")) {
if ("SpellMagnet".equals(sa.getParam("AILogic"))) {
return doSpellMagnet(sa, topSa, aiPlayer);
}
if ("Self".equals(sa.getParam("DefinedMagnet"))) {
return doSpellMagnet(sa, topSa, aiPlayer);
}
return true;
@@ -64,8 +61,18 @@ public class ChangeTargetsAi extends SpellAbilityAi {
if (!topSa.usesTargeting() || topSa.getTargets().getTargetCards().contains(sa.getHostCard())) {
// if this does not target at all or already targets host, no need to redirect it again
// TODO: currently the AI does not know how to change several targets to the same object (e.g.
// Cone Flame) and will stupidly keep retargeting the first available target unless stopped here.
// Needs investigation and improvement.
return false;
}
if (topSa.getTargets().getNumTargeted() > 1 && topSa.hasParam("DividedAsYouChoose")) {
// TODO: currently the AI will crash the game if it tries to change the target of a SA with a
// divided allocation map. May need improvement.
return false;
}
if (topSa.getHostCard() != null && !topSa.getHostCard().getController().isOpponentOf(aiPlayer)) {
// make sure not to redirect our own abilities
return false;
@@ -74,8 +81,9 @@ public class ChangeTargetsAi extends SpellAbilityAi {
// don't try targeting it if we can't legally target the host card with it in the first place
return false;
}
if ("Spellskite".equals(sa.getHostCard().getName())) {
if (sa.getPayCosts().getCostMana() != null && "{P/U}".equals(sa.getPayCosts().getCostMana().getMana().getShortString())) {
// e.g. Spellskite or a creature receiving its ability that requires Phyrexian mana P/U
int potentialDmg = ComputerUtil.predictDamageFromSpell(topSa, aiPlayer);
boolean canPayBlue = ComputerUtilMana.canPayManaCost(new ManaCostBeingPaid(new ManaCost(new ManaCostParser("U"))), sa, aiPlayer);
if (potentialDmg != -1 && potentialDmg <= 2 && !canPayBlue && topSa.getTargets().getTargets().contains(aiPlayer)) {

View File

@@ -4,6 +4,6 @@ Types:Creature Vedalken Wizard
PT:1/4
K:Flash
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may change a target of target spell or ability to CARDNAME.
SVar:TrigChange:AB$ ChangeTargets | Cost$ 0 | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card | DefinedMagnet$ Self | ChangeSingleTarget$ True | AILogic$ SpellMagnet
SVar:TrigChange:AB$ ChangeTargets | Cost$ 0 | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card | DefinedMagnet$ Self | ChangeSingleTarget$ True
SVar:Picture:http://www.wizards.com/global/images/magic/general/mizzium_meddler.jpg
Oracle:Flash (You may cast this spell any time you could cast an instant.)\nWhen Mizzium Meddler enters the battlefield, you may change a target of target spell or ability to Mizzium Meddler.

View File

@@ -6,6 +6,5 @@ K:Flash
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | TriggerDescription$ When CARDNAME enters the battlefield, change the target of target spell that targets only a single creature to Muck Drubb.
SVar:TrigChange:AB$ ChangeTargets | Cost$ 0 | TargetType$ Spell | ValidTgts$ Card | DefinedMagnet$ Self | TargetsSingleTarget$ True | TargetValidTargeting$ Creature
K:Madness:2 B
SVar:RemAIDeck:True
SVar:Picture:http://www.wizards.com/global/images/magic/general/muck_drubb.jpg
Oracle:Flash (You may cast this spell any time you could cast an instant.)\nWhen Muck Drubb enters the battlefield, change the target of target spell that targets only a single creature to Muck Drubb.\nMadness {2}{B} (If you discard this card, you may cast it for its madness cost instead of putting it into your graveyard.)

View File

@@ -2,6 +2,6 @@ Name:Spellskite
ManaCost:2
Types:Artifact Creature Horror
PT:0/4
A:AB$ ChangeTargets | Cost$ PU | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card | DefinedMagnet$ Self | ChangeSingleTarget$ True | AILogic$ SpellMagnet | SpellDescription$ Change a target of target spell or ability to CARDNAME.
A:AB$ ChangeTargets | Cost$ PU | TargetType$ Spell,Activated,Triggered | ValidTgts$ Card | DefinedMagnet$ Self | ChangeSingleTarget$ True | SpellDescription$ Change a target of target spell or ability to CARDNAME.
SVar:Picture:http://www.wizards.com/global/images/magic/general/spellskite.jpg
Oracle:{P/U}: Change a target of target spell or ability to Spellskite. ({P/U} can be paid with either {U} or 2 life.)