From dbed4468c50b188a6845287e8ffb5154de02843a Mon Sep 17 00:00:00 2001 From: marti Date: Sat, 3 Jan 2026 00:00:36 +0100 Subject: [PATCH] Fix tile alignment: Enforce strict connection for multi-cell doors and fix exit reference logic --- src/engine/dungeon/DungeonGenerator.js | 47 +++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/engine/dungeon/DungeonGenerator.js b/src/engine/dungeon/DungeonGenerator.js index 756c142..9e77c4a 100644 --- a/src/engine/dungeon/DungeonGenerator.js +++ b/src/engine/dungeon/DungeonGenerator.js @@ -65,17 +65,17 @@ export class DungeonGenerator { return false; } - // Validate exit exists - const exitExists = this.availableExits.some( + // Find the full exit object from availableExits (so we have tileId, etc.) + const foundExit = this.availableExits.find( e => e.x === exitPoint.x && e.y === exitPoint.y && e.direction === exitPoint.direction ); - if (!exitExists) { + if (!foundExit) { console.warn("Invalid exit selected"); return false; } - this.selectedExit = exitPoint; + this.selectedExit = foundExit; // Draw next card this.currentCard = this.deck.draw(); @@ -150,7 +150,44 @@ export class DungeonGenerator { if (!this.currentCard || this.state !== PLACEMENT_STATE.PLACING_TILE) return false; const variant = this.currentCard.variants[this.placementRotation]; - return this.grid.canPlace(variant, this.placementX, this.placementY); + + // 1. Basic Grid Collision + if (!this.grid.canPlace(variant, this.placementX, this.placementY)) { + return false; + } + + // 2. Strict Door Alignment Check + if (this.selectedExit) { + // Identify the full "door" group (e.g., the pair of cells forming the exit) + // We look for other available exits on the same tile, facing the same way, and adjacent. + const sourceExits = this.availableExits.filter(e => + e.tileId === this.selectedExit.tileId && + e.direction === this.selectedExit.direction && + (Math.abs(e.x - this.selectedExit.x) + Math.abs(e.y - this.selectedExit.y)) <= 1 + ); + + // For every cell in the source door, the new tile MUST have a connecting exit + for (const source of sourceExits) { + // The coordinate where the new tile's exit should be + const targetPos = this.neighbor(source.x, source.y, source.direction); + const requiredDirection = this.opposite(source.direction); + + // Does the new tile provide an exit here? + const hasMatch = variant.exits.some(localExit => { + const gx = this.placementX + localExit.x; + const gy = this.placementY + localExit.y; + return gx === targetPos.x && + gy === targetPos.y && + localExit.direction === requiredDirection; + }); + + if (!hasMatch) { + return false; // Misalignment: New tile doesn't connect to all parts of the door + } + } + } + + return true; } cancelPlacement() {