Reversi.jl

A high-performance Reversi (Othello) engine in Julia built on bitboard representation, with a clean three-layer architecture:

LayerDirectoryResponsibility
Core gamesrc/core/Pure game state, rules, bitboard logic
I/Osrc/io/File formats: game records, WTHOR binary
UIsrc/ui/Terminal (CUI), GLMakie GUI

Installation

using Pkg
Pkg.add(url="https://github.com/sotashimozono/Reversi.jl")

Quick start

using Reversi

# Terminal game — Human vs Random AI
play_game(HumanPlayer(), RandomPlayer())
# GUI game
launch_gui(HumanPlayer(), RandomPlayer())

Custom player interface

using Reversi

struct MyPlayer <: Player end

function Reversi.get_move(::MyPlayer, game::ReversiGame)
    moves = valid_moves(game)
    isempty(moves) && return nothing   # pass
    return rand(moves)                 # your logic here
end

play_game(MyPlayer(), RandomPlayer(); verbose=false)

Key design decisions

IN_PROGRESS result constant

GameRecord.result uses named constants instead of magic numbers:

ConstantValueMeaning
BLACK1Black wins
WHITE-1White wins
EMPTY0Draw
IN_PROGRESS2Game not yet finished

Safe pass!

pass!(game) checks that the current player genuinely has no legal moves. Use pass!(game; force=true) only when you need to override (e.g. WTHOR replay).

Base.copy vs deepcopy

copy(game) performs a fast field-by-field copy of the game state (all fields are value types). Prefer it over deepcopy in hot loops such as tree search.

validate_record before replay

err = validate_record(record)
err === nothing || error("Bad record: $err")
replayed = replay_game(record; strict=true)