CRITICAL FINDING: Map-Relative Coordinate System

Discovery (2026-02-11)

Root Cause of ALL Special Level Terrain Mismatches

In NetHack Lua special levels, coordinates for doors, ladders, objects, and monsters are RELATIVE to the map origin after des.map() is called, not absolute screen coordinates.

Evidence

Lua Code (tower1.lua)

des.map({ halign = "half-left", valign = "center", map = [[
  --- --- ---  
  |.| |.| |.|  
---S---S---S---
...
]] });

des.door("closed",08,03)  -- Row 3 OF THE MAP, not screen row 3

C Behavior

JS Behavior (INCORRECT)

Impact

Required Fix

  1. Add coordinate context tracking:
    levelState.mapCoordMode = true;  // Set after des.map()
    levelState.mapOriginX = xstart;
    levelState.mapOriginY = ystart;
    
  2. Update coordinate-using functions:
    • door(x, y) → convert to (xstart + x, ystart + y) if mapCoordMode
    • ladder(x, y) → same conversion
    • object(x, y) → same conversion
    • monster(x, y) → same conversion
    • trap(x, y) → same conversion
  3. Reset on new map:
    • Each des.map() call resets the origin
  4. Handle special cases:
    • Absolute coords still needed for some functions (mazewalk, region, etc.)
    • May need explicit des.absolute_coords() or similar

Test Validation

After implementing, tower1 test should show:

Priority

CRITICAL - This blocks accurate replication of all special levels. Must be implemented before special level comparison tests can pass.

Files Affected