King of the Hill - ยานอวกาศ!


64

หากคุณเคยเล่นSpacewar! คุณรู้ว่ามันเป็นเกมที่สนุก หากคุณยังไม่รู้ให้รู้เลยว่ามันเป็นเกมคอมพิวเตอร์เกมแรกและสำคัญที่สุดเกมหนึ่ง (และเป็น) และมันก็ยังสนุก! โคลนที่ฉันโตขึ้นมาคืออันนี้ซึ่งเห็นได้ชัดและน่าเสียดายที่ Windows เท่านั้น ดังนั้นฉันจึงสร้างมันขึ้นมาใหม่!

The KotH โฮสต์ที่นี่: PPCG - Spacewar! กษัตริย์ของเขา ฉันแนะนำให้คุณเล่นเป็นมนุษย์ต่อต้านบอทอย่างน้อยหนึ่งตัวเพื่อให้เข้าใจถึงวิธีการทำงานของเกม

เกม

  • หนึ่งเฟรมคือ 30 มิลลิวินาที (ดังนั้นประมาณ 33 เฟรมต่อวินาที)
  • ฟิลด์นี้มีความกว้าง 800 พิกเซลและสูง 600 พิกเซล
  • สนามนั้นเป็นวงแหวนซึ่งหมายความว่ายานอวกาศและขีปนาวุธที่เคลื่อนที่ออกนอกสนามปรากฏขึ้นอีกด้านหนึ่ง
  • ยานอวกาศมีสองสีคือสีแดงและสีน้ำเงิน
    • สีแดงวางตำแหน่งที่ x = 50 และสุ่ม y ระหว่าง 50, (ความสูงของฟิลด์ - 50) พิกเซล
    • สีน้ำเงินอยู่ในตำแหน่งที่ x = (ความกว้างของฟิลด์ - 50) และสุ่ม y ระหว่าง 50, (ความสูงของฟิลด์ - 50) พิกเซล
    • ทั้งสองหน้า x = (ความกว้างของฟิลด์) / 2
  • การควบคุมที่ใช้ได้คือ:
    • เลี้ยวซ้าย - 5 องศาต่อกรอบทวนเข็มนาฬิกา
    • เลี้ยวขวา - 5 องศาต่อกรอบตามเข็มนาฬิกา
    • ขีปนาวุธไฟ - เดินทางด้วยความเร็ว 10 พิกเซลต่อเฟรมนอกเหนือจากความเร็วของเรือในทิศทางที่เรือกำลังชี้
    • รถดับเพลิง - เร่งยานอวกาศที่ 0.30 พิกเซลต่อเฟรมในทิศทางที่ยานอวกาศชี้
    • Hyperspace jump - เทเลพอร์ตไปยังพิกัดสุ่มในสนามโดยมีโอกาส 25% ในการระเบิด พิกัดสุ่มเหล่านี้อาจอยู่ด้านบนของดวงอาทิตย์
  • ความเร็วสูงสุดของเรือรบคือ 15 พิกเซลต่อเฟรมภายใต้กำลังเครื่องยนต์และ 40 พิกเซลต่อเฟรมเมื่อเพิ่มแรงโน้มถ่วง
    • เมื่อเดินทางเร็วกว่า 15 พิกเซลต่อเฟรมแรงขับของเครื่องยนต์อาจเปลี่ยนทิศทางหรือช้าลงเท่านั้น
  • เกี่ยวกับขีปนาวุธ:
    • ขีปนาวุธเดินทางเป็นเส้นตรง
    • ขีปนาวุธอาจถูกยิงในอัตราสูงสุด 1 ต่อ 0.1 วินาที
    • ขีปนาวุธมีอายุการใช้งาน 2.25 วินาที
    • เรือแต่ละลำมีขีปนาวุธไม่เกิน 20 ลำ
    • ขีปนาวุธเป็นอนุภาคจุดภายใน
  • มีดวงอาทิตย์อยู่ตรงกลางซึ่งเป็นอันตรายอย่างยิ่งต่อเรือของคุณ การติดต่อเพียงเล็กน้อยนั้นเป็นอันตรายถึงชีวิต ดวงอาทิตย์นี้ยังทำลายขีปนาวุธ
  • ดวงอาทิตย์มีแรงดึงดูด การเร่งความเร็วผลลัพธ์คือ 5000 / (ระยะทาง ^ 2) พิกเซล / เฟรม ^ 2 โดยที่ระยะทางเป็นพิกเซล ยานอวกาศและขีปนาวุธได้รับผลกระทบ
  • เรือทั้งสองลำมีพื้นที่โจมตีสามส่วน: จมูก, ปีกซ้ายและปีกขวา
    • การชกที่จมูกนั้นคือความตายทันที
    • การโจมตีทั้งสองข้างจะช่วยลดอัตราการเลี้ยวของยานอวกาศและความเร่งของเครื่องยนต์ลงครึ่งหนึ่ง
    • หากปีกทั้งสองถูกทำลายยานอวกาศจะไม่สามารถหลบหลีกและสามารถยิงขีปนาวุธได้
  • เรืออาจชนกัน
    • ผลกระทบจากจมูกจมูกนั้นร้ายแรงสำหรับเรือทั้งสองลำ
    • การกระทบของปีกจมูกทำลายปีก
    • ผลกระทบจากปีกหนึ่งข้างนั้นทำลายทั้งสองปีก
  • เรือที่ตายแล้วนั้นจะแข็งและแข็งจนกระทั่งพวกมันจะระเบิด 1 วินาทีในภายหลัง
  • หลังจากเรืออย่างน้อยหนึ่งลำเสียชีวิตสนามจะถูกรีเซ็ต 3 วินาทีในภายหลัง จนกว่าจะถึงตอนนั้นดวงอาทิตย์และขีปนาวุธที่เหลือก็ยังคงเป็นอันตราย

เกมดั้งเดิมยังมีดาวเคราะห์น้อยที่อันตรายและทำลายไม่ได้ แต่ฉันจะไม่รวมสิ่งเหล่านั้น

กฎระเบียบ

  • บอตของคุณต้องเขียนด้วย JavaScript
  • บอทของคุณควร จำกัด การตัดสินใจไว้ที่ประมาณ 10 มิลลิวินาที หากฉันสังเกตเห็นความล่าช้าที่สอดคล้องกันเนื่องจากบ็อตของคุณฉันจะตัดสิทธิ์และแจ้งให้คุณทราบเพื่อให้คุณสามารถแก้ไขได้
  • บอตจะสามารถเข้าถึงสิ่งต่อไปนี้:
    • ความกว้างของฟิลด์และความสูงของฟิลด์
    • ตำแหน่งของดวงอาทิตย์และรัศมี
    • ตำแหน่งการหมุนความเร็วรูปร่างสต็อกขีปนาวุธและสถานะอินเปอร์สเปซของเรือรบทั้งสองลำ
    • ตำแหน่งและความเร็วของขีปนาวุธทั้งหมด
  • เมื่อได้รับแจ้งบอตของคุณควรส่งคืนรายการสตริง
    • สตริงเหล่านี้ควรจะเป็นหนึ่งต่อไปนี้: turn left, turn right, fire engine, ,fire missile hyperspaceสตริงอื่น ๆ จะถูกละเว้น
    • หากมีการซ้ำซ้อนจะมีการจดบันทึกครั้งแรกเท่านั้น
    • hyperspace จะมีความสำคัญมากกว่าคนอื่น ๆ ทั้งหมด
    • turn leftและturn rightในเวลาเดียวกันจะไม่มีผลกระทบ
    • fire engine จะไม่มีผลกระทบหากเรือมีเพียงจมูกหรือตาย
    • fire missile จะไม่มีผลใด ๆ หากมีการยิงขีปนาวุธเร็วเกินไป
  • ในการเปลี่ยนแปลงจากปกติบอทของคุณได้รับอนุญาตให้ใช้ประโยชน์จากพฤติกรรมของบอทอื่น ๆ ฉันต้องการส่งเสริม metagame
    • บอตไม่สามารถเลียนแบบบ็อตอื่น ๆ (เช่นไม่มีการอ่านใจ)
    • บอตไม่สามารถตั้งค่าตัวแปรใด ๆ ที่ใช้โดยเกมและรหัสฟิสิกส์ (เช่นไม่มีการโกง)

รายละเอียดการปฏิบัติ Bot

bot_<name>.jsผมจะเก็บบอทของคุณในไฟล์จาวาสคริปต์ของตัวเองที่มีอยู่โดยอัตโนมัติที่มีชื่อไฟล์ ดังนั้นอย่าใส่ช่องว่างหรือตัวอักษรใด ๆ ที่จะเข้าไปยุ่งกับสิ่งนี้หรือตั้งชื่อฟังก์ชั่นใน JavaScript นั่นเป็นเพราะคุณควรกำหนดฟังก์ชั่นดังต่อไปนี้และ<name>_setup(team) <name>_getActions(gameInfo, botVars)ยิ่งไปกว่านั้นในหน้ามี textareas สำหรับuserbot อยู่ซึ่งคุณสามารถแก้ไขเพื่อทดสอบรหัสของคุณได้

