Page 3 of 4

Re: Code from slapshot5

PostPosted: 13 Apr 2010, 19:55
by Chris H.
Rob Cashwalker wrote:Also, this sort of ability is very common, and you should be able to turn the code into a keyword.
`
Shhh ... I am now in the process of converting a small portion of his code into a keyword. :mrgreen:

The enPump keyword was more work than I had at first expected and now I need something a wee bit easier and it might as well serve as an inside joke among us developers.

So I will now pre-anounce the Ironclaw Orcs keyword or

CARDNAME can't block creatures with power (pertinent data)

:D :lol:

Re: Code from slapshot5

PostPosted: 13 Apr 2010, 20:55
by DennisBergkamp
We should probably also convert : "This card doesn't untap during your untap step." to "CARDNAME doesn't untap during your untap step.", and "This creature cannot block" to "CARDNAME cannot block".

EDIT: And "This card attacks each turn if able."

Re: Code from slapshot5

PostPosted: 13 Apr 2010, 22:15
by slapshot5
Chris H. wrote:Shhh ... I am now in the process of converting a small portion of his code into a keyword.
Cool. Thanks Chris.

Re: Code from slapshot5

PostPosted: 13 Apr 2010, 22:17
by slapshot5
More code - this time, Natural Selection

CardFactory.java:
Code: Select all
       //*************** START *********** START **************************

       else if(cardName.equals("Natural Selection")) {
          /* Look at the top 3 cards of target player's library and put them
           * back in any order. You may have that player shuffle his or
           * her library */

          final SpellAbility spell = new Spell(card) {
             private static final long serialVersionUID = 8649520296192617609L;
             
             @Override
             public void resolve() {
                String player = getTargetPlayer();
                PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
                if(lib.size() < 3) return;
                CardList topThree =   new CardList();
                //show top 3 cards:
                topThree.add(lib.get(0));
                topThree.add(lib.get(1));
                topThree.add(lib.get(2));
                for(int i = 1; i <= 3; i++) {
                   String Title = "Put on top: ";
                   if(i == 2) Title = "Put second from top: ";
                   if(i == 3) Title = "Put third from top: ";
                   Object o = AllZone.Display.getChoiceOptional(Title, topThree.toArray());
                   if(o == null) break;
                   Card c_1 = (Card) o;
                   topThree.remove(c_1);
                   lib.remove(c_1);
                   lib.add(c_1, i - 1);
                }
                String[] choices = new String[] {"Yes", "No"};
                Object o = AllZone.Display.getChoice("Shuffle target player's library?", choices);
                String myChoice = (String) o;
                if(myChoice.equals("Yes")) {
                   AllZone.GameAction.shuffle(getTargetPlayer());
                }
             }
             @Override
             public boolean canPlayAI() {
                //basically the same reason as Sensei's Diving Top
                return false;
             }
          };//spell
          card.clearSpellAbility();
          card.addSpellAbility(spell);
          spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));
       }
       //*************** END ************ END **************************
cards.txt:
Code: Select all
Natural Selection
G
Instant
Look at the top 3 cards of target player's library and put them back in any order. You may have that player shuffle his or her library.
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/natural_selection.jpg
-slapshot5

Re: Code from slapshot5

PostPosted: 14 Apr 2010, 03:22
by zerker2000
Or we could change "CARDNAME" to "This card"...

Re: Code from slapshot5

PostPosted: 14 Apr 2010, 04:18
by slapshot5
Here is code for Reinforcements from Alliances.

Currently, the AI can't use this card. The AI would be very easy to implement, but I need to set three target cards. Can I do that?

cards.txt:
Code: Select all
Reinforcements
W
Instant
Put up to three target creature cards from your graveyard on top of your library.
CardFactory.java:
Code: Select all
//*************** START *********** START **************************

       else if(cardName.equals("Reinforcements")) {
          /* Put up to three target creature cards from your
           * graveyard on top of your library.
           */

          final SpellAbility spell = new Spell(card) {
            private static final long serialVersionUID = 4075591356690396548L;
            
            @Override
             public boolean canPlayAI() {
                //AI could easily play this, but I need to set 3 target cards
               //Can I do that?
                return false;
             }
            @Override
             public void resolve() {
                String player = card.getController();
                PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player);
                PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);

                CardList creatures = new CardList(grave.getCards());
                creatures = creatures.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.isCreature();
                        }
                    });
                //now, select three creatures
                int end = -1;
                end = Math.min(creatures.size(), 3);
                for(int i = 1; i <= end; i++) {
                   String Title = "Put on top of library: ";
                   if(i == 2) Title = "Put second from top of library: ";
                   if(i == 3) Title = "Put third from top of library: ";
                   Object o = AllZone.Display.getChoiceOptional(Title, creatures.toArray());
                   if(o == null) break;
                   Card c_1 = (Card) o;
                   creatures.remove(c_1); //remove from the display list
                   grave.remove(c_1); //remove from graveyard
                   lib.add(c_1, i - 1);
                }
                
             }
          };//spell
          card.clearSpellAbility();
          card.addSpellAbility(spell);
       }
       //*************** END ************ END **************************
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/reinforcements.jpg
-slapshot5

Re: Code from slapshot5

PostPosted: 15 Apr 2010, 12:41
by Chris H.
zerker2000 wrote:Or we could change "CARDNAME" to "This card"...
`
I like "CARDNAME" as it is easy to determine that this will be replaced with the actual card's name. I think that it was a good choice. :D

