Seven mill-formation variants on concentric-ring graph boards, with placement and movement phases, and the same embed and SDK every family uses.
Every game family shares one embed surface. Select the family and variant through the URL.
<iframe
src="https://engine.moddable.games/play/?embed=1&family=morris&variant=nine-mens-morris"
style="width:100%;max-width:560px;aspect-ratio:1/1;border:none"
title="Play Morris"
></iframe>
| Param | Values | Default |
|---|---|---|
embed | 1 | Required for embed mode |
family | morris | chess |
variant | Any variant key below | nine-mens-morris |
opponent | ai | human | ai |
difficulty | beginner | easy | medium | hard | expert | medium |
theme | Board theme id | classic |
Commands accept either the generic game: prefix or the family prefix, so game:undo and morris:undo both work.
iframe.contentWindow.postMessage({ type: 'game:setVariant', variant: 'lasker-morris' }, '*')
iframe.contentWindow.postMessage({ type: 'game:setDifficulty', difficulty: 'hard' }, '*')
iframe.contentWindow.postMessage({ type: 'game:newGame' }, '*')
iframe.contentWindow.postMessage({ type: 'game:undo' }, '*')
iframe.contentWindow.postMessage({ type: 'game:resign' }, '*')
iframe.contentWindow.postMessage({ type: 'game:requestState' }, '*')
window.addEventListener('message', (e) => {
switch (e.data.type) {
case 'game:ready': break // { family, variant, state }
case 'game:move': break // { move, state }
case 'game:status': break // { text, gameOver, family, variant }
case 'game:state': break // { state } in reply to requestState
}
})
All seven variants from the moddable-rules Morris hub are playable. Each is fully declared in frontmatter; the plugin holds no variant-specific code.
| Key | Board | Distinguishing rule |
|---|---|---|
nine-mens-morris | 3 concentric squares | 9 pieces each; place then move; mill removes one opponent piece |
six-mens-morris | 2 concentric squares | 6 pieces each; no placement phase (start on board) |
three-mens-morris | 1 square + centre | 3 pieces each; tic-tac-toe on a graph; first mill wins |
twelve-mens-morris | 4 concentric squares | 12 pieces each; diagonals on the outer ring |
lasker-morris | 3 concentric squares | 10 pieces each; may hop over an adjacent man |
morabaraba | 3 concentric squares | South African variant; diagonal connections |
shax | 3 concentric squares | 12 pieces each; Somali variant |
The plugin handles placement, movement, mill detection, and removal. All configuration arrives via frontmatter:
| Config key | Effect |
|---|---|
piecesPerPlayer | How many men each player places (3, 6, 9, 10, or 12) |
allowHop | Whether a man may hop over an adjacent man (Lasker) |
diagonals | Whether diagonal edges exist on the graph |
flyingWhenThree | A player reduced to 3 men may move to any empty node |
The game has two phases: placement (alternating until all men are down) and movement (slide along edges). Forming a mill (three in a row along an edge) lets the player remove one opponent piece. A player with fewer than 3 pieces or no legal moves loses.
import { createGame, createAI, listVariants } from 'moddable-engine/play'
listVariants('morris') // [{ key, label, group, board }]
const game = createGame('morris', 'nine-mens-morris')
game.applyMove({ action: 'place', to: 'n1' })
const ai = createAI('morris', 'nine-mens-morris', { difficulty: 'hard' })
ai.pickMove(game.getState().slice, 0) // minimax with mill evaluation