Mancala

Six sow-and-capture variants on the pit topology, with bonus turns, relay sowing, and the same embed and SDK every family uses.

Embed via iframe

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=mancala&variant=kalah"
  style="width:100%;max-width:560px;aspect-ratio:2/1;border:none"
  title="Play Mancala"
></iframe>

URL parameters

ParamValuesDefault
embed1Required for embed mode
familymancalachess
variantAny variant key belowkalah
opponentai | humanai
difficultybeginner | easy | medium | hard | expertmedium
themeBoard theme idclassic

postMessage control

Commands accept either the generic game: prefix or the family prefix, so game:undo and mancala:undo both work.

iframe.contentWindow.postMessage({ type: 'game:setVariant', variant: 'oware' }, '*')
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' }, '*')

Events from embed

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
  }
})

Variants

All six variants from the moddable-rules Mancala hub are playable. Each is fully declared in frontmatter; the plugin holds no variant-specific code.

KeyPitsDistinguishing rule
kalah6 per sideCapture opposite pit; bonus turn when last seed lands in own store
oware6 per sideCapture from opponent's row when last seed makes 2 or 3; grand-slam protection
congkak7 per sideBonus turn on store landing; Malaysian variant
sungka7 per sideFilipino variant; simultaneous first sow
ayo6 per sideRelay sowing (continue from the pit the last seed lands in)
toguz-korgool9 per sideTuz capture (claim an opponent pit permanently)

Mechanics

The plugin handles sowing, capture, and store logic. All configuration arrives via frontmatter:

Config keyEffect
pitsPerSideNumber of pits each player owns (6, 7, or 9)
seedsPerPitStarting seeds in each pit
captureRuleWhen and how seeds are captured (opposite, count-based, relay)
bonusTurnOnStoreLast seed in own store earns another turn
relaySowingContinue sowing from the pit where the last seed landed

The game ends when one side is empty. Remaining seeds go to their owner's store. Most seeds wins.

SDK

import { createGame, createAI, listVariants } from 'moddable-engine/play'

listVariants('mancala')                       // [{ key, label, group, board }]
const game = createGame('mancala', 'kalah')
game.applyMove({ action: 'sow', pit: 2, to: 'pit-2' })

const ai = createAI('mancala', 'kalah', { difficulty: 'hard' })
ai.pickMove(game.getState().slice, 0)         // minimax with pit evaluation