<name>_setup(team)

ฟังก์ชั่นนี้มีไว้สำหรับให้คุณกำหนดตัวแปรใด ๆ ที่คุณต้องการคงอยู่ teamจะเป็นอย่างใดอย่างหนึ่งหรือ"red" "blue"ฟังก์ชั่นนี้จะต้องส่งคืนวัตถุ กำหนดตัวแปรดังนี้:

var vars = {};
vars['example'] = "example";
return vars;

varsวัตถุนี้จะถูกส่งผ่านไปยังฟังก์ชั่นอื่น ๆ :

<name>_getActions(gameInfo, botVars)

botVars<name>_setup(team)เป็นวัตถุที่ส่งกลับโดย gameInfoเป็นวัตถุที่มีตัวแปรดังต่อไปนี้:

redScore
blueScore
timeLeft

fieldWidth
fieldHeight

sun_x
sun_y
sun_r //sun's radius

gravityStrength //acceleration in pixels/frame^2 at 1 pixel away from the sun's center
engineThrust    //acceleration in pixels/frame^2

speedLimit //maximum speed under engine power
maxSpeed   //maximum speed from gravity boosts

red_x
red_y
red_rot          //rotation in degrees
red_xv           //x velocity
red_yv           //y velocity
red_shape        //one of "full ship", "left wing", "right wing", "nose only"
red_missileStock //the number of missiles red has left
red_inHyperspace //true if red is in hyperspace
red_exploded     //until red explodes, it is still solid and hazardous
red_alive
// likewise for blue //

numMissiles
missiles //this is a list of objects, each with the following variables
  x
  y
  xv
  yv

บอทของคุณสามารถเข้าถึงสิ่งเหล่านี้ได้อย่างเต็มที่ ฉันค่อนข้างมั่นใจว่าคุณสามารถเขียนถึงพวกเขาและไม่ส่งผลกระทบต่อตัวแปรดั้งเดิม แต่ไม่ทำเช่นนั้น หมายเหตุเกี่ยวกับการหมุน:เรือรบชี้ไปที่ทิศทาง + y, ลงด้านล่างดังนั้นทุกสิ่งที่คุณต้องการจัดแนวกับยานจะต้องมีการชดเชย 90 องศา นอกจากนี้การหมุนในเชิงบวกตามเข็มนาฬิกา

ฟังก์ชั่นนี้จะต้องส่งคืนรายการสตริงที่แสดงถึงการกระทำของบอทของคุณ ตัวอย่างเช่น["turn right","thrust"]. รายละเอียดเพิ่มเติมเกี่ยวกับสิ่งนี้อยู่ในส่วนของกฎ

รายละเอียดเพิ่มเติม

คุณอาจใช้สิ่งต่อไปนี้:

LineIntersection(L1, L2)

L1 และ L2 เป็นอาร์เรย์สององค์ประกอบของอาร์เรย์สององค์ประกอบ นั่นคือและL1 := [[x1,y1],[x2,y2]] ฟังก์ชั่นนี้จะคำนวณจุดตัดของสองเส้นและผลตอบแทนนี้:L2 := [[u1,v1],[u2,v2]] คือพิกัดของจุดตัดและเป็นอัตราส่วนคู่หนึ่งที่แสดงว่าจุดตัดกันแต่ละจุดนั้นยาวเท่าไหร่ ในขณะที่จะหมายความว่าจุดตัดเป็นหนึ่งในสี่ของวิธีการจากไปและเช่นเดียวกันสำหรับ หากไม่มีจุดตัดอาร์เรย์ว่างจะถูกส่งคืน[[x,y], [a,b]][x,y][a,b]a = 0.25[x1,y1][x2,y2]b

window["shipShapes"]

var shipShapes = {
    'full ship': [[-8,16],[0,-8],[8,16]],
    'left wing': [[-8,16],[0,-8],[4,4],[0,8],[0,16]],
    'right wing':[[-4,4],[0,-8],[8,16],[0,16],[0,8]],
    'nose only': [[-4,4],[0,-8],[4,4],[0,8]]
};

นี่คือพิกัดของรูปหลายเหลี่ยมของเรือ เพื่อให้การรับพิกัดปัจจุบันง่ายขึ้นคุณอาจใช้ ...

getShipCoords(<color>)

getShipCoords("red")จะส่งคืนพิกัดปัจจุบันของจุดยอดของเรือของ Red และเช่นเดียวกันกับgetShipCoords("blue")และ Blue พิกัดเหล่านี้อยู่ในรายการดังนี้: [[x1,y1],[x2,y2],[x3,y3],...]. รูปหลายเหลี่ยมถูกปิดโดยปริยายดังนั้นจึงมีเส้นแบ่งระหว่างคู่แรกและพิกัดสุดท้าย

คุณไม่สามารถเข้าถึงหรือแก้ไขตัวแปรหรือฟังก์ชั่นอื่น ๆ ที่ใช้งานโดยเกม / เว็บไซต์ และแน่นอนไม่ได้ตั้งชื่อฟังก์ชั่นของคุณเหมือนกัน ฉันไม่คิดว่านี่จะเป็นปัญหา แต่ถ้าบอตของคุณแตกรหัสเกม ไม่มีการบันทึกหรือตรวจจับข้อยกเว้น

การชนะ

  • ทุกคู่ของบอทจะต้องเล่นอย่างน้อย 10 ครั้งทั้งสองวิธี (ดังนั้นอย่างน้อย 20 เกมทั้งหมด)
  • มุ่งหวังที่จะมีอัตราส่วนแพ้ / ชนะสูงสุดโดยรวม หากบ็อตของคุณทำได้ดีมากเทียบกับบอทตัวอื่น แต่แพ้กับอีกบอทที่สามนั่นไม่ดีเท่าการชนะต่อสองและแพ้ต่อสอง (เหมือนกฎทั่วไปของหัวแม่มือ)
  • ทุกบอทจะคำนวณอัตราส่วน (ชนะ + 1) / (ขาดทุน + 1) จากนั้นจะคำนวณค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐานของอัตราส่วนเหล่านี้ ค่าเฉลี่ยที่สูงกว่าจะมีลำดับความสำคัญและในกรณีที่ค่าเฉลี่ยอยู่ภายใน 1 หน่วยของกันและกันค่าความแปรปรวนต่ำกว่าจะมีลำดับความสำคัญ
  • การให้คะแนนจะเริ่มในหนึ่งสัปดาห์นับจากวันนี้หรือหลังจากสามวันที่ไม่มีการส่งผลงานใหม่ นี่คือดังนั้นฉันไม่ต้องทำซ้ำการจับคู่ของบอท

เหนือสิ่งอื่นใดขอให้สนุก!


ลีดเดอร์บอร์ด (2016-01-08 05:15):

#   Name                       Mean      StdDev
1.  Helios                     13.625    6.852
2.  EdgeCase                    8.335    8.155
3.  OpponentDodger              8.415    8.186
4.  OrbitBot                    5.110    6.294
5.  SunAvoider                  5.276    6.772
6.  DangitBobby                 3.320    4.423
7.  SprayAndPray                3.118    4.642
8.  Engineer                    3.903    6.315
9.  RighthandedSpasms           1.805    2.477
10. AttackAndComeBack           2.521    2.921
11. PanicAttack                 2.622    3.102
12. FullSpeedAhead              2.058    3.295
13. UhhIDKWhatToCallThisBot     2.555    3.406
14. MissilesPlusScore           0.159    0.228
15. Hyper                       0.236    0.332
16. RandUmmm                    0.988    1.329
17. Kamikaze                    0.781    1.793

หมายเหตุ:สิ่งนี้อาจเปลี่ยนแปลงได้เมื่อฉันเรียกใช้เกมมากขึ้น นอกจากนี้การเรียงลำดับ 9-13 ทำให้ฉันรำคาญใจดังนั้นฉันอาจปรับแต่งวิธีการให้คะแนนเพื่อให้ตรงกับสัญชาตญาณว่าควรจัดอันดับอย่างไร

(หมายถึงและส่วนเบี่ยงเบนมาตรฐานถูกปัดเศษเป็นทศนิยมสามหลักนอกจากนี้Hyperควรเป็นเช่นHYPERนั้น แต่จะทำให้การไฮไลต์ยุ่งเหยิง: P)


คะแนนใด ๆ .... ....
ev3commander

มันเข้าสู่ระบบจับข้อยกเว้น?
TheNumberOne

1
คุณควรระบุว่าการโทรหาเซกเมนต์LineIntersectionที่ไม่ตัดกันจะส่งคืนอาร์เรย์ว่าง
LegionMammal978

1
ฉันคิดว่าฉันทำมัน!
ev3commander

3
@ CrazyPython: ฉันจะโต้เถียงสองคนแรกพิจารณาว่าโดยทั่วไปฉันจะคัดลอกเกม แต่สิ่งที่สามคือสิ่งที่ฉันต้องการ ขอบคุณ! : D
El'endia Starman

คำตอบ:


12

Helios

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

เขาไม่ชอบดวงอาทิตย์ (ปลอม) ตัวอื่นดังนั้นเขาจึงพยายามอยู่ห่างจากดวงอาทิตย์ เขาไม่ชอบบอทคนอื่นดังนั้นเขาจึงยิงใส่พวกเขาถ้าเขาอยู่ในตำแหน่งที่ดี

function Helios_setup(team) {
    var botVars = {};
    botVars.myPrefix = team + "_";
    botVars.enemyPrefix = team == "red" ? "blue_" : "red_";
    return botVars;
}

function Helios_getActions(gameInfo, botVars) {
    var actions = [];
    var halfPi = Math.PI / 2;
    var engageAngle = Math.PI / 8;

    var field = {};
    field.width = gameInfo.fieldWidth;
    field.height = gameInfo.fieldHeight;
    field.halfWidth = field.width / 2;
    field.halfHeight = field.height / 2;
    field.posOffsetX = field.width * 3 / 2 - gameInfo[botVars.myPrefix + "x"];
    field.posOffsetY = field.height * 3 / 2 - gameInfo[botVars.myPrefix + "y"];
    field.posAngle = (450 - gameInfo[botVars.myPrefix + "rot"]) % 360 * Math.PI / 180;
    field.posSin = Math.sin(-field.posAngle);
    field.posCos = Math.cos(-field.posAngle);
    field.movOffsetXV = -gameInfo[botVars.myPrefix + "xv"];
    field.movOffsetYV = gameInfo[botVars.myPrefix + "yv"];
    field.movAngle = Math.atan2(-field.movOffsetYV, -field.movOffsetXV);
    field.movSin = Math.sin(-field.movAngle);
    field.movCos = Math.cos(-field.movAngle);

    function zeroIfUndefined(v) {
        return v === undefined ? 0 : v;
    }

    function sqr(x) {
        return x * x
    }

    function getEntity(source, prefix) {
        var tmpX = (field.posOffsetX + zeroIfUndefined(source[prefix + "x"])) % field.width - field.halfWidth;
        var tmpY = field.halfHeight - (field.posOffsetY + zeroIfUndefined(source[prefix + "y"])) % field.height;
        var tmpXV = zeroIfUndefined(source[prefix + "xv"]);
        var tmpYV = -zeroIfUndefined(source[prefix + "yv"]);
        var e = {};
        e.posX = tmpX * field.posCos - tmpY * field.posSin;
        e.posY = tmpX * field.posSin + tmpY * field.posCos;
        e.posR = Math.sqrt(sqr(e.posX) + sqr(e.posY));
        e.posPhi = Math.atan2(e.posY, e.posX);
        e.posXV = tmpXV * field.posCos - tmpYV * field.posSin;
        e.posYV = tmpXV * field.posSin + tmpYV * field.posCos;
        e.posV = Math.sqrt(sqr(e.posXV) + sqr(e.posYV));
        e.movX = tmpX * field.movCos - tmpY * field.movSin;
        e.movY = tmpX * field.movSin + tmpY * field.movCos;
        e.movR = Math.sqrt(sqr(e.movX) + sqr(e.movY));
        e.movPhi = Math.atan2(e.movY, e.movX);
        e.movXV = (tmpXV + field.movOffsetXV) * field.movCos - (tmpYV + field.movOffsetYV) * field.movSin;
        e.movYV = (tmpXV + field.movOffsetXV) * field.movSin + (tmpYV + field.movOffsetYV) * field.movCos;
        return e;
    }

    function getShip(prefix) {
        var ship = getEntity(gameInfo, prefix);
        ship.missileStock = gameInfo[prefix + "missileStock"];
        ship.inHyperspace = gameInfo[prefix + "inHyperspace"];
        ship.exploded = gameInfo[prefix + "exploded"];
        ship.alive = gameInfo[prefix + "alive"];
        return ship;
    }

    var myShip = getShip(botVars.myPrefix);
    myShip.movAngle = (field.posAngle - field.movAngle + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
    var enemyShip = getShip(botVars.enemyPrefix);
    var sun = getEntity(gameInfo, "sun_");

    enemyShip.intersectionLine = [[enemyShip.movX - enemyShip.movXV * 30, enemyShip.movY - enemyShip.movYV * 30],
            [enemyShip.movX + enemyShip.movXV * 30, enemyShip.movY + enemyShip.movYV * 30]];

    var intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle) * 10 * 30, Math.sin(myShip.movAngle) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersection = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle - 0.001) * 10 * 30, Math.sin(myShip.movAngle - 0.001) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersectionLeft = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }
    intersection = LineIntersection([[0, 0], [Math.cos(myShip.movAngle + 0.001) * 10 * 30, Math.sin(myShip.movAngle + 0.001) * 10 * 30]],
            enemyShip.intersectionLine);
    if (intersection.length == 2) {
        myShip.intersectionRight = Math.abs(intersection[1][0] / 2 + 0.5 - intersection[1][1]);
    }

    function danger() {
        var tmp1 = sqr(sun.movXV) + sqr(sun.movYV);
        var tmp2 = tmp1 == 0 ? 0 : Math.max(0, Math.min(1, ((-sun.movX) * sun.movXV + (-sun.movY) * sun.movYV) / tmp1));
        var dis = Math.sqrt(sqr(sun.movX + tmp2 * sun.movXV) + sqr(sun.movY + tmp2 * sun.movYV));
        if (dis < 30) {
            return true;
        }
        var shipLine1 = [[-16, 8], [-16, -8]];
        var shipLine2 = [[-16, 8], [8, 0]];
        var shipLine3 = [[-16, -8], [8, 0]];
        if (gameInfo.missiles !== undefined) {
            for (var i = 0; i < gameInfo.missiles.length; i++) {
                var missile = getEntity(gameInfo.missiles[i], "");
                var missileLine = [[missile.movX + missile.movXV * 0.5, missile.movY + missile.movYV * 0.5],
                        [missile.movX + missile.movXV * 3, missile.movY + missile.movYV * 3]];
                if (LineIntersection(shipLine1, missileLine).length == 2 ||
                        LineIntersection(shipLine2, missileLine).length == 2 ||
                        LineIntersection(shipLine3, missileLine).length == 2) {
                  return true;
                }
            }
        }
        return false;
    }

    function fire() {
        return enemyShip.alive && !enemyShip.inHyperspace && myShip.intersection !== undefined &&
            myShip.intersection < 0.1 + myShip.missileStock / 200;
    }

    function evadeSun() {
        if ((sun.movPhi >= 0 && myShip.movAngle < 0) || (sun.movPhi <= 0 && myShip.movAngle > 0)) {
            actions.push("fire engine");
        }
        if (sun.movPhi > 0) {
            if (Math.abs(myShip.movAngle) < halfPi) {
                actions.push("turn right");
            } else {
                actions.push("turn left");
            }
        } else {
            if (Math.abs(myShip.movAngle) < halfPi) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
    }

    function aim() {
        if (myShip.intersection !== undefined && myShip.intersectionLeft !== undefined && myShip.intersectionLeft < myShip.intersection) {
            actions.push("turn left");
        } else if (myShip.intersection !== undefined && myShip.intersectionRight !== undefined && myShip.intersectionRight < myShip.intersection) {
            actions.push("turn right");
        } else {
            if (enemyShip.posPhi > 0) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
        if (myShip.posV < 2 || (enemyShip.alive && (enemyShip.movXV >= 0 || myShip.missileStock == 0))) {
            actions.push("fire engine");
        }
    }

    function brake() {
        if (myShip.movAngle > 0) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        }
        if (Math.abs(myShip.movAngle) > Math.PI * 3 / 4) {
            actions.push("fire engine");
        }
    }

    function engage() {
        if (enemyShip.missileStock > 0) {
            if ((enemyShip.posPhi > 0 && enemyShip.posPhi < engageAngle) || enemyShip.posPhi < -engageAngle) {
                actions.push("turn right");
            } else {
                actions.push("turn left");
            }
        } else {
            if (enemyShip.posPhi > 0) {
                actions.push("turn left");
            } else {
                actions.push("turn right");
            }
        }
        actions.push("fire engine");
    }

    if (myShip.alive && !myShip.inHyperspace) {
        if (danger()) {
            actions.push("hyperspace");
        }
        if (fire()) {
            actions.push("fire missile");
        }
        if (enemyShip.exploded || enemyShip.inHyperspace || sun.movR < 150 || (sun.movR < 300 && Math.abs(sun.movPhi) < Math.PI)) {
            evadeSun();
        } else if (enemyShip.posR < 300 || myShip.intersection !== undefined) {
            aim();
        } else if (myShip.posV > 10) {
            brake();
        } else {
            engage();
        }
    }

    return actions;
}

