Thursday, July 5, 2007

Programming Shock

Many cards and abilities are similar to Shock. In case you can’t remember, Shock deals 2 damage to target creature or player. First, Shock has to be added to the cards.txt file. Cards.txt holds all of the text that the card displays as well as the mana cost.

Shock
R
Instant
Shock deals 2 damage to target creature or player.

The resolve method checks to see if the card is still in play, something that we take for granted in a real-life game. SpellAbility only allows for 1 target to be set, either a card or a player by the setTargetPlayer(String player) and setTargetCard(Card) methods. To get the target you call either getTargetPlayer or getTargetCard. The SpellAbiliy method setBeforePayMana(Input), lets the user actually choose the target card or player. CardFactoryUtil has a bunch of reusable Input classes that gets a user choice. If the spell just targeted a creature you would use CardFactoryUtil.input_targetCreature.

SpellAbility canPlayAI method returns false if you do not want the computer to play this spell. A very simple AI for Shock is below. canPlayAI is called first, and if it returns true, then chooseTargetAI is called. chooseTargetAI sets the target for the spell by either calling setTargetCard(Card) or setTargetPlayer(String player). Some cards like Wrath of God do not have a chooseTargetAI method, because no targets are needed.

This checks to see that the human player (you) have at least 1 creature in play and sets that creature as the target. A more sophisticated AI would try to get the best creature that Shock could kill, like a 2/2 flyer. The AI could also see if you had low life, and could alternately target you instead of a creature. The regular AI for Shock tries to kill a creature with flying or you if your life is low.


//simple AI for Shock
//should be put in a SpellAbility object
public boolean canPlayAI()
{
CardList list = CardFactoryUtil.AI_getHumanCreature();
return 0 < list.size();
}
public void chooseTargetAI()
{
CardList list = CardFactoryUtil.AI_getHumanCreature();
setTargetCard(list.get(0));
}

//Complete card
final Card card = new Card();
card.setName(“Shock”);
card.setManaCost("R");
card.setOwner(Constant.Player.Human);
card.setController(Constant.Player.Human);

final SpellAbility spell = new Spell(card)
{
int damage = 2;

public boolean canPlayAI() {return false;}

public void resolve()
{
if(getTargetCard() != null)
{
if(AllZone.GameAction.isCardInPlay(getTargetCard()))
{
Card c = getTargetCard();
c.addDamage(damage);
}
}
else
AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(damage);
}//resolve()
};//SpellAbility
card.addSpellAbility(spell);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell));

//Shock as it would be in CardFactory
if(cardName.equals("Shock"))
{
final SpellAbility spell = new Spell(card)
{
//same stuff
};//SpellAbility

//this is cleared because a card is presumed to be a permanent
//all Sorceries and Instants have to call card.clearSpellAbility()
card.clearSpellAbility();
card.addSpellAbility(spell);

spell.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(spell));
}

3 comments:

Randell said...

Hello, I just recently started a blog along the same lines, well basically dedicated to Magic the Gathering. It's kinda ironic but I am also a programmer, I am new to wordpress but have had a website since earlier this year. I was searching for blogs about Magic the Gathering to add to my blogroll and I came across this. Anywho, I have marked your site so I can add you to my blogroll as to my surprise I have not seen many blogs on MTG. I would appreciate it if you could check out my website, its MTG Players and provide any feedback. You can also be one of the first to check out my blog endeaver which just replaced my old site less than a week ago By the way since I am new to wordpress, I would appreciate any tips you could offer and feel free to add my blog to your blog-role if you like.
Thanks

clacker said...

The "Programming Shock" post was really useful to me. I was fighting the Input class and trying to get it work correctly for a simple case, but if CardFactoryUtil can provide an easier way to do it then I'll use that instead. It was also good to see the use of canPlayAI() and chooseTargetAI().

Forge said...

Hi randell your website looks good.

To clacker, I'm glad this was useful. I should be covering Giant Growth and triggered abilities on creatures soon. Have fun programming. :)

Input can be very confusing. Most of the basic Input's are in CardFactoryUtil like targetting a creature or player. You can look over the code for Sunlace for an input that cannot target a non-white creature.

Maybe I should go over Input more closely.