Page 1 of 1

Discard random as cost

PostPosted: 20 Nov 2010, 18:51
by Malacath
Hi there,

I'm totally new to Forge coding, but have some basic Java knowledge. I wanted to try and add a single card and just click random card on magiccards.info and got a Stormscale Anarch.
The code I did so far:
Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Stormscale Anarch")) {
           
           Target tgt = new Target("TgtCP");
           Ability_Cost abCost = new Ability_Cost("0", cardName, true);
           
           final Ability_Activated ability = new Ability_Activated(card, abCost, tgt) {
            /**
             * ToDo: Discard as a Cost!
             */
            private static final long serialVersionUID = 1L;
            int damage = 2;
               
                @Override
                public void resolve() {
                   Player player = card.getController();
                   if(player.equals(AllZone.HumanPlayer)) {
                      PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, AllZone.HumanPlayer);
                        CardList list = new CardList(hand.getCards());
                        list.shuffle();
                        Card c = list.get(0);
                        c.getController().discard(c, null);
                        if(CardUtil.getColors(c).size() >= 2) {
                           if(getTargetPlayer() == null) {
                              getTargetCard().addDamage(damage*2, card);
                           }
                           else {
                              getTargetPlayer().addDamage(damage*2, card);
                           }
                        }
                        else {
                           if(getTargetPlayer() == null) {
                              getTargetCard().addDamage(damage, card);
                           }
                           else {
                              getTargetPlayer().addDamage(damage, card);
                           }
                        }
                   }
                   else {
                      PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, AllZone.ComputerPlayer);
                        CardList list = new CardList(hand.getCards());
                        list.shuffle();
                        Card c = list.get(0);
                        c.getController().discard(c, null);
                       
                    }
                }//resolve()
               
                @Override
                public boolean canPlayAI() {
                    Card[] hand = AllZone.Computer_Hand.getCards();
                    return (hand.length > 0);
                }
               
                @Override
                public boolean canPlay() {
                   Card[] hand = AllZone.Human_Hand.getCards();
                    return hand.length > 0 && super.canPlay();
                }
               
            };
            ability.setDescription("2R, Discard a card at random: Stormscale Anarch deals 2 damage to target creature or player. If the discarded card was multicolored, Stormscale Anarch deals 4 damage to that creature or player instead.");
            ability.setStackDescription(card.getName() + " - Stormscale Anarch deals 2 or 4 damage to target creature or player.");
            card.addSpellAbility(ability);
           

        }//*************** END ************ END **************************
