Intro
นี่คือการโต้ตอบแบบกษัตริย์ของเขาประกวดซึ่งคอนโทรลเลอร์มีอยู่ใน Stack Snippet ที่ด้านล่างของคำถาม ตัวควบคุมจะอ่านคำตอบและเล่นผ่านเกมโดยอัตโนมัติ ทุกคนสามารถเรียกใช้ได้ทุกเมื่อในเบราว์เซอร์
กลศาสตร์ของการประกวดครั้งนี้มีความคล้ายคลึงกับสีแดงกับสีน้ำเงิน - Pixel ทีม BattleBots ยกเว้นเกมที่กำลังเล่นอยู่ในขณะที่ยังใช้กริดอยู่จะแตกต่างกันโดยสิ้นเชิง แต่ละเกมคือ 1 ต่อ 1 และไม่มีทีม แต่ละรายการจะต่อสู้เพื่อตัวเองและมีเพียงหนึ่งเดียวเท่านั้นที่จะเป็นผู้ชนะรอบชิงชนะเลิศ
คอนโทรลเลอร์ใช้ JavaScript และ JavaScript เป็นภาษาสคริปต์ฝั่งไคลเอ็นต์เท่านั้นที่สนับสนุนเบราว์เซอร์ส่วนใหญ่คำตอบทั้งหมดจะต้องเขียนด้วย JavaScript เช่นกัน
ในข้อมูลจำเพาะนี้ข้อความที่เป็นตัวเอียงใช้เพื่อระบุคำที่เป็นทางการสำหรับช่างเกมหรือทรัพย์สิน ข้อกำหนดเหล่านี้มีการใช้ตลอดเพื่อช่วยรักษาวิธีการอ้างอิงถึงส่วนต่าง ๆ ของเกมไว้อย่างเหนียวแน่นและชัดเจน
เพลย์
ข้อมูลพื้นฐานเกี่ยวกับ
คำตอบสำหรับคำถามนี้ทุกคนเป็นตัวแทนของผู้เล่น เกมการแข่งขันระหว่างผู้เล่นสองP1และP2 แต่ละควบคุมผู้เล่นฝูง 8 บอทหมายเลขตั้งแต่ 0 ถึง 7 เกมจะเกิดขึ้นในตาราง , 128 × 64 เซลล์ที่เกิดเหตุซึ่งอยู่ด้านล่าง 8 แถวเริ่มจากการเป็นผนัง (ที่บล็อก ') และแถวอื่น ๆ เริ่มต้นเป็นอากาศ เซลล์นอกขอบเขตกริดถือว่าเป็นอากาศ
พิกัด x ของกริดจะอยู่ในช่วงจาก 0 ทางด้านซ้ายถึง 127 ทางด้านขวาและ y มีช่วงจาก 0 ที่ด้านบนถึง 63 ที่ด้านล่าง
ตัวอย่างตารางเริ่มต้น:
บ็อตจะอยู่ในแนวเดียวกับเซลล์กริดเสมอและบ็อตจำนวนมากอาจอยู่ในเซลล์เดียวกัน บอตสามารถครอบครองเซลล์อากาศได้เท่านั้น บอทของ P1 มักจะเริ่มในบรรทัดที่ 0-7 ที่ด้านซ้ายสุดของแถวเหนือกำแพงและบอทของ P2 จะเริ่มในแถวที่ 7-0 ที่ด้านขวาสุดเสมอ
เพื่อนบ้านของบอทหรือมือถือเป็น 8 เซลล์โดยตรงมุมฉากและเส้นทแยงมุมกับมัน
เขตการมอง ( FOV ) ของบอทคือเซลล์สี่เหลี่ยมจัตุรัสขนาด 13 × 13 ที่มีศูนย์กลางอยู่ที่บอท บอทของเซลล์หรือศัตรูถูกกล่าวว่าอยู่ใน FOV ของผู้เล่นหากอยู่ใน FOV อย่างน้อยหนึ่งบอทของผู้เล่น
การเคลื่อนไหว & การกระทำ
ในระหว่างเกมผู้เล่นแต่ละคนได้รับการย้าย 1000 ครั้ง P1 เลื่อนก่อนแล้วตามด้วย P2 จากนั้นตามด้วย P1 และต่อ ๆ ไปจนกระทั่งมีการเคลื่อนไหวทั้งหมด 2,000 ครั้งซึ่งจะทำให้เกมจบลง
ในระหว่างการย้ายผู้เล่นแต่ละคนจะได้รับข้อมูลเกี่ยวกับสถานะของเกมและเซลล์กริดและบอทของศัตรูใน FOV ของพวกเขาและใช้มันเพื่อตัดสินใจเกี่ยวกับการกระทำของบอทของพวกเขาแต่ละคน
การกระทำเริ่มต้นจะไม่ทำอะไรเลยโดยที่บอทไม่ย้ายหรือโต้ตอบกับกริด
การดำเนินการอื่น ๆ ที่มีการย้าย , คว้าและสถานที่ :
บอทสามารถย้ายไปยังหนึ่งในเซลล์ที่อยู่ใกล้เคียง C ได้ถ้า:
- C ไม่อยู่นอกขอบเขต
- C คืออากาศ (เช่นไม่ใช่กำแพง)
- และอย่างน้อยหนึ่งในประเทศเพื่อนบ้านของ C เป็นกำแพง
ถ้าสำเร็จบอทจะย้ายไปที่ C
บอทสามารถคว้าหนึ่งในเซลล์ใกล้เคียง C ได้ถ้า:
- C ไม่อยู่นอกขอบเขต
- C คือกำแพง
- และบอทก็ไม่ได้ถือกำแพงอยู่แล้ว
หากประสบความสำเร็จ C จะกลายเป็นอากาศและบอทก็จะถือกำแพงได้
บอทสามารถวางไว้ที่หนึ่งในเซลล์ใกล้เคียง C ถ้า:
- C ไม่อยู่นอกขอบเขต
- C คืออากาศ
- ไม่มีบอทของผู้เล่นทั้งสองใช้ C
- บอทกำลังถือกำแพงอยู่
หากประสบความสำเร็จ C จะกลายเป็นกำแพงและบอทจะไม่ถือกำแพงอีกต่อไป
การกระทำที่ไม่สำเร็จส่งผลให้ไม่ทำอะไรเลย
เซลล์ที่ถูกครอบครองโดยบ็อตแบกผนังอย่างน้อยหนึ่งแห่งจะมีสี่เหลี่ยมจัตุรัสสีผนังเล็ก ๆ บอทเริ่มโดยไม่มีกำแพง
หน่วยความจำ
ในระหว่างการเคลื่อนย้ายผู้เล่นสามารถเข้าถึงและเปลี่ยนหน่วยความจำสตริงว่างเปล่าเริ่มแรกที่มีอยู่ตลอดทั้งเกมและสามารถใช้เพื่อเก็บข้อมูลเชิงกลยุทธ์
เป้าหมาย
เซลล์ในกากบาทสีเหลืองเป็นเป้าหมายซึ่งจะเริ่มในตำแหน่งสุ่ม ผู้เล่นแต่ละคนมีคะแนนที่เริ่มต้นที่ 0 เมื่อบอทของผู้เล่นย้ายไปที่เป้าหมายคะแนนของผู้เล่นนั้นจะเพิ่มขึ้น 1 และเป้าหมายจะถูกเปลี่ยนตำแหน่งแบบสุ่มก่อนเทิร์นถัดไป ผู้เล่นที่มีคะแนนสูงสุดในตอนท้ายของเกมที่ชนะ มันเสมอกันถ้าคะแนนเท่ากัน
หากบอตหลายตัวเคลื่อนที่ไปยังเป้าหมายระหว่างการย้ายผู้เล่นยังคงได้รับเพียงแค่จุดเดียว
หากเป้าหมายอยู่ในที่เดียวกันสำหรับการเคลื่อนไหว 500 ครั้งการเปลี่ยนตำแหน่งนั้นจะถูกสุ่มอีกครั้ง เมื่อใดก็ตามที่เป้าหมายอยู่ในตำแหน่งสุ่มจะรับประกันได้ว่าจะไม่ถูกวางไว้ในเซลล์ที่ครอบครองโดยบอท
โปรแกรมอะไร
เขียนเนื้อหาสำหรับฟังก์ชันนี้:
function myMove(p1, id, eid, move, goal, grid, bots, ebots, getMem, setMem) {
//body goes here
}
มันจะถูกเรียกหนึ่งครั้งทุกครั้งที่ผู้เล่นของคุณเคลื่อนไหวและต้องการคืนการกระทำที่คุณต้องการให้บอทของคุณแต่ละคนไปในระหว่างการเคลื่อนไหวนั้น
คุณสามารถใช้รหัสBaselineเป็นจุดเริ่มต้น
พารามิเตอร์
p1
เป็นบูลนั่นคือtrue
ถ้าคุณเป็น P1 และfalse
ถ้าคุณเป็น P2id
เป็นจำนวนเต็มที่เป็น ID คำตอบของคำตอบของคุณ
- คุณสามารถค้นหา ID ของคำตอบได้โดยคลิกที่ลิงก์ 'แชร์' ด้านล่างและค้นหาหมายเลขทันที
a/
ใน URL- ID ของรายการทดสอบคือ -1
eid
เป็นจำนวนเต็มที่เป็น ID คำตอบของคำตอบของศัตรูของคุณmove
เป็นจำนวนเต็มตั้งแต่ 1 ถึง 1,000 ที่บอกว่าคุณกำลังเคลื่อนไหวอะไรgoal
เป็นวัตถุที่มีx
และy
คุณสมบัติ นี่คือพิกัดของเป้าหมาย พวกเขาจะได้รับแม้ว่าเป้าหมายจะออกมาจาก FOV ของคุณgrid
เป็นฟังก์ชั่นที่ใช้ใน x และ ygrid(x,y)
ขัดแย้งเช่น มันกลับมา:
-1
สำหรับ 'ไม่ทราบ' หากอาร์กิวเมนต์ไม่ใช่จำนวนเต็มสองค่าหรือหากx,y
ไม่ได้อยู่ใน FOV ของคุณ0
สำหรับ 'อากาศ' ถ้าx,y
อยู่นอกขอบเขตหรือถ้าเซลล์ที่x,y
มีอากาศ1
สำหรับ 'ผนัง' หากเซลล์ที่x,y
เป็นผนัง
bots
คืออาร์เรย์ของบอท 8 อันของคุณ องค์ประกอบของวัตถุที่มีคุณสมบัติx
,y
และhasWall
:
x
และy
เป็นพิกัดของบอทhasWall
คือtrue
ถ้าบอทจะแบกผนังและfalse
หากไม่ได้
bots
มีการจัดเรียงตามปกติเสมอดัชนี Nth สอดคล้องกับหมายเลข bot Nebots
เป็นอาร์เรย์ของวัตถุที่มีx
,y
และคุณสมบัติเช่นเดียวกับhasWall
bots
เฉพาะบอทของศัตรูใน FOV ของคุณเท่านั้นที่เข้าebots
มา ดังนั้นมันจะมีความยาว 0 ถ้าหากไม่มีบอทศัตรูใน FOV ของคุณ มันมีคำสั่งแบบสุ่มgetMem
เป็นฟังก์ชันที่ไม่มีอาร์กิวเมนต์ที่ส่งคืนหน่วยความจำของคุณsetMem
เป็นฟังก์ชั่นที่รับอาร์กิวเมนต์หนึ่งตัว M หาก M เป็นสายอักขระ 256 ตัวหรือน้อยกว่าหน่วยความจำของคุณจะถูกอัพเดตเป็น M ไม่เช่นนั้นจะไม่มีอะไรเกิดขึ้น
console
วัตถุของเบราว์เซอร์นั้นมีให้สำหรับรายการทดสอบเพียงอย่างเดียว
ส่งคืนค่า
ฟังก์ชันของคุณจำเป็นต้องส่งคืนอาร์เรย์ของจำนวนเต็ม 8 จำนวนโดยมีค่าตั้งแต่ 0 ถึง 24 ค่าที่ดัชนี N คือการดำเนินการที่บอทหมายเลข N จะรับ
บอตทั้งหมดของคุณจะไม่ทำอะไรเลยถ้าฟังก์ชั่นของคุณ:
- โยนความผิดพลาดใด ๆ ( ข้อผิดพลาด )
- ใช้เวลานานกว่า20 มิลลิวินาทีในการดำเนินการ ( หมดเวลา )
- ไม่ส่งคืนอาร์เรย์จำนวนเต็ม 8 จำนวนตั้งแต่ 0 ถึง 24 ( มีรูปแบบไม่ถูกต้อง )
เพื่อความสะดวกจะมีการแสดงจำนวนข้อผิดพลาดการหมดเวลาและการดำเนินการที่ผิดรูปแบบเมื่อเกมสิ้นสุด
แต่ละหมายเลขตั้งแต่ 0 ถึง 24 สอดคล้องกับการกระทำของบอทโดยเฉพาะ:
- 0 ใช้เพื่อไม่ทำอะไรเลย
- 1-8 สำหรับการเคลื่อนย้าย
- 9-16 มีไว้สำหรับโลภ
- 17-24 สำหรับการวาง
แต่ละค่า 8 ค่าสำหรับการเคลื่อนที่การจับและการวางสอดคล้องกับหนึ่งในเซลล์ใกล้เคียงของบอทดังที่แสดงไว้ที่นี่:
ตัวอย่างเช่น15
การกระทำคือการจับเซลล์ด้านล่าง ธ ปท.
การกระทำของบอทนั้นได้รับการจัดการตามลำดับบอท 0 ถึงบอท 7 ตัวอย่างเช่นถ้าในระหว่างการย้ายบอทหนึ่ง 0 ถูกบอกให้วางผนังในเซลล์อากาศบ็อตเดียวกัน 1 ถูกบอกให้ย้ายไปที่เซลล์อากาศจะกลายเป็นกำแพงก่อนบอท การกระทำของ 1 ได้รับการจัดการและบอท 1 จะไม่ประสบความสำเร็จ
การกระทำที่ไม่ประสบความสำเร็จกลายเป็นทำ nothings และบอกว่าจะล้มเหลว ตัวนับการกระทำที่ล้มเหลวจะปรากฏขึ้นเมื่อเกมสิ้นสุด
กฎระเบียบ
ฉันอาจตัดสิทธิ์ผู้ใช้หรือคำตอบที่ไม่ปฏิบัติตามกฎเหล่านี้เป็นการชั่วคราวหรือถาวร ผลงานที่ถูกตัดสิทธิ์จะไม่มีสิทธิ์ชนะ
เมื่อประกาศตัวแปรหรือฟังก์ชั่นคุณต้องใช้
var
คำหลัก
เช่นvar x = 10
หรือvar sum = function(a, b){ return a + b }
สิ่งต่าง ๆ ที่ประกาศโดยไม่var
กลายเป็นส่วนกลางและอาจรบกวนการทำงานของคอนโทรลเลอร์ มีการดำเนินการตามขั้นตอนต่าง ๆ เพื่อให้การแทรกแซงนี้เป็นไปไม่ได้ แต่ให้ทำเช่นนี้เพื่อให้แน่ใจรหัสของคุณไม่ควรทำงานช้าหรือเสียเวลา
เป็นไปไม่ได้ที่จะหยุดการทำงานของ JavaScript ในการทำงานกลางคันดังนั้นโค้ดของผู้เล่นแต่ละคนจะถูกเรียกใช้จนเสร็จสมบูรณ์ หากรหัสของคุณใช้เวลานานในการรันทุกคนที่ใช้งานเครื่องเล่นของคุณจะสังเกตเห็นและรำคาญ โดยทั่วไปแล้วรายการจะทำงานได้ดีภายในขีด จำกัด 20ms- คุณต้องใช้รหัสที่เข้ากันได้กับ ECMAScript 5 ใน Firefox เวอร์ชันล่าสุดเนื่องจากนี่คือที่ที่ฉันจะใช้งาน อย่าใช้คุณสมบัติจาก ECMAScript 6เนื่องจากยังไม่รองรับในเบราว์เซอร์จำนวนมาก
- คุณอาจตอบได้สูงสุด 3ครั้ง แต่หากกลยุทธ์ของคุณแตกต่างกันมาก คุณสามารถแก้ไขคำตอบได้มากเท่าที่ต้องการ
- คุณอาจจะไม่พยายามที่จะมีการจัดเรียงของหน่วยความจำใด ๆ ยกเว้นผ่านการใช้และ
getMem
setMem
- คุณต้องไม่พยายามเข้าถึงหรือดัดแปลงคอนโทรลเลอร์รหัสของผู้เล่นอื่นหรือแหล่งข้อมูลภายนอก
- คุณไม่สามารถพยายามแก้ไขสิ่งใด ๆ ที่มีอยู่ใน JavaScript
- คำตอบไม่จำเป็นต้องกำหนด
Math.random
คุณอาจจะใช้
รูปแบบคำตอบ
#EntryName
Notes, etc.
<!-- language: lang-js -->
//function body
//probably on multiple lines
More notes, etc.
บล็อกโค้ดหลายบรรทัดแรกจะต้องมีเนื้อหาของฟังก์ชันของคุณ
ชื่อรายการมีความยาวได้ไม่เกิน 20 ตัวอักษร
รายการของคุณจะปรากฏขึ้นในตัวควบคุมที่มีชื่อเรื่องEntryName - Username [answer ID]
รวมทั้ง[DQ]
ถ้ามันถูกตัดสิทธิ์
การชนะ
เมื่อคำถามเกิดขึ้นเป็นเวลาอย่างน้อย 3 สัปดาห์และเมื่อการตอบคำถามสิ้นสุดลงฉันจะครองตำแหน่งแชมป์
ฉันจะใช้คุณสมบัติการทำงานอัตโนมัติของคอนโทรลเลอร์ ในรอบการทำงานอัตโนมัติผู้เล่นที่ไม่ได้ถูกตัดสิทธิ์ทุกคนเล่นเกมสองเกมโดยมีเกมหนึ่งเป็น P1 หนึ่งเกมเป็น P2 (รอบสองรอบ)
ฉันจะทำงานอัตโนมัติให้มากที่สุดเท่าที่จะทำได้ภายในเวลาไม่กี่ชั่วโมง สิ่งนี้จะขึ้นอยู่กับจำนวนการส่งที่มีและเวลาที่มีความเข้มข้น แต่โปรดมั่นใจได้เลยว่าฉันจะได้รับลีดเดอร์บอร์ดขั้นสุดท้ายที่แม่นยำ ผู้เล่นที่ชนะมากที่สุดคือผู้ชนะและคำตอบจะได้รับการยอมรับ
ฉันจะใช้ Firefox บนแล็ปท็อปที่มี Windows 8.1 64 บิต, RAM 4 GB และโปรเซสเซอร์ Quad-Core 1.6GHz
รางวัล
ฉันจะเขียนและโพสต์ความท้าทาย PPCG ที่อุทิศให้กับผู้ชนะโดยเฉพาะ มันจะเกี่ยวข้องกับชื่อผู้ใช้อวตารหรือสิ่งที่เกี่ยวกับพวกเขา ฉันจะตัดสินใจว่าการแข่งขันจะจบลงเมื่อใด ฉันจะเขียนให้ดีที่สุดในความสามารถของฉันและพยายามทำให้แน่ใจว่ามันจะกลายเป็นคำถามเครือข่ายที่น่าสนใจ
ตัวควบคุม
เรียกใช้ตัวอย่างนี้หรือไปที่JSFiddle นี้เพื่อใช้ตัวควบคุม มันเริ่มต้นด้วยการสุ่มเลือกผู้เล่น ฉันทดสอบอย่างถี่ถ้วนใน Firefox และ Chrome เท่านั้น
<style>html *{font-family:Consolas,Arial,sans-serif}canvas{margin:6px}button,input table,select{font-size:100%}textarea{font-family:monospace}input[type=text],textarea{padding:2px}textarea[readonly]{background-color:#eee}select{width:250pt;margin:3px 0}input[type=radio]{vertical-align:-.25em}input[type=checkbox]{vertical-align:-.15em}.c{margin:12px}.h{font-size:125%;font-weight:700}#main td{padding:12px;text-align:left}#main table{margin-left:auto;margin-right:auto}#main{text-align:center}#title{margin:12px;font-size:175%;font-weight:700;color:#333}#delay{text-align:right}#statsTable table{border-collapse:collapse}#statsTable td{border:1px solid gray;padding:3pt;font-family:monospace;text-align:center}#footnotes{margin:18px 0 0;font-size:75%}#arWrapper{border:2px solid red;background-color:#fff4f4}</style><div id=loadStatus>Loading entries...</div><div id=main><div id=title>Block Building Bot Flocks</div><div><span id=p1Title class=p1Color></span> vs. <span id=p2Title class=p2Color></span></div><canvas id=canvas>Canvas unsupported!</canvas><div><span id=p1Score class=p1Color>0</span> | <span id=moveCounter>0</span> | <span id=p2Score class=p2Color>0</span></div><div class=c><button id=runPause type=button onclick=runPause()>Run</button> <button id=moveOnce type=button onclick=moveOnce()>Move Once</button> <button type=button onclick=newGame()>New Game</button></div><div class=c><input id=delay size=4 value=20> ms delay <input id=showNumbers type=checkbox onclick=toggleNumbers()><label for=showNumbers>Show bot numbers</label> <input id=showLOS type=checkbox onclick=toggleLOS()><label for=showLOS>Show field of view</label></div><table><tr><td><div id=p1Header class="p1Color h">Player 1</div><div><select id=p1Select onchange=changeSelect(!0)></select></div><div><a id=p1Link href=javascript:;>Answer Link</a></div><td><div id=p2Header class="p2Color h">Player 2</div><div><select id=p2Select onchange=changeSelect(!1)></select></div><div><a id=p2Link href=javascript:;>Answer Link</a></div></table><div>Test Entry</div><div><textarea id=testEntry rows=8 cols=64>return [0,0,0,0,0,0,0,0]</textarea></div><div class=c><button type=button onclick=autorun()>Autorun N Rounds</button> N = <input id=N size=4 value=1> <input id=arTestEntry type=checkbox><label for=arTestEntry>Include Test Entry</label></div><div id=footnotes><input id=debug type=checkbox onclick=toggleDebug()><label for=debug>Console debug messages</label> | Scale: <input id=sc1 type=radio name=sc value=1><label for=sc1>Micro</label><input id=sc3 type=radio name=sc value=3><label for=sc3>Small</label><input id=sc6 type=radio name=sc value=6 checked><label for=sc6>Normal</label><input id=sc9 type=radio name=sc value=9><label for=sc9>Large</label> | Colors: <input id=normalCo type=radio name=co value=normal checked><label for=normalCo>Normal</label><input id=pastelCo type=radio name=co value=pastel><label for=pastelCo>Pastels</label><input id=neonCo type=radio name=co value=neon><label for=neonCo>Neon</label> <button type=button onclick=reload()>Reload</button><div id=invalidWrapper><br>No entry name/code found: <span id=invalid></span></div></div></div><div id=arWrapper><div id=arInfo class=c>Autorun in progress. Running game <span id=arProgress></span>.</div><div id=arResults><div class="c h">Autorun Results</div><div class=c>Players: <span id=arPlayers></span><br>Rounds: <span id=arRounds></span><br>Games per round: <span id=arGpR></span><br>Total games: <span id=arTotal></span><br></div><div class=c><strong>Leaderboard:</strong></div><div id=leaderboard class=c></div><div class=c>(W = wins, T = ties, L = losses, G = total goals, E = errors, I = timeouts, M = malformed actions, F = failed actions)</div><div class=c><strong>Player vs. Player Statistics:</strong></div><div id=statsTable class=c></div><div class=c>The top row has the ID's of P1.<br>The left column has the ID's of P2.<br>Every other cell not on the diagonal has the form "[P1 win count] [tie count] [P2 win count]".</div><div class=c><button type=button onclick=closeAutorun()>Close</button></div></div></div><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script>function setGlobals(e){G={},G.QID=50690,G.SITE="codegolf",G.DQ_ANSWERS=[],G.DQ_USERS=[],G.DEBUG=Q("#debug").is(":checked"),G.SHOW_NUMBERS=Q("#showNumbers").is(":checked"),G.SHOW_LOS=Q("#showLOS").is(":checked"),G.BOTS=8,G.LOS=6,G.W=128,G.H=64,G.SCALE=e?6:parseInt(Q('input[name="sc"]:checked').val()),G.CW=G.SCALE*G.W,G.CH=G.SCALE*G.H,G.TOTAL_MOVES=2e3,G.GOAL_LIFESPAN=500,G.MEM_MAX_LENGTH=256,G.TIME_LIMIT=20;var t=Q('input[name="co"]:checked').val();e||"normal"===t?G.COLORS={AIR:"#ccc",WALL:"#888",GOAL:"rgba(255,255,0,0.6)",BG:"#f7f7f7",P1:"#00f",P1_TEXT:"#008",P1_LOS:"rgba(0,0,255,0.1)",P2:"#f00",P2_TEXT:"#800",P2_LOS:"rgba(255,0,0,0.1)"}:"pastel"===t?G.COLORS={AIR:"#cef0ff",WALL:"#66cc66",GOAL:"rgba(0,0,0,0.3)",BG:"#fdfde6",P1:"#f4a034",P1_TEXT:"#a35f00",P1_LOS:"rgba(255,179,71,0.2)",P2:"#f67cf6",P2_TEXT:"#b408b4",P2_LOS:"rgba(249,128,249,0.2)"}:"neon"===t&&(G.COLORS={AIR:"#000",WALL:"#444",GOAL:"rgba(255,255,0,0.9)",BG:"#999",P1:"#0f0",P1_TEXT:"#5f5",P1_LOS:"rgba(255,128,0,0.15)",P2:"#f0f",P2_TEXT:"#f5f",P2_LOS:"rgba(0,255,255,0.15)"}),G.SCOREBOARD={P1SCORE:void 0,MOVE:void 0,P2SCORE:void 0},G.CTX=void 0,G.PLAYERS=void 0,G.GAME=void 0,G.TIMER=void 0,G.RUNNING=!1}function reload(){var e="undefined"==typeof G;e||stopTimer(),setGlobals(e);var t=Q("#canvas");t.width(G.CW).height(G.CH).prop({width:G.CW,height:G.CH}),G.CTX=t[0].getContext("2d"),G.CTX.font=(2*G.SCALE).toString()+"px Courier New",G.SCOREBOARD.P1SCORE=Q("#p1Score"),G.SCOREBOARD.MOVE=Q("#moveCounter"),G.SCOREBOARD.P2SCORE=Q("#p2Score"),Q("body").css("background-color",G.COLORS.BG),Q(".p1Color").css("color",G.COLORS.P1),Q(".p2Color").css("color",G.COLORS.P2),Q("#invalidWrapper").hide(),Q("#arWrapper").hide(),loadAnswers(G.SITE,G.QID,function(e){Q.isArray(e)?(Q("#loadStatus").remove(),loadPlayers(e),newGame()):Q("#loadStatus").text("Error loading entries - "+e)})}function maskedEval(e,t){var r={};for(i in this)r[i]=void 0;for(i in t)t.hasOwnProperty(i)&&(r[i]=t[i]);return new Function("with(this) { "+e+";}").call(r)}function toKey(e,t){return G.W*t+e}function fromKey(e){return{x:e%G.W,y:Math.floor(e/G.W)}}function outOfBounds(e,t){return 0>e||e>=G.W||0>t||t>=G.H}function rnd(e){return Math.floor(Math.random()*e)}function isInt(e){return"number"==typeof e&&e%1===0}function isString(e){return"string"==typeof e||e instanceof String}function decode(e){return Q("<textarea>").html(e).text()}function shuffle(e){for(var t,r,o=e.length;o;t=rnd(o),r=e[--o],e[o]=e[t],e[t]=r);}function makeTable(e){for(var t=Q("<table>"),r=0;r<e.length;r++){for(var o=Q("<tr>"),a=0;a<e[r].length;a++)o.append(Q("<td>").text(e[r][a]));t.append(o)}return t}function toggleDebug(){G.DEBUG=Q("#debug").is(":checked")}function toggleNumbers(){G.SHOW_NUMBERS=Q("#showNumbers").is(":checked"),drawGame(G.GAME)}function toggleLOS(){G.SHOW_LOS=Q("#showLOS").is(":checked"),drawGame(G.GAME)}function closeAutorun(){Q("#arWrapper").hide(),Q("#main").show()}function changeSelect(e){var t=Q(e?"#p1Select":"#p2Select").val(),r=Q(e?"#p1Link":"#p2Link");null===t&&0>t?r.attr("href","javascript:;"):r.attr("href",G.PLAYERS[t].link)}function stopTimer(){"undefined"!=typeof G.TIMER&&clearInterval(G.TIMER)}function moveOnce(){gameOver(G.GAME)||(moveGame(G.GAME),drawGame(G.GAME),gameOver(G.GAME)&&(stopTimer(),Q("#runPause").text("Run").prop("disabled",!0),Q("#moveOnce").prop("disabled",!0),G.DEBUG&&console.log("======== GAME OVER: "+G.GAME.p1.score+" TO "+G.GAME.p2.score+" ========"),alert(gameOverMessage(G.GAME))))}function runPause(){if(G.RUNNING)stopTimer(),Q("#runPause").text("Run"),Q("#moveOnce").prop("disabled",!1);else{var e=parseInt(Q("#delay").val());if(isNaN(e)||0>e)return void alert("Delay must be a non-negative integer.");Q("#runPause").text("Pause"),Q("#moveOnce").prop("disabled",!0),G.TIMER=setInterval(moveOnce,e)}G.RUNNING=!G.RUNNING}function newGame(){stopTimer();var e=G.PLAYERS[Q("#p1Select").val()],t=G.PLAYERS[Q("#p2Select").val()];G.RUNNING=!1,Q("#runPause").text("Run").prop("disabled",!1),Q("#moveOnce").prop("disabled",!1),Q("#p1Title").text(e.title),Q("#p2Title").text(t.title),G.GAME=createGame(e,t),drawGame(G.GAME)}function tryParse(e,t){var r=parseInt(Q(e).val());return!isNaN(r)&&r>=0?r:void alert(t+" must be a non-negative integer.")}function autorun(){function e(){for(var e=new Array(a.length),t={},r=["wins","goals","errors","timeouts","malformed","invalid"],n=0;n<e.length;n++){t.wins=t.ties=t.losses=t.goals=t.errors=t.timeouts=t.malformed=t.invalid=0;for(var l=0;l<e.length;l++)n!==l&&(t.ties+=s[n][l].ties+s[l][n].ties,t.losses+=s[n][l].p2.wins+s[l][n].p1.wins,r.forEach(function(e){t[e]+=s[n][l].p1[e]+s[l][n].p2[e]}));e[n]={wins:t.wins,text:a[n].title+" : "+t.wins+"W, "+t.ties+"T, "+t.losses+"L, "+t.goals+"G, "+t.errors+"E, "+t.timeouts+"I, "+t.malformed+"M, "+t.invalid+"F"}}e=e.sort(function(e,t){return t.wins-e.wins}).map(function(t,r){return r+1+". "+t.text+(r<e.length-1?"<br>":"")});for(var i=new Array(s.length+1),G=0;G<i.length;G++){i[G]=new Array(s.length+1);for(var c=0;c<i.length;c++){var f;i[G][c]=0===c&&0===G?"P2\\P1":0===c?a[G-1].id:0===G?a[c-1].id:(f=s[c-1][G-1])?f.p1.wins+" "+f.ties+" "+f.p2.wins:"-"}}Q("#arPlayers").text(a.length),Q("#arRounds").text(o),Q("#arGpR").text(S/o),Q("#arTotal").text(S),Q("#leaderboard").empty().append(e),Q("#statsTable").empty().append(makeTable(i)),Q("#arInfo").hide(),Q("#arResults").show()}function t(e,t){for(var r=createGame(a[e],a[t]);!gameOver(r);)moveGame(r);r.p1.score>r.p2.score?s[e][t].p1.wins++:r.p1.score<r.p2.score?s[e][t].p2.wins++:s[e][t].ties++,["p1","p2"].forEach(function(o){s[e][t][o].goals+=r[o].score,s[e][t][o].errors+=r[o].stats.errors,s[e][t][o].timeouts+=r[o].stats.timeouts,s[e][t][o].malformed+=r[o].stats.malformed,s[e][t][o].invalid+=r[o].stats.invalid.reduce(function(e,t){return e+t},0)})}function r(){if(c!==f&&(t(c,f),++p<=S&&Q("#arProgress").text(p+"/"+S)),f+1<a.length)f++;else if(f=0,c+1<a.length)c++;else{if(c=0,!(o>i+1))return void e();i++}setTimeout(r,0)}var o=parseInt(Q("#N").val());if(isNaN(o)||1>o)return void alert("N must be a positive integer.");var a=[];Q("#arTestEntry").is(":checked")&&a.push(G.PLAYERS[0]);for(var n=1;n<G.PLAYERS.length;n++)G.PLAYERS[n].dq||a.push(G.PLAYERS[n]);for(var s=new Array(a.length),n=0;n<a.length;n++){s[n]=new Array(a.length);for(var l=0;l<a.length;l++)n!==l&&(s[n][l]={ties:0,p1:{wins:0,goals:0,errors:0,timeouts:0,malformed:0,invalid:0},p2:{wins:0,goals:0,errors:0,timeouts:0,malformed:0,invalid:0}})}var i=0,c=0,f=0,p=1,S=o*a.length*(a.length-1);Q("#arProgress").text("1/"+S),Q("#main").hide(),Q("#arInfo").show(),Q("#arResults").hide(),Q("#arWrapper").show(),setTimeout(r,0)}function gameOver(e){return e.move>=G.TOTAL_MOVES}function gameOverMessage(e){function t(e,t){return"P"+(t?1:2)+": "+e.entry.title+"\nScore: "+e.score+"\nErrors: "+e.stats.errors+"\nTimeouts: "+e.stats.timeouts+"\nMalformed actions: "+e.stats.malformed+"\nFailed actions: ["+e.stats.invalid.toString().replace(/,/g,", ")+"]"}var r="GAME OVER - ";return r+=e.p1.score>e.p2.score?"PLAYER 1 WINS":e.p1.score<e.p2.score?"PLAYER 2 WINS":"TIE GAME",r+="\n\n"+t(e.p1,!0)+"\n\n"+t(e.p2,!1)}function createGame(e,t){function r(e){return{entry:e,bots:new Array(G.BOTS),mem:"",score:0,stats:{errors:0,timeouts:0,malformed:0,invalid:Array.apply(null,new Array(G.BOTS)).map(Number.prototype.valueOf,0)}}}var o={},a=Math.floor(.875*G.H)-1;o.move=0,o.walls=new Array(G.H);for(var n=0;n<G.H;n++){o.walls[n]=new Array(G.W);for(var s=0;s<G.W;s++)o.walls[n][s]=n>a}o.p1=r(e),o.p2=r(t);for(var l=0;l<G.BOTS;l++)o.p1.bots[l]={x:l,y:a,hasWall:!1},o.p2.bots[l]={x:G.W-1-l,y:a,hasWall:!1};if(-1===o.p1.entry.id||-1===o.p2.entry.id){var i=decode(Q("#testEntry").val());-1===o.p1.entry.id&&(o.p1.entry.code=i),-1===o.p2.entry.id&&(o.p2.entry.code=i)}return resetGoal(o),G.DEBUG&&console.log("======== NEW GAME: "+o.p1.entry.title+" VS "+o.p2.entry.title+" ========"),o}function moveGame(e){movePlayer(e,++e.move%2===1),++e.goal.age>=G.GOAL_LIFESPAN&&resetGoal(e)}function setupParams(e,t){function r(e,t){var r=toKey(e,t);if(!n.hasOwnProperty(r)){n[r]=!1;for(var a=0;a<G.BOTS;a++)if(Math.abs(o.bots[a].x-e)<=G.LOS&&Math.abs(o.bots[a].y-t)<=G.LOS){n[r]=!0;break}}return n[r]}var o=t?e.p1:e.p2,a=t?e.p2:e.p1,n={},s={};s.p1=t,s.id=o.entry.id,s.eid=a.entry.id,s.score=o.score,s.escore=a.score,s.move=Math.floor((e.move+1)/2),s.goal={x:e.goal.x,y:e.goal.y},s.getMem=function(){return o.mem},s.setMem=function(e){isString(e)&&e.length<=G.MEM_MAX_LENGTH&&(o.mem=e)},s.grid=function(t,o){return isInt(t)&&isInt(o)&&r(t,o)?outOfBounds(t,o)?0:e.walls[o][t]?1:0:-1},s.bots=new Array(G.BOTS),s.ebots=[];for(var l=0;l<G.BOTS;l++)s.bots[l]={x:o.bots[l].x,y:o.bots[l].y,hasWall:o.bots[l].hasWall},r(a.bots[l].x,a.bots[l].y)&&s.ebots.push({x:a.bots[l].x,y:a.bots[l].y,hasWall:a.bots[l].hasWall});return shuffle(s.ebots),-1===o.entry.id&&(s.console=console),s}function movePlayer(e,t){var r,o,a=t?e.p1:e.p2,n=t?e.p2:e.p1,s=setupParams(e,t);G.DEBUG&&(console.log("######## MOVE "+e.move+" - P"+(t?1:2)+" ########"),console.log("PARAMETERS:"),console.log(s)),o=performance.now();try{r=maskedEval(a.entry.code,s)}catch(n){return a.stats.errors++,void(G.DEBUG&&(console.log("!!!! ERRORED !!!!"),console.log(n)))}if(o=performance.now()-o,G.DEBUG&&console.log("TIME TAKEN: "+o+"ms"),o>G.TIME_LIMIT)return a.stats.timeouts++,void(G.DEBUG&&console.log("!!!! TIMED OUT !!!!"));if(G.DEBUG&&(console.log("ACTIONS:"),console.log(r)),!Array.isArray(r)||r.length!==G.BOTS)return a.stats.malformed++,void(G.DEBUG&&console.log("!!!! MALFORMED ACTIONS !!!!"));for(var l=0;l<G.BOTS;l++)if(!isInt(r[l])||r[l]<0||r[l]>24)return a.stats.malformed++,void(G.DEBUG&&console.log("!!!! MALFORMED ACTIONS !!!!"));performActions(e,a,r)}function performActions(e,t,r){function o(e){t.stats.invalid[e]++,G.DEBUG&&console.log("!! BOT"+e+" ACTION FAILED !!")}function a(e){return e.x!==i||e.y!==c}for(var n=!1,s=0;s<G.BOTS;s++){var l=r[s];if(l){var i,c;switch((l-1)%8){case 0:i=-1,c=-1;break;case 1:i=0,c=-1;break;case 2:i=1,c=-1;break;case 3:i=-1,c=0;break;case 4:i=1,c=0;break;case 5:i=-1,c=1;break;case 6:i=0,c=1;break;case 7:i=1,c=1}if(i+=t.bots[s].x,c+=t.bots[s].y,outOfBounds(i,c))o(s);else switch(Math.floor((l-1)/8)){case 0:!e.walls[c][i]&&(i>0&&c>0&&e.walls[c-1][i-1]||c>0&&e.walls[c-1][i]||i<G.W-1&&c>0&&e.walls[c-1][i+1]||i>0&&e.walls[c][i-1]||i<G.W-1&&e.walls[c][i+1]||i>0&&c<G.H-1&&e.walls[c+1][i-1]||c<G.H-1&&e.walls[c+1][i]||i<G.W-1&&c<G.H-1&&e.walls[c+1][i+1])?(t.bots[s].x=i,t.bots[s].y=c,i!==e.goal.x||c!==e.goal.y||n||(n=!0,G.DEBUG&&console.log("** BOT"+s+" REACHED GOAL **"))):o(s);break;case 1:e.walls[c][i]&&!t.bots[s].hasWall?(e.walls[c][i]=!1,t.bots[s].hasWall=!0):o(s);break;case 2:!e.walls[c][i]&&t.bots[s].hasWall&&e.p1.bots.every(a)&&e.p2.bots.every(a)?(e.walls[c][i]=!0,t.bots[s].hasWall=!1):o(s)}}}n&&(t.score++,resetGoal(e)),G.DEBUG&&(console.log("FINAL PLAYER STATE:"),console.log(t))}function resetGoal(e){for(var t={},r=[],o=0;o<G.BOTS;o++)t[toKey(e.p1.bots[o].x,e.p1.bots[o].y)]=!0,t[toKey(e.p2.bots[o].x,e.p2.bots[o].y)]=!0;for(var a=0;a<G.H;a++)for(var n=0;n<G.W;n++){var s=toKey(n,a);t.hasOwnProperty(s)||r.push(s)}var l=fromKey(r[rnd(r.length)]);e.goal={age:0,x:l.x,y:l.y}}function drawGame(e){function t(e,t){G.CTX.fillRect(e*G.SCALE,t*G.SCALE,G.SCALE,G.SCALE)}function r(e,t){G.CTX.fillRect(e*G.SCALE+1,t*G.SCALE+1,G.SCALE-2,G.SCALE-2)}G.CTX.fillStyle=G.COLORS.AIR,G.CTX.fillRect(0,0,G.CW,G.CH),G.CTX.fillStyle=G.COLORS.WALL;for(var o=0;o<G.H;o++)for(var a=0;a<G.W;a++)e.walls[o][a]&&t(a,o);if(G.SHOW_LOS){var n=(2*G.LOS+1)*G.SCALE;G.CTX.fillStyle=G.COLORS.P1_LOS;for(var s=0;s<G.BOTS;s++)G.CTX.fillRect((e.p1.bots[s].x-G.LOS)*G.SCALE,(e.p1.bots[s].y-G.LOS)*G.SCALE,n,n);G.CTX.fillStyle=G.COLORS.P2_LOS;for(var s=0;s<G.BOTS;s++)G.CTX.fillRect((e.p2.bots[s].x-G.LOS)*G.SCALE,(e.p2.bots[s].y-G.LOS)*G.SCALE,n,n)}G.CTX.fillStyle=G.COLORS.P1;for(var s=0;s<G.BOTS;s++)t(e.p1.bots[s].x,e.p1.bots[s].y);G.CTX.fillStyle=G.COLORS.P2;for(var s=0;s<G.BOTS;s++)t(e.p2.bots[s].x,e.p2.bots[s].y);G.CTX.fillStyle=G.COLORS.WALL;for(var s=0;s<G.BOTS;s++)e.p1.bots[s].hasWall&&r(e.p1.bots[s].x,e.p1.bots[s].y),e.p2.bots[s].hasWall&&r(e.p2.bots[s].x,e.p2.bots[s].y);if(G.SHOW_NUMBERS){var l=-.1,i=2.75;G.CTX.fillStyle=G.COLORS.P1_TEXT;for(var s=0;s<G.BOTS;s++)G.CTX.fillText(s.toString(),(e.p1.bots[s].x+l)*G.SCALE,(e.p1.bots[s].y+i)*G.SCALE);G.CTX.fillStyle=G.COLORS.P2_TEXT;for(var s=0;s<G.BOTS;s++)G.CTX.fillText(s.toString(),(e.p2.bots[s].x+l)*G.SCALE,(e.p2.bots[s].y+i)*G.SCALE)}G.CTX.fillStyle=G.COLORS.GOAL,t(e.goal.x+1,e.goal.y),t(e.goal.x-1,e.goal.y),t(e.goal.x,e.goal.y+1),t(e.goal.x,e.goal.y-1),G.SCOREBOARD.P1SCORE.text(e.p1.score),G.SCOREBOARD.MOVE.text(e.move),G.SCOREBOARD.P2SCORE.text(e.p2.score)}function loadPlayers(e){var t=/<pre\b[^>]*><code\b[^>]*>([\s\S]*?)<\/code><\/pre>/,r=/<h1\b[^>]*>(.*?)<\/h1>/;G.PLAYERS=[];var o={id:-1,dq:!1,code:void 0,link:"javascript:;",title:"TEST ENTRY [-1]"};G.PLAYERS.push(o);var a=[];e.forEach(function(e){var o=decode(e.owner.display_name),n=t.exec(e.body),s=r.exec(e.body);if(null===n||n.length<=1||null===s||s.length<=1)return a.push(" "),void a.push(Q("<a>").text(o).attr("href",e.link));var l={};l.id=e.answer_id,l.dq=G.DQ_ANSWERS.indexOf(e.answer_id)>-1||G.DQ_USERS.indexOf(e.owner.user_id)>-1,l.code=decode(n[1]),l.link=e.link,l.title=s[1].substring(0,20)+" - "+o+" ["+l.id.toString()+"]",l.dq&&(l.title+="[DQ]"),G.PLAYERS.push(l)}),a.length>0&&(Q("#invalid").empty().append(a),Q("#invalidWrapper").show());for(var n=new Array(G.PLAYERS.length),s=new Array(G.PLAYERS.length),l=0;l<G.PLAYERS.length;l++)n[l]=Q("<option>").text(G.PLAYERS[l].title).val(l),s[l]=Q("<option>").text(G.PLAYERS[l].title).val(l);Q("#p1Select").empty().append(n).val(rnd(G.PLAYERS.length)),changeSelect(!0),Q("#p2Select").empty().append(s).val(rnd(G.PLAYERS.length)),changeSelect(!1)}function loadAnswers(e,t,r){function o(){Q.get("https://api.stackexchange.com/2.2/questions/"+t.toString()+"/answers?page="+(s++).toString()+"&pagesize=100&order=asc&sort=creation&site="+e+"&filter=!YOKGPOBC5Yad4mOOn8Z4WcAE6q",a)}function a(e){e.hasOwnProperty("error_id")?r(e.error_id.toString()):(n=n.concat(e.items),e.hasMore?o():r(n))}var n=[],s=1;o(s,a)}Q=jQuery,Q(reload);</script>
คำถามนี้มีห้องแชทของตัวเอง ฉันจะโพสต์กระดานผู้นำที่นั่นทุกสองสามวัน