Código de golf asistido por herramientas

39

TAS Golf

SMB1 1-1 finalizando

Al estilo de un speedrun asistido por herramientas con un giro de código de golf, el objetivo de este desafío es completar el Mundo 1-1 del juego original de Super Mario Bros para el NES en el lenguaje de programación elegido en el menor número de bytes posible, usando solo las entradas del controlador en el juego en el formato que describiré a continuación. Su programa debe generar stdoutuna lista de líneas en este formato, creado específicamente para este desafío:

up down left right start select A B

Comenzando con el primer cuadro, cada nueva línea representa las entradas para el Controlador 1 para un cuadro particular. El orden de los botones por cuadro no importa, y pueden separarse por cualquier cantidad de espacios en blanco que no sean de nueva línea. Todos o ninguno de los nombres de los botones se pueden incluir por línea. Por ejemplo, un programa simple de Python que presiona el D-pad hacia la derecha durante 3 cuadros y luego presiona A podría verse así:

for _ in range(3): print('right')
print('A')

Y su salida (que alimentaría en mi emulador para verificar) sería:

right
right
right
A

Aquí, definimos 'éxito' como alcanzar la bandera al final del Mundo 1-1 que se muestra arriba. La puntuación para este envío de Python de ejemplo, si tuvo éxito (que no lo hace), sería de 44 bytes , o la longitud original del programa Python.

Para un ejemplo de archivo de entrada de trabajo que creé basado en el TAS más rápido actual , vea este Github Gist: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1 Tenga en cuenta que este archivo completa todo el juego.

No hay forma de ingresar entradas de subtrama . Tampoco hay forma de ingresar entradas en el controlador del Jugador 2, pero eso tampoco debería ser necesario (o útil) para completar el nivel o el juego.

La versión de SMB utilizada será la ROM iNES original de EE. UU./ Japón (md5sum 811b027eaf99c2def7b933c5208636de: la versión de EE. UU. Es exactamente la misma que la versión japonesa, por lo que funcionará, la ROM está comúnmente etiquetada Super Mario Bros (JU) (PRG 0)o es similar).

Para probar los envíos, ejecutaré los programas, los canalizaré stdouten un archivo input.txt y los cargaré en FCEUX usando este script Lua mario.luaque escribí para este desafío:

for line in io.lines('input.txt') do
   local t = {}
   for w in line:gmatch("%S+") do
      t[w] = true;
   end;
   joypad.set(1, t);
   emu.frameadvance();
end;
while (true) do
   emu.frameadvance();
end;

El comando específico que usaré es fceux mario.nes --loadlua mario.lua. No hay límite de tiempo para los programas, aunque finalmente deben terminar.

Esta es una pequeña línea de Bash que hice para convertir un archivo de película FCEUX (.fm2) a input.txt para mi script, si ayuda:

cat movie.fm2 | cut -d'|' -f 3 | sed 's/\.//g' | sed 's/R/right /g' | sed 's/L/left /g' | sed 's/D/down /g' | sed 's/U/up /g' | sed 's/T/start /g' | sed 's/S/select /g' | sed 's/B/B /g' | sed 's/A/A /g' | tail -n +13 > input.txt

Como referencia, aquí hay un mapa de resolución completa del Mundo 1-1 (abra la imagen en una nueva pestaña para resolución completa): (fuente: mariouniverse.com )Mundo 1-1

Nota: A primera vista, esto puede parecer un desafío de complejidad de Kolmogorov en mi archivo input.txt dado. Sin embargo, en realidad el desafío es más complejo que eso porque (a) el input.txt que proporcioné definitivamente no es el más corto posible y (b) nunca ha habido un intento de crear el conjunto más corto posible de pulsaciones de teclas para SMB en este formato . El 'TAS con la menor cantidad de botones posible' es diferente porque permite mantener presionados los botones durante mucho tiempo, lo que agregaría longitud a la salida deseada en este desafío.

