Think Fast: Allowing the AI to Respond to the Stack
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Agetian, friarsol, Blacksmith, KrazyTheFox, CCGHQ Admins
5 posts
• Page 1 of 1
Think Fast: Allowing the AI to Respond to the Stack
by lord of 13 » 04 Dec 2010, 17:21
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();
}
><><><><><><><
Currently developing Mindgames, for playing a rules-enforced game of MtG.
RECENT PROJECTS
->XMLScript
->Zwiel Platformer
Currently developing Mindgames, for playing a rules-enforced game of MtG.
RECENT PROJECTS
->XMLScript
->Zwiel Platformer
-

lord of 13 - DEVELOPER
- Posts: 79
- Joined: 06 Jan 2010, 01:36
- Has thanked: 0 time
- Been thanked: 0 time
Re: Think Fast: Allowing the AI to Respond to the Stack
by Rob Cashwalker » 04 Dec 2010, 18:12
The theory we're going with, is that the Ability object will have additional AI methods specific to each sort of point where the AI would want to check if it should play that ability.
So Giant Growth (AbilityFactory_Pump) would have implement two new methods - chkAI_DeclareAttack() and chkAI_DeclareBlock(). (theoretically, the original canPlayAI would be deprecated) Those methods would be called during the appropriate steps to evaluate the situation.
Other abilities would get chkAI_Upkeep or something, which would be checked in those appropriate steps.
Finally, adding a chkAI_SpellOnStack method would enable responding to spells on the stack. Most abilities may want to have this method and it may be very tricky... Giant Growth in response to damage or -1/-1 effects; Regeneration in response to destroy effects; counterspell in response to just about anything...
So Giant Growth (AbilityFactory_Pump) would have implement two new methods - chkAI_DeclareAttack() and chkAI_DeclareBlock(). (theoretically, the original canPlayAI would be deprecated) Those methods would be called during the appropriate steps to evaluate the situation.
Other abilities would get chkAI_Upkeep or something, which would be checked in those appropriate steps.
Finally, adding a chkAI_SpellOnStack method would enable responding to spells on the stack. Most abilities may want to have this method and it may be very tricky... Giant Growth in response to damage or -1/-1 effects; Regeneration in response to destroy effects; counterspell in response to just about anything...
The Force will be with you, Always.
-

Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Think Fast: Allowing the AI to Respond to the Stack
by lord of 13 » 04 Dec 2010, 18:33
Hmm... alright.
So I should discard my current changes to that method and move on to the Boolean Qualifiers? Do you have plans for that?
So I should discard my current changes to that method and move on to the Boolean Qualifiers? Do you have plans for that?
><><><><><><><
Currently developing Mindgames, for playing a rules-enforced game of MtG.
RECENT PROJECTS
->XMLScript
->Zwiel Platformer
Currently developing Mindgames, for playing a rules-enforced game of MtG.
RECENT PROJECTS
->XMLScript
->Zwiel Platformer
-

lord of 13 - DEVELOPER
- Posts: 79
- Joined: 06 Jan 2010, 01:36
- Has thanked: 0 time
- Been thanked: 0 time
Re: Think Fast: Allowing the AI to Respond to the Stack
by friarsol » 04 Dec 2010, 21:08
This functionality already exists in spell ability restrictions.
Take a look in there and there's a bunch of cards already using it but I'm not at my computer to give examples. Also look into lunge for how that card works in newer functionality
Take a look in there and there's a bunch of cards already using it but I'm not at my computer to give examples. Also look into lunge for how that card works in newer functionality
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Think Fast: Allowing the AI to Respond to the Stack
by friarsol » 05 Dec 2010, 04:52
Ok here's more of an explanation about SA_Restrictions, since I was on my phone before:
They are automatically attached to AbilityFactory Architecture. They can handle many similar things to what you are referring to. We have a bunch of things already doing just that.
Example Vedalken Certarch for MetalCraft using IsPresent and PresentCompare:
With the AbilityFactory system, I was going to attach the parsed AF to the SpellAbility to solve your question of "How do I know what a spell on the stack does?" this may not get us all of the cards, but it should give us a large majority. I just need to finish getting SubAbilities done before I can get that going.
I'm not sure if having separate functions for each Phase is really necessary for the AI. We could just use the current functions and return false for any phase that the spell wouldn't be cast in.
In Rob's example he talks about AF_Pump. So in Declare Attackers you would use Pump abilities that gave Evasion (either so your creature can block a different creature, or avoid other creatures). In Declare Blockers, you would protect your creatures from dying or kill opposing creatures (or deliver a death blow to the player). Before a Combat phase you might give a creature Haste. The only other case is responding to a non-Empty Stack. This situation is only for protecting your guy to a damage/pump curse.
They are automatically attached to AbilityFactory Architecture. They can handle many similar things to what you are referring to. We have a bunch of things already doing just that.
Example Vedalken Certarch for MetalCraft using IsPresent and PresentCompare:
- Code: Select all
A:AB$Tap | Cost$ T | ValidTgts$ Artifact,Creature,Land | TgtPrompt$ Select target artifact, creature or land. | IsPresent$ Artifact | PresentCompare$ GE3 | PrecostDesc$ Metalcraft - | SpellDescription$ Tap target artifact, creature or land.
With the AbilityFactory system, I was going to attach the parsed AF to the SpellAbility to solve your question of "How do I know what a spell on the stack does?" this may not get us all of the cards, but it should give us a large majority. I just need to finish getting SubAbilities done before I can get that going.
I'm not sure if having separate functions for each Phase is really necessary for the AI. We could just use the current functions and return false for any phase that the spell wouldn't be cast in.
In Rob's example he talks about AF_Pump. So in Declare Attackers you would use Pump abilities that gave Evasion (either so your creature can block a different creature, or avoid other creatures). In Declare Blockers, you would protect your creatures from dying or kill opposing creatures (or deliver a death blow to the player). Before a Combat phase you might give a creature Haste. The only other case is responding to a non-Empty Stack. This situation is only for protecting your guy to a damage/pump curse.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
5 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 23 guests