It is currently 12 Sep 2025, 09:44
   
Text Size

Programming a card

Post MTG Forge Related Programming Questions Here

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

Re: Programming a card

Postby DennisBergkamp » 05 Dec 2009, 01:12

For the Lobotomist, you probably need two blocks of code, one for the removing of cards (similar to Fable of Wolf and Owl) + adding them to the list, then another block for constantly checking whatever card is banned (similar to Meddling Mage or Gaddock Teeg). But I don't know, the Lobotomist might be trickier...

I'd have to think about how to do Dovescape exactly, but I think you can use sa.isSpell(). So instead of:

Code: Select all
SpellAbility sa = AllZone.Stack.pop();
                  
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
You could do something like :

Code: Select all
SpellAbility sa = AllZone.Stack.peek();

while (!sa.isSpell() || AllZone.Stack.size() == 0 )
{
     sa = AllZone.Stack.pop();
}

if (sa.isSpell())
{
     AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
}
Not sure if it actually works, but give it a shot, it should do something in the right direction :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Programming a card

Postby Triadasoul » 05 Dec 2009, 10:22

It doesn't work for me. I implemented it like this ( it may be not what you meant, cause i don't have full understanding of how it works ):

PS:But when i moved the code to the first palce of playCard(c) list, it doesn't crash the game. And it moved the ability of Dovescape to the card that should be countered in the stack. But when ability resolves it doesn't counter anything.

Code: Select all
   public static void playCard_Dovescape(Card c)
      {
         PlayerZone hplay = AllZone.getZone(Constant.Zone.Play,
               Constant.Player.Human);
         PlayerZone cplay = AllZone.getZone(Constant.Zone.Play,
               Constant.Player.Computer);

         CardList list = new CardList();
         list.addAll(hplay.getCards());
         list.addAll(cplay.getCards());
           int cmc = CardUtil.getConvertedManaCost(c.getManaCost());
         list = list.getName("Dovescape");
        // SpellAbility sa = AllZone.Stack.peek();
         if ( ! c.getType().contains("Creature") && list.size()>0   ) {
      
            
            final Card card = list.get(0);

            Ability ability2 = new Ability(card, "0")
            {
               public void resolve()
               {
                  SpellAbility sa = AllZone.Stack.peek();

                  while (!sa.isSpell() || AllZone.Stack.size() == 0 )
                  {
                       sa = AllZone.Stack.pop();
                  }

                  if (sa.isSpell())
                  {
                       AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
                  }
            
               }
            }; // ability2

            ability2.setStackDescription("Dovescape Ability");
            AllZone.Stack.add(ability2);
      
         for (int j = 0; j < list.size()*cmc; j++)
         {
            Card crd = new Card();
               String controller = c.getController();
            crd.setOwner(controller);
            crd.setController(controller);
            
            crd.setName("Bird");
            crd.setImageName("WU 1 1 Bird");
            crd.setManaCost("WU");
            crd.setToken(true);

            crd.addType("Creature");
            crd.addType("Bird");
            crd.addIntrinsicKeyword("Flying");

            crd.setBaseAttack(1);
            crd.setBaseDefense(1);

            PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller);
            play.add(crd);
         }
         }
      } // Dovescape
It crashes the game with this message:
Code: Select all
Detailed error trace:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
   at java.util.ArrayList.RangeCheck(Unknown Source)
   at java.util.ArrayList.remove(Unknown Source)
   at forge.MagicStack.pop(MagicStack.java:43)
   at forge.GameActionUtil$178.resolve(GameActionUtil.java:855)
   at forge.Input_StackNotEmpty.selectButtonOK(Input_StackNotEmpty.java:39)
   at forge.GuiInput.selectButtonOK(GuiInput.java:32)
   at forge.GuiDisplay3.okButtonActionPerformed(GuiDisplay3.java:1064)
   at forge.GuiDisplay3.access$3(GuiDisplay3.java:1063)
   at forge.GuiDisplay3$25.actionPerformed(GuiDisplay3.java:791)
   at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
   at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
   at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
   at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
   at javax.swing.AbstractButton.doClick(Unknown Source)
   at javax.swing.AbstractButton.doClick(Unknown Source)
   at forge.GuiDisplay3$26.keyPressed(GuiDisplay3.java:810)
   at java.awt.Component.processKeyEvent(Unknown Source)
   at javax.swing.JComponent.processKeyEvent(Unknown Source)
   at java.awt.Component.processEvent(Unknown Source)
   at java.awt.Container.processEvent(Unknown Source)
   at java.awt.Component.dispatchEventImpl(Unknown Source)
   at java.awt.Container.dispatchEventImpl(Unknown Source)
   at java.awt.Component.dispatchEvent(Unknown Source)
   at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
   at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
   at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
   at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
   at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
   at java.awt.Component.dispatchEventImpl(Unknown Source)
   at java.awt.Container.dispatchEventImpl(Unknown Source)
   at java.awt.Window.dispatchEventImpl(Unknown Source)
   at java.awt.Component.dispatchEvent(Unknown Source)
   at java.awt.EventQueue.dispatchEvent(Unknown Source)
   at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.run(Unknown Source)
