diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-03-12 15:28:19 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-03-12 15:28:19 +0300 |
commit | 77b2f09883d4144c01802c5c75622e28f3864ca0 (patch) | |
tree | 5f6297e83295de990fd916b55e76af27e5a86a73 | |
parent | 2e6a4a8761bf037283f7eb8dbfd57ab7b9e977a9 (diff) | |
download | carcassonne-engine-ts-77b2f09883d4144c01802c5c75622e28f3864ca0.tar.gz |
refactor: separate TileOnBoard class
-rw-r--r-- | src/Board/Board.test.ts | 25 | ||||
-rw-r--r-- | src/Board/Board.ts | 21 | ||||
-rw-r--r-- | src/Tile/Tile.test.ts | 56 | ||||
-rw-r--r-- | src/Tile/Tile.ts | 62 | ||||
-rw-r--r-- | src/Tile/TileOnBoard.test.ts | 57 | ||||
-rw-r--r-- | src/Tile/TileOnBoard.ts | 46 |
6 files changed, 138 insertions, 129 deletions
diff --git a/src/Board/Board.test.ts b/src/Board/Board.test.ts index c4e5ed1..1370a87 100644 --- a/src/Board/Board.test.ts +++ b/src/Board/Board.test.ts @@ -1,30 +1,31 @@ import assert from 'assert'; import Tile, { Feature } from '../Tile/Tile'; -import Board from "./Board"; +import TileOnBoard from '../Tile/TileOnBoard'; +import Board from './Board'; const { Road, Town, Empty } = Feature; describe('Board', () => { describe('constructor', () => { - it('Should initialize empty board with a starting cell', () => { + it('Should initialize empty board with a starting tile', () => { const board = new Board(); - assert.strictEqual(board.cells.length, 1); - assert.deepStrictEqual(board.cells[0], new Tile(Road, [Town, Road, Empty, Road])); + assert.strictEqual(board.tiles.length, 1); + assert.deepStrictEqual(board.tiles[0], new TileOnBoard(Road, [Town, Road, Empty, Road])); }); }); describe('getAttachments', () => { - it('Should correctly determine legal moves for 1-cell board', () => { + it('Should correctly determine legal moves for 1-tile board', () => { const board = new Board(); - const attachTo = board.cells[0]; - const cell = new Tile(Town, [Empty, Town, Empty, Town]); - const legalMoves = board.getAttachments(cell); + const attachTo = board.tiles[0]; + const tile = new Tile(Town, [Empty, Town, Empty, Town]); + const legalMoves = board.getAttachments(tile); assert.strictEqual(legalMoves.length, 4); - assert.deepStrictEqual(legalMoves[0], { side: 0, rotation: 1, attachTo, cell }); - assert.deepStrictEqual(legalMoves[1], { side: 0, rotation: 3, attachTo, cell }); - assert.deepStrictEqual(legalMoves[2], { side: 2, rotation: 0, attachTo, cell }); - assert.deepStrictEqual(legalMoves[3], { side: 2, rotation: 2, attachTo, cell }); + assert.deepStrictEqual(legalMoves[0], { side: 0, rotation: 1, attachTo, tile }); + assert.deepStrictEqual(legalMoves[1], { side: 0, rotation: 3, attachTo, tile }); + assert.deepStrictEqual(legalMoves[2], { side: 2, rotation: 0, attachTo, tile }); + assert.deepStrictEqual(legalMoves[3], { side: 2, rotation: 2, attachTo, tile }); }); }); }); diff --git a/src/Board/Board.ts b/src/Board/Board.ts index f1aa45b..59afd31 100644 --- a/src/Board/Board.ts +++ b/src/Board/Board.ts @@ -1,26 +1,27 @@ import _ from 'lodash'; -import Tile, { Feature } from "../Tile/Tile"; +import Tile, { Feature } from '../Tile/Tile'; +import TileOnBoard from '../Tile/TileOnBoard'; const { Road, Town, Empty } = Feature; export default class Board { - cells: Tile[]; + tiles: TileOnBoard[]; - constructor(cells?: Tile[]) { - if (cells) this.cells = cells; - else this.cells = [new Tile(Road, [Town, Road, Empty, Road])] + constructor(tiles?: TileOnBoard[]) { + if (tiles) this.tiles = tiles; + else this.tiles = [new TileOnBoard(Road, [Town, Road, Empty, Road])] } print() { - this.cells.forEach(cell => cell.print()); + this.tiles.forEach(tile => tile.print()); } - getAttachments(cell: Tile) { - return _.flatten(this.cells.map(attachTo => attachTo.getAttachments(cell))); + getAttachments(tile: Tile) { + return _.flatten(this.tiles.map(attachTo => attachTo.getAttachments(tile))); } - getLegalMoves(cell: Tile) { - const attachments = this.getAttachments(cell); + getLegalMoves(tile: Tile) { + const attachments = this.getAttachments(tile); console.log(attachments); } } diff --git a/src/Tile/Tile.test.ts b/src/Tile/Tile.test.ts deleted file mode 100644 index 62ac51e..0000000 --- a/src/Tile/Tile.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import assert from 'assert'; -import Tile, { Direction, Feature } from './Tile'; - -const { North, East, South, West } = Direction; -const { Road, Town, Empty, River } = Feature; - -describe('Tile', () => { - describe('getSide', () => { - it('Should get North, East, South and West sides correctly', () => { - const cell = new Tile(Empty, [Road, Town, Empty, River]); - - assert.strictEqual(cell.getSide(North), Road); - assert.strictEqual(cell.getSide(East), Town); - assert.strictEqual(cell.getSide(South), Empty); - assert.strictEqual(cell.getSide(West), River); - }); - - it('Should respect cell orientation', () => { - const cell = new Tile(Empty, [Road, Town, Empty, River]); - cell.rotate(5); - - assert.strictEqual(cell.getSide(North), River); - assert.strictEqual(cell.getSide(East), Road); - assert.strictEqual(cell.getSide(South), Town); - assert.strictEqual(cell.getSide(West), Empty); - }); - - it('Should work with negative orientation', () => { - const cell = new Tile(Empty, [Road, Town, Empty, River]); - cell.rotate(-7); - - assert.strictEqual(cell.getSide(North), River); - assert.strictEqual(cell.getSide(East), Road); - assert.strictEqual(cell.getSide(South), Town); - assert.strictEqual(cell.getSide(West), Empty); - }); - }); - - describe('getAttachments', () => { - it('Should correclty list legal attachments', () => { - const attachTo = new Tile(Town, [Road, Town, Town, Road]) - const cell = new Tile(Road, [Empty, Road, Road, Empty]) - - cell.print(); - attachTo.print(); - - const attachments = attachTo.getAttachments(cell); - assert.strictEqual(attachments.length, 4); - assert.deepStrictEqual(attachments[0], { side: 0, rotation: 0, cell, attachTo }); - assert.deepStrictEqual(attachments[1], { side: 0, rotation: 1, cell, attachTo }); - assert.deepStrictEqual(attachments[2], { side: 3, rotation: 0, cell, attachTo }); - assert.deepStrictEqual(attachments[3], { side: 3, rotation: 3, cell, attachTo }); - }); - }); -}); - diff --git a/src/Tile/Tile.ts b/src/Tile/Tile.ts index 4eee263..4dd6ecb 100644 --- a/src/Tile/Tile.ts +++ b/src/Tile/Tile.ts @@ -1,8 +1,3 @@ -import _ from 'lodash'; -import Debug, { Debugger } from 'debug'; - -const debug = Debug('cell'); - export enum Direction { North, East, @@ -11,66 +6,31 @@ export enum Direction { } export enum Feature { - Empty = " ", - Road = "R", - Town = "T", - River = "I", - Church = "C", -} - -export interface Attachment { - attachTo: Tile; - side: Direction; - cell: Tile; - rotation: number; // Clockwise rotation of a cell + Empty = ' ', + Road = 'R', + Town = 'T', + River = 'I', + Church = 'C', } +// Abstract Tile data export default class Tile { center: Feature; - private sides: [Feature, Feature, Feature, Feature]; - neighbors: [Tile, Tile, Tile, Tile]; - private orientation: number // amount of 90-degree counter-clockwise rotations from original orientation + sides: [Feature, Feature, Feature, Feature]; shield?: boolean; - debug: Debugger; - - public constructor(center: Feature, sides: [Feature, Feature, Feature, Feature], orientation = 0, shield = false) { + public constructor(center: Feature, sides: [Feature, Feature, Feature, Feature], shield = false) { this.center = center; this.sides = sides; this.shield = shield; - this.orientation = orientation; - } - - print() { - console.log( ` ${this.getSide(Direction.North)} \n${this.getSide(Direction.West)}${this.center}${this.getSide(Direction.East)}\n ${this.getSide(Direction.South)} `); } getSide(direction: Direction) { - return this.sides[(((this.orientation + direction) % 4) + 4) % 4]; - } - - rotate(rotation = 1) { - debug(`Rotating ${rotation} clockwise`) - this.orientation = this.orientation - rotation; + return this.sides[((direction % 4) + 4) % 4]; } - getAttachments(cell: Tile) { - return _.flatten([0, 1, 2, 3].map(side => { - const item = this.getSide(side); - return [0, 1, 2, 3] - .filter(rotation => cell.getSide(side - rotation + 2) === item) - .map(rotation => ({ - cell, - rotation, - side, - attachTo: this as Tile - })) - })); - } - - attach(cell: Tile, side: Direction) { - if (this.neighbors[side]) throw new Error('There is something already attached to this side!'); - this.neighbors[side] = cell; + print() { + console.log( ` ${this.getSide(Direction.North)} \n${this.getSide(Direction.West)}${this.center}${this.getSide(Direction.East)}\n ${this.getSide(Direction.South)} `); } } diff --git a/src/Tile/TileOnBoard.test.ts b/src/Tile/TileOnBoard.test.ts new file mode 100644 index 0000000..7448435 --- /dev/null +++ b/src/Tile/TileOnBoard.test.ts @@ -0,0 +1,57 @@ +import assert from 'assert'; +import TileOnBoard from './TileOnBoard'; +import { Direction, Feature } from './Tile'; + +const { North, East, South, West } = Direction; +const { Road, Town, Empty, River } = Feature; + +describe('TileOnBoard', () => { + describe('getSide', () => { + it('Should get North, East, South and West sides correctly', () => { + const tile = new TileOnBoard(Empty, [Road, Town, Empty, River]); + + assert.strictEqual(tile.getSide(North), Road); + assert.strictEqual(tile.getSide(East), Town); + assert.strictEqual(tile.getSide(South), Empty); + assert.strictEqual(tile.getSide(West), River); + }); + + it('Should respect tile orientation', () => { + const tile = new TileOnBoard(Empty, [Road, Town, Empty, River]); + tile.rotate(5); + + assert.strictEqual(tile.getSide(North), River); + assert.strictEqual(tile.getSide(East), Road); + assert.strictEqual(tile.getSide(South), Town); + assert.strictEqual(tile.getSide(West), Empty); + }); + + it('Should work with negative orientation', () => { + const tile = new TileOnBoard(Empty, [Road, Town, Empty, River]); + tile.rotate(-7); + + assert.strictEqual(tile.getSide(North), River); + assert.strictEqual(tile.getSide(East), Road); + assert.strictEqual(tile.getSide(South), Town); + assert.strictEqual(tile.getSide(West), Empty); + }); + }); + + describe('getAttachments', () => { + it('Should correclty list legal attachments', () => { + const attachTo = new TileOnBoard(Town, [Road, Town, Town, Road]) + const tile = new TileOnBoard(Road, [Empty, Road, Road, Empty]) + + tile.print(); + attachTo.print(); + + const attachments = attachTo.getAttachments(tile); + assert.strictEqual(attachments.length, 4); + assert.deepStrictEqual(attachments[0], { side: 0, rotation: 0, tile, attachTo }); + assert.deepStrictEqual(attachments[1], { side: 0, rotation: 1, tile, attachTo }); + assert.deepStrictEqual(attachments[2], { side: 3, rotation: 0, tile, attachTo }); + assert.deepStrictEqual(attachments[3], { side: 3, rotation: 3, tile, attachTo }); + }); + }); +}); + diff --git a/src/Tile/TileOnBoard.ts b/src/Tile/TileOnBoard.ts new file mode 100644 index 0000000..65f3731 --- /dev/null +++ b/src/Tile/TileOnBoard.ts @@ -0,0 +1,46 @@ +import _ from 'lodash'; +import Tile, { Feature, Direction } from './Tile'; + +export interface Attachment { + attachTo: Tile; + side: Direction; + tile: Tile; + rotation: number; // Clockwise rotation of a tile +} + +export default class TileOnBoard extends Tile { + neighbors: [Tile, Tile, Tile, Tile]; + private orientation: number // amount of 90-degree counter-clockwise rotations from original orientation + + constructor(center: Feature, sides: [Feature, Feature, Feature, Feature], shield = false, orientation = 0) { + super(center, sides, shield); + this.orientation = orientation; + } + + getSide(direction: Direction) { + return this.sides[(((this.orientation + direction) % 4) + 4) % 4]; + } + + rotate(rotation = 1) { + this.orientation = this.orientation - rotation; + } + + getAttachments(tile: Tile): Attachment[] { + return _.flatten([0, 1, 2, 3].map(side => { + const item = this.getSide(side); + return [0, 1, 2, 3] + .filter(rotation => tile.getSide(side - rotation + 2) === item) + .map(rotation => ({ + tile, + rotation, + side, + attachTo: this as Tile + })) + })); + } + + attach(tile: Tile, side: Direction) { + if (this.neighbors[side]) throw new Error('There is something already attached to this side!'); + this.neighbors[side] = tile; + } +} |