ทำรัฐประหารให้กลายเป็นราชาแห่งขุนเขา!


14

ลีดเดอร์บอร์ด

  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: แลกเปลี่ยน การตอบสนองทางกฎหมาย: (ความท้าทายที่ไม่เชื่อผู้เล่นที่มีเอกอัครราชทูต)qp
  • T: ภาษี การตอบสนองทางกฎหมาย: (ความท้าทายที่ไม่เชื่อผู้เล่นมีดยุค)qp
  • A: ลอบสังหาร การตอบสนองทางกฎหมาย: s(บล็อกเป็น Contessa) q(ความท้าทาย) และครบหนึ่ง_, ', <, =, 0ที่อยู่ในมือของคุณ
  • S: ขโมย การตอบสนองทางกฎหมาย: a(บล็อกเป็นเอกอัครราชทูต) c(บล็อกเป็นกัปตัน) (ความท้าทายที่ไม่เชื่อผู้เล่นที่มีกัปตัน)qp
  • d: ปิดกั้นความช่วยเหลือจากต่างประเทศในฐานะ Duke คำตอบทางกฎหมาย: \n(ยอมรับการบล็อก), q(ความท้าทาย, ไม่เชื่อว่าผู้เล่นมีดยุค)
  • a: บล็อก Steal ในฐานะทูต การตอบสนองทางกฎหมาย: \n(ยอมรับการบล็อก), q(ความท้าทาย, ไม่เชื่อว่าผู้เล่นมีเอกอัครราชทูต)
  • c: บล็อก Steal ในฐานะกัปตัน \n(ยอมรับการบล็อก), q(ท้าทาย, ไม่เชื่อว่าผู้เล่นมีกัปตัน)
  • s: บล็อก Assassinate เป็น Contessa คำตอบทางกฎหมาย: \n(ยอมรับการบล็อก), q(ความท้าทาย, ไม่เชื่อว่าผู้เล่นมี Contessa)
  • p: ผ่านการท้าทายการแลกเปลี่ยน / ภาษี / ขโมยเมื่อไม่ใช่ตาคุณ ไม่ได้ใช้กับA; _'<=0จะลดลงที่จะท้าทายหนึ่งลอบสังหารเขียน การตอบสนองทางกฎหมาย: \n(จบเทิร์นของคุณ) และหากคุณเพิ่งประสบความสำเร็จในการแลกเปลี่ยนให้เขียนการ์ดที่คุณต้องการเก็บไว้จากอาร์กิวเมนต์บรรทัดคำสั่งที่สี่ไปยัง STDOUT
  • q: ท้าทายการกระทำหรือบล็อกล่าสุด การตอบสนองทางกฎหมาย: หากคุณมีการ์ดสำหรับการกระทำที่ถูกท้าทายไม่ว่า~^*!$จะเป็นอะไรก็ตาม หากคุณไม่ทำสิ่งใด_'<=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 ฉันพยายามอย่างหนักเพื่อที่จะทำงานนั้นใช้เวลาทั้งวันเต็ม (เมื่อฉันใช้เวลาทั้งวันในการเขียนความท้าทายดั้งเดิม) แต่การแลกเปลี่ยนได้พิสูจน์แล้วว่ามีความซับซ้อนมากในการใช้วิธีการนั้นรวมทั้งจะเพิ่มความซับซ้อนของการส่งโดยกำหนดให้พวกเขาติดตามการนับเหรียญของตัวเอง ดังนั้นฉันได้โพสต์ความท้าทายมากหรือน้อยเหมือนเดิม


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

@tsh โปรแกรมมักจะจบเทิร์นโดยการเขียนบรรทัดใหม่ แต่มันอาจจะเขียนตัวอักษรก่อนหน้านั้นหากใช้รายได้หรือสูญเสียการ์ดในเทิร์นของตัวเอง ความท้าทายที่ประสบความสำเร็จ / บล็อกจะจบเทิร์น บล็อกที่ประสบความสำเร็จจากการขโมยจะไป: การเขียนโปรแกรมSบล็อกโปรแกรม B โดยการเขียนc, A \nปฏิเสธที่จะท้าทายโดยการเขียน ความท้าทายที่ประสบความสำเร็จของขโมยจะไป: เขียนS, B ท้าทายโดยการเขียนq, A concedes ความท้าทายโดยการเขียนเช่น_\nคุณอาจใช้เวลาเพียงหนึ่งการกระทำต่อเทิร์นรวมถึงการแลกเปลี่ยน การตอบสนองทางกฎหมายต่อ Exchange นั้นผ่านและท้าทาย
สีม่วง P

2
@jaaq ฉันยังไม่ได้ตัดสินใจเกี่ยวกับกำหนดส่ง อย่างน้อยฉันจะให้มันเปิดจนกว่าคุณจะส่ง :)
Purple Purple

1
@jaaq ผู้ตัดสินดำเนินการc 10 รอบการแข่งขัน 10 ครั้งแต่ละครั้งโดยที่cคือจำนวนของคู่แข่ง ปัจจุบันมีผู้แข่งขัน 13 คนส่งผลให้ 10 (13P2) = 10 (13! / 11!) = 10 (13 * 12) = 1560 แมตช์
สีม่วง P

1
@ Jaaq ฉันไปแล้ว ฉันกลับมาแล้ว. Updated
สีม่วง P

คำตอบ:


4

เครื่องคิดเลข

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

from __future__ import division
import sys
import random
import operator

_, filename, othercoins, mycoins, mycards = sys.argv[:5]
legalActions = sys.argv[5:]

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}

obviousActions = ['~', '^', '*', '!', '$']
lossActions = ['_', "'", '<', '=', '0']

statefilename = './state.txt'
flags = set()
# Flags:
# 1 We went first
# $ Attacking with Duke
# * Attacking with Captain
# ^ Attacking with Assassin
# d Opponent used Duke
# c Opponent used Captain
# A Opponent used Assassin
# F Opponent used Foreign Aid

with open(statefilename, "a+") as statefile:
    statefile.seek(0)
    if statefile.readline().strip() == filename:
        flags = set(statefile.readline().strip())

with open(filename, "r+") as history:
    line = "\n"
    turn = 0
    oppcardcount = 4 - len(mycards)
    for a in history:
        line = a
        turn += 1
        if [c for c in line if c in lossActions]:
            oppcardcount -= 1
    else:
        flags.add("1")

    mycoins = int(mycoins)
    othercoins = int(othercoins)
    mycardcount = len(mycards)

    if line == 'T':
        othercoins += 3
        flags.add('d')
    elif line == 'S':
        othercoins += (2 if mycoins > 2 else mycoins)
        mycoins -= (2 if mycoins > 2 else mycoins)
        flags.add('c')
    elif line == 'A':
        othercoins -= 3
        mycardcount -= 1
        flags.add('A')
    elif line == 'F':
        flags.add('F')
    elif line == 'I\n':
        # If opponent is backing down, they're not so scary anymore
        flags.discard('d')
        flags.discard('c')
        flags.discard('F')

    # What's the least aggressive play that still wins?
    iGetStolen = ('c' in flags and not '*' in mycards and not '~' in mycards)
    iGetAssassinated = ('A' in flags and not '!' in mycards)
    incomeTimeToWin = max(0,7*oppcardcount-mycoins)+oppcardcount if not iGetStolen else 1000
    faidTimeToWin = max(0,7*oppcardcount-mycoins+1)//2+oppcardcount if not iGetStolen else 1000
    dukeTimeToWin = max(0,7*oppcardcount+(2*(oppcardcount-mycardcount) if iGetStolen else 0)-mycoins+2)//(3 if not iGetStolen else 1)+oppcardcount
    assassinTimeToWin = max(0,3*oppcardcount-mycoins)+oppcardcount if not iGetStolen else oppcardcount if mycoins >= 5*oppcardcount-2 else 1000
    captainTimeToWin = max(0,7*oppcardcount-mycoins+1)//2+oppcardcount
    faidAssassinTimeToWin = max(0,3*oppcardcount-mycoins+1)//2+oppcardcount if not iGetStolen else 1000
    dukeAssassinTimeToWin = max(0,3*oppcardcount+(2*(oppcardcount-mycardcount) if iGetStolen else 0)-mycoins+2)//(3 if not iGetStolen else 1)+oppcardcount
    captainAssassinTimeToWin = max(0,3*oppcardcount-mycoins+1)//2+oppcardcount
    opponentMoneySpeed = (2 if iGetStolen else 3 if 'd' in flags else 2 if 'F' in flags and not '$' in mycards else 1)
    opponentTimeToWin = max(0,(3 if iGetAssassinated else 7)*mycardcount-othercoins+opponentMoneySpeed-1)//opponentMoneySpeed+mycardcount
    opponentTimeToWinCaptained = max(0,(3 if iGetAssassinated else 7)*mycardcount+2*(mycardcount-oppcardcount)-(othercoins-2 if othercoins>2 else 0)+opponentMoneySpeed-3)//(opponentMoneySpeed-2)+mycardcount if opponentMoneySpeed > 2 else 1000

    def pickCardToLose():
        favoriteCards = []
        if dukeTimeToWin < opponentTimeToWin and '$' in mycards:
            favoriteCards = ['$', '!', '*', '~', '^']
        elif dukeAssassinTimeToWin < opponentTimeToWin and ('$' in mycards or '$' in flags) and '^' in mycards:
            favoriteCards = ['^', '$', '!', '*', '~']
        elif assassinTimeToWin < opponentTimeToWin and '^' in mycards:
            favoriteCards = ['^', '!', '*', '~', '$']
        elif captainTimeToWin < opponentTimeToWinCaptained and '*' in mycards:
            favoriteCards = ['*', '!', '$', '^', '~']
        elif faidTimeToWin < opponentTimeToWin and '^' in mycards and not 'd' in flags:
            favoriteCards = ['!', '*', '~', '$', '^']
        elif faidAssassinTimeToWin < opponentTimeToWin and '^' in mycards and not 'd' in flags:
            favoriteCards = ['^', '!', '*', '~', '$']
        elif captainAssassinTimeToWin < opponentTimeToWinCaptained and '*' in mycards and '^' in mycards:
            favoriteCards = ['^', '*', '!', '$', '~']
        else:
            favoriteCards = ['!', '*', '~', '$', '^']
        # Losing a card.  Decide which is most valuable.
        for k in favoriteCards:
            if k in mycards:
                cardToLose = k
        return reveal_to_punishment[cardToLose]

    action = legalActions[0]
    if line == "\n":
        # First turn behavior
        if '$' in mycards and 'T' in legalActions:
            action = 'T'
            flags.add('$')
        elif '*' in mycards and 'S' in legalActions:
            action = 'S'
            flags.add('*')
        elif '^' in mycards and 'I\n' in legalActions:
            action = 'I\n'
            flags.add('^')
        elif '~' in mycards and 'E' in legalActions:
            action = 'E'
        elif 'T' in legalActions:
            # Contessa/Contessa?  Need to lie.
            action = 'T'
            flags.add('$')
    elif set(obviousActions).intersection(legalActions):
        # Always take these actions if possible
        for a in set(obviousActions).intersection(legalActions):
            action = a
        # This might change our strategy
        flags.discard(action)
    elif '$' in mycards and 'd' in legalActions:
        action = 'd'
    elif '~' in mycards and 'a' in legalActions:
        action = 'a'
    elif '*' in mycards and 'c' in legalActions:
        action = 'c'
    elif '!' in mycards and 's' in legalActions:
        action = 's'
    elif 'q' in legalActions and line[-1] in 'dacs':
        # We're committed at this point
        action = 'q'
    elif 'q' in legalActions and '*' in flags and line[-1] in 'SE':
        # Don't allow these when using a steal strategy
        action = 'q'
    elif 'q' in legalActions and turn == 1:
        if line == 'T':
            if mycards == '$$' or mycards == '^^' or mycards == '!!':
                action = 'q'
            else:
                action = 'p'
                flags.add('d')
        elif line == 'S':
            if '$' in mycards and '^' in mycards:
                action = 'p'
                flags.add('c')
            else:
                action = 'q'
        elif line == 'E':
            action = 'p'
    elif line == 'A' and len(mycards) > 1:
        # Don't challenge the first assasination.  We'll get 'em later.
        action = pickCardToLose()
        flags.add('A')
    elif line == 'A':
        # Can't let this pass
        action = 'q'
    elif line == 'C':
        # Taking damage
        action = pickCardToLose()
    elif len(line) == 2 and line[1] == 'q':
        # My base action was successfully challenged
        action = pickCardToLose()+"\n"
        # Also stop claiming what we were challenged for
        if line == "Tq":
            flags.discard('$')
        elif line == "Sq":
            flags.discard('*')
        elif line == "Aq":
            flags.discard('^')
    elif len(line) == 3 and line[1] == 'q':
        # I failed challenging a base action
        action = pickCardToLose()
    elif len(line) == 3 and line[2] == 'q':
        # My block was successfully challenged
        action = pickCardToLose()
    elif len(line) == 4 and line[2] == 'q':
        # I failed challenging a block
        action = pickCardToLose()+"\n"
    else:
        if 'p' in legalActions:
            # Default to pass if no other action is chosen
            action = 'p'

        if dukeTimeToWin <= opponentTimeToWin and ('$' in mycards or '$' in flags):
            if 'C' in legalActions:
                action = 'C'
            elif 'T' in legalActions:
                action = 'T'
        elif incomeTimeToWin <= opponentTimeToWin:
            if 'C' in legalActions:
                action = 'C'
            elif 'I\n' in legalActions:
                action = "I\n"
        elif dukeAssassinTimeToWin <= opponentTimeToWin and ('$' in mycards or '$' in flags) and '^' in mycards and mycardcount > 1:
            if 3*oppcardcount <= mycoins - (2*(oppcardcount-1) if iGetStolen else 0) and 'A' in legalActions:
                action = 'A'
            elif 'T' in legalActions:
                action = 'T'
            flags.add('^');
        elif assassinTimeToWin <= opponentTimeToWin and '^' in mycards:
            if 'A' in legalActions:
                action = 'A'
            elif 'I\n' in legalActions:
                action = 'I\n'
            flags.add('^');
        elif captainTimeToWin <= opponentTimeToWinCaptained and '*' in mycards:
            if 'C' in legalActions:
                action = 'C'
            elif 'S' in legalActions:
                action = 'S'
            elif 'I\n' in legalActions:
                action = 'I\n'
            flags.add('*');
        elif faidTimeToWin <= opponentTimeToWin and not 'd' in flags:
            if 'C' in legalActions:
                action = 'C'
            elif 'F' in legalActions:
                action = 'F'
        elif faidAssassinTimeToWin <= opponentTimeToWin and '^' in mycards and not 'd' in flags:
            if 'A' in legalActions:
                action = 'A'
            elif 'F' in legalActions:
                action = 'F'
            flags.add('^');
        elif captainAssassinTimeToWin <= opponentTimeToWinCaptained and '*' in mycards and '^' in mycards:
            if 'A' in legalActions:
                action = 'A'
            elif 'S' in legalActions:
                action = 'S'
            flags.add('^');
            flags.add('*');
        elif 'q' in legalActions:
            action = 'q'
        # No winning strategy.  Find something useful to do anyway.
        elif 'C' in legalActions and not '^' in flags:
            action = 'C'
        elif 'S' in legalActions and '*' in flags:
            action = 'S'
        elif 'A' in legalActions and '^' in flags:
            action = 'A'
        elif 'E' in legalActions and '~' in mycards and dukeAssassinTimeToWin < opponentTimeToWin:
            action = 'E'
        elif 'F' in legalActions and not 'd' in flags:
            action = 'F'
        elif 'T' in legalActions:
            action = 'T'
            flags.add('$');
    if action == 'q':
        if line == 'T' or line == 'Fd':
            flags.discard('d')
        elif line == 'S' or line == 'Sc':
            flags.discard('c')
        elif line == 'A':
            flags.discard('A')
    history.write(action)

if len(mycards) > 2:
    favoriteCards = []
    if dukeTimeToWin < opponentTimeToWin and '$' in mycards:
        favoriteCards = ['$', '!', '*', '~', '^']
    elif dukeAssassinTimeToWin < opponentTimeToWin and ('$' in mycards or '$' in flags) and '^' in mycards:
        favoriteCards = ['^', '$', '!', '*', '~']
    elif assassinTimeToWin < opponentTimeToWin and '^' in mycards:
        favoriteCards = ['^', '!', '*', '~', '$']
    elif captainTimeToWin < opponentTimeToWinCaptained and '*' in mycards:
        favoriteCards = ['*', '!', '$', '^', '~']
    elif faidTimeToWin < opponentTimeToWin and '^' in mycards and not 'd' in flags:
        favoriteCards = ['!', '*', '~', '$', '^']
    elif faidAssassinTimeToWin < opponentTimeToWin and '^' in mycards and not 'd' in flags:
        favoriteCards = ['^', '!', '*', '~', '$']
    elif captainAssassinTimeToWin < opponentTimeToWinCaptained and '*' in mycards and '^' in mycards:
        favoriteCards = ['^', '*', '!', '$', '~']
    else:
        favoriteCards = ['!', '*', '~', '$', '^']
    # Losing two cards.  Decide which is most valuable.
    possibleCards = [k for k in favoriteCards if k in mycards]
    if len(possibleCards) < len(mycards) - 2:
        possibleCards = list(mycards)
        random.shuffle(possibleCards)
    mycards = ''.join(possibleCards[:(len(mycards)-2)])
    print mycards

with open(statefilename, "w") as statefile:
    statefile.write(filename+"\n")
    statefile.write(''.join(list(flags))+"\n")

กบฎ

ตอนแรกบอกความจริง แต่เริ่มโกหกเมื่อมันหยุดถูกท้าทาย นอกจากนี้ยังมีพฤติกรรมการแก้ปัญหาบางอย่าง (ประมาณว่าฉันประพฤติตัวอย่างไรเมื่อเล่นเกมนี้กับมนุษย์)

import sys
import random

_, filename, othercoins, mycoins, mycards = sys.argv[:5]
legalActions = sys.argv[5:]

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}

obviousActions = ['C', '~', '^', '*', '!', '$']
lossActions = ['_', "'", '<', '=' '0']

statefilename = './state.txt'
myclaims = set()
otherclaims = set()
mycaughtlies = set()
othercaughtlies = set()
flags = set()
# Flags:
# * Opponent had a chance to challenge us just now
# & Opponent has stopped wildly challenging everything
# E We have exchanged at least once
# S Opponent did not block a steal.  Go for the jugular!
# _ Opponent has lost a card

with open(statefilename, "a+") as statefile:
    statefile.seek(0)
    if statefile.readline().strip() == filename:
        myclaims = set(statefile.readline().strip())
        otherclaims = set(statefile.readline().strip())
        mycaughtlies = set(statefile.readline().strip())
        othercaughtlies = set(statefile.readline().strip())
        flags = set(statefile.readline().strip())

def getFavoriteCards():
    favoriteCards = []
    if '*' in otherclaims:
        favoriteCards.append('~')
    elif not '~' in otherclaims:
        favoriteCards.append('*')
    if len(otherclaims) > (0 if '_' in flags else 1) and mycoins > 1 and not '!' in otherclaims:
        favoriteCards.append('^')
    favoriteCards.append('!')
    favoriteCards.append('$')
    if not '~' in favoriteCards:
        favoriteCards.append('~')
    return favoriteCards

def pickCardToLose():
    # Losing a card.  Decide which is most valuable.
    favoriteCards = getFavoriteCards()
    cardToLose = ''
    for k in favoriteCards:
        if k in mycards:
            cardToLose = k
    for k in mycards:
        if not k in favoriteCards:
            cardToLose = k
    return reveal_to_punishment[cardToLose]

