It is currently 03 Sep 2025, 13:03
   
Text Size

spRaiseDead

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

spRaiseDead

Postby 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.
Last edited by Chris H. on 03 Nov 2009, 17:13, edited 1 time in total.
User avatar
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

Postby 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 :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: spReturnGraveyardHandCreature

Postby Marek14 » 16 Oct 2009, 06:07

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 :)
Maybe AI could cast it to return one creature when in some definable pinch, like when an opponent could kill it with next attack...
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: spRaiseDead

Postby 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.
Last edited by Chris H. on 03 Nov 2009, 17:14, edited 1 time in total.
User avatar
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

Postby 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
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: spRaiseDead

Postby 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. 8)
Last edited by Chris H. on 03 Nov 2009, 17:15, edited 1 time in total.
User avatar
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

Postby 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
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: spRaiseDead

Postby 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. :wink:

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.
User avatar
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

Postby zerker2000 » 18 Oct 2009, 21:21

Chris H. wrote:
zerker2000 wrote:You are welcome. Why are we discussing this keyword in two threads anyways?
`
You ask a mighty good question. :wink:

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.
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?
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
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: spRaiseDead

Postby 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.
User avatar
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

Postby 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
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: spRaiseDead

Postby 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.
Last edited by Chris H. on 03 Nov 2009, 17:17, edited 1 time in total.
User avatar
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

Postby zerker2000 » 19 Oct 2009, 01:43

Chris H. wrote:Thank you, that looks interesting. It is very close to what I have
That does make a lot of sense: we each copied the code for Raise Dead and changed a few lines :).
Your way is likely more rules compliant than mine.
Anything reasonably rules compliant would have targeting take place as a BeforePayMana input, not as part of the code :?
you 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.
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 :).
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
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: spRaiseDead

Postby 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. :D I think that I was getting ahead of myself. Once the return creature keyword is finished, it should be possible to change the code and it will then become:

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.
User avatar
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

Postby 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. #-o

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. :wink:

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.
User avatar
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

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 41 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 41 users online :: 0 registered, 0 hidden and 41 guests (based on users active over the past 10 minutes)
Most users ever online was 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 41 guests

Login Form