-- ============================================================ -- GUANTE BLANCO — port a la fantasy console "ascii" del original -- de David Radisic para Amstrad CPC (AMSOFT, 1985). -- Sergi Valor, 2026. -- -- FASE 1: estructura base. Las 5 habitaciones se dibujan con -- sus paredes, puertas, ventanas y conmutadores. Tecla 1..5 -- conmuta la habitación visible para verificar el render. -- ============================================================ -- ============================================================ -- CONFIGURACION -- ============================================================ MODO = 3 -- mode(3) = 32x24 ANCHO = 32 ALTO = 24 -- Layout (HUD/banners alrededor del área de habitación) FILA_BANNER = 0 -- "Habitacion: X" FILA_MSG = 23 -- mensajes "Choque", "MORDIDO" AREA_Y0 = 1 -- primera fila donde se pinta la habitación AREA_Y1 = 22 -- última fila -- ============================================================ -- PALETA (mapeo CPC firmware → CGA disponible) -- Original: INK 0,0 (negro) / 1,26 (pastel) / 2,15 (blanco) / -- 3,25 (pastel verde) / 4,14 (amarillo) / 5,24,12 (parpadeo) / -- 6,0 (negro al inicio, luego 24,12) / 7,8 = paper de la habit. -- ============================================================ COL_FONDO = COLOR_BLACK COL_LADRON = COLOR_WHITE -- INK 1 pastel COL_PUERTA = COLOR_LIGHT_GRAY -- INK 2 blanco COL_VENTANA = COLOR_YELLOW -- INK 4 COL_CONMUT = COLOR_LIGHT_GREEN -- INK 3 COL_JOYA = COLOR_LIGHT_RED -- INK 5 (parpadeo en original) COL_OBSTACULO = COLOR_BROWN -- INK 6 COL_PERRO = COLOR_WHITE -- INK 1 COL_PARED = COLOR_LIGHT_BLUE -- el rectángulo L original era PEN 1 azul COL_PAPER_HAB_ON = COLOR_DARK_GRAY -- paper de la habitación con luz (INK 7,10) COL_PAPER_HAB_OFF = COLOR_BLACK -- paper de la habitación sin luz (INK 7,0) COL_TEXTO = COLOR_LIGHT_GRAY COL_MSG = COLOR_LIGHT_RED -- ============================================================ -- GLIFOS (códigos que vamos a redefinir con setchar) -- ============================================================ GL_LADRON = 224 -- hombre$ = chr(224) GL_LADRON_M = 225 -- ladrón "mordido" (línea 2570 del original) GL_VENT_H = 250 -- ventana horizontal (2 chars) GL_VENT_V = 251 -- ventana vertical (3 chars verticales) GL_PUERTA_H = 252 -- puerta horizontal GL_PUERTA_V = 253 -- puerta vertical GL_PERRO = 255 -- el perro GL_JOYA = 144 -- joya$ = chr(144) GL_OBSTACULO = 233 -- obj$ = chr(233) GL_CONM_L_OFF = 246 -- conm$(1,0) GL_CONM_L_ON = 247 -- conm$(1,1) GL_CONM_R_OFF = 248 -- conm$(2,0) GL_CONM_R_ON = 249 -- conm$(2,1) GL_PARED = 143 -- nuestro char de pared (el original usaba DRAW de líneas) -- ============================================================ -- TIPOS DE CELDA DEL MAPA -- ============================================================ T_VACIO = 0 T_PARED = 1 T_PUERTA_H = 2 T_PUERTA_V = 3 T_VENT_H = 4 T_VENT_V = 5 T_CONM_L = 6 T_CONM_R = 7 T_JOYA = 8 T_OBSTACULO = 9 T_PERRO = 10 -- ============================================================ -- DEFINIR GLIFOS (bitmaps idénticos a los SYMBOL del original -- cuando los hay, diseñados a mano cuando vienen del char-ROM -- CPC y no aparecen en el .bas). -- ============================================================ function definir_glifos() -- SYMBOL 240..245 del original (partes del sprite del ladrón -- y/o decoración — el código los ignora en colisiones con -- "IF ASC(ht$)>239 AND ASC(ht$)<246 THEN 1520") setchar(240, 8, 8, 8, 8, 8, 8, 8, 8) setchar(241, 0, 0, 0, 0, 255, 0, 1, 0) setchar(242, 0, 0, 0, 0, 15, 8, 8, 8) setchar(243, 0, 0, 0, 0, 248, 8, 8, 8) setchar(244, 8, 8, 8, 8, 248, 0, 0, 0) setchar(245, 8, 8, 8, 8, 15, 0, 0, 0) -- SYMBOL 246..249 — conmutadores L/R, on/off (bitmaps literales) setchar(GL_CONM_L_OFF, 8, 12, 13, 14, 12, 12, 8, 8) setchar(GL_CONM_L_ON, 8, 12, 12, 14, 13, 12, 9, 8) setchar(GL_CONM_R_OFF, 8, 24, 88, 56, 24, 24, 8, 8) setchar(GL_CONM_R_ON, 8, 24, 24, 56, 88, 24, 8, 8) -- SYMBOL 250..253 — ventanas y puertas (bitmaps literales) setchar(GL_VENT_H, 0, 0, 255, 129, 129, 129, 255, 0) setchar(GL_VENT_V, 28, 20, 20, 20, 20, 20, 20, 28) setchar(GL_PUERTA_H, 0, 0, 255, 255, 255, 255, 255, 0) setchar(GL_PUERTA_V, 28, 28, 28, 28, 28, 28, 28, 28) -- SYMBOL 255 — el perro (bitmap literal del original) setchar(GL_PERRO, 195, 165, 60, 126, 90, 60, 36, 24) -- chr 224 (ladrón normal) y 225 (ladrón mordido): el original usaba -- las caritas del char-ROM CPC tal cual. En ascii el charset trae -- esas mismas caritas en los mismos códigos, así que no se redefinen. -- Pared: bloque sólido para el rectángulo L del original setchar(GL_PARED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF) end -- ============================================================ -- DEFINICIÓN DE LAS 5 HABITACIONES -- Coordenadas tomadas LITERALMENTE de las DATAs del bombardero.bas: -- - minx, miny, maxx, maxy: interior (líneas 3020-3060) -- - puertas D y ventanas W: posición en pared (líneas 2680-3010) -- - conmutadores S: posición en pared, orient L/R -- - dir: N, S, E, O (-1 = bloqueado, 0 = escape, n = id habitación) -- ============================================================ HABITACIONES = { [1] = { nombre = "Pasillo", minx = 5, miny = 4, maxx = 8, maxy = 21, elementos = { { tipo="puerta_h", x=6, y=3 }, -- N: a dir[1]=0 (escape) { tipo="puerta_h", x=6, y=22 }, -- S: a dir[2]=4 (Cocina) { tipo="puerta_v", x=4, y=12 }, -- O: a dir[4]=2 (Sala) { tipo="puerta_v", x=9, y=11 }, -- E: a dir[3]=3 (Comedor) { tipo="conm", x=4, y=11, orient="L", on=false }, { tipo="conm", x=9, y=14, orient="R", on=false }, }, dir = { 0, 4, 3, 2 }, -- N, S, E, O luz = false, }, [2] = { nombre = "Sala", minx = 3, miny = 4, maxx = 9, maxy = 21, elementos = { { tipo="puerta_v", x=10, y=12 }, -- E: a dir[3]=1 (Pasillo) { tipo="vent_h", x=6, y=3 }, -- N (bloqueado, dir[1]=-1) { tipo="vent_v", x=2, y=12 }, -- O (bloqueado, dir[4]=-1) { tipo="conm", x=10, y=11, orient="R", on=false }, { tipo="conm", x=10, y=15, orient="R", on=false }, }, dir = { -1, -1, 1, -1 }, luz = false, }, [3] = { nombre = "Comedor", minx = 3, miny = 4, maxx = 9, maxy = 21, elementos = { { tipo="vent_v", x=10, y=12 }, -- E (bloqueado, dir[3]=-1) { tipo="vent_h", x=6, y=3 }, -- N (bloqueado, dir[1]=-1) { tipo="puerta_v", x=2, y=12 }, -- O: a dir[4]=1 (Pasillo) { tipo="conm", x=2, y=11, orient="L", on=false }, { tipo="conm", x=2, y=15, orient="L", on=false }, }, dir = { -1, -1, -1, 1 }, luz = false, }, [4] = { nombre = "Cocina", minx = 3, miny = 6, maxx = 13, maxy = 21, elementos = { { tipo="puerta_h", x=6, y=5 }, -- N: a dir[1]=1 (Pasillo) { tipo="puerta_h", x=6, y=22 }, -- S: a dir[2]=0 (escape) { tipo="vent_h", x=10, y=22 }, -- otra ventana en la pared S { tipo="vent_v", x=14, y=13 }, -- E (bloqueado, dir[3]=-1) { tipo="puerta_v", x=2, y=13 }, -- O: a dir[4]=5 (Despensa) { tipo="conm", x=2, y=16, orient="L", on=false }, }, dir = { 1, 0, -1, 5 }, luz = false, }, [5] = { nombre = "Despensa", minx = 3, miny = 6, maxx = 9, maxy = 21, elementos = { { tipo="puerta_v", x=10, y=12 }, -- E: a dir[3]=4 (Cocina) { tipo="conm", x=10, y=11, orient="R", on=false }, }, dir = { -1, -1, 4, -1 }, luz = false, }, } -- ============================================================ -- ESTADO GLOBAL -- ============================================================ rm = 1 -- habitación actual (variable rm del original) xp, yp = 6, 4 -- posición del ladrón hombre_glifo = GL_LADRON mapa = {} -- mapa[hab][x][y] = tipo de celda -- ============================================================ -- CONSTRUCCIÓN DEL MAPA LÓGICO -- Por habitación se construye una matriz [x][y] con el tipo de -- celda. Las paredes son el contorno (minx-1, maxx+1, miny-1, -- maxy+1). Las puertas, ventanas y conmutadores sobrescriben la -- pared. El interior queda como T_VACIO (se rellenará con joyas -- y obstáculos en la Fase 3). -- ============================================================ function init_mapa() for id, hab in pairs(HABITACIONES) do mapa[id] = {} for x = 0, ANCHO-1 do mapa[id][x] = {} for y = 0, ALTO-1 do mapa[id][x][y] = T_VACIO end end -- Paredes: contorno del rectángulo interior local x0, y0 = hab.minx - 1, hab.miny - 1 local x1, y1 = hab.maxx + 1, hab.maxy + 1 for x = x0, x1 do mapa[id][x][y0] = T_PARED mapa[id][x][y1] = T_PARED end for y = y0, y1 do mapa[id][x0][y] = T_PARED mapa[id][x1][y] = T_PARED end -- Elementos: sobrescriben la pared for _, e in ipairs(hab.elementos) do if e.tipo == "puerta_h" then mapa[id][e.x ][e.y] = T_PUERTA_H mapa[id][e.x+1][e.y] = T_PUERTA_H elseif e.tipo == "vent_h" then mapa[id][e.x ][e.y] = T_VENT_H mapa[id][e.x+1][e.y] = T_VENT_H elseif e.tipo == "puerta_v" then mapa[id][e.x][e.y ] = T_PUERTA_V mapa[id][e.x][e.y+1] = T_PUERTA_V mapa[id][e.x][e.y+2] = T_PUERTA_V elseif e.tipo == "vent_v" then mapa[id][e.x][e.y ] = T_VENT_V mapa[id][e.x][e.y+1] = T_VENT_V mapa[id][e.x][e.y+2] = T_VENT_V elseif e.tipo == "conm" then mapa[id][e.x][e.y] = (e.orient == "L") and T_CONM_L or T_CONM_R end end end end -- ============================================================ -- OFFSET DE CENTRADO -- En cada render, calcula el offset (off_x, off_y) para centrar -- el rectángulo de la habitación (paredes incluidas) dentro del -- área de juego. -- ============================================================ function offset_centrado() local hab = HABITACIONES[rm] local w = (hab.maxx + 1) - (hab.minx - 1) + 1 local h = (hab.maxy + 1) - (hab.miny - 1) + 1 local off_x = flr((ANCHO - w) / 2) - (hab.minx - 1) local off_y = flr((AREA_Y0 + AREA_Y1 - h) / 2) - (hab.miny - 1) + 1 return off_x, off_y end -- ============================================================ -- RENDER -- ============================================================ function pintar_fondo() color(COL_TEXTO, COL_FONDO) cls() end function pintar_banner() color(COL_TEXTO, COL_FONDO) print("Habitacion: "..HABITACIONES[rm].nombre, 1, FILA_BANNER) end function glifo_de(tipo, on) if tipo == T_PARED then return GL_PARED end if tipo == T_PUERTA_H then return GL_PUERTA_H end if tipo == T_PUERTA_V then return GL_PUERTA_V end if tipo == T_VENT_H then return GL_VENT_H end if tipo == T_VENT_V then return GL_VENT_V end if tipo == T_CONM_L then return on and GL_CONM_L_ON or GL_CONM_L_OFF end if tipo == T_CONM_R then return on and GL_CONM_R_ON or GL_CONM_R_OFF end if tipo == T_JOYA then return GL_JOYA end if tipo == T_OBSTACULO then return GL_OBSTACULO end if tipo == T_PERRO then return GL_PERRO end return nil end function color_de(tipo) if tipo == T_PARED then return COL_PARED end if tipo == T_PUERTA_H then return COL_PUERTA end if tipo == T_PUERTA_V then return COL_PUERTA end if tipo == T_VENT_H then return COL_VENTANA end if tipo == T_VENT_V then return COL_VENTANA end if tipo == T_CONM_L then return COL_CONMUT end if tipo == T_CONM_R then return COL_CONMUT end if tipo == T_JOYA then return COL_JOYA end if tipo == T_OBSTACULO then return COL_OBSTACULO end if tipo == T_PERRO then return COL_PERRO end return COL_TEXTO end -- Devuelve el "estado on/off" de un conmutador concreto buscando en -- los elementos de la habitación. function conm_estado(hab, x, y) for _, e in ipairs(hab.elementos) do if e.tipo == "conm" and e.x == x and e.y == y then return e.on end end return false end function pintar_habitacion() local hab = HABITACIONES[rm] local off_x, off_y = offset_centrado() local paper = hab.luz and COL_PAPER_HAB_ON or COL_PAPER_HAB_OFF -- Paper del interior color(COL_TEXTO, paper) local blank = " " for y = hab.miny, hab.maxy do for x = hab.minx, hab.maxx do print(blank, x + off_x, y + off_y) end end -- Paredes y elementos for y = hab.miny - 1, hab.maxy + 1 do for x = hab.minx - 1, hab.maxx + 1 do local t = mapa[rm][x][y] if t ~= T_VACIO then local on = false if t == T_CONM_L or t == T_CONM_R then on = conm_estado(hab, x, y) end local g = glifo_de(t, on) if g then color(color_de(t), COL_FONDO) print(chr(g), x + off_x, y + off_y) end end end end -- El ladrón color(COL_LADRON, paper) print(chr(hombre_glifo), xp + off_x, yp + off_y) end -- ============================================================ -- BUCLE PRINCIPAL — FASE 1 -- Solo render estático. Teclas 1..5 cambian habitación visible. -- ============================================================ function init() mode(MODO) border(COL_FONDO) color(COL_TEXTO, COL_FONDO) definir_glifos() init_mapa() rm = 1 -- Posición inicial del ladrón en cada habitación (centrada-ish) xp = flr((HABITACIONES[rm].minx + HABITACIONES[rm].maxx) / 2) yp = HABITACIONES[rm].miny + 2 cls() end function update() -- FASE 1: navegación manual entre habitaciones para verificar if btnp(KEY_1) then rm = 1 end if btnp(KEY_2) then rm = 2 end if btnp(KEY_3) then rm = 3 end if btnp(KEY_4) then rm = 4 end if btnp(KEY_5) then rm = 5 end -- Tecla L para alternar la luz de la habitación actual (debug) if btnp(KEY_L) then HABITACIONES[rm].luz = not HABITACIONES[rm].luz end -- Reposicionar al ladrón al cambiar de habitación local hab = HABITACIONES[rm] if xp < hab.minx or xp > hab.maxx or yp < hab.miny or yp > hab.maxy then xp = flr((hab.minx + hab.maxx) / 2) yp = hab.miny + 2 end pintar_fondo() pintar_banner() pintar_habitacion() color(COL_TEXTO, COL_FONDO) print("1..5 hab. L luz", 1, FILA_MSG) end