homeworlds
v0.9.0
Published
TypeScript rules engine for the Binary Homeworlds board game.
Readme
homeworlds
TypeScript rules engine for the Binary Homeworlds board game.
Install
npm install homeworldsFeatures
- Complete Binary Homeworlds rules enforcement
- Immutable state — every action returns a new state object
- Built-in validation —
validate.actionseparates checking from execution - O(1) undo/rewind — each action produces an
UndoRecordfor instant reversal - Isomorphic — runs in Node.js and the browser
- Zero config — no setup beyond install
Quick Example
import { create, performAction } from "homeworlds";
// Create initial state for two players
const state = create.state(["alice", "bob"]);
// Alice chooses her homeworld
const { err, state: s1, undo } = performAction(state, "CHOOSE_HOMEWORLD", {
player: "alice",
stars: [
create.star({ color: "YELLOW", size: 2 }),
create.star({ color: "RED", size: 3 }),
],
ships: [create.ship({ color: "GREEN", size: 3, owner: "alice" })],
});
if (err) {
console.error(err);
} else {
console.log(s1.board); // alice's homeworld system is on the board
}API Reference
create
Factory helpers for game entities and state.
create.state(players: [PlayerId, PlayerId]): State
Returns a fresh game state. players is a two-element tuple of player IDs — Binary Homeworlds is strictly a two-player game. The first element takes the first turn.
create.ship(args: Ship): Ship
Normalises and returns a Ship object. Generates an id if none is provided.
| Field | Type | Required |
|---------|------------|----------|
| color | Color | yes |
| size | Size | yes |
| owner | PlayerId | yes |
| id | string | no |
create.star(args: Star): Star
Normalises and returns a Star (a Piece without an owner).
| Field | Type | Required |
|---------|---------|----------|
| color | Color | yes |
| size | Size | yes |
| id | string| no |
create.system(args: System): System
Normalises and returns a System object.
validate.action(state, action, args)
Signature: validate.action(state: State, action: Action, args: ActionArgs): string | null
Checks whether action with args is legal in state. Returns an error message string if invalid, or null if the action is valid. Does not mutate state.
performAction(state, action, args)
Signature: performAction(state: State, action: Action, args: ActionArgs): PerformActionResult
Validates and executes an action. Returns a result object — state is never mutated.
interface PerformActionResult {
err: string | null; // null on success
state: State; // new state (or original state on error)
undo: UndoRecord | null; // use with undoAction to reverse
gameOver?: GameOver; // present when the game ends
}On error err is set, state is the original state, and undo is null.
undoAction(state, record)
Signature: undoAction(state: State, record: UndoRecord): State
Reverses a previously performed action using the UndoRecord returned by performAction. Returns the prior state. Does not validate — the caller is responsible for applying records in reverse order.
types
Re-exported TypeScript type definitions. Import types directly:
import { types } from "homeworlds";
// types.State, types.Action, types.Ship, etc.Or import from the package root with a type-only import:
import type { State, Action, ActionArgs } from "homeworlds";Types Reference
Color
type Color = "RED" | "GREEN" | "BLUE" | "YELLOW";Size
type Size = 1 | 2 | 3;Action
type Action =
| "ATTACK"
| "BUILD"
| "MOVE"
| "TRANSFORM"
| "CATASTROPHE"
| "CHOOSE_HOMEWORLD"
| "SACRIFICE_START"
| "SACRIFICE"
| "END_TURN"
| "PASS"
| "CONCEDE";Color-to-action mapping
| Color | Action | Effect |
|----------|-------------|-------------------------------------------|
| RED | ATTACK | Capture an opponent ship of smaller size |
| GREEN | BUILD | Place a new ship from the bank |
| YELLOW | MOVE | Move a ship to a connected system |
| BLUE | TRANSFORM | Change a ship's color to another in-system color |
ActionArgs
interface ActionArgs {
player: PlayerId;
from?: { id: string }; // MOVE — origin system
to?: System; // MOVE — destination system
ship?: { id: string }; // ATTACK, MOVE, TRANSFORM, SACRIFICE_START
system?: { id: string }; // ATTACK, BUILD, TRANSFORM, CATASTROPHE, SACRIFICE_START
color?: Color; // ATTACK, BUILD, TRANSFORM, CATASTROPHE, SACRIFICE
stars?: Star[]; // CHOOSE_HOMEWORLD
ships?: Ship[]; // CHOOSE_HOMEWORLD
}State
interface State {
bank: Bank; // remaining pieces per color
board: System[]; // all active systems
players: string[]; // ordered player list
activePlayer: number; // index into players
history: HistoryItem[]; // completed actions
turn?: Turn; // in-progress turn (sacrifice state, etc.)
gameOver?: GameOver; // present when game has ended
}GameOver
interface GameOver {
winner: string | null; // null on draw
reason: "homeworld_destroyed" | "no_ships_at_homeworld" | "concede" | "draw";
}License
MIT
