For those who are unfamiliar with Magic (as it's often called informally), casting costs are values that represent the "mana" needed to cast a "spell". Mana comes from different sources, and has certain colors assigned to each type of mana. For example, a hypothetical "blue" spell may require 2 blue mana, and two mana of any color, whereas another spell may require 1 green mana, 2 red mana, and 3 mana of any color. There is a finite number of mana colors (red, blue, green, black, white, and colorless (which is agnostic of mana color, in other words, colorless casting costs can be paid for by any color of mana). So, supposing we had a spell that costs 2 green, 1 blue, and 3 colorless, it could only be paid for with 2 green, 1 blue, and 3 of any combination of colors. What would be some effective ways to represent this in a program? I'm currently writing this in Java, but generic advice would also be nice. If you have any questions, comment, and I will clarify my question if need be.
-
Nothing, as of yet. I'm just getting into Java, and I figured that modeling a complex system that I'm familiar with (MTG) would be the best way to learn the language. I'm just looking for advice. – wafflesausage Aug 07 '14 at 00:47
3 Answers
The natural way to represent the mana cost of an MtG spell is as a mapping from mana types to (non-negative) integers; in Java terms, a Map<ManaType, int>
, where ManaType
would most reasonably be an enum.
Of course, there are other ways you could represent mana costs, too, e.g. as vectors of integers. However, the nice thing about the map representation, besides its naturalness, is that it's easily extensible, if and when you find yourself needing to represent, say, Phyrexian mana or snow mana or that silly pink mana from Unhinged.
In many other languages, like JavaScript, such a map could also be conveniently initialized using a literal syntax like:
manaCost: { colorless: 1, green: 2 }
Alas, Java still has no collection literals, but at least you can use double brace initialization to get something vaguely similar.

- 1
- 1

- 49,047
- 9
- 93
- 153
-
Ah, thanks for pointing out that it should be non-negative. Don't want to break the game more than it already is ;) – wafflesausage Aug 07 '14 at 00:44
I would have a class called ManaCost, which every card needs.
enum ManaColor {
RED, GREEN, BLUE, BLACK, WHITE;
}
class ManaCost {
private int colorlessCost;
private HashMap<ManaColor,Integer> colorCosts;
public int getConvertedManaCost(){
int convertedManaCost = 0;
for(Integer colorCost : colorCosts.values()){
convertedManaCost = convertedManaCost + colorCost;
}
convertedManaCost = convertedManaCost + colorlessCost;
return convertedManaCost;
}
public Integer getColorCost(ManaColor color){
return this.colorCosts.get(color);
}
}
class Card {
private ManaCost manaCost;
...
}
Yep, I do play Magic :) ConvertedManaCost = sum of all mana costs.

- 602
- 1
- 10
- 20
The casting cost representation can be a very straightforward class or struct. Been a while since I wrote Java, so here's a C# example that should translate to Java in a straightforward manner (anyone feel free to edit this answer to make it correct Java):
class SpellCost
{
public int GreenCost { get; set; }
public int RedCost { get; set }
// etc
public int AnyCost { get; set; }
}
The algorithm that deducts mana points for casting a spell would deduct from the player's current mana directly for each color (voiding the casting if it would drop the mana for any of those colors to a negative value), then use some formula to elect which mana pool to deduct AnyCost from (again voiding the casting if total remaining mana is less than AnyCost).
In Magic the number of different mana pools is rather small. If you were dealing with a large and/or variable number of pools, you could instead use a HashMap<ManaType, int>
keyed by ManaType with values representing the cost for that mana type.
When casting the spell, you would then iterate the HashMap<ManaType, int>
, deducting each mana cost from the player's mana pool and voiding the casting if any of the mana costs cannot be paid.

- 147,927
- 63
- 340
- 553
-
Why not using Maps instead of creating a method for every color? Avoid repeating code :) – Breno Inojosa Aug 07 '14 at 00:14
-
That is what I wanted to express with `Dictionary` (which is the .NET term). I'll update my answer to use the correct Java terminology. – Eric J. Aug 07 '14 at 00:40