UNPKG

ymir-js

Version:

This toolkit is created to make it easier for you to develop games like chess, checkers, go, match 3 puzzle and more. It is still under development.

243 lines (178 loc) 5.95 kB
import getAvailableColumns from '../../utils/getAvailableColumns'; import parseCoord from '../../utils/parseCoord'; import Item, { ItemType, MovementType } from './item'; export type DistanceType = { x: number; y: number; }; export type BoardConfig = { x: number; y: number; }; export type ColumnType = { item: ItemType; }; export type BoardType = { [key: string]: ColumnType; }; export type Direction = | 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight' | 'right' | 'left' | 'top' | 'bottom'; export type BoardMatrixItem = { coord: string; item: ItemType; }; class Board { config: BoardConfig; board: BoardType = {}; constructor(config: BoardConfig) { const board = Board.createBoard(config); this.config = config; this.board = board; return this; } static createBoard = (config: BoardConfig): BoardType => { const { x, y } = config; const board: BoardType = {}; for (let rowIndex = 0; rowIndex < x; rowIndex += 1) { for (let colIndex = 0; colIndex < y; colIndex += 1) { board[`${rowIndex}|${colIndex}`] = { item: null }; } } return board; }; updateBoard = (board: BoardType) => { this.board = board; return this; }; updateBoardWithMatrix = (matrix: ItemType[][]) => { const newBoard: BoardType = {}; matrix.forEach((row: ItemType[], rowIndex: number) => { row.forEach((item: ItemType, colIndex: number) => { newBoard[`${rowIndex}|${colIndex}`] = { item: new Item(item) }; }); }); this.updateBoard(newBoard); }; getBoardMatrix = (): BoardMatrixItem[][] => { const matrix = []; Object.entries(this.board).forEach(([coord, data]) => { const [rowId, colId] = parseCoord(coord); const item = { coord, ...data }; if (matrix[rowId]) { matrix[rowId][colId] = item; } else { matrix[rowId] = [item]; } }); return matrix; }; getItem = (coord: string): ItemType => { const isExistCoord = this.isExistCoord(coord); if (!isExistCoord) return null; return this.board[coord].item; }; setItem = (coord: string, item: ItemType): void => { const isExistCoord = this.isExistCoord(coord); if (!isExistCoord) return; this.board[coord].item = item; }; removeItem = (coord: string): void => { const isExistCoord = this.isExistCoord(coord); if (!isExistCoord) return; this.board[coord].item = null; }; moveItem = (fromCoord: string, toCoord: string): void => { const isExistFromCoord = this.isExistCoord(fromCoord); const isExistToCoord = this.isExistCoord(toCoord); if (!isExistFromCoord || !isExistToCoord) return; const { item } = this.board[fromCoord]; this.board[fromCoord].item = null; this.board[toCoord].item = item; }; switchItem = (fromCoord: string, toCoord: string): void => { const isExistFromCoord = this.isExistCoord(fromCoord); const isExistToCoord = this.isExistCoord(toCoord); if (!isExistFromCoord || !isExistToCoord) return; const { item: fromItem } = this.board[fromCoord]; const { item: toItem } = this.board[toCoord]; this.board[fromCoord].item = toItem; this.board[toCoord].item = fromItem; }; selectItem = (coord: string): void => { const isExistCoord = this.isExistCoord(coord); if (!isExistCoord) return; const { item } = this.board[coord]; if (item) { item.selected = true; } }; deselectItem = (coord: string): void => { const isExistCoord = this.isExistCoord(coord); if (!isExistCoord) return; const { item } = this.board[coord]; if (item) { item.selected = false; } }; deselectAllItems = (): void => { Object.keys(this.board).forEach((coord) => { const { item } = this.board[coord]; if (item) { item.selected = false; } }); }; isEmpty = (coord: string): boolean => { const isExistCoord = this.isExistCoord(coord); if (!isExistCoord) return; return !this.board[coord].item; }; isExistCoord = (coord: string): boolean => !!this.board[coord]; getDistanceBetweenTwoCoords = ( fromCoord: string, toCoord: string ): DistanceType => { const isExistFromCoord = this.isExistCoord(fromCoord); const isExistToCoord = this.isExistCoord(toCoord); if (!isExistFromCoord || !isExistToCoord) return; const [fromRowId, fromColId] = parseCoord(fromCoord); const [toRowId, toColId] = parseCoord(toCoord); return { y: toRowId - fromRowId, x: toColId - fromColId }; }; getDirection = (fromCoord: string, toCoord: string): Direction => { const isExistFromCoord = this.isExistCoord(fromCoord); const isExistToCoord = this.isExistCoord(toCoord); if (!isExistFromCoord || !isExistToCoord) return; const [fromRowId, fromColId] = parseCoord(fromCoord); const [toRowId, toColId] = parseCoord(toCoord); if (fromColId > toColId && fromRowId < toRowId) return 'bottomLeft'; if (fromColId < toColId && fromRowId < toRowId) return 'bottomRight'; if (fromColId > toColId && fromRowId > toRowId) return 'topLeft'; if (fromColId < toColId && fromRowId > toRowId) return 'topRight'; if (fromColId < toColId && fromRowId === toRowId) return 'right'; if (fromColId > toColId && fromRowId === toRowId) return 'left'; if (fromColId === toColId && fromRowId > toRowId) return 'top'; if (fromColId === toColId && fromRowId < toRowId) return 'bottom'; return null; }; getAvailableColumns = ( coord: string, movement: MovementType, columnsObj?: boolean ): string[] | { [key: string]: string[] } => { const avaiblableColumns = []; const columns = getAvailableColumns(coord, movement); if (columnsObj) return columns; return avaiblableColumns .concat(...Object.values(columns)) .filter(this.isExistCoord); }; } export default Board;