Golf de code assisté par outil

39

TAS Golf

SMB1 1-1 se terminant

A la manière d'un speedrun assisté par outil avec une touche de code-golf, l'objectif de ce défi est de terminer les Mondiaux 1-1 du jeu original Super Mario Bros pour NES dans le langage de programmation de votre choix, avec le moins d'octets possible. en utilisant uniquement les entrées du contrôleur de jeu dans le format que je vais décrire ci-dessous. Votre programme doit générer stdoutune liste de lignes dans ce format, créées spécifiquement pour ce défi:

up down left right start select A B

À partir de la première image, chaque nouvelle ligne représente les entrées du contrôleur 1 pour une image particulière. L'ordre des boutons par image n'a pas d'importance et ils peuvent être séparés par n'importe quelle quantité d'espaces non newline. Tout ou aucun ou certains des noms de boutons peuvent être inclus par ligne. Par exemple, un simple programme Python qui appuie à droite sur le D-pad pendant 3 images puis sur A pourrait ressembler à ceci:

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

Et sa sortie (que je voudrais alimenter dans mon émulateur pour vérifier) ​​serait:

right
right
right
A

Ici, nous définissons le "succès" comme atteindre le drapeau à la fin du Mondial 1-1 illustré ci-dessus. Le score de cet exemple de soumission Python, s'il a réussi (ce qui n'a pas été le cas), serait de 44 octets , ou la longueur d'origine du programme Python.

Pour un exemple de fichier d’entrée de travail que j’ai créé sur la base du TAS le plus rapide , voir le présent Gistub: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1 Notez que ce fichier complète le jeu entier.

Il n'y a aucun moyen d'entrer des entrées de sous-trame . Il n’existe également aucun moyen de saisir des entrées dans le contrôleur du joueur 2, mais cela ne devrait pas non plus être nécessaire (ni utile) pour terminer le niveau ou la partie.

La version de SMB utilisée sera la ROM iNES USA / Japon d'origine (md5sum 811b027eaf99c2def7b933c5208636de - la version USA est identique à la version japonaise, elle fonctionnera donc, la ROM est étiquetée Super Mario Bros (JU) (PRG 0)ou similaire).

Pour tester les soumissions, je vais exécuter les programmes, les stdouttransférer dans un fichier input.txt et les charger dans FCEUX en utilisant le script Lua que mario.luaj'ai écrit pour ce défi:

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;

La commande spécifique que je vais utiliser est fceux mario.nes --loadlua mario.lua. Les programmes n’ont pas de limite de temps, bien qu’ils doivent finir par s’arrêter.

Voici un petit exemple de Bash one-liner que j'ai créé pour convertir un fichier vidéo FCEUX (.fm2) en fichier input.txt pour mon script, si cela aide:

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

Pour référence, voici une carte en haute résolution de Monde 1-1 (ouvrez l'image dans un nouvel onglet pour une résolution complète): (source: mariouniverse.com )Monde 1-1

Remarque: à première vue, cela peut sembler être un défi de complexité de Kolmogorov sur mon fichier input.txt. Cependant, en réalité, le défi est plus complexe que cela car (a) le fichier input.txt que j’ai fourni n’est certainement pas le plus court possible et (b) il n’a jamais été tenté de créer le plus court jeu de touches possible pour SMB dans ce format . Le «nombre le plus bas de boutons» connu TAS est différent car il permet de maintenir les boutons enfoncés pendant une longue période, ce qui ajouterait de la longueur à la sortie souhaitée dans ce challenge.

Harry
la source
1
Bien que vous ayez fourni une vidéo du niveau, je ne peux pas compter le nombre de droits de la vidéo. Pourriez-vous nous dire les mouvements nécessaires?
1
Avez-vous posté ceci dans le bac à sable? Je ne m'en souviens pas.
1
Je pense que c'est assez drôle vous avez 16 votes positifs et pas de réponses :)
2
@JackBates c'est le signe d'une bonne question, non négligeable mais qui pose problème
FlipTack
1
404 sur cette image de carte en pleine résolution, je pense
Liam

Réponses:

20

Python 2, 69 48 46 44 octets

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

Voyez-le en action sur youtube!

Trouvé automatiquement avec (une version modifiée de) ce 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
la source
1
@ Harry S'il vous plaît vérifier la nouvelle version.
Orlp
1
@ Harry Je viens d'ajouter une nouvelle version qui économise 2 octets supplémentaires en ... n'utilisant pas le bouton B! Cela fait à peine partie des 99 répétitions, il a presque fallu perdre un octet pour faire plus de 100 répétitions.
Orlp
1
La version 44 octets a également été confirmée, amusant à regarder!
Harry
1
Ahh, c'est le genre de réponse que je voulais, mais je n'ai pas pu trouver les bons numéros !! Très bien fait.
Lynn
1
@Harry Ceci est un de mes enregistrements: youtube.com/watch?v=2-I1EEOlQYA
orlp
5

Python 2, 107 octets

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
la source
Très impressionnant et déjà beaucoup plus court que je pensais! Peut-être que j'aurais dû rester avec le jeu complet après tout, haha. De plus, j'ai testé cela et je peux confirmer qu'il complète le niveau, si je peux l'enregistrer, je les téléchargerai peut-être sous forme de vidéos YouTube!
Harry
1

JavaScript (ES6), 59 caractères

_=>`start

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

Ceci produit le même texte que la réponse de orlp . J'ai moi-même essayé de trouver une meilleure méthode, mais les films que j'ai convertis en input.txtfichier ne sont pas toujours lus correctement. Chaque fois que j'ai essayé d'exécuter l'émulateur à partir de cmd, une erreur s'est produite "an unknown error occurred".

Luke
la source
Je ne peux pas l'exécuter maintenant de mon côté, mais s'il produit le même input.txt que la réponse de orlp, nous l'appellerons vérifié!
Harry