It is currently 11 Sep 2025, 21:57
   
Text Size

Disciple of Kangee

Post MTG Forge Related Programming Questions Here

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

Disciple of Kangee

Postby Chris H. » 17 Dec 2009, 18:17

I think that I have completed the Disciple of Kangee card. Target creature now gains flying and becomes blue until end of turn. I ran some tests and now realize that I am not sure if I understand the implementation.

Currently, I can change a white creature into a white and blue creature with a gold border. Is this correct?

Or should the blue replace the white until end of turn?

Code: Select all
Disciple of Kangee
2 W
Creature Wizard
no text
2/2
`
Code: Select all
       //*************** START *********** START **************************
       else if(cardName.equals("Disciple of Kangee"))
       {
         final SpellAbility ability = new Ability_Tap(card, "U")
         {
           private static final long serialVersionUID = -5169389637917649036L;
         public boolean canPlayAI()
           {
             if(CardFactoryUtil.AI_doesCreatureAttack(card))
               return false;

             return CardFactoryUtil.AI_getHumanCreature("Flying", card, false).isEmpty() &&
                    (getCreature().size() != 0);
           }
           public void chooseTargetAI()
           {
             card.tap();
             Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
             setTargetCard(target);
           }
           CardList getCreature()
           {
             CardList list = new CardList(AllZone.Computer_Play.getCards());
             list = list.filter(new CardListFilter()
             {
               public boolean addCard(Card c)
               {
                 return c.isCreature() && (!CardFactoryUtil.AI_doesCreatureAttack(c)) &&
                        (! c.getKeyword().contains("Flying")) && CardFactoryUtil.canTarget(card, c);
               }
             });
             list.remove(card);
             return list;
           }//getCreature()
           public void resolve()
           {
             if(AllZone.GameAction.isCardInPlay(getTargetCard())  && CardFactoryUtil.canTarget(card, getTargetCard()) )
             {
               final Card[] creature = new Card[1];
               final Command EOT = new Command()
               {
               private static final long serialVersionUID = -1899153704584793548L;

            public void execute()
                 {
                   if(AllZone.GameAction.isCardInPlay(creature[0]))
                   {
                     creature[0].removeExtrinsicKeyword("Flying");
                     creature[0].removeExtrinsicKeyword(creature[0].getName() + " is blue.");
                   }
                 }
               };
               creature[0] = getTargetCard();
               creature[0].addExtrinsicKeyword("Flying");
               if(!creature[0].getManaCost().equals("U"))
               {
                 creature[0].addExtrinsicKeyword(creature[0].getName() + " is blue.");
               }
               AllZone.EndOfTurn.addUntil(EOT);
             }//if (card is in play)
           }//resolve()
         };//SpellAbility
         card.addSpellAbility(ability);
         ability.setDescription("U, tap: Target creature gains flying and becomes blue until end of turn.");

         ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
       }//*************** END ************ END **************************
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: Disciple of Kangee

Postby Marek14 » 17 Dec 2009, 18:22

It replaces the original color. Compare Disciple of Kangee with Indigo Faerie.
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: Disciple of Kangee

Postby DennisBergkamp » 17 Dec 2009, 19:48

I think your new code works correctly now Chris... The targeted creature will ONLY be blue, except the GUI doesn't really show it correctly yet (look at Ghostfire, it can target spells that have protection from red, but the GUI will still show a red border).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Disciple of Kangee

Postby Chris H. » 17 Dec 2009, 20:01

DennisBergkamp wrote:I think your new code works correctly now Chris... The targeted creature will ONLY be blue, except the GUI doesn't really show it correctly yet (look at Ghostfire, it can target spells that have protection from red, but the GUI will still show a red border).
`
Great. :D

I was starting to consider saving the manaCost to a var and checking to see if any other zerker type color keywords are present. This way I could delete this color data and restore it at end of turn. :roll:

I quess that it would be nice to adapt other sections of the code to reflect the current color status, just more work. The deck Editors for example.
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: Disciple of Kangee

Postby Chris H. » 17 Dec 2009, 20:58

Drat. I just ran a test and verified that zerker's color keyword is additive and not a replacement effect. :( I ran the two decks below against each other.

The computer used it's Disciple of Kangee on it's Devoted Hero. The Devoted Hero then attacked. I used my Disciple of Kangee on my Crimson Kobolds and then gave it pro from white with my Mother of Runes.

My Crimson Kobolds block the computer's attacking Devoted Hero and my Crimson Kobolds survived. I will need to do some more coding to finish off the updated Disciple of Kangee code.

