com.phasmidsoftware.gambit.game

Members list

Type members

Classlikes

class AlphaBetaPlayer[P, S, M, Pl, K](me: Pl, depth: Int = ...)(using state: State[P, S], game: Game[S, M, Pl], ttCache: TTCache[K]) extends Player[S, M, Pl]

A generic alpha-beta pruning player. For more information, see https://en.wikipedia.org/wiki/Alpha-beta_pruning

A generic alpha-beta pruning player. For more information, see https://en.wikipedia.org/wiki/Alpha-beta_pruning

Implements minimax search with alpha-beta pruning to a configurable depth. Alpha-beta pruning eliminates branches that cannot affect the final decision, reducing the effective branching factor from b to approximately sqrt(b) in the best case -- effectively doubling the achievable search depth for the same computation compared to plain minimax.

== Heuristic Convention ==

State.heuristic(s) is positive when the player who just moved to reach s is doing well. This is consistent with the convention used throughout Gambit. At leaf nodes (terminal or depth limit reached), the raw heuristic is returned. The maximizing/minimizing logic correctly accounts for this convention.

== Move Ordering ==

Moves are ordered by heuristic before recursing -- highest first for the maximizing player, lowest first for the minimizing player. This shallow search ordering maximises the probability of early pruning, approaching the theoretical best-case performance of alpha-beta.

== Mutable State ==

Alpha and beta bounds are tracked with mutable variables, and boundary/break is used for early termination on a prune. This is intentional: alpha-beta pruning is fundamentally about early exit based on accumulated bounds, and fighting that with purely functional constructs would sacrifice both clarity and performance. Mutable state is appropriate here for the same reason it is appropriate in high-performance sorting algorithms.

== Transposition Table ==

An optional key function maps a state to a cache key. When set via withKeyFn, alphaBeta looks up the key before evaluating and caches the result afterwards, avoiding re-evaluation of positions reachable by multiple move orderings (transpositions). The table is cleared between games via gameOver.

Caching behaviour is controlled by the given TTCache[K] in scope:

  • FlatTTCache[K] — single HashMap[K, TTEntry]; reuses entries cached at equal or greater depth. Suitable for shallow games (TicTacToe, Connect Four).

  • TrancheTTCache[K] — separate sub-table per depth; benchmarked ~25% faster for deep searches (bridge double-dummy, ~52 plies).

Both implementations store TTFlag (Exact / LowerBound / UpperBound) with each entry and only reuse entries whose flag is compatible with the current alpha-beta window, preventing cache poisoning from incompatible bounds.

Type parameters

K

The type of the transposition table key. Use Any when no caching is needed (via the companion apply); otherwise a compact type such as Int, (Long, Long), or a case class that has correct equals/hashCode.

M

The type representing the move in the game.

P

The type representing a proto-state, which helps transition between game states.

Pl

The type representing the players in the game.

S

The type representing the game state.

Value parameters

depth

the maximum search depth (default is 6). Determines how far ahead the algorithm looks in the game tree.

game

the typeclass providing game-specific behaviours.

me

the player identifier representing this player.

state

the typeclass providing state-specific functionalities.

ttCache

the TTCache typeclass instance that handles probe/store/clear. Supply a given FlatTTCache[K] for shallow games or a given TrancheTTCache[K] for deep searches. Only consulted when a key function has been set via withKeyFn.

Attributes

Companion
object
Supertypes
trait Player[S, M, Pl]
class Object
trait Matchable
class Any
Known subtypes

Companion object for AlphaBetaPlayer.

Companion object for AlphaBetaPlayer.

Provides a convenience apply for the common case where no transposition table is needed. The key type is erased to Any; callers that want a typed key should use new AlphaBetaPlayer[P, S, M, Pl, K](...) directly.

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
case class AlphaBetaWindow(alpha: Double, beta: Double)

The alpha-beta window for the root search.

The alpha-beta window for the root search.

Value parameters

alpha

the lower bound: the maximizing player is guaranteed at least this score.

beta

the upper bound: the minimizing player is guaranteed at most this score.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

Object representing constants or utilities related to the AlphaBetaWindow.

Object representing constants or utilities related to the AlphaBetaWindow.

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type
case class Contestant[S, M, Pl](name: String, player: Player[S, M, Pl])

A named contestant in a tournament.

A named contestant in a tournament.

Wraps a Player with a display name so the league table can identify each entry independently of the Boolean player-identity used internally by two-player GameRunner.

Type parameters