with open(filename, "r+") as history:
    line = "\n"
    for a in history:
        line = a
    if 'q' in legalActions:
        otherclaims.add(punishment_to_reveal[actions_dict[line[-1]]])
    if len(line) > 2 and line.endswith('\n') and line[-2] in lossActions:
        otherclaims.discard(punishment_to_reveal[line[-2]])
        flags.add('_')
    if len(line) > 2 and line.endswith('\n') and (line.startswith('Ep') or line.startswith('Eq~')):
        othercaughtlies = set()
    if '*' in flags:
        flags.discard('*')
        if line[-1] not in 'qdacs':
            flags.add('&')
            if line[-2] == 'F':
                othercaughtlies.add('$')
            if line[-2] == 'S':
                othercaughtlies.add('*')
                othercaughtlies.add('~')
            if line[-2] == 'A':
                othercaughtlies.add('!')
    action = legalActions[0]
    if set(obviousActions).intersection(legalActions):
        # Always take these actions if possible
        for a in set(obviousActions).intersection(legalActions):
            action = a
        if action in reveal_to_punishment:
            myclaims.discard(action)
    elif '&' in flags:
        preferredActions = []
        mysafecards = myclaims.union(mycards)

        # Calculate the financial situation
        mygain = 0
        oppgain = 0
        if '*' in mysafecards and not '*' in otherclaims and not '~' in otherclaims:
            mygain += 2
            oppgain -= 2
        elif '$' in mysafecards:
            mygain += 3
        elif not '$' in otherclaims:
            mygain += 1 # This script doesn't use foreign aid
        else:
            mygain += 1
        if '*' in otherclaims and not '*' in mysafecards and not '~' in mysafecards:
            oppgain += 2
            mygain -= 2
        elif '$' in mysafecards:
            oppgain += 3
        elif not '$' in otherclaims:
            oppgain += 2
        else:
            oppgain += 1
        mydist = 7 - int(mycoins)
        oppdist = 7 - int(othercoins)
        if '^' in mysafecards and len(otherclaims) > (0 if '_' in flags else 1) and not '!' in otherclaims:
            mydist -= 4
        if '^' in otherclaims and not '!' in mysafecards:
            oppdist -= 4
        if mydist > 0 and (oppdist <= 0 or mygain <= 0 or (oppgain > 0 and ((oppdist+oppgain-1) // oppgain) < ((mydist+mygain-1) // mygain))):
            # Not winning.  Do something desperate.
            timeToLive = ((oppdist+oppgain-1) // oppgain) if oppdist > 0 else 0
            favoriteCards = getFavoriteCards()
            if timeToLive < len(otherclaims):
                preferredActions.append('q')
            if (timeToLive or len(mycards) > 1) and favoriteCards[0] not in mysafecards:
                preferredActions.append('E')
            elif mycoins >= 3 and random.randint(0,2):
                preferredActions.append('A')
            else:
                preferredActions.append('S')

        preferredActions.append('s')
        if 'a' in legalActions and ('~' in mycards or '*' in mycards) and not 's' in flags:
            # Allow the first steal, as bait
            preferredActions.append('p')
            flags.add('s')
            if '~' in mycards:
                flags.discard('E')
        if '$' in mysafecards:
            preferredActions.append('d')
        if '~' in mysafecards:
            preferredActions.append('a')
        elif '*' in mysafecards:
            preferredActions.append('c')
        else:
            preferredActions.append('c' if random.randint(0,1) else 'a')
        if not 'E' in flags:
            preferredActions.append('E')
        if not ('~' in otherclaims or '*' in otherclaims):
            preferredActions.append('S')
        if len(otherclaims) > (0 if '_' in flags else 1) and ('^' in mycards or not '_' in flags) and not '!' in otherclaims:
            preferredActions.append('A')
        preferredActions.append('T')
        if line[-1] in actions_dict and punishment_to_reveal[actions_dict[line[-1]]] in othercaughtlies:
            preferredActions.append('q')
        preferredActions += ['p', '\n']
        if len(myclaims) < len(mycards):
            # Slip a lie in before admitting all cards in hand
            preferredActions = [a for a in preferredActions
                if not a in actions_dict
                or not punishment_to_reveal[actions_dict[a]] in mysafecards]
        else:
            preferredActions = [a for a in preferredActions
                if not a in actions_dict
                or punishment_to_reveal[actions_dict[a]] in mycards
                or not punishment_to_reveal[actions_dict[a]] in mycaughtlies]
        preferredActions = [a for a in preferredActions if a in legalActions]
        if preferredActions:
            action = preferredActions[0]
        else:
            loss = pickCardToLose()
            if loss in legalActions:
                action = loss
            elif loss+"\n" in legalActions:
                action = loss+"\n"
    else:
        preferredActions = []
        if not ('~' in otherclaims or '*' in otherclaims):
            preferredActions.append('S')
        preferredActions += ['T', 'E', 'd', 'a', 'c', 's', 'p', '\n']
        if not '!' in otherclaims:
            preferredActions.append('A')
        preferredActions = [a for a in preferredActions if a in legalActions]
        # Filter out lies, provided that doesn't filter out everything
        preferredActions = [a for a in preferredActions
            if not a in actions_dict
            or punishment_to_reveal[actions_dict[a]] in mycards
        ] or [a for a in preferredActions
            if not a in actions_dict
            or not punishment_to_reveal[actions_dict[a]] in mycaughtlies
        ]
        if preferredActions:
            action = preferredActions[0]
        else:
            loss = pickCardToLose()
            if loss in legalActions:
                action = loss
            elif loss+"\n" in legalActions:
                action = loss+"\n"
        if 'a' in legalActions:
            if action not in 'acq':
                # If vulnerable to stealing, don't admit it!
                action = random.choice('acq')
            elif not 's' in flags:
                # Allow the first steal, as bait
                action = 'p'
                flags.add('s')
                if '~' in mycards:
                    flags.discard('E')
    if action.strip("\n") in lossActions:
        myclaims.discard(punishment_to_reveal[action.strip("\n")])
        if line[-1] == 'q':
            # Also stop claiming what we were challenged for
            myclaims.discard(punishment_to_reveal[actions_dict[line[-2]]])
            mycaughtlies.add(punishment_to_reveal[actions_dict[line[-2]]])
    if action == 'q':
        # We challenged it.  One way or another, they will not have this card later.
        otherclaims.discard(punishment_to_reveal[actions_dict[line[-1]]])
        othercaughtlies.add(punishment_to_reveal[actions_dict[line[-1]]])
    if action in actions_dict:
        myclaims.add(punishment_to_reveal[actions_dict[action]])
        flags.add('*')
    history.write(action)

if len(mycards) > 2:
    flags.add('E')
    mycaughtlies = set()
    # Losing two cards.  Decide which is most valuable.
    favoriteCards = getFavoriteCards()
    # After an exchange, we can claim what we like.  Throw in some lying for more flexibility.
    myclaims = set()
    possibleCards = [k for k in favoriteCards if k in mycards]
    if random.randint(1,len(possibleCards)) > len(mycards) - 2:
        myclaims.add(possibleCards[0])
        possibleCards = possibleCards[1:]
    if len(possibleCards) < len(mycards) - 2:
        possibleCards = list(mycards)
        random.shuffle(possibleCards)
    mycards = ''.join(possibleCards[:(len(mycards)-2)])
    print mycards

with open(statefilename, "w") as statefile:
    statefile.write(filename+"\n")
    statefile.write(''.join(list(myclaims))+"\n")
    statefile.write(''.join(list(otherclaims))+"\n")
    statefile.write(''.join(list(mycaughtlies))+"\n")
    statefile.write(''.join(list(othercaughtlies))+"\n")
    statefile.write(''.join(list(flags))+"\n")

โจร

พยายามกำจัดเอกอัครราชทูตและหัวหน้าของคู่ต่อสู้และชนะโดยการขโมย

import sys
import random

_, filename, othercoins, mycoins, mycards = sys.argv[:5]
legalActions = sys.argv[5:]

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}

obviousActions = ['C', '~', '^', '*', '!', '$']
lossActions = ['_', "'", '<', '=' '0']

def getFavoriteCards():
    return ['*', '!', '~', '$', '^']

def pickCardToLose():
    # Losing a card.  Decide which is most valuable.
    favoriteCards = getFavoriteCards()
    cardToLose = ''
    for k in favoriteCards:
        if k in mycards:
            cardToLose = k
    for k in mycards:
        if not k in favoriteCards:
            cardToLose = k
    return reveal_to_punishment[cardToLose]

with open(filename, "r+") as history:
    line = "\n"
    turn = 0
    for a in history:
        line = a
        turn += 1
    action = legalActions[0]
    if set(obviousActions).intersection(legalActions):
        # Always take these actions if possible
        for a in set(obviousActions).intersection(legalActions):
            action = a
    elif 'p' in legalActions and turn == 1 and line == "E":
        # Let this pass... once
        action = 'p'
    elif 'q' in legalActions and line[-1] in 'SEac':
        # These get in the way of stealing, get rid of them even if it costs us a card
        action = 'q'
    elif 'E' in legalActions and '~' in mycards and '*' not in mycards:
        action = 'E'
    elif 'S' in legalActions:
        action = 'S'
    elif 's' in legalActions:
        if '!' in mycards:
            action = 's'
        elif len(mycards) == 1:
            action = random.choice('sq')
        else:
            action = pickCardToLose()
    elif 'p' in legalActions:
        action = 'p'
    elif line == 'A' or line == 'C':
        # Taking damage
        action = pickCardToLose()
    elif len(line) == 2 and line[1] == 'q':
        # My base action was successfully challenged
        action = pickCardToLose()+"\n"
    elif len(line) == 3 and line[1] == 'q':
        # I failed challenging a base action
        action = pickCardToLose()
    elif len(line) == 3 and line[2] == 'q':
        # My block was successfully challenged
        action = pickCardToLose()
    elif len(line) == 4 and line[2] == 'q':
        # I failed challenging a block
        action = pickCardToLose()+"\n"
    history.write(action)

if len(mycards) > 2:
    # Losing two cards.  Decide which is most valuable.
    favoriteCards = getFavoriteCards()
    possibleCards = [k for k in favoriteCards if k in mycards]
    if mycards.count('*') > 1:
        # Hooray captains!
        possibleCards = ['*'] + possibleCards
    if len(possibleCards) < len(mycards) - 2:
        possibleCards = list(mycards)
        random.shuffle(possibleCards)
    mycards = ''.join(possibleCards[:(len(mycards)-2)])
    print mycards

Bloody Murder

คู่กับ Bandit อันนี้ไปในกลยุทธ์ Duke + Assassin

import sys
import random

_, filename, othercoins, mycoins, mycards = sys.argv[:5]
legalActions = sys.argv[5:]

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}

obviousActions = ['C', '~', '^', '*', '!', '$']
lossActions = ['_', "'", '<', '=' '0']

def getFavoriteCards():
    return ['^', '$', '!', '*', '~']

def pickCardToLose():
    # Losing a card.  Decide which is most valuable.
    favoriteCards = getFavoriteCards()
    cardToLose = ''
    for k in favoriteCards:
        if k in mycards:
            cardToLose = k
    for k in mycards:
        if not k in favoriteCards:
            cardToLose = k
    return reveal_to_punishment[cardToLose]

with open(filename, "r+") as history:
    line = "\n"
    stealHappened = 0
    oppcardcount = 4 - len(mycards)
    for a in history:
        line = a
        if line[0] == 'S':
            stealHappened = 1
        if [c for c in line if c in lossActions]:
            oppcardcount -= 1
    action = legalActions[0]
    if set(obviousActions).intersection(legalActions):
        # Always take these actions if possible
        for a in set(obviousActions).intersection(legalActions):
            action = a
    elif 'q' in legalActions and line[-1] in 's':
        # We need this gone
        action = 'q'
    elif 'E' in legalActions and '~' in mycards:
        action = 'E'
    elif 'A' in legalActions and (len(mycards) == 1 or mycoins >= 3*oppcardcount+(2 if stealHappened and oppcardcount>1 else 0)):
        action = 'A'
    elif 'T' in legalActions:
        action = 'T'
    elif 'd' in legalActions:
        action = 'd'
    elif 'c' in legalActions and '*' in mycards:
        action = 'c'
    elif 'a' in legalActions and '~' in mycards:
        action = 'a'
    elif 's' in legalActions:
        if '!' in mycards:
            action = 's'
        elif len(mycards) == 1:
            action = random.choice('sq')
        else:
            action = pickCardToLose()
    elif 'p' in legalActions:
        action = 'p'
    elif line == 'A' or line == 'C':
        # Taking damage
        action = pickCardToLose()
    elif len(line) == 2 and line[1] == 'q':
        # My base action was successfully challenged
        action = pickCardToLose()+"\n"
    elif len(line) == 3 and line[1] == 'q':
        # I failed challenging a base action
        action = pickCardToLose()
    elif len(line) == 3 and line[2] == 'q':
        # My block was successfully challenged
        action = pickCardToLose()
    elif len(line) == 4 and line[2] == 'q':
        # I failed challenging a block
        action = pickCardToLose()+"\n"
    history.write(action)

if len(mycards) > 2:
    # Losing two cards.  Decide which is most valuable.
    favoriteCards = getFavoriteCards()
    possibleCards = [k for k in favoriteCards if k in mycards]
    if mycards.count('^') > 1:
        # Hooray assassins!
        possibleCards = ['^'] + possibleCards
    if len(possibleCards) < len(mycards) - 2:
        possibleCards = list(mycards)
        random.shuffle(possibleCards)
    mycards = ''.join(possibleCards[:(len(mycards)-2)])
    print mycards

ทั้งหมดเพิ่มไปยังกระดานผู้นำและทำได้ค่อนข้างดี! ฉันแนะนำให้เปลี่ยนชื่อ Betrayer เป็น Turncoat ได้ไหม? ทำให้มันดูน่าทึ่งขึ้นอีกนิด :)
สีม่วง P

@PurpleP เปลี่ยนชื่อ! "Betrayer" เป็นตัวเลือกที่ค่อนข้างร้อนแรง มันถูกตั้งชื่อตามตัวฉันเองในระหว่างการพัฒนา แต่มันก็ดูไม่ถูกต้องเมื่อฉันมีผู้แข่งขันหลายคน
Brilliand

เพิ่มเครื่องคิดเลขในกระดานผู้นำแล้ว
สีม่วง P

1
ขอแสดงความยินดีเครื่องคิดเลขคือ King of the Hill!
Purple P

4

Solver

Solver พยายามจดจำการ์ดที่เล่นก่อนหน้านี้และการเคลื่อนไหวก่อนหน้าของคู่ต่อสู้

นี่เป็นรุ่นที่ 2 ที่ยังไม่เสร็จ (และตอนนี้มันเป็นเรื่องใหญ่)

เพื่อให้ทำงานบนโหนด 10 เพิ่ม competitors.append(Player("Solver", ["node", "--experimental-modules", "./solver.mjs"]))

ถ้าโหนด 12 competitors.append(Player("Solver", ["node", "./solver.js"]))

ระวังกับประเภทไฟล์

import  fs from 'fs'
import { promisify } from 'util'

const appendFile = promisify(fs.appendFile)
const writeFile = promisify(fs.writeFile)
const readFile = promisify(fs.readFile)

const delay = ms => new Promise(_ => setTimeout(_, ms));

let [filename, othercoins, mycoins, mycards ] = process.argv.slice(2)
othercoins = +othercoins
mycoins = +mycoins

const move = async m => await appendFile(filename, m)
const message = m => process.stdout.write(m)
const endTurn = async _ => await move(`\n`) 

const stateFileName = `./state.json`

const defaultState = {
    inTheDeck: [],
    oponentCards: [],
    oponentMissingTempCard: "",
    oponentMissingCards: [],
    oponentDropedCards: [],
    oponentCardModifier: 0
}

const CardTypes = Object.freeze({
    Ambassador : `Ambassador`,
    Assassin : `Assassin`,
    Captain  : `Captain`,
    Contessa : `Contessa`,
    Duke     : `Duke`,
})

const revealTable = Object.freeze({
    [CardTypes.Ambassador]: `~`,
    [CardTypes.Assassin]: `^`,
    [CardTypes.Captain]: `*`,
    [CardTypes.Contessa]: `!`,
    [CardTypes.Duke]: `$`,
})

const giveUpTable = Object.freeze({
    [CardTypes.Ambassador]: `_`,
    [CardTypes.Assassin]: `'`,
    [CardTypes.Captain]: `<`,
    [CardTypes.Contessa]: `=`,
    [CardTypes.Duke]: `0`,
})

function GetRevealCardChar(cardType) {
    return revealTable[cardType]
}

function GetRevealCardType(char) {
    return Object.keys(revealTable).find(key => revealTable[key] === char)
}

function GetGiveUpCardChar(cardType) {
    return giveUpTable[cardType]
}

function GetGiveUpCardType(char) {
    return Object.keys(giveUpTable).find(key => giveUpTable[key] === char)
}

async function GiveUpCard(cardType, endTurn = false) {
    return await move(
        GetGiveUpCardChar(cardType) + `${endTurn?`\n`:``}`
    );
}

function OponentCanHave(cardType) {
    // it has it
    if (!!~state.oponentCards.indexOf(cardType)) return true

    if (state.oponentCards.length + state.oponentDropedCards.length >= 2) return false

    return true
}


function GiveCard(getOrder = false) {
    // TODO: Tactic
    const giveAwayOrder = [
        CardTypes.Captain,
        CardTypes.Ambassador,
        CardTypes.Contessa,
        CardTypes.Assassin,
        CardTypes.Duke,
    ]

    const tmp =  mycards
        .split('')
        .map(GetRevealCardType)

    let [unique, duplicate] = tmp.reduce(([unique, duplicate], item) => {
        return unique.includes(item) ? 
            [unique, [...duplicate, item]] :
            [[...unique, item], duplicate]
    }
    , [[],[]])

    unique.sort(
        (a, b) => giveAwayOrder.indexOf(a) - giveAwayOrder.indexOf(b));
    duplicate.sort(
        (a, b) => giveAwayOrder.indexOf(a) - giveAwayOrder.indexOf(b))

    const out = [...duplicate, ...unique]

    return getOrder? out: GetGiveUpCardChar(out[0]);
}

const iHaveAmbassador = !!~mycards.indexOf(`~`)
const iHaveAssassin = !!~mycards.indexOf(`^`)
const iHaveCaptain = !!~mycards.indexOf(`*`)
const iHaveContessa = !!~mycards.indexOf(`!`)
const iHaveDuke = !!~mycards.indexOf(`$`)

let state = defaultState

;(async ()=>{
    const data = (await readFile(filename, `utf8`)).replace(/\r/g, ``)

    const isNewGame = data === "" && mycoins === 1 && othercoins === 1

    if (isNewGame) {
        await writeFile(stateFileName, JSON.stringify(state))
    } else {
        state = JSON.parse(await readFile(stateFileName, `utf8`))
    }
    //console.error(state);
    let line = data.split(/\n/g).pop()

    // I am in the exchnage
    if (mycards.length >= 3) {
        const [c1, c2] = GiveCard(true).reverse()

        if (mycards.length === 3) {
            state.inTheDeck.push(c1)
            message(GetRevealCardChar(c1))
        }
        if (mycards.length === 4) {
            state.inTheDeck.push(c1, c2)
            message(`${GetRevealCardChar(c1)}${GetRevealCardChar(c2)}`)
        }
        return await move(`\n`)
    }

    const newTurn = line === ``

    if (newTurn) {
        if (mycoins >= 7) {
            return await move(`C`)
        }

        if (othercoins >= 6) {
            if (iHaveCaptain) 
                return await move(`S`)


            if (mycoins <= 6 && mycards.length <= 1) {
                // TODO: bluff 
            }
        }

        if (
            !iHaveDuke &&
            !iHaveContessa &&
            iHaveAmbassador
        ) {
            return await move(`E`)
        }

        // Assasinate if oponent has no Contessa
        if (
            mycoins >= 3 &&
            iHaveAssassin &&
            !~state.oponentCards.indexOf(CardTypes.Contessa)
        ) {
            return await move(`A`)
        }

        if (iHaveDuke) {

            return await move(`T`)
        }

        return await move(`I\n`)
    }

    // Exchange
    if (line === `Eq`) {
        if (iHaveAmbassador)
            return await move(GetRevealCardChar(CardTypes.Ambassador))

        return await GiveUpCard(GiveCard(true)[0])
    }

    // Tax Challenge
    if(line === `Tq`) {
        if (iHaveDuke)
            return await move(GetRevealCardChar(CardTypes.Duke))

        return await GiveUpCard(GiveCard(true)[0])
    }


    if (line === `Sa`) {
        if (!~state.oponentCards.indexOf(CardTypes.Ambassador)) {
            state.oponentMissingTempCard = CardTypes.Ambassador
            return await move(`q`)
        }
        return await endTurn()
    }

    if (line === `Sc`) {
        if (!~state.oponentCards.indexOf(CardTypes.Captain)) {
            state.oponentMissingTempCard = CardTypes.Captain
            return await move(`q`)
        }
        return await endTurn()
    }

    if (line=== `Saq${GetRevealCardChar(CardTypes.Ambassador)}`) {
        state.oponentMissingTempCard = ``
        state.oponentCards.push(
            CardTypes.Ambassador
        );
        return await GiveUpCard(GiveCard(true)[0], true)
    }

    if (line=== `Scq${GetRevealCardChar(CardTypes.Captain)}`) {
        state.oponentMissingTempCard = ``
        state.oponentCards.push(
            CardTypes.Captain
        );
        return await GiveUpCard(GiveCard(true)[0], true)
    }

    if (line === `Sq`) {
        if (iHaveCaptain)
            return await move(GetRevealCardChar(CardTypes.Captain))

        return await GiveUpCard(GiveCard(true)[0])
    }

    // Assassinate Block and Chalange it
    if (line === `As`) {
        state.oponentMissingTempCard = CardTypes.Contessa
        return await move(`q`)
    }

    // Assasint blocked by Contessa
    if (line === `Asq${GetRevealCardChar(CardTypes.Contessa)}`) {
        state.oponentMissingTempCard = ``
        state.oponentCards.push(
            CardTypes.Contessa
        )
        // Assassin useless here lets give it up
        return await GiveUpCard(CardTypes.Assassin, true)
    }

    // Assassinate challenge
    if (line === `Aq`) {
        if (iHaveAssassin)
            return await move(GetRevealCardChar(CardTypes.Assassin))

        return await GiveUpCard(GiveCard(true)[0])
    }


    // Defense Moves
    if (line === `C`) {
        return await GiveUpCard(GiveCard(true)[0])
    }


    if (line === `A`) {
        if (iHaveContessa)
            return await move(`s`)


        if (!!~state.oponentCards.indexOf(CardTypes.Assassin)) {
            // If oponent has an Assasin card lets bluff
            return await move(`s`)
        } else {
            state.oponentMissingTempCard = CardTypes.Assassin
            return await move(`q`)
        }

    }

    if (line === `Aq${GetRevealCardChar(CardTypes.Assassin)}`) {
        state.oponentMissingTempCard = ``
        state.oponentCards.push(
            CardTypes.Assassin
        );
        return await GiveUpCard(GiveCard(true)[0], true)
    }

    if (line === `Asq`) {
        if (iHaveContessa)
            return await move(GetRevealCardChar(CardTypes.Contessa))

        return await GiveUpCard(GiveCard(true)[0])
    }

    if (line === `S`) {
        if (iHaveAmbassador)
            return await move(`a`)

        if (iHaveCaptain)
            return await move(`c`)

        return await move(`p`)
    }

    if (line === `Saq`) {
        if (iHaveAmbassador)
            return await move(GetRevealCardChar(CardTypes.Ambassador))

        return await GiveUpCard(GiveCard(true)[0])
    }

    if (line === `Scq`) {
        if (iHaveCaptain)
            return await move(GetRevealCardChar(CardTypes.Captain))

        return await GiveUpCard(GiveCard(true)[0])
    }

    if (line === `F`) {
        if (iHaveDuke)
            return await move(`d`)

        return await move(`p`)
    }

    if (line === `Fdq`) {
        if (iHaveDuke)
            return await move(GetRevealCardChar(CardTypes.Duke))

        return await GiveUpCard(GiveCard(true)[0])
    }

    if (line === `E`) {
        if (!OponentCanHave(CardTypes.Ambassador)) {
            return await move(`q`)
        }

        state.oponentCards = []
        state.oponentMissingCards = []
        state.oponentMissingTempCard = ''

        return await move(`p`)
    }


    if (line === `Eq${GetRevealCardChar(CardTypes.Ambassador)}`) {
        console.error(111, `THIS SHOULD NEVER HAPPEN`)
        return await GiveUpCard(GiveCard(true)[0])
    }

    if (line === `T`) {
        if (!OponentCanHave(CardTypes.Duke)) {
            return await move(`q`)
        }
        return await move(`p`)
    }

    if (line === `Tq${GetRevealCardChar(CardTypes.Duke)}`) {
        console.error(111, `THIS SHOULD NEVER HAPPEN`)
        return await GiveUpCard(GiveCard(true)[0])
    }


    // remove oponents drop card from the state
    // can't detect if oponent has the same card twice
    if (!!~Object.values(giveUpTable).indexOf(line.substr(-1))) {
        // Catch the bluff
        if (state.oponentMissingTempCard !== "") {
            state.oponentMissingCards.push(state.oponentMissingTempCard)
            state.oponentMissingTempCard = ""
        }

        // maybe we should asume user doeas not has the same card?

        const cardType = GetGiveUpCardType(line.substr(-1))
        state.oponentCards.filter(c => c !== cardType)
        state.inTheDeck.push(cardType)
        state.oponentDropedCards.push(cardType)
    }

    return await endTurn()

})()
.then(async () => {
    await writeFile(stateFileName, JSON.stringify(state))
})
.catch(console.error.bind(console))


```

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

เวอร์ชั่นใหม่ขึ้นมามันเป็นข้อตกลงกับ Exchange
ปีเตอร์

1
ฉันจะอัปเดตกระดานแต้มนำเมื่อคุณเผยแพร่เวอร์ชันที่เสร็จสิ้นแล้ว
สีม่วง P

ขอขอบคุณฉันเพิ่งเปิดตัวหากผู้เล่นแสดงการ์ดของเขาว่า ID การ์ดนั้นถูกลบออกจากมือของเขาและเพิ่มกลับไปที่เด็ค นั่นทำให้ตรรกะครึ่งหนึ่งของฉันผิด: DI ต้องแก้ไข (ฉันประหลาดใจที่ฉันทำคะแนนได้ดีด้วยตรรกะที่ไม่ดี) pastebin.com/AXGJ9v5Q <--- การกลับมา 2 ครั้งล่าสุด! ถูกลบมือของฉัน หรือว่าเป็นบั๊ก?
ปีเตอร์

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

3

ทนายความ

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

import sys

_, filename, othercoins, mycoins, mycards = sys.argv[:5]


def give_card():
    if "^" in mycards:
        return "'"
    if "~" in mycards:
        return "_"
    if "!" in mycards:
        return "="
    if "*" in mycards:
        return "<"
    return "0"


with open(filename, "r+") as history:
    line = "\n"
    for a in history:
        print("line:", a)
        line = a
    if line.endswith("\n"):
        if int(mycoins) >= 10:
            history.write("C")
        elif "$" in mycards:
            history.write("T")
        elif "*" in mycards and int(othercoins) > 0:
            history.write("S")
        else:
            history.write("F")
    elif line == "F":
        if "$" in mycards:
             history.write("d")
        else:
             history.write("p")
    elif line == "C":
        history.write(give_card())
    elif line == "E":
        if len(mycards) > 1:
            history.write("q")
        else: 
            history.write("p")
    elif line == "T":
        if len(mycards) > 1:
            history.write("q")
        else: 
            history.write("p")
    elif line == "A":
        if "!" in mycards:
            history.write("s")
        else: 
            history.write(give_card())
    elif line == "S":
        if "~" in mycards:
            history.write("a")
        elif "*" in mycards:
            history.write("c")
        elif len(mycards) > 1:
            history.write("q")
        else:
            history.write("p")
    elif line.endswith("d") and len(mycards) > 1:
        history.write("q")
    elif line.endswith("a") and len(mycards) > 1:
        history.write("q")
    elif line.endswith("c") and len(mycards) > 1:
        history.write("q")
    elif line.endswith("s") and len(mycards) > 1:
        history.write("q")
    elif line.endswith("sq"):
        history.write("!")
    elif line.endswith("aq"):
        history.write("~")
    elif line.endswith("cq"):
        history.write("*")
    elif line.endswith("dq"):
        history.write("$")
    elif line.endswith("Tq"):
        history.write("$")
    elif line.endswith("Sq"):
        history.write("*")
    elif line[-1] in "~^*!$":
        history.write(give_card())
        if line[-3] in "acds":
            history.write("\n")
    else:
        history.write("\n")

อาจมีข้อบกพร่องในโปรแกรมนี้ เมื่อคุณพบพวกเขาโปรดแจ้งให้เราทราบ


@PurpleP จุดดี ฉันคงที่ ทักษะการตัดสินใจมีความสำคัญมากสำหรับทนายความที่ดี
ฮิทสึ

คุณได้ตรวจสอบแล้วว่าไฟล์นั้นไม่ได้ขึ้นบรรทัดใหม่จริงหรือ? (เช่นเปิดไฟล์และเห็นอักษรตัวใหญ่ตรงกลางบรรทัด) ฉันกำลังหาสาเหตุของเรื่องนี้และต้องการตรวจสอบให้แน่ใจว่ามีการยกเว้น
Hiatsu

@PurpleP ฉันสามารถอัปโหลดเวอร์ชันการดีบักที่ใช้ STDOUT เพื่อจุดประสงค์ที่ไม่แลกเปลี่ยนและคุณส่งผลลัพธ์กลับมาให้ฉันได้หรือไม่?
ฮิทสึ

ขอให้เรายังคงอภิปรายนี้ในการแชท
สีม่วง P

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

2

สุ่ม

การสุ่มไม่ทราบว่าจะต้องทำอะไรดังนั้นเขาจึงสุ่มเลือกสิ่งที่ถูกกฎหมาย

package main

import (
    "fmt"
    "math/rand"
    "os"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    filename := os.Args[1]
    ourCards := os.Args[4]
    legalActions := os.Args[5:]
    file, _ := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND, 0755)
    defer file.Close()

    file.WriteString(legalActions[rand.Intn(len(legalActions))])
    switch len(ourCards) {
    case 3:
        os.Stdout.Write([]byte{ourCards[rand.Intn(3)]})
    case 4:
        i1 := 0
        i2 := 0
        for ok := true; ok; ok = i1 == i2 {
            i1 = rand.Intn(4)
            i2 = rand.Intn(4)
        }
        keptCards := []byte{ourCards[i1], ourCards[i2]}
        os.Stdout.Write(keptCards)
    }
}

ผู้ท้าชิง

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

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "os"
    "strconv"
)

var revealToPunishment = map[byte]byte{'~': '_', '^': '\'', '*': '<', '!': '=', '$': '0'}

func main() {
    filename := os.Args[1]
    coinCount := os.Args[3]
    ourCards := os.Args[4]
    file, _ := os.OpenFile(filename, os.O_RDWR, 0755)
    defer file.Close()

    rawBytes, _ := ioutil.ReadAll(file)
    if len(rawBytes) == 0 {
        file.Write([]byte("I\n"))
        return
    }
    lines := bytes.Split(rawBytes, []byte{'\n'})
    switch rawBytes[len(rawBytes)-1] {
    case '\n':
        // Our turn, do we have enough coins for a Coup?
        if c, _ := strconv.Atoi(coinCount); c >= 7 {
            file.Write([]byte{'C'})
            // We don't, so take income.
        } else {
            file.Write([]byte("I\n"))
        }
    // Opponent did something challengeable. We don't believe them for a second.
    // Challenge it.
    case 'E', 'T', 'A', 'S', 'a', 'c', 'd', 's':
        file.Write([]byte{'q'})
    // Opponent Couped us or our challenge failed. Give up a card.
    case 'C':
        file.Write([]byte{revealToPunishment[ourCards[0]]})
    case '~', '*', '^', '!', '$':
        file.Write([]byte{revealToPunishment[ourCards[0]]})
        lastLine := lines[len(lines)-1]
        switch lastLine[len(lastLine)-3] {
        case 'a', 'c', 'd', 's':
            file.WriteString("\n")
        }
    // Our challenge succeeded or we Couped the opponent! End our turn.
    case '_', '\'', '<', '=', '0':
        file.Write([]byte{'\n'})
    default:
        // Opponent took some other action. Let it pass.
        file.Write([]byte{'p'})
    }
}

รวบรวมโปรแกรมเหล่านี้ด้วย go build random.go/challenger.goและทำงานด้วยหรือ./random./challenger


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

2

taxman

Taxman อยู่ที่นี่เพื่อรวบรวมภาษี ใช้นักฆ่าถ้าพวกเขามี บล็อกเฉพาะในกรณีที่พวกเขามีการ์ดที่จะบล็อก ความท้าทายแบบสุ่ม

เขียนใน c #, ฉันใช้เวลานานเกินไปในการสร้างลำดับชั้นของคลาสสำหรับการกระทำที่แตกต่างทั้งหมดที่สามารถทำได้

แก้ไข:ขณะนี้มีการปรับปรุงตรรกะเช่นไม่อ้างว่ามีดุ๊กเมื่อพวกเขาได้เลิกดยุคหลังจากถูกท้าทาย และไม่พยายามรวมกันอีกต่อไปหากฝ่ายตรงข้ามบล็อกด้วย contessa (และไม่ถูกท้าทาย)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

internal static class Program
{
    public static void Main(string[] args)
    {
#if DEBUG
        // Can't figure out how to pass newline as a command line arg.
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i] == "I\\n")
                args[i] = "I\n";
        }
#endif
        if (!ProcessArgs(args, out string filename, out int opCoin, out int myCoin, out IEnumerable<Card> cards, out IEnumerable<Output> validOutputs))
        {
            Console.WriteLine("Error with args.");
            return;
        }

        var taxman = new Taxman(filename, opCoin, myCoin, cards, validOutputs);
        taxman.DukeEm();
    }

    private static bool ProcessArgs(string[] args, out string filename, out int opCoin, out int myCoin, out IEnumerable<Card> cards, out IEnumerable<Output> validOutputs)
    {
        if (args.Length < 4)
        {
            throw new InvalidOperationException("Error: Not enough args.");
        }
        bool success = true;

        filename = args[0];
        success &= int.TryParse(args[1], out opCoin) && opCoin >= 0 && opCoin <= 12;
        success &= int.TryParse(args[2], out myCoin) && myCoin >= 0 && myCoin <= 12;

        cards = Card.ParseSymbols(args[3]);

        IEnumerable<char> validOutputArgs = args.Skip(4).Select(outputArg => outputArg.First());
        // Income and Surrenders on our turn include \n, we use chars below so don't include the newline, hence the call to .First().
        // Code below should be smart enough to also write a newline if necessary.

        validOutputs = Output.ParseSymbols(validOutputArgs);
        return success;
    }
}

internal sealed class Taxman
{
    private const string _OustedAsDukeFileName = "MyTotallyCoolStateFile.txt";
    private const string _OppClaimsContessaFileName = "OppClaimsContess.txt";
    private readonly Random _Rand = new Random();
    private readonly List<Card> _GiveUpPreferences = new List<Card> { Card.Duke, Card.Assassin, Card.Ambassador, Card.Contessa, Card.Captain };

    private double BaseProbabilityToChallenge => 0.1d;
    private bool _Written = false;
    private bool _MyTurn;
    private bool? _OustedAsDuke = null;
    private bool? _OppClaimsContessa = null;

    private string FileName { get; }
    private int OppCoin { get; }
    private int MyCoin { get; }
    private IEnumerable<Card> Cards { get; }
    private IEnumerable<Output> ValidOutputs { get; }
    private IEnumerable<Output> GameSoFar { get; }
    private int OppCardCount { get; }
    private int MyCardCount => Cards.Count();

    private int OppScore => (10 * OppCardCount) + OppCoin;
    private int MyScore => (10 * MyCardCount) + MyCoin;

    private bool OustedAsDuke
    {
        get
        {
            if (_OustedAsDuke.HasValue)
            {
                return _OustedAsDuke.Value;
            }
            else
            {
                if (string.IsNullOrWhiteSpace(File.ReadAllText(_OustedAsDukeFileName)))
                {
                    _OustedAsDuke = false;
                    return false;
                }
                else
                {
                    _OustedAsDuke = true;
                    return true;
                }
            }
        }
        set
        {
            File.WriteAllText(_OustedAsDukeFileName, value ? "Ousted" : string.Empty);
            _OustedAsDuke = value;
        }
    }

    private bool OppClaimsContessa
    {
        get
        {
            if (_OppClaimsContessa.HasValue)
            {
                return _OppClaimsContessa.Value;
            }
            else
            {
                if (string.IsNullOrWhiteSpace(File.ReadAllText(_OppClaimsContessaFileName)))
                {
                    _OppClaimsContessa = false;
                    return false;
                }
                else
                {
                    _OppClaimsContessa = true;
                    return true;
                }
            }
        }
        set
        {
            File.WriteAllText(_OppClaimsContessaFileName, value ? "Claimed" : string.Empty);
            _OppClaimsContessa = value;
        }
    }

    public Taxman(string fileName, int oppCoin, int myCoin, IEnumerable<Card> cards, IEnumerable<Output> validOutputs)
    {
        FileName = fileName; OppCoin = oppCoin; MyCoin = myCoin; Cards = cards; ValidOutputs = validOutputs;

        GameSoFar = ReadFile();

        //calculate how many cards the opponent has.
        int giveUps = GameSoFar.Count(output => output is GiveUp);
        int myGiveUps = 2 - MyCardCount;
        var oppGiveUps = giveUps - myGiveUps;
        OppCardCount = 2 - oppGiveUps;
    }

    public void DukeEm()
    {
        if (Cards.Skip(2).Any())
        {
            Exchange();
            Write(Output.EndTurn);
            return;
        }

        var prev = GameSoFar.LastOrDefault() ?? Output.EndTurn;
        if (prev == Output.EndTurn) // Income is I\n so shows up as an EndTurn
        {
            ChooseAction();
        }
        else if (prev == Action.ForeignAid)
        {
            if (!OustedAsDuke)
                Write(Block.Duke);
            else
                Write(Output.Pass);
        }
        else if (prev == Action.Coup)
        {
            GiveUpDecide();
        }
        else if (prev == ChallengeableAction.Exchange || prev == ChallengeableAction.Tax)
        {
            if (ShouldChallenge((ChallengeableAction)prev))
                Write(Output.Challenge);
            else
                Write(Output.Pass);
        }
        else if (prev == ChallengeableAction.Assassinate)
        {
            RespondToAssassinate();
        }
        else if (prev == ChallengeableAction.Steal)
        {
            RespondToSteal();
        }
        else if (prev == Block.Duke || prev == Block.Ambassador || prev == Block.Captain || prev == Block.Contessa)
        {
            Debug.Assert(prev == Block.Contessa, "We should never take an action that a different card would block.");

            if (ShouldChallenge((Block)prev))
                Write(Output.Challenge);
            else
            {
                Write(Output.EndTurn);
                OppClaimsContessa = true;
            }
        }
        else if (prev == Output.Pass)
        {
            Write(Output.EndTurn);
        }
        else if (prev == Output.Challenge)
        {
            var challengedOutput = (IChallengeable)GameSoFar.TakeLast(2).First();
            RespondToChallenge(challengedOutput);
        }
        else if (prev is Card)
        {
            GiveUpDecide();
        }
        else if (prev is GiveUp)
        {
            if (prev == GiveUp.Contessa)
                OppClaimsContessa = false;

            Write(Output.EndTurn);
        }
        else
        {
            Debug.Fail("Should have hit one of the conditions above.");
            WriteRandomValid();
        }
    }

    private void Exchange()
    {
        int handSize = MyCardCount - 2;
        var cardsToKeep = new List<Card>();
        var workingCards = Cards.ToList();

        while (cardsToKeep.Count < handSize)
        {
            if (!cardsToKeep.Contains(Card.Duke) && workingCards.Remove(Card.Duke))
                cardsToKeep.Add(Card.Duke);
            else if (!cardsToKeep.Contains(Card.Assassin) && !OppClaimsContessa && workingCards.Remove(Card.Assassin))
                cardsToKeep.Add(Card.Assassin);
            else if (!cardsToKeep.Contains(Card.Ambassador) && workingCards.Remove(Card.Ambassador))
                cardsToKeep.Add(Card.Ambassador);
            else if (!cardsToKeep.Contains(Card.Contessa) && workingCards.Remove(Card.Contessa))
                cardsToKeep.Add(Card.Contessa);
            else if (!cardsToKeep.Contains(Card.Captain) && workingCards.Remove(Card.Captain))
                cardsToKeep.Add(Card.Captain);
            else
            {
                cardsToKeep.Add(workingCards[0]);
                workingCards.RemoveAt(0);
            }
        }
        var keptCards = new string(cardsToKeep.Select(card => card.Symbol).ToArray());
        Console.WriteLine(keptCards);
    }

    private IEnumerable<Output> ReadFile()
    {
        var text = File.ReadAllText(FileName);

        // Check if we're at the start of the game, 1 character means our opponent went first.
        if (text == null || text.Length <= 1)
        {
            // Do any start up like creating a state file.
            Debug.Assert(MyCardCount == 2 && MyCoin == 1 && OppCoin == 1, "Should always start with 2 cards in hand and have 1 coin each.");
            using (File.Create(_OustedAsDukeFileName))
            using (File.Create(_OppClaimsContessaFileName))
            { ; }
        }

        var lastLine = text.Split('\n').LastOrDefault();
        _MyTurn = lastLine == null || lastLine.Length % 2 == 0;

        return Output.ParseSymbols(text);
    }

    private void ChooseAction()
    {
        if (MyCoin >= 3 && Cards.Contains(Card.Assassin))
        {
            // If we have the coins to assasinate and have the card to assasinate then go for it.
            Write(ChallengeableAction.Assassinate);
        }
        else if (MyCoin >= 7)
        {
            // If we have the coins to coup then go for it.
            Write(Action.Coup);
        }
        else if (Cards.Contains(Card.Ambassador) && !Cards.Contains(Card.Duke))
        {
            // If we don't /actually/ have a duke but we do have ambassador and can exchange into one, then try do that.
            Write(ChallengeableAction.Exchange);
            // TODO if we've exchanged multiple times already perhaps we should try something different?
        }
        else if (!OustedAsDuke)
        {
            // Take tax because We totally always have a duke.
            // Except if we've been previously challenged and shown to not have a duke, in which case exchange to get a new Duke.
            Write(ChallengeableAction.Tax);
        }
        else
        {
            Write(ChallengeableAction.Exchange);
            // Even if we don't find a duke from the exchange we can pretend that we did.
            OustedAsDuke = false;
        }
    }

    private void RespondToAssassinate()
    {
        if (Cards.Contains(Card.Contessa))
            Write(Block.Contessa);
        else if (MyCardCount <= 1)
        {
            // We will lose if we don't challenge or block.
            if (ShouldRandomChallenge(0.5d))
                Write(Output.Challenge);
            else
                Write(Block.Contessa);
        }
        else if (ShouldChallenge(ChallengeableAction.Assassinate))
            Write(Output.Challenge);
        else
            GiveUpDecide();
    }

    private void RespondToSteal()
    {
        // prefer to block with ambassador before captain.
        if (Cards.Contains(Card.Ambassador))
            Write(Block.Ambassador);
        else if (Cards.Contains(Card.Captain))
            Write(Block.Captain);
        else if (ShouldChallenge(ChallengeableAction.Steal))
            Write(Output.Challenge);
        else
            Write(Output.Pass);
        // TODO if opp is continually stealing we need to figure out who wins the race if we keep taking Tax.
    }

    private void RespondToChallenge(IChallengeable challengedAction)
    {
        if (Cards.Contains(challengedAction.RequiredCard))
            Write(challengedAction.RequiredCard);
        else
            GiveUpDecide();

        if (challengedAction == ChallengeableAction.Tax)
            OustedAsDuke = true;
    }

    private void GiveUpDecide()
    {
        Write(Cards.OrderBy(card => _GiveUpPreferences.IndexOf(card)).Last().GiveUp);

        if (_MyTurn)
            Write(Output.EndTurn);
    }

    private bool ShouldChallenge(IChallengeable prev)
    {
        // Never challenge if we're far enough ahead, always challenge if far enough behind
        if (MyScore > (OppScore + 7))
        {
            return false;
        }
        else if (MyScore < (OppScore - 10))
        {
            return true;
        }
        else
        {
            if (prev == ChallengeableAction.Assassinate)
                return ShouldRandomChallenge(BaseProbabilityToChallenge * 0.5d);
            else if (prev is Block)
                return ShouldRandomChallenge(BaseProbabilityToChallenge * 2d);
            else if (prev == ChallengeableAction.Tax && OppCoin >= 4 && MyCardCount <= 1 && (MyCoin < 7 || OppCardCount > 1))
                return true;
            else
                return ShouldRandomChallenge(BaseProbabilityToChallenge);
        }
    }

    private bool ShouldRandomChallenge(double prob)
    {
        return _Rand.NextDouble() < prob;
    }

    private void WriteRandomValid()
    {
        int index = _Rand.Next(0, ValidOutputs.Count());
        var randomOutput = ValidOutputs.ElementAt(index);
        Write(randomOutput);
    }

    private void Write(Output output)
    {
        Debug.Assert(!_Written || (_MyTurn && output == Output.EndTurn), "If we've already written a value we shouldn't be trying to write another.");
        Debug.Assert(ValidOutputs.Contains(output), "Should only be writing valid outputs to file.");

        File.AppendAllText(FileName, output.Symbol.ToString());
        _Written = true;
    }
}

[DebuggerDisplay("{Symbol}")]
internal class Output
{
    public static readonly Output Pass = new Output() { Symbol = 'p' };
    public static readonly Output Challenge = new Output() { Symbol = 'q' };
    public static readonly Output EndTurn = new Output() { Symbol = '\n' };

    private static readonly Output[] _BaseOutputs = new Output[3] { Pass, Challenge, EndTurn };

    protected Output() { }

    public static IEnumerable<Output> AllOutputs => ChallengeableAction.Actions.Concat(Block.Blocks.Concat(Card.Cards.Concat(GiveUp.GiveUps.Concat(_BaseOutputs))));

    public static IList<Output> ParseSymbols(IEnumerable<char> symbols)
    {
        var parsedOutputs = new List<Output>();
        foreach (var symbol in symbols)
        {
            if (symbol == '\r') continue; // newlines can show up as \r\n so need to skip the \r.
            var matchingOutput = AllOutputs.FirstOrDefault(output => output.Symbol == symbol);
            if (matchingOutput == null)
            {
                throw new InvalidOperationException($"Could not parse Output symbol: \"{symbol}\"");
            }
            parsedOutputs.Add(matchingOutput);
        }
        return parsedOutputs;
    }

    public char Symbol { get; protected set; }
}

internal sealed class Card : Output
{
    public static readonly Card Ambassador = new Card() { Symbol = '~', GiveUp = GiveUp.Ambassador, AvailableAction = ChallengeableAction.Exchange, AvalableBlock = Block.Ambassador };
    public static readonly Card Assassin = new Card() { Symbol = '^', GiveUp = GiveUp.Assassin, AvailableAction = ChallengeableAction.Assassinate };
    public static readonly Card Captain = new Card() { Symbol = '*', GiveUp = GiveUp.Captain, AvailableAction = ChallengeableAction.Steal, AvalableBlock = Block.Captain };
    public static readonly Card Contessa = new Card() { Symbol = '!', GiveUp = GiveUp.Contessa, AvalableBlock = Block.Contessa };
    public static readonly Card Duke = new Card() { Symbol = '$', GiveUp = GiveUp.Duke, AvailableAction = ChallengeableAction.Tax, AvalableBlock = Block.Duke };

    private static readonly Card[] _Cards = new Card[5] { Ambassador, Assassin, Captain, Contessa, Duke };

    private Card() { }

    public static IEnumerable<Card> Cards => _Cards;

    public GiveUp GiveUp { get; private set; }
    public ChallengeableAction AvailableAction { get; private set; }//=> ChallengeableAction.ChallengeableActions.SingleOrDefault(action => action.RequiredCard == this);
    public Block AvalableBlock { get; private set; }// => Block.Blocks.SingleOrDefault(block => block.RequiredCard == this);

    new public static IEnumerable<Card> ParseSymbols(IEnumerable<char> cardSymbols)
    {
        var parsedCards = new List<Card>();
        foreach (var symbol in cardSymbols)
        {
            var matchingCard = Cards.FirstOrDefault(card => card.Symbol == symbol);
            if (matchingCard == null) throw new InvalidOperationException($"Could not parse card symbol: {symbol}");
            parsedCards.Add(matchingCard);
        }
        return parsedCards;
    }
}

internal class Action : Output
{
    public static readonly Action Income = new Action() { Symbol = 'I' };
    public static readonly Action ForeignAid = new Action() { Symbol = 'F', BlockedBy = new Block[1] { Block.Duke } };
    public static readonly Action Coup = new Action() { Symbol = 'C' };

    protected Action() : base() { }

    public IEnumerable<Block> BlockedBy { get; protected set; } = new Block[0];
}

internal sealed class ChallengeableAction : Action, IChallengeable
{
    public static readonly ChallengeableAction Tax = new ChallengeableAction() { Symbol = 'T' };
    public static readonly ChallengeableAction Assassinate = new ChallengeableAction() { Symbol = 'A', BlockedBy = new Block[1] { Block.Contessa } };
    public static readonly ChallengeableAction Exchange = new ChallengeableAction() { Symbol = 'E' };
    public static readonly ChallengeableAction Steal = new ChallengeableAction { Symbol = 'S', BlockedBy = new Block[2] { Block.Ambassador, Block.Captain } };

    private static readonly Action[] _Actions = new Action[7] { Income, ForeignAid, Coup, Tax, Assassinate, Exchange, Steal };
    private static readonly ChallengeableAction[] _ChallengeableActions = new ChallengeableAction[4] { Tax, Assassinate, Exchange, Steal };

    private ChallengeableAction() : base() { }

    public static IEnumerable<Action> Actions => _Actions;
    public static IEnumerable<ChallengeableAction> ChallengeableActions => _ChallengeableActions;

    public Card RequiredCard => Card.Cards.Single(card => card.AvailableAction == this);
}

internal sealed class Block : Output, IChallengeable
{
    public static readonly Block Duke = new Block() { Symbol = 'd' };
    public static readonly Block Ambassador = new Block() { Symbol = 'a' };
    public static readonly Block Captain = new Block() { Symbol = 'c' };
    public static readonly Block Contessa = new Block() { Symbol = 's' };

    private static readonly Block[] _Blocks = new Block[4] { Ambassador, Captain, Contessa, Duke };

    private Block() : base() { }

    public static IEnumerable<Block> Blocks => _Blocks;

    public Card RequiredCard => Card.Cards.Single(card => card.AvalableBlock == this);
    public Action ActionBlocked => ChallengeableAction.Actions.Single(action => action.BlockedBy.Contains(this));
}

internal sealed class GiveUp : Output
{
    public static readonly GiveUp Ambassador = new GiveUp() { Symbol = '_' };
    public static readonly GiveUp Assassin = new GiveUp() { Symbol = '\'' };
    public static readonly GiveUp Captain = new GiveUp() { Symbol = '<' };
    public static readonly GiveUp Contessa = new GiveUp() { Symbol = '=' };
    public static readonly GiveUp Duke = new GiveUp() { Symbol = '0' };

    private static readonly GiveUp[] _GiveUps = new GiveUp[5] { Ambassador, Assassin, Captain, Contessa, Duke };

    private GiveUp() : base() { }

    public static IEnumerable<GiveUp> GiveUps => _GiveUps;

    public Card Card => Card.Cards.Single(card => card.GiveUp == this);
}

internal interface IChallengeable { Card RequiredCard { get; } }

ฉันไม่สามารถแสดงความคิดเห็นในโพสต์ต้นฉบับ แต่ฉันต้องการที่จะชี้ให้เห็นข้อผิดพลาดในผู้ตัดสินในdetermine_turn_effects()การกระทำ Steal คือการใช้เหรียญของฝ่ายตรงข้ามทั้งหมด ควรใช้อย่างน้อยสองเหรียญ
Dysnomian

เมื่อโปรแกรมนี้พยายามแลกเปลี่ยนมันจะสูญเสียโดยการส่งออกสตริงที่ว่างเปล่า ตัวอย่างเกมเทียบกับสุ่ม
สีม่วง P

ฉันรวบรวมมันด้วย visual studio บน windows เมื่อฉันกลับถึงบ้านฉันจะตรวจสอบให้แน่ใจว่าใช้งานได้กับโมโนเช่นกัน การแลกเปลี่ยนใช้ Console.WriteLine () เพื่อเขียนไปยัง std out สิ่งนี้ใช้ได้เมื่อฉันทดสอบฉันจะตรวจสอบเพิ่มเติมและอัปเดต
Dysnomian

1
ฉันคิดว่าปัญหาคือคุณกำลังตรวจสอบ "lastArg" แต่การ์ด Exchange จะมอบให้คุณที่ดัชนี 3 เช่นเดียวกับการ์ดอื่น ๆ ของคุณ
สีม่วง P

1
เพิ่มในกระดานผู้นำ
สีม่วง P

1

ทนายความของ Rando Aggro

เช่นเดียวกับทนายความมันทำในสิ่งที่ถูกกฎหมายเท่านั้น อย่างไรก็ตามมัน Assassinates, coups ก่อนหน้านี้และจะเลือกการกระทำบางอย่างแบบสุ่ม (เช่นเมื่อใดจะท้าทาย)

#! /usr/bin/env python3
import sys
import random

_, filename, othercoins, mycoins, mycards = sys.argv[:5]


def give_card():
    if "~" in mycards: # give up Ambassador
        return "_"
    if "!" in mycards: # give up Contessa
        return "="
    if "^" in mycards: # give up Assassin
        return "'"
    if "*" in mycards: # give up Captain
        return "<"
    return "0" # give up Duke


with open(filename, "r+") as history:
    line = "\n"
    for a in history:
        line = a # get the last line of the file
    print("{}, {}, {}, {}".format(line, othercoins, mycoins, mycards))
    if line.endswith("\n"): # it has an endline, eg this is a new action
        if int(mycoins) >= 7:
            history.write("C") # coup if I have to
        elif int(mycoins) >= 3 and "^" in mycards:
            history.write("A") # assassinate if I can
        elif "*" in mycards and int(othercoins) > 0:
            history.write("S") # steal if i can
        elif "$" in mycards:
            history.write("T") # tax if i can
        elif random.randint(0,1):
            history.write("F") # foreign aid 50% of the time
        else:
            history.write("I\n") # income
    elif line == "F": # they tried to foreign aid
        if "$" in mycards:
             history.write("d") # block if i can
        else:
             history.write("p")
    elif line == "C": # they coup, sad
        history.write(give_card())
    elif line == "E": # they Exchange
        if random.randint(0,1):
            history.write("q") # challenge 50% of the time
        else: 
            history.write("p") 
    elif line == "T": # they tax
        if random.randint(0,1):
            history.write("q") # challenge 50% of the time
        else: 
            history.write("p") 
    elif line == "A": # they assassinate
        if "!" in mycards:
            history.write("s") # block with contessa if i can
        elif random.randint(0,1):
            history.write("q") # challenge 50% of the time
        else: 
            history.write(give_card()) # otherwise give up a card
    elif line == "S": # they steal
        if "~" in mycards:
            history.write("a") # block with ambassador if i can
        elif "*" in mycards:
            history.write("c") # block with captain if i can
        elif random.randint(0,1):
            history.write("q") # challenge 50% of the time
        else:
            history.write("p")
    elif line.endswith("d") and random.randint(0,1): # they block my foreign aid
        history.write("q") # challenge 50% of the time
    elif line.endswith("a") and random.randint(0,1): # they block as ambassador
        history.write("q") # challenge 50% of the time
    elif line.endswith("c") and random.randint(0,1): # they block as captain
        history.write("q") # challenge 50% of the time
    elif line.endswith("s") and random.randint(0,1): # they block as contessa
        history.write("q") # challenge 50% of the time
    elif line.endswith("sq"): # they challenged my contessa block
        history.write("!") # reveal that i have contessa (no condition because i never lie block)
    elif line.endswith("aq"): # they challenge my Ambassador block
        history.write("~") # reveal that i have a captain (no condition because i never lie block)
    elif line.endswith("cq"): # they challenged my Captain block
        history.write("*") # reveal that I have a Captain (no condition because i never lie block)
    elif line.endswith("dq"): # they challenge my Duke block
        history.write("$") # reveal that I have a Duke (no condition because i never lie block)
    elif line.endswith("Tq"): # they challenge my Tax 
        history.write("$") # reveal that I have a Duke (no condition because i fake tax)
    elif line.endswith("Aq"): # they challenge my assassinate
        history.write("^") # reveal that I had an Assasin
    elif line.endswith("Sq"): # they challenge my steal
        history.write("*") # reveal that I have a Captain
    elif line[-1] in "~^*!$": # they respond to my challenge successfully
        history.write(give_card()) # give up card
        if line[-3] in "acds":
            history.write("\n")
    else:
        history.write("\n")
    history.seek(0)
    print("out")
    print(history.read())

ฉันจัดเรียงฟังก์ชั่น give_card เพื่อยกเลิกบัตรทนายความไม่ได้ใช้ก่อน หากคุณใช้ Assassin จริงๆคุณอาจต้องการจัดเรียงฟังก์ชันนั้นใหม่เพื่อให้ใช้งานได้นานขึ้น
Hiatsu

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

1

หน้ากาก

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

รวบรวมgo build mask.go, ./maskทำงานกับ

package main

import (
    "bytes"
    "io/ioutil"
    "os"
    "strconv"
    "strings"
)

var revealToPunishment = map[byte]byte{'~': '_', '^': '\'', '*': '<', '!': '=', '$': '0'}
var assertedCardMap = map[byte]byte{'A': '^', 'E': '~', 'S': '*', 'T': '$', 'a': '~', 'c': '*', 's': '!', 'd': '$'}

func actWithOneCard(file *os.File, coinCount int, ourCards string) {
    if coinCount >= 7 {
        file.WriteString("C")
    } else if ourCards == "$" {
        file.WriteString("T")
    } else {
        file.WriteString("I\n")
    }
}

func mostRecentClaim(lines [][]byte) byte {
    // If we blocked and were not challenged on the opponent's last turn, return
    // what we claimed to have in the block.
    opponentsLastTurn := lines[len(lines)-1]
    switch b := opponentsLastTurn[len(opponentsLastTurn)-1]; b {
    case 'a', 'c', 's', 'd':
        return b
    }
    // Otherwise, return the first character of our last turn.
    ourLastTurn := lines[len(lines)-2]
    return ourLastTurn[0]
}

func whatWePlanToDoNext(lines [][]byte, coinCount int) string {
    if len(lines) < 2 || mostRecentClaim(lines) == 'E' {
        if coinCount >= 3 {
            return "A"
        } else {
            return "T"
        }
    } else {
        return "E"
    }
}

func ourTurn(file *os.File, coinCount int, ourCards string, lines [][]byte) {
    if len(ourCards) == 1 {
        actWithOneCard(file, coinCount, ourCards)
        return
    }
    file.WriteString(whatWePlanToDoNext(lines, coinCount))
}

func handleChallenge(file *os.File, ourCards string, lines [][]byte) {
    lastLine := lines[len(lines)-1]
    attemptedAction := lastLine[len(lastLine)-2]
    assertedCard := assertedCardMap[attemptedAction]
    for i := range ourCards {
        if ourCards[i] == assertedCard && ourCards[i] != '\x00' {
            file.Write([]byte{assertedCard})
            return
        }
    }
    cardToGiveUp := giveUpCard(ourCards)
    file.Write([]byte{revealToPunishment[cardToGiveUp]})
    switch attemptedAction {
    case 'a', 'c', 'd', 's':
    default:
        file.WriteString("\n")
    }
}

func giveUpCard(ourCards string) byte {
    // If we have a Duke, give up the other card.
    if dukeIndex := strings.Index(ourCards, "$"); -1 < dukeIndex && len(ourCards) == 2 {
        return ourCards[(dukeIndex+1)%2]
    }
    return ourCards[0]
}

func main() {
    filename := os.Args[1]
    coinCount, _ := strconv.Atoi(os.Args[3])
    ourCards := os.Args[4]
    file, _ := os.OpenFile(filename, os.O_RDWR, 0755)
    defer file.Close()

    rawBytes, _ := ioutil.ReadAll(file)
    lines := bytes.Split(rawBytes, []byte{'\n'})
    if len(lines[len(lines)-1]) == 0 {
        lines = lines[:len(lines)-1]
    }
    if len(rawBytes) == 0 {
        file.WriteString("T")
        return
    }
    // Exchange. Prioritize Ambassador, Duke, Assassin.
    if len(ourCards) > 2 {
        var has_ambassador, has_duke, has_assassin bool
        var keptCards string
        for len(ourCards) > 2 {
            var i int
            if i = strings.Index(ourCards, "~"); !has_ambassador && i > -1 {
                keptCards += "~"
                has_ambassador = true
                ourCards = ourCards[:i] + ourCards[i+1:]
            } else if i = strings.Index(ourCards, "$"); !has_duke && i > -1 {
                keptCards += "$"
                has_duke = true
                ourCards = ourCards[:i] + ourCards[i+1:]
            } else if i = strings.Index(ourCards, "^"); !has_assassin && i > -1 {
                keptCards += "^"
                has_assassin = true
                ourCards = ourCards[:i] + ourCards[i+1:]
            } else {
                keptCards += ourCards[:1]
                ourCards = ourCards[1:]
            }
        }
        ourCards = keptCards
        os.Stdout.WriteString(ourCards)
    }
    switch rawBytes[len(rawBytes)-1] {
    case '\n':
        ourTurn(file, coinCount, ourCards, lines)
    // Opponent Couped us. Give up a card.
    case 'C':
        file.Write([]byte{revealToPunishment[giveUpCard(ourCards)]})
    // Opponent blocked, or we Assassinated/Couped them. End our turn.
    case 'a', 'c', 'd', 's', 'p', '_', '\'', '<', '=', '0':
        file.WriteString("\n")
    case 'q':
        handleChallenge(file, ourCards, lines)
    // Opponent did something blockable, block it.
    case 'F':
        file.WriteString("d")
    case 'A':
        file.WriteString("s")
    case 'S':
        if strings.Contains(ourCards, "*") {
            file.WriteString("c")
        } else {
            file.WriteString("a")
        }
    // Opponent took some other action. Let it pass.
    default:
        file.WriteString("p")
    }
}

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

3
@GregMartin หากผู้หญิงคนใดพูดว่าฉันชอบการส่งผลงานของฉันจินตนาการว่าพวกเขาเป็นผู้วางแผนศาลเหมือนในเกมไพ่ทำให้เธอรู้สึกขุ่นเคืองหรือไม่พอใจฉันจะเปลี่ยนมันในจังหวะการเต้นของหัวใจ แต่คุณไม่ใช่ผู้หญิงเกรก และฉันไม่ชอบที่คุณได้ส่งคำตอบเชิงลบที่ฉันใส่ลงไปและคำตอบที่ดีที่สุดในการท้าทายของฉัน - ไม่ใช่เพราะมันไม่เกี่ยวข้องหรือเป็นคำตอบที่ไม่ดีสำหรับคำถาม แต่เป็นเพราะเทรนด์ทางสังคมเล็กน้อย .
Purple P

1

นักการพนัน

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

เขียนใน Python3:

import sys
import random
import time

random.seed(time.time())  # lets keep it rather random

_, filename, othercoins, mycoins, mycards = sys.argv[:5]
legal_actions = sys.argv[5:]

othercoins = int(othercoins)
mycoins = int(mycoins)

income = 'I\n'

foreign_aid, coup, exchange, tax, assassinate, steal, block_aid, \
block_steal_amb, block_steal_cap, block_assassinate, \
pass_challange, do_challenge = "FCETASdacspq"


loosing_actions = "_'<=0"
loose_ambassador, loose_assassin, loose_captain, loose_contessa, loose_duke = loosing_actions
have_ambassador, have_assassin, have_captain, \
have_contessa, have_duke = "~^*!$"

actions_dict = {
    exchange: loose_ambassador, tax: loose_duke, assassinate: loose_assassin, steal: loose_captain,
    block_aid: loose_duke, block_steal_amb: loose_ambassador, block_steal_cap: loose_captain, block_assassinate: loose_contessa
}


def guess_opponents_hand():
    # get number of each card still in play and not in hand
    card_counts = [3] * 5
    card_give_up = list("_'<=0")
    with open(filename, 'r') as history:
        while True:
            line = history.readline()
            if not line:
                break
            for card in card_give_up:
                if card in line:
                    card_counts[card_give_up.index(card)] -= 1

    have_cards = list("~^*!$")

    if sum(card_counts) == 15:
        num_cards = 2
    elif sum(card_counts) == 14:
        if len(mycards) == 1:
            num_cards = 2
        else:
            num_cards = 1
    else:
        num_cards = 1

    for card in mycards:
        card_counts[have_cards.index(card)] -= 1

    # randomly sample a hand for the opponent
    card_1 = sample_from_probabilities([i / sum(card_counts) for i in card_counts], card_give_up)
    if num_cards == 1:
        return card_1
    card_counts[card_give_up.index(card_1)] -= 1
    return card_1 + sample_from_probabilities([i / sum(card_counts) for i in card_counts], card_give_up)


def sample_from_probabilities(success_probabilities, actions):
    # weighted random
    return random.choices(actions, success_probabilities)[0]

def get_prev_char(line, x=1):
    try:
        return line[-1*x]
    except:
        return ""


def get_prev_line(lines):
    try:
        return lines[-2]
    except:
        return []


def give_card(not_swap=True):
    if have_ambassador in mycards:  # give up Ambassador
        return loose_ambassador if not_swap else have_ambassador
    if have_contessa in mycards:  # give up Contessa
        return loose_contessa if not_swap else have_contessa
    if have_assassin in mycards:  # give up Assassin
        return loose_assassin if not_swap else have_assassin
    if have_duke in mycards:  # give up duke
        return loose_duke if not_swap else have_duke
    return loose_captain if not_swap else have_captain  # give up captain


action = legal_actions[0]  # failsafe
with open(filename, 'r') as file:
    all_lines = file.readlines()
    try:
        curr_line = all_lines[-1]
    except IndexError:
        curr_line = ""

obvious_actions = ['C', '~', '^', '*', '!', '$']  # borrowed from Brilliand
obvious = list(set(obvious_actions).intersection((set(legal_actions))))


otherhand = guess_opponents_hand()


# take care of easy choices
if obvious:
    action = coup if coup in obvious else obvious[0]
elif len(set(list(loosing_actions)).intersection(set(legal_actions))) == len(set(legal_actions)):
    action = give_card()
elif len(set([i+'\n' for i in list(loosing_actions)]).intersection(set(legal_actions))) == len(set(legal_actions)):
    action = give_card() + '\n'
elif len(legal_actions) == 1:
    action = legal_actions[0]
elif assassinate in legal_actions and have_assassin in mycards:  # if we can legally assassinate, we try to
    action = assassinate
elif steal in legal_actions and othercoins > 1 and have_captain in mycards:  # we steal when we can or have to prevent a killing coup
    action = steal
elif steal in legal_actions and 7 <= othercoins <= 8 and len(mycards) == 1 and have_assassin not in mycards:
    action = steal
elif block_assassinate in legal_actions and have_contessa in mycards:
    action = block_assassinate
elif block_aid in legal_actions and have_duke in mycards:
    action = block_aid
elif block_steal_cap in legal_actions and have_captain in mycards:
    action = block_steal_cap
elif block_steal_amb in legal_actions and have_ambassador in mycards:
    action = block_steal_amb
elif tax in legal_actions and have_duke in mycards:
    action = tax
elif foreign_aid in legal_actions and foreign_aid in get_prev_line(all_lines):  # opponent wouldn't foreign aid with a duke
    action = foreign_aid
elif block_aid in legal_actions:
    if loose_duke not in otherhand and len(mycards) > 1:
        action = block_aid
    else:
        action = pass_challange if pass_challange in legal_actions else "\n"


elif do_challenge in legal_actions:
    no_challenge = pass_challange if pass_challange in legal_actions else "\n"
    action = do_challenge if len(mycards) > 1 else no_challenge  # failsafe
    if get_prev_char(curr_line) == block_aid and (not loose_duke in otherhand or len(mycards) > 1):  # we don't think opponent has a duke
        action = do_challenge
    elif get_prev_char(curr_line) == exchange:
        action = pass_challange
    elif block_assassinate in legal_actions:
        if len(mycards) == 1:
            if loose_assassin in otherhand and loose_contessa not in otherhand:
                action = block_assassinate
            elif loose_assassin not in otherhand:
                action = do_challenge
            else:
                action = random.choice([block_assassinate, do_challenge])
        else:
            action = give_card()
    elif block_steal_amb in legal_actions:
        if len(mycards) > 1 and 7 <= mycoins <= 8:
            if loose_captain in otherhand:
                probs = [0.4, 0.4, 0.2]
            else:
                probs = [0.2, 0.2, 0.6]

            action = sample_from_probabilities(probs, [block_steal_amb, block_steal_cap, do_challenge])
        elif len(mycards) == 1 and len(otherhand) == 1 and 7 <= mycoins <= 8:
            action = do_challenge  # worth the risk if we defend a winning move
        else:
            action = do_challenge if len(mycards) > 1 else pass_challange  # failsafe
            # go with default

    elif get_prev_char(curr_line) == tax and loose_duke not in otherhand and len(mycards) > 1:
        action = do_challenge
    elif get_prev_char(curr_line) == exchange:
        action = pass_challange
    elif get_prev_char(curr_line) in {block_steal_cap, block_steal_amb, block_aid, block_assassinate}:
        if get_prev_char(curr_line) == block_aid:
            action = do_challenge
        elif get_prev_char(curr_line) == block_assassinate:
            if len(otherhand) == 1 and loose_contessa not in otherhand:
                action = do_challenge
        elif get_prev_char(curr_line) == block_steal_amb:
            action = pass_challange if pass_challange in legal_actions else "\n"

# other choices shall be weighted random choices
elif len(set(legal_actions).intersection({assassinate, steal, tax, income, exchange})) >= 3:
    # decide between aggro ass, aggro steal, aggro Tax, Income, Exchange
    assumed_values = [(assassinate in legal_actions) * (loose_assassin not in otherhand) * 0.1 * len(mycards) * (len(otherhand) - 1) * (mycoins >= 3),
                      (othercoins > 1) * ((othercoins > 5 * 0.3) + othercoins * 0.05) * (len(mycards) - 1) * (loose_ambassador not in otherhand),
                      0.1 * (loose_duke not in otherhand) * (len(mycards) - 1)**(len(otherhand) - 1),
                      0.3,
                      (have_ambassador in mycards) * 0.5/len(mycards)
                      ]
    normalized_probs = [float(i) / sum(assumed_values) for i in assumed_values]
    actions = [assassinate, steal, tax, income, exchange]
    action = sample_from_probabilities(normalized_probs, actions)
elif get_prev_char(curr_line) == do_challenge or get_prev_char(curr_line) == coup:
    # we lost a challenge or coup
    card = give_card()
    action = card if card in legal_actions else action
else:
    # We missed a case. This shouldn't happen. Please tell me so I can fix it!
    # Note: A failsafe always taking a legal action is in place, so please comment out the error raising after telling me :)
    raise RuntimeError("Please tell me this happened, give me the history file, comment out this line, "
                       "and replay. THANKS!")
    pass

with open(filename, "a") as history:
    history.write(str(action))

if len(mycards) > 2:
    mycards = mycards.replace(give_card(False), "", 1)
    mycards = mycards.replace(give_card(False), "", 1)
    print(mycards)

นักสถิติ

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

import sys
import random
import time

random.seed(time.time())  # lets keep it rather random

_, filename, othercoins, mycoins, mycards = sys.argv[:5]
legal_actions = sys.argv[5:]

othercoins = int(othercoins)
mycoins = int(mycoins)

income = 'I\n'

foreign_aid, coup, exchange, tax, assassinate, steal, block_aid, \
block_steal_amb, block_steal_cap, block_assassinate, \
pass_challange, do_challenge = "FCETASdacspq"


loosing_actions = "_'<=0"
loose_ambassador, loose_assassin, loose_captain, loose_contessa, loose_duke = loosing_actions
have_ambassador, have_assassin, have_captain, \
have_contessa, have_duke = "~^*!$"

actions_dict = {
    exchange: loose_ambassador, tax: loose_duke, assassinate: loose_assassin, steal: loose_captain,
    block_aid: loose_duke, block_steal_amb: loose_ambassador, block_steal_cap: loose_captain, block_assassinate: loose_contessa
}


def guess_opponents_hand():
    # get number of each card still in play and not in hand
    card_counts = [3] * 5
    card_give_up = list("_'<=0")
    with open(filename, 'r') as history:
        while True:
            line = history.readline()
            if not line:
                break
            for card in card_give_up:
                if card in line:
                    card_counts[card_give_up.index(card)] -= 1

    have_cards = list("~^*!$")

    if sum(card_counts) == 15:
        num_cards = 2
    elif sum(card_counts) == 14:
        if len(mycards) == 1:
            num_cards = 2
        else:
            num_cards = 1
    else:
        num_cards = 1

    for card in mycards:
        card_counts[have_cards.index(card)] -= 1

    # randomly sample a hand for the opponent
    card_1 = sample_from_probabilities([i / sum(card_counts) for i in card_counts], card_give_up)
    if num_cards == 1:
        return card_1
    card_counts[card_give_up.index(card_1)] -= 1
    return card_1 + sample_from_probabilities([i / sum(card_counts) for i in card_counts], card_give_up)


def sample_from_probabilities(success_probabilities, actions):
    # statistical max, decide randomly on equivalent probabilities
    max_prob = max(success_probabilities)
    indicies = []
    idx = 0
    for i in success_probabilities:
        if i == max_prob:
            indicies.append(idx)
        idx += 1
    choice = random.choice(indicies)
    return actions[choice]


def get_prev_char(line, x=1):
    try:
        return line[-1*x]
    except:
        return ""


def get_prev_line(lines):
    try:
        return lines[-2]
    except:
        return []


def give_card(not_swap=True):
    if have_ambassador in mycards:  # give up Ambassador
        return loose_ambassador if not_swap else have_ambassador
    if have_contessa in mycards:  # give up Contessa
        return loose_contessa if not_swap else have_contessa
    if have_assassin in mycards:  # give up Assassin
        return loose_assassin if not_swap else have_assassin
    if have_duke in mycards:  # give up duke
        return loose_duke if not_swap else have_duke
    return loose_captain if not_swap else have_captain  # give up captain


action = legal_actions[0]  # failsafe
with open(filename, 'r') as file:
    all_lines = file.readlines()
    try:
        curr_line = all_lines[-1]
    except IndexError:
        curr_line = ""

obvious_actions = ['C', '~', '^', '*', '!', '$']  # borrowed from Brilliand
obvious = list(set(obvious_actions).intersection((set(legal_actions))))


otherhand = guess_opponents_hand()


# take care of easy choices
if obvious:
    action = coup if coup in obvious else obvious[0]
elif len(set(list(loosing_actions)).intersection(set(legal_actions))) == len(set(legal_actions)):
    action = give_card()
elif len(set([i+'\n' for i in list(loosing_actions)]).intersection(set(legal_actions))) == len(set(legal_actions)):
    action = give_card() + '\n'
elif len(legal_actions) == 1:
    action = legal_actions[0]
elif assassinate in legal_actions and have_assassin in mycards:  # if we can legally assassinate, we try to
    action = assassinate
elif steal in legal_actions and othercoins > 1 and have_captain in mycards:  # we steal when we can or have to prevent a killing coup
    action = steal
elif steal in legal_actions and 7 <= othercoins <= 8 and len(mycards) == 1 and have_assassin not in mycards:
    action = steal
elif block_assassinate in legal_actions and have_contessa in mycards:
    action = block_assassinate
elif block_aid in legal_actions and have_duke in mycards:
    action = block_aid
elif block_steal_cap in legal_actions and have_captain in mycards:
    action = block_steal_cap
elif block_steal_amb in legal_actions and have_ambassador in mycards:
    action = block_steal_amb
elif tax in legal_actions and have_duke in mycards:
    action = tax
elif foreign_aid in legal_actions and foreign_aid in get_prev_line(all_lines):  # opponent wouldn't foreign aid with a duke
    action = foreign_aid
elif block_aid in legal_actions:
    if loose_duke not in otherhand and len(mycards) > 1:
        action = block_aid
    else:
        action = pass_challange if pass_challange in legal_actions else "\n"


elif do_challenge in legal_actions:
    no_challenge = pass_challange if pass_challange in legal_actions else "\n"
    action = do_challenge if len(mycards) > 1 else no_challenge  # failsafe
    if get_prev_char(curr_line) == block_aid and (not loose_duke in otherhand or len(mycards) > 1):  # we don't think opponent has a duke
        action = do_challenge
    elif get_prev_char(curr_line) == exchange:
        action = pass_challange
    elif block_assassinate in legal_actions:
        if len(mycards) == 1:
            if loose_assassin in otherhand and loose_contessa not in otherhand:
                action = block_assassinate
            elif loose_assassin not in otherhand:
                action = do_challenge
            else:
                action = random.choice([block_assassinate, do_challenge])
        else:
            action = give_card()
    elif block_steal_amb in legal_actions:
        if len(mycards) > 1 and 7 <= mycoins <= 8:
            if loose_captain in otherhand:
                probs = [0.4, 0.4, 0.2]
            else:
                probs = [0.2, 0.2, 0.6]

            action = sample_from_probabilities(probs, [block_steal_amb, block_steal_cap, do_challenge])
        elif len(mycards) == 1 and len(otherhand) == 1 and 7 <= mycoins <= 8:
            action = do_challenge  # worth the risk if we defend a winning move
        else:
            action = do_challenge if len(mycards) > 1 else pass_challange  # failsafe
            # go with default

    elif get_prev_char(curr_line) == tax and loose_duke not in otherhand and len(mycards) > 1:
        action = do_challenge
    elif get_prev_char(curr_line) == exchange:
        action = pass_challange
    elif get_prev_char(curr_line) in {block_steal_cap, block_steal_amb, block_aid, block_assassinate}:
        if get_prev_char(curr_line) == block_aid:
            action = do_challenge
        elif get_prev_char(curr_line) == block_assassinate:
            if len(otherhand) == 1 and loose_contessa not in otherhand:
                action = do_challenge
        elif get_prev_char(curr_line) == block_steal_amb:
            action = pass_challange if pass_challange in legal_actions else "\n"

# other choices shall be weighted random choices
elif len(set(legal_actions).intersection({assassinate, steal, tax, income, exchange})) >= 3:
    # decide between aggro ass, aggro steal, aggro Tax, Income, Exchange
    assumed_values = [(assassinate in legal_actions) * (loose_assassin not in otherhand) * 0.1 * len(mycards) * (len(otherhand) - 1) * (mycoins >= 3),
                      (othercoins > 1) * ((othercoins > 5 * 0.3) + othercoins * 0.05) * (len(mycards) - 1) * (loose_ambassador not in otherhand),
                      0.1 * (loose_duke not in otherhand) * (len(mycards) - 1)**(len(otherhand) - 1),
                      0.3,
                      (have_ambassador in mycards) * 0.5/len(mycards)
                      ]
    normalized_probs = [float(i) / sum(assumed_values) for i in assumed_values]
    actions = [assassinate, steal, tax, income, exchange]
    action = sample_from_probabilities(normalized_probs, actions)
elif get_prev_char(curr_line) == do_challenge or get_prev_char(curr_line) == coup:
    # we lost a challenge or coup
    card = give_card()
    action = card if card in legal_actions else action
else:
    # We missed a case. This shouldn't happen. Please tell me so I can fix it!
    # Note: A failsafe always taking a legal action is in place, so please comment out the error raising after telling me :)
    raise RuntimeError("Please tell me this happened, give me the history file, comment out this line, "
                       "and replay. THANKS!")
    pass

with open(filename, "a") as history:
    history.write(str(action))

if len(mycards) > 2:
    mycards = mycards.replace(give_card(False), "", 1)
    mycards = mycards.replace(give_card(False), "", 1)
    print(mycards)


1
โปรแกรมนี้ล้มเหลวในไฟล์ว่างเปล่าเมื่อมันไปก่อน Traceback (most recent call last): File "gambler.py", line 94, in <module> otherhand = guess_opponents_hand() File "gambler.py", line 61, in guess_opponents_hand card_counts[card_give_up.index(card_1)] -= 1 ValueError: ['_'] is not in listเมื่อมันไปสองก็เกิดปัญหากับข้อความเช่น:
สีม่วง P

สามารถแก้ไขข้อผิดพลาดนั้นได้ ขอโทษฉันโพสต์มันด้วยความรีบ ๆ ฉันจะทำให้แน่ใจว่าได้ทดสอบกับผู้ชี้ขาดของคุณจนถึงวันพรุ่งนี้ แต่มีการแก้ไขข้อผิดพลาดที่ชัดเจน ขอโทษอีกครั้ง.
jaaq

1
ข่าวดีการแลกเปลี่ยนของนักพนันทำงานกับเครื่องของฉัน! มันยังคงล้มเหลวหากคู่ต่อสู้พยายามช่วยเหลือจากต่างประเทศและไม่มี Duke แต่มันถูกเพิ่มไปยังกระดานผู้นำ
สีม่วง P

1
@jaaq ยังคงริบอยู่ถ้าคู่ต่อสู้พยายามช่วยเหลือจากต่างประเทศและไม่มี Duke; จำเป็นต้องตอบกลับด้วยการผ่านไม่ใช่การสิ้นสุดของเทิร์น
Brilliand

1
@jaaq ฉันแก้ไขข้อผิดพลาดที่ Brilliand กล่าวถึงและเพิ่มสถิติในลีดเดอร์บอร์ด เมื่อรายการของคุณถูกลอบสังหารด้วยบัตรที่เหลือหนึ่งใบพวกเขาจะถูกปรับเป็นลายลักษณ์อักษร\nแทนบัตรที่พวกเขาต้องการยกเลิก ในสถานการณ์เช่นนี้ดีกว่าที่จะต่อสู้กับบล็อกหรือความท้าทาย หากนักพนันชนะ 5 เกมที่ถูกริบเช่นนี้มันจะเกิดขึ้นเป็นครั้งแรก
สีม่วง P
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.