/** * AST evaluator - transforms parsed AST into roll results. * * @module evaluator/evaluator */ import { EvaluatorError } from '../errors.js'; import type { ASTNode } from '../parser/ast.js'; import type { RNG } from '../rng/types.js'; import type { DieResult, EvaluateOptions, RollResult } from '../types.js'; import { DegreeOfSuccess } from '../types.js'; import { DEFAULT_MAX_EXPLODE_ITERATIONS } from './modifiers/explode.js'; import { DEFAULT_MAX_REROLL_ITERATIONS } from './modifiers/reroll.js'; export { EvaluatorError }; /** * Default value of `EvaluationOptions.maxDice`: the number of dice a single * evaluation may roll before `DICE_LIMIT_EXCEEDED` is thrown. * * Counted across the whole expression, not per pool, so `6000d6+6000d6` * breaches it. Includes dice rolled by explosions, rerolls, and * meta-expressions. * * @category Limits */ export declare const DEFAULT_MAX_DICE = 10000; export { DEFAULT_MAX_EXPLODE_ITERATIONS, DEFAULT_MAX_REROLL_ITERATIONS }; /** * Per-branch accumulator for what flows up a recursion unchanged or merged. A * field a parent reformats instead belongs on {@link EvalResult}. * * Module-level export, deliberately absent from `src/index.ts` — the package * surface never mentions it. See {@link mergeMetaRolls} for why the export * exists at all. */ export type EvalContext = { rolls: DieResult[]; /** * Set by a parent that discards its child's `rendered`. Every pool modifier * does: it rebuilds the breakdown from the target's `expression` plus a * `renderDice` pass of its own. * * ! In a chain each modifier's own context is the next one out's discarded * ! target, so a render site that skips the check leaves every level above the * ! innermost still rendering into the void. * * ! Does not propagate into nested contexts — `(4d6)kh1` evaluates into a * ! fresh one, so only a modifier's direct dice-pool target is spared. */ suppressRender?: boolean; /** * Populated by `evalVersus` with the resolved degree and natural value. * `evaluate()` reads this from the top-level ctx to surface `degree` and * `natural` on the final `RollResult`. Only populated when `vs` is the * root of the expression. */ versusMetadata?: { degree: DegreeOfSuccess; natural: number | undefined; dcTotal: number; }; }; /** * Evaluates a parsed AST against an {@link RNG} and returns the roll result. * * The second half of the pipeline — {@link roll} is `evaluate(parse(...))`. * Call it directly to reuse one AST across many rolls, or to drive a * hand-built AST. * * Unlike `roll`, the RNG is required: `evaluate` never invents a randomness * source, so a caller can never accidentally get an unseeded roll. * * @param ast - The AST to evaluate, from {@link parse} or hand-built * @param rng - Randomness source; one `nextInt` call per die * @param options - Evaluation limits plus the original `notation` string, * which the AST cannot supply * @returns Complete {@link RollResult} * @throws {EvaluatorError} On a limit breach, division by zero, an undefined * variable, or a non-finite total * @throws {RollParserError} `INVALID_EVALUATION_LIMIT` when a supplied limit is * not an integer in range — raised before any die is rolled * * @example * ```typescript * import { evaluate, parse } from 'roll-parser'; * import { createMockRng } from 'roll-parser/testing'; * * const ast = parse('2d6+3'); * const result = evaluate(ast, createMockRng([4, 2]), { notation: '2d6+3' }); * result.total; // 9 * result.rendered; // '2d6[4, 2] + 3 = 9' * ``` * * Omitting `notation` falls back to the normalized `expression`, which is * reconstructed from the AST — so `RollResult.notation` is always a string, * just not necessarily the one the user typed. * * @category Core */ export declare function evaluate(ast: ASTNode, rng: RNG, options?: EvaluateOptions): RollResult; //# sourceMappingURL=evaluator.d.ts.map