viernes, 19 de octubre de 2012

UCBLogo: usando Logo para escribir en Logo


LOGO, en UCBLogo, no permite trabajar con imágenes, por lo que los dibujos los hemos de hacer también mediante programación. Se me ocurrió, sin embargo, que podríamos usar el propio UCBLogo y la interacción con el ratón para poder hacer una sencilla aplicación que permitiera dibujar con el ratón y que el resultado quedara guardado para otras aplicaciones. Para ello sencillamente habría que transformar las operaciones del ratón en código en LOGO y poder escribirlo a un fichero. Bueno, pues esto es lo que hace este sencillo programa.

Cómo funciona el programa: el programa nos pregunta al iniciar el nombre que vamos a dar a un fichero, lo crea y hace que la salida de escritura (la que se usa con el comando print que por defecto sale en la parte inferior en blanco de la pantalla) sea el propio fichero. Para ello usamos estos comandos:

print "Escribe_el_nombre_del_fichero
make "fichero readword  ;readword lee una palabra
openwrite fichero  ;abrimos el fichero para escritura
setwrite fichero   ;hacemos que el comando print escriba en el fichero

Veamos ahora un ejemplo visual de un dibujo en pantalla y el código que genera en el fichero:



Salida del programa en el fichero hola:

pendown
setxy 93+cx 90+cy
pendown
setxy 125+cx -4+cy
pendown
setxy -1+cx 0+cy
penup
setxy -39+cx -19+cy
pendown
setxy -49+cx 53+cy
pendown
setxy -130+cx 24+cy
pendown
setxy -42+cx -19+cy
penup
setxy -10+cx 31+cy
pendown
setxy -14+cx 88+cy
pendown
setxy 12+cx 95+cy
penup
setxy 12+cx 95+cy

Como vemos tenemos que escribir estas líneas. ¿Cómo lo hacemos? Concatenando palabras con el comando word:

make "w1 "setxy| |  

define una variable de nombre w1 que vale “setxy “, pues los caracteres | | sirven para poner un espacio (el espacio va entre las líneas verticales). A continuación hacemos:

make "rx first mousepos
make "w2 word w1 rx

que hace que la nueva variable w2 valga lo que valía w1 con el añadido de rx. Y así sucesivamente vamos construyendo todo el renglón añadiendo términos hasta llegar a la variable w5 que es la concatenación de todas ellas:

make "w3 word w2 "+cx| |
make "w4 word w3 ry
make "w5 word w4 "+cy| |
print "pendown
print w5

El programa hace uso de los dos botones del ratón y escribe código parecido pero diferente para cada uno de ellos. También se usa una variable puedopulsar (ya explicada en el videojuego captura la bola) para garantizar que sólo se escriba una vez por pulsación del botón del ratón.

Código del programa

;
; Raultecnologia
; Este sencillo programa nos permite realizar un dibujo sencillo con el raton
; que genera en un fichero el codigo en LOGO para el programa UCBLogo que
; nos permite dibujar dicho dibujo.
; Al hacer uso de las variables "cx" y "cy" sumadas a las coordenadas x,y,
; disponemos de un metodo para introducir nuestro dibujo en cualquier programa
; del UCBLogo
; Con el boton izquierdo del raton dibujamos linea y con el derecho vamos a otro
; punto sin dibujar
; La tecla "q" acaba el dibujo
;


showturtle
to inicio
print "Escribe_el_nombre_del_fichero
make "fichero readword
openwrite fichero
setwrite fichero
make "puedopulsar 1
make "tecla "p
penup
raton
end

