mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
- AI fix for Tap abilities that target multiple cards.
This commit is contained in:
@@ -3,7 +3,6 @@ ManaCost:U
|
||||
Types:Sorcery
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ U | TargetMin$ 1 | TargetMax$ 2 | TgtPrompt$ Choose target creature without horsemanship | ValidTgts$ Creature.withoutHorsemanship | SpellDescription$ Tap one or two target creatures without horsemanship.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/broken_dam.jpg
|
||||
SetInfo:PTK|Common|http://magiccards.info/scans/en/p3k/37.jpg
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Artifact
|
||||
Text:no text
|
||||
A:AB$ Tap | Cost$ 3 T | ValidTgts$ Creature | TgtPrompt$ Select target creature | ConditionNotAllM12Empires$ True | SubAbility$ DBControl | SpellDescription$ Tap target creature. Gain control of that creature instead if you control artifacts named Scepter of Empires and Throne of Empires.
|
||||
SVar:DBControl:DB$ GainControl | Defined$ Targeted | ConditionAllM12Empires$ True
|
||||
SVar:RemAIDeck:True
|
||||
SVar:RemRandomDeck:True
|
||||
SVar:Rarity:Uncommon
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/crown_of_empires.jpg
|
||||
SetInfo:M12|Uncommon|http://magiccards.info/scans/en/m12/203.jpg
|
||||
|
||||
@@ -4,7 +4,6 @@ Types:Instant
|
||||
Text:no text
|
||||
K:Flashback 1 U
|
||||
A:SP$ Tap | Cost$ 1 W | ValidTgts$ Creature | TgtPrompt$ Select up to two target creatures | TargetMin$ 0 | TargetMax$ 2 | SpellDescription$ Tap up to two target creatures.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/feeling_of_dread.jpg
|
||||
SetInfo:ISD|Common|http://magiccards.info/scans/en/isd/14.jpg
|
||||
|
||||
@@ -4,7 +4,6 @@ Types:Instant
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ 2 U | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Choose target creature | ValidTgts$ Creature | SubAbility$ TrigPump | SpellDescription$ Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
|
||||
SVar:TrigPump:DB$Pump | Cost$ 0 | Defined$ Targeted | KW$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/frost_breath.jpg
|
||||
SetInfo:M12|Common|http://magiccards.info/scans/en/m12/54.jpg
|
||||
|
||||
@@ -4,7 +4,6 @@ Types:Instant
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ 2 W | ValidTgts$ Creature | TgtPrompt$ Select target creature | TargetMin$ 2 | TargetMax$ 2 | SubAbility$ DBUnattach | SpellDescription$ Choose two target creatures. Tap those creatures, then unattach all Equipment from them.
|
||||
SVar:DBUnattach:DB$ UnattachAll | Defined$ Targeted | UnattachValid$ Equipment
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/fulgent_distraction.jpg
|
||||
SetInfo:SOM|Common|http://magiccards.info/scans/en/som/7.jpg
|
||||
Oracle:Choose two target creatures. Tap those creatures, then unattach all Equipment from them.
|
||||
|
||||
@@ -3,7 +3,6 @@ ManaCost:1 W
|
||||
Types:Instant
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ 1 W | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Choose target creature | ValidTgts$ Creature | SpellDescription$ Tap up to two target creatures.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/lead_astray.jpg
|
||||
SetInfo:JUD|Common|http://magiccards.info/scans/en/ju/14.jpg
|
||||
|
||||
@@ -4,7 +4,6 @@ Types:Instant
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ 2 W | TargetMin$ 0 | TargetMax$ 2 | TgtPrompt$ Choose target creature | ValidTgts$ Creature | SpellDescription$ Tap up to two target creatures. | SubAbility$ DBDraw
|
||||
SVar:DBDraw:DB$Draw | NumCards$ 1 | SpellDescription$ Draw a card.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/repel_the_darkness.jpg
|
||||
SetInfo:ROE|Common|http://magiccards.info/scans/en/roe/42.jpg
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Artifact
|
||||
Text:no text
|
||||
A:AB$ DealDamage | Cost$ T | Tgt$ TgtP | NumDmg$ X | References$ X | SpellDescription$ CARDNAME deals 1 damage to target player. It deals 3 damage to that player instead if you control artifacts named Crown of Empires and Throne of Empires.
|
||||
SVar:X:Count$AllM12Empires.3.1
|
||||
SVar:RemAIDeck:True
|
||||
SVar:RemRandomDeck:True
|
||||
SVar:Rarity:Uncommon
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/scepter_of_empires.jpg
|
||||
SetInfo:M12|Uncommon|http://magiccards.info/scans/en/m12/216.jpg
|
||||
|
||||
@@ -3,7 +3,6 @@ ManaCost:3 W
|
||||
Types:Sorcery Arcane
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ 3 W | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Choose target creature | ValidTgts$ Creature | SpellDescription$ Tap up to three target creatures.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/terashis_cry.jpg
|
||||
SetInfo:CHK|Common|http://magiccards.info/scans/en/chk/47.jpg
|
||||
|
||||
@@ -3,7 +3,6 @@ ManaCost:1 U
|
||||
Types:Sorcery
|
||||
Text:no text
|
||||
A:SP$ Tap | Cost$ 1 U | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Choose target creature without flying | ValidTgts$ Creature.withoutFlying | SpellDescription$ Tap up to three target creatures without flying.
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/tidal_surge.jpg
|
||||
SetInfo:PO2|Common|http://magiccards.info/scans/en/po2/56.jpg
|
||||
|
||||
@@ -6,7 +6,6 @@ A:SP$ Tap | Cost$ X G | ValidTgts$ Creature | TgtPrompt$ Select target creature
|
||||
SVar:DBDamage:DB$ DamageAll | NumDmg$ 2 | ValidCards$ Remembered.withFlying | SpellDescription$ CARDNAME deals 2 damage to each of those creatures with flying.
|
||||
SVar:X:Targeted$Amount
|
||||
SVar:MaxTgts:Count$Valid Creature
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Uncommon
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/winter_blast.jpg
|
||||
SetInfo:5ED|Uncommon|http://magiccards.info/scans/en/5e/205.jpg
|
||||
|
||||
@@ -6,7 +6,6 @@ A:SP$ Tap | Cost$ X B B | TargetMin$ 0 | TargetMax$ MaxTgts | References$ X,MaxT
|
||||
# It may seem wrong to not use X in the target, but since the Targets are what defines X, it's redundant (and not supported by the code)
|
||||
SVar:X:Targeted$Amount
|
||||
SVar:MaxTgts:Count$Valid Creature
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Rarity:Common
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/word_of_binding.jpg
|
||||
SetInfo:DRK|Common|http://magiccards.info/scans/en/dk/17.jpg
|
||||
|
||||
@@ -36,9 +36,12 @@ import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.phase.Combat;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.ComputerUtil;
|
||||
import forge.game.player.ComputerUtilBlock;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiUtils;
|
||||
@@ -352,7 +355,6 @@ public class AbilityFactoryPermanentState {
|
||||
* @return a boolean.
|
||||
*/
|
||||
private static boolean untapPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
final Target tgt = sa.getTarget();
|
||||
|
||||
boolean randomReturn = true;
|
||||
@@ -852,8 +854,6 @@ public class AbilityFactoryPermanentState {
|
||||
* @return a boolean.
|
||||
*/
|
||||
private static boolean tapCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
|
||||
final HashMap<String, String> params = af.getMapParams();
|
||||
final Target tgt = sa.getTarget();
|
||||
final Card source = sa.getSourceCard();
|
||||
@@ -867,10 +867,11 @@ public class AbilityFactoryPermanentState {
|
||||
if (turn.isHuman()) {
|
||||
// Tap things down if it's Human's turn
|
||||
} else if (phase.inCombat() && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||
// TODO Tap creatures down if in combat
|
||||
// Tap creatures down if in combat -- handled in tapPrefTargeting().
|
||||
} else if (source.isSorcery()) {
|
||||
// Cast it if it's a sorcery.
|
||||
} else {
|
||||
// Generally don't want to tap things during AI turn outside of
|
||||
// combat
|
||||
// Generally don't want to tap things with an Instant during AI turn outside of combat
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -953,7 +954,6 @@ public class AbilityFactoryPermanentState {
|
||||
* @return a boolean.
|
||||
*/
|
||||
private static boolean tapPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
final Target tgt = sa.getTarget();
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
@@ -999,8 +999,7 @@ public class AbilityFactoryPermanentState {
|
||||
CardList tapList = AllZone.getHumanPlayer().getCardsIn(ZoneType.Battlefield);
|
||||
tapList = tapList.filter(CardListFilter.UNTAPPED);
|
||||
tapList = tapList.getValidCards(tgt.getValidTgts(), source.getController(), source);
|
||||
// filter out enchantments and planeswalkers, their tapped state doesn't
|
||||
// matter.
|
||||
// filter out enchantments and planeswalkers, their tapped state doesn't matter.
|
||||
final String[] tappablePermanents = { "Creature", "Land", "Artifact" };
|
||||
tapList = tapList.getValidCards(tappablePermanents, source.getController(), source);
|
||||
tapList = tapList.getTargetableCards(sa);
|
||||
@@ -1019,17 +1018,21 @@ public class AbilityFactoryPermanentState {
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// TODO is this good enough? for up to amounts?
|
||||
if (!tapCastLessThanMax(source)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tapList.getNotType("Creature").size() == 0) {
|
||||
choice = CardFactoryUtil.getBestCreatureAI(tapList); // if only
|
||||
// creatures
|
||||
// take
|
||||
// the
|
||||
// best
|
||||
PhaseHandler phase = Singletons.getModel().getGameState().getPhaseHandler();
|
||||
if (phase.inCombat() && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) {
|
||||
// Tap creatures if in combat during AI's turn.
|
||||
CardList creatureList = tapList.filter(CardListFilter.CREATURES);
|
||||
choice = CardFactoryUtil.getBestCreatureAI(creatureList);
|
||||
} else if (tapList.getNotType("Creature").size() == 0) {
|
||||
// if only creatures take the best
|
||||
choice = CardFactoryUtil.getBestCreatureAI(tapList);
|
||||
} else {
|
||||
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false);
|
||||
}
|
||||
@@ -1041,7 +1044,9 @@ public class AbilityFactoryPermanentState {
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// TODO is this good enough? for up to amounts?
|
||||
if (!tapCastLessThanMax(source)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1053,6 +1058,31 @@ public class AbilityFactoryPermanentState {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it OK to cast this for less than the Max Targets?
|
||||
* @param source
|
||||
*/
|
||||
private static boolean tapCastLessThanMax(final Card source) {
|
||||
boolean ret = true;
|
||||
if (source.getManaCost().countX() > 0) {
|
||||
// If TargetMax is MaxTgts (i.e., an "X" cost), this is fine because AI is limited by mana available.
|
||||
} else {
|
||||
// Otherwise, if life is possibly in danger, then this is fine.
|
||||
Combat combat = new Combat();
|
||||
combat.initiatePossibleDefenders(AllZone.getComputerPlayer());
|
||||
CardList attackers = AllZoneUtil.getCreaturesInPlay(AllZone.getHumanPlayer());
|
||||
for (Card att : attackers) {
|
||||
combat.addAttacker(att);
|
||||
}
|
||||
combat = ComputerUtilBlock.getBlockers(combat, AllZoneUtil.getCreaturesInPlay(AllZone.getComputerPlayer()));
|
||||
if (!CombatUtil.lifeInDanger(combat)) {
|
||||
// Otherwise, return false. Do not play now.
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* tapUnpreferredTargeting.
|
||||
@@ -1075,8 +1105,7 @@ public class AbilityFactoryPermanentState {
|
||||
list = list.getValidCards(tgt.getValidTgts(), source.getController(), source);
|
||||
list = list.getTargetableCards(sa);
|
||||
|
||||
// filter by enchantments and planeswalkers, their tapped state doesn't
|
||||
// matter.
|
||||
// filter by enchantments and planeswalkers, their tapped state doesn't matter.
|
||||
final String[] tappablePermanents = { "Enchantment", "Planeswalker" };
|
||||
CardList tapList = list.getValidCards(tappablePermanents, source.getController(), source);
|
||||
|
||||
@@ -1139,17 +1168,16 @@ public class AbilityFactoryPermanentState {
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// TODO is this good enough? for up to amounts?
|
||||
if (!tapCastLessThanMax(source)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tapList.getNotType("Creature").size() == 0) {
|
||||
choice = CardFactoryUtil.getBestCreatureAI(tapList); // if only
|
||||
// creatures
|
||||
// take
|
||||
// the
|
||||
// best
|
||||
// if only creatures take the best
|
||||
choice = CardFactoryUtil.getBestCreatureAI(tapList);
|
||||
} else {
|
||||
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false);
|
||||
}
|
||||
@@ -1161,7 +1189,9 @@ public class AbilityFactoryPermanentState {
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// TODO is this good enough? for up to amounts?
|
||||
if (!tapCastLessThanMax(source)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2061,8 +2091,6 @@ public class AbilityFactoryPermanentState {
|
||||
* @return a boolean.
|
||||
*/
|
||||
private static boolean tapOrUntapCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
|
||||
final HashMap<String, String> params = af.getMapParams();
|
||||
final Target tgt = sa.getTarget();
|
||||
final Card source = sa.getSourceCard();
|
||||
@@ -2152,7 +2180,6 @@ public class AbilityFactoryPermanentState {
|
||||
* @return a boolean.
|
||||
*/
|
||||
private static boolean tapOrUntapPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
final Target tgt = sa.getTarget();
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
@@ -2499,7 +2526,6 @@ public class AbilityFactoryPermanentState {
|
||||
* @return a boolean.
|
||||
*/
|
||||
private static boolean phasesPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
|
||||
// AI cannot use this properly until he can use SAs during Humans turn
|
||||
final Target tgt = sa.getTarget();
|
||||
|
||||
boolean randomReturn = true;
|
||||
|
||||
Reference in New Issue
Block a user