EL JUEGO
Pipe Mania es un videojuego de puzzle desarrollado en 1989 por The Assembly Line para Amiga. Posteriormente LucasFilm Games hizo versiones para otras máquinas bajo el nombre de Pipe Dream.
El título está protagonizado por un fontanero, Alfonzo, cuyo objetivo es encajar piezas de tubería que aparecen aleatoriamente en una matriz en la que hay un grifo del que sale agua.
Se debe estar pendiente de dos marcadores que realizan una cuenta atrás:
- “T”: Indica el tiempo que queda antes que el agua empiece a recorrer las tuberías.
- “D”: Indica el tiempo que queda para terminar el nivel. Cada unidad corresponde a un bloque.
Poner un bloque de tuberías en una casilla ocupada nos bloqueará durante unos instantes.
A partir de ciertos niveles aparecen bloques con una llave inglesa o segmentos de tubería, que no se pueden ocupar.
En la pantalla de presentación podemos indicar el nivel, entre 1 y 9, en el que empezar la partida.
Esta versión sigue exactamente la misma mecánica, pero se han eliminado las fases de bonus y ciertos tipos de bloques.
Controles:
Controla el cursor con “Q” – “A” – “O” – “P” y pulsa “Espacio” para colocar un segmento de tuberías.
Descargar juego en formato "TAP":
BLOQUES
Se ha dividido el listado en 9 bloques:
- Declaración de las matrices e inicio del juego.
- Bucle principal de desarrollo.
- Pasar el Nivel
- Rutinas varias.
- Final de la partida.
- Presentación e inicio de la partida.
- Preparar y mostrar la zona de juego.
- Cargar UDG .
- DATA con los UDG del juego y valores de matrices.
COMO FUNCIONA
Todo el programa ocupa 91 líneas.
10 - Definimos las matrices del juego.
30 – Salto a la subrutina redefine los caracteres y define variables globales.
100 – Inicio del bucle principal. Si el cursor está bloqueado saltá a la línea 160.
105 – Coger la tecla pulsada. Si no se ha pulsado ninguna tecla salta a 160.
115 – Bloque que mueve el cursor en función de la tecla pulsada.
135 – Si no se pulsa “Espacio” salta a 160.
140 – Comprueba si la casilla está ocupada por un bloque especial, saltando a 160 si lo está.
145 – Si está ocupada por una tubería pone el contador “N” a 10 y nos bloqueará.
150 – Bloque que comprueba que por el bloque no pase agua.
155 – Colocar el bloque en la posición indicada, actualizando el cursor y la fila de los siguientes bloques.
160 – Descuenta el tiempo del indicador “T”. Si todavía queda salta a 185.
165 – Contador que controla el avance del agua por las tuberías. Si no debe avanzar salta a 185.
170 – Bloque que controla el avance del agua por las tuberías. Si no puede, pone “D=-9” para romper el REPEAT.
175 – Descuenta el contador “D” y comprueba el tipo de tubería en el que está el agua.
180 – Cambia el gráfico de la tubería y le asigna la dirección correspondiente.
185 – Si todavía queda tiempo en el contador “D” y el agua circula bien por la tubería vuelve al REPEAT de la línea 100.
200 – Si “D=-9” salta a 1900 y finaliza la partida, sino es que se ha superado el nivel.
205 – Bloque que acaba de rellenar de agua todo el circuito de tuberías montado.
220 – Actualiza los puntos, incrementa el nivel y salta a 2100 para montar un nivel nuevo.
1000 – Rutina que coloca un bloque en una posición determinada.
1100 – Rutina que selecciona aleatoriamente un nuevo bloque para salir en las siguientes tiradas.
1200 – Rutina que muestra los próximos cinco bloques que han de salir.
1300 – Pone el cursor en la casilla seleccionada.
1350 – Quita el cursor de la casilla seleccionada.
1400 – Muestra el marcador de 8 dígitos con los puntos o el récord.
1900 – Finaliza la partida, actualizando el marcador y realizando una pausa antes de saltar a la presentación.
2000 – Pantalla inicial del juego.
2065 – Se espera que se pulse una tecla. Si es entre “1” y “9” se coge como nivel inicial y sino empieza la partida.
2100 – Inicializar variables y determina la dificultad del nivel.
2105 – Dibuja la zona de juego.
2115 – Calcula los siguientes cinco bloques que saldrán.
2120 – Inicializa la posición de las distintas casillas.
2130 – Calcula la posición de la casilla inicial y guarda en “W” la dirección de la VRAM de la primera posición del agua.
2135 – Calcula y coloca el cursor.
2140 – A partir de cierto nivel se colocan bloques con la llave inglesa, alejadas 3 posiciones de la casilla inicial.
3000 – Selección de colores, borrar de pantalla, ocultar cursor y ocultar el “CAPS” superior.
3005 – Lectura de los DATA de los UDG.
3010 – Montar matrices con tiras de caracteres.
3020 – Leer los DATA con las direcciones del agua y sus incrementos.
3025 – Carga una matriz con strings numerados de “01” a “25” y usado por los marcadores. Es más rápido así.
9000 – DATA con los gráficos de los UDG.
9500 – DATA con los distintas tipos de bloque.
9600 – DATA con las direcciones del agua según el tipo de tubería.
9700 – DATA usado para cambiar el valor de “W” al apuntar a la VRAM.
EL LISTADO
Código: Seleccionar todo
' Inicializar Matrices e Inicio Juego
10 DIMT(10,7),B$(12),S$(4),M$(25),U$(11),J(4)
30 GOSUB3000:GOTO2000
' Lectura del Teclado
100 REPEAT:IFNTHENN=N-1:GOTO160
105 K=PEEK(520):IFK=56THEN160
115 IFK=157THENIFX<10THENGOSUB1350:X=X+1:GOSUB1300
120 IFK=149THENIFX>1THENGOSUB1350:X=X-1:GOSUB1300
125 IFK=174THENIFY<7THENGOSUB1350:Y=Y+1:GOSUB1300
130 IFK=177THENIFY>1THENGOSUB1350:Y=Y-1:GOSUB1300
' ¿Se pulsa Disparo?
135 IFK<>132THEN160
140 F=T(X,Y):IFF>7THEN160
145 A=X:B=Y:I=X*3+4:K=Y*3:IFFTHENN=10:SHOOT
' ¿Hay Agua en la Posición Seleccionada?
150 IFSCRN(I+1,K)>114ORSCRN(I+1,K+2)>114THEN160
151 IFSCRN(I,K+1)>114ORSCRN(I+2,K+1)>114THEN160
' Colocar el Bloque
155 C=VAL(RIGHT$(A$,1)):GOSUB1000:GOSUB1300:GOSUB1100:GOSUB1200
' Descontar Tiempo
160 IFH>.05THENH=H-.05:PLOT3,18,M$(H):GOTO185
' Delay Avance Agua
165 R=R-1:IFRTHEN185
' ¿La Tubería esta Bien Encajada?
170 R=10:F=PEEK(W)-103:IFF<1THEND=-9:GOTO185
' Descontar Distancia
175 PLOT36,0,M$(D):D=D-.34:IFF>11THENF=F-11
' Cambiar gráfico a Tubería con Agua
180 POKEW,F+114:O=VAL(MID$(U$(F),O,1)):W=W+J(O):S=S+5
' Volver a 100 si Sigue el Juego
185 UNTILD<0
' Pasar Nivel
200 IFD=-9THEN1900ELSEPING:PING
205 F=PEEK(W)-103:IFF<1THEN220
210 IFF>11THENF=F-11
215 POKEW,F+114:O=VAL(MID$(U$(F),O,1)):W=W+J(O):S=S+5:GOTO205
220 PING:GOSUB1400:WAIT500:L=L+1:GOTO2100
' Rutinas Varias
1000 T(A,B)=C:A=A*3+4:B=B*3
1005 PLOTA,B,LEFT$(B$(C),3):PLOTA,B+1,MID$(B$(C),4,3)
1010 PLOTA,B+2,RIGHT$(B$(C),3):RETURN
1100 I=INT(RND(1)*7)+1:IFI=I1THEN1100
1105 I1=I:A$=RIGHT$(STR$(I),1)+A$:IFLEN(A$)>5THENA$=LEFT$(A$,5)
1110 RETURN
1200 FORF=1TO5:A=2:B=F*3-1:C=VAL(MID$(A$,F,1)):GOSUB1005:NEXT:RETURN
1300 A=X*3+4:B=Y*3:PLOTA,B,"^":PLOTA+2,B,"_":PLOTA,B+2,"_":PLOTA+2,B+2,"^"
1305 RETURN
1350 A=X*3+4:B=Y*3:PLOTA,B,"a":PLOTA+2,B,"c":PLOTA,B+2,"e":PLOTA+2,B+2,"g"
1355 RETURN
1400 A=11:B=S
1405 PLOTA,0,RIGHT$("0000000"+MID$(STR$(B),2),7):RETURN
' Fin del Juego
1900 EXPLODE:GOSUB1400:WAIT600:GETA$:IFS>GTHENG=S
' Pantalla de Presentación
2000 L=1:S=0:CLS:PLOT4,1,"hqj n hqjhqm hljhqjhji n hqj"
2010 PLOT4,2,"lqp i lqplm kqm rrrlqlrrr i lql"
2015 PLOT4,3,"o o o nqm oroo oonp o o o"
2020 PLOT4,5,"kqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqm"
2030 PLOT8,7,CHR$(6)+"(C) SCAINET SOFT, 2015"
2035 PLOT10,11,"CONTROLS: LEFT = O":PLOT20,12,"RIGHT = P"
2040 PLOT20,13,"UP = Q":PLOT20,14,"DOWN = A":PLOT20,15,"FIRE =SPC"
2045 PLOT13,18,CHR$(7)+"s||||||||||u":PLOT13,19,CHR$(7)+"} LEVEL: 1 }"
2050 PLOT13,20,CHR$(7)+"y||||||||||{":PLOT9,23,"hqqqqqqqqqqqqqqqqqqqqj"
2055 PLOT9,24,"r PRESS KEY TO START r":PLOT9,25,"nqqqqqqqqqqqqqqqqqqqqp"
2065 GETA$:IFA$>="1"ANDA$<="9"THENPLOT23,19,A$:L=VAL(A$):GOTO2065
2070 CLS:PLOT1,0,CHR$(7)+"L:"+M$(L)+" P1:00000000 HI: 0 D:"
2075 A=24:B=G:GOSUB1405:FORF=2TO16:PLOT1,F,CHR$(6)+" "+CHR$(3):NEXT
' Calcular y Mostrar el Nivel
2100 N=0:R=10:H=21-L:IFH<15THENH=15
2101 D=14+L:IFD>25THEND=25
2102 PLOT4,0,RIGHT$("0"+MID$(STR$(L),2),2):PLOT36,0,M$(D)
2105 PLOT6,2,S$(4):PLOT6,24,S$(4):PLOT1,18,CHR$(7)+"T"+M$(H)+CHR$(3)
2110 FORF=3TO21STEP3:PLOT6,F,S$(1):PLOT6,F+1,S$(2):PLOT6,F+2,S$(3):NEXT
2115 A$="":FORF=1TO5:GOSUB1100:NEXT:GOSUB1200
2120 FORF=1TO10:FORI=1TO7:T(F,I)=0:NEXTI,F:O=INT(RND(1)*4)+1
2130 X1=INT(RND(1)*8)+2:Y1=INT(RND(1)*5)+2:W=48085+Y1*120+X1*3+(J(O)*2)
2135 A=X1:B=Y1:C=O+8:GOSUB1000:X=X1+1:Y=Y1:GOSUB1300:IFL<6THEN100
2140 K=L-5:IFK>7THENK=7
2141 C=8:FORF=1TOK:GOSUB1500:GOSUB1000:NEXT:IFL<9THEN100
2145 K=L-8:IFK>7THENK=7
2146 FORF=1TOK:GOSUB1500:T(A,B)=8:A=A*3+4:B=B*3:C=INT(RND(1)*7)+1:GOSUB1005
2147 NEXT:GOTO100
' Lectura de UDG e Inicializar Matrices
3000 CLS:INK3:PAPER4:POKE#BBA3,0:POKE#26A,10:G=0:PLOT16,12,"WAIT ..."
3005 FORF=46808TO47087:READD:POKEF,D:NEXT:FORF=1TO12:READB$(F):NEXT
3010 FORF=1TO10:S$(1)=S$(1)+"abc":S$(2)=S$(2)+"d d":S$(3)=S$(3)+"efg":NEXT
3015 FORF=1TO3:S$(F)="\"+S$(F)+"\":NEXT:FORF=1TO8:S$(4)=S$(4)+"]]]]":NEXT
3020 FORF=1TO11:READU$(F):NEXT:FORF=1TO4:READJ(F):NEXT
3025 FORF=0TO25:M$(F)=RIGHT$("0"+MID$(STR$(F),2),2):NEXT
3030 RETURN
' Gráficos del Juego
9000 DATA0,0,28,16,28,4,28,0,54,54,54,54,54,54,54,54,0,63,21,21,42,42,63,0
9005 DATA0,22,6,12,12,24,26,0,0,26,24,12,12,6,22,0,14,15,28,28,15,14,14,4
9010 DATA0,31,16,16,19,18,18,18,0,63,0,0,63,0,0,0,0,62,2,2,50,18,18,18
9015 DATA18,18,18,18,18,18,18,18,18,18,18,19,16,16,31,0,0,0,0,63,0,0,63,0
9020 DATA18,18,18,50,2,2,62,0,0,0,15,21,26,21,26,22,63,22,26,22,26,22,26,22
9025 DATA0,0,60,22,42,54,26,22,0,32,63,53,42,63,32,0,26,22,59,21,42,55,26,22
9030 DATA0,1,63,21,43,63,1,0,26,22,27,23,26,15,0,0,26,22,26,22,26,22,26,63
9035 DATA26,22,42,22,42,60,0,0,0,0,63,21,42,63,0,0,26,22,26,22,26,22,26,22
9040 DATA0,0,15,31,31,31,30,30,63,30,30,30,30,30,30,30,0,0,60,62,62,62,30,30
9045 DATA0,32,63,63,63,63,32,0,30,30,63,63,63,63,30,30,0,1,63,63,63,63,1,0
9050 DATA30,30,31,31,31,15,0,0,30,30,30,30,30,30,30,63,30,30,62,62,62,60,0,0
9055 DATA0,0,63,63,63,63,0,0,30,30,30,30,30,30,30,30
' Formas de los Bloques
9500 DATA"abcdhmeog","abckjdeog","aickpdefg","aicdnmefg"
9505 DATA"aicdrdeog","abckqmefg","aicklmeog","abcd`defg"
9510 DATA"atcd[defg","abcd[xefg","abcd[dezg","abcv[defg"
' Cambios de Dirección de las Tuberias
9600 DATA"2003","1030","4300","0204","1234","0204"
9605 DATA"0021","1030","0140","0204","1030"
' Cambios al Explorar VRAM
9700 DATA-40,1,40,-1
APUNTES FINALES
Pensando en mi próximo proyecto 1K para el ZX-81 me vino, no se como, este juego a la cabeza y buscando información por internet me animé a realizar una primera versión para MSX. Problemas de tiempo y la facilidad de usar el EUPHORIC de MS-DOS en mi portátil me animaron a adaptarlo al ORIC, comprobando previamente que no existe ninguna versión conocida.
En cinco días he dejado esta versión lista, prescindiendo de ciertos niveles y bloques que aparecen en la versión original, basándome gráficamente en la versión de Spectrum.
Afortunadamente este emulador permite, pulsando “F3”, mapear el teclado del ORIC con las teclas del PC lo que facilita mucho la introducción del programa. Desde el emulador he generado el TAP y desde el “Oricutron” de Windows he generado el listado en un fichero de texto que he usado para depurar el código fuente.
La verdad es que he quedado muy satisfecho ya que tanto el funcionamiento como el rendimiento es perfecto, y se deja jugar perfectamente. El sistema para ir incrementando la dificultad me ha dado más de un dolor de cabeza porque el juego ha de ser difícil pero posible.
Las cosillas de la versión ORIC
Como siempre que se programa en el ORIC, los gráficos se han tenido que rediseñar ya que en lugar de la habitual matriz de 8x8 pixels pasamos a una de 8x6.
Como el ORIC tiene un modo texto de 26 filas y 40 columnas, la zona de juego tiene las dimensiones de la versión original de Amiga 500 de 7 filas x 10 columnas en lugar de los 7x9 de la versión Spectrum.
Me habría gustado lucirme más con el color de la pantalla, pero el “peculiar” sistema del ORIC no me lo ha permitido. Consultado con el diseñador gráfico de mi empresa, hemos creído que era la mejor solución. Muy a lo MSX... azul y amarillo.
Para el control del cursor se lee el teclado mediante un “PEEK 520” y así se evitan problemas con las mayúsculas/minúsculas y te aseguras que siempre lea la última tecla pulsada, accediendo al buffer del teclado.
Y para el sonido, una vez más he tirado de los predefinidos por el ORIC demostrando mi incapacidad en este campo...
Y el agua fluye...
La principal y casi única dificultad del proyecto a consistido en hacer circular el agua por la tubería, y aunque en un principio parecía un tema bastante complejo, después de algún paseo con “brain-storming” incluido, he encontrado una solución muy sencilla y rápida.
1. Disponemos de 7 tipos de bloques distintos para montar nuestro circuito.
2. Cada uno de estos 7 bloques usan algunos de los 11 gráficos distintos de tubería, numerados de 97 a 104.
3. El agua puede tener 4 posibles direcciones, numeradas siguiendo el sentido de las agujas del reloj.
4. Cargamos la matriz “U$” con los valores DATA de las líneas 9600 y 9605. Cada uno de estos valores contiene cuatro números. La posición indica la dirección por la que entra el agua y el valor de esa posición indica la nueva dirección que ha de tomar el agua. Si el valor es 0 quiere decir que ha entrado por una dirección incorrecta y finaliza la partida.
5. Por ejemplo, el valor U$ del segmento de tubería 3 (codo inferior/izquierda) es “4300”. Así, si entra agua sube y entra por debajo (dirección 1) se cambia a izquierda (dirección 4). Si entra avanza hacia la derecha (dirección 2) se cambia a bajar (dirección 3). Pero si el agua viene desde la arriba o desde la izquierda el valor es “0” y finaliza la partida.
6. Al iniciar un nivel se calcula la posición inicial del bloque de salida y en la variable “W” nos guardamos la dirección de memoria de vídeo VRAM por donde empezará a circular el agua y en la variable “O” su dirección (1, 2, 3 ó 4).
7. Cuando el agua empieza a circular miramos el gráfico correspondiente a ese trozo de tubería y cogemos su código (entre 1 y 11) y en función de la dirección de entrada del agua (1 a 4), calculamos el cambio de dirección según la matriz guardada en “U$” y actualizamos la posición en la VRAM a la que apunta la variable “W” según los valores de la matriz “J”. Esta matriz contiene 4 valores: -40, 1, 40 y –1 y se suman a “W” en función de la nueva dirección para que apunte a la dirección de la VRAM correcta para calcular el siguiente trozo de tubería.
8. A continuación cambiamos el CHAR de la tubería por su correspondiente con agua, mediante un POKE. Si el gráfico de la posición indicada por “W” no corresponde al de una tubería, con agua o sin, finaliza la partida. He usado un POKE porque es más rápido y fácil de controlar (solo uso una variable) que haciéndolo mediante un PLOT y dos variables.
Todo esto, que parece muy liado, se resuelve durante la partida con 3 líneas de código, la 170, 175 y 180. Así de sencillo.
Al completar el nivel se realiza el mismo proceso para calcular el tramo construido correcto, con una copia del código anterior y alguna simple modificación, en las líneas 205, 210 y 215.
Pues nada más, solo me queda esperar que os guste, y ojito... que engancha lo suyo...
Os invito a probarlo.