aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-03-12 15:28:19 +0300
committereug-vs <eugene@eug-vs.xyz>2022-03-12 15:28:19 +0300
commit77b2f09883d4144c01802c5c75622e28f3864ca0 (patch)
tree5f6297e83295de990fd916b55e76af27e5a86a73
parent2e6a4a8761bf037283f7eb8dbfd57ab7b9e977a9 (diff)
downloadcarcassonne-engine-ts-77b2f09883d4144c01802c5c75622e28f3864ca0.tar.gz
refactor: separate TileOnBoard class
-rw-r--r--src/Board/Board.test.ts25
-rw-r--r--src/Board/Board.ts21
-rw-r--r--src/Tile/Tile.test.ts56
-rw-r--r--src/Tile/Tile.ts62
-rw-r--r--src/Tile/TileOnBoard.test.ts57
-rw-r--r--src/Tile/TileOnBoard.ts46
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;
+ }
+}