to raton
if keyp [make "tecla rc]
make "rx first mousepos
make "ry last mousepos
if button = 0 [make "puedopulsar 1]
if puedopulsar = 1 [if button = 1 [make "puedopulsar 0 hideturtle pendown~
 setxy rx ry make "w1 "setxy| | make "w2 word w1 rx make "w3 word w2 "+cx| |~
 make "w4 word w3 ry make "w5 word w4 "+cy| | print "pendown print w5]]
if puedopulsar = 1 [if button = 2 [make "puedopulsar 0 showturtle penup~
 setxy rx ry make "w1 "setxy| | make "w2 word w1 rx make "w3 word w2 "+cx| |~
 make "w4 word w3 ry make "w5 word w4 "+cy| | print "penup print w5]]
if tecla = "q [close fichero]
raton
end

UCBLogo: videojuego del tiro parabólico


Este videojuego fue uno de los primeros que hice (y versionado posteriormente con una segunda versión en la que incluí la selección de dibujos hechos por los alumnos). El juego se trata de manejar un disparador al que podemos cambiar la inclinación de ángulo y la fuerza del mismo con el objetivo de que el proyectil alcance a un tanque.



Comentario: el videojuego hace uso de las ecuaciones del tiro parabólico, que serían:

x = x0 + v0x·t
y = y0 + v0y·t -½g·t2

que en el programa toman la forma de :

make "x -260+((v0x*tiempo)/100)
make "y -130+(((v0y*tiempo)-(0.5*9.8*tiempo*tiempo))/100)

A estas alturas supongo que todo el código sería entendible.

Código del juego

;
; Juego del tiro parabolico
; Raultecnologia
; ejemplo de aplicacion de programacion en LOGO con el programa UCBLogo
; para empezar el juego teclea el procedimiento inicio
;

; en primer lugar definimos unas cuestiones de inicio: la información en pantalla
;
make "intentos 0
make "dianas 0

to inicio
clearscreen
setpencolor 7
tanque
penup
showturtle
setxy -80 180
label "Disparo_Recarga_teclas_m_n
setxy 150 150
label "Numero_de_intentos
setxy 150 130
label intentos
setxy 150 100
label "Numero_de_aciertos
setxy 150 80
label dianas
setxy -300 150
label "Fuerza_teclas_k_l
make "grados 45
make "fuerza 500
make "tiempo 0
setxy -300 130
label fuerza
setxy -300 100
label "Inclinacion_teclas_i_o
setxy -300 80
label grados
rt grados
setxy -260 -130
pendown
parabola
end

;
; el procedimiento tanque sencillmente dibuja el tanque en un lugar aleatorio
;
to tanque
penup
make "xtanque random 200
setxy xtanque -130
pendown
fd 5 rt 90 fd 20 rt 90 fd 5 rt 90 fd 20 rt 180
penup
fd 8 lt 90 fd 5
pendown
fd 5 rt 90 fd 10 rt 90 fd 5
penup
back 2 rt 90 fd 10
pendown
fd 12 rt 90 fd 2 rt 90 fd 12 lt 90
end

;
; el procedimiento parabola describe las condiciones de velocidad inicial y grados del tiro
;
to parabola
penup
make "var1 rc
if var1 = "i [left 1 make "grados grados+1 setxy -300 80 label grados setxy -260 -130]
if var1 = "o [rt 1 make "grados grados-1 setxy -300 80 label grados setxy -260 -130]
if var1 = "l [make "fuerza fuerza+10 setxy -300 130 label fuerza setxy -260 -130]
if var1 = "k [make "fuerza fuerza-10 setxy -300 130 label fuerza setxy -260 -130]
if var1 = "m [make "v0x fuerza*cos grados make "v0y fuerza*sin grados hideturtle setpencolor 6 disparo v0x v0y]
parabola
end

;
; el procedimiento disparo dibuja la trayectoria parabolica del tiro
;
to disparo :v0x :v0y
pendown
make "x -260+((v0x*tiempo)/100)
make "y -130+(((v0y*tiempo)-(0.5*9.8*tiempo*tiempo))/100)
setxy x y
arc 360 4
make "tiempo tiempo+1
wait 1
penerase
arc 360 4
penpaint
if y < -130 [explosion1 acierto xtanque x]
disparo v0x v0y
end