Re: Code from slapshot5

PostPosted: 15 Apr 2010, 13:53
by Rob Cashwalker
The way you handle the input (to loop three times choosing cards) is the same basic process you should have the AI go through. All you have to do is sort the graveyard by some criteria, and then take the top three cards. The AI to play the spell in the first place should attempt to do some of this decision making so that if there aren't three cards to be returned, then don't play the spell.

Re: Code from slapshot5

PostPosted: 15 Apr 2010, 19:04
by DennisBergkamp
Yeah, there's no need to use setTargetCard() in this case. Like Rob said, just be sure to check if it matches the criteria of having at least 3 creatures (or maybe just 2?) in the graveyard.

You could do something like this:

Code: Select all
//*************** START *********** START **************************

        else if(cardName.equals("Reinforcements")) {
           /* Put up to three target creature cards from your
            * graveyard on top of your library.
            */
           final SpellAbility spell = new Spell(card) {
             private static final long serialVersionUID = 4075591356690396548L;
             
             CardList getComputerCreatures()
             {
                 CardList list = new CardList(AllZone.Computer_Graveyard.getCards());
                 list = list.getType("Creature");
                 
                 //put biggest attack creats first
                 if (list.size()>0)
                    CardListUtil.sortAttack(list);
                 
                 return list;
             }
             
             @Override
              public boolean canPlayAI() {
                 return getComputerCreatures().size() >= 3;
              }
             @Override
              public void resolve() {
                 String player = card.getController();
                 PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player);
                 PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);

                 CardList creatures = new CardList(grave.getCards());
                 creatures = creatures.filter(new CardListFilter() {
                         public boolean addCard(Card c) {
                             return c.isCreature();
                         }
                     });
                 if (player.equals(Constant.Player.Human))
                 {
                    //now, select three creatures
                    int end = -1;
                    end = Math.min(creatures.size(), 3);
                    for(int i = 1; i <= end; i++) {
                       String Title = "Put on top of library: ";
                       if(i == 2) Title = "Put second from top of library: ";
                       if(i == 3) Title = "Put third from top of library: ";
                       Object o = AllZone.Display.getChoiceOptional(Title, creatures.toArray());
                       if(o == null) break;
                       Card c_1 = (Card) o;
                       creatures.remove(c_1); //remove from the display list
                       grave.remove(c_1); //remove from graveyard
                       lib.add(c_1, i - 1);
                    }
                 }
                 else //Computer
                 {
                    CardList list = getComputerCreatures();
                    int max = list.size();
                   
                    if (max > 3)
                       max = 3;
                   
                    for (int i=0;i<max;i++)
                    {
                       grave.remove(list.get(i));
                       lib.add(list.get(i), i);
                    }
                 }
                 
              }
           };//spell
           card.clearSpellAbility();
           card.addSpellAbility(spell);
        }
        //*************** END ************ END **************************
