openings

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 6, 2026 License: MIT Imports: 4 Imported by: 1

README

chess-openings

Tests Go Report Card Go Reference

A Go library for identifying chess openings from move sequences. It uses the Lichess chess-openings database (~3,500 named openings across all ECO codes) and identifies openings by matching board positions, which naturally handles transpositions.

Features

  • Position-based matching that handles transpositions (same position via different move orders)
  • Accepts UCI, SAN, PGN, FEN, and EPD input formats
  • Embedded database with no external files or network access required at runtime
  • ~3,500 named openings covering ECO codes A through E
  • Includes modern openings

Installation

go get github.com/ksysoev/chess-openings@latest

Usage

package main

import (
	"fmt"
	"log"

	openings "github.com/ksysoev/chess-openings"
)

func main() {
	book := openings.New()

	// Classify from SAN moves
	result, err := book.ClassifySAN([]string{"e4", "c5", "Nf3", "d6"})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s %s\n", result.Opening.ECO, result.Opening.Name)
	// Output: B50 Sicilian Defense: Modern Variations

	// Classify from UCI moves
	result, err = book.Classify([]string{"d2d4", "d7d5", "b1c3", "g8f6", "c1f4"})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s %s\n", result.Opening.ECO, result.Opening.Name)
	// Output: D01 Rapport-Jobava System

	// Classify from a PGN string
	result, err = book.ClassifyPGN("1. e4 e5 2. Nf3 Nc6 3. Bb5")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s %s\n", result.Opening.ECO, result.Opening.Name)
	// Output: C60 Ruy Lopez

	// Look up a position by FEN
	opening, found := book.ClassifyPosition(
		"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
	)
	if found {
		fmt.Printf("%s %s\n", opening.ECO, opening.Name)
	}
}

API

Method Input Description
New() - Creates a Book loaded with the full Lichess database
Classify(uciMoves) UCI move strings Identifies opening with transposition support
ClassifySAN(sanMoves) SAN move strings Same as Classify but with SAN input
ClassifyPGN(pgn) PGN string Parses PGN (with optional tags/comments) and identifies the opening
ClassifyPosition(fen) FEN string Looks up the opening for a board position
LookupPosition(epd) EPD string Direct position lookup in the database
LookupMoves(uciMoves) UCI move strings Exact move sequence lookup (no transpositions)
SearchMoves(uciMoves) UCI move strings Deepest match along a move sequence (no transpositions)
Size() - Returns the number of unique positions in the book

Data Source

Opening data is from the Lichess chess-openings project, licensed under CC0 1.0. The data files are embedded in the binary at compile time.

License

chess-openings is licensed under the MIT License. See the LICENSE file for more details.

Documentation

Overview

Package openings provides chess opening identification from move sequences.

It uses the Lichess chess-openings database (~3,500 named openings) and identifies openings by matching board positions, which naturally handles transpositions. For example, reaching the Rapport-Jobava System via 1.d4 Nf6 2.Nc3 d5 3.Bf4 (transposed) is correctly identified the same as the standard 1.d4 d5 2.Nc3 Nf6 3.Bf4.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Book

type Book struct {
	// contains filtered or unexported fields
}

Book is a chess opening identification engine loaded with the Lichess opening database. It identifies openings by matching board positions, which naturally handles transpositions.

func New

func New() *Book

New creates a new Book loaded with the full Lichess opening database. The database contains ~3,500 named openings across all ECO codes (A-E). Opening data is pre-computed at generation time, so New only needs to build the lookup structures without any PGN parsing or board replay.

func (*Book) Classify

func (b *Book) Classify(uciMoves []string) (*Classification, error)

Classify identifies the opening from a sequence of moves in UCI notation (e.g. "e2e4", "d7d5", "c2c4"). It replays the moves on a chess board and checks each resulting position against the opening database.

Returns the most specific (deepest) opening found. This approach naturally handles transpositions: if a game reaches a known opening position via a non-standard move order, it will still be correctly identified.

Returns a Classification with a nil Opening if no known opening was found.

func (*Book) ClassifyPGN

func (b *Book) ClassifyPGN(pgn string) (*Classification, error)

ClassifyPGN identifies the opening from a PGN string. It accepts both full PGN (with tag pairs, comments, NAGs, and variations) and plain move text (e.g. "1. e4 e5 2. Nf3 Nc6"). Non-movetext elements are stripped automatically.

func (*Book) ClassifyPosition

func (b *Book) ClassifyPosition(fen string) (*Opening, bool)

ClassifyPosition computes the EPD for the given FEN string and looks it up. This is a convenience method for users who have a FEN string instead of EPD.

func (*Book) ClassifySAN

func (b *Book) ClassifySAN(sanMoves []string) (*Classification, error)

ClassifySAN identifies the opening from a sequence of moves in Standard Algebraic Notation (e.g. "e4", "d5", "c4"). It works the same as Classify but accepts SAN input.

func (*Book) LookupMoves

func (b *Book) LookupMoves(uciMoves []string) (*Opening, bool)

LookupMoves finds the opening matching the exact UCI move sequence in the trie. Unlike Classify, this does not check positions and does not handle transpositions.

func (*Book) LookupPosition

func (b *Book) LookupPosition(epd string) (*Opening, bool)

LookupPosition finds the opening for a given EPD position string. EPD format is FEN without the halfmove clock and fullmove number fields: "<piece-placement> <active-color> <castling> <en-passant>".

func (*Book) SearchMoves

func (b *Book) SearchMoves(uciMoves []string) *Opening

SearchMoves walks the trie following UCI moves and returns the deepest opening found along the path. Unlike Classify, this only matches by exact move sequence without position-based transposition detection.

func (*Book) Size

func (b *Book) Size() int

Size returns the number of unique positions in the opening book.

type Classification

type Classification struct {
	// Opening is the identified opening. Nil if no known opening was found.
	Opening *Opening
	// Ply is the half-move depth at which the opening was identified.
	// For example, after 1.e4 e5 the ply is 2.
	Ply int
}

Classification is the result of identifying a game's opening.

type Opening

type Opening struct {
	// ECO is the Encyclopedia of Chess Openings classification code (e.g. "D01").
	ECO string
	// Name is the full opening name (e.g. "Rapport-Jobava System").
	Name string
	// PGN is the canonical move sequence in standard algebraic notation.
	PGN string
}

Opening represents a named chess opening position.

Directories

Path Synopsis
cmd
generate command
Command generate fetches the Lichess chess-openings database and produces a Go source file with pre-computed EPD positions and UCI move sequences.
Command generate fetches the Lichess chess-openings database and produces a Go source file with pre-computed EPD positions and UCI move sequences.
internal
epdutil
Package epdutil provides shared chess position and PGN parsing utilities used by both the openings library and the code generator (cmd/generate).
Package epdutil provides shared chess position and PGN parsing utilities used by both the openings library and the code generator (cmd/generate).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL