import { Rng } from './policy'; export type PlayerRef = number | string; /** * The forward model the search drives. Implement these over your engine: * `applyAction` is the transition function, `evaluate` is the leaf heuristic * (higher = better for `perspective`), and `determinize` samples the hidden * state so the search isn't allowed to peek at information a player shouldn't * have. `orderActions` is an optional breadth control (good move ordering lets * `maxBranch` prune to the promising moves). */ export interface SearchModel { legalActions(state: TState): TAction[]; applyAction(state: TState, action: TAction): TState; isTerminal(state: TState): boolean; currentPlayer(state: TState): PlayerRef; /** Position value from `perspective`'s point of view (higher is better). */ evaluate(state: TState, perspective: PlayerRef): number; /** Sample a concrete world consistent with `perspective`'s knowledge. */ determinize?(state: TState, perspective: PlayerRef, rng: Rng): TState; /** Reorder actions best-first; the search expands only the first `maxBranch`. */ orderActions?(state: TState, actions: TAction[]): TAction[]; } export interface SearchOptions { /** Plies to look ahead, including the root action itself (>= 1). */ depth: number; perspective: PlayerRef; rng?: Rng; /** Worlds to sample for imperfect-information averaging (default 1). */ determinizations?: number; /** Cap candidates expanded per node (default unlimited). */ maxBranch?: number; } export interface ScoredAction { readonly action: TAction; readonly value: number; } /** * Value every root action by simulating it forward. For each action we average * its minimax value across `determinizations` sampled worlds. Returns one entry * per (ordered, breadth-capped) root action; the caller turns these values into * a choice (e.g. skill-scaled softmax via {@link chooseActionIndex}). */ export declare function searchActionValues(rootState: TState, model: SearchModel, options: SearchOptions): ScoredAction[];