Wednesday, June 11, 2008

Programming Hybrid Mana 2

I could have gone the easy route and not programmed hybrid mana at all. I could have just let the user select which cost they would play. Like if the card cost (G/W) the user would select G or W and then tap the appriopriate land.

My previous pseudocode looks correct but there were a still a few errors I had to fix. First, you have to internally reverse the mana cost because otherwise the colorless part will “eat” the colored mana the rest of the cost needs.

For example, 2WW needs to be reversed to WW2. So when you add mana, the white mana part is checked first. In other words, when you pay W toward the cost 2WW the result should be 2W not 1WW. And when you display the cost to the user, the output has to be reversed again.

Below I will example how to use my Python code that handles mana costs. Some examples of valid mana costs are
2
1 W
X U
GW
RB RB
2/G 2/G 2/G

Each part is separated with a space, which just makes it easier to split up. GW means you can pay G or W and 2/G means that you can pay either 2 or G. The class ManaCost is the class that you will be using. ManaCost is low level and a graphical component is supposed to use ManaCost and allow the user to select the appropriate land or mana. The graphical component would also tap the land if the mana was needed. An example of how to use ManaCost is given below.

c = ManaCost()
c.setManaCost(“2 W W”)
c.isNeeded(“W”) #true
c.addMana(“W”)
print c.toString() #2 W
c.addMana(“W”)
c.addMana(“U”)
c.addMana(“U”)
print c.isPaid() #true

Feel free to use this in your own projects. This has been tested thoroughly comes with a wide variety of test cases: TestManaCost and TestManaPart.

Download Python Code

Monday, June 9, 2008

Super Rares

Just in case you missed it, starting with the card set Shards of Alara there will be "mythic rares". One mythic rare for every 8 booster packs. The card picture is a preview card of a mythic rare planeswalker in Shards of Alara.

The Year of Living Changerously - by Mark Rosewater

And checkout some of the card art from Eventide.

Programming Hybrid Mana

I have talked about programming normal mana costs (2WW), but Shadowmoor features new, unusual costs like (2/B), you may pay 2 of any mana or B. Shadowmoor also brings back hybrid costs like (G/B), you may pay G or B. The reason I mention all of this, is because these new costs mean more programming (which isn’t necessarily a bad thing).

I have done some additional programming and the good news is that I can process all mana costs that Wizards has ever printed, except for the weird snow mana that Coldsnap introduced. I wanted to talk about the logic that my code uses.

Everything came together when I started thinking about dividing the mana cost into smaller parts. So “2WW” would have the parts: 2, W, W. Each individual part would know what kind of mana it needed. So the object ManaPart would have a only a few methods as shown below. The method needsMana() returns true if that mana is needed. The object ManaPart greatly simplifies the task of programming X and hybrid costs.

ManaPart
addMana(String mana)
needsMana(String) : boolean
isPaid() : boolean
toString() : String

But wait!! I haven’t shown you the magic yet. Each ManaPart object also has a method named correctManaPart(String part) that returns either true or false. This method answers the question “Does this object handle this kind of mana?” So the ManaPart that handles X costs always handles the X regardless of the rest of the cost. So I could easily handle snow mana, because it would involve just adding a new ManaPart.

I’m going to try to describe the pseudocode below. TotalManaCost is given a cost like 2WW creates the correct ManaPart for each part. In this example, the parts are “2”, “W”, and “W” so three ManaPart objects are created.
TotalManaCost.setCost(String cost):

#first divide “2 W W”, into 2, W, W
split cost into parts
for p in parts:
for m in (all manaParts):
if m.correctCost(p)
totalCost.add(create ManaPart(p))


method addMana(String mana):
#loop through to see which ManaPart needs mana
#manaPart is a list (array)
for z in manaPart:
if z.isNeeded(mana):
z.addMana(mana)
return
I know that reading the pseudo-code helps understand the overall process but seeing the actual code really helps. The method for addMana() was pasted from the actual source code.

Download Python Code – I’ll explain it in more detail in my next post.

Friday, June 6, 2008

Shandalar Patch

This is the biggest patch that I could find for Shandalar and it adds 200+ cards and allows you to mulligan. I got this patch from http://www.manalink.de

ManaLink 2.0

Wednesday, June 4, 2008

Magic For Beginners

I added a few beginner decks for those people who are learning Magic for the first time. Basically the decks are named like "0-learn-red-level-1" which means this is red, level 1 deck. Level 1 is only creatures with no abilities and then level 2 adds spells and so on. Hopefully this will help a few people.

Windows Download

Adventures in Programming: Double Clicking

While working on the next version of MTG Forge, which will be called “AI Mage”, I encountered a little snafu. The graphic library (PyGame) which also handles all events doesn’t seem to have a “double click” event. While double-clicking is common when using Windows, I guess it is rare when it comes to videogames. So I was left with a problem, how could I simulate double-clicking? I couldn’t just use single-clicking since I allow the user to rearrange the cards. So what was I going to do?

I don’t know if this solution is optimal or not, but I substituted right-clicking instead. So you use the left mouse button to move a card and the right button to play the card. Hopefully this will eliminate the nuisance of accidentally playing a card, which is very common with Magic Online.

I could have tried to devise a way to measure the time between clicks, so that I could turn a single click into a double click but I wanted a simple solution. On a side note, I was hoping that AI Mage could run on a Macintosh, but I don’t know if they use a two button mouse. I know the old Macs used only a one button mouse.

The joys of programming, oh how I love (and sometimes hate) thee. If my brain can concentrate well enough, I actually spend my time programming instead of playing videogames.

Monday, June 2, 2008

More Shandalar

MTG Forge was written because I enjoyed Shandalar so much. Shandalar being the 1998 MicroProse version of Magic: The Gathering called “Duels of the Planeswalkers” which also had an expansion called “Spells of the Ancients.” It is amazing that even 10 years ago the word “planeswalker” was around but it was not made into a card until recently. Anyways, Shandalar was great fun and featured constructed (all the cards), sealed, and a basic RPG.

After playing many days of constructed, I was beginning to get bored so I hesitantly tried the sealed deck option. As it turned out, it was even better than constructed. Although Shandalar’s sealed card pool was pretty abysmal, I always seemed to have more red cards, it was still new and exciting. MTG Forge stemmed from the simple idea that I wanted to add and remove cards from the sealed card pool.

I knew that trying to program Magic was a big task and that I probably wouldn’t ever be able to program a whole block, so MTG Forge was designed primarily for sealed games. Since sealed games usually have lots of creatures, I figured that programming the AI to use creatures would be easier than spells, since many spells depend on the board situation like Wrath of God.

In many ways Shandalar is still the gold standard. The game board and card presentation is clear and easy to understand. Selecting your phase stops is very simple. And the AI does occasionally surprise me. Shandalar’s AI seems to be able to do simple combos although it randomly shoots itself in the foot by playing Weakness (enchant creature -2/-1) on its own creature. Overall Shandalar’s AI is probably better than MTG Forge’s, but Forge does better at creature combat. I don’t necessarily take this as a putdown since Shandalar had more manpower.

There have been a few unofficial updates to Shandalar but they tend to be pretty random. I found a few patches at http://www.manalink.de but nothing is really organized. You can download Shandalar from here, but you will have to use BitTorrent. Enjoy.