สงครามนาโนคอร์


21

นี่คือการดัดแปลงของCore Warซึ่งเป็นโปรแกรม KOTH ย้อนหลังไปถึงศตวรรษที่ 20 การจะมีความเฉพาะเจาะจงมากขึ้นก็จะใช้ชุดคำสั่งง่ายอย่างไม่น่าเชื่อตามหลักออกจากข้อเสนอเดิม

พื้นหลัง

ใน Core War มีสองโปรแกรมที่ต่อสู้เพื่อควบคุมคอมพิวเตอร์ เป้าหมายของแต่ละโปรแกรมคือการชนะโดยการค้นหาและยุติโปรแกรมที่เป็นปฏิปักษ์

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

เป้าหมายคือการยุติโปรแกรมฝ่ายตรงข้าม โปรแกรมจะหยุดทำงานเมื่อพยายามเรียกใช้คำสั่งที่ไม่ถูกต้องซึ่งเป็นDATคำสั่งใด ๆ

ชุดคำสั่ง

แต่ละโปรแกรมประกอบด้วยชุดคำสั่งระดับต่ำซึ่งแต่ละโปรแกรมใช้สองฟิลด์เรียกว่าฟิลด์ A และ B

ชุดคำสั่งนี้ดึงมาจากสเป็คดั้งเดิมมาก การเปลี่ยนแปลงที่สำคัญคือ 1) การชี้แจงเกี่ยวกับคำสั่งการเพิ่ม / การลบและ 2) การเปลี่ยนแปลงของ#โหมดการกำหนดแอดเดรสเพื่อให้สามารถใช้งานได้ทุกที่ Core Wars เวอร์ชันเต็มส่วนใหญ่มี opcode มากกว่า 20 โหมดโหมดการกำหนดแอดเดรส 8 โหมดและชุด "คำแนะนำการปรับเปลี่ยน"

opcodes

แต่ละคำสั่งจะต้องมีหนึ่งในเจ็ดรหัสที่แตกต่างกัน

  • DAT A B- (ข้อมูล) - นี้ก็ถือเป็นตัวเลขและA Bที่สำคัญกระบวนการจะหยุดทำงานเมื่อพยายามเรียกใช้คำสั่ง DAT
  • MOV A B- (ย้าย) - การเคลื่อนไหวนี้เนื้อหาของที่ตั้งหน่วยความจำตำแหน่งหน่วยความจำA Bนี่คือการสาธิตก่อนและหลัง:

    MOV 2 1
    ADD @4 #5
    JMP #1 -1
    
    MOV 2 1
    JMP #1 -1
    JMP #1 -1
    
  • ADD A B- (เพิ่ม) - นี้จะเพิ่มเนื้อหาของที่ตั้งหน่วยความจำตำแหน่งหน่วยความจำA Bมีการเพิ่มฟิลด์สองฟิลด์แรกของทั้งสองและฟิลด์ที่สองจะถูกเพิ่ม

    ADD 2 1
    MOV @4 #5
    JMP #1 -1
    
    ADD 2 1
    MOV @5 #4
    JMP #1 -1
    
  • SUB A B- (ลบ) - ลบนี้เนื้อหาของที่ตั้งหน่วยความจำAมาจาก (และร้านค้าผลลง) Bสถานที่ตั้งของหน่วยความจำ

    SUB 2 1
    MOV @4 #5
    JMP #1 -1
    
    SUB 2 1
    MOV @3 #6
    JMP #1 -1
    
  • JMP A B- (กระโดด) - ข้ามไปยังตำแหน่งAซึ่งจะถูกเรียกใช้รอบถัดไป Bต้องเป็นตัวเลข แต่ไม่ทำอะไรเลย (คุณสามารถใช้เพื่อเก็บข้อมูลได้)

    JMP 2 1337
    ADD 1 2
    ADD 2 3
    

    การกระโดดหมายความว่าADD 2 3จะถูกดำเนินการรอบถัดไป

  • JMZ A B- (กระโดดถ้าศูนย์) - หากทั้งสองช่องของเส้นBเป็น 0 Aแล้วโปรแกรมกระโดดไปยังสถานที่

    JMZ 2 1
    SUB 0 @0
    DAT 23 45
    

    เนื่องจากทั้งสองฟิลด์ของคำสั่ง 1 เป็น 0 คำสั่ง DAT จะถูกดำเนินการในเทิร์นถัดไปซึ่งนำไปสู่

  • CMP A B- (เปรียบเทียบและข้ามถ้าไม่เท่ากัน) - ถ้าฟิลด์ในคำแนะนำAและBไม่เท่ากันข้ามคำสั่งถัดไป

    CMP #1 2
    ADD 2 #3
    SUB @2 3
    

    เนื่องจากทั้งสองฟิลด์ของคำแนะนำ 1 และ 2 มีค่าเท่ากันคำสั่ง ADD จึงไม่ถูกข้ามและถูกเรียกใช้ในเทิร์นถัดไป

เมื่อเพิ่ม / ลบคำแนะนำสองคำทั้งสองฟิลด์ (A และ B) จะถูกเพิ่ม / ลบคู่ที่ชาญฉลาด โหมดการกำหนดแอดเดรสและ opcode จะไม่เปลี่ยนแปลง

ที่อยู่โหมด

มีโหมดการกำหนดแอดเดรสสามแบบ แต่ละฟิลด์ของคำสั่งมีหนึ่งในสามโหมดการกำหนดแอดเดรสเหล่านี้

  • ทันที#X - Xเป็นบรรทัดที่จะใช้โดยตรงในการคำนวณ ตัวอย่างเช่น#0เป็นบรรทัดแรกของโปรแกรม เส้นเชิงลบหมายถึงเส้นในแกนกลางก่อนที่จะเริ่มโปรแกรม

    ... //just a space-filler
    ...
    ADD #3 #4
    DAT 0 1
    DAT 2 4
    

    สิ่งนี้จะเพิ่มบรรทัดแรกของสองบรรทัด DAT เป็นสองเนื่องจากอยู่ในบรรทัดที่ 3 และ 4 ตามลำดับ อย่างไรก็ตามคุณไม่ต้องการใช้รหัสนี้เนื่องจาก DAT จะฆ่าบอทของคุณในรอบต่อไป

  • สัมพัทธ์X - ตัวเลขXแสดงตำแหน่งของที่อยู่หน่วยความจำเป้าหมายเทียบกับที่อยู่ปัจจุบัน หมายเลขที่ตำแหน่งนี้ถูกใช้ในการคำนวณ หากบรรทัด#35ถูกดำเนินการและมีอยู่ระบบจะใช้-5บรรทัด#30นั้น

    ... //just a space-filler
    ...
    ADD 2 1
    DAT 0 1
    DAT 2 4
    

    นี่จะเพิ่มบรรทัด DAT ที่สองเป็นบรรทัดแรก

  • ทางอ้อม@X - ตัวเลขXแสดงถึงที่อยู่ญาติ เนื้อหาในตำแหน่งนั้นจะถูกเพิ่มลงในหมายเลข X ชั่วคราวเพื่อสร้างที่อยู่ใหม่ที่สัมพันธ์กันซึ่งหมายเลขจะถูกดึงออกมา หากบรรทัด#35กำลังถูกดำเนินการและฟิลด์ที่สองคือ@4และฟิลด์ที่สองของบรรทัด#39มีจำนวน-7ดังนั้น#32จะใช้บรรทัด

    ... //just a space-filler
    ...
    ADD @1 @1
    DAT 0 1
    DAT 2 4
    

    สิ่งนี้จะเพิ่ม DAT แรกเป็นสอง แต่ในวิธีที่ซับซ้อนกว่า ฟิลด์แรกคือ @ 1 ซึ่งรับข้อมูลจากที่อยู่สัมพัทธ์ซึ่งเป็นฟิลด์แรกของ DAT แรกซึ่งเป็น 0 นี่ถูกตีความว่าเป็นที่อยู่ญาติที่สองจากตำแหน่งนั้นดังนั้น 1 + 0 = 1 จะให้ผลรวมทั้งหมด ชดเชยจากคำสั่งเดิม สำหรับเขตข้อมูลที่สอง @ 1 ได้รับค่าจากที่อยู่สัมพัทธ์ (1 ในเขตข้อมูลที่สองของ DAT แรก) และเพิ่มเข้าไปในตัวเองในลักษณะเดียวกัน ออฟเซ็ตรวมเท่ากับ 1 + 1 = 2 ADD 1 2ดังนั้นคำสั่งนี้จะถูกดำเนินการในทำนองเดียวกันกับ

แต่ละโปรแกรมสามารถมีได้สูงสุด 64 คำสั่ง

เมื่อรอบเริ่มต้นโปรแกรมทั้งสองจะถูกวางแบบสุ่มในธนาคารหน่วยความจำที่มี 8192 ตำแหน่ง ตัวชี้คำสั่งสำหรับแต่ละโปรแกรมเริ่มต้นที่จุดเริ่มต้นของโปรแกรมและเพิ่มขึ้นหลังจากรอบการดำเนินการแต่ละรอบ โปรแกรมจะตายเมื่อตัวชี้คำแนะนำพยายามดำเนินการDATคำสั่ง

พารามิเตอร์ของแกน

ขนาดแกนหลักคือ 8192 โดยมีการหมดเวลา 8192 * 8 = 65536 เห็บ หลักคือเป็นวงกลมเพื่อให้การเขียนไปยังที่อยู่ 8195 เป็นเช่นเดียวกับการเขียนไปยังที่อยู่ 3. DAT #0 #0ที่อยู่ที่ไม่ได้ใช้ทั้งหมดจะเริ่มต้นได้ที่

ผู้แข่งขันแต่ละรายจะต้องไม่ยาวเกิน 64 บรรทัด จำนวนเต็มจะถูกเก็บเป็นจำนวนเต็ม 32 บิต

วจีวิภาค

เพื่อให้การเขียนโปรแกรมง่ายขึ้นสำหรับคู่แข่งฉันจะเพิ่มคุณสมบัติ line-label ใน parser คำใด ๆ ที่เกิดขึ้นบนบรรทัดก่อน opcode จะถูกตีความเป็นป้ายกำกับบรรทัด ตัวอย่างเช่นมีป้ายกำกับเส้นtree mov 4 6 treeหากทุกที่ในโปรแกรมมีเขตข้อมูลที่มีtree #treeหรือ@treeจะมีการแทนที่ตัวเลข นอกจากนี้ยังไม่สนใจการใช้อักษรตัวพิมพ์ใหญ่

นี่คือตัวอย่างของวิธีการแทนที่ป้ายกำกับบรรทัด:

labelA add labelB @labelC
labelB add #labelC labelC
labelC sub labelA @labelB

ในที่นี้ป้ายกำกับ A, B และ C อยู่ในบรรทัดที่ 0, 1 และ 2 อินสแตนซ์ของ#labelจะถูกแทนที่ด้วยหมายเลขบรรทัดของป้ายกำกับ อินสแตนซ์ของlabelหรือ@labelถูกแทนที่ด้วยตำแหน่งสัมพัทธ์ของฉลาก โหมดที่อยู่จะถูกรักษาไว้

ADD 1 @2
ADD #2 1
SUB -2 @-1

เกณฑ์การให้คะแนน

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

สำหรับแต่ละคู่ที่นักรบชนะจะได้รับ 2 คะแนน สำหรับการเสมอกันนักรบจะได้รับ 1 แต้ม

คุณได้รับอนุญาตให้ส่งนักสู้มากกว่าหนึ่งคน ใช้กฎทั่วไปสำหรับการส่งหลายครั้งเช่นไม่มีการแท็กทีมไม่มีการร่วมมือไม่มีการทำราชา ฯลฯ ไม่มีที่ว่างสำหรับเรื่องนี้ใน Core War แต่อย่างใดดังนั้นจึงไม่ควรเป็นเรื่องใหญ่

ผู้ควบคุม

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

บอทตัวอย่าง

นี่คือบอทตัวอย่างที่แสดงให้เห็นถึงคุณลักษณะบางอย่างของภาษา

main mov bomb #-1
     add @main main
     jmp #main 0
bomb dat 0 -1

บอทนี้ทำงานโดยการลบหน่วยความจำอื่น ๆ ทั้งหมดในแกนกลางอย่างช้าๆโดยแทนที่ด้วย "ระเบิด" เนื่องจากระเบิดเป็นDATคำสั่งโปรแกรมใด ๆ ที่ไปถึงระเบิดจะถูกทำลาย

มีป้ายกำกับสองบรรทัดคือ "หลัก" และ "ระเบิด" ซึ่งทำหน้าที่แทนหมายเลข หลังจากประมวลผลล่วงหน้าโปรแกรมจะมีลักษณะดังนี้:

MOV 3 #-1
ADD @-1 -1
JMP #0 0
DAT 0 -1

บรรทัดแรกคัดลอกระเบิดไปยังบรรทัดเหนือโปรแกรมทันที บรรทัดถัดไปจะเพิ่มมูลค่าของระเบิด ( 0 -1) ลงในคำสั่งย้ายและยังแสดงให้เห็นถึงการใช้@โหมดการกำหนดแอดเดรส การเพิ่มนี้ทำให้คำสั่ง move ชี้ไปที่เป้าหมายใหม่ คำสั่งถัดไปโดยไม่มีเงื่อนไขกระโดดกลับไปที่จุดเริ่มต้นของโปรแกรม


กระดานแต้มนำปัจจุบัน

24 - Turbo
22 - DwarvenEngineer
20 - HanShotFirst
18 - Dwarf
14 - ScanBomber
10 - Paranoid
10 - FirstTimer
10 - Janitor
10 - วิวัฒนาการ
6 - EasterBunny
6 - CopyPasta
4 - Imp
2 - Slug

ผลลัพธ์แบบคู่:

