Not much more than a decade ago, my brothers (and some other family) were in town for the Superbowl. Just outside, a veritable blizzard was doing all in its power to make the world entirely impassable. Inside, we were comfortably snacking and making ready for the game.
Little did I know, trouble was brewing.
As my brothers sat together across the room, the stirrings of a decidedly devious discussion had begun. They conspired together upon a single smartphone whence I overheard an ominous plot. I distinctly heard of an intended quest to brave the blizzard and acquire a set of small, magical cardboard tomes with which we might engage in a form of table-top combat. I was not familiar with these tomes. But, I was highly intrigued. And, with the roads being entirely empty, since no one else in their right minds would be on them, it seemed to us to be "perfect timing" for such a quest.
And thus, we set out through an unrelenting blizzard, over neigh impassable roads, where no other fool dared tread, on Super Bowl Sunday, mere hours before kickoff to acquire Magic the Gathering (MTG) starter boxes.
Our unfamiliarity with the game was part of the appeal when we began to play. We started with basic cards and a cheat-sheet of the rules. We didn't even know about the game's "stack" mechanism. And so, we imbibed, we played, and we debated the rules.
Roughly once or twice a year for some years, we would similarly get together, buy a few boosters, and carry on in the same fashion. We knew a little more of the rules each time and expanded our decks slightly each time from boosters alone or (on special occasions) a deck builder's toolkit. Each of us were just as likely to walk away from each game with a victory, none of us having made any serious investment in the game.
It is in these early stages where I created the MTG Deck Analyzer to help us understand some of the statistical nuances of deck building. Some of us were growing frustrated with coming up short on mana or missing our win condition. And, to be honest, this project really helped bolster my own interest in the game for awhile. It combined and entangled the game with software making and math — both of which I am interested in, and one of which I actually have some years of experience in!
But, the years went on. We became more well-versed in the rules. We had accumulated more cards. And some of us, at times, invested more than the others in finding and buying individual cards to create a fine tuned — and an often truly competitive — deck. Things became unbalanced. And, most of the "newness" and debate over the rules had vanished. Overall, the outcomes were now heavily correlated to our individuals investments in the game.
This progression made for some MTG nights that just weren't quite as fun as they had been.
It's not always fun to show up to game night, having had almost zero time to invest in the game, to be completely trounced by someone who has invested tons of time and money into learning something of the meta-game and invested into good, individual cards.
You know?
So, I've been toying with the idea of an open "trading card" game, where you can "mint" your own cards, provided that they (and your decks) follow some open source rules.
Let's call it Open Mint TCG.