M

the move type.

Pl

the player identity type.

S

the state type.

Value parameters

name

display name for the league table.

player

the underlying player.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
class FlatTTCache[K](maxSize: Int = ...) extends TTCache[K]

A flat (single-HashMap) transposition table.

A flat (single-HashMap) transposition table.

Suitable for shallow games (e.g. TicTacToe, Connect Four) where results computed at a greater-or-equal depth are valid to reuse at the current depth.

Type parameters

K

the key type.

Value parameters

maxSize

maximum number of entries; writes are suppressed once the table reaches this size. Default is unlimited.

Attributes

Supertypes
trait TTCache[K]
class Object
trait Matchable
class Any
object GambitConfig

Loads and exposes typed configuration values for the Gambit framework.

Loads and exposes typed configuration values for the Gambit framework.

Configuration is read from application.conf on the classpath (standard Typesafe Config behaviour). All values have hard-coded fallbacks so the application runs correctly even if no config file is present.

== HOCON structure ==

gambit {
 tournament.gamesPerPairing = 6
 alphaBeta.depth1           = 4
 alphaBeta.depth2           = 6
 mcts.iterations1           = 200
 mcts.iterations2           = 500
 mcts.explorationConstant   = 1.4142135623730951
}

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
trait Game[S, M, Pl]

Typeclass: describes the rules of a game in terms of state S, move M, and player identity Pl.

Typeclass: describes the rules of a game in terms of state S, move M, and player identity Pl.

A Game instance captures everything the GameRunner needs to know about the mechanics of a specific game — how moves are applied, whose turn it is, where the game starts, and how many players are involved.

This separates game rules (Game[S, M, Pl]) from game strategy (Player[S, M, Pl]) and game execution (GameRunner[P, S, M, Pl]).

Type parameters

M

the move type.

Pl