Dwarf > Imp
CopyPasta > Imp
Evolved > Imp
FirstTimer > Imp
Imp > Janitor
Imp > ScanBomber
Slug > Imp
DwarvenEngineer > Imp
HanShotFirst > Imp
Turbo > Imp
EasterBunny > Imp
Paranoid > Imp
Dwarf > CopyPasta
Dwarf > Evolved
Dwarf > FirstTimer
Dwarf > Janitor
Dwarf > ScanBomber
Dwarf > Slug
DwarvenEngineer > Dwarf
HanShotFirst > Dwarf
Turbo > Dwarf
Dwarf > EasterBunny
Dwarf > Paranoid
Evolved > CopyPasta
FirstTimer > CopyPasta
Janitor > CopyPasta
ScanBomber > CopyPasta
CopyPasta > Slug
DwarvenEngineer > CopyPasta
HanShotFirst > CopyPasta
Turbo > CopyPasta
CopyPasta > EasterBunny
Paranoid > CopyPasta
Evolved > FirstTimer
Evolved > Janitor
ScanBomber > Evolved
Evolved > Slug
DwarvenEngineer > Evolved
HanShotFirst > Evolved
Turbo > Evolved
EasterBunny > Evolved
Paranoid > Evolved
Janitor > FirstTimer
ScanBomber > FirstTimer
FirstTimer > Slug
DwarvenEngineer > FirstTimer
HanShotFirst > FirstTimer
Turbo > FirstTimer
FirstTimer > EasterBunny
FirstTimer > Paranoid
ScanBomber > Janitor
Janitor > Slug
DwarvenEngineer > Janitor
HanShotFirst > Janitor
Turbo > Janitor
Janitor > EasterBunny
Janitor > Paranoid
ScanBomber > Slug
DwarvenEngineer > ScanBomber
HanShotFirst > ScanBomber
Turbo > ScanBomber
ScanBomber > EasterBunny
ScanBomber > Paranoid
DwarvenEngineer > Slug
HanShotFirst > Slug
Turbo > Slug
EasterBunny > Slug
Paranoid > Slug
DwarvenEngineer > HanShotFirst
Turbo > DwarvenEngineer
DwarvenEngineer > EasterBunny
DwarvenEngineer > Paranoid
Turbo > HanShotFirst
HanShotFirst > EasterBunny
HanShotFirst > Paranoid
Turbo > EasterBunny
Turbo > Paranoid
Paranoid > EasterBunny

การอัปเดตล่าสุด (เวอร์ชั่นใหม่ของ Turbo และ Paranoid) ใช้เวลาประมาณ 5 นาทีในการเรียกใช้บนแล็ปท็อปเครื่องเก่า ฉันขอขอบคุณ Ilmari Karonen สำหรับการปรับปรุงตัวควบคุมของเขา หากคุณมีสำเนาของคอนโทรลเลอร์คุณควรอัพเดทไฟล์ของคุณ


จะเกิดอะไรขึ้นถ้าบอทคู่แข่งสองรายพยายามใช้ป้ายกำกับเดียวกัน
mbomb007

1
@ mbomb007 Labels เป็นสิ่งที่ประมวลผลล่วงหน้าและคำนวณเป็นไฟล์ต้นฉบับของ bot ที่กำลังถูกวิเคราะห์คำ ป้ายกำกับของคุณจะไม่ทำงานกับป้ายกำกับคู่แข่งใด ๆ
PhiNotPi

1
@ mbomb007 เพื่อให้โปรแกรมไม่ซ้อนทับกัน นอกจากนี้ฉันไม่ได้วางแผนที่จะเพิ่มคุณสมบัติใด ๆ เพิ่มเติมให้กับรุ่นนี้บันทึกสิ่งเหล่านั้นสำหรับ Micro Core War
PhiNotPi

1
@ mbomb007 การกำหนดแอดเดรสทางอ้อมอ้างอิงฟิลด์เดียวกันกับที่ทำการอ้างอิง (ที่ 1 หรือที่ 2) ไม่มีตัวดัดแปลงคำสั่ง ฉันไม่ได้อ้างอิงความท้าทายนี้จากมาตรฐาน '94
PhiNotPi

2
@Thrax ฉันจะบอกว่าไม่ว่าคุณจะไม่ จำกัด เพียงการส่งครั้งเดียว ใช้กฎการส่งหลายแบบทั่วไป (ไม่มีแท็กการรวมแท็ก ฯลฯ ) แม้ว่าจะมีพื้นที่ไม่มากนักสำหรับความร่วมมือในสงครามหลักอย่างไรก็ตาม
PhiNotPi

คำตอบ:


9

วิศวกร Dwarven

ดาวแคระใหม่ที่ได้รับการปรับปรุง ชนะกับทุกสิ่งที่ส่งมาแล้ว corestepแฟนซี - ขนาดขั้นตอนเพิ่มขึ้นอาจเป็น overkill ที่นี่

        MOV bomb    @aim
aim     MOV bomb    @-6326
        SUB step    aim
step    JMZ #0      6328
        MOV 0       1
bomb    DAT 0       3164

คุณสมบัติเด่น ได้แก่ การทิ้งระเบิดอย่างรวดเร็วที่ขว้างระเบิดสองลูกในรอบสี่เพื่อความเร็วการระเบิดเฉลี่ย 0.5c ในศัพท์แสงหลักของสงครามเก่าและการใช้JMZเพื่อตรวจจับเมื่อการทิ้งระเบิดเสร็จสิ้นและถึงเวลาเปลี่ยนแผน B ( นี่เปรต)


ฉันเคยเล่น Core War ย้อนกลับไปในยุค 90 (คุณบางคนอาจเคยเห็นหนังสือคู่มือพื้นฐานที่ฉันเขียนไว้ในปี 97) ดังนั้นฉันคิดว่ามันน่าสนใจที่จะดูว่ากลยุทธ์เก่า ๆ ของ RedCode '88 / '94 มีประโยชน์ในตัวแปรนี้

ความคิดแรกของฉันคือ:

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

  • จากนั้นอีกครั้งCMPการสแกนยังอาจเร็วกว่าการทิ้งระเบิดดังนั้นสแกนเนอร์ที่รวดเร็วจึงมีโอกาส

  • การขาด / ลดลงจะทำให้แกนล้างช้ามาก ในความเป็นจริงแกนกลางที่ชัดเจนในตัวแปรนี้ค่อนข้างจะเป็นแค่เครื่องบินทิ้งระเบิดที่มีขนาดสเต็ป (suboptimal) ที่± 1 อีกครั้งนี้ยังสแกนเนอร์เจ็บ; สแกนเนอร์ one-shot →กลยุทธ์เครื่องบินทิ้งระเบิดอาจทำงานได้

  • Quickscanners / quickbombers (กลยุทธ์ของเกมยุคแรกที่ใช้วงวนสแกน / วางระเบิดที่ไม่มีการควบคุมสำหรับผู้ที่ไม่คุ้นเคยกับ Core War Jargon) ยังคงมีประโยชน์ แต่สำหรับโปรแกรมที่มีความยาวเท่านั้น ผลที่นี่) ยากที่จะบอกว่ามันคุ้มค่ากับปัญหาหรือไม่

  • ระบบการให้คะแนนเป็นเรื่องที่น่าสนใจ ความสัมพันธ์คะแนนครึ่งเท่าคะแนนชนะ (มากกว่า 1/3 ในสงครามหลักดั้งเดิม) ทำให้พวกเขาน่าสนใจยิ่งขึ้น จากนั้นอีกครั้งเกี่ยวกับโปรแกรมเดียวที่น่าจะทำคะแนนได้มากภายใต้กฎเหล่านี้คือการแสดงผล (นอกจากนี้การไม่มีเดอ / เพิ่มขึ้นทำให้เกิดความยากลำบากดังนั้นแม้แต่อิมแพคง่าย ๆ ก็ยังมีโอกาสได้คะแนนเท่ากันถ้าพวกเขาไปถึงคู่ต่อสู้ที่ยังมีชีวิตอยู่)

  • นอกจากนี้เนื่องจากการจัดอันดับสุดท้ายขึ้นอยู่กับโปรแกรมที่คุณชนะเท่านั้นและไม่ว่าคุณจะเอาชนะพวกเขาไปเท่าใดมันจึงมีแนวโน้มที่จะสนับสนุนรายการทั่วไป จะดีกว่าที่เพิ่งชนะทั้งหมดของฝ่ายตรงข้ามของคุณมากกว่าที่จะทำลายโดยสิ้นเชิงครึ่งหนึ่งของพวกเขาและเพิ่งสูญเสียไปส่วนที่เหลือ

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

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

