Король пагорба - Космонавт!


64

Якщо ви коли-небудь грали у Spacewar! , ви знаєте, це була весела гра. Якщо ви цього не зробили, знайте це: це була (і є) одна з перших і найважливіших комп'ютерних ігор. І це все одно весело! Клон, на якому я виріс, - це цей , мабуть, і, на жаль, тільки Windows. Так я відтворив це!

Тут розміщується KotH : PPCG - Spacewar! Король пагорба . Я закликаю вас грати як людина проти хоча б ще одного бота, щоб відчути, як працює гра.

Гра

  • Один кадр - 30 мілісекунд (таким чином, близько 33 кадрів в секунду).
  • Поле становить 800 пікселів у ширину та 600 пікселів у висоту.
  • Поле є тороїдальним, тобто космічні кораблі та ракети, які рухаються поза полем, з’являються на протилежному боці.
  • Є два космічні кораблі, червоний і синій.
    • Червоний розміщується у x = 50, а випадковий y між 50, (висота поля - 50) пікселів.
    • Синій розміщений у x = (ширина поля - 50), а випадковий y між 50, (висота поля - 50) пікселів.
    • Обидві грані x = (ширина поля) / 2.
  • Доступні елементи управління:
    • Поверніть ліворуч - 5 градусів на кадр проти годинникової стрілки.
    • Поверніть праворуч - 5 градусів на кадр за годинниковою стрілкою.
    • Вогнева ракета - рухається із додатковою швидкістю 10 пікселів на кадр, на додаток до швидкості руху корабля, у напрямку, яким судно вказувало.
    • Пожежна машина - прискорює космічний корабель на рівні 0,30 пікселів на кадр у напрямку, який показує космічний корабель.
    • Гіперпростірний стрибок - телепортується до деяких випадкових координат у полі, з 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 не матиме ефекту, якщо ракета була випущена занадто недавно.
  • У зміні від звичного вашому боту дозволяється використовувати поведінку інших ботів. Я хочу заохочувати метаграми.
    • Боти можуть не імітувати інших ботів. (Тобто, не читаючи розуму.)
    • Боти можуть не встановлювати змінних, використовуваних кодом гри та фізики. (Тобто, не обман.)

Деталі реалізації бота

Я буду зберігати ваш бот у власному файлі JavaScript, який автоматично включається, з ім'ям файлу bot_<name>.js. Тому не вводьте пробіли чи символи, які б заважали цьому чи іменували функцію в JavaScript. Це тому, що слід визначити наступні функції: <name>_setup(team)і <name>_getActions(gameInfo, botVars). Далі на сторінці є текстові області для користувача , які ви можете відредагувати, щоб перевірити свій код.

<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), потім буде розраховано середнє та стандартне відхилення цих коефіцієнтів. Вища середня матиме пріоритет, і якщо засоби знаходяться в межах однієї одиниці один одного, нижча дисперсія матиме пріоритет.
  • Підрахунок балів розпочнеться або через тиждень з сьогоднішнього дня, або через три дні без подання нових заявок. Це так, що мені не потрібно повторювати жодне спарювання ботів.

Перш за все, весело провести час!


Таблиця лідерів (08.08.2016 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

Геліос

Цей бот є центром Всесвіту, або, принаймні, він думає, що він є. Перше, що він робить - це виправити серйозну помилку і розмістити себе в центрі системи координат. Потім він обертає що-небудь навколо себе.

Йому не подобається інше (фальшиве) сонце, тому він намагається триматися подалі від нього. Він також не любить інших ботів, тому він стріляє в них, якщо він в хорошій стрілянині.

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 Я зробив кілька оновлень для бота.
Sleafar

Ваше оновлення зараз наживо!
El'endia Starman

Це дуже добре працює проти OrbitBot :)
TheNumberOne

1
@Soaku Я думаю, що головна відмінність цього бота від більшості інших полягає в тому, що цей бот націлений на свого опонента перед стрільбою.
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

В даний час немає націлювання або уникнення зіткнення . Він намагається орбіти Сонця.

Редагувати: тепер переходить у гіперпростір, коли вплив неминучий.

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

Праворучні спазми

Назва є досить описовою. Вибирається 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

Цей виклик потребував випадкового бота. Бонусні бали за гольф?

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 це є випадковим бот;)
Конор О'Брайен

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

Страшенно проти противникаDodger ... Зв'язаний з 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

ОпонентDodger

ЗАРАЗУЙТЕ ВІД МЕНІ ОПОНЕНТ !!!

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

Дякуємо користувачеві81655 за якийсь код!


Цей бот зараз живий!
El'endia Starman

2

Шпигун

Історія

Прототипом цього бота був бот, який мав два режими: божевільний режим і звичайний режим. Коли він був у божевільному режимі, він залишався там для постійної кількості кліщів. Існувала постійна ймовірність вступу в божевільний режим. Це також було значно простір, коли було близько до сонця. У божевільному режимі він націлювався на іншого бота і стріляв постійно. У звичайному режимі він відлетів від іншого бота, не стріляючи.

Я налаштував цей прототип, щоб він був у божевільному режимі тоді і тільки тоді, якщо противник буде досить близьким. Тоді у мене з’явилася божевільна ідея: що робити, якщо вона залишилася лише в божевільному режимі? Після деяких експериментів (я додав, що бот стріляв випадковим чином, коли він був у звичайному режимі), я знайшов, що новий бот бив кожного бота, крім Геліоса. Це мій код наприкінці цього процесу, але перед очищенням.

Я весь бот написав у текстовій зоні KotH або в красуні JS. (Я коротко користувався редактором Atom при очищенні - але, як, наприклад, два рядки коду)

Бот

Цей бот містить багато коду, запозиченого у інших ботів. Він перевертає код від Kamikaze, щоб тікати від іншого бота, а не бігти до іншого бота, і він бере код від EdgeCase для гіперпробігу, коли він знаходиться близько до сонця.

Це арка Немесіс - Геліос. Це незвичайний і довгі чати з мартіні.

Він тікає від іншого бота з 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;
}

Різне

Примітка. Можливо, я щось зламав при очищенні коду, тому що я не перевіряв бота після очищення коду.

Це також набагато набагато краще, ніж усі мої інші боти - він фактично перемагає будь-якого іншого бота, крім Helios (редагувати) , SetCourseFor30Degrees та OrbitBot! Це зв'язок із SunAvoider.

Бічна примітка: Я жахливий у JavaScript, не знаю чому.


@ 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% шанс повернути ліворуч; але якщо він не поверне ліворуч, він поверне праворуч. Після того, як у нього закінчиться ракет, час врешті змусить його зупинитися через сонце.

EDIT: Додано трохи логіки, щоб не стріляти, коли ворог живий, тому що його можуть вбити власні ракети.

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

Снайпер

Я трохи грав з передбаченням, щоб створити снайперського бота, який обстрілює його ворогів. Мій JavaScript занадто великий, щоб вмістити відповідь, ось ось посилання, bot_Sniper .


Нарешті обійшов тестування цього бота, і, на жаль, він справді сповільнює гру. Це досить хитро, тому вам потрібно якось швидше зробити свій код.
El'endia Starman

Наступного разу слід опублікувати його в службі на зразок [GitHub Gists] (gist.github.com), призначеної для коду.
noɥʇʎԀʎzɐɹƆ

Спробуйте оптимізувати свій код; Б'юсь об заклад, що це дійсно хороший бот, враховуючи, наскільки це довго. Ви можете спробувати ввести деякі змінні або функції.
noɥʇʎԀʎzɐɹƆ

У вас також є декілька дублікатів коду - я думаю, вам було б багато користі від розміщення вашого бота в огляді коду , під час обміну стеками.
noɥʇʎԀʎzɐɹƆ

Ви також можете визначити функції, що вводяться в Action (), у зовнішню область, тому інтерпретатору не потрібно переробляти його щоразу, коли Ви запускаєте Actions (). Також слід спробувати профайлювати код, щоб пришвидшити його.
noɥʇʎԀʎzɐɹƆ

1

SmartArrow

Як стрілка, але розумна

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

Камікадзе-

Також не розроблений для конкурентоспроможності. Задля розваги. Він замикає простори поблизу сонця і переслідує гравця, не стріляючи кулями. Приємно дивитися, як цей бот переслідує беззбройну версію Spy, але, на жаль, не можна мати більше ніж один користувальницький робот.

El'endia: коли-небудь розглядали питання про додавання декількох користувачів;)

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, то я запитую декілька ботів користувача - поле коду другого може бути прихованим розширенням за замовчуванням
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;
}

ГІПЕР

ГІПЕРСПАСІЙ ОХЛАДЕН !!!!!!!!!!!!!!!!

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}

Координатнийвплив

Виходячи з Координатів, напрочуд ефективно:

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ɐɹƆ

Якщо ви коли-небудь додасте ще одного бота, напишіть мені, щоб я знав, що ви зробили це. Ваш третій бот зараз у прямому ефірі.
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

Стрілка

Просто переслідуйте свого ворога, гіперпростору, коли йому загрожує небезпека, і простоюйте, коли його ворог мертвий.

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% часу. Я начебто хочу побачити, як KamikazePlus переслідує Шпигуна та шпигуна, як тікає, як божевільний.

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 ганяється за шпигуном. : P
El'endia Starman

@ El'endiaStarman Я вважаю, що це цікаво спостерігати, як KamikazePlus воює сам, без куль і overideHyperspace = 0;; вони просто не вистачають, коли намагаються йти один на одного.
noɥʇʎԀʎzɐɹƆ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.