Camel Up Cup: การแข่งขันเกมกระดาน AI


11

Camel Up Cup 2k18

ในความท้าทายนี้เราจะเล่นเกมกระดานที่ได้รับความนิยมอย่าง Camel Up

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

วิธีการเล่น

นี่คือความคิดคร่าวๆของวิธีการเล่น การดูวิดีโออย่างใดอย่างหนึ่งอาจมีประโยชน์มากกว่าเพราะมีภาพ :)

ในเทิร์นของคุณคุณมี 4 ตัวเลือก

  1. ย้ายอูฐ นี่เป็นการเลือกอูฐจากผู้ที่ไม่ได้ย้ายและย้ายระหว่าง 1-3 ช่องว่าง คุณได้รับ 1 เหรียญ รอบสิ้นสุดเมื่ออูฐทั้งห้าเคลื่อนไหวแล้วพวกเขาก็สามารถเคลื่อนไหวได้ทั้งหมด
  2. วางกับดัก สิ่งนี้จะปรากฏบนกระดานจนกระทั่งสิ้นสุดรอบ คุณเลือก +1 กับดัก หากอูฐหรืออูฐสแต็คตกลงมาพวกมันจะเคลื่อนที่ +1 และคุณจะได้รับเหรียญ คุณไม่สามารถวางกับดักในสี่เหลี่ยมจัตุรัสคุณสามารถวางกับดักที่ที่อูฐอยู่แม้ว่ามันจะมีผลกับอูฐที่ตกลงมาบนหลังเท่านั้น
  3. เดิมพันผู้ชนะรอบ คุณเดิมพันกับผู้ชนะรอบ พวกเขาชนะคุณจะได้รับ 5/3/2/1 ทั้งนี้ขึ้นอยู่กับว่าคุณเป็นคนที่ 1/2/3 เพื่อเดิมพันกับอูฐนั้น
  4. ผู้ชนะเกม / ผู้แพ้ คุณเดิมพันว่าใครจะเป็นคนแรกหรือคนสุดท้ายในตอนท้ายของเกม คุณได้รับ 8/5/3/1/1 (ฉันคิดว่า) ขึ้นอยู่กับว่าคุณอยู่ที่ 1/2/3 / ฯลฯ เพื่อเดิมพันกับอูฐนั้น

หมายเหตุ:

  • มีอูฐ 5 ตัว พวกเขาเริ่มจากตำแหน่งสุ่มจาก 0-2
  • เมื่ออูฐถูกย้าย (ดูด้านบนสำหรับสิ่งที่เรียกสิ่งนี้) พวกมันจะขยับ 1-3 กำลังสอง หากพวกเขาจะถูกวางไว้ในตารางที่มีอูฐอีกพวกเขาจะวาง "ด้านบน" ของอื่น ๆ สร้างอูฐสแต็ค หากมีการเคลื่อนย้ายอูฐก็จะย้ายอูฐทุกตัวที่อยู่เหนือมันไปวางบนกองอูฐ อูฐที่ด้านบนของสแต็คจะถูกพิจารณาในการนำ
  • หากคุณลงสู่กับดัก +1 (ดูด้านบนสำหรับสิ่งที่เรียกสิ่งนี้) คุณจะเลื่อนไปข้างหน้าหนึ่งช่อง ใช้กฎการสแต็กมาตรฐาน
  • อย่างไรก็ตามหากคุณกด -1 กับดักคุณจะเลื่อนหนึ่งช่องถอยหลัง คุณอยู่ใต้กองอูฐที่อยู่ในจัตุรัสนั้นถ้ามี
  • เกมจะจบลงเมื่ออูฐพุ่งเข้าสู่ตารางที่ 16 สิ่งนี้จะเรียกใช้รอบปลายและจุดจบของเกมทันที
  • การเดิมพันผู้ชนะเกม / ผู้แพ้สามารถทำได้เพียงครั้งเดียวต่ออูฐ คือคุณไม่สามารถเดิมพันอูฐเพื่อชนะและแพ้ในเกม

ท้าทาย

ในการท้าทายนี้คุณจะเขียนโปรแกรม Python 3 เพื่อเล่นผู้เล่นสี่คนผู้ชนะจะได้รับเกมทั้งหมดของ Camel Up

โปรแกรมของคุณจะได้รับ gamestate ซึ่งประกอบด้วย:

  • camel_track : กับที่ตั้งของอูฐ
  • Trap_track : ด้วยตำแหน่งของกับดัก (รายการของรูปแบบ [trap_type (-1,1), ผู้เล่น])
  • player_has_placed_trap : อาร์เรย์ที่บอกคุณว่าผู้เล่นวางกับดักรอบนี้หรือไม่
  • round_bets : อาร์เรย์ของการวางเดิมพันรอบนี้ จากรูปแบบ [อูฐ, ผู้เล่น]
  • game_winner_bets / game_loser_bets : อาร์เรย์ของการเดิมพันที่ผู้เล่นทำเพื่อให้อูฐชนะหรือแพ้ในเกม คุณจะสามารถเห็นคุณค่าของผู้เล่นที่ทำการเดิมพันไม่ใช่ผู้ที่เดิมพัน คุณสามารถรู้ว่าคุณเป็นใครเดิมพัน #of แบบฟอร์ม [อูฐผู้เล่น]
  • player_game_bets : การเป็นตัวแทนของ game_winner_bets / game_loser_bets ดูเฉพาะการเดิมพันที่บอทของคุณทำ
  • player_money_values : อาร์เรย์ที่แสดงจำนวนเงินที่ผู้เล่นแต่ละคนมี
  • camel_yet_to_move : อาร์เรย์แสดงว่าอูฐได้ย้ายรอบนี้

นอกจากเกมแล้วคุณยังจะได้รับ:

  • ผู้เล่น : จำนวนเต็มบอกคุณว่าหมายเลขผู้เล่นของคุณคืออะไร (0-3)

ไวยากรณ์สำหรับสิ่งที่ผู้เล่นควรกลับมาคือ:

  • [0]: ย้ายอูฐ
  • [1, Trap_type, trap_location]: วางกับดัก
  • [2, projected_round_winner]: ทำการเดิมพันผู้ชนะรอบ
  • [3, projected_game_winner]: ทำการเดิมพันผู้ชนะเกม
  • [4, projected_game_loser]: ทำการเดิมพันผู้แพ้เกม

สิ่งนี้ควรห่อหุ้มด้วยวิธีการเคลื่อนไหว (ผู้เล่น, นักเล่นเกม)

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

class Player1(PlayerInterface):
     def move(player,g):
         if min(g.player_money_values) == g.player_money_values[player]:
            return [2,random.randint(0,len(g.camels)-1)]
        return [1,math.floor(2*random.random())*2-1,random.randint(1,10)]

เกมดังกล่าวได้รับเลือกด้วยเหตุผลหลายประการ: มีตัวเลือกค่อนข้างเล็กให้เลือก (ประมาณ 20 ตัวเลือกต่อเทิร์น, แคบลงได้อย่างง่ายดายจนถึงประมาณ 3-4), เกมสั้นและมีองค์ประกอบของโชค (ทำให้ ดังนั้นแม้แต่บอท "ที่ไม่ดี" ก็สามารถชนะได้)

เพลย์

รองชนะเลิศอันดับการแข่งขันสามารถพบได้ที่นี่: อูฐขึ้นถ้วย วิ่งcamelup.pyเพื่อรันทัวร์นาเมนต์หรือฟังก์ชั่น PlayGame เพื่อเล่นเกม ฉันจะอัปเดตที่เก็บข้อมูลนั้นด้วยการส่งใหม่ players.pyโปรแกรมตัวอย่างที่สามารถพบได้ใน

การแข่งขันประกอบด้วย 100 เกมต่อผู้เล่น 10 คน (ปัดเศษขึ้นดังนั้นผู้เล่น 14 คนหมายถึง 200 เกม) แต่ละเกมจะมีผู้เล่นสุ่มสี่คนที่เลือกจากกลุ่มผู้เล่นเพื่อเติมเต็มสี่ตำแหน่ง ผู้เล่นจะไม่สามารถอยู่ในเกมได้สองครั้ง

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

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

ผู้เล่นที่ส่งจะถูกเพิ่มลงในพูล ฉันเพิ่มบอทที่โง่สามตัวและอีกอันที่ฉันเริ่มไว้

คำเตือน

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

จำกัด เวลาที่บอทของคุณใช้คือประมาณ 10 วินาทีต่อเทิร์น

การส่งอาจไม่ซ้ำกันก่อนหน้านี้ส่ง

