cg-core: make cg-shuffle optionally seeded and reproducible

cg-shuffle gains an optional SEED and a `cg-shuffle-seed' dynamic var.
With a seed the order is deterministic and identical on every platform,
so a deal can be replayed, shared between players, or pinned in a test;
the index comes from secure-hash (spec-defined output everywhere, 7 hex
digits stay a fixnum even on 32-bit Emacs), so no bignum/overflow
behaviour can vary it.  With no seed the shuffle is the byte-for-byte
old system-random path -- normal play is unchanged.

Test cgt-shuffle-seeded pins determinism, permutation, override and a
cross-platform golden prefix; fails on the prior one-arg cg-shuffle.
Suite 159/159.
This commit is contained in:
Corwin Brust 2026-08-03 22:18:02 -05:00
parent 1a59003b13
commit 6379127e17
8 changed files with 180 additions and 15 deletions

View file

@ -318,7 +318,7 @@ TOTAL is the running count after the play."
(cl-labels ((txt (str x y &optional sz bold)
(apply #'svg-text svg str :x x :y y :font-size (or sz 12) :fill lc
:font-family cg-svg-font-family (and bold '(:font-weight "bold"))))
(peg (label sc y)
(cg-crib--peg (label sc y)
(txt label pad (+ y 11) 12)
(let ((bx (+ pad 90)))
(svg-rectangle svg bx y barw peg-h :rx 4 :fill "none"
@ -334,8 +334,8 @@ TOTAL is the running count after the play."
(cg-svg-card svg xx y :rank (car sp) :suit (cdr sp)))
(setq xx (+ xx (round (* w 0.5))))))))
(txt (format "Cribbage (to %d)" target) pad (+ y-title 12) 13 t)
(peg "You" (aref scores 0) y-peg)
(peg "Computer" (aref scores 1) (+ y-peg peg-h peg-gap))
(cg-crib--peg "You" (aref scores 0) y-peg)
(cg-crib--peg "Computer" (aref scores 1) (+ y-peg peg-h peg-gap))
(txt (format "%s deals" (cg-crib--who (cg-get game :dealer)))
(+ pad 90 barw 60) (+ y-peg 11) 11)
(let ((mx pad))