It is currently 28 Oct 2025, 18:26
   
Text Size

Academy Rector code question

Post MTG Forge Related Programming Questions Here

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

Academy Rector code question

Postby Chris H. » 19 Dec 2010, 15:12

In recnt months I have tried to add a yes/no dialog to the cards which are missing this choice. I am also trying to replace the list-form yes/no dialog with a button-type yes/no dialog. I have some initial work done for Academy Rector. I ran into a couple of issues and I could use some advice on how to proceed.

On my local copy Academy Rector will now use a button-type yes/no dialog. A list dialog comes up with a listing of all of the enchantments located in your library.

I noticed that in the old code if you selected an Enchant creature aura that you would get a listing with the creatures on both sides of the battlefield. This can make it difficult to select the correct creature for your curse or your buff.

There are a number of cards which share the "When CARDNAME is put into a graveyard from " {play or battlefield} style of code. They have a Command which does much of the work and use one of the CardFactoryUtil inputs. These inputs require a spell ability as a parameter included in the call.

These cards have a spell ability and a stack description. Academy Rector does not and is different and is handled differently. So, is having a spell ability, an "AllZone.Stack.add(ability);" and a stack description a rules correct way of implementing these types of cards. If not, then they may have been coded this way inorder to use one of the more user-frindly inputs.

So I am kind of stuck on the Academy Rector code mods for the moment. Should I add the missing spell ability, an "AllZone.Stack.add(ability);" and a stack description? Or if this is not correct, is it possible to modify the input_targetSpecific() method and make a 2nd one which would use a command rather than a sa as a parameter?
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: Academy Rector code question

Postby Sloth » 19 Dec 2010, 15:57

