Vua đồi - Spacewar!


64

Nếu bạn đã từng chơi Spacewar! , bạn biết đó là một trò chơi thú vị. Nếu bạn chưa biết, hãy biết điều này: đó là (và là) một trong những trò chơi máy tính đầu tiên và quan trọng nhất. Và nó vẫn vui! Bản sao mà tôi lớn lên là cái này , rõ ràng và không may, chỉ có Windows. Vì vậy, tôi đã tạo lại nó!

KotH được lưu trữ tại đây: PPCG - Spacewar! Vua đồi . Tôi khuyến khích bạn chơi như một con người chống lại ít nhất một bot khác để cảm nhận về cách trò chơi hoạt động.

Tro choi

  • Một khung hình là 30 mili giây (do đó, khoảng 33 khung hình mỗi giây).
  • Trường rộng 800 pixel và cao 600 pixel.
  • Trường này là hình xuyến, có nghĩa là tàu vũ trụ và tên lửa di chuyển bên ngoài trường xuất hiện ở phía đối diện.
  • Có hai tàu vũ trụ, đỏ và xanh.
    • Màu đỏ được định vị ở x = 50 và y ngẫu nhiên trong khoảng 50, (chiều cao trường - 50) pixel.
    • Màu xanh được định vị ở x = (chiều rộng trường - 50) và y ngẫu nhiên trong khoảng từ 50, (chiều cao trường - 50) pixel.
    • Cả hai mặt x = (chiều rộng trường) / 2.
  • Các điều khiển có sẵn là:
    • Rẽ trái - 5 độ mỗi khung hình ngược chiều kim đồng hồ.
    • Rẽ phải - 5 độ mỗi khung theo chiều kim đồng hồ.
    • Tên lửa lửa - di chuyển với tốc độ thêm 10 pixel mỗi khung hình ngoài vận tốc của con tàu, theo hướng con tàu đang chỉ.
    • Động cơ chữa cháy - tăng tốc tàu vũ trụ ở 0,30 pixel mỗi khung hình theo hướng tàu vũ trụ đang chỉ.
    • Nhảy siêu không gian - dịch chuyển đến một số tọa độ ngẫu nhiên trong trường, với 25% cơ hội phát nổ. Các tọa độ ngẫu nhiên này có thể nằm trên đỉnh của mặt trời.
  • Tốc độ tối đa cho tàu là 15 pixel mỗi khung hình dưới công suất động cơ và 40 pixel mỗi khung hình khi được tăng trọng lực.
    • Khi di chuyển nhanh hơn 15 pixel mỗi khung hình, lực đẩy của động cơ chỉ có thể thay đổi hướng hoặc giảm tốc độ.
  • Về tên lửa:
    • Tên lửa đi theo một đường thẳng.
    • Tên lửa có thể được bắn với tốc độ tối đa 1 trên 0,1 giây.
    • Tên lửa có thời gian tồn tại 2,25 giây.
    • Tàu có tối đa 20 tên lửa mỗi tên.
    • Tên lửa là các hạt điểm bên trong.
  • Có một mặt trời ở chính trung tâm cực kỳ nguy hiểm cho tàu của bạn. Tiếp xúc nhẹ nhất là gây tử vong. Mặt trời này cũng phá hủy tên lửa.
  • Mặt trời có trọng lực. Gia tốc kết quả là 5000 / (khoảng cách ^ 2) pixel / khung ^ 2, trong đó khoảng cách tính bằng pixel. Tàu vũ trụ và tên lửa bị ảnh hưởng.
  • Cả hai tàu đều có ba vùng tấn công: mũi, cánh trái và cánh phải.
    • Một cú đánh vào mũi là chết ngay lập tức.
    • Một cú đánh vào một trong hai cánh làm giảm tốc độ quay của tàu vũ trụ và tăng tốc động cơ xuống một nửa.
    • Nếu cả hai cánh bị phá hủy, tàu vũ trụ không thể được điều động và chỉ có thể bắn tên lửa.
  • Tàu có thể va chạm với nhau.
    • Một tác động mũi-mũi gây tử vong cho cả hai tàu.
    • Một tác động cánh mũi phá hủy cánh.
    • Một tác động cánh phá hủy cả hai cánh.
  • Tàu chết là rắn và đóng băng cho đến khi chúng phát nổ 1 giây sau đó.
  • Sau khi ít nhất một tàu đã chết, trường được đặt lại 3 giây sau đó. Cho đến lúc đó, mặt trời và bất kỳ tên lửa nào còn lại vẫn nguy hiểm.