ณ จุดนั้นฉันใช้เวลามากเกินไปในการปรับแต่งและเพิ่มประสิทธิภาพรหัสล่ามของ PhiNotPi เพราะฉันคิดว่าฉันอาจต้องใช้การทดลองกำลังดุร้ายมากมายเพื่อปรับค่าคงที่ให้เหมาะสม ตามที่เกิดขึ้นฉันไม่เคยทำเช่นนั้น - รหัสด้านบนเป็นเวอร์ชั่นแรกที่ใช้งานได้จริงมาก (หลังจากความพยายามที่ล้มเหลวสองสามครั้งที่เพิ่งฆ่าตัวตายเนื่องจากข้อบกพร่องที่โง่)


เคล็ดลับที่ทำให้เครื่องบินทิ้งระเบิดเร็วของฉันคือการใช้ที่อยู่ทางอ้อมเพื่อทิ้งระเบิดสองลูกสำหรับแต่ละADDครั้ง นี่คือวิธีการทำงาน:

  1. MOV bomb @aimในรอบแรกที่เราดำเนินการ นี่เป็นการคัดลอกbombคำสั่งไปยังจุดศูนย์กลางของaimจุดB ไปยังจุดเริ่มต้น (6326 คำแนะนำก่อนหน้าaimนี้หรือ 6328 คำสั่งก่อนหน้าstepนี้คุณจะเห็นว่าทำไมตัวเลขเหล่านี้ถึงมีความสำคัญในภายหลัง)

  2. ในขั้นตอนต่อไปเราดำเนินการตามaimคำสั่งเอง! MOV bomb @-6326ในครั้งแรกผ่านก็มีลักษณะเช่นนี้ ดังนั้นจึงคัดลอกbombไปยังตำแหน่งที่ฟิลด์ B ของคำสั่งที่ 6326 บรรทัดก่อนที่จะชี้ไปที่

    ดังนั้นสิ่งที่มีที่ 6326 สายก่อนaim? ทำไมเป็นสำเนาของbombเราเพิ่งวางไว้ที่นั่นหนึ่งรอบก่อนหน้า! และเราเพิ่งจัดสิ่งต่าง ๆ เพื่อให้ B-field ของbombมีค่าไม่เป็นศูนย์ดังนั้นระเบิดใหม่จะไม่ถูกคัดลอกที่ด้านบนของเก่า แต่ห่างออกไป (ในความเป็นจริงที่นี่ระยะทางคือ 3164 ซึ่งเป็นครึ่งหนึ่งของขนาดขั้นตอนที่ระบุ 6328 ของเรา แต่การชดเชยอื่น ๆ อาจใช้งานได้

  3. ในรอบต่อไปเราปรับจุดมุ่งหมายของเราด้วยSUB step aimซึ่งหักค่าของstepการเรียนการสอน (ซึ่งยังเกิดขึ้นเป็นกระโดดที่เรากำลังจะดำเนินการต่อไปแม้ว่ามันจะได้รับเพียงแค่ง่ายDATที่ไหนสักแห่ง) aimจาก

    (หนึ่งรายละเอียดที่จะต้องทราบที่นี่เป็นที่ที่เราชนิดของต้องการ A-คุณค่าของการstepเป็นศูนย์เพื่อให้เรายังจะโยนระเบิดเดียวกันในการทำซ้ำต่อไปแม้ที่ไม่จำเป็นอย่างเคร่งครัดแม้ว่า. เพียงระเบิดโยน โดยคำสั่งแรกต้องมีฟิลด์ B เท่ากับ 3164 ส่วนที่เหลือสามารถเป็นอะไรก็ได้)

  4. ถัดไปJMZตรวจสอบว่าคำสั่ง 6328 ขั้นตอนที่อยู่ห่างจากมันยังคงเป็นศูนย์และถ้าเป็นเช่นนั้นกระโดดกลับไปที่ด้านบนของรหัส ตอนนี้ 6328 คือขนาดขั้นตอนของเครื่องบินทิ้งระเบิดของเราและหารด้วย 8 (แต่ไม่ใช่ 16) ดังนั้นถ้าเราเพิ่งทิ้งระเบิดทุก ๆ 6328 ก้าวในที่สุดเราก็กลับไปที่จุดเริ่มต้นโดยมีการทิ้งระเบิดทุกคำสั่งที่แปดในแกนกลาง (และด้วยระเบิดพิเศษชดเชย 3163 = 6328/2 ≡ 4 (mod 8) เราจะตีทุกคำสั่งที่สี่ )

    แต่เราเริ่มต้นระเบิดวิ่งของเราได้ที่ 6328 คำแนะนำก่อนJMZและก้าวไปข้างหลังโดย -6328 ในทุกซ้ำดังนั้นเรากำลังจะระเบิดสถานที่ 6328 ขั้นตอนหลังจากJMZเพียงหนึ่งซ้ำก่อนที่เราจะตีJMZตัวเอง ดังนั้นเมื่อJMZตรวจพบระเบิดที่คำสั่ง 6328 หลังจากนั้นมันเป็นสัญญาณว่าเราได้ครอบคลุมแกนหลักมากที่สุดเท่าที่เราสามารถทำได้โดยไม่ต้องกดปุ่มตัวเองและควรเปลี่ยนไปใช้กลยุทธ์การสำรองข้อมูลก่อนที่เราจะฆ่าตัวเอง

  5. สำหรับกลยุทธ์การสำรองข้อมูลมันเป็นเพียงแค่เด็กMOV 0 1ซนธรรมดาเพราะตอนนี้ฉันไม่สามารถคิดอะไรได้ดีไปกว่านี้แล้ว วิธีที่ฉันเห็นถ้าเราวางระเบิดทุกจุดที่สี่ของแกนกลางและยังไม่ชนะเราอาจต่อสู้กับบางสิ่งที่เล็กหรือป้องกันมากและอาจลองเอาตัวรอดและผูกเน็คไท ไม่เป็นไรเพราะโดยทั่วไปแล้วโปรแกรมขนาดเล็กหรือการป้องกันดังกล่าวจะไม่สามารถฆ่าสิ่งอื่นได้ดีนักและแม้ว่าเราจะชนะเพียงไม่กี่ครั้งโดยบังเอิญเราอาจยังออกมาข้างหน้า


ps ในกรณีที่คนอื่นต้องการมันนี่ฉันส้อมดีขึ้นเล็กน้อยของรหัสการแข่งขัน PhiNotPi ของ เร็วประมาณสองเท่าบันทึกผลการรบเก่าเพื่อที่คุณจะได้ไม่ต้องเรียกใช้ซ้ำอีกครั้งและแก้ไขสิ่งที่ฉันเชื่อว่าเป็นข้อบกพร่องเล็กน้อยในการคำนวณผลการรบ การเปลี่ยนแปลงที่ได้รับการรวมเข้ากับเวอร์ชั่นฉีดโดย PhiNotPi ขอบคุณ!


1
เพียงเท่านี้คุณก็รู้ว่าการให้คะแนนจะเป็นการทดสอบทุกสถานที่ที่เป็นจุดเริ่มต้นของโปรแกรมและโปรแกรมที่ทำคะแนนให้ได้มากที่สุด สิ่งนี้ทำให้ความสัมพันธ์เป็นไปไม่ได้หรือไม่เอื้ออำนวยอย่างสมบูรณ์เนื่องจากตราบใดที่โปรแกรมไม่เคยฆ่าตัวเองและทิ้งระเบิดอย่างน้อยหนึ่งที่อยู่ครั้งเดียวมันจะเอาชนะการรับรู้ได้รับชัยชนะและความสัมพันธ์ที่เหลือ
mbomb007

9

มุมมองกราฟ

สามารถใช้เป็นเครื่องมือแก้ไขข้อบกพร่องได้ จะแสดงหลักและแสดงตำแหน่งของผู้เล่น ในการใช้งานคุณต้องโทรจากรหัส ฉันยังให้การปรับเปลี่ยนGame.javaที่แสดง GraphView โดยอัตโนมัติ

PhiNotPi และ Ilmari Karonen เพิ่งเปลี่ยนคอนโทรลเลอร์ Ilmari Karonen ใจดีพอที่จะให้ GameView ที่อัปเดตแล้วที่สถานที่นี้

import javax.swing.*;
import java.awt.*;

public class GameView extends JComponent{

    final static Color[] commandColors = new Color[]{
            Color.black, //DAT
            Color.blue,  //MOV
            Color.blue,  //ADD
            Color.blue,  //SUB
            Color.blue,  //JMP
            Color.blue,  //JMZ
            Color.blue,  //CMP
    };

    final static Color[] specialColors = new Color[]{
            new Color(0,0,0),
            new Color(190, 255, 152),
            Color.yellow,
            new Color(0, 93, 14),
            new Color(96, 92, 4),
            new Color(0, 93, 14),
            new Color(96, 92, 4),
            new Color(0, 93, 14),
            new Color(96, 92, 4)
    };

    final static Color playerOneColor = Color.green;
    final static Color playerTwoColor = Color.white;

    final Game game;

    int playerOneLocation;
    int playerTwoLocation;

    final static int width = 128;
    final static int height = 64;

    public GameView(Game game) {
        this.game = game;
    }

    @Override
    public void paint(Graphics g) {
        int pixelWidth = getSize().width;
        int pixelHeight = getSize().height;
        if (width > pixelWidth){
            pixelWidth = width;
            setSize(width, pixelHeight);
        }
        if (height > pixelHeight){
            pixelHeight = height;
            setSize(pixelWidth, height);
        }
        int squareWidth = Math.min(pixelWidth / width, pixelHeight / height);
        for (int x = 0; x < squareWidth * width; x += squareWidth){
            for (int y = 0; y < squareWidth * height; y += squareWidth){
                int index = (y / squareWidth) * width + (x / squareWidth);
                Color color = commandColors[game.core[index][0]];
                if (game.coreData[index] != 0){
                    color = specialColors[game.coreData[index]];
                }
                if (index == playerOneLocation){
                    color = playerOneColor;
                }
                if (index == playerTwoLocation){
                    color = playerTwoColor;
                }
                g.setColor(color);
                g.fillRect(x, y, squareWidth, squareWidth);
            }
        }
    }

    public void setLocations(int p1loc, int p2loc){
        this.playerOneLocation = p1loc;
        this.playerTwoLocation = p2loc;
    }
}

ดัดแปลง Game.java:

import javax.swing.*;
import java.util.Random;
import java.util.ArrayList;
import java.util.Arrays;
/**
 * This runs a game of Core Wars between two players.  It can be called mutiple times.
 * 
 * @author PhiNotPi 
 * @version 3/10/15
 */
public class Game
{
    final Player p1;
    final Player p2;
    final int coreSize;
    final int coreSizeM1;
    final int maxTime;
    final int debug;
    public int[][] core;
    public int[] coreData; //Used in debugging.
    int offset1;
    int offset2;
    Random rand;
    ArrayList<int[]> p1code;
    ArrayList<int[]> p2code;
    int p1size;
    int p2size;
    GameView gameView;
    int time = 1000000; //Time in nanoseconds between frames
    public Game(Player A, Player B, int coreSize, int maxTime, int debug)
    {
        p1 = A;
        p2 = B;

        coreSize--;
        coreSize |= coreSize >> 1;
        coreSize |= coreSize >> 2;
        coreSize |= coreSize >> 4;
        coreSize |= coreSize >> 8;
        coreSize |= coreSize >> 16;
        coreSize++;

        this.coreSize = coreSize;
        this.coreSizeM1 = coreSize - 1;
        this.maxTime = maxTime / 2;
        this.debug = debug;
        core = new int[coreSize][5];
        rand = new Random();
        p1code =  p1.getCode();
        p1size = p1code.size();
        p2code =  p2.getCode();
        p2size = p2code.size();
        if (debug == 1){
            gameView = new GameView(this);
            JFrame frame = new JFrame("Game");
            frame.add(gameView);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            frame.setSize(128, 64);
            coreData = new int[coreSize];
        }
    }

    public int runAll()
    {
        int sum = 0;
        for(int i = 0; i < coreSize - p1size - p2size; i++)
        {
            sum += run(i) - 1;
        }
        if(sum > 0)
        {
            return 1;
        }
        if(sum < 0)
        {
            return -1;
        }
        return 0;
    }

    public int run()
    {
        return run(rand.nextInt(coreSize - p1size - p2size + 1));
    }

    public int run(int deltaOffset)
    {
        core = new int[coreSize][5];
        //offset1 = rand.nextInt(coreSize);
        offset1 = 0;
        for(int i = 0; i != p1size; i++)
        {
            //System.arraycopy(p1.getCode().get(i), 0, core[(offset1 + i) % coreSize], 0, 5 );
            int[] line = p1code.get(i);
            int loc = (offset1 + i) & coreSizeM1;
            core[loc][0] = line[0];
            core[loc][1] = line[1];
            core[loc][2] = line[2];
            core[loc][3] = line[3];
            core[loc][4] = line[4];
            if (debug != 0){
                coreData[loc] = 1;
            }
        }
        offset2 = offset1 + p1size + deltaOffset;
        for(int i = 0; i != p2size; i++)
        {
            //System.arraycopy(p2.getCode().get(i), 0, core[(offset2 + i) % coreSize], 0, 5 );
            int[] line = p2code.get(i);
            int loc = (offset2 + i) & coreSizeM1;
            core[loc][0] = line[0];
            core[loc][1] = line[1];
            core[loc][2] = line[2];
            core[loc][3] = line[3];
            core[loc][4] = line[4];
            if (debug != 0){
                coreData[loc] = 2;
            }
        }

        int p1loc = offset1 & coreSizeM1;
        int p2loc = offset2 & coreSizeM1;
        for(int time = 0; time != maxTime; time++)
        {
            if(debug != 0)
            {
                //printCore(p1loc,p2loc);
                //System.out.println("p1loc " + p1loc);
                //System.out.println("offset " + offset1);
                gameView.setLocations(p1loc, p2loc);
                gameView.repaint();
                try {
                    Thread.sleep(time / 1000000, time % 1000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if(core[p1loc][0] == 0)
            {
                return 0;
            }
            p1loc = execute(p1loc, offset1, 1);

            if(debug != 0)
            {
                //printCore(p1loc,p2loc);
                //System.out.println("p2loc " + p2loc);
                //System.out.println("offset " + offset2);
                gameView.setLocations(p1loc, p2loc);
                gameView.repaint();
                /*try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
            }
            if(core[p2loc][0] == 0)
            {
                return 2;
            }
            p2loc = execute(p2loc, offset2, 2);

        }
        return 1;
    }
    public int execute(int ploc, int offset, int player)
    {
        int line1 = offset + core[ploc][3];
        if(core[ploc][1] != 0)
        {
            line1 += ploc - offset;
        }
        if(core[ploc][1] == 2)
        {
            line1 += core[line1 & coreSizeM1][3];
        }
        int line2 = offset + core[ploc][4];
        if(core[ploc][2] != 0)
        {
            line2 += ploc - offset;
        }
        if(core[ploc][2] == 2)
        {
            line2 += core[line2 & coreSizeM1][4];
        }
        line1 = line1 & coreSizeM1;
        line2 = line2 & coreSizeM1;
        int opcode = core[ploc][0];
        ploc = (ploc + 1) & coreSizeM1;
        //String opDescription = "";
        if(opcode == 1)
        {
            core[line2][0] = core[line1][0];
            core[line2][1] = core[line1][1];
            core[line2][2] = core[line1][2];
            core[line2][3] = core[line1][3];
            core[line2][4] = core[line1][4];
            if (debug != 0) {
                coreData[line2] = player + 2;
            }
            return ploc;
            //opDescription = "Moved from " + line1 + " to " + line2;
        }
        if(opcode == 2)
        {
            core[line2][3] += core[line1][3];
            core[line2][4] += core[line1][4];
            if (debug != 0) {
                coreData[line2] = player + 4;
            }
            return ploc;
            //opDescription = "Added " + line1 + " to " + line2;
        }
        if(opcode == 3)
        {
            core[line2][3] -= core[line1][3];
            core[line2][4] -= core[line1][4];
            if (debug != 0) {
                coreData[line2] = player + 6;
            }
            return ploc;
                //opDescription = "Subtracted " + line1 + " to " + line2;
        }
        if(opcode == 4)
        {
            ploc = line1;
            return ploc;
                //opDescription = "Jumped to " + line1;
        }
        if(opcode == 5)
        {
                if(core[line2][3] == 0 && core[line2][4] == 0)
                {
                    ploc = line1;
                    //opDescription = "Jumped to " + line1;
                }
                else
                {
                    //opDescription = "Did not jump to " + line1;
                }
                return ploc;
        }
        if(opcode == 6)
        {
            if(core[line1][3] == core[line2][3] && core[line1][4] == core[line2][4])
            {
                //opDescription = "Did not skip because " + line1 + " and " + line2 + " were equal.";
            }
            else
            {
                ploc = (ploc + 1) & coreSizeM1;
                //opDescription = "Skipped because " + line1 + " and " + line2 + " were not equal.";
            }
            return ploc;
        }
        if(debug != 0)
        {
            //System.out.println(opDescription);
        }
        return ploc;
    }
    /*public void printCore(int p1loc, int p2loc)
    {
        int dupCount = 0;
        int[] dupLine = new int[]{0,0,0,0,0};
        for(int i = 0; i < core.length; i++)
        {
            int[] line = core[i];
            if(Arrays.equals(line, dupLine) && i != p1loc && i != p2loc)
            {
                if(dupCount == 0)
                {
                    System.out.println(Player.toString(line));
                }
                dupCount++;
            }
            else
            {
                if(dupCount == 2)
                {
                    System.out.println(Player.toString(dupLine));
                }
                else if(dupCount > 2)
                {
                    System.out.println("    " + (dupCount - 1) + " lines skipped.");
                }
                System.out.println(Player.toString(line));
                if(i == p1loc)
                {
                    System.out.print(" <- 1");
                }
                if(i == p2loc)
                {
                    System.out.print(" <- 2");
                }
                dupLine = line;
                dupCount = 1;
            }
        }
        if(dupCount == 2)
        {
            System.out.println(Player.toString(dupLine));
        }
        else if(dupCount > 2)
        {
            System.out.println("    " + (dupCount - 1) + " lines skipped.");
        }
    }*/
}

ดูเหมือนว่าคุณจะทำการดัดแปลงกับ Player เช่นกัน ฉันได้รับ./Game.java:275: error: method toString in class Object cannot be applied to given types; System.out.println(Player.toString(line)); ^ required: no arguments found: int[]
AShelly

@Ashelly ขออภัยเกี่ยวกับเรื่องนั้น ฉันควรแสดงความคิดเห็นprintCore()วิธีการ
TheNumberOne

9

กังหัน

main   add three target
test   jmz -1 @target
bomb   mov three @target
       sub j1 target 
       mov jump @target
       sub j1 target 
       mov copy @target
       sub j1 target
two    mov decr @target
j1     jmp @target 1
target dat -8 -8   
decr   sub #two 3
copy   mov 2 @2
jump   jmp -2 0
three dat -9 -9

ความพยายาม CoreWar ครั้งที่ 2 ของฉัน ออกแบบมาเพื่อเอาชนะคนแคระ สแกนข้อมูล 3 ครั้งจากนั้นจึงวางระเบิดทุก ๆ 2 แต่ละขั้นตอนจะดำเนินการใน 3 คำสั่งด้วยความหวังว่าระเบิดของคนแคระจะพลาด

ใหม่ Turbo ++ : ปรับปรุงแล้ว มันจะสแกนไปข้างหลังจนกระทั่งพบข้อมูลจากนั้นย้ายตัวเองไปที่นั่นแล้วระเบิดไปข้างหลัง ความหวังก็คือการเคลื่อนไหวนั้นจะขัดขวางคู่ต่อสู้หรือไปยังสถานที่ที่ทิ้งระเบิดแล้วและปลอดภัย (ish)

... และการแก้ไขเพื่อให้สแกนได้มากขึ้นจะทำให้ทุกคนชนะ!


ดูเหมือนว่าจะชนะมากกว่าคนแคระ ขอแสดงความยินดี! ฉันคิดว่าคุณสามารถไปถึงอันดับสามได้หากคุณสามารถเอาชนะ Imp ได้
Ilmari Karonen

ฉันอัปเดตอันนี้ แต่จริงๆแล้วมันเป็นวิวัฒนาการที่ค่อนข้างใหญ่จากอันที่แล้ว ฉันควรทำรายการใหม่แทนหรือไม่?
AShelly

ฉันไม่คิดว่าจะพูดกับพี่นภา แต่ฉันคิดว่ามันขึ้นอยู่กับคุณ การอัปเดตในสถานที่โดยพื้นฐานแล้วหมายถึงการถอนรายการเก่าของคุณ ยังไงก็ตามขอแสดงความยินดีกับการทิ้งระเบิดให้สำเร็จในอันดับที่สาม! ฉันคิดว่าคุณเป็นคนเดียวที่เอาชนะ DwarvenEngineer ได้
Ilmari Karonen

ทำได้ดี ;). คุณเป็นคนที่จะต้องเอาชนะในตอนนี้!
กด

8

แคระ

โปรแกรมทั่วไปและเรียบง่ายที่แสดงถึงการขว้างก้อนหินแคระ มันวางDATคำสั่งทุกสี่ที่อยู่

add 2 3
mov 2 @2
jmp -2 #4
dat #0 #4

แก้ไข: แก้ไขที่อยู่ เห็นได้ชัดว่าโหมดการกำหนดแอดเดรสนั้นแตกต่างจากสเป็คของ OP ที่เชื่อมโยงกับ


ฉันคิดว่ามันคือ "เพิ่ม # 3 3" สำหรับบรรทัดแรกใช่ไหม
ตี

@Hit Nope ฉันต้องการที่จะตีทุกที่อยู่ 4 ฉันสามารถใช้add 3 3แต่แล้วมันจะเป็นสองเท่าของแต่ละวงแทนที่จะเพิ่มและนั่นจะไม่เป็นประโยชน์ #4เป็นแบบทันทีดังนั้นจึงเพิ่มจำนวน4เป็นค่าที่ 2 ในที่อยู่ที่อยู่3หลังที่อยู่ปัจจุบัน
mbomb007

ฉันคิดว่าคุณกำลังตีความ#โหมดที่อยู่ผิด ๆในความท้าทาย ตามที่ระบุไว้ในข้อมูลจำเพาะฉันได้ทำการเปลี่ยนเป็น#โหมดการกำหนดแอดเดรส
PhiNotPi

คุณควรไปเช่น: "เพิ่ม 2 3 mov 2 @ 2 jmp -2 4 dat 0 4"
Hit

ด้วยพฤติกรรมที่ถูกต้องมันยังเอาชนะการพัฒนา
Hit

7

วิวัฒน์

ฉันไม่เข้าใจว่ามันทำงานอย่างไร ดูเหมือนว่าจะสร้างซอร์สโค้ดก่อนที่จะทำอะไร ฉันจะรักมันถ้ามีคนอธิบายให้ฉันฟังว่ามันทำงานยังไง

หลังจากศึกษามันฉันพบว่ามันเป็นเพียงแค่ดาวแคระที่ปรับแต่งพร้อมตัวป้องกัน แทนที่จะทำการทิ้งระเบิดศัตรูด้วยDATคำแนะนำมันจะสับรหัสศัตรู มันยังวางระเบิดทุก ๆ สองรีจิสเตอร์แทนที่จะเป็นทุก ๆ เมื่อให้เวลาพอมันจะทำลายตัวเองอย่างไม่ต้องสงสัย

MOV -2 #-1
MOV #4 -9
SUB -5 #6
MOV #1 1
MOV #-6 #4
SUB @8 @7
JMP -3 @4
DAT #-4 8
JMP -1 9
JMP 5 #-10
CMP @-1 #0
SUB 3 #-10
JMP @10 #-9
JMZ #1 10
MOV #3 2
ADD @9 @-3
CMP #-3 @7
DAT @0 @-2
JMP @-7 #6
DAT @-8 -6
MOV @0 #9
MOV #2 1
DAT @6882 #-10
JMP @3 4
CMP @8 2
ADD -7 @11
ADD @1 #-9
JMZ @-5 7
CMP 11 5526
MOV @8 6
SUB -6 @0
JMP 1 11
ADD @-3 #-8
JMZ @-14 @-5
ADD 0 @-8
SUB #3 @9
JMP #-1 5
JMP #9 @1
CMP -9 @0
SUB #4 #-2
JMP #-8 5
DAT -1 @-10
MOV 6 #2
CMP @-11 #-14
ADD @4 @-3
MOV @5 #-6
SUB -3 -2
DAT @-10 #-1
MOV #-13 #-6
MOV #1 5
ADD 5 #-5
MOV -8 @-1
DAT 0 10
DAT #5 #7
JMZ 6 -5
JMZ -12 -11
JMP 5 @-7
MOV #7 -3
SUB #-7 @-3
JMP -4 @-11
CMP @-5 #-2
JMZ @-1 #0
ADD #3 #2
MOV #5 @-6

1
แล้วคุณได้รับมาจากไหน
PyRulez

4
@PyRulez คอมพิวเตอร์สร้างขึ้นโดยใช้อัลกอริทึมทางพันธุกรรม
TheNumberOne

1
ดูเหมือนว่าการประมวลผลจะไม่คืบหน้าไปไกลกว่าบรรทัด # 6 เนื่องจากมีการข้ามไปในโปรแกรม ฉันเชื่อว่าเหตุผลที่ทำให้สำเร็จคือมีการเคลื่อนไหว / วนซ้ำมากกว่าคู่แข่ง
PhiNotPi

6

FirstTimer

หากใช้งานได้ก็ควรพยายามเข้ารับตำแหน่งที่จุดเริ่มต้นของแกนกลางและสร้างแนวรับ

main MOV 5 #0
     ADD #data #main
     CMP #main #max
     JMP #0 0
     JMP #main 0
     MOV #data #100
     ADD #data -1
     JMP -2 0
data DAT 1 1
max  DAT 8 3

มันไม่ทำงานอย่างที่ฉันคิดว่าคุณคิดว่ามันจะ: #0หมายถึงจุดเริ่มต้นของโปรแกรมของคุณ (เช่นเดียวกับ#main) ไม่ใช่จุดเริ่มต้นของแกนกลาง (ซึ่งไม่ใช่แนวคิดที่มีความหมายจริงๆ - หลักคือ วงกลมรหัสของคุณไม่สามารถบอกได้ว่ามันจะเริ่มหรือสิ้นสุด) สิ่งที่เกิดขึ้นคือคำสั่งแรกของคุณ ( main) เขียนทับตัวเองด้วยMOV #data #100หลังจากนั้นรหัสของคุณจะกลายเป็นแกนหลักไปข้างหน้า 0.25c (= หนึ่งคำสั่งต่อสี่รอบ)
Ilmari Karonen

@IlmariKaronen โอ้ขอบคุณสำหรับการอธิบาย ฉันทำผิดพลาด#0สำหรับการเริ่มต้นของแกน 5 คำแนะนำแรกนั้นไร้ประโยชน์อย่างสมบูรณ์แล้ว
Thrax

6

CopyPasta

ไม่เคยเข้าร่วม CoreWar โปรแกรมง่ายๆนี้กำลังพยายามคัดลอกตัวเองแล้วดำเนินการคัดลอก มันอาจมีพฤติกรรมที่ไม่ถูกต้องโปรดบอกฉันว่ามันเป็นอย่างนั้นหรือเปล่า

มันเป็นสิ่งที่สงบเกินไปและไม่สามารถชนะได้ในความเป็นจริง

MOV 6 0
MOV @-1 @-1
CMP @-2 3
JMP 4242 0
SUB -3 -4
JMP -4 0
DAT 0 4244

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

โอเค :) เวอร์ชั่นที่เก่ากว่าไม่ออกจากลูป 1 มันไม่ใช่พฤติกรรมที่ต้องการจริงๆฉันพยายามแก้ไขมัน
Hit

ดูเหมือนเวอร์ชันปัจจุบันจะใช้งานไม่ได้ ฉันไม่รู้ว่าทำไม
PhiNotPi

1
ฉันได้ปรับปรุงเครื่องมือตรวจแก้จุดบกพร่องดังนั้นตอนนี้ฉันสามารถวินิจฉัยปัญหาได้ สิ่งที่เกิดขึ้นคือโปรแกรมคัดลอกเฉพาะส่วนที่สองของตัวเอง (เริ่มต้นที่JMP loop 0) จากนั้นเมื่อมันข้ามไปที่จุดเริ่มต้นของการคัดลอกมันเป็นเพียงพื้นที่ว่างและจะสูญเสีย
PhiNotPi

2
โปรดละเว้นความคิดเห็นก่อนหน้าของฉัน (ลบตอนนี้); ฉันทดสอบโค้ดของคุณในเวอร์ชันที่ไม่ถูกต้อง (เป็นเรื่องผิดพลาดเนื่องจากความผิดพลาดจากการคัดลอกวาง) ซึ่งเป็นสาเหตุที่ทำให้ฉันทำงานได้ไม่ดี
Ilmari Karonen

6

ภารโรง

ควรตรวจสอบว่าที่อยู่ต่อไปนี้ว่างเปล่าหรือไม่และถ้าไม่ล้างมัน (เช่นนั้นหวังว่าจะลบบอทของคู่ต่อสู้)

แก้ไข:เวอร์ชันใหม่นี้ควรเร็วขึ้น (ตอนนี้ฉันเข้าใจJMZคำสั่งและการ@อ้างอิงอย่างถูกต้องแล้ว)

JMZ 2 6
MOV 4 @-1
ADD 2 -2
JMP -3 0
DAT 0 1
DAT 0 0

ภารโรงไม่ได้ฆ่าตัวตายด้วย JMZ แรกหรือไม่? อย่างน้อยก็ควรเป็น JMZ 2 8 วิธีการใช้ @ คุณสามารถลดการเพิ่มสองรายการลงในอันเดียวได้ บางสิ่งที่ชอบ: "JMZ 2 @ 5 MOV 5 @ 4 เพิ่ม 2 3 JMP -3 0 DAT 0 1 DAT 0 2 DAT 0 0" (ยังไม่ทดลอง)
กด

@ มันไม่ได้กระโดดเพราะที่อยู่ 2 จากที่นั่นADD 3 -2แต่คุณคิดถูกว่าเขาควรจะเปลี่ยนฉันคิดว่า
mbomb007

ใช่ฉันอ่านคำสั่งผิดJMZและคิดว่าJMZ A BกำลังตรวจสอบAและกระโดดไปที่B0 เมื่อเห็นได้ชัดว่ามันตรงกันข้าม ขอบคุณสำหรับการสังเกตเห็นเพราะผมไม่ได้ :)
plannapus

5

ScanBomber

ลบความคิดเห็นของฉันก่อนรวบรวม สแกนครู่หนึ่งแล้วระเบิดเมื่อพบโปรแกรม แม้ว่ามันจะยังคงสูญเสียให้กับคนแคระของฉัน

scan add #eight #range  ; scan
jmz #scan @range
sub #six #range
fire mov #zero @range   ; bombs away! (-6)
add #two #range
mov #zero @range
add #two #range
mov #zero @range
add #two #range
mov #zero @range        ; (+0)
add #two #range
mov #zero @range
add #two #range
mov #zero @range
add #two #range
mov #zero @range
add #two #range
mov #zero @range        ; (+8)
range jmp #scan 6
two dat 0 2
six dat 0 6
zero dat 0 0
eight dat 0 8

OP กำหนดไว้#อย่างสมบูรณ์แตกต่างจากสเป็คอย่างสมบูรณ์ (อ่านลิงก์ที่เขาลิงก์) ฉันยังไม่ได้แก้ไขโปรแกรมนี้
mbomb007

@TheBestOne ฉันคิดว่าฉันคงมัน ตอนนี้มันดูสมเหตุสมผลหรือไม่? หรือฉันต้องใส่#ก่อนอ้างอิงทุกครั้งzero? ใช่ฉันคิดว่าฉันต้อง ...
mbomb007

มันทำงานได้ดีในขณะนี้ มันเต้นทุกบอทยกเว้น Dwarf และ Imp
TheNumberOne

@TheBestOne Dwarf เล็กเกินไปและจะตรวจพบได้เพียง 50% ของการจัดวางโปรแกรมที่เป็นไปได้ มันน่าจะสูญเสีย Imp เพียงเพราะมันระเบิดตัวเองหลังจากที่ไปรอบ ๆ หน่วยความจำทั้งหมด
mbomb007

5

ฮันช็อตแรก (v2)

ฉันคิดว่าการแข่งขันสามารถใช้ความหลากหลายมากขึ้นดังนั้นนี่คือรายการที่สองของฉัน: CMPสแกนเนอร์แบบนัดเดียว

นี่คือรุ่น 2 ที่มีการป้องกันการต่อต้านแบบปรับปรุงที่ดีขึ้น - ตอนนี้มันสามารถเอาชนะ Imp ได้เพียงแค่จุดเดียวเท่านั้น มันยังคงสูญเสียไปให้กับ Dwarven Engineer แต่ก็ยังเอาชนะทุกสิ่งทุกอย่างได้

scan    ADD bomb    aim
aim     CMP 17      12
        JMZ scan    #-3
loop    MOV bomb    @aim
        ADD step    aim
step    JMP loop    #2
bomb    DAT 10      10

มันทำงานได้โดยการเปรียบเทียบตำแหน่งหลักที่อยู่ติดกัน 5 ขั้นตอนเป็นระยะ 10 ขั้นตอนจนกระทั่งพบความแตกต่าง เมื่อมันเกิดขึ้นมันจะเริ่มขว้างระเบิดเป็นระยะ 2 ขั้นตอนจนกระทั่งมันฆ่าฝ่ายตรงข้ามหรือวนรอบทุกรอบแกนกลางเพื่อเข้าถึงตัวมันเอง

หากการสแกนทำ ไม่พบสิ่งใดในที่สุดก็จะวนไปรอบ ๆ และค้นหารหัสของตัวเองและโจมตี นี่จะเป็นการฆ่าตัวตาย แต่สำหรับเรื่องบังเอิญโชคดีที่ระเบิดลูกแรกตกลงมาอย่างตรงไปตรงมาaimทำให้เกิดการระเบิดครั้งต่อไปที่จะถูกโยน 12 ตำแหน่ง (มากกว่า 2 ปกติ) ลงไปในแกนกลาง (สิ่งนี้เกิดขึ้นกับความน่าจะเป็น 50% หากการสแกนพบบางอย่าง แต่ไม่สามารถฆ่าฝ่ายตรงข้ามได้) เนื่องจากขนาดแกนกลางเป็นทวีคูณของสองสิ่งนี้จะเกิดขึ้นเช่นกันหากการทิ้งระเบิดรอบลูปทำให้ไม่จำเป็นต้อง กลยุทธ์การสำรองข้อมูลเพิ่มเติม

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



4

กระสุน

     mov    ones    @-1024
     mov    from    -3
     mov    here    -3
loop mov    @-5 @-4
     add    ones  -5
     jmz    -17 -6
     add    ones  -8    
     jmp    loop    42
ones dat    1   1
from dat    2   2
here dat    -11 -11

คลานผ่านพื้นที่หน่วยความจำด้านหลัง บางครั้งจะทิ้งระเบิดไกลออกไป


3

กระต่ายอีสเตอร์

เขาสนุกกับการกระโดดไปข้างหลัง :)

loop mov 0 -10
     add data loop
     cmp -7 data
     jmp -13 0
     jmp loop 0
data dat 1 1

3

หวาดระแวง

ชนิดของการคัดลอกพาสต้า แต่จะตรวจสอบว่ารหัสได้รับการแก้ไขโดยการทิ้งระเบิดหรือไม่ ถ้าเป็นเช่นนั้นก็จะคัดลอกดาวแคระและดำเนินการมัน หากฉันจัดการสร้าง GameView อีกครั้งฉันจะพยายามเปลี่ยนค่าคงที่บางส่วน

copy    MOV data copy
loop    MOV @-1 @-1
    CMP @copy end
out JMP check 0
    SUB loop copy
    JMP loop 0
data    DAT 0 4109
check   MOV data copy
loop2   CMP @copy @copy
    JMP ok 0
    MOV aah 2
ok  CMP @copy end
    JMP 4098 0
    SUB loop copy
    JMP loop2 0
panic   MOV end copy
    MOV jump out
    JMP loop 0
jump    JMP 4124 0
dwarf   ADD 2 bomb
    MOV bomb @bomb
    JMP dwarf 4
bomb    DAT 0 4
aah JMP 3 0
end DAT 19 4127

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