Haven't tested yet, but it should work.

Re: Code from slapshot5

PostPosted: 16 Apr 2010, 04:39
by Rob Cashwalker
AI also would want to take into consideration whether or not waiting three turns to draw a fresh card is a good idea or not... like if there's less than 5 or 6 lands... don't bury land underneath the cards.

Re: Code from slapshot5

PostPosted: 16 Apr 2010, 05:02
by slapshot5
Here's Code for Hurkyl's Recall

cards.txt
Code: Select all
Hurkyl's Recall
1 U
Instant
Return all artifacts target player owns to his or her hand.
URL
Code: Select all
http://www.wizards.com/global/images/magic/general/hurkyls_recall.jpg
CardFactory.java:
Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Hurkyl's Recall")) {
           /*
            * Return all artifacts target player owns to his or her hand.
            */
            SpellAbility spell = new Spell(card) {
            private static final long serialVersionUID = -4098702062413878046L;
            
            @Override
            public boolean canPlayAI() {
               PlayerZone humanPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
               CardList humanArts = new CardList(humanPlay.getCards());
               humanArts = humanArts.getType("Artifact");
               if(humanArts.size() > 0) {
                  return true;
               }
               else {
                  return false;
               }
            }//canPlayAI
            
            @Override
            public void chooseTargetAI() {
                setTargetPlayer(Constant.Player.Human);
             }//chooseTargetAI()
            
            @Override
                public void resolve() {
                   String player = getTargetPlayer();
                   PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
                   PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player);
                   final String opponent = AllZone.GameAction.getOpponent(player);
                   PlayerZone oppPlay = AllZone.getZone(Constant.Zone.Play, opponent);
                    CardList artifacts = new CardList(play.getCards());
                    artifacts.addAll(oppPlay.getCards());
                    artifacts = artifacts.getType("Artifact");
                   
                    for(int i = 0; i < artifacts.size(); i++) {
                       Card thisArtifact = artifacts.get(i);
                       //if is token, remove token from play, else return artifact to hand
                       if(thisArtifact.getOwner().equals(player)) {
                          if(thisArtifact.isToken()) {
                             play.remove(thisArtifact);
                          }
                          else {
                             AllZone.GameAction.moveTo(hand, thisArtifact);
                          }
                       }
                    }
                }//resolve()
            };
            card.clearSpellAbility();
            card.addSpellAbility(spell);
            spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));
        }//*************** END ************ END **************************
Note: This is *owns*, not *controls*. I had to do a quick tweak of the code once I flipped the light switch of my brain.

-slapshot5

Re: Code from slapshot5

PostPosted: 16 Apr 2010, 15:27
by Chris H.
DennisBergkamp wrote:We should probably also convert : "This card doesn't untap during your untap step." to "CARDNAME doesn't untap during your untap step.", and "This creature cannot block" to "CARDNAME cannot block".

EDIT: And "This card attacks each turn if able."
`
There are a number of keywords to be converted over. :( The code and the cards.txt entries will need a lot of work and testing ... I can't promise to finish this off anytime soon. :wink:

Re: Code from slapshot5

PostPosted: 18 Apr 2010, 05:22
by slapshot5
Hi all,

I'm looking to implement Lodestone Bauble. One of the things that needs to happen is:

"That player draws a card at the beginning of the next turn's upkeep."

Is that currently possible to make happen in Forge or not?

Thanks,
-slapshot5

Re: Code from slapshot5

PostPosted: 18 Apr 2010, 20:02
by slapshot5
Re: Reinforcements
DennisBergkamp wrote:You could do something like this:
Haven't tested yet, but it should work.
Dennis,

I just tested your posted code for Reinforcements a bit for Human and Computer. It seems to be working as expected. Please commit. cards.txt and URL posted above.

Thanks,
-slapshot5

Re: Code from slapshot5

PostPosted: 18 Apr 2010, 20:56
by DennisBergkamp
Ok, I think the CardFactory part is committed already, but true, I think I forgot to add cards.txt and the pic link. I'll also commit some of the other cards you posted :)

As for Lodestone Bauble, it's definitely possible but some additional coding would have to be done first. We are currently doing delayed triggers like that during the End of Turn step and End of Combat step.