labyrinth-game-logic
Version:
A libary that implements the boardgame labyrinth and exposes the functionality to create and interact with games
444 lines (413 loc) • 13.9 kB
text/typescript
/**
* @author Timo Lehnertz
*/
/**
* Immutable Vec2 class
*/
declare class Vec2 {
readonly x: number;
readonly y: number;
constructor(x: number, y: number);
equals(other: Vec2): boolean;
add(b: Vec2): Vec2;
subtract(b: Vec2): Vec2;
multiply(scalar: number): Vec2;
distanceFrom(other: Vec2): number;
manhattanDistanceFrom(other: Vec2): number;
get length(): number;
setX(x: number): Vec2;
setY(y: number): Vec2;
}
/**
* @author Timo Lehnertz
*/
/**
* Immutable BoardPosition class representing a location on the board
* (0|0) is in the top left corner (Northwest)
*/
declare class BoardPosition extends Vec2 {
isInBounds(width: number, height: number): boolean;
isEdge(width: number, height: number): boolean;
add(b: Vec2): BoardPosition;
static create(instance: BoardPosition): BoardPosition;
setX(x: number): BoardPosition;
setY(y: number): BoardPosition;
}
/**
* @author Timo lehnertz
*/
/**
* Immutable Treasure class representing a treasure
*/
declare class Treasure {
readonly id: number;
constructor(id: number);
equals(other: Treasure): boolean;
static compare(a: Treasure | null, b: Treasure | null): boolean;
static create(instance: Treasure): Treasure;
}
/**
* @author Timo Lehnertz
*/
/**
* Immutable Playerstate class containing all information about a player.
* Only publicly exposes the information that other players and the player itself can legaly know
*/
declare class PlayerState {
private readonly foundTreasures;
private readonly remainingTreasures;
readonly currentTreasure: Treasure | null;
readonly position: BoardPosition;
constructor(foundTreasures: Treasure[], remainingTreasures: Treasure[], currentTreasure: Treasure | null, position: BoardPosition);
/**
* Returns the number of remaining treasures to be found including the currently open treasure
*/
get remainingTreasureCount(): number;
get lastFoundTreasure(): Treasure | null;
get foundTreasureCount(): number;
getFoundTreasure(index: number): Treasure;
setPosition(newPosition: BoardPosition): PlayerState;
collectTreasure(treasure: Treasure): PlayerState;
removeLastTreasure(): PlayerState;
/**
* Treasures are immutable so we dont need to make a deep copy here
*/
private copyFoundTreasures;
/**
* Treasures are immutable so we dont need to make a deep copy here
*/
private copyRemainingTreasures;
equals(other: PlayerState): boolean;
static create(instance: PlayerState): PlayerState;
}
/**
* @author Timo Lehnertz
*/
/**
* Immutable AllPlayerStates class containing the states of all players
*/
declare class AllPlayerStates {
private readonly allPlayerStates;
readonly playerIndexToMove: number;
constructor(allPlayerStates: PlayerState[], playerIndexToMove: number);
get playerCount(): number;
getPlayerPositions(): BoardPosition[];
private copyPlayerStates;
collectTreasure(playerIndex: number, foundTreasure: Treasure): AllPlayerStates;
removeLastTreasure(playerIndex: number): AllPlayerStates;
mutateAll(mutationCallback: (playerState: PlayerState) => PlayerState): AllPlayerStates;
movePlayer(playerIndex: number, to: BoardPosition): AllPlayerStates;
getPlayerToMoveState(): PlayerState;
getPlayerState(playerIndex: number): PlayerState;
nextPlayer(): AllPlayerStates;
prevPlayer(): AllPlayerStates;
getPlayerStatesWithAllTreasures(): {
playerIndex: number;
playerState: PlayerState;
}[];
equals(other: AllPlayerStates): boolean;
static create(instance: AllPlayerStates): AllPlayerStates;
}
/**
* @author Timo lehnertz
*/
declare enum Heading {
NORTH = 0,
EAST = 1,
SOUTH = 2,
WEST = 3
}
declare class HeadingHelper {
readonly heading: Heading;
constructor(heading: Heading);
static getAllHeadings(): Heading[];
get inverted(): Heading;
get vec2(): Vec2;
}
/**
* @author Timo Lehnertz
*/
interface PathPart {
from: BoardPosition;
to: BoardPosition;
heading: Heading;
}
/**
* Mutable Path class representing a path from one field to another
*/
declare class Path {
readonly parts: PathPart[];
constructor(parts: PathPart[]);
getHeadings(position: BoardPosition): Heading[];
get length(): number;
getPart(index: number): PathPart;
}
/**
* @author Timo Lehnertz
*/
/**
* Immutable ShiftPosition class representing a unique way of shifting on a board
*/
declare class ShiftPosition {
readonly heading: Heading;
readonly index: number;
constructor(heading: Heading, index: number);
get shiftVector(): Vec2;
static create(instance: ShiftPosition): ShiftPosition;
equals(other: ShiftPosition): boolean;
private static checkOverflow;
shiftPlayer(playerPosition: BoardPosition, width: number, height: number): BoardPosition;
}
/**
* @author Timo Lehnertz
*/
/**
* Immutable OpenSides class representing the open sides of a tile
*/
declare class OpenSides {
readonly northOpen: boolean;
readonly eastOpen: boolean;
readonly southOpen: boolean;
readonly westOpen: boolean;
constructor(tileType: TileType, rotation: number);
isOpposingOpen(heading: Heading): boolean;
get headings(): Heading[];
}
/**
* @author Timo lehnertz
*/
declare enum TileType {
STREIGHT = 0,
L = 1,
T = 2
}
/**
* Immutable Tile class representing a single tile
*/
declare class PathTile {
/**
* Key
*/
readonly tileType: TileType;
readonly treasure: Treasure | null;
readonly rotation: number;
readonly homeOfPlayerIndex: number | null;
constructor(tileType: TileType, treasure: Treasure | null, rotation: number, homeOfPlayerIndex: number | null);
get openSides(): OpenSides;
private static normalizeRotation;
rotate(repeat: number): PathTile;
setHomeOfPlayerIndex(homeOfPlayerIndex: number): PathTile;
setTreasure(treasure: Treasure | null): PathTile;
equals(other: PathTile): boolean;
static create(instance: PathTile): PathTile;
}
/**
* @author Timo lehnertz
*/
/**
* Immutable Board class representing the gameboard.
*/
declare class Board {
private tiles;
readonly looseTile: PathTile;
readonly shiftPosition: ShiftPosition;
readonly width: number;
readonly height: number;
/**
* @param tiles Must a quadratic array
* @param looseTile the tile that is currently free
*/
constructor(tiles: PathTile[][], looseTile: PathTile, shiftPosition: ShiftPosition);
insertLooseTile(): Board;
generateDistances(from: BoardPosition): number[][];
generateShortestPath(from: BoardPosition, to: BoardPosition): Path | null;
getReachablePositions(from: BoardPosition): BoardPosition[];
isReachable(from: BoardPosition, to: BoardPosition): boolean;
rotateLooseTile(rotateBeforeShift: number): Board;
static getValidSizes(maxSize: number): number[];
/**
* @param size Width or height
*/
static isSizeValid(size: number): boolean;
static getMaxPlayerCount(width: number, height: number): number;
static getHomePositionIncrement(size: number): number;
static generatePlayerHomePositions(width: number, height: number): BoardPosition[];
static getPlayerHomePosition(playerIndex: number, width: number, height: number): BoardPosition;
generateValidShiftPositions(): ShiftPosition[];
private static getShiftPositionCount;
isShiftPositionValid(shiftPosition: ShiftPosition): boolean;
invertShiftPosition(shiftPosition: ShiftPosition): ShiftPosition;
getLastMovedTilePosition(shiftPosition: ShiftPosition): BoardPosition;
getFirstMovedTilePosition(shiftPosition: ShiftPosition): BoardPosition;
setShiftPosition(shiftPosition: ShiftPosition): Board;
/**
* Because Tile is immutable we dont need to make a deep copy here
*/
private copyTiles;
getTile(position: BoardPosition): PathTile;
getTreasureAt(position: BoardPosition): Treasure | null;
equals(other: Board): boolean;
static create(instance: Board): Board;
}
/**
* @author Timo lehnertz
*/
/**
* Immutable Move class representing a move in the game
*/
declare class Move {
readonly playerIndex: number;
readonly rotateBeforeShift: number;
readonly fromShiftPosition: ShiftPosition;
readonly toShiftPosition: ShiftPosition;
readonly from: BoardPosition;
readonly to: BoardPosition;
readonly collectedTreasure: Treasure | null;
constructor(playerIndex: number, rotateBeforeShift: number, fromShiftPosition: ShiftPosition, toShiftPosition: ShiftPosition, from: BoardPosition, to: BoardPosition, collectedTreasure: Treasure | null);
static create(instance: Move): Move;
equals(other: Move): boolean;
}
/**
* Immutable Cyrb64 Hash class using the
*/
declare class Cyrb64 {
private readonly a;
private readonly b;
constructor(a: number, b: number);
static hashString(str: string, seed: number): Cyrb64;
equals(other: Cyrb64): boolean;
}
/**
* @author Timo lehnertz
*/
/**
* GameState class representing the state of a game
* This class exposes all information about the game that a player could legally know by looking at the board
*/
declare class GameState {
readonly board: Board;
readonly allPlayerStates: AllPlayerStates;
readonly historyMoves: Move[];
private hashCache;
constructor(board: Board, allPlayerStates: AllPlayerStates, historyMoves: Move[]);
/**
* @throws Error in case the move is not valid
*/
validateMove(move: Move): void;
/**
* @throws Error in case the move is not valid
*/
move(move: Move): GameState;
undoMove(): {
newGameState: GameState;
undoneMove: Move;
};
rotateLooseTile(rotateBeforeShift: number): GameState;
setShiftPosition(shiftPosition: ShiftPosition): GameState;
insertLooseTile(): GameState;
private movePlayer;
private collectTreasure;
getWinnerIndex(): number | null;
private removeLastTreasure;
private nextPlayer;
private prevPlayer;
private copyHistory;
private addMoveToHistory;
private removeLastHistoryMove;
equals(other: GameState): boolean;
static create(instance: GameState): GameState;
hash(): Cyrb64;
}
declare class RandomNumberGenerator {
readonly seed: string;
private a;
private b;
private c;
private d;
private generator;
constructor(seed: string);
rand(): number;
private cyrb128;
private sfc32;
}
interface CardRatios {
lCards: number;
streightCards: number;
tCards: number;
}
interface TreasureCardChances {
lCardTreasureChance: number;
streightCardTreasureChance: number;
tCardTreasureChance: number;
fixCardTreasureChance: number;
}
interface GameSetup {
seed: string;
playerCount: number;
boardWidth: number;
boardHeight: number;
cardsRatio: CardRatios;
treasureCardChances: TreasureCardChances;
}
type GameTileType = "fix" | "homePoint" | TileType;
interface PlayerListener {
yourTurn: (gameState: GameState, move: (move: Move) => boolean) => void;
}
interface WinListener {
gameEnded: (winnerIndex: number) => void;
}
/**
* Game class representing a game
*/
declare class Game {
private _gameState;
private redoHistory;
private constructor();
/**
* Game Logic -------------------
*/
move(move: Move): void;
undoLastMove(): void;
redoLastMove(): void;
get gameState(): GameState;
/**
* Setup logic
*/
static getDefaultSetup(): GameSetup;
static finalizeSetup(setup?: Partial<GameSetup>): GameSetup;
static buildFromSetup(partialSetup?: Partial<GameSetup>): Game;
private static getTreasureCount;
private static generateRandomBoard;
private static generateRandomTileType;
static getRandomTreasureProvider(generator: RandomNumberGenerator, treasures: Treasure[], treasureCardChances?: TreasureCardChances): (cardType?: GameTileType) => Treasure | null;
/**
* @param numberOfPlayers Has to be either 2, 3 or 4
*/
private static generatePlayerStates;
static generateTreasures(amount: number): Treasure[];
static buildFromString(str: string): Game;
stringify(): string;
}
/**
* @author Timo Lehnertz
*/
/**
* Returns a number between 0 and BEST_MOVE_WEIGHT (inclusive) based on the standing
*/
type EvaluatorFunction = (gameState: GameState, playerIndex: number) => number;
type MoveGenerator = (gameState: GameState) => Move;
declare function generateShiftPositions(gameState: GameState): ShiftPosition[];
declare function generateRandomMove(gameState: GameState): Move;
declare function generateMoves(gameState: GameState, toShiftPosition: ShiftPosition, rotation: number): Move[];
declare function positionByTreasure(board: Board, treasure: Treasure): BoardPosition | null;
/**
*
* @param evaluate Eval function
* @param strength number between 0 and 1 0 => random move, 1 => strongest move
* @returns The move generator
*/
declare function buildMoveGenerator(evaluate: EvaluatorFunction, strength: number): MoveGenerator;
declare function manhattanEvaluator(gameState: GameState, playerIndex: number): number;
declare function printBoard(board: Board): void;
declare function stringifyTile(pathTile: PathTile): string;
export { AllPlayerStates, Board, BoardPosition, type CardRatios, type EvaluatorFunction, Game, type GameSetup, GameState, type GameTileType, Heading, HeadingHelper, Move, type MoveGenerator, OpenSides, Path, PathTile, type PlayerListener, PlayerState, RandomNumberGenerator, ShiftPosition, TileType, Treasure, type TreasureCardChances, Vec2, type WinListener, buildMoveGenerator, generateMoves, generateRandomMove, generateShiftPositions, manhattanEvaluator, positionByTreasure, printBoard, stringifyTile };