spRaiseDead
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
58 posts
• Page 1 of 4 • 1, 2, 3, 4
spRaiseDead
by Chris H. » 15 Oct 2009, 21:40
Originally, I had planned to combine the code from Regrowth and Raise Dead for a new keyword. Add in additional coding and we would be able to include a few more spells. After a few weeks I decided to scale this down to just a Raise Dead type keyword.
At this time the keyword looks like this:
spReturnGraveyardHandCreature:{num}/{Quantifier}
After setting this up to handle the four Raise Dead spells I placed the code within a while loop. This allows for Death's Duet to be added. Death's Duet is set up to require a minimum of two creatures in your graveyard and you have to return two creatures. I believe that this is rules compliant.
I am now in the process of modifying the code to use "getChoiceOptional" to prepare for Urborg Uprising which states "Return up to two target creature cards from your graveyard to your hand."
I assume that you can cast this card and return 0, 1 or 2 creatures. Is this interpretation of the rules correct? I assume that I should restrict the AI to casting this only if there is two or more creatures in the computer's graveyard.
At this time the keyword looks like this:
spReturnGraveyardHandCreature:{num}/{Quantifier}
After setting this up to handle the four Raise Dead spells I placed the code within a while loop. This allows for Death's Duet to be added. Death's Duet is set up to require a minimum of two creatures in your graveyard and you have to return two creatures. I believe that this is rules compliant.
I am now in the process of modifying the code to use "getChoiceOptional" to prepare for Urborg Uprising which states "Return up to two target creature cards from your graveyard to your hand."
I assume that you can cast this card and return 0, 1 or 2 creatures. Is this interpretation of the rules correct? I assume that I should restrict the AI to casting this only if there is two or more creatures in the computer's graveyard.
Last edited by Chris H. on 03 Nov 2009, 17:13, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spReturnGraveyardHandCreature
by DennisBergkamp » 15 Oct 2009, 21:50
Sure, that should work. I did something similar with devour, which might be a good place to check.
EDIT: and yes, rules-wise, that's correct. I also would put the same check in canPlayAI() and only allow the computer to cast it when there are two or more creatures in his graveyard.
CardFactoryUtil.AI_getBestCreature(list) should be helpful to find the best creatures
EDIT: and yes, rules-wise, that's correct. I also would put the same check in canPlayAI() and only allow the computer to cast it when there are two or more creatures in his graveyard.
CardFactoryUtil.AI_getBestCreature(list) should be helpful to find the best creatures

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: spReturnGraveyardHandCreature
by Marek14 » 16 Oct 2009, 06:07
Maybe AI could cast it to return one creature when in some definable pinch, like when an opponent could kill it with next attack...DennisBergkamp wrote:Sure, that should work. I did something similar with devour, which might be a good place to check.
EDIT: and yes, rules-wise, that's correct. I also would put the same check in canPlayAI() and only allow the computer to cast it when there are two or more creatures in his graveyard.
CardFactoryUtil.AI_getBestCreature(list) should be helpful to find the best creatures
Re: spRaiseDead
by Chris H. » 18 Oct 2009, 16:31
I am having a problem with parsing the fields for this keyword:
spReturnGraveyardHandCreature:{num}/{?}/{?}/{?}/{?}:{?}:{?}
I can parse the intrinsic keyword and the number fields OK. These two will be the only fields that are mandatory. The fields that are represented by the "{?}" will not be mandatory.
I can do a "String k[] = parse.split(":")" and the array k[] may have 2 or 4 cells.
I can do a "String kk[] = k[1].split("/")" and the array kk[] may have 1 through 5 cells.
Is there a way to determine how many cells are in these two arrays? I want to be careful and not get an error when referring to a cell number that is greater than the number of cells in the array.
spReturnGraveyardHandCreature:{num}/{?}/{?}/{?}/{?}:{?}:{?}
I can parse the intrinsic keyword and the number fields OK. These two will be the only fields that are mandatory. The fields that are represented by the "{?}" will not be mandatory.
I can do a "String k[] = parse.split(":")" and the array k[] may have 2 or 4 cells.
I can do a "String kk[] = k[1].split("/")" and the array kk[] may have 1 through 5 cells.
Is there a way to determine how many cells are in these two arrays? I want to be careful and not get an error when referring to a cell number that is greater than the number of cells in the array.
Last edited by Chris H. on 03 Nov 2009, 17:14, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spReturnGraveyardHandCreature
by zerker2000 » 18 Oct 2009, 17:53
An array's length is a public final variable, array.length. Therefore, if you are trying not to get into an arrayIndexOutOfBounds exception from kk[i], you should check that i < kk.length.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: spRaiseDead
by Chris H. » 18 Oct 2009, 18:05
`zerker2000 wrote:An array's length is a public final variable, array.length. Therefore, if you are trying not to get into an arrayIndexOutOfBounds exception from kk[i], you should check that i < kk.length.
Thank you Zeerker. I will try this command out and I think that it should help me finish this keyword.

Last edited by Chris H. on 03 Nov 2009, 17:15, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spReturnGraveyardHandCreature
by zerker2000 » 18 Oct 2009, 18:16
You are welcome. Why are we discussing this keyword in two threads anyways?
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: spRaiseDead
by Chris H. » 18 Oct 2009, 19:59
`zerker2000 wrote:You are welcome. Why are we discussing this keyword in two threads anyways?
You ask a mighty good question.

