UNPKG

@gamepark/rules-api

Version:

API to implement the rules of a board game

122 lines 4.94 kB
import { applyAutomaticMoves, hasRandomMove } from '../utils'; import { Material } from './items'; import { GameMemory, PlayerMemory } from './memory'; import { MaterialMoveBuilder } from './moves'; /** * Helper class to implement {@link GameSetup} when using the {@link MaterialRules} approach. */ export class MaterialGameSetup { /** * The game setup state we are working on * @protected */ game = { players: [], items: {}, memory: {} }; /** * Get an instance of the rules of the game */ get rules() { return new this.Rules(this.game); } /** * Entry point for {@link GameSetup} * @param options Options of the game * @param tutorial Initial tutorial state if any * @returns the initial state of the game */ setup(options, tutorial) { this.game = { players: getPlayerIds(options), items: {}, memory: {}, tutorial }; this.setupMaterial(options); this.start(options); return this.game; } /** * @returns array of the player ids (shortcut for this.game.players) */ get players() { return this.game.players; } /** * Override this function if you need to set up some material before the game starts. Called by {@link setup}. * @param _options Options of the game */ setupMaterial(_options) { } /** * Help function to execute a move immediately on the game state. * When the game is on, the moves should never be played directly: the framework takes care of playing the moves when necessary * (on te server, on the clients, during replays...). * However, during the setup, the moves must be played immediately in the game state to provide the initial game state to the framework. * This help function allows to easily play a {@link MaterialMove}, using the rules provided in {@link Rules}, including the consequences. * * @param move The MaterialMove to play * @protected */ playMove(move) { if (hasRandomMove(this.rules)) { move = this.rules.randomize(move); } const consequences = this.rules.play(JSON.parse(JSON.stringify(move))); applyAutomaticMoves(this.rules, consequences); } /** * Helper function to manipulate the items of the game. See {@link Material}. * @param type The type of Material we want to work on * @returns a Material instance to manipulate all the material of that type in current game state. */ material(type) { return new Material(type, this.game.items[type], move => this.playMove(move)); } /** * Utility function to access the memory tool for the game or on player. * this.game.memory can be used to store any data that is not available through the state of the material, or current rule. * * @param player Optional, identifier of the player if we want to manipulate a specific player's memory * @returns {@link GameMemory} or {@link PlayerMemory} utility * @protected */ getMemory(player) { return player === undefined ? new GameMemory(this.game) : new PlayerMemory(this.game, player); } /** * Helper function to memorize some information that does not fit in an item or the rules state, in the game state * @param key Key under which the memory is store. Usually a value of a numeric enum named "Memory". * @param value Value to memorize * @param player optional, if we need to memorize a different value for each player. */ memorize(key, value, player) { return this.getMemory(player).memorize(key, value); } /** * Helper function to play a {@link StartPlayerTurn} move on the game setup state. * @param id Rule id to start * @param player Player that starts the game (default value: this.game.players[0]) */ startPlayerTurn(id, player = this.game.players[0]) { this.playMove(MaterialMoveBuilder.startPlayerTurn(id, player)); } /** * Helper function to play a {@link StartSimultaneousRule} move on the game setup state. * @param id Rule id to start * @param players Players that are active (all the players by default) */ startSimultaneousRule(id, players) { this.playMove(MaterialMoveBuilder.startSimultaneousRule(id, players)); } /** * Helper function to play a {@link StartRule} move on the game setup state. * @param id Rule id to start */ startRule(id) { this.playMove(MaterialMoveBuilder.startRule(id)); } } function getPlayerIds(options) { if (Array.isArray(options.players)) { return options.players.map((player, index) => player.id ?? index + 1); } else { const numberOfPlayers = options.players ?? 2; return Array.from(Array(numberOfPlayers).keys()).map(index => (index + 1)); } } //# sourceMappingURL=MaterialGameSetup.js.map