{"asset_map": {"soldier_blue_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/soldier_blue_walk_837e8d79-1560-44a3-ac3a-5f39cca30065.webp", "type": "image", "prompt": "Generate a tiny 20x20 pixel art soldier for a top-down strategy game. The soldier is wearing a bright blue uniform (#6FB1E8). View is from directly above (top-down). Cute and readable style, dark clean outline. This is frame 1 of a walk cycle with the left leg forward. Transparent background.", "description": "Top-down pixel art player soldier, frame 1 of walk cycle with left leg forward", "subtype": "character", "aspect_ratio": [348, 700], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "soldier_blue_walk2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/soldier_blue_walk2_b825e21c-f66e-45b7-8672-a956f7845955.webp", "type": "image", "prompt": "Generate a tiny 20x20 pixel art soldier matching soldier_blue_walk exactly, but with the right leg forward for the second frame of the walk cycle. Top-down view, blue uniform (#6FB1E8), dark outline, transparent background.", "description": "Top-down pixel art player soldier, frame 2 of walk cycle with right leg forward", "subtype": "character", "aspect_ratio": [575, 1181], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "soldier_red_walk": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/soldier_red_walk_3c6749d9-0f55-4d6d-8fb5-1d36e1fd1b5b.webp", "type": "image", "prompt": "Generate a tiny 20x20 pixel art soldier, identical in style and top-down perspective to soldier_blue_walk but wearing a coral red uniform (#FF8B94). Left leg forward walking pose, dark outline, transparent background.", "description": "Top-down pixel art enemy soldier, frame 1 of walk cycle with left leg forward", "subtype": "character", "aspect_ratio": [619, 1247], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "soldier_red_walk2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/soldier_red_walk2_2c33c5eb-421a-460a-a592-2d39eb8169ea.webp", "type": "image", "prompt": "Generate a tiny 20x20 pixel art soldier, identical in style and top-down perspective to soldier_red_walk but with the right leg forward. Coral red uniform (#FF8B94), dark outline, transparent background.", "description": "Top-down pixel art enemy soldier, frame 2 of walk cycle with right leg forward", "subtype": "character", "aspect_ratio": [576, 1222], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "base_building_blue": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/base_building_blue_d983c39d-93d6-444a-84d9-9786aa308465.webp", "type": "image", "prompt": "Generate a 48x48 pixel art military base building, top-down view. Simple iconic fortress design with gray stone walls and a bright blue (#6FB1E8) roof or flag. Clean geometric shapes, dark outline, polished game asset style, transparent background.", "description": "Pixel art military command center with blue flag/roof for player territory", "subtype": "object", "aspect_ratio": [971, 980], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "base_building_red": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/base_building_red_8a893e98-35ea-4aa1-985b-d2e5fbdd466f.webp", "type": "image", "prompt": "Generate a 48x48 pixel art military base building, top-down view. Structurally identical to base_building_blue but with a coral red (#FF8B94) roof or flag. Gray stone walls, dark outline, transparent background.", "description": "Pixel art military command center with red flag/roof for enemy territory", "subtype": "object", "aspect_ratio": [1013, 1022], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "base_building_neutral": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/base_building_neutral_ecaad6a1-c4bd-4306-a589-f20b923ebf4c.webp", "type": "image", "prompt": "Generate a 48x48 pixel art military base building, top-down view. Structurally identical to base_building_blue but with a neutral gray (#B8B8B8) roof or flag. Gray stone walls, dark outline, transparent background.", "description": "Pixel art military command center with gray flag/roof for neutral territory", "subtype": "object", "aspect_ratio": [1013, 1024], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "tree_decoration": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/tree_decoration_6300b013-a7ad-4d3d-942f-6613bbe8009e.webp", "type": "image", "prompt": "Generate a tiny 16x16 pixel art tree viewed from top-down. Round muted green treetop, minimal brown trunk detail. Simple, non-distracting decorative element for a game map, transparent background.", "description": "Minimal top-down pixel art tree for map decoration", "subtype": "other", "aspect_ratio": [521, 659], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "rock_decoration": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/rock_decoration_80691758-11de-4b1a-aee6-0f6780106ae2.webp", "type": "image", "prompt": "Generate a tiny 12x12 pixel art boulder viewed from top-down. Simple gray stone with basic shading for dimension. Minimalist style, transparent background.", "description": "Minimal top-down pixel art rock for map decoration", "subtype": "other", "aspect_ratio": [469, 428], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "battle_explosion": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/battle_explosion_5f0d7305-4159-4c69-8f7c-fcbd576604db.webp", "type": "image", "prompt": "Generate a 32x32 pixel art explosion. Stylized bright burst with yellow and orange center fading to red edges. Include sharp white highlights for impact. Professional game effect, transparent background.", "description": "Pixel art explosion effect for troop combat", "subtype": "effect", "aspect_ratio": [766, 807], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "march_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/march_sound_634db60c-7974-45dd-9c4c-ea464e3da5b4.mp3", "type": "audio", "prompt": "Short, rhythmic loop of multiple soldiers marching in unison. Light, crisp footsteps on grass/dirt, slightly stylized and cartoonish. Subtle and clean, designed for overlapping playback. 110 BPM rhythm.", "description": "Rhythmic soldier marching sound effect for troop movement", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.25, "loop": true, "animation": null}, "battle_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/battle_sound_2894a7a8-837c-4ba8-a76d-d6014bfccae8.mp3", "type": "audio", "prompt": "Stylized game combat sound. Sharp metallic sword clangs mixed with muffled thuds and tiny cartoonish shouts. Punchy and energetic, non-violent arcade aesthetic, high-quality impact layers.", "description": "Brief combat clash sound effect for territory battles", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2, "loop": false, "animation": null}, "victory_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/victory_sound_efb72938-4191-4edf-b698-8d14fbe5a8f8.mp3", "type": "audio", "prompt": "Short heroic orchestral fanfare. Bright brass trumpets, triumphant percussion, and a rising melodic phrase resolving in a powerful major chord. Satisfying, celebratory, and rewarding.", "description": "Triumphant fanfare for winning the game", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 4, "loop": false, "animation": null}, "defeat_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/defeat_sound_09393814-ec19-4bcd-9bd8-b4b6c3cf9c3c.mp3", "type": "audio", "prompt": "Descending orchestral phrase. Low cello and muted brass playing a melancholic 3-note melody. Soft, disappointed tone that settles into a low hum. Not too harsh.", "description": "Somber audio cue for game over/defeat", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3, "loop": false, "animation": null}, "territory_capture_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/territory_capture_sound_13d6335e-6792-41fc-904f-72e47a88f82d.mp3", "type": "audio", "prompt": "Bright, resonant chime with a shimmering reverb tail. A clear 'ding' or 'pop' sound followed by a short upward melodic trill. High-frequency, positive, and tactile feedback.", "description": "Positive chime for capturing a territory", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.17, "loop": false, "animation": null}, "button_click_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/button_click_sound_33dcf44e-fe9a-4bdd-bc7c-7da3f8f9f88a.mp3", "type": "audio", "prompt": "Subtle, high-quality plastic button click. Short attack, clean 'tick' sound, very low decay. Professional, neutral, and satisfying for repeated UI interaction.", "description": "Soft UI interaction sound effect", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.3, "loop": false, "animation": null}, "background_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/background_music_b044b1eb-155a-4230-9335-133a8edfb4a1.mp3", "type": "audio", "prompt": "Upbeat military-themed orchestral strategy music. Driving snare drum rudiments, rhythmic string ostinatos, and heroic brass stabs. 115 BPM, 4/4 time, key of G minor. Maintains energy and focus for tactical thinking. Seamless loop points, professional arrangement.", "description": "Main gameplay theme music with a military strategic feel", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>War Conquest: Territory Battle</title>\n    <link href=\"https://fonts.googleapis.com/css2?family=Orbitron:wght@700;900&family=Inter:wght@400;600;700&display=swap\" rel=\"stylesheet\">\n    <style>\n        :root {\n            --color-water: #2B5F9E;\n            --color-player: #6FB1E8;\n            --color-enemy: #FF8B94;\n            --color-neutral: #B8B8B8;\n            --color-border: #2C3E50;\n            --color-text: #FFFFFF;\n            --space-sm: 16px;\n            --space-md: 24px;\n            --transition-fast: 150ms;\n            --transition-normal: 300ms;\n        }\n\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n\n        body, html {\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n            touch-action: none;\n            -ms-touch-action: none;\n            font-family: 'Inter', sans-serif;\n        }\n\n        #game-world {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            background-color: var(--color-water);\n        }\n\n        #game-canvas {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n        }\n\n        /* UI Overlay */\n        .ui-overlay {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            pointer-events: none;\n            z-index: 10;\n        }\n\n        .ui-overlay > * {\n            pointer-events: auto;\n        }\n\n        /* HUD */\n        .top-hud {\n            position: absolute;\n            top: var(--space-sm);\n            left: var(--space-sm);\n            right: var(--space-sm);\n            display: flex;\n            flex-direction: column;\n            gap: 12px;\n            pointer-events: none;\n        }\n\n        .hud-row {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n\n        .level-info {\n            background: rgba(0, 0, 0, 0.7);\n            padding: 8px 16px;\n            border-radius: 8px;\n            color: #FFD700;\n            font-family: 'Orbitron', sans-serif;\n            font-size: 18px;\n            font-weight: 700;\n        }\n\n        .stat-display {\n            background: rgba(0, 0, 0, 0.7);\n            padding: 8px 16px;\n            border-radius: 12px;\n            color: var(--color-text);\n            font-size: 20px;\n            font-weight: 700;\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            pointer-events: auto;\n        }\n\n        .stat-icon {\n            width: 32px;\n            height: 32px;\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-size: 18px;\n        }\n\n        .player-stat .stat-icon {\n            background-color: var(--color-player);\n        }\n\n        .enemy-stat .stat-icon {\n            background-color: var(--color-enemy);\n        }\n\n        /* Control Buttons */\n        .control-buttons {\n            position: absolute;\n            top: var(--space-sm);\n            right: var(--space-sm);\n            display: flex;\n            gap: 12px;\n        }\n\n        .btn {\n            width: 96px;\n            height: 96px;\n            background: rgba(0, 0, 0, 0.7);\n            border: 3px solid rgba(255, 255, 255, 0.3);\n            border-radius: 16px;\n            color: var(--color-text);\n            font-size: 40px;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);\n        }\n\n        .btn:hover {\n            background: rgba(0, 0, 0, 0.85);\n            border-color: rgba(255, 255, 255, 0.5);\n            transform: scale(1.05);\n        }\n\n        .btn:active {\n            transform: scale(0.95);\n        }\n\n        /* Game Over Screen */\n        .game-over-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.85);\n            display: none;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 100;\n        }\n\n        .game-over-screen.show {\n            display: flex;\n        }\n\n        .game-over-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 72px;\n            font-weight: 900;\n            color: var(--color-text);\n            text-shadow: 4px 4px 8px rgba(0, 0, 0, 0.8);\n            margin-bottom: 32px;\n            animation: slideIn 0.5s ease-out;\n        }\n\n        .game-over-title.victory {\n            color: #4CAF50;\n        }\n\n        .game-over-title.defeat {\n            color: #F44336;\n        }\n\n        .game-over-stats {\n            background: rgba(255, 255, 255, 0.1);\n            padding: 32px;\n            border-radius: 16px;\n            margin-bottom: 48px;\n            font-size: 28px;\n            color: var(--color-text);\n            text-align: center;\n            line-height: 1.6;\n        }\n\n        .restart-btn {\n            width: 320px;\n            height: 96px;\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n            border: none;\n            border-radius: 16px;\n            color: var(--color-text);\n            font-size: 32px;\n            font-weight: 700;\n            cursor: pointer;\n            transition: all var(--transition-normal);\n            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);\n        }\n\n        .restart-btn:hover {\n            transform: scale(1.05);\n            box-shadow: 0 8px 24px rgba(102, 126, 234, 0.5);\n        }\n\n        .restart-btn:active {\n            transform: scale(0.95);\n        }\n\n        /* Pause Menu */\n        .pause-menu {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.85);\n            display: none;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 100;\n        }\n\n        .pause-menu.show {\n            display: flex;\n        }\n\n        .pause-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 60px;\n            font-weight: 900;\n            color: var(--color-text);\n            margin-bottom: 48px;\n        }\n\n        .pause-btn {\n            width: 320px;\n            height: 80px;\n            background: rgba(255, 255, 255, 0.1);\n            border: 3px solid rgba(255, 255, 255, 0.3);\n            border-radius: 12px;\n            color: var(--color-text);\n            font-size: 28px;\n            font-weight: 600;\n            cursor: pointer;\n            margin-bottom: 16px;\n            transition: all var(--transition-fast);\n        }\n\n        .pause-btn:hover {\n            background: rgba(255, 255, 255, 0.2);\n            border-color: rgba(255, 255, 255, 0.5);\n        }\n\n        @keyframes slideIn {\n            from {\n                opacity: 0;\n                transform: translateY(-50px);\n            }\n            to {\n                opacity: 1;\n                transform: translateY(0);\n            }\n        }\n\n        /* Main Menu / Level Selection */\n        .menu-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(180deg, #1a2a6c 0%, #b21f1f 50%, #fdbb2d 100%);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 200;\n            padding: 40px;\n        }\n\n        .menu-screen.hidden {\n            display: none;\n        }\n\n        .menu-title {\n            font-family: 'Orbitron', sans-serif;\n            font-size: 64px;\n            color: white;\n            text-align: center;\n            margin-bottom: 40px;\n            text-shadow: 0 0 20px rgba(0,0,0,0.5);\n        }\n\n        .difficulty-toggle {\n            display: flex;\n            gap: 20px;\n            margin-bottom: 40px;\n        }\n\n        .diff-btn {\n            padding: 15px 30px;\n            font-size: 20px;\n            font-weight: bold;\n            border: 2px solid white;\n            background: rgba(255,255,255,0.1);\n            color: white;\n            border-radius: 10px;\n            cursor: pointer;\n            transition: all 0.2s;\n        }\n\n        .diff-btn.active {\n            background: white;\n            color: #b21f1f;\n        }\n\n        .level-grid {\n            display: grid;\n            grid-template-columns: repeat(5, 1fr);\n            gap: 15px;\n            max-height: 600px;\n            overflow-y: auto;\n            padding: 20px;\n            background: rgba(0,0,0,0.3);\n            border-radius: 15px;\n            width: 100%;\n        }\n\n        .level-card {\n            aspect-ratio: 1;\n            background: rgba(255,255,255,0.2);\n            border: 2px solid rgba(255,255,255,0.5);\n            border-radius: 10px;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            color: white;\n            font-size: 24px;\n            font-weight: bold;\n            cursor: pointer;\n            transition: transform 0.1s;\n        }\n\n        .level-card:hover {\n            transform: scale(1.1);\n            background: rgba(255,255,255,0.4);\n        }\n\n        .level-card.locked {\n            opacity: 0.5;\n            cursor: not-allowed;\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\">\n        <canvas id=\"game-canvas\"></canvas>\n        \n        <div class=\"ui-overlay\">\n            <div class=\"top-hud\">\n                <div class=\"hud-row\">\n                    <div class=\"level-info\" id=\"level-display\">LEVEL 1</div>\n                    <div class=\"level-info\" id=\"difficulty-display\">NORMAL</div>\n                </div>\n                <div class=\"hud-row\">\n                    <div class=\"stat-display player-stat\">\n                        <div class=\"stat-icon\">\ud83d\udc64</div>\n                        <span id=\"player-troops\">0</span>\n                    </div>\n                    <div class=\"stat-display enemy-stat\">\n                        <div class=\"stat-icon\">\ud83e\udd16</div>\n                        <span id=\"enemy-troops\">0</span>\n                    </div>\n                </div>\n            </div>\n\n            <div class=\"control-buttons\">\n                <button class=\"btn\" id=\"pause-btn\">\u23f8</button>\n            </div>\n\n            <div class=\"game-over-screen\" id=\"game-over\">\n                <div class=\"game-over-title\" id=\"game-over-title\">VICTORY!</div>\n                <div class=\"game-over-stats\" id=\"game-over-stats\">\n                    Territories Controlled: 10<br>\n                    Total Troops: 450\n                </div>\n                <button class=\"restart-btn\" id=\"next-level-btn\" style=\"margin-bottom: 12px;\">NEXT LEVEL</button>\n                <button class=\"restart-btn\" id=\"game-over-restart-btn\">RESTART GAME</button>\n            </div>\n\n            <div class=\"pause-menu\" id=\"pause-menu\">\n                <div class=\"pause-title\">PAUSED</div>\n                <button class=\"pause-btn\" id=\"resume-btn\">Resume</button>\n                <button class=\"pause-btn\" id=\"pause-restart-btn\">Restart Game</button>\n                <button class=\"pause-btn\" id=\"main-menu-btn\">Main Menu</button>\n            </div>\n\n            <div class=\"menu-screen\" id=\"main-menu\">\n                <div class=\"menu-title\">WAR CONQUEST</div>\n                <div class=\"difficulty-toggle\">\n                    <button class=\"diff-btn active\" id=\"diff-normal\">NORMAL</button>\n                    <button class=\"diff-btn\" id=\"diff-hard\">HARD</button>\n                </div>\n                <div class=\"level-grid\" id=\"level-grid\">\n                    <!-- Levels generated by JS -->\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <script>\n        /*\n         * WAR CONQUEST: TERRITORY BATTLE\n         * \n         * A real-time strategy game where players command armies to conquer territories.\n         * - Tap territories to select and deploy troops\n         * - Control territories to generate more soldiers\n         * - Defeat all enemy territories to win\n         * \n         * Features:\n         * - Dynamic territory generation with strategic connections\n         * - Real-time troop production and movement\n         * - AI opponent with strategic behavior\n         * - Edit mode for customizing game parameters\n         * - Mobile-first touch controls\n         */\n\n        async function run(mode) {\n            const gameWorld = document.getElementById('game-world');\n            const canvas = document.getElementById('game-canvas');\n            const ctx = canvas.getContext('2d');\n\n            // Initialize display\n            function resizeCanvas() {\n                canvas.width = gameWorld.clientWidth;\n                canvas.height = gameWorld.clientHeight;\n            }\n            resizeCanvas();\n            window.addEventListener('resize', resizeCanvas);\n\n            // Asset cache\n            const assetCache = {};\n            const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n            const audioBuffers = {};\n\n            // Preload assets\n            async function preloadAssets() {\n                const assetIds = [\n                    'soldier_blue_walk', 'soldier_blue_walk2',\n                    'soldier_red_walk', 'soldier_red_walk2',\n                    'base_building_blue', 'base_building_red', 'base_building_neutral',\n                    'tree_decoration', 'rock_decoration', 'battle_explosion',\n                    'march_sound', 'battle_sound', 'victory_sound', 'defeat_sound',\n                    'territory_capture_sound', 'button_click_sound', 'background_music'\n                ];\n\n                const promises = assetIds.map(async (id) => {\n                    const assetInfo = lib.getAsset(id);\n                    if (!assetInfo) return;\n\n                    if (assetInfo.type === 'image') {\n                        return new Promise((resolve) => {\n                            const img = new Image();\n                            img.onload = () => {\n                                assetCache[id] = img;\n                                resolve();\n                            };\n                            img.onerror = () => resolve();\n                            img.src = assetInfo.url;\n                        });\n                    } else if (assetInfo.type === 'audio') {\n                        try {\n                            const response = await fetch(assetInfo.url);\n                            const arrayBuffer = await response.arrayBuffer();\n                            const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n                            audioBuffers[id] = audioBuffer;\n                        } catch (e) {\n                            lib.log(`Failed to load audio: ${id}`);\n                        }\n                    }\n                });\n\n                await Promise.all(promises);\n            }\n\n            await preloadAssets();\n\n            // Audio playback helper\n            function playSound(soundId, volume = 1.0, loop = false) {\n                if (!audioBuffers[soundId]) return null;\n                \n                const source = audioContext.createBufferSource();\n                const gainNode = audioContext.createGain();\n                \n                source.buffer = audioBuffers[soundId];\n                source.loop = loop;\n                gainNode.gain.value = volume;\n                \n                source.connect(gainNode);\n                gainNode.connect(audioContext.destination);\n                source.start(0);\n                \n                return source;\n            }\n\n            // Start background music\n            let backgroundMusic = null;\n            if (mode === 'play') {\n                backgroundMusic = playSound('background_music', 0.3, true);\n            }\n\n            // Initialize game config with defaults if not set\n            if (!window.gameConfig) {\n                window.gameConfig = {};\n            }\n\n            const defaults = {\n                territoryCount: 10,\n                territorySizeVariation: 'Mixed',\n                waterColor: '#2B5F9E',\n                landColorScheme: 'Classic',\n                startingTerritoriesPlayer: 1,\n                startingTerritoriesEnemy: 1,\n                neutralTerritories: 8,\n                troopGenerationRate: 1.0,\n                initialTroopCount: 50,\n                troopSendPercentage: 50,\n                aiDifficulty: 'Medium',\n                aiAggression: 'Balanced',\n                winCondition: 'Eliminate All Enemies',\n                timeLimit: 'None'\n            };\n\n            // Apply defaults\n            for (const key in defaults) {\n                if (window.gameConfig[key] === undefined) {\n                    window.gameConfig[key] = defaults[key];\n                }\n            }\n\n            // Game parameters\n            lib.showGameParameters({\n                name: 'War Conquest Settings',\n                params: {\n                    'Territory Count': {\n                        key: 'territoryCount',\n                        type: 'slider',\n                        min: 6,\n                        max: 15,\n                        step: 1\n                    },\n                    'Territory Size': {\n                        key: 'territorySizeVariation',\n                        type: 'dropdown',\n                        options: [\n                            { label: 'Uniform', value: 'Uniform' },\n                            { label: 'Mixed', value: 'Mixed' },\n                            { label: 'Random', value: 'Random' }\n                        ]\n                    },\n                    'Player Start Territories': {\n                        key: 'startingTerritoriesPlayer',\n                        type: 'slider',\n                        min: 1,\n                        max: 3,\n                        step: 1\n                    },\n                    'Enemy Start Territories': {\n                        key: 'startingTerritoriesEnemy',\n                        type: 'slider',\n                        min: 1,\n                        max: 3,\n                        step: 1\n                    },\n                    'Troop Generation Rate': {\n                        key: 'troopGenerationRate',\n                        type: 'slider',\n                        min: 0.5,\n                        max: 2.0,\n                        step: 0.1\n                    },\n                    'Initial Troops': {\n                        key: 'initialTroopCount',\n                        type: 'dropdown',\n                        options: [\n                            { label: '0', value: 0 },\n                            { label: '50', value: 50 },\n                            { label: '100', value: 100 },\n                            { label: '200', value: 200 }\n                        ]\n                    },\n                    'Troop Send %': {\n                        key: 'troopSendPercentage',\n                        type: 'dropdown',\n                        options: [\n                            { label: '25%', value: 25 },\n                            { label: '50%', value: 50 },\n                            { label: '75%', value: 75 },\n                            { label: '100%', value: 100 }\n                        ]\n                    },\n                    'AI Difficulty': {\n                        key: 'aiDifficulty',\n                        type: 'dropdown',\n                        options: [\n                            { label: 'Easy', value: 'Easy' },\n                            { label: 'Medium', value: 'Medium' },\n                            { label: 'Hard', value: 'Hard' }\n                        ]\n                    },\n                    'AI Aggression': {\n                        key: 'aiAggression',\n                        type: 'dropdown',\n                        options: [\n                            { label: 'Defensive', value: 'Defensive' },\n                            { label: 'Balanced', value: 'Balanced' },\n                            { label: 'Aggressive', value: 'Aggressive' }\n                        ]\n                    }\n                }\n            });\n\n            // Runtime state (not in gameConfig)\n            let territories = [];\n            let troopGroups = [];\n            let activeEffects = [];\n            let tintedCache = {};\n            let selectedTerritory = null;\n            let gameState = 'menu';\n            let isPaused = false;\n            let lastUpdateTime = Date.now();\n            let troopAccumulator = 0;\n            let aiThinkTimer = 0;\n            let hudUpdateTimer = 0;\n            let clashCheckTimer = 0;\n            let noChangeTimer = 0;\n            let lastTerritoryState = null;\n\n            function getTintedSprite(spriteId, hue) {\n                const cacheKey = `${spriteId}_${hue}`;\n                if (tintedCache[cacheKey]) return tintedCache[cacheKey];\n\n                const original = assetCache[spriteId];\n                if (!original) return null;\n\n                const canvas = document.createElement('canvas');\n                canvas.width = original.width;\n                canvas.height = original.height;\n                const tCtx = canvas.getContext('2d');\n                \n                if (hue !== 0) {\n                    tCtx.filter = `hue-rotate(${hue}deg)`;\n                }\n                tCtx.drawImage(original, 0, 0);\n                \n                tintedCache[cacheKey] = canvas;\n                return canvas;\n            }\n\n            function addExplosion(x, y) {\n                activeEffects.push({\n                    x, y,\n                    type: 'explosion',\n                    life: 0.4,\n                    maxLife: 0.4\n                });\n            }\n            \n            let currentLevel = 1;\n            let selectedDifficulty = 'Normal';\n\n            // Seeded random for deterministic levels\n            function seededRandom(seed) {\n                const x = Math.sin(seed++) * 10000;\n                return x - Math.floor(x);\n            }\n\n            const factionData = {\n                'player': { color: '#6FB1E8', hue: 0, building: 'base_building_blue', soldier: 'soldier_blue_walk' },\n                'enemy_1': { color: '#FF8B94', hue: 0, building: 'base_building_red', soldier: 'soldier_red_walk' },\n                'enemy_2': { color: '#A29BFE', hue: 250, building: 'base_building_red', soldier: 'soldier_red_walk' }, // Purple\n                'enemy_3': { color: '#55E6C1', hue: 160, building: 'base_building_red', soldier: 'soldier_red_walk' }, // Green\n                'enemy_4': { color: '#F9CA24', hue: 50, building: 'base_building_red', soldier: 'soldier_red_walk' },  // Orange/Yellow\n                'enemy_5': { color: '#FF78CB', hue: 300, building: 'base_building_red', soldier: 'soldier_red_walk' }, // Pink\n                'enemy_6': { color: '#1abc9c', hue: 180, building: 'base_building_red', soldier: 'soldier_red_walk' }, // Turquoise\n                'enemy_7': { color: '#e67e22', hue: 30, building: 'base_building_red', soldier: 'soldier_red_walk' },  // Orange-Brown\n                'neutral': { color: '#B8B8B8', hue: 0, building: 'base_building_neutral', soldier: null }\n            };\n\n            // Territory generation\n            function generateTerritories(level, difficulty) {\n                const territories = [];\n                const seed = level * (difficulty === 'Hard' ? 2 : 1);\n                let randIdx = seed;\n                \n                function getNextRand() {\n                    return seededRandom(randIdx++);\n                }\n\n                // Scaling properties based on level\n                let count = Math.min(8 + Math.floor(level / 3), 24);\n                if (difficulty === 'Hard') count = Math.max(count, 15);\n                const padding = 80;\n                const minDistance = level > 20 ? 110 : 130;\n\n                for (let i = 0; i < count; i++) {\n                    let x, y, radius;\n                    let attempts = 0;\n                    \n                    do {\n                        x = padding + getNextRand() * (canvas.width - padding * 2);\n                        y = padding + getNextRand() * (canvas.height - padding * 2);\n                        \n                        radius = 55 + getNextRand() * 35;\n                        attempts++;\n                    } while (\n                        attempts < 100 &&\n                        territories.some(t => {\n                            const dx = t.x - x;\n                            const dy = t.y - y;\n                            return Math.sqrt(dx * dx + dy * dy) < minDistance;\n                        })\n                    );\n\n                    territories.push({\n                        id: i,\n                        x,\n                        y,\n                        radius,\n                        owner: 'neutral',\n                        troops: 15 + Math.floor(getNextRand() * 25),\n                        connections: []\n                    });\n                }\n\n                // Assign player starting territory\n                territories[0].owner = 'player';\n                territories[0].troops = 50;\n\n                // Determine number of enemy factions\n                let enemyFactionCount = Math.min(1 + Math.floor(level / 10), 4);\n                let enemiesPerFaction = (difficulty === 'Hard') ? 2 : 1;\n\n                if (difficulty === 'Hard') {\n                    // Hard mode has 4-7 enemy factions as requested\n                    enemyFactionCount = Math.min(4 + Math.floor(level / 10), 7);\n                    enemiesPerFaction = 1; // Keep it clean with more factions\n                }\n\n                const availableIndices = Array.from({length: territories.length - 1}, (_, i) => i + 1);\n                // Shuffle available indices\n                for (let i = availableIndices.length - 1; i > 0; i--) {\n                    const j = Math.floor(getNextRand() * (i + 1));\n                    [availableIndices[i], availableIndices[j]] = [availableIndices[j], availableIndices[i]];\n                }\n\n                for (let f = 1; f <= enemyFactionCount; f++) {\n                    const factionKey = `enemy_${f}`;\n                    for (let e = 0; e < enemiesPerFaction; e++) {\n                        if (availableIndices.length > 0) {\n                            const idx = availableIndices.pop();\n                            territories[idx].owner = factionKey;\n                            territories[idx].troops = (difficulty === 'Hard' ? 50 : 40 + Math.floor(getNextRand() * 20));\n                        }\n                    }\n                }\n\n                // Create connections based on proximity\n                for (let i = 0; i < territories.length; i++) {\n                    const distances = territories\n                        .map((t, idx) => ({\n                            idx,\n                            dist: Math.hypot(t.x - territories[i].x, t.y - territories[i].y)\n                        }))\n                        .filter(d => d.idx !== i)\n                        .sort((a, b) => a.dist - b.dist)\n                        .slice(0, 3 + Math.floor(level / 15));\n\n                    distances.forEach(d => {\n                        if (!territories[i].connections.includes(d.idx)) {\n                            territories[i].connections.push(d.idx);\n                        }\n                        if (!territories[d.idx].connections.includes(i)) {\n                            territories[d.idx].connections.push(i);\n                        }\n                    });\n                }\n\n                return territories;\n            }\n\n            // Troop group class\n            class TroopGroup {\n                constructor(from, to, count, owner) {\n                    this.from = from;\n                    this.to = to;\n                    this.count = Math.floor(count);\n                    this.owner = owner;\n                    this.progress = 0;\n                    this.soldiers = [];\n\n                    // Visual soldier limit for performance\n                    const visualLimit = 12;\n                    const soldierCount = Math.min(this.count, visualLimit);\n                    const spacing = 18;\n                    for (let i = 0; i < soldierCount; i++) {\n                        this.soldiers.push({\n                            offset: (i * spacing) - (soldierCount * spacing / 2),\n                            animFrame: Math.random() > 0.5 ? 0 : 1,\n                            animTimer: Math.random() * 0.3\n                        });\n                    }\n                }\n\n                update(deltaTime) {\n                    const fromTerr = territories[this.from];\n                    const toTerr = territories[this.to];\n                    const distance = Math.hypot(toTerr.x - fromTerr.x, toTerr.y - fromTerr.y);\n                    const speed = 150; // pixels per second\n\n                    this.progress += (speed / distance) * deltaTime;\n                    \n                    // Current position for collision detection\n                    this.x = fromTerr.x + (toTerr.x - fromTerr.x) * this.progress;\n                    this.y = fromTerr.y + (toTerr.y - fromTerr.y) * this.progress;\n\n                    // Update soldier animations\n                    this.soldiers.forEach(soldier => {\n                        soldier.animTimer += deltaTime;\n                        if (soldier.animTimer >= 0.3) {\n                            soldier.animTimer = 0;\n                            soldier.animFrame = 1 - soldier.animFrame;\n                        }\n                    });\n\n                    // Sync visual soldiers with count if it reduced due to mid-air combat\n                    const desiredSoldierCount = Math.min(Math.floor(this.count), 50);\n                    if (this.soldiers.length > desiredSoldierCount) {\n                        this.soldiers.length = desiredSoldierCount;\n                    }\n\n                    return this.progress >= 1.0;\n                }\n\n                draw(ctx) {\n                    const fromTerr = territories[this.from];\n                    const toTerr = territories[this.to];\n\n                    const x = fromTerr.x + (toTerr.x - fromTerr.x) * this.progress;\n                    const y = fromTerr.y + (toTerr.y - fromTerr.y) * this.progress;\n\n                    const angle = Math.atan2(toTerr.y - fromTerr.y, toTerr.x - fromTerr.x);\n                    const perpAngle = angle + Math.PI / 2;\n\n                    const faction = factionData[this.owner];\n                    const spriteBase = faction.soldier;\n\n                    // Group drawing for efficiency\n                    this.soldiers.forEach(soldier => {\n                        const offsetX = x + Math.cos(perpAngle) * soldier.offset;\n                        const offsetY = y + Math.sin(perpAngle) * soldier.offset;\n\n                        const frameName = soldier.animFrame === 0 ? spriteBase : spriteBase + '2';\n                        const sprite = getTintedSprite(frameName, faction.hue);\n\n                        if (sprite) {\n                            ctx.save();\n                            ctx.translate(offsetX, offsetY);\n                            ctx.rotate(angle);\n                            ctx.drawImage(sprite, -10, -10, 20, 20);\n                            ctx.restore();\n                        }\n                    });\n\n                    // Draw count badge\n                    if (this.count > 0) {\n                        ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n                        ctx.beginPath();\n                        ctx.roundRect(x - 22, y - 45, 44, 22, 5);\n                        ctx.fill();\n                        ctx.fillStyle = '#FFFFFF';\n                        ctx.font = 'bold 16px Inter';\n                        ctx.textAlign = 'center';\n                        ctx.textBaseline = 'middle';\n                        ctx.fillText(Math.floor(this.count), x, y - 34);\n                    }\n                }\n            }\n\n            function startGame(level, difficulty) {\n                currentLevel = level;\n                selectedDifficulty = difficulty;\n                \n                document.getElementById('main-menu').classList.add('hidden');\n                document.getElementById('game-over').classList.remove('show');\n                document.getElementById('pause-menu').classList.remove('show');\n                \n                // Show HUD\n                document.querySelector('.top-hud').style.display = 'flex';\n                document.querySelector('.control-buttons').style.display = 'flex';\n                \n                document.getElementById('level-display').textContent = `LEVEL ${currentLevel}`;\n                document.getElementById('difficulty-display').textContent = selectedDifficulty.toUpperCase();\n                \n                territories = generateTerritories(currentLevel, selectedDifficulty);\n                troopGroups = [];\n                activeEffects = [];\n                selectedTerritory = null;\n                gameState = 'playing';\n                isPaused = false;\n                troopAccumulator = 0;\n                aiThinkTimer = 0;\n                noChangeTimer = 0;\n                \n                playSound('button_click_sound', 0.5);\n            }\n\n            // AI logic\n            function updateAI(deltaTime) {\n                if (gameState !== 'playing' || isPaused) return;\n\n                const difficulty = selectedDifficulty;\n                let thinkInterval = 1.5; // Normal\n                \n                if (difficulty === 'Hard') {\n                    // Hard mode is \"calm and strategic\" - slower updates but smarter decisions\n                    thinkInterval = 3.5; \n                }\n\n                aiThinkTimer += deltaTime;\n                if (aiThinkTimer < thinkInterval) return;\n                aiThinkTimer = 0;\n\n                const allFactions = [...new Set(territories.map(t => t.owner))];\n                const aiFactions = allFactions.filter(o => o.startsWith('enemy_'));\n\n                aiFactions.forEach(faction => {\n                    const myTerritories = territories.filter(t => t.owner === faction);\n                    if (myTerritories.length === 0) return;\n\n                    if (difficulty === 'Hard') {\n                        // STRATEGIC HARD MODE\n                        myTerritories.forEach(source => {\n                            const neighbors = source.connections.map(id => territories[id]);\n                            \n                            // 1. Internal Reinforcement: Help neighbors under pressure\n                            const myWeakNeighbors = neighbors.filter(n => n.owner === faction && n.troops < source.troops * 0.4);\n                            if (myWeakNeighbors.length > 0 && source.troops > 40) {\n                                const target = myWeakNeighbors.sort((a, b) => a.troops - b.troops)[0];\n                                const sendCount = Math.floor(source.troops * 0.4);\n                                troopGroups.push(new TroopGroup(source.id, target.id, sendCount, faction));\n                                source.troops -= sendCount;\n                                return; // One action per think cycle per territory\n                            }\n\n                            // 2. Interception Strategy: If a neighbor is being attacked, send troops to help\n                            const hostileTroopsTargetingMe = troopGroups.filter(g => g.to === source.id && g.owner !== faction);\n                            if (hostileTroopsTargetingMe.length > 0 && source.troops > 10) {\n                                // Already at source, just defending. But maybe neighbors can help?\n                                neighbors.filter(n => n.owner === faction && n.troops > 30).forEach(neighbor => {\n                                    const sendCount = Math.floor(neighbor.troops * 0.5);\n                                    troopGroups.push(new TroopGroup(neighbor.id, source.id, sendCount, faction));\n                                    neighbor.troops -= sendCount;\n                                });\n                            }\n\n                            // 3. Calm Attack: Only attack if we have a clear advantage\n                            const enemyTargets = neighbors.filter(t => t.owner !== faction);\n                            if (enemyTargets.length > 0 && source.troops > 50) {\n                                const target = enemyTargets.sort((a, b) => a.troops - b.troops)[0];\n                                const advantageRatio = target.owner === 'neutral' ? 1.0 : 1.5;\n                                \n                                if (source.troops > target.troops * advantageRatio) {\n                                    const sendCount = Math.floor(source.troops * 0.7);\n                                    troopGroups.push(new TroopGroup(source.id, target.id, sendCount, faction));\n                                    source.troops -= sendCount;\n                                }\n                            }\n                        });\n                    } else {\n                        // NORMAL MODE: Standard active behavior\n                        myTerritories.forEach(source => {\n                            if (source.troops < 20) return;\n                            \n                            const targets = source.connections\n                                .map(id => territories[id])\n                                .filter(t => t.owner !== faction);\n                            \n                            if (targets.length === 0) return;\n\n                            // Normal AI attacks more frequently but with less preparation\n                            if (Math.random() > 0.5) {\n                                const target = targets[Math.floor(Math.random() * targets.length)];\n                                if (source.troops > target.troops + 5 || target.owner === 'neutral') {\n                                    const sendCount = Math.floor(source.troops * 0.5);\n                                    troopGroups.push(new TroopGroup(source.id, target.id, sendCount, faction));\n                                    source.troops -= sendCount;\n                                }\n                            }\n                        });\n                    }\n                });\n            }\n            // Setup level grid\n            const levelGrid = document.getElementById('level-grid');\n            levelGrid.innerHTML = ''; // Clear existing\n            for (let i = 1; i <= 50; i++) {\n                const card = document.createElement('div');\n                card.className = 'level-card';\n                card.textContent = i;\n                card.onclick = () => startGame(i, selectedDifficulty);\n                levelGrid.appendChild(card);\n            }\n\n            // Difficulty buttons\n            const diffNormal = document.getElementById('diff-normal');\n            const diffHard = document.getElementById('diff-hard');\n\n            diffNormal.onclick = () => {\n                selectedDifficulty = 'Normal';\n                diffNormal.classList.add('active');\n                diffHard.classList.remove('active');\n                playSound('button_click_sound', 0.5);\n            };\n\n            diffHard.onclick = () => {\n                selectedDifficulty = 'Hard';\n                diffHard.classList.add('active');\n                diffNormal.classList.remove('active');\n                playSound('button_click_sound', 0.5);\n            };\n\n            // Restart buttons\n            document.getElementById('next-level-btn').onclick = () => {\n                const nextLvl = Math.min(currentLevel + 1, 50);\n                startGame(nextLvl, selectedDifficulty);\n            };\n\n            document.getElementById('game-over-restart-btn').onclick = () => startGame(currentLevel, selectedDifficulty);\n            document.getElementById('pause-restart-btn').onclick = () => startGame(currentLevel, selectedDifficulty);\n            document.getElementById('main-menu-btn').onclick = () => {\n                document.getElementById('pause-menu').classList.remove('show');\n                document.getElementById('main-menu').classList.remove('hidden');\n                gameState = 'menu';\n                playSound('button_click_sound', 0.5);\n            };\n\n            // Input handling\n            let touchStartPos = null;\n            let lastTapTime = 0;\n\n            function handleTerritorySelect(x, y) {\n                // Find clicked territory\n                for (let i = territories.length - 1; i >= 0; i--) {\n                    const t = territories[i];\n                    const dx = t.x - x;\n                    const dy = t.y - y;\n                    if (dx * dx + dy * dy <= t.radius * t.radius) {\n                        if (mode === 'edit') {\n                            selectedTerritory = t.id;\n                            return true;\n                        } else if (mode === 'play' && !isPaused) {\n                            if (selectedTerritory === null && t.owner === 'player') {\n                                selectedTerritory = t.id;\n                                playSound('button_click_sound', 0.5);\n                                return true;\n                            } else if (selectedTerritory !== null) {\n                                const source = territories[selectedTerritory];\n                                if (source.connections.includes(t.id)) {\n                                    const sendCount = Math.floor(source.troops * (window.gameConfig.troopSendPercentage / 100));\n                                    if (sendCount > 0) {\n                                        troopGroups.push(new TroopGroup(source.id, t.id, sendCount, 'player'));\n                                        source.troops -= sendCount;\n                                        playSound('march_sound', 0.3);\n                                    }\n                                    selectedTerritory = null;\n                                    return true;\n                                }\n                            }\n                        }\n                    }\n                }\n                \n                if (mode === 'play') {\n                    selectedTerritory = null;\n                }\n                return false;\n            }\n\n            // Touch events\n            canvas.addEventListener('touchstart', (e) => {\n                e.preventDefault();\n                const touch = e.touches[0];\n                const rect = canvas.getBoundingClientRect();\n                const x = touch.clientX - rect.left;\n                const y = touch.clientY - rect.top;\n                touchStartPos = { x, y };\n            });\n\n            canvas.addEventListener('touchend', (e) => {\n                e.preventDefault();\n                if (!touchStartPos) return;\n\n                const currentTime = Date.now();\n                if (currentTime - lastTapTime < 200) return;\n                lastTapTime = currentTime;\n\n                handleTerritorySelect(touchStartPos.x, touchStartPos.y);\n                touchStartPos = null;\n            });\n\n            // Mouse events\n            canvas.addEventListener('mousedown', (e) => {\n                const rect = canvas.getBoundingClientRect();\n                const x = e.clientX - rect.left;\n                const y = e.clientY - rect.top;\n                handleTerritorySelect(x, y);\n            });\n\n            // Pause button\n            const pauseBtn = document.getElementById('pause-btn');\n            const pauseMenu = document.getElementById('pause-menu');\n            const resumeBtn = document.getElementById('resume-btn');\n\n            pauseBtn.addEventListener('click', () => {\n                playSound('button_click_sound', 0.5);\n                isPaused = true;\n                pauseMenu.classList.add('show');\n            });\n\n            resumeBtn.addEventListener('click', () => {\n                playSound('button_click_sound', 0.5);\n                isPaused = false;\n                pauseMenu.classList.remove('show');\n            });\n\n            // Draw territory\n            function drawTerritory(ctx, territory) {\n                const faction = factionData[territory.owner];\n\n                // Draw territory body\n                ctx.fillStyle = faction.color;\n                ctx.strokeStyle = '#2C3E50';\n                ctx.lineWidth = 4;\n                ctx.beginPath();\n                ctx.arc(territory.x, territory.y, territory.radius, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.stroke();\n\n                // Draw selection indicator\n                if (selectedTerritory === territory.id) {\n                    ctx.strokeStyle = '#FFD700';\n                    ctx.lineWidth = 6;\n                    ctx.setLineDash([10, 5]);\n                    ctx.beginPath();\n                    ctx.arc(territory.x, territory.y, territory.radius + 8, 0, Math.PI * 2);\n                    ctx.stroke();\n                    ctx.setLineDash([]);\n                }\n\n                // Draw building\n                const building = getTintedSprite(faction.building, faction.hue);\n                if (building) {\n                    ctx.drawImage(building, territory.x - 24, territory.y - 30, 48, 48);\n                }\n\n                // Draw troop count\n                ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';\n                ctx.fillRect(territory.x - 40, territory.y + 20, 80, 36);\n                ctx.fillStyle = '#FFFFFF';\n                ctx.font = 'bold 28px Inter';\n                ctx.textAlign = 'center';\n                ctx.textBaseline = 'middle';\n                ctx.fillText(Math.floor(territory.troops), territory.x, territory.y + 38);\n\n                // Draw connections in edit mode\n                if (mode === 'edit') {\n                    ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';\n                    ctx.lineWidth = 2;\n                    ctx.setLineDash([5, 5]);\n                    territory.connections.forEach(connId => {\n                        const conn = territories[connId];\n                        ctx.beginPath();\n                        ctx.moveTo(territory.x, territory.y);\n                        ctx.lineTo(conn.x, conn.y);\n                        ctx.stroke();\n                    });\n                    ctx.setLineDash([]);\n                }\n            }\n\n            // Check win/lose conditions\n            function checkGameOver() {\n                const playerTerritories = territories.filter(t => t.owner === 'player');\n                const enemyTerritories = territories.filter(t => t.owner.startsWith('enemy_'));\n\n                if (playerTerritories.length === 0) {\n                    gameState = 'defeat';\n                    showGameOver(false);\n                    if (backgroundMusic) backgroundMusic.stop();\n                    playSound('defeat_sound', 0.7);\n                    return true;\n                }\n\n                if (enemyTerritories.length === 0) {\n                    gameState = 'victory';\n                    showGameOver(true);\n                    if (backgroundMusic) backgroundMusic.stop();\n                    playSound('victory_sound', 0.7);\n                    return true;\n                }\n\n                // Check for stalemate\n                const currentState = territories.map(t => t.owner).join(',');\n                if (currentState === lastTerritoryState) {\n                    noChangeTimer += 1/60;\n                    if (noChangeTimer > 60) {\n                        const playerTroops = territories.filter(t => t.owner === 'player').reduce((sum, t) => sum + t.troops, 0);\n                        const enemyTroops = territories.filter(t => t.owner === 'enemy').reduce((sum, t) => sum + t.troops, 0);\n                        if (playerTroops > enemyTroops) {\n                            gameState = 'victory';\n                            showGameOver(true);\n                        } else {\n                            gameState = 'defeat';\n                            showGameOver(false);\n                        }\n                        if (backgroundMusic) backgroundMusic.stop();\n                        return true;\n                    }\n                } else {\n                    noChangeTimer = 0;\n                    lastTerritoryState = currentState;\n                }\n\n                return false;\n            }\n\n            function showGameOver(victory) {\n                const gameOverScreen = document.getElementById('game-over');\n                const gameOverTitle = document.getElementById('game-over-title');\n                const gameOverStats = document.getElementById('game-over-stats');\n                const nextLevelBtn = document.getElementById('next-level-btn');\n\n                const playerTerritories = territories.filter(t => t.owner === 'player').length;\n                const totalTroops = territories.filter(t => t.owner === 'player').reduce((sum, t) => sum + t.troops, 0);\n\n                gameOverTitle.textContent = victory ? 'VICTORY!' : 'DEFEAT';\n                gameOverTitle.className = 'game-over-title ' + (victory ? 'victory' : 'defeat');\n                gameOverStats.innerHTML = `Territories Controlled: ${playerTerritories}<br>Total Troops: ${Math.floor(totalTroops)}`;\n                \n                nextLevelBtn.style.display = victory ? 'block' : 'none';\n                \n                gameOverScreen.classList.add('show');\n            }\n\n            // Update HUD\n            function updateHUD() {\n                const playerTroops = territories.filter(t => t.owner === 'player').reduce((sum, t) => sum + Math.floor(t.troops), 0);\n                const enemyTroops = territories.filter(t => t.owner.startsWith('enemy_')).reduce((sum, t) => sum + Math.floor(t.troops), 0);\n\n                document.getElementById('player-troops').textContent = playerTroops;\n                document.getElementById('enemy-troops').textContent = enemyTroops;\n            }\n\n            // Main game loop\n            let lastTime = performance.now();\n\n            function gameLoop(timestamp) {\n                let deltaTime = Math.min((timestamp - lastTime) / 1000, 0.11);\n                lastTime = timestamp;\n\n                if (isPaused) {\n                    requestAnimationFrame(gameLoop);\n                    return;\n                }\n\n                // Clear canvas\n                ctx.fillStyle = window.gameConfig.waterColor || '#2B5F9E';\n                ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n                if (mode === 'play' && gameState === 'playing') {\n                    // Update troop production\n                    let rate = window.gameConfig.troopGenerationRate;\n                    // Scale rate based on difficulty and level\n                    if (selectedDifficulty === 'Hard') rate *= 1.3;\n                    rate *= (1 + currentLevel * 0.01);\n\n                    troopAccumulator += deltaTime * rate;\n                    if (troopAccumulator >= 1.0) {\n                        const troopsToAdd = Math.floor(troopAccumulator);\n                        troopAccumulator -= troopsToAdd;\n\n                        territories.forEach(t => {\n                            if (t.owner !== 'neutral') {\n                                t.troops += troopsToAdd;\n                            }\n                        });\n                    }\n\n                    // Update troop groups\n                    for (let i = troopGroups.length - 1; i >= 0; i--) {\n                        const group = troopGroups[i];\n                        if (group.update(deltaTime)) {\n                            // Troop group arrived\n                            const target = territories[group.to];\n                            \n                            if (target.owner === group.owner) {\n                                // Reinforcement\n                                target.troops += group.count;\n                            } else {\n                                // Combat\n                                if (group.count > target.troops) {\n                                    // Attacker wins\n                                    const oldOwner = target.owner;\n                                    target.owner = group.owner;\n                                    target.troops = group.count - target.troops;\n                                    if (oldOwner !== 'neutral') {\n                                        playSound('battle_sound', 0.5);\n                                    }\n                                    if (group.owner === 'player') {\n                                        playSound('territory_capture_sound', 0.6);\n                                    }\n                                } else {\n                                    // Defender wins\n                                    target.troops -= group.count;\n                                    playSound('battle_sound', 0.5);\n                                }\n                            }\n                            \n                            troopGroups.splice(i, 1);\n                        }\n                    }\n\n                    // Mid-air troop combat (Clash in transit) - Optimized frequency\n                    clashCheckTimer += deltaTime;\n                    if (clashCheckTimer >= 0.05) { // Check every 50ms\n                        clashCheckTimer = 0;\n                        for (let i = 0; i < troopGroups.length; i++) {\n                            for (let j = i + 1; j < troopGroups.length; j++) {\n                                const gA = troopGroups[i];\n                                const gB = troopGroups[j];\n                                \n                                if (gA.owner !== gB.owner && gA.count > 0 && gB.count > 0) {\n                                    const dist = Math.hypot(gA.x - gB.x, gA.y - gB.y);\n                                    if (dist < 40) {\n                                        const clashAmount = Math.min(gA.count, gB.count);\n                                        gA.count -= clashAmount;\n                                        gB.count -= clashAmount;\n                                        \n                                        addExplosion((gA.x + gB.x) / 2, (gA.y + gB.y) / 2);\n                                        if (Math.random() > 0.7) playSound('battle_sound', 0.1);\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    // Update and draw effects\n                    for (let i = activeEffects.length - 1; i >= 0; i--) {\n                        const fx = activeEffects[i];\n                        fx.life -= deltaTime;\n                        if (fx.life <= 0) {\n                            activeEffects.splice(i, 1);\n                            continue;\n                        }\n\n                        if (fx.type === 'explosion') {\n                            const sprite = assetCache['battle_explosion'];\n                            if (sprite) {\n                                ctx.save();\n                                ctx.globalAlpha = fx.life / fx.maxLife;\n                                const size = 60 * (1.2 - fx.life / fx.maxLife);\n                                ctx.drawImage(sprite, fx.x - size/2, fx.y - size/2, size, size);\n                                ctx.restore();\n                            }\n                        }\n                    }\n\n                    // Remove eliminated groups\n                    troopGroups = troopGroups.filter(g => g.count > 0);\n\n                    // Update AI\n                    updateAI(deltaTime);\n\n                    // Check game over\n                    checkGameOver();\n\n                    // Update HUD - Throttled\n                    hudUpdateTimer += deltaTime;\n                    if (hudUpdateTimer >= 0.2) {\n                        hudUpdateTimer = 0;\n                        updateHUD();\n                    }\n                }\n\n                // Draw connections\n                ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';\n                ctx.lineWidth = 1.5;\n                territories.forEach(t => {\n                    t.connections.forEach(connId => {\n                        if (connId > t.id) {\n                            const conn = territories[connId];\n                            ctx.beginPath();\n                            ctx.moveTo(t.x, t.y);\n                            ctx.lineTo(conn.x, conn.y);\n                            ctx.stroke();\n                        }\n                    });\n                });\n\n                // Draw territories\n                territories.forEach(t => drawTerritory(ctx, t));\n\n                // Draw troop groups\n                troopGroups.forEach(g => g.draw(ctx));\n\n                // Draw valid targets when selected\n                if (selectedTerritory !== null && mode === 'play') {\n                    const source = territories[selectedTerritory];\n                    ctx.strokeStyle = 'rgba(255, 255, 0, 0.5)';\n                    ctx.lineWidth = 4;\n                    source.connections.forEach(connId => {\n                        const target = territories[connId];\n                        ctx.beginPath();\n                        ctx.arc(target.x, target.y, target.radius + 4, 0, Math.PI * 2);\n                        ctx.stroke();\n                    });\n                }\n\n                requestAnimationFrame(gameLoop);\n            }\n\n            requestAnimationFrame(gameLoop);\n        }\n    </script>\n</body>\n</html>", "game_config": "{\"territoryCount\": 10, \"territorySizeVariation\": \"Mixed\", \"waterColor\": \"#2B5F9E\", \"landColorScheme\": \"Classic\", \"startingTerritoriesPlayer\": 1, \"startingTerritoriesEnemy\": 1, \"neutralTerritories\": 8, \"troopGenerationRate\": 1.0, \"initialTroopCount\": 50, \"troopSendPercentage\": 50, \"aiDifficulty\": \"Medium\", \"aiAggression\": \"Balanced\", \"winCondition\": \"Eliminate All Enemies\", \"timeLimit\": \"None\"}", "game_design_document": "## Core Game Loop and Mechanics\n\n**War Conquest: Territory Battle** is a real-time strategy game where players command armies to conquer enemy territories through tactical deployment and resource management.\n\n### Moment-to-Moment Gameplay\n1. **Territory Control**: The map is divided into territories (land masses) separated by water. Each territory can be controlled by the player (blue) or enemy (red/pink)\n2. **Unit Production**: Controlled territories automatically generate soldier units over time. The more territories you control, the faster you produce units\n3. **Troop Deployment**: Players tap/click on their territory to select it, then tap/click on a target territory to send troops. A stream of soldiers marches from source to destination\n4. **Combat Resolution**: When troops arrive at an enemy territory, they engage in battle. The side with more troops wins and captures/defends the territory\n5. **Strategic Expansion**: Players must balance offense (sending troops to conquer) and defense (keeping enough troops at home bases)\n\n### Progression and Engagement\n- **Early Game**: Start with one home base, carefully expand to nearby neutral territories\n- **Mid Game**: Control multiple territories, manage multiple fronts, defend against enemy counterattacks\n- **Late Game**: Massive armies clash, strategic territory control becomes crucial\n- **Replayability**: Randomized map layouts, different starting positions, varying difficulty levels\n\n### Win/Lose Conditions\n- **Victory**: Eliminate all enemy territories by reducing their troop count to zero and capturing their last base\n- **Defeat**: Lose all your territories to the enemy\n- **Stalemate Prevention**: If no territory changes hands for 60 seconds, the side with more total troops wins\n\n### What Makes It Compelling\n- **Satisfying Scale**: Watching hundreds of tiny soldiers march and clash creates visual spectacle\n- **Strategic Depth**: Simple mechanics (tap to send troops) but deep strategy (when to attack, when to defend, which territories to prioritize)\n- **Tension and Momentum**: The constant production of units creates urgency - every second counts\n- **Clear Feedback**: Large numbers showing troop counts make the game state always readable\n\n## Starting Scope\n\n### First Iteration (Implement Now)\n1. **Single Level**: One fixed map with 8-12 territories of varying sizes\n2. **Player vs AI**: One AI opponent with basic aggressive behavior\n3. **Core Mechanics**:\n   - Territory ownership (player blue, enemy red, neutral gray)\n   - Automatic troop generation (1 soldier per second per territory)\n   - Tap to select territory, tap to send 50% of troops\n   - Troop movement along paths between territories\n   - Simple combat (higher number wins, subtract difference)\n   - Victory/defeat detection\n4. **Visual Polish**:\n   - Animated soldier sprites marching in formation\n   - Territory borders with distinct colors\n   - Troop count numbers prominently displayed\n   - Simple particle effects for battles\n5. **UI Elements**:\n   - Total troop count display\n   - Victory/defeat screen with restart button\n   - Pause button\n\n### Future Iterations (Plan For Later)\n- Multiple levels with different map layouts\n- Multiple AI opponents (3-4 factions)\n- Special territory types (fortresses that produce faster, resource nodes)\n- Unit upgrades and special abilities\n- Different unit types (infantry, cavalry, archers)\n- Multiplayer support\n- Campaign mode with progression\n\n## Game Perspective\n\n**Top-down** perspective with a fixed camera showing the entire battlefield. This allows players to see all territories, troop movements, and strategic positions at once. The map fills the screen with slight padding, similar to the reference image.\n\n## Game World and Level Design\n\n### Map Structure\nThe game world is a stylized map divided by water (blue) and land masses (territories in various colors):\n\n**Territory Layout** (First Level):\n- **Total Territories**: 10 territories of varying sizes\n- **Starting Positions**: \n  - Player starts with 1 territory (bottom-left, light blue)\n  - Enemy starts with 1 territory (top-right, pink/red)\n  - 8 neutral territories (gray) scattered across the map\n- **Territory Sizes**: \n  - Small territories (50-80px radius): Generate 1 troop/second\n  - Medium territories (80-120px radius): Generate 1 troop/second\n  - Large territories (120-160px radius): Generate 1 troop/second\n  - (All same generation rate for simplicity in first iteration)\n\n**Connectivity**:\n- Each territory connects to 2-4 neighboring territories\n- Connections are represented by valid paths where troops can march\n- Water acts as natural barriers between territories\n- Strategic chokepoints exist where multiple territories meet\n\n**Visual Layout**:\n- Irregular, organic territory shapes (like continents/islands)\n- Dark blue water fills the background\n- Territories have distinct colored fills with dark outlines\n- Small decorative elements (trees, rocks) on land for visual interest\n- Troop count numbers displayed prominently in white with dark outline\n\n### Level Flow\n1. **Opening** (0-30 seconds): Players learn controls by capturing nearby neutral territories\n2. **Expansion** (30-90 seconds): Race against AI to control the most neutral territories\n3. **Conflict** (90+ seconds): Direct confrontation as players attack each other's territories\n4. **Resolution**: One side gains momentum and conquers all enemy territories\n\n## Edit Mode Design\n\nEdit mode allows players to customize the battlefield and game parameters to create their own strategic scenarios.\n\n### Editable Properties\n\n**Map Configuration**:\n- **Number of Territories**: 6-15 territories (slider)\n- **Territory Size Variation**: Small/Medium/Large mix (dropdown: \"Uniform\", \"Mixed\", \"Random\")\n- **Water Color**: Color picker for ocean/water background\n- **Land Color Scheme**: Preset palettes (dropdown: \"Classic\", \"Desert\", \"Forest\", \"Ice\", \"Volcanic\")\n\n**Game Balance**:\n- **Starting Territories**: How many territories each side starts with (1-3)\n- **Neutral Territories**: Number of unclaimed territories at start (0-12)\n- **Troop Generation Rate**: Soldiers per second per territory (0.5x, 1x, 1.5x, 2x)\n- **Initial Troop Count**: Starting soldiers in each territory (0, 50, 100, 200)\n- **Troop Send Percentage**: How many troops are sent when attacking (25%, 50%, 75%, 100%)\n\n**AI Behavior**:\n- **AI Difficulty**: Dropdown (Easy, Medium, Hard)\n  - Easy: Attacks randomly, slow reaction time\n  - Medium: Prioritizes weak territories, moderate reaction\n  - Hard: Strategic targeting, fast reaction, coordinates attacks\n- **AI Aggression**: Slider (Defensive, Balanced, Aggressive)\n\n**Victory Conditions**:\n- **Win Condition**: Dropdown (\"Eliminate All Enemies\", \"Control 75% of Map\", \"Reach 500 Total Troops\")\n- **Time Limit**: Optional timer (None, 3min, 5min, 10min)\n\n### Edit Mode Interface\n- **Side Panel**: Scrollable panel on the right side (200px wide) with all editable properties\n- **Live Preview**: Changes update the map in real-time\n- **Reset Button**: Restore default settings\n- **Randomize Map**: Generate a new random map layout\n- **Play Button**: Start the game with current settings\n\n### Constraints\n- Minimum 6 territories to ensure strategic gameplay\n- Maximum 15 territories to prevent performance issues and maintain readability\n- At least 2 territories must be reachable from any starting position\n- Troop generation rate capped at 2x to prevent runaway snowballing\n- AI must always have at least 1 starting territory\n\n## Control Design\n\n### Mobile Controls (Touch - Primary)\n\n**Territory Selection and Troop Deployment**:\n- **Single Tap on Owned Territory**: Select territory (highlight with pulsing border)\n- **Single Tap on Target Territory**: Send 50% of troops from selected territory to target\n  - If target is owned: Reinforce with troops\n  - If target is enemy/neutral: Attack with troops\n- **Tap Empty Space**: Deselect current territory\n\n**Visual Feedback**:\n- Selected territory shows animated pulsing border\n- Valid target territories highlight when a territory is selected\n- Drag line appears from selected territory to finger position, snapping to valid targets\n- Troop count preview shows how many troops will be sent\n\n**UI Buttons**:\n- **Pause Button**: Top-right corner (80x80px), pauses game and shows menu\n- **Info Button**: Top-left corner (80x80px), shows current stats (territories controlled, total troops)\n\n### Desktop Controls (Keyboard + Mouse - Secondary)\n\n**Mouse Controls**:\n- **Left Click on Owned Territory**: Select territory\n- **Left Click on Target Territory**: Send 50% of troops from selected territory to target\n- **Right Click**: Deselect current territory\n- **Mouse Hover**: Highlight territory under cursor, show troop count tooltip\n\n**Keyboard Shortcuts**:\n- **Space**: Pause/unpause game\n- **R**: Restart level\n- **Esc**: Deselect territory or open pause menu\n- **1-9**: Quick-select owned territories by number (if you have multiple)\n\n**Visual Feedback**:\n- Mouse cursor changes to pointer over territories\n- Hover effects on territories\n- Same selection and targeting feedback as mobile\n\n### Control Implementation Notes\n- **Touch ID Tracking**: Track each touch by ID to prevent multi-touch interference\n- **Prevent Defaults**: Prevent context menu on right-click, prevent text selection on drag\n- **Clear on Blur**: Clear all input states when window loses focus\n- **Responsive Hit Areas**: Territory hit detection uses the full territory shape, not just the center\n- **Debouncing**: Prevent accidental double-taps from sending troops twice (200ms cooldown)\n\n## Art Style and Visual Theme\n\n### Overall Style\n**Stylized Military Strategy** with a clean, readable aesthetic inspired by mobile strategy games. The art style balances visual appeal with clarity - players must instantly understand the game state at a glance.\n\n### Visual Theme\n- **Tone**: Lighthearted military strategy, not grim or realistic\n- **Color Palette**: \n  - Water: Deep blue (#2B5F9E) with subtle wave texture\n  - Player territories: Light blue (#6FB1E8)\n  - Enemy territories: Coral pink/red (#FF8B94)\n  - Neutral territories: Light gray (#B8B8B8)\n  - UI elements: White text with dark outlines for readability\n- **Mood**: Strategic, competitive, but accessible and fun\n\n### Asset Specifications\n\n**Soldier Units**:\n- **Style**: Tiny, cute pixel art or simple vector soldiers (16x16 to 24x24 pixels)\n- **Design**: Top-down view, clearly showing team color (blue or red uniform)\n- **Animation**: Simple 2-frame walk cycle\n- **Scale**: Small enough that 100+ can be on screen without clutter\n\n**Territories**:\n- **Rendering**: Code-rendered using Canvas with SVG-like paths\n- **Borders**: 3-4px dark outlines (#2C3E50)\n- **Fill**: Solid colors based on ownership, with subtle gradient for depth\n- **Decorations**: Small trees, rocks, or buildings rendered as simple shapes (optional, for visual interest)\n\n**UI Elements**:\n- **Style**: Modern, flat design with subtle shadows\n- **Buttons**: Rounded rectangles with icons\n- **Numbers**: Large, bold sans-serif font (48-72px for troop counts)\n- **Effects**: Minimal particle effects for battles (small explosions, dust clouds)\n\n**Special Effects**:\n- **Troop Movement**: Dotted line trail showing path\n- **Battle Effects**: Small explosion sprites or particle bursts when troops clash\n- **Territory Capture**: Brief flash or pulse animation when ownership changes\n- **Selection**: Animated dashed border around selected territory\n\n### Consistency Requirements\n- All soldier sprites must match in size and style\n- Territory colors must be distinct and colorblind-friendly\n- UI elements follow the same rounded, flat design language\n- Effects are subtle and don't obscure gameplay information\n\n### Technical Rendering Decisions\n- **Canvas Rendering**: Territories, water, borders, troop paths\n- **Generated Assets**: Soldier sprites, building/decoration sprites, particle effects\n- **CSS/HTML**: UI overlays, buttons, menus, text displays\n- **Optimization**: Use sprite batching for soldiers, cache territory shapes", "persistent_storage_config": null, "game_metadata": {"game_id": "01KSFMHQ63BCM6QAHFAPN9EY8W", "title": "War Inc: Rising", "description": "Command armies to conquer territories in this strategic real-time battle game where numbers and tactics determine victory!", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_c4b8b9cc-f004-40a7-a1d8-115f32e9b9fd.webp", "created_at": 1779715132, "updated_at": 1779789522773.8894, "art_style": null}}