From 7fe5bab9a0af4633d53954a54802aa24c4824c67 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 18 May 2026 13:35:03 +0200 Subject: [PATCH] Fase 1: estructura base i les 5 habitacions --- .gitignore | 9 +- ASCII_API.md | 275 ++++++++++++++++++++++++++++ chuleta_font_ascii.png | Bin 0 -> 35706 bytes guante_blanco.bas | 318 +++++++++++++++++++++++++++++++++ guante_blanco.lua | 396 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 997 insertions(+), 1 deletion(-) create mode 100644 ASCII_API.md create mode 100644 chuleta_font_ascii.png create mode 100644 guante_blanco.bas create mode 100644 guante_blanco.lua diff --git a/.gitignore b/.gitignore index 7014d68..4438869 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,7 @@ $RECYCLE.BIN/ .LSOverride # Icon must end with two \r -Icon +Icon # Thumbnails ._* @@ -67,3 +67,10 @@ Temporary Items # .nfs files are created when an open file is removed but is still being accessed .nfs* +# ---> Guante Blanco +# Binari de l'intèrpret ascii (es compila a part) +/ascii +# Fitxer de rècord generat pel joc +/records + + diff --git a/ASCII_API.md b/ASCII_API.md new file mode 100644 index 0000000..657a413 --- /dev/null +++ b/ASCII_API.md @@ -0,0 +1,275 @@ +# ASCII — Referencia del intérprete Lua + +Documento extraído del código fuente en `c:/mingw/gitea/ascii/` (principalmente `ascii.cpp`, `lua.cpp`, `play.cpp`, `ascii.h`). Sirve como guía para portar Pepe Runner desde Turbo Pascal a Lua. + +> Versión analizada del intérprete: v0.6.1 aprox (según el mensaje del boot ROM en `lua.cpp`). + +--- + +## 1. Modelo de ejecución + +Cada juego/programa es **un solo fichero `.lua`** que define dos funciones globales: + +```lua +function init() + -- se llama una sola vez al arrancar +end + +function update() + -- se llama cada frame (~60 FPS, vsync) +end +``` + +- El intérprete se invoca como `ascii.exe nombre_juego.lua`. Si no se pasa argumento, intenta cargar `game.lua`. +- También se puede **arrastrar y soltar** un `.lua` sobre la ventana para cargarlo. +- **F5** reinicia el juego (re-llama a `init()` y vuelve a empezar el bucle). +- **ESC** pausa la ejecución y abre una consola de depuración (`> ` prompt). Los comandos `run` y `cont` la cierran. Comandos prefijados con `?` evalúan e imprimen (ej.: `?1+1`). +- Se usa la versión estándar de Lua que está vendorizada en `ascii/lua/` (con `luaL_openlibs`), así que están disponibles `string`, `math`, `table`, etc. + +--- + +## 2. Modos de pantalla — `mode(n)` + +| Modo | Resolución carácter | Resolución pixel | Notas | +|------|--------------------:|-----------------:|-------| +| 0 | 80 × 30 | 640 × 240 | Color único global (no por-carácter) — usado para depuración / texto. `current_color` aplica a toda la pantalla. | +| 1 | 40 × 30 | 320 × 240 | **Modo por defecto.** Color por carácter. | +| 2 | 20 × 15 | 160 × 120 | Mitad de resolución. Cómodo para tiles grandes (ej.: sokoban). | +| 3 | 32 × 24 | 256 × 192 | Estilo "ZX Spectrum" (con bordes anchos). | + +Cada carácter es **8×8 píxeles**. Los gráficos son texto coloreado, no píxeles libres — el "lienzo" es una matriz de celdas (carácter + atributo de color). + +--- + +## 3. Paleta de colores (16, CGA/EGA) + +Constantes Lua predefinidas (`lua.cpp` líneas 610-625): + +| Código | Constante | Aprox. | +|-------:|------------------------|---------------| +| 0 | `COLOR_BLACK` | #000000 | +| 1 | `COLOR_BLUE` | #0000AA | +| 2 | `COLOR_GREEN` | #00AA00 | +| 3 | `COLOR_CYAN` | #00AAAA | +| 4 | `COLOR_RED` | #AA0000 | +| 5 | `COLOR_MAGENTA` | #AA00AA | +| 6 | `COLOR_BROWN` | #AA5500 | +| 7 | `COLOR_LIGHT_GRAY` | #AAAAAA | +| 8 | `COLOR_DARK_GRAY` | #555555 | +| 9 | `COLOR_LIGHT_BLUE` | #5555FF | +| 10 | `COLOR_LIGHT_GREEN` | #55FF55 | +| 11 | `COLOR_LIGHT_CYAN` | #55FFFF | +| 12 | `COLOR_LIGHT_RED` | #FF5555 | +| 13 | `COLOR_LIGHT_MAGENTA` | #FF55FF | +| 14 | `COLOR_YELLOW` | #FFFF55 | +| 15 | `COLOR_WHITE` | #FFFFFF | + +El atributo de color de una celda es 1 byte: nibble bajo = INK (tinta), nibble alto = PAPER (fondo). + +--- + +## 4. API — Funciones expuestas a Lua + +### Pantalla y color + +| Función | Descripción | +|---------|-------------| +| `mode(n)` | Cambia modo de pantalla (0-3) y hace cls. | +| `cls([chr=32])` | Limpia con el carácter dado (32 = espacio). En modo ≠0 además rellena el color attr. | +| `ink(c)` | Color de tinta (0-15). | +| `paper(c)` | Color de fondo (0-15). | +| `border(c)` | Color del borde de la ventana. | +| `color(ink, paper, [border])` | Combina los tres. | +| `locate(x, y)` | Posiciona cursor en celda (x, y). | +| `print(str, [x, y])` | Imprime `str` (sin salto de línea). Si se dan x,y, primero hace `locate`. | +| `crlf()` | CR + LF (mueve cursor a inicio de siguiente línea). | + +### Entrada + +| Función | Descripción | +|---------|-------------| +| `btn(k)` | `true` si la tecla `k` está pulsada *en este frame* (estado SDL_GetKeyboardState). | +| `btnp(k)` | `true` solo en el frame en que la tecla se pulsa (edge). | +| `mousex()` / `mousey()` | Posición del ratón en **coordenadas de carácter** (ya escalado al modo). | +| `mousewheel()` | Delta de la rueda en este frame. | +| `mousebutton(i)` | `true` si el botón `i` está pulsado (1=izq, 2=medio, 3=der; usa `SDL_BUTTON(i)`). | + +> **Nota**: `whichbtn()` está declarado en `ascii.h` y existe en C++, pero **no está expuesto a Lua** (no aparece en los `lua_setglobal` de `lua.cpp`). Para detectar qué tecla se ha pulsado en un frame hay que iterar con `btnp()` sobre las constantes `KEY_*`. + +> **Bug de `tostr` con negativos**: la implementación de `tostr()` en `lua.cpp` (función `intToStr`) hace `(x % 10) + '0'` que con `x = -1` produce `-1 + 48 = 47`, o sea `'/'`. Por tanto `tostr(-1)` devuelve `"/"`, `tostr(-2)` devuelve `"."`, etc. Si vas a imprimir un número que puede ser negativo, usa `string.format("%d", n)` (que sí maneja signo) o clampa con `max(0, n)` antes de pasar a `tostr`. + +Códigos de tecla — todos definidos como globales `KEY_*` en Lua. Lista completa (de `lua.cpp` 502-608): + +``` +KEY_A..KEY_Z = 4..29 +KEY_1..KEY_0 = 30..39 (1=30, 2=31, ..., 9=38, 0=39) +KEY_RETURN=40 KEY_ESCAPE=41 KEY_BACKSPACE=42 KEY_TAB=43 KEY_SPACE=44 +KEY_MINUS=45 KEY_EQUALS=46 KEY_LEFTBRACKET=47 KEY_RIGHTBRACKET=48 +KEY_BACKSLASH=49 KEY_NONUSHASH=50 KEY_SEMICOLON=51 KEY_APOSTROPHE=52 +KEY_GRAVE=53 KEY_COMMA=54 KEY_PERIOD=55 KEY_SLASH=56 KEY_CAPSLOCK=57 +KEY_F1..KEY_F12 = 58..69 +KEY_PRINTSCREEN=70 KEY_SCROLLLOCK=71 KEY_PAUSE=72 +KEY_INSERT=73 KEY_HOME=74 KEY_PAGEUP=75 KEY_DELETE=76 KEY_END=77 KEY_PAGEDOWN=78 +KEY_RIGHT=79 KEY_LEFT=80 KEY_DOWN=81 KEY_UP=82 +KEY_NUMLOCKCLEAR=83 KEY_KP_DIVIDE=84 KEY_KP_MULTIPLY=85 KEY_KP_MINUS=86 KEY_KP_PLUS=87 KEY_KP_ENTER=88 +KEY_KP_1..KEY_KP_0 = 89..98 KEY_KP_PERIOD=99 +KEY_NONUSBACKSLASH=100 KEY_APPLICATION=101 +KEY_LCTRL=224 KEY_LSHIFT=225 KEY_LALT=226 KEY_LGUI=227 +KEY_RCTRL=228 KEY_RSHIFT=229 KEY_RALT=230 KEY_RGUI=231 +``` + +(Son los SDL2 scancodes.) + +### Matemáticas + +`abs(x)`, `ceil(x)`, `flr(x)`, `sgn(x)`, `sin(x)`, `cos(x)`, `atan2(dx, dy)`, `sqrt(x)`, `max(a,b)`, `min(a,b)`, `mid(a,b,c)` (devuelve el del medio, equivalente a `clamp`). + +`rnd(n)` devuelve un entero en `[0, n-1]` (`rand()%n`). `srand(seed)` siembra el RNG. + +### Strings + +| Función | Descripción | +|---------|-------------| +| `tostr(v)` | Convierte valor a string. Soporta nil, function, table (formato `{k=v,...}`), number, boolean, string. | +| `strlen(s)` | Longitud en bytes. | +| `ascii(s, i)` | Código del byte en índice `i` (0-based). | +| `chr(n)` | String de un solo carácter cuyo código es `n`. | +| `substr(s, start, length)` | Subcadena. | + +> Nota: Lua estándar también está disponible, así que `string.format`, `string.sub`, etc., funcionan. Pero los demos usan estas helpers. + +### Memoria + +| Función | Descripción | +|---------|-------------| +| `peek(addr)` | Lee 1 byte de la VRAM/memoria (0..0x1FFF). | +| `poke(addr, val)` | Escribe 1 byte. | +| `memcpy(dst, src, size)` | Copia bytes en la memoria del fantasy console. | +| `setchar(idx, b0..b7)` | Define los 8 bytes del carácter `idx` en el char-ROM (sobrescribe la fuente). | + +**Mapa de memoria** (8 KB total, `mem[8192]`): + +- `0x0000` (0): char_screen (matriz de códigos de carácter por celda) +- Tras char_screen viene color_screen (offset = `screen_width * screen_height`) +- `0x0A00` (2560 = `MEM_CHAR_OFFSET`): char-ROM (definición de glifos, 8 bytes por carácter, 256 chars = 2048 bytes) +- `0x1200` (4608 = `MEM_BOOT_OFFSET`): zona de boot/recursos de ROM + +Para los modos 1 y 2 los color_screen offsets son 1200 y 300 respectivamente; en modo 3 es 768; en modo 0 no hay color_screen por celda (color global). + +### Audio + +**Sonido simple:** +- `sound(freq, len)` — onda cuadrada a `freq` Hz durante `len` (en algo similar a centésimas de segundo; `audio_len = len*44.1`). +- `nosound()` — silencio inmediato. + +**Mini-lenguaje MML — `play(str)`:** + +Sintaxis tipo BASIC `PLAY` / MML. Tokens (case-sensitive, minúsculas): + +| Token | Significado | +|-------|-------------| +| `c d e f g a b` | Nota. Acepta sufijo `#` o `+` (sostenido) o `-` (bemol). Luego dígito 0-9 para duración. | +| `r` | Silencio. Acepta dígito de duración. | +| `o<0-7>` | Octava absoluta. | +| `>` `<` | Sube / baja octava. | +| `l<0-9>` | Longitud por defecto para notas sin duración. | +| `v<0-9>` | Volumen (se traduce a `(d-0)<<4`). | +| `t<0-9>` | Tempo. | + +Duraciones: índice 0-9 → tabla `{313,625,938,1250,1875,2500,3750,5000,7500,10000}` (de "redonda" a "trentaidosava", aproximadamente). + +Ejemplo (de `breakout.lua`): + +```lua +play("l0o3bagfedc") -- escala descendente como sonido de game-over +play("o5l0c") -- pitido agudo (rebote) +``` + +### Ficheros y portapapeles + +| Función | Descripción | +|---------|-------------| +| `load([filename])` | Reinicia y carga otro `.lua` (o el mismo si filename=nil). | +| `fileout(name, addr, size)` | Vuelca `size` bytes de memoria a un binario. | +| `filein(name, addr, size)` | Carga un binario a memoria. | +| `toclipboard(str)` | Copia al portapapeles del SO. | +| `fromclipboard()` | Lee del portapapeles (máx 1023 chars). | + +### Utilidades de tiempo / frame + +| Función | Descripción | +|---------|-------------| +| `time()` | Milisegundos desde inicio (`SDL_GetTicks()`). | +| `cnt()` | Contador de frames desde el último `rst()`. | +| `rst()` | Resetea el contador de frames a 0. | +| `log(str)` | Imprime en la consola de debug (no en pantalla). | + +--- + +## 5. Caracteres especiales útiles + +Los demos usan códigos > 127 que corresponden a glifos definidos en `rom.c` (el char-ROM por defecto). Algunos vistos: + +- `\003` (3) — un bloque relleno (usado en pong para los compases) +- `\016` (16) — cubo de caja (en sokoban) +- `\127` (127) — pared en sokoban (redefinido con `setchar(127, ...)`) +- `\143`, `\154`, `\150`, `\156`, `\149` — esquinas y trazos de marcos +- `\248`, `\250`, `\251` — sprite animado de "OK" en sokoban +- `\233` — pelota en breakout +- `\131` — pala en breakout +- `\001` — cubo de tetromino (redefinido con `setchar(1, 0xff,0x81,...)`) + +Para usarlos siempre se puede hacer `setchar(idx, b0..b7)` con la bitmap deseada y luego imprimirlo con `print(chr(idx), x, y)`. + +--- + +## 6. Patrón típico de un juego + +```lua +function init() + mode(1) + cls() + -- estado inicial + player = {x=10, y=15} + score = 0 +end + +function update() + -- input + if btnp(KEY_LEFT) then player.x = player.x - 1 end + if btnp(KEY_RIGHT) then player.x = player.x + 1 end + + -- lógica + -- ... + + -- render (no hay vsync explícito; el bucle ya hace flip al final) + cls() + color(COLOR_WHITE, COLOR_BLACK) + print("\248", player.x, player.y) + print("SCORE: "..tostr(score), 0, 0) +end +``` + +**Cosas a recordar:** + +- No se "pintan" píxeles; se imprime un código de carácter en una celda y se le asocia un atributo de color (ink + paper). Para gráficos personalizados, redefinir glifos con `setchar`. +- El bucle de render lo hace el motor C++ después de `update()` — no hay que llamar a ningún `flip`. +- El `state machine` típico se hace asignando `update = otra_funcion` (ver `demos/sokoban.lua`). +- Las coordenadas de pantalla son **enteras y por celda**, no por píxel. (0,0) es esquina superior izquierda. +- Para depurar: `log("mensaje")` o pulsar ESC y usar la consola con `?variable`. + +--- + +## 7. Cómo compilar el intérprete + +Desde `c:/mingw/gitea/ascii/`: + +```sh +make windows +``` + +Requiere MinGW (g++) y SDL2 para Windows. Produce `ascii.exe`. Para correr Pepe Runner: + +```sh +ascii.exe pepe_runner.lua +``` diff --git a/chuleta_font_ascii.png b/chuleta_font_ascii.png new file mode 100644 index 0000000000000000000000000000000000000000..5356fa55020b571abe77e6eb92ed122de79021d4 GIT binary patch literal 35706 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 A6aWAK literal 0 HcmV?d00001 diff --git a/guante_blanco.bas b/guante_blanco.bas new file mode 100644 index 0000000..edb2ad4 --- /dev/null +++ b/guante_blanco.bas @@ -0,0 +1,318 @@ +10 'GUANTE BLANCO, por David Radisic +20 'copyright (c) AMSOFT 1985 +30 ' +40 MODE 0:INK 0,0:BORDER 0:INK 1,26:INK 2,15:INK 3,25 +50 INK 4,14:INK 5,24,12:INK 6,0:INK 7,0:INK 8,0:PAPER #1, 7 +60 retardo=200 +70 DIM objx(5,20),objy(5,20),joyax(5,20),joyay(5,20) +80 GOSUB 380 +90 GOSUB 720 +100 pausa=200:GOSUB 340 +110 IF joyas=0 THEN GOSUB 980 +120 PEN 4 +130 FOR i=10 TO 12 +140 LOCATE 15,i:PRINT"BOTIN"; +150 NEXT +160 PAPER 0:CLS#2:PAPER 8 +170 GOSUB 1180 +180 GOSUB 1240 +190 GOSUB 1380 +200 GOSUB 1520 +210 IF rm=0 THEN GOSUB 1910 +220 IF muerto=0 THEN 160 +230 pausa=100:GOSUB 340 +240 PAPER 0:CLS:PEN 1 +250 LOCATE 4,3:PRINT"Quiere jugar"; +260 LOCATE 5,5:PRINT"otra vez?"; +270 PEN 5:LOCATE 7,7:PRINT"S/N"; +280 i$=UPPER$(INKEY$):IF i$<>"S" AND i$<>"N" THEN 280 +290 IF i$="N" THEN MODE 2:PEN 1:STOP +300 RUN +310 IF perro=1 THEN RETURN +320 perro=1:perrox=minx(rm):perroy=miny(rm) +330 RETURN +340 FOR bucle=1 TO pausa +350 FRAME +360 NEXT +370 RETURN +380 rm=1:xp=6:yp=4:hombre$=CHR$(224):perro=0:robado=0 +390 SYMBOL 240,8,8,8,8,8,8,8,8 +400 SYMBOL 241,0,0,0,0,255,0,1,0 +410 SYMBOL 242,0,0,0,0,15,8,8,8 +420 SYMBOL 243,0,0,0,0,248,8,8,8 +430 SYMBOL 244,8,8,8,8,248,0,0,0 +440 SYMBOL 245,8,8,8,8,15,0,0,0 +450 SYMBOL 246,8,12,13,14,12,12,8,8 +460 SYMBOL 247,8,12,12,14,13,12,9,8 +470 SYMBOL 248,8,24,88,56,24,24,8,8 +480 SYMBOL 249,8,24,24,56,88,24,8,8 +490 SYMBOL 250,0,0,255,129,129,129,255,0 +500 SYMBOL 251,28,20,20,20,20,20,20,28 +510 SYMBOL 252,0,0,255,255,255,255,255,0 +520 SYMBOL 253,28,28,28,28,28,28,28,28 +530 SYMBOL 255,195,165,60,126,90,60,36,24 +540 ENT 1,12,-4,1 +550 ENT -2,=1000,60,=3000,40 +560 ENV 1,10,1,5,2,-4,1,2,-1,20 +570 vent$(1)=STRING$(2,250):vent$(2)=CHR$(251)+CHR$(8)+CHR$(10)+CHR$(251)+CHR$(8)+CHR$(10)+CHR$(251) +580 puerta$(1)=STRING$(2,252): puerta$(2)=CHR$(253)+CHR$(8)+CHR$(10)+CHR$(253)+CHR$(8)+CHR$(10)+CHR$(253) +590 conm$(1,0)=CHR$(246):conm$(1,1)=CHR$(247) +600 conm$(2,0)=CHR$(248):conm$(2,1)=CHR$(249) +610 joya$=CHR$(144):obj$=CHR$(233):perro$=CHR$(255) +620 gol$=CHR$(246)+CHR$(248)+CHR$(247)+CHR$(249)+CHR$(252)+CHR$(253)+CHR$(250)+CHR$(251)+joya$+obj$+perro$ +630 RESTORE 3020 +640 FOR i=1 TO 5 +650 READ minx(i),miny(i),maxx(i),maxy(i) +660 READ dir(i,1),dir(i,2),dir(i,3),dir(i,4) +670 NEXT +680 WINDOW #1,minx(rm)-1,maxx(rm)+1,miny(rm)-1,maxy(rm)+1 +690 WINDOW #2,1,14,1,25 +700 CLS#1:PAPER #0,8 +710 RETURN +720 ORIGIN 50,50 +730 INK 6,24,12 +740 RESTORE 3070 +750 GOSUB 1290 +760 LOCATE 1,20 +770 PEN 5:PRINT">"; +780 PEN 1:PRINT"Puertas y ventanas"; +790 PEN 5:PRINT"<";:PEN 1 +800 LOCATE 5,21:PRINT"para escapar"; +810 LOCATE 9,1:PRINT"PASE":LOCATE 10,2:PRINT CHR$(213)CHR$(212); +820 pausa=300:GOSUB 340 +830 CLS:LOCATE 1,3:INK 6,0 +840 PEN 1:PRINT hombre$;" Usted, el ladron":PRINT +850 PEN 2:PRINT LEFT$(puerta$(1),1);LEFT$(puerta$(2),1);"Puertas":PRINT +860 PEN 3:PRINT conm$(1,0);conm$(2,0);" Luces apagadas":PRINT +870 PEN 3:PRINT conm$(1,1);conm$(2,1);" Luces encendidas" :PRINT +880 PEN 4:PRINT LEFT$(vent$(1),1);LEFT$(vent$(2),1);" Ventanas":PRINT +890 PEN 5:PRINT joya$;" Piedras preciosas":PRINT +900 PAPER 1:PEN 0:PRINT obj$;" Obstaculos":PEN 1:PAPER 0:PRINT +910 PEN 1:PRINT perro$;" El perro" +920 PEN 5:PRINT:PRINT:PRINT +930 PRINT"Utilice joystick":PRINT"o teclas de cursor" +940 aux=REMAIN(1) +950 AFTER retardo*4,1 GOSUB 340 +960 RETURN +970 ' +980 'Generar joyas y obstaculos +990 ' +1000 FOR hab=1 TO 5 +1010 joyar=INT(RND*8)+2:objr=INT(RND*10)+5 +1020 minx=minx(hab):miny=miny(hab):maxx=maxx(hab):maxy=maxy(hab) +1030 FOR i=1 TO joyar +1040 x=INT(RND*(maxx-minx+1))+minx +1050 y=INT(RND*(maxy-miny+1))+miny +1060 joyax(hab,i)=x:joyay(hab,i)=y +1070 joyas=joyas+1 +1080 NEXT i +1090 FOR i=1 TO objr +1100 x=INT(RND*(maxx-minx+1))+minx +1110 y=INT(RND*(maxy-miny+1))+miny +1120 objx(hab,i)=x:objy(hab,i)=y +1130 NEXT i +1140 joyas(hab)=joyar:obj(hab)=objr +1150 NEXT hab +1160 CLS +1170 RETURN +1180 ON rm GOTO 1190,1200,1210,1220,1230 +1190 RESTORE 2680:RETURN +1200 RESTORE 2750:RETURN +1210 RESTORE 2820:RETURN +1220 RESTORE 2890:RETURN +1230 RESTORE 2970:RETURN +1240 PAPER 0:READ rm$:PAPER 8 +1250 WINDOW #1,minx(rm)-1,maxx(rm)+1,miny(rm)-1,maxy(rm)+1:CLS#1 +1260 PEN 1:LOCATE 1,1:PRINT SPACE$(19); +1270 LOCATE 1,1:PRINT"Habitacion: ";rm$; +1280 IF luces(rm) THEN INK 7,10:INK 8,10 ELSE INK 7,0:INK 8,0 +1290 READ a$:IF a$="FIN" THEN RETURN +1300 IF a$="D" THEN 2190 +1310 IF a$="W" THEN 2270 +1320 IF a$="L" THEN GRAPHICS PEN 1:GOTO 2350 +1330 IF a$="S" THEN 2430 +1340 IF a$="F" THEN GRAPHICS PEN 6:GOTO 2350 +1350 PRINT"***ERROR ***"; +1360 STOP +1370 ' +1380 'Dibujar joyas/objetos +1390 ' +1400 PEN 6 +1410 FOR i=1 TO obj(rm) +1420 LOCATE objx(rm,i),objy(rm,i) +1430 PRINT obj$; +1440 NEXT +1450 PEN 5 +1460 FOR i=1 TO joyas(rm) +1470 LOCATE joyax(rm,i),joyay(rm,i) +1480 PRINT joya$; +1490 NEXT +1500 PEN 1:LOCATE xp,yp:PRINT hombre$; +1510 RETURN +1520 xf=0:yf=0:PEN 1 +1530 IF INKEY(0)<>-1 OR INKEY(72)<>-1 THEN yf=-1 +1540 IF INKEY(2)<>-1 OR INKEY(73)<>-1 THEN yf=1 +1550 IF INKEY(8)<>-1 OR INKEY(74)<>-1 THEN xf=-1 +1560 IF INKEY(1)<>-1 OR INKEY(75)<>-1 THEN xf=1 +1570 IF xf=0 AND yf=0 THEN 1640 +1580 LOCATE xp+xf,yp+yf:ht$=COPYCHR$(#0) +1590 IF ASC(ht$)>239 AND ASC(ht$)<246 THEN 1520 +1600 IF ht$<>" " THEN 1670 +1610 LOCATE xp,yp:PRINT" "; +1620 PAPER 0:LOCATE 4,24:PRINT" ";:PAPER 8 +1630 xp=xp+xf:yp=yp+yf +1640 LOCATE xp,yp:PRINT hombre$; +1650 IF perro>0 THEN perro=perro MOD 2+1:IF perro=2 THEN 2560 +1660 GOTO 1520 +1670 gol=INSTR(gol$,ht$):car=ASC(MID$(gol$,gol,1)) +1680 ON gol GOTO 1700,1700,1700,1700,1760,1760,1860,1910,1980,2100,2660 +1690 GOTO 1610 +1700 IF gol>2 AND gol<5 THEN car=car-1 +1710 IF gol<3 THEN car=car+1 +1720 PEN 3:LOCATE xp+xf,yp+yf:PRINT CHR$(car); +1730 luces(rm)=luces(rm) XOR 1 +1740 IF luces(rm) THEN INK 7,10:INK 8,10 ELSE INK 7,0:INK 8,0 +1750 GOTO 1520 +1760 IF xf<>0 AND yf<>0 THEN 1640 +1770 IF xf<0 THEN dir=4 ELSE IF xf>0 THEN dir=3 +1780 IF yf<0 THEN dir=1 ELSE IF yf>0 THEN dir=2 +1790 IF dir(rm,dir)=-1 THEN 1640 ELSE rm=dir(rm,dir) +1800 IF perro>0 THEN GOSUB 310 +1810 IF dir=1 THEN xp=6:yp=maxy(rm) +1820 IF dir=2 THEN xp=6:yp=miny(rm) +1830 IF dir=3 THEN xp=minx(rm):yp=13 +1840 IF dir=4 THEN xp=maxx(rm):yp=13 +1850 RETURN +1860 IF xp>5 AND xp<8 THEN 1890 +1870 IF xp<6 THEN dir=4 ELSE dir=3 +1880 GOTO 1790 +1890 IF yp>13 THEN dir=2 ELSE dir=1 +1900 GOTO 1790 +1910 PAPER 0:CLS:PEN 1 +1920 LOCATE 3,3:PRINT"Usted ha escapado"; +1930 LOCATE 8,5:PRINT"con"; +1940 IF joyas=robado THEN LOCATE 8,7:PRINT"todas las";ELSE LOCATE 8,7 +1950 PRINT USING" ##";robado; +1960 PEN 5:LOCATE 8,9:PRINT"joyas"; +1970 muerto=1:RETURN +1980 LOCATE xp,yp:PRINT" ";:xp=xp+xf:yp=yp+yf +1990 i=0 +2000 i=i+1 +2010 IF i>joyas(rm) THEN 1520 +2020 IF joyax(rm,i)<>xp OR joyay(rm,i)<>yp THEN 2000 +2030 IF i=joyas(rm) THEN 2060 +2040 joyax(rm,i)=joyax(rm,joyas(rm)) +2050 joyay(rm,i)=joyay(rm,joyas(rm)) +2060 joyas(rm)=joyas(rm)-1:robado=robado+1 +2070 MOVE 400,150+(robado*2),1,1:DRAW 555,150+(robado*2),1,1 +2080 SOUND 129,248,10,12,0,1 +2090 GOTO 1990 +2100 ruido=INT(RND*15) +2110 SOUND 1,3000,10,ruido,0,0,10 +2120 PAPER 0:LOCATE 4,24:PRINT"Choque ";:PAPER 8 +2130 IF ruido<10 OR retardo=50 THEN 1640 +2140 retardo=retardo-50 +2150 aux=REMAIN(1) +2160 AFTER retardo*4,1 GOSUB 310 +2170 GOTO 1640 +2180 ' +2190 'Dibujar puertas +2200 ' +2210 READ no,pu$ +2220 IF pu$="V" THEN pu=2 ELSE pu=1 +2230 PEN 2 +2240 pic$=puerta$(pu):GOSUB 2510 +2250 GOTO 1290 +2260 ' +2270 'Dibujar ventanas +2280 ' +2290 READ no,ve$ +2300 IF ve$="V" THEN ve=2 ELSE ve=1 +2310 PEN 4 +2320 pic$=vent$(ve):GOSUB 2510 +2330 GOTO 1290 +2340 ' +2350 'Dibujar rectas +2360 ' +2370 READ x1,y1,x2,y2 +2380 MOVE x1,y1,0 +2390 DRAW x1,y2,0:DRAW x2,y2,0 +2400 DRAW x2,y1,0:DRAW x1,y1,0 +2410 GOTO 1290 +2420 ' +2430 'Dibujar interruptores +2440 ' +2450 READ no,co$ +2460 IF co$="L" THEN co=1 ELSE co=2 +2470 PEN 3 +2480 pic$=conm$(co,0):GOSUB 2510 +2490 GOTO 1290 +2500 ' +2510 'Escribir car +2520 ' +2530 READ x,y:LOCATE x,y:PRINT pic$; +2540 no=no-1:IF no>0 THEN 2530 +2550 RETURN +2560 PEN 1:LOCATE perrox,perroy:PRINT" "; +2570 hombre$=CHR$(225) +2580 IF (perrox=xp AND perroy=yp) OR (perrox=xp+xf AND perroy=yp+yf) THEN 2660 +2590 IF perroxxp THEN perrox=perrox-1 +2610 IF perroyyp THEN perroy=perroy-1 +2630 LOCATE perrox,perroy:PRINT perro$; +2640 SOUND 1,0,RND*40,10,1,2,31 +2650 GOTO 1520 +2660 PRINT"MORDIDO"; +2670 muerto=1:RETURN +2680 DATA Pasillo +2690 DATA L,64,308,226,4 +2700 DATA D,2,H,6,3,6,22 +2710 DATA D,2,V,4,12,9,11 +2720 DATA S,1,L,4,11 +2730 DATA S,1,R,9,14 +2740 DATA FIN +2750 DATA Sala +2760 DATA L,2,308,258,4 +2770 DATA D,1,V,10,12 +2780 DATA W,1,H,6,3 +2790 DATA W,1,V,2,12 +2800 DATA S,2,R,10,11,10,15 +2810 DATA FIN +2820 DATA Comedor +2830 DATA L,2,308,258,4 +2840 DATA W,1,V,10,12 +2850 DATA W,1,H,6,3 +2860 DATA D,1,V,2,12 +2870 DATA S,2,L,2,11,2,15 +2880 DATA FIN +2890 DATA Cocina +2900 DATA L,2,276,384,4 +2910 DATA D,2,H,6,5,6,22 +2920 DATA W,1,H,10,22 +2930 DATA W,1,V,14,13 +2940 DATA D,1,V,2,13 +2950 DATA S,1,L,2,16 +2960 DATA FIN +2970 DATA Despensa +2980 DATA L,2,276,256,4 +2990 DATA D,1,V,10,12 +3000 DATA S,1,R,10,11 +3010 DATA FIN +3020 DATA 5,4,8,21,0,4,3,2 +3030 DATA 3,4,9,21,-1,-1,1,-1 +3040 DATA 3,4,9,21,-1,-1,-1,1 +3050 DATA 3,6,13,21,1,0,-1,5 +3060 DATA 3,6,9,21,-1,-1,4,-1 +3070 DATA L,64,308,480,100 +3080 DATA F,250,98,294,102 +3090 DATA F,250,306,294,310 +3100 DATA F,390,94,430,106 +3110 DATA F,390,302,430,314 +3120 DATA F,474,240,488,270 +3130 DATA F,474,124,488,154 +3140 DATA F,58,240,72,270 +3150 DATA L,226,308,322,180 +3160 DATA L,160,180,480,100 +3170 DATA L,64,180,160,100 +3180 DATA FIN diff --git a/guante_blanco.lua b/guante_blanco.lua new file mode 100644 index 0000000..2c46cc3 --- /dev/null +++ b/guante_blanco.lua @@ -0,0 +1,396 @@ +-- ============================================================ +-- 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