# ymir-js > ymir-js is a TypeScript toolkit for board games. It ships complete, tested rule engines for checkers (Turkish and International), chess, Go and match-3, built on a small generic `Board`/`Item` core that you can use for your own games. Zero runtime dependencies, ES module only, Node 20.19+ / 22.12+ or any modern bundler. Install only the packages you need and import named exports from them: `@ymir-js/core` for the board (`import { Board, Item } from '@ymir-js/core'`), plus `@ymir-js/checkers` (`CheckersGame`), `@ymir-js/chess` (`ChessGame`), `@ymir-js/go` (`GoGame`) or `@ymir-js/match3` (`Match3Board`). Each game package depends on `@ymir-js/core`. Existing code may import from the older all-in-one `ymir-js` package, kept for backward compatibility with the same names (and the grouped `Core`, `Checkers`, `Chess`, `Go`, `Match3`, `Utils` exports); use the scoped packages for new code. Things to know before writing code with it: - Coordinates are strings `"row|col"`, zero-based, row 0 at the top (e.g. `"3|4"`). Chess also accepts algebraic squares (`"e4"`); convert with `toSquare` / `fromSquare`. Go converts to GTP vertices with `board.toGTP` / `board.fromGTP`. - `new Board({ rows, cols })` creates a board; `getItem`, `setItem`, `moveItem`, `removeItem`, `switchItem`, `isEmpty`, `isExistCoord`, `getBoardMatrix`, plus `getNeighbors(coord, { diagonal })`, `getReachable(from, { steps, canEnter, diagonal })` (a Map of square → steps; `from` may be several squares, counting from the nearest) and `findPath(from, to, options)` for movement ranges and routes. `squares()` lists every square as `{ coord, row, col, item }`; `findCoord(predicate)`, `findCoords(predicate?)` and `countItems(predicate?)` search the items; `isEdge(coord)` tells the outer ring. `ray(coord, direction, steps?)` is the line of squares in one direction up to the edge (for sliding pieces, blasts, Reversi flips); `loadRows(rows, toItem)` / `toRows(toChar)` read and write a position as text rows. `clone()` copies the whole board (same class, nothing shared); `snapshot()` / `restore(snapshot)` save and put back the items, for undo. Items are copied with `cloneItem`: same class, plain objects and arrays copied deeply. Coord helpers: `toCoord(row, col)`, `parseCoord(coord)` → `[row, col]`, `stepCoord(coord, direction, steps?)`, `manhattan(a, b)`, and `DIRECTIONS` / `LINEAR_DIRECTIONS` / `ANGULAR_DIRECTIONS` / `DIRECTION_STEPS`. Methods are bound, so they can be passed as callbacks. Off-board coords are safe: `getItem` returns `null`, `isEmpty` returns `false`. - Each game has a "game" class that owns turns, history, undo and the result, and a board you can read: `CheckersGame` (+ `TurkishBoard`, `InternationalBoard`), `ChessGame` (+ `ChessBoard`), `GoGame` (+ `GoBoard`), and `Match3Board` (single-player, no game class). - Moves are validated: `play` / `move` throw on an illegal move. Ask first with `getLegalMoves()` (all games), `checkPlay` (Go) or `canSwap` (match-3). - Checkers, chess and Go report their state with `getStatus()` (playing, won, draw and why) and save and restore with `toJSON()` / `fromJSON()`. Match-3 has no end state of its own; `swap` reports points and `getPossibleMoves()` is never empty because the board reshuffles itself. - Built-in computer players: `checkersBoard.autoPlay(color, { onMove })` and `chessGame.getBestMove({ depth })`. - Rules follow the official sources: FMJD for International checkers (incl. 25-move and 16/5-move endgame draws), Turkish draughts (pieces removed one by one, no 180° king turn, "one piece each" draw), FIDE chess (perft-verified move generation), and standard Go (simple or positional superko, area or territory scoring). ## Docs - [README](https://github.com/aykutkardas/ymir-js/blob/main/README.md): install, the core board API, and a section per game with examples and rule tables. - [Full reference](https://aykutkardas.github.io/ymir-js/llms-full.txt): the README plus every public type declaration, in one plain-text file. ## Games - [Checkers](https://github.com/aykutkardas/ymir-js/blob/main/packages/checkers/src/board.ts): `TurkishBoard` / `InternationalBoard` with `getLegalMoves(color)` (mandatory and maximum capture, full capture chains), `playMove(move)`, `autoPlay`; moves are `{ from, path, captured }`. - [Checkers game](https://github.com/aykutkardas/ymir-js/blob/main/packages/checkers/src/game.ts): `CheckersGame.create('turkish' | 'international')`, `play`, `undo`, `redo`, `getStatus()` (win, repetition, king-move and lone-king draws), `toJSON`. - [International notation](https://github.com/aykutkardas/ymir-js/blob/main/packages/checkers/src/international/notation.ts): PDN FEN (`toFEN`, `setFEN`) and moves (`32-28`, `28x19x8`). - [Chess](https://github.com/aykutkardas/ymir-js/blob/main/packages/chess/src/game.ts): `new ChessGame(fen?)`, `move('Nf3' | 'g1f3' | { from, to, promotion })`, `getLegalMoves(square?)`, `getStatus()`, `fen()`, `pgn()`, `undo()`, `getBestMove({ depth })`, `perft(depth)`. - [Go](https://github.com/aykutkardas/ymir-js/blob/main/packages/go/src/game.ts): `new GoGame({ size, rules, komi, ko, setup })`, `play(coord)`, `checkPlay`, `pass`, `resign`, `koPoint`, `captures`, after two passes `toggleDead` and `getScore()`. - [Go board](https://github.com/aykutkardas/ymir-js/blob/main/packages/go/src/board.ts): groups, liberties, captures, scoring, GTP coordinates. - [Match 3](https://github.com/aykutkardas/ymir-js/blob/main/packages/match3/src/board.ts): `new Match3Board({ rows, cols, kinds, random }).init()`, `swap(from, to)` returns every cascade step (`matches`, `cleared`, `fallen`, `spawned`, `points`), `getPossibleMoves()`, `shuffle()`. - [Core board](https://github.com/aykutkardas/ymir-js/blob/main/packages/core/src/board.ts): the generic `Board` every game builds on. ## Live examples - [Checkers](https://aykutkardas.github.io/ymir-js/examples/checkers/): Turkish and International against the computer, with undo. [Source](https://github.com/aykutkardas/ymir-js/tree/main/examples/checkers) - [Chess](https://aykutkardas.github.io/ymir-js/examples/chess/): against the built-in engine at three levels, or two players. [Source](https://github.com/aykutkardas/ymir-js/tree/main/examples/chess) - [Go](https://aykutkardas.github.io/ymir-js/examples/go/): 9×9, 13×13 and 19×19, with scoring. [Source](https://github.com/aykutkardas/ymir-js/tree/main/examples/go) - [Match 3](https://aykutkardas.github.io/ymir-js/examples/match3/): a 20-move puzzle with cascades and hints. [Source](https://github.com/aykutkardas/ymir-js/tree/main/examples/match3) ## Custom games (built on the core) These are not part of the library; each example writes its own rules on `Board` and `Item` and is meant to be read as a tutorial for building a new game. - [Hnefatafl rules](https://github.com/aykutkardas/ymir-js/blob/main/examples/hnefatafl/src/rules.ts): Copenhagen Hnefatafl (Viking chess) on the core: a `Piece extends Item` with `{ linear: true }` movement, `getColumnsByDirection` for moves, sandwich and shieldwall captures, king capture, exit fort and encirclement checks, and a `TaflGame` with undo. [Play](https://aykutkardas.github.io/ymir-js/examples/hnefatafl/) - [Sokoban rules](https://github.com/aykutkardas/ymir-js/blob/main/examples/sokoban/src/rules.ts): walls, boxes and the player as items; a push uses `getColumnsByDirection(player, { [direction]: true, stepCount: 2 })` for the next two squares and two `moveItem` calls; levels in the standard text format (`#@$.*+`); undo and a breadth-first solver. [Play](https://aykutkardas.github.io/ymir-js/examples/sokoban/) - [Tactics rules](https://github.com/aykutkardas/ymir-js/blob/main/examples/tactics/src/rules.ts): a turn-based battle; units are `Item` with typed stats in `data`; movement ranges from `getReachable` with a `canEnter` that walks through allies and around rocks; `findPath` for the walking animation; counter-attacks; a simple AI in `ai.ts`. [Play](https://aykutkardas.github.io/ymir-js/examples/tactics/) - [Reversi rules](https://github.com/aykutkardas/ymir-js/blob/main/examples/reversi/src/rules.ts): discs are items; the flips for a square come from `getColumnsByDirection(coord, { linear: true, angular: true, stepCount: 7 })` (all eight lines); passing, game end, undo; an alpha-beta player in `ai.ts`. [Play](https://aykutkardas.github.io/ymir-js/examples/reversi/) - [Invaders rules](https://github.com/aykutkardas/ymir-js/blob/main/examples/invaders/src/rules.ts): a real-time Invaders-style shooter on the core; invaders and shields are `Item`; the formation marches with `moveItem` (leading invaders first) and steps down at the edges; shooters are the invaders with nothing below them, from `getColumnsByDirection(coord, { bottom: true, stepCount })`; `tick(ms)`, seeded. [Play](https://aykutkardas.github.io/ymir-js/examples/invaders/) - [Bomberman rules](https://github.com/aykutkardas/ymir-js/blob/main/examples/bomberman/src/rules.ts): a real-time game on the core; walls, crates, bombs and power-ups are `Item`; a blast is `getColumnsByDirection(coord, { linear: true, stepCount: range })` cut at walls and at the first crate or bomb (chain reactions); enemies chase with `findPath`; the game advances with `tick(ms)` and is seeded, so it can be tested and replayed. [Play](https://aykutkardas.github.io/ymir-js/examples/bomberman/) ## Optional - [Tests](https://github.com/aykutkardas/ymir-js/tree/main/packages): `*.spec.ts` next to each module show exact expected behaviour, including perft counts for chess. - [npm package](https://www.npmjs.com/package/ymir-js) - [Source repository](https://github.com/aykutkardas/ymir-js)