Código assistido por ferramentas Golf

39

TAS Golf

SMB1 1-1 final

No estilo de um speedrun assistido por ferramentas com uma reviravolta no código de golfe, o objetivo desse desafio é completar o mundo 1-1 do jogo Super Mario Bros original para o NES na linguagem de programação escolhida no menor número de bytes possível, usando apenas as entradas do controlador no jogo no formato que descreverei abaixo. Seu programa deve gerar stdoutuma lista de linhas neste formato, criada especificamente para este desafio:

up down left right start select A B

Começando com o primeiro quadro, cada nova linha representa as entradas para o Controlador 1 para um quadro específico. A ordem dos botões por quadro não importa e eles podem ser separados por qualquer quantidade de espaço em branco que não seja da nova linha. Todos ou nenhum ou alguns dos nomes dos botões podem ser incluídos por linha. Por exemplo, um programa Python simples que pressiona o direcional para a direita por 3 quadros e pressiona A pode ser assim:

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

E sua saída (que eu alimentaria no meu emulador para verificar) seria:

right
right
right
A

Aqui, definimos 'sucesso' como alcançar a bandeira no final do Mundo 1-1 na foto acima. A pontuação para este exemplo de envio do Python, se for bem-sucedida (o que não ocorre), seria 44 bytes ou o comprimento original do programa Python.

Para um exemplo de arquivo de entrada de trabalho que criei com base no TAS mais rápido atual , consulte este Github Gist: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1 Observe que este arquivo completa o jogo inteiro.

Não há como inserir entradas de subquadro . Também não há como inserir entradas no controle do jogador 2, mas isso também não deve ser necessário (ou útil) para concluir o nível ou o jogo.

A versão do SMB usada será a ROM iNES dos EUA / Japão original (md5sum 811b027eaf99c2def7b933c5208636de - a versão dos EUA é exatamente a mesma da versão japonesa, portanto, qualquer uma delas funcionará, a ROM é geralmente rotulada Super Mario Bros (JU) (PRG 0)ou similar).

Para testar os envios, executarei os programas, canalizá- stdoutlos em um arquivo input.txt e carregá-los no FCEUX usando este script Lua mario.luaque escrevi para este desafio:

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;

O comando específico que vou usar é fceux mario.nes --loadlua mario.lua. Não há limite de tempo para os programas, embora eles precisem terminar.

Este é um pouco da linha Bash que fiz para converter um arquivo de filme FCEUX (.fm2) em um input.txt para o meu script, se ajudar:

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

Para referência, aqui está um mapa de resolução total do Mundo 1-1 (abra a imagem em uma nova guia para resolução total): (fonte: mariouniverse.com )Mundo 1-1

Nota: À primeira vista, isso pode parecer um desafio à complexidade Kolmogorov no meu arquivo input.txt. No entanto, na realidade, o desafio é mais complexo do que isso porque (a) o input.txt que forneci definitivamente não é o mais curto possível e (b) nunca houve uma tentativa de criar o menor conjunto possível de pressionamentos de tecla para SMB nesse formato . O 'menor número possível de botões' conhecido do TAS é diferente porque permite manter os botões pressionados por um longo período de tempo, o que aumentaria a produção desejada neste desafio.

Harry
fonte
1
Embora você tenha fornecido um vídeo de nível, não posso contar quantos direitos existem no vídeo. Você poderia nos dizer as mudanças necessárias?
1
Você postou isso na Sandbox? Eu não lembro disso.
1
Eu acho que é muito engraçado você tem 16 upvotes e nenhuma resposta :)
2
@JackBates esse é o sinal de um bom, challengjng, questão não trivial
FlipTack
1
404 em que a imagem completa do mapa resolução Acho
Liam

Respostas:

20

Python 2, 69 48 46 44 bytes

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

Veja em ação no youtube!

Encontrado automaticamente com (uma versão modificada) deste 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
fonte
1
@ Harry Verifique a nova versão.
orlp
1
@ Harry Acabei de adicionar outra nova versão que economiza mais 2 bytes ... não usando o botão B! Ele mal se encaixa nas 99 repetições, quase teve que perder um byte ao fazer mais de 100 repetições.
orlp 04/02
1
Versão de 44 bytes também confirmada, divertido de assistir!
Harry
1
Ahh, esse é o tipo de resposta que eu estava procurando, mas não consegui encontrar os números certos !! Muito bem feito.
Lynn
1
@Harry Esta é uma gravação minha: 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
fonte
Muito impressionante e já muito mais curto do que eu pensava! Talvez eu devesse ter ficado com o jogo completo, afinal, haha. Também testei isso e posso confirmar que conclui o nível; se eu conseguir gravar, talvez eu envie todos eles como vídeos do YouTube!
Harry
1

JavaScript (ES6), 59 caracteres

_=>`start

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

Isso gera o mesmo texto que a resposta do orlp . Tentei criar um método melhor, mas os filmes que converti em um input.txtarquivo nem sempre eram exibidos corretamente. Sempre que eu tentava executar o emulador a partir do cmd, recebia um erro informando "an unknown error occurred".

Luke
fonte
Não posso executá-lo agora do meu lado, mas se der o mesmo input.txt que a resposta do orlp, chamaremos de verificado!
Harry