It is currently 03 Nov 2025, 19:00
   
Text Size

Code from slapshot5

Post MTG Forge Related Programming Questions Here

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

Re: Code from slapshot5

Postby Chris H. » 13 Apr 2010, 19:55

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:
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: Code from slapshot5

Postby DennisBergkamp » 13 Apr 2010, 20:55

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

Re: Code from slapshot5

Postby slapshot5 » 13 Apr 2010, 22:15

Chris H. wrote:Shhh ... I am now in the process of converting a small portion of his code into a keyword.
Cool. Thanks Chris.
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 13 Apr 2010, 22:17

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
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby zerker2000 » 14 Apr 2010, 03:22

Or we could change "CARDNAME" to "This card"...
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: Code from slapshot5

Postby slapshot5 » 14 Apr 2010, 04:18

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
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby Chris H. » 15 Apr 2010, 12:41

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
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: Code from slapshot5

Postby Rob Cashwalker » 15 Apr 2010, 13:53

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.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Code from slapshot5

Postby DennisBergkamp » 15 Apr 2010, 19:04

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

Re: Code from slapshot5

Postby Rob Cashwalker » 16 Apr 2010, 04:39

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.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Code from slapshot5

Postby slapshot5 » 16 Apr 2010, 05:02

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
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby Chris H. » 16 Apr 2010, 15:27

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:
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: Code from slapshot5

Postby slapshot5 » 18 Apr 2010, 05:22

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
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 18 Apr 2010, 20:02

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
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby DennisBergkamp » 18 Apr 2010, 20:56

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.
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 11 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 11 users online :: 0 registered, 0 hidden and 11 guests (based on users active over the past 10 minutes)
Most users ever online was 9298 on 10 Oct 2025, 12:54

Users browsing this forum: No registered users and 11 guests

Login Form