import { Tree } from "./tree.js"; import { Node } from "./node.js"; import { EvaluateNodeFunc } from "./interfaces.js"; import { SearchOpts, SearchResult } from "./search.js"; /** * Extends the tree class with function specifically for minimax searches */ export declare class SearchTree extends Tree { opts: SearchOpts; /** Tracks whether a searched has expired due to time */ protected expired: boolean; /** Time the search will expire. 0 disables expiry */ protected expireTime: number; /** Flags that full depth has *not* been reached when set to false*/ protected fullDepth: boolean; /** Enables presort of children internally */ protected presortEnable: boolean; /** Number of leaf or depth = 0 reached during current call */ protected outcomes: number; /** Flag set if node limit has been reached */ protected nodeLimitExceeded: boolean; constructor(root: Node, opts?: SearchOpts); /** Callback to evaluate the value of gamestate attached to node */ EvaluateNode: EvaluateNodeFunc; /** The specific evaldepth function for a search mode. Must be implemented */ protected evalDepth(depth?: number): SearchResult; /** * Searches the tree repeatedly, incrementing the depth each time. * Returns after reaching target depth, or early if tree is complete or time exceeded. * ### Relevant {@link SearchOpts | options} * - {@link SearchOpts.depth} | Maximum depth to search for. 0 for unlimited * - {@link SearchOpts.timeout} | Maximum time to search for. 0 for unlimited * - {@link SearchOpts.pruning} * - {@link SearchOpts.initialDepth} * - {@link SearchOpts.genBased} (Only if {@link NegamaxOpts.pruning} is not {@link PruningType.NONE}) * - {@link SearchOpts.presort} * * @param depth Overide the depth parameter set in {@link Negamax.opts} * @returns The result of the search */ protected evalDeepening(): SearchResult; /** * Search the tree according to the options specified by the options (opts). * @returns Result from the tree search */ evaluate(): SearchResult; /** * Called during deepening search between each depth. * Does nothing until overidden */ depthCallback(tree: SearchTree, result: SearchResult): void; /** * Checks if expiry is enable and has happened * @returns `true` if time has expired, otherwise `false` */ protected checkExpiry(): boolean; /** * Checks if node limit is enabled and returns `true` if it has been exceeded, * otherwise returns `false`. */ protected checkNodeLimit(): boolean; /** * Returns either the array of node children or a generator which may create children on the fly * Also presorts children if enabled * @param node Node to return an iterable of children * @returns An iterable for going through children of node */ protected getChildren(node: Node): Iterable>; /** * Sorts the child nodes of given parent {@link Node} according to inherited value. * Sort is descending by default * * Sorts using the method specififed in * {@link SearchOpts.method | opts.SearchOpts.SortMethod}. * @param node parent {@link Node} of children to sort * @param reverse Optionally sort ascending instead * @returns The child with the highest value */ protected sortChildren(node: Node, reverse?: boolean): Node; /** * Selects from the nodes children which all have an equal best value (and depth) * Uniform random weighting * Node.child must already represent best child * @param node Parent to select best child from * @returns randomly selected best child with same value as best */ protected randomBestChild(node: Node): Node; /** Selects best child from nodes children according to the weighting factor */ protected randomWeightedChild(node: Node, weight: number): Node; /** Generator that yields all the nodes along the optimal * path, starting from and including `node` */ protected routeGen(node: Node): Generator>; /** Generator that yields all the moves along the optimal path */ protected optimalMoveGen(node: Node): Generator; /** * Function to return the list of moves starting from the root * that are the 'optimal' path. * * Must be called after evaluating the tree. * * @returns A list of moves from the active root {@link Node} * that represent the optimal sequence through the game. */ getOptimalMoves(): M[]; removeNodes(): number; /** * Recursively go through node and its children removing all * nodes that are not best */ protected removeNonBestNodes(node: Node, depth: number, keep: boolean): number; }