MonteCarloSearch

dicechess.engine.search.MonteCarloSearch

Monte-Carlo search bot (difficulty 7).

Ranks every legal full-turn path by the Rao-Blackwellized Monte-Carlo win probability of the resulting position (MonteCarloEquity) and plays the highest-scoring one; an immediate king capture is always preferred. Where the primitive bots score only a single ply of heuristics, this estimates the full-game win probability via rollouts, so it accounts for deeper consequences.

Per-move cost scales with the number of legal turns × the rollout budget, so DefaultConfig uses a modest budget. Tests and benchmarks pass an explicit MonteCarloConfig and scala.util.Random through findBestMove(state:dicechess\.engine\.domain\.GameState,config:dicechess\.engine\.search\.MonteCarloConfig,random:scala\.util\.Random)* for reproducible, faster, or stronger play.

Attributes

Source
MonteCarloSearch.scala
Graph
Supertypes
class Object
trait Matchable
class Any
Show all
Self type

Members list

Value members

Concrete methods

override def findBestMove(state: GameState): Option[ScoredSequence]

Finds and returns the best full-turn path according to this strategy.

Finds and returns the best full-turn path according to this strategy.

Value parameters

state

the current dicechess.engine.domain.GameState; state.activeColor identifies the side to move

Attributes

Returns

Some([[ScoredSequence]]) when at least one legal path exists; None when the player must pass

Definition Classes
Source
MonteCarloSearch.scala
override def findBestMove(state: GameState, random: Random): Option[ScoredSequence]

Reproducible entry point (e.g. the arena): the default rollout budget, driven by the supplied random.

Reproducible entry point (e.g. the arena): the default rollout budget, driven by the supplied random.

Attributes

Definition Classes
Source
MonteCarloSearch.scala
def findBestMove(state: GameState, config: MonteCarloConfig, random: Random): Option[ScoredSequence]

Finds the best turn under an explicit rollout budget and random source.

Finds the best turn under an explicit rollout budget and random source.

Attributes

Source
MonteCarloSearch.scala
def findBestMove(state: GameState, config: MonteCarloConfig, deadlineNanos: Long, random: Random): Option[ScoredSequence]

Finds the best turn under a wall-clock deadline (deadlineNanos, a java.lang.System.nanoTime value), so a bot on a game clock never overruns. The caller allocates the game budget into a per-move deadline.

Finds the best turn under a wall-clock deadline (deadlineNanos, a java.lang.System.nanoTime value), so a bot on a game clock never overruns. The caller allocates the game budget into a per-move deadline.

Strategy: take any immediate king capture for free; otherwise rank turns by a cheap material score, keep the top MaxCandidates, and Monte-Carlo-evaluate them in that order, giving each an equal slice of the remaining time and stopping at the deadline. The best material turn is the fallback, so a legal move is always returned even if the deadline elapses before any rollout completes. This path is non-deterministic by design.

Attributes

Source
MonteCarloSearch.scala
override def findBestMove(state: GameState, deadlineNanos: Long, random: Random): Option[ScoredSequence]

Time-budgeted entry point (see TimeBudgetedSearch). Evaluates within the wall-clock deadlineNanos using a rollout cap high enough that the deadline — not the rollout count — bounds the search, so the whole budget is spent on the strongest play available in the time given.

Time-budgeted entry point (see TimeBudgetedSearch). Evaluates within the wall-clock deadlineNanos using a rollout cap high enough that the deadline — not the rollout count — bounds the search, so the whole budget is spent on the strongest play available in the time given.

Attributes

Definition Classes
Source
MonteCarloSearch.scala
override def shouldAcceptDouble(state: GameState, currentStake: Int, responder: Color): Boolean

Determines whether the bot should accept (Take) or decline (Drop) a double from the opponent, evaluated from the perspective of responder.

Determines whether the bot should accept (Take) or decline (Drop) a double from the opponent, evaluated from the perspective of responder.

This is the single policy point for the take/drop decision: strategies that want their own threshold or estimator override this overload. The two-argument form below only delegates here, so a policy written against it is bypassed whenever a caller names the responder explicitly (which every caller holding a doubleDecision state must, see the hazard note there).

