Інструмент за допомогою коду Golf


39

TAS Golf

SMB1 1-1 закінчення

У стилі скоромовки з інструментами з поворотом коду-гольфу, метою цього завдання є завершити Світ 1-1 оригінальної гри Super Mario Bros для NES на обраній вами мові програмування якомога менше байтів, використовуючи лише входи в ігровий контролер у форматі, який я опишу нижче. Ваша програма повинна вивести stdoutсписок рядків у цьому форматі, створений спеціально для цього завдання:

up down left right start select A B

Починаючи з першого кадру, кожен новий рядок представляє входи для контролера 1 для певного кадру. Порядок кнопок на кадр не має значення, і їх можна розділити будь-якою кількістю пробілів, що не є новим рядком. Усі або жодні або деякі назви кнопок можуть бути включені в рядок. Наприклад, проста програма Python, яка натискає D-pad прямо на 3 кадри, а потім натискає A, може виглядати так:

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

І його вихід (який я б подав у свій емулятор для перевірки) був би:

right
right
right
A

Тут ми визначаємо "успіх" як досягнення прапора в кінці Світу 1-1, зображеному вище. Оцінка для цього прикладу подання Python, якщо це вдалося (а це не так), складе 44 байти , або початкова довжина програми Python.

Для прикладу робочого вхідного файлу, який я створив на основі поточного найшвидшого TAS , див. Цей Github Gist: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1, який враховує, що цей файл завершує всю гру.

Немає можливості вводити входи підрамника . Також немає можливості вводити входи в контролер програвача 2, але це також не повинно бути необхідним (або корисним) для завершення рівня або гри.

Використаною версією SMB буде оригінальний ROM iNES для США / Японії (md5sum 811b027eaf99c2def7b933c5208636de - версія США точно така ж, як і японська версія, тому або працюватиме, і ПЗУ зазвичай позначено маркою Super Mario Bros (JU) (PRG 0)або подібною).

Щоб перевірити подані матеріали, я запускаю програми, stdoutпередаю їх у файл input.txt і завантажую їх у FCEUX за допомогою цього сценарію Lua, який mario.luaя написав для цього завдання:

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;

Конкретна команда, яку я буду використовувати, - це fceux mario.nes --loadlua mario.lua. Програми не обмежуються часом, хоча вони з часом повинні припинитись.

Це маленький однофайлер Bash, який я зробив, щоб перетворити файл фільму FCEUX (.fm2) у input.txt для мого сценарію, якщо це допоможе:

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

Для довідки, тут карта повної роздільної здатності світу 1-1 (відкрийте зображення в новій вкладці для повного дозволу): (джерело: mariouniverse.com )Світ 1-1

Примітка. На перший погляд це може здатися проблемою складності Колмогорова в моєму файлі input.txt. Однак насправді виклик є складнішим, ніж це, тому що (a) наданий мною вклад.txt, безумовно, не найкоротший і (b) ніколи не було спроб створити якомога коротший набір клавіш для SMB у цьому форматі. . Найвідоміша з найменших кнопок, відома TAS, відрізняється тим, що вона дозволяє тримати тривалий час натискання кнопок, що додало б довжину бажаному виводу в цьому виклику.


1
Хоча ви надали відео такого рівня, я не можу підрахувати, скільки прав на це. Не могли б ви сказати нам необхідні кроки?

1
Ви розмістили це в пісочниці? Я цього не пам’ятаю.

1
Я думаю, що це досить смішно, у вас 16 оновлень і жодних відповідей :)

2
@JackBates - це знак хорошого, непростого, нетривіального питання
FlipTack

1
404 на тому зображенні карти повної роздільної здатності, я думаю
Ліам

Відповіді:


20

Python 2, 69 48 46 44 байт

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

Подивіться це в дії на youtube!

Автоматично знайдений (модифікована версія) цього хакі-сценарію:

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

1
@Harry Перевірте нову версію.
orlp

1
@Harry Я тільки що додав ще одну нову версію, яка зберігає ще 2 байти на ... не використовуючи кнопку B! Він ледве вписується в 99 повторів, майже довелося витрачати байт, роблячи 100+ повторів.
orlp

1
44-байтну версію також підтвердили, весело дивитися!
Гаррі

1
Ах, це така відповідь, на яку я йшов, але я не зміг знайти правильних цифр !! Дуже красиво зроблено.
Лінн

1
@Harry Це мій запис: youtube.com/watch?v=2-I1EEOlQYA
orlp

5

Python 2, 107 байт

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

Дуже вражаючий і вже набагато коротший, ніж я думав! Можливо, я мав би дотримуватися повноцінної гри зрештою, ха-ха. Також я тестував це і можу підтвердити, що він завершує рівень, якщо я можу його записати, можливо, я завантажу їх як відео на YouTube!
Гаррі

1

JavaScript (ES6), 59 символів

_=>`start

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

Це виводить той самий текст, що і відповідь orlp . Я сам спробував придумати кращий метод, але фільми, які я перетворив у input.txtфайл, не завжди відтворювались належним чином. Кожного разу, коли я намагався запустити емулятор від cmd, у мене з’явилася помилка із зазначенням "an unknown error occurred".


Неможливо запустити його зараз на моєму кінці, але якщо він виводить той самий input.txt, що і відповідь orlp, тоді ми будемо називати його перевіреним!
Гаррі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.