;
; el procedimiento acierto define que ocurre cuando el proyectil llega al suelo
;
to acierto :xtanque :xmisil
make "intentos intentos+1
make "diferencia int xtanque-xmisil
make "intdiferencia diferencia*diferencia
if intdiferencia < 1000 [if diferencia < 0 [explosion2 make "dianas dianas+1]]
recarga
end

;
; el procedimiento recarga sirve para reiniciar el siguiente tiro
;
to recarga
wait 5
make "var2 rc
if var2 = "n [inicio]
recarga
end

to explosion1
lt 90-grados
fd 10
back 10
rt 30
fd 8
back 8
rt 30
fd 8
back 8
lt 90
fd 8
back 8
lt 30
fd 8
back 8
rt 60
end


to explosion2
setpencolor 4
fd 25
back 25
rt 30
fd 15
back 15
rt 30
fd 15
back 15
lt 90
fd 15
back 15
lt 30
fd 15
back 15
rt 60
end

UCBLogo: videojuego del tetris


El Tetris es un videojuego clásico en el que unas piezas van descendiendo y el objetivo es hacer líneas completas.
 

Consideraciones: es importante analizar primero cómo es el Tetris para abordar su programación. Veamos primero las piezas:



Tenemos 7 piezas (las de la imagen superior en la que hemos puesto un número como identificador de la pieza que es la que usaremos para la programación) con un denominador común: todas ellas están formadas por 4 cuadrados (de ahí la palabra Tetris, de cuatro). Además, las piezas se pueden girar y desplazar lateralmente a voluntad y van descendiendo lentamente. El “campo de juego” es un rectángulo de base 10 cuadraditos y altura 20, por lo que parece adecuado volver a usar una matriz o tabla para realizar los cálculos del programa.

1.- Piezas como conjunto de 4 cuadrados: como las 7 piezas están hechas de 4 cuadrados, vamos a entender que cada pieza es un conjunto de 4 cuadrados. Las coordenadas de cada cuadrado serán x1,y1 para el primero, x2, y2 para el segundo y así x3,y3 y x4,y4 para el 3º y 4º respectivamente. En realidad vamos a manejar las coordenadas del primer cuadrado y el resto se calcularán de manera relativa para el resto. Veámoslo para la pieza llamada T:


Si las coordenadas del primer cuadrado son x1,y1, las del resto de cuadraditos, relativas a estas, serían las siguientes:

x2 = x1+1, y2 = y1
x3 = x1+2, y2 = y1
x4 = x1+1, y4 = y1+1

que en código es:

make "x2 x1+1 make "x3 x1+2 make "x4 x1+1 make "y2 y1 make "y3 y1 make "y4 y1+1

Pues bien, esto está hecho para todas las piezas en el procedimiento eligepieza, donde de paso se elige el color con la variable c:

make "pieza random 7
;
; pieza 0 es la 0, 1 la I, 2 la L, 3, la J, 4 la T, 5 la S y 6 la Z
;
if [pieza=0][make "c 1 make "x2 x1+1 make "x3 x1 make "x4 x1+1 make "y2 y1 make "y3 y1+1 make "y4 y1+1]
if [pieza=1][make "c 4 make "x2 x1 make "x3 x1 make "x4 x1 make "y2 y1+1 make "y3 y1+2 make "y4 y1+3]
if [pieza=2][make "c 5 make "x2 x1 make "x3 x1 make "x4 x1+1 make "y2 y1+1 make "y3 y1+2 make "y4 y1]
if [pieza=3][make "c 7 make "x2 x1+1 make "x3 x1+1 make "x4 x1+1 make "y2 y1 make "y3 y1+1 make "y4 y1+2]
if [pieza=4][make "c 8 make "x2 x1+1 make "x3 x1+2 make "x4 x1+1 make "y2 y1 make "y3 y1 make "y4 y1+1]
if [pieza=5][make "c 2 make "x2 x1+1 make "x3 x1+1 make "x4 x1+2 make "y2 y1 make "y3 y1+1 make "y4 y1+1]
if [pieza=6][make "c 3 make "x2 x1+1 make "x3 x1-1 make "x4 x1 make "y2 y1 make "y3 y1+1 make "y4 y1+1]

2.- Los giros como transformaciones de coordenadas de los 4 cuadrados: una vez establecida cada pieza como un conjunto de 4 cuadrados, podemos aplicar la misma filosofía a la hora de aplicar los giros: en vez de giros, estos serán transformaciones de coordenadas respecto a su situación anterior de tal forma que pondremos los cuadraditos en función de dónde estaban antes. Ahora bien, hay que tener en cuenta la situación de cada pieza, así que el procedimiento girar llama a uno u otro procedimiento en función de qué pieza es y de qué situación de giro lleve:

to girar
if [pieza=1][ifelse [giro=0][p1a][p1b]]
if [pieza=5][ifelse [giro=0][p5a][p5b]]
if [pieza=6][ifelse [giro=0][p6a][p6b]]
if [pieza=2][ifelse [giro=0][p2a][ifelse[giro=1][p2b][ifelse[giro=2][p2c][p2d]]]]
if [pieza=3][ifelse [giro=0][p3a][ifelse[giro=1][p3b][ifelse[giro=2][p3c][p3d]]]]
if [pieza=4][ifelse [giro=0][p4a][ifelse[giro=1][p4b][ifelse[giro=2][p4c][p4d]]]]
end

La pieza 1 sólo tiene dos posibles posiciones, de tal forma que si la variable giro vale 0 se ejecuta el procedimiento p1a y si la variable giro vale 1 entonces se ejecuta el procedimiento p1b (esto es lo que hace el comando ifelse, si se cumple la condición ejecuta la primera sentencia y si no se cumple, ejecuta la segunda), procedimientos que toman esta forma:

to p1a
make "c1 x1 make "d1 y1 make "c2 x2+1 make "d2 y2-1 make "c3 x3+2 make "d3 y3-2 make "c4 x4+3 make "d4 y4-3
choque
if [haychoque=0][make "x2 x2+1 make "y2 y2-1 make "x3 x3+2 make "y3 y3-2 make "x4 x4+3 make "y4 y4-3 make "giro 1]
end
to p1b
make "c1 x1 make "d1 y1 make "c2 x2-1 make "d2 y2+1 make "c3 x3-2 make "d3 y3+2 make "c4 x4-3 make "d4 y4+3
choque
if [haychoque=0][make "x2 x2-1 make "y2 y2+1 make "x3 x3-2 make "y3 y3+2 make "x4 x4-3 make "y4 y4+3 make "giro 0]
end

P1a y p1b establecen las nuevas coordenadas si hay posibilidad de giro, pues invocan al procedimiento choque que lo que hace es mirar si las nuevas coordenadas de giro están o no ocupadas (si están ocupadas no podrá ser realizado el giro).

Las piezas 2, 3 y 4 tienen 4 posibilidades, luego la variable giro podrá tomar 4 valores. Para ello usaremos varios ifelse anidados, tal y como se ve en el código.

Si analizamos de nuevo lo que ocurre con la pieza 4, podemos ver que durante los giros la pieza adopta estas 4 posibilidades:



Numeramos los 4 cuadraditos para cada transformación de coordenadas. El punto rojo marca la posición inicial del cuadradito 1 (el que deriva las coordenadas x1,y1). De esta forma tenemos las siguientes transformaciones:

Giro 1: x1=x1, y1=y1, x2=x2-1, y2=y2+1, x3=x3-2, y3=y3+2, x4=x4, y4=y4
Siendo giro 1 la transformación de la primera forma a la segunda forma.

Que en código toma esta expresión:

if [haychoque=0][make "x2 x2-1 make "y2 y2+1 make "x3 x3-2 make "y3 y3+2 make "giro 1]

(notando que aquellas transformaciones que quedan igual como y4=y4 no hace falta escribirlas). El resto de transformaciones se hacen igual y son las escritas en el código.

3.- Manejando dos tablas a la vez: si se mira el código, se verá que hay dos tablas, una denominada tabla y otra denominada tablacolor. La primera es para la jugabilidad general y la principal y la segunda la hice con el objetivo de poder recordar los colores cuando se hace una línea, pues los cuadraditos bajan y, como cada pieza es de un color diferente, el cuadradito que desciende debe tener el color que tenía. El contenido de tablacolor se establece cuando la pieza se detiene y hace que los cuadraditos de esa pieza queden con el color que tenían. El contenido de la tabla es la siguiente: 0 para no ocupación, 5 para las paredes, 6 para las piezas paradas.

4.- Saber si hay o no línea: el procedimiento para saber si hay o no línea es el siguiente: el procedimiento juego llama, cuando la variable contador es 0, al procedimiento bajapieza que es el encargado de bajar la pieza. El procedimiento bajapieza llama al procedimiento choque para saber si va a chocar la pieza con algo (si va a chocar la pieza con algo es que no puede bajar más y se parará). Si la pieza debe parar, entonces se invoca el procedimiento parapieza, que es el encargado de transformar la pieza en una pieza parada (valor 6 en la tabla) y llama al procedimiento lineasiono (para saber si hay o no línea). El procedimiento lineasiono comprueba si hubo o no línea (contando el número de cuadraditos de la fila) y, si la hubo, invoca al procedimiento haylinea (encargado de sumar los puntos) y al procedimiento caer (pues las línea se elimina y los cuadraditos de abajo deben caer). Como al eliminar una línea y haber cuadraditos por encima puede ser que se hagan más de una línea, el procedimiento caer llama al procedimiento caehasta. Como vemos, algo un poco complicado.


Código del juego

;
; Videojuego Tetris
; Raultecnologia
; el programa esta en LOGO para usar directamente en el UCBLogo
; para empezar el juego teclea el procedimiento inicio
;

;
; Pantalla de presentacion
;
to inicio
hideturtle
clearscreen
setpensize 1
penup
setxy -200 140
setpencolor 4
label "|Videojuego Tetris|
setxy -200 110
setpencolor 7
label "|teclas o p para mover y tecla q para rotar|
setxy -200 -20
label "|Elige 1 juego facil o 2 juego dificil|
make "tecla rc
clearscreen
setpencolor 7
if [tecla="1] [make "contadorinicio 500 comienzo]
if [tecla="2] [make "contadorinicio 200 comienzo]
inicio
end



;
; el procedimiento campo dibuja la pantalla principal
;
to campo
setpencolor 15
for [i 0 11][penup setxy i*11+11 0+11 cuadrado mdsetitem (list :i+1 1) :tabla 5]
for [j 0 25][penup setxy 0+11 j*11+11 cuadrado mdsetitem (list 1 :j+1) :tabla 5]
for [j 0 25][penup setxy 11*11+11 j*11+11 cuadrado mdsetitem (list 12 :j+1) :tabla 5]
end

;
; el procedimiento cuadrado dibuja un cuadrado
;
to cuadrado
pendown
fd 10
rt 90
fd 10
rt 90
fd 10
rt 90
fd 10
rt 90
rt 45
fd 14
back 14
rt 45
fd 10
lt 90
lt 45
fd 14
back 14
lt 45
fd 10
rt 90
penup
end


;
; procedimiento eligepieza sirve para elegir la pieza
;
to eligepieza
make "giro 0
make "pieza random 7
;make "pieza 4
make "x1 5
make "y1 25
;
; pieza 0 es la 0, 1 la I, 2 la L, 3, la J, 4 la T, 5 la S y 6 la Z
;
if [pieza=0][make "c 1 make "x2 x1+1 make "x3 x1 make "x4 x1+1 make "y2 y1 make "y3 y1+1 make "y4 y1+1]
if [pieza=1][make "c 4 make "x2 x1 make "x3 x1 make "x4 x1 make "y2 y1+1 make "y3 y1+2 make "y4 y1+3]
if [pieza=2][make "c 5 make "x2 x1 make "x3 x1 make "x4 x1+1 make "y2 y1+1 make "y3 y1+2 make "y4 y1]
if [pieza=3][make "c 7 make "x2 x1+1 make "x3 x1+1 make "x4 x1+1 make "y2 y1 make "y3 y1+1 make "y4 y1+2]
if [pieza=4][make "c 8 make "x2 x1+1 make "x3 x1+2 make "x4 x1+1 make "y2 y1 make "y3 y1 make "y4 y1+1]
if [pieza=5][make "c 2 make "x2 x1+1 make "x3 x1+1 make "x4 x1+2 make "y2 y1 make "y3 y1+1 make "y4 y1+1]
if [pieza=6][make "c 3 make "x2 x1+1 make "x3 x1-1 make "x4 x1 make "y2 y1 make "y3 y1+1 make "y4 y1+1]

make "dentro mditem (list :x1 :y1) :tabla
if [dentro>3][fin]
make "dentro mditem (list :x2 :y2) :tabla
if [dentro>3][fin]
make "dentro mditem (list :x3 :y3) :tabla
if [dentro>3][fin]
make "dentro mditem (list :x4 :y4) :tabla
if [dentro>3][fin]

end

to pintapieza
setpencolor c
penup
setxy x1*11 y1*11
cuadrado
setxy x2*11 y2*11
cuadrado
setxy x3*11 y3*11
cuadrado
setxy x4*11 y4*11
cuadrado
end

to borrapieza
penup
setpc 0
setxy x1*11 y1*11
cuadrado
setxy x2*11 y2*11
cuadrado
setxy x3*11 y3*11
cuadrado
setxy x4*11 y4*11
cuadrado
end



;
; el procedimiento comienzo establece las condiciones iniciales
;
to comienzo
clearscreen
;
; definimos una tabla llenas de ceros salvo que esté ocupada por paredes o por restos de piezas
; tambien definimos una tabla para guardar la informacion del color de las piezas
;
make "size_x 15
make "size_y 30
make "tabla (mdarray (list :size_x :size_y) 1)
for [i 1 size_x 1] [for [j 1 size_y 1] [mdsetitem (list :i :j) :tabla 0]]
make "tablacolor (mdarray (list :size_x :size_y) 1)
for [i 1 size_x 1] [for [j 1 size_y 1] [mdsetitem (list :i :j) :tablacolor 0]]
campo
penup
hideturtle
make "contador contadorinicio

make "puntos 0
make "giro 0
setpencolor 7
setxy 30 -40
label "Puntos
setxy 100 -40
label puntos
make "tecla 0
eligepieza
pintapieza
juego
end




;
; el procedimiento juego controla las condiciones del juego
;
to juego

make "contador contador-1
if keyp [make "tecla rc]
if [tecla = "o][tecla_o make "tecla 0]
if [tecla = "p][tecla_p make "tecla 0]
if [tecla = "q][copia borrapieza girar pintapieza make "tecla 0]
;if [contador=0][comprueba compruebacolor bajapieza]
if [contador=0][bajapieza]
juego
end

;
; bajapieza es el procedimiento para cuando toca bajar una linea
;
to bajapieza
make "c1 x1 make "c2 x2 make "c3 x3 make "c4 x4 make "d1 y1-1
make "d2 y2-1 make "d3 y3-1 make "d4 y4-1
choque
ifelse [haychoque=0][borrapieza make "contador contadorinicio make "y1 y1-1 make "y2 y2-1 make "y3 y3-1 make "y4 y4-1 pintapieza][parapieza]
end

;to comprueba
;penup
;setpencolor 7
;for [i 1 13][for[j 1 30] [make "dentro mditem (list :i :j) :tabla setxy -200+12*i -100+12*j label dentro]]
;end

;to compruebacolor
;penup
;setpencolor 7
;for [i 1 13][for[j 1 30] [make "dentro mditem (list :i :j) :tablacolor setxy -400+12*i -100+12*j label dentro]]
;end

;
; procedimiento que indica que la pieza ya no puede bajar
;
to parapieza
mdsetitem (list :x1 :y1) :tabla 6
mdsetitem (list :x2 :y2) :tabla 6
mdsetitem (list :x3 :y3) :tabla 6
mdsetitem (list :x4 :y4) :tabla 6
mdsetitem (list :x1 :y1) :tablacolor c
mdsetitem (list :x2 :y2) :tablacolor c
mdsetitem (list :x3 :y3) :tablacolor c
mdsetitem (list :x4 :y4) :tablacolor c
lineasiono
eligepieza
pintapieza
make "contador contadorinicio
end

;
; procedimiento para ver si hay o no una linea de tetris
;
to lineasiono
make "cuenta 0
make "hubolinea 0
for [j 2 30][make "cuenta 0 for[i 2 11][make "dentro mditem (list :i :j) :tabla if[dentro=6][make "cuenta cuenta+1] if [cuenta=10][make "ylinea j haylinea make "hubolinea 1]]]
if [hubolinea=1][caer]
if [hubolinea=1][lineasiono]
end

to caer
for [i 2 11][for[j 3 30] [make "ii i make "jj j make "dentro mditem (list :i :j) :tabla make "dentrocolor mditem (list :i :j) :tablacolor if[dentro=6][caehasta]]]
end

to caehasta
setpencolor 0 setxy ii*11 jj*11 cuadrado
setpencolor dentrocolor
mdsetitem (list :ii :jj) :tabla 0
mdsetitem (list :ii :jj) :tablacolor 0
make "k jj-1
make "dentrok mditem (list :ii :k) :tabla
while [dentrok=0][make "k k-1 make "dentrok mditem (list :ii :k) :tabla]
mdsetitem (list :ii :k+1) :tabla 6
mdsetitem (list :ii :k+1) :tablacolor dentrocolor
setxy ii*11 (k+1)*11 cuadrado
end

to haylinea
for [i 2 11][mdsetitem (list :i :ylinea) :tabla 0]
for [i 2 11][mdsetitem (list :i :ylinea) :tablacolor 0]
for [i 2 11][setpencolor 0 setxy i*11 ylinea*11 cuadrado]
penup
make "puntos puntos+10
setpencolor 7
setxy 30 -40
label "Puntos
setxy 100 -40
label puntos
end

to copia
make "c1 x1 make "c2 x2 make "c3 x3 make "c4 x4 make "d1 y1 make "d2 y2 make "d3 y3 make "d4 y4
end

to tecla_o
make "c1 x1-1 make "c2 x2-1 make "c3 x3-1 make "c4 x4-1 make "d1 y1 make "d2 y2 make "d3 y3 make "d4 y4
choque
if [haychoque=0][borrapieza make "x1 x1-1 make "x2 x2-1 make "x3 x3-1 make "x4 x4-1 pintapieza]
end

to tecla_p
make "c1 x1+1 make "c2 x2+1 make "c3 x3+1 make "c4 x4+1 make "d1 y1 make "d2 y2 make "d3 y3 make "d4 y4
choque
if [haychoque=0][borrapieza make "x1 x1+1 make "x2 x2+1 make "x3 x3+1 make "x4 x4+1 pintapieza]
end

;
; choque mira si cuando hay un cambio de posicion esta es posible
;
to choque
make "dentroa mditem (list :c1 :d1) :tabla
make "dentrob mditem (list :c2 :d2) :tabla
make "dentroc mditem (list :c3 :d3) :tabla
make "dentrod mditem (list :c4 :d4) :tabla
ifelse[dentroa>4][make "haychoque 1][ifelse[dentrob>4][make "haychoque 1][ifelse[dentroc>4][make "haychoque 1][ifelse[dentrod>4][make "haychoque 1][make "haychoque 0]]]]
end

to girar
if [pieza=1][ifelse [giro=0][p1a][p1b]]
if [pieza=5][ifelse [giro=0][p5a][p5b]]
if [pieza=6][ifelse [giro=0][p6a][p6b]]

if [pieza=2][ifelse [giro=0][p2a][ifelse[giro=1][p2b][ifelse[giro=2][p2c][p2d]]]]
if [pieza=3][ifelse [giro=0][p3a][ifelse[giro=1][p3b][ifelse[giro=2][p3c][p3d]]]]
if [pieza=4][ifelse [giro=0][p4a][ifelse[giro=1][p4b][ifelse[giro=2][p4c][p4d]]]]
end

;
; aqui vienen los procedimientos para los giros
;
to p1a
make "c1 x1 make "d1 y1 make "c2 x2+1 make "d2 y2-1 make "c3 x3+2 make "d3 y3-2 make "c4 x4+3 make "d4 y4-3
choque
if [haychoque=0][make "x2 x2+1 make "y2 y2-1 make "x3 x3+2 make "y3 y3-2 make "x4 x4+3 make "y4 y4-3 make "giro 1]
end
to p1b
make "c1 x1 make "d1 y1 make "c2 x2-1 make "d2 y2+1 make "c3 x3-2 make "d3 y3+2 make "c4 x4-3 make "d4 y4+3
choque
if [haychoque=0][make "x2 x2-1 make "y2 y2+1 make "x3 x3-2 make "y3 y3+2 make "x4 x4-3 make "y4 y4+3 make "giro 0]
end

to p5a
make "c1 x1+1 make "d1 y1 make "c2 x2 make "d2 y2+1 make "c3 x3-1 make "d3 y3 make "c4 x4-2 make "d4 y4+1
choque
if [haychoque=0][make "x1 x1+1 make "y2 y2+1 make "x3 x3-1 make "x4 x4-2 make "y4 y4+1 make "giro 1]
end
to p5b
make "c1 x1-1 make "d1 y1 make "c2 x2 make "d2 y2-1 make "c3 x3+1 make "d3 y3 make "c4 x4+2 make "d4 y4-1
choque
if[haychoque=0][make "x1 x1-1 make "y2 y2-1 make "x3 x3+1 make "x4 x4+2 make "y4 y4-1 make "giro 0]
end

to p6a
make "c1 x1 make "d1 y1+1 make "c2 x2-1 make "d2 y2+2 make "c3 x3 make "d3 y3-1 make "c4 x4-1 make "d4 y4
choque
if [haychoque=0][make "y1 y1+1 make "x2 x2-1 make "y2 y2+2 make "y3 y3-1 make "x4 x4-1 make "giro 1]
end
to p6b
make "c1 x1 make "d1 y1-1 make "c2 x2+1 make "d2 y2-2 make "c3 x3 make "d3 y3+1 make "c4 x4+1 make "d4 y4
choque
if [haychoque=0][make "y1 y1-1 make "x2 x2+1 make "y2 y2-2 make "y3 y3+1 make "x4 x4+1 make "giro 0]
end


;
; p2a, p2b, p2c y p2d son las transformaciones de coordenadas en los giros para la pieza 2
;
to p2a
make "d1 y1+1 make "c2 x2+1 make "c3 x3+2 make "d3 y3-1 make "c4 x4-1
choque
if [haychoque=0][make "y1 y1+1 make "x2 x2+1 make "x3 x3+2 make "y3 y3-1 make "x4 x4-1 make "giro 1]
end
to p2b
make "c1 x1+1 make "d1 y1-1 make "c3 x3-1 make "d3 y3+1 make "d4 y4+2
choque
if [haychoque=0][make "x1 x1+1 make "y1 y1-1 make "x3 x3-1 make "y3 y3+1 make "y4 y4+2 make "giro 2]
end
to p2c
make "c1 x1-1 make "d2 y2-1 make "c3 x3+1 make "d3 y3-2 make "c4 x4+2 make "d4 y4-1
choque
if [haychoque=0][make "x1 x1-1 make "y2 y2-1 make "x3 x3+1 make "y3 y3-2 make "x4 x4+2 make "y4 y4-1 make "giro 3]
end
to p2d
make "c2 x2-1 make "d2 y2+1 make "c3 x3-2 make "d3 y3+2 make "c4 x4-1 make "d4 y4-1
choque
if [haychoque=0][make "x2 x2-1 make "y2 y2+1 make "x3 x3-2 make "y3 y3+2 make "x4 x4-1 make "y4 y4-1 make "giro 0]
end

;
; p3a, p3b, p3c y p3d son las transformaciones de coordenadas en los giros para la pieza 3
;
to p3a
make "d1 y1+1 make "c2 x2-1 make "d3 y3-1 make "c4 x4+1 make "d4 y4-2
choque
if [haychoque=0][make "y1 y1+1 make "x2 x2-1 make "y3 y3-1 make "x4 x4+1 make "y4 y4-2 make "giro 1]
end
to p3b
make "c1 x1+1 make "d1 y1+1 make "d2 y2+2 make "c3 x3-1 make "d3 y3+1 make "c4 x4-2
choque
if [haychoque=0][make "x1 x1+1 make "y1 y1+1 make "y2 y2+2 make "x3 x3-1 make "y3 y3+1 make "x4 x4-2 make "giro 2]
end
to p3c
make "c1 x1+1 make "d1 y1-2 make "c2 x2+2 make "d2 y2-1 make "c3 x3+1 make "d4 y4+1
choque
if [haychoque=0][make "x1 x1+1 make "y1 y1-2 make "x2 x2+2 make "y2 y2-1 make "x3 x3+1 make "y4 y4+1 make "giro 3]
end
to p3d
make "c1 x1-2 make "c2 x2-1 make "d2 y2-1 make "c4 x4+1 make "d4 y4+1
choque
if [haychoque=0][make "x1 x1-2 make "x2 x2-1 make "y2 y2-1 make "x4 x4+1 make "y4 y4+1 make "giro 0]
end

;
; p4a, p4b, p4c y p4d son las transformaciones de coordenadas en los giros para la pieza 4
;
to p4a
make "c2 x2-1 make "d2 y2+1 make "c3 x3-2 make "d3 y3+2
choque
if [haychoque=0][make "x2 x2-1 make "y2 y2+1 make "x3 x3-2 make "y3 y3+2 make "giro 1]
end
to p4b
make "d1 y1+1 make "c2 x2+1 make "c3 x3+2 make "d3 y3-1 make "d4 y4-1
choque
if [haychoque=0][make "y1 y1+1 make "x2 x2+1 make "x3 x3+2 make "y3 y3-1 make "y4 y4-1 make "giro 2]
end
to p4c
make "c1 x1+1 make "d1 y1-1 make "c3 x3-1 make "d3 y3+1 make "c4 x4-1 make "d4 y4+1
choque
if [haychoque=0][make "x1 x1+1 make "y1 y1-1 make "x3 x3-1 make "y3 y3+1 make "x4 x4-1 make "y4 y4+1 make "giro 3]
end
to p4d
make "c1 x1-1 make "d2 y2-1 make "c3 x3+1 make "d3 y3-2 make "c4 x4+1
choque
if [haychoque=0][make "x1 x1-1 make "y2 y2-1 make "x3 x3+1 make "y3 y3-2 make "x4 x4+1 make "giro 0]
end

;
; fin finaliza el juego
;
to fin
setpencolor 1
penup
setxy 0 -70
label "|FIN DE LA PARTIDA|
setxy 0 -90
label "|Pulsa una tecla para empezar|
wait 120
make "tecla rc
inicio
end