/**
 * Coarse classification of a node's terminal status, independent of payoff.
 * The actual per-player payoff lives in {@link StateNodeoutcome }.
 */
export type StateType = number;
export namespace StateType {
    let Undecided: number;
    let Terminal: number;
    let DepthCapped: number;
    let NoMoves: number;
}
/**
 * @template State, Action
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2026
 */
export class StateNode<State, Action> {
    /**
     * How deep is the node in the tree
     * @type {number}
     */
    depth: number;
    /**
     * Total number of explored playouts through this node.
     * @type {number}
     */
    playouts: number;
    /**
     * Per-player heuristic estimate of the value of this state.
     * For terminal nodes this mirrors {@link StateNode#outcome}.
     * For internal nodes this is refined by maxN backup as children materialize.
     * Index = player ID.
     * @type {Float64Array | null}
     */
    heuristicValue: Float64Array | null;
    /**
     * Per-player cumulative payoff aggregated by backpropagation.
     * Average value for player `p` is `totalScore[p] / playouts` once `playouts > 0`.
     * @type {Float64Array | null}
     */
    totalScore: Float64Array | null;
    /**
     * Per-player payoff at this terminal node, cached at materialization.
     * `null` for non-terminal nodes (uses {@link StateNode#heuristicValue} as a stand-in).
     * @type {Float64Array | null}
     */
    outcome: Float64Array | null;
    /**
     * Player ID of whoever chooses the next move from this state.
     * `-1` for terminal nodes (no decision to make).
     * @type {number}
     */
    activePlayer: number;
    /**
     * @type {null|StateNode}
     */
    parent: null | StateNode<any, any>;
    /**
     *
     * @type {null|MoveEdge[]}
     */
    moves: null | MoveEdge<any>[];
    /**
     *
     * @type {StateType}
     */
    type: StateType;
    /**
     * Allocate the per-player buffers. Must be called before any backprop or selection.
     * @param {number} numPlayers
     */
    allocate(numPlayers: number): void;
    bubbleUpHeuristicScore(): void;
    /**
     * maxN backup: the active player picks the child that maximizes their own
     * component; the chosen child's entire heuristic vector is copied here.
     *
     * This generalizes minimax across N players and asymmetric turn orders: the
     * non-active components ride along, representing "what would happen to player Y
     * if X plays the way X wants from this state".
     */
    aggregateHeuristicScore(): void;
    /**
     * @param state
     * @param {function(State, source:StateNode):MoveEdge[]} computeValidMoves
     * @param {function(State):number} computeActivePlayer
     * @param {function(State):Float64Array} computeOutcome called when expansion produces no moves
     * @returns {number} number of children
     */
    expand(state: any, computeValidMoves: any, computeActivePlayer: (arg0: State) => number, computeOutcome: (arg0: State) => Float64Array): number;
    /**
     * Walk up from this node to the root, adding the per-player outcome to each
     * ancestor's cumulative score and incrementing their visit count.
     * @param {Float64Array} outcomeVector indexed by player ID
     */
    backpropagate(outcomeVector: Float64Array): void;
    /**
     * Whenever this is a terminal state or not (win/loss/tie/no-moves/depth-cap)
     * @returns {boolean}
     */
    isTerminal(): boolean;
    /**
     *
     * @returns {boolean}
     */
    isExpanded(): boolean;
    /**
     * Pick the best moves from this node's perspective — i.e. for whichever
     * player owns the decision here.
     * @returns {MoveEdge[]}
     */
    pickBestMoves(): MoveEdge<any>[];
    /**
     *
     * @param {function(StateNode)} visitor
     */
    traverse(visitor: (arg0: StateNode<any, any>) => any): void;
}
import { MoveEdge } from "./MoveEdge.js";
//# sourceMappingURL=StateNode.d.ts.map