Skip to main content
The Board class represents piece positions on a chess board, while Position and Chess classes manage complete game state including turn, castling rights, and move generation.

Board Class

The Board class stores piece positions using bitboards. It implements both ByRole<SquareSet> and ByColor<SquareSet>, allowing direct access to piece sets.
export class Board implements Iterable<[Square, Piece]>, ByRole<SquareSet>, ByColor<SquareSet> {
  occupied: SquareSet;  // All occupied squares
  promoted: SquareSet;  // Promoted pieces (for Crazyhouse)
  
  white: SquareSet;     // All white pieces
  black: SquareSet;     // All black pieces
  
  pawn: SquareSet;      // All pawns
  knight: SquareSet;    // All knights
  bishop: SquareSet;    // All bishops
  rook: SquareSet;      // All rooks
  queen: SquareSet;     // All queens
  king: SquareSet;      // All kings
}

Creating Boards

default

Create a board with the standard starting position:
static default(): Board
Example:
import { Board } from 'chessops';

const board = Board.default();
console.log(board.occupied.size());  // 32 pieces

empty

Create an empty board:
static empty(): Board
Example:
import { Board } from 'chessops';

const board = Board.empty();
console.log(board.occupied.isEmpty());  // true

reset and clear

Modify an existing board:
reset(): void  // Reset to starting position
clear(): void  // Remove all pieces

Querying Pieces

get

Get the piece at a specific square:
get(square: Square): Piece | undefined
Example:
import { Board, parseSquare } from 'chessops';

const board = Board.default();
const piece = board.get(parseSquare('e2')!);
console.log(piece);  // { role: 'pawn', color: 'white', promoted: false }

getColor and getRole

Get just the color or role at a square:
getColor(square: Square): Color | undefined
getRole(square: Square): Role | undefined
Example:
import { Board, parseSquare } from 'chessops';

const board = Board.default();
const e2 = parseSquare('e2')!;
console.log(board.getColor(e2));  // 'white'
console.log(board.getRole(e2));   // 'pawn'

has

Check if a square is occupied:
has(square: Square): boolean
Example:
import { Board, parseSquare } from 'chessops';

const board = Board.default();
console.log(board.has(parseSquare('e2')!));  // true
console.log(board.has(parseSquare('e4')!));  // false

Modifying the Board

set

Place a piece on a square, returning any piece that was replaced:
set(square: Square, piece: Piece): Piece | undefined
Example:
import { Board, parseSquare } from 'chessops';

const board = Board.empty();
board.set(parseSquare('e4')!, { role: 'knight', color: 'white' });
board.set(parseSquare('d5')!, { role: 'pawn', color: 'black' });

take

Remove and return the piece from a square:
take(square: Square): Piece | undefined
Example:
import { Board, parseSquare } from 'chessops';

const board = Board.default();
const piece = board.take(parseSquare('e2')!);
console.log(piece);  // { role: 'pawn', color: 'white', promoted: false }
console.log(board.has(parseSquare('e2')!));  // false

Accessing Piece Sets

pieces

Get all pieces of a specific color and role:
pieces(color: Color, role: Role): SquareSet
Example:
import { Board } from 'chessops';

const board = Board.default();
const whiteKnights = board.pieces('white', 'knight');
// SquareSet containing b1 and g1

Helper Methods

rooksAndQueens(): SquareSet
bishopsAndQueens(): SquareSet
steppers(): SquareSet       // Knights, pawns, and kings
sliders(): SquareSet        // Bishops, rooks, and queens
Example:
import { Board } from 'chessops';

const board = Board.default();
const sliders = board.sliders();
// All bishops, rooks, and queens

kingOf

Find the unique king of a color:
kingOf(color: Color): Square | undefined
Example:
import { Board, makeSquare } from 'chessops';

const board = Board.default();
const whiteKing = board.kingOf('white');
console.log(makeSquare(whiteKing!));  // 'e1'

Iteration

Boards are iterable over [square, piece] pairs:
*[Symbol.iterator](): Iterator<[Square, Piece]>
Example:
import { Board, makeSquare } from 'chessops';

const board = Board.default();
for (const [square, piece] of board) {
  console.log(`${piece.color} ${piece.role} on ${makeSquare(square)}`);
}

Cloning and Comparison

clone(): Board
Example:
import { Board, boardEquals } from 'chessops';

const board1 = Board.default();
const board2 = board1.clone();

console.log(boardEquals(board1, board2));  // true

Position Class

The abstract Position class extends Board with full game state including move generation and validation. The Chess class is the concrete implementation for standard chess.
export abstract class Position {
  board: Board;
  pockets: Material | undefined;  // For Crazyhouse
  turn: Color;
  castles: Castles;
  epSquare: Square | undefined;
  remainingChecks: RemainingChecks | undefined;  // For 3check
  halfmoves: number;
  fullmoves: number;

  protected constructor(readonly rules: Rules) {}
}

Position Properties

board
Board
required
The current board position
turn
Color
required
The side to move
castles
Castles
required
Castling rights and rook positions
epSquare
Square | undefined
En passant target square, if any
halfmoves
number
required
Halfmove clock for the 50-move rule
fullmoves
number
required
Full move number (starts at 1, increments after black’s move)
pockets
Material | undefined
Captured pieces available for drops (Crazyhouse only)
remainingChecks
RemainingChecks | undefined
Remaining checks until victory (3check variant only)

Chess Class

The Chess class is the standard implementation of Position for regular chess:
export class Chess extends Position {
  private constructor() {
    super('chess');
  }

  static default(): Chess
  static fromSetup(setup: Setup): Result<Chess, PositionError>
  clone(): Chess
}

Creating Positions

default

Create the standard starting position:
static default(): Chess
Example:
import { Chess } from 'chessops';

const pos = Chess.default();
console.log(pos.turn);       // 'white'
console.log(pos.fullmoves);  // 1

fromSetup

Create a position from a Setup object:
static fromSetup(setup: Setup): Result<Chess, PositionError>
Example:
import { Chess } from 'chessops';
import { parseFen } from 'chessops/fen';

const setup = parseFen('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1').unwrap();
const pos = Chess.fromSetup(setup).unwrap();
console.log(pos.turn);  // 'black'

Context

The ctx() method computes important position information:
ctx(): Context
king
Square | undefined
The square of the king to move
blockers
SquareSet
Pieces pinned to the king
checkers
SquareSet
Pieces giving check
variantEnd
boolean
Whether the variant-specific end condition is met
mustCapture
boolean
Whether all legal moves must be captures (antichess)
Example:
import { Chess } from 'chessops';

const pos = Chess.default();
const ctx = pos.ctx();

console.log(ctx.checkers.isEmpty());  // true (no check)
console.log(ctx.blockers.isEmpty());  // true (no pins)

Move Generation

dests

Get legal destination squares for a piece:
dests(square: Square, ctx?: Context): SquareSet
Example:
import { Chess, parseSquare, makeSquare } from 'chessops';

const pos = Chess.default();
const e2Dests = pos.dests(parseSquare('e2')!);

for (const dest of e2Dests) {
  console.log(makeSquare(dest));  // e3, e4
}

allDests

Get legal moves for all pieces of the side to move:
allDests(ctx?: Context): Map<Square, SquareSet>
Example:
import { Chess, makeSquare } from 'chessops';

const pos = Chess.default();
const allMoves = pos.allDests();

for (const [from, dests] of allMoves) {
  for (const to of dests) {
    console.log(`${makeSquare(from)}${makeSquare(to)}`);
  }
}

dropDests

Get legal drop squares (for Crazyhouse):
dropDests(ctx?: Context): SquareSet

Move Validation

isLegal

Check if a move is legal:
isLegal(move: Move, ctx?: Context): boolean
Example:
import { Chess, parseSquare } from 'chessops';

const pos = Chess.default();
const move = { from: parseSquare('e2')!, to: parseSquare('e4')! };

console.log(pos.isLegal(move));  // true

Position Queries

Game State

isCheck(): boolean
isCheckmate(ctx?: Context): boolean
isStalemate(ctx?: Context): boolean
isEnd(ctx?: Context): boolean
isInsufficientMaterial(): boolean
hasInsufficientMaterial(color: Color): boolean
Example:
import { Chess } from 'chessops';
import { parseFen } from 'chessops/fen';

const setup = parseFen('r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 3 3').unwrap();
const pos = Chess.fromSetup(setup).unwrap();

console.log(pos.isCheck());  // true

outcome

Get the game outcome:
outcome(ctx?: Context): Outcome | undefined
Example:
import { Chess } from 'chessops';

const pos = Chess.default();
const outcome = pos.outcome();

if (outcome) {
  if (outcome.winner) {
    console.log(`${outcome.winner} wins`);
  } else {
    console.log('Draw');
  }
} else {
  console.log('Game continues');
}

Making Moves

play

Make a move, mutating the position:
play(move: Move): void
Example:
import { Chess, parseSquare } from 'chessops';

const pos = Chess.default();
pos.play({ from: parseSquare('e2')!, to: parseSquare('e4')! });

console.log(pos.turn);  // 'black'
console.log(pos.fullmoves);  // 1

pos.play({ from: parseSquare('e7')!, to: parseSquare('e5')! });
console.log(pos.turn);  // 'white'
console.log(pos.fullmoves);  // 2

Conversion

toSetup

Convert position to a Setup object:
toSetup(): Setup
Example:
import { Chess } from 'chessops';
import { makeFen } from 'chessops/fen';

const pos = Chess.default();
pos.play({ from: parseSquare('e2')!, to: parseSquare('e4')! });

const setup = pos.toSetup();
const fen = makeFen(setup);
console.log(fen);
// rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1

clone

Create a deep copy:
clone(): Chess
Example:
import { Chess, parseSquare } from 'chessops';

const pos1 = Chess.default();
const pos2 = pos1.clone();

pos1.play({ from: parseSquare('e2')!, to: parseSquare('e4')! });

console.log(pos1.turn);  // 'black'
console.log(pos2.turn);  // 'white' (unchanged)

Build docs developers (and LLMs) love