diff --git a/data/json/terrain.json b/data/json/terrain.json index dcc7d78..4a68760 100644 --- a/data/json/terrain.json +++ b/data/json/terrain.json @@ -1 +1 @@ -{"_comment":"Static land/water mask. SAILABLE WATER = the map's own PATHING MAP (data/extracted/war3map.wpm, bit 0x40 = no-water, 4x4 32u subcells per 128u tile, majority vote): the engine's truth for where ships could actually sail in the original. This REPLACES the minimap NON-BLUE colour key (~0.66 water), which over-watered: green 'shallow' paint is often visually-wet-but-UNSAILABLE, merging lanes the real map separates (owner-reported 2026-07-08: the NE lane must NOT merge into the east-edge lane; the wpm separates them). The wpm reads ~0.55 sailable over the playable crop and all 26 known anchors (HQs, harbours, spawns, lane waypoints) sit sailable. The ONLY additions on top of the raw wpm grid are MINIMAL 1-cell connectivity necks (so every shop + dock/spawn reaches the sea and the two bases stay water-connected) PLUS the two owner-approved WEST sail-around island moats (Swedish Lumber Mill, Goblin Potion Dealer: land core + thin 1-cell navigable ring + EXACTLY ONE entrance; deterministic post-step). water=true is ship-navigable. The OPTIONAL `depth` field (0=land,1=deep,2=shallow,3=pink) is additive render metadata the SIM IGNORES; the minimap colours band each FINAL water cell so a client paints the water shades like the original. Regenerate with: make terrain (tools/extractor/terrain.py; pure stdlib, reads wpm+w3e+PNG, no venv). yOrientation 'top-down' means rle row 0 is the NORTH (max-Y) edge.","source":"data/extracted/war3map.wpm (pathing map, bit 0x40=no-water; THE sailability authority) + data/extracted/war3map.w3e (grid geometry) + data/reference/war3mapMap.png (depth render metadata only)","target":"the original map's enforced ship-pathing (wpm no-water), cropped to the playable rectangle","rule":"water = wpm NOT-no-water majority over the 16 32u subcells per 128u tile, MINUS singleton speckle, PLUS minimal 1-cell connectivity necks (Dijkstra cost 1 water / 30 land) for shops, docks/spawns and base-to-base, PLUS the two carved WEST sail-around island moats (compact land core + thin 1-cell water ring + exactly one entrance) around the Swedish Lumber Mill and Goblin Potion Dealer shops. depth sub-classifies FINAL water cells from the minimap colours for RENDER only: DEEP (R-B>35 AND R>=G), PINK (R>150 AND B>120 AND R-G>15), else SHALLOW; a water cell whose pixels read land-blue falls back to SHALLOW.","playableBounds":{"minX":-5376.0,"minY":-7424.0,"maxX":4864.0,"maxY":6912.0},"bounds":{"minX":-5440.0,"minY":-7488.0,"maxX":4928.0,"maxY":6976.0},"cols":81,"rows":113,"cellSizeX":128.0,"cellSizeY":128.0,"yOrientation":"top-down","yOrientationNote":"rle row 0 = max-Y (north); last row = min-Y (south). col 0 = min-X (west). col=floor((x-minX)/cellSizeX), row=floor((maxY-y)/cellSizeY). The minimap is north-up; tiles are sampled at their world centers via the content-box registration, emit row 0 = north, matching sim isWater.","rleFormat":"water[r] = [leadingValue, run0, run1, ...]; runs alternate from leadingValue (0=land,1=water) and sum to cols.","depthRleFormat":"OPTIONAL render metadata, the sim IGNORES it. depth[r] = [value0, run0, value1, run1, ...] (explicit value per run; values 0=land, 1=deep, 2=shallow, 3=pink; runs sum to cols). depth[r][col]>0 IFF water[r][col]==1 (exactly consistent with the authoritative `water` mask). Carved necks/moats with no minimap colour emit as shallow (2).","waterFraction":0.552824,"validation":{"hqsOnWater":"2/2","harboursOnWater":"4/4","playerSpawnsOnWater":"12/12","lanes":["south-west: spawnWater=True connToEnemyHQ=True","south-east: spawnWater=True connToEnemyHQ=True","north-west: spawnWater=True connToEnemyHQ=True","north-east: spawnWater=True connToEnemyHQ=True"],"basesConnected":true,"shopsReachable":"16/16","shopReach":["Swedish Lumber Mill: reachable=True nearestSeaCells=1","Goblin Potion Dealer: reachable=True nearestSeaCells=1","Elven Library: reachable=True nearestSeaCells=0","Ship Wreck: reachable=True nearestSeaCells=0","Elven Library: reachable=True nearestSeaCells=2","Ale Brewery: reachable=True nearestSeaCells=1","Equipment Merchant: reachable=True nearestSeaCells=1","Heavy Weapons Merchant: reachable=True nearestSeaCells=1","Weapons Merchant: reachable=True nearestSeaCells=2","Equipment Merchant: reachable=True nearestSeaCells=1","Bill (Trade Master): reachable=True nearestSeaCells=1","Pirate Boat Merchant: reachable=True nearestSeaCells=0","Will (Trade Master): reachable=True nearestSeaCells=2","Weapons Merchant: reachable=True nearestSeaCells=2","Heavy Weapons Merchant: reachable=True nearestSeaCells=2","Goblin Bomb Shop: reachable=True nearestSeaCells=0"],"repairRegionsReachable":"2/2","repairRegionReach":["Repair_Station_South: reachable=True","Repair_Station_North: reachable=True"],"waterFraction":0.5528,"eastThirdWaterRun":"median=4.0 mean=5.40 count=248","bottomRightWaterRun":"median=3.0 mean=3.77 count=90","necks":{"basePlatformCellsAdded":0,"connectivityNeckCellsAdded":0,"shopNeckCellsAdded":2,"repairRegionNeckCellsAdded":0,"waterFractionBefore":0.5527,"waterFractionAfter":0.5529,"shopsReachable":"16/16","repairRegionsReachable":"2/2","singletonCellsDropped":4,"westIslandLoops":{"Swedish Lumber Mill":{"shopCell":[6,61],"anchor":[4,61],"shopInCore":true,"shopInRing":false,"shopOnLand":true,"cycleLen":24,"entranceCells":[[4,65]],"entrances":1,"cellsChanged":44},"Goblin Potion Dealer":{"shopCell":[3,96],"anchor":[3,94],"shopInCore":true,"shopInRing":false,"shopOnLand":true,"cycleLen":24,"entranceCells":[[0,98]],"entrances":1,"cellsChanged":29},"waterFractionBefore":0.5529,"waterFractionAfter":0.5528,"totalCellsChanged":73}},"sideRoutes":{"westLumberMillIsland":{"islandLandCells":25,"ringWaterCells":20,"entrances":1},"westGoblinPotionIsland":{"islandLandCells":25,"ringWaterCells":20,"entrances":1},"eastBreweryWrap":{"brewerySeaReachable":true,"farEastNorthWaterCells":151},"bottomRightWinding":{"tanSegments":88,"tanMaxRun":17,"windingNotBlob":false}},"wpmAgreement":0.9918,"wpmConfusion":"agree=0.9918 ours-only(necks/moats)=0.0042 ref-only(denoised)=0.004","depthSplitLandDeepShallowPink":[0.4472,0.2434,0.3007,0.0087],"colourKeyAgreement":0.6793},"water":[[0,81],[0,36,2,43],[0,35,4,42],[0,28,3,4,4,42],[0,23,2,3,11,42],[0,23,16,42],[0,24,18,23,3,13],[0,28,15,20,6,12],[0,28,14,19,10,10],[0,28,11,22,3,5,2,10],[0,28,10,23,2,7,2,9],[0,28,10,23,2,7,2,9],[0,4,3,15,16,3,5,10,1,4,2,8,2,8],[0,3,5,13,26,3,2,3,3,3,2,8,2,6,1,1],[0,3,6,11,28,2,14,4,5,4,4],[0,4,14,1,29,1,15,3,6,3,5],[0,4,14,1,44,4,14],[0,6,58,2,14,1],[0,6,51,5,8,2,9],[0,6,8,1,37,1,1,9,7,2,8,1],[1,2,4,43,15,6,3,5,3],[1,49,6,6,20],[1,15,1,33,6,11,15],[0,1,4,1,9,1,33,6,15,10,1],[0,1,4,1,8,2,17,5,2,1,8,4,7,2,10,6,3],[1,9,7,15,7,2,1,8,3,8,9,4,4,3,1],[1,9,10,14,5,11,3,7,12,8,2],[1,9,10,14,6,10,3,6,14,5,4],[1,9,7,2,1,13,6,3,1,8,2,5,4,2,5,1,4,4,4],[1,7,9,2,1,12,7,3,1,8,2,5,3,3,4,4,10],[1,7,9,15,2,24,1,6,3,5,9],[0,3,8,6,22,1,33,8],[0,5,8,4,59,5],[0,6,9,2,14,2,44,4],[0,10,21,3,2,4,38,3],[0,10,22,2,2,3,39,3],[0,11,66,4],[0,16,60,5],[0,16,60,5],[0,6,3,8,33,2,23,6],[0,4,7,7,32,4,3,2,2,2,7,11],[0,3,10,6,31,2,5,24],[0,2,3,2,6,7,11,1,1,3,2,1,18,24],[1,5,2,5,7,12,5,21,20,1,3],[0,1,4,2,4,8,13,4,20,3,2,10,1,3,4,2],[0,1,3,3,5,7,32,2,3,3,2,5,13,2],[0,2,2,3,6,6,32,2,3,10,12,3],[0,2,12,3,34,2,3,11,11,3],[0,3,7,2,2,2,16,4,15,1,5,10,11,3],[0,4,10,3,16,3,3,1,16,5,2,4,12,2],[0,4,10,6,13,3,3,2,14,6,3,3,4,2,5,3],[0,2,13,5,10,6,3,2,13,6,5,2,3,5,3,3],[1,16,4,9,7,3,2,11,5,8,3,1,6,6],[0,1,2,2,4,3,5,3,8,6,6,1,10,5,9,11,5],[0,2,1,2,3,6,4,3,7,5,6,2,10,5,10,12,3],[0,5,3,6,4,3,8,1,9,2,25,5,2,5,2,1],[0,5,3,7,4,2,18,2,25,3,5,2,4,1],[0,15,4,2,17,2,26,2,12,1],[0,1,7,7,4,2,16,3,11,3,12,3,10,2],[0,1,1,5,1,6,15,1,21,5,10,4,8,3],[0,1,1,5,1,6,15,1,20,6,3,3,5,3,7,4],[0,1,1,5,1,6,18,5,13,12,6,2,3,8],[0,1,1,5,1,5,5,3,11,5,13,12,3,6,2,8],[0,1,1,5,1,5,3,5,10,6,15,9,3,7,2,5,2,1],[0,1,7,4,3,5,11,6,14,10,3,7,3,3,3,1],[0,4,1,7,3,4,12,6,14,9,5,5,4,3,3,1],[0,4,5,3,3,3,13,6,19,3,7,1,6,3,4,1],[1,2,1,7,2,3,4,13,4,20,6,11,3,5],[0,3,2,2,3,2,3,5,13,2,21,5,20],[0,3,2,2,7,6,13,1,22,5,20],[0,3,10,6,32,2,6,1,19,2],[0,3,9,8,30,3,6,2,5,2,11,2],[0,4,2,3,2,9,12,2,16,3,4,5,5,1,5,1,6,1],[0,19,12,3,21,10,8,2,6],[0,18,13,3,2,2,17,12,2,1,4,1,6],[0,13,2,3,18,2,13,2,2,5,1,6,2,1,3,3,1,1,3],[0,13,2,3,19,1,12,3,2,4,3,5,2,8,4],[0,13,37,3,2,4,2,6,2,12],[0,15,18,2,16,2,3,11,2,12],[0,15,16,4,2,3,11,2,3,10,4,11],[0,14,23,3,18,8,4,7,2,2],[0,14,16,1,7,2,18,5,2,2,3,6,4,1],[0,14,16,1,23,8,3,4,2,4,6],[0,13,17,1,23,8,4,3,2,2,8],[0,13,26,1,17,5,4,3,6,5,1],[0,11,28,1,11,3,4,3,5,4,3,5,3],[0,10,6,3,11,8,14,3,3,3,6,4,1,4,5],[0,11,5,3,11,8,15,4,11,7,6],[0,11,19,8,15,4,6,3,3,5,3,4],[0,12,18,8,10,9,5,5,3,2,4,5],[0,12,19,1,15,21,7,6],[1,7,5,2,3,30,5,1,17,4,5,2],[1,1,5,1,5,2,4,30,3,2,18,2,6,1,1],[1,1,5,1,5,36,2,4,10,1,12,1,3],[1,1,5,1,4,37,2,5,7,5,10,1,3],[1,1,5,1,3,45,4,9,8,2,3],[1,1,5,1,3,45,3,11,6,3,3],[1,7,3,41,2,18,4,4,2],[1,1,8,11,1,29,4,10,4,4,2,3,4],[1,1,3,15,3,28,4,6,1,3,4,9,4],[1,18,5,27,4,2,1,2,3,3,4,7,5],[1,1,2,12,9,24,5,3,7,3,4,5,6],[0,12,2,17,9,4,1,8,3,7,4,14],[0,31,9,13,3,7,4,14],[0,31,9,14,4,5,4,14],[0,31,10,14,10,16],[0,28,14,15,7,17],[0,27,16,16,1,21],[0,28,14,39],[0,30,4,47],[0,30,4,47],[0,30,4,47],[0,31,2,48]],"depth":[[0,81],[0,36,2,2,0,43],[0,35,2,3,1,1,0,42],[0,28,2,3,0,4,2,4,0,42],[0,23,2,2,0,3,2,11,0,42],[0,23,2,8,1,5,2,3,0,42],[0,24,2,6,1,8,2,4,0,23,2,3,0,13],[0,28,2,2,1,8,2,5,0,20,2,6,0,12],[0,28,2,2,1,8,2,4,0,19,2,4,1,2,2,4,0,10],[0,28,2,1,1,10,0,22,2,1,1,2,0,5,2,2,0,10],[0,28,1,10,0,23,2,2,0,7,2,2,0,9],[0,28,1,10,0,23,2,2,0,7,2,2,0,9],[0,4,2,1,1,2,0,15,1,16,0,3,1,5,0,10,2,1,0,4,2,2,0,8,2,2,0,8],[0,3,2,2,1,3,0,13,1,26,0,3,2,2,0,3,2,3,0,3,2,2,0,8,2,2,0,6,2,1,0,1],[0,3,2,2,1,4,0,11,1,28,0,2,2,14,0,4,2,5,0,4,2,4],[0,4,2,1,1,5,2,4,1,2,2,2,0,1,1,13,2,1,1,2,2,3,1,1,2,4,1,5,0,1,2,15,0,3,2,6,0,3,2,5],[0,4,2,2,1,1,2,1,1,3,2,5,1,2,0,1,1,12,2,11,1,6,2,15,0,4,2,14],[0,6,2,2,1,1,2,6,1,13,2,14,1,1,2,1,1,3,2,11,1,1,2,2,1,1,2,2,0,2,2,14,0,1],[0,6,2,3,3,1,1,1,3,3,2,1,1,2,2,1,1,10,2,1,1,1,2,7,1,2,2,5,1,3,2,10,0,5,2,8,0,2,2,9],[0,6,2,1,3,2,2,2,3,3,0,1,2,3,1,11,2,8,3,2,1,1,2,2,1,1,2,1,1,4,2,4,0,1,2,1,0,9,2,7,0,2,2,8,0,1],[1,2,0,4,2,1,3,2,2,4,3,2,2,3,1,12,2,7,3,2,1,1,2,1,1,1,2,2,1,4,2,1,0,15,2,6,0,3,2,5,0,3],[1,3,2,4,3,1,2,5,3,3,2,3,1,13,2,5,3,2,1,1,2,5,1,4,0,6,2,1,1,3,2,2,0,20],[1,2,2,11,3,2,0,1,2,3,1,11,2,3,3,2,2,3,1,3,2,2,1,2,2,3,1,1,0,6,2,1,1,3,2,7,0,15],[0,1,1,1,2,3,0,1,2,9,0,1,2,3,1,11,2,3,3,1,1,1,2,3,1,2,2,4,1,2,2,3,0,6,1,1,2,1,1,2,2,11,0,10,2,1],[0,1,1,1,2,3,0,1,2,8,0,2,2,3,1,11,2,3,0,5,2,2,0,1,2,6,1,1,2,1,0,4,2,2,1,2,2,1,1,1,2,1,0,2,2,10,0,6,2,3],[2,9,0,7,1,1,2,2,1,11,2,1,0,7,2,2,0,1,2,4,1,4,0,3,2,3,1,4,2,1,0,9,2,4,0,4,2,3,0,1],[2,9,0,10,1,11,2,3,0,5,2,7,1,4,0,3,1,7,0,12,1,3,2,5,0,2],[2,8,1,1,0,10,1,11,2,3,0,6,2,5,1,5,0,3,1,6,0,14,1,3,2,2,0,4],[2,4,1,5,0,7,1,2,0,1,1,11,2,2,0,6,2,3,0,1,2,1,1,7,0,2,1,5,0,4,1,2,0,5,1,1,0,4,1,4,0,4],[2,4,3,3,0,9,1,2,0,1,1,11,2,1,0,7,2,3,0,1,1,8,0,2,1,5,0,3,1,3,0,4,1,4,0,10],[2,7,0,9,1,14,2,1,0,2,1,1,2,7,1,16,0,1,1,6,0,3,1,5,0,9],[0,3,2,8,0,6,1,14,2,2,1,2,2,1,1,1,2,1,1,1,0,1,2,1,1,32,0,8],[0,5,2,8,0,4,1,14,2,2,1,2,2,5,1,11,2,3,1,1,2,3,1,2,2,1,1,15,0,5],[0,6,2,9,0,2,1,14,0,2,1,1,2,2,1,16,2,6,1,2,2,1,1,16,0,4],[0,10,2,9,1,12,0,3,2,1,1,1,0,4,1,10,2,11,1,1,2,1,1,3,2,6,1,2,2,2,1,2,0,3],[0,10,2,10,1,11,2,1,0,2,2,1,1,1,0,3,1,11,2,28,0,3],[0,11,2,9,1,10,2,5,1,14,2,1,1,1,2,7,1,1,2,18,0,4],[0,16,2,5,1,7,2,7,1,3,2,6,1,5,2,27,0,5],[0,16,2,5,1,7,2,14,1,1,2,1,1,5,2,27,0,5],[0,6,2,3,0,8,2,2,1,9,2,15,1,7,0,2,2,23,0,6],[0,4,2,7,0,7,1,12,2,13,1,7,0,4,2,3,0,2,2,2,0,2,3,3,2,4,0,11],[0,3,2,2,1,1,2,1,1,1,2,5,0,6,1,12,2,11,1,8,0,2,2,5,0,24],[0,2,2,3,0,2,2,6,0,7,1,11,0,1,2,1,0,3,2,2,0,1,2,2,1,11,2,5,0,24],[2,5,0,2,2,5,0,7,1,12,0,5,2,6,1,10,2,5,0,20,2,1,0,3],[0,1,1,1,2,3,0,2,2,4,0,8,1,12,2,1,0,4,2,7,1,9,2,4,0,3,2,2,0,10,2,1,0,3,2,4,0,2],[0,1,2,3,0,3,2,5,0,7,1,11,2,1,1,1,2,11,1,8,0,2,2,3,0,3,2,2,0,5,2,13,0,2],[0,2,2,2,0,3,1,1,2,5,0,6,1,10,2,8,1,1,2,4,1,9,0,2,2,2,1,1,0,10,2,12,0,3],[0,2,2,4,1,4,2,4,0,3,2,2,1,8,2,10,1,1,2,6,1,7,0,2,2,3,0,11,2,11,0,3],[0,3,2,4,1,3,0,2,2,2,0,2,2,3,1,8,2,5,0,4,2,7,1,8,0,1,2,5,0,10,2,4,3,1,2,6,0,3],[0,4,2,3,1,3,2,4,0,3,2,3,1,7,2,6,0,3,3,1,1,2,0,1,2,3,1,1,2,1,1,2,2,1,1,3,2,5,0,5,2,2,0,4,2,4,3,1,2,7,0,2],[0,4,2,10,0,6,1,7,2,5,3,1,0,3,1,3,0,2,2,8,1,2,2,4,0,6,1,2,2,1,0,3,1,1,2,3,0,2,2,5,0,3],[0,2,2,13,0,5,2,1,1,6,2,3,0,6,1,3,0,2,2,8,1,2,2,3,0,6,1,4,2,1,0,2,1,1,2,2,0,5,2,3,0,3],[3,1,1,3,2,12,0,4,2,1,1,5,2,1,1,2,0,7,1,2,2,1,0,2,2,6,1,4,2,1,0,5,2,1,1,7,0,3,2,1,0,6,2,6],[0,1,1,2,0,2,2,4,0,3,2,5,0,3,2,1,1,5,2,1,1,1,0,6,1,4,2,2,0,1,2,6,1,3,2,1,0,5,1,9,0,11,2,5],[0,2,1,1,0,2,2,3,0,6,2,4,0,3,1,5,2,2,0,5,1,4,2,2,0,2,2,4,1,6,0,5,1,8,2,2,0,12,2,2,1,1],[0,5,2,3,0,6,2,4,0,3,1,5,2,3,0,1,1,7,2,2,0,2,2,1,1,9,2,5,1,8,2,2,0,5,2,2,0,5,1,1,2,1,0,1],[0,5,3,1,2,2,0,7,2,4,0,2,1,5,2,4,1,6,2,3,0,2,2,2,1,8,2,6,3,1,1,5,2,1,1,2,0,3,2,5,0,2,1,2,2,2,0,1],[0,15,2,4,0,2,1,5,2,5,1,7,0,2,2,3,1,9,2,6,1,5,2,3,0,2,2,12,0,1],[0,1,2,1,3,5,2,1,0,7,2,4,0,2,1,5,2,4,3,1,1,3,2,3,0,3,2,3,1,8,0,3,2,6,1,2,2,4,0,3,2,10,0,2],[0,1,2,1,0,5,3,1,0,6,2,6,1,8,2,1,0,1,3,4,2,9,1,8,0,5,2,10,0,4,2,8,0,3],[0,1,1,1,0,5,3,1,0,6,2,6,1,9,0,1,2,1,1,2,3,1,2,9,1,7,0,6,2,3,0,3,2,5,0,3,2,7,0,4],[0,1,1,1,0,5,2,1,0,6,2,6,1,11,2,1,0,5,2,6,1,7,0,12,2,4,1,1,2,1,0,2,2,3,0,8],[0,1,1,1,0,5,2,1,0,5,2,5,0,3,1,10,3,1,0,5,2,6,1,7,0,12,2,2,3,1,0,6,2,2,0,8],[0,1,1,1,0,5,2,1,0,5,2,3,0,5,1,9,3,1,0,6,3,2,2,4,1,9,0,9,2,3,0,7,2,2,0,5,2,2,0,1],[0,1,1,4,3,2,2,1,0,4,2,3,0,5,1,10,3,1,0,6,3,2,2,4,1,8,0,10,2,3,0,7,2,3,0,3,2,3,0,1],[0,4,1,1,0,7,2,3,0,4,2,1,1,10,2,1,0,6,3,1,2,5,1,8,0,9,2,5,0,5,2,4,0,3,2,3,0,1],[0,4,1,3,2,2,0,3,2,3,0,3,2,3,1,8,2,2,0,6,2,6,1,9,2,4,0,3,2,6,1,1,0,1,2,6,0,3,2,4,0,1],[1,2,0,1,3,1,1,3,2,2,3,1,0,2,2,3,0,4,2,3,1,8,2,2,0,4,2,7,1,4,2,1,1,5,2,3,0,6,2,3,1,3,2,1,1,2,2,2,0,3,2,5],[0,3,3,1,1,1,0,2,1,1,2,1,3,1,0,2,2,3,0,5,2,3,1,9,2,1,0,2,2,1,1,10,2,2,1,5,2,3,0,5,2,5,1,3,2,12],[0,3,3,1,2,1,0,2,1,1,3,1,2,5,0,6,2,2,1,9,2,2,0,1,2,1,1,12,2,2,1,4,2,3,0,5,2,4,1,4,2,12],[0,3,2,3,1,3,2,4,0,6,2,3,1,8,2,5,1,13,2,1,1,2,0,2,2,2,1,1,2,3,0,1,1,1,2,8,1,1,2,9,0,2],[0,3,2,3,1,2,3,1,2,3,0,8,2,2,1,8,2,5,1,6,2,1,1,8,0,3,2,6,0,2,2,5,0,2,2,6,1,2,2,3,0,2],[0,4,2,2,0,3,2,2,0,9,2,2,1,6,2,4,0,2,2,2,1,2,2,5,1,7,0,3,2,4,0,5,2,5,0,1,2,4,1,1,0,1,2,1,1,2,2,3,0,1],[0,19,2,2,1,7,2,3,0,3,2,3,1,1,2,6,1,6,2,5,0,10,2,8,0,2,1,3,2,2,3,1],[0,18,2,2,1,9,2,2,0,3,2,2,0,2,2,5,1,8,2,4,0,12,2,2,0,1,2,4,0,1,1,2,3,1,2,3],[0,13,2,2,0,3,2,1,1,11,2,1,1,1,2,4,0,2,2,3,1,9,2,1,0,2,2,2,0,5,2,1,0,6,2,2,0,1,2,3,0,3,2,1,0,1,2,3],[0,13,2,2,0,3,1,12,2,1,1,1,2,5,0,1,2,3,1,9,0,3,2,2,0,4,2,3,0,5,2,2,0,8,2,4],[0,13,2,4,1,1,2,2,1,9,2,12,1,9,0,3,2,2,0,4,3,2,0,6,2,2,0,12],[0,15,1,3,2,2,1,7,2,6,0,2,2,6,1,10,0,2,2,3,0,11,2,2,0,12],[0,15,1,3,2,3,1,6,2,4,0,4,2,2,0,3,2,1,1,1,2,1,1,8,0,2,2,3,0,10,2,4,0,11],[0,14,2,1,1,3,2,3,1,6,2,1,1,1,2,8,0,3,2,3,1,8,2,7,0,8,2,4,0,7,2,2,0,2],[0,14,2,1,1,12,2,3,0,1,2,1,1,6,0,2,2,3,1,8,2,7,0,5,2,2,0,2,2,3,0,6,2,4,0,1],[0,14,2,1,1,13,2,2,0,1,2,1,1,6,2,5,1,8,2,3,0,8,2,3,0,4,2,2,0,4,2,6],[0,13,2,3,1,12,2,2,0,1,2,1,1,6,2,5,1,7,2,3,1,1,0,8,2,4,0,3,2,2,0,2,2,8],[0,13,1,1,2,3,1,11,2,1,1,1,2,1,1,7,2,1,0,1,2,2,1,7,2,8,0,5,2,4,0,3,2,6,0,5,2,1],[0,11,2,1,1,2,2,4,1,11,2,3,1,6,2,1,0,1,2,1,1,8,2,2,0,3,2,4,0,3,2,5,0,4,2,3,0,5,2,3],[0,10,2,1,1,2,2,3,0,3,1,10,2,1,0,8,2,3,1,10,2,1,0,3,2,3,0,3,2,6,0,4,2,1,0,4,2,5],[0,11,1,2,2,3,0,3,1,9,2,2,0,8,2,3,1,5,2,1,1,3,2,2,1,1,0,4,2,11,0,7,2,6],[0,11,1,3,2,5,1,8,2,3,0,8,2,3,1,4,2,3,1,2,2,3,0,4,2,6,0,3,2,3,0,5,2,3,0,4],[0,12,1,5,2,2,1,9,2,2,0,8,2,2,1,5,2,3,0,9,2,3,1,1,2,1,0,5,2,3,0,2,2,4,0,5],[0,12,1,16,2,3,0,1,2,8,1,5,2,2,0,21,2,7,0,6],[2,7,0,5,1,2,0,3,1,12,2,11,1,5,2,2,0,5,2,1,0,17,2,4,0,5,2,2],[2,1,0,5,2,1,0,5,1,2,0,4,1,12,2,5,1,3,2,2,1,5,2,3,0,3,2,2,0,18,2,2,0,6,2,1,0,1],[2,1,0,5,2,1,0,5,3,1,2,4,1,13,2,4,1,4,2,2,1,6,2,2,0,2,2,4,0,10,2,1,0,12,2,1,0,3],[2,1,0,5,2,1,0,4,2,8,1,16,2,2,1,10,2,1,0,2,2,5,0,7,2,5,0,10,2,1,0,3],[2,1,0,5,2,1,0,3,2,8,1,29,2,1,1,1,2,5,1,1,0,4,2,9,0,8,2,2,0,3],[2,1,0,5,2,1,0,3,2,5,1,32,2,8,0,3,2,11,0,6,2,3,0,3],[2,1,1,3,2,3,0,3,2,5,1,9,2,2,1,22,2,3,0,2,2,18,0,4,2,4,0,2],[3,1,0,8,2,5,1,6,0,1,1,3,2,2,1,1,2,2,1,21,0,4,2,1,1,2,2,7,0,4,2,2,1,2,0,2,1,1,2,2,0,4],[1,1,0,3,2,5,1,1,2,3,1,5,2,1,0,3,2,1,1,1,2,6,1,20,0,4,2,1,1,1,2,4,0,1,2,3,0,4,2,6,1,1,2,2,0,4],[3,1,1,1,2,7,1,2,2,2,1,4,2,1,0,5,2,9,1,18,0,4,2,2,0,1,2,2,0,3,2,3,0,4,2,5,1,2,0,5],[2,1,0,2,2,6,1,6,0,9,2,9,1,15,0,5,2,3,0,7,2,3,0,4,2,4,1,1,0,6],[0,12,1,1,2,1,0,17,2,7,1,2,0,4,1,1,0,8,2,3,0,7,2,4,0,14],[0,31,2,8,1,1,0,13,2,3,0,7,2,4,0,14],[0,31,2,9,0,14,2,4,0,5,2,4,0,14],[0,31,2,10,0,14,2,10,0,16],[0,28,2,14,0,15,2,7,0,17],[0,27,3,1,2,15,0,16,2,1,0,21],[0,28,2,14,0,39],[0,30,2,4,0,47],[0,30,2,4,0,47],[0,30,2,4,0,47],[0,31,1,1,2,1,0,48]]} +{"_comment":"Static land/water mask. SAILABLE WATER = the map's own PATHING MAP (data/extracted/war3map.wpm, bit 0x40 = no-water, 4x4 32u subcells per 128u tile, majority vote): the engine's truth for where ships could actually sail in the original. This REPLACES the minimap NON-BLUE colour key (~0.66 water), which over-watered: green 'shallow' paint is often visually-wet-but-UNSAILABLE, merging lanes the real map separates (owner-reported 2026-07-08: the NE lane must NOT merge into the east-edge lane; the wpm separates them). The wpm reads ~0.55 sailable over the playable crop and all 26 known anchors (HQs, harbours, spawns, lane waypoints) sit sailable. The ONLY additions on top of the raw wpm grid are MINIMAL 1-cell connectivity necks (so every shop + dock/spawn reaches the sea and the two bases stay water-connected) PLUS the two owner-approved WEST sail-around island moats (Swedish Lumber Mill, Goblin Potion Dealer: land core + thin 1-cell navigable ring + EXACTLY ONE entrance; deterministic post-step). water=true is ship-navigable. The OPTIONAL `depth` field (0=land,1=deep,2=shallow,3=pink) is additive render metadata the SIM IGNORES; the minimap colours band each FINAL water cell so a client paints the water shades like the original. Regenerate with: make terrain (tools/extractor/terrain.py; pure stdlib, reads wpm+w3e+PNG, no venv). yOrientation 'top-down' means rle row 0 is the NORTH (max-Y) edge.","source":"data/extracted/war3map.wpm (pathing map, bit 0x40=no-water; THE sailability authority) + data/extracted/war3map.w3e (grid geometry) + data/reference/war3mapMap.png (depth render metadata only)","target":"the original map's enforced ship-pathing (wpm no-water), cropped to the playable rectangle","rule":"water = wpm NOT-no-water majority over the 16 32u subcells per 128u tile, MINUS singleton speckle, PLUS minimal 1-cell connectivity necks (Dijkstra cost 1 water / 30 land) for shops, docks/spawns and base-to-base, PLUS the two carved WEST sail-around island moats (compact land core + thin 1-cell water ring + exactly one entrance) around the Swedish Lumber Mill and Goblin Potion Dealer shops. depth sub-classifies FINAL water cells from the minimap colours for RENDER only: DEEP (R-B>35 AND R>=G), PINK (R>150 AND B>120 AND R-G>15), else SHALLOW; a water cell whose pixels read land-blue falls back to SHALLOW.","playableBounds":{"minX":-5376.0,"minY":-7424.0,"maxX":4864.0,"maxY":6912.0},"bounds":{"minX":-5440.0,"minY":-7488.0,"maxX":4928.0,"maxY":6976.0},"cols":162,"rows":226,"cellSizeX":64.0,"cellSizeY":64.0,"yOrientation":"top-down","yOrientationNote":"rle row 0 = max-Y (north); last row = min-Y (south). col 0 = min-X (west). col=floor((x-minX)/cellSizeX), row=floor((maxY-y)/cellSizeY). The minimap is north-up; tiles are sampled at their world centers via the content-box registration, emit row 0 = north, matching sim isWater.","rleFormat":"water[r] = [leadingValue, run0, run1, ...]; runs alternate from leadingValue (0=land,1=water) and sum to cols.","depthRleFormat":"OPTIONAL render metadata, the sim IGNORES it. depth[r] = [value0, run0, value1, run1, ...] (explicit value per run; values 0=land, 1=deep, 2=shallow, 3=pink; runs sum to cols). depth[r][col]>0 IFF water[r][col]==1 (exactly consistent with the authoritative `water` mask). Carved necks/moats with no minimap colour emit as shallow (2).","waterFraction":0.513165,"validation":{"hqsOnWater":"2/2","harboursOnWater":"4/4","playerSpawnsOnWater":"12/12","lanes":["south-west: spawnWater=True connToEnemyHQ=True","south-east: spawnWater=True connToEnemyHQ=True","north-west: spawnWater=True connToEnemyHQ=True","north-east: spawnWater=True connToEnemyHQ=True"],"basesConnected":true,"shopsReachable":"16/16","shopReach":["Swedish Lumber Mill: reachable=True nearestSeaCells=1","Goblin Potion Dealer: reachable=True nearestSeaCells=1","Elven Library: reachable=True nearestSeaCells=0","Ship Wreck: reachable=True nearestSeaCells=0","Elven Library: reachable=True nearestSeaCells=4","Ale Brewery: reachable=True nearestSeaCells=2","Equipment Merchant: reachable=True nearestSeaCells=3","Heavy Weapons Merchant: reachable=True nearestSeaCells=2","Weapons Merchant: reachable=True nearestSeaCells=4","Equipment Merchant: reachable=True nearestSeaCells=2","Bill (Trade Master): reachable=True nearestSeaCells=3","Pirate Boat Merchant: reachable=True nearestSeaCells=0","Will (Trade Master): reachable=True nearestSeaCells=4","Weapons Merchant: reachable=True nearestSeaCells=2","Heavy Weapons Merchant: reachable=True nearestSeaCells=3","Goblin Bomb Shop: reachable=True nearestSeaCells=0"],"repairRegionsReachable":"2/2","repairRegionReach":["Repair_Station_South: reachable=True","Repair_Station_North: reachable=True"],"waterFraction":0.5132,"eastThirdWaterRun":"median=6.0 mean=8.56 count=568","bottomRightWaterRun":"median=5.0 mean=5.87 count=200","necks":{"basePlatformCellsAdded":1,"connectivityNeckCellsAdded":0,"shopNeckCellsAdded":4,"repairRegionNeckCellsAdded":0,"waterFractionBefore":0.5136,"waterFractionAfter":0.5137,"shopsReachable":"16/16","repairRegionsReachable":"2/2","singletonCellsDropped":0,"straddledChannelCellsRestored":0,"westIslandLoops":{"Swedish Lumber Mill":{"shopCell":[12,123],"anchor":[8,123],"shopInCore":true,"shopInRing":false,"shopOnLand":true,"cycleLen":40,"entranceCells":[[7,117]],"entrances":1,"cellsChanged":93},"Goblin Potion Dealer":{"shopCell":[7,192],"anchor":[7,188],"shopInCore":true,"shopInRing":false,"shopOnLand":true,"cycleLen":40,"entranceCells":[[7,194]],"entrances":1,"cellsChanged":49},"waterFractionBefore":0.5137,"waterFractionAfter":0.5132,"totalCellsChanged":142}},"laneTopologyVsWpm":{"anchors":22,"pairwiseMismatches":0},"sideRoutes":{"westLumberMillIsland":{"islandLandCells":81,"ringWaterCells":36,"entrances":1},"westGoblinPotionIsland":{"islandLandCells":81,"ringWaterCells":36,"entrances":1},"eastBreweryWrap":{"brewerySeaReachable":true,"farEastNorthWaterCells":226},"bottomRightWinding":{"tanSegments":196,"tanMaxRun":27,"windingNotBlob":false}},"wpmAgreement":0.996,"wpmConfusion":"agree=0.996 ours-only(necks/moats)=0.0018 ref-only(denoised)=0.0022","depthSplitLandDeepShallowPink":[0.4868,0.2337,0.272,0.0075],"colourKeyAgreement":0.6694},"water":[[0,162],[0,162],[0,162],[0,71,6,85],[0,71,6,85],[0,57,2,12,6,85],[0,57,2,12,6,85],[0,47,2,7,7,8,6,85],[0,47,2,7,7,8,6,85],[0,47,4,4,22,85],[0,47,4,4,22,85],[0,47,32,54,2,27],[0,47,32,54,2,27],[0,55,30,44,8,25],[0,55,30,44,8,25],[0,57,28,40,14,23],[0,57,28,37,20,20],[0,57,20,45,7,8,5,20],[0,57,20,45,7,8,5,20],[0,57,20,45,5,11,5,19],[0,57,20,45,5,12,5,18],[0,57,18,46,4,15,4,18],[0,57,18,46,4,16,2,19],[0,57,18,48,2,16,4,17],[0,57,19,47,2,16,4,17],[0,7,8,28,33,5,12,18,4,8,2,18,2,17],[0,7,8,28,37,1,13,6,4,6,5,8,2,18,3,16],[0,7,10,24,54,5,5,5,7,6,4,16,3,11,3,2],[0,7,10,24,54,5,5,1,2,2,8,5,4,9,4,2,4,11,3,2],[0,7,11,15,2,4,56,4,30,6,11,7,3,1,5],[0,7,12,9,2,3,2,4,56,3,31,6,2,1,8,7,9],[0,9,26,4,56,3,29,8,11,7,9],[0,9,26,4,56,3,28,9,13,5,9],[0,9,3,2,21,4,88,6,28,1],[0,9,2,1,116,5,18,1,9,1],[0,12,106,5,6,4,6,4,12,1,4,2],[0,11,104,8,6,4,6,4,18,1],[0,13,14,3,79,15,15,5,18],[0,13,15,2,74,1,4,16,14,6,16,1],[0,13,15,2,68,29,12,6,13,4],[0,2,2,9,84,30,13,5,5,1,6,5],[1,4,9,84,20,2,18,1,1,1,10,6,6],[1,3,1,2,2,89,13,2,4,3,18,2,23],[1,97,12,14,39],[1,29,3,65,12,17,36],[0,3,26,3,65,13,23,29],[0,2,7,4,16,3,66,12,23,29],[0,2,7,4,16,3,35,8,4,4,16,11,10,3,18,18,3],[0,2,7,4,16,4,34,8,4,4,16,7,14,3,18,1,2,15,3],[0,2,7,4,5,13,31,15,2,4,14,8,15,7,2,3,13,10,6,1],[0,3,7,3,4,14,31,15,2,4,14,8,15,7,2,8,9,9,6,1],[1,17,19,26,15,2,4,14,8,15,18,2,1,5,7,6,3],[1,17,20,27,12,6,1,14,8,12,24,7,5,6,3],[1,17,21,28,10,21,8,12,26,12,7],[1,17,21,28,12,20,6,13,26,12,7],[1,19,14,2,3,27,13,21,5,11,8,2,20,9,8],[1,19,14,2,3,27,11,5,4,15,4,11,8,2,20,9,8],[1,13,20,2,3,26,12,5,4,15,4,10,9,2,10,4,9,6,8],[1,13,20,2,3,24,15,4,4,15,5,9,6,5,10,5,22],[1,13,20,2,3,24,3,2,9,5,4,15,3,11,5,8,8,8,19],[1,13,20,29,13,6,4,15,3,10,3,12,7,8,19],[0,4,9,6,2,12,29,3,12,4,32,3,13,6,10,17],[0,5,11,3,2,12,44,4,32,3,29,17],[0,6,17,11,43,4,64,4,2,11],[0,9,15,10,44,3,64,1,6,10],[0,10,17,7,30,2,87,9],[0,11,17,6,29,3,87,9],[0,19,12,3,28,4,5,9,73,9],[0,19,43,5,4,9,76,6],[0,21,41,7,2,9,76,5,1],[0,21,43,4,3,7,78,5,1],[0,21,43,4,5,4,79,6],[0,21,42,1,9,1,81,7],[0,25,129,8],[0,25,2,4,120,11],[0,32,119,11],[0,33,118,11],[0,33,66,4,48,11],[0,33,66,4,48,11],[0,11,8,18,62,10,5,2,34,12],[0,11,8,18,62,9,6,3,5,3,16,21],[0,7,16,14,62,9,6,4,4,40],[0,7,16,14,63,4,2,3,4,49],[0,5,7,3,12,11,62,3,10,49],[0,4,7,4,12,14,20,3,3,6,3,2,21,3,3,1,7,49],[0,3,7,5,10,16,20,3,2,7,3,2,35,48,1],[1,2,1,7,5,10,13,2,1,20,12,3,2,35,48,1],[1,2,1,7,5,7,16,23,12,40,6,2,32,4,5],[0,3,6,6,6,17,26,8,39,8,2,32,4,5],[0,3,6,6,6,17,26,8,31,4,4,6,4,20,4,4,8,5],[0,2,7,5,10,15,28,3,33,4,4,6,4,20,4,4,8,5],[0,2,5,7,11,13,63,6,5,7,2,10,26,5],[0,5,3,6,11,13,64,5,5,7,2,10,26,5],[0,5,3,5,14,11,64,5,5,21,22,7],[0,5,3,5,14,10,64,6,4,22,23,6],[0,5,14,1,2,3,2,6,33,2,33,4,6,23,22,6],[0,5,14,6,2,6,32,6,30,4,8,22,21,6],[0,6,13,6,2,6,31,9,5,3,20,4,8,22,22,5],[0,8,12,5,2,6,31,9,4,4,20,3,9,9,2,11,23,4],[0,8,19,12,28,6,4,4,29,12,5,8,6,4,13,4],[0,8,19,12,28,5,6,3,30,11,6,7,6,4,11,6],[0,8,19,13,22,10,6,5,26,12,8,6,6,8,7,6],[0,4,26,10,21,12,5,5,26,12,8,6,6,8,7,6],[0,3,27,10,19,14,5,5,22,16,8,6,4,11,7,5],[1,30,10,19,14,5,5,22,16,9,5,4,12,6,5],[1,6,5,6,1,15,7,16,17,6,4,21,9,17,21,11],[0,2,4,5,6,6,10,7,16,17,6,4,20,10,17,21,11],[0,2,4,5,6,9,9,5,16,11,12,4,18,12,17,25,7],[0,4,2,5,6,10,9,5,15,11,12,4,18,12,19,23,7],[0,4,2,5,4,14,7,7,13,9,12,6,18,10,21,25,5],[0,11,4,14,7,7,12,1,2,2,4,1,12,6,18,10,20,11,4,10,4,2],[0,11,4,14,8,6,15,2,17,6,48,10,6,9,4,2],[0,11,4,14,8,6,15,3,16,6,48,9,7,5,7,3],[0,9,8,14,6,6,34,4,50,6,10,5,7,3],[0,9,8,14,6,6,34,4,50,6,13,2,7,3],[0,7,6,18,6,6,30,1,2,5,20,6,26,4,22,3],[0,7,6,13,2,3,6,6,31,7,20,6,26,4,22,3],[0,7,1,18,2,1,8,6,14,4,13,7,20,10,21,9,16,5],[0,3,11,14,9,5,15,4,40,10,20,10,16,5],[0,3,1,9,1,14,29,4,40,12,7,4,7,10,14,7],[0,3,1,9,1,14,29,4,40,11,7,6,6,10,14,7],[0,3,1,9,1,14,29,4,2,7,30,12,6,7,10,6,4,17],[0,3,1,9,1,14,32,1,2,10,26,26,10,5,5,17],[0,3,1,9,1,13,10,1,25,11,25,26,4,4,2,5,5,17],[0,3,1,9,1,13,10,5,21,12,25,25,4,4,2,6,4,17],[0,3,1,9,1,1,2,10,7,8,21,12,25,23,6,13,3,17],[0,3,1,9,1,1,2,10,6,9,21,12,29,19,6,14,2,17],[0,3,1,9,1,1,2,8,4,1,2,9,20,14,29,19,4,16,2,10,6,1],[0,3,11,1,2,7,5,12,20,14,28,20,4,16,5,7,6,1],[0,15,2,7,5,10,22,14,27,19,6,16,5,7,4,3],[0,9,8,8,4,10,22,14,26,15,2,3,6,15,5,8,4,3],[0,9,8,8,4,8,24,14,26,8,2,5,2,1,12,8,8,8,4,3],[0,8,9,8,5,7,24,14,26,5,5,7,13,8,8,8,4,3],[0,1,2,4,12,6,5,7,25,13,36,7,6,1,7,1,13,5,10,1],[0,1,2,4,12,6,5,7,27,11,37,7,2,3,22,5,2,2,6,1],[0,1,2,4,2,6,4,6,5,11,24,6,41,12,22,3,1,2,1,2,7],[0,1,2,3,3,6,4,6,5,11,24,6,41,10,28,2,10],[0,6,3,6,4,4,7,11,24,4,44,9,40],[0,6,3,6,4,4,6,12,25,3,43,10,38,1,1],[0,5,4,6,12,12,27,3,34,3,6,10,35,4,1],[0,5,4,6,12,12,29,1,34,3,12,2,37,4,1],[0,7,18,14,63,4,12,2,12,5,1,2,10,1,6,5],[0,7,18,14,62,5,12,5,9,5,1,2,17,5],[0,7,6,4,6,18,23,3,33,6,12,5,9,5,22,3],[0,7,6,4,6,18,22,4,32,7,7,10,9,5,9,3,10,3],[0,41,22,6,30,7,4,2,1,15,6,2,10,3,12,1],[0,41,22,5,31,7,4,2,1,16,17,3,12,1],[0,37,24,7,3,6,34,21,15,4,10,1],[0,37,24,8,2,6,34,22,5,2,7,4,7,1,2,1],[0,27,2,8,24,8,2,6,26,2,4,25,4,2,7,4,11],[0,27,2,8,25,2,2,2,3,6,26,2,4,25,3,3,7,4,2,3,6],[0,27,2,8,36,4,23,7,2,10,4,10,4,3,2,11,1,2,6],[0,26,3,7,37,4,22,8,2,10,4,10,4,16,9],[0,26,5,4,38,4,22,8,2,10,4,12,2,18,2,4,1],[0,26,73,8,2,10,4,12,2,18,2,4,1],[0,26,2,2,37,4,30,6,4,6,2,16,2,25],[0,30,37,4,30,6,4,6,2,15,4,6,2,16],[0,30,33,8,2,1,27,6,4,23,5,4,3,16],[0,31,32,7,3,6,22,6,4,21,7,4,2,17],[0,29,33,8,3,8,22,4,6,19,7,16,2,5],[0,29,34,5,2,1,2,8,22,4,7,18,7,16,2,5],[0,29,33,1,12,6,36,15,7,16,2,5],[0,29,30,3,13,6,35,12,2,4,5,16,2,5],[0,29,30,3,15,4,26,18,5,4,2,1,4,10,10,1],[0,29,30,4,15,3,26,18,5,7,4,9,11,1],[0,27,32,4,44,18,6,8,2,9,12],[0,27,32,4,44,18,6,8,2,5,16],[0,27,32,4,14,1,31,16,6,8,2,4,7,9,1],[0,27,50,3,29,15,7,8,2,4,6,10,1],[0,27,50,3,26,1,8,9,7,8,9,13,1],[0,26,51,3,22,5,9,6,9,8,8,14,1],[0,21,10,7,22,11,6,3,22,7,7,6,9,10,5,9,7],[0,21,11,6,22,3,2,10,2,3,21,8,7,7,8,10,4,10,7],[0,21,11,6,22,17,28,5,7,6,12,16,11],[0,21,11,6,21,17,29,8,4,6,13,15,11],[0,23,9,5,22,17,29,9,13,6,4,12,7,6],[0,23,9,5,22,18,29,9,12,6,4,12,5,8],[0,23,36,18,29,9,10,8,6,8,7,8],[0,23,37,17,20,17,11,8,6,7,5,11],[0,25,35,17,16,21,4,16,5,4,8,11],[0,25,35,14,19,42,5,3,8,11],[0,25,4,3,30,2,29,45,9,15],[0,25,4,4,29,2,29,11,2,33,8,15],[0,2,11,12,2,7,59,11,2,34,7,10,5],[0,2,1,9,1,11,3,9,60,6,4,16,2,17,6,10,4,1],[0,2,1,9,1,11,3,9,61,4,6,15,2,38],[0,2,1,9,1,11,4,6,63,4,6,55],[0,2,1,9,1,10,72,6,8,18,4,24,1,6],[0,2,1,9,1,10,72,6,9,14,2,1,7,21,1,6],[0,2,1,9,1,1,1,6,74,6,9,13,12,20,1,5,1],[0,2,1,9,1,1,1,6,74,6,9,8,2,3,12,20,1,5,1],[0,2,1,9,1,1,1,6,89,7,20,14,5,6],[0,2,1,9,1,1,1,6,89,6,22,13,5,6],[0,2,11,8,89,5,23,13,5,6],[0,7,1,12,82,3,5,5,27,9,6,5],[0,7,5,8,20,2,60,4,24,5,8,6,8,5],[0,7,6,7,20,3,57,7,22,6,9,5,6,7],[0,7,6,4,23,3,57,8,11,3,5,10,7,5,5,8],[0,7,2,1,3,4,22,4,57,8,11,3,5,9,10,2,5,9],[1,3,6,29,9,53,8,4,3,4,3,5,9,17,9],[1,36,11,53,8,4,3,4,5,3,12,14,9],[1,36,11,50,1,2,7,5,3,2,7,7,8,12,11],[1,1,5,25,16,50,9,6,3,2,8,6,8,12,11],[1,1,5,8,4,4,2,6,28,22,7,4,15,6,15,6,29],[1,1,24,4,34,16,8,4,15,6,15,6,29],[0,25,2,36,16,27,6,15,6,29],[0,25,2,36,16,28,5,15,6,29],[0,63,16,28,6,14,8,27],[0,63,16,28,6,14,8,27],[0,63,16,29,9,8,4,33],[0,63,16,30,13,3,4,33],[0,63,20,29,17,33],[0,63,20,30,16,33],[0,55,30,29,6,42],[0,55,30,33,2,42],[0,55,30,33,2,42],[0,55,30,77],[0,59,8,4,1,90],[0,59,8,95],[0,61,6,95],[0,61,6,95],[0,61,6,95],[0,61,6,95],[0,61,6,95],[0,61,6,95],[0,63,2,97]],"depth":[[0,162],[0,162],[0,162],[0,71,2,6,0,85],[0,71,2,6,0,85],[0,57,2,2,0,12,2,6,0,85],[0,57,2,2,0,12,2,6,0,85],[0,47,2,2,0,7,2,7,0,8,2,6,0,85],[0,47,2,2,0,7,2,7,0,8,2,6,0,85],[0,47,2,4,0,4,2,22,0,85],[0,47,2,4,0,4,2,22,0,85],[0,47,2,15,1,10,2,7,0,54,2,2,0,27],[0,47,2,14,1,13,2,5,0,54,2,2,0,27],[0,55,2,5,1,16,2,9,0,44,2,8,0,25],[0,55,2,5,1,16,2,9,0,44,2,8,0,25],[0,57,2,4,1,16,2,8,0,40,2,14,0,23],[0,57,2,4,1,16,2,8,0,37,2,20,0,20],[0,57,2,3,1,17,0,45,2,7,0,8,2,5,0,20],[0,57,2,2,1,18,0,45,2,2,1,2,2,3,0,8,2,5,0,20],[0,57,2,2,1,18,0,45,2,2,1,3,0,11,2,5,0,19],[0,57,1,20,0,45,2,3,1,1,2,1,0,12,2,5,0,18],[0,57,1,18,0,46,2,4,0,15,2,4,0,18],[0,57,1,18,0,46,2,4,0,16,2,2,0,19],[0,57,1,18,0,48,2,2,0,16,2,4,0,17],[0,57,1,19,0,47,2,2,0,16,2,4,0,17],[0,7,2,4,1,4,0,28,1,33,0,5,1,3,2,2,1,7,0,18,2,4,0,8,2,2,0,18,2,2,0,17],[0,7,2,3,1,5,0,28,1,37,0,1,1,13,0,6,2,4,0,6,2,5,0,8,2,2,0,18,2,3,0,16],[0,7,2,3,1,7,0,24,1,54,0,5,2,5,0,5,2,7,0,6,2,4,0,16,2,3,0,11,2,3,0,2],[0,7,2,3,1,7,0,24,1,54,0,5,2,5,0,1,2,2,0,2,2,8,0,5,2,4,0,9,2,4,0,2,2,4,0,11,2,3,0,2],[0,7,2,3,1,8,0,15,2,1,1,1,0,4,1,56,0,4,2,30,0,6,2,11,0,7,2,3,0,1,2,5],[0,7,1,1,2,2,1,9,0,9,2,1,1,1,0,3,1,1,2,1,0,4,1,31,2,2,1,3,2,6,1,1,2,2,1,11,0,3,2,31,0,6,2,2,0,1,2,8,0,7,2,9],[0,9,2,1,1,11,2,8,1,4,2,2,0,4,1,25,2,3,1,3,2,7,1,1,2,7,1,10,0,3,2,29,0,8,2,11,0,7,2,9],[0,9,2,2,1,11,2,8,1,3,2,2,0,4,1,24,2,22,1,10,0,3,2,28,0,9,2,13,0,5,2,9],[0,9,2,3,0,2,2,2,1,6,2,11,1,2,0,4,1,23,2,22,1,12,2,31,0,6,2,28,0,1],[0,9,2,2,0,1,2,1,1,1,2,2,1,3,2,13,1,26,2,26,1,12,2,32,0,5,2,18,0,1,2,9,0,1],[0,12,2,4,1,2,2,13,1,5,2,1,1,20,2,30,1,6,2,23,1,1,2,1,0,5,1,1,2,5,0,4,2,6,0,4,2,12,0,1,2,4,0,2],[0,11,2,13,3,3,2,4,1,3,2,3,1,19,2,19,3,1,1,2,2,9,1,6,2,22,0,8,1,1,2,5,0,4,2,6,0,4,2,18,0,1],[0,13,2,6,3,2,1,1,2,1,3,4,0,3,2,1,1,3,2,3,1,19,2,2,1,2,2,14,3,1,1,4,2,8,1,7,2,15,0,15,2,15,0,5,2,18],[0,13,2,5,1,1,3,9,0,2,2,3,1,1,2,3,1,21,2,16,3,2,1,4,2,7,1,7,2,10,0,1,2,4,0,16,2,14,0,6,2,16,0,1],[0,13,2,2,3,4,2,4,3,5,0,2,2,7,1,22,2,15,3,4,1,3,2,7,1,7,2,3,0,29,2,12,0,6,2,13,0,4],[0,2,1,2,0,9,2,1,3,5,2,5,3,6,2,7,1,22,2,15,3,4,1,3,2,3,1,1,2,3,1,7,2,2,0,30,2,13,0,5,2,5,0,1,2,6,0,5],[1,4,0,9,2,1,3,5,2,7,3,4,2,7,1,23,2,15,3,4,1,2,2,2,1,2,2,3,1,8,2,1,0,20,1,2,0,18,2,1,0,1,2,1,0,10,2,6,0,6],[1,3,0,1,1,2,0,2,2,6,3,5,2,7,3,5,2,7,1,22,2,15,3,3,1,3,2,8,1,8,0,13,2,1,1,1,0,4,1,2,2,1,0,18,2,2,0,23],[1,7,2,7,3,3,2,10,3,5,2,6,1,26,2,11,3,3,1,3,2,8,1,8,0,12,2,2,1,6,2,6,0,39],[1,6,2,9,3,2,2,10,3,2,0,3,2,6,1,24,2,1,1,1,2,12,3,1,1,4,2,5,1,2,2,2,1,7,0,12,2,2,1,6,2,9,0,36],[0,3,1,2,2,11,3,1,2,10,3,2,0,3,2,6,1,23,2,5,3,4,2,6,3,1,1,5,2,4,1,4,2,6,1,1,0,13,2,1,1,6,2,16,0,29],[0,2,1,2,2,5,0,4,2,14,3,2,0,3,2,6,1,23,2,5,3,5,2,5,3,1,1,5,2,5,1,4,2,7,0,12,1,7,2,16,0,29],[0,2,1,2,2,5,0,4,2,16,0,3,2,6,1,22,2,6,3,1,0,8,2,1,3,1,1,2,0,4,2,5,1,3,2,8,0,11,1,2,2,2,1,3,2,3,0,3,2,18,0,18,2,3],[0,2,1,3,2,4,0,4,2,16,0,4,2,4,1,23,2,6,3,1,0,8,2,4,0,4,2,10,1,2,2,4,0,7,2,4,1,3,2,1,1,3,2,3,0,3,2,1,1,1,2,16,0,1,2,2,0,15,2,3],[0,2,1,3,2,4,0,4,2,5,0,13,2,7,1,23,2,1,0,15,2,2,0,4,2,10,1,3,2,1,0,8,2,5,1,4,2,2,1,1,2,3,0,7,2,2,0,3,2,13,0,10,2,6,0,1],[0,3,1,1,2,6,0,3,2,4,0,14,2,8,1,22,2,1,0,15,2,2,0,4,2,9,1,5,0,8,2,5,1,7,2,3,0,7,2,2,0,8,2,9,0,9,2,6,0,1],[2,17,0,19,2,3,1,22,2,1,0,15,2,2,0,4,2,7,1,7,0,8,2,4,1,9,2,2,0,18,2,2,0,1,2,4,1,1,0,7,2,6,0,3],[1,2,2,15,0,20,2,2,1,23,2,2,0,12,2,6,0,1,2,7,1,7,0,8,2,1,1,11,0,24,1,7,0,5,2,6,0,3],[2,17,0,21,2,1,1,22,2,5,0,10,1,1,2,13,1,7,0,8,1,12,0,26,1,5,2,7,0,7],[2,17,0,21,2,1,1,22,2,5,0,12,2,12,1,8,0,6,1,13,0,26,1,6,2,6,0,7],[2,10,1,1,2,6,1,2,0,14,2,2,0,3,2,1,1,22,2,4,0,13,2,10,1,11,0,5,1,11,0,8,1,2,0,20,1,5,2,4,0,8],[2,8,1,7,2,2,1,2,0,14,2,2,0,3,1,23,2,4,0,11,2,5,0,4,2,2,1,13,0,4,1,11,0,8,1,2,0,20,1,5,2,4,0,8],[2,8,1,5,0,20,1,2,0,3,1,23,2,3,0,12,2,5,0,4,1,15,0,4,1,10,0,9,1,2,0,10,1,4,0,9,1,6,0,8],[2,9,1,4,0,20,1,2,0,3,1,23,2,1,0,15,2,4,0,4,1,15,0,5,1,9,0,6,1,5,0,10,1,5,0,22],[2,9,3,4,0,20,1,2,0,3,1,22,2,2,0,3,2,2,0,9,2,5,0,4,1,15,0,3,1,11,0,5,1,8,0,8,1,8,0,19],[2,13,0,20,1,27,2,2,0,13,2,6,0,4,1,15,0,3,1,10,0,3,1,12,0,7,1,8,0,19],[0,4,2,9,0,6,2,2,0,12,1,28,2,1,0,3,2,2,1,2,2,8,0,4,2,2,1,30,0,3,1,13,0,6,1,10,0,17],[0,5,2,11,0,3,2,2,0,12,1,30,2,4,1,3,2,7,0,4,2,2,1,30,0,3,1,29,0,17],[0,6,2,17,0,11,1,29,2,4,1,3,2,2,1,2,2,3,0,4,2,1,1,63,0,4,1,2,0,11],[0,9,2,15,0,10,1,29,2,4,1,3,2,2,1,2,2,4,0,3,1,22,2,4,1,38,0,1,1,5,2,1,0,10],[0,10,2,17,0,7,1,29,2,1,0,2,2,1,1,3,2,10,1,22,2,5,1,2,2,6,1,4,2,2,1,31,2,1,0,9],[0,11,2,17,0,6,1,29,0,3,2,1,1,3,2,4,1,29,2,4,1,1,2,7,1,4,2,3,1,31,0,9],[0,19,2,12,0,3,2,1,1,27,0,4,2,1,1,2,2,2,0,9,1,23,2,4,1,1,2,7,1,5,2,1,1,28,2,1,1,3,0,9],[0,19,2,17,1,26,0,5,2,4,0,9,1,20,2,18,1,15,2,6,1,9,2,2,1,6,0,6],[0,21,2,18,1,23,0,7,2,1,1,1,0,9,1,19,2,20,1,1,2,2,1,1,2,3,1,5,2,13,1,3,2,4,1,4,2,1,0,5,2,1],[0,21,2,18,1,24,2,1,0,4,2,2,1,1,0,7,1,21,2,18,1,3,2,32,1,4,0,5,2,1],[0,21,2,19,1,22,2,2,0,4,2,2,1,3,0,4,1,22,2,18,1,1,2,1,1,1,2,36,0,6],[0,21,2,20,1,20,2,2,0,1,2,6,1,3,0,1,1,24,2,19,1,1,2,37,0,7],[0,25,2,16,1,19,2,10,1,28,2,2,1,2,2,14,1,2,2,36,0,8],[0,25,2,2,0,4,2,8,1,1,2,2,1,15,2,13,1,28,2,19,1,1,2,33,0,11],[0,32,2,10,1,14,2,15,1,1,2,1,1,1,2,1,1,1,2,11,1,11,2,53,0,11],[0,33,2,10,1,14,2,1,1,2,2,28,1,10,2,53,0,11],[0,33,2,10,1,14,2,31,1,10,2,1,0,4,2,48,0,11],[0,33,2,10,1,14,2,29,1,12,2,1,0,4,2,48,0,11],[0,11,2,8,0,18,2,2,1,17,2,30,1,13,0,10,2,5,0,2,2,13,3,1,2,20,0,12],[0,11,2,8,0,18,1,20,2,29,1,13,0,9,2,6,0,3,2,5,0,3,2,3,3,3,2,10,0,21],[0,7,2,16,0,14,1,23,2,26,1,13,0,9,2,6,0,4,2,4,0,40],[0,7,2,16,0,14,2,2,1,22,2,24,1,15,0,4,2,2,0,3,2,4,0,49],[0,5,2,6,1,1,0,3,1,2,2,10,0,11,2,1,1,24,2,21,1,16,0,3,1,1,2,9,0,49],[0,4,2,7,0,4,1,1,2,11,0,14,1,20,0,3,2,3,0,6,2,3,0,2,2,4,1,17,0,3,1,3,0,1,2,7,0,49],[0,3,2,7,0,5,2,10,0,16,1,20,0,3,1,1,2,1,0,7,2,3,0,2,2,4,1,21,2,10,0,48,2,1],[2,2,0,1,2,7,0,5,2,10,0,13,1,2,0,1,1,20,0,12,2,1,1,2,0,2,2,6,1,18,2,11,0,48,1,1],[2,2,0,1,2,7,0,5,2,7,0,16,1,23,0,12,2,12,1,18,2,10,0,6,2,2,0,32,2,4,0,5],[0,3,1,1,2,5,0,6,2,6,0,17,1,25,2,1,0,8,2,13,1,18,2,8,0,8,2,2,0,32,2,2,1,2,0,5],[0,3,1,2,2,4,0,6,2,6,0,17,1,24,2,2,0,8,2,14,1,17,0,4,2,4,0,6,2,4,0,20,2,4,0,4,2,6,1,1,2,1,0,5],[0,2,2,1,1,2,2,4,0,5,2,10,0,15,1,22,2,6,0,3,2,16,1,17,0,4,2,4,0,6,2,4,0,20,2,4,0,4,2,8,0,5],[0,2,2,5,0,7,2,11,0,13,1,22,2,2,1,2,2,22,1,15,0,6,2,4,1,1,0,7,2,2,0,10,2,26,0,5],[0,5,2,3,0,6,2,11,0,13,1,21,2,27,1,16,0,5,2,3,1,2,0,7,2,2,0,10,2,26,0,5],[0,5,2,3,0,5,1,4,2,10,0,11,2,1,1,19,2,16,1,3,2,9,1,16,0,5,2,3,1,2,0,21,2,22,0,7],[0,5,2,3,0,5,1,6,2,8,0,10,2,2,1,17,2,18,1,4,2,9,1,14,0,6,2,4,0,22,2,23,0,6],[0,5,2,8,1,6,0,1,2,2,0,3,2,2,0,6,2,6,1,16,2,11,0,2,2,7,1,2,2,10,1,14,0,4,2,6,0,23,2,22,0,6],[0,5,2,8,1,6,0,6,2,2,0,6,2,6,1,16,2,10,0,6,2,16,1,14,0,4,2,8,0,22,2,5,3,1,2,15,0,6],[0,6,2,8,1,5,0,6,2,2,0,6,2,6,1,16,2,9,0,9,2,5,0,3,2,5,1,15,0,4,2,8,0,22,2,7,3,1,2,14,0,5],[0,8,2,7,1,5,0,5,2,2,0,6,2,6,1,16,2,9,0,9,2,1,1,3,0,4,2,5,1,7,2,2,1,6,0,3,2,9,0,9,2,2,0,11,2,6,3,3,2,14,0,4],[0,8,2,7,1,5,2,7,0,12,2,1,1,14,2,13,0,6,3,1,1,3,0,4,2,5,1,2,2,1,1,4,2,3,1,6,2,8,0,12,2,5,0,8,2,6,0,4,2,13,0,4],[0,8,2,9,1,3,2,7,0,12,2,1,1,14,2,13,0,5,3,1,1,5,0,3,2,10,1,2,2,4,1,5,2,1,1,1,2,7,0,11,2,6,0,7,2,6,0,4,2,11,0,6],[0,8,2,19,0,13,2,1,1,13,2,8,0,10,1,6,0,5,2,10,1,1,2,3,1,5,2,7,0,12,2,1,1,3,2,3,1,1,0,6,2,6,0,8,2,7,0,6],[0,4,2,26,0,10,2,3,1,11,2,7,0,12,1,5,0,5,2,11,1,1,2,3,1,3,2,8,0,12,1,5,2,2,1,1,0,6,1,1,2,5,0,8,2,7,0,6],[0,3,2,27,0,10,2,3,1,12,2,4,0,14,1,5,0,5,2,12,1,1,2,1,1,4,2,4,0,16,1,6,2,2,0,6,1,1,2,3,0,11,2,7,0,5],[2,3,1,4,2,23,0,10,2,2,1,11,2,1,1,4,2,1,0,14,1,5,0,5,2,11,1,8,2,3,0,16,1,7,2,2,0,5,1,1,2,3,0,12,2,6,0,5],[3,3,1,3,0,5,2,6,0,1,2,15,0,7,2,2,1,10,2,3,1,1,0,17,1,4,2,2,0,4,2,11,1,8,2,2,0,9,2,3,1,14,0,21,2,11],[0,2,1,4,0,5,2,6,0,6,2,10,0,7,2,3,1,9,2,3,1,1,0,17,1,4,2,2,0,4,2,11,1,8,2,1,0,10,1,17,0,21,2,11],[0,2,1,4,0,5,2,6,0,9,2,9,0,5,2,3,1,9,2,3,1,1,0,11,1,9,2,3,0,4,2,10,1,7,2,1,0,12,3,1,1,16,0,25,2,7],[0,4,1,2,0,5,2,6,0,10,2,9,0,5,2,1,1,10,2,4,0,11,1,8,2,4,0,4,2,9,1,9,0,12,1,16,2,3,0,23,2,7],[0,4,1,2,0,5,2,4,0,14,2,7,0,7,1,10,2,3,0,9,1,9,2,3,0,6,2,6,1,12,0,10,1,17,2,4,0,25,2,3,1,2],[0,11,2,4,0,14,2,7,0,7,1,10,2,2,0,1,2,2,0,2,2,1,1,3,0,1,1,9,2,3,0,6,2,3,1,1,2,1,1,13,0,10,1,16,2,2,1,1,2,1,0,11,2,4,0,10,1,1,2,3,0,2],[0,11,3,1,2,3,0,14,2,8,0,6,1,10,2,5,0,2,1,14,2,3,0,6,2,3,1,16,2,2,1,2,2,6,1,15,2,1,1,3,0,10,2,6,0,9,1,1,2,3,0,2],[0,11,3,2,2,2,0,14,2,8,0,6,1,10,2,5,0,3,1,12,2,4,0,6,2,3,1,16,2,12,3,1,1,11,2,2,1,3,0,9,2,7,0,5,1,4,2,3,0,3],[0,9,3,3,2,5,0,14,2,6,0,6,1,10,2,8,1,13,2,3,0,4,2,5,1,17,2,11,3,1,1,10,2,4,1,1,2,1,0,6,2,10,0,5,1,1,2,6,0,3],[0,9,3,3,2,5,0,14,2,6,0,6,1,10,2,9,1,15,0,4,2,5,1,17,2,13,1,9,2,6,0,6,2,13,0,2,2,7,0,3],[0,7,3,6,0,18,2,6,0,6,1,10,2,8,3,1,1,8,2,3,0,1,1,2,0,5,2,5,1,15,0,6,2,12,1,5,2,9,0,4,2,22,0,3],[0,7,3,6,0,13,2,2,0,3,2,6,0,6,1,10,2,8,3,1,1,6,2,6,0,7,2,5,1,15,0,6,2,13,1,3,2,10,0,4,2,22,0,3],[0,7,3,1,0,18,2,2,0,1,2,8,0,6,1,10,2,4,0,4,3,2,1,2,3,4,2,5,0,7,2,5,1,15,0,10,2,9,1,3,2,9,0,9,2,16,0,5],[0,3,2,1,1,2,3,7,2,1,0,14,2,9,0,5,1,15,0,4,3,8,2,17,1,15,0,10,2,20,0,10,2,16,0,5],[0,3,2,1,0,9,2,1,0,14,1,1,2,12,1,16,0,4,2,1,3,7,2,17,1,15,0,12,2,7,0,4,2,7,0,10,2,14,0,7],[0,3,1,1,0,9,2,1,0,14,1,1,2,12,1,16,0,4,2,1,3,1,1,3,3,2,2,18,1,15,0,11,2,7,0,6,2,6,0,10,2,14,0,7],[0,3,1,1,0,9,2,1,0,14,2,13,1,16,0,4,2,1,3,1,0,7,2,3,3,1,2,12,1,14,0,12,2,6,0,7,2,10,0,6,2,4,0,17],[0,3,1,1,0,9,2,1,0,14,2,13,1,19,0,1,1,2,0,10,2,13,1,13,0,26,2,6,1,2,2,2,0,5,2,5,0,17],[0,3,1,1,0,9,2,1,0,13,2,10,0,1,2,3,1,22,0,11,2,12,1,13,0,26,2,4,0,4,3,2,0,5,2,5,0,17],[0,3,1,1,0,9,2,1,0,13,2,10,0,5,1,21,0,12,2,11,1,14,0,25,2,3,3,1,0,4,3,2,0,6,2,4,0,17],[0,3,1,1,0,9,2,1,0,1,2,2,0,10,2,7,0,8,1,19,3,2,0,12,2,11,1,14,0,23,2,6,0,13,2,3,0,17],[0,3,1,1,0,9,2,1,0,1,2,2,0,10,2,6,0,9,1,19,3,2,0,12,3,3,2,8,1,17,2,1,0,19,2,6,0,14,2,2,0,17],[0,3,1,1,0,9,3,1,0,1,2,2,0,8,2,4,0,1,2,2,0,9,1,20,0,14,3,3,2,8,1,17,2,1,0,19,2,4,0,16,2,2,0,10,2,6,0,1],[0,3,1,7,3,4,0,1,2,2,0,7,2,5,0,12,1,19,3,1,0,14,3,3,2,8,1,17,0,20,2,4,0,16,2,5,0,7,2,6,0,1],[0,15,2,2,0,7,2,5,0,10,2,2,1,19,3,1,0,14,3,3,2,8,1,16,0,19,2,6,0,16,2,5,0,7,2,4,0,3],[0,9,1,3,3,2,2,3,0,8,2,4,0,10,2,2,1,19,2,1,0,14,3,2,2,9,1,15,0,15,2,2,0,3,2,6,0,15,2,5,0,8,2,4,0,3],[0,9,1,5,2,3,0,8,2,4,0,8,2,5,1,17,2,2,0,14,1,1,2,10,1,15,0,8,2,2,0,5,2,2,0,1,2,12,0,8,2,8,0,8,2,4,0,3],[0,8,1,6,3,1,2,2,0,8,2,5,0,7,2,5,1,17,2,2,0,14,2,11,1,15,0,5,2,5,0,7,2,12,1,1,0,8,2,8,0,8,2,4,0,3],[0,1,1,2,0,4,1,7,3,1,2,4,0,6,2,5,0,7,2,6,1,17,2,2,0,13,2,11,1,18,2,7,0,7,2,6,0,1,2,4,1,3,0,1,1,2,2,4,1,1,2,6,0,5,2,10,0,1],[0,1,1,2,0,4,3,1,1,6,3,1,2,3,3,1,0,6,2,5,0,7,2,8,1,16,2,3,0,11,2,11,1,7,2,2,1,10,2,7,0,7,2,2,0,3,2,5,1,6,2,3,1,3,2,5,0,5,2,2,0,2,2,6,0,1],[0,1,1,2,0,4,3,2,0,6,2,3,3,1,0,6,2,5,0,11,2,5,1,15,2,3,1,1,0,6,2,4,1,6,2,4,1,7,2,3,1,11,2,6,0,12,2,8,1,4,2,3,1,2,2,5,0,3,2,1,0,2,2,1,0,2,2,7],[0,1,1,2,0,3,3,3,0,6,1,1,2,3,0,6,2,5,0,11,2,5,1,16,2,1,1,2,0,6,2,2,1,19,2,3,1,11,2,6,0,10,2,10,1,5,2,13,0,2,2,10],[0,6,3,3,0,6,1,2,2,2,0,4,2,7,0,11,2,4,1,18,2,2,0,4,2,3,1,20,2,4,1,10,2,7,0,9,2,8,1,7,2,25],[0,6,3,2,2,1,0,6,1,2,3,1,2,1,0,4,2,6,0,12,2,4,1,18,2,3,0,3,2,2,1,23,2,3,1,9,2,6,0,10,2,8,1,8,2,22,0,1,2,1],[0,5,3,2,2,2,0,6,1,3,2,9,0,12,2,5,1,18,2,4,0,3,2,1,1,25,2,3,1,4,2,1,0,3,2,6,0,10,2,14,1,3,2,8,1,1,2,9,0,4,2,1],[0,5,3,1,2,3,0,6,1,3,2,9,0,12,2,5,1,17,2,7,0,1,2,1,1,26,2,2,1,5,0,3,2,4,1,2,2,6,0,2,1,2,2,16,1,1,2,18,0,4,2,1],[0,7,2,6,1,5,2,7,0,14,2,4,1,18,2,9,1,32,0,4,2,12,0,2,2,12,0,5,2,1,0,2,2,8,1,2,0,1,2,6,0,5],[0,7,2,6,1,3,3,2,2,7,0,14,2,5,1,16,2,10,1,12,2,3,1,16,0,5,2,12,0,5,2,9,0,5,2,1,0,2,2,8,1,4,2,5,0,5],[0,7,2,5,1,1,0,4,3,2,2,4,0,18,2,3,1,14,2,6,0,3,2,4,1,8,2,6,1,15,0,6,2,12,0,5,2,9,0,5,2,9,1,7,2,6,0,3],[0,7,2,6,0,4,2,6,0,18,2,3,1,13,2,6,0,4,2,5,1,5,2,9,1,13,0,7,2,7,0,10,2,9,0,5,2,7,1,2,0,3,2,1,1,4,2,5,0,3],[0,41,2,3,1,12,2,7,0,6,2,4,1,3,2,11,1,12,0,7,2,4,0,2,2,1,0,15,2,6,0,2,2,8,1,2,0,3,2,1,1,5,2,4,3,2,0,1],[0,41,2,1,1,15,2,6,0,5,2,7,1,1,2,11,1,12,0,7,2,4,0,2,2,1,0,16,2,16,1,1,0,3,2,1,1,6,2,3,3,2,0,1],[0,37,2,4,1,18,2,2,0,7,2,3,0,6,2,10,1,12,2,12,0,21,2,15,0,4,1,5,2,3,3,2,0,1],[0,37,2,4,1,18,2,2,0,8,2,2,0,6,2,8,1,16,2,10,0,22,2,5,0,2,2,7,0,4,1,2,3,3,2,2,0,1,2,2,0,1],[0,27,2,2,0,8,2,3,1,20,2,1,0,8,2,2,0,6,2,7,1,18,2,1,0,2,2,4,0,25,2,4,0,2,2,7,0,4,1,2,2,9],[0,27,2,2,0,8,2,2,1,21,2,2,0,2,1,1,2,1,0,2,2,3,0,6,2,5,1,18,2,3,0,2,2,4,0,25,2,3,0,3,2,7,0,4,2,2,0,3,2,6],[0,27,2,2,0,8,2,1,1,22,2,3,1,2,2,8,0,4,2,6,1,17,0,7,2,2,0,10,2,4,0,10,2,4,0,3,2,2,0,11,2,1,0,2,2,6],[0,26,2,3,0,7,2,1,1,24,2,2,1,2,2,8,0,4,2,6,1,16,0,8,2,2,0,10,2,4,0,10,2,4,0,16,2,9],[0,26,2,4,1,1,0,4,2,1,1,24,2,13,0,4,2,6,1,16,0,8,2,2,0,10,2,4,0,12,2,2,0,18,2,2,0,4,2,1],[0,26,2,4,1,1,2,3,1,2,2,4,1,19,2,24,1,16,0,8,2,2,0,10,3,2,2,2,0,12,2,2,0,18,2,2,0,4,2,1],[0,26,2,2,0,2,2,1,1,5,2,5,1,17,2,9,0,4,2,13,1,17,0,6,2,4,0,6,1,2,0,16,2,2,0,25],[0,30,1,7,2,4,1,14,2,12,0,4,2,12,1,18,0,6,2,4,0,6,1,2,0,15,2,4,0,6,2,2,0,16],[0,30,1,7,2,1,1,1,2,4,1,11,2,9,0,8,2,2,0,1,2,9,1,18,0,6,2,4,0,23,2,5,0,4,2,3,0,16],[0,31,1,6,2,6,1,11,2,9,0,7,2,3,0,6,2,4,1,1,2,1,1,16,0,6,2,4,0,21,2,7,0,4,2,2,0,17],[0,29,2,1,1,7,2,6,1,11,2,2,1,2,2,4,0,8,2,3,0,8,2,5,1,16,2,1,0,4,2,6,0,19,2,7,0,16,2,2,0,5],[0,29,2,1,1,7,2,3,1,1,2,1,1,12,2,2,1,2,2,5,0,5,2,2,0,1,2,2,0,8,2,5,1,16,2,1,0,4,2,7,0,18,2,7,0,16,2,2,0,5],[0,29,2,2,1,7,2,1,1,15,2,8,0,1,2,4,1,6,2,2,0,6,2,5,1,16,2,15,0,15,2,7,0,16,2,2,0,5],[0,29,2,2,1,24,2,4,0,3,2,3,1,10,0,6,2,5,1,16,2,14,0,12,2,2,0,4,2,5,0,16,2,2,0,5],[0,29,2,2,1,24,2,4,0,3,2,2,1,12,2,1,0,4,2,5,1,16,2,5,0,18,2,5,0,4,2,2,0,1,2,4,0,10,2,10,0,1],[0,29,2,2,1,25,2,3,0,4,2,1,1,13,2,1,0,3,2,5,1,16,2,5,0,18,2,5,0,7,2,4,0,9,2,11,0,1],[0,27,2,5,1,24,2,3,0,4,2,1,1,13,2,8,1,16,2,5,1,1,0,18,2,6,0,8,2,2,0,9,2,12],[0,27,2,6,1,24,2,2,0,4,2,1,1,13,2,8,1,15,2,6,1,1,0,18,2,6,0,8,2,2,0,5,2,16],[0,27,2,6,1,23,2,2,1,1,0,4,2,1,1,13,0,1,2,6,1,15,2,7,1,2,2,1,0,16,2,6,0,8,2,2,0,4,2,7,0,9,2,1],[0,27,1,1,2,6,1,22,2,2,1,2,2,3,1,14,0,3,2,4,1,14,2,11,0,15,2,7,0,8,2,2,0,4,2,6,0,10,2,1],[0,27,1,1,2,6,1,22,2,2,1,2,2,3,1,14,0,3,2,3,1,15,2,8,0,1,2,8,0,9,2,7,0,8,2,9,0,13,2,1],[0,26,1,2,2,8,1,23,2,5,1,13,0,3,2,3,1,15,2,4,0,5,2,9,0,6,2,9,0,8,2,8,0,14,2,1],[0,21,2,2,1,4,2,4,0,7,1,20,2,2,0,11,1,6,0,3,2,3,1,16,2,3,0,7,2,7,0,6,2,8,1,1,0,10,2,5,0,9,2,7],[0,21,2,1,1,5,2,5,0,6,1,20,2,2,0,3,2,1,3,1,0,10,1,1,2,1,0,3,2,3,1,18,0,8,2,7,0,7,2,8,0,10,2,4,0,10,2,7],[0,21,1,6,2,5,0,6,1,19,2,3,0,17,2,5,1,10,2,1,1,8,2,4,0,5,2,7,0,6,2,12,0,16,2,11],[0,21,1,6,2,5,0,6,1,18,2,3,0,17,2,6,1,9,2,3,1,5,2,5,1,1,0,8,2,4,0,6,2,13,0,15,2,11],[0,23,1,5,2,4,0,5,2,1,1,18,2,3,0,17,2,6,1,8,2,5,1,4,2,6,0,9,2,13,0,6,2,4,0,12,2,7,0,6],[0,23,1,6,2,3,0,5,2,2,1,16,2,4,0,18,2,5,1,7,2,7,1,4,2,6,0,9,2,12,0,6,2,4,0,12,2,5,0,8],[0,23,1,6,2,10,1,16,2,4,0,18,2,4,1,8,2,9,1,2,2,3,1,3,0,9,2,10,0,8,2,6,0,8,2,7,0,8],[0,23,1,11,2,5,1,17,2,4,0,17,2,4,1,8,2,8,0,17,2,6,1,1,2,4,0,8,2,6,0,7,2,5,0,11],[0,25,1,10,2,3,1,18,2,4,0,17,2,4,1,11,2,1,0,21,2,4,0,16,2,5,0,4,2,8,0,11],[0,25,1,32,2,3,0,14,2,7,1,9,2,3,0,42,2,5,0,3,2,8,0,11],[0,25,1,4,0,3,1,25,2,5,0,2,2,17,1,8,2,4,0,45,2,9,0,15],[0,25,1,4,0,4,1,25,2,4,0,2,2,17,1,8,2,4,0,11,2,2,0,33,2,8,0,15],[0,2,2,11,0,12,1,2,0,7,1,25,2,3,1,2,2,9,1,1,2,7,1,8,2,4,0,11,2,2,0,34,2,7,0,10,2,5],[0,2,2,1,0,9,2,1,0,11,1,3,0,9,1,24,2,10,1,6,2,5,1,9,2,6,0,6,2,4,0,16,2,2,0,17,2,6,0,10,2,4,0,1],[0,2,2,1,0,9,2,1,0,11,1,1,3,2,0,9,2,1,1,23,2,9,1,7,2,5,1,10,2,6,0,4,2,6,0,15,2,2,0,38],[0,2,2,1,0,9,2,1,0,11,3,3,2,1,0,6,2,1,1,1,2,1,1,24,2,8,1,7,2,4,1,12,2,5,0,4,2,6,0,55],[0,2,2,1,0,9,2,1,0,10,1,1,2,10,1,2,2,2,1,27,2,4,1,2,2,4,1,1,2,4,1,13,2,2,0,6,2,8,0,18,2,4,0,24,2,1,0,6],[0,2,2,1,0,9,2,1,0,10,2,15,1,33,2,3,1,20,2,1,0,6,2,8,1,1,0,14,2,2,0,1,2,7,0,21,2,1,0,6],[0,2,2,1,0,9,2,1,0,1,2,1,0,6,2,17,1,56,2,1,0,6,2,6,1,3,0,13,2,12,0,20,2,1,0,5,1,1],[0,2,2,1,0,9,2,1,0,1,2,1,0,6,2,16,1,57,2,1,0,6,2,6,1,2,2,1,0,8,2,2,0,3,2,12,0,20,2,1,0,5,1,1],[0,2,2,1,0,9,2,1,0,1,2,1,0,6,2,12,1,60,2,17,0,7,2,20,0,14,2,5,0,6],[0,2,2,1,0,9,2,1,0,1,2,1,0,6,2,9,1,63,2,17,0,6,2,22,0,13,2,5,0,6],[0,2,2,1,1,3,3,3,2,4,0,8,2,9,1,64,2,16,0,5,2,16,1,1,2,6,0,13,2,5,0,6],[0,7,1,1,0,12,2,10,1,18,2,5,1,42,2,2,1,1,2,4,0,3,2,5,0,5,2,16,1,1,2,10,0,9,2,6,0,5],[0,7,1,1,2,4,0,8,2,9,1,11,0,2,1,6,2,5,1,46,2,3,0,4,2,6,1,2,2,10,1,2,2,4,0,5,2,4,1,4,0,6,2,8,0,5],[0,7,1,1,2,5,0,7,2,9,1,11,0,3,1,5,2,5,1,2,2,4,1,41,0,7,2,3,1,4,2,15,0,6,2,5,1,4,0,5,1,1,2,5,0,7],[0,7,1,1,2,5,0,4,2,11,1,12,0,3,1,1,2,2,1,2,2,5,1,2,2,5,1,40,0,8,2,2,1,3,2,6,0,3,2,5,0,10,2,7,0,5,1,1,2,4,0,8],[0,7,2,2,0,1,2,3,0,4,2,2,1,2,2,6,1,10,2,1,1,1,0,4,1,1,2,2,1,2,2,12,1,40,0,8,2,2,1,1,2,8,0,3,2,5,0,9,2,10,0,2,1,1,2,4,0,9],[3,1,1,2,0,6,2,10,1,3,2,5,1,8,2,3,0,9,2,15,1,38,0,8,2,4,0,3,2,4,0,3,2,5,0,9,2,11,1,3,2,3,0,9],[3,2,1,2,2,15,1,4,2,4,1,7,2,2,0,11,2,17,1,36,0,8,2,4,0,3,1,1,2,3,0,5,2,3,0,12,2,8,1,4,2,2,0,9],[2,19,1,6,2,3,1,5,2,3,0,11,2,18,1,32,0,1,1,2,0,7,2,5,0,3,1,2,0,7,2,7,0,8,2,8,1,4,0,11],[2,1,0,5,2,13,1,7,2,1,1,4,0,16,2,19,1,29,2,2,0,9,2,6,0,3,1,2,0,8,2,6,0,8,2,8,1,4,0,11],[2,1,0,5,2,8,0,4,2,1,1,3,0,2,1,6,0,28,2,16,1,6,0,7,1,4,0,15,2,6,0,15,2,6,0,29],[2,1,0,24,1,1,2,3,0,34,2,14,1,2,0,8,1,4,0,15,2,6,0,15,2,6,0,29],[0,25,2,2,0,36,2,15,1,1,0,27,2,6,0,15,2,6,0,29],[0,25,2,2,0,36,2,16,0,28,2,5,0,15,2,6,0,29],[0,63,2,16,0,28,2,6,0,14,2,8,0,27],[0,63,2,16,0,28,2,6,0,14,2,8,0,27],[0,63,2,16,0,29,2,9,0,8,2,4,0,33],[0,63,2,16,0,30,2,13,0,3,2,4,0,33],[0,63,2,20,0,29,2,17,0,33],[0,63,2,20,0,30,2,16,0,33],[0,55,3,1,2,29,0,29,2,6,0,42],[0,55,3,1,2,29,0,33,2,2,0,42],[0,55,3,1,2,29,0,33,2,1,1,1,0,42],[0,55,2,30,0,77],[0,59,2,8,0,4,2,1,0,90],[0,59,2,8,0,95],[0,61,2,6,0,95],[0,61,2,6,0,95],[0,61,2,6,0,95],[0,61,2,6,0,95],[0,61,2,6,0,95],[0,61,2,1,1,2,2,3,0,95],[0,63,3,2,0,97]]} diff --git a/packages/core/src/sim/movement.ts b/packages/core/src/sim/movement.ts index e7c5c61..58fab2c 100644 --- a/packages/core/src/sim/movement.ts +++ b/packages/core/src/sim/movement.ts @@ -725,7 +725,7 @@ function laneNavGoal( field, entity.x, entity.y, - isShortApproach ? DOCK_APPROACH_LOCAL_GOAL_CELLS : undefined, + isShortApproach ? dockApproachCells(mask.cellSizeX) : undefined, ); if (step !== null) return step; } @@ -742,7 +742,7 @@ function laneNavGoal( orderY, entity.x, entity.y, - isShortApproach ? DOCK_APPROACH_LOCAL_GOAL_CELLS : undefined, + isShortApproach ? dockApproachCells(ruleset.map.waterMask.cellSizeX) : undefined, ); return step ?? { x: orderX, y: orderY }; } @@ -780,11 +780,18 @@ function fieldToPoint(mask: WaterMask, x: number, y: number): NavField | null { return field; } -/** Hand-off distance (in cells) for a SHIP rounding land onto a dock: follow the - * field gradient to within ONE cell of the goal's water-access cell before the - * straight-line final step, so the ship rounds the coastal spit instead of - * beelining into it. Open hauls keep navStepToward's default (6). */ -const DOCK_APPROACH_LOCAL_GOAL_CELLS = 1; +/** Hand-off distance for a SHIP rounding land onto a dock, in WORLD UNITS + * (~one 128u legacy cell): follow the field gradient to within this range of + * the goal's water-access cell before the straight-line final step, so the + * ship rounds the coastal spit instead of beelining into it. Converted to + * grid hops per-mask so behavior is resolution-independent (the emitted + * grid is 64u cells as of the full-res lane deduction). Open hauls keep + * navStepToward's unit-derived default. */ +const DOCK_APPROACH_LOCAL_GOAL_UNITS = 128; + +function dockApproachCells(cellSize: number): number { + return Math.max(1, Math.round(DOCK_APPROACH_LOCAL_GOAL_UNITS / cellSize)); +} /** True if the straight segment (x0,y0)->(x1,y1) passes over any LAND cell * (sampled at half-cell resolution incl. the endpoint), i.e. a naive diff --git a/packages/core/src/sim/types.ts b/packages/core/src/sim/types.ts index 133d9e7..3d0e060 100644 --- a/packages/core/src/sim/types.ts +++ b/packages/core/src/sim/types.ts @@ -1773,17 +1773,22 @@ export function navStepToward( field: NavField, x: number, y: number, - localGoalDistCells = 6, + localGoalDistCells?: number, ): { x: number; y: number } | null { const { bounds, cols, rows, cellSizeX, cellSizeY, dist } = field; if (dist.length === 0) return null; // stub field (no real mask) -> straight line + // Default local-goal basin: ~768 WORLD UNITS (six 128u legacy cells), + // derived from the field's cell size so the hand-off distance is + // resolution-independent (the emitted grid is 64u cells as of the + // full-res lane deduction). + const localGoal = localGoalDistCells ?? Math.max(1, Math.round(768 / cellSizeX)); if (x < bounds.minX || x >= bounds.maxX || y <= bounds.minY || y > bounds.maxY) return null; const col = Math.floor((x - bounds.minX) / cellSizeX); const row = Math.floor((bounds.maxY - y) / cellSizeY); if (col < 0 || col >= cols || row < 0 || row >= rows) return null; const here = dist[row * cols + col] ?? NAV_UNREACHABLE; if (here === NAV_UNREACHABLE) return null; // on land / unreachable -> let slide handle it - if (here <= localGoalDistCells) return null; // near the goal -> straight line in + if (here <= localGoal) return null; // near the goal -> straight line in // Lowest-distance navigable 8-neighbour (deterministic neighbour order). const NEIGHBOURS: readonly [number, number][] = [ diff --git a/packages/core/test/fog.test.ts b/packages/core/test/fog.test.ts index c9fb66c..4bcf2c8 100644 --- a/packages/core/test/fog.test.ts +++ b/packages/core/test/fog.test.ts @@ -85,7 +85,7 @@ function findPair(blocked: boolean, minD: number, maxD: number): { a: { x: numbe for (let c = 2; c < cols - 2; c += 2) { if (cells[r * cols + c] !== 1) continue; const a = world(c, r); - const reach = Math.ceil(maxD / 128) + 1; + const reach = Math.ceil(maxD / cellSizeX) + 1; for (let dr = -reach; dr <= reach; dr += 2) { for (let dc = -reach; dc <= reach; dc += 2) { const nc = c + dc; diff --git a/packages/core/test/terrain-integration.test.ts b/packages/core/test/terrain-integration.test.ts index 184e3a5..1e47661 100644 --- a/packages/core/test/terrain-integration.test.ts +++ b/packages/core/test/terrain-integration.test.ts @@ -78,7 +78,8 @@ describe('terrain integration (real water mask)', () => { expect(ruleset.map.waterMask.cells.length).toBeGreaterThan(0); // The mask is SAILABILITY from the map's own PATHING MAP (war3map.wpm bit // 0x40 = no-water — the engine's enforced truth; see terrain.py), cropped - // to the 81x113 PLAYABLE tilepoint grid (the unplayable border removed; + // to the 162x226 PLAYABLE grid (64u cells — 2x the tilepoint spacing; + // lane-topology equivalence vs the raw 32u wpm is gate G6) (the unplayable border removed; // the WEST bound extended 3 cells west of the camera bounds so the Goblin // Potion Dealer shop sits off the grid edge — see docs/TERRAIN.md // WEST-BOUND EXTENSION), PLUS only MINIMAL 1-cell connectivity necks (so @@ -91,10 +92,10 @@ describe('terrain integration (real water mask)', () => { // real map separates. const water = ruleset.map.waterMask.cells.reduce((n, c) => n + c, 0); const total = ruleset.map.waterMask.cells.length; - expect(total).toBe(81 * 113); - // ~0.553: the wpm sailable fraction over the playable crop (+ necks + - // moats). Same band as the extractor's fail-loud gate [0.50, 0.62]: - // well above = colour-key-style over-watering, well below = over-dry. + expect(total).toBe(162 * 226); // 64u cells (full-res lane deduction) + // ~0.513: the wpm sailable fraction at 64u cells with LAND-BIASED ties + // (straddling walls are kept, conservatively thickening land). Same band + // as the extractor's fail-loud gate [0.50, 0.62]. expect(water / total).toBeGreaterThan(0.5); expect(water / total).toBeLessThan(0.62); // Nav fields are populated (a real flood from each base goal). diff --git a/packages/server/test/ai-match.test.ts b/packages/server/test/ai-match.test.ts index 409c476..ae59a63 100644 --- a/packages/server/test/ai-match.test.ts +++ b/packages/server/test/ai-match.test.ts @@ -351,7 +351,12 @@ describe('bot-vs-bot match (real brain, both teams AI)', () => { // touched. The HQ-damage milestone is therefore replaced by the funnel's real // signal: enemy towers keep taking chip from held creeps across the run. it('over a long match the funnel keeps engaging the enemy towers, without idling in retreat', async () => { - const LONG_CAP = 6000; + // 9000 ticks: on the TRUE 64u map (full-res lane deduction) the lanes are + // tighter than the old blobby 128u mask — opposing waves clash in narrow + // chokes and the first tower-chipping leaker lands around tick ~5000 in a + // 10-captain probe (later with only these 2 captains). Same window as the + // core terrain-integration grind test. + const LONG_CAP = 9000; const invPeak = new Map(); const retreatThinks = new Map(); const totalThinks = new Map(); diff --git a/tools/extractor/terrain.py b/tools/extractor/terrain.py index ff731e5..f1cede6 100644 --- a/tools/extractor/terrain.py +++ b/tools/extractor/terrain.py @@ -170,7 +170,17 @@ SAMPLE_PATCH = 3 # NxN minimap pixel patch sampled per tile (majority vote) # --- connectivity-neck knobs (kept small/explicit so additions are auditable) -- -ACCESS_CELLS = 2 # a shop is "sea-reachable" if main-sea water is within this +# EMIT SUBDIVISION (owner-directed 2026-07-09: "the full res map is accurate if +# you can deduce the lanes correctly"): the emitted grid is 64u cells — HALF the +# 128u tilepoint spacing, double resolution. Measured on the wpm: real channels +# are never narrower than 128u (4 subcells) and real walls never thinner than +# 64u (2 subcells); a 128u grid provably cannot represent an unaligned 128u +# channel (both straddling cells fall under 50% water -> lane LOST) nor a 64u +# wall inside a majority-water cell (-> lanes MERGED). At 64u with land-biased +# ties, every real channel and wall survives quantization by construction. +EMIT_SUBDIV = 2 # 64u cells (128 / EMIT_SUBDIV) + +ACCESS_CELLS = 2 * EMIT_SUBDIV # a shop is "sea-reachable" if main-sea water is within this # Manhattan radius (~256u). Kept tight so the carved neck # brings navigable water RIGHT UP to the shop on its sea-facing # side -- a shop with water only 3 cells away on the far side @@ -197,7 +207,7 @@ # are matched by their owner-circled world coords (deterministic, explicit -- NOT # "western-most x", which would grab the north Pigfarm Elven Library instead). WEST_ISLAND_SHOPS = ((-4640.0, -928.0), (-4960.0, -5344.0)) # LumberMill, GoblinPotion -WEST_ISLAND_CORE_R = 2 # filled (2R+1)x(2R+1) land core; moat ring at chebyshev R+1. +WEST_ISLAND_CORE_R = 2 * EMIT_SUBDIV # filled (2R+1)x(2R+1) land core; moat ring at chebyshev R+1. # --------------------------------------------------------------------------- @@ -230,22 +240,34 @@ def wpm_sailable_grid(geom: dict, wpm: dict, map_min_x: float, map_min_y: float) 16 wpm subcells (4x4 x 32u) under the 128u cell that do NOT carry the no-water bit. Same shape/orientation as classify_grid's output.""" cols, nrows = geom["cols"], geom["rows"] + csx, csy = geom["csx"], geom["csy"] ww, wh, flags = wpm["width"], wpm["height"], wpm["flags"] + # Subcell sample offsets: centers of the 32u wpm cells under one emitted + # cell. LAND-BIASED tie (water only when STRICTLY more than half the + # subcells sail): preserves the original's 64u walls when they straddle a + # cell boundary — both straddling cells land as LAND (wall kept, + # conservatively thickened) instead of both as water (lanes merged). Real + # channels are >=128u wide (measured), so a straddling channel still owns + # a fully-water cell and survives. + nsx = max(1, round(csx / 32)) + nsy = max(1, round(csy / 32)) + offs_x = [(-csx / 2) + (i + 0.5) * 32 for i in range(nsx)] + offs_y = [(-csy / 2) + (i + 0.5) * 32 for i in range(nsy)] grid: list[list[int]] = [] for r in range(nrows): line: list[int] = [] for c in range(cols): x, y = cell_center(c, r, geom) total = sailable = 0 - for oy in (-48.0, -16.0, 16.0, 48.0): - for ox in (-48.0, -16.0, 16.0, 48.0): + for oy in offs_y: + for ox in offs_x: wx = int((x + ox - map_min_x) // 32) wy = int((y + oy - map_min_y) // 32) if 0 <= wx < ww and 0 <= wy < wh: total += 1 if not (flags[wy * ww + wx] & 0x40): sailable += 1 - line.append(1 if (total > 0 and sailable / total >= 0.5) else 0) + line.append(1 if (total > 0 and sailable * 2 > total) else 0) grid.append(line) return grid @@ -298,7 +320,10 @@ def crop_geometry(w3e: dict, cols_idx: list[int], rows_idx: list[int], playable: max_x = cx + cols_idx[-1] * TILE_SPACING + half min_y = cy + rows_idx[0] * TILE_SPACING - half max_y = cy + rows_idx[-1] * TILE_SPACING + half - cols, nrows = len(cols_idx), len(rows_idx) + # EMIT_SUBDIV: same playable bounds, finer cells (64u at 2) — see the + # constant's doc. Every downstream consumer (cell_for/cell_center, carves, + # gates, the sim) works off cols/rows/csx/csy generically. + cols, nrows = len(cols_idx) * EMIT_SUBDIV, len(rows_idx) * EMIT_SUBDIV bounds = {"minX": min_x, "minY": min_y, "maxX": max_x, "maxY": max_y} return { "bounds": bounds, @@ -1104,6 +1129,189 @@ def _water_connected(rows: list[list[int]], cols: int, nrows: int, # --------------------------------------------------------------------------- +def restore_straddled_channels(rows: list[list[int]], wpm: dict, geom: dict, + map_min_x: float, map_min_y: float) -> int: + """Undo the land-biased tie's channel NARROWING without undoing its wall + PRESERVATION. The tie votes a half-water cell to land; when a real >=128u + channel straddles the 64u grid, that shaves it to a single 64u cell — + narrower than the original (creeps are ~60u wide; opposing waves plug a + 64u choke that the real 128u choke lets flow). Flip a tied-to-land cell + back to water ONLY when every sailable wpm subcell under it AND under its + 8-adjacent water cells belongs to ONE full-res component — then the flip + widens an existing channel and provably cannot bridge two distinct + channels (the walls the tie exists to protect). Single deterministic + scan; returns cells flipped.""" + cols, nrows = geom["cols"], geom["rows"] + csx, csy = geom["csx"], geom["csy"] + ww, wh, flags = wpm["width"], wpm["height"], wpm["flags"] + + def sail(sx: int, sy: int) -> bool: + return 0 <= sx < ww and 0 <= sy < wh and not (flags[sy * ww + sx] & 0x40) + + # Full-res component labels over the whole wpm (cheap, ~200k cells). + lbl = [-1] * (ww * wh) + next_id = 0 + for start in range(ww * wh): + if lbl[start] >= 0 or (flags[start] & 0x40): + continue + stack = [start] + lbl[start] = next_id + while stack: + idx = stack.pop() + x, y = idx % ww, idx // ww + for dx in (-1, 0, 1): + for dy in (-1, 0, 1): + nx, ny = x + dx, y + dy + if (dx or dy) and 0 <= nx < ww and 0 <= ny < wh: + nidx = ny * ww + nx + if lbl[nidx] < 0 and not (flags[nidx] & 0x40): + lbl[nidx] = next_id + stack.append(nidx) + next_id += 1 + + nsx = max(1, round(csx / 32)) + nsy = max(1, round(csy / 32)) + offs_x = [(-csx / 2) + (i + 0.5) * 32 for i in range(nsx)] + offs_y = [(-csy / 2) + (i + 0.5) * 32 for i in range(nsy)] + + def cell_labels(c: int, r: int) -> set[int]: + x, y = cell_center(c, r, geom) + out: set[int] = set() + for oy in offs_y: + for ox in offs_x: + sx = int((x + ox - map_min_x) // 32) + sy = int((y + oy - map_min_y) // 32) + if 0 <= sx < ww and 0 <= sy < wh and not (flags[sy * ww + sx] & 0x40): + out.add(lbl[sy * ww + sx]) + return out + + flipped = 0 + for r in range(nrows): + for c in range(cols): + if rows[r][c]: + continue + own = cell_labels(c, r) + if len(own) != 1: + continue # no water under it, or it touches two channels: keep land + union = set(own) + for dc in (-1, 0, 1): + for dr in (-1, 0, 1): + nc, nr = c + dc, r + dr + if (dc or dr) and 0 <= nc < cols and 0 <= nr < nrows and rows[nr][nc]: + union |= cell_labels(nc, nr) + if union == own: + rows[r][c] = 1 + flipped += 1 + return flipped + + +def lane_topology_gate(rows: list[list[int]], wpm: dict, layout: dict, geom: dict, + map_min_x: float, map_min_y: float) -> dict: + """G6 (hard gate): the emitted grid must preserve the FULL-RES lane + topology — for every pair of gameplay anchors (HQs, harbours, shops, lane + spawns), 'water-connected on the emitted grid' must equal 'water-connected + on the raw 32u wpm' within the playable crop. This is the owner's + 2026-07-09 directive made permanent: the full-res map is the truth; the + grid is only correct if the lanes deduce correctly. Fails loud on any + lost channel (connected in wpm, separated in grid) or false merge + (separated in wpm, connected in grid).""" + cols, nrows = geom["cols"], geom["rows"] + b = geom["bounds"] + ww, wh, flags = wpm["width"], wpm["height"], wpm["flags"] + + def sail(sx: int, sy: int) -> bool: + return 0 <= sx < ww and 0 <= sy < wh and not (flags[sy * ww + sx] & 0x40) + + # 8-connected component labels on the emitted grid. + lbl_g = [[-1] * cols for _ in range(nrows)] + next_id = 0 + for r0 in range(nrows): + for c0 in range(cols): + if not rows[r0][c0] or lbl_g[r0][c0] >= 0: + continue + q = deque([(c0, r0)]) + lbl_g[r0][c0] = next_id + while q: + c, r = q.popleft() + for dc in (-1, 0, 1): + for dr in (-1, 0, 1): + nc, nr = c + dc, r + dr + if (dc or dr) and 0 <= nc < cols and 0 <= nr < nrows \ + and rows[nr][nc] and lbl_g[nr][nc] < 0: + lbl_g[nr][nc] = next_id + q.append((nc, nr)) + next_id += 1 + + # 8-connected component labels on the raw wpm subcells within the crop. + sx0, sy0 = int((b["minX"] - map_min_x) // 32), int((b["minY"] - map_min_y) // 32) + sx1, sy1 = int((b["maxX"] - map_min_x) // 32), int((b["maxY"] - map_min_y) // 32) + lbl_w: dict[tuple[int, int], int] = {} + wid = 0 + for sy in range(sy0, sy1): + for sx in range(sx0, sx1): + if not sail(sx, sy) or (sx, sy) in lbl_w: + continue + q = deque([(sx, sy)]) + lbl_w[(sx, sy)] = wid + while q: + x, y = q.popleft() + for dx in (-1, 0, 1): + for dy in (-1, 0, 1): + n = (x + dx, y + dy) + if (dx or dy) and n not in lbl_w and sx0 <= n[0] < sx1 \ + and sy0 <= n[1] < sy1 and sail(*n): + lbl_w[n] = wid + q.append(n) + wid += 1 + + anchors: list[tuple[str, float, float]] = [] + for s in layout.get("structures", []): + if s.get("role") in ("hq", "harbour", "shop") and s.get("x") is not None: + anchors.append((str(s.get("name") or s.get("role")), s["x"], s["y"])) + for lane in layout.get("creepSpawns", {}).get("lanes", []): + sp = lane.get("spawnPoint", {}) + anchors.append((str(lane.get("id")), sp["x"], sp["y"])) + + def near_g(x: float, y: float, rad: int = 6): + c0, r0 = cell_for(x, y, geom) + best = None + for dr in range(-rad, rad + 1): + for dc in range(-rad, rad + 1): + c, r = c0 + dc, r0 + dr + if 0 <= c < cols and 0 <= r < nrows and rows[r][c]: + d = dc * dc + dr * dr + if best is None or d < best[0]: + best = (d, lbl_g[r][c]) + return best and best[1] + + def near_w(x: float, y: float, rad: int = 12): + s0 = (int((x - map_min_x) // 32), int((y - map_min_y) // 32)) + best = None + for dy in range(-rad, rad + 1): + for dx in range(-rad, rad + 1): + n = (s0[0] + dx, s0[1] + dy) + if n in lbl_w: + d = dx * dx + dy * dy + if best is None or d < best[0]: + best = (d, lbl_w[n]) + return best and best[1] + + lab_g = [near_g(x, y) for (_, x, y) in anchors] + lab_w = [near_w(x, y) for (_, x, y) in anchors] + mismatches: list[str] = [] + for i in range(len(anchors)): + for j in range(i + 1, len(anchors)): + same_g = lab_g[i] is not None and lab_g[i] == lab_g[j] + same_w = lab_w[i] is not None and lab_w[i] == lab_w[j] + if same_g != same_w: + kind = "LOST CHANNEL" if same_w else "FALSE MERGE" + mismatches.append(f"{kind}: {anchors[i][0]} <-> {anchors[j][0]}") + if mismatches: + raise SystemExit("terrain: lane-topology gate G6 FAILED (emitted grid vs full-res wpm):\n " + + "\n ".join(mismatches)) + return {"anchors": len(anchors), "pairwiseMismatches": 0} + + def validate(rows: list[list[int]], layout: dict, geom: dict) -> dict: """Fail-loud fidelity gate (G3 shops / G5 structures+spawns / base-to-base / G2 lane widths / fraction band).""" @@ -1336,7 +1544,7 @@ def entrance_count(island_cells: set[tuple[int, int]]) -> int: stack.append(nb) return groups - def island_land(world_x: float, world_y: float, max_cells: int = 60) -> set[tuple[int, int]]: + def island_land(world_x: float, world_y: float, max_cells: int = 60 * EMIT_SUBDIV * EMIT_SUBDIV) -> set[tuple[int, int]]: """4-connected LAND component containing the shop cell (the island the owner sails around). Capped so a connection to the mainland is not counted as 'the island'.""" @@ -1688,6 +1896,7 @@ def main() -> None: # rows = the working mask; keep the denoised raw wpm grid as the reference # the G2 agreement compares the final (carved) mask against. rows = [list(r) for r in sail] + restored = restore_straddled_channels(rows, wpm, geom, w3e["centerX"], w3e["centerY"]) removed = drop_singletons(rows, geom["cols"], geom["rows"]) ref_after_denoise = [list(r) for r in rows] # the reference G2 compares against @@ -1696,6 +1905,7 @@ def main() -> None: # fire; they only guarantee every shop/base/dock reaches the sea (G3/G4). neck_report = carve_connectivity(rows, soft, layout, geom) neck_report["singletonCellsDropped"] = removed + neck_report["straddledChannelCellsRestored"] = restored # 6. WEST-ISLAND LOOPS (owner-approved): ring each of the two west-island shops # with a closed 1-cell navigable moat + EXACTLY ONE entrance (deterministic @@ -1707,10 +1917,14 @@ def main() -> None: west_island_report = carve_west_island_loops(rows, layout, geom) neck_report["westIslandLoops"] = west_island_report + # G6: lane-topology equivalence vs the full-res pathing map (hard gate). + topo_report = lane_topology_gate(rows, wpm, layout, geom, w3e["centerX"], w3e["centerY"]) + rle = [rle_encode_row(r) for r in rows] wf = water_fraction(rows) report = validate(rows, layout, geom) report["necks"] = neck_report + report["laneTopologyVsWpm"] = topo_report report["sideRoutes"] = confirm_side_routes(rows, ref_after_denoise, layout, geom) # OPTIONAL depth metadata (0=land,1=deep,2=shallow,3=pink): the minimap colour