Thirteen draughts variants with forced-capture chains, flying kings, a minimax opponent, and embed support.
<iframe
src="https://engine.moddable.games/play/?embed=1&family=draughts&variant=international"
style="width:100%;max-width:560px;aspect-ratio:1/1;border:none"
title="Play Draughts"
></iframe>
The parameters, commands and events are identical to every other family. See the Go page for the full table; substitute family=draughts.
Parameters follow the draughts hub in moddable-rules.
| Key | Board | Distinguishing rule |
|---|---|---|
english | 8×8 | Men capture forwards only, kings do not fly |
international | 10×10 | Flying kings, longest capture chain compulsory |
brazilian | 8×8 | International rules on the small board |
canadian | 12×12 | International rules, thirty pieces a side |
russian | 8×8 | Backward capture, mid-jump promotion, free choice |
pool | 8×8 | Russian rules, the US tournament standard |
german | 8×8 | Capture in all directions, no majority rule |
spanish | 8×8 | Majority rule, ties resolved in favour of the king |
czech | 8×8 | King captures take priority over man captures |
italian | 8×8 | Men may not capture kings |
turkish-draughts | 8×8 | Orthogonal movement across all sixty-four squares |
ghanaian | 10×10 | Reduced to one piece is a loss |
spantsiretti | 10×8 | Russian rules on a wider board |
A multi-jump is a sequence of moves, not one move. The plugin signals continueTurn after each jump, so the turn does not advance and the controller anchors selection to the jumping piece until the chain is exhausted.
ctrl.handleClick(from) // select
ctrl.handleClick(firstJump) // capture, turn does not pass
ctrl.getState().chainAnchor // the piece mid-chain
ctrl.handleClick(secondJump) // continue the same chain
While a chain is live the interaction model rejects clicks that would abandon it. Board state and turn order stay consistent because the core move pipeline, not the interface, owns the decision.
Every variant above is expressed through the plugin's parametric configuration, with no per-variant code:
| Parameter | Effect |
|---|---|
directions | diagonal or orthogonal movement and capture |
manCapture | forward or all |
forcedCapture | Captures are compulsory when available |
maximalCapture | The longest available chain must be taken |
majorityPrefersKing | Ties in chain length resolve to the king's capture |
kingCapturePriority | Any king capture outranks any man capture |
menCannotCaptureKings | Men may not jump kings |
flyingKings | Kings slide any distance along a line |
promotionDuring | Promotion mid-chain continues as a king |
removeImmediately | Captured pieces leave after each jump, not at the end |
loseOnSinglePiece | Being reduced to one piece is a loss |
The SDK is the same across every family; only the family key and the shape of a move differ.
import { createGame, getLegalMoves, getGameStatus, createAI, listVariants } from 'moddable-engine/play'
listVariants('draughts') // [{ key, label, group, board, description }]
const game = createGame('draughts', 'international')
game.getLegalMoves() // [{ from, to, captures: [...] }, ...]
game.applyMove({ from: 31, to: 22 })
getGameStatus('draughts', 'international', game.getState())
const ai = createAI('draughts', 'international', { difficulty: 'hard' })
ai.pickMove(game.getState().slice, 0) // minimax by default for draughts
Difficulty accepts beginner, easy, medium, hard and expert.
Because captures are compulsory in most variants, getLegalMoves already reflects the forced-capture and maximal-capture parameters — a quiet move simply will not be in the list when a capture is available. A multi-jump arrives as a sequence of separate moves rather than one move; see capture chains above, and drive it through the chain interaction model:
import { interactionModelFor } from 'moddable-engine/play'
const model = interactionModelFor('draughts') // the 'chain' model
model.handleClick(pos, ctx) // rejects clicks that abandon a live chain
Seven hub variants are not registered, each because it needs a mechanic the plugin does not model:
Each is named in UNSUPPORTED in the variant module with its reason, so the gap is visible in code rather than silently missing.