ลีดเดอร์บอร์ด
154 Calculator
144 Taxman
138 Statistician
137 Solver
137 RandoAggroLawyer
136 Gambler
134 Turncoat
119 Lawyer
119 BloodyMurder
113 Bandit
79 Challenger
74 Mask
64 Random
การเก็บถาวรของการจับคู่ล่าสุดรวมถึงบันทึกและไฟล์เอาต์พุตทั้งหมดจะพร้อมใช้งาน
เครื่องคิดเลขโดย Brilliand เป็นผู้ชนะ! คำตอบของเขาได้รับการยอมรับ แต่นั่นไม่ได้หมายความว่าความท้าทายจะจบลง รู้สึกอิสระที่จะส่งรายการใหม่หรือแก้ไขรายการปัจจุบันของคุณและพยายามที่จะทำให้เขาล้มบัลลังก์ ฉันจะให้รางวัลแก่หัวหน้าเมื่อสิ้นเดือน
กฎการเล่น
รัฐประหารเป็นเกมไพ่ที่ออกแบบมาสำหรับผู้เล่น 2-6 คนซึ่งเราจะเล่นด้วยกันสองคน ประกอบด้วยเหรียญกษาปณ์ (ไม่มีที่สิ้นสุดเพื่อจุดประสงค์ของเรา) และสำรับไพ่ 15 ใบซึ่งประกอบด้วย 3 ประเภทดังต่อไปนี้: เอกอัครราชทูตนักฆ่ากัปตันคอนเทสซาดยุค ในช่วงเริ่มต้นของเกมผู้เล่นแต่ละคนจะได้รับเหรียญหนึ่งใบและแจกไพ่สองใบโดยการสุ่มซึ่งพวกเขาเก็บเป็นความลับจนกว่าจะมีความจำเป็น เป้าหมายคือผู้เล่นคนสุดท้ายที่มีไพ่ในมือคุณ
ผู้เล่นอาจทำสิ่งใดสิ่งหนึ่งต่อไปนี้โดยไม่คำนึงถึงไพ่:
- รายได้: รับ 1 เหรียญจากคลัง ยกเลิกการปิดกั้นและไม่สามารถแก้แค้นได้
- ความช่วยเหลือจากต่างประเทศ: รับ 2 เหรียญจากคลัง สามารถถูกบล็อกโดยผู้เล่นที่มี Duke ทักท้วงไม่ได้
- รัฐประหาร: นำการ์ดของฝ่ายตรงข้ามที่คุณเลือกออกจากการเล่น ราคา 7 เหรียญ ผู้ที่ตกเป็นเหยื่ออาจเลือกบัตรที่จะทิ้ง หากผู้เล่นมี 10 เหรียญขึ้นไปในช่วงเริ่มต้นของการเปิดพวกเขาจะต้องรัฐประหาร ยกเลิกการปิดกั้นและไม่สามารถแก้แค้นได้
ผู้เล่นอาจดำเนินการอย่างใดอย่างหนึ่งดังต่อไปนี้ขึ้นอยู่กับไพ่ของพวกเขา:
- แลกเปลี่ยน: ผู้เล่นที่มีเอกอัครราชทูตอาจรับไพ่สองใบจากสำรับ จากนั้นพวกเขาอาจเลือกจากมือของพวกเขาและไพ่ที่ถูกดึงมากเท่าที่พวกเขามี (นั่นคือถ้าพวกเขามีไพ่เพียงใบเดียวพวกเขาอาจแลกเปลี่ยนเป็นหนึ่งในไพ่ที่ดึงออกมาหรือเก็บไว้และถ้าพวกเขามีไพ่สองใบพวกเขาอาจเลือกไพ่สองในสี่ใบใดก็ได้) ไพ่ที่ไม่พึงประสงค์สองใบจะถูกส่งกลับไปที่ดาดฟ้า . เลิกบล็อกได้ แต่ท้าทายได้
- Assassinate: ผู้เล่นที่มี Assassin อาจใช้จ่าย 3 เหรียญเพื่อนำการ์ดของฝ่ายตรงข้ามออกจากเกม ผู้ที่ตกเป็นเหยื่ออาจเลือกบัตรที่จะทิ้ง สามารถถูกบล็อกโดยผู้เล่นที่มี Contessa ซึ่งในกรณีนี้เหรียญจะไม่ถูกส่งคืน ท้าทายได้ในกรณีที่เหรียญถูกส่งคืน
- Steal: ผู้เล่นที่มี Captain อาจใช้สองเหรียญจากคู่ต่อสู้ หากฝ่ายตรงข้ามมีหนึ่งเหรียญพวกเขาจะรับเหรียญนั้น หากฝ่ายตรงข้ามมีเหรียญศูนย์พวกเขาอาจไม่ขโมย สามารถถูกบล็อกโดยผู้เล่นที่มีเอกอัครราชทูตหรือกัปตัน คัดค้านตุลาการ
- ภาษี: ผู้เล่นที่มี Duke อาจใช้เวลา 3 เหรียญจากคลัง เลิกบล็อกได้ แต่ท้าทายได้
ส่วนที่ยุ่งยากของการรัฐประหารคือผู้เล่นได้รับอนุญาตให้โกหกเกี่ยวกับการ์ดที่พวกเขามี! หนึ่งไม่จำเป็นต้องมีการ์ดเพื่อพยายามดำเนินการหรือบล็อกที่เกี่ยวข้องกับมัน
เมื่อผู้เล่นทำการกระทำของการ์ดฝ่ายตรงข้ามใด ๆ (แม้แต่ผู้ที่ไม่ได้รับอันตรายจากการกระทำนั้น) อาจท้าทายนักแสดงและบอกว่าพวกเขาไม่เชื่อว่าพวกเขามีการ์ดสำหรับการกระทำนั้น หากผู้ท้าชิงถูกต้องการกระทำจะถูกยกเลิกและนักแสดงจะต้องทิ้งการ์ดใบเดียวที่พวกเขาเลือก (คืนเหรียญใด ๆ ที่พวกเขาใช้ถ้ามี) หากไม่มีการดำเนินการนักแสดงจะคืนบัตรที่พวกเขาถูกท้าทายไปที่ดาดฟ้าและดึงการ์ดใบใหม่ออกมาและผู้ท้าชิงจะต้องทิ้งการ์ดใบใดใบหนึ่งของพวกเขา ผู้เล่นจะต้องซื่อสัตย์เกี่ยวกับสิ่งที่พวกเขาถือบัตรเมื่อถูกท้าทาย
การ์ดที่ถูกตัดออกจากการเล่นกับ Assassinate, Coup และการท้าทายที่หายไปจะไม่ถูกส่งกลับไปที่เด็ค แต่การ์ดที่เปิดเผยว่าเป็นส่วนหนึ่งของการท้าทายที่ชนะจะถูกส่งกลับไปที่เด็ค
บล็อกอาจถูกท้าทายเช่นเดียวกับการกระทำ ตัวอย่างเช่นหากผู้เล่น A อ้างความช่วยเหลือจากต่างประเทศและผู้เล่น B กล่าวว่า "ฉันมี Duke และฉันปิดกั้นความช่วยเหลือจากต่างประเทศของคุณ" A อาจพูดว่า "ฉันไม่เชื่อว่าคุณมี Duke" หากการยืนยันนั้นถูกต้อง B จะแพ้ไพ่เพราะการถูกจับได้ว่าเป็นการโกหกและ A ใช้เวลา 2 เหรียญ ถ้าไม่ใช่ A แพ้การ์ดและไม่ได้รับเหรียญและ B ต้องคืน Duke ของพวกเขาไปที่เด็คและจั่วการ์ดใหม่
วิธีบล็อกและความท้าทายในการทำงานกับ Assassinate จะต้องเป็นเนื้อออก สมมติว่าผู้เล่น A บอกว่า "ฉันมีนักฆ่าและฉันสังหารผู้เล่นข" หาก B ไม่พยายามท้าทายหรือบล็อก A การลอบสังหารจะเกิดขึ้น: B แพ้การ์ดและ A จ่าย 3 เหรียญ
อีกวิธีหนึ่ง B สามารถท้าทายโดยพูดว่า "ฉันไม่เชื่อว่าคุณมีนักฆ่า" หากเป็นจริงแล้ว A จะทิ้งการ์ดและเหรียญของพวกเขาจะถูกส่งคืนในขณะที่ B นั้นไม่ได้รับผลกระทบและเทิร์นของ A จะจบลง หากความเชื่อของ B ไม่ถูกต้องและ A ถือ Assassin แล้ว B จะสูญเสียไพ่ทั้งสองและล้มเหลวหนึ่งใบสำหรับการท้าทายที่ไม่ถูกต้องและอีกใบหนึ่งจากการลอบสังหาร
แทนที่จะท้าทาย B สามารถพูดว่า "ฉันมี Contessa และฉันปิดกั้นการลอบสังหาร" ถ้า A เชื่อ B ดังนั้นเทิร์นของ A จะจบลงและเหรียญของพวกเขาจะไม่ถูกส่งคืน แต่ A สามารถท้าบล็อกและพูดว่า "ฉันไม่เชื่อว่าคุณมี Contessa" หากในความเป็นจริง B ถือ Contessa ดังนั้น A แพ้การ์ดสำหรับการท้าทายที่ไม่ถูกต้อง แต่ถ้า B ไม่ทำเช่นนั้น B แพ้การ์ดใบเดียวที่ถูกจับได้ว่าโกหกและอีกใบจากการลอบสังหาร
ตรรกะที่คล้ายกับคำอธิบายข้างต้นนำไปใช้กับความสามารถในการขโมยของกัปตันซึ่งการกระทำหรือบล็อกสามารถท้าทายได้
เป็นไปได้ที่จะสูญเสียการ์ดของคุณทั้งสองและถูกกำจัดในคราวเดียวถ้าคุณประสบความสำเร็จในการลอบสังหารหรือคุณถูกจับโดยอ้างว่าคุณมี Contessa เพื่อบล็อกการลอบสังหาร คุณสูญเสียไพ่หนึ่งใบจากการท้าทายและการ์ดหนึ่งใบจากการลอบสังหาร
ท้าทาย
งานของคุณคือการเขียนโปรแกรมที่จะเล่นรัฐประหาร มันจะได้รับเป็นอาร์กิวเมนต์บรรทัดคำสั่ง:
- ชื่อของไฟล์ที่มีรายการของมันและการกระทำของฝ่ายตรงข้าม
- จำนวนเต็มตั้งแต่ 0 ถึง 12 ระบุจำนวนเหรียญของฝ่ายตรงข้าม
- จำนวนเต็มตั้งแต่ 0 ถึง 12 ระบุจำนวนเหรียญ
- สตริงที่มีความยาวหนึ่งถึงสี่ตัวอักษรเพื่อระบุไพ่ของมัน โดยปกติจะเป็นเพียงหนึ่งหรือสองใบที่โปรแกรมของคุณมี แต่ถ้าโปรแกรมของคุณเพิ่งประสบความสำเร็จในการแลกเปลี่ยนมันจะมีความยาวn + 2 ตัวอักษรโดยที่nคือจำนวนการ์ดที่เหลือของคุณ โปรแกรมของคุณจะต้องส่งออกการ์ดn ที่ต้องการเก็บไว้ใน STDOUT (โปรแกรมต้องไม่อ่านหรือเข้าถึง STDOUT นอกเหนือจากจุดประสงค์นี้ - หากคุณต้องการสร้างผลลัพธ์การดีบักโปรดเขียนถึง STDERR)
- มีข้อโต้แย้งอย่างน้อยหนึ่งข้อบ่งชี้ถึงการเคลื่อนไหวทางกฎหมายที่อาจเกิดขึ้น
(ตัวอย่างการร้องขอ: yourprogram file.txt 1 7 '~!' a c p q
หมายถึง "ฝ่ายตรงข้ามของคุณมี 1 เหรียญคุณมี 7 เหรียญเอกอัครราชทูตและ Contessa เขียนไปที่ file.txt คุณเลือก a, c, p หรือ q ตามประวัติเกมและสถานะเกมปัจจุบัน ")
โปรแกรมของคุณจะต้องเพิ่มหนึ่งหรือสองอักขระ (ในสองสถานการณ์) ลงในไฟล์ที่ระบุเพื่อระบุการทำงาน ต้องไม่แก้ไขเนื้อหาที่มีอยู่ของไฟล์ มันอาจสร้างไฟล์ใหม่ใด ๆ ที่มันต้องการ แต่เฉพาะในไดเรกทอรีที่มีการเรียกใช้ โปรดระบุคำสั่งที่จำเป็นทั้งหมดเพื่อรวบรวมและเรียกใช้โปรแกรมของคุณ
ฉันได้ให้ตัวอย่างคู่แข่งสองรายด้านล่างซึ่งเขียนใน Go
รูปแบบผลลัพธ์คือ:
I\n
: รายได้ การตอบสนองทางกฎหมาย: การดำเนินการเทิร์นใด ๆ (สมมติว่าหนึ่งมีเหรียญสำหรับการลอบสังหาร / รัฐประหาร)F
: ความช่วยเหลือจากต่างประเทศ คำตอบทางกฎหมาย:d
(บล็อกเหมือน Duke),p
(ปล่อยให้มันผ่านไป)C
: ทำรัฐประหาร. การตอบสนองทางกฎหมาย: แล้วแต่จำนวนใดของ_
,'
,<
,=
,0
ที่อยู่ในมือของคุณE
: แลกเปลี่ยน การตอบสนองทางกฎหมาย: (ความท้าทายที่ไม่เชื่อผู้เล่นที่มีเอกอัครราชทูต)q
p
T
: ภาษี การตอบสนองทางกฎหมาย: (ความท้าทายที่ไม่เชื่อผู้เล่นมีดยุค)q
p
A
: ลอบสังหาร การตอบสนองทางกฎหมาย:s
(บล็อกเป็น Contessa)q
(ความท้าทาย) และครบหนึ่ง_
,'
,<
,=
,0
ที่อยู่ในมือของคุณS
: ขโมย การตอบสนองทางกฎหมาย:a
(บล็อกเป็นเอกอัครราชทูต)c
(บล็อกเป็นกัปตัน) (ความท้าทายที่ไม่เชื่อผู้เล่นที่มีกัปตัน)q
p
d
: ปิดกั้นความช่วยเหลือจากต่างประเทศในฐานะ Duke คำตอบทางกฎหมาย:\n
(ยอมรับการบล็อก),q
(ความท้าทาย, ไม่เชื่อว่าผู้เล่นมีดยุค)a
: บล็อก Steal ในฐานะทูต การตอบสนองทางกฎหมาย:\n
(ยอมรับการบล็อก),q
(ความท้าทาย, ไม่เชื่อว่าผู้เล่นมีเอกอัครราชทูต)c
: บล็อก Steal ในฐานะกัปตัน\n
(ยอมรับการบล็อก),q
(ท้าทาย, ไม่เชื่อว่าผู้เล่นมีกัปตัน)s
: บล็อก Assassinate เป็น Contessa คำตอบทางกฎหมาย:\n
(ยอมรับการบล็อก),q
(ความท้าทาย, ไม่เชื่อว่าผู้เล่นมี Contessa)p
: ผ่านการท้าทายการแลกเปลี่ยน / ภาษี / ขโมยเมื่อไม่ใช่ตาคุณ ไม่ได้ใช้กับA
;_'<=0
จะลดลงที่จะท้าทายหนึ่งลอบสังหารเขียน การตอบสนองทางกฎหมาย:\n
(จบเทิร์นของคุณ) และหากคุณเพิ่งประสบความสำเร็จในการแลกเปลี่ยนให้เขียนการ์ดที่คุณต้องการเก็บไว้จากอาร์กิวเมนต์บรรทัดคำสั่งที่สี่ไปยัง STDOUTq
: ท้าทายการกระทำหรือบล็อกล่าสุด การตอบสนองทางกฎหมาย: หากคุณมีการ์ดสำหรับการกระทำที่ถูกท้าทายไม่ว่า~^*!$
จะเป็นอะไรก็ตาม หากคุณไม่ทำสิ่งใด_'<=0
จากมือของคุณที่คุณต้องการยอมแพ้ตามด้วยการขึ้นบรรทัดใหม่หากว่าเป็นตาคุณแล้ว~
,^
,*
,!
,$
: เผยให้เห็นว่าคุณได้บอกความจริงเกี่ยวกับการถือครองตามลำดับเอกอัครราชทูต, ฆาตกร, กัปตันเป็น Contessa และ Duke (ยังใช้แทนบัตรเหล่านี้ในการขัดแย้งบรรทัดคำสั่งและ STDOUT การส่งออกในตลาดหลักทรัพย์ ) การตอบสนองทางกฎหมาย: แล้วแต่จำนวนใดของ_
,'
,<
,=
,0
คุณมีอยู่ในมือของคุณ_
,'
,<
,=
,0
: ให้ขึ้นเป็นการลงโทษตามลำดับเอกอัครราชทูตและฆ่ากัปตันเป็น Contessa และดุ๊กเพราะคุณสูญเสียความท้าทายหรือถูกลอบสังหาร / couped การตอบสนองทางกฎหมาย:\n
.\n
: จบตาของคุณในการทำเช่นนั้นปฏิเสธที่จะท้าทายบล็อกถ้ามี คำตอบทางกฎหมาย: การกระทำใด ๆ ตัวอักษรตัวใหญ่ (สมมติว่าหนึ่งมีเหรียญสำหรับการลอบสังหาร / รัฐประหารและฝ่ายตรงข้ามมีเหรียญสำหรับขโมย)
รูปแบบมีคุณสมบัติที่มีประโยชน์ดังต่อไปนี้:
- ผลัดกันเริ่มต้นด้วยอักษรตัวใหญ่
- เส้นตามรูปแบบ: ตัวอักษรตัวพิมพ์ใหญ่ตัวอักษรตัวพิมพ์เล็กเครื่องหมายวรรคตอนหรือ 0 สำหรับการ์ดที่เปิดเผยขึ้นบรรทัดใหม่
- ไฟล์ที่ลงท้ายด้วยขึ้นบรรทัดใหม่หรือไฟล์ว่างเปล่าระบุว่าเป็นการเริ่มต้นของการเปิดโปรแกรมของคุณและจะต้องเลือกตัวอักษรพิมพ์ใหญ่
- การดำเนินการทางกฎหมายที่คุณได้รับอนุญาตให้ดำเนินการในการร้องขอนั้นมักจะถูกกำหนดโดยอักขระตัวสุดท้ายในไฟล์ ข้อยกเว้นคือ
q
ซึ่งจะมีตรรกะบางอย่างที่เกี่ยวข้องกับมัน ดูฟังก์ชันget_legal_actions
ในผู้ชี้ขาดเพื่อช่วยให้เข้าใจสิ่งนี้ หรือคุณสามารถใช้การดำเนินการทางกฎหมายที่คุณได้รับในบรรทัดคำสั่ง - จำนวนตัวอักษรในบรรทัดระบุว่าเทิร์นนั้นเป็นของคุณและโปรแกรมของคุณถูกขอให้เลือกการกระทำท้าทายบล็อกหรือจบเทิร์น
- จำนวนอักขระแปลก ๆ บนเส้นแสดงว่าการเลี้ยวไม่ใช่ของคุณและโปรแกรมของคุณจะถูกขอให้บล็อกท้าทายหรือเปิดเผย / ยอมจำนนบัตร
ฉันจะยกตัวอย่างสำหรับทุกการกระทำ
I\n
เป็นวิธีที่เข้าใจง่ายที่สุด โปรแกรมใช้หนึ่งเหรียญของรายได้จากนั้นจะสิ้นสุดลง นี่เป็นหนึ่งในสองกรณีที่โปรแกรมจะต้องพิมพ์อักขระสองตัวเนื่องจากรายได้เป็นการกระทำเดียวที่คู่ต่อสู้ไม่ได้รับผลกระทบและไม่สามารถบล็อกหรือท้าทายได้
Fp\n
หมายถึงว่าหนึ่งโปรแกรมรับความช่วยเหลือจากต่างประเทศฝ่ายตรงข้ามปฏิเสธที่จะบล็อก ( p
) ในการร้องขอครั้งต่อไปโปรแกรมแรกตั้งข้อสังเกตว่าด้วยตัวอักษรตัวเล็กสุดท้ายp
และ / หรือจำนวนตัวอักษรในบรรทัดนี้ก็ถึงตานี้ซึ่งยังไม่สิ้นสุดดังนั้นจึงรู้วิธีจบเทิร์นปัจจุบันโดยการพิมพ์ newline
C=\n
หมายความว่าหนึ่งโปรแกรมเปิดตัวรัฐประหาร คู่ต่อสู้ของมันรู้ว่ามันถูกเรียกให้ตอบโต้ด้วยจำนวนตัวอักษรแปลก ๆ ในสายทำให้ Contessa อีกครั้งโปรแกรมแรกรู้ว่านี่เป็นการเปิดที่ไม่สมบูรณ์ในการเรียกใช้ครั้งถัดไปโดยจำนวนตัวอักษรในบรรทัดดังนั้นจึงเขียนบรรทัดใหม่เพื่อสิ้นสุดเทิร์น
Eq~<\n
จะหมายถึงว่าหนึ่งโปรแกรมพยายามแลกเปลี่ยน ( E
) และคู่ต่อสู้ท้าทาย ( q
) โปรแกรมการแลกเปลี่ยนเปิดเผยว่ามีผู้เอกอัครราชทูต ( ~
) จริงและผู้เข้าแข่งขันยอมแพ้การลงโทษ ( <
) หลังจากผู้ท้าชิงออกแล้วโปรแกรมการแลกเปลี่ยนจะถูกเรียกอีกครั้งโดยมีสตริงสี่ตัวอักษรเป็นอาร์กิวเมนต์บรรทัดคำสั่งที่สี่ (หรืออักขระสามตัวหากมีเพียงการ์ดเดียว) มันเขียนตัวละครที่เป็นตัวแทนของการ์ดที่ต้องการเก็บไว้ใน STDOUT และขึ้นบรรทัดใหม่ไปยังไฟล์
Tq'\n
หมายความว่าโปรแกรมหนึ่งพยายามภาษีที่ไม่จริงถูกท้าทายและยกเลิกการเป็นนักฆ่า มันแสดงให้เห็นกรณีอื่น ๆ ที่มีการเขียนตัวละครสองตัว: ถ้าเป็นตาคุณแล้วและคุณถูกบังคับให้ทิ้งการ์ดไม่ว่าจะเป็นการท้าทายที่ถูกต้องของฝ่ายตรงข้าม (จากที่นี่) หรือจากการท้าทายที่ไม่ถูกต้องของบล็อก บัตรที่คุณแพ้และขึ้นบรรทัดใหม่เพื่อจบเทิร์นของคุณ
Asq!'\n
จะหมายถึงว่าผู้เล่น B พยายามลอบสังหารผู้เล่น A ( A
) แต่ A อ้างว่ามี Contessa เพื่อบล็อก ( s
) B ไม่เชื่อและท้าทาย ( q
) A เปิดเผยว่าจริง ๆ แล้วพวกเขามี Contessa ( !
) B ยอมแพ้ Assassin เพื่อเป็นการลงโทษ, สูญเสียเหรียญ, และจบเทิร์นของพวกเขา ( '\n
), เขียนตัวละครสองตัวในกรณีพิเศษนั้น (ถ้า A ตัดสินใจที่จะไม่ปิดกั้นหรือท้าทายมันอาจจะเขียน=
แล้วฝ่ายตรงข้ามจะได้เห็นว่าเทิร์นโอเวอร์และเขียนขึ้นบรรทัดใหม่จากนั้นบรรทัดจะได้อ่านA=\n
เช่นตัวอย่างรัฐประหาร)
Sq*0\n
หมายความว่าโปรแกรมหนึ่งพยายามขโมย คู่ต่อสู้ท้าทายไม่เชื่อว่าขโมยมีกัปตัน; และโปรแกรมดั้งเดิมเผยให้เห็นกัปตันดังนั้นการท้าทายจึงไม่ประสบความสำเร็จและผู้ท้าชิงยอมแพ้ดยุค (ตัวเลือกอื่นสำหรับคู่ต่อสู้ของมันคือการยอมรับการขโมยโดยการเขียนp
คู่ต่อสู้ของมันจะตรวจพบจุดจบของการเลี้ยวและการเขียน\n
ซึ่งส่งผลให้เกิดบรรทัดSp\n
)
ผู้ชี้ขาด
โปรแกรมจะถูกเรียกใช้งานโดยสคริปต์ Python นี้ มันดำเนินการสิบรอบซึ่งคู่แข่งทุกคนต้องเผชิญกับคู่แข่งอื่น ๆ ในขณะที่ไปทั้งครั้งแรกและครั้งที่สอง มันติดตามบัตรและการนับเหรียญและกำหนดผู้แพ้โดยโปรแกรมแรกที่จะจบบรรทัดด้วยเครื่องหมายวรรคตอนสองครั้ง โปรแกรมที่ออกโดยมีสถานะไม่เป็นศูนย์แก้ไขไฟล์เขียนการย้ายที่ผิดกฎหมายไปยังไฟล์หรือพยายามแลกเปลี่ยนผิดกฎหมายจะถูกริบโดยอัตโนมัติ หากผู้เล่นแต่ละคนใช้เวลามากกว่า 100 การกระทำรวมถึงบล็อกและความท้าทายโดยไม่มีผู้ชนะทั้งสองโปรแกรมจะแพ้ ผู้ชนะจะได้รับหนึ่งจุด ผู้เล่นที่โปรแกรมได้คะแนนมากที่สุดจะเป็นผู้ชนะ
ฉันขอแนะนำให้คุณอ่านซอร์สโค้ดของ Arbiter โดยเฉพาะget_legal_actions
ฟังก์ชั่น มันอาจช่วยให้คุณเข้าใจข้อกำหนดและเขียนโปรแกรมของคุณเอง
import itertools
import os
import random
import subprocess
class Player:
def __init__(self, name, command):
self.name = name
self.command = command
self.score = 0
self.coins = 1
self.cards = ""
actions_dict = {
'E': '_', 'T': '0', 'A': "'", 'S': '<',
'd': '0', 'a': '_', 'c': '<', 's': '='
}
punishment_to_reveal = {'_': '~', "'": '^', '<': '*', '=': '!', '0': '$'}
reveal_to_punishment = {
punishment_to_reveal[k]: k for k in punishment_to_reveal
}
def get_legal_actions(history, player, opponent):
c = history[-1]
result = ""
# Our turn begins; choose an action.
if c == '\n':
if player.coins >= 10:
return ["C"]
ret = ['I\n'] + list("FET")
if player.coins >= 3:
ret.append("A")
if player.coins >= 7:
ret.append('C')
if opponent.coins > 0:
ret.append("S")
return ret
# Opponent attempted foreign aid; can pass or claim Duke to block.
elif c == 'F':
return list('dp')
# We have been Couped; must surrender a card.
elif c == 'C':
return player.cards
# We failed a challenge; must surrender a card and print a newline
# if it is our turn.
elif c in '~^*!$':
if history[-3] in 'acds':
return [card + '\n' for card in player.cards]
return player.cards
# Opponent attempted Exchange or Tax; can pass or challenge.
elif c == 'E' or c == 'T':
return list('pq')
# Opponent attempted an Assassination; can block, challenge, or give in.
elif c == 'A':
return list('sq') + player.cards
# Opponent attempted to Steal; can pass, block as Ambassador/Captain,
# or challenge.
elif c == 'S':
return list('acpq')
# Opponent blocked; can challenge or withdraw.
elif c in 'acds':
return list('q\n')
# Opponent passed on blocking Foreign Aid/Tax/Exchange or they gave up a
# card as punishment, must end turn.
elif c in "p_'<=0":
return ['\n']
# Opponent challenged us.
elif c == 'q':
challenged_action = history[-2]
# If we have the card they challenged us over, must reveal it.
necessary_card = actions_dict[challenged_action]
if necessary_card in player.cards:
return [punishment_to_reveal[necessary_card]]
# Otherwise, we can give up either of our cards, writing a newline
# if it is our turn.
if challenged_action in 'acds':
return list(player.cards)
else:
return [card + '\n' for card in player.cards]
else:
return None
deck = ['_', "'", '<', '=', '0'] * 3
random.shuffle(deck)
def determine_turn_effects(line, output, cards, current_player, opponent):
last_action = line[-2]
# Only operate if the opponent declined to challenge (p) or the
# program successfully challenged their block
if last_action in "p_'<=0":
primary_action = line[0]
# Foreign Aid
if primary_action == 'F':
print current_player.name, "received 2 coins of Foreign Aid"
current_player.coins += 2
# Tax
elif primary_action == 'T':
print current_player.name, "received 3 coins of Tax"
current_player.coins += 3
# Steal
elif primary_action == 'S':
stolen_coins = 1 if opponent.coins == 1 else 2
print current_player.name,\
"stole %d coins from %s" % (stolen_coins, opponent.name)
current_player.coins += stolen_coins
opponent.coins -= stolen_coins
# Exchange, store desired cards and replace undesired ones
elif primary_action == 'E':
print current_player.name, "tried to take %r" % output, "from", cards
legal_outputs = [''.join(p) for p in itertools.permutations(
cards, len(current_player.cards))]
if output not in legal_outputs:
print current_player.name, "forfeits by illegal exchange"
return opponent
current_player.cards = [
reveal_to_punishment[c] for c in output
]
undesired_cards = list(cards)
for c in output:
undesired_cards.remove(c)
for card in undesired_cards:
deck.append(reveal_to_punishment[card])
random.shuffle(deck)
# Coins are not returned from a successful Contessa block
elif last_action == 's':
print current_player.name, "lost 3 coins from a Contessa block"
current_player.coins -= 3
return None
def play_game(player1, player2, round_number, game_number):
outfilename = os.path.abspath(__file__)[:-len(__file__)] + '_'.join([
player1.name, player2.name, str(round_number), str(game_number)
]) + '.txt'
print outfilename
f = open(outfilename, 'w')
f.close()
players_list = [player1, player2]
player1.cards = [deck.pop(), deck.pop()]
player2.cards = [deck.pop(), deck.pop()]
current_player_index = 0
for i in range(200):
current_player = players_list[current_player_index]
opponent = players_list[(current_player_index+1) % 2]
legal_actions = []
original_contents = []
original_contents_joined = ""
with open(outfilename, 'r') as outfile:
original_contents = outfile.readlines()
original_contents_joined = ''.join(original_contents)
if len(original_contents) == 0:
legal_actions = ['I\n'] + list("FEST")
else:
legal_actions = get_legal_actions(
original_contents[-1], current_player, opponent)
if not legal_actions:
print "Error: file ended in invalid character"
return current_player
# Has the player completed an Exchange? Pass them new cards if so.
exchange_cards = ""
old_last_line = original_contents[-1] if len(original_contents) > 0 else '\n'
if old_last_line[-1] != '\n' and old_last_line[0] == 'E' and \
len(old_last_line) % 2 == 0 and old_last_line[-1] in "p_'<=0":
exchange_cards = punishment_to_reveal[deck.pop()] + \
punishment_to_reveal[deck.pop()]
cards = exchange_cards + ''.join(
punishment_to_reveal[card] for card in current_player.cards)
args = current_player.command + [
outfilename,
str(opponent.coins),
str(current_player.coins),
cards
] + legal_actions
print ' '.join(args)
output = ""
os.chdir(current_player.name)
try:
output = subprocess.check_output(args)
# Competitors that fail to execute must forfeit
except subprocess.CalledProcessError:
print current_player.name, "forfeits by non-zero exit status"
return opponent
finally:
os.chdir('..')
new_contents = []
new_contents_joined = ""
with open(outfilename, 'r') as outfile:
new_contents = outfile.readlines()
new_contents_joined = ''.join(new_contents)
if original_contents_joined != new_contents_joined[:-2] and \
original_contents_joined != new_contents_joined[:-1]:
print current_player.name, "forfeits by modifying the file"
print "old:", original_contents
print "new:", new_contents
return opponent
new_last_line = new_contents[-1]
the_move_made = ""
for action in legal_actions:
if new_last_line.endswith(action):
the_move_made = action
break
# Competitors that make an illegal move must forfeit
if not the_move_made:
print current_player.name, "forfeits with an illegal move,",\
"last line: %r" % new_last_line
print opponent.name, "wins!"
return opponent
print current_player.name, "played %r" % the_move_made
# Side effects of moves.
#
# Income, give the current player a coin.
if the_move_made == "I\n":
print current_player.name, "received 1 coin of income"
current_player.coins += 1
# The program surrendered a card on its turn; take it away.
elif len(the_move_made) == 2:
print current_player.name, "lost a card from being challenged"
current_player.cards.remove(the_move_made[0])
# Coins are not returned from a successful Contessa block
if new_last_line[-3] == '!':
print current_player.name, "lost 3 coins from a Contessa block"
current_player.coins -= 3
# The program surrendered a card when it was not its turn.
elif the_move_made in "_'<=0":
print current_player.name, "gave up a", the_move_made
current_player.cards.remove(the_move_made)
if new_last_line[0] == 'C':
opponent.coins -= 7
elif new_last_line[0] == 'A':
opponent.coins -= 3
# Did the program unsuccessfully challenge an Assassination
# (e.g. Aq^0\n)
# or get caught falsely blocking with a Contessa
# (e.g. Asq0\n)?
# If yes, it loses right away.
if new_last_line[0] == 'A' and new_last_line[1] in 'qs' and \
len(new_last_line) == 4:
print current_player.name, "lost both cards in the same turn."
print opponent.name, "wins!"
return opponent
elif the_move_made == 'S':
print current_player.name, "attempted Steal"
elif the_move_made == 'T':
print current_player.name, "attempted Tax"
elif the_move_made == 'A':
print current_player.name, "attempted Assassinate"
elif the_move_made == 'C':
print current_player.name, "launched a Coup"
elif the_move_made == 'F':
print current_player.name, "attempted Foreign Aid"
elif the_move_made == 'E':
print current_player.name, "attempted Exchange"
elif the_move_made == 'q':
print current_player.name, "challenged"
elif the_move_made == 'p':
print current_player.name, "passed"
elif the_move_made == 'a':
print current_player.name, "blocked with an Ambassador"
elif the_move_made == 'c':
print current_player.name, "blocked with a Captain"
elif the_move_made == 's':
print current_player.name, "blocked with a Contessa"
elif the_move_made == 'd':
print current_player.name, "blocked with a Duke"
# The program revealed a card from an opponent's unsuccessful challenge.
# Give it a new card.
# Special case: a program whose Exchange is unsuccessfully challenged
# may keep the Ambassador it revealed in the Exchange, so give a new
# card for a revealed Ambassador only if it was used to block a Steal.
elif the_move_made in '^*!$' or (the_move_made == '~' and
new_last_line[0] == 'S'):
p = reveal_to_punishment[the_move_made]
current_player.cards.remove(p)
current_player.cards.append(deck.pop())
deck.append(p)
random.shuffle(deck)
print current_player.name, "did have a", the_move_made
# The program ended its turn. We must examine the rest of the line to
# determine the side effects.
elif the_move_made == '\n':
potential_winner = determine_turn_effects(
new_last_line, output.strip(), cards, current_player,
opponent)
if potential_winner:
print potential_winner.name,\
"wins because their opponent made an illegal exchange!"
return potential_winner
# One player has lost all their cards. Victory for the opponent!
if current_player.cards == []:
print opponent.name, "wins by eliminating both opponent cards!"
return opponent
current_player_index += 1
current_player_index %= 2
return None
competitors = []
competitors.append(Player("Challenger", ["./challenger"]))
competitors.append(Player("Random", ["./random"]))
# ...More competitors here
for i in range(10):
print "-- Round", i
j = 0
for pairing in itertools.permutations(competitors, 2):
player1, player2 = pairing
print '--- Game', j, ':', player1.name, 'vs.', player2.name
winner = play_game(player1, player2, i, j)
if not winner:
j += 1
continue
winner.score += 1
player1.coins = 1
player1.cards = ""
player2.coins = 1
player2.cards = ""
deck = ['_', "'", '<', '=', '0'] * 3
random.shuffle(deck)
j += 1
competitors.sort(reverse=True, key=lambda player: player.score)
for player in competitors:
print '%5d %s' % (player.score, player.name)
เบ็ดเตล็ด
โปรแกรมหนึ่งไม่สามารถมีรหัสเฉพาะสำหรับโปรแกรมอื่นและโปรแกรมไม่สามารถช่วยเหลือซึ่งกันและกัน (คุณอาจมีหลายโปรแกรม แต่ไม่สามารถโต้ตอบกันได้ แต่อย่างใด)
หากโปรแกรมของคุณแพ้การ์ดทั้งสองในคราวเดียวกันมันต้องเขียนเพียงการ์ดเดียว ผู้ชี้ขาดจะตรวจพบว่ามันถูกกำจัดไปแล้ว
เป็นไปได้และสนับสนุน แต่ไม่จำเป็นสำหรับโปรแกรมที่จะตรวจสอบประวัติของเกมในไฟล์ โดยการทำเช่นนั้นพวกเขาสามารถระบุได้ว่าการ์ดของฝ่ายตรงข้ามที่อ้างว่ามี
ในเกมจริงของรัฐประหารคุณสามารถท้าทายการกระทำแล้วพยายามปิดกั้นในทางกลับกัน ฉันไม่สามารถทำสเปคได้หากฉันอนุญาตดังนั้นคุณอาจท้าทายหรือบล็อกการกระทำที่กำหนด แต่ไม่ใช่ทั้งสองอย่าง
คำขอโทษของฉันต่อ @PeterTaylor ซึ่งเมื่อก่อนหน้านี้ฉันโพสต์สิ่งนี้แนะนำให้ฉันโพสต์ไว้ในแซนด์บ็อกซ์และทำโพรโทคอลใหม่เพื่อส่งออกไปป์ใน STDOUT / STDIN ฉันพยายามอย่างหนักเพื่อที่จะทำงานนั้นใช้เวลาทั้งวันเต็ม (เมื่อฉันใช้เวลาทั้งวันในการเขียนความท้าทายดั้งเดิม) แต่การแลกเปลี่ยนได้พิสูจน์แล้วว่ามีความซับซ้อนมากในการใช้วิธีการนั้นรวมทั้งจะเพิ่มความซับซ้อนของการส่งโดยกำหนดให้พวกเขาติดตามการนับเหรียญของตัวเอง ดังนั้นฉันได้โพสต์ความท้าทายมากหรือน้อยเหมือนเดิม
S
บล็อกโปรแกรม B โดยการเขียนc
, A \n
ปฏิเสธที่จะท้าทายโดยการเขียน ความท้าทายที่ประสบความสำเร็จของขโมยจะไป: เขียนS
, B ท้าทายโดยการเขียนq
, A concedes ความท้าทายโดยการเขียนเช่น_\n
คุณอาจใช้เวลาเพียงหนึ่งการกระทำต่อเทิร์นรวมถึงการแลกเปลี่ยน การตอบสนองทางกฎหมายต่อ Exchange นั้นผ่านและท้าทาย