1
ฉันคิดว่านี่เป็นหนึ่งในบอทที่ฉันโปรดปรานจนถึงตอนนี้ มันเป็นเรื่องที่ดีอย่างน่าประหลาดใจ!
El'endia Starman

@ El'endiaStarman ฉันได้อัปเดตบางอย่างเพื่อ bot
Sleafar

การอัปเดตของคุณพร้อมใช้แล้ว!
El'endia Starman

วิธีนี้ใช้งานได้ดีกับ OrbitBot :)
TheNumberOne

1
@ โซโอคุฉันคิดว่าความแตกต่างที่สำคัญระหว่างบอทนี้กับคนอื่น ๆ ส่วนใหญ่ก็คือบอทนี้มีเป้าหมายที่คู่ต่อสู้ของเขาก่อนที่จะยิง
Sleafar

9

SunAvoider

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

function SunAvoider_setup(team) {
    var botVars = {};

    botVars["color"] = team;

    return botVars;
}

function SunAvoider_getActions(gameInfo, botVars) {
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        var shipx = gameInfo[botVars["color"]+"_x"];
        var shipy = gameInfo[botVars["color"]+"_y"];
        var sunx = gameInfo["sun_x"];
        var suny = gameInfo["sun_y"];
        var dx = shipx - sunx;
        var dy = shipy - suny;
        var dis = Math.sqrt(dx*dx+dy*dy);
        var fireEngineChance = (dis-100)/(gameInfo["fieldHeight"]/2);

        if (Math.random() > fireEngineChance){ actions.push("fire engine") }

        var ang1 = gameInfo[botVars["color"]+"_rot"]+90;
        var ang2 = Math.degrees( Math.atan2(dy, dx) );
        var angDiff = ang2 - ang1;
        if (angDiff < -180) { //http://stackoverflow.com/a/7869457/1473772
            angDiff += 360;
        } else if (angDiff > 180) {
            angDiff -= 360;
        }

        if (angDiff >= 0) {
            actions.push("turn left");
        } else if (angDiff < 0) {
            actions.push("turn right");
        }
    }

    return actions;
}

9

EdgeCase

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

function EdgeCase_setup(team) {
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}

function EdgeCase_getActions(gameInfo, botVars) {
  var actions = [];

  // Get our ship's position
  var rotation, x, y, opponentAlive;
  if(botVars.color == "red") {
    rotation = gameInfo.red_rot;
    x = gameInfo.red_x;
    y = gameInfo.red_y;
    opponentAlive = gameInfo.blue_alive;
  }
  else if(botVars.color == "blue") {
    rotation = gameInfo.blue_rot;
    x = gameInfo.blue_x;
    y = gameInfo.blue_y;
    opponentAlive = gameInfo.red_alive;
  }

  // Calculate our rotation compared to the sun in degrees
  var sunX = gameInfo.sun_x,
      sunY = gameInfo.sun_y,
      angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
      rotationToSun = (rotation - angle + 360) % 360;

  // Check if we need to hyperspace to avoid the sun
  var rX = x - sunX,
      rY = y - sunY,
      distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
  if(distanceFromSun < 30) actions.push("hyperspace");
  else {

    // Turn away from the sun
    if(rotationToSun > 90 && rotationToSun < 270) {
      actions.push("turn right");
    }
    else actions.push("turn left");

    // Fire engines if we're pointing away from the sun
    if(rotationToSun > 180) {
      actions.push("fire engine");
    }

    // If we shoot while our opponent's dead we can only kill ourself
    else if(opponentAlive) actions.push("fire missile");
  }

  return actions;
}

บอทนี้ใช้งานได้แล้วตอนนี้! นอกจากนี้อันนี้ยังง่ายต่อการอยู่รอดอย่างน่าประหลาดใจ อาจจะเกี่ยวข้องกับวิธีการที่จะไม่ส่งขีปนาวุธสแปมไปทุกหนทุกแห่งเหมือนกับที่อื่น ๆ : P
El'endia Starman

7

OrbitBot

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

แก้ไข: ตอนนี้เข้าสู่ hyperspace เมื่อผลกระทบใกล้เข้ามา

function OrbitBot_setup(team) {
  var botVars = {};

  botVars.color = team;
  return botVars;
}


function OrbitBot_getActions(gameInfo, botVars) {
  var actions = [];

  function getVar(name) {
    return gameInfo[botVars.color + "_" + name];
  }

  function getEnemyVar(name) {
    var eColor;
    if (botVars.color == 'blue') {
        eColor = 'red';
    } else {
        eColor = 'blue';
    }
    return gameInfo[eColor + "_" + name];
  }

  function distance(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  }

  function toroidDistance(x1, y1, x2, y2) {
    dx = Math.abs(x1 - x2);
        while (dx > gameInfo.fieldWidth) {
        dx -= gameInfo.fieldWidth;
    }
    dx = Math.min(dx, gameInfo.fieldWidth - dx);
    dy = Math.abs(y1 - y2);
        while (dx > gameInfo.fieldHeight) {
        dx -= gameInfo.fieldHeight;
    }
    dy = Math.min(dy, gameInfo.fieldHeight - dy);
    return Math.sqrt(dx*dx+dy*dy);
  }

  function angleDistance(theta1, theta2) {
    var d = theta1 - theta2;
    while (d < 0 || d > Math.PI) {
      if (d < 0) {
        d += Math.PI * 2;
      }
      if (d > Math.PI * 2) {
        d -= Math.PI * 2;
      } else if (d > Math.PI) {
        d = Math.PI * 2 - d;
      }
    }
    return d;
  }

  function toRad(degrees) {
    return degrees / 180 * Math.PI;
  }

  function cap(x, y, limit) {
    var r = x*x+y*y;
    if (r < limit * limit) {
        r = Math.sqrt(r);
        x = x * r / limit;
      y = y * r / limit;
    }
    return [x,y];
  }

  var shape = getVar('shape');

  if (shape != 'nose only') {
    var broken = shape != 'full ship';
    var sunX = gameInfo.sun_x,
      sunY = gameInfo.sun_y,
      sunG = gameInfo.gravityStrength;

    function desirability(x, y, vx, vy) {     //Borrowed from a useless bot.
      var lowest = distance(x, y, sunX, sunY) - 5;
      var missiles = gameInfo.missiles;
      for (var i = 0; i < missiles.length; i++) {
        var mx = missiles[i].x + missiles[i].xv / 2;
        var my = missiles[i].y + missiles[i].yv / 2;
        lowest = Math.min(lowest, toroidDistance(x, y, mx, my) - distance(0, 0, missiles[i].xv, missiles[i].yv));
      }
      return lowest - 16;
    }

    var x = getVar("x"),
      y = getVar("y"),
      vx = getVar("xv"),
      vy = getVar("yv");

    function desirabilityByAcceleration(ax, ay) {//Borrowed from a useless bot.
        var x1 = x,
            y1 = y,
          vx1 = vx,
          vy1 = vy;
      var speed = distance(0,0,vx1,vy1);
      var limit = Math.max(gameInfo.speedLimit, speed);

      vx1 += ax;
      vy1 += ay;
      var temp = cap(vx1, vy1, limit);
      vx1 = temp[0];
      vy1 = temp[1];


      var dx = x1 - sunX;
      var dy = y1 - sunY;
      var dis = Math.sqrt(dx*dx+dy*dy);
      if (dis > 5){
        var force = sunG / (dis * dis);
      } else {
        var force = sunG /5;
      }
      vx1 -= force*dx/dis;
      vy1 -= force*dy/dis;

      var temp = cap(vx1, vy1, 40);
      vx1 = temp[0];
      vy1 = temp[1];

      x1 += vx1;
      y1 += vy1;

      return desirability(x1, y1, vx1, vy1);
    }

    var r = distance(sunX, sunY, x, y);
    var theta = Math.atan((y - sunY) / (x - sunX));

    var sunA = sunG/r/r,
            sunAx = -Math.cos(theta) * sunA,
        sunAy = -Math.sin(theta) * sunA;

    var dv = Math.sqrt(sunG / r);
    var dvx = -dv * Math.sin(theta);
    var dvy = dv * Math.cos(theta);
    if (distance(-dvx, -dvy, vx, vy) < distance(dvx, dvy, vx, vy)) {
      dvx = -dvx;
      dvy = -dvy;
    }

    var dax = dvx - vx;
    var day = dvy - vy;

    var dAngle = Math.atan(day / dax);
    if (dax < 0) {
        dAngle += Math.PI;
    }
    var cAngle = toRad(getVar('rot') - 90);
    var dLeft = angleDistance(cAngle - toRad(broken ? 2.5 : 5), dAngle);
    var dRight = angleDistance(cAngle + toRad(broken ? 2.5 : 5), dAngle);
    var dNeither = angleDistance(cAngle, dAngle);
    if (dLeft < dRight && dLeft < dNeither) {
      actions.push('turn left');
    } else if (dRight < dLeft && dRight < dNeither) {
      actions.push('turn right');
    }

    var cax = Math.cos(cAngle) * (broken ? .15 : .3);
    var cay = Math.sin(cAngle) * (broken ? .15 : .3);

    var ax = 0;
    var ay = 0;

    if (distance(cax, cay, dax, day) < distance(0, 0, dax, day)) {
      actions.push('fire engine');
      ax = cax;
      ay = cay;
    }

    if (desirabilityByAcceleration(ax, ay) <= 16) {
        actions.push('hyperspace');
    }

  }

  return actions;
}

