- 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.ai.SpellAbilityAi;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser; import forge.card.mana.ManaCostParser;
import forge.card.mana.ManaCostShard;
import forge.game.Game; import forge.game.Game;
import forge.game.mana.ManaCostBeingPaid; import forge.game.mana.ManaCostBeingPaid;
import forge.game.player.Player; import forge.game.player.Player;
@@ -26,11 +27,9 @@ public class ChangeTargetsAi extends SpellAbilityAi {
final Game game = sa.getHostCard().getGame(); final Game game = sa.getHostCard().getGame();
final SpellAbility topSa = game.getStack().isEmpty() ? null : ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa); final SpellAbility topSa = game.getStack().isEmpty() ? null : ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa);
if (sa.hasParam("AILogic")) { if ("Self".equals(sa.getParam("DefinedMagnet"))) {
if ("SpellMagnet".equals(sa.getParam("AILogic"))) {
return doSpellMagnet(sa, topSa, aiPlayer); return doSpellMagnet(sa, topSa, aiPlayer);
} }
}
// The AI can't otherwise play this ability, but should at least not miss mandatory activations (e.g. triggers). // The AI can't otherwise play this ability, but should at least not miss mandatory activations (e.g. triggers).
return sa.isMandatory(); return sa.isMandatory();
@@ -41,11 +40,9 @@ public class ChangeTargetsAi extends SpellAbilityAi {
final Game game = sa.getHostCard().getGame(); final Game game = sa.getHostCard().getGame();
final SpellAbility topSa = game.getStack().isEmpty() ? null : ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa); final SpellAbility topSa = game.getStack().isEmpty() ? null : ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa);
if (sa.hasParam("AILogic")) { if ("Self".equals(sa.getParam("DefinedMagnet"))) {
if ("SpellMagnet".equals(sa.getParam("AILogic"))) {
return doSpellMagnet(sa, topSa, aiPlayer); return doSpellMagnet(sa, topSa, aiPlayer);
} }
}
return true; return true;
} }
@@ -64,8 +61,18 @@ public class ChangeTargetsAi extends SpellAbilityAi {
if (!topSa.usesTargeting() || topSa.getTargets().getTargetCards().contains(sa.getHostCard())) { 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 // 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; 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)) { if (topSa.getHostCard() != null && !topSa.getHostCard().getController().isOpponentOf(aiPlayer)) {
// make sure not to redirect our own abilities // make sure not to redirect our own abilities
return false; return false;
@@ -75,7 +82,8 @@ public class ChangeTargetsAi extends SpellAbilityAi {
return false; 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); int potentialDmg = ComputerUtil.predictDamageFromSpell(topSa, aiPlayer);
boolean canPayBlue = ComputerUtilMana.canPayManaCost(new ManaCostBeingPaid(new ManaCost(new ManaCostParser("U"))), sa, 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)) { if (potentialDmg != -1 && potentialDmg <= 2 && !canPayBlue && topSa.getTargets().getTargets().contains(aiPlayer)) {

View File

@@ -4,6 +4,6 @@ Types:Creature Vedalken Wizard
PT:1/4 PT:1/4
K:Flash 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. 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 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. 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. 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 SVar:TrigChange:AB$ ChangeTargets | Cost$ 0 | TargetType$ Spell | ValidTgts$ Card | DefinedMagnet$ Self | TargetsSingleTarget$ True | TargetValidTargeting$ Creature
K:Madness:2 B K:Madness:2 B
SVar:RemAIDeck:True
SVar:Picture:http://www.wizards.com/global/images/magic/general/muck_drubb.jpg 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.) 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 ManaCost:2
Types:Artifact Creature Horror Types:Artifact Creature Horror
PT:0/4 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 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.) Oracle:{P/U}: Change a target of target spell or ability to Spellskite. ({P/U} can be paid with either {U} or 2 life.)