https://www.youtube.com/watch?v=Z4E-NdWWHoo


    -- funcion de retraso para hacer al programa esperar un tiempo
    function Delay(sec)
	 os.startTimer(sec)
	 while true do
	  event, param1 = os.pullEvent()
	  if event == "timer" then break end
	 end
    end
	
    --Funcion para mover 1 fila
    function mover(fila,tiempo,tablacaras1,tablacolores1)
		    -- Inicializacion de la variable local de caras del ordenador
		    local cara = "bottom"
		    -- llenamos la variable local y si viene algo no esperado activamos la cara de abajo
		    if fila >= 1 and fila <= 6 then
				    cara= tablacaras1[fila]
		    else
				    cara = "bottom"
		    end
		    -- Activamos todos los pintones en orden con el retraso seleccionado y los desactivamos
		    for v = 1,12 do
				    rs.setBundledOutput( cara, colors.combine( rs.getBundledOutput( cara ), colors[tablacolores1[v]] ) )
				    Delay(tiempo)
		    end
		    for v = 1,12 do
				    rs.setBundledOutput( cara, colors.subtract( rs.getBundledOutput( cara ), colors[tablacolores1[v]] ) )
				    Delay(tiempo)
		    end
    end
    -- Funcion para mover 2 filas a la vez
    function mover2(fila1,fila2,tiempo,tablacaras2,tablacolores2)
		    -- Inicializacion de las variable locales de las caras del ordenador
		    local cara1 = "bottom"
		    local cara2 = "bottom"
		    -- llenamos la variables locales y si viene algo no esperado seleccionamos la cara de abajo
		    if fila1 >= 1 and fila1 <= 6 then
				    cara1= tablacaras2[fila1]
		    else
				    cara1 = "bottom"
		    end
		    if fila2 >= 1 and fila2 <= 6 then
				    cara2= tablacaras2[fila2]
		    else
				    cara2 = "bottom"
		    end
		    -- Activamos todos los pintones en orden con el retraso seleccionado y los desactivamos
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.combine( rs.getBundledOutput( cara1 ), colors[tablacolores2[v]] ) )
				    rs.setBundledOutput( cara2, colors.combine( rs.getBundledOutput( cara2 ), colors[tablacolores2[v]] ) )
				    Delay(tiempo)
		    end
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.subtract( rs.getBundledOutput( cara1 ), colors[tablacolores2[v]] ) )
				    rs.setBundledOutput( cara2, colors.subtract( rs.getBundledOutput( cara2 ), colors[tablacolores2[v]] ) )
				    Delay(tiempo)
		    end
    end
    -- Funcion para mover 3 filas a la vez
    function mover3(fila1,fila2,fila3,tiempo,tablacaras3,tablacolores3)
		    -- Inicializacion de las variable locales de las caras del ordenador
		    local cara1 = "bottom"
		    local cara2 = "bottom"
		    local cara3 = "bottom"
		    -- llenamos la variables locales y si viene algo no esperado seleccionamos la cara de abajo
		    if fila1 >= 1 and fila1 <= 6 then
				    cara1= tablacaras3[fila1]
		    else
				    cara1 = "bottom"
		    end
		    if fila2 >= 1 and fila2 <= 6 then
				    cara2= tablacaras3[fila2]
		    else
				    cara2 = "bottom"
		    end
		    if fila3 >= 1 and fila3 <= 6 then
				    cara3= tablacaras3[fila3]
		    else
				    cara3 = "bottom"
		    end
		    -- Activamos todos los pintones en orden con el retraso seleccionado y los desactivamos
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.combine( rs.getBundledOutput( cara1 ), colors[tablacolores3[v]] ) )
				    rs.setBundledOutput( cara2, colors.combine( rs.getBundledOutput( cara2 ), colors[tablacolores3[v]] ) )
				    rs.setBundledOutput( cara3, colors.combine( rs.getBundledOutput( cara3 ), colors[tablacolores3[v]] ) )
				    Delay(tiempo)
		    end
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.subtract( rs.getBundledOutput( cara1 ), colors[tablacolores3[v]] ) )
				    rs.setBundledOutput( cara2, colors.subtract( rs.getBundledOutput( cara2 ), colors[tablacolores3[v]] ) )
				    rs.setBundledOutput( cara3, colors.subtract( rs.getBundledOutput( cara3 ), colors[tablacolores3[v]] ) )
				    Delay(tiempo)
		    end
    end
	
    -- Funcion para mover 4 filas a la vez
    function mover4(fila1,fila2,fila3,fila4,tiempo,tablacaras4,tablacolores4)
		    -- Inicializacion de las variable locales de las caras del ordenador
		    local cara1 = "bottom"
		    local cara2 = "bottom"
		    local cara3 = "bottom"
		    local cara4 = "bottom"
		    -- llenamos la variables locales y si viene algo no esperado seleccionamos la cara de abajo
		    if fila1 >= 1 and fila1 <= 6 then
				    cara1= tablacaras4[fila1]
		    else
				    cara1 = "bottom"
		    end
		    if fila2 >= 1 and fila2 <= 6 then
				    cara2= tablacaras4[fila2]
		    else
				    cara2 = "bottom"
		    end
		    if fila3 >= 1 and fila3 <= 6 then
				    cara3= tablacaras4[fila3]
		    else
				    cara3 = "bottom"
		    end
		    if fila4 >= 1 and fila4 <= 6 then
				    cara4= tablacaras4[fila4]
		    else
				    cara4 = "bottom"
		    end
		    -- Activamos todos los pintones en orden con el retraso seleccionado y los desactivamos
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.combine( rs.getBundledOutput( cara1 ), colors[tablacolores4[v]] ) )
				    rs.setBundledOutput( cara2, colors.combine( rs.getBundledOutput( cara2 ), colors[tablacolores4[v]] ) )
				    rs.setBundledOutput( cara3, colors.combine( rs.getBundledOutput( cara3 ), colors[tablacolores4[v]] ) )
				    rs.setBundledOutput( cara4, colors.combine( rs.getBundledOutput( cara4 ), colors[tablacolores4[v]] ) )
				    Delay(tiempo)
		    end
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.subtract( rs.getBundledOutput( cara1 ), colors[tablacolores4[v]] ) )
				    rs.setBundledOutput( cara2, colors.subtract( rs.getBundledOutput( cara2 ), colors[tablacolores4[v]] ) )
				    rs.setBundledOutput( cara3, colors.subtract( rs.getBundledOutput( cara3 ), colors[tablacolores4[v]] ) )
				    rs.setBundledOutput( cara4, colors.subtract( rs.getBundledOutput( cara4 ), colors[tablacolores4[v]] ) )
				    Delay(tiempo)
		    end
    end;
	
    -- Funcion para mover 5 filas a la vez
    function mover5(fila1,fila2,fila3,fila4,fila5,tiempo,tablacaras5,tablacolores5)
		    -- Inicializacion de las variable locales de las caras del ordenador
		    local cara1 = "bottom"
		    local cara2 = "bottom"
		    local cara3 = "bottom"
		    local cara4 = "bottom"
		    local cara5 = "bottom"
		    -- llenamos la variables locales y si viene algo no esperado seleccionamos la cara de abajo
		    if fila1 >= 1 and fila1 <= 6 then
				    cara1= tablacaras5[fila1]
		    else
				    cara1 = "bottom"
		    end
		    if fila2 >= 1 and fila2 <= 6 then
				    cara2= tablacaras5[fila2]
		    else
				    cara2 = "bottom"
		    end
		    if fila3 >= 1 and fila3 <= 6 then
				    cara3= tablacaras5[fila3]
		    else
				    cara3 = "bottom"
		    end
		    if fila4 >= 1 and fila4 <= 6 then
				    cara4= tablacaras5[fila4]
		    else
				    cara4 = "bottom"
		    end
		    if fila5 >= 1 and fila5 <= 6 then
				    cara5= tablacaras5[fila5]
		    else
				    cara5 = "bottom"
		    end
		    -- Activamos todos los pintones en orden con el retraso seleccionado y los desactivamos
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.combine( rs.getBundledOutput( cara1 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara2, colors.combine( rs.getBundledOutput( cara2 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara3, colors.combine( rs.getBundledOutput( cara3 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara4, colors.combine( rs.getBundledOutput( cara4 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara5, colors.combine( rs.getBundledOutput( cara5 ), colors[tablacolores5[v]] ) )
				    Delay(tiempo)
		    end
		    for v = 1,12 do
				    rs.setBundledOutput( cara1, colors.subtract( rs.getBundledOutput( cara1 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara2, colors.subtract( rs.getBundledOutput( cara2 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara3, colors.subtract( rs.getBundledOutput( cara3 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara4, colors.subtract( rs.getBundledOutput( cara4 ), colors[tablacolores5[v]] ) )
				    rs.setBundledOutput( cara5, colors.subtract( rs.getBundledOutput( cara5 ), colors[tablacolores5[v]] ) )
				    Delay(tiempo)
		    end
    end
    --Buble Principal de programa
	
    -- Iniciamos la variable de movimientos (numero d veces que se moveran las filas)
    local movimientos = 150
    -- Inicializamos las variable necesarias para el programa
    local columnas = 1
    local contador = 1
    local na = 7
    local nb = 7
    local nc = 7
    local ne = 7
    local nf = 7
    local velocidad = 1
    local dificultad = 1
    -- Cargamos el array con los colores ordenados de los pistones pegajosos
    local tablacolores = {"blue","purple","cyan","green","gray","pink","lime","yellow","brown","magenta","orange","white"}
    -- Cargamos el array con las caras ordenadas de las filas
    local tablacaras = {"front","left","bottom","back","right","top"}
    -- Limpiamos el terminal del ordenador
    term.clear()
    -- Posicionamos el cursor en la posicion 1,1
    term.setCursorPos(1,1)
    -- Pequeño spam pq yo lo valgo
    print("Bienvenido al arcoiris de la muerte 1.0")
    print("Creado por ELFCO para celebrar los 50subs del")
    print("canal de youtube www.youtube.com/user/elfco")
    print("Escoje la dificultad (1 - 10): ")
    -- Leemos la dificultad seleccionada
    dificultad = read("*")
    print("Escoje la velocidad (1 - 10): ")
    -- Leemos la velocidad seleccionada
    velocidad = read("*")
    print("El juego comenzara en 20 seg, diviertete... \'q\' para salir")
    -- Calculamos los movimientos en base a la dificultad seleccionada
    movimientos = movimientos * (dificultad / 10)
    -- Si la velocidad seleccionada esta entre 1 y 10 calculamos la velocidad en base a la velocidad seleccionada
    if tonumber(velocidad) >= 1 and tonumber(velocidad) <= 10 then
		    velocidad = 0.10 / tonumber(velocidad)
    else
		    velocidad = 0.001
    end
    -- Enviamos una señal de redstone por el cable rojo de la parte frontal
    rs.setBundledOutput( "front", colors.combine( rs.getBundledOutput( "front" ), colors["red"] ) )
    -- Esperamos 20 segundos
    Delay(20);
    -- Cerramos la puerta enviando una señal de redstone por el cable negro de la parte frontal
    rs.setBundledOutput( "front", colors.combine( rs.getBundledOutput( "front" ), colors["black"] ) )
    -- Esperamos 2 segundos
    Delay(2);
    -- Empieza el juego
    while contador < movimientos do
		    -- Recojemos cualquier evento en el SO del ordenador
		    event, param = os.pullEvent()
		    -- Inicializamos la variables de las caras
		    na = 7
		    nb = 7
		    nc = 7
		    ne = 7
		    nf = 7
		    -- Si la dificultad seleccionada esta entre 1 y 5 se pueden mover de 1 a la dificultad seleccionada
		    -- dificultad 1: 1 sola columna de cada vez
		    -- dificultad 2: 1 o 2 columnas de cada vez
		    -- dificultad 3: 1, 2 o 3 columnas de cada vez
		    -- dificultad 4: 1, 2, 3 o 4 columnas de cada vez
		    -- dificultad 5: 1, 2, 3, 4 o 5 columnas de cada vez
		    if tonumber(dificultad) <= 5 then
				    -- calculamos aleatoriamente la columnas que se van a mover
				    columnas = math.random(1,dificultad)
				    -- Si se mueve una columna solo
				    if columnas == 1 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- la movemos
						    mover(na,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 2
				    elseif columnas == 2 then
						    -- Calculamos aleatoriamente la 1º columna que se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- movemos las 2 columnas
						    mover2(na,nb,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 3
				    elseif columnas == 3 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 3º columna que se va a mover que no sea la 1º o la 2º
						    while (na == nc) or (nb == nc) or (nc == 7) do
								    nc = math.random(6)
						    end
						    --movemos las 3 columnas
						    mover3(na,nb,nc,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 4
				    elseif columnas == 4 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 3º columna que se va a mover que no sea la 1º o la 2º
						    while (na == nc) or (nb == nc) or (nc == 7) do
								    nc = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 4º columna que se va a mover que no sea la 1º, 2º o 3º
						    while (na == ne) or (nb == ne) or (nc == ne) or (ne == 7) do
								    ne = math.random(6)
						    end
						    -- movemos las 4 columnas
						    mover4(na,nb,nc,ne,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 5
				    elseif columnas >= 5 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 3º columna que se va a mover que no sea la 1º o la 2º
						    while (na == nc) or (nb == nc) or (nc == 7) do
								    nc = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 4º columna que se va a mover que no sea la 1º, 2º o 3º
						    while (na == ne) or (nb == ne) or (nc == ne) or (ne == 7) do
								    ne = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 5º columna que se va a mover que no sea la 1º, 2º, 3º o 4º
						    while (na == nf) or (nb == nf) or (nc == nf) or (ne == nf) or (nf == 7) do
								    nf = math.random(6)
						    end
						    -- movemos las 5 columnas
						    mover5(na,nb,nc,ne,nf,velocidad,tablacaras,tablacolores)
				    end
				    -- Acumulamos el contador para los movimientos
				    contador = contador + 1
		    -- Si la dificultad seleccionada es mayor a 5 vamos eliminando el limite inferior por cada nivel superior a 5
		    -- dificultad 6 : 2, 3, 4 o 5 columnas
		    -- dificultad 7 : 3, 4 o 5 columnas
		    -- dificultad 8 : 4 o 5 columnas
		    -- dificultad 9 o superior 5 columnas
		    else
				    -- calculamos las columnas a mover
				    columnas = math.random(1+(dificultad-5),dificultad)
				    -- Si se mueven 2
				    if columnas == 2 then
						    -- Calculamos aleatoriamente la 1º columna que se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- movemos las 2 columnas
						    mover2(na,nb,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 3
				    elseif columnas == 3 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 3º columna que se va a mover que no sea la 1º o la 2º
						    while (na == nc) or (nb == nc) or (nc == 7) do
								    nc = math.random(6)
						    end
						    --movemos las 3 columnas
						    mover3(na,nb,nc,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 4
				    elseif columnas == 4 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 3º columna que se va a mover que no sea la 1º o la 2º
						    while (na == nc) or (nb == nc) or (nc == 7) do
								    nc = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 4º columna que se va a mover que no sea la 1º, 2º o 3º
						    while (na == ne) or (nb == ne) or (nc == ne) or (ne == 7) do
								    ne = math.random(6)
						    end
						    -- movemos las 4 columnas
						    mover4(na,nb,nc,ne,velocidad,tablacaras,tablacolores)
				    -- Si se mueven 5
				    elseif columnas >= 5 then
						    --Calculamos aleatoriamente cual se va a mover
						    na = math.random(6)
						    -- Calculamos aleatoriamente la 2º columna que se va a mover que no sea la 1º
						    while (na == nb) or (nb == 7) do
								    nb = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 3º columna que se va a mover que no sea la 1º o la 2º
						    while (na == nc) or (nb == nc) or (nc == 7) do
								    nc = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 4º columna que se va a mover que no sea la 1º, 2º o 3º
						    while (na == ne) or (nb == ne) or (nc == ne) or (ne == 7) do
								    ne = math.random(6)
						    end
						    -- Calculamos aleatoriamente la 5º columna que se va a mover que no sea la 1º, 2º, 3º o 4º
						    while (na == nf) or (nb == nf) or (nc == nf) or (ne == nf) or (nf == 7) do
								    nf = math.random(6)
						    end
						    -- movemos las 5 columnas
						    mover5(na,nb,nc,ne,nf,velocidad,tablacaras,tablacolores)
				    end
				    -- aumentamos el contador de los movimientos
				    contador = contador + 1
				    -- si ha pulsado q paramos el juego
				    if event == "char" and param == "q" then
						    break
				    end
		    end
    end;
    -- Esperamos 2 segundos
    Delay(2);
    -- Quitamos las señales de redstone del cable negro y rojo
    rs.setBundledOutput( "front", colors.subtract( rs.getBundledOutput( "front" ), colors["black"] ) )
    rs.setBundledOutput( "front", colors.subtract( rs.getBundledOutput( "front" ), colors["red"] ) )
    -- desafiamos un poco.
    print("Divertido?, ¿porque no pruebas algo mas dificil?")