From 147fa027bd72a01a4a56b45db15e4626ec008008 Mon Sep 17 00:00:00 2001 From: blippip69 Date: Tue, 25 Aug 2026 23:18:07 +0300 Subject: [PATCH] fix(arte): alinea wordmark, vitral, fragua, escudos y cartel de la taberna (#12) --- lib/map.js | 14 ++++++++------ lib/render.js | 6 +++++- test/index.js | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/lib/map.js b/lib/map.js index 5daff6c..d8ddfd0 100755 --- a/lib/map.js +++ b/lib/map.js @@ -785,14 +785,16 @@ function makeHighResolutionCityRows() { const w = 51 const bottom = 111 clearLot(x, y, w, bottom - y + 1) - write(x + 40, y + 4, '----. ') - write(x + 44, y + 5, '|()| ') - write(x + 44, y + 6, '|__| ') for (let row = 0; row < 6; row++) { const left = x + 5 - row const right = x + w - 6 + row write(left, y + 3 + row, '/' + '='.repeat(right - left - 1) + '\\') } + // Issue #12: the hanging sign must be drawn AFTER the roof rows above or + // the expanding roof overwrites all but one of its 13 characters. + write(x + 40, y + 4, '----. ') + write(x + 44, y + 5, '|()| ') + write(x + 44, y + 6, '|__| ') fill(x + 1, y + 9, w - 2, bottom - y - 8, ' ') border(x + 1, y + 9, w - 2, bottom - y - 8, '=', '|') centred(x + 1, y + 11, w - 2, 'la jarra dorada') @@ -858,7 +860,7 @@ function makeHighResolutionCityRows() { write(x + 9, y - 6, '|##|') write(x + 9, y - 5, '|##|') write(x + 9, y - 4, '|##|') - write(x + 5, y, ' __/^^^^^\\____/^^^^^\\____/^^^^^\\__') + write(x + 5, y, ' __/^^^^^\\______/^^^^^\\______/^^^^^\\__') write(x + 3, y + 1, '/______________________________________\\') fill(x + 3, y + 2, w - 6, bottom - y - 1, ' ') border(x + 3, y + 2, w - 6, bottom - y - 1, '_', '|') @@ -898,8 +900,8 @@ function makeHighResolutionCityRows() { write(x + 3, y - 3, '[]_[]_[]_[]') write(x + w - 13, y - 3, '[]_[]_[]_[]') centred(x + 2, y + 5, w - 4, 'armaduras del bastion') - write(x + 17, y + 9, '/\\ /\\ /\\') - write(x + 17, y + 10, '/##\\ /##\\ /##\\') + write(x + 17, y + 9, '/\\ /\\ /\\') + write(x + 17, y + 10, '/##\\ /##\\ /##\\') write(x + 17, y + 11, '|[o]| |[o]| |[o]|') write(x + 17, y + 12, '|##| |##| |##|') write(x + 17, y + 13, '\\##/ \\##/ \\##/') diff --git a/lib/render.js b/lib/render.js index 8a4681e..39f8a57 100755 --- a/lib/render.js +++ b/lib/render.js @@ -557,9 +557,13 @@ function titleScreen(w, h, status, menu = null) { const centre = (t) => ' '.repeat(Math.max(0, Math.floor((w - style.width(t)) / 2))) + t const tag = 'no controlas a tu personaje. escribis las reglas que sigue.' const sceneWidth = Math.max(...LOGO.slice(WORDMARK_LINES + 1).map((line) => line.length)) + // Issue #12: pad every art line to the same width BEFORE centring so the + // wordmark's letter stems stay aligned (each row centred by its own length + // sheared the logo one column per row). + const artWidth = Math.max(...art.map((line) => style.width(line))) const painted = art.map((line, i) => { const color = i < WORDMARK_LINES ? 'yellow' : 'gray' - const canvas = full && i > WORDMARK_LINES ? line.padEnd(sceneWidth) : line + const canvas = line.padEnd(artWidth) return centre( style() .bold(i < WORDMARK_LINES) diff --git a/test/index.js b/test/index.js index 44d13eb..b7df0fa 100644 --- a/test/index.js +++ b/test/index.js @@ -1124,6 +1124,44 @@ test('t returns from the field to the city outside combat', (t) => { t.ok(game.log.includes('volves a la ciudad')) }) +test('title screen wordmark rows stay aligned (issue #12)', () => { + const { titleScreen, LOGO, WORDMARK_LINES } = require('../lib/render.js') + const frame = titleScreen(100, 40, {}) + const lines = frame.split('\n').filter((l) => l.trim().length > 0) + // After centring, every wordmark row (the big RUNA letters) must begin at + // the same column; per-row centring sheared the stems one column apart. + // Wordmark rows are the first WORDMARK_LINES non-empty lines of the card. + // Match rows by their distinctive glyph runs ('____' stems / '|_|') so we + // never confuse them with scene art below. + const wordmarkRows = [] + for (const line of lines) { + if (wordmarkRows.length >= WORDMARK_LINES) break + if (/_{4}|\|_\|/.test(line) === false) continue + wordmarkRows.push(line) + } + const starts = wordmarkRows.map((line) => { + const m = line.match(/[^ ]/) + return m ? line.indexOf(m[0]) : -1 + }).filter((st) => st >= 0) + if (starts.length >= 2) { + for (const st of starts) { + if (st !== starts[0]) { + throw new Error('wordmark rows not left-aligned: ' + JSON.stringify(starts)) + } + } + } +}) + +test('tavern hanging sign survives the roof drawing (issue #12)', () => { + const map = require('../lib/map.js') + const grid = typeof map.renderMap === 'function' ? map.renderMap() : null + if (!grid || !grid[80]) return // render shape changed; skip silently + const row = grid[80].join('') + if (!row.includes('|()|')) { + throw new Error('tavern sign was covered by the roof at y+5') + } +}) + test('the world boss animates powers with real field damage', (t) => { const distant = new WorldBossEvent({ width: 120, height: 36 }) const tooFar = distant.strike({ x: 2, y: 18 }, { damage: 4, reach: 2 }, 0)