Trò chơi ban đầu cũng có các tiểu hành tinh chết người và không thể phá hủy, nhưng tôi sẽ không bao gồm những tiểu hành tinh đó.

Những quy định

  • Bot của bạn phải được viết bằng JavaScript.
  • Bot của bạn nên giới hạn quyết định của nó trong khoảng 10 mili giây. Nếu tôi nhận thấy độ trễ phù hợp vì bot của bạn , tôi sẽ loại bỏ nó và cho bạn biết để bạn có thể khắc phục nó.
  • Bots sẽ có quyền truy cập vào sau:
    • Chiều rộng trường và chiều cao trường
    • Vị trí mặt trời và bán kính
    • Vị trí, góc quay, vận tốc, hình dạng, kho tên lửa và trạng thái không gian siêu tốc của cả hai tàu
    • Vị trí và vận tốc của tất cả các tên lửa
  • Khi được nhắc, bot của bạn sẽ trả về một danh sách các chuỗi.
    • Những chuỗi nên là một trong các nội dung sau: turn left, turn right, fire engine, fire missile, hyperspace. Bất kỳ chuỗi nào khác sẽ bị bỏ qua.
    • Nếu có bất kỳ bản sao, chỉ có cái đầu tiên sẽ được ghi chú.
    • hyperspace được ưu tiên hơn tất cả những người khác.
    • turn leftturn rightđồng thời sẽ không có hiệu lực.
    • fire engine sẽ không có tác dụng nếu con tàu chỉ có mũi hoặc đã chết.
    • fire missile sẽ không có tác dụng nếu một tên lửa bị bắn quá gần đây.
  • Trong một thay đổi so với thông thường, bot của bạn được phép khai thác hành vi của các bot khác. Tôi muốn khuyến khích một metagame.
    • Bots có thể không mô phỏng các bot khác. (Tức là không đọc tâm trí.)
    • Bots có thể không đặt bất kỳ biến nào được sử dụng bởi mã trò chơi và vật lý. (Tức là không gian lận.)

Chi tiết triển khai Bot

Tôi sẽ lưu trữ bot của bạn trong tệp JavaScript của riêng nó được bao gồm tự động, với tên tệp bot_<name>.js. Vì vậy, đừng đặt bất kỳ khoảng trắng hoặc ký tự nào có thể can thiệp vào điều này hoặc đặt tên hàm trong JavaScript. Đó là bởi vì bạn nên xác định các chức năng sau: <name>_setup(team)<name>_getActions(gameInfo, botVars). Tiếp tục xuống trang, tồn tại các textareas cho userbot , bạn có thể chỉnh sửa để kiểm tra mã của mình.

<name>_setup(team)

Hàm này dành cho bạn để xác định bất kỳ biến nào bạn muốn duy trì. teamsẽ hoặc là "red"hoặc "blue". Hàm này phải trả về một đối tượng. Xác định các biến như vậy:

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

Đây varsđối tượng sẽ được thông qua vào chức năng khác:

<name>_getActions(gameInfo, botVars)

botVarslà đối tượng được trả về bởi <name>_setup(team). gameInfolà một đối tượng chứa các biến sau:

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

Bot của bạn có toàn quyền truy cập vào. Tôi khá chắc chắn rằng bạn có thể viết thư cho họ và không ảnh hưởng đến các biến ban đầu, nhưng dù sao thì đừng làm điều đó. Một lưu ý về các vòng quay: tàu chỉ theo hướng + y, hướng xuống dưới, do đó, bất cứ điều gì bạn muốn căn chỉnh với tàu cần phải được bù 90 độ. Ngoài ra, xoay tích cực là theo chiều kim đồng hồ.

