1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-09 09:18:01 +00:00
nescript/examples/war/state.ne

83 lines
4.2 KiB
Text
Raw Normal View History

2026-04-15 15:22:20 +00:00
// war/state.ne — every mutable variable the game touches.
//
// NEScript allocates top-level `var` declarations in general RAM
// (the analyzer places them starting at $10 / $18 depending on
// whether the program declares background/palette updates). We
// keep everything global so helper functions can read and write
// without having to take parameters and return values — the
// 6502's 8-register ABI makes every extra parameter an extra
// LDA/STA pair.
// ── Decks + pot ───────────────────────────────────────────
// Each deck is a circular buffer backed by a 52-byte array.
// `*_front` is the index of the next card to draw; `*_count` is
// the number of cards currently in the buffer. Both fields wrap
// mod 52 — there's a helper for that in war/deck.ne.
var deck_a: u8[52]
var deck_a_front: u8 = 0
var deck_a_count: u8 = 0
var deck_b: u8[52]
var deck_b_front: u8 = 0
var deck_b_count: u8 = 0
// Pot holds every card currently in play (the normal-round draws
// and, during a war, the face-down buries too). Drained into the
// winner's deck after each round resolves.
var pot: u8[52]
var pot_count: u8 = 0
// ── The two cards showing face-up this round ─────────────
// These are the packed rank/suit bytes drawn from each deck at
// the start of a round. During a war, the old face-up cards get
// pushed into the pot and new values land in these slots.
var card_a: u8 = 0
var card_b: u8 = 0
// ── Game mode + phase machine ─────────────────────────────
var mode: u8 = 0 // 0/1/2 players
var a_is_cpu: u8 = 1 // bool-ish
var b_is_cpu: u8 = 1
var phase: u8 = 0 // one of the P_* constants
var phase_timer: u8 = 0 // counts up during each phase
// ── Animation state ───────────────────────────────────────
// Shared by every card-fly phase. We step (fly_x, fly_y) by a
// constant FLY_STEP per frame in the directions encoded in
// fly_dx_sign / fly_dy_sign. The screen layout is arranged so
// that FRAMES_FLY * FLY_STEP exactly matches the deck-to-play
// distance on both axes — see render.ne for the math.
var fly_x: u8 = 0
var fly_y: u8 = 0
var fly_dx_sign: u8 = 0 // 0 = +FLY_STEP / 1 = -FLY_STEP
var fly_dy_sign: u8 = 0
var fly_card: u8 = 0 // packed rank/suit to show during the fly
var fly_face_up: u8 = 1 // 0 = show card back, 1 = show face
// ── Title menu ────────────────────────────────────────────
var title_cursor: u8 = 1 // menu index (0/1/2) — default "1 PLAYER"
var title_timer: u8 = 0 // auto-advance counter
var title_debounce: u8 = 0 // menu input debounce
var title_blink: u8 = 0 // "PRESS A" blink counter
// ── Deal state ────────────────────────────────────────────
var deal_next: u8 = 0 // next card index to deal
var deal_timer: u8 = 0
// ── Victory state ─────────────────────────────────────────
var winner: u8 = 0 // 0 = A wins, 1 = B wins
var victory_timer: u8 = 0
// ── RNG ──────────────────────────────────────────────────
// 8-bit Galois LFSR state. Seeded from the free-running title
// frame counter at the moment the title screen transitions to
// Deal, so the shuffle is deterministic once the user commits
// to starting a game. The jsnes headless harness always starts
// at frame 45, so the seed is stable there too.
var rng_state: u8 = 0xA7
// ── Global free-running frame counter ────────────────────
// Used by any state that needs a coarse "which frame are we
// on" read without installing its own counter.
var global_tick: u16 = 0