👁️
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

check front face specifically for type legality

+41 -4
+1
src/lib/__tests__/test-cards.json
··· 25 25 "Barkchannel Pathway": "59d22de5-e310-44d7-89cf-ef3529e40cef", 26 26 "Basking Broodscale": "a7c69802-99c4-4778-934e-cc09ba58c267", 27 27 "Beastcaller Savant": "e28227eb-b3b5-42fa-b597-1fefd2a70186", 28 + "Behold the Unspeakable": "464372ef-0b16-4b8d-ba6f-fbf5c905c479", 28 29 "Beloved Chaplain": "a07406b7-faa1-4ed3-ab84-314c40f3f7f1", 29 30 "Bird Admirer": "58bd02ae-2676-4c9c-b24e-2bd51be8bde7", 30 31 "Birds of Paradise": "d3a0b660-358c-41bd-9cd2-41fbf3491b1a",
+20
src/lib/deck-validation/__tests__/rules.test.ts
··· 604 604 const violations = commanderUncommonRule.validate(ctx); 605 605 expect(violations).toHaveLength(0); 606 606 }); 607 + 608 + it("rejects DFC saga that transforms into creature (front face check)", async () => { 609 + // Behold the Unspeakable has an uncommon printing and transforms into 610 + // a legendary creature, but the FRONT face is a Saga - not legal for PDH 611 + const behold = await cards.get("Behold the Unspeakable"); 612 + const deck = makeDeck([makeCard(behold, "commander")], "paupercommander"); 613 + const printingsMap = new Map<OracleId, Card[]>(); 614 + printingsMap.set(behold.oracle_id, [ 615 + mockPrinting(behold, "uncommon", ["paper"]), 616 + ]); 617 + const ctx = await makeContextWithCards( 618 + deck, 619 + [behold], 620 + undefined, 621 + printingsMap, 622 + ); 623 + const violations = commanderUncommonRule.validate(ctx); 624 + expect(violations).toHaveLength(1); 625 + expect(violations[0].message).toContain("not a creature"); 626 + }); 607 627 }); 608 628 609 629 describe("signatureSpellRule color identity", () => {
+7 -4
src/lib/deck-validation/rules/commander.ts
··· 7 7 type Violation, 8 8 violation, 9 9 } from "../types"; 10 - import { getOracleText, getTypeLine } from "../utils"; 10 + import { getFrontFaceTypeLine, getOracleText, getTypeLine } from "../utils"; 11 11 12 12 /** 13 13 * Commander required - at least one commander ··· 74 74 /** 75 75 * Check if card has a creature type valid for commander (creature, vehicle, spacecraft with P/T). 76 76 * Shared between regular Commander and PDH validation. 77 + * 78 + * For DFCs/MDFCs, checks the FRONT FACE only - a Saga that transforms into 79 + * a creature (e.g., Behold the Unspeakable) is NOT a legal commander. 77 80 */ 78 81 export function hasCommanderCreatureType(card: Card): boolean { 79 - const typeLine = getTypeLine(card).toLowerCase(); 82 + const typeLine = getFrontFaceTypeLine(card).toLowerCase(); 80 83 81 84 if (typeLine.includes("creature")) return true; 82 85 if (typeLine.includes("vehicle")) return true; ··· 90 93 } 91 94 92 95 export function isValidCommanderType(card: Card): boolean { 93 - const typeLine = getTypeLine(card).toLowerCase(); 96 + const frontTypeLine = getFrontFaceTypeLine(card).toLowerCase(); 94 97 const oracleText = getOracleText(card).toLowerCase(); 95 98 96 - const isLegendary = typeLine.includes("legendary"); 99 + const isLegendary = frontTypeLine.includes("legendary"); 97 100 const canBeCommander = oracleText.includes("can be your commander"); 98 101 99 102 // Grist-style cards: creatures in all zones except battlefield
+13
src/lib/deck-validation/utils.ts
··· 34 34 35 35 return ""; 36 36 } 37 + 38 + /** 39 + * Get the front face type line only. 40 + * For DFCs/MDFCs, commander legality is determined by the front face. 41 + * A Saga that transforms into a creature (e.g., Behold the Unspeakable) 42 + * is NOT a legal commander because the front face is a Saga. 43 + */ 44 + export function getFrontFaceTypeLine(card: Card): string { 45 + if (card.card_faces && card.card_faces.length > 0) { 46 + return card.card_faces[0].type_line ?? ""; 47 + } 48 + return card.type_line ?? ""; 49 + }