slaywithfriends/docs/plans/2026-02-24-run-loop-design.md

1.6 KiB

run loop design

fight -> reward -> fight -> die -> restart

run state

new layer above combat state:

  • character ("ironclad")
  • hp, maxHp
  • deck (master deck, starts as starter, grows with reward picks)
  • cardRewardsDeck (character's common + uncommon cards, shuffled)
  • combatCount (tracking)

after victory

  • combat phase transitions to "rewards"
  • reveal top 3 from cardRewardsDeck
  • player picks 1 (added to master deck) or skips (all 3 shuffled back in)
  • new combat starts: fresh enemy, player keeps HP and deck

after defeat

  • show defeat overlay with "try again" prompt
  • clicking it starts a completely fresh run (starter deck, full hp, reshuffled rewards deck)

reward ui

  • 3 cards shown where the hand normally renders
  • each card clickable to pick it
  • "skip" button to pass on all 3
  • uses existing card image rendering

data flow

  • createRunState(character) builds run state, including rewards deck from cards.json (character's common + uncommon cards, shuffled)
  • createCombatState accepts run state (deck, hp) instead of always using starter deck and max hp
  • on combat end, hp and deck flow back up to run state
  • on reward pick, card moves from rewards deck to master deck
  • on skip, revealed cards shuffle back into rewards deck

board game rules followed

  • card rewards deck is a pre-shuffled deck you draw through (not random generation)
  • reveal 3, pick 1 or skip
  • skipped cards shuffle back in immediately (full act-transition shuffle deferred)
  • rare rewards are separate and not included yet (tied to map node types)
  • source: docs/rules-canon.md, docs/reference.txt