the player identity type (e.g., Boolean for two-player, an enum for bridge's four seats).

S

the state type.

Attributes

Supertypes
class Object
trait Matchable
class Any
object GameResult

Companion for GameResult providing factory methods.

Companion for GameResult providing factory methods.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
GameResult.type
class GameRunner[P, S, M, Pl](playerMap: Map[Pl, Player[S, M, Pl]], random: Random = ...)(using state: State[P, S], game: Game[S, M, Pl])

A generic game runner that plays a sequence of games between any number of players, for any game representable as a State[P, S] and Game[S, M, Pl].

A generic game runner that plays a sequence of games between any number of players, for any game representable as a State[P, S] and Game[S, M, Pl].

Type parameters: P — proto-state type (used by State.construct) S — state type M — move type Pl — player identity type (e.g., Boolean for two-player, Seat for bridge)

Value parameters

game

implicit Game[S, M, Pl] for game mechanics.

playerMap

a map from player identity to Player instance.

random

a Random instance for reproducibility.

state

implicit State[P, S] for goal detection.

Attributes

Supertypes
class Object
trait Matchable
class Any
class MCTSNode[S, M, Pl](val state: S, val move: Option[M], val movedBy: Option[Pl], var visits: Int, var wins: Double, val children: ListBuffer[MCTSNode[S, M, Pl]], var untriedMoves: List[M])

A node in the MCTS search tree.

A node in the MCTS search tree.

Mutable: visits and wins are updated in-place during backpropagation. Children are added during expansion. untriedMoves shrinks as children are expanded.

No parent reference -- backpropagation uses an explicit path stack accumulated during selection, avoiding circular references and the GC/equality issues that back-references cause in tree structures.

Type parameters

M

the move type.

Pl

the player identity type.

S

the state type.

Value parameters

children

expanded child nodes.

move

the move that led to this state (None for root).

movedBy

the player who made move (None for root).

state

the game state at this node.

untriedMoves

moves not yet expanded into children.

visits

number of times this node has been visited.

wins

cumulative score from simulations through this node, from the perspective of movedBy.

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object MCTSNode

Companion object for MCTSNode, providing factory methods.

Companion object for MCTSNode, providing factory methods.

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
MCTSNode.type
class MCTSPlayer[P, S, M, Pl](me: Pl, iterations: Int = ..., explorationConstant: Double = ...)(using state: State[P, S], game: Game[S, M, Pl]) extends Player[S, M, Pl]

A generic Monte Carlo Tree Search player. For more information about MCTS, see https://en.wikipedia.org/wiki/Monte_Carlo_tree_search

A generic Monte Carlo Tree Search player. For more information about MCTS, see https://en.wikipedia.org/wiki/Monte_Carlo_tree_search

Implements the standard four-phase MCTS loop:

  1. Selection -- walk the tree by UCB1 (Upper Confidence Bound) until an unexpanded node is found.
  2. Expansion -- add one new child for an untried move.
  3. Simulation -- play randomly to a terminal state (rollout).
  4. Backprop -- update visit/win counts along the path to root.

The search tree is retained between calls to chooseMove. After each move the subtree rooted at the chosen child becomes the new root, carrying forward all accumulated visit and win counts. If the opponent plays an unexplored line the retained tree cannot be advanced and a fresh root is created instead.

Tree matching uses == on the state type S; callers must ensure S has meaningful equality (satisfied by case class and case object).

== Future upgrades ==

  • Actor-based parallelism: move the mutable tree into an Akka/Pekko actor. Multiple rollout worker actors could then submit simulation results to the tree actor concurrently (root parallelization), giving a near-linear speedup with the number of cores.

  • Heuristic rollouts: replace pure random simulation with a heuristic-guided playout for stronger play.

Type parameters

M

the move type.

P

the proto-state type.

Pl

the player identity type.

S

the state type.

Value parameters

explorationConstant

UCB1 exploration parameter C (default sqrt(2)).

game

implicit Game[S, M, Pl] for move application.

iterations

number of MCTS iterations per move (default 1000).

me

this player's identity.

state

implicit State[P, S] for goal detection.

Attributes

Supertypes
trait Player[S, M, Pl]
class Object
trait Matchable
class Any
case class MatchResult[Pl](results: Seq[GameResult[Pl]])

A MatchResult aggregates GameResults over a series of games. Provides win/loss/draw counts and total games for a given player.

A MatchResult aggregates GameResults over a series of games. Provides win/loss/draw counts and total games for a given player.

Type parameters

Pl

the player identity type.

Value parameters

results

the sequence of individual game results.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
case class Move[P, S](f: S => P, desc: String) extends Transition[P, S]

A case class that implements Transition[S].

A case class that implements Transition[S].

Type parameters

P

a proto-state, from which a state S can be constructed.

S

the type of the input parameter and of the result.

Value parameters

desc

the human-legible description of f.

f

a function S => P.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
trait Transition[P, S]
trait S => (P, S)
class Object
trait Matchable
class Any
Show all
class NodeLimitException(val nodes: Int) extends Exception

Exception thrown when the node count limit is exceeded. Caught by analyzeDoubleDummy to return the best result found so far.

Exception thrown when the node count limit is exceeded. Caught by analyzeDoubleDummy to return the best result found so far.

Attributes

Supertypes
class Exception
class Throwable
trait Serializable
class Object
trait Matchable
class Any
Show all
trait Player[S, M, Pl]

A Player in a game of type S, making moves of type M, identified as player Pl.

A Player in a game of type S, making moves of type M, identified as player Pl.

Type parameters

M

the move type.

Pl

the player identity type.

S

the state type.

Attributes

Supertypes
class Object
trait Matchable
class Any
Known subtypes
class RandomPlayer
class MenacePlayer
class RandomPlayer
class AlphaBetaPlayer[P, S, M, Pl, K]
class MCTSPlayer[P, S, M, Pl]
Show all
trait State[P, S] extends Ordering[S]

Type class for a State. A State is a position in a game or other situation which requires heuristically-directed tree search. For example, a State might describe a board position in Tic-tac-toe or Chess.

Type class for a State. A State is a position in a game or other situation which requires heuristically-directed tree search. For example, a State might describe a board position in Tic-tac-toe or Chess.

NOTE that State depends on Transition. CONSIDER eliminating Transition such that all logic is defined by State.

Type parameters

P

a proto-state, that's to say a type such that a P, S tuple can be converted into a new S.

S

the underlying type on which the state is based.

Attributes

Supertypes
trait Ordering[S]
trait PartialOrdering[S]
trait Equiv[S]
trait Serializable
trait Comparator[S]
class Object
trait Matchable
class Any
Show all
Known subtypes
trait TTCache[K]

Typeclass for a transposition table used by AlphaBetaPlayer.

Typeclass for a transposition table used by AlphaBetaPlayer.

Implementations are responsible for:

  • Storing a result together with the alpha-beta bounds under which it was computed (so that a TTFlag can be derived and checked on re-use).
  • Probing the table and returning a usable value only when the cached entry's flag is compatible with the current alpha-beta window.
  • Clearing all cached data between games.

== Probe semantics ==

Given a cached TTEntry with sufficient depth:

  • Exact → return entry.value directly.
  • LowerBound → tighten alpha: if the updated alpha >= beta, return entry.value (cut-off); otherwise return None (continue searching with tightened alpha — not possible to propagate here, so we return None and let the caller re-search).
  • UpperBound → tighten beta: if alpha >= the updated beta, return entry.value (cut-off); otherwise return None.

Type parameters

K

the type of the transposition table key.

Attributes

Supertypes
class Object
trait Matchable
class Any
Known subtypes
class FlatTTCache[K]
class TrancheTTCache[K]
case class TTEntry(value: Double, depth: Int, flag: TTFlag)

A single entry in the transposition table, recording the cached minimax value, the depth at which it was computed, and the bound type.

A single entry in the transposition table, recording the cached minimax value, the depth at which it was computed, and the bound type.

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
enum TTFlag

Transposition table flag indicating the type of a cached alpha-beta value.

Transposition table flag indicating the type of a cached alpha-beta value.

When alpha-beta search returns a value v for a node with window [alphaOrig, beta]:

  • ExactalphaOrig < v < beta: the value is exact; reuse freely.
  • UpperBoundv <= alphaOrig: search failed low; v is an upper bound on the true value.
  • LowerBoundv >= beta: search failed high; v is a lower bound on the true value.

Attributes

Supertypes
trait Enum
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all
class Tournament[P, S, M, Pl](contestants: Seq[Contestant[S, M, Pl]], gamesPerPairing: Int = ..., random: Random = ...)(using state: State[P, S], game: Game[S, M, Pl])

A round-robin tournament for two-player zero-sum games.

A round-robin tournament for two-player zero-sum games.

Every pair of contestants plays gamesPerPairing games with each contestant taking the first-player role in half the games, so neither side has a systematic first-move advantage in the overall standings.

== Scoring == Standard football (soccer) 3-1-0 scoring: Win = 3 points Draw = 1 point Loss = 0 points

Ties in the table are broken by goal difference (wins minus losses), then by total wins.

== Usage ==

 val t = Tournament(contestants, gamesPerPairing = 10, random = new Random(42L))
 println(t.leagueTable)

Type parameters

M

the move type.

P

the proto-state type.

Pl

the player identity type.

S

the state type.

Value parameters

contestants

the players to enter in the tournament.

game

implicit Game[S, M, Pl].

gamesPerPairing

number of games each ordered pair plays (A-as-first vs B-as-second). Each unordered pair therefore plays 2 * gamesPerPairing games in total.

random

random source passed to each GameRunner.

state

implicit State[P, S].

Attributes

Supertypes
class Object
trait Matchable
class Any
class TrancheTTCache[K](reuseDeeper: Boolean = ..., maxSize: Int = ...) extends TTCache[K]

A depth-tranche transposition table.

A depth-tranche transposition table.

Maintains a separate HashMap[K, TTEntry] per search depth. A hit requires an exact depth match (or, if reuseDeeper is true, also accepts entries from deeper tranches). Benchmarked ~25% faster than FlatTTCache for deep searches such as bridge double-dummy (~52 plies).

Type parameters

K

the key type.

Value parameters

maxSize

total entry cap across all tranches. Default unlimited.

reuseDeeper

if true, a miss at the current depth also checks deeper tranches. Default false.

Attributes

Supertypes
trait TTCache[K]
class Object
trait Matchable
class Any
trait Transition[P, S] extends S => (P, S)

A function that transitions from a state S to a prototype state.

A function that transitions from a state S to a prototype state.

Type parameters

P

a proto-state, from which a state S can be constructed.

S

the type of the input.

Attributes

Supertypes
trait S => (P, S)
class Object
trait Matchable
class Any
Known subtypes
class Move[P, S]

Types

type GameResult[Pl] = Map[Pl, Int]

A GameResult captures the outcome of one complete game for all players. Each player maps to a score, typically -1 (loss), 0 (draw), or +1 (win) for two-player zero-sum games. For trick-taking games like bridge, the scores might represent tricks won per side.

A GameResult captures the outcome of one complete game for all players. Each player maps to a score, typically -1 (loss), 0 (draw), or +1 (win) for two-player zero-sum games. For trick-taking games like bridge, the scores might represent tricks won per side.

A GameResult is typically a subset of a MatchResult and is a Map of Pl -> Int.

Attributes