← Shadows results

Shadows

Gemma 4 31b · basic

Initial view of Shadows

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 34,955 bytes · SHA-256 15bdacee53a3
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Shadows of the Abyss</title>
    <link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@700&family=Crimson+Text:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
    <style>
        :root {
            --bg-color: #0a0a0c;
            --card-bg: #1a1a20;
            --accent-color: #8b0000;
            --text-color: #d1d1d1;
            --gold-color: #ffd700;
            --energy-color: #4da6ff;
            --block-color: #a9a9a9;
            --hp-color: #ff4d4d;
        }

        body, html {
            margin: 0; padding: 0; width: 100%; height: 100%;
            background-color: var(--bg-color);
            color: var(--text-color);
            font-family: 'Crimson Text', serif;
            overflow: hidden;
            user-select: none;
        }

        h1, h2, h3 { font-family: 'Cinzel', serif; color: var(--accent-color); margin: 0; }

        #game-container {
            position: relative; width: 100vw; height: 100vh;
            display: flex; justify-content: center; align-items: center;
        }

        .screen {
            position: absolute; width: 100%; height: 100%;
            display: none; flex-direction: column;
            align-items: center; justify-content: center;
            text-align: center;
        }

        .screen.active { display: flex; }

        /* Class Selection */
        .class-grid { display: flex; gap: 20px; margin-top: 40px; }
        .class-card {
            background: var(--card-bg); border: 2px solid #444;
            padding: 20px; width: 200px; cursor: pointer;
            transition: 0.3s; border-radius: 10px;
        }
        .class-card:hover { border-color: var(--accent-color); transform: translateY(-10px); }

        /* Map */
        #map-canvas {
            background: #111; border: 3px solid #333;
            cursor: pointer; box-shadow: 0 0 50px rgba(0,0,0,0.8);
        }

        /* Combat */
        #combat-arena {
            width: 100%; height: 100%;
            background: radial-gradient(circle, #222 0%, #000 100%);
            display: flex; flex-direction: column;
            justify-content: space-between; padding: 20px; box-sizing: border-box;
        }

        .battle-top {
            display: flex; justify-content: space-around; align-items: center;
            height: 60%; width: 100%;
        }

        .entity {
            position: relative; display: flex; flex-direction: column; align-items: center;
            transition: transform 0.1s;
        }
        .entity-sprite {
            width: 120px; height: 120px; background: #333;
            border-radius: 50%; border: 4px solid var(--accent-color);
            margin-bottom: 10px; display: flex; align-items: center; justify-content: center;
            font-size: 40px;
        }
        .status-bar { width: 150px; background: #444; height: 15px; border: 1px solid #000; position: relative; }
        .hp-fill { background: var(--hp-color); height: 100%; width: 100%; transition: width 0.3s; }
        .block-badge {
            position: absolute; top: -20px; right: -20px;
            background: var(--block-color); color: #000;
            width: 30px; height: 30px; border-radius: 50%;
            display: flex; align-items: center; justify-content: center;
            font-weight: bold; font-size: 14px; border: 2px solid #000;
        }
        .intent-icon {
            position: absolute; top: -60px; font-size: 24px;
            background: rgba(0,0,0,0.6); padding: 5px 10px; border-radius: 5px;
        }

        .hand {
            display: flex; justify-content: center; align-items: flex-end;
            gap: 10px; height: 220px; width: 100%;
        }
        .card {
            width: 130px; height: 180px; background: var(--card-bg);
            border: 2px solid #555; border-radius: 10px; cursor: pointer;
            position: relative; display: flex; flex-direction: column;
            padding: 10px; box-sizing: border-box; transition: 0.2s;
            color: #eee; text-align: center;
        }
        .card:hover { transform: translateY(-30px) scale(1.1); border-color: var(--energy-color); }
        .card .cost {
            position: absolute; top: -10px; left: -10px;
            width: 25px; height: 25px; background: var(--energy-color);
            color: #000; border-radius: 50%; font-weight: bold; line-height: 25px;
        }
        .card .name { font-family: 'Cinzel', serif; font-size: 14px; margin-bottom: 10px; color: #fff; }
        .card .desc { font-size: 12px; line-height: 1.2; }

        .hud {
            position: absolute; top: 20px; left: 20px; text-align: left;
            font-family: 'Cinzel', serif; font-size: 20px;
        }

        .btn {
            padding: 10px 20px; background: var(--accent-color); color: white;
            border: none; cursor: pointer; font-family: 'Cinzel', serif;
            border-radius: 5px; transition: 0.2s;
        }
        .btn:hover { background: #c00; }
        .btn:disabled { background: #555; cursor: not-allowed; }

        #end-turn-btn {
            position: absolute; right: 40px; bottom: 100px;
            padding: 20px 30px; font-size: 18px;
        }

        /* Modal / Reward */
        .modal {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.9); display: none;
            justify-content: center; align-items: center; z-index: 100;
        }
        .modal-content {
            background: var(--card-bg); padding: 40px; border: 3px solid var(--accent-color);
            border-radius: 15px; max-width: 800px; text-align: center;
        }
        .reward-options { display: flex; gap: 20px; margin: 20px 0; }

        /* Shop/Rest */
        .shop-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin: 20px 0; }
        .shop-item {
            background: #222; border: 1px solid #444; padding: 10px;
            cursor: pointer; border-radius: 5px;
        }
        .shop-item:hover { background: #333; border-color: var(--gold-color); }

        .log {
            position: absolute; left: 20px; bottom: 150px; width: 300px;
            max-height: 150px; overflow-y: auto; font-size: 14px;
            color: #aaa; pointer-events: none; text-align: left;
        }

        .effect-badge {
            font-size: 10px; background: #444; color: #fff;
            padding: 2px 4px; border-radius: 3px; margin: 2px;
            display: inline-block;
        }
    </style>
</head>
<body>

<div id="game-container">
    <!-- Main Menu -->
    <div id="screen-start" class="screen active">
        <h1>SHADOWS OF THE ABYSS</h1>
        <p>Select Your Cursed Archetype</p>
        <div class="class-grid">
            <div class="class-card" onclick="game.selectClass('Blood Reaper')">
                <h3>Blood Reaper</h3>
                <p>Sacrifice HP for immense power and bleeding wounds.</p>
            </div>
            <div class="class-card" onclick="game.selectClass('Shadowmancer')">
                <h3>Shadowmancer</h3>
                <p>Manipulate shadows to weaken foes and vanish from sight.</p>
            </div>
            <div class="class-card" onclick="game.selectClass('Hellforged')">
                <h3>Hellforged</h3>
                <p>Wield the fires of hell to burn all in your path.</p>
            </div>
        </div>
    </div>

    <!-- Map -->
    <div id="screen-map" class="screen">
        <h2 id="map-title">The Crypts</h2>
        <canvas id="map-canvas" width="600" height="800"></canvas>
        <div style="margin-top: 10px;">Gold: <span id="map-gold">0</span> | HP: <span id="map-hp">0/70</span></div>
    </div>

    <!-- Combat -->
    <div id="screen-combat" class="screen">
        <div id="combat-arena">
            <div class="hud">
                <div>Energy: <span id="combat-energy">3/3</span></div>
                <div>HP: <span id="combat-hp">70/70</span></div>
                <div>Gold: <span id="combat-gold">0</span></div>
            </div>
            
            <div class="battle-top" id="battle-entities">
                <!-- Player and Enemies injected here -->
            </div>

            <div class="log" id="combat-log"></div>
            
            <div class="hand" id="combat-hand"></div>
            <button id="end-turn-btn" class="btn" onclick="combat.endPlayerTurn()">End Turn</button>
        </div>
    </div>

    <!-- Modal -->
    <div id="modal" class="modal">
        <div class="modal-content" id="modal-inner"></div>
    </div>
</div>

<script>
/**
 * DATA & CONFIG
 */
const CARDS_DB = {
    Basic: {
        Strike: { name: 'Strike', cost: 1, type: 'Attack', desc: 'Deal 6 damage', effect: (t, p) => { t.takeDamage(6 + p.strength); }, upgrade: { desc: 'Deal 8 damage', effect: (t, p) => { t.takeDamage(8 + p.strength); } } },
        Defend: { name: 'Defend', cost: 1, type: 'Skill', desc: 'Gain 5 Block', effect: (t, p) => { p.gainBlock(5 + p.dexterity); }, upgrade: { desc: 'Gain 8 Block', effect: (t, p) => { p.gainBlock(8 + p.dexterity); } } },
    },
    BloodReaper: {
        SanguineStrike: { name: 'Sanguine Strike', cost: 1, type: 'Attack', desc: 'Deal 8 dmg. Heal 2 HP.', effect: (t, p) => { t.takeDamage(8 + p.strength); p.heal(2); }, upgrade: { desc: 'Deal 10 dmg. Heal 3 HP.', effect: (t, p) => { t.takeDamage(10 + p.strength); p.heal(3); } } },
        Hemorrhage: { name: 'Hemorrhage', cost: 1, type: 'Attack', desc: 'Deal 5 dmg. Apply 3 Bleed.', effect: (t, p) => { t.takeDamage(5 + p.strength); t.applyStatus('Bleed', 3); }, upgrade: { desc: 'Deal 6 dmg. Apply 4 Bleed.', effect: (t, p) => { t.takeDamage(6 + p.strength); t.applyStatus('Bleed', 4); } } },
        Bloodletting: { name: 'Bloodletting', cost: 1, type: 'Attack', desc: 'Lose 3 HP. Deal 12 dmg.', effect: (t, p) => { p.takeDamage(3); t.takeDamage(12 + p.strength); }, upgrade: { desc: 'Lose 2 HP. Deal 15 dmg.', effect: (t, p) => { p.takeDamage(2); t.takeDamage(15 + p.strength); } } },
        CrimsonEruption: { name: 'Crimson Eruption', cost: 2, type: 'Attack', desc: 'Deal 8 dmg to ALL. Lose 2 HP.', effect: (t, p) => { combat.allEnemies().forEach(e => e.takeDamage(8 + p.strength)); p.takeDamage(2); }, upgrade: { desc: 'Deal 10 dmg to ALL. Lose 2 HP.', effect: (t, p) => { combat.allEnemies().forEach(e => e.takeDamage(10 + p.strength)); p.takeDamage(2); } } },
        CrimsonShield: { name: 'Crimson Shield', cost: 1, type: 'Skill', desc: 'Gain 6 Block. Lose 2 HP.', effect: (t, p) => { p.gainBlock(6 + p.dexterity); p.takeDamage(2); }, upgrade: { desc: 'Gain 8 Block. Lose 2 HP.', effect: (t, p) => { p.gainBlock(8 + p.dexterity); p.takeDamage(2); } } },
        BloodWard: { name: 'Blood Ward', cost: 1, type: 'Skill', desc: 'Gain 3 Block. Gain 1 Regen.', effect: (t, p) => { p.gainBlock(3 + p.dexterity); p.applyStatus('Regen', 1); }, upgrade: { desc: 'Gain 4 Block. Gain 2 Regen.', effect: (t, p) => { p.gainBlock(4 + p.dexterity); p.applyStatus('Regen', 2); } } },
        SacrificialBarrier: { name: 'Sacrificial Barrier', cost: 2, type: 'Skill', desc: 'Gain 10 Block. Lose 5 HP.', effect: (t, p) => { p.gainBlock(10 + p.dexterity); p.takeDamage(5); }, upgrade: { desc: 'Gain 13 Block. Lose 5 HP.', effect: (t, p) => { p.gainBlock(13 + p.dexterity); p.takeDamage(5); } } },
        VitalSurge: { name: 'Vital Surge', cost: 1, type: 'Skill', desc: 'Gain block = missing HP. Exhaust.', effect: (t, p) => { p.gainBlock(70 - p.hp); p.exhaustCard(); }, upgrade: { desc: 'Gain block = missing HP + 3. Exhaust.', effect: (t, p) => { p.gainBlock(73 - p.hp); p.exhaustCard(); } } },
        LifeTap: { name: 'Life Tap', cost: 0, type: 'Skill', desc: 'Draw 2 cards. Lose 3 HP.', effect: (t, p) => { p.drawCards(2); p.takeDamage(3); }, upgrade: { desc: 'Draw 3 cards. Lose 3 HP.', effect: (t, p) => { p.drawCards(3); p.takeDamage(3); } } },
        RendFlesh: { name: 'Rend Flesh', cost: 1, type: 'Skill', desc: 'Apply 5 Bleed to ALL. Lose 2 HP.', effect: (t, p) => { combat.allEnemies().forEach(e => e.applyStatus('Bleed', 5)); p.takeDamage(2); }, upgrade: { desc: 'Apply 7 Bleed to ALL. Lose 2 HP.', effect: (t, p) => { combat.allEnemies().forEach(e => e.applyStatus('Bleed', 7)); p.takeDamage(2); } } },
        SoulSiphon: { name: 'Soul Siphon', cost: 2, type: 'Power', desc: 'Start turn: gain 1 Energy, lose 1 HP.', effect: (t, p) => { p.powers.push('SoulSiphon'); }, upgrade: { cost: 1, desc: 'Start turn: gain 1 Energy, lose 1 HP.', effect: (t, p) => { p.powers.push('SoulSiphon'); } } },
        BloodPact: { name: 'Blood Pact', cost: 1, type: 'Power', desc: 'Whenever you lose HP from card, gain 1 Str.', effect: (t, p) => { p.powers.push('BloodPact'); }, upgrade: { desc: 'Whenever you lose HP from card, gain 2 Str.', effect: (t, p) => { p.powers.push('BloodPactUpgrade'); } } },
    },
    Shadowmancer: {
        ShadowBolt: { name: 'Shadow Bolt', cost: 1, type: 'Attack', desc: 'Deal 6 dmg. Apply 1 Weak.', effect: (t, p) => { t.takeDamage(6 + p.strength); t.applyStatus('Weak', 1); }, upgrade: { desc: 'Deal 8 dmg. Apply 2 Weak.', effect: (t, p) => { t.takeDamage(8 + p.strength); t.applyStatus('Weak', 2); } } },
        GraspOfDespair: { name: 'Grasp of Despair', cost: 1, type: 'Attack', desc: 'Deal 4 dmg. Apply 1 Vuln.', effect: (t, p) => { t.takeDamage(4 + p.strength); t.applyStatus('Vulnerable', 1); }, upgrade: { desc: 'Deal 5 dmg. Apply 2 Vuln.', effect: (t, p) => { t.takeDamage(5 + p.strength); t.applyStatus('Vulnerable', 2); } } },
        NightmareLash: { name: 'Nightmare Lash', cost: 2, type: 'Attack', desc: 'Deal 7 dmg. If Weak, +7 dmg.', effect: (t, p) => { let d = 7 + p.strength; if (t.status.Weak > 0) d += 7; t.takeDamage(d); }, upgrade: { desc: 'Deal 9 dmg. If Weak, +9 dmg.', effect: (t, p) => { let d = 9 + p.strength; if (t.status.Weak > 0) d += 9; t.takeDamage(d); } } },
        EternalDarkness: { name: 'Eternal Darkness', cost: 2, type: 'Attack', desc: 'Deal 3 dmg to random 3x.', effect: (t, p) => { for(let i=0; i<3; i++) { let target = combat.getRandomEnemy(); target.takeDamage(3 + p.strength); } }, upgrade: { desc: 'Deal 4 dmg to random 3x.', effect: (t, p) => { for(let i=0; i<3; i++) { let target = combat.getRandomEnemy(); target.takeDamage(4 + p.strength); } } } },
        CloakOfShadows: { name: 'Cloak of Shadows', cost: 1, type: 'Skill', desc: 'Gain 5 Block. Draw 1.', effect: (t, p) => { p.gainBlock(5 + p.dexterity); p.drawCards(1); }, upgrade: { desc: 'Gain 7 Block. Draw 1.', effect: (t, p) => { p.gainBlock(7 + p.dexterity); p.drawCards(1); } } },
        HauntingMist: { name: 'Haunting Mist', cost: 1, type: 'Skill', desc: 'Gain 7 Block. All Weak 1.', effect: (t, p) => { p.gainBlock(7 + p.dexterity); combat.allEnemies().forEach(e => e.applyStatus('Weak', 1)); }, upgrade: { desc: 'Gain 9 Block. All Weak 1.', effect: (t, p) => { p.gainBlock(9 + p.dexterity); combat.allEnemies().forEach(e => e.applyStatus('Weak', 1)); } } },
        PhantomArmor: { name: 'Phantom Armor', cost: 1, type: 'Skill', desc: 'Gain 8 Block. Next turn 2 Dex.', effect: (t, p) => { p.gainBlock(8 + p.dexterity); p.nextTurnDex += 2; }, upgrade: { desc: 'Gain 10 Block. Next turn 3 Dex.', effect: (t, p) => { p.gainBlock(10 + p.dexterity); p.nextTurnDex += 3; } } },
        WhisperingShroud: { name: 'Whispering Shroud', cost: 1, type: 'Skill', desc: 'Gain 4 Block. Next turn 4 Block.', effect: (t, p) => { p.gainBlock(4 + p.dexterity); p.nextTurnBlock += 4; }, upgrade: { desc: 'Gain 5 Block. Next turn 5 Block.', effect: (t, p) => { p.gainBlock(5 + p.dexterity); p.nextTurnBlock += 5; } } },
        Shadowform: { name: 'Shadowform', cost: 2, type: 'Skill', desc: 'Gain 2 Intangible. Exhaust.', effect: (t, p) => { p.applyStatus('Intangible', 2); p.exhaustCard(); }, upgrade: { desc: 'Gain 3 Intangible. Exhaust.', effect: (t, p) => { p.applyStatus('Intangible', 3); p.exhaustCard(); } } },
        CurseOfMisfortune: { name: 'Curse of Misfortune', cost: 1, type: 'Skill', desc: 'Enemy -3 Str this turn. 1 Vuln.', effect: (t, p) => { t.strength -= 3; t.applyStatus('Vulnerable', 1); }, upgrade: { desc: 'Enemy -4 Str this turn. 2 Vuln.', effect: (t, p) => { t.strength -= 4; t.applyStatus('Vulnerable', 2); } } },
        DarkRitual: { name: 'Dark Ritual', cost: 0, type: 'Skill', desc: 'Gain 2 Energy. Shuffle Dazed.', effect: (t, p) => { p.energy += 2; p.addToDeck('Dazed'); }, upgrade: { desc: 'Gain 2 Energy. Shuffle Dazed.', effect: (t, p) => { p.energy += 2; p.addToDeck('Dazed'); } } },
        UmbralMastery: { name: 'Umbral Mastery', cost: 2, type: 'Power', desc: 'Start turn: All enemies Weak 1.', effect: (t, p) => { p.powers.push('UmbralMastery'); }, upgrade: { desc: 'Start turn: All enemies Weak 2.', effect: (t, p) => { p.powers.push('UmbralMasteryUpgrade'); } } },
    },
    Hellforged: {
        Firebolt: { name: 'Firebolt', cost: 1, type: 'Attack', desc: 'Deal 7 dmg. Apply 2 Burn.', effect: (t, p) => { t.takeDamage(7 + p.strength); t.applyStatus('Burn', 2); }, upgrade: { desc: 'Deal 9 dmg. Apply 3 Burn.', effect: (t, p) => { t.takeDamage(9 + p.strength); t.applyStatus('Burn', 3); } } },
        HellfireBlast: { name: 'Hellfire Blast', cost: 2, type: 'Attack', desc: 'Deal 9 dmg to ALL.', effect: (t, p) => { combat.allEnemies().forEach(e => e.takeDamage(9 + p.strength)); }, upgrade: { desc: 'Deal 12 dmg to ALL.', effect: (t, p) => { combat.allEnemies().forEach(e => e.takeDamage(12 + p.strength)); } } },
        SearingStrike: { name: 'Searing Strike', cost: 1, type: 'Attack', desc: 'Deal 6 dmg. Next turn +1 Energy.', effect: (t, p) => { t.takeDamage(6 + p.strength); p.nextTurnEnergy += 1; }, upgrade: { desc: 'Deal 8 dmg. Next turn +1 Energy.', effect: (t, p) => { t.takeDamage(8 + p.strength); p.nextTurnEnergy += 1; } } },
        Immolate: { name: 'Immolate', cost: 2, type: 'Attack', desc: 'Deal 12 dmg. Exhaust.', effect: (t, p) => { t.takeDamage(12 + p.strength); p.exhaustCard(); }, upgrade: { desc: 'Deal 16 dmg. Exhaust.', effect: (t, p) => { t.takeDamage(16 + p.strength); p.exhaustCard(); } } },
        ObsidianSkin: { name: 'Obsidian Skin', cost: 1, type: 'Skill', desc: 'Gain 7 Block.', effect: (t, p) => { p.gainBlock(7 + p.dexterity); }, upgrade: { desc: 'Gain 10 Block.', effect: (t, p) => { p.gainBlock(10 + p.dexterity); } } },
        FlameWard: { name: 'Flame Ward', cost: 1, type: 'Skill', desc: 'Gain 5 Block. Randomenemy Burn 2.', effect: (t, p) => { p.gainBlock(5 + p.dexterity); combat.getRandomEnemy().applyStatus('Burn', 2); }, upgrade: { desc: 'Gain 6 Block. Randomenemy Burn 3.', effect: (t, p) => { p.gainBlock(6 + p.dexterity); combat.getRandomEnemy().applyStatus('Burn', 3); } } },
        DemonicResilience: { name: 'Demonic Resilience', cost: 1, type: 'Skill', desc: 'Gain 4 Block. Heal 2 HP.', effect: (t, p) => { p.gainBlock(4 + p.dexterity); p.heal(2); }, upgrade: { desc: 'Gain 5 Block. Heal 3 HP.', effect: (t, p) => { p.gainBlock(5 + p.dexterity); p.heal(3); } } },
        BrimstoneShield: { name: 'Brimstone Shield', cost: 1, type: 'Skill', desc: 'Gain 3 Block. +2 Str this turn.', effect: (t, p) => { p.gainBlock(3 + p.dexterity); p.strength += 2; combat.tempBuffs.push({type:'strength', val: 2, duration: 1}); }, upgrade: { desc: 'Gain 4 Block. +3 Str this turn.', effect: (t, p) => { p.gainBlock(4 + p.dexterity); p.strength += 3; combat.tempBuffs.push({type:'strength', val: 3, duration: 1}); } } },
        SummonImp: { name: 'Summon Imp', cost: 1, type: 'Skill', desc: 'Add Imp Claw to hand. Exhaust.', effect: (t, p) => { p.addToHand('ImpClaw'); p.exhaustCard(); }, upgrade: { desc: 'Add Imp Claw+ to hand. Exhaust.', effect: (t, p) => { p.addToHand('ImpClawPlus'); p.exhaustCard(); } } },
        InfernalPact: { name: 'Infernal Pact', cost: 0, type: 'Skill', desc: 'Lose 2 HP. Gain 2 Energy. Add Imp Claw.', effect: (t, p) => { p.takeDamage(2); p.energy += 2; p.addToHand('ImpClaw'); }, upgrade: { desc: 'Lose 1 HP. Gain 2 Energy. Add Imp Claw+.', effect: (t, p) => { p.takeDamage(1); p.energy += 2; p.addToHand('ImpClawPlus'); } } },
        HellfireAura: { name: 'Hellfire Aura', cost: 2, type: 'Power', desc: 'Start turn: deal 3 dmg to ALL.', effect: (t, p) => { p.powers.push('HellfireAura'); }, upgrade: { desc: 'Start turn: deal 5 dmg to ALL.', effect: (t, p) => { p.powers.push('HellfireAuraUpgrade'); } } },
        SoulBurn: { name: 'Soul Burn', cost: 1, type: 'Skill', desc: 'Apply 8 Burn to enemy. Draw 1.', effect: (t, p) => { t.applyStatus('Burn', 8); p.drawCards(1); }, upgrade: { desc: 'Apply 10 Burn to enemy. Draw 1.', effect: (t, p) => { t.applyStatus('Burn', 10); p.drawCards(1); } } },
    },
    Colorless: {
        FlashOfInsight: { name: 'Flash of Insight', cost: 1, type: 'Skill', desc: 'Draw 2 cards.', effect: (t, p) => { p.drawCards(2); }, upgrade: { desc: 'Draw 3 cards.', effect: (t, p) => { p.drawCards(3); } } },
        IronWill: { name: 'Iron Will', cost: 1, type: 'Skill', desc: 'Gain 8 Block.', effect: (t, p) => { p.gainBlock(8 + p.dexterity); }, upgrade: { desc: 'Gain 11 Block.', effect: (t, p) => { p.gainBlock(11 + p.dexterity); } } },
        QuickSlash: { name: 'Quick Slash', cost: 1, type: 'Attack', desc: 'Deal 7 damage.', effect: (t, p) => { t.takeDamage(7 + p.strength); }, upgrade: { desc: 'Deal 9 damage.', effect: (t, p) => { t.takeDamage(9 + p.strength); } } },
        PotentBrew: { name: 'Potent Brew', cost: 0, type: 'Skill', desc: 'Gain 1 Energy. Exhaust.', effect: (t, p) => { p.energy += 1; p.exhaustCard(); }, upgrade: { desc: 'Gain 2 Energy. Exhaust.', effect: (t, p) => { p.energy += 2; p.exhaustCard(); } } },
    }
};

const ENEMIES = {
    Act1: {
        SkeletonWarrior: { name: 'Skeleton Warrior', hp: 22, pattern: [{type:'Attack', val:6}, {type:'Attack', val:6}, {type:'Defend', val:8}], sprite: '💀' },
        ZombieBrute: { name: 'Zombie Brute', hp: 28, pattern: [{type:'Attack', val:8}, {type:'Debuff', status:'Weak', val:2}, {type:'Attack', val:8}], sprite: '🧟' },
        DarkCultist: { name: 'Dark Cultist', hp: 20, pattern: [{type:'Buff', stat:'strength', val:3}, {type:'Attack', val:5}, {type:'Attack', val:5}], sprite: '🧙' },
        RatSwarm: { name: 'Rat Swarm', hp: 15, pattern: [{type:'MultiAttack', count:2, val:3}, {type:'MultiAttack', count:2, val:3}], sprite: '🐀' },
        TombGuardian: { name: 'Tomb Guardian', hp: 42, pattern: [{type:'ShieldBash', atk:6, block:8}, {type:'Flurry', count:3, val:4}, {type:'HeavySlam', val:12}], sprite: '🛡️' },
        BloodWitch: { name: 'Blood Witch', hp: 36, pattern: [{type:'Drain', atk:5, heal:4}, {type:'Curse', vuln:1, weak:1}, {type:'BloodRitual', atk:7, heal:4}], sprite: '🧛' },
        LichKing: { name: 'Lich King', hp: 65, pattern: [{type:'Summon', unit:'SkeletonWarrior'}, {type:'Attack', val:8}, {type:'Defend', val:12}], sprite: '👑' },
    },
    // Act 2 and 3 defined similarly... simplified for now
};

/**
 * GAME LOGIC
 */
class Entity {
    constructor(name, hp) {
        this.name = name;
        this.maxHp = hp;
        this.hp = hp;
        this.block = 0;
        this.strength = 0;
        this.dexterity = 0;
        this.status = { Weak: 0, Vulnerable: 0, Bleed: 0, Burn: 0, Poison: 0, Regen: 0, Intangible: 0 };
        this.powers = [];
    }

    takeDamage(amt) {
        if (this.status.Intangible > 0) amt = 1;
        if (this.status.Vulnerable > 0) amt = Math.floor(amt * 1.5);
        
        let remaining = amt;
        if (this.block > 0) {
            let absorbed = Math.min(this.block, remaining);
            this.block -= absorbed;
            remaining -= absorbed;
        }
        this.hp -= remaining;
        if (this.hp < 0) this.hp = 0;
        combat.log(`${this.name} takes ${amt - (amt - remaining)} damage.`);
    }

    gainBlock(amt) {
        this.block += amt;
    }

    applyStatus(type, val) {
        this.status[type] += val;
        combat.log(`${this.name} gains ${val} ${type}.`);
    }

    heal(amt) {
        this.hp = Math.min(this.maxHp, this.hp + amt);
    }
}

class Player extends Entity {
    constructor(className) {
        super(className, 70);
        this.className = className;
        this.energy = 3;
        this.maxEnergy = 3;
        this.gold = 99;
        this.deck = [];
        this.hand = [];
        this.drawPile = [];
        this.discardPile = [];
        this.nextTurnEnergy = 0;
        this.nextTurnBlock = 0;
        this.nextTurnDex = 0;
        this.relics = [];
        this.potions = [];
        this.exhausted = [];

        // Starting Deck
        for(let i=0; i<5; i++) this.deck.push({id: 'Strike', upgraded: false});
        for(let i=0; i<4; i++) this.deck.push({id: 'Defend', upgraded: false});
        
        const sigMap = { 'Blood Reaper': 'SanguineStrike', 'Shadowmancer': 'ShadowBolt', 'Hellforged': 'Firebolt' };
        this.deck.push({id: sigMap[className], upgraded: false});
    }

    drawCards(count) {
        for (let i = 0; i < count; i++) {
            if (this.drawPile.length === 0) {
                this.drawPile = [...this.discardPile];
                this.discardPile = [];
                this.shuffle(this.drawPile);
            }
            if (this.drawPile.length > 0) {
                this.hand.push(this.drawPile.pop());
            }
        }
    }

    addToDeck(cardId) { this.deck.push({id: cardId, upgraded: false}); }
    
    addToHand(cardId) { this.hand.push({id: cardId, upgraded: false}); }

    exhaustCard() {
        // Implementation: mark card as exhausted in current combat session
        const index = this.hand.findIndex(c => c === this.currentCard);
        if (index !== -1) {
            const card = this.hand.splice(index, 1)[0];
            this.exhausted.push(card);
        }
    }

    shuffle(array) {
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
    }
}

const game = {
    player: null,
    act: 1,
    floor: 1,
    currentScreen: 'screen-start',

    selectClass(className) {
        this.player = new Player(className);
        this.showScreen('screen-map');
        this.renderMap();
    },

    showScreen(id) {
        document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
        document.getElementById(id).classList.add('active');
        this.currentScreen = id;
    },

    renderMap() {
        const canvas = document.getElementById('map-canvas');
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const nodes = [
            {f: 2, t: 'Enemy', x: 200, y: 700}, {f: 2, t: 'Enemy', x: 400, y: 700},
            {f: 3, t: 'Enemy', x: 300, y: 600},
            {f: 4, t: 'Event', x: 300, y: 500},
            {f: 5, t: 'Shop', x: 300, y: 400},
            {f: 6, t: 'Enemy', x: 300, y: 300},
            {f: 7, t: 'Rest', x: 300, y: 200},
            {f: 15, t: 'Boss', x: 300, y: 50}
        ];

        nodes.forEach(n => {
            ctx.beginPath();
            ctx.arc(n.x, n.y, 20, 0, Math.PI*2);
            ctx.fillStyle = n.t === 'Boss' ? 'red' : (n.t === 'Enemy' ? '#555' : '#44a');
            ctx.fill();
            ctx.fillStyle = 'white';
            ctx.fillText(n.t, n.x - 20, n.y - 30);
        });

        canvas.onclick = (e) => {
            const rect = canvas.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const y = e.clientY - rect.top;
            // Simple "click any node" to start combat for demo
            this.startCombat('SkeletonWarrior');
        };

        document.getElementById('map-gold').innerText = this.player.gold;
        document.getElementById('map-hp').innerText = `${this.player.hp}/${this.player.maxHp}`;
    },

    startCombat(enemyKey) {
        combat.init(enemyKey);
        this.showScreen('screen-combat');
    }
};

const combat = {
    player: null,
    enemies: [],
    turn: 'player',
    tempBuffs: [],

    init(enemyKey) {
        this.player = game.player;
        this.enemies = [new Entity(ENEMIES.Act1[enemyKey].name, ENEMIES.Act1[enemyKey].hp)];
        this.enemies[0].sprite = ENEMIES.Act1[enemyKey].sprite;
        this.enemies[0].pattern = ENEMIES.Act1[enemyKey].pattern;
        this.enemies[0].patternIdx = 0;

        this.player.drawPile = [...this.player.deck];
        this.player.shuffle(this.player.drawPile);
        this.player.discardPile = [];
        this.player.hand = [];
        this.player.block = 0;
        this.player.energy = this.player.maxEnergy;

        this.player.drawCards(5);
        this.render();
        this.log("Combat Started!");
    },

    allEnemies() { return this.enemies; },
    getRandomEnemy() { return this.enemies[Math.floor(Math.random() * this.enemies.length)]; },

    log(msg) {
        const l = document.getElementById('combat-log');
        l.innerHTML += `<div>${msg}</div>`;
        l.scrollTop = l.scrollHeight;
    },

    playCard(cardIndex) {
        if (this.turn !== 'player') return;
        const cardObj = this.player.hand[cardIndex];
        const cardData = this.getCardData(cardObj);

        if (this.player.energy < cardData.cost) {
            this.log("Not enough energy!");
            return;
        }

        this.player.energy -= cardData.cost;
        this.player.currentCard = cardObj;
        
        const target = this.getRandomEnemy();
        cardData.effect(target, this.player);
        
        this.player.discardPile.push(this.player.hand.splice(cardIndex, 1)[0]);
        this.render();
    },

    getCardData(cardObj) {
        let pool = CARDS_DB.Basic;
        if (game.player.className === 'Blood Reaper') pool = {...CARDS_DB.Basic, ...CARDS_DB.BloodReaper};
        if (game.player.className === 'Shadowmancer') pool = {...CARDS_DB.Basic, ...CARDS_DB.Shadowmancer};
        if (game.player.className === 'Hellforged') pool = {...CARDS_DB.Basic, ...CARDS_DB.Hellforged};
        
        const data = pool[cardObj.id];
        return cardObj.upgraded ? data.upgrade : data;
    },

    endPlayerTurn() {
        this.turn = 'enemy';
        this.player.block = 0;
        // Discard hand
        this.player.discardPile.push(...this.player.hand);
        this.player.hand = [];
        
        this.log("Enemy's Turn...");
        this.render();
        
        setTimeout(() => this.enemyTurn(), 800);
    },

    enemyTurn() {
        this.enemies.forEach(e => {
            if (e.hp <= 0) return;
            const act = e.pattern[e.patternIdx];
            this.executeEnemyAction(e, act);
            e.patternIdx = (e.patternIdx + 1) % e.pattern.length;
        });

        setTimeout(() => {
            this.turn = 'player';
            this.startPlayerTurn();
        }, 1000);
    },

    executeEnemyAction(e, act) {
        if (act.type === 'Attack') {
            this.player.takeDamage(act.val + e.strength);
        } else if (act.type === 'Defend') {
            e.gainBlock(act.val);
        } else if (act.type === 'Debuff') {
            this.player.applyStatus(act.status, act.val);
        } else if (act.type === 'Buff') {
            e[act.stat] += act.val;
        } else if (act.type === 'MultiAttack') {
            for(let i=0; i<act.count; i++) this.player.takeDamage(act.val + e.strength);
        } else if (act.type === 'ShieldBash') {
            this.player.takeDamage(act.val + e.strength);
            e.gainBlock(act.block);
        }
        this.render();
    },

    startPlayerTurn() {
        this.player.energy = this.player.maxEnergy + this.player.nextTurnEnergy;
        this.player.nextTurnEnergy = 0;
        this.player.gainBlock(this.player.nextTurnBlock);
        this.player.nextTurnBlock = 0;
        this.player.dexterity += this.player.nextTurnDex;
        this.player.nextTurnDex = 0;
        
        this.player.drawCards(5);
        this.log("Your Turn!");
        this.render();
    },

    render() {
        document.getElementById('combat-energy').innerText = `${this.player.energy}/${this.player.maxEnergy}`;
        document.getElementById('combat-hp').innerText = `${this.player.hp}/${this.player.maxHp}`;
        document.getElementById('combat-gold').innerText = this.player.gold;

        const arena = document.getElementById('battle-entities');
        arena.innerHTML = '';

        // Player
        const pDiv = document.createElement('div');
        pDiv.className = 'entity';
        pDiv.innerHTML = `
            <div class="entity-sprite" style="background: #224">👤</div>
            <div class="status-bar"><div class="hp-fill" style="width:${(this.player.hp/this.player.maxHp)*100}%"></div></div>
            <div style="margin-top:5px">${this.player.name}</div>
            ${this.player.block > 0 ? `<div class="block-badge">${this.player.block}</div>` : ''}
            <div style="font-size:12px">${Object.entries(this.player.status).filter(([k,v])=>v>0).map(([k,v])=>`<span class="effect-badge">${k}:${v}</span>`).join('')}</div>
        `;
        arena.appendChild(pDiv);

        // Enemies
        this.enemies.forEach((e, idx) => {
            const eDiv = document.createElement('div');
            eDiv.className = 'entity';
            const intent = e.pattern[e.patternIdx];
            const intentText = intent.type === 'Attack' ? `⚔️ ${intent.val}` : (intent.type === 'Defend' ? `🛡️ ${intent.val}` : '❓');
            
            eDiv.innerHTML = `
                <div class="intent-icon">${intentText}</div>
                <div class="entity-sprite">${e.sprite}</div>
                <div class="status-bar"><div class="hp-fill" style="width:${(e.hp/e.maxHp)*100}%"></div></div>
                <div style="margin-top:5px">${e.name}</div>
                ${e.block > 0 ? `<div class="block-badge">${e.block}</div>` : ''}
            `;
            arena.appendChild(eDiv);
        });

        const handDiv = document.getElementById('combat-hand');
        handDiv.innerHTML = '';
        this.player.hand.forEach((card, idx) => {
            const data = this.getCardData(card);
            const cDiv = document.createElement('div');
            cDiv.className = 'card';
            cDiv.onclick = () => this.playCard(idx);
            cDiv.innerHTML = `
                <div class="cost">${data.cost}</div>
                <div class="name">${data.name}</div>
                <div class="desc">${data.desc}</div>
            `;
            handDiv.appendChild(cDiv);
        });
    }
};

// Initial startup
window.onload = () => {
    // Setup screens
};

</script>
</body>
</html>
<!-- agent-meta {"model":"gemma-4-31b","provider":"cerebras","persona":"basic","sessionId":"371f27c0-e7d2-41d4-b85e-2e1a47942ca7","tokensIn":8243,"tokensOut":11762,"tokensTotal":20005,"turns":1,"toolCalls":0,"failedToolCalls":0,"timestamp":"2026-07-14T21:56:42.466Z"} -->