Page 1 of 1

screwed over by input again...

PostPosted: 06 May 2010, 06:01
by slapshot5
Everytime I think I start to understand input and abilities better, I run into something that screws me over.

Mana Vault is my latest example. In GameActionUtil, I have an upkeep method to handle this:

"At the beginning of your upkeep, you may pay 4. If you do, untap Mana Vault."

So, the code looks like:

Code: Select all
private static void upkeep_Mana_Vault() {
      //this card is filtered out for the computer, so we will only worry about Human here
      final String player = AllZone.Phase.getActivePlayer();
      CardList vaults = AllZoneUtil.getPlayerCardsInPlay(player, "Mana Vault");
      for(Card vault:vaults) {
         if(vault.isTapped()) {
            final Card thisVault = vault;
            final String[] choices = {"Yes", "No"};
            Object o = AllZone.Display.getChoice("Untap Mana Vault?", choices);
            String choice = (String) o;
            if(choice.equals("Yes")) {
               //prompt for pay mana cost, then untap
               final SpellAbility untap = new Ability(thisVault, "4") {
                  @Override
                  public void resolve() {
                     thisVault.untap();
                  }
               };//Ability
               untap.setStackDescription("Untap "+thisVault);
               untap.setBeforePayMana(new Input_PayManaCost(untap));
               //AllZone.Stack.add(untap);
            }
         }
      }
   }
But, this doesn't get added onto the stack like I expect.

1) in it's current form, no mana cost is prompted to be paid
2) nothing is put on the stack
3) the resolve() is thus, expectedly ignored

If I uncomment the AllZone.Stack.add(untap), then it goes on the stack, but mana is not prompted for.

Obviously, my untap.setBeforePayMana(new Input_PayManaCost(untap)); is doing nothing.

What bonehead thing am I doing wrong?

Thanks,
-slapshot5

Re: screwed over by input again...

PostPosted: 06 May 2010, 16:01
by DennisBergkamp
I'm in the same boat, I still get stumped by those annoying inputs sometimes...
But in this case, nothing happens because nothing gets put on the stack... what if you replace the commented line //AllZone.Stack.add(untap) with "AllZone.GameAction.playSpellAbility(untap);" ?

Re: screwed over by input again...

PostPosted: 06 May 2010, 16:15
by Chris H.
DennisBergkamp wrote:I'm in the same boat,
`
I think we all get stumped at one point or another. I found an input while working in CardFactory_Auras. I guess that it was either Dennis or Triadasoul who wrote the code for that one aura.

That one input made sense to me. And yet most of the code is still beyond me. :wink:

Re: screwed over by input again...

PostPosted: 06 May 2010, 16:19
by slapshot5
DennisBergkamp wrote: what if you replace the commented line //AllZone.Stack.add(untap) with "AllZone.GameAction.playSpellAbility(untap);" ?
Thanks Dennis. That seems to be just what I needed.

-slapshot5

Re: screwed over by input again...

PostPosted: 06 May 2010, 21:42
by mtgrares
Input is just really confusing. I tried to make Input simple but it just isn't. I understand it, but of course I wrote it, so I hope I understand it.

Re: screwed over by input again...

PostPosted: 07 May 2010, 02:45
by slapshot5
Bad luck streak with input. I'm trying to program Recall.

"Discard X cards, then return a card from your graveyard to your hand for each card discarded this way. Exile Recall."

Seems easy enough since the "X X" mana cost is handled.

But, I tried this:

Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Recall")) {

           final SpellAbility spell = new Spell(card) {
              @Override
              public boolean canPlayAI() {
                 return false;
              }

              @Override
              public void resolve() {
                 int numCards = card.getXManaCostPaid();
                 final String player = card.getController();
                 int maxCards = AllZoneUtil.getPlayerHand(player).size();
                 numCards = Math.min(numCards, maxCards);
                 CardList grave = AllZoneUtil.getPlayerGraveyard(card.getController());
                 if(player.equals(Constant.Player.Human)){
                    AllZone.InputControl.setInput(CardFactoryUtil.input_discard(numCards));
                    for(int i = 1; i <= numCards; i++) {
                       String title = "Return card from grave to hand";
                       Object o = AllZone.Display.getChoice(title, grave.toArray());
                       if(o == null) break;
                       Card toHand = (Card) o;
                       grave.remove(toHand);
                       AllZone.GameAction.moveToHand(toHand);
                    }
                 }
                 else { //computer
                    AllZone.GameAction.discardRandom(Constant.Player.Computer, numCards);
                    for(int i = 1; i <= numCards; i ++) {
                       Card t1 = CardFactoryUtil.AI_getBestCreature(grave);
                       if(null != t1) {
                          t1 = grave.get(0);
                          grave.remove(t1);
                          AllZone.GameAction.moveToHand(t1);
                       }
                    }
                 }
                 AllZone.GameAction.removeFromGame(card);
                 System.out.println("Recall: x is: "+card.getXManaCostPaid());
              }//resolve()
           };//SpellAbility

           spell.setStackDescription(card.getName()+" - discard X cards and return X cards to your hand.");
           card.clearSpellAbility();
           card.addSpellAbility(spell);
        }//*************** END ************ END **************************
But, it prompts for input, but doesn't wait for input before popping up the AllZone.Display.getChoice(...) code.

I must be missing something simple. Does input_discard just not wait?

I think my idea is right.

-slapshot5

Re: screwed over by input again...

PostPosted: 07 May 2010, 18:39
by mtgrares
input_discard waits kinda. Input_Discard waits in the user interface, not in the code so that is why is just zips through and shows Display.getChoice(). I think you have to create a new Input that discards and in Input.clickCard() put

Code: Select all
                    for(int i = 1; i <= numCards; i++) {
                       String title = "Return card from grave to hand";
                       Object o = AllZone.Display.getChoice(title, grave.toArray());
                       if(o == null) break;
                       Card toHand = (Card) o;
                       grave.remove(toHand);
                       AllZone.GameAction.moveToHand(toHand);
                    }
The only way to do something after an Input, is to create your own Input and have Input call whatever code after the user clicks on a player or clicks on a card.

Although Dennis is probably better at this than I am. :)

Re: screwed over by input again...

PostPosted: 08 May 2010, 06:18
by slapshot5
Thanks Rares! I got it working. I feel good about Input gain because I have bent it to my will. :)

-slapshot5

Re: screwed over by input again...

PostPosted: 11 May 2010, 15:31
by mtgrares
If it helps, Input is just the State Pattern. So if you read up on it, that might help.

From wikpedia, "This pattern is used in computer programming to represent the state of an object. This is a clean way for an object to partially change its type at runtime."

Input represents the "state" of the mouse and cards/phases change the state.