นี่คือการดัดแปลงของCore Warซึ่งเป็นโปรแกรม KOTH ย้อนหลังไปถึงศตวรรษที่ 20 การจะมีความเฉพาะเจาะจงมากขึ้นก็จะใช้ชุดคำสั่งง่ายอย่างไม่น่าเชื่อตามหลักออกจากข้อเสนอเดิม
พื้นหลัง
ใน Core War มีสองโปรแกรมที่ต่อสู้เพื่อควบคุมคอมพิวเตอร์ เป้าหมายของแต่ละโปรแกรมคือการชนะโดยการค้นหาและยุติโปรแกรมที่เป็นปฏิปักษ์
การต่อสู้เกิดขึ้นภายในหน่วยความจำหลักของคอมพิวเตอร์ หน่วยความจำนี้เรียกว่าแกนและมีที่อยู่ 8192 เมื่อการต่อสู้เริ่มต้นขึ้นรหัสสำหรับผู้แข่งขันแต่ละคน (เรียกว่านักรบ) จะถูกวางในหน่วยความจำแบบสุ่ม การดำเนินการโปรแกรมสลับกันระหว่างนักรบโดยปฏิบัติหนึ่งคำสั่งของแต่ละนักรบ แต่ละคำสั่งมีความสามารถในการปรับเปลี่ยนส่วนหนึ่งของแกนนำไปสู่ความเป็นไปได้ของโปรแกรมปรับเปลี่ยนด้วยตนเอง
เป้าหมายคือการยุติโปรแกรมฝ่ายตรงข้าม โปรแกรมจะหยุดทำงานเมื่อพยายามเรียกใช้คำสั่งที่ไม่ถูกต้องซึ่งเป็นDAT
คำสั่งใด ๆ
ชุดคำสั่ง
แต่ละโปรแกรมประกอบด้วยชุดคำสั่งระดับต่ำซึ่งแต่ละโปรแกรมใช้สองฟิลด์เรียกว่าฟิลด์ A และ B
ชุดคำสั่งนี้ดึงมาจากสเป็คดั้งเดิมมาก การเปลี่ยนแปลงที่สำคัญคือ 1) การชี้แจงเกี่ยวกับคำสั่งการเพิ่ม / การลบและ 2) การเปลี่ยนแปลงของ#
โหมดการกำหนดแอดเดรสเพื่อให้สามารถใช้งานได้ทุกที่ Core Wars เวอร์ชันเต็มส่วนใหญ่มี opcode มากกว่า 20 โหมดโหมดการกำหนดแอดเดรส 8 โหมดและชุด "คำแนะนำการปรับเปลี่ยน"
opcodes
แต่ละคำสั่งจะต้องมีหนึ่งในเจ็ดรหัสที่แตกต่างกัน
DAT A B
- (ข้อมูล) - นี้ก็ถือเป็นตัวเลขและA
B
ที่สำคัญกระบวนการจะหยุดทำงานเมื่อพยายามเรียกใช้คำสั่ง DATMOV 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
เป็น 0A
แล้วโปรแกรมกระโดดไปยังสถานที่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 สำหรับการปรับปรุงตัวควบคุมของเขา หากคุณมีสำเนาของคอนโทรลเลอร์คุณควรอัพเดทไฟล์ของคุณ