/** * World coordinate placement and chaining for Diablo II levels. * * Resolves seamless adjacency along SEAMLESS_ADJACENCY and propagates coordinates * from anchor levels (seeded from Levels.txt), aligning automap bounding boxes * with zero gaps, zero overlaps, and zero tears. */ import type { WorldGraph, LevelRow, WorldEdge } from './world-graph.ts' import { assignGateSides, buildWorldGraph } from './world-graph.ts' export interface WorldOffset { levelId: number offsetX: number offsetY: number sizeX: number sizeY: number } interface AnchorSpec { readonly levelId: number readonly offsetX: number readonly offsetY: number readonly sizeX?: number readonly sizeY?: number } /** * Anchor level coordinates seeded from Levels.txt / level definitions. * Keyed by 0-based act index (0..4). */ export const ACT_ANCHORS: Readonly> = { // Act 1: Cold Plains (Level 3) at (1000, 1000) 0: [{ levelId: 3, offsetX: 1000, offsetY: 1000, sizeX: 80, sizeY: 80 }], // Act 2: Lut Gholein (Level 40) at (1000, 1000), Canyon of Magi (Level 46) at (2500, 1000) 1: [ { levelId: 40, offsetX: 1000, offsetY: 1000, sizeX: 56, sizeY: 56 }, { levelId: 46, offsetX: 2500, offsetY: 1000, sizeX: 80, sizeY: 80 }, ], // Act 3: Kurast Docks (Level 75) at (1000, 1000) 2: [{ levelId: 75, offsetX: 1000, offsetY: 1000, sizeX: 64, sizeY: 48 }], // Act 4: Pandemonium Fortress (Level 103) at (1000, 1000) 3: [{ levelId: 103, offsetX: 1000, offsetY: 1000, sizeX: 32, sizeY: 24 }], // Act 5: Harrogath (Level 109) at (1000, 1000), Bloody Foothills (Level 110) at (760, 1000) 4: [ { levelId: 109, offsetX: 1000, offsetY: 1000, sizeX: 40, sizeY: 40 }, { levelId: 110, offsetX: 760, offsetY: 1000, sizeX: 240, sizeY: 48 }, ], } /** Pre-baked canonical LevelRow records for all 136 game levels. */ export const CANONICAL_LEVEL_ROWS: readonly LevelRow[] = [ { "id": 1, "act": 0, "name": "Act 1 - Town", "drlgType": 2, "sizeX": 56, "sizeY": 40, "waypoint": 0, "position": 1, "portal": 1, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 2, "act": 0, "name": "Act 1 - Wilderness 1", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 8, 8, 8, 8, 0 ], "warp": [ -1, -1, -1, 0, 1, 2, 3, -1 ] }, { "id": 3, "act": 0, "name": "Act 1 - Wilderness 2", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 1, "position": 0, "portal": 1, "offsetX": 1000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 9, 9, 9, 9, 0 ], "warp": [ -1, -1, -1, 0, 1, 2, 3, -1 ] }, { "id": 4, "act": 0, "name": "Act 1 - Wilderness 3", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 2, "position": 0, "portal": 0, "offsetX": 1000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 10, 10, 10, 10, 0 ], "warp": [ -1, -1, -1, 0, 1, 2, 3, -1 ] }, { "id": 5, "act": 0, "name": "Act 1 - Wilderness 4", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 3, "position": 0, "portal": 1, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 10, 10, 10, 10, 0 ], "warp": [ -1, -1, -1, 0, 1, 2, 3, -1 ] }, { "id": 6, "act": 0, "name": "Act 1 - Wilderness 5", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 4, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 20, 11, 11, 11, 11, 0 ], "warp": [ -1, -1, 10, 0, 1, 2, 3, -1 ] }, { "id": 7, "act": 0, "name": "Act 1 - Wilderness 6", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 255, "position": 0, "portal": 1, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 12, 12, 12, 12, 0 ], "warp": [ -1, -1, -1, 0, 1, 2, 3, -1 ] }, { "id": 8, "act": 0, "name": "Act 1 - Cave 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1000, "depend": 0, "vis": [ 2, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 4, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 9, "act": 0, "name": "Act 1 - Cave 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1300, "depend": 0, "vis": [ 3, 0, 0, 0, 13, 0, 0, 0 ], "warp": [ 4, -1, -1, -1, 5, -1, -1, -1 ] }, { "id": 10, "act": 0, "name": "Act 1 - Cave 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1600, "depend": 0, "vis": [ 4, 5, 0, 0, 14, 0, 0, 0 ], "warp": [ 4, 4, -1, -1, 5, -1, -1, -1 ] }, { "id": 11, "act": 0, "name": "Act 1 - Cave 4", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1900, "depend": 0, "vis": [ 6, 0, 0, 0, 15, 0, 0, 0 ], "warp": [ 4, -1, -1, -1, 5, -1, -1, -1 ] }, { "id": 12, "act": 0, "name": "Act 1 - Cave 5", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 2200, "depend": 0, "vis": [ 7, 0, 0, 0, 16, 0, 0, 0 ], "warp": [ 4, -1, -1, -1, 5, -1, -1, -1 ] }, { "id": 13, "act": 0, "name": "Act 1 - Cave 2 Treasure", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 2500, "depend": 0, "vis": [ 0, 9, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 4, -1, -1, -1, -1, -1, -1 ] }, { "id": 14, "act": 0, "name": "Act 1 - Cave 3 Treasure", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 2624, "depend": 0, "vis": [ 0, 10, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 4, -1, -1, -1, -1, -1, -1 ] }, { "id": 15, "act": 0, "name": "Act 1 - Cave 4 Treasure", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 2748, "depend": 0, "vis": [ 0, 11, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 4, -1, -1, -1, -1, -1, -1 ] }, { "id": 16, "act": 0, "name": "Act 1 - Cave 5 Treasure", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 2872, "depend": 0, "vis": [ 0, 12, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 4, -1, -1, -1, -1, -1, -1 ] }, { "id": 17, "act": 0, "name": "Act 1 - Graveyard", "drlgType": 3, "sizeX": 40, "sizeY": 48, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 18, 19, 0, 0, 0, 0, 0, 0 ], "warp": [ 6, 7, -1, -1, -1, -1, -1, -1 ] }, { "id": 18, "act": 0, "name": "Act 1 - Crypt 1 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1000, "depend": 0, "vis": [ 17, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 19, "act": 0, "name": "Act 1 - Crypt 2 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1300, "depend": 0, "vis": [ 17, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 20, "act": 0, "name": "Act 1 - Tower 2", "drlgType": 2, "sizeX": 8, "sizeY": 8, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1600, "depend": 0, "vis": [ 6, 21, 0, 0, 0, 0, 0, 0 ], "warp": [ 11, 12, -1, -1, -1, -1, -1, -1 ] }, { "id": 21, "act": 0, "name": "Act 1 - Crypt 3 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1000, "depend": 0, "vis": [ 20, 22, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, 9, -1, -1, -1, -1, -1, -1 ] }, { "id": 22, "act": 0, "name": "Act 1 - Crypt 3 B", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1300, "depend": 0, "vis": [ 21, 23, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, 9, -1, -1, -1, -1, -1, -1 ] }, { "id": 23, "act": 0, "name": "Act 1 - Crypt 3 C", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1600, "depend": 0, "vis": [ 22, 24, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, 9, -1, -1, -1, -1, -1, -1 ] }, { "id": 24, "act": 0, "name": "Act 1 - Crypt 3 D", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1900, "depend": 0, "vis": [ 23, 25, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, 9, -1, -1, -1, -1, -1, -1 ] }, { "id": 25, "act": 0, "name": "Act 1 - Crypt 3 E", "drlgType": 2, "sizeX": 30, "sizeY": 30, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 2200, "depend": 0, "vis": [ 24, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 26, "act": 0, "name": "Act 1 - Monastery", "drlgType": 2, "sizeX": 64, "sizeY": 18, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1000, "depend": 0, "vis": [ 0, 27, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 27, "act": 0, "name": "Act 1 - Courtyard 1", "drlgType": 2, "sizeX": 56, "sizeY": 40, "waypoint": 5, "position": 0, "portal": 1, "offsetX": 0, "offsetY": -40, "depend": 26, "vis": [ 26, 28, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 28, "act": 0, "name": "Act 1 - Barracks", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 27, 29, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 14, -1, -1, -1, -1, -1, -1 ] }, { "id": 29, "act": 0, "name": "Act 1 - Jail 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 6, "position": 0, "portal": 1, "offsetX": 3500, "offsetY": 1000, "depend": 0, "vis": [ 28, 30, 0, 0, 0, 0, 0, 0 ], "warp": [ 13, 14, -1, -1, -1, -1, -1, -1 ] }, { "id": 30, "act": 0, "name": "Act 1 - Jail 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1300, "depend": 0, "vis": [ 29, 31, 0, 0, 0, 0, 0, 0 ], "warp": [ 13, 14, -1, -1, -1, -1, -1, -1 ] }, { "id": 31, "act": 0, "name": "Act 1 - Jail 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1600, "depend": 0, "vis": [ 30, 32, 0, 0, 0, 0, 0, 0 ], "warp": [ 13, 13, -1, -1, -1, -1, -1, -1 ] }, { "id": 32, "act": 0, "name": "Act 1 - Courtyard 2", "drlgType": 2, "sizeX": 18, "sizeY": 20, "waypoint": 7, "position": 0, "portal": 0, "offsetX": 4000, "offsetY": 1000, "depend": 0, "vis": [ 31, 33, 0, 0, 0, 0, 0, 0 ], "warp": [ 14, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 33, "act": 0, "name": "Act 1 - Cathedral", "drlgType": 2, "sizeX": 28, "sizeY": 34, "waypoint": 255, "position": 0, "portal": 1, "offsetX": -4, "offsetY": -34, "depend": 32, "vis": [ 32, 34, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 15, -1, -1, -1, -1, -1, -1 ] }, { "id": 34, "act": 0, "name": "Act 1 - Catacombs 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1000, "depend": 0, "vis": [ 33, 35, 0, 0, 0, 0, 0, 0 ], "warp": [ 16, 18, -1, -1, -1, -1, -1, -1 ] }, { "id": 35, "act": 0, "name": "Act 1 - Catacombs 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 8, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1300, "depend": 0, "vis": [ 34, 36, 0, 0, 0, 0, 0, 0 ], "warp": [ 17, 18, -1, -1, -1, -1, -1, -1 ] }, { "id": 36, "act": 0, "name": "Act 1 - Catacombs 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 1, "offsetX": 4500, "offsetY": 1600, "depend": 0, "vis": [ 35, 37, 0, 0, 0, 0, 0, 0 ], "warp": [ 17, 18, -1, -1, -1, -1, -1, -1 ] }, { "id": 37, "act": 0, "name": "Act 1 - Catacombs 4", "drlgType": 2, "sizeX": 22, "sizeY": 31, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1900, "depend": 0, "vis": [ 36, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 17, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 38, "act": 0, "name": "Act 1 - Tristram", "drlgType": 2, "sizeX": 43, "sizeY": 48, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 5000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 39, "act": 0, "name": "Act 1 - Moo Moo Farm", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 5000, "offsetY": 1148, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 40, "act": 1, "name": "Act 2 - Town", "drlgType": 2, "sizeX": 56, "sizeY": 56, "waypoint": 9, "position": 1, "portal": 1, "offsetX": 1000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 47, 47, 50, 0, 0, 0 ], "warp": [ -1, -1, 19, 20, 24, -1, -1, -1 ] }, { "id": 41, "act": 1, "name": "Act 2 - Desert 1", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 55, 55, 55, 55, 0, 0, 0, 0 ], "warp": [ 33, 34, 35, 36, -1, -1, -1, -1 ] }, { "id": 42, "act": 1, "name": "Act 2 - Desert 2", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 11, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 56, 56, 56, 56, 0, 0, 0, 0 ], "warp": [ 33, 34, 35, 36, -1, -1, -1, -1 ] }, { "id": 43, "act": 1, "name": "Act 2 - Desert 3", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 13, "position": 0, "portal": 1, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 62, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, 47, -1, -1, -1 ] }, { "id": 44, "act": 1, "name": "Act 2 - Desert 4", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 14, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 65, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, 50, -1, -1, -1, -1, -1 ] }, { "id": 45, "act": 1, "name": "Act 2 - Desert 5", "drlgType": 3, "sizeX": 32, "sizeY": 32, "waypoint": 255, "position": 0, "portal": 1, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 58, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 37, -1, -1, -1, -1, -1, -1 ] }, { "id": 46, "act": 1, "name": "Act 2 - Valley of the Kings", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 17, "position": 1, "portal": 1, "offsetX": 2500, "offsetY": 1000, "depend": 0, "vis": [ 0, 66, 67, 68, 69, 70, 71, 72 ], "warp": [ -1, 38, 39, 40, 41, 42, 43, 44 ] }, { "id": 47, "act": 1, "name": "Act 2 - Sewer 1 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1000, "depend": 0, "vis": [ 40, 40, 48, 0, 0, 0, 0, 0 ], "warp": [ 22, 21, 23, -1, -1, -1, -1, -1 ] }, { "id": 48, "act": 1, "name": "Act 2 - Sewer 1 B", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 10, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1300, "depend": 0, "vis": [ 47, 0, 49, 0, 0, 0, 0, 0 ], "warp": [ 22, -1, 23, -1, -1, -1, -1, -1 ] }, { "id": 49, "act": 1, "name": "Act 2 - Sewer 1 C", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1600, "depend": 0, "vis": [ 48, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 22, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 50, "act": 1, "name": "Act 2 - Harem", "drlgType": 2, "sizeX": 16, "sizeY": 19, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1000, "depend": 0, "vis": [ 40, 0, 51, 51, 0, 0, 0, 0 ], "warp": [ 25, -1, 28, 29, -1, -1, -1, -1 ] }, { "id": 51, "act": 1, "name": "Act 2 - Corrupt Harem 1", "drlgType": 1, "sizeX": 100, "sizeY": 100, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1119, "depend": 0, "vis": [ 50, 50, 52, 52, 0, 0, 0, 0 ], "warp": [ 26, 27, 28, 29, -1, -1, -1, -1 ] }, { "id": 52, "act": 1, "name": "Act 2 - Basement 1", "drlgType": 1, "sizeX": 100, "sizeY": 100, "waypoint": 15, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1319, "depend": 0, "vis": [ 51, 51, 53, 53, 0, 0, 0, 0 ], "warp": [ 26, 27, 32, 32, -1, -1, -1, -1 ] }, { "id": 53, "act": 1, "name": "Act 2 - Basement 2", "drlgType": 1, "sizeX": 100, "sizeY": 100, "waypoint": 255, "position": 0, "portal": 1, "offsetX": 2000, "offsetY": 1519, "depend": 0, "vis": [ 52, 52, 54, 54, 0, 0, 0, 0 ], "warp": [ 30, 31, 32, 32, -1, -1, -1, -1 ] }, { "id": 54, "act": 1, "name": "Act 2 - Basement 3", "drlgType": 1, "sizeX": 100, "sizeY": 100, "waypoint": 255, "position": 1, "portal": 1, "offsetX": 2000, "offsetY": 1719, "depend": 0, "vis": [ 53, 53, 0, 0, 0, 0, 0, 0 ], "warp": [ 30, 31, -1, -1, -1, -1, -1, -1 ] }, { "id": 55, "act": 1, "name": "Act 2 - Tomb 1 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1000, "depend": 0, "vis": [ 41, 0, 0, 0, 59, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, 46, -1, -1, -1 ] }, { "id": 56, "act": 1, "name": "Act 2 - Tomb 2 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1300, "depend": 0, "vis": [ 42, 0, 0, 0, 57, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, 46, -1, -1, -1 ] }, { "id": 57, "act": 1, "name": "Act 2 - Tomb 2 B", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 12, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1600, "depend": 0, "vis": [ 56, 0, 0, 0, 60, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, 46, -1, -1, -1 ] }, { "id": 58, "act": 1, "name": "Act 2 - Tomb 3 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1900, "depend": 0, "vis": [ 45, 0, 0, 0, 61, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, 46, -1, -1, -1 ] }, { "id": 59, "act": 1, "name": "Act 2 - Tomb 1 Treasure", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 2200, "depend": 0, "vis": [ 55, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 60, "act": 1, "name": "Act 2 - Tomb 2 Treasure", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 2500, "depend": 0, "vis": [ 57, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 61, "act": 1, "name": "Act 2 - Tomb 3 Treasure", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 2800, "depend": 0, "vis": [ 58, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 62, "act": 1, "name": "Act 2 - Lair 1 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1000, "depend": 0, "vis": [ 43, 63, 0, 0, 0, 0, 0, 0 ], "warp": [ 48, 49, -1, -1, -1, -1, -1, -1 ] }, { "id": 63, "act": 1, "name": "Act 2 - Lair 1 B", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1300, "depend": 0, "vis": [ 62, 64, 0, 0, 0, 0, 0, 0 ], "warp": [ 48, 49, -1, -1, -1, -1, -1, -1 ] }, { "id": 64, "act": 1, "name": "Act 2 - Lair 1 Treasure", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1600, "depend": 0, "vis": [ 63, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 48, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 65, "act": 1, "name": "Act 2 - Sewer 2 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4000, "offsetY": 1000, "depend": 0, "vis": [ 44, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 22, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 66, "act": 1, "name": "Act 2 - Tomb Tal 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1000, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 67, "act": 1, "name": "Act 2 - Tomb Tal 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1300, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 68, "act": 1, "name": "Act 2 - Tomb Tal 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1600, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 69, "act": 1, "name": "Act 2 - Tomb Tal 4", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 1900, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 70, "act": 1, "name": "Act 2 - Tomb Tal 5", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 2200, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 71, "act": 1, "name": "Act 2 - Tomb Tal 6", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 2500, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 72, "act": 1, "name": "Act 2 - Tomb Tal 7", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4500, "offsetY": 2800, "depend": 0, "vis": [ 46, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 45, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 73, "act": 1, "name": "Act 2 - Duriel's Lair", "drlgType": 2, "sizeX": 32, "sizeY": 47, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 4500, "offsetY": 3100, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 74, "act": 1, "name": "Act 2 - Arcane", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 16, "position": 1, "portal": 1, "offsetX": 5000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 75, "act": 2, "name": "Act 3 - Town", "drlgType": 2, "sizeX": 64, "sizeY": 48, "waypoint": 18, "position": 1, "portal": 0, "offsetX": 1000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 76, "act": 2, "name": "Act 3 - Jungle 1", "drlgType": 3, "sizeX": 64, "sizeY": 192, "waypoint": 19, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 84, 85, 0, 0, 0, 0, 0, 0 ], "warp": [ 51, 51, -1, -1, -1, -1, -1, -1 ] }, { "id": 77, "act": 2, "name": "Act 3 - Jungle 2", "drlgType": 3, "sizeX": 64, "sizeY": 192, "waypoint": 20, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 78, "act": 2, "name": "Act 3 - Jungle 3", "drlgType": 3, "sizeX": 64, "sizeY": 192, "waypoint": 21, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 86, 88, 0, 0, 0, 0, 0, 0 ], "warp": [ 53, 54, -1, -1, -1, -1, -1, -1 ] }, { "id": 79, "act": 2, "name": "Act 3 - Kurast 1", "drlgType": 3, "sizeX": 80, "sizeY": 64, "waypoint": 22, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 80, "act": 2, "name": "Act 3 - Kurast 2", "drlgType": 3, "sizeX": 80, "sizeY": 64, "waypoint": 23, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 92, 92, 94, 95, 0, 0, 0, 0 ], "warp": [ 57, 57, 61, 61, -1, -1, -1, -1 ] }, { "id": 81, "act": 2, "name": "Act 3 - Kurast 3", "drlgType": 3, "sizeX": 80, "sizeY": 64, "waypoint": 24, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 92, 92, 96, 97, 0, 0, 0, 0 ], "warp": [ 57, 57, 61, 61, -1, -1, -1, -1 ] }, { "id": 82, "act": 2, "name": "Act 3 - Kurast 4", "drlgType": 3, "sizeX": 48, "sizeY": 16, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 98, 99, 0, 0, 0, 0 ], "warp": [ -1, -1, 61, 61, -1, -1, -1, -1 ] }, { "id": 83, "act": 2, "name": "Act 3 - Travincal", "drlgType": 3, "sizeX": 64, "sizeY": 64, "waypoint": 25, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 100, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 64, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 84, "act": 2, "name": "Act 3 - Spider 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1000, "depend": 0, "vis": [ 0, 76, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 52, -1, -1, -1, -1, -1, -1 ] }, { "id": 85, "act": 2, "name": "Act 3 - Spider 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1300, "depend": 0, "vis": [ 0, 76, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 52, -1, -1, -1, -1, -1, -1 ] }, { "id": 86, "act": 2, "name": "Act 3 - Dungeon 1 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1000, "depend": 0, "vis": [ 87, 78, 0, 0, 0, 0, 0, 0 ], "warp": [ 56, 55, -1, -1, -1, -1, -1, -1 ] }, { "id": 87, "act": 2, "name": "Act 3 - Dungeon 1 B", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1300, "depend": 0, "vis": [ 90, 86, 0, 0, 0, 0, 0, 0 ], "warp": [ 56, 55, -1, -1, -1, -1, -1, -1 ] }, { "id": 88, "act": 2, "name": "Act 3 - Dungeon 2 A", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1600, "depend": 0, "vis": [ 89, 78, 0, 0, 0, 0, 0, 0 ], "warp": [ 56, 55, -1, -1, -1, -1, -1, -1 ] }, { "id": 89, "act": 2, "name": "Act 3 - Dungeon 2 B", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1900, "depend": 0, "vis": [ 91, 88, 0, 0, 0, 0, 0, 0 ], "warp": [ 56, 55, -1, -1, -1, -1, -1, -1 ] }, { "id": 90, "act": 2, "name": "Act 3 - Dungeon 1 Treasure", "drlgType": 2, "sizeX": 40, "sizeY": 40, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2200, "depend": 0, "vis": [ 0, 87, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 55, -1, -1, -1, -1, -1, -1 ] }, { "id": 91, "act": 2, "name": "Act 3 - Dungeon 2 Treasure", "drlgType": 2, "sizeX": 40, "sizeY": 40, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2340, "depend": 0, "vis": [ 0, 89, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 55, -1, -1, -1, -1, -1, -1 ] }, { "id": 92, "act": 2, "name": "Act 3 - Sewer 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1000, "depend": 0, "vis": [ 80, 80, 81, 81, 93, 0, 0, 0 ], "warp": [ 58, 59, 58, 59, 60, -1, -1, -1 ] }, { "id": 93, "act": 2, "name": "Act 3 - Sewer 2", "drlgType": 2, "sizeX": 18, "sizeY": 22, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1300, "depend": 0, "vis": [ 92, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 58, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 94, "act": 2, "name": "Act 3 - Temple 1", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1000, "depend": 0, "vis": [ 80, 80, 0, 0, 0, 0, 0, 0 ], "warp": [ 62, 63, -1, -1, -1, -1, -1, -1 ] }, { "id": 95, "act": 2, "name": "Act 3 - Temple 2", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1124, "depend": 0, "vis": [ 80, 80, 0, 0, 0, 0, 0, 0 ], "warp": [ 62, 63, -1, -1, -1, -1, -1, -1 ] }, { "id": 96, "act": 2, "name": "Act 3 - Temple 3", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1248, "depend": 0, "vis": [ 81, 81, 0, 0, 0, 0, 0, 0 ], "warp": [ 62, 63, -1, -1, -1, -1, -1, -1 ] }, { "id": 97, "act": 2, "name": "Act 3 - Temple 4", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1372, "depend": 0, "vis": [ 81, 81, 0, 0, 0, 0, 0, 0 ], "warp": [ 62, 63, -1, -1, -1, -1, -1, -1 ] }, { "id": 98, "act": 2, "name": "Act 3 - Temple 5", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1496, "depend": 0, "vis": [ 82, 82, 0, 0, 0, 0, 0, 0 ], "warp": [ 62, 63, -1, -1, -1, -1, -1, -1 ] }, { "id": 99, "act": 2, "name": "Act 3 - Temple 6", "drlgType": 2, "sizeX": 24, "sizeY": 24, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1620, "depend": 0, "vis": [ 82, 82, 0, 0, 0, 0, 0, 0 ], "warp": [ 62, 63, -1, -1, -1, -1, -1, -1 ] }, { "id": 100, "act": 2, "name": "Act 3 - Mephisto 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1000, "depend": 0, "vis": [ 101, 101, 83, 83, 0, 0, 0, 0 ], "warp": [ 67, 68, 65, 66, -1, -1, -1, -1 ] }, { "id": 101, "act": 2, "name": "Act 3 - Mephisto 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 26, "position": 0, "portal": 0, "offsetX": 3500, "offsetY": 1300, "depend": 0, "vis": [ 102, 102, 100, 100, 0, 0, 0, 0 ], "warp": [ 67, 68, 65, 66, -1, -1, -1, -1 ] }, { "id": 102, "act": 2, "name": "Act 3 - Mephisto 3", "drlgType": 2, "sizeX": 41, "sizeY": 29, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 3500, "offsetY": 1600, "depend": 0, "vis": [ 0, 0, 101, 101, 0, 0, 0, 0 ], "warp": [ -1, -1, 65, 66, -1, -1, -1, -1 ] }, { "id": 103, "act": 3, "name": "Act 4 - Town", "drlgType": 2, "sizeX": 32, "sizeY": 24, "waypoint": 27, "position": 1, "portal": 0, "offsetX": 1000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 104, "act": 3, "name": "Act 4 - Mesa 1", "drlgType": 3, "sizeX": 80, "sizeY": 64, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 105, "act": 3, "name": "Act 4 - Mesa 2", "drlgType": 3, "sizeX": 64, "sizeY": 80, "waypoint": 255, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 106, "act": 3, "name": "Act 4 - Mesa 3", "drlgType": 3, "sizeX": 80, "sizeY": 64, "waypoint": 28, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 107, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 69, -1, -1, -1, -1, -1, -1 ] }, { "id": 107, "act": 3, "name": "Act 4 - Lava 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 29, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 106, 108, 0, 0, 0, 0, 0, 0 ], "warp": [ 70, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 108, "act": 3, "name": "Act 4 - Diablo 1", "drlgType": 3, "sizeX": 120, "sizeY": 120, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 1500, "offsetY": 1000, "depend": 0, "vis": [ 107, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 109, "act": 4, "name": "Act 5 - Town", "drlgType": 2, "sizeX": 40, "sizeY": 40, "waypoint": 30, "position": 1, "portal": 0, "offsetX": 1000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 110, "act": 4, "name": "Act 5 - Siege 1", "drlgType": 3, "sizeX": 240, "sizeY": 48, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 760, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 111, "act": 4, "name": "Act 5 - Barricade 1", "drlgType": 3, "sizeX": -1, "sizeY": -1, "waypoint": 31, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 112, "act": 4, "name": "Act 5 - Barricade 2", "drlgType": 3, "sizeX": -1, "sizeY": -1, "waypoint": 32, "position": 0, "portal": 0, "offsetX": -1, "offsetY": -1, "depend": 0, "vis": [ 0, 0, 113, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, 71, -1, -1, -1, -1, -1 ] }, { "id": 113, "act": 4, "name": "Act 5 - Ice Cave 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 33, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1000, "depend": 0, "vis": [ 112, 115, 114, 0, 0, 0, 0, 0 ], "warp": [ 73, 74, 75, -1, -1, -1, -1, -1 ] }, { "id": 114, "act": 4, "name": "Act 5 - Ice Cave 1A", "drlgType": 1, "sizeX": 64, "sizeY": 64, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1300, "depend": 0, "vis": [ 113, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 73, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 115, "act": 4, "name": "Act 5 - Ice Cave 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 34, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1464, "depend": 0, "vis": [ 113, 117, 116, 0, 0, 0, 0, 0 ], "warp": [ 73, 74, 75, -1, -1, -1, -1, -1 ] }, { "id": 116, "act": 4, "name": "Act 5 - Ice Cave 2A", "drlgType": 1, "sizeX": 32, "sizeY": 32, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1764, "depend": 0, "vis": [ 115, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 73, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 117, "act": 4, "name": "Act 5 - Barricade Snow", "drlgType": 3, "sizeX": 128, "sizeY": 80, "waypoint": 36, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 1896, "depend": 0, "vis": [ 115, 0, 118, 0, 0, 0, 0, 0 ], "warp": [ 72, -1, 71, -1, -1, -1, -1, -1 ] }, { "id": 118, "act": 4, "name": "Act 5 - Ice Cave 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 37, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2076, "depend": 0, "vis": [ 117, 120, 119, 0, 0, 0, 0, 0 ], "warp": [ 73, 74, 75, -1, -1, -1, -1, -1 ] }, { "id": 119, "act": 4, "name": "Act 5 - Ice Cave 3A", "drlgType": 1, "sizeX": 32, "sizeY": 32, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2376, "depend": 0, "vis": [ 118, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 73, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 120, "act": 4, "name": "Act 5 - Mountain Top", "drlgType": 2, "sizeX": 20, "sizeY": 28, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2508, "depend": 0, "vis": [ 118, 128, 0, 0, 0, 0, 0, 0 ], "warp": [ 79, 80, -1, -1, -1, -1, -1, -1 ] }, { "id": 121, "act": 4, "name": "Act 5 - Temple Entrance", "drlgType": 2, "sizeX": 22, "sizeY": 27, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 2000, "offsetY": 2636, "depend": 0, "vis": [ 0, 122, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, 76, -1, -1, -1, -1, -1, -1 ] }, { "id": 122, "act": 4, "name": "Act 5 - Temple 1", "drlgType": 1, "sizeX": 80, "sizeY": 80, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2763, "depend": 0, "vis": [ 121, 123, 0, 0, 0, 0, 0, 0 ], "warp": [ 78, 77, -1, -1, -1, -1, -1, -1 ] }, { "id": 123, "act": 4, "name": "Act 5 - Temple 2", "drlgType": 1, "sizeX": 80, "sizeY": 80, "waypoint": 35, "position": 0, "portal": 0, "offsetX": 2000, "offsetY": 2943, "depend": 0, "vis": [ 122, 124, 0, 0, 0, 0, 0, 0 ], "warp": [ 78, 77, -1, -1, -1, -1, -1, -1 ] }, { "id": 124, "act": 4, "name": "Act 5 - Temple Boss", "drlgType": 2, "sizeX": 84, "sizeY": 84, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 1000, "depend": 0, "vis": [ 123, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 78, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 125, "act": 4, "name": "Act 5 - Hell 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 2500, "offsetY": 1184, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 126, "act": 4, "name": "Act 5 - Hell 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 2500, "offsetY": 1484, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 127, "act": 4, "name": "Act 5 - Hell 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 2500, "offsetY": 1784, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 128, "act": 4, "name": "Act 5 - Baal Temple 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 2084, "depend": 0, "vis": [ 120, 129, 0, 0, 0, 0, 0, 0 ], "warp": [ 81, 82, -1, -1, -1, -1, -1, -1 ] }, { "id": 129, "act": 4, "name": "Act 5 - Baal Temple 2", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 38, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 2384, "depend": 0, "vis": [ 128, 130, 0, 0, 0, 0, 0, 0 ], "warp": [ 81, 82, -1, -1, -1, -1, -1, -1 ] }, { "id": 130, "act": 4, "name": "Act 5 - Baal Temple 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 2500, "offsetY": 2684, "depend": 0, "vis": [ 129, 131, 0, 0, 0, 0, 0, 0 ], "warp": [ 81, 82, -1, -1, -1, -1, -1, -1 ] }, { "id": 131, "act": 4, "name": "Act 5 - Throne Room", "drlgType": 2, "sizeX": 40, "sizeY": 52, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 3000, "offsetY": 1000, "depend": 0, "vis": [ 130, 132, 0, 0, 0, 0, 0, 0 ], "warp": [ 81, 82, -1, -1, -1, -1, -1, -1 ] }, { "id": 132, "act": 4, "name": "Act 5 - World Stone", "drlgType": 2, "sizeX": 55, "sizeY": 55, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 3000, "offsetY": 1152, "depend": 0, "vis": [ 131, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 81, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 133, "act": 4, "name": "Act 5 - Pandemonium 1", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 4000, "offsetY": 1500, "depend": 0, "vis": [ 17, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ 8, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 134, "act": 4, "name": "Act 5 - Pandemonium 2", "drlgType": 3, "sizeX": 80, "sizeY": 80, "waypoint": 255, "position": 1, "portal": 1, "offsetX": 4000, "offsetY": 1700, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 135, "act": 4, "name": "Act 5 - Pandemonium 3", "drlgType": 1, "sizeX": 200, "sizeY": 200, "waypoint": 255, "position": 1, "portal": 0, "offsetX": 4000, "offsetY": 2884, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] }, { "id": 136, "act": 4, "name": "Act 5 - Pandemonium Finale", "drlgType": 2, "sizeX": 43, "sizeY": 48, "waypoint": 255, "position": 0, "portal": 0, "offsetX": 5000, "offsetY": 1000, "depend": 0, "vis": [ 0, 0, 0, 0, 0, 0, 0, 0 ], "warp": [ -1, -1, -1, -1, -1, -1, -1, -1 ] } ] /** Helper to derive dimensions for a level in world coordinates. */ export function getLevelDimensions(levelId: number, row?: LevelRow): { sizeX: number; sizeY: number } { if (levelId === 111) return { sizeX: 58, sizeY: 155 } if (levelId === 112) return { sizeX: 58, sizeY: 154 } if (row && row.sizeX > 0 && row.sizeY > 0) { return { sizeX: row.sizeX, sizeY: row.sizeY } } return { sizeX: 80, sizeY: 80 } } /** * Resolve global world coordinates for all levels in an act. * * Chaining traverses contiguous outdoor levels along SEAMLESS_ADJACENCY from * anchor levels (Cold Plains, Lut Gholein, Kurast Docks, Pandemonium Fortress, * Harrogath / Bloody Foothills), propagating offsets according to seam sides * so that adjacent levels touch with zero gaps and zero overlaps. * * @param act - The act number (1..5 or 0..4). * @param seed - Act layout seed for gate side assignment. * @param graph - Optional world graph; when omitted, builds from canonical level definitions. * @returns Map from levelId to WorldOffset. */ function doRectanglesOverlap(a: WorldOffset, b: WorldOffset): boolean { return ( a.offsetX < b.offsetX + b.sizeX && a.offsetX + a.sizeX > b.offsetX && a.offsetY < b.offsetY + b.sizeY && a.offsetY + a.sizeY > b.offsetY ) } function computeOffsetsForGraph( activeGraph: WorldGraph, targetAct: number, ): Map { const actLevels = Array.from(activeGraph.levels.values()).filter(l => l.act === targetAct) const levelMap = new Map(actLevels.map(l => [l.id, l])) const result = new Map() const queue: number[] = [] // 1. Seed anchor levels const anchors = ACT_ANCHORS[targetAct] ?? [] for (const anchor of anchors) { if (!levelMap.has(anchor.levelId)) continue const row = levelMap.get(anchor.levelId) const dims = getLevelDimensions(anchor.levelId, row) const offset: WorldOffset = { levelId: anchor.levelId, offsetX: anchor.offsetX, offsetY: anchor.offsetY, sizeX: anchor.sizeX ?? dims.sizeX, sizeY: anchor.sizeY ?? dims.sizeY, } result.set(anchor.levelId, offset) queue.push(anchor.levelId) } // 2. BFS propagation along seamless adjacency while (queue.length > 0) { const currentId = queue.shift()! const current = result.get(currentId)! const edges = activeGraph.edges.filter(e => e.from === currentId && e.kind === 'seamless') for (const edge of edges) { const nextId = edge.to if (result.has(nextId) || !levelMap.has(nextId)) continue const nextRow = levelMap.get(nextId) const nextDims = getLevelDimensions(nextId, nextRow) let nextOffsetX: number let nextOffsetY: number // Ground-truth Act 5 barricade corridor alignment matching ka.ma0 Layer 79: // Level 110 at (760, 1000) West gate connects to Level 111 (width 58) -> offset X = 702 // Level 111 connects North to Level 112 (width 58) -> offset X = 702 // Recorded cluster: X in [702..759], Y in [717..1026] if (currentId === 110 && nextId === 111) { nextOffsetX = current.offsetX - nextDims.sizeX // 760 - 58 = 702 nextOffsetY = 871 } else if (currentId === 111 && nextId === 112) { nextOffsetX = 702 nextOffsetY = current.offsetY - nextDims.sizeY // 871 - 154 = 717 } else { switch (edge.sideFrom) { case 'east': nextOffsetX = current.offsetX + current.sizeX nextOffsetY = current.offsetY + Math.floor((current.sizeY - nextDims.sizeY) / 2) break case 'west': nextOffsetX = current.offsetX - nextDims.sizeX nextOffsetY = current.offsetY + Math.floor((current.sizeY - nextDims.sizeY) / 2) break case 'south': nextOffsetX = current.offsetX + Math.floor((current.sizeX - nextDims.sizeX) / 2) nextOffsetY = current.offsetY + current.sizeY break case 'north': nextOffsetX = current.offsetX + Math.floor((current.sizeX - nextDims.sizeX) / 2) nextOffsetY = current.offsetY - nextDims.sizeY break default: nextOffsetX = current.offsetX + current.sizeX nextOffsetY = current.offsetY break } } result.set(nextId, { levelId: nextId, offsetX: nextOffsetX, offsetY: nextOffsetY, sizeX: nextDims.sizeX, sizeY: nextDims.sizeY, }) queue.push(nextId) } } // 3. Isolated independent levels (depend === 0): keep static offsets from Levels.txt for (const row of actLevels) { if (result.has(row.id) || (row.depend && row.depend > 0)) continue const dims = getLevelDimensions(row.id, row) const ox = row.offsetX !== -1 ? row.offsetX : 2000 const oy = row.offsetY !== -1 ? row.offsetY : 1000 + row.id * 50 result.set(row.id, { levelId: row.id, offsetX: ox, offsetY: oy, sizeX: dims.sizeX, sizeY: dims.sizeY, }) } // 4. Dependent levels (row.depend > 0): resolve relative to parent origin let resolvedAny = true while (resolvedAny) { resolvedAny = false for (const row of actLevels) { if (result.has(row.id)) continue if (row.depend > 0 && result.has(row.depend)) { const parent = result.get(row.depend)! const dims = getLevelDimensions(row.id, row) const relX = row.offsetX !== -1 ? row.offsetX : 0 const relY = row.offsetY !== -1 ? row.offsetY : 0 result.set(row.id, { levelId: row.id, offsetX: parent.offsetX + relX, offsetY: parent.offsetY + relY, sizeX: dims.sizeX, sizeY: dims.sizeY, }) resolvedAny = true } } } // 5. Fallback for any unplaced orphan levels (e.g. broken depend references) for (const row of actLevels) { if (result.has(row.id)) continue const dims = getLevelDimensions(row.id, row) const ox = row.offsetX !== -1 ? row.offsetX : 2000 const oy = row.offsetY !== -1 ? row.offsetY : 1000 + row.id * 50 result.set(row.id, { levelId: row.id, offsetX: ox, offsetY: oy, sizeX: dims.sizeX, sizeY: dims.sizeY, }) } return result } function hasPlacementOverlap(offsets: Map): boolean { const placed = Array.from(offsets.values()) for (let i = 0; i < placed.length; i++) { for (let j = i + 1; j < placed.length; j++) { if (doRectanglesOverlap(placed[i]!, placed[j]!)) return true } } return false } /** * Resolve global world coordinates for all levels in an act. * * Chaining traverses contiguous outdoor levels along SEAMLESS_ADJACENCY from * anchor levels (Cold Plains, Lut Gholein, Kurast Docks, Pandemonium Fortress, * Harrogath / Bloody Foothills), propagating offsets according to seam sides * so that adjacent levels touch with zero gaps and zero overlaps. * * @param act - The act number (1..5 or 0..4). * @param seed - Act layout seed for gate side assignment. * @param graph - Optional world graph; when omitted, builds from canonical level definitions. * @returns Map from levelId to WorldOffset. */ export function resolveWorldOffsets( act: number, seed: number, graph?: WorldGraph, ): Map { const targetAct = act >= 1 && act <= 5 ? act - 1 : (act >= 0 && act < 5 ? act : 0) // If graph is provided and already has gate sides assigned, use it directly if (graph && !graph.edges.some(e => e.kind === 'seamless' && e.sideFrom === null)) { return computeOffsetsForGraph(graph, targetAct) } const baseGraph = graph ?? buildWorldGraph(CANONICAL_LEVEL_ROWS) const maxAttempts = 64 let fallbackOffsets: Map | null = null for (let attempt = 0; attempt < maxAttempts; attempt++) { const attemptSeed = attempt === 0 ? seed : ((seed + attempt * 7919) >>> 0) const activeGraph = assignGateSides(baseGraph, attemptSeed) const offsets = computeOffsetsForGraph(activeGraph, targetAct) if (!fallbackOffsets) { fallbackOffsets = offsets } if (!hasPlacementOverlap(offsets)) { return offsets } } return fallbackOffsets! }