npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pompidup/kingdomino-engine

v3.5.1

Published

A simple engine for the game Kingdomino

Readme

Kingdomino Engine

Node.js CI Branches Functions Lines Statements Coverage total

A TypeScript engine for the Kingdomino board game and its expansions.

Overview

This engine provides the core logic for Kingdomino: state management, rule enforcement, scoring, and turn flow. It is not a UI — consumers drive the game by calling engine methods and passing game state back in.

The engine is stateless: each method takes the current game state as input and returns a new game state. It is your responsibility to persist the state between calls.

Requirements

  • Node.js >= 20

Installation

npm install @pompidup/kingdomino-engine

Quick Start

import { createGameEngine, isGameWithNextAction } from "@pompidup/kingdomino-engine";

const engine = createGameEngine({});

// Create and set up a game
let game = engine.createGame({ mode: "Classic" });
game = engine.addPlayers({ game, players: ["Alice", "Bob"] });
game = engine.startGame({ game });

// Game loop
while (isGameWithNextAction(game)) {
  const { nextLord, nextAction } = game.nextAction;

  if (nextAction === "pickDomino") {
    const domino = game.currentDominoes.find((d) => !d.picked);
    if (domino) {
      game = engine.chooseDomino({ game, lordId: nextLord, dominoPick: domino.domino.number });
    }
  } else if (nextAction === "placeDomino") {
    const lord = game.lords.find((l) => l.id === nextLord);
    const player = game.players.find((p) => p.id === lord?.playerId);
    if (lord?.dominoPicked && player) {
      const placements = engine.getValidPlacements({ kingdom: player.kingdom, domino: lord.dominoPicked });
      if (placements.length > 0) {
        game = engine.placeDomino({ game, lordId: nextLord, position: placements[0].position, rotation: placements[0].rotation });
      } else {
        game = engine.discardDomino({ game, lordId: nextLord });
      }
    }
  } else {
    game = engine.discardDomino({ game, lordId: nextLord });
  }
}

const results = engine.getResults({ game });
console.log(results.result);

Game Modes

| Mode | Description | |------|-------------| | Classic | Original Kingdomino rules. 1-4 players, 5x5 kingdom, terrain-based scoring. | | QueenDomino | Full Queendomino expansion with buildings, coins, knights, the Queen and the Dragon. | | KingdominoOrigins-Discovery | Origins expansion — volcanoes, fire tokens, fire-based scoring. | | KingdominoOrigins-Totem | Origins — Discovery + wooden resources + totem majority tiles. | | KingdominoOrigins-Tribe | Origins — Discovery + resources + cave board + cavemen recruitment. | | AgeOfGiants | Age of Giants extension — giants, quest tiles, 5-player support, 12 new dominos on Classic. | | AgeOfGiants-QueenDomino | Age of Giants combined with QueenDomino. |

let game = engine.createGame({ mode: "Classic" });
let game = engine.createGame({ mode: "QueenDomino" });
let game = engine.createGame({ mode: "KingdominoOrigins-Discovery" });
let game = engine.createGame({ mode: "AgeOfGiants" });

See Game Modes for rules, player counts, and extra rules details.

Queendomino

The QueenDomino mode adds significant new mechanics to the base game:

  • Construction squares on some domino tiles where buildings can be placed
  • Coins (7 starting) used to purchase buildings or use the Dragon
  • Knights (max 3) placed on dominos to collect tax from construction squares
  • Buildings (18 types) purchased from the Builders Board, granting crowns, towers, and end-game bonuses
  • The Queen goes to the player with the most towers, granting +1 crown to the best territory
  • The Dragon burns a building tile from the Builders Board

The turn flow is extended with optional actions after placing a domino:

placeDomino → placeKnight → constructBuilding → useDragon → pickDomino
               (optional)      (optional)         (optional)
// Handle QueenDomino optional actions in your game loop
if (nextAction === "placeKnight" || nextAction === "constructBuilding" || nextAction === "useDragon") {
  game = engine.skipOptionalAction({ game, lordId: nextLord });
}

See Queendomino Guide for the complete rules, building list, and game loop example.

Kingdomino Origins

Origins introduces prehistoric terrains and fire-based scoring across three modes:

  • Discovery: Volcanoes provide fire tokens. Scoring = region size × fire symbols.
  • Totem: Discovery + wooden resources + totem majority tiles for bonus points.
  • Tribe: Discovery + resources + cave board with 22 cavemen to recruit.
if (nextAction === "placeFireToken") {
  game = engine.placeFireToken({ game, lordId: nextLord, position });
}
if (nextAction === "recruitCaveman") {
  game = engine.recruitCaveman({ game, lordId: nextLord, cavemanId, position, resourcePositions });
}

See Origins Guide for the complete rules and mechanics.

Age of Giants

