78 lines
2.6 KiB
TypeScript
78 lines
2.6 KiB
TypeScript
import { CellType } from "../constants/CellType";
|
|
import { Direction } from "../constants/Direction";
|
|
import { ExitType } from "../constants/ExitType";
|
|
import { PieceId, pieceMap } from "../constants/Pieces";
|
|
import { Exit } from "./Exit";
|
|
import { ExternalNode } from "./ExternalNode";
|
|
import { InternalNode } from "./InternalNode";
|
|
import { PlacedPiece } from "./PlacedPiece";
|
|
|
|
export class Cell {
|
|
public readonly externalNodes: Map<Direction, ExternalNode>;
|
|
public readonly cellType: CellType;
|
|
public placedPiece?: {
|
|
piece: PlacedPiece;
|
|
id: PieceId;
|
|
};
|
|
|
|
constructor(cellType: CellType) {
|
|
this.externalNodes = new Map([
|
|
[Direction.NORTH, new ExternalNode(this, Direction.NORTH)],
|
|
[Direction.SOUTH, new ExternalNode(this, Direction.SOUTH)],
|
|
[Direction.EAST, new ExternalNode(this, Direction.EAST)],
|
|
[Direction.WEST, new ExternalNode(this, Direction.WEST)],
|
|
]);
|
|
this.cellType = cellType;
|
|
}
|
|
|
|
public getNodeAt(direction: Direction): ExternalNode {
|
|
const node = this.externalNodes.get(direction);
|
|
if (!node) throw Error(`Could not find node at ${direction}`);
|
|
return node!;
|
|
}
|
|
|
|
public placePiece(pieceId: PieceId) {
|
|
if (this.placedPiece !== undefined) return;
|
|
const piece = pieceMap[pieceId];
|
|
const connectionTypes = Array.from(piece.tracks).flatMap((track) => {
|
|
const directions =
|
|
track.joinedPoints.secondPoint instanceof InternalNode
|
|
? [track.joinedPoints.firstPoint]
|
|
: [track.joinedPoints.firstPoint, track.joinedPoints.secondPoint];
|
|
return directions.map((direction) => {
|
|
return { direction: direction, type: track.type };
|
|
});
|
|
});
|
|
connectionTypes.forEach(({ direction, type }) => {
|
|
const adjacentPoint = this.getNodeAt(direction).traverseBorder();
|
|
if (adjacentPoint instanceof Exit) {
|
|
if (
|
|
adjacentPoint.type !== ExitType.AMBIVALENT &&
|
|
adjacentPoint.type.toString() !== type.toString()
|
|
) {
|
|
throw Error(
|
|
`Unable to place piece, invalid border at direction ${direction}`,
|
|
);
|
|
}
|
|
} else {
|
|
if (adjacentPoint.cell.placedPiece !== undefined) {
|
|
const adjacentTrack =
|
|
adjacentPoint.cell.placedPiece.piece.findTrackForDirection(
|
|
adjacentPoint.direction,
|
|
);
|
|
if (adjacentTrack !== undefined && adjacentTrack.type !== type) {
|
|
throw Error(
|
|
`Unable to place piece next to another due to conflicting track types at ${direction}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
this.placedPiece = {
|
|
piece: piece.toPlacedPiece(this),
|
|
id: pieceId,
|
|
};
|
|
}
|
|
}
|