Mine-Field 1K para ZX-81

Foro dedicado a la programación en todo tipo de sistemas clásicos.
dancresp
Amiga 1200
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

Mine-Field 1K para ZX-81

Mensajepor dancresp » 17 Jul 2013, 20:40

DSC_1199.JPG
DSC_1199.JPG (79.1 KiB) Visto 11435 veces


EL JUEGO
El objetivo del juego consiste en descubrir todas las casillas del tablero de juego y localizar las 10 minas que contiene.

Cuando introducimos el número de fila y de columna el programa nos indica la cantidad de minas que hay alrededor de esa casilla. Si añadimos un carácter más, marcaremos la casilla con un asterisco, como “sospechosa” de contener una mina.


BLOQUES
He dividido el listado en 4 bloques:

- Línea REM usada como matriz numérica donde guardamos el estado de las 100 casillas.
- Borrado de la matriz y generar el campo minado.
- Introducir las coordenadas.
- Revisar la celda y las de alrededor.


COMO FUNCIONA
A continuación detallo, línea por línea, el funcionamiento del programa.

Se utilizan las siguientes variables:
F – Variable para bucles.
I – Variable para bucles.
X – Coordenada horizontal de la casilla introducida.
Y – Coordenada vertical de la casilla introducida.
U – Variable que contiene el valor “1”.
P – Puntero al primer carácter después del REM en la línea 5. Se usa como matriz numérica.
A – Variable de apoyo.
A$ - Variable donde se guarda las coordenadas de la casilla.

5 – Línea REM que contiene 100 caracteres.
10 – Activamos el modo FAST.
15 – Guardamos el valor 1 en la variable “U”. Se usará a lo largo del programa y permite ahorrar memoria.
20 – Se muestra el identificador de las casillas horizontales.
25 – Guardamos el valor 16514 en la variable “P”. Apunta al primer carácter después del REM de la línea 5.
30 – Inicio de un bucle entre los valores 0 y 99.
35 – Ponemos los caracteres de la línea REM a 0 mediante un POKE.
40 – Final del bucle. Ya tenemos la matriz inicializada.
50 – Inicio de un bucle entre los valores 0 y 9.
55 – Guardamos en “A” un valor entre 0 y 99, ya que “I” ha quedado con valor 100 al finalizar el bucle anterior.
60 – Si esa posición en la línea REM vale 1 vuelve a la línea 55.
65 – Hacemos un POKE a la línea REM y ponemos el valor de la posición a 1.
70 – Imprimimos una tira de guiones en la zona de juego y su posición vertical.
75 – Final del bucle.
80 – Activamos el modo SLOW.
100 – Introducimos la casilla en la variable “A$”.
105 – Guardamos en “Y” el primer carácter de “A$”, que es la fila.
110 – Guardamos en “X” el segundo carácter de “A$”, que es la columna.
115 – Situamos el cursor del PRINT en la posición Y,X más una casilla.
120 – Si la longitud de “A$” es 2 salta a la línea 135.
125 – Se considera que se está marcando una casilla y se pone un “*” en la posición indicada.
130 – Salta a la línea 80 para volver a introducir otra casilla.
135 – Si la casilla está a 1 pone una “X” y fuerza un STOP provocando un ERROR al usar la variable inexistente “Z”.
140 – Se activa el modo FAST.
200 – Se inicializa la variable “A” con 0.
205 – Inicio del bucle de control vertical desde la fila anterior a la siguiente de la indicada.
210 – Inicio del bucle de control horizontal desde la columna anterior a la siguiente de la indicada.
215 – Se suma 1 a “A” si la casilla está a 1 y entre las coordenadas 0 y 9, tanto vertical como horizontalmente.
220 – Final del bucle horizontal.
225 – Final del bucle vertical.
230 – Si “A” es distinto de 0 pone el número de minas en la casilla que hemos introducido.
235 – Si “A” es igual a 0 pone un espacio en la casilla indicada.
240 – Salta a la línea 80 para activar el modo SLOW y volver a introducir otro número.


EL PROGRAMA
listado.jpg
listado.jpg (198.07 KiB) Visto 11435 veces


APUNTES FINALES
Hacía 29 años que no programaba en un ZX-81 con 1 KB, y que mejor que re-estrenarse con un juego.

Asumiendo que en este sistema los juegos de acción no suelen quedar muy bien si están hechos en BASIC, que mejor que hacer un rompe-cocos. Siempre nos queda el modo FAST.

Así que me he decidido a hacer una versión del “Campo Minado” que había programado en M-BASIC bajo CP/M-86.

Desarrollar este juego ha sido todo un reto, y por poco no lo consigo…

Peleando con la memoria:
- Un ZX-81 básico dispone de 1024 bytes de RAM libres.
- Las variables de sistema ocupan 125 bytes.
- La memoria de video para un tablero de juego de 10x10 más los indicadores de fila y columna ocupan un total de 11x11=121 bytes, más los 25 bytes de final de línea, ocupan 146 bytes. Más unos 5 ó 6 de la zona del INPUT.
Total unos 150 bytes menos.

Necesito 7 variables numéricas, que ocupan 7 bytes cada una y una alfanumérica que no debería ocupar más de 7 bytes, pero que depende de lo que se introduzca en el INPUT. Así que, en principio, las variables consumen unos 50 bytes más.

Total que 1024-125-150-50=699 bytes para el programa.

Y para rematar, hay que guardar una matriz de 100 posiciones para guardar la posición de las bombas:
- Si se usa una matriz numérica ocupa más de 500 bytes. Inviable.
- Si se usa una variable de cadena de 100 posiciones ocupa unos 105 bytes pero complica la gestión posterior.

¿Como se hace?
El programa se ha desarrollado en un TIMEX SINCLAIR 1000 con 2 KB para evitar el engorro de programar con 1 KB y su molesta “escalada” de líneas en pantalla mientras programas. Así daba uso a este equipo, con el que nunca había programado.

Durante el desarrollo existía una línea:
9999 PRINT (PEEK 16396+256*PEEK 16397)-16509

... que me ha permitido controlar lo que ocupaba el programa. Este no debe ocupar más de 600 Bytes.

Una vez el programa funcionaba correctamente se ha cargado en un SINCLAIR ZX-81 para verificar que funciona con 1KB y hacer los correspondientes ajustes en caso de error. Evidentemente solo ejecutarlo ha dado un error de memoria llena.

¿Como ahorrar memoria?
Mi primera decisión ha sido usar como matriz donde guardar la posición de las bombas, una línea REM (línea 5) con 100 caracteres. Con esto he ahorrado unos bytes ya que solo ocupa espacio como línea de programa pero no en el área de variables, y encima facilita la gestión posterior. Así, cada vez que se ejecuta el programa cambia el contenido de la línea. Aparecen unos espacios donde no hay bomba, y un cuadradito donde hay la bomba.

Como usaré el valor 1 varias veces, he declarado una variable “U” en la línea 15 con ese valor. Se ha declarado mediante un VAL porque el valor ocupa 7 bytes en la zona de variables, pero en la zona del programa ocupa 3 bytes menos que de la forma tradicional y queda más claro que con un CODE. Y con “U+U” puedo obtener un 2.

Declaro la variable P como puntero al primer carácter después del REM en la línea 5, ya que se usará varias veces. El programa se empieza a guardar a partir de la dirección 16509 y el primer carácter después del REM está en 16514.

Como sustitutivo del valor 0 uso NOT PI ya que solo ocupa 2 bytes en lugar de los 5 habituales.

En las líneas 30-40 hay un bucle que usa la variable “I”. La estructura del bucle ocupa 18 bytes. De todas formas, el bucle va de 0 a 99, y al finalizar I=100. En la línea 55 uso este valor para calcular la posición aleatoria de las bombas y ahorro meter un valor numérico.

Las casillas de las bombas tienen un valor de 0 (vacía) o 1 (bomba). Esto me ha permitido usar IF sin signos de condición, como se puede ver en las líneas 60, 135 y en la suma de 215. Si hubiera usado una variable de cadena no lo podría haber hecho, o tendría que hacer un VAL.

En la línea 215 controlo las bombas que hay alrededor de la casilla indicada. Para ello hago un doble bucle que comprueba 3x3 casillas, y suma 1 cada vez que encuentra una bomba y la casilla está en una posición entre 0 y 9. Esto es así para evitar las casillas cerca de los bordes del tablero. Esta línea me daba errores “4” por falta de memoria durante la ejecución.

He evitado el uso de GOSUB-RETURN y otras cosas y en todo momento el programa se ejecuta de arriba a abajo.

Para forzar la detención del programa y ahorrar un STOP si tocamos una bomba, en la línea 135 hago un PRINT de la variable Z, que no está definida. Esto provoca un error 2 y detiene el programa.

La ejecución en 1 KB
Ni que decir que al probar el programa en el ZX-81 con 1 KB me ha dado un problema de memoria. Esto me ha obligado a sustituir algunos VAL por CODE y a depurar todavía más el programa, a parte de eliminar la línea 9999.

También encontré la forma de simplificar ciertos cálculos, como en la línea 135, a declarar la variable “U” para almacenar el 1, y alguna otra cosilla.

He activado el modo FAST al hacer los cálculos para conseguir que funcione de una forma rápida.

Por desgracia no he podido validar que el valor introducido es correcto por temas de memoria, así que si se introduce un valor incorrecto nos aparecerá un error 3, y se detendrá el programa.

Tampoco he podido hacer que descubra las casillas colindantes a la indicada hasta que encuentra una mina, pero para ello debería haber dispuesto de unos 250 bytes más. Por ello hay que ir descubriendo casilla a casilla.

Con todo, el programa ocupa unos 600 bytes, funciona perfectamente y con una buena velocidad, así que, al final…

Prueba superada !!!


Os invito a probarlo.

DSC_1192.JPG
DSC_1192.JPG (93.86 KiB) Visto 11435 veces

DSC_1197.JPG
DSC_1197.JPG (102.09 KiB) Visto 11435 veces

DSC_1200.JPG
DSC_1200.JPG (93.46 KiB) Visto 11435 veces

DSC_1193.JPG
DSC_1193.JPG (80.09 KiB) Visto 11435 veces
Buscando la IP de la W.O.P.R.

Avatar de Usuario
Alan_Smithee
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 158
Registrado: 11 Mar 2007, 22:57
Gracias dadas: 3 veces
Gracias recibidas: 39 veces

Re: Mine-Field 1K para ZX-81

Mensajepor Alan_Smithee » 17 Jul 2013, 21:30

¡Enhorabuena! He pasado recientemente por un "desafío" similar al hacer la versión ZX81 del "Castillo Belmar" de los chicos de Commodore Plus (detalles y descarga en unos días en mi blog). El plan era reproducir en la máquina de Sinclair la "hazaña" compresora del autor original inglés, Paul Panks, de meter una aventura minimalista pero funcional en el BASIC de un Commodore de 2 KB...

No hubo manera. :lol: :lol: :lol:

Las propias versiones de Panks para ZX81 de sus aventuras de Vic20 y similares siempre, de hecho, ocupaban el doble en la máquina de Sinclair debido a las peculiaridades conocidas del BASIC de ZX81: carencia de instrucciones READ-DATA, limitación a una sentencia por línea... Usando el mismo tipo de trucos que has utilizado aquí (variables y matrices camufladas en cadenas de texto y esos malabarismos que nos conocemos los spectrumeros 8-) ) y trabajando con la herramienta text2p y el emulador EightyOne conseguí meter la aventura de 2 KB en un ZX81 ampliado a 4 KB de memoria. Y ya me pude dar con un canto en los dientes. Por supuesto ¡lo bien que me lo pasé en el proceso no me lo quita nadie!

¡Enhorabuena de nuevo por tu éxito! :beer:

--

Avatar de Usuario
zitror
Amiga 2500
Amiga 2500
Mensajes: 5349
Registrado: 02 Jul 2006, 00:16
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
Ubicación: El interior de un Z80
Gracias dadas: 248 veces
Gracias recibidas: 103 veces
Contactar:

Re: Mine-Field 1K para ZX-81

Mensajepor zitror » 18 Jul 2013, 13:28

Joder, increible tu trabajo con solo 1Kb ¡qué currada! =D>

¿Ya habías programado anteriormente con 1Kb o cuando te lo compraron tus padres tuviste directamente la expansión de memoria?

Lo de los agujeritos del Timex me lo tienes que explicar :shock:

Salu2 ;)
(C) 1.982 Sinclair Research Ltd

La buhardilla de Zitror

Avatar de Usuario
gamer80
Atari 1040 STf
Atari 1040 STf
Mensajes: 781
Registrado: 31 Oct 2011, 19:34
Ubicación: ESPARTA
Gracias dadas: 20 veces
Gracias recibidas: 34 veces
Contactar:

Re: Mine-Field 1K para ZX-81

Mensajepor gamer80 » 18 Jul 2013, 13:49

Increible hacer algo en solo 1k, me ha venido a la cabeza el tío que hizo el ajedrez para zx81, cómo se las ingeniaría =D>
"Hazlo o no lo hagas, pero no lo intentes" -Maestro Yoda-

Avatar de Usuario
outrunfan
Amstrad PCW 8256
Amstrad PCW 8256
Mensajes: 136
Registrado: 19 Oct 2010, 19:24

Re: Mine-Field 1K para ZX-81

Mensajepor outrunfan » 18 Jul 2013, 15:23

Solo un Kb Dancresp ?????????? :shock: Si eso se gasta poniendo solo REM. Hablando de esto se me han venido a la cabeza las lineas REM fantasma para ahorrar memoria.
SELECT MUSIC BY STEERING: MAGICAL SOUND SHOWER

dancresp
Amiga 1200
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

Re: Mine-Field 1K para ZX-81

Mensajepor dancresp » 18 Jul 2013, 23:31

Alan_Smithee escribió:Las propias versiones de Panks para ZX81 de sus aventuras de Vic20 y similares siempre, de hecho, ocupaban el doble en la máquina de Sinclair debido a las peculiaridades conocidas del BASIC de ZX81: carencia de instrucciones READ-DATA, limitación a una sentencia por línea... Usando el mismo tipo de trucos que has utilizado aquí (variables y matrices camufladas en cadenas de texto y esos malabarismos que nos conocemos los spectrumeros 8-) ) y trabajando con la herramienta text2p y el emulador EightyOne conseguí meter la aventura de 2 KB en un ZX81 ampliado a 4 KB de memoria. Y ya me pude dar con un canto en los dientes. Por supuesto ¡lo bien que me lo pasé en el proceso no me lo quita nadie!

Vi el hilo del Commodore 16, pero no he conseguido encontrar información de la versión del ZX-81.
Sería interesante echarle un vistazo... :-ss

Pero coincido contigo que hacer nada en esta máquina es todo un logro, porque tal y como trata los números (siempre reales), el no poder meter varios comandos en una línea, y otras carencias y limitaciones hacen que pierdas mucha de la poca memoria que tiene...


zitror escribió:¿Ya habías programado anteriormente con 1Kb o cuando te lo compraron tus padres tuviste directamente la expansión de memoria?

Mis primeros 4 o 5 meses de ZX-81 me los pasé programando cosillas en 1 KB.
Ya los recuperaré y los publicaré, porque alguno es hasta interesante, pero creo que esta es mi mejor creación con 1 KB, al menos técnicamente. :geek:

zitror escribió:Lo de los agujeritos del Timex me lo tienes que explicar :shock:

Tengo dos Timex-1000, pero solo este tiene los agujeritos.
Ignoro el motivo, pero vienen de fábrica porque están muy bien hechos... :-k
Buscando la IP de la W.O.P.R.

Avatar de Usuario
zup
Amiga 2500
Amiga 2500
Mensajes: 2973
Registrado: 04 Sep 2009, 20:07
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Nintendo DS/3DS
Primera consola: Nintendo GameBoy
Ubicación: Navarra
Gracias dadas: 68 veces
Gracias recibidas: 329 veces
Contactar:

Re: Mine-Field 1K para ZX-81

Mensajepor zup » 19 Jul 2013, 08:06

Ahorrando algún otro byte... recuerda que SGN PI=1.

Además cada línea se lleva por delante 4 bytes, para el número de línea y su longitud. Agrupar varias sentencias por línea ahorrará bytes, pero irá en contra de la legibilidad del programa.

Todo esto en un Spectrum, no sé si SGN existe en el BASIC del ZX81, o los detalles exactos de cómo almacena las líneas de BASIC en memoria.
I have traveled across the universe and through the years to find Her. Sometimes going all the way is just a start.
Además vendo cosas!

dancresp
Amiga 1200
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

Re: Mine-Field 1K para ZX-81

Mensajepor dancresp » 19 Jul 2013, 13:53

zup escribió:Además cada línea se lleva por delante 4 bytes, para el número de línea y su longitud. Agrupar varias sentencias por línea ahorrará bytes, pero irá en contra de la legibilidad del programa.

El BASIC del ZX-81 es como el del SPECTRUM pero con menos comandos. Sus 8 KB de ROM no dan para más.

Y por desgracia no permite poner varios comandos en la misma línea.
Esto afecta a la velocidad y sobretodo, a la memoria. :(
Buscando la IP de la W.O.P.R.

Shaun_B
ZX Spectrum 16
ZX Spectrum 16
Mensajes: 4
Registrado: 02 Ene 2014, 01:56
Sistema Favorito: C64
primer_sistema: Spectrum +2
consola_favorita: (Otro)
Primera consola: (Otro)

Re: Mine-Field 1K para ZX-81

Mensajepor Shaun_B » 02 Ene 2014, 19:28

Minesweep Redux:

Imagen

en la línea tres

Código: Seleccionar todo

3 PRINT USR VAL "3275"; ...


es un truco para cambiar al modo "FAST". Es el mismo que

Código: Seleccionar todo

3 FAST
4 PRINT ...


pero utiliza una línea en lugar de dos.

El listado de programas cambia a "SLOW" en la línea 15 usando el mismo principio.

La versión "Redux" se ha archivado en los foros Sinclair ZX World en sinclairzxworld.com/viewtopic.php?f=4&t=552&p=13577#p13577

Lo siento por los pobres traducciones al Español.

Shaun.

Avatar de Usuario
Hark0
Amiga 1200
Amiga 1200
Mensajes: 1695
Registrado: 11 Jul 2012, 23:44
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: (Otro)
Primera consola: (Otro)
Ubicación: Cornellà de Llobregat - Barcelona
Contactar:

Re: Mine-Field 1K para ZX-81

Mensajepor Hark0 » 02 Ene 2014, 23:04

- de 1 Kb!

Un máquina... eso es lo que eres... ;)

Enhorabuena! =D>
http://www.zxuno.com
ZX-Uno · Clon de ordenador ZX Spectrum basado en FPGA.


Volver a “Programación”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 32 invitados