From 949969bda3a581734e9448975d8272386193dd90 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Tue, 3 Dec 2024 18:09:04 +0100 Subject: [PATCH] Disallow piece placement when piece is not connected to adjacent piece or exit --- interface/constants/Pieces.ts | 2 +- interface/types/Cell.ts | 101 ++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/interface/constants/Pieces.ts b/interface/constants/Pieces.ts index fc12356..e71f635 100644 --- a/interface/constants/Pieces.ts +++ b/interface/constants/Pieces.ts @@ -294,7 +294,7 @@ const T_JUNCTION_ROAD: Piece = new Piece({ }, { startPoint: Direction.WEST, - type: TrackType.RAIL, + type: TrackType.ROAD, }, ], }); diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 9f79fad..9bac0ba 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -1,10 +1,12 @@ import { CellType } from "../constants/CellType"; -import { Direction } from "../constants/Direction"; +import { Direction, directions } from "../constants/Direction"; import { ExitType } from "../constants/ExitType"; import { PieceId, pieceMap } from "../constants/Pieces"; +import { TrackType } from "../constants/TrackType"; import { Exit } from "./Exit"; import { ExternalNode } from "./ExternalNode"; import { InternalNode } from "./InternalNode"; +import { Piece } from "./Piece"; import { PlacedPiece } from "./PlacedPiece"; export class Cell { @@ -33,45 +35,72 @@ export class Cell { 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}`, - ); - } - } - } - }); + const piece: Piece = pieceMap[pieceId]; + + this.validatePiecePlacement(piece); this.placedPiece = { piece: piece.toPlacedPiece(this), id: pieceId, }; } + + private validatePiecePlacement(piece: Piece) { + const hasAnyConnection = Array.from(piece.tracks) + .map((track) => { + const trackExternalNodes = [ + this.getNodeAt(track.joinedPoints.firstPoint), + ]; + if (!(track.joinedPoints.secondPoint instanceof InternalNode)) { + trackExternalNodes.push( + this.getNodeAt(track.joinedPoints.secondPoint), + ); + } + return { + trackExternalNodes: trackExternalNodes, + trackType: track.type, + }; + }) + .some(({ trackExternalNodes, trackType }) => { + let isTrackConnected: boolean = false; + trackExternalNodes + .filter((node) => node.traverseBorder() instanceof Exit) + .forEach((node) => { + const exitType = (node.traverseBorder() as Exit).type; + isTrackConnected = true; + if ( + exitType !== ExitType.AMBIVALENT && + exitType.toString() !== trackType.toString() + ) { + throw Error( + `Unable to place piece, invalid exit type at direction ${node.direction}`, + ); + } + }); + + trackExternalNodes + .filter((node) => node.traverseBorder() instanceof ExternalNode) + .forEach((node) => { + const adjacentExternalNode = node.traverseBorder() as ExternalNode; + const adjacentTrack = + adjacentExternalNode.cell.placedPiece?.piece.findTrackForDirection( + adjacentExternalNode.direction, + ); + if (adjacentTrack !== undefined) { + isTrackConnected = true; + if (adjacentTrack.type !== trackType) { + throw Error( + `Unable to place piece next to another due to conflicting track types at ${node.direction}`, + ); + } + } + }); + + return isTrackConnected; + }); + + if (!hasAnyConnection) { + throw Error("No adjacent exit or piece available to connect to"); + } + } }