import _ from 'lodash'; import Tile, { Feature, Direction } from '../Tile/Tile'; import TileOnBoard, { Attachment } from '../Tile/TileOnBoard'; const { Road, Town, Grass } = Feature; const { North, East, South, West } = Direction; export default class Board { tiles: TileOnBoard[]; constructor(tiles?: TileOnBoard[]) { if (tiles) this.tiles = tiles; else this.tiles = [new TileOnBoard(Road, [Town, Road, Grass, Road])] } 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.getSide(North)} `; }) .join('|') ); console.log( _.range(minX, maxX + 1) .map((x: number) => { const tile = _.find(rowTiles, { position: { x, y } }); if (!tile) return ' '; return `${tile.getSide(West)}${tile.center}${tile.getSide(East)}`; }) .join('|') ); console.log( _.range(minX, maxX + 1) .map((x: number) => { const tile = _.find(rowTiles, { position: { x, y } }); if (!tile) return ' '; return ` ${tile.getSide(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(); } isLegalAttachment(attachment: Attachment) { const { tile, side, attachTo, orientation } = attachment; const xIncrement = { [East]: 1, [West]: -1, }; const yIncrement = { [North]: 1, [South]: -1, }; const position = { x: attachTo.position.x + (xIncrement[side] || 0), y: attachTo.position.y + (yIncrement[side] || 0), }; const isBusy = _.find(this.tiles, { position }); if (isBusy) return false; // TODO: compute this array at runtime const neighborIncrements = [ { x: 0, y: -1, side: 0 }, { x: -1, y: 0, side: 1 }, { x: 0, y: 1, side: 2 }, { x: 1, y: 0, side: 3 }, ]; return _.every(_.map(neighborIncrements, ({ x, y, side }) => { const neighbor = _.find(this.tiles, { position: { x: position.x + x, y: position.y + y, } }); if (!neighbor) return true; if (neighbor.getSide(side) !== tile.getSide(side - orientation + 2)) return false; return true; })); } attach(attachment: Attachment) { const { tile, attachTo, side, orientation } = attachment; const xIncrement = { [East]: 1, [West]: -1, }; const yIncrement = { [North]: 1, [South]: -1, }; const tileOnBoard = new TileOnBoard( tile.center, tile.sides, tile.shield, { x: attachTo.position.x + (xIncrement[side] || 0), y: attachTo.position.y + (yIncrement[side] || 0), }, orientation, ); this.tiles.push(tileOnBoard); } }