I will try to keep the thread here from now on. I am now working your suggestion into my spReturnGraveyardHandCreature keyword. So far, so good.
`I think he is saying that flashback is easy to add in once you have the keyword. As for the keyword, have you looked at e.g. Tradewind Rider code? I think its "tap two creatures" code could be modified to target a creature in the graveyard instead, and the "field to hand" code be modified to return from graveyard instead.
My spReturnGraveyardHandCreature keyword code uses the code from Raise Dead and the other 3 similar spells. After wrapping the spell ability I modified it and it currently can also use Death's Duet. With your help I am now adding in the code to allow Urborg Uprising.
It looks like I may be able to add in two additional spells later this week.
I think that Morgue Theft will have to be a stand alone card and will not be able to use my spReturnGraveyardHandCreature keyword.
Last edited by Chris H. on 03 Nov 2009, 17:16, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spReturnGraveyardHandCreature
by zerker2000 » 18 Oct 2009, 21:21
Oh, we already have Raise Dead? Then wouldn't you just have the code use an ArrayList<Card> instead of a Card for targeting, put a for(numCards) loop around the fetch and resolve code, and use ".add" instead of "=" to set targets?Chris H. wrote:`zerker2000 wrote:You are welcome. Why are we discussing this keyword in two threads anyways?
You ask a mighty good question.![]()
I will try to keep the thread here from now on. I am now working your suggestion into my spReturnGraveyardHandCreature keyword. So far, so good.`I think he is saying that flashback is easy to add in once you have the keyword. As for the keyword, have you looked at e.g. Tradewind Rider code? I think its "tap two creatures" code could be modified to target a creature in the graveyard instead, and the "field to hand" code be modified to return from graveyard instead.
My spReturnGraveyardHandCreature keyword code uses the code from Raise Dead and the other 3 similar spells. After wrapping the spell ability I modified it and it currently can also use Death's Duet. With your help I am now adding in the code to allow Urborg Uprising.
It looks like I may be able to add in two additional spells later this week.
I think that Morgue Theft will have to be a stand alone card and will not be able to use my spReturnGraveyardHandCreature keyword.
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: spRaiseDead
by Chris H. » 18 Oct 2009, 21:40
`zerker2000 wrote:Oh, we already have Raise Dead? Then wouldn't you just have the code use an ArrayList<Card> instead of a Card for targeting, put a for(numCards) loop around the fetch and resolve code, and use ".add" instead of "=" to set targets?
Give me a few days to clean up the code and to finish adding this one card that I have been working on for the last week. I will then post what I have even though it will still be a work in progress. We can then discuss your ideas.
Last edited by Chris H. on 03 Nov 2009, 17:17, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spReturnGraveyardHandCreature
by zerker2000 » 18 Oct 2009, 22:33
I'm just stating the way I'd do it:
- Code: Select all
{
final int numCreatures=intgere.parseInt(Keyword.split(":")[1]);//usage:spReturnGraveyardHandCreature:X
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI() {return getGraveCreatures().size() >= numCreatures;}
CardList targets;
public void chooseTargetAI()
{
CardList grave = getGraveCreatures();
targets = new CardList();
for(int i=0; i<numCreatures; i++)
{
Card c = CardFactoryUtil.AI_getBestCreature(grave);
targets.add(c);
grave.remove(c);
}
}
public void resolve()
{
if(card.getController().equals(Constant.Player.Human))
{
CardList grave = getGraveCreatures();
targets = new CardList();
if(grave.size() > numCreatures)
for(int i=0; i<numCreatures ; i++)
{
Card c = AllZone.Display.getChoice("Select card", grave.toArray());
targets.add(c);
grave.remove(c);
}
else target = grave;
}
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
for(Card c : targets)
if(AllZone.GameAction.isCardInZone(c, grave))
AllZone.GameAction.moveTo(hand, c);
}//resolve()
public boolean canPlay()
{
return getGraveCreatures().size() >= numCreatures;
}
CardList getGraveCreatures()
{
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
CardList list = new CardList(grave.getCards());
list = list.getType("Creature");
return list;
}
};//SpellAbility
card.addSpellAbility(spell);
}
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: spRaiseDead
by Chris H. » 18 Oct 2009, 23:18
Thank you, that looks interesting. It is very close to what I have, except you are putting multiple target creatures chosen into an array. Your way is likely more rules compliant than mine.
I placed the Raise Dead code into a loop and then loop through this for each of the creatures. Choose a creature and put it into play and then repeat this process for additional creatures.
I placed the Raise Dead code into a loop and then loop through this for each of the creatures. Choose a creature and put it into play and then repeat this process for additional creatures.
Last edited by Chris H. on 03 Nov 2009, 17:17, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spReturnGraveyardHandCreature
by zerker2000 » 19 Oct 2009, 01:43
That does make a lot of sense: we each copied the code for Raise Dead and changed a few linesChris H. wrote:Thank you, that looks interesting. It is very close to what I have