Code: Select all
Computer Devoted Hero
[general]
constructed
[main]
1 Devoted Hero
3 Mox Pearl
1 Mox Sapphire
1 Disciple of Kangee
1 Phyrexian Walker
[sideboard]
`
Code: Select all
Human Mother of Runes
[general]
constructed
[main]
1 Crimson Kobolds
2 Mox Pearl
1 Mox Sapphire
1 Disciple of Kangee
1 Phyrexian Walker
1 Mother of Runes
[sideboard]
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: Disciple of Kangee

Postby Chris H. » 18 Dec 2009, 14:25

I have changed the code and now the Disciple of Kangee ability is a replacement rather than an additive effect. I check for and remove zerker's color keywords and add them back in at EOT. We can now change a Crimson Kobolds to the appropriate color. Great.

But what do we do with the target's mana cost? I originally changed the mana cost to "" but I realized that this could create problems with other effects.

Currently, I toLowerCase and then to UpperCase the mana cost. This is somewhat better but will still likely create problems with other effects. Gotta love them hacks.

What should I do? Is there a command that can be used to quickly convert the mana cost to it's CCC? Does anyone have any ideas?

Code: Select all
       //*************** START *********** START **************************
       else if(cardName.equals("Disciple of Kangee"))
       {
         final SpellAbility ability = new Ability_Tap(card, "U")
         {
           private static final long serialVersionUID = -5169389637917649036L;
         public boolean canPlayAI()
           {
             if(CardFactoryUtil.AI_doesCreatureAttack(card))
               return false;

             return CardFactoryUtil.AI_getHumanCreature("Flying", card, false).isEmpty() &&
                    (getCreature().size() != 0);
           }
           public void chooseTargetAI()
           {
             card.tap();
             Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
             setTargetCard(target);
           }
           CardList getCreature()
           {
             CardList list = new CardList(AllZone.Computer_Play.getCards());
             list = list.filter(new CardListFilter()
             {
               public boolean addCard(Card c)
               {
                 return c.isCreature() && (!CardFactoryUtil.AI_doesCreatureAttack(c)) &&
                        (! c.getKeyword().contains("Flying")) && CardFactoryUtil.canTarget(card, c);
               }
             });
             list.remove(card);
             return list;
           }//getCreature()
           public void resolve()
           {
             if (AllZone.GameAction.isCardInPlay(getTargetCard())  && CardFactoryUtil.canTarget(card, getTargetCard()) )
             {
               final Card[] creature = new Card[1];
              
               creature[0] = getTargetCard();
               final String origManaCost = creature[0].getManaCost();
               final String tgtName = creature[0].getName();
               final String[] creatureIsColor = {tgtName + " is black.", tgtName + " is blue.", tgtName + " is green.",
                                         tgtName + " is red.", tgtName + " is white.", tgtName + " is colorless."};
               final boolean[] colorFlag = {false, false, false, false, false, false};
                
               for (int i=0; i<6; i++)
               {
                 if (creature[0].getIntrinsicKeyword().contains(creatureIsColor[i]))
                 {
                   colorFlag[i] = true;
//                   creature[0].removeExtrinsicKeyword(creatureIsColor[i]);
                 }
               }
              
               final Command EOT = new Command()
               {
              private static final long serialVersionUID = -1899153704584793548L;

              public void execute()
                 {
                   if (AllZone.GameAction.isCardInPlay(creature[0]))
                   {
                     creature[0].removeExtrinsicKeyword("Flying");
                     creature[0].removeExtrinsicKeyword(tgtName + " is blue.");
                     creature[0].setManaCost(origManaCost.toUpperCase());
                     for (int i=0; i<6; i++)
                     {
                       if (colorFlag[i])
                       {
                         creature[0].addIntrinsicKeyword(creatureIsColor[i]);
                       }
                     }
                   }
                 }
               };
               creature[0].setManaCost(origManaCost.toLowerCase());
               for (int i=0; i<6; i++)
               {
                 if (colorFlag[i])
                 {
                   creature[0].removeIntrinsicKeyword(creatureIsColor[i]);
                 }
               }
               creature[0].addExtrinsicKeyword("Flying");
               creature[0].addExtrinsicKeyword(tgtName + " is blue.");
               AllZone.EndOfTurn.addUntil(EOT);
             }//if (card is in play)
           }//resolve()
         };//SpellAbility
         card.addSpellAbility(ability);
         ability.setDescription("U, tap: Target creature gains flying and becomes blue until end of turn.");

         ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
       }//*************** END ************ END **************************
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: Disciple of Kangee

Postby Marek14 » 18 Dec 2009, 14:37

In ideal world, the effects that change color do that regardless of the mana cost - the mana cost is never changed (save from copy effects), and it's only used as the "first step" in determining color.
Marek14
Tester
 
Posts: 2773
Joined: 07 Jun 2008, 07:54
Has thanked: 0 time
Been thanked: 303 times

Re: Disciple of Kangee

Postby Chris H. » 19 Dec 2009, 02:31

I found the cmc method and I have updated the code to use this to remove the color from the target card. It is a hack, but this is probably as close as I can get to being rules compliant. ](*,) :wink:

Code: Select all
       //*************** START *********** START **************************
       else if(cardName.equals("Disciple of Kangee"))
       {
         final SpellAbility ability = new Ability_Tap(card, "U")
         {
           private static final long serialVersionUID = -5169389637917649036L;
         public boolean canPlayAI()
           {
             if(CardFactoryUtil.AI_doesCreatureAttack(card))
               return false;

             return CardFactoryUtil.AI_getHumanCreature("Flying", card, false).isEmpty() &&
                    (getCreature().size() != 0);
           }
           public void chooseTargetAI()
           {
             card.tap();
             Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
             setTargetCard(target);
           }
           CardList getCreature()
           {
             CardList list = new CardList(AllZone.Computer_Play.getCards());
             list = list.filter(new CardListFilter()
             {
               public boolean addCard(Card c)
               {
                 return c.isCreature() && (!CardFactoryUtil.AI_doesCreatureAttack(c)) &&
                        (! c.getKeyword().contains("Flying")) && CardFactoryUtil.canTarget(card, c);
               }
             });
             list.remove(card);
             return list;
           }//getCreature()
           public void resolve()
           {
             if (AllZone.GameAction.isCardInPlay(getTargetCard())  && CardFactoryUtil.canTarget(card, getTargetCard()) )
             {
               final Card[] creature = new Card[1];
              
               creature[0] = getTargetCard();
               final String origManaCost = creature[0].getManaCost();
               final String tgtName = creature[0].getName();
               final String[] creatureIsColor = {tgtName + " is black.", tgtName + " is blue.", tgtName + " is green.",
                                         tgtName + " is red.", tgtName + " is white.", tgtName + " is colorless."};
               final boolean[] colorFlag = {false, false, false, false, false, false};
                
               for (int i=0; i<6; i++)
               {
                 if (creature[0].getIntrinsicKeyword().contains(creatureIsColor[i]))
                 {
                   colorFlag[i] = true;
                 }
               }
              
               final Command EOT = new Command()
               {
              private static final long serialVersionUID = -1899153704584793548L;

              public void execute()
                 {
                   if (AllZone.GameAction.isCardInPlay(creature[0]))
                   {
                     creature[0].removeExtrinsicKeyword("Flying");
                     creature[0].removeExtrinsicKeyword(tgtName + " is blue.");
                     creature[0].setManaCost(origManaCost);
                     for (int i=0; i<6; i++)
                     {
                       if (colorFlag[i])
                       {
                         creature[0].addIntrinsicKeyword(creatureIsColor[i]);
                       }
                     }
                   }
                 }
               };
               creature[0].setManaCost(Integer.toString(CardUtil.getConvertedManaCost(origManaCost)));
               for (int i=0; i<6; i++)
               {
                 if (colorFlag[i])
                 {
                   creature[0].removeIntrinsicKeyword(creatureIsColor[i]);
                 }
               }
               creature[0].addExtrinsicKeyword("Flying");
               creature[0].addExtrinsicKeyword(tgtName + " is blue.");
               AllZone.EndOfTurn.addUntil(EOT);
             }//if (card is in play)
           }//resolve()
         };//SpellAbility
         card.addSpellAbility(ability);
         ability.setDescription("U, tap: Target creature gains flying and becomes blue until end of turn.");

         ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
       }//*************** END ************ END **************************
`
I will make an update to the SVN this weekend. I see that the weather forecast will have me snowed in all weekend. 8)
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: Disciple of Kangee