บอทของคุณได้รับการเพิ่ม
Conor O'Brien

การอัปเดตของคุณพร้อมใช้แล้ว!
El'endia Starman

5

RighthandedSpasms

ชื่อนี้ค่อนข้างสื่อความหมาย เลือกturn rightโดยมีความน่าจะเป็น 0.5 โดยfire engineมีความน่าจะเป็น 0.5 และfire missileมีความน่าจะเป็น 0.8 เป็นเรื่องที่น่าแปลกใจมากเพราะมันเป็นสิ่งที่คาดเดาไม่ได้จริงๆ

function RighthandedSpasms_setup(team) {
    var botVars = {};

    botVars["color"] = team;

    return botVars;
}

function RighthandedSpasms_getActions(gameInfo, botVars) {
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        if (Math.random() > 0.5) { actions.push("turn right") }
        if (Math.random() > 0.5) { actions.push("fire engine") }
        if (Math.random() > 0.8) { actions.push("fire missile") }
    }

    return actions;
}

5

RandUmmm

ความท้าทายนี้ต้องการบอทแบบสุ่ม คะแนนโบนัสสำหรับ golfiness?

function RandUmmm_setup(t){
    function P(n,t,r,o,e,f,g){for(o=[e=1<<(f=n.length)];e;)for(t=e.toString(2),r=g=t.length,o[--e]=[];r;)~-t[--r]||o[e].push(n[r+f-g]);return o}var q=P(["fire missile","turn right","fire engine","turn left"]);q.pop();
    return {color:t,m:function(){return q[Math.random()*q.length|0]}};
}

function RandUmmm_getActions(g,b){
    return b.m();
}

เย็น! (โดยวิธีการที่ ธ ปทของฉันชนะ 13-7 ไม่. โดยมากพิจารณาฉันหายไป 9-1 ครั้ง แต่นั่นเป็นจำนวนมากของจุดรวม 20 จุดใน 90 วินาที.!)
ev3commander

@ BlockCoder1392 มันเป็นบอทแบบสุ่ม;)
Conor O'Brien

4

วิศวกร

ชอบใช้ไฮเปอร์สเปซเมื่ออยู่ในอันตราย หากต้องการดูว่าเป็นพลังที่แท้จริงให้เปิดคอนโซลและประเภทของเบราว์เซอร์ของoverideHyperspace = 0;คุณ หากคุณลืมเครื่องหมายอัฒภาคคุณจะได้รับ ASI สำหรับคริสต์มาส

function Engineer_setup(t){
    return{c:t,C:"red0blue".split(0)[+(t=="red")]};
}

function Engineer_getActions(gameInfo,botVars){
    var actions = [];

    function d(x1,y1,x2,y2){return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))}
    function hS(g){return d(g.sun_x,g.sun_y,g[botVars.c+"_x"],g[botVars.c+"_y"])<50}
    function enemyDist(g){return d(g[botVars.c+"_x"],g[botVars.c+"_y"],g[botVars.C+"_x"],g[botVars.C+"_y"]);}

    function hSm(g){
        // get closest missile
        var r = (g.missiles||[{x:10000,y:10000}]).reduce(function(p,c){return Math.min(d(c.x,c.y,g[botVars.c+"_x"],g[botVars.c+"_y"]),p)},Infinity);
        return r<18;
    }
    function dF(g){
        var a = Math.degrees(Math.atan2(g[botVars.C+"_y"]-g[botVars.c+"_y"],g[botVars.C+"_x"]-g[botVars.c+"_x"]));
        var tP = (g[botVars.c+"_rot"]+360-a)%360;
        return [a,tP];
    }
    function lOr(g){
        var tP = dF(g)[1];
        return 90<tP&&tP<270?"turn left":"turn right";
    }
    function thrust(g){
        return Math.abs(dF(g)-g[botVars.c+"_rot"]);
    }

    // are we too close to the sun or a missile?
    if(hS(gameInfo)||hSm(gameInfo))actions.push("hyperspace");

    // should we fire?
    if(enemyDist(gameInfo)<200)actions.push("fire missile");

    // direction function
    actions.push(lOr(gameInfo,botVars));

    if(Math.random()<.7)actions.push("fire engine");
    return actions;
}

3

SprayAndPray

function SprayAndPray_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}

function SprayAndPray_getActions(gameInfo, botVars) {
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push("turn left");
        if (Math.random() > 0.5) { actions.push("fire engine")};
       actions.push("fire missile");
    }

    return actions;
}

ยิงอย่างรุนแรงในทุกทิศทาง มันไม่ได้มีประสิทธิภาพมาก!


บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

3

กองบินกล้าตาย

ไม่ค่อยมีการแข่งขัน แต่ฉันคิดว่ามันคงจะสนุก! เพียงบินตรงไปยังคู่ต่อสู้ในขณะที่ยิง

function Kamikaze_setup(team) {
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}

function Kamikaze_getActions(gameInfo, botVars) {
  var actions = [];

  // Get our ship's position
  var us, them, red = {
        rotation: gameInfo.red_rot,
        x: gameInfo.red_x,
        y: gameInfo.red_y,
        alive: gameInfo.blue_alive
      },
      blue = {
        rotation: gameInfo.blue_rot,
        x: gameInfo.blue_x,
        y: gameInfo.blue_y,
        alive: gameInfo.blue_alive
      };
  if(botVars.color == "red") {
    us = red;
    them = blue;
  }
  else if(botVars.color == "blue") {
    us = blue;
    them = red;
  }

  // Turn towards our opponent's position
  var angle = Math.degrees(Math.atan2(them.y - us.y, them.x- us.x)),
      rotationToOpponent = (us.rotation - angle + 360) % 360;
  if(rotationToOpponent > 90 && rotationToOpponent < 270) {
    actions.push("turn left");
  }
  else actions.push("turn right");

  actions.push("fire missile", "fire engine");

  return actions;
}

บอทของคุณได้รับการเพิ่ม!
Conor O'Brien

แย่มากกับ OpponentDodger ... ผูกกับ PanicAttack ...
noɥʇʎԀʎzɐɹƆ

2

UhhIDKWhatToCallThisBot

เพียงแค่สิ่งที่สุ่ม

function UhhIDKWhatToCallThisBot_setup(team) {
var botVars = {};
 botVars['t'] = 0;
botVars["color"] = team;
     return botVars;

}

function UhhIDKWhatToCallThisBot_getActions(gameInfo, botVars) {
    var actions = [];
    //when i need it: "turn left",
    //Use missiles sparingly!
    var WCID = [
    "fire engine",
     "turn right",
    "fire engine",
    "fire missile",
    "turn right",
    "fire engine"]

    if (gameInfo[botVars["color"]+"_alive"]) {
        botVars['t']++;
        actions.push(WCID[botVars[t]%(WCID.length)]);
    }
     return actions;
}

เกิดอะไรขึ้นกับกอล์ฟลึกลับ?
noɥʇʎԀʎzɐɹƆ

2

OpponentDodger

ได้รับจากฉัน OPPONENT !!!

function OpponentDodger_setup(t){b={};b["c"]=t;b['o']=(t=="red")?"blue":"red";return b;}function OpponentDodger_getActions(g,b){a=[];o=b["c"];j={r:g[o+"_rot"],x:g[o+"_x"],y:g[o+"_y"]};o=b["o"];p={r:g[o+"_rot"],x:g[o+"_x"],y:g[o+"_y"]};l=Math.degrees(Math.atan2(p.y-j.y,p.x-j.x)),x=(j.r-l+360)%360;if(x > 90 && x < 270)a.push("turn right");else a.push("turn left");a.push("fire engine");return a;}  

ขอบคุณ user81655 สำหรับรหัสบางส่วน!


บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

2

สอดแนม

เรื่องราว

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

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

ฉันเขียนบอททั้งหมดของฉันใน textarea KotH หรือ JS beautifier (ฉันใช้ตัวแก้ไข Atom สั้น ๆ เมื่อทำการล้าง - แต่เหมือนกับโค้ดสองบรรทัด)

บอท

บอทนี้มีรหัสจำนวนมากที่ยืมมาจากบ็อตอื่น ๆ มันพลิกโค้ดจาก Kamikaze เพื่อวิ่งหนีจากบอทอื่นแทนที่จะวิ่งไปที่บอทอื่นและใช้โค้ดจาก EdgeCase สำหรับการไฮเปอร์สเปซเมื่อใกล้ดวงอาทิตย์