Anything reasonably rules compliant would have targeting take place as a BeforePayMana input, not as part of the codeYour way is likely more rules compliant than mine.

This would make interface less confusing, though I do at list remove the creatures already selected from the list... also, I do hope that by "put it into play" you mean return it to its owner's handyou are putting multiple target creatures chosen into an array. ... I placed the Raise Dead code into a loop and then loop through this for each of the creatures. Choose a creature and put it into play and then repeat this process for additional creatures.

O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.
--Eladamri, the Seed of Freyalise
- zerker2000
- Programmer
- Posts: 569
- Joined: 09 May 2009, 21:40
- Location: South Pasadena, CA
- Has thanked: 0 time
- Been thanked: 0 time
Re: spRaiseDead
by Chris H. » 19 Oct 2009, 09:47
`zerker2000 wrote:This would make interface less confusing, though I do at list remove the creatures already selected from the list... also, I do hope that by "put it into play" you mean return it to its owner's hand.
Once again, thank you.
And yes, I misspoke.

spReturnGraveyardHand{Other}
and once that is finished, a few more modifications could change the keyword to:
spReturnGraveyard{Play}Creature
Last edited by Chris H. on 03 Nov 2009, 17:17, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: spRaiseDead
by Chris H. » 20 Oct 2009, 00:51
I have merged Zeerker's code into the keyword and I have it working. We now have:
Death's Duet
Disentomb
Raise Dead
Recover
Return to Battle
Urborg Uprising
Urborg Uprising was somewhat difficult to add but it is now working. The human can return from 0 to 2 creatures while the computer is limited to returning 2 creatures.
I would like to add Boggart Birth Rite but I would need a separate way of filtering a list of Goblin type creatures. I may try to figure this out, but I have not yet found anything that looks promising in CardFactoryUtil.
I looked through the source code in the hope that I could add in Disturbed Burial. Buyback cards look like they have to be hard coded and can not be "tacked-on" via a keyword field.
I have had mixed success adding Morgue Theft via a "tacked-on" keyword field. When Morgue Theft is Flashback-ed it will return a creature form the graveyard. If there are no creatures in the graveyard, Morgue Theft can still be Flashback-ed.
When the human uses the Flashback with no creatures in his graveyard the spell will just fall through the method with out an error. When the computer uses the Flashback with no creatures we get an out of bounds exception and I get to see the error window that Silly Freak added.
And it looks like Call to the Netherworld and Reaping the Graves will be far to complicated to even try to add via this keyword.
Death's Duet
Disentomb
Raise Dead
Recover
Return to Battle
Urborg Uprising
Urborg Uprising was somewhat difficult to add but it is now working. The human can return from 0 to 2 creatures while the computer is limited to returning 2 creatures.
I would like to add Boggart Birth Rite but I would need a separate way of filtering a list of Goblin type creatures. I may try to figure this out, but I have not yet found anything that looks promising in CardFactoryUtil.
I looked through the source code in the hope that I could add in Disturbed Burial. Buyback cards look like they have to be hard coded and can not be "tacked-on" via a keyword field.
I have had mixed success adding Morgue Theft via a "tacked-on" keyword field. When Morgue Theft is Flashback-ed it will return a creature form the graveyard. If there are no creatures in the graveyard, Morgue Theft can still be Flashback-ed.

When the human uses the Flashback with no creatures in his graveyard the spell will just fall through the method with out an error. When the computer uses the Flashback with no creatures we get an out of bounds exception and I get to see the error window that Silly Freak added.

And it looks like Call to the Netherworld and Reaping the Graves will be far to complicated to even try to add via this keyword.
Last edited by Chris H. on 03 Nov 2009, 17:18, edited 1 time in total.
-
Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
58 posts
• Page 1 of 4 • 1, 2, 3, 4
Who is online
Users browsing this forum: No registered users and 41 guests