Chris H. wrote:So I am kind of stuck on the Academy Rector code mods for the moment. Should I add the missing spell ability, an "AllZone.Stack.add(ability);" and a stack description? Or if this is not correct, is it possible to modify the input_targetSpecific() method and make a 2nd one which would use a command rather than a sa as a parameter?
Ruleswise the ability should use the stack (it's a triggered ability), so your opponent is able to Stifle it.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Academy Rector code question

Postby friarsol » 19 Dec 2010, 16:22

From a rules perspective here's what happens with all of those cards:

It hits the graveyard from the battlefield, and it's triggered ability goes on the stack. When it resolves you choose whether or not to exile it. If you do, you search up an enchantment and put it onto the battlefield. If the enchantment is an Aura, you then choose a legal card to attach it to (this is non-targeted).

Technically, all of that is one resolving ability. If there are two abilities (one for the trigger and one for the fetch) it's not quite right.

In the future, once we have AF_Trigger setup it should be able to handle this situation in one encompassing Ability. (Assuming at that point we have some type of "conditional" AF. That will handle "You may do X. If you do, do <subAbility>")
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Academy Rector code question

Postby Chris H. » 19 Dec 2010, 17:08

Thank you for the info Sloth and Sol. :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: Academy Rector code question

Postby Chris H. » 21 Dec 2010, 19:42

I finished my improvements for Academy Rector. It was more work than I expected but I had a null error to fix ... had to make my own input to avoid this bug.

I have included the code below but it will be hard to read given the amount of indentation needed to make it work. The destroy Command now only holds the "AllZone.Stack.add(ability);" line of code. Everything else was moved into an ability. The input is also inside of the ability. I think this is what Sol wanted to see.

Code: Select all
        //*************** START *********** START **************************
        else if(cardName.equals("Academy Rector")) {
            final SpellAbility ability = new Ability(card, "0") {
               
                @Override
                public void resolve() {
                   
                    if (card.getController().equals(AllZone.HumanPlayer)) {
                        StringBuilder question = new StringBuilder();
                        question.append("Exile ").append(card.getName());
                        question.append(" and place an enchantment from your library onto the battlefield?");
                       
                        if (GameActionUtil.showYesNoDialog(card, question.toString())) {
                            AllZone.GameAction.exile(card);
                            PlayerZone lib = AllZone.getZone(Constant.Zone.Library, AllZone.HumanPlayer);
                            CardList list = AllZoneUtil.getPlayerCardsInLibrary(AllZone.HumanPlayer);
                            list = list.getType("Enchantment");
                           
                            if (list.size() > 0) {
                                Object objectSelected = AllZone.Display.getChoiceOptional("Choose an enchantment", list.toArray());
                               
                                if (objectSelected != null) {
                                    PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, AllZone.HumanPlayer);
                                    final Card c = (Card) objectSelected;
                                    lib.remove(c);
                                    play.add(c);
                                   
                                    if (c.isAura()) {
                                       
                                        String enchantThisType[] = {""};
                                        String message[] = {""};
                                       
                                        // The type following "Enchant" maybe upercase or lowercase, cardsfolder has both
                                        // Note that I am being overly cautious.
                                       
                                        if (c.getKeyword().contains("Enchant creature without flying") || c.getKeyword().contains("Enchant Creature without flying")) {
                                            enchantThisType[0] = "Creature.withoutFlying";
                                            message[0] = "Select a creature without flying";
                                        } else if (c.getKeyword().contains("Enchant creature with converted mana cost 2 or less") || c.getKeyword().contains("Enchant Creature with converted mana cost 2 or less")) {
                                            enchantThisType[0] = "Creature.cmcLE2";
                                            message[0] = "Select a creature with converted mana cost 2 or less";
                                        } else if (c.getKeyword().contains("Enchant red or green creature")) {
                                            enchantThisType[0] = "Creature.Red,Creature.Green";
                                            message[0] = "Select a red or green creature";
                                        } else if (c.getKeyword().contains("Enchant tapped creature")) {
                                            enchantThisType[0] = "Creature.tapped";
                                            message[0] = "Select a tapped creature";
                                        } else if (c.getKeyword().contains("Enchant creature") || c.getKeyword().contains("Enchant Creature")) {
                                            enchantThisType[0] = "Creature";
                                            message[0] = "Select a creature";
                                        } else if (c.getKeyword().contains("Enchant wall") || c.getKeyword().contains("Enchant Wall")) {
                                            enchantThisType[0] = "Wall";
                                            message[0] = "Select a Wall";
                                        } else if (c.getKeyword().contains("Enchant land you control") || c.getKeyword().contains("Enchant Land you control")) {
                                            enchantThisType[0] = "Land.YouCtrl";
                                            message[0] = "Select a land you control";
                                        } else if (c.getKeyword().contains("Enchant land") || c.getKeyword().contains("Enchant Land")) {
                                            enchantThisType[0] = "Land";
                                            message[0] = "Select a land";
                                        } else if (c.getKeyword().contains("Enchant artifact") || c.getKeyword().contains("Enchant Artifact")) {
                                            enchantThisType[0] = "Artifact";
                                            message[0] = "Select an artifact";
                                        } else if (c.getKeyword().contains("Enchant enchantment") || c.getKeyword().contains("Enchant Enchantment")) {
                                            enchantThisType[0] = "Enchantment";
                                            message[0] = "Select an enchantment";
                                        }
                                       
                                        CardList allCards = new CardList();
                                        allCards.addAll(AllZone.Human_Battlefield.getCards());
                                        allCards.addAll(AllZone.Computer_Battlefield.getCards());
                                       
                                        // Make sure that we were able to match the selected aura with our list of criteria
                                       
                                        if (enchantThisType[0] != "" && message[0] != "") {
                                       
                                            final CardList choices = allCards.getValidCards(enchantThisType[0], card.getController(), card);
                                            final String msg = message[0];
                                       
                                            AllZone.InputControl.setInput(new Input() {
                                                private static final long serialVersionUID = -6271957194091955059L;

                                                @Override
                                                public void showMessage() {
                                                    AllZone.Display.showMessage(msg);
                                                    ButtonUtil.enableOnlyOK();
                                                }
                                           
                                                @Override
                                                public void selectButtonOK() {
                                                    stop();
                                                }
                                           
                                                @Override
                                                public void selectCard(Card card, PlayerZone zone) {
                                                    if (choices.contains(card)) {
                                                   
                                                        if (AllZone.GameAction.isCardInPlay(card)) {
                                                            c.enchantCard(card);
                                                            stop();
                                                        }
                                                    }
                                                }//selectCard()
                                            });// Input()
                                           
                                        }// if we were able to match the selected aura with our list of criteria
                                    }// If enchantment selected is an aura
                                }// If an enchantment is selected
                            }// If there are enchantments in library
                           
                        }// If answered yes to may exile
                    }// If player is human
                   
                    // player is the computer
                    else {
                        PlayerZone lib = AllZone.getZone(Constant.Zone.Library, AllZone.ComputerPlayer);
                        CardList list = new CardList(lib.getCards());
                        list = list.filter(new CardListFilter() {
                            public boolean addCard(Card c) {
                                return c.isEnchantment() && !c.isAura();
                            }
                        });
                       
                        if (list.size() > 0) {
                            PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, AllZone.ComputerPlayer);
                            Card c = CardFactoryUtil.AI_getBestEnchantment(list, card, false);
                            lib.remove(c);
                            play.add(c);
                            AllZone.GameAction.exile(card);
                        }
                    }// player is the computer
                }// resolve()
            };// ability
           
            StringBuilder sb = new StringBuilder();
            sb.append("Academy Rector - ").append(card.getController());
            sb.append(" may exile this card and place an enchantment from his library onto the battlefield.");
            ability.setStackDescription(sb.toString());
           
            final Command destroy = new Command() {
                private static final long serialVersionUID = -4352349741511065318L;
                public void execute() {
                   
                    AllZone.Stack.add(ability);
                   
                }// execute()
            };// Command destroy
           
            card.addDestroyCommand(destroy);
        }//*************** 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


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 23 guests

Main Menu

User Menu

Our Partners


Who is online

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

Login Form