// ============================================================================ // ARCANE DUELS — Complete Card Database // An original TCG with 5 colors: Radiance, Tide, Shadow, Flame, Growth // ============================================================================ const COLORS = { RADIANCE: 'radiance', // White — order, healing, protection TIDE: 'tide', // Blue — knowledge, control, illusion SHADOW: 'shadow', // Black — death, sacrifice, power FLAME: 'flame', // Red — chaos, destruction, speed GROWTH: 'growth', // Green — nature, strength, growth COLORLESS: 'colorless', }; const TYPES = { CREATURE: 'creature', SORCERY: 'sorcery', INSTANT: 'instant', ENCHANTMENT: 'enchantment', ARTIFACT: 'artifact', LAND: 'land', }; // Keywords mapping const KEYWORDS = { SWIFT: 'swift', // Can attack immediately (Haste) VIGILANT: 'vigilant', // Doesn't tap to attack (Vigilance) SOARING: 'soaring', // Can only be blocked by Soaring/Reaching (Flying) GUARDIAN: 'guardian', // Deals damage first in combat (First Strike) FORTIFIED: 'fortified', // Can't attack (Defender) DRAINING: 'draining', // Gain life equal to damage dealt (Lifelink) OVERWHELMING: 'overwhelming', // Excess combat damage hits player (Trample) VENOMOUS: 'venomous', // Any damage is lethal (Deathtouch) REACHING: 'reaching', // Can block Soaring creatures (Reach) }; // Mana cost encoding: { radiance: N, tide: N, shadow: N, flame: N, growth: N, colorless: N } // e.g. 2W = { colorless: 2, radiance: 1 } let nextId = 1; function card(props) { return { id: nextId++, ...props }; } // ============================================================================ // RADIANCE (White) — 12 cards // ============================================================================ const radianceCards = [ card({ name: 'Sanctuary Guard', type: TYPES.CREATURE, cost: { colorless: 1, radiance: 1 }, color: COLORS.RADIANCE, power: 2, toughness: 2, keywords: [], abilities: [], flavor: 'The temple never falls while its guardians stand.', rarity: 'common', }), card({ name: 'Dawn Priest', type: TYPES.CREATURE, cost: { colorless: 2, radiance: 1 }, color: COLORS.RADIANCE, power: 1, toughness: 4, keywords: [KEYWORDS.FORTIFIED], abilities: [{ trigger: 'upkeep', effect: 'gainLife', amount: 1 }], flavor: 'Each sunrise is a prayer answered.', rarity: 'uncommon', }), card({ name: 'Shieldbearer', type: TYPES.CREATURE, cost: { radiance: 1 }, color: COLORS.RADIANCE, power: 1, toughness: 1, keywords: [KEYWORDS.VIGILANT], abilities: [], flavor: 'Always watching, never resting.', rarity: 'common', }), card({ name: 'Radiant Champion', type: TYPES.CREATURE, cost: { colorless: 3, radiance: 2 }, color: COLORS.RADIANCE, power: 4, toughness: 4, keywords: [KEYWORDS.VIGILANT], abilities: [], flavor: 'She carries the light of a thousand dawns into battle.', rarity: 'rare', }), card({ name: 'Lightbringer', type: TYPES.CREATURE, cost: { colorless: 2, radiance: 1 }, color: COLORS.RADIANCE, power: 2, toughness: 2, keywords: [], abilities: [{ trigger: 'enters', effect: 'gainLife', amount: 3 }], flavor: 'Where she walks, wounds close and despair lifts.', rarity: 'common', }), card({ name: 'Angelic Sentinel', type: TYPES.CREATURE, cost: { colorless: 3, radiance: 2 }, color: COLORS.RADIANCE, power: 3, toughness: 5, keywords: [KEYWORDS.SOARING, KEYWORDS.VIGILANT], abilities: [], flavor: 'Its wings span the horizon, shielding the faithful below.', rarity: 'rare', }), card({ name: 'Holy Wrath', type: TYPES.SORCERY, cost: { colorless: 2, radiance: 2 }, color: COLORS.RADIANCE, abilities: [{ effect: 'destroyCreatureIf', condition: 'powerGte4' }], flavor: 'The righteous need not fear judgment.', rarity: 'uncommon', }), card({ name: 'Mending Light', type: TYPES.INSTANT, cost: { radiance: 1 }, color: COLORS.RADIANCE, abilities: [{ effect: 'gainLife', amount: 4 }], flavor: 'A warm glow that knits flesh and spirit alike.', rarity: 'common', }), card({ name: 'Celestial Shield', type: TYPES.INSTANT, cost: { colorless: 1, radiance: 1 }, color: COLORS.RADIANCE, abilities: [{ effect: 'pumpCreature', power: 0, toughness: 4, duration: 'endOfTurn' }], flavor: 'The blow struck true—but found only light.', rarity: 'common', }), card({ name: 'Divine Decree', type: TYPES.ENCHANTMENT, cost: { colorless: 2, radiance: 2 }, color: COLORS.RADIANCE, abilities: [{ effect: 'anthemBuff', power: 1, toughness: 1 }], flavor: 'By decree of the High Luminary, all shall stand firm.', rarity: 'rare', }), card({ name: 'Purifying Light', type: TYPES.SORCERY, cost: { colorless: 3, radiance: 2 }, color: COLORS.RADIANCE, abilities: [{ effect: 'destroyAllCreatures' }], flavor: 'When the light burns too bright, nothing remains.', rarity: 'rare', }), card({ name: 'Resolute Defender', type: TYPES.CREATURE, cost: { colorless: 1, radiance: 1 }, color: COLORS.RADIANCE, power: 1, toughness: 3, keywords: [KEYWORDS.GUARDIAN], abilities: [], flavor: 'His shield has turned a thousand blades.', rarity: 'common', }), ]; // ============================================================================ // TIDE (Blue) — 12 cards // ============================================================================ const tideCards = [ card({ name: 'Reef Scholar', type: TYPES.CREATURE, cost: { colorless: 1, tide: 1 }, color: COLORS.TIDE, power: 1, toughness: 2, keywords: [], abilities: [{ trigger: 'enters', effect: 'drawCards', amount: 1 }], flavor: 'The coral libraries hold secrets older than the continents.', rarity: 'common', }), card({ name: 'Tidal Serpent', type: TYPES.CREATURE, cost: { colorless: 4, tide: 2 }, color: COLORS.TIDE, power: 5, toughness: 5, keywords: [KEYWORDS.SOARING], abilities: [], flavor: 'It moves between sea and sky as if the boundary were a suggestion.', rarity: 'rare', }), card({ name: 'Mistwalker', type: TYPES.CREATURE, cost: { colorless: 2, tide: 1 }, color: COLORS.TIDE, power: 2, toughness: 1, keywords: [KEYWORDS.SOARING], abilities: [], flavor: 'It drifts through the fog, never quite where you expect.', rarity: 'common', }), card({ name: 'Arcane Student', type: TYPES.CREATURE, cost: { tide: 1 }, color: COLORS.TIDE, power: 1, toughness: 1, keywords: [], abilities: [{ trigger: 'tap', effect: 'scry', amount: 1 }], flavor: 'Every page reveals a new horizon.', rarity: 'common', }), card({ name: 'Current Channeler', type: TYPES.CREATURE, cost: { colorless: 2, tide: 2 }, color: COLORS.TIDE, power: 2, toughness: 4, keywords: [], abilities: [{ trigger: 'spellCast', effect: 'drawCards', amount: 1 }], flavor: 'Magic flows through her like water through a delta.', rarity: 'rare', }), card({ name: 'Mind Shatter', type: TYPES.INSTANT, cost: { tide: 2 }, color: COLORS.TIDE, abilities: [{ effect: 'counterSpell' }], flavor: 'Your incantation unravels before the last syllable.', rarity: 'uncommon', }), card({ name: 'Essence Drain', type: TYPES.INSTANT, cost: { colorless: 1, tide: 1 }, color: COLORS.TIDE, abilities: [{ effect: 'bounceCreature' }], flavor: 'Returned to the aether, as if it had never been summoned.', rarity: 'common', }), card({ name: 'Foresight', type: TYPES.SORCERY, cost: { tide: 1 }, color: COLORS.TIDE, abilities: [{ effect: 'drawCards', amount: 2 }], flavor: 'To see what comes is the first step to mastering it.', rarity: 'common', }), card({ name: 'Mental Fortress', type: TYPES.ENCHANTMENT, cost: { colorless: 2, tide: 1 }, color: COLORS.TIDE, abilities: [{ effect: 'extraDraw', amount: 1 }], flavor: 'Within these walls, knowledge multiplies endlessly.', rarity: 'rare', }), card({ name: 'Time Warp', type: TYPES.SORCERY, cost: { colorless: 3, tide: 2 }, color: COLORS.TIDE, abilities: [{ effect: 'extraTurn' }], flavor: 'Yesterday and tomorrow are merely pages to be turned.', rarity: 'mythic', }), card({ name: 'Frost Barrier', type: TYPES.INSTANT, cost: { colorless: 1, tide: 1 }, color: COLORS.TIDE, abilities: [{ effect: 'tapCreature' }], flavor: 'Frozen mid-stride, locked in a prison of ice.', rarity: 'common', }), card({ name: 'Thought Thief', type: TYPES.CREATURE, cost: { colorless: 1, tide: 1 }, color: COLORS.TIDE, power: 2, toughness: 1, keywords: [], abilities: [{ trigger: 'dealsDamage', effect: 'drawCards', amount: 1 }], flavor: 'What you know, he knows. What he knows, you never will.', rarity: 'uncommon', }), ]; // ============================================================================ // SHADOW (Black) — 12 cards // ============================================================================ const shadowCards = [ card({ name: 'Graveborn Ghoul', type: TYPES.CREATURE, cost: { colorless: 1, shadow: 1 }, color: COLORS.SHADOW, power: 2, toughness: 2, keywords: [], abilities: [], flavor: 'It remembers nothing of its former life, only hunger.', rarity: 'common', }), card({ name: 'Soul Collector', type: TYPES.CREATURE, cost: { colorless: 3, shadow: 2 }, color: COLORS.SHADOW, power: 3, toughness: 4, keywords: [KEYWORDS.DRAINING], abilities: [], flavor: 'Each soul taken makes it stronger, and its victims weaker.', rarity: 'rare', }), card({ name: 'Plague Rat', type: TYPES.CREATURE, cost: { colorless: 1, shadow: 1 }, color: COLORS.SHADOW, power: 1, toughness: 1, keywords: [], abilities: [{ effect: 'plagueRatBonus' }], flavor: 'Where one scurries, a hundred follow.', rarity: 'common', }), card({ name: 'Night Terror', type: TYPES.CREATURE, cost: { colorless: 2, shadow: 1 }, color: COLORS.SHADOW, power: 2, toughness: 1, keywords: [KEYWORDS.SOARING], abilities: [], flavor: 'It feeds on screams the way others feed on bread.', rarity: 'common', }), card({ name: 'Bone Revenant', type: TYPES.CREATURE, cost: { colorless: 4, shadow: 2 }, color: COLORS.SHADOW, power: 6, toughness: 5, keywords: [KEYWORDS.VENOMOUS], abilities: [], flavor: 'Assembled from the bones of fallen champions.', rarity: 'rare', }), card({ name: 'Vampiric Noble', type: TYPES.CREATURE, cost: { colorless: 2, shadow: 1 }, color: COLORS.SHADOW, power: 3, toughness: 2, keywords: [KEYWORDS.DRAINING], abilities: [], flavor: 'She attends the finest galas. Few guests leave alive.', rarity: 'uncommon', }), card({ name: 'Raise Dead', type: TYPES.SORCERY, cost: { shadow: 1 }, color: COLORS.SHADOW, abilities: [{ effect: 'returnFromGraveyard', type: 'creature' }], flavor: 'Death is merely a temporary inconvenience.', rarity: 'common', }), card({ name: 'Dark Pact', type: TYPES.SORCERY, cost: { shadow: 2 }, color: COLORS.SHADOW, abilities: [{ effect: 'drawCards', amount: 2 }, { effect: 'loseLife', amount: 2 }], flavor: 'Power has a price. The wise pay it willingly.', rarity: 'uncommon', }), card({ name: 'Assassinate', type: TYPES.INSTANT, cost: { colorless: 1, shadow: 2 }, color: COLORS.SHADOW, abilities: [{ effect: 'destroyCreature' }], flavor: 'No spell, no blade—just silence, then nothing.', rarity: 'uncommon', }), card({ name: 'Drain Life', type: TYPES.SORCERY, cost: { shadow: 2 }, color: COLORS.SHADOW, abilities: [{ effect: 'drainLife', isX: true }], flavor: 'Your loss is my gain, in the most literal sense.', rarity: 'uncommon', }), card({ name: 'Cursed Ground', type: TYPES.ENCHANTMENT, cost: { colorless: 1, shadow: 1 }, color: COLORS.SHADOW, abilities: [{ trigger: 'creatureDies', effect: 'opponentLosesLife', amount: 1 }], flavor: 'Nothing rests peacefully here.', rarity: 'uncommon', }), card({ name: 'Mind Rot', type: TYPES.SORCERY, cost: { colorless: 1, shadow: 1 }, color: COLORS.SHADOW, abilities: [{ effect: 'opponentDiscards', amount: 2 }], flavor: 'Thoughts dissolve like morning mist in the darkness.', rarity: 'common', }), ]; // ============================================================================ // FLAME (Red) — 12 cards // ============================================================================ const flameCards = [ card({ name: 'Goblin Striker', type: TYPES.CREATURE, cost: { flame: 1 }, color: COLORS.FLAME, power: 1, toughness: 1, keywords: [KEYWORDS.SWIFT], abilities: [], flavor: 'Speed is a virtue. Thinking is not.', rarity: 'common', }), card({ name: 'Fire Elemental', type: TYPES.CREATURE, cost: { colorless: 3, flame: 2 }, color: COLORS.FLAME, power: 5, toughness: 4, keywords: [], abilities: [], flavor: 'Born of the mountain\'s heart, it answers to no master.', rarity: 'uncommon', }), card({ name: 'Lightning Imp', type: TYPES.CREATURE, cost: { colorless: 1, flame: 1 }, color: COLORS.FLAME, power: 2, toughness: 1, keywords: [KEYWORDS.SWIFT], abilities: [], flavor: 'It arrives with the thunder and leaves with the echo.', rarity: 'common', }), card({ name: 'Lava Golem', type: TYPES.CREATURE, cost: { colorless: 2, flame: 1 }, color: COLORS.FLAME, power: 3, toughness: 2, keywords: [], abilities: [], flavor: 'Molten stone given purpose, if not grace.', rarity: 'common', }), card({ name: 'Dragon of the Peaks', type: TYPES.CREATURE, cost: { colorless: 4, flame: 2 }, color: COLORS.FLAME, power: 5, toughness: 5, keywords: [KEYWORDS.SOARING, KEYWORDS.SWIFT], abilities: [], flavor: 'The mountain trembles when it wakes. The world trembles when it flies.', rarity: 'mythic', }), card({ name: 'Berserker Ogre', type: TYPES.CREATURE, cost: { colorless: 2, flame: 2 }, color: COLORS.FLAME, power: 4, toughness: 3, keywords: [KEYWORDS.OVERWHELMING], abilities: [], flavor: 'Subtlety is a foreign concept. Destruction is its mother tongue.', rarity: 'uncommon', }), card({ name: 'Lightning Bolt', type: TYPES.INSTANT, cost: { flame: 1 }, color: COLORS.FLAME, abilities: [{ effect: 'dealDamage', amount: 3, target: 'any' }], flavor: 'The sky cracks open and chooses its victim.', rarity: 'common', }), card({ name: 'Fireball', type: TYPES.SORCERY, cost: { flame: 1 }, color: COLORS.FLAME, abilities: [{ effect: 'dealDamage', target: 'any', isX: true }], flavor: 'The equation is simple: more mana, more fire.', rarity: 'uncommon', }), card({ name: 'Inferno', type: TYPES.SORCERY, cost: { colorless: 3, flame: 2 }, color: COLORS.FLAME, abilities: [{ effect: 'dealDamageAll', amount: 3 }], flavor: 'Everything burns eventually. This just speeds up the schedule.', rarity: 'rare', }), card({ name: 'Battle Rage', type: TYPES.INSTANT, cost: { flame: 1 }, color: COLORS.FLAME, abilities: [{ effect: 'pumpCreature', power: 3, toughness: 0, duration: 'endOfTurn' }], flavor: 'Thought yields to instinct, instinct to fury.', rarity: 'common', }), card({ name: 'Flame Barrage', type: TYPES.INSTANT, cost: { colorless: 1, flame: 1 }, color: COLORS.FLAME, abilities: [{ effect: 'dealDamage', amount: 2, target: 'any' }], flavor: 'One bolt for spite. Two for certainty.', rarity: 'common', }), card({ name: 'Reckless Charge', type: TYPES.SORCERY, cost: { flame: 1 }, color: COLORS.FLAME, abilities: [{ effect: 'giveKeyword', keyword: KEYWORDS.SWIFT }, { effect: 'pumpCreature', power: 2, toughness: 0, duration: 'endOfTurn' }], flavor: 'Strategy is for cowards. Real warriors just run faster.', rarity: 'common', }), ]; // ============================================================================ // GROWTH (Green) — 12 cards // ============================================================================ const growthCards = [ card({ name: 'Woodland Elf', type: TYPES.CREATURE, cost: { growth: 1 }, color: COLORS.GROWTH, power: 1, toughness: 1, keywords: [], abilities: [{ trigger: 'tap', effect: 'addMana', color: 'any' }], flavor: 'The forest speaks through her, and she answers with magic.', rarity: 'common', }), card({ name: 'Highland Bear', type: TYPES.CREATURE, cost: { colorless: 1, growth: 1 }, color: COLORS.GROWTH, power: 2, toughness: 2, keywords: [], abilities: [], flavor: 'It needs no magic. Teeth and claws suffice.', rarity: 'common', }), card({ name: 'Ironbark Treant', type: TYPES.CREATURE, cost: { colorless: 3, growth: 2 }, color: COLORS.GROWTH, power: 5, toughness: 7, keywords: [], abilities: [], flavor: 'Centuries of growth have made it as unyielding as stone.', rarity: 'rare', }), card({ name: 'Wild Stallion', type: TYPES.CREATURE, cost: { colorless: 2, growth: 1 }, color: COLORS.GROWTH, power: 3, toughness: 3, keywords: [], abilities: [], flavor: 'Untamed and untameable, it runs where it wills.', rarity: 'common', }), card({ name: 'Ancient Wurm', type: TYPES.CREATURE, cost: { colorless: 4, growth: 2 }, color: COLORS.GROWTH, power: 7, toughness: 7, keywords: [KEYWORDS.OVERWHELMING], abilities: [], flavor: 'Older than the forests it burrows beneath.', rarity: 'mythic', }), card({ name: 'Thornweaver', type: TYPES.CREATURE, cost: { colorless: 2, growth: 1 }, color: COLORS.GROWTH, power: 2, toughness: 3, keywords: [KEYWORDS.REACHING], abilities: [], flavor: 'Its thorny tendrils snatch birds from the sky.', rarity: 'common', }), card({ name: 'Giant Growth', type: TYPES.INSTANT, cost: { growth: 1 }, color: COLORS.GROWTH, abilities: [{ effect: 'pumpCreature', power: 3, toughness: 3, duration: 'endOfTurn' }], flavor: 'Nature\'s fury compressed into a single heartbeat.', rarity: 'common', }), card({ name: "Nature's Gift", type: TYPES.SORCERY, cost: { colorless: 1, growth: 1 }, color: COLORS.GROWTH, abilities: [{ effect: 'searchLand' }], flavor: 'The land provides for those who listen.', rarity: 'common', }), card({ name: 'Regenerate', type: TYPES.INSTANT, cost: { growth: 1 }, color: COLORS.GROWTH, abilities: [{ effect: 'preventDamage', target: 'creature' }], flavor: 'What was broken, the forest mends.', rarity: 'common', }), card({ name: 'Overrun', type: TYPES.SORCERY, cost: { colorless: 3, growth: 2 }, color: COLORS.GROWTH, abilities: [{ effect: 'pumpAll', power: 3, toughness: 3, keyword: KEYWORDS.OVERWHELMING }], flavor: 'The forest does not march. It stampedes.', rarity: 'rare', }), card({ name: 'Vine Snare', type: TYPES.INSTANT, cost: { colorless: 1, growth: 1 }, color: COLORS.GROWTH, abilities: [{ effect: 'preventCombatDamage' }], flavor: 'Thorned vines erupt from the earth, halting all charge.', rarity: 'common', }), card({ name: 'Feral Instinct', type: TYPES.INSTANT, cost: { growth: 1 }, color: COLORS.GROWTH, abilities: [{ effect: 'pumpCreature', power: 1, toughness: 1, duration: 'endOfTurn' }, { effect: 'drawCards', amount: 1 }], flavor: 'Trust the animal within.', rarity: 'uncommon', }), ]; // ============================================================================ // COLORLESS — Artifacts (7 cards) // ============================================================================ const artifactCards = [ card({ name: 'Crystal Amulet', type: TYPES.ARTIFACT, cost: { colorless: 2 }, color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'any' }], flavor: 'It pulses with the light of every color, and none.', rarity: 'uncommon', }), card({ name: 'War Golem', type: TYPES.CREATURE, subtype: 'artifact', cost: { colorless: 5 }, color: COLORS.COLORLESS, power: 4, toughness: 4, keywords: [], abilities: [], flavor: 'Forged in the War of Five Suns, it still remembers how to fight.', rarity: 'common', }), card({ name: 'Enchanted Blade', type: TYPES.ARTIFACT, subtype: 'equipment', cost: { colorless: 3 }, color: COLORS.COLORLESS, abilities: [{ effect: 'equipBuff', power: 2, toughness: 1 }], flavor: 'Its edge never dulls, and its hunger never fades.', rarity: 'uncommon', }), card({ name: 'Healing Draught', type: TYPES.ARTIFACT, cost: { colorless: 1 }, color: COLORS.COLORLESS, abilities: [{ trigger: 'tap_sacrifice', effect: 'gainLife', amount: 3 }], flavor: 'One sip restores what hours of rest cannot.', rarity: 'common', }), card({ name: 'Mind Stone', type: TYPES.ARTIFACT, cost: { colorless: 2 }, color: COLORS.COLORLESS, abilities: [ { trigger: 'tap', effect: 'addMana', color: 'colorless' }, { trigger: 'tap_sacrifice', effect: 'drawCards', amount: 1 }, ], flavor: 'It stores thoughts the way a gem stores light.', rarity: 'uncommon', }), card({ name: 'Iron Shield', type: TYPES.ARTIFACT, subtype: 'equipment', cost: { colorless: 2 }, color: COLORS.COLORLESS, abilities: [{ effect: 'equipBuff', power: 0, toughness: 3 }], flavor: 'Heavy, inelegant, and thoroughly reliable.', rarity: 'common', }), card({ name: 'Arcane Compass', type: TYPES.ARTIFACT, cost: { colorless: 1 }, color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'scry', amount: 1 }], flavor: 'It always points toward what you need most.', rarity: 'common', }), ]; // ============================================================================ // LANDS — 5 Basic + 5 Dual // ============================================================================ const landCards = [ // Basic Lands card({ name: 'Sunlit Plains', type: TYPES.LAND, subtype: 'basic', color: COLORS.RADIANCE, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'radiance' }], rarity: 'basic', }), card({ name: 'Coral Reef', type: TYPES.LAND, subtype: 'basic', color: COLORS.TIDE, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'tide' }], rarity: 'basic', }), card({ name: 'Dark Swamp', type: TYPES.LAND, subtype: 'basic', color: COLORS.SHADOW, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'shadow' }], rarity: 'basic', }), card({ name: 'Volcanic Peak', type: TYPES.LAND, subtype: 'basic', color: COLORS.FLAME, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'flame' }], rarity: 'basic', }), card({ name: 'Verdant Forest', type: TYPES.LAND, subtype: 'basic', color: COLORS.GROWTH, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'growth' }], rarity: 'basic', }), // Dual Lands card({ name: 'Dual Springs', type: TYPES.LAND, subtype: 'dual', color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'radiance|tide' }], rarity: 'rare', }), card({ name: 'Ashen Moor', type: TYPES.LAND, subtype: 'dual', color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'shadow|flame' }], rarity: 'rare', }), card({ name: 'Twilight Glade', type: TYPES.LAND, subtype: 'dual', color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'radiance|growth' }], rarity: 'rare', }), card({ name: 'Molten Cavern', type: TYPES.LAND, subtype: 'dual', color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'flame|growth' }], rarity: 'rare', }), card({ name: 'Frozen Depths', type: TYPES.LAND, subtype: 'dual', color: COLORS.COLORLESS, abilities: [{ trigger: 'tap', effect: 'addMana', color: 'tide|shadow' }], rarity: 'rare', }), ]; // ============================================================================ // ALL CARDS // ============================================================================ const ALL_CARDS = [ ...radianceCards, ...tideCards, ...shadowCards, ...flameCards, ...growthCards, ...artifactCards, ...landCards, ]; // Card lookup by ID const CARD_DB = {}; ALL_CARDS.forEach((c) => { CARD_DB[c.id] = c; }); // Get the converted mana cost (total mana needed) function getManaCost(cost) { if (!cost) return 0; return Object.values(cost).reduce((sum, v) => sum + v, 0); } // Build a starter deck for a given color (24 lands + 36 spells) function buildStarterDeck(color) { const colorCards = ALL_CARDS.filter( (c) => c.color === color && c.type !== TYPES.LAND ); const basicLand = ALL_CARDS.find( (c) => c.type === TYPES.LAND && c.subtype === 'basic' && c.color === color ); const deck = []; // Add 4 copies of each color card (up to 9 unique cards = 36) const spellCards = colorCards.slice(0, 9); spellCards.forEach((c) => { for (let i = 0; i < 4; i++) deck.push(c.id); }); // Fill to 60 with basic lands while (deck.length < 60) { deck.push(basicLand.id); } return deck; } // Prebuilt starter decks const STARTER_DECKS = { radiance: { name: 'Dawn\'s Wrath', color: COLORS.RADIANCE }, tide: { name: 'Depths of Knowledge', color: COLORS.TIDE }, shadow: { name: 'Veil of Shadows', color: COLORS.SHADOW }, flame: { name: 'Infernal Fury', color: COLORS.FLAME }, growth: { name: 'Primal Might', color: COLORS.GROWTH }, }; module.exports = { COLORS, TYPES, KEYWORDS, ALL_CARDS, CARD_DB, getManaCost, buildStarterDeck, STARTER_DECKS, };