Page 1 of 2

Added some cards

PostPosted: 05 Mar 2010, 06:35
by BinarySpike
Hello, I am new to the forum and I just recently learned how to compile Forge and add some of my own cards in the Java code.

First, I am having trouble understanding all the data types (aka classes) but I was able to piece together cards from other ones to make working cards. I mainly added these cards to simulate a token deck I am building, it works nicely whenever Beastmaster ascension works (It doesn't work half the time ](*,) so I have to visualize an army of +11/+11 insect creatures and +12/+12 wolves) Here is the list:

Howl of the Night Pack
Beacon of Creation
Khalni Heart Expedition
Echoing Courage
Harrow (halfway working)

Khalni and Harrow I just copied Kodama's Reach and switched some code around.
Howl of the Night Pack was easy, and then Beacon of Creation was a copy except I added "shuffle back into deck" effect from another Beacon card. Echoing Courage has a brother that does the opposite.

Second, I noticed a couple bugs in the downloadable source code (from google code). Mainly Bushido can be multi-proc'd for infinite creature size. Useful in quest mode ^_^ And Beastmaster Ascension doesn't seem to work when the opponent blocks. If someone could find a better way to program the Beastmasters ability I would also add Coat of Arms (because it works under a similar principle)

Finally, I can provide source for those cards upon request, and if anyone has any mono-green token card suggestions that need programming I could take a kick at it.

Thoughts?

Re: Added some cards

PostPosted: 05 Mar 2010, 06:55
by DennisBergkamp
Welcome to the forums, BinarySpike!
We could always use the help.... I didn't know Beastmaster Ascension only works half the time, I'll look into it (by the way, is it the counter adding, or the pump ability that's not working correctly?)

I can guess what happens with the Bushido bug... does it by any chance happen when using abilities during the step that's right after the Declare Attackers step?
Same will probably hold for exalted...

As for the cards you coded (thanks!), I could either give you committer privileges on the SVN (and you could just submit your code directly), or you could paste your code in this thread and I would just add it manually. First way is probably easier (just pm me your email address), but I don't mind adding the code myself either.

As for mono green cards suggestions... check out this thread: viewtopic.php?f=26&t=2091&start=0

Re: Added some cards

PostPosted: 05 Mar 2010, 17:25
by DennisBergkamp
I've tested Beastmaster Ascension a bunch of times... I didn't see it fail once. Are you aware that it's supposed to only give +5/+5 once (and not +5/+5 for each 7 Quest counters) ?

Re: Added some cards

PostPosted: 05 Mar 2010, 20:23
by BinarySpike
For the Bushido bug, it's when you declare it as a blocker. "To Block, click your Opponents attacker first, then your blocker(s)"

Once you select the creature with bushido a Bushido effect goes on the stack, you hit Okay to resolve it, and then you can select that same devoted retainer to block again, the effect goes on the stack, and you can block again, and again, and again.

Beastmaster ascension sometimes doesn't pump, it's wonky because if I have 2 or 3 out, sometimes it works and sometimes it doesn't. I retested in a fresh download of Forge and it works perfectly (squirrel nest/earthcraft combo) so I am stumped, maybe I can debug in Eclipse.

As for the SVN commit, please no, my code is extremely sloppy, I directly copied Kodama's Reach to Khalni Heart Expedition and Harrow, and I had no idea what serialVersionUID was so I just made it up. Here are my first three:

Howl of the Night Pack
6 G
Sorcery
Put a 2/2 green Wolf creature token onto the battlefield for each Forest you control.
howl_of_the_night_pack.jpg http://gatherer.wizards.com/Handlers/Im ... &type=card
Code: Select all
//*************** START *********** START **************************
            else if (cardName.equals("Howl of the Night Pack"))
            {
               SpellAbility spell = new Spell(card)
                {
                private static final long serialVersionUID = 0000000000000000001L;

                public void resolve()
                  {
                   PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
                    CardList land = new CardList(play.getCards());
                    land = land.getType("Forest");
                    makeToken();
                      for(int i = 1; i < land.size(); i++)
                           makeToken();
                  }//resolve()
                
                public void makeToken()
                {
                   CardFactoryUtil.makeToken("Wolf", "G 2 2 Wolf", card, "G", new String[]{"Creature", "Wolf"}, 2, 2, new String[] {""});
                }
                };
                card.clearSpellAbility();
                card.addSpellAbility(spell);
             }//*************** END ************ END **************************
Beacon of Creation
3 G
Sorcery
Put a 1/1 green Insect creature token onto the battlefield for each Forest you control. Shuffle Beacon of Creation into its owner's library.
beacon_of_creation.jpg http://gatherer.wizards.com/Handlers/Im ... &type=card
Code: Select all
//*************** START *********** START **************************
            else if (cardName.equals("Beacon of Creation"))
            {
               SpellAbility spell = new Spell(card)
                {
                private static final long serialVersionUID = 0000000000000000002L;

                public void resolve()
                  {
                   PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
                    CardList land = new CardList(play.getCards());
                    land = land.getType("Forest");
                    makeToken();
                      for(int i = 1; i < land.size(); i++)
                           makeToken();
                  
                    // shuffle back into library
                  PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController());
                  library.add(card);
                  AllZone.GameAction.shuffle(card.getController());
                  
                  }//resolve()
                
                public void makeToken()
                {
                   CardFactoryUtil.makeToken("Insect", "G 1 1 Insect", card, "G", new String[]{"Creature", "Insect"}, 1, 1, new String[] {""});
                }
                };
                card.clearSpellAbility();
                card.addSpellAbility(spell);
             }//*************** END ************ END **************************
Echoing Courage
1 G
Instant
Target creature and all other creatures with the same name as that creature get +2/-+2 until end of turn.
echoing_courage.jpg http://gatherer.wizards.com/Handlers/Im ... &type=card
Code: Select all
//*************** START *********** START **************************
    else if(cardName.equals("Echoing Courage"))
    {
      final SpellAbility spell = new Spell(card)
      {
      private static final long serialVersionUID = 3154935854257358023L;

      public boolean canPlayAI()
        {
          CardList c = getCreature();
          if(c.isEmpty())
            return false;
          else
          {
            setTargetCard(c.get(0));
            return true;
          }
        }//canPlayAI()
        CardList getCreature()
        {
          CardList out = new CardList();
          CardList list = CardFactoryUtil.AI_getHumanCreature("Flying", card, true);
          list.shuffle();

          for(int i = 0; i < list.size(); i++)
            if((list.get(i).getNetAttack() >= 2) && (list.get(i).getNetDefense() <= 2))
              out.add(list.get(i));

          //in case human player only has a few creatures in play, target anything
          if(out.isEmpty() &&
              0 < CardFactoryUtil.AI_getHumanCreature(2, card, true).size() &&
             3 > CardFactoryUtil.AI_getHumanCreature(card, true).size())
          {
            out.addAll(CardFactoryUtil.AI_getHumanCreature(2, card, true).toArray());
            CardListUtil.sortFlying(out);
          }
          return out;
        }//getCreature()


        public void resolve()
        {
          if(AllZone.GameAction.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(card, getTargetCard()) )
          {
            final Card c = getTargetCard();
           
            c.addTempAttackBoost(2);
             c.addTempDefenseBoost(2);

             AllZone.EndOfTurn.addUntil(new Command()
             {
            private static final long serialVersionUID = 1327455269456577020L;

            public void execute()
                {
                   c.addTempAttackBoost(-2);
                   c.addTempDefenseBoost(-2);
                }
             });

            //get all creatures
            CardList list = new CardList();
            list.addAll(AllZone.Human_Play.getCards());
            list.addAll(AllZone.Computer_Play.getCards());

            list = list.getName(getTargetCard().getName());
            list.remove(getTargetCard());
             
            if (!getTargetCard().isFaceDown())
               for(int i = 0; i < list.size(); i++)
               {
                  final Card crd = list.get(i);
                  
                  crd.addTempAttackBoost(2);
                  crd.addTempDefenseBoost(2);
                  
                  AllZone.EndOfTurn.addUntil(new Command()
                    {
                  private static final long serialVersionUID = 5151337777143949221L;

                  public void execute()
                       {
                          crd.addTempAttackBoost(-2);
                          crd.addTempDefenseBoost(-2);
                       }
                    });
                  //list.get(i).addDamage(2);
               }
                
          }//in play?
        }//resolve()
      };//SpellAbility
      card.clearSpellAbility();
      card.addSpellAbility(spell);

      spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
    }//*************** END ************ END **************************

Re: Added some cards

PostPosted: 05 Mar 2010, 21:24
by BinarySpike
As with the beastmaster ascension, the execute() command for it seems stop being called. I noticed some things though. First, I can play a second Beastmaster and it will cause the other to proc, and my Squirrel's get +5/+5. Second, if I have 7 squirrels attack right after I put the card down, it procs.

Using deduction I found that this is the process that it should envolve:
Declare Attackers: Select creature..
Declare Attackers: Play Instants and Abilities...
Declare Blockers: Play Instants and Abilities...
(from freshly downloaded forge)

HOWEVER, the Declare Attackers: Play Instants and Abilities is not being used in the source version I downloaded a couple days ago and edited. This is the step that the +5/+5's are getting applied. Maybe something I added changed functionality, when I have time later today or tomorrow morning I will do a fresh source and maybe SVN and try compiling those. (eclipse is a pain)

Re: Added some cards

PostPosted: 05 Mar 2010, 21:49
by DennisBergkamp
Alright cool! I'll just add these in myself, thanks for coding them!
I wouldn't worry about sloppy code though, most of forge's code is very very sloppy :mrgreen: The Serial version ID stuff is something you can have Eclipse do automatically (check out how in this thread: viewtopic.php?f=52&t=1801 )

About Beastmaster Ascension: yes, I did change quite a bit of the combat code (and added that new phase), so it might be that it was bugged a few versions ago but fixed in this latest version.

I'll try to fix the Bushido blocking thing.

Re: Added some cards

PostPosted: 06 Mar 2010, 14:11
by jim
I'm in a similar situation to BinarySpike. I've been coding a few cards in a local copy of Forge and wondering if they were worth submitting or not. Since this is my first attempt at Java code and I don't understand all the classes, the answer is probably not, but I'm happy to take pointers on how to improve. I'd be especially interested to know if I could have done this with one of the new keywords somehow.

Assuming BinarySpike doesn't mind me chiming in on his thread, here's my attempt at Wall of Reverence. I based the code on Eldrazi Monument. I've tested it as the human player but I haven't seen the AI use it yet.

Code: Select all
   public static void endOfTurn_Wall_Of_Reverence()
   {
      final String player = AllZone.Phase.getActivePlayer();
      final PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player);
      CardList list = new CardList(playZone.getCards());
      list = list.getName("Wall of Reverence");
      
      Ability ability;
      for (int i = 0; i < list.size(); i++)
      {
         final Card card = list.get(i);
         ability = new Ability(list.get(i), "0")
         {
            public void resolve()
            {
               CardList creats = new CardList(playZone.getCards());
               CardList validTargets = new CardList();
               creats = creats.getType("Creature");
               for (int i = 0; i < creats.size(); i++) {
                  if (CardFactoryUtil.canTarget(card, creats.get(i))) {
                     validTargets.add(creats.get(i));
                  }
               }
               if (validTargets.size() == 0)
                  return;
               
               if (player.equals(Constant.Player.Human))
               {
                  Object o = AllZone.Display.getChoiceOptional("Select creature for Wall of Reverence life gain", validTargets.toArray());
                  if (o != null) {
                     Card c = (Card) o;
                     int power=c.getNetAttack();
                     PlayerLife life = AllZone.GameAction.getPlayerLife(player);
                     life.addLife(power);
                  }
               }
               else//computer
               {
                  CardListUtil.sortAttack(validTargets);
                  Card c = creats.get(0);
                  if (c != null) {
                     int power = c.getNetAttack();
                     PlayerLife life = AllZone.GameAction.getPlayerLife(player);
                     life.addLife(power);
                  }
               }
            } // resolve
         }; // ability
         ability.setStackDescription("Wall of Reverence - "
               + player + " gains life equal to target creature's power.");
         AllZone.Stack.add(ability);
      }
            
   }

