DraftZero: an FDN sealed deck builder learned from self-play

A deck builder for Magic: The Gathering Foundations (FDN) sealed, trained only from games it played, never from human decklists. Given a sealed pool (about 81 non-basic cards from six packs), it builds a 40-card deck.

What it learned

Trained only on its own games, the builder learns to build simple, white-based creature decks that the bot playing them can pilot well: white in about 85% of its decks, white-green in 42% (human players: 17%), fewer tricks and card-advantage spells than people play. More search in its training games made its decks steadily more human-like. It is a deck builder for its pilot, gorge's search with DraftZero's network, not a model of how strong humans build.

Results

Win rate of the builder's decks against the decks humans built from the same pools (17lands data), with both decks played by gorge's search at 100 simulations. One standard error is about 1 point at 2,000 games.

Builder Sealed test pools (1,000) Draft test pools (1,000; never trained on) Cards shared with the human deck (of 40, sealed)
sealed_builder_phaseC_gen1.pt (the final model) 63.8% of 2,000 19.9
sealed_builder_phaseB_gen4.pt 63.8% of 2,000 57.5% of 2,000 19.2
17lands heuristic (best two colours by games-in-hand win rate) 55.2% 50.9% 20.5
A builder trained to imitate the human decks 53.0% 52.7% 23.6

All numbers are in results.json. The win rate measures how well a deck suits this pilot: the human decks' strengths (tricks, card advantage, planeswalkers) need play the pilot doesn't have.

Files

File What
sealed_builder_phaseC_gen1.pt The final model: an ensemble of 5 deck value networks, trained on self-play games at 100 simulations (phase C, generation 1)
sealed_builder_phaseB_gen4.pt The phase B generation 4 ensemble (games at 25 simulations), the other builder scored on the test pools
FDN_cardnames.txt The 286 FDN card names, in the order of the networks' count vectors (17lands' column order)
example_pool.json One sealed pool (17lands val pool 0) to try it on
results.json The evaluation numbers above, with standard errors
SHA256SUMS Checksums of every file

The model

Each ensemble file holds five deck value networks (about 26,000 parameters each) and a little metadata (the land counts the training games covered; whether castability is on). A network scores a whole deck; it never outputs one.

  • Input: a deck as a count vector over FDN's 286 cards (basic lands included), plus a fixed table of 76 printed facts per card (mana cost, types, power and toughness, keywords, rarity, mechanics tags, colours a land makes), stored inside the file. Each card also has learned identity parameters (an embedding and corrections), which start at zero.
  • Output: a deck strength s(deck). Trained as Bradley-Terry on game results: P(deck A beats deck B) = sigmoid(s(A) − s(B) + β · [A played first]).
  • Parts: an additive card-quality term weighted by how castable the deck's mana makes each card; a structure MLP over deck totals built from learnable card roles (land-ness, effective mana value, creature-ness, colours made); a DeepSets context term. Details in the report, §4.

Building a deck is a search against the ensemble's mean score:

  1. Score a quick deck for each colour combination.
  2. Refine the best four by one-for-one swaps until no swap helps.
  3. Keep the best.

Use

git clone --branch sealed-builder-v1 https://github.com/danieljbrooks/draft-zero.git
cd draft-zero && pip install numpy torch
huggingface-cli download danbrooks/draftzero-fdn-sealed-builder --local-dir hf-sealed
import json, sys
import numpy as np
sys.path.insert(0, "gorge")
from sealed import model as M, build as B, decks as D

ens = M.Ensemble.load("hf-sealed/sealed_builder_phaseC_gen1.pt")
pool = D.C.vec(json.load(open("hf-sealed/example_pool.json"))["pool"])    # {card name: copies}, non-basic cards
quality = np.mean([m.quality().detach().numpy() for m in ens.members], 0)
deck = B.build(pool, B.Objective(ens, "mean"), quality, lands=ens.meta.get("lands"))
print(D.C.dict(deck))                                                       # {card name: copies}, 40 cards

Building takes about a second per pool on a laptop CPU. FDN only: the networks know FDN's 286 cards.

Training

  • Data: the networks never saw a human deck. Self-play games in gorge between decks the builder made from 6,240 17lands sealed pools (pool contents only): about 280,000 games in the final model's lineage, out of 1.1 million in the project.
  • Curriculum:
    • 3 generations of games played by gorge's heuristic bot, the first on random decks;
    • 7 of games played by the search at 25 simulations;
    • 2 at 100 simulations.
  • Each generation: about 800 pools × 5 exploratory decks, 10,000-40,000 games.
  • Compute: a laptop, a shared 2× RTX PRO 6000 box (r1, courtesy of Dama) and community RunPod pods; about $9 of cloud compute.

Licence and data

The weights are released under CC BY 4.0. Pools and human decks come from 17lands' public datasets (CC BY 4.0); 17lands does not endorse this project. Card facts come from XMage (MIT) and 17lands' card table. No Forge card scripts (GPL-3.0) are included.

Downloads last month

-

Downloads are not tracked for this model. How to track
Video Preview
loading