Hàm này phải trả về một danh sách các chuỗi, thể hiện hành động của bot của bạn. Ví dụ , ["turn right","thrust"]. Thông tin chi tiết về điều này nằm trong phần Quy tắc .

Chi tiết bổ sung

Bạn cũng có thể sử dụng những điều sau đây:

LineIntersection(L1, L2)

L1 và L2 là mảng hai phần tử của mảng hai phần tử. Đó là, L1 := [[x1,y1],[x2,y2]]L2 := [[u1,v1],[u2,v2]]. Hàm này tính toán giao điểm của hai dòng và trả về điều này : [[x,y], [a,b]]. [x,y]là tọa độ của điểm giao nhau và [a,b]là một cặp tỷ số biểu thị khoảng cách dọc theo mỗi đường của điểm giao nhau. Như trong, a = 0.25có nghĩa là điểm giao nhau là một phần tư quãng đường từ [x1,y1]đến [x2,y2], và tương tự như vậy cho b. Nếu không có giao điểm, một mảng trống được trả về.

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]]
};

Đây là tọa độ của đa giác của tàu. Để làm cho tọa độ hiện tại dễ dàng hơn, bạn cũng có thể sử dụng ...

getShipCoords(<color>)

getShipCoords("red")sẽ trả về tọa độ hiện tại của các đỉnh của tàu Red, và tương tự cho getShipCoords("blue")và Blue. Các tọa độ này nằm trong một danh sách như vậy : [[x1,y1],[x2,y2],[x3,y3],...]. Đa giác được đóng hoàn toàn, do đó, có một đường giữa cặp tọa độ đầu tiên và cuối cùng.

Bạn không được truy cập hoặc thay đổi bất kỳ biến hoặc chức năng nào khác được sử dụng bởi trò chơi / trang web. Và chắc chắn không đặt tên cho chức năng của bạn giống nhau. Tôi không thấy trước rằng đây sẽ là một vấn đề, nhưng nếu bot của bạn phá vỡ mã trò chơi, đó là một khả năng. Không có đăng nhập hoặc bắt ngoại lệ.

Chiến thắng

  • Mỗi cặp bot sẽ được chơi ít nhất 10 lần, cả hai cách. (Vì vậy, tổng cộng ít nhất 20 trò chơi.)
  • Nhằm mục đích để có tỷ lệ thắng / thua cao nhất nói chung . Nếu bot của bạn làm rất tốt với một bot khác, nhưng thua ba người kia, điều đó không tốt bằng chiến thắng trước hai và thua hai (như một quy tắc chung).
  • Đối với mỗi bot, các tỷ lệ (thắng + 1) / (thua + 1) sẽ được tính toán, sau đó độ lệch trung bình và độ lệch chuẩn của các tỷ lệ này sẽ được tính. Một giá trị trung bình cao hơn sẽ có mức độ ưu tiên và trong trường hợp các phương tiện nằm trong 1 đơn vị của nhau, phương sai thấp hơn sẽ có mức độ ưu tiên.
  • Ghi điểm sẽ bắt đầu hoặc trong một tuần kể từ hôm nay hoặc sau ba ngày không có bài nộp mới. Điều này là do đó tôi không phải lặp lại bất kỳ cặp bot nào.

Trên hết, hãy vui vẻ!