โปรดอย่าดูการเดิมพัน game_winner หรือ game_loser จากผู้เล่นอื่น มันค่อนข้างง่ายที่จะทำ แต่ยังคงโกง

หากคุณมีคำถามใด ๆ อย่าลังเลที่จะถาม

การชนะ

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

ผล

Player0: 12
Player1: 0
Player2: 1
Sir_Humpfree_Bogart: 87

บางทีฉันอาจจะอ่านมันได้ แต่มีอูฐเล่นอยู่กี่ตัว? นอกจากนี้พวกเขาต้องเดินทางไปยังอีกฝั่งหนึ่งกี่สี่เหลี่ยม? จากรหัส GitHub ของคุณฉันค่อนข้างมั่นใจว่ามันเป็นอูฐ 5 ตัวและ 25 ช่อง แต่ฉันไม่เห็นสิ่งนี้ในคำอธิบายการท้าทาย สำหรับการวางเดิมพันเราสามารถเดิมพันจำนวนเท่าใดก็ได้หรือจะเป็นการเดิมพัน 1 ตามค่าเริ่มต้น? เรามีวงเงินการใช้จ่ายหรือเราสามารถเดิมพันได้ทุกรอบหรือไม่? สำหรับผู้เล่นที่ย้ายอูฐอูฐตัวไหนล่ะ? อูฐกับ player-nr ของคุณใช่ไหม? ถ้าใช่ทำไมมี 4 ผู้เล่น แต่ 5 อูฐ?
Kevin Cruijssen

1
คงจะดีกว่าถ้ามีคำตอบ Perl
ผู้ชายที่สุ่ม

ยินดีต้อนรับสู่ PPCG!
AdmBorkBork

100 เกมต่อ 10 ผู้เล่นดูเหมือนจะค่อนข้างต่ำ IMO โดยเฉพาะอย่างยิ่งกับเกมที่มีการสุ่มมาก
นาธานเมอร์ริ

1
@AdmBorkBork ขอขอบคุณ! ฉันยังใหม่กับสิ่งนี้ดังนั้นยินดีต้อนรับพอยน์เตอร์ทั้งหมด สิ่งนี้ทำงานได้ดีในชีวิตจริง - แสดงให้เห็นว่ามันเล่นที่นี่อย่างไร
Tyler Barron

คำตอบ:


1

Sir_Humpfree_Bogart.py

นี่คือฉันบอทที่ทำสำหรับอูฐขึ้นการแข่งขันถ้วย

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

EV_roundwin = (chance_1st)*(payout) + (chance_2nd)*(payout) - (chance_3rd_or_worse)*(cost)

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

EV_gamewin = (chance_1st)*(payout) - (chance_2nd_or_worse)*(cost)

ตัวเลือกอื่นเท่านั้นที่เคลื่อนไหวอูฐ (ซึ่งให้ผลตอบแทนหนึ่งเหรียญเสมอดังนั้นค่าที่คาดไว้คือหนึ่ง) และวางกับดัก ทั้งสองทีมรู้สึกว่าการวางกับดักเป็นตัวเลือกที่อ่อนแอพอที่จะเพิกเฉยได้ ด้วยข้อมูลนี้บอตจึงเลือกตัวเลือกที่มีค่าสูงสุดที่คาดไว้

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

Functional_EV = EV + (upshot-EV) * riskiness

โดย upshot คือการจ่ายเงินสูงสุดที่คุณจะได้รับจากการตัดสินใจและความเสี่ยงอยู่ในช่วงตั้งแต่ 0 ถึง 1


0

players.py

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

import random
import math
from playerinterface import PlayerInterface

class Player0(PlayerInterface):
    def move(player,g):
        #This dumb player always moves a camel
        return [0]

class Player1(PlayerInterface):
    def move(player,g):
        #This player is less dumb. If they have the least amount of money they'll make a round winner bet
        #If they aren't in last then they'll place a trap on a random square. Still p dumb though
        if min(g.player_money_values) == g.player_money_values[player]:
            return [2,random.randint(0,len(g.camels)-1)]
        return [1,math.floor(2*random.random())*2-1,random.randint(1,10)]

class Player2(PlayerInterface):
    def move(player,g):
        #This dumb player always makes a round winner bet
        return [2,random.randint(0,len(g.camels)-1)]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.