Last edited by Triadasoul on 05 Dec 2009, 11:24, edited 2 times in total.
Triadasoul
 
Posts: 223
Joined: 21 Jun 2008, 20:17
Has thanked: 0 time
Been thanked: 4 times

Re: Programming a card

Postby Marek14 » 05 Dec 2009, 10:53

BTW, why is it necessary to set mana cost of a token? It's imprecise to say the least (effects checking mana cost, or at least converted mana cost, of permanents are dime a dozen).

Maybe a better solution would be to implement color overriding so you wouldn't be tied by the mana cost. This would also allow for more precise Ghostfire.
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: Programming a card

Postby zerker2000 » 05 Dec 2009, 21:01

The reason is that "CARDNAME is COLOR." was added quite recently, and noone has converted token code to use it yet. I think I did change Ghostfire and Kobolds to use it though.

EDIT: Also, should "Manland P/T: {X}" be a keyword, possibly even accepting keywords like First Strike and Changeling?
Also, something that has been bothering me a while: why isn't it possible to split off CardFactory_Keywords, and make its method parseKeywords(Card c, String[] keywords), which can be called by abilities as well as init (and of course would default to card.addKeyword).
Last edited by zerker2000 on 05 Dec 2009, 21:10, edited 1 time in total.
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: Programming a card

Postby DennisBergkamp » 05 Dec 2009, 21:05

I think Zerker implemented color overriding (using keyword: "{cardName} is {color}"). In the current version, Ghostfire actually IS Colorless, and Kobolds of Kher Keep Red.

Hmm, I'll play around with Dovescape a bit, to see if I can get it working.

EDIT: you beat me to it, zerker :D Yeah, it might be worth converting all tokens to use the keyword instead of manacost.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Programming a card

Postby zerker2000 » 05 Dec 2009, 21:14

Wait, didn't we reroute all tokens through a central makeToken code block recently, i.e. we'd need to change ~2 lines instead of 22? Also, considering idea in above edit: could that not be moved to card.addKeyword altogether, or possibly as addComplicatedKeywords()?
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: Programming a card

Postby Marek14 » 05 Dec 2009, 22:36

zerker2000 wrote:EDIT: Also, should "Manland P/T: {X}" be a keyword, possibly even accepting keywords like First Strike and Changeling?
Don't forget specification of color/creature subtypes.

BTW, thanks to technical details of layers, animated Mutavault actually doesn't have changeling - it just has all creature types. Adding changeling to an object does nothing (since the abilities are added in later layer than changing of subtypes, so it wouldn't apply anymore).
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: Programming a card

Postby zerker2000 » 05 Dec 2009, 23:09

Err, I think it still works in forge :?. So would the keyword be "Becomes P/T color Type Creature with keyword: {X} {Y}"?
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: Programming a card

Postby Marek14 » 06 Dec 2009, 06:28

zerker2000 wrote:Err, I think it still works in forge :?. So would the keyword be "Becomes P/T color Type Creature with keyword: {X} {Y}"?
Probably. And, if you add a similar keyword which will use converted mana cost instead of P/T, it will be usable for things like March of the Machines or Opalescence.

There is one more thing, and that is that there should be a way to do a permanent effect like this - see Stalking Stones or Balduvian Frostwaker.
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: Programming a card

Postby zerker2000 » 06 Dec 2009, 18:29

March of the Machines and Opalescence are static effects, though I think someone is working on keywording those as well. For "Becomes", you have a point: maybe "BecomesTillEOT" as the keyword above, and "Becomes" be permanent.
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: Programming a card

Postby Marek14 » 06 Dec 2009, 21:24

zerker2000 wrote:March of the Machines and Opalescence are static effects, though I think someone is working on keywording those as well. For "Becomes", you have a point: maybe "BecomesTillEOT" as the keyword above, and "Becomes" be permanent.
There are temporary effects that animate something with P/T equal to CMC as well - Karn's Touch, Karn, Silver Golem, Toymaker, and Xenic Poltergeist
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: Programming a card

Postby zerker2000 » 06 Dec 2009, 22:39

Ah yes, I remember Karn being used to blow up moxen and artifact lands.
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: Programming a card

Postby DennisBergkamp » 06 Dec 2009, 22:50

BTW, Triadasoul, what cards did you use to have Dovescape counter abilities?
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Programming a card

Postby Triadasoul » 06 Dec 2009, 23:23

Triadasoul
 
Posts: 223
Joined: 21 Jun 2008, 20:17
Has thanked: 0 time
Been thanked: 4 times

Re: Programming a card

Postby DennisBergkamp » 07 Dec 2009, 04:44

Hm, yeah Dovescape is a tricky fix. I'll keep trying.
Anyway, I did add the token generation block in the actual ability though, what would happen before was the ability would get put on the stack, but at the same time (ability didn't resolve yet) UW birds would be put onto the battlefield.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

PreviousNext

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 34 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 34 users online :: 0 registered, 0 hidden and 34 guests (based on users active over the past 10 minutes)
Most users ever online was 7967 on 09 Sep 2025, 23:08

Users browsing this forum: No registered users and 34 guests

Login Form