397 lines
15 KiB
Lua
397 lines
15 KiB
Lua
-- ============================================================
|
|
-- 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
|