Bảng xếp hạng (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

Lưu ý: Điều này có thể thay đổi khi tôi chạy nhiều trò chơi hơn. Thêm vào đó, thứ tự xếp hạng 9-13 làm phiền tôi, vì vậy tôi có thể điều chỉnh phương pháp tính điểm để phù hợp hơn với trực giác của một người về cách họ nên được xếp hạng.

(Phương tiện và độ lệch chuẩn được làm tròn đến ba chữ số thập phân Ngoài ra,. HyperNên HYPERnhưng điều đó messes lên nổi bật:. P)


Có điểm nào không? ....
ev3commander

Nó đăng nhập bắt ngoại lệ?
TheNumberOne

1
Bạn nên xác định rằng việc gọi LineIntersectioncác phân đoạn không giao nhau trả về một mảng trống.
LegionMammal978

1
Tôi nghĩ rằng tôi đã làm điều đó!
ev3commander

3
@CrazyPython: Tôi tranh chấp hai người đầu tiên xem xét rằng về cơ bản tôi đã sao chép một trò chơi, nhưng thứ ba là chính xác những gì tôi muốn. Cảm ơn! : D
El'endia Starman

Câu trả lời:


12

Helios

Bot này là trung tâm của vũ trụ, hoặc ít nhất là anh ta nghĩ rằng mình là. Điều đầu tiên anh ta làm là sửa một lỗi nghiêm trọng và đặt mình vào trung tâm của hệ tọa độ. Sau đó, anh ta xoay bất cứ thứ gì xung quanh mình.

Anh ấy không thích mặt trời (giả) khác, vì vậy anh ấy cố gắng tránh xa nó. Anh ta cũng không thích các bot khác, do đó anh ta bắn vào chúng, nếu anh ta ở vị trí bắn tốt.

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
Tôi nghĩ rằng đây là một trong những bot yêu thích của tôi cho đến nay. Thật đáng ngạc nhiên!
El'endia Starman

@ El'endiaStarman Tôi đã thực hiện một số cập nhật cho bot.
Sleafar

Cập nhật của bạn hiện đang hoạt động!
El'endia Starman

Điều này hoạt động rất tốt đối với OrbitBot :)
TheNumberOne

1
@Soaku Tôi nghĩ rằng sự khác biệt chính giữa bot này và hầu hết những người khác là, bot này nhắm vào đối thủ của mình trước khi bắn.
Sleafar

9

SunAvoider

Cái này chỉ cố tránh xa mặt trời. Nó hoạt động khá tốt ... cho đến khi nó bị phá hủy một hoặc cả hai cánh, thì đó thường chỉ là vấn đề thời gian trước khi nó rơi vào.

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

Bay ở tốc độ tối đa từ mặt trời về phía rìa bản đồ! Khi thấy nó hướng về phía mặt trời, nó sẽ bắt đầu bắn trong khi quay đi để quay trở lại mép. Nó cũng đi vào không gian siêu tốc khi nó sắp chạm mặt trời.

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;
}

Bot này hiện đang sống! Ngoài ra, điều này là đáng ngạc nhiên dễ dàng để tồn tại chống lại. Có lẽ phải làm thế nào với việc nó không spam tên lửa ở mọi nơi như một số tên lửa khác. : P
El'endia Starman

7

OrbitBot

Hiện tại không có mục tiêu hoặc tránh va chạm . Nó cố gắng quay quanh mặt trời.

Chỉnh sửa: Bây giờ đi vào không gian quá mức khi tác động sắp xảy ra.

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;
}

Bot của bạn đã được thêm vào
Conor O'Brien

Cập nhật của bạn hiện đang hoạt động!
El'endia Starman

5

Tay phải

Tên khá mô tả. Chọn turn rightvới xác suất 0,5, fire enginevới xác suất 0,5 và fire missilevới 0,8 xác suất. Đáng ngạc nhiên là khó khăn, chủ yếu là vì nó thực sự không thể đoán trước.

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

Thử thách này cần một bot ngẫu nhiên. Điểm thưởng cho golf?

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();
}

Mát mẻ! (Bằng cách này, bot của tôi thắng 13-7 Không. Bởi rất nhiều, xem xét tôi mất 9-1 lần, nhưng đó là một rất nhiều điểm trong tổng số 20 điểm trong 90 giây.!)
ev3commander

@ BlockCoder1392 nó một bot ngẫu nhiên;)
Conor O'Brien

4

Kỹ sư

Thích sử dụng siêu không gian khi gặp nguy hiểm. Để xem sức mạnh thực sự của nó, hãy mở bảng điều khiển và gõ trình duyệt của bạn overideHyperspace = 0;. Nếu bạn quên dấu chấm phẩy, bạn sẽ nhận được ASI cho Giáng sinh.

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

