Lights-Out 1K para ZX-81
-
- Amiga 1200
- Mensajes: 1393
- Registrado: 23 Dic 2008, 17:53
- Sistema Favorito: MSX
- primer_sistema: ZX81
- Primera consola: Atari 2600
- Gracias dadas: 3 veces
- Gracias recibidas: 20 veces
Lights-Out 1K para ZX-81
EL JUEGO
El objetivo del juego consiste en apagar todos las luces del tablero de juego.
Debemos introducir dos números entre 1 y 5: Primero la Fila y después la Columna. Después de cada número hay que pulsar ENTER. A continuación cambiaremos el estado de esa luz y de la que esta arriba, abajo, derecha e izquierda.
El juego dispone de 10 niveles predefinidos, y a partir de aquí el ordenador genera tableros aleatorios.
Descargar el juego en formato ".Z81" (Snapshot del EightyOne):
BLOQUES
He dividido el listado en 6 bloques:
- Datos de los primeros 10 tableros.
- Decodificar los datos del tablero.
- Impresión del tablero.
- Pasar de nivel.
- Introducir la posición y cambiar los estados correspondientes.
- Invertir el estado de una luz.
COMO FUNCIONA
A continuación detallo, línea por línea, el funcionamiento del programa.
Se utilizan las siguientes variables:
F – Variable numérica.
I – Variable numérica.
N – Variable numérica.
B – Variable numérica.
P – Variable con el puntero a los datos del nivel activo en la línea REM.
A$ - Variable donde se guarda el estado del tablero activo.
10 – Línea REM que contiene los datos de los 10 niveles, agrupados de 5 en 5 caracteres.
12 – Guardamos el valor 16514 en la variable “P”. Apunta al primer carácter después del REM de la línea 10.
20 – Inicializo el valor de la variable A$ donde se guarda el estado de las 25 luces del nivel activo.
22 – Inicio del bucle que procesará los 5 caracteres que contienen el estado de las luces del nivel. De 0 a 4.
24 – Se coge el valor del carácter correspondiente y se guarda en “N”.
26 – Se inicializa el valor de la variable “B=16”.
28 – Si el valor de “N” es mayor o igual a “B”, “F=1”, sino “F=0”.
30 – Se añade el valor de “F” en A$.
32 – Si “F” es distinto de 0 se resta “B” de “N”.
34 – Divide el valor de “B” entre 2.
36 – Si “B” es mayor o igual a 1 salta a la línea 28.
38 – Final del bucle.
40 – Borra la pantalla.
42 – Inicio del bucle que controla las filas. De 0 a 4.
44 – Inicio del bucle que controla las columnas. De 1 a 5.
46 – Imprimir la luz con el estado correspondiente.
48 – Final del bucle de columnas.
50 – Se rompe el PRINT de la línea 46.
52 – Se hace un PRINT de una línea en blanco.
54 – Final del bucle de filas.
56 – Si hay luces encendidas se salta a la línea 60.
58 – Se incrementa “P” en 5 para que apunte a los datos del siguiente nivel de la línea REM.
59 – Salta a la línea 20.
60 – Se introduce la fila.
62 – Se introduce la columna.
64 – Se guarda en “N” la luz seleccionada.
66 – Se salta a la subrutina de la línea 90.
68 – Se resta 5 a “N” para revisar la luz superior.
70 – Si la posición es superior a 0 se salta a la subrutina de la línea 90.
72 – Se suma 10 a “N” para revisar la luz inferior.
74 – Si la posición es inferior a 25 se salta a la subrutina de la línea 90.
76 – Se resta 6 a “N” para revisar la luz de la izquierda.
78 – Si la fila es superior a 1 se salta a la subrutina de la línea 90.
80 – Se suma 2 a “N” para revisar la luz de la derecha.
82 – Si la fila es inferior a 5 se salta a la subrutina de la línea 90.
84 – Salta a la línea 60.
90 – Se consulta el estado de la luz y se invierte su valor. De 0 a 1 o de 1 a 0.
92 – Se guarda en A$ el nuevo estado de la posición.
94 – Final de la subrutina.
EL PROGRAMA
APUNTES FINALES
No hay dos sin tres. Después de las versiones 1K de los programas “Minefield” y “Sudoku” me quedaba pendiente adaptar este juego, que ya había programado anteriormente para el THOMSON MO-5, ORIC, MSX y en M-BASIC bajo CP/M.
Y por primera vez no he usado un ZX-81 real. He usado el emulador “EightyOne” con unos resultados muy satisfactorios, aunque no es lo mismo que usar el hardware auténtico.
Desarrollar este juego ha sido un nuevo reto, ya que tenía serías dudas antes de comenzar de que pudiera meterlo en los 600 bytes que ha acabado ocupando.
Peleando con la memoria (una vez más):
Un ZX-81 básico dispone de 1024 bytes de RAM libres. Las variables de sistema ocupan 125 bytes y la memoria de video para el tablero de juego ocupa 5x9=45 bytes, más los 25 bytes de final de línea, ocupan unos 70 bytes.
Necesito 5 variables numéricas, que ocupan 7 bytes cada una y una alfanumérica que ocupa 25 bytes. Así que, en principio, las variables consumen unos 60 bytes más aprox.
Los datos de los 10 niveles necesitan 50 bytes más, a razón de 5 bytes por nivel.
¿Como ahorrar memoria?
Antes de empezar el programa me planteé como codificar los niveles ya que no podía guardar 25 tiras de 1 y 0 para cada uno de los 10 niveles, cosa que me había ocupado unos 250 bytes. Así que he montado un sistema que me permite almacenar cada fila de luces en un único carácter, usando sus 5 últimos bites. Uno para cada estado de la luz de una fila.
Este es el sistema de codificación empleado:
Entre las líneas 20 y 38 hay una rutina que se encarga de coger el valor del carácter de la línea REM, según la tabla de caracteres del ZX-81, para posteriormente pasarlo a binario mediante un sencillo conversor decimal / binario. El resultado es una tira de 25 caracteres 1 o 0 que se guardan en la variable A$. Esto ha ahorrado mucha memoria, y el proceso es más compacto y rápido de lo que esperaba. En total ocupa unos 200 bytes.
A continuación y mediante un doble bucle muestro el tablero. Los caracteres usados son contiguos, y se suma 0 o 1 en función del estado de esa luz.
He aprovechado el comando VAL para obtener el valor de A$. Si hay 25 ceros, el valor es 0 y incrementa el puntero del nivel y muestra un nuevo tablero. Sino nos pide una nueva tirada.
En este caso he optado a pedir las posiciones porque ocupa menos memoria, es más sencillo de gestionar y me facilita los cálculos siguientes.
En la línea 90 hay una sencilla subrutina que consulta una posición “N” de la variable A$, invierte el valor y lo vuelve a guardar es la misma posición. Esta rutina se llama 5 veces con posiciones distintas en cada tirada.
Como sustitutivo del valor 0 uso NOT PI ya que solo ocupa 2 bytes en lugar de los 5 habituales, y utilizo el menor número posible de variables.
¿Que se ha quedado en el tintero?
- No he podido implementar un tablero con las coordenadas, ni puedo comprobar que sean correctas.
- No hay ayuda disponible como en versiones anteriores, y no se puede reinicializar un nivel.
- No hay indicador de nivel ni contador de movimientos realizados.
Como curiosidad, al pasar del nivel 10 el puntero “P” apunta fuera de la línea REM y se usan los bytes del propio programa en BASIC para generar nuevos niveles, que no tienen una solución garantizada.
Con todo, prueba superada !!!
Os invito a probarlo.
Buscando la IP de la W.O.P.R.
¿Quién está conectado?
Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados