UNPKG

@gamepark/rules-api

Version:

API to implement the rules of a board game

144 lines (143 loc) 7.09 kB
/** * The Rules class is the basic minimal API to implement when adapting a board game on Game Park. * It has the ability to tell whether it is a player's turn to play, what moves are legal, what happens when a move is played, and when the game is over. * * @typeparam Game - Data structure of the game state * @typeparam Move - Data structure of a game move * @typeparam PlayerId - type of the player's identifiers. Usually a number or a numeric enum. */ export declare abstract class Rules<Game = any, Move = any, PlayerId = any> { /** * The state of the game */ game: Game; /** * Construct a new instance of the Rules to work on a game state * @param game the state of the game to work on */ constructor(game: Game); /** * A shortcut for this.game for backward compatibility */ get state(): Game; /** * The delegation allows to split the rules in smaller and simpler parts. * Override this method to delegate the behavior of the other method to another Rules class. * * @return the Rule you want to delegate the current game behavior to */ delegate(): Rules<Game, Move, PlayerId> | undefined; /** * The delegation allows to split the rules in smaller and simpler parts. * Default behavior call {@link delegate} and returns either an empty array, or an array with the delegate if any. * Override this method to delegate the behavior of the other method to multiple Rules class. * * @return an array of Rules to delegate the current game behavior to */ delegates(): Rules<Game, Move, PlayerId>[]; /** * Implement this to tell at any point in the game which player is active or not. * When it's a player's turn, his thinking time decreases. * A player whose turn it's not can have authorised moves, so this method is not sufficient to prevent a player from playing. * Supports delegation: it returns true if any {@link delegates} return true. * * @param playerId - Identifier of a player * @returns true if it is this player's turn to play */ isTurnToPlay(playerId: PlayerId): boolean; /** * When only one player is active at a time, you can implement this method instead of "isTurnToPlay" to tell which player is active. * Supports delegation: if any {@link delegates} returns an active player, it will return it. * * @return @typeParam PlayerId - The identifier of the active player */ getActivePlayer(): PlayerId | undefined; /** * This method allows the Game Park server to authorise only valid moves in accordance with the game rules. * The default behavior calls {@link getLegalMoves}, and returns true when at least one move is equal. * Supports delegation with {@link delegates}. A move is legal if it is legal for at least one delegate. * * @param playerId - Identifier of a player * @param move - a Move to control * @returns true if the move can be played by this player */ isLegalMove(playerId: PlayerId, move: Move): boolean; /** * This method lists all the moves that are legal for a given player. * This is optional but convenient: it is used by {@link isLegalMove}, {@link Bot} and many UI features from @gamepark/react-game to automatically * highlight what can be done on the screen. * Beware of the size of the list however: if the game offers to many legal moves, you might have to fall back to implementing {@link isLegalMove} and a * custom {@link Bot}. * * Supports delegation with {@link delegates}: by default it will return all the legal moves of each delegate. * * @param playerId - Identifier of a player * @returns the list of the moves */ getLegalMoves(playerId: PlayerId): Move[]; /** * When some game state require automatic actions to be taken by the players, you can return a list of moves to play played automatically. * It can be a sequences in the rules where everything is scripted for instance (no choices left for players). * * Supports delegation with {@link delegates}: by default it will return all the automatic moves of each delegate. * * @returns the list of the moves that must be played automatically */ getAutomaticMoves(): Move[]; /** * Executes a move on current game state. * This method is the only one that should mutate the state of the game. * When a move is played by a player, or automatically played as a consequence of another move, it will be played by this method, independently on Game Park * server and on every player or spectator clients. It can also be replayed in replay or undo features. * * A move should not change a lot the game state: instead, this method should return new moves to play as consequences. * Dividing moves into small parts with consequences is key to producing step-by-step animations in the UI. * * see {@link https://en.wikipedia.org/wiki/Command_pattern} * * Supports delegation with {@link delegates}: by default it will play the move on each delegate, and return all the consequences. * * @param move - the Move to execute on the game state * @param context - context of execution: see {@link PlayMoveContext} * @returns A list of moves that should be immediately played as consequences of this move */ play(move: Move, context?: PlayMoveContext): Move[]; /** * This method must return true when the game is over. * * Supports delegation with {@link delegates}: by default it will return true if there is at least one delegate, and every delegate returns true. * Default behavior returns true if playersIds is provided, and it is not {@link isTurnToPlay} for any player - however this behavior is deprecated. * * @param playerIds - All the player ids in the game. Do not use (deprecated). * @returns true if game is over */ isOver(playerIds?: PlayerId[]): boolean; /** * Implement this method when some moves output cannot be predicted on the client side. * Unpredictable moves will not be proceeded by the client, which will wait for the server's response. * Examples: rolling dices, drawing a card * * @param move a move that is going to be played * @param player the player that played this move, or the move that triggered it as a consequence * @returns true if the move cannot be predicted from the player point of view */ isUnpredictableMove?(move: Move, player: PlayerId): boolean; } export interface RulesCreator<Game = any, Move = any, Player = number> { new (state: Game, client?: { player?: Player; }): Rules<Game, Move, Player>; } /** * The context when a move is played. */ export type PlayMoveContext = { /** * true if move is only played locally on a player's client */ local?: boolean; /** * True if the move will not be kept in the game's history */ transient?: boolean; };