UNPKG

domino-engine

Version:

Domino Engine to create Domino Games. The library would generate all the tiles and structures to easily create one of the multiple domino games.

133 lines (107 loc) 3.22 kB
export enum Pips { blank = "0", one = "1", two = "2", tree = "3", four = "4", five = "5", six = "6", seven = "7", eight = "8", nine = "9", ten = "10", eleven = "11", twelve = "12", } export const Values: number[] = Object.keys(Pips).map((pip) => Number(Pips[pip]) ); export const ValuesToKeys = Object.keys(Pips).reduce((acum, pip) => { acum[Pips[pip]] = pip; return acum; }, {}); export const KeysToValues = Object.keys(Pips).reduce((acum, pip) => { acum[pip] = Number(Pips[pip]); return acum; }, {}); export class Tile { private values: [Pips, Pips]; private isDouble: boolean = false; private connected = new Set<{ value: Pips; tile: Tile }>(); public isRoot: boolean = false; constructor(one: Pips, two: Pips) { this.values = [one, two]; if (one === two) { this.isDouble = true; } } value = () => [...this.values]; toString = () => `[${this.values[0]},${this.values[1]}]`; has = (match: Pips) => this.values.includes(match); canAttach = (tile: Tile) => { const [value1, value2] = tile.value(); const match = this.has(value1) || this.has(value2); if (!match) return false; return this.isDouble ? this.connected.size <= 4 : this.connected.size <= 2; }; attach = (tile: Tile, value: Pips, options: { clean?: boolean } = {}) => { const ofSameValue = [...this.connected].filter( (currentTile) => currentTile.value === value ).length; const enoughSpace = this.isDouble ? ofSameValue < 3 : ofSameValue < 2; if (this.canAttach(tile) && tile.canAttach(this) && enoughSpace) { this.connected.add({ value, tile }); if (!options.clean) { tile.attach(this, value, { clean: true }); } return true; } return false; }; attached = () => [...this.connected]; } export type Suite = { [key in Pips]: Tile; }; export type Hand = Set<Tile>; export const generateSuite = (amount?: Pips) => { const box = new Set<Tile>(); const max = Number(amount || Values[Values.length - 1]); for (let suiteIndex = max; suiteIndex > -1; suiteIndex--) { const suite = Pips[ValuesToKeys[suiteIndex]]; const suiteTile = new Tile(suite, suite); box.add(suiteTile); for (let valueIndex = suiteIndex - 1; valueIndex > -1; valueIndex--) { const value = Pips[ValuesToKeys[valueIndex]]; const tile: Tile = new Tile(suite, value); box.add(tile); } } return box; }; export class Box { private box: Tile[]; constructor(options: { box?: Set<Tile>; level?: Pips } = {}) { this.box = [...(options.box || generateSuite(options.level)).values()]; } next = (amount: number = 1) => { const drawed: Tile[] = []; while (amount > 0) { const tile = this.box.pop(); drawed.push(tile); amount--; } return drawed; }; draw = () => this.box.splice(~~(Math.random() * this.box.length), 1); suffle = () => { const shuffled: Tile[] = []; while (this.box.length !== 0) { const randomIndex = ~~(Math.random() * this.box.length); shuffled.push(this.box[randomIndex]); this.box.splice(randomIndex, 1); } this.box = shuffled; }; valueOf = () => [...this.box]; }