From 1a6646569a1c75c8e80efbb43bdc388b20f6d5f5 Mon Sep 17 00:00:00 2001 From: byblik Date: Tue, 25 Aug 2026 10:01:04 +0300 Subject: [PATCH] fix: art gaps stop being invisible walls (#6) write() punched every space of sign and facade text into the grid, and four glyphs the art uses but TILES never declared fell through to NOWHERE, solid by default: about 24.9 percent of the city was unwalkable air. Sign writing now skips gap spaces while deliberate set/fill carving keeps its behaviour, and the four glyphs get honest rows in the table - carved ground open, lattice and ornaments solid. A whole-map scan asserts zero NOWHERE cells. --- lib/map.js | 16 ++++++++++++- test/index.js | 1 + test/no-invisible-walls.test.js | 40 +++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/no-invisible-walls.test.js diff --git a/lib/map.js b/lib/map.js index de3673a..273e91b 100755 --- a/lib/map.js +++ b/lib/map.js @@ -56,6 +56,13 @@ const TILES = { o: { id: 'rock', name: 'una piedra', solid: true }, t: { id: 'tree', name: 'un arbol', solid: true }, '~': { id: 'water', name: 'el agua', solid: true }, + // Art leftovers that used to fall through to NOWHERE and become invisible + // walls (#6): carved-out ground reads as open floor, lattice windows and + // tiny ornament glyphs stay part of the facade they decorate. + ' ': { id: 'open', name: 'el hueco del arte', solid: false }, + '=': { id: 'lattice', name: 'una reja', solid: true }, + '`': { id: 'ornament', name: 'un adorno', solid: true }, + "'": { id: 'ornament', name: 'un adorno', solid: true }, C: { id: 'door.home', name: 'tu casa', solid: false, enter: { kind: 'home' } }, I: { id: 'door.church', name: 'la iglesia', solid: false, enter: { kind: 'church' } }, @@ -599,7 +606,14 @@ function makeHighResolutionCityRows() { } } const write = (x, y, text) => { - for (let i = 0; i < String(text).length; i++) set(x + i, y, String(text)[i]) + for (let i = 0; i < String(text).length; i++) { + // Spaces between sign words or around stamped art are gaps, not terrain: + // writing them would punch NOWHERE holes into whatever lies beneath and + // leave invisible walls behind (#6). Deliberate carving goes through + // set()/fill() directly, which keeps its explicit-space behaviour. + if (String(text)[i] === ' ') continue + set(x + i, y, String(text)[i]) + } } const centred = (x, y, w, text) => write(x + Math.floor((w - String(text).length) / 2), y, text) const border = (x, y, w, h, horizontal = '-', vertical = '|') => { diff --git a/test/index.js b/test/index.js index 478ca41..6a53e4f 100644 --- a/test/index.js +++ b/test/index.js @@ -17,6 +17,7 @@ const { const render = require('../lib/render.js') require('./sage.test.js') +require('./no-invisible-walls.test.js') function press(game, name) { return game.onKey({ type: 'key', is: (...keys) => keys.includes(name) }) diff --git a/test/no-invisible-walls.test.js b/test/no-invisible-walls.test.js new file mode 100644 index 0000000..4015e47 --- /dev/null +++ b/test/no-invisible-walls.test.js @@ -0,0 +1,40 @@ +const { test } = require('brittle') +const M = require('../lib/map.js') + +test('art leftover glyphs live in the tile table, not in NOWHERE (#6)', (t) => { + t.is(M.TILES[' '].id, 'open') + t.is(M.TILES[' '].solid, false, 'a carved-out gap is open ground') + t.is(M.TILES['='].solid, true, 'the lattice stays part of the facade') + t.is(M.TILES['`'].solid, true) + t.is(M.TILES["'"].solid, true) +}) + +test('no in-bounds cell of the city resolves to NOWHERE anymore (#6)', (t) => { + // The issue counted 15938 of 64000 cells (24.9%) falling into NOWHERE via + // four undeclared glyphs. Every glyph the art uses must now be declared. + const city = M.MAPS.city + let nowhere = 0 + for (let y = 0; y < city.height; y++) { + for (let x = 0; x < city.width; x++) { + if (M.tileAt(city, x, y).id === 'nowhere') nowhere++ + } + } + t.is(nowhere, 0, 'every glyph in the active art is declared in TILES') +}) + +test('walking into an art gap meets open ground, not an invisible wall (#6)', (t) => { + const city = M.MAPS.city + let checked = 0 + for (let y = 0; y < city.height; y++) { + const row = city.rows[y] + for (let x = 0; x < row.length; x++) { + if (row[x] !== ' ') continue + checked++ + if (M.isSolid(city, x, y)) { + t.fail(`space at ${x},${y} is still solid`) + return + } + } + } + t.ok(checked > 10000, `the scan actually saw the art gaps (saw ${checked})`) +}) \ No newline at end of file