I have some problems now:
1) The discard random is not a cost but rather an effect, meaning you can cast your whole hand and still do 2 damage without discarding
2) I can't test the card for AI, because whenever I run Forge and finish a turn I have to discard my whole hand and still the AI's turn doesn't start
3) How do I commit a new card when it's finished(without breaking anything)
4) Which main type do I have to run to get into Forge Main Menu (when right-clicking and "Run As .."

I hope my questions aren't too dumb... thanks for helping in advanced.

greetings Malacath

PS: I'm looking forward to be able to contribute to Forge, hope that will happen someday ^^

Re: Discard random as cost

PostPosted: 20 Nov 2010, 21:22
by Sloth
Hello Malacath!

We already have discard at random as a cost. Look into Cost_Payment.java. Cheking what card was discarded hasn't been done before though (maybe look at the sac cost, I think something like this has been done there).

Re: Discard random as cost

PostPosted: 21 Nov 2010, 05:01
by friarsol
Just as Sloth said with a bit more explanation.

Random discard already exists in Ability_Cost. When you create an Ability_Cost, don't just put "0" put the cost for the ability. For your card that would be "2 R Discard<1/Random>"

Currently the discarded card isn't recorded when the cost is paid for (which would happen in Cost_Payment), but you could probably follow the example that Sacrifice does, since this is implemented for Fling.

This is the key line in Cost_Payment.sacrificeType()
Code: Select all
payment.getAbility().addSacrificedCost(card);
If you don't feel comfortable doing that just let me know, and I'll try to get around to it sometime soon.

I always run Gui_NewGame when debugging. I'm not sure if that's what you are asking?

Re: Discard random as cost

PostPosted: 21 Nov 2010, 11:13
by Chris H.
friarsol wrote:I always run Gui_NewGame when debugging. I'm not sure if that's what you are asking?
`
I have been using Eclipse for almost two years now and this still happens to me. I build the project and when I attempt to run the code Eclipse or I will select to run from the wrong class file. This can cause some weird results.

Sol is right about this one. Try selecting:

Run -> Run As -> Java Application -> Gui_NewGame.

Re: Discard random as cost

PostPosted: 21 Nov 2010, 17:57
by Malacath
Thank you, I still didn't actually get it working.

I always run Gui_NewGame when debugging. I'm not sure if that's what you are asking?
Yes thanks, I always ran GUI_Winlose and pressed quit, therefore a lot of things were messed up.

This is the key line in Cost_Payment.sacrificeType()
Code: Select all
payment.getAbility().addSacrificedCost(card);
So do I get it right, that I have to add a discardedType to Cost_Payment or is that unnecessary? Actually I understand this line as it would only write into a cardList and the card has to be known, but my main problem is to find out which card is randomly choosen to discard. I would need something that writes the random card into a variable as it's choosen.

Maybe I'm missing something, or maybe a lot ^^.

Re: Discard random as cost

PostPosted: 21 Nov 2010, 19:53
by friarsol
Actually I was just looking in this code, and it's going to work a little differently than how sacrifice works. I'll see if I can get something functional for you to link into.

Re: Discard random as cost

PostPosted: 21 Nov 2010, 23:05
by friarsol
I may have gotten a little carried away. But knowing info about a discarded card was something that I had planned to do and it turned out pretty easy once I started looking into it.

I ended up adding some small bits of code to get this to work with one of the new Ability_Factories, instead of writing up a whole card block in the code.

Code: Select all
Name:Stormscale Anarch
ManaCost:2 R R
Types:Creature Viashino Shaman
Text:no text
PT:2/2
A:AB$DealDamage | Cost$ 2 R Discard<1/Random> | Tgt$ TgtCP | NumDmg$ X | SpellDescription$ CARDNAME deals 2 damage to target creature or player. If the discarded card was multicolored, CARDNAME deals 4 damage to that creature or player instead.
SVar:X:Discarded$CardMulticolor.4.2
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/stormscale_anarch.jpg
End
If you have any questions about the final data object feel free to ask.

Re: Discard random as cost

PostPosted: 22 Nov 2010, 14:55
by Malacath
So is it generally a better idea to script (or whatever it's called) the cards into the *.txt files rather then writing Java code for them?

Re: Discard random as cost

PostPosted: 22 Nov 2010, 15:07
by friarsol
Yep much better idea.

If you create cards as data objects, you are reusing code that has already been tested, plus the AI is more likely to be able to use the card (since that code should have at least basic AI in place). It also makes it way easier to fix mistakes, since the code doesn't need to be re-compiled.

We have a good amount of information on the Wiki most specifically in the New Structures portion.

Re: Discard random as cost

PostPosted: 22 Nov 2010, 15:22
by Rob Cashwalker
There will likely always be cards in Forge that will remain hard-coded. Our goal is to implement as much as possible using scripts for the reasons friarsol mentioned.
Reading through various blocks of code in CardFactory_ files, you may get a sense that "you've seen this code before". Those cards may all share a mechanic, which is a good candidate for a script conversion. Finding the common code, identifying the variable parts, enhancing the AI, re-writing it all together into a new script keyword, I find to be more rewarding than doing a single card. Not only does it allow us to clear out the hard-coded cards to reduce our compiled size, but it opens the door to all variations on the mechanic that may have been printed that we didn't already have, and any variation yet to be printed.

Re: Discard random as cost

PostPosted: 23 Nov 2010, 12:28
by Malacath
OK, thanks a lot.
I hope I will find some time to just add some cards, or help with anything else, but yesterday school started bugging me again.

greetings Malacath