Postby zerker2000 » 19 Dec 2009, 02:56

Optimal solution(which I, coder of color keywords, hereby endorse): in getColors, blank the output array the first time you encounter such keywords. Maybe in fact whenever you encounter them, as long as the parser can be made to understand "all colors" and/or "is COLOR1 and COLOR2[ and COLOR3...]" and such provisions are made for Transguild Courier.

EDIT: As far as I can remember, comp rules say it's supposed to work this way in the first place.
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: Disciple of Kangee

Postby Chris H. » 19 Dec 2009, 13:40

I think that I found your color keyword code in CardUtil.java. There is a section which starts with:

Code: Select all
public static ArrayList<String> getColors(Card c)
`
An interesting section of code and a step in the right direction.

I admit that my knowledge base and skill level is fairly limited. I can see that there will need to be a way to determine if this keyword needs to be an additive or a replacement effect. I will have to let the lead programmers deal with this part of the code base.
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: Disciple of Kangee

Postby zerker2000 » 20 Dec 2009, 04:55

CardUtil.getColors is the method used by spells/abilities requiring colors, and what should be used by GUI(though I think it isn't). I think originally it did something along the lines of "For each letter in the mana cost, add the appropriate color to the output array". Then I came along and inserted keyword handling.
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: Disciple of Kangee

Postby Chris H. » 25 Dec 2009, 01:52

While I have been fairly busy recently, I did set aside some time to look at some of the color code. I agree that some of the GUI appears to not use this color code. Kobolds have a black border rather than a red one for example. It is somewhat confusing to see black, color keyword and colorless cards with a black border.

I see that with v12-14 that the Kobolds now have a designation of red in the color column of the deck editor. That is a nice addition.
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: Disciple of Kangee

Postby Chris H. » 25 Dec 2009, 15:21

I think that I found the GUI code which creates the color borders for cards located in GuiDisplay.java. I think that zerker's color keyword could be added this code and this would allow cards to have the appropriate border color with his keyword.

This brings up several issues. I imagine that Rares originally wrote this code when there were no card jpgs to display. The few cards that were included were simple enough that it did not at that time lead to some of the discrepancies that I am seeing at this time.

Some people are creatures of habit and may not like it if too many modifications are made to this code. Other people will want to see card border colors become more rules compliant.

I think that I am in the second camp. I recently modified the Disciple of Kangee. It would be nice if the target creature would have it's border color changed to blue until the end of turn.

How do other people feel?
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: Disciple of Kangee

Postby DennisBergkamp » 25 Dec 2009, 16:36

Yeah I think border colors should change (it's not like we're changing the color of the card picture after all).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Disciple of Kangee

Postby Chris H. » 25 Dec 2009, 17:49

I have made the changes and it appears to work correctly. Kobolds now have a red colored border. Ghostfire has a gray colored border, yeah ... but for some reason zerkers color keyword is no displaying the cart text:

"Ghostfire is colorless."

The code changes below:

Code: Select all
        if(CardUtil.getColors(card).size() != 1)
          color = Color.orange;
        else if(CardUtil.getColor(card).equals(Constant.Color.Colorless) || (card.getIntrinsicKeyword().contains(card.getName() + " is colorless.")))
          color = Color.gray;
        else if(CardUtil.getColor(card).equals(Constant.Color.Black) || (card.getIntrinsicKeyword().contains(card.getName() + " is black.")))
          color = Color.black;
        else if(CardUtil.getColor(card).equals(Constant.Color.Green) || (card.getIntrinsicKeyword().contains(card.getName() + " is green.")))
          color = new Color(0, 220, 39);
        else if(CardUtil.getColor(card).equals(Constant.Color.White) || (card.getIntrinsicKeyword().contains(card.getName() + " is white.")))
          color = Color.white;
        else if(CardUtil.getColor(card).equals(Constant.Color.Red) || (card.getIntrinsicKeyword().contains(card.getName() + " is red.")))
          color = Color.red;
        else if(CardUtil.getColor(card).equals(Constant.Color.Blue) || (card.getIntrinsicKeyword().contains(card.getName() + " is blue.")))
          color = Color.blue;
        else color = Color.gray;
`

There is another code section which follows, I have not changed it and things appear to work so far. The code below, I guess should also be changed?

Code: Select all
        if(!card.isArtifact()) {
            int r = color.getRed();
            int g = color.getGreen();
            int b = color.getBlue();
           
            int shade = 10;
           
            r -= shade;
            g -= shade;
            b -= shade;
           
            r = Math.max(0, r);
            g = Math.max(0, g);
            b = Math.max(0, b);
           
            color = new Color(r, g, b);
        }
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 26 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 26 users online :: 0 registered, 0 hidden and 26 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 26 guests

Login Form