Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MTG Draft Assistant

Given the cards in a booster pack and the cards you have already picked, this model ranks which card to take next. It generalizes to unseen sets: a card it has never seen during training still receives a representation for zero-shot inference.

The model was trained on processed draft data from 30 different sets from 17Lands. SOS and MSH were excluded from training and evaluated as chronological holdouts.

Metrics

Results for the validation-selected seed 42 checkpoint. Lower NLL is better; SOS and MSH did not participate in training or checkpoint selection.

Split Top-1 Top-3 NLL
Known test 68.26% 95.17% 0.8184
SOS holdout 50.49% 85.41% 1.3349
MSH holdout 51.50% 85.95% 1.2839

Known and holdout metrics

Usage

Stateful API

from mtgda import MtgDraftAssistant

assistant = MtgDraftAssistant.from_pretrained("pier97/mtgda")

draft = assistant.new_draft()

for recommendation in draft.see([
    "Lightning Bolt",
    "Llanowar Elves",
    "Cancel",
]):
    print(recommendation.name, recommendation.probability)

draft.pick("Lightning Bolt")

Stateless API

from mtgda import DraftStep, MtgDraftAssistant

assistant = MtgDraftAssistant.from_pretrained("pier97/mtgda")

history = [
    DraftStep(
        pack=("Lightning Bolt", "Llanowar Elves", "Cancel"),
        pick="Lightning Bolt",
    )
]

recommendations = assistant.rank(
    history,
    ["Shock", "Giant Growth", "Murder"],
)

Unseen and custom cards

Cards can be passed as names from the bundled catalog or as Scryfall-style dictionaries for custom, preview, or newly released cards.

custom = {
    "name": "Made-Up Card",
    "type_line": "Creature - Goblin",
    "mana_cost": "{1}{R}",
    "power": "3",
    "toughness": "1",
    "oracle_text": (
        "Haste. When this creature enters, "
        "it deals 2 damage to any target."
    ),
    "layout": "normal",
}

recommendations = assistant.rank(
    [],
    [custom, "Giant Growth", "Cancel"],
)

Card representations are cached by the assistant after their first encoding.

How it works

  • The card encoder combines a 320-dimensional MPNet text representation, 16 numeric features, and 207 deterministic mechanic flags into a 543-dimensional card vector.
  • The draft model is a two-layer causal encoder-decoder transformer with 320-dimensional hidden states, eight attention heads, pooled pack memory, and a candidate scorer.
  • The Python API resolves card names, encodes uncached cards in batches, maintains draft history, and returns ranked recommendations with probabilities.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages