Think Fast: Allowing the AI to Respond to the Stack
So... this weekend was fairly quiet so I decided to try editing Forge's code again. I downloaded the latest SVN and Eclipse/Subclipse and starting coding.
I have two goals for this weekend:
1. Develop a primitive architecture to allow the AI to respond to spells/abilities on the stack successfully
2. Extend the scripting interface to support BooleanEnablers
a. Essentially, mechanics that are dependent on some sort of boolean conditional -> Think Metalcraft, Threshold, and the Zendikar Vampires mechanic as well as Landfall. Possibly can be extended to Kinship and "If you control another [cardType], [doStuff]" effects.
b. Syntax in the card files would be [Mox Opal]:
c. Compounding them would also be supported - simply use boolean operators and evaluate at runtime
I have a question: how do you query a card to find out if it is a counterspell? getSpellAbilities()... and then what? Or if it has protection? Or should I merely search the card's text to see if it contains the word "Counter"?
My modifications are inside ComputerAI_General.java in the method stackResponse
The code I've written so far immediately precedes the final line of the method - AllZone.Phase.passPriority();
I have two goals for this weekend:
1. Develop a primitive architecture to allow the AI to respond to spells/abilities on the stack successfully
2. Extend the scripting interface to support BooleanEnablers
a. Essentially, mechanics that are dependent on some sort of boolean conditional -> Think Metalcraft, Threshold, and the Zendikar Vampires mechanic as well as Landfall. Possibly can be extended to Kinship and "If you control another [cardType], [doStuff]" effects.
b. Syntax in the card files would be [Mox Opal]:
- Code: Select all
K[Metalcraft]: tap: Add W
K[Metalcraft]: tap: Add U
K[Metalcraft]: tap: Add B
K[Metalcraft]: tap: Add R
K[Metalcraft]: tap: Add G
c. Compounding them would also be supported - simply use boolean operators and evaluate at runtime
- Code: Select all
K[Metalcraft && Threshold]: tap: Add W
K[Metalcraft || Threshold]: tap: Add 1
//Searing Blaze
K[!Landfall]: spDamageTgtC:1:Drawback$DamageTgt/1:CARDNAME deals 1 damage to target creature and 1 damage to that creature's controller.
K[Landfall]: spDamageTgtC:3:Drawback$DamageTgt/3:CARDNAME deals 3 damage to target creature and 3 damage to that creature's controller.
I have a question: how do you query a card to find out if it is a counterspell? getSpellAbilities()... and then what? Or if it has protection? Or should I merely search the card's text to see if it contains the word "Counter"?
My modifications are inside ComputerAI_General.java in the method stackResponse
The code I've written so far immediately precedes the final line of the method - AllZone.Phase.passPriority();
- Code: Select all
//LordOf13: Following code can and should be encapsulated into its own method... later
//LordOf13: Essentially, find out if the spell is helpful to the human
// or hurtful to the AI.
// It's assumed that targeting the appropriate player makes it helpful/hurtful.
//
// Then, identify if whose cards it targets - is it helpful
// or hurtful to permanents? Similar assumptions as above.
// For reference, the computer being targeted is more important than its cards
// being targeted
Target targeted = sa.getTarget();
ArrayList<Player> targetPlayer = targeted.getTargetPlayers();
Card[] targetCard = new Card[targeted.getTargetCards().size()];
targeted.getTargetCards().toArray(targetCard);
boolean hurtful = targetPlayer.contains(AllZone.ComputerPlayer),
helpful = targetPlayer.contains(AllZone.HumanPlayer);
boolean creatureHurt = false, creatureHelp = false;
for (int i = 0; i < targetCard.length; i++)
{
PlayerZone zone = AllZone.getZone(targetCard[i]);
if (zone == null)//it's in a mysterious unrecognized zone
continue;
if (zone.getPlayer() == AllZone.ComputerPlayer)
creatureHelp = true;
if (zone.getPlayer() == AllZone.HumanPlayer)
creatureHurt = true;
}
//disregard abilities for now and only consider cards in hand
ArrayList<Card> castable = new ArrayList<Card>();
Card[] hand = AllZone.Computer_Hand.getCards();
for (int i = 0; i < hand.length; i++)
{
//TO DO: Check if you can generate enough mana to cast it
if (hand[i].isInstant() || hand[i].hasKeyword("Flash"))
castable.add(hand[i]);
}
//now... see which cards are useful
Iterator<Card> castableIter = castable.iterator();
Card card;
while (castableIter.hasNext())
{
card = castableIter.next();
}