Acosar
fuente
1
Si bien ha proporcionado un video del nivel, no puedo contar cuántos derechos tiene el video. ¿Podría decirnos los movimientos necesarios?
1
¿Publicaste esto en el Sandbox? No lo recuerdo
1
Creo que es bastante divertido que tengas 16 votos a favor y no hay respuestas :)
2
@JackBates es el signo de una buena pregunta desafiante y no trivial
FlipTack
1
404 en esa imagen de mapa de resolución completa, creo
Liam

Respuestas:

20

Python 2, 69 48 46 44 bytes

print"start\n\n"*19+(27*"A right\n"+"\n")*99

¡Véalo en acción en youtube!

Encontrado automáticamente con (una versión modificada de) este script hacky:

start = 18
oncycle = 21
offcycle = 4


while true do
    emu.poweron()
    -- emu.speedmode("maximum")

    starting = 0
    i = 0
    frames = 0
    last_mario_x = -1

    emu.message(start .. " " .. oncycle .. " ".. offcycle)


    state = 0
    while state ~= 6 and state ~= 11 and frames < 4000 do
        if frames > 500 and frames % 100 == 0 then
            mario_x = memory.readbyte(0x6D) * 0x100 + memory.readbyte(0x86)
            if mario_x == last_mario_x then emu.message("stuck " .. mario_x .. " " .. last_mario_x); break end
            last_mario_x = mario_x
        end

        if starting < start then
            joypad.set(1, {start=1})
            emu.frameadvance(); frames = frames + 1;
            joypad.set(1, {})
            emu.frameadvance(); frames = frames + 1;
            starting = starting + 1
        else
            if i < oncycle then
                joypad.set(1, {A=1, B=1, right=1})
                i = i + 1
            else
                joypad.set(1, {})
                i = i +  1
                if i == oncycle + offcycle then
                    i = 0
                end
            end

            emu.frameadvance()
            frames = frames + 1
        end

        state = memory.readbyte(0x000E)
        if state == 4 then
            emu.message("success!")
            os.exit()
            break
        end

    end

    if start < 30 then
        start = start + 1
    elseif offcycle < 10 then
        start = 18
        offcycle = offcycle + 1
    else
        offcycle = 1
        oncycle = oncycle + 1
    end
end
orlp
fuente
1
@Harry Verifique la nueva versión.
orlp
1
@Harry Acabo de agregar otra nueva versión que ahorra 2 bytes más al ... ¡no usar el botón B! Apenas cabe en las 99 repeticiones, casi tuvo que perder un byte haciendo más de 100 repeticiones.
orlp
1
Versión de 44 bytes también confirmada, ¡divertido de ver!
Harry
1
Ahh, este es el tipo de respuesta que estaba buscando, ¡pero no pude encontrar los números correctos! Muy bien hecho.
Lynn
1
@Harry Esta es una grabación mía: youtube.com/watch?v=2-I1EEOlQYA
orlp
5

Python 2, 107 bytes

i=0
print'\n'*33+'start'
for c in'~~22 +  2 2? @  F        . \r0'+'@'*10:print'A B right\n'[i:]*ord(c);i^=2
Lynn
fuente
Muy impresionante y ya mucho más corto de lo que pensaba! Quizás debería haberme quedado con el juego completo después de todo, jaja. También probé esto y puedo confirmar que completa el nivel, si puedo hacer que se grabe, tal vez los subiré a todos como videos de YouTube.
Harry
1

JavaScript (ES6), 59 caracteres

_=>`start

`[a="repeat"](19)+(`A right
`[a](27)+`
`)[a](99)

Esto genera el mismo texto que la respuesta de orlp . Traté de encontrar un método mejor, pero las películas que convertí en un input.txtarchivo no siempre se reprodujeron correctamente. Cada vez que intenté ejecutar el emulador desde cmd, recibí un error que indicaba "an unknown error occurred".

Luke
fuente
No puedo ejecutarlo ahora mismo, pero si genera el mismo input.txt que la respuesta de orlp, lo llamaremos verificado.
Harry