Disallow placing piece in places with invalid adjacent connections

pull/8/head
MiguelMLorente 2024-12-03 13:46:52 +01:00
parent 1ab3db8f67
commit b1d57ebfcd
5 changed files with 63 additions and 12 deletions

View File

@ -11,5 +11,4 @@ export * from "./types/ExternalNode";
export * from "./types/InternalNode";
export * from "./types/Piece";
export * from "./types/PlacedPiece";
export * from "./types/Node";
export * from "./BoardBuilder";

View File

@ -1,7 +1,10 @@
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 {
@ -30,8 +33,44 @@ 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}`,
);
}
}
}
});
this.placedPiece = {
piece: pieceMap[pieceId].toPlacedPiece(this),
piece: piece.toPlacedPiece(this),
id: pieceId,
};
}

View File

@ -1,4 +0,0 @@
import { ExternalNode } from "./ExternalNode";
import { InternalNode } from "./InternalNode";
export type Node = ExternalNode | InternalNode;

View File

@ -1,22 +1,25 @@
import { Direction } from "../constants/Direction";
import { TrackType } from "../constants/TrackType";
import { Cell } from "./Cell";
import { ExternalNode } from "./ExternalNode";
import { InternalNode } from "./InternalNode";
import { Node } from "./Node";
export class PlacedPiece {
tracks: Set<{
nodes: {
firstNode: Node;
secondNode: Node;
firstNode: ExternalNode;
secondNode: ExternalNode | InternalNode;
};
type: TrackType;
}>;
internalNode?: InternalNode;
cell: Cell;
constructor(
tracks: Set<{
nodes: { firstNode: Node; secondNode: Node };
nodes: {
firstNode: ExternalNode;
secondNode: ExternalNode | InternalNode;
};
type: TrackType;
}>,
internalNodes: InternalNode | undefined,
@ -26,4 +29,13 @@ export class PlacedPiece {
this.internalNode = internalNodes;
this.cell = cell;
}
public findTrackForDirection(direction: Direction) {
return Array.from(this.tracks).find(
(track) =>
track.nodes.firstNode.direction === direction ||
(track.nodes.secondNode instanceof ExternalNode &&
track.nodes.secondNode.direction === direction),
);
}
}

View File

@ -25,7 +25,12 @@ const BoardCell = (props: BoardCellProps) => {
const handleBoardCellClick = () => {
const selectedDie = dice.find((die) => die.isSelected);
if (!selectedDie) return;
try {
cell.placePiece(selectedDie.pieceId);
} catch (error) {
console.log(error);
return;
}
setDice(
dice.map((die) => {
return die !== selectedDie