Golf z asystą narzędziową

39

TAS Golf

Zakończenie SMB1 1-1

W stylu Speedrun narzędzia wspomagane z domieszką code-golf, celem tego wyzwania jest zakończenie świata 1-1 z oryginalnego Super Mario Bros gry na NES w wybranym języku programowania w jak najmniejszej liczbie bajtów, jak to możliwe, używając tylko wejść kontrolera w grze w formacie, który opiszę poniżej. Twój program musi wyświetlać stdoutlistę linii w tym formacie, stworzoną specjalnie dla tego wyzwania:

up down left right start select A B

Zaczynając od pierwszej ramki, każda nowa linia reprezentuje dane wejściowe dla Kontrolera 1 dla konkretnej ramki. Kolejność przycisków na ramkę nie ma znaczenia, i można je oddzielić dowolną liczbą spacji niebędących znakami nowej linii. W wierszu można podać wszystkie lub brak nazw przycisków lub niektóre z nich. Na przykład prosty program w języku Python, który naciska D-pad w prawo dla 3 ramek, a następnie naciska A, może wyglądać następująco:

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

A jego wynik (który chciałbym wprowadzić do mojego emulatora w celu weryfikacji) to:

right
right
right
A

Tutaj definiujemy „sukces” jako osiągnięcie flagi pod koniec świata 1-1 na zdjęciu powyżej. Wynik dla tego przykładowego przesłania w języku Python, jeśli się powiedzie (czego nie powiedzie się), wyniesie 44 bajty lub oryginalną długość programu w języku Python.

Na przykład działający plik wejściowy, który utworzyłem w oparciu o bieżący najszybszy TAS , zobacz Github Gist: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1 Pamiętaj, że ten plik kończy całą grę.

Nie ma możliwości wprowadzania danych wejściowych w ramce pomocniczej . Nie ma również możliwości wprowadzania danych wejściowych do kontrolera Gracza 2, ale nie powinno to być również konieczne (ani przydatne) do ukończenia poziomu lub gry.

Użyta wersja SMB będzie oryginalnym ROMem USA / Japonii iNES ROM (md5sum 811b027eaf99c2def7b933c5208636de - wersja USA jest dokładnie taka sama jak wersja japońska, więc albo będzie działać, ROM jest zwykle oznaczony Super Mario Bros (JU) (PRG 0)lub podobny).

Aby przetestować zgłoszenia, uruchomię programy, stdoutpotokuję je do pliku input.txt i ładuję do FCEUX za pomocą skryptu Lua, mario.luaktóry napisałem dla tego wyzwania:

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;

Konkretne polecenie, którego będę używać, to fceux mario.nes --loadlua mario.lua. Programy nie mają ograniczenia czasowego, ale ostatecznie muszą się zakończyć.

To jest mały linijka Bash, którą zrobiłem, aby przekonwertować plik filmu FCEUX (.fm2) na input.txt dla mojego skryptu, jeśli to pomaga:

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

Dla porównania, oto mapa świata 1-1 w pełnej rozdzielczości (otwórz obraz w nowej karcie dla pełnej rozdzielczości): (źródło: mariouniverse.com )Świat 1-1

Uwaga: Na pierwszy rzut oka może to wydawać się wyzwaniem złożoności Kołmogorowa w moim pliku input.txt. Jednak w rzeczywistości wyzwanie jest bardziej złożone, ponieważ (a) podany przeze mnie plik input.txt zdecydowanie nie jest najkrótszy z możliwych i (b) nigdy nie podjęto próby stworzenia możliwie najkrótszego zestawu naciśnięć klawiszy dla SMB w tym formacie . Znane TAS „najmniejszej możliwej liczby przycisków” jest inne, ponieważ pozwala na długie przytrzymanie przycisków, co zwiększy długość pożądanego wyjścia w tym wyzwaniu.

Złupić
źródło
1
Chociaż dostarczyłeś wideo poziomu, nie mogę policzyć, ile praw jest w tym filmie. Czy możesz nam powiedzieć, jakie ruchy są potrzebne?
1
Czy opublikowałeś to w piaskownicy? Nie pamiętam tego
1
Myślę, że to dość zabawne, masz 16 pozytywnych opinii i brak odpowiedzi :)
2
@JackBates to znak dobrego, trudnego, nietrywialnego pytania
FlipTack
1
404 na tym obrazie mapy w pełnej rozdzielczości, myślę
Liam,

Odpowiedzi:

20

Python 2, 69 48 46 44 bajtów

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

Zobacz to w akcji na youtube!

Automatycznie znaleziony z (zmodyfikowaną wersją) tego hacky skryptu:

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
źródło
1
@Harry Sprawdź nową wersję.
orlp
1
@Harry Właśnie dodałem kolejną nową wersję, która oszczędza 2 kolejne bajty przez ... nieużywanie przycisku B. Ledwo mieści się w 99 powtórzeniach, prawie musiałem zmarnować bajt na robienie ponad 100 powtórzeń.
orlp
1
Potwierdzono także wersję 44-bajtową, fajnie się ogląda!
Harry
1
Achh, to była odpowiedź, na którą chciałem, ale nie mogłem znaleźć odpowiednich liczb !! Bardzo ładnie wykonane.
Lynn
1
@Harry To moje nagranie: youtube.com/watch?v=2-I1EEOlQYA
orlp
5

Python 2, 107 bajtów

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
źródło
Bardzo imponujące i już znacznie krótsze niż myślałem! Może mimo wszystko powinienem był trzymać się pełnej gry, haha. Przetestowałem to i mogę potwierdzić, że ukończył poziom, jeśli uda mi się go nagrać, może prześlę je wszystkie jako filmy z YouTube'a!
Harry
1

JavaScript (ES6), 59 znaków

_=>`start

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

Daje to taki sam tekst jak odpowiedź orlp . Sam próbowałem wymyślić lepszą metodę, ale filmy przekonwertowane na input.txtplik nie zawsze były odtwarzane poprawnie. Za każdym razem, gdy próbowałem uruchomić emulator z cmd, pojawia się komunikat o błędzie "an unknown error occurred".

Łukasz
źródło
Nie mogę go teraz uruchomić na moim końcu, ale jeśli wyświetli to samo input.txt co odpowiedź orlp, wtedy nazwiemy go zweryfikowanym!
Harry