MonteCarloEquity

dicechess.engine.search.MonteCarloEquity

Rao-Blackwellized Monte-Carlo pre-roll equity estimator.

For a position with too few games in the database to read an empirical win-rate, this estimates P(White win) / P(Black win) / P(undecided) on demand. It is the Scala port of the C++ reference (https://github.com/rabestro/dice-chess-engine).

Algorithm

Each rollout walks a random game and, at every ply, integrates the exact per-ply king-capture probability p = wins / 216 from KingCaptureProbability instead of sampling a 0/1 win:

survive = 1
for each ply (side S to move):
 p = P(S captures the opponent king on this roll)   // exact, over all 216 rolls
 winsOf(S) += survive * p
 survive   *= (1 - p)
 advance to a random surviving continuation          // a sampled non-capturing turn

Because the win mass at each node is added analytically (Rao-Blackwellization) rather than as a Bernoulli sample, the estimator has far lower variance than vanilla 0/1 Monte-Carlo — EquityEstimate.varianceReductionVsVanilla reports the measured ratio.

Deviation from the reference

The reference advances the rollout to any sampled legal turn, including king-captures. A king capture is terminal, so following it produces a king-less board that is then (incorrectly) played on, a small second-order bias. As the rules source of truth this estimator instead conditions the continuation on survival: it advances only through turns that do not capture a king (the event with probability 1 - p that survive already tracks). The analytic per-ply terms — and therefore the variance self-check — are unaffected.

Attributes

Source
MonteCarloEquity.scala
Graph
Supertypes
class Object
trait Matchable
class Any
Self type

Members list

Value members

Concrete methods

def estimate(state: GameState, config: MonteCarloConfig, random: Random): EquityEstimate

Estimates pre-roll equity with the given configuration and random source.

Estimates pre-roll equity with the given configuration and random source.

Attributes

Source
MonteCarloEquity.scala
def estimate(state: GameState, config: MonteCarloConfig, deadlineNanos: Long, random: Random): EquityEstimate

Estimates pre-roll equity, stopping early once deadlineNanos (a java.lang.System.nanoTime value) is reached — but always after at least one rollout, so the result is never empty. Use for wall-clock-bounded callers such as a time-budgeted bot; unlike the rollout/targetError budgets, the deadline path is non-deterministic (it depends on machine speed), so reserve it for play, not for reproducible tests.

Estimates pre-roll equity, stopping early once deadlineNanos (a java.lang.System.nanoTime value) is reached — but always after at least one rollout, so the result is never empty. Use for wall-clock-bounded callers such as a time-budgeted bot; unlike the rollout/targetError budgets, the deadline path is non-deterministic (it depends on machine speed), so reserve it for play, not for reproducible tests.

Attributes

Source
MonteCarloEquity.scala
def estimate(state: GameState, rollouts: Int, random: Random): EquityEstimate

Estimates pre-roll equity with a fixed rollout budget.

Estimates pre-roll equity with a fixed rollout budget.

Attributes

Source
MonteCarloEquity.scala

Estimates pre-roll equity with default settings and a fresh (unseeded) random source.

Estimates pre-roll equity with default settings and a fresh (unseeded) random source.

Attributes

Source
MonteCarloEquity.scala