Value parameters

currentStake

the proposed double stake (e.g. 2, 4...)

responder

the colour of the player responding to the double offer

state

current game state (dice pool is empty); its active colour is the side to move, which in a double decision is the offerer, not the responder

Attributes

Returns

true to accept the double (Take), false to resign the current stake (Drop)

Definition Classes
Source
MonteCarloSearch.scala
override def shouldOfferDouble(state: GameState, currentStake: Int): Boolean

Determines whether the bot should offer a double before its dice roll.

Determines whether the bot should offer a double before its dice roll.

Value parameters

currentStake

the current stake of the game

state

current game state (dice pool is empty)

Attributes

Returns

true to offer a double, false otherwise

Definition Classes
Source
MonteCarloSearch.scala

Inherited methods

protected def estimateWinProbability(state: GameState): Double

Estimates the winning probability in [0.0, 1.0] for the side to move. Convenience over winProbability for offer decisions, where the deciding side is the active colour; do not override it, override winProbability.

Estimates the winning probability in [0.0, 1.0] for the side to move. Convenience over winProbability for offer decisions, where the deciding side is the active colour; do not override it, override winProbability.

Attributes

Inherited from:
SearchAlgorithm
Source
SearchAlgorithm.scala
def shouldAcceptDouble(state: GameState, currentStake: Int): Boolean

Determines whether the bot should accept (Take) or decline (Drop) a double from the opponent, taking the side to move as the responder. Kept for source and binary compatibility; it delegates to the three-argument overload.

Determines whether the bot should accept (Take) or decline (Drop) a double from the opponent, taking the side to move as the responder. Kept for source and binary compatibility; it delegates to the three-argument overload.

Value parameters

currentStake

the proposed double stake (e.g. 2, 4...)

state

current game state (dice pool is empty)

Attributes

Returns

true to accept the double (Take), false to resign the current stake (Drop)

Note

Perspective hazard: this overload evaluates the win probability of state.activeColor. In a double decision state, state.activeColor is the player who offered the double, NOT the responder, so a caller that feeds the delivered position here asks whether the offerer should take. Callers must prefer shouldAcceptDouble(state, currentStake, responder); strategies must override that overload, not this one.

Inherited from:
SearchAlgorithm
Source
SearchAlgorithm.scala
override def shouldAcceptDraw(state: GameState): Boolean

Accepts a draw when the position is a dead draw by shouldOfferDraw's own test, or when it is so unfavourable that playing on is worse than splitting the point.

Accepts a draw when the position is a dead draw by shouldOfferDraw's own test, or when it is so unfavourable that playing on is worse than splitting the point.

The second branch uses the centipawn evaluation from Evaluator.evaluate from the active side's perspective. The threshold of −200cp (a pawn's disadvantage) is deliberately conservative — it avoids accepting draws in roughly equal positions while cutting losses in clearly lost ones. The first branch keeps offering and accepting consistent: a position the bot would offer a draw in is never one it declines.

Attributes

Definition Classes
Inherited from:
DrawOfferLogic
Source
DrawOfferLogic.scala
override def shouldOfferDraw(state: GameState): Boolean

Offers a draw when the position is a theoretical dead draw: neither player can ever force a king capture — the win condition in Dice Chess.

Offers a draw when the position is a theoretical dead draw: neither player can ever force a king capture — the win condition in Dice Chess.

The check requires all of the following:

  • No pawns, knights, rooks, or queens on the board.
  • Each side has at most one bishop.
  • The two kings are not on adjacent squares.
  • For every bishop on the board, the opposing king stands on a square of the opposite colour — making a diagonal attack impossible in either direction.

These constraints capture the standard "insufficient material" cases:

  • K vs K
  • K+B vs K (defending king on correct colour)
  • K+B vs K+B (one bishop each, both kings safe)

Attributes

Definition Classes
Inherited from:
DrawOfferLogic
Source
DrawOfferLogic.scala

Concrete fields

Default per-move budget — a balance between playing strength and decision latency.

Default per-move budget — a balance between playing strength and decision latency.

Attributes

Source
MonteCarloSearch.scala