Phun và cầu nguyện

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;
}

Cháy dữ dội theo mọi hướng. Nó không hiệu quả lắm!


Bot này hiện đang sống!
El'endia Starman

3

Kamikaze

Không cạnh tranh lắm nhưng tôi nghĩ nó sẽ rất vui! Chỉ cần bay thẳng về phía đối thủ trong khi bắn.

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;
}

Bot của bạn đã được thêm vào!
Conor O'Brien

Khủng khiếp chống lại đối thủDodger ... Bị trói buộc với PanicAttack ...
noɥʇʎԀʎzɐɹƆ

2

UhhIDKWhatToCall ThisBot

Chỉ là thứ ngẫu nhiên.

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;
}

Có chuyện gì với môn golf khó hiểu?
noɥʇʎԀʎzɐɹƆ

2

Đối thủ

NHẬN NGAY TỪ TÔI HOẠT ĐỘNG !!!

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;}  

Cảm ơn user81655 cho một số mã!


Bot này hiện đang sống!
El'endia Starman

2

Gián điệp

Câu chuyện

Nguyên mẫu của bot này là một bot có hai chế độ: chế độ điên và chế độ bình thường. Khi nó ở chế độ điên, nó ở đó với số lượng bọ chét không đổi. Có một xác suất tiếp tục vào chế độ điên. Nó cũng quá mẫn khi ở gần mặt trời. Trong chế độ điên, nó nhắm vào bot khác và bắn liên tục. Ở chế độ bình thường, nó bay khỏi bot khác, không bắn.

Tôi đã điều chỉnh nguyên mẫu đó để nó ở chế độ điên nếu và chỉ khi kẻ địch đủ gần. Sau đó, tôi đã có một ý tưởng điên rồ: nếu nó chỉ ở trong chế độ điên rồ thì sao? Sau một vài thử nghiệm (tôi đã thêm vào việc làm cho bot cháy ngẫu nhiên khi nó ở chế độ bình thường) Tôi thấy tôi bot mới đánh bại mọi bot trừ Helios. Đây là mã của tôi ở cuối quá trình này, nhưng trước khi dọn dẹp.

Tôi đã viết toàn bộ bot của mình trong textarea KotH hoặc trình làm đẹp JS. (Tôi đã sử dụng ngắn gọn trình soạn thảo Atom khi dọn dẹp - nhưng giống như hai dòng mã)

Bot

Bot này chứa rất nhiều mã mượn từ các bot khác. Nó lật mã từ Kamikaze để chạy khỏi bot khác thay vì chạy sang bot khác và nó lấy mã từ EdgeCase để siêu âm khi ở gần mặt trời.

Đó là kẻ thù vòm là Helios. Nó là một trong những cuộc trò chuyện kỳ ​​lạ và dài với một martini.

Nó chạy trốn khỏi con bot khác với 70% cơ hội bắn tên lửa và siêu âm khi nó ở gần mặt trời. Đơn giản vậy thôi. Vâng.

Chỉnh sửa: Tôi đã thử nghiệm bot của mình với mã mới và nó không thành công cho mọi bot khác. Tôi đang làm việc để sửa nó. Tôi chỉ xác nhận điều này chỉ dành cho bot mới của tôi.

Mật mã

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;
}

Linh tinh

Lưu ý: Tôi có thể đã phá vỡ thứ gì đó khi dọn mã vì tôi đã không kiểm tra bot sau khi làm sạch mã.

Nó cũng tốt hơn nhiều so với tất cả các bot khác của tôi - nó thực sự đánh bại mọi bot khác ngoại trừ Helios (chỉnh sửa) , SetC thuyếtFor30Degrees và OrbitBot! Nó quan hệ với SunAvoider.

Lưu ý bên lề: Tôi ghê gớm với javascript, không biết tại sao.


@ El'endiaStarman vui lòng đặt bot sống tạm dừng; Tôi cần sửa bot của mình - phiên bản đã dọn sạch còn tệ hơn nhiều so với phiên bản ô uế.
noɥʇʎԀʎzɐɹƆ