มันเป็นกรรมตามสนองประตูโค้งคือ Helios มันเป็นสิ่งที่แปลกออกไปและคุยกันยาวกับมาร์ตินี่

มันวิ่งออกไปจากบอทอื่นที่มีโอกาส 70% ในการยิงขีปนาวุธและไฮเปอร์สเปซเมื่ออยู่ใกล้ดวงอาทิตย์ ง่ายเหมือนที่ อ๋อ

แก้ไข: ฉันทดสอบบอทของฉันด้วยรหัสใหม่และมันล้มเหลวสำหรับบอทอื่น ๆ ทุกคน ฉันกำลังแก้ไขมันอยู่ ฉันเพิ่งยืนยันว่านี่เป็นเพียงบอทใหม่ของฉัน

รหัส

function Spy_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function Spy_getActions(gameInfo, botVars) {
    var actions = [];
    var us, them, red = {
            rotation: gameInfo.red_rot,
            x: gameInfo.red_x,
            y: gameInfo.red_y,
            alive: gameInfo.blue_alive
        },
        blue = {
            rotation: gameInfo.blue_rot,
            x: gameInfo.blue_x,
            y: gameInfo.blue_y,
            alive: gameInfo.blue_alive
        };
    if (botVars.color == "red") {
        us = red;
        them = blue;
    } else if (botVars.color == "blue") {
        us = blue;
        them = red;
    }

    function distance(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Get our ship's position
    var rotation, x, y, opponentAlive;
    if (botVars.color == "red") {
        rotation = gameInfo.red_rot;
        x = gameInfo.red_x;
        y = gameInfo.red_y;
        opponentAlive = gameInfo.blue_alive;
    } else if (botVars.color == "blue") {
        rotation = gameInfo.blue_rot;
        x = gameInfo.blue_x;
        y = gameInfo.blue_y;
        opponentAlive = gameInfo.red_alive;
    }

    // Calculate our rotation compared to the sun in degrees
    var sunX = gameInfo.sun_x,
        sunY = gameInfo.sun_y,
        angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
        rotationToSun = (rotation - angle + 360) % 360;

    // Check if we need to hyperspace to avoid the sun
    var rX = x - sunX,
        rY = y - sunY,
        distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
    if (distanceFromSun < 30) {
        actions.push("hyperspace");
        console.log("Command Module is Hyperspacing.")
    }
    if (gameInfo[botVars["color"] + "_alive"]) {
        var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
            rotationToOpponent = (us.rotation - angle + 360) % 360;
        if (rotationToOpponent > 90 && rotationToOpponent < 270) {
            actions.push("turn right");
        } else {
            actions.push("turn left");
        };
        actions.push("fire engine");
        if (Math.random() > 0.3) {
            actions.push("fire missile")
        }

    }
    return actions;
}

คนอื่น ๆ

หมายเหตุ: ฉันอาจทำอะไรบางอย่างผิดพลาดเมื่อล้างรหัสเพราะฉันไม่ได้ทดสอบ bot หลังจากล้างรหัส

นอกจากนี้ยังดีกว่าบอทอื่น ๆ ของฉันมาก - มันเอาชนะบอทอื่น ๆ ทั้งหมดยกเว้น Helios (แก้ไข) , SetCourseFor30Degrees และ OrbitBot! มันเชื่อมโยงกับ SunAvoider

ด้านหมายเหตุ: ฉันน่ากลัวที่จาวาสคริปต์ไม่รู้ว่าทำไม


@ El'endiaStarman กรุณาใส่วางบอทสดเมื่อหยุด; ฉันต้องแก้ไขบอทของฉัน - เวอร์ชันที่ล้างแล้วนั้นแย่กว่าเวอร์ชันที่ไม่สะอาดมาก
noɥʇʎԀʎzɐɹƆ

เอาล่ะแจ้งให้เราทราบเมื่อมีการแก้ไข
El'endia Starman

@ El'endiaStarman ฉันทำอะไรแล้วมันก็ทำงานอีกครั้ง การแก้จุดบกพร่องคุณรู้! (ยังไม่เสร็จสิ้น)
noɥʇʎԀʎzɐɹƆ

@ El'endiaStarman ... เสร็จแล้ว!
noɥʇʎԀʎzɐɹƆ

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

1

AttackAndComeBack

แทนที่จะหมุนวนมาที่ด้านบนและออกจากด้านล่าง (กลับมาที่ด้านบน) ยิงอย่างรวดเร็ว โดยทั่วไปหลีกเลี่ยงแสงแดด

function AttackAndComeBack_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}

function AttackAndComeBack_getActions(gameInfo, botVars) {
    var actions = [];
    actions.push("fire missile");
    if (Math.random()>0.4){actions.push("turn right");}
    else {actions.push("turn left");}
    actions.push("fire engine");
    return actions;
}

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

1

FullSpeedAhead

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

function FullSpeedAhead_setup(team){
    return {color: team};
}

function FullSpeedAhead_getActions(gameInfo, botVars){
    var actions = [];

    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push("fire engine");
        actions.push("fire missile");
    }
    return actions;
}

ไม่เลวเท่าที่ฉันคิด ...
noɥʇʎԀʎzɐɹƆ

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

1

อาการตื่นตระหนก

มีโอกาส 50% ในการยิงและมีโอกาส 80% ที่จะเลี้ยวซ้าย แต่ถ้ามันไม่เลี้ยวซ้ายมันจะเลี้ยวขวา หลังจากที่ขีปนาวุธหมดเวลาในที่สุดจะทำให้หยุดเนื่องจากดวงอาทิตย์

แก้ไข:เพิ่มตรรกะบางอย่างที่จะไม่ยิงเมื่อศัตรูยังมีชีวิตอยู่เพราะมันอาจถูกขีปนาวุธฆ่าตัวเอง

function PanicAttack_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    return botVars;
}

function PanicAttack_getActions(gameInfo, botVars) {
    var actions = [];
    actions.push("fire engine");
    if(botVars.color == "red") {
        var opponentAlive = gameInfo.blue_alive;
    }
    else if(botVars.color == "blue") {
        var opponentAlive = gameInfo.red_alive;
    }

    if ((Math.random()>0.5)&&opponentAlive) {
        actions.push("fire missile");
    }

    if (Math.random()>0.2) {
        actions.push("turn left");
    } else {
        actions.push("turn right");
    }

    return actions;
}

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

@ El'endiaStarman โปรดอัปเดตอีกครั้ง
noɥʇʎԀʎzɐɹƆ

การอัปเดตของคุณพร้อมใช้แล้ว!
El'endia Starman

1

DangitBobby

บ๊อบบี้ฮิลล์ไม่สนใจสิ่งที่คนอื่นคิดเกี่ยวกับเขา - เขาค่อนข้างพอใจที่จะแกว่งไปมาอย่างเกียจคร้านรอบสนามและอดทนรอให้คู่ต่อสู้ของเขาหมดแรงก่อนที่จะโดดเด่นราวกับงูเห่า "แหบแห้ง"

function DangitBobby_setup(team) {
    var botVars = {};
    botVars["color"] = team;
    if (team == 'red'){
        botVars['them'] = "blue";
    }
    else{
        botVars['them'] = 'red';
    }
    return botVars;
}

function DangitBobby_getActions(gameInfo, botVars) {
    var actions = [];
    if (gameInfo[botVars["color"]+"_alive"]) {
        actions.push('turn right');
        actions.push('fire engine');
        if (gameInfo[botVars['them']+'_missileStock'] == 0){
                actions.push('fire missile');
        }

    }
}

"นั่นเป็นของฉัน! ฉันไม่รู้จักคุณ!"


บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

1

นกปากซ่อม

ฉันได้เล่นกับการคาดเดาสำหรับการสร้างบอทซุ่มยิงที่ snipes ศัตรูของเขา จาวาสคริปต์ของฉันมีขนาดใหญ่เกินไปที่จะใส่ในคำตอบดังนั้นนี่คือการเชื่อมโยง, bot_Sniper


ในที่สุดก็มีการทดสอบบอทนี้และน่าเสียดายที่เกมนี้ช้าลงจริงๆ มันค่อนข้างจะขาด ๆ หาย ๆ ดังนั้นคุณต้องทำให้โค้ดของคุณเร็วขึ้น
El'endia Starman

ครั้งต่อไปคุณควรโพสต์ไว้ในบริการเช่น [GitHub Gists] (gist.github.com) ที่ออกแบบมาสำหรับรหัส
noɥʇʎԀʎzɐɹƆ

ลองเพิ่มประสิทธิภาพรหัสของคุณ ฉันพนันได้เลยว่ามันเป็นบอทที่ดีมากเมื่อพิจารณาว่ามันนานแค่ไหน คุณสามารถลองใช้ตัวแปรหรือฟังก์ชั่นบางอย่าง
noɥʇʎԀʎzɐɹƆ

