Tool-Assisted Code Golf


39

TAS Golf

SMB1 1-1 สิ้นสุดแล้ว

ในรูปแบบของspeedrun ที่ได้รับการช่วยเหลือจากเครื่องมือด้วยการหมุนรหัส - กอล์ฟเป้าหมายของความท้าทายนี้คือการทำให้เกมSuper Mario Brosดั้งเดิมของWorld 1-1เสร็จสมบูรณ์สำหรับ 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

ที่นี่เรานิยาม 'ความสำเร็จ' ในการเข้าถึงธงเมื่อสิ้นสุด World 1-1 ดังภาพด้านบน คะแนนสำหรับการส่ง Python ตัวอย่างนี้ถ้าทำสำเร็จ (ซึ่งไม่เป็น) จะเป็น44 ไบต์หรือความยาวดั้งเดิมของโปรแกรม Python

สำหรับตัวอย่างไฟล์อินพุตที่ใช้งานได้ที่ฉันสร้างขึ้นตามTAS ที่เร็วที่สุดในปัจจุบันให้ดู Github Gist นี้: https://gist.github.com/anonymous/6f1a73cbff3cd46c9e1cf8d5c2ff58e1โปรดทราบว่าไฟล์นี้เสร็จสิ้นทั้งเกม

ไม่มีทางที่จะใส่ไม่เป็นปัจจัยการผลิตเฟรม นอกจากนี้ยังไม่มีวิธีป้อนอินพุตในคอนโทรลเลอร์ของผู้เล่น 2 แต่ก็ไม่จำเป็นเช่นกัน (หรือมีประโยชน์) สำหรับการจบระดับหรือเกม

เวอร์ชันของ SMB ที่ใช้จะเป็น USA / Japan iNES ROM ดั้งเดิม (md5sum 811b027eaf99c2def7b933c5208636de - เวอร์ชั่น USA นั้นเหมือนกันกับเวอร์ชั่นญี่ปุ่นดังนั้นจะใช้งานได้ ROM จะมีป้ายกำกับ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 one-liner เล็ก ๆ น้อย ๆ ที่ฉันสร้างขึ้นเพื่อแปลงไฟล์ภาพยนตร์ 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

สำหรับการอ้างอิงนี่คือแผนที่ความละเอียดเต็มของ World 1-1 (เปิดภาพในแท็บใหม่สำหรับความละเอียดเต็ม): (แหล่งที่มา: mariouniverse.com )โลก 1-1

หมายเหตุ: จากภาพรวมครั้งแรกสิ่งนี้อาจดูเหมือนความท้าทายที่ซับซ้อนของ Kolmogorov ในไฟล์ input.txt ที่ฉันได้รับ อย่างไรก็ตามในความเป็นจริงความท้าทายนั้นซับซ้อนกว่านั้นเนื่องจาก (a) input.txt ที่ฉันให้ไว้ไม่ได้สั้นที่สุดและ (b) ไม่เคยมีความพยายามในการสร้างชุดคีย์เพรสที่สั้นที่สุดเท่าที่จะเป็นไปได้สำหรับ SMB ในรูปแบบนี้ . 'ปุ่มน้อยที่สุดที่เป็นไปได้' TAS ที่รู้จักนั้นแตกต่างกันเพราะช่วยให้กดปุ่มค้างไว้เป็นเวลานานซึ่งจะเพิ่มความยาวให้กับเอาต์พุตที่ต้องการในความท้าทาย


1
ในขณะที่คุณให้วิดีโอในระดับฉันไม่สามารถนับจำนวนสิทธิ์ในวิดีโอ คุณสามารถบอกให้เราทราบการเคลื่อนไหวที่จำเป็น?

1
คุณโพสต์สิ่งนี้ใน Sandbox หรือไม่? ฉันจำไม่ได้

1
ฉันคิดว่ามันค่อนข้างตลกที่คุณมีผู้

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 ไบต์ยังได้รับการยืนยันสนุกกับการดู!
Harry

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
Harry

1

JavaScript (ES6), 59 ตัวอักษร

_=>`start

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

นี้ outputs ข้อความเดียวกับคำตอบของ orlp ฉันลองใช้วิธีที่ดีกว่าด้วยตัวเอง แต่ภาพยนตร์ที่ฉันแปลงเป็นinput.txtไฟล์ไม่ได้เล่นอย่างถูกต้องเสมอไป "an unknown error occurred"เมื่อใดก็ตามที่ฉันพยายามเรียกใช้โปรแกรมจำลองจากคำสั่งที่ผมได้รับข้อผิดพลาดที่ระบุ


ไม่สามารถเรียกใช้ตอนท้ายของฉันได้ แต่ถ้ามันส่งออก input.txt เดียวกันกับคำตอบของ orlp เราจะเรียกมันว่ายืนยัน!
Harry
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.