Được rồi, cho tôi biết khi nào nó được sửa.
El'endia Starman

@ El'endiaStarman Tôi đã làm một điều và sau đó nó hoạt động trở lại. Gỡ lỗi, bạn biết đấy! (chưa được thực hiện)
noɥʇʎԀʎzɐɹƆ 18/07/2016

@ El'endiaStarman ... và thế là xong!
noɥʇʎԀʎzɐɹƆ

Bot này hiện đang sống!
El'endia Starman

1

Tấn côngAndComeBack

Thay vì xoáy, nó đến ở phía trên và thoát ra ở phía dưới (trở lại ở phía trên), bắn rất nhanh. Nói chung là tránh nắng.

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;
}

Bot này hiện đang sống!
El'endia Starman

1

FullSpeedAhead

Luôn luôn bắn cả động cơ và tên lửa mà không cần quay đầu. Đôi khi kéo dài đáng ngạc nhiên rất lâu trước khi chạm mặt trời.

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;
}

Không tệ như tôi nghĩ ...
noɥʇʎԀʎzɐɹƆ

Bot này hiện đang sống!
El'endia Starman

1

Cuộc tấn công hoảng loạn

Có 50% cơ hội bắn và 80% cơ hội rẽ trái; Nhưng nếu nó không rẽ trái, nó sẽ rẽ phải. Sau khi nó hết tên lửa, thời gian cuối cùng sẽ khiến nó dừng lại do mặt trời.

EDIT: Đã thêm một số logic để không khai hỏa khi kẻ thù còn sống vì nó có thể bị giết bởi chính tên lửa của nó.

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;
}

Bot này hiện đang sống!
El'endia Starman

@ El'endiaStarman Vui lòng cập nhật lại
noɥʇʎԀʎzɐɹƆ

Cập nhật của bạn hiện đang hoạt động!
El'endia Starman

1

DangitBulk

Bobby Hill không quan tâm đến những gì người khác nghĩ về anh ta - anh ta khá hài lòng khi lắc lư khắp sân và kiên nhẫn chờ đợi đối thủ hết hơi trước khi tấn công như một con rắn hổ mang "khàn khàn".

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');
        }

    }
}

"ĐÓ LÀ MUA CỦA TÔI! TÔI KHÔNG BIẾT BẠN!"


Bot này hiện đang sống!
El'endia Starman

1

Kẻ bắn tỉa

Tôi đã chơi với dự đoán một chút để tạo ra một bot bắn tỉa bắn tỉa kẻ thù của mình. Javascript của tôi quá lớn để phù hợp với câu trả lời vì vậy đây là một liên kết, bot_Sniper .


Cuối cùng cũng phải thử nghiệm bot này, và thật không may, nó thực sự làm chậm trò chơi. Nó khá khó hiểu, vì vậy bạn cần phải làm cho mã của mình nhanh hơn bằng cách nào đó.
El'endia Starman

Lần tới, bạn nên đăng nó trong một dịch vụ như [GitHub Gists] (gist.github.com) được thiết kế cho mã.
noɥʇʎԀʎzɐɹƆ 18/07/2016

Hãy thử tối ưu hóa mã của bạn; Tôi cá rằng đó là một bot thực sự tốt khi xem xét nó dài bao nhiêu. Bạn có thể thử inling một số biến hoặc chức năng.
noɥʇʎԀʎzɐɹƆ 18/07/2016

Bạn cũng có một số mã trùng lặp - Tôi nghĩ rằng bạn sẽ có rất nhiều để đạt được từ việc đăng bot của bạn lên đánh giá mã , trên trao đổi ngăn xếp.
noɥʇʎԀʎzɐɹƆ 18/07/2016

Bạn cũng có thể xác định các hàm bạn đặt trong Hành động () trong phạm vi bên ngoài, do đó trình thông dịch không phải lặp lại mỗi lần bạn chạy Hành động (). Bạn cũng nên thử hồ sơ mã của bạn để tăng tốc nó.
noɥʇʎԀʎzɐɹƆ