คุณยังมีรหัสที่ซ้ำกัน - ฉันคิดว่าคุณจะมีจำนวนมากที่จะได้รับจากการโพสต์บอทของคุณเพื่อตรวจสอบโค้ดจากการแลกเปลี่ยนสแต็ก
noɥʇʎԀʎzɐɹƆ

คุณยังสามารถกำหนดฟังก์ชั่นที่คุณใส่ไว้ใน Actions () ในขอบเขตภายนอกดังนั้นล่ามไม่จำเป็นต้องแยกแยะมันซ้ำทุกครั้งที่คุณเรียกใช้ Actions () คุณควรลองสร้างรหัสเพื่อเพิ่มความเร็ว
noɥʇʎԀʎzɐɹƆ

1

SmartArrow

เหมือน Arrow แต่ฉลาด

function SmartArrow_setup(team) {
    var botVars = {};
    botVars['mpref'] = team + '_';
    botVars['epref'] = team == 'red' ? 'blue_' : 'red_';
    botVars['ecolor'] = team == 'red' ? 'blue' : 'red';
    return botVars;
}

function SmartArrow_getActions(gameInfo, botVars) {
    var actions = [];
    var x = gameInfo[botVars['mpref'] + 'x'],
        y = gameInfo[botVars['mpref'] + 'y'],
        rot = gameInfo[botVars['mpref'] + 'rot']; // SmartArrow position and rotation
    var ex = gameInfo[botVars['epref'] + 'x'],
        ey = gameInfo[botVars['epref'] + 'y']; // Enemy position
    var sunx = gameInfo.sun_x,
        suny = gameInfo.sun_y; // Sun position
    var Dsunx = Math.abs(x - sunx),
        Dsuny = Math.abs(y - suny); // Sun position delta
    var dex = Math.abs(x - ex),
        dey = Math.abs(y - ey); // Enemy position delta
    var sangle = Math.degrees(Math.atan2(suny - y, sunx - x)),
        snrot = (rot - sangle + 360) % 360;
    if (Dsunx < 40 && Dsuny < 40) // If SmartArrow is too close from sun, hyperspace !
        return ['hyperspace'];
    var missiles = gameInfo.missiles;
    for (var i = 0; i < missiles.length; i++) { // Avoid all these silly missiles
        var dx = Math.abs(x - missiles[i].x),
            dy = Math.abs(y - missiles[i].y);
        if (dx < 10 && dy < 10)
            return ['hyperspace'];
    }
    if (gameInfo[botVars['epref'] + 'alive']) { // If his enemy is alive, SmartArrow try to kill him (logic)
        var angle = Math.degrees(Math.atan2(ey - y, ex - x)),
            nrot = (rot - angle + 360) % 360;
        if (nrot > 90 && nrot < 270)
            actions.push('turn left');
        else
            actions.push('turn right');
        if (nrot > 80 && nrot < 100
         && Math.random() > 0.5) actions.push('fire missile'); // If SmartArrow is in a good spot, shot this silly oponnent
        if (Math.random() > 0.5) actions.push('fire engine');
    }
    else { // Simply (try to) act like SunAvoider if his enemy is dead
        if (snrot > 90 && snrot < 270)
            actions.push('turn right');
        else
            actions.push('turn left');
        if (Dsunx < 300 && Dsuny < 300)
            actions.push('fire engine');
        if (dex < 40 && dey < 40)
            actions.push('hyperspace'); // Dying on the corpse of his opponent is dumb.
    }
    return actions;
}

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

1

Kamikaze-

ยังไม่ได้ออกแบบมาให้แข่งขันแค่เล่น ๆ. มัน hyperspaces เมื่อใกล้กับดวงอาทิตย์และไล่ผู้เล่นโดยไม่ต้องยิงกระสุน มันสนุกที่ได้ดูบอทนี้ไล่ Spy รุ่นที่ไม่มีอาวุธ แต่คุณไม่สามารถมี userbot ได้มากกว่าหนึ่งคนโชคไม่ดี

El'endia: เคยพิจารณาเพิ่มมากกว่าหนึ่ง userbot;)

function KamikazePlus_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function KamikazePlus_getActions(gameInfo, botVars) {
    var actions = [];
    var us, them, red = {
            rotation: gameInfo.red_rot,
            x: gameInfo.red_x,
            y: gameInfo.red_y,
            alive: gameInfo.blue_alive
        },
        blue = {
            rotation: gameInfo.blue_rot,
            x: gameInfo.blue_x,
            y: gameInfo.blue_y,
            alive: gameInfo.blue_alive
        };
    if (botVars.color == "red") {
        us = red;
        them = blue;
    } else if (botVars.color == "blue") {
        us = blue;
        them = red;
    }

    function distance(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Get our ship's position
    var rotation, x, y, opponentAlive;
    if (botVars.color == "red") {
        rotation = gameInfo.red_rot;
        x = gameInfo.red_x;
        y = gameInfo.red_y;
        opponentAlive = gameInfo.blue_alive;
    } else if (botVars.color == "blue") {
        rotation = gameInfo.blue_rot;
        x = gameInfo.blue_x;
        y = gameInfo.blue_y;
        opponentAlive = gameInfo.red_alive;
    }

    // Calculate our rotation compared to the sun in degrees
    var sunX = gameInfo.sun_x,
        sunY = gameInfo.sun_y,
        angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
        rotationToSun = (rotation - angle + 360) % 360;

    // Check if we need to hyperspace to avoid the sun
    var rX = x - sunX,
        rY = y - sunY,
        distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
    if (distanceFromSun < 30) {
        actions.push("hyperspace");
        console.log("Command Module is Hyperspacing.")
    }
    if (gameInfo[botVars["color"] + "_alive"]) {
        var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
            rotationToOpponent = (us.rotation - angle + 360) % 360;
        if (rotationToOpponent > 90 && rotationToOpponent < 270) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        };
        actions.push("fire engine");
    }
    return actions;
}

เพิ่งใช้รหัส Kamikaze + และกำจัดส่วนการยิงขีปนาวุธ


ฉันอาจจะไม่เพิ่มบ็อตนี้เนื่องจากเรามีบอตกามิกาเซ่ตัวอื่นอยู่แล้วและฉันอยากจะมีบอทกามิกาเซ่สามตัวแทน นอกจากนี้อันนี้เล็กน้อยกว่าอีกสองอัน
El'endia Starman

@ El'endiaStarman ถ้าอย่างนั้นฉันขอ userbots หลายคน - ฟิลด์รหัสตัวที่สองสามารถเป็นค่าเริ่มต้นที่ซ่อนได้ซึ่งสามารถขยายได้
noɥʇʎԀʎzɐɹƆ

0

MissilesPlusScore

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

function MissilesPlusScore__setup(team) {
var botVars = {};
botVars["color"] = team;
return botVars;
}
function MissilesPlusScore_getActions(gameInfo, botVars) {
var actions = [];
var moves=["fire missile","hyperspace","turn right","turn left","fire engine","fire missile","turn right","hyperspace","turn left","fire missile","hyperspace","turn right","turn left","hyperspace","fire engine","fire missile","turn right","turn left","hyperspace","fire missile","turn right","turn left","fire engine","hyperspace","fire missile","turn right","turn left","hyperspace"];
if(gameInfo[botVars["color"]+"_alive"]){
var num=gameInfo["redScore"]-gameInfo["blueScore"];
if(num<0){num=num*-1;}
if(num===0){actions.push(moves[Math.round(Math.random()*4)]);}
else{
actions.push(moves[num+gameInfo["numMissiles"]]);
}
}
    return actions;
}

HYPER

HYPERSPACE นั้นเย็นสบาย !!!!!!!!!!!!!!!!

function HYPER_setup(team){var botVars={};botVars["color"]=team;return botVars}function HYPER_getActions(gameInfo,botVars){var actions=[];if(gameInfo[botVars["color"]+"_alive"]){actions.push(["fire engine","fire missile","hyperspace"][Math.round(Math.random()*2)])};return actions}

CoordinateInfluence

จากพิกัดที่มีประสิทธิภาพอย่างน่าประหลาดใจ:

function CoordinateInfluence_setup(team) {
var botVars = {};
botVars["color"] = team;
return botVars;
}
function CoordinateInfluence_getActions(gameInfo, botVars) {
var actions = [];
if (gameInfo[botVars["color"]+"_alive"]) {
if(gameInfo["blue_x"]>gameInfo["red_x"]){
if(gameInfo["blue_y"]<gameInfo["red_y"]){actions.push("turn right");}
else{actions.push("fire engine");}
}
else if(gameInfo["blue_y"]<gameInfo["red_y"]){
if(gameInfo["blue_x"]>gameInfo["red_x"]){actions.push("turn left");}
else{actions.push("fire missile");}
}
else{actions.push("hyperspace");}
}
return actions;
}

