proxy-printer について
proxy-printer は、Magic: The Gathering のプレイヤーやデッキ構築ワークフロー向けのスキルで、解析済みデッキリストからカードとトークンのプロキシ PDF を作成します。印刷内容は Scryfall の検索結果を参照し、ASCII アートカタログにも対応します。
主な機能
- 01カードのプロキシ PDF 作成
- 02重複を除いたトークン PDF 作成
- 03Scryfall からカードデータを取得
- 04用紙サイズと部数の指定
- 05タイプと名前に応じた ASCII アート選択
活用シーン
- 01デッキリストを実物のプロキシとして印刷
- 02デッキ用トークンのプロキシを作成
- 03TCGPlayer CSV や Moxfield テキストを印刷用ファイルに変換
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dan-blanchard/ mtg-skills --skill proxy-printerインストール後、Claude Code で/proxy-printerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CONTEXT.mdpyproject.tomluv.lock詳細
プロキシ印刷
解析済みのMTGデッキリストを、印刷可能なプロキシPDFに変換します。このスキルは2つの成果物を出力します。cards.pdf(デッキ内の各カードのコピーごとにプロキシを1枚)と、tokens.pdf(デッキ内のいずれかのカードが生成するトークンの種類ごとにプロキシを1枚。Scryfallのoracle_idで重複を除外)です。どちらも同じレンダリングテンプレートを使用します。カード名バナー、サブタイプに応じたASCIIアート、タイプバナー、オラクルテキスト、P/Tです。
このスキルは単独で呼び出すことも(ユーザーがリストを渡し、エージェントがPDFを印刷します)、別のウィザードから呼び出すこともできます。deck-wizardとcube-wizardはどちらも、このスキルが使用する解析済みデッキJSONスキーマを出力します。
絶対に守るルール
**トレーニングデータのオラクルテキストからプロキシをレンダリングしてはいけません。**生成されるPDFに記載されるカード名、マナ・コスト、タイプ行、オラクルテキスト、P/T、トークン側のスタッツは、すべてproxy-printが実行するScryfall検索から取得しなければなりません。権威あるレンダラーはCLIです。エージェントが印刷内容を「修正」することは許可されていません。
このスキルを使う場面
- ユーザーがデッキリストを渡し、印刷可能なプロキシを求めている場合。
- ユーザーがTCGPlayerの注文CSV/Moxfieldのtxt/プレーンテキストのカードリストを渡し、実際にカードを印刷したい場合。
- 上位レベルのスキル(deck-wizard、cube-wizard)が、デッキ構築セッションの最後に印刷可能な成果物を作成する場合。
ワークフロー
[raw deck list] → parse-deck → deck.json → proxy-print --kind cards → cards.pdf
\→ proxy-print --kind tokens → tokens.pdf
ステップ1 — 入力を解析する
ユーザーから渡されたものが解析済みデッキJSON以外の場合は、まずparse-deckを実行して正規スキーマを生成します。parse-deckはMoxfield、MTGO、プレーンテキスト、CSV(TCGPlayer注文CSV形式を含む)に対応しています。
parse-deck input.txt > /tmp/deck.json
ステップ2 — 必要に応じてバルクデータを更新する
proxy-printはScryfallのバルクJSONを読み込みます。キャッシュファイルが7日より古い場合、CLIは終了コード1で終了し、この手順を案内するメッセージを表示します。次を実行します。
download-mtgjson
ほぼ一度だけの作業です。プロキシにアーティストのクレジット付きアートを使う場合は、まずクレジット付きカタログを作成してください(通常は
fetch-art --from-deck deck.jsonで十分です。所要時間は約15秒で、全件取得すると約108秒です)。詳しくは以下のASCII art catalogをご覧ください。
ステップ3 — カードをレンダリングする
proxy-print --kind cards \
--deck /tmp/deck.json \
--bulk-data /tmp/scryfall-bulk/default-cards.json \
--out /tmp/cards.pdf
ステップ4 — トークンをレンダリングする
proxy-print --kind tokens \
--deck /tmp/deck.json \
--bulk-data /tmp/scryfall-bulk/default-cards.json \
--out /tmp/tokens.pdf
2つのレンダリング処理は意図的に分けています。デッキの変更がカード(またはトークンリスト)だけに影響する場合、ユーザーが片方だけを再印刷できるようにするためです。
CLIリファレンス
proxy-print --kind {cards,tokens} --deck DECK.json --out OUT.pdf [options]
| フラグ | 必須 | デフォルト | 備考 |
|---|---|---|---|
--kind | はい | — | cardsまたはtokens |
--deck PATH | はい | — | 解析済みデッキJSON |
--out PATH | はい | — | 出力PDFのパス |
--bulk-data PATH | いいえ | 自動 | ScryfallのバルクJSON。キャッシュ済みのデフォルトを自動で解決します |
--page-size letter|a4 | いいえ | letter | ページサイズ |
--copies N | いいえ | 1 | 各カード/トークンの追加コピー数 |
--include-sideboard | いいえ | オン | cardsモード。--no-sideboardで切り替えます |
--no-sideboard | いいえ | オフ | cardsモード |
--report-art-coverage | いいえ | オフ | tokensモード。トークンごとのJSONをstderrに出力します |
終了コード:0 成功、1 バルクデータがない/古い、2 デッキJSONが無効、3 出力先に書き込めない、4 レンダリングエラー。
レイアウト
カードとトークンには共通のレンダリングテンプレートを使います。カードのオラクルテキストの量に応じて、各要素の比率が調整されます。
┌───────────────────────────────┐
│ ╔══════════════════════════╗ │ name banner
│ ║ NAME {COST} ║ │ (cost omitted for tokens)
├─╚══════════════════════════╝──┤
│ (ASCII art) │ art region (proportional)
├───────────────────────────────┤
│ ╔══════════════════════════╗ │ type banner
│ ║ Type — Subtype {C} ║ │
├─╚══════════════════════════╝──┤
│ oracle text │ oracle region (proportional)
│ ┌─────┐ │
│ │ P/T │ │
└───────────────────────┴─────┴─┘
カードの寸法:2.5″ × 3.5″。グリッド:LetterまたはA4で1ページあたり3 × 3 = 9枚。
ASCII アートカタログ
アートは 2 つの階層から取得されます。手作業で厳選されたローカルカタログの上に、出典付きカタログが重ねられています。
- ローカルカタログ — リポジトリ内の
mtg-utils/src/mtg_utils/data/card_art/に含まれています。カードのサブタイプごとに 1 つの.txtファイル(クリーチャー/アーティファクト/エンチャント/土地のサブタイプ)に加え、カードタイプのフォールバック(creature.txt、artifact.txt、enchantment.txt、land.txt、sorcery.txt、instant.txt、planeswalker.txt)と、最終的な_generic.txtがあります。手作業で厳選された ASCII アートで、出典情報は付属しません。 - 出典付きカタログ — ユーザーが追加するキャッシュで、
$MTG_SKILLS_CACHE_DIR/attributed-art/(デフォルトは~/.cache/mtg-skills/attributed-art/)にあります。ファイルにはタイトル、出典、ライセンスを記した 3 行のヘッダーが付いています。ここからアートが取得された場合、プロキシの左下のフッターに、P/T と同じ行でart by <Name>と表示されます(実際の MTG カードでアーティストのクレジットが記載される位置です)。
検索順序
各カードについて、サブタイプ、カードタイプ、_generic の順にスラッグを検索します。各スラッグでは、まず出典付きカタログを検索し、次にローカルカタログを検索します。最初に見つかったものが使われます。
type_lineを解析します。—の後にある各サブタイプを順番に処理します(Vampire Knight→vampire、次にknight)。attributed/<sub>.txtを検索local/<sub>.txtを検索
- サブタイプに該当するものがなかった場合、カードタイプの単語を順に検索します(Token/Legendary/Snow/Tribal/Basic などのメタワードは除外)。各カードタイプについて、次を検索します。
attributed/<card-type>.txtを検索local/<card-type>.txtを検索
- 最後のフォールバック:
local/_generic.txt。
このようにスラッグごとに交互に検索する方式(出典付きカタログをすべて検索してからローカルカタログを検索するのではなく)により、手作業で厳選されたローカルの Vampire が、汎用的な出典付き Creature より優先されます。通常はこちらが望ましい動作です。詳細は
docs/adr/0006-attributed-art-catalog.md を参照してください。
アートは設計上、P/T に依存しません。すべての Soldier トークンで soldier.txt が共有され、P/T はプロキシ上にテキストで表示されます。
属性付きカタログへのデータ登録(必要に応じて一度だけ)
属性付きカタログは空の状態で配布されます。fetch-art を使ってデータを登録します。これは Scryfall のカタログエンドポイントから MTG のすべてのサブタイプを取得し、2 つの ASCII アートソース(asciiart.eu のカテゴリページと、asciiart.website にある Christopher Johnson のコレクション。browse.php?show=tags から約 1148 個のタグを自動検出します。カテゴリとフランチャイズのアートが混同されていたものについては、タグが MTG のコンセプトに直接対応します)から候補を収集します。目標サイズの 20×10 に合わせてスコアリングし(上限は 30×18)、proxy-print が読み取れる 3 行のライセンスヘッダー付き .txt ファイルとして、帰属情報を記録して保存します。各ファイルのヘッダーにはソースごとの帰属条件が記載されます。asciiart.website のヘッダーには、そのサイトが付与していないライセンスがあるかのように記述せず、「個人利用向けプロキシ」と正直に明記します。
デッキごとのワークフロー(通常のプロキシ印刷におすすめ)では、デッキで実際に使用するサブタイプと、Scryfall の all_parts から取得したデッキ生成トークンのすべてのサブタイプに対象を絞ります。
fetch-art --from-deck /tmp/deck.json
一般的な Commander デッキでは、固有のサブタイプは約 30 個です。タグの取得は 1 回あたり約 0.4 秒かかるため、初回の取得には約 15 秒かかり、7 日間のキャッシュがあればほぼ瞬時に完了します。フルスイープ(--from-deck なし)には初回の実行で約 108 秒かかるため、さまざまなデッキのプロキシを印刷する場合に限って実行する価値があります。
--by-name を追加すると、個々のカード名のアートも取得できます。これは proxy-print の差別化処理で使用されます(同じサブタイプのアートを共有する複数の別名カードがある場合、利用可能なアートがあれば、それぞれ別の作品を割り当てます)。
fetch-art --from-deck /tmp/deck.json --by-name
カード名をキーにした処理では、次の 2 つのソースを順番に試します。
- asciiart.eu の完全一致名検索(
/search?q=<full name>)。 アートのタイトル全体から一致するものを検索するため、複数語からなる MTG の名前も通常は見つかります。Lightning Bolt → 稲妻の ASCII アート、Black Lotus → 蓮のアート、Sword of Truth and Justice → 剣のアート、という具合です。 - (1)で何も見つからなかった場合は、asciiart.website で単語ごとに検索します。 このサイトの検索はタイトルではなくタグ名に対して行われるため、カード名を単語に分割し、API で 4 文字以上の各単語を試します(内部では CSRF とフォーム POST を使用します)。例:「Brain Maggot」→「Brain」→脳のアート、「Llanowar Elves」→「Elves」→(30×18 の上限に収まるものがあれば)エルフのアート。
カード名でサイズ内に収まる候補が見つからない場合は、描画時にタイプをキーとしたアートにフォールバックします。
fetch-art
HTTP レスポンスは $MTG_SKILLS_CACHE_DIR/ascii-art-fetcher/ 以下に 7 日間ディスクキャッシュされるため、再実行の負荷は軽くなります。--report-missing を追加すると、サイズに合う候補がなかったすべてのサブタイプを確認できます。これらは描画時にローカルカタログへフォールバックします。
Treasure、Saga、Innistrad など、MTG 固有のメカニクスやセット名・次元名にあたるサブタイプは、意図的にスキップされます。これらはローカルカタログで処理します。
差分検出パスで見つからない場合に、固有のアートを手作業で作成する
差分検出パスは、同じタイプ別グループ内のカードを名前で検索しますが、差し替えられるのはカタログに実際にあるアートだけです。Mana Confluence や Temple of Malady のようなMTG固有のコンセプト名の場合、asciiart.euやasciiart.websiteには、通常予算内で使えるものがありません。その場合、proxy-print は次の警告を出力します。
WARN: 3 cards share land.txt (Mana Confluence, Temple of Abandon, Temple of Malady). Consider hand-curating name-keyed art.
この警告が表示されたら、該当するカードのプレースホルダーアートを手描きで用意することを提案してください。カタログの不足を補う作業です。手順は次のとおりです。
mtg-utils/src/mtg_utils/data/card_art/*.txtから、スタイルの参考になるファイルを2~3個読みます。それぞれのカードのテーマに関連する題材のファイルを選んでください(たとえば、寺院をテーマにした土地カードなら、temple.txt、monument.txt、またはその他の建築物の作品を確認します)。これらから、既存コレクションのサイズの目安、ASCII表現の語彙、美的スタイルを確認できます。- カードごとに小さなASCIIアートを描きます。幅は30文字以下、高さは18行以下です。フェッチャーと同じサイズの目安です。レンダラーは固定のアート領域に収まるよう、フォントを自動で拡大・縮小します。視覚的に表現してください。形や線で対象を描き、文字を形の代わりに使わないでください(
feedback_ascii_art_no_labels.mdのメモを参照)。 - 各ファイルを
$MTG_SKILLS_CACHE_DIR/attributed-art/<name-slug>.txt(デフォルトは~/.cache/mtg-skills/attributed-art/<name-slug>.txt)に、次の3行のクレジット付きアート用ヘッダーを付けて保存します。
レンダラーは# <Title> (hand-drawn for proxy run) # Source: hand-drawn ASCII # Personal-use proxy <blank line> <art body>lookup_art_by_nameを通じて(name-slug).txtを検出し、解決結果にtier="name"のタグを付け、フッター領域にクレジット((by <name>)の括弧書きから取得)を表示します。手描きの作品では、ヘッダーの(by …)は省略できます。その場合、クレジット欄は空欄のままになります。 proxy-printを再実行します。同じコマンドを使い、フラグは変更しません。差分検出パスが新しいファイルを自動的に検出するため、再取得は不要です。
これは最後の手段です。通常は fetch-art --from-deck deck.json --by-name を使います。手作業での追加は、検索で見つからなかったカードだけを補います。
フッター領域
タイプバナーの下にある左下の帯は、クレジット付きアートがある場合にアーティストのクレジット(art by <Name>)を表示するための領域です。トークンには from: <source> の行を表示しません。どの呪文でトークンが生成されたかはプレイヤーがたった今唱えた呪文から分かりますし、デッキリストにも同じ情報が記載されています。この領域をアーティストのクレジットに使うことで、トークンにも実際のMTGカードと同じ左下のクレジットを表示できます。
アート内に埋め込まれたアーティストのイニシャルである署名は、取得時にそのまま保持され、フッターとは別にasciiart.euのFAQで求められるクレジット表記をすでに満たしています。
タイプバナーの位置
トークン以外のカードでは、タイプバナーの下端は y + CARD_H / 3 に固定されます。これはカードの下から1/3の位置で、実際のMTGカードのタイプ行と同じ位置です。カード間でアート領域の高さは変わりません(約128 ptで、最大約9 ptの14行アートを収めるのに十分です)。バナーの下はオラクルテキストで埋められます。オラクルテキストが短い場合、バナーが移動するのではなく、その下に空白が残ります(これも実際のMTGカードと同じです)。
トークンでは従来の動的なレイアウトを維持します。トークンにはオラクルテキストがない場合が多いため、バナーがカード下部近く、パワー/タフネスのすぐ上にある見た目のほうが、実際のMTGトークンの枠に近くなります。
WARN: 出力の解釈
proxy-print は警告を標準エラー出力に書き込みますが、終了コードは0です。次の2つのパターンに注意してください。
WARN: missing from bulk: <name>— Scryfallのキャッシュ済みバルクデータにこのカードがありません。最もよくある原因は、「Paradise Chocobo」(「Birds of Paradise」のFIC版)のような別名です。ユーザーは元のリストを確認して名前を修正するか、まったく新しいセットの場合はバルクデータを更新してください。WARN: token id <id> from <source>— カードのall_partsが、ローカルのバルクデータにないトークンIDを参照しています。まれなケースなので、無視して問題ありません。
どちらの場合も、自動的にエスカレーションしないでください。スキップされたカードをユーザーに伝え、続行してください。
よくある落とし穴
- オラクルテキストを言い換えないでください。 レンダリングされた PDF でオラクルテキストが途切れている場合は、レイアウトを修正してください(レンダラーはフォントサイズを 9.5pt から 6.5pt まで自動で縮小します)。テキストの内容は編集しないでください。
- トークンを手動で追加しないでください。 カードがトークンを生成するはずなのに、レンダリングされた tokens.pdf に表示されない場合、それは Scryfall の
all_partsで関連付けられていないためです。カスタムトークンや自作トークンは対象外です。 - 反射的に
download-mtgjsonを実行しないでください。 約 500MB をダウンロードします。proxy-printが終了コード 1 で終了し、更新するよう指示した場合にのみ更新してください。 - 2 つの PDF を結合しないでください。 意図的に別々にしています。プレイ中、トークンは脇に置き、カードはデッキに入れます。ユーザーはほぼ必ず、それぞれを個別に印刷または差し替えたいと考えています。
制限事項
- Scryfall にないカスタムトークンや自作トークンは、通知なしでスキップされます。
- 画像ベースのプロキシ(Scryfall のアート)は v1 ではサポートされていません。
- カットガイドやトンボは描画されません。
- 両面カードの裏面はレンダリングされません(プロキシには表面のみが表示され、両面のオラクルテキストは連結されます)。
- シンボルフォントによるマナ・コストの描画は対象外です。マナ・コストには Scryfall の中括弧形式(例:
{2}{B}{R})を使用します。
スキル間の連携
- deck-wizard は、調整セッションの後に
proxy-printを実行し、デッキ JSON とともに印刷可能な成果物を出力できます。 - cube-wizard は解析済みのキューブ JSON を使用します。これは
proxy-printで使う場合、解析済みのデッキ JSON と同じ形式です(統率者とカードのリストがあり、サイドボードはありません)。 - lgs-search は独立しています。プロキシは自宅で印刷するためのものであり、カードの調達には使いません。