Age of Giants extends Classic (or QueenDomino) with giants, quest tiles, and 5-player support:

  • 60 dominos (48 original + 12 new with giant/footprint symbols)
  • Giants cover crowns on your kingdom, reducing opponents' scores
  • Quest tiles (2 per game) provide end-game bonus scoring conditions
  • 5-player support with 5 dominos revealed per turn
if (nextAction === "placeGiant") {
  game = engine.placeGiant({ game, lordId: nextLord, position });
}
if (nextAction === "sendGiant") {
  game = engine.sendGiant({ game, lordId: nextLord, giantIndex, targetPlayerId, targetCrownPosition });
}

See Age of Giants Guide for the complete rules and mechanics.

Extra Rules

| Rule | Description | Restriction | |------|-------------|-------------| | The Middle Kingdom | +10 points if castle is centered | — | | Harmony | +5 points if no dominos were discarded | — | | The Mighty Duel | All 48 dominos, 7x7 kingdom | 2 players only | | Dynasty | Play 3 games, highest total wins | — |

game = engine.addExtraRules({ game, extraRules: ["The middle Kingdom", "Harmony"] });

// Dynasty: aggregate results from multiple games
const dynastyResults = engine.getDynastyResults({ games: [game1, game2, game3] });

See Game Modes for details.

Engine Options

const engine = createGameEngine({
  logging: true,                          // Console logging
  logger: { info: console.log, error: console.error },  // Custom logger
  shuffleMethod: (arr) => arr,            // Custom shuffle (e.g. no-op for testing)
  uuidMethod: () => "custom-uuid",        // Custom UUID generator
  events: { onGameEnd: () => {} },        // Event callbacks
  debug: true,                            // Debug mode
});

API Overview

Core Methods

| Method | Description | |--------|-------------| | getModes | Get available game modes | | createGame | Create a new game | | addPlayers | Add 1-4 players | | addExtraRules | Add optional extra rules | | startGame | Start the game | | chooseDomino | Pick a domino from the revealed set | | placeDomino | Place a domino on the kingdom | | discardDomino | Discard when no valid placement exists | | getResults | Get final rankings and scores | | calculateScore | Calculate score for any kingdom | | getValidPlacements | Find all valid placements for a domino | | canPlaceDomino | Check if any placement exists | | serialize / deserialize | Save and restore game state | | getDynastyResults | Aggregate scores from multiple games |

Queendomino Methods

| Method | Description | |--------|-------------| | placeKnight | Place a knight and collect tax | | constructBuilding | Buy and place a building | | useDragon | Destroy a building tile from the board | | skipOptionalAction | Skip the current optional action |

Origins Methods

| Method | Description | |--------|-------------| | placeFireToken | Place a fire token after placing a volcano domino | | recruitCaveman | Recruit a caveman from the cave board (Tribe mode) |

Age of Giants Methods

| Method | Description | |--------|-------------| | placeGiant | Place a giant on a crown in your kingdom | | sendGiant | Send a giant to an opponent's kingdom |

See API Reference for complete method signatures, types, and error codes.

Additional Features

  • Bot / AI: 4 built-in strategies (randomStrategy, greedyStrategy, advancedStrategy, expertStrategy) with playBotTurn() helper
  • Mixed games: Human and bot players in the same game via bot: { strategyName } on player input
  • Undo / Redo: Snapshot-based history with createGameHistory(), pushState(), undo(), redo()
  • Action Log: Immutable log via wrapWithActionLog(engine) for replay with replayActions()
  • Events: Callbacks via EngineConfig.events (onDominoPlaced, onGameEnd, etc.)
  • Debug Mode: wrapWithDebug(engine) with 3 verbosity levels
  • Seeded games: Deterministic shuffle via createGame({ mode, seed: "my-seed" })
  • Serialization: serializeGame() / deserializeGame() and save points
  • WASM Build: pnpm build:wasm produces a WebAssembly module usable from any language

Documentation

| Document | Content | |----------|---------| | Game Modes | Modes, rules by player count, extra rules, game flow | | Queendomino Guide | Complete Queendomino rules, mechanics, and examples | | Origins Guide | Kingdomino Origins rules, fire tokens, resources, cavemen | | Age of Giants Guide | Age of Giants rules, giants, quest tiles, 5-player support | | API Reference | All methods, types, error codes, and utilities | | WASM Build | Cross-language usage via WebAssembly |

Development

pnpm install          # Install dependencies
pnpm test             # Run tests (watch mode)
pnpm test -- --run    # Run tests once
pnpm coverage         # Tests with coverage
pnpm typecheck        # Type check (tsc)
pnpm lint             # Lint (biome)
pnpm build            # Build (ESM to dist/)
pnpm build:wasm       # Build WASM module (requires javy)

Contributing

  1. Fork the repository
  2. Create a branch (git checkout -b feature/your-feature)
  3. Make changes with tests (pnpm test -- --run && pnpm typecheck)
  4. Open a Pull Request