tafl
Version:
A Typescript library for Hnefatafl (Viking Chess, or Tafl) that is used for move generation/validation, piece placement/movement, and game over detection. You can use it to simulate games between AI agents - written for this purpose, and also serves as th
141 lines (140 loc) • 6.01 kB
TypeScript
interface Named {
name: String;
}
interface Coords {
readonly r: number;
readonly c: number;
}
interface MoveAction {
from: Coords;
to: Coords;
}
interface Game extends Named {
getPossibleActions(state: GameState): MoveAction[];
isActionPossible(state: GameState, action: MoveAction): boolean;
isGameOver(state: GameState): typeof state;
act(state: GameState, action: MoveAction): typeof state;
}
export declare enum Piece {
__ = " ",
PA = "A",
PD = "D",
PK = "K"
}
export declare type Board = Array<Array<Piece>>;
export interface GameState {
board?: Board;
actions?: Array<MoveAction>;
boardHistory?: Record<string, number>;
turn?: number;
result?: {
finished: boolean;
winner?: TaflSide;
desc: string;
};
captures?: Array<Coords>;
lastAction?: MoveAction;
rules?: {
[key: string]: TaflRule;
};
}
export declare class TaflBoard {
static readonly _7_BRANDUBH: Piece[][];
static readonly _9_TABLUT: Piece[][];
static readonly _11_CLASSIC: Piece[][];
static readonly _11_LINE: Piece[][];
static readonly _11_TAWLBWRDD: Piece[][];
static readonly _11_LEWISS: Piece[][];
static readonly _13_PARLETT: Piece[][];
static readonly _15_DAMIEN_WALKER: Piece[][];
static readonly _19_ALEA_EVANGELII: Piece[][];
}
export declare class TaflSide extends String {
static readonly ATTACKER = "Attacker";
static readonly DEFENDER = "Defender";
}
export declare class TaflRule {
static readonly KING_IS_ARMED = "kingIsArmed";
static readonly KING_CAN_RETURN_TO_CENTER = "kingCanReturnToCenter";
static readonly ATTACKER_COUNT_TO_CAPTURE = "attackerCountToCapture";
static readonly REPETITION_TURN_LIMIT = "repetitionTurnLimit";
static readonly SHIELD_WALLS = "shieldWalls";
static readonly EXIT_FORTS = "exitForts";
static readonly EDGE_ESCAPE = "edgeEscape";
static readonly CORNER_BASE_WIDTH = "cornerBaseWidth";
static readonly STARTING_SIDE = "startingSide";
static readonly SAVE_BOARD_HISTORY = "saveBoardHistory";
static readonly SAVE_ACTIONS = "saveActions";
}
export declare class TaflRuleSet {
static readonly COPENHAGEN: {
kingIsArmed: boolean;
kingCanReturnToCenter: boolean;
attackerCountToCapture: number;
repetitionTurnLimit: number;
shieldWalls: boolean;
exitForts: boolean;
edgeEscape: boolean;
cornerBaseWidth: number;
startingSide: string;
saveBoardHistory: boolean;
saveActions: boolean;
};
}
export declare class Tafl implements Game {
name: string;
controlMap: Map<TaflSide, Set<Piece>>;
sideMap: Map<Piece, TaflSide>;
initialState(init?: GameState): GameState;
log(thing: any): void;
isCenter(board: Board, coords: Coords): boolean;
isCorner(state: GameState, coords: Coords): boolean;
isEdge(state: GameState, coords: Coords): boolean;
repr(coords: Coords): String;
coords(repr: String): Coords;
toPathRepr(...args: Array<Coords>): String;
toPathCoords(path: String): Array<Coords>;
insideBounds(board: Board, coords: Coords): boolean;
connectedPieces(board: Board, coords: Coords, side: TaflSide): Set<String>;
connectedDefenders(board: Board, coords: Coords): Set<String>;
connectedAttackers(board: Board, coords: Coords): Set<String>;
possiblySurroundingPieces(board: Board, kingCoords: Coords, side: TaflSide): Array<Coords>;
possiblySurrondingDefenders(board: Board, kingCoords: Coords): Array<Coords>;
possiblySurrondingAttackers(board: Board, kingCoords: Coords): Array<Coords>;
isInsideEye(board: Board, coords: Coords, fullFortStructure: Set<String>): boolean;
getPossibleSmallestFortStructure(board: Board, innerSet: Set<String>, fullStructure: Set<String>): Set<String>;
getEmptyPiecesAndOpponentsInsideSmallestClosedStructure(board: Board, kingCoords: Coords, closedStructure: Set<String>, oppSide?: TaflSide): Array<Set<String>>;
getEmptyPiecesAndAttackersInsideSmallestFort(board: Board, kingCoords: Coords, fullFortStructure: Set<String>): Array<Set<String>>;
insideFort(board: Board, kingCoords: Coords): boolean;
kingEscapedThroughFort(state: GameState): boolean;
isBase(state: GameState, coords: Coords): boolean;
isEmpty(board: Board, coords: Coords): boolean;
isEmptyBase(state: GameState, coords: Coords): boolean;
isKing(board: Board, coords: Coords): boolean;
isAttacker(board: Board, coords: Coords): boolean;
isDefender(board: Board, coords: Coords): boolean;
isDefenderOrKing(board: Board, coords: Coords): boolean;
canHelpCapture(state: GameState, coords: Coords, canHelp: TaflSide): boolean;
turnSide(state: GameState): TaflSide;
opponentSide(state: GameState): TaflSide;
canControl(side: TaflSide, piece: Piece): boolean;
sideOfPiece(piece: Piece): TaflSide | undefined;
pieceAt(board: Board, coords: Coords): Piece;
canMovePieceHere(state: GameState, piece: Piece, coords: Coords): boolean;
getPossibleMovesFrom(state: GameState, coords: Coords): Array<Coords>;
canMakeAMove(state: GameState, side: TaflSide): boolean;
getKingCoords(board: Board): Coords;
didAttackersSurroundDefenders(board: Board): boolean;
canBeCaptured(board: Board, coords: Coords, side: TaflSide): boolean;
checkCaptures(state: GameState): Array<Coords>;
checkShieldWalls(state: GameState): Array<Coords>;
getBoardHash(board: Board): string;
addBoardToHistory(state: GameState, board: Board): typeof state;
getEquivalentBoards(board: Board): Record<string, Board>;
fortSearchFromKing(board: Board, kingCoords: Coords): boolean;
getPossibleActions(state: GameState, side?: TaflSide): Array<MoveAction>;
isActionPossible(state: GameState, act: MoveAction): boolean;
isGameOver(state: GameState): typeof state;
act(state: GameState, moveAction: MoveAction): typeof state;
}
export {};