nx_folkgame_race_lib.nx
buildroot/runtime/nx_folkgame_race_lib.nx
about
nx_folkgame_race_lib.nx -- THE RACE FAMILY: a track, a randomiser, entry, bearing off, hitting
and blocking.
SCOPE STATED BEFORE ANY CLAIM. Twenty-two registry rows are race games. This engine covers the
TRACK sub-family -- a linear course both players run in opposite directions: Backgammon, Nard, the
Royal Game of Ur, Senet, Sugoroku, Liubo, Zohn Ahl, Main Kabul. The cross-and-circle boards
(Pachisi, Chaupar, Ashta Chamma, Ludo, Yut Nori, Patolli, Pancha Keliya) fold four arms onto a
per-player track and are a SEPARATE rung; the spiral and ladder boards (the Game of the Goose,
Hyena Chase, Mehen, Snakes and Ladders) need special-square rules and are a THIRD. Saying which
eight of the twenty-two this reaches is the difference between a family row and a family claim.
STATE ENCODING: state[c] is a SIGNED count -- positive is the first player, negative the second.
That is the representation the game itself has, and it makes a point's owner and its height one
number instead of two that can disagree.
DIRECTION: the first player runs from index 0 toward the end and bears off past track-1; the second
runs the other way and bears off past 0. So a point's PIP VALUE differs per player, which is why
fgr_pip takes a side rather than reading one number off the board.
THE RANDOMISER IS SEEDED AND LIVES IN THE SAVED POSITION. A race is not deterministic, but a
REPLAY of one must be: the seed is scalar slot 12, inside what fg_save and fg_load copy, so
restoring a position restores the die that follows it. A seed kept beside the position instead of
inside it is a seed a save silently loses, and the replay then diverges from the game it claims to
be replaying.
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 1 imports · 1 importers
imports: nx_folkgame_lib.nx
imported by: nx_folkgame_race_gate.nx
structs
| none |
consts
| 27 | const FGR_S_BAR1: i64 = 8 |
| 28 | const FGR_S_BAR2: i64 = 9 |
| 29 | const FGR_S_OFF1: i64 = 10 |
| 30 | const FGR_S_OFF2: i64 = 11 |
| 31 | const FGR_S_SEED: i64 = 12 |
| 36 | const FGR_LCG_MUL: i64 = 1664525 |
| 37 | const FGR_LCG_ADD: i64 = 1013904223 |
| 38 | const FGR_LCG_MOD: i64 = 4294967296 |
| 177 | const FGR_FROM_BAR: i64 = 0 - 2 |
functions
| 40 | func fgr_startarr(base: i64) -> *i64 |
| 44 | func fgr_track(base: i64) -> i64 { let hd: *i64 = fg_hdr(base); return hd[FG_H_TRACK] } called by 7: fgr_pipfgr_totalfgr_is_offfgr_home_sizefgr_can_bearofffgr_entry_point+1 calls 1: fg_hdr |
| 45 | func fgr_pieces(base: i64) -> i64 { let hd: *i64 = fg_hdr(base); return hd[FG_H_PIECES] } |
| 47 | func fgr_bar(base: i64, side: i64) -> i64 |
| 52 | func fgr_off(base: i64, side: i64) -> i64 |
| 60 | func fgr_on(base: i64, side: i64, c: i64) -> i64 |
| 69 | func fgr_pip(base: i64, side: i64) -> i64 |
| 87 | func fgr_total(base: i64, side: i64) -> i64 |
| 95 | func fgr_reset(base: i64, seed: i64) -> i64 |
| 111 | func fgr_die(base: i64) -> i64 |
| 126 | func fgr_dest(base: i64, side: i64, c: i64, d: i64) -> i64 |
| 130 | func fgr_is_off(base: i64, side: i64, dest: i64) -> i64 |
| 139 | func fgr_blocked(base: i64, side: i64, c: i64) -> i64 |
| 153 | func fgr_home_size(base: i64) -> i64 |
| 159 | func fgr_can_bearoff(base: i64, side: i64) -> i64 |
| 178 | func fgr_entry_point(base: i64, side: i64, d: i64) -> i64 |
| 186 | func fgr_moves(base: i64, d: i64, out: *i64) -> i64 |
| 214 | func fgr_put(base: i64, side: i64, c: i64, delta: i64) -> i64 |
| 221 | func fgr_apply(base: i64, from: i64, d: i64) -> i64 |
| 259 | func fgr_terminal(base: i64) -> i64 |