import _ from 'lodash'; import Tile, { Attachment, Direction } from '../Tile/Tile'; const { North, East, South, West } = Direction; export default class Board { tiles: Tile[]; constructor(tiles?: Tile[]) { if (tiles) this.tiles = tiles; else this.tiles = [new Tile('R', 'CRFR')] } print() { const maxY = _.maxBy(this.tiles, 'position.y').position.y; const minY = _.minBy(this.tiles, 'position.y').position.y; const maxX = _.maxBy(this.tiles, 'position.x').position.x; const minX = _.minBy(this.tiles, 'position.x').position.x; _.range(maxY, minY - 1, -1) .map((y: number) => { const rowTiles = _.filter(this.tiles, { position: { y } }); console.log( _.range(minX, maxX + 1) .map((x: number) => { const tile = _.find(rowTiles, { position: { x, y } }); if (!tile) return ' '; return ` ${tile.edges[North]} `; }) .join('|') ); console.log( _.range(minX, maxX + 1) .map((x: number) => { const tile = _.find(rowTiles, { position: { x, y } }); if (!tile) return ' '; return `${tile.edges[West]}${tile.center}${tile.edges[East]}`; }) .join('|') ); console.log( _.range(minX, maxX + 1) .map((x: number) => { const tile = _.find(rowTiles, { position: { x, y } }); if (!tile) return ' '; return ` ${tile.edges[South]} `; }) .join('|') ); }); } getAttachments(tile: Tile): Attachment[] { return _ .flatten(this.tiles.map(attachTo => attachTo.getAttachments(tile))) .filter((attachment: Attachment) => this.isLegalAttachment(attachment)); } previewAttachment(attachment: Attachment) { console.log(attachment); const previewBoard = _.cloneDeep(this); previewBoard.attach(attachment); previewBoard.print(); } getTileNeighbors(position: Tile['position']): Tile[] { // Do not change the order! const neighborIncrements = [ { x: 0, y: 1 }, { x: 1, y: 0 }, { x: 0, y: -1 }, { x: -1, y: 0 }, ]; return _.map(neighborIncrements, ({ x, y }) => { return _.find(this.tiles, { position: { x: position.x + x, y: position.y + y, } }); }); } calculateNewTilePosition(attachment: Attachment): Tile['position'] { const { attachTo: { position }, edge } = attachment const xIncrement = { [East]: 1, [West]: -1, }; const yIncrement = { [North]: 1, [South]: -1, }; return { x: position.x + (xIncrement[edge] || 0), y: position.y + (yIncrement[edge] || 0), }; } isLegalAttachment(attachment: Attachment) { const { tile } = attachment; const position = this.calculateNewTilePosition(attachment); const isBusy = _.find(this.tiles, { position }); if (isBusy) return false; const neighbors = this.getTileNeighbors(position); const neighborsRegex = _.map(neighbors, (neighbor: Tile, edge: number) => neighbor?.edges[edge] || '.').join(''); const str = [tile.edges, tile.edges, tile.edges].join(''); console.log(neighborsRegex, str); return new RegExp(neighborsRegex).test(str); } attach(attachment: Attachment) { const { tile, orientation } = attachment; const position = this.calculateNewTilePosition(attachment); const tileOnBoard = new Tile( tile.center, tile.edges, tile.shield, position, orientation, ); this.tiles.push(tileOnBoard); } }