1
0
Fork 0
polaris-task-force/src/lib/minigames/poker/deck.ts
Z8MB1E 6968ee0abc feat(poker): add poker engine, evaluation and stats libs with tests
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-11 03:25:43 -04:00

60 lines
1.9 KiB
TypeScript

/**
* Deck creation and deterministic shuffling for the poker engine.
* Pure: randomness is always injected; no module-level state.
*/
import type { Card, Rank, Suit } from "./types";
const SUITS: readonly Suit[] = ["s", "h", "d", "c"];
const MIN_RANK: Rank = 2;
const MAX_RANK: Rank = 14;
/** A fresh, ordered 52-card deck (order is deterministic before shuffling). */
export function createDeck(): Card[] {
const deck: Card[] = [];
for (const suit of SUITS) {
for (let rank = MIN_RANK; rank <= MAX_RANK; rank += 1) {
deck.push({ rank: rank as Rank, suit });
}
}
return deck;
}
/**
* Small, fast seeded PRNG (mulberry32). Used so a whole multi-hand game can
* be replayed from a single integer seed stored in the table state.
*/
export function mulberry32(seed: number): () => number {
let a = seed >>> 0;
return () => {
a = (a + 0x6d2b79f5) >>> 0;
let t = a;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
/** Fisher-Yates shuffle; returns a new array, never mutates the input. */
export function shuffleDeck(cards: readonly Card[], rng: () => number): Card[] {
const deck = [...cards];
for (let i = deck.length - 1; i > 0; i -= 1) {
const j = Math.floor(rng() * (i + 1));
const tmp = deck[i];
deck[i] = deck[j];
deck[j] = tmp;
}
return deck;
}
const GOLDEN_RATIO_32 = 0x9e3779b9;
/** Per-hand seed derived from the table's base seed and the hand number. */
export function handSeed(baseSeed: number, handNumber: number): number {
return (baseSeed + Math.imul(handNumber, GOLDEN_RATIO_32)) >>> 0;
}
/** The exact shuffled deck used for a given hand of a given game seed. */
export function createShuffledDeck(baseSeed: number, handNumber: number): Card[] {
return shuffleDeck(createDeck(), mulberry32(handSeed(baseSeed, handNumber)));
}