Werkzeuggestützter Code Golf

39

TAS Golf

SMB1 1-1 Endung

Im Stil eines toolgestützten Speedruns mit einem Code-Golf-Twist besteht das Ziel dieser Herausforderung darin, World 1-1 des ursprünglichen Super Mario Bros- Spiels für das NES in der von Ihnen gewählten Programmiersprache in so wenigen Bytes wie möglich zu beenden. Verwenden Sie nur die In-Game-Controller-Eingänge im unten beschriebenen Format. Ihr Programm muss stdouteine Liste von Zeilen in diesem Format ausgeben , die speziell für diese Herausforderung erstellt wurden:

up down left right start select A B

Beginnend mit dem ersten Frame repräsentiert jede neue Zeile die Eingänge für Controller 1 für einen bestimmten Frame. Die Reihenfolge der Schaltflächen pro Frame spielt keine Rolle. Sie können durch eine beliebige Anzahl von Leerzeichen (ohne Zeilenumbruch) voneinander getrennt werden. Alle oder keine oder einige der Schaltflächennamen können pro Zeile eingefügt werden. Ein einfaches Python-Programm, das das Steuerkreuz drei Frames lang nach rechts drückt und dann A drückt, könnte beispielsweise so aussehen:

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

Und seine Ausgabe (die ich in meinen Emulator einspeisen würde, um zu überprüfen) wäre:

right
right
right
A

Hier definieren wir "Erfolg" als das Erreichen der Flagge am Ende von World 1-1, wie oben abgebildet. Die Punktzahl für diese Python-Beispielübermittlung beträgt , falls sie erfolgreich war (was nicht der Fall ist), 44 Byte oder die ursprüngliche Länge des Python-Programms.

Eine Beispiel-Eingabedatei, die ich basierend auf dem aktuell schnellsten TAS erstellt habe , finden Sie in der folgenden Github-Liste: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1 Beachten Sie, dass diese Datei das gesamte Spiel abschließt.

Es gibt keine Möglichkeit, Subframe-Eingänge einzugeben . Es gibt auch keine Möglichkeit, Eingaben in den Controller von Spieler 2 einzugeben, aber dies sollte auch nicht notwendig (oder nützlich) sein, um das Level oder Spiel zu beenden.

Die verwendete SMB-Version ist das Original-iNES-ROM für USA / Japan (md5sum 811b027eaf99c2def7b933c5208636de). Die USA-Version ist genau die gleiche wie die japanische Version. Entweder funktioniert sie, das ROM ist allgemein beschriftet Super Mario Bros (JU) (PRG 0)oder ähnlich.

Um die Einsendungen zu testen, stdoutführe ich die Programme aus, leite sie in eine input.txt-Datei und lade sie mit dem Lua-Skript, das mario.luaich für diese Herausforderung geschrieben habe, in FCEUX :

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;

Der spezifische Befehl, den ich verwenden werde, ist fceux mario.nes --loadlua mario.lua. Es gibt keine zeitliche Begrenzung für die Programme, obwohl sie eventuell beendet werden müssen.

Dies ist ein kleiner Bash-Einzeiler, den ich erstellt habe, um eine FCEUX-Filmdatei (.fm2) in eine input.txt für mein Skript zu konvertieren, wenn dies hilft:

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

Als Referenz finden Sie hier eine Karte von World 1-1 in voller Auflösung (öffnen Sie das Bild in einem neuen Tab, um es in voller Auflösung anzuzeigen ) : (Quelle: mariouniverse.com )Welt 1-1

Hinweis: Auf den ersten Blick scheint dies eine Herausforderung für die Kolmogorov-Komplexität in meiner angegebenen input.txt-Datei zu sein. In der Realität ist die Herausforderung jedoch komplexer, da (a) die von mir bereitgestellte input.txt definitiv nicht die kürzeste ist und (b) noch nie versucht wurde, eine möglichst kurze Anzahl von Tastendrücken für SMB in diesem Format zu erstellen . Das "Möglichst wenige Tasten" bekannte TAS unterscheidet sich, da es das Halten von Tasten für eine lange Zeit ermöglicht, was die gewünschte Ausgabe bei dieser Herausforderung verlängern würde.

Harry
quelle
1
Obwohl Sie ein Video des Levels bereitgestellt haben, kann ich nicht zählen, wie viele Rechte das Video enthält. Können Sie uns die erforderlichen Schritte mitteilen?
1
Hast du das in der Sandbox gepostet? Ich erinnere mich nicht daran.
1
Ich finde es ziemlich lustig, dass du 16 Upvotes und keine Antworten
2
@ JackBates, das ist das Zeichen einer guten, herausfordernden, nicht trivialen Frage
FlipTack
1
404 auf diesem Kartenbild in voller Auflösung denke ich
Liam

Antworten:

20

Python 2, 69 48 46 44 Bytes

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

Sehen Sie es in Aktion auf Youtube!

Wird mit (einer geänderten) Version dieses Hacky-Skripts automatisch gefunden:

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
quelle
1
@Harry Bitte überprüfen Sie die neue Version.
Orlp
1
@Harry Ich habe gerade eine neue Version hinzugefügt, die 2 weitere Bytes spart, indem ... nicht die B-Taste gedrückt wird! Es passt kaum in die 99 Wiederholungen, musste fast ein Byte für mehr als 100 Wiederholungen verschwenden.
Orlp
1
44-Byte-Version auch bestätigt, Spaß zu sehen!
Harry
1
Ahh, das ist die Art von Antwort, die ich gesucht habe, aber ich konnte nicht die richtigen Zahlen finden !! Sehr schön gemacht.
Lynn
1
@ Harry Dies ist eine Aufnahme von mir: 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
quelle
Sehr beeindruckend und schon viel kürzer als ich dachte! Vielleicht hätte ich doch bei dem ganzen Spiel bleiben sollen, haha. Auch ich habe das getestet und kann bestätigen, dass es das Level beendet. Wenn ich es aufnehmen kann, lade ich sie vielleicht alle als YouTube-Videos hoch!
Harry
1

JavaScript (ES6), 59 Zeichen

_=>`start

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

Dies gibt den gleichen Text wie die Antwort von orlp aus . Ich habe versucht, mir eine bessere Methode auszudenken, aber die Filme, die ich in eine input.txtDatei konvertiert habe, wurden nicht immer richtig abgespielt. Immer wenn ich versuchte, den Emulator von cmd aus zu starten, wurde eine Fehlermeldung angezeigt "an unknown error occurred".

Luke
quelle
Ich kann es momentan nicht ausführen, aber wenn es dieselbe input.txt ausgibt wie die Antwort von orlp, werden wir es als verifiziert bezeichnen!
Harry