I added an explicit call to this routine in EndOfTurn.java in the executeAt() routine, right after the code for Pestilence:
GameActionUtil.endOfTurn_Wall_Of_Reverence();
and here's the standard stuff for cards.txt:
Wall of Reverence
3 W
Creature Spirit Wall
At the beginning of your end step, you may gain life equal to the power of target creature you control.
1/6
Defender
Flying
wall_of_reverence.jpg http://www.wizards.com/global/images/ma ... erence.jpg

Re: Added some cards

PostPosted: 06 Mar 2010, 20:32
by DennisBergkamp
Jim,

I think Wall of Reverence is good (looking through the code, I probably would've coded it exactly the same), there's unfortunately no way currently to code it through keywords.
Thanks for adding it! I will merge it into my local version.

Re: Added some cards

PostPosted: 06 Mar 2010, 21:49
by jim
Dennis,

Thanks very much for looking it over: it's good to know I didn't miss anything obvious. I greatly appreciate you adding it to your local version, and I'll be happy not to have to re-integrate it when the next beta comes out.

I was curious -- is there a way to test cards out other than playing them? Not that I mind playing games of Magic, but coding a card and then waiting for it to come up in the game seems kind of hit and miss. :) Is there some other way to test, especially for the AI?

Re: Added some cards

