TrainsAndRoads/interface/types/Cell.ts

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,
};
}
}