บอททั้งสองแบบนี้ใช้งานได้จริง
El'endia Starman

คุณควรโพสต์หลายคำตอบแทน
noɥʇʎԀʎzɐɹƆ

หากคุณเคยเพิ่มบอตอีกโปรด ping ฉันดังนั้นฉันรู้ว่าคุณทำ บอทที่สามของคุณใช้งานได้แล้ว
El'endia Starman

0

SetCourseFor30Degrees

ไม่มีความคิดว่าทำไมกัปตันจึงยืนกรานที่จะวางเรือในระยะ 30 องศา แต่เดี๋ยวก่อนในฐานะธงต่ำคุณเป็นใคร อย่างน้อยคุณก็ได้รับอนุญาตให้หลีกเลี่ยงแสงแดด! และคุณได้รับอนุญาตให้ยิงขีปนาวุธ ... ไม่อนุญาตให้เล็งพวกเขา ...

function SetCourseFor30Degrees_setup(team) 
{
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function SetCourseFor30Degrees_getActions(gameInfo, botVars)
{
var actions = [];
var ang1 = gameInfo[botVars["color"]+"_rot"]+0;
var fireChance=0.95;
// sun avoidance
   var x = gameInfo[botVars["color"]+"_x"];
   var y = gameInfo[botVars["color"]+"_y"];
   var sunX = gameInfo["sun_x"]+0;
   var sunY = gameInfo["sun_y"]+0;
  var dx = sunX- x;
   var dy = sunY - y;
var shortRangeAvoidanceDistance = (dx * dx + dy * dy ) ;

 x = gameInfo[botVars["color"]+"_x"]+gameInfo[botVars["color"]+"_xv"]*10;
 y = gameInfo[botVars["color"]+"_y"]+gameInfo[botVars["color"]+"_yv"]*10;
 dx = sunX- x;
 dy = sunY - y;

var longRangeAvoidanceDistance = (dx * dx + dy * dy ) ;


var vel = Math.sqrt(gameInfo[botVars["color"]+"_xv"]*gameInfo[botVars["color"]+"_xv"]+
gameInfo[botVars["color"]+"_yv"]*gameInfo[botVars["color"]+"_yv"]);

var close=vel*1.5;

if (shortRangeAvoidanceDistance <= close* close)
{
  actions.push("hyperspace");
}
else
{
   if (longRangeAvoidanceDistance <= 200*200)
   {

     x = x+Math.cos((ang1-5)*Math.PI/180)*vel ;
     y = y+Math.sin((ang1-5)*Math.PI/180)*vel ;
     dx = sunX- x;
     dy = sunY - y;
     if (( dx * dx + dy * dy ) > longRangeAvoidanceDistance  )
     {
       actions.push("turn right")
     }
     else
     {
        actions.push("turn left")
     }
  }
  else
  {
    var course = botVars["color"]=="red"?30:-30;
    if (ang1>course ) {actions.push("turn left")}
    if (ang1<course ) {actions.push("turn right")}
  }
  if (Math.random() > fireChance){ actions.push("fire missile") }
  actions.push("fire engine")
}
return actions;
}

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

0

ลูกศร

เพียงแค่ไล่ล่าศัตรูของเขา hyperspace เมื่อเขาตกอยู่ในอันตรายและไม่ได้ใช้งานเมื่อศัตรูของเขาตาย

function Arrow_setup(team) {
    var botVars = {};
    botVars['mpref'] = team + '_';
    botVars['epref'] = team == 'red' ? 'blue_' : 'red_';
    return botVars;
}

function Arrow_getActions(gameInfo, botVars) {
    var actions = [];
    var x = gameInfo[botVars['mpref'] + 'x'],
        y = gameInfo[botVars['mpref'] + 'y'],
        rot = gameInfo[botVars['mpref'] + 'rot']; // My position and rotation
    var ex = gameInfo[botVars['epref'] + 'x'],
        ey = gameInfo[botVars['epref'] + 'y']; // Enemy position
    var Dsunx = Math.abs(x - gameInfo.sun_x);
    var Dsuny = Math.abs(y - gameInfo.sun_y);
    if (Dsunx < 30 && Dsuny < 30) // If Arrow is too close from sun, hyperspace !
        return ['hyperspace'];
    var missiles = gameInfo.missiles;
    for (var i = 0; i < missiles.length; i++) {
        var dx = Math.abs(x - missiles[i].x);
        var dy = Math.abs(y - missiles[i].y);
        if (dx < 10 && dy < 10)
            return ['hyperspace'];
    }
    if (gameInfo[botVars['epref'] + 'alive']) {
        var angle = Math.degrees(Math.atan2(ey - y, ex - x)),
            nrot = (rot - angle + 360) % 360;
        if (nrot > 90 && nrot < 270)
            actions.push('turn left');
        else
            actions.push('turn right');
        if (Math.random() > 0.5) actions.push('fire missile');
    }
    if (Math.random() > 0.5) actions.push('fire engine');
    return actions;
}

บอทนี้ใช้งานได้แล้วตอนนี้!
El'endia Starman

@ El'endiaStarman ฉันได้อัพเดทบอท
TuxCrafting

การอัปเดตพร้อมใช้งานแล้ว! ไม่มากของหนึ่งแม้ว่า : P
El'endia Starman

0

กามิกาเซ่ +

ไม่ได้ออกแบบมาให้แข่งขัน แค่เล่น ๆ. ในทางเทคนิคแล้วมันจะตรงกันข้ามกับ Spy: ไล่ล่าผู้เล่นไฮเปอร์สเปซเมื่ออยู่ใกล้กับดวงอาทิตย์ยิงขีปนาวุธ 70% ของเวลา ฉัน sorta ต้องการเห็น KamikazePlus ไล่ Spy และ Spy วิ่งออกไปเหมือนคนบ้า

function KamikazePlus_setup(team) {
  // Typical setup. Nothing to see here. ;)
  var botVars = {};
  botVars["color"] = team;
  return botVars;
}


function KamikazePlus_getActions(gameInfo, botVars) {
    var actions = [];
    var us, them, red = {
            rotation: gameInfo.red_rot,
            x: gameInfo.red_x,
            y: gameInfo.red_y,
            alive: gameInfo.blue_alive
        },
        blue = {
            rotation: gameInfo.blue_rot,
            x: gameInfo.blue_x,
            y: gameInfo.blue_y,
            alive: gameInfo.blue_alive
        };
    if (botVars.color == "red") {
        us = red;
        them = blue;
    } else if (botVars.color == "blue") {
        us = blue;
        them = red;
    }

    function distance(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Get our ship's position
    var rotation, x, y, opponentAlive;
    if (botVars.color == "red") {
        rotation = gameInfo.red_rot;
        x = gameInfo.red_x;
        y = gameInfo.red_y;
        opponentAlive = gameInfo.blue_alive;
    } else if (botVars.color == "blue") {
        rotation = gameInfo.blue_rot;
        x = gameInfo.blue_x;
        y = gameInfo.blue_y;
        opponentAlive = gameInfo.red_alive;
    }

    // Calculate our rotation compared to the sun in degrees
    var sunX = gameInfo.sun_x,
        sunY = gameInfo.sun_y,
        angle = Math.atan2(sunY - y, sunX - x) * 180 / Math.PI,
        rotationToSun = (rotation - angle + 360) % 360;

    // Check if we need to hyperspace to avoid the sun
    var rX = x - sunX,
        rY = y - sunY,
        distanceFromSun = Math.sqrt(rX * rX + rY * rY) - gameInfo.sun_r;
    if (distanceFromSun < 30) {
        actions.push("hyperspace");
        console.log("Command Module is Hyperspacing.")
    }
    if (gameInfo[botVars["color"] + "_alive"]) {
        var angle = Math.degrees(Math.atan2(them.y - us.y, them.x - us.x)),
            rotationToOpponent = (us.rotation - angle + 360) % 360;
        if (rotationToOpponent > 90 && rotationToOpponent < 270) {
            actions.push("turn left");
        } else {
            actions.push("turn right");
        };
        actions.push("fire engine");
        if (Math.random() > 0.3) {
            actions.push("fire missile")
        }

    }
    return actions;
}

โดยทั่วไปจะใช้รหัสของ Spy และพลิก "ซ้าย" และ "ขวา"


บอทนี้ใช้งานได้แล้วตอนนี้! และใช่มันสนุกมากที่ได้ดู KamikazePlus ไล่ล่า Spy : P
El'endia Starman

@ El'endiaStarman ฉันพบว่ามันสนุกที่ได้ดู KamikazePlus ต่อสู้กับตัวเองโดยไม่มีสัญลักษณ์แสดงหัวข้อย่อยและoverideHyperspace = 0;; พวกเขาเพียง แต่คิดถึงเมื่อพวกเขาพยายามจะไปกัน
noɥʇʎԀʎzɐɹƆ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.