UNPKG

@ayshrj/ludo.js

Version:

A TypeScript-based headless Ludo game engine for simulating game logic, AI moves, and game state management.

138 lines (134 loc) 4.52 kB
import { EventEmitter } from 'events'; /** * The player colors we can have in Ludo. */ type Color = "red" | "green" | "yellow" | "blue"; /** * Represents a single cell on the 15x15 board. */ interface Block { redTrack?: number; greenTrack?: number; blueTrack?: number; yellowTrack?: number; isSafeZone?: boolean; isStartingPosition?: Color; isHome?: Color; isOnPathToFinalPosition?: Color; isFinalPosition?: Color; } /** * Stores positions of the 4 tokens for each color (0..56, or -1 if in "home") */ type TokenPositions = { [key in Color]: [number, number, number, number]; }; /** * The possible game states: */ type GameState = "playerHasToRollADice" | "playerHasToSelectAPosition" | "gameFinished"; /** * A snapshot of the game's state, emitted whenever changes occur. */ interface LudoGameState { turn: Color; tokenPositions: TokenPositions; ranking: Color[]; boardStatus: string; diceRoll: number | null; lastDiceRoll: number | null; gameState: GameState; players: Color[]; } /** * Generate initial position of the tokens */ declare function initializeTokenPosition(): TokenPositions; /** * The Ludo class extends EventEmitter so you can listen to "stateChange" events. */ declare class Ludo extends EventEmitter { private numberOfPlayers; /** The 15x15 board, with `Block` or `null` if not used. */ board: (Block | null)[][]; /** The positions of all tokens for each color. */ tokenPositions: TokenPositions; /** The color currently taking its turn. */ currentPiece: Color; /** Which colors have completely finished (all tokens at final), in order. */ ranking: Color[]; /** The current dice roll value, or null if not rolled yet. */ currentDiceRoll: number | null; /** The previous dice roll value (for reference in UI, etc.). */ lastDiceRoll: number | null; /** Token indices (0..3) that are valid to move with the current dice roll. */ validTokenIndices: number[]; /** Number of consecutive sixes rolled by the current player. */ currentConsecutiveSixes: number; /** Track length from index 0 to 56. */ readonly TRACK_LENGTH = 57; /** Indices on the track considered "safe" (cannot be captured). */ readonly safeZones: number[]; /** A status message about the current board state (e.g. "Blue captured a token"). */ currentBoardStatus: string; /** The overall game state. */ gameState: GameState; /** Color-specific paths for each player's tokens ([row, col] coordinates). */ colorPaths: Record<Color, [number, number][]>; /** The active player colors in this game (e.g. ["blue","red","green"]). */ players: Color[]; /** * Create a new Ludo game with the specified number of players (2..4). * Emits a "stateChange" event whenever the internal state changes. */ constructor(numberOfPlayers?: 2 | 3 | 4); /** * Emit the current state to all listeners of "stateChange". */ private emitStateChange; /** * Reset the entire board, token positions, ranking, etc. * Randomly selects which color starts. */ reset(): void; /** * Rotate (r,c) by 90/180/270 around center (7,7). */ private rotateCoord; /** * Roll the dice for the current player, if allowed. * Automatically checks for consecutive sixes & skip turn if needed. */ rollDiceForCurrentPiece(): number; /** * The user/bot picks which token to move (0..3), if valid. */ selectToken(tokenIndex: number): void; /** * Return valid token indices for a given dice roll. */ private getValidMoves; /** * Check if any opponent is on newPos. If so, capture them (send home). * Returns number of captures. */ private handleCollisions; /** * Proceed to the next player's turn, or end the game if all finished. */ private nextTurn; /** * Reset the current dice roll & valid token indices. Optionally clear lastDiceRoll. */ private resetTurnState; /** * Returns a snapshot of the current state, used by emitStateChange() or for UI. */ getCurrentState(): LudoGameState; /** * A basic AI heuristic for picking the best token to move given currentDiceRoll. * Returns -1 if no moves. */ bestMove(): number; } export { type Block, type Color, type GameState, Ludo, type LudoGameState, type TokenPositions, initializeTokenPosition };