aboutsummaryrefslogtreecommitdiff
path: root/src/Tile
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-03-12 15:10:54 +0300
committereug-vs <eugene@eug-vs.xyz>2022-03-12 15:10:54 +0300
commit2e6a4a8761bf037283f7eb8dbfd57ab7b9e977a9 (patch)
tree22012ec08067f92d8baf9ab3039f3f7cda3e7402 /src/Tile
parent8aa2213390e01996e3f9682abfd5910c698df0e2 (diff)
downloadcarcassonne-engine-ts-2e6a4a8761bf037283f7eb8dbfd57ab7b9e977a9.tar.gz
refactor: rename Cell -> Tile, Item -> Feature
Diffstat (limited to 'src/Tile')
-rw-r--r--src/Tile/Tile.test.ts56
-rw-r--r--src/Tile/Tile.ts76
2 files changed, 132 insertions, 0 deletions
diff --git a/src/Tile/Tile.test.ts b/src/Tile/Tile.test.ts
new file mode 100644
index 0000000..62ac51e
--- /dev/null
+++ b/src/Tile/Tile.test.ts
@@ -0,0 +1,56 @@
+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
new file mode 100644
index 0000000..4eee263
--- /dev/null
+++ b/src/Tile/Tile.ts
@@ -0,0 +1,76 @@
+import _ from 'lodash';
+import Debug, { Debugger } from 'debug';
+
+const debug = Debug('cell');
+
+export enum Direction {
+ North,
+ East,
+ South,
+ West
+}
+
+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
+}
+
+
+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
+ shield?: boolean;
+
+ debug: Debugger;
+
+ public constructor(center: Feature, sides: [Feature, Feature, Feature, Feature], orientation = 0, 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;
+ }
+
+ 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;
+ }
+}