Topologies

The five spatial structures that underpin every board game in the engine.

The universal adapter

Topologies are the engine's defining architectural insight. Every package above topologies defines a contract (movement rays, adjacency, layout). Topologies implement that contract. The consuming package never knows which topology it's using.

This means a piece movement rule written for grid automatically works on hex if both implement the same traversal contract. New topologies auto-work with all existing higher packages.

Grid

Rectangular boards with cells addressed by algebraic notation (a1, b2, etc.).

Games: Chess, Draughts, Go, Xiangqi, Shogi, Reversi, Tafl, Halma, Dou Shou Qi, Fanorona, Surakarta, the Royal Game of Ur, Senet, Pachisi and Chaupar.

Layouts:

Coordinates: Algebraic — a1 (bottom-left) to h8 (top-right for 8x8).

topology:
  type: grid
  rows: 8
  cols: 8
  layout: cells    # or intersections, cross

Arcs: arcs joins pairs of edge points round the outside of the board, so a line that runs off one end carries on through it. Surakarta's eight loops are declared this way. Ordinary moves never use an arc; a capture declared as a rail does.

topology:
  type: grid
  rows: 6
  cols: 6
  layout: intersections
  arcs:
    - [[0, 1], [1, 0]]   # off the top at b6, back in along row 5

Hex

Hexagonal boards using axial coordinates (q, r).

Games: Hex, Y, Nukes, Glinski Chess, McCooey Chess, Hex Shogi.

Shapes:

Coordinates: Axial — q,r pairs (e.g. 0,0 is centre, 1,-1 is adjacent).

topology:
  type: hex
  shape: hexagonal
  radius: 5
  orientation: pointy   # or flat

Track

Linear or circuit paths with numbered positions.

Games: Backgammon and the Landlord's Game. The race games walk routes laid over their own boards instead; see Race Games.

Coordinates: Zero-indexed position numbers — 0 to positions-1.

topology:
  type: track
  positions: 24

Pit

Mancala-family sowing layouts with pits and optional stores.

Games: Kalah, Oware, Bao, Congkak, Pallanguzhi, Toguz Korgool, Sungka, Ayo.

Coordinates: pit-0 to pit-N (playing pits), store-0, store-1 (end stores).

topology:
  type: pit
  cols: 6          # pits per side
  rows: 2          # sides (default 2)
  stores: true     # end stores (default true)

Graph

Arbitrary node-edge structures for boards that aren't regular grids.

Games: Morris, Stern-Halma, Nyout and Asalto.

Structures:

Coordinates: Node IDs, numbered from one in the order the structure lays them out: n1, n2 and so on, or h1 to h121 for the star. Explicit node definitions may name their own. The star and the cross place their nodes on a lattice, so rays and jumps across them run straight.

topology:
  type: graph
  structure: concentric-rings
  params:
    rings: 3
    midpoints: true

Tableau

The table a card, tile or dice game is played on: hands, piles, a wall, a layout of cards. It has no cells to move between; the tableau plugin places components on it.

Games: every card, domino, mahjong and dice game. See Cards, Tiles and Dice.

Hexagonal trisection

A hexagon cut into three sectors, one per player, meeting at the centre. Each sector is two quadrilaterals of size by size, a half-board of 2 * size files by size ranks. Pieces stand in the cells (Yalta Chess) or where the lines cross (San-kwo-k'i).

Coordinates: sector, file and rank, each as its owner reads them: Ae2 is the first seat's e2, Be2 the second's.

topology:
  type: hexagonal-trisection

Triangular

A board of triangles, declared as a picture: one string per rank from the top, A for a triangle with its apex up, V apex down, . no cell. Sankaku Shogi's 44 triangles are its only board so far.

topology:
  type: triangular
  shape:
    - "..AVA.."
    - ".AVAVA."
    - "AVAVAVA"
    - "VAVAVAV"
    - "AVAVAVA"
    - "VAVAVAV"
    - ".VAVAV."
    - "..VAV.."

Registry

Topologies are registered at packages/topologies/registry.js. All 5 built-in types auto-register when packages/topologies/index.js is imported. Custom topologies can be added at runtime:

import { register } from 'packages/topologies/registry.js'

register('triangular', {
  factory: (config) => createTriangularTopology(config),
  schema: { type: 'triangular', required: ['sideLength'] }
})