PostPosted: 06 Mar 2010, 22:14
by zerker2000
Well, there aren't any restrictions on deck size, nor many of the keywords, so I suppose if you add
Code: Select all
Mana Tap
0
Artifact
NOTE:This is not a real card :)
T: add WWUUBBRRGG
Untap:0
to your cards.txt and make a deck along the lines of:
Code: Select all
--TEST-nightpack
[general]
constructed
[main]
1 Mana Tap
1 Howl of the Night Pack
1 Fastbond
2 Forest
1 Dryad Arbor
1 Breeding Pool
[sideboard]
Namely, 7 cards, of which 1 is the "Mana Tap" and the rest are the cards whose interaction you're testing. Then, turn of millloss, and you're good to go.

Re: Added some cards

PostPosted: 06 Mar 2010, 22:16
by Chris H.
jim wrote:I was curious -- is there a way to test cards out other than playing them? Not that I mind playing games of Magic, but coding a card and then waiting for it to come up in the game seems kind of hit and miss. :) Is there some other way to test, especially for the AI?
`
We tend to create small < 60 cards decks with just enough cards to run the test. Mox can be used as mana sources as they go into play quickly. Currently I am working on modifying the VanillaEquipment keyword. Here is the test deck that I am using: :)


You can also design a very small deck for the computer to use. As I was modifying some existing code so that we could have the Windstorm spell, I designed these two decks for testing:


and ...


Re: Added some cards

PostPosted: 06 Mar 2010, 22:49
by jim
Thanks guys,

This makes perfect sense, once I get past the mindset of testing with 60-card decks. Thanks!

Re: Added some cards

PostPosted: 07 Mar 2010, 00:38
by Chris H.
jim wrote:Thanks guys,

This makes perfect sense, once I get past the mindset of testing with 60-card decks. Thanks!
`
Oh, and make sure that you uncheck the check boxes for:

Stack AI Land
Milling = Loss Condition


:wink:

Re: Added some cards

PostPosted: 07 Mar 2010, 02:06
by zerker2000
Actually, I think Stack AI Land has error catching, so in the case there isn't enough land it merely shuffles; milling oneself is the real problem for such decks.

Re: Added some cards

PostPosted: 07 Mar 2010, 02:13
by Chris H.
zerker2000 wrote:Actually, I think Stack AI Land has error catching, so in the case there isn't enough land it merely shuffles; milling oneself is the real problem for such decks.
`
I just ran a test deck by the computer and it only had creatures. The computer loaded the deck with no problems.

Dennis must have made a change to the code. In the old days before the stack AI land check box was implemented, things were different. I remember times when the game would not go past the New Game window ... unless the computer had at least 7 basic lands in it's deck. :)