1

SmartArrow

Giống như Mũi tên, nhưng thông minh.

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;
}

Bot này hiện đang sống!
El'endia Starman

1

Kamikaze-

Cũng không được thiết kế để cạnh tranh. Chỉ để cho vui. Nó thổi phồng khi ở gần mặt trời và đuổi theo người chơi mà không bắn đạn. Thật thú vị khi xem bot này đuổi theo một phiên bản Spy không vũ trang, nhưng thật không may, bạn không thể có nhiều hơn một userbot.

El'endia: từng cân nhắc thêm nhiều hơn một 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;
}

Chỉ cần lấy mã của Kamikaze + và thoát khỏi phần bắn tên lửa.


Tôi có thể sẽ không thêm bot này vì chúng tôi đã có một bot Kamikaze khác , và tôi không muốn có ba bot kamikaze. Bên cạnh đó, cái này tầm thường hơn hai cái kia.
El'endia Starman

@ El'endiaStarman sau đó tôi đang yêu cầu nhiều người dùng - trường mã thứ hai có thể là một ẩn có thể mở rộng mặc định
noɥʇʎԀʎz

0

MissilesPlusScore

Một số ý tưởng kỳ lạ tôi đã đưa ra rằng giá trị tuyệt đối của sự khác biệt về điểm số và sử dụng một danh sách các bước di chuyển ngẫu nhiên dựa trên cách chơi. Nó hoạt động tốt chống lại bot với chiến lược nhưng thất bại trước cơn bão tên lửa. Cũng là đầu tiên của tôi .

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;
}

HY SINH

THỦY LỰC LÀ COOL !!!!!!!!!!!!!!!!

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}

Phối hợp

Dựa trên các tọa độ, hiệu quả đáng ngạc nhiên:

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;
}

Cả hai bot này đều sống.
El'endia Starman

Bạn nên đăng nhiều câu trả lời thay thế.
noɥʇʎԀʎzɐɹƆ

Nếu bạn từng thêm một bot khác, vui lòng ping tôi để tôi biết bạn đã làm. Bot thứ ba của bạn hiện đang hoạt động.
El'endia Starman

0

SetC thuyếtFor30Degrees

Không biết tại sao thuyền trưởng lại khăng khăng đặt con tàu theo hướng 30 độ, nhưng này, với tư cách là một người thấp kém, bạn sẽ hỏi ai? Ít nhất bạn đã được cho phép để tránh ánh nắng mặt trời! Và bạn được phép bắn tên lửa ... chỉ không được phép nhắm chúng ...

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;
}

Bot này hiện đang sống!
El'endia Starman

0

Mũi tên

Đơn giản là đuổi theo kẻ thù của anh ta, siêu không gian khi anh ta gặp nguy hiểm và nhàn rỗi khi kẻ thù của anh ta chết.

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;
}

Bot này hiện đang sống!
El'endia Starman

@ El'endiaStarman Tôi đã cập nhật bot
TuxCrafting

Bản cập nhật hiện đang hoạt động! Không có nhiều của một mặc dù. : P
El'endia Starman

0

Kamikaze +

Không được thiết kế để cạnh tranh. Chỉ để cho vui. Về mặt kỹ thuật, nó làm điều ngược lại với Spy: đuổi theo người chơi, siêu không gian khi ở gần mặt trời, bắn tên lửa 70% thời gian. Tôi chỉ muốn thấy KamikazePlus đuổi theo Spy và Spy chạy trốn như một kẻ điên.

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;
}

Về cơ bản chỉ cần lấy mã của Spy và lật "trái" và "phải".


Bot này hiện đang sống! Và vâng, thật vui khi xem KamikazePlus đuổi theo Spy. : P
El'endia Starman

@ El'endiaStarman Tôi thấy thật thú vị khi xem KamikazePlus tự chiến đấu mà không có đạn và overideHyperspace = 0;; họ chỉ mất tích khi họ cố gắng đi bên nhau.
noɥʇʎԀʎzɐɹƆ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.