It could ...
- Have open-source, programmatic rules.
- Be mostly stable, limiting the need to "keep up."
- Evolve through RFCs if needed.
- Let anyone create cards.
- Limit card population and impose rarity with fun crypto math.
- Create an aftermarket without being dominated by it. (Hopefully)
I don't have much detail in mind beyond that. But, there are two basic lines of thought to consider. Both hinge on controlling for rarity through cryptographic hashing.
What is Cryptographic Hashing?
A "normal" hash function takes some input data and maps it to a number within a fixed range. We usually represent hashes (the output number) as a fixed-width hexadecimal string. A simple example could be to count the number of lower case letters in a string, divide by 7, and return the remainder (using the modulo operation).
$$\text{sillyHash} = \text{count}\!\left(\text{lower_case in string}\right) \bmod 7$$
Some example hashes:
Input String | Lower Case Letters | Hash Output |
---|---|---|
Input string a. | 11 | 4 |
Input string A. | 10 | 3 |
Input string b. | 11 | 4 |
A cryptographic hash function produces a much larger range of numbers, has chaotic looking output, and is impossibly hard to find collisions for. (A collision is when two distinct inputs produce the same output.) So, if you hash any input string, it is incredibly unlikely you'll be able to find another input string that produces the same output. On top of that, the output values are chaotic enough that you can't even predict characteristics of the output ahead of time.
Let's look at SHA-256
(a well-known cryptographic hash function) as an example to see what I mean. Almost any set of nearly-identical strings should produce wildly different outputs:
Input String | SHA-256 Output |
---|---|
Input string a. | 3f7965f07cb9379b6ff88a2e0c34e7a6bec7d1b7c675ef81f0499decdb4151e3 |
Input string A. | c6ec603f4391a7339e21c20a12ef1004065bfb4cde9c825783893e721cabd5c6 |
Input string b. | 14efacde322be94ff95a525b60b5a78b026aad74834a6862a2527e4ae5c5a28c |
You can see that these outputs look completely unrelated. In the cryptocurrency world, we leverage this "wild" behavior to force miners to "prove they did work" to mine coins. The act of mining crypto essentially consists of searching for a nonce (a meaningless number) that can be added to some transaction data to produce a "valid hash." We then put restrictions on what a "valid hash" looks like to intentionally make it difficult to find. Thus, mining crypto requires a lot of computation. And, whoever finds a valid hash for a block of transactions first wins the bounty.
To help visualize this, let's define a "valid hash" to be one that contains 11 or more zeros. We'll test this out by appending nonces to ends of the example strings from above. And, for this example, we'll only consider the first 1000 possible nonces.
Input String | SHA-256 Output | Zeros |
---|---|---|
Input string a. (123) | a470d02c405d0218e80c87cad627bb6f7e0d20d0fd2b30ee60808374d28175b0 |
12 |
Input string A. | UNSOLVED |
N/A |
Input string b. (458) | b807b2aa110de40017799ddc5f0c8745a7d600cebde5b38fd90eb5053d800085 |
12 |
You can see that in our very simple example, it took hundreds of trials to validate two of the strings, and one of them wasn't viable at all. As we increase the number of zeros required, or require that zeros be consecutive, or set upper or lower bounds on the numeric value of the string, we can control how much work is needed to find a valid hash with a lot of precision.
It's important to remember, there's no known way to do any of this "backwards." This is the value of cryptographic hashing. You can't reverse the function from a desired output to find an input. You just have try a bunch of inputs and see what you get. And by carefully controlling which output characteristic are valid, you can control how long it takes to find a valid input on average.
So, with this basic understanding of cryptographic hashing, let's look at the high level options I have in mind.
Option 1: Targeted Mining
In this option, players (or dedicated miners) would hand-pick the card attributes they want for each card and then try to mine it. (Or mint it.) For a grossly simplified example, let's pretend that a card can have two properties: Health (\(h\)) and Attack (\(a\)). From there, we can decide how rare a card should be. And, we can state rarity as a probability of mining the target card in any given minute: $$P = \frac{4}{2^h + 2^a}$$
We can enforce this rarity through the cryptographic hashing properties explained above. This allows us to create intrinsic, mathematically enforced card rarity. We can make it so that legal "unicorns" could still exist — but be very rare. And, if we want, we could make "god" cards possible — but almost entirely nonexistent. And, this would all be enforced by the laws of math and physics. Anyone can mint cards, because the laws of physics enforce card rarity.
Here are some example card configurations using the example rarity formula. In addition to providing \(P\), I've included the average number of minutes expected to mine an individual card of each configuration:
Health | Attack | \(P\) | Avg. Minutes to Mine |
---|---|---|---|
1 | 1 | 100.0000% | 1 |
1 | 2 | 66.6667% | 2 |
2 | 2 | 50.0000% | 2 |
1 | 5 | 11.7647% | 9 |
5 | 1 | 11.7647% | 9 |
5 | 5 | 6.2500% | 16 |
1 | 10 | 0.3899% | 257 |
10 | 10 | 0.1953% | 512 |
1 | 20 | 0.0004% | 262145 |
20 | 20 | 0.0002% | 524288 |
So, this option lets players build almost anything what they want while also providing reasonable impedance around overpowered nonsense. This option is really appealing to me when I think of how little time I have to sift through cards, try to find new strategies amongst them, and play test before sitting down for a "friendly" match. Instead, I could "engineer" a fairly precise build, see roughly how long it will take to mine, and then, provided I can mine it before the heat death of the universe (or even just my next game), I just click "Start Mining" and wait.
However ... this option has exactly none of the excitement or surprise that comes with opening a new pack of cards. And, that brings us to ...
Option 2: Blind Mining
In this option, we sort of poke at the other side of hashing algorithm. Since the output of a hash appears "random", we would extract card properties directly from the hash.
Instead of inputting the card properties we want, we'd input some noisy looking "genetic" code. We'd then hit the "Start Mining" button, and our mining app would search through candidate card genes at random — one by one. We would include viability hashes to make mining require work, the same as Option 1, but we would then extract card properties directly from hashing outputs. This would ensure miners cannot hand-pick their cards, keeping them "blind" to what they'll get.
But, it could also make mining cards exciting and fun.
Taking a very small example, let's say that our "genetic code" is any six character string consisting of the letters a, b, c, and d. This schema gives us 4096 valid genetic codes. We could then say that our viability, health, and attack formulas look like this:
$$\text{isValid} = \text{count("0" in sha256(code + ":viability")) > 8}$$ $$\text{health} = \text{floor}\!\left(\frac{\text{count("0" in sha256(code + ":health"))}}{2}\right)$$ $$\text{attack} = \text{floor}\!\left(\frac{\text{count("0" in sha256(code + ":attack"))}}{2}\right)$$
So, if we have "bcdddb"
as a genetic code, we'd get the following:
Attribute | Hash | Result |
---|---|---|
Viability | 64780e27aa5a3ef93fa0168238c5d6120cd2d033ed04a9022ff81aa00ed009f3 |
Legal |
Health | 62c9974b225d4b012e411650f2f088598b5845734a21cb2ea6e38dc4fe3cc5e6 |
1 |
Attack | 90f5fe752569e270388a57179c765d800809b9af209f196892eeea200d37651f |
4 |
Given the small "genetic space" of this example, we can enumerate all possible cards to see what the distribution of cards looks like in our very limited example scheme:
Health | Attack | Count |
---|---|---|
4 | 2 | 1 |
3 | 1 | 1 |
4 | 3 | 1 |
1 | 4 | 1 |
4 | 0 | 1 |
0 | 3 | 1 |
2 | 5 | 1 |
4 | 1 | 1 |
0 | 2 | 1 |
3 | 0 | 2 |
3 | 3 | 2 |
1 | 0 | 2 |
4 | 4 | 2 |
2 | 2 | 3 |
0 | 1 | 3 |
3 | 2 | 5 |
1 | 3 | 6 |
2 | 3 | 7 |
1 | 1 | 8 |
1 | 2 | 10 |
2 | 1 | 16 |
Out of a candidate pool of 4096 possible genetic codes, 75 of them are legal. And, due to the lower probability of hashes containing many zeros, the population of high power cards is lower than the population of low power cards. With a longer genetic code and some tuning around the attribute extraction, we could easily end up with a distribution that looks similar to that of a "real" trading card game.
In Both Options ...
I would anticipate that we want cards to "expire" or "phase out" of standard play formats. They could have universal times-to-live or be pinned to a particular "season". Either way, we probably don't want to sit down at a table for a standard game and face off against "ancient god" cards that are so rare and powerful they took someone months or years to mine. (At least not until the end of a season, perhaps.)
Due to the open nature of the game, any valid, "in-season" card is allowed at a table. You can mine cards using an app from your computer, in a cloud environment overnight, or buy them in a marketplace (Physical or digital.). When you have cards you like, you can just print them out and bring them to the table. Or... you could pay a printer to get professional copies of your cards.
When you sit at a table to play, you'll normally just trust your friends when they say their cards are legal. But, if you doubt your "friends", each card will include a QR code you can use to validate its legality. Scan the code to see everything you need to know about it (including its rightful owner).
So, where do I go from here?
Well, from here, I need your feedback, and I need to know if you're interested. If you are, visit the Github repository where all of the open source specifications, RFC process, and technical implementation will live. Star it. Follow it. And, if you have opinions or ideas, open issues (or comment on them) with your feedback.
For what it's worth, I don't think I'm fully done playing MTG in life. After all, I am running and operating an MTG Deck Analyzer that is still seeing a growing user base and some exciting features left to build. But, I'm also pretty eager start down this open format path if it can recreate some of the things I like about MTG ... without forcing me to pay to win.
So, hopefully I'll see you on Github! 🍻 I'd really love to build this. But, ideally not alone ...
If you enjoyed anything about this article, subscribe so you don't miss out!
Published: 9/1/2025.
Topics: computer science, crypto, crypto mining, games, mtg, open mint tcg, trading card games