BattleShips-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

BattleShips-1K para ZX-81

Mensajepor dancresp » 29 May 2014, 20:30

bship_1.gif
bship_1.gif (7.05 KiB) Visto 9266 veces


EL PROGRAMA
Este programa es una sencilla versión del clásico juego de los barquitos para jugar contra el ZX-81.

Cada contrincante dispone de una flota de 5 barcos de dos posiciones cada uno.

En el tablero de 10x10 casillas se muestra la posición de los barcos del jugador y las tiradas que va realizando el ZX-81. El jugador deberá llevar el control de sus jugadas en una hoja de papel o jugando de memoria.

Inicia la partida el ZX-81 y de forma alternativa se van realizando las tiradas. En caso de que el ZX-81 toque un barco del jugador, vuelve a realizar una nueva tirada. A continuación tira el jugador introduciendo un valor formado por una letra y un número, correspondientes al formato "fila/columna”.

El primer jugador que hunde los cinco barcos del adversario gana la partida. Para iniciar una nueva partida se debe detener el programa con “BREAK” y hacer “RUN”.

Descargar el juego en formato ".z81" (Snapshot de EightOne):
BattleShips.rar
(1.07 KiB) Descargado 287 veces


BLOQUES
He dividido el listado en 6 bloques:

- Inicializar variables principales.
- Mostrar el tablero.
- Introducir la posición de los barcos de los dos jugadores.
- Tirada del ZX-81.
- Tirada del jugador.
- Rutina de entrada de datos del jugador y cálculo de la posición.


COMO FUNCIONA
El programa ocupa 30 líneas. A continuación detallo el funcionamiento de cada una.

Se utilizan las siguientes variables:
D – Variable que contiene el valor “10”.
M – Variable usada como puntero a la memoria del buffer de impresora.
F – Variable para bucles, o auxiliar en varios puntos.
X – Posición horizontal de la tirada.
Y – Posición vertical de la tirada.
A$ - Casilla donde se tira.

2 – Guardamos el valor 10 en la variable “D”. Se usará a lo largo del programa y permite ahorrar memoria.
4 – Guardamos el valor 16444 en la variable “M”. Se usa como puntero para guardar la posición de los barcos del ZX-81.
10 – Muestra el valor de las columnas.
12 – Inicio del bucle que dibuja el tablero.
14 – Muestra el valor de las filas.
16 – Final del bucle que dibuja el tablero.
20 – Inicio del bucle para introducir la posición de los barcos del jugador y del ZX-81.
22 – Saltamos a la línea 62 que pide la posición de la tirada del jugador.
24 – Mostrar el barco en la posición indicada.
26 – Posicionamiento de un barco por parte del ZX-81.
28 – Final del bucle de posicionamiento.
30 – Tirada aleatoria vertical del ZX-81.
32 – Tirada aleatoria horizontal del ZX-81.
34 – Posicionar el cursor en la posición de la tirada del ZX-81.
36 – Guarda en F el carácter que hay en esa posición de la pantalla.
38 – Si ya hay una “X” vuelve a la línea 30 para hacer una nueva tirada.
40 – Pone una “X” en la posición de la tirada y posiciona el cursor en la posición 20,0 para el mensaje del jugador.
42 – Si la tirada del ZX-81 no ha tocado un barco del jugador salta a la línea 50.
44 – Modifica la tirada horizontal del ZX-81, eligiendo la posición siguiente o anterior si se sale del tablero.
48 – EL ZX-81 vuelve a tirar.
50 - Saltamos a la línea 62 que pide la posición de la tirada del jugador.
52 – Inicio del bucle que revisa si se ha tocado alguno de los cinco barcos del ZX-81.
54 – Si la tirada coincide con la posición o posición contigua de un barco del ZX-81 pone “HIT” en pantalla.
56 – Final del bucle de revisión.
58 – Imprime tres espacios que pueden borrar el mensaje “HIT” de la tirada anterior.
60 – Salta a la línea 30 para una nueva tirada del ZX-81.
62 – Introducir la tirada del jugador.
64 – Calcular la posición vertical de la tirada.
66 – Calcular la posición horizontal de la tirada.
68 – Final y retorno de la subrutina.


EL PROGRAMA
listado.gif
listado.gif (10.73 KiB) Visto 9257 veces


APUNTES FINALES
Después de varios juegos de un solo jugador y un par de proyectos más serios (FORTH y ASSEMBLER) para el ZX-81 tenía ganas de programar un juego en el que pudieras jugar contra el ordenador.

Mi primer intento ha sido este, y uno de los objetivos era hacer que el ordenador jugara con “cierta” inteligencia. Esto es que no tire dos veces en la misma casilla y que al tocar un barco del adversario intente hundirlo. Lo he conseguido “casi” todo, con matices.


La primera en la frente
Mi primer intento consistió en una versión en la que aparecían los dos tableros. El tema funcionaba bastante bien hasta que tuve que implementar las partes más complejas. Al poco apareció el fatídico error 4 de “No hay memoria”.

bship_5.gif
bship_5.gif (42.32 KiB) Visto 9266 veces


La memoria de pantalla se llevaba una cuarta parte de la RAM y no cabía el resto del programa. Pero bueno, durante un ratito a medio funcionado...

A partir de ese punto me he visto obligado a realizar los recortes oportunos para conseguir encajarlo en el mísero K de RAM.
El resultado es más que satisfactorio.


Metiendo un juego de los barquitos en 550 bytes y 30 líneas de código BASIC
Una vez me las he pasado canutas para conseguir hacer que funcione con las limitadas capacidades del ZX-81 básico. Y una vez más aquí ha estado la gracia del proyecto.

Como siempre, lo primero ha sido introducir una línea con la que voy controlando la memoria que ocupa el programa:
9999 PRINT (PEEK VAL"16396"+VAL"256"*PEEK VAL"16397")-VAL"16552"
Esta línea ocupa 43 bytes, que ganaré al borrarla al finalizar el desarrollo del programa, o antes si es preciso.

He usado los trucos habituales del ZX-81 para ahorrar memoria en el uso de valores numéricos. Así, “NOT PI” es 0 y "SGN PI" es 1, uso de VAL, y como el valor 10 se usa varias veces he asignado ese valor a la variable "D". Para valores de un dígito o que no puedo asignar con CODE uso VAL para dejar el programa algo más comprensible, y para el resto uso CODE.

Para este proyecto solo utilizo 5 variables numéricas, que voy reutilizando en distintas partes, y una alfanumérica donde almaceno la entrada del jugador. Con todo, esto ocupa unos 50 bytes.

Vamos por partes:

Dibujando el tablero
Esta parte se ha llevado 4 líneas simples de código. Eso si, la memoria de video puede llegar a ocupar un total de 156 bytes entre el tablero (11x11), el mensaje HIT y 3 espacios (6 bytes) y la zona del INPUT (4 bytes si no nos pasamos en la entrada), A más de las 25 marcas de final de línea típicas del ZX-81 cuando tiene menos de 4KB de RAM.

Colocando los barcos
Esta parte ocupa solo 5 líneas, y me siento especialmente orgulloso. Explico el motivo.

Cada jugador debe introducir 5 barcos que ocupan dos posiciones. En el caso del jugador, salvo que haya mala intención, la colocación debe ser correcta. Pero en el caso del ZX-81 hay que evitar que dos barcos puedan ocupar la misma posición, y con una simple línea y algo de ingenio lo he conseguido.

Vamos a repetir las siguientes líneas un total de cinco veces. Una por barco y usando el valor del bucle “F” como contador.

Para que el jugador coloque un barco se llama a la subrutina que hay en la línea 62. Nos pide introducir una posición con el formato “fila/columna” y a continuación se convierte el valor de la letra en un valor entre 0 y 9 que se guarda en “Y” (fila) , y el valor numérico entre 0 y 9 se guarda en “X” (columna). Con estos dos valores ponemos el gráfico del barco en la posición correspondiente del tablero. Bastante simple.

Para las posiciones de los barcos del ZX-81 la cosa se complica.

Primero hay que pensar donde se van a guardar. Imposible crear una matriz de dos dimensiones con tan poca memoria.
¿Solución? Uso el buffer de la impresora (33 bytes sin uso durante la ejecución del programa) para guardar la primera posición absoluta de cada barco. El tablero ocupa un total de 100 casillas que internamente van numeradas con un valor entre 0 y 99. Así la fila A va de la casilla 0 a la 9, B de la 10 a la 19, y así hasta el final. De esta forma, la casilla “B5” se guarda como 15 y la casilla “J9” como 99, por ejemplo.

Y para evitar que la posición de dos barcos coincida, he dividido el tablero en 5 zonas de dos líneas cada una, así el primer barco debe estar entre la casilla 0 y la 19, el segundo entre la 20 y la 39, etc. De esta forma no hay que hacer ninguna comprobación, aunque si se sabe el “truco” cuando hundes un barco en una fila no hace falta seguir buscando en esa zona.

