npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

draughts

v0.2.1

Published

A javascript draughts library for move generation/validation, piece placement/movement and draw detection

Readme

draughts.js

A modern ES6 JavaScript draughts (checkers) library for move generation/validation, piece placement/movement, and draw detection - basically everything but the AI.

Inspired by chess.js

Features

  • ES6+ Modern JavaScript with comprehensive JSDoc type annotations
  • Full draughts/checkers game logic including captures, promotions, and game ending conditions
  • FEN notation support for position loading and saving
  • PDN (Portable Draughts Notation) for game import/export
  • Move validation and legal move generation
  • TypeScript-friendly with detailed JSDoc types
  • Node.js and Browser compatible

Installation

Browser

<script src="path/to/draughts.js"></script>

Node.js

npm install draughts
const Draughts = require('draughts');
// or import Draughts from 'draughts'; // ES6 modules

Quick Start

// Create a new game
const game = new Draughts();

// Play a random game
while (!game.gameOver()) {
  const moves = game.moves();
  const randomMove = moves[Math.floor(Math.random() * moves.length)];
  game.move(randomMove);
}

console.log('Game over!');
console.log('Final position:', game.fen());
console.log('Game notation:', game.pdn());

API Reference

Constructor

new Draughts([fen])

Creates a new draughts game instance.

// Start with default position
const game = new Draughts();

// Load a specific position using FEN
const game = new Draughts('W:W31-50:B1-20');

Parameters:

  • fen (string, optional): FEN string to initialize the board position

Game State Methods

.gameOver()

Returns true if the game has ended (no legal moves or no pieces remaining).

const game = new Draughts();
console.log(game.gameOver()); // false

.turn()

Returns the current player's turn as a lowercase string.

const game = new Draughts();
console.log(game.turn()); // 'w' (white to move)

.inDraw()

Returns true if the game is drawn. (Currently always returns false - TODO)

console.log(game.inDraw()); // false

Move Generation and Validation

.moves([square])

Returns an array of legal moves for the current position.

const game = new Draughts();
const moves = game.moves();
console.log(moves.length); // Number of legal moves

// Get moves for a specific square
const squareMoves = game.moves(35);

.getLegalMoves(square)

Returns legal moves from a specific square.

const game = new Draughts();
const moves = game.getLegalMoves(35);
console.log(moves);
// [
//   { jumps: [], takes: [], from: 35, to: 30, piecesTaken: undefined },
//   { jumps: [], takes: [], from: 35, to: 31, piecesTaken: undefined }
// ]

.move(moveObject)

⚠️ API Change: Now requires move object instead of string!

Attempts to make a move. Returns the move object if legal, false otherwise.

const game = new Draughts();

// ✅ Correct - Use move object
const result = game.move({ from: 35, to: 30 });
console.log(result);
// { jumps: [], takes: [], from: 35, to: 30, flags: 'n', piece: 'w' }

// ❌ Old string format no longer works
// game.move('35-30'); // Returns false

Parameters:

  • moveObject (object): Move object with from and to properties
    • from (number): Source square (1-50)
    • to (number): Destination square (1-50)

Board Manipulation

.get(square)

Returns the piece at the given square.

const game = new Draughts();
console.log(game.get(35)); // 'w' (white piece)
console.log(game.get(25)); // '0' (empty square)

.put(piece, square)

Places a piece on the board.

game.clear();
game.put('w', 35); // Place white piece on square 35
console.log(game.get(35)); // 'w'

Parameters:

  • piece (string): Piece type ('b', 'B', 'w', 'W')
  • square (number): Target square (1-50)

.remove(square)

Removes and returns the piece at the given square.

const piece = game.remove(35);
console.log(piece); // 'w'
console.log(game.get(35)); // '0'

.clear()

Clears the board to the starting position.

game.clear();

.reset()

Resets the game to the initial starting position.

game.reset();

Position and Notation

.fen()

Returns the current position in FEN (Forsyth-Edwards Notation).

const game = new Draughts();
console.log(game.fen());
// 'W:W31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50:B1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20'

.load(fen)

Loads a position from a FEN string.

const success = game.load('W:W31-50:B1-20');
console.log(success); // true if loaded successfully

.validate_fen(fen)

Validates a FEN string without loading it.

const result = game.validate_fen('W:W31-50:B1-20');
console.log(result);
// { valid: true, error_number: 0, error: { code: 0, message: 'no errors' } }

.ascii([unicode])

Returns an ASCII representation of the board.

const game = new Draughts();
console.log(game.ascii());
// +-------------------------------+
// |     b   b   b   b   b         |
// |   b   b   b   b   b           |
// |     b   b   b   b   b         |
// |   b   b   b   b   b           |
// |     0   0   0   0   0         |
// |   0   0   0   0   0           |
// |     w   w   w   w   w         |
// |   w   w   w   w   w           |
// |     w   w   w   w   w         |
// |   w   w   w   w   w           |
// +-------------------------------+

// Use Unicode symbols
console.log(game.ascii(true)); // Uses ♠, ♥, etc. symbols

Game History

.history([options])

Returns the move history.

const game = new Draughts();
game.move({ from: 35, to: 30 });
game.move({ from: 19, to: 23 });

console.log(game.history());
// ['35-30', '19-23']

// Get verbose history with detailed move objects
console.log(game.history({ verbose: true }));
// [{ from: 35, to: 30, flags: 'n', piece: 'w', moveNumber: 1 }, ...]

.undo()

Undoes the last move.

const game = new Draughts();
const originalFen = game.fen();

game.move({ from: 35, to: 30 });
const undoneMove = game.undo();

console.log(game.fen() === originalFen); // true
console.log(undoneMove); // The move that was undone

PDN (Portable Draughts Notation)

.header([key, value, ...])

Sets or gets PDN header information.

// Set headers
game.header('White', 'Alice', 'Black', 'Bob', 'Date', '2024-01-01');

// Get headers
console.log(game.header());
// { White: 'Alice', Black: 'Bob', Date: '2024-01-01' }

.pdn([options])

Exports the game in PDN format.

const game = new Draughts();
game.header('White', 'Alice', 'Black', 'Bob');
game.move({ from: 35, to: 30 });
game.move({ from: 19, to: 23 });

console.log(game.pdn());
// [White "Alice"]
// [Black "Bob"]
//
// 1. 35-30 19-23

Options:

  • maxWidth (number): Maximum line width for formatting
  • newline_char (string): Character to use for line breaks (default: '\n')

.parsePDN(pdn, [options])

Loads a game from PDN notation.

const pdn = `
[White "Alice"]
[Black "Bob"]
[Result "1-0"]

1. 35-30 19-23 2. 30-25 20-24
`;

const success = game.parsePDN(pdn);
console.log(success); // true if parsed successfully

Utility Methods

.captures()

Returns all possible capture moves for the current player.

const captures = game.captures();
console.log(captures); // Array of capture move objects

.perft(depth)

Performance test function - counts total positions at given depth.

const nodeCount = game.perft(3);
console.log(`Positions at depth 3: ${nodeCount}`);

TypeScript Support

The library includes comprehensive JSDoc type annotations for excellent TypeScript support:

interface MoveObject {
  from: number;           // Source square (1-50)
  to: number;             // Destination square (1-50)
  flags: string;          // Move flags: 'n', 'c', 'p'
  piece: string;          // Moving piece: 'b', 'B', 'w', 'W'
  takes?: number[];       // Captured piece positions
  jumps?: number[];       // Jump sequence positions
  piecesTaken?: string[]; // Captured piece types
}

interface ValidationResult {
  valid: boolean;
  error?: {
    code: number;
    message: string;
  };
  fen: string;
}

Examples

Basic Game Loop

const game = new Draughts();

while (!game.gameOver()) {
  const moves = game.moves();
  
  if (moves.length === 0) break;
  
  // Make a random move
  const randomMove = moves[Math.floor(Math.random() * moves.length)];
  const result = game.move(randomMove);
  
  if (result) {
    console.log(`Move: ${result.from}-${result.to}`);
  }
}

console.log('Final position:', game.fen());

Loading and Analyzing Positions

// Load a specific position
const game = new Draughts('B:W31,32,33,34,35,36,37,38,39,40:B11,12,13,14,15,16,17,18,19,20');

console.log('Current turn:', game.turn());
console.log('Legal moves:', game.moves().length);
console.log('Captures available:', game.captures().length);

// Show the board
console.log(game.ascii());

Working with PDN

const game = new Draughts();

// Set up game metadata
game.header('Event', 'Friendly Match');
game.header('White', 'Player 1');
game.header('Black', 'Player 2');
game.header('Date', '2024-01-01');

// Play some moves
game.move({ from: 35, to: 30 });
game.move({ from: 19, to: 23 });
game.move({ from: 32, to: 28 });

// Export as PDN
console.log(game.pdn());

Browser Compatibility

Works in all modern browsers that support ES6 features:

  • Chrome 51+
  • Firefox 54+
  • Safari 10+
  • Edge 15+

For older browsers, use a transpiler like Babel.

Sites Using draughts.js

Need a user interface? Try the draughtsboardJS library.

Maintainers

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MPL-2.0 License.