# single combat encounter - design doc first playable slice of slaywithfriends. one ironclad player vs one enemy. proves the core card engine works. ## decisions - rendering: html/css with card images (no canvas) - framework: none. vanilla js, es modules, bun serve - networking: client-only. all state in browser - character: ironclad (simplest mechanics) - interaction: two-tap (select card, tap target) - mobile: design for 375px baseline, scales up naturally ## state model single object drives everything. pure functions produce new state. nothing mutates directly. state = { player: { hp, maxHp, energy, maxEnergy, block, strength, drawPile: [...cardIds], hand: [...cardIds], discardPile: [...cardIds], exhaustPile: [...cardIds], powers: [...cardIds], }, enemy: { id, name, hp, maxHp, block, strength, vulnerable, weak, action, actionTrack: [...], trackPosition, }, combat: { turn, phase: 'player_turn' | 'enemy_turn' | 'rewards' | 'ended', dieResult, selectedCard, log: [...], } } ## card data schema cards are json entries keyed by id. effects are typed arrays. { "strike_r": { "name": "Strike", "cost": 1, "type": "attack", "effects": [{"type": "hit", "value": 6}], "image": "assets/images/ironclad/starter/0.png", "keywords": [], "description": "Deal 6 damage.", "upgraded": "strike_r+" } } effect types for first slice: hit, block, draw, strength, vulnerable, weak, exhaust, lose_hp. ## enemy data schema { "jaw_worm": { "name": "Jaw Worm", "hp": 6, "actionType": "die", "actions": { "1": {"intent": "attack", "effects": [{"type": "hit", "value": 3}]}, ... } } } three action types: single (same every turn), die (keyed to die roll), cube (ordered list with advancing pointer, gray actions don't repeat). ## rendering layout three vertical zones: enemy zone (~40%) enemy art, hp bar, block, status tokens, intent info bar (fixed) energy pips, hp bar, block shield, strength, pile counts hand (~35%) cards fan out, overlap if many, selected card lifts pile overlays: tap draw/discard count to see scrollable card grid. ## two-tap interaction 1. tap card in hand - it lifts and highlights 2. enemy zone becomes valid target (highlighted border) 3. skills that don't need a target auto-play 4. tap enemy - card plays, effects resolve, card animates to discard 5. not enough energy - card shakes and drops back 6. tap selected card again to deselect ## combat loop player turn: 1. reset energy to 3, block to 0 2. draw 5 cards (shuffle discard into draw if needed) 3. roll die (1-6), determines enemy intent 4. resolve start-of-turn triggers 5. play phase - player acts freely 6. "end turn" button ends play phase 7. end-of-turn triggers, discard remaining hand enemy turn (auto-resolves): 1. remove enemy block 2. enemy executes action 3. advance cube-action pointer if applicable 4. brief pause (~1s) for player to read combat ends when enemy hp hits 0 (victory) or player hp hits 0 (defeat). ## damage formula 1. start with base hit value 2. add attacker strength (+1 per token) 3. if target vulnerable, double result 4. if attacker weak, subtract 1 5. weak AND vulnerable cancel out - skip both 6. subtract target block, remainder hits hp 7. consume 1 vulnerable from target after attack 8. consume 1 weak from attacker after attack 9. multi-hit: loop N times, consume tokens only after all hits 10. aoe/multi-hit: only 1 weak consumed total ## enemy ai data-driven. each enemy's action is an effects array resolved the same way as card effects. intent displayed as icon + number after die roll so player can plan. ## project structure slaywithfriends/ index.html style.css src/ main.js entry point, init, render loop state.js state creation, pure action functions effects.js effect resolver combat.js turn flow orchestration enemy-ai.js resolve enemy actions render.js state to dom cards.js load/query card data enemies.js load/query enemy data die.js die roll data/ cards.json card database enemies.json enemy database potions.json potion database relics.json relic database assets/ video game card images StS_BG_assets/ board game assets docs/ rules and plans ## out of scope - map / room navigation - deck building / rewards / card selection - merchant / campfire / events - potions and relics - multiplayer / networking - persistent state / save / load - sound - ironclad passive (heal 1 hp end of combat) - tutorial ## data pipeline board game card sheet images being extracted to json by agent. video game wiki data (wiki.gg Module:Cards/data) available as secondary reference. board game values are source of truth.