De esta forma, con el POKE de la línea 26 y una simple fórmula coloco la posición absoluta de un barco en un byte del buffer de la impresora con la seguridad que ningún más se coloque encima. Eso si, puede darse el caso que dos barcos estén colocados en casillas adjuntas, aunque las probabilidades son bajas. Es lo que hay.

Tira el ZX-81
Para evitar que el ordenador no tire dos veces en la misma casilla y no tengo espacio para guardar las posiciones donde ya he tirado, voy a usar la memoria de pantalla para este efecto. Así, genero dos números aleatorios, posiciono el cursor en la posición de la pantalla correspondiente con el PRINT AT de la línea 34 y consulto en la memoria de pantalla si hay una “X”. En caso afirmativo vuelvo a generar dos nuevos números, hasta que la tirada es correcta.

A continuación pongo una “X” en esa posición y consulto el carácter que había en esa posición de la pantalla, y que está guardado en “F”. Si no he tocado un barco salto a la línea 50 para que tire el jugador.

Si he tocado una parte de un barco, se activa una sencilla rutina de “inteligencia artificial” que lo que hace es incrementar en 1 la posición horizontal de la tirada realizada (a la derecha), y en caso de salir del margen del tablero restar 2 para tirar a la izquierda. Salto a la línea 34 y vuelvo a comprobar que hay en esa posición.

Como las variables “X” e “Y” están compartidas por los dos jugadores, he tenido que hacer que el ordenador pueda realizar una nueva tirada en caso de tocar un barco del jugador para no perder la posición. Y en caso de no dar con la otra mitad del barco, entra en un proceso de “amnesia” hasta que un nuevo número aleatorio le haga dar con él.

Tira el jugador
En este caso vamos a volver a ir a la subrutina de la línea 62, la cual a partir de unas coordenadas nos devuelve una posición horizontal (X) y una vertical (Y).

A continuación se inicia un bucle que se repite 5 veces y que sirve para comprobar si el valor absoluto de las coordenadas indicadas coinciden con la posición de uno de los barcos del ZX-81 o con la posición contigua, ya que el barco ocupa dos posiciones. El valor absoluto se calcula multiplicando la coordenada vertical por diez y sumándole la horizontal.

Si hemos tocado un barco aparece el texto “HIT” , en una posición que hemos colocado al hacer el PRINT “X” de la tirada del ZX-81.

Al acabar la comprobación se imprimen 3 espacios. Si no se ha tocado ningún barco, borrará el mensaje “HIT” (si estaba) y sino se pondrán en la línea siguiente lo que no afecta en nada (pero ocupan 3 bytes).

Final de partida
Como en ningún momento se controla el número de impactos de ninguno de los contendientes, la partida puede entrar en un bucle sin fin cuando el ZX-81 ha llenado todas las casillas. Así que cuando uno de los contendientes haya localizado las 10 partes de los barcos, se deberá hacer un “BREAK” y un “RUN” para iniciar otra partida.

Y si ya has tenido bastante, siempre nos quedará “NEW”.


Para terminar
Me he quedado con las ganas de mostrar los dos tableros, controlar las posiciones de los barcos, las coordenadas y alguna otra cosilla, pero la verdad es que no había memoria para más.


Pues nada más. Con sus limitaciones el programa funciona más que bien y es hasta entretenido, así que…

Os invito a probarlo.

bship_2.gif
bship_2.gif (8.13 KiB) Visto 9266 veces

bship_3.gif
bship_3.gif (8.19 KiB) Visto 9266 veces
Buscando la IP de la W.O.P.R.

rgrocha
Spectrum 48K Plus
Spectrum 48K Plus
Mensajes: 36
Registrado: 19 Ago 2013, 22:00
Sistema Favorito: Commodore Amiga
primer_sistema: Spectrum 16Kb/48Kb
Ubicación: Tenerife
Gracias recibidas: 1 vez

Re: BattleShips-1K para ZX-81

Mensajepor rgrocha » 30 May 2014, 00:27

Precisamente hoy habia sacado el ZX81 para ver como iba de salud... Y con esto ahora ya tengo entretenimiento para el fin de semana :-D

GRACIAS!!

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: BattleShips-1K para ZX-81

Mensajepor Hark0 » 30 May 2014, 07:20

Fantástico post!!!

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

Avatar de Usuario
UFO
Atari 1040 STf
Atari 1040 STf
Mensajes: 803
Registrado: 19 Feb 2010, 15:16
Sistema Favorito: PC
primer_sistema: MSX
consola_favorita: Sega Genesis/Megadrive
Primera consola: TV Games/Pong Clone
Gracias dadas: 43 veces
Gracias recibidas: 4 veces

Re: BattleShips-1K para ZX-81

Mensajepor UFO » 30 May 2014, 09:38

Esto es genial, vaya! Enhorabuena! :D
-

Avatar de Usuario
radastan
Amiga 2500
Amiga 2500
Mensajes: 4542
Registrado: 11 Jun 2007, 19:29
Sistema Favorito: Spectrum 16Kb/48Kb
primer_sistema: Spectrum 16Kb/48Kb
consola_favorita: Sega Genesis/Megadrive
Primera consola: TV Games/Pong Clone
Ubicación: Córdoba
Gracias dadas: 9 veces
Gracias recibidas: 40 veces
Contactar:

Re: BattleShips-1K para ZX-81

Mensajepor radastan » 31 May 2014, 10:57

Con cosas así entiendo como el zx81, con un miserable kb, revoluciono la informática.
Yo tengo una máquina del tiempo, se llama ZX Spectrum, siempre me devuelve a los buenos momentos.
(\.../) (\.../) (\.../) (\.../)
( *.*) ('.'= ) ('.'= ) ('.'= )
(")_(") (")_(") (")_(") (")_(")
╔═══╦═══╦═══╦══╦══╗
║╔═╗║╔═╗║╔═╗╠╣╠╩╣╠╝
║║─║║╚══╣║─╚╝║║─║║
║╚═╝╠══╗║║─╔╗║║─║║
║╔═╗║╚═╝║╚═╝╠╣╠╦╣╠╗
╚╝─╚╩═══╩═══╩══╩══╝

Luna
Amiga 1200
Amiga 1200
Mensajes: 1974
Registrado: 01 Jun 2013, 16:21
Sistema Favorito: PC
primer_sistema: ZX81
consola_favorita: Sega Saturn
Primera consola: Atari 2600
Ubicación: Republica de catalunya
Gracias dadas: 30 veces
Gracias recibidas: 29 veces
Contactar:

Re: BattleShips-1K para ZX-81

Mensajepor Luna » 31 May 2014, 17:45

Imagen

Gracias...

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: BattleShips-1K para ZX-81

Mensajepor dancresp » 31 May 2014, 20:57

Bueno, pues parece que el juego ha gustado, lo cual se agradece... :oops:

Todos estos proyectos en BASIC son un "rompecocos" brutal, y aquí está la gracia. #-o

El haber conseguido programar en 1K un "Sudoku" con 20 líneas de BASIC (¿récord Guinness?), un "Light Out" con 10 niveles predefinidos, el del laberinto con un mapa de 9x9 posiciones, el buscaminas y ahora el de los barquitos, te da una sensación al acabarlos de "lo conseguí" muy gratificante, y difícil de explicar.

Y no os cuento el ensamblador y, muy especialmente, cuando hice mi primer bucle "DO LOOP" con el "FORTH-1K".

Mi primer sistema fue éste y aunque tengo la ampliación de 16KB, el programarlo con 1K le da un "algo" único, y para cosas más "profesionales" tengo mis queridos MSX, que también tienen "su que". Solo he de ver el "Nuclear Invaders", el "Star Wars" o el "Jawbreaker" para asumir de lo que son capaces...

Fin del ladrillo, pero habrá más... :-ss
Buscando la IP de la W.O.P.R.

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: BattleShips-1K para ZX-81

Mensajepor zitror » 01 Jun 2014, 23:31

Esto merece ser twiteado @Dancresp =D>
(C) 1.982 Sinclair Research Ltd

La buhardilla de Zitror

Avatar de Usuario
bitvision
Dragon 32
Dragon 32
Mensajes: 23
Registrado: 15 Mar 2014, 02:21
Sistema Favorito: MSX
primer_sistema: MSX
consola_favorita: Nintendo SNES
Primera consola: Nintendo SNES
Ubicación: Farnborough, Hampshire, UK
Gracias recibidas: 1 vez

Re: BattleShips-1K para ZX-81

Mensajepor bitvision » 21 Jun 2014, 10:32

Se sale! Enhorabuena!

Avatar de Usuario
bitvision
Dragon 32
Dragon 32
Mensajes: 23
Registrado: 15 Mar 2014, 02:21
Sistema Favorito: MSX
primer_sistema: MSX
consola_favorita: Nintendo SNES
Primera consola: Nintendo SNES
Ubicación: Farnborough, Hampshire, UK
Gracias recibidas: 1 vez

Re: BattleShips-1K para ZX-81

Mensajepor bitvision » 21 Jun 2014, 10:32

Se sale! Enhorabuena!


Volver a “Programación”

¿Quién está conectado?

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