Turning Magic Cards into OSR Monsters

This was a fun project that pulled inspiration from a number of places. First, in
my last two campaigns I turned MTG land cards into hex maps. I love the art in
Magic and it provides such great inspiration — my next project is a series of
TikToks using random land cards to build a world. Second, at a creator meet-up
someone had codified MTG keywords for Mörk Borg. Third, I really want someone to
make a TCG version of a TTRPG. But also, please don’t. I’ll go bankrupt.

Intro aside, the tool’s below and everything after it is how it works.

Draw a few and you’ll spot a pattern: while these are perfectly plausible
monsters, they’re sometimes a bit too strong or weak for their level. They
average out fine, but you’ll find the odd three-drop that swings like a level 5,
how loose it gets depends on the stat.

See the Pen MTG TTRPG Monster Creator by Gregory (@worldsbywally) on CodePen.

I actually think this is a feature and not a bug. There are a few reasons it
happens: keywords that let you cheat a creature out early (Convoke, Affinity,
Delve) leave it underpowered for its printed cost, and multicolour cards run a
bit stronger. Both are exactly what you’d expect from a Magic card, so I decided
not to over-correct for either.

The core stats

The most boring way to look at a monster is its AC, HP, attack bonus and damage.
That’s where I started. Magic gives you two numbers for this; classic TTRPGs use
four.

I did some analysis to find the averages by level in both, then built a
transformation mapping average power by mana value onto average attack bonus by
level, and the same for toughness onto AC. That gave me two formulas:

Attack bonus = card power
AC = 11 + toughness/2 (round up) + Dex adjustment

The attack one genuinely surprised me. There is no transformation. Card power
climbs +0.82 a level; the attack bonus of a real monster climbs +0.71. Magic’s
cost curve and an OSR threat curve are, near enough, the same curve. I tried some
more complicated ideas before realizing that using it exactly as-is worked best.

AC was the opposite. Toughness climbs +0.79 a level where AC climbs +0.36 —
almost exactly double. That means raw toughness is simultaneously too low at
level 1 and too high at level 10, which no amount of adding a constant will fix.
It had to be halved.

For HP I found it’s roughly 4.5 per level, so that’s the base, plus Constitution
scaled by tier, since I wanted Con to actually matter at high level. Damage and
number of attacks came from the same kind of look at averages by level.

The next set of adjustments came from the colour pie.

The colour pie

Magic is built on ally and enemy colours, and colour tends to define a card’s
abilities and archetypes. We could debate endlessly how to map this, but I
decided to put the stats on the colour pie in between the colours:

    W --- Wis/Int --- U
   /                    \
  Con                   Dex
   \                    /
    G                  B
     \                /
      -- Str --- Cha --
              R

Reading around the wheel: White–Blue is Wis/Int, Blue–Black is Dex,
Black–Red is Cha, Red–Green is Str, Green–White is Con.

Then each colour votes: its two neighbouring edges go high, and the edge
directly opposite, between its two enemies, goes low.

ColourVotes highVotes low
WhiteCon, WisCha
BlueDex, IntStr
BlackCha, DexCon
RedCha, StrWis
GreenCon, StrDex

Add up the votes from a card’s colour identity: positive is high, zero is mid,
negative is low. Allied pairs stack their votes and come out spiky. Enemy pairs
cancel each other and come out flat. Colourless votes for nothing and sits on mid
across the board.

(White takes Wis off the shared White–Blue edge and Blue takes Int, so each ends
up with exactly two highs. Red, sitting opposite, dumps Wis on its own. Six stats
didn’t work perfectly with five colors.)

That told me which stats should be high, mid and low. Next I had to find what
those are actually worth, which got a bit more convoluted but ended up here:

LevelHighMidLow
1+10−2
2+20−2
3+2+1−2
4+3+1−2
5+3+1−2
6+4+1−2
7+4+1−2
8+4+2−1
9+5+3+1
10+5+3−1

The high and low numbers took the highest and lowest stat for each monster, then
the mode (most common) for the high, and the median (the middle) for the low.
The mid value is just the median across all stats for monsters of that level.

Unlike monsters in Pathfinder or D&D, OSR monsters mostly don’t derive AC and HP
from their stats the way players do. But I wanted to carry some of that theme
over, so each stat now pulls a real lever:

StatWhat it does
StrPicks the damage die — low, middle or high column for its level
DexAdjusts AC by its distance from the level’s mid value
ConAdds to HP, scaled by tier
Int / Wis / ChaThe best of the three becomes the casting stat

The Dex adjustment is deliberately lopsided: a creature gets the full bonus
upward but only half the penalty downward. Green dumps Dex, and without that
softening a 6/6 trampler was landing at AC 11. That just felt wrong, so I
adjusted it.

Creature types and keywords

The final layer adds abilities from creature type and keywords.

First, casters. Wizards get arcane spells, Clerics get divine ones, and their
casting modifier comes off the colour pie like everything else. Each gets one
random spell per spell tier it could reach at its level, and because they’re
rolled fresh every draw, pulling the same card twice shuffles its spellbook.

Then I looked at the most common creature types and keywords and started throwing
out abilities. That needed a couple of small formulas:

  • Ability DC = 10 + half level, rounded down
  • Area attacks (a dragon’s breath, say) = ⌊level ÷ 3⌋d8, minimum 1d8

Here’s a sample of what’s in there now:

TriggerAbilityEffect
DeathtouchDeathtouchFirst attack also deals 1d4 Con damage
TrampleTrampleOnce per turn on a hit, move to another target within near and attack at disadvantage
VigilanceVigilantOnce per round, strike a target moving into or out of close
LifelinkLifelinkRegains half the damage it deals
RegenerateRegenerateRegains HP at the start of its turn
DefenderDefenderDamage die steps down once, +1 AC
Double strikeDouble StrikeOne more attack than its level would give it
HasteHasteAdvantage on initiative
HexproofHexproofAdvantage on saves against spells targeting it
InfectPoisonDC save or take 1d4 damage of monsters best stat
Undying / PersistUndyingOn death, DC 10 Con save to return at 1 HP
DragonBreath WeaponExhales over double near, DC save or take the area damage
DwarfStoutAdds its level to its HP
GoblinWaryCan’t be surprised
RogueSneak AttackExtra damage against an unaware target
VampireBlood DrainDrains Con and heals itself

There are about forty of these now. Send me a note on other keywords and what you
think they should do, and I’ll consider adding them.

A couple of these are advice rather than mechanics. Abilities that let you cast
things faster — Convoke, Affinity, Delve — leave a creature small for its printed
cost, so those cards get a note suggesting you run them a level lower. The
discount is real and grows with cost: Delve creatures average 1.3 power below
the mean for their mana value.

The results

I haven’t playtested these yet, so I’m very open to feedback.

This is where that “depends which stat you look at” comes in, and it surprised
me. I plotted the mean and interquartile range by level for both attack bonus and
AC. The IQR is the distance from the 25th to the 75th percentile, and it does a
reasonable job of capturing dispersion. The two stats behave nothing alike.

Attack bonus lands almost exactly on the average but varies wildly. The
generator’s IQR is 1.90 against the bestiary’s 0.85 — more than twice as
wide. At mana value 7 the published monsters occupy a middle half of exactly
+6 to +6, no width at all, while the cards run +4 to +7.

AC does not do this. Its IQR comes out at 2.17 against 1.95, essentially the
same spread.

While untested, I think I like the variance. A monster with an attack a bit too
high or low, that fits the description better, feels right and leads to better
stories than a pile of monsters that are identical by level.


Magic: The Gathering is a trademark of Wizards of the Coast, which does not
endorse this tool. Card images and data come from Scryfall. Shadowdark is copyright of Arcane Library LLC, this post has no association with.

Leave a Reply