Команда The Hill!


27

Цей виклик був натхненний відмінним викликом @HelkaHomba Red vs. Blue - Pixel Team Battlebots . Цей виклик був, мабуть, найкращим, що я бачив на цьому сайті. Колись.

Моя проблема все ще сильно відрізняється, але @HelkaHomba заслуговує на заслугу натхнення.

Огляд

Це команда, де ваша команда перемагає, маючи у вашій команді всіх живих. Іншими словами, остання команда виграє. Малюнки будуть повторно виконані.

Ви на дошці. Ви знаєте свою позицію в першому раунді (позначте 0). Ви також знаєте, хто в районі навколо вас:

Єдиний червоний квадрат у сітці 9х9, оточений білими клітинками.

У цьому випадку ви всі наодинці (або так ви думаєте) ні з ким навколо себе. Ви можете бачити навколишні елементи в першому аргументі вашому ontickоброблювачу. Більше про API пізніше.

Ваша команда

Ваша команда визначається вашим ідентифікатором користувача. Щоб дізнатися це, натисніть на зображення профілю:

Фотографія мого профілю

Потім знайдіть свій ідентифікатор користувача в адресному рядку:

Це між / користувачами / та / yourusername

Якщо це не дивно, ви в команді синіх.

Якщо це навіть, ви в червоній команді.

Запрошуємо до мальованих кіл.

Ваше (ботове) ім'я

Ім'я вашого бота починається з першої літери вашої команди ("r" або "b"). Він повинен відповідати регулярному вираженню /^(r|b)[A-Za-z_-]$/. Крім цього, ви можете вибрати ім’я вашого бота. Будь ласка, не використовуйте вже існуючий.

Починаючи

Червоні гравці почнуться біля верхньої частини карти, а сині - біля нижньої. Вам надається спеціальна інформація про перший галочку ( environmentпараметр ) параметра для ontickфункції. Я рекомендую зберігати це. Докладніше див. API.

На черзі

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

Повороту дій

Ви можете робити лише одну дію за оборот.

  • Рухатися

    Коли ви хочете переїхати, ви телефонуєте this.move(num)в API. numце клітинка, в яку ви хочете перейти:

    0 - верхній лівий, 1 - верхній, 2 - верхній правий, 3 - середній правий, 4 - середній лівий, 5 - нижній лівий, 6 - нижній, і 7 - нижній правий.

    Відносні місця розташування чисел, на які можна перемістити, зберігаються в глобальній константі threeByThree:

[
    [0, 1, 2],
    [3, undefined, 4],
    [5, 6, 7]
]

Якщо ви переходите до стіни чи іншого гравця, нічого не відбувається.

  • Обертати

    Для обертання ви дзвоните this.rotate(num). Число - це напрямок, який потрібно обертати:

    0 вгорі, 1 праворуч, 2 вниз, а 3 - ліворуч

    Обертання абсолютне.

  • Вбити

    Якщо інший гравець (від іншої команди) знаходиться у комірці, перед якою ви стикаєтесь, ви можете зателефонувати this.kill()та вбити їх. Якщо там нікого немає, або вони у вашій команді, це нічого не робить. Приклад:

    Такі ж цифри, як і вище, клітина 0 зелена, 1 синя, 2 помаранчева, а 3 - жовта

    Якщо до вас звернуться 0, ви можете вбити зеленого. Якщо вам повернуто 1, ви можете вбити синього. Якщо вам повернуть 2, ви можете вбити помаранчевий. Якщо вам повернуто 3, ви можете вбити жовтого.

  • Бомба

    Бомбардування вбиває всіх гравців, включаючи вас та товаришів по команді на 9 квадратах навколо вас. Приклад:

    У кожній комірці є сітка 9х9 з "х" с.

    Чому б вам хотілося це робити? Камікадзе . Якщо в 9-ти осередках навколо вас більше гравців, які не перебувають у вашій команді, знаходяться у вашій команді, ви можете розглянути можливість бомбардування. (Я пропоную спочатку сповістити своїх товаришів!)

  • Помістіть міну

    Це створює площу смерті для інших, хто не є у вашій команді. Розміщуючи мінну землю, ви також рухаєтесь, щоб не наступати на неї. Ви називаєте, this.landMine(num)де num - це квадрат, на який ви хочете піти. Приклад:

    Єдиний червоний квадрат у сітці 9х9, оточений білими клітинками.

    Тоді ви телефонуєте this.landMine(4):

    [Сітка 9х9, з червоним "М" посередині та червоною клітиною в середині праворуч.

    Бачите, що "М"? Це міна. Інші можуть це бачити ... поки що. Будь-хто, навіть той, хто не є у вашій команді, може побачити міну на галочці, яку вона розмістила. Але після цього галочка закінчилася, ніхто, навіть ви її не можете побачити. Але воно вибухне, як тільки ворог перейде над ним. Приклад:

    Дві сітки 9х9, синя клітинка посередині зліва в першій, червона "М" посередині першої, червона "х" посередині другої та стрілка між ними.

    Синій рушив на вашу міну, і БУМ! Ви щойно отримали ще одне вбивство.

    За кожні 2 вбивства, які ви отримуєте (від прямого вбивства або мін), ви отримуєте 1 додаткову міну. Ви також отримуєте його на старті.

  • Копати

    Коли копаєте, ви шукаєте мін у зоні 5х5, зосередженій навколо вас. Це не показує команди бота, яка розмістила міну. (Пам'ятайте, що вас не може вбити міна, розміщена кимось у вашій команді.) Наприклад, якщо це була сітка навколо вас:

    Тоді повернене значення this.dig()буде:

[undefined,undefined,undefined,true,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,
undefined,undefined,true,undefined,undefined,
true,undefined,undefined,undefined,undefined]

Індекси масиву починаються вгорі ліворуч, рухаючись праворуч, ніж вниз, не враховуючи себе:

Всього їх 23, і їх відносні місця зберігаються в глобальній константі fiveByFive:

[
    [0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9],
    [10, 11, undefined, 12, 13],
    [14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23]
]

Зауважте, що копати виявляють міни, розміщені на попередніх кліщах, на відміну від aroundMe.

Зв'язок

Коли ти хочеш з кимось поговорити, ти дзвониш this.sendMessage(recipients, team, data). Дані можуть бути все, що завгодно, і ви можете надсилати їх будь-кому, кому завгодно, навіть гравцям інших команд. Це можна використати для обману погано запрограмованих ботів, але всі гравці можуть бачити, хто надіслав повідомлення та в якій команді вони є.

Приклад:

Надішліть щось боту під назвою "redisbest":

this.sendMessage("redisbest", undefined, "Hi!");

Надішліть щось боту з назвою "redisbest" та "blueiscool":

this.sendMessage(["redisbest", "blueiscool"], undefined, {hello: "there"});

Надішліть щось всій команді червоних

this.sendMessage(undefined, "red", {hello: "red"});

Надішліть щось кожному

this.sendMessage(undefined, "*", {hello: "everyone"});

Надішліть щось усій червоній команді та боту під назвою "blueiscool":

this.sendMessage("blueiscool", "red", {hello: "bots"});

API

Ваш код повинен складатися з одного дзвінка до createBotфункції. Більш нічого. Приклад коду:

createBot({
    ontick: function(environment) {
        return new Promise((resolve, reject)=>{
            this.move(0);//example
            resolve();//please call this when you are done
        });
    },
    onmessage: function(data, from, fromBot) {
        console.log("onMessage: " + this.name + " from " + this.team + " got message ", data, " from " + from + ", on team " + fromTeam);
        this.sendMessage(["bot", "otherbot"], "team", "some data");
    },
    team: "red",//your team
    name: "rmyteamname",//team name must begin with the first letter of your team's name
    onkill: function(){
        //say goodbye
    }
});

(Ви можете скопіювати та вставити це. Просто змініть його для своєї команди тощо)

Методи

  • ontick(environment)

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

    this (коли в режимі ontick)

    • landMines Скільки мін залишилось у вас. Чим більше вбиваєш, тим більше набуваєш мін. За кожні 2 боти, яких ти вбиваєш, ти отримуєш ще 1 міна. Ви також отримуєте 1 для початку.
    • direction Напрямок, з яким ви стикаєтесь.
    • storage Зберігання, яке зберігається між дзвінками до onTickта onMessage. Порожній об’єкт на старті. Модифікуйте для будь-яких цілей, але переконайтесь, що це масив чи об’єкт завжди, щоб переконатися, що він зберігається правильно.
    • move(num) Перемістіться до вказаної позиції. Не робить нічого, якщо недійсний. Детальніше див. Вище.
    • rotate(num) Поверніть у вказане положення. Не робить нічого, якщо недійсний. Детальніше див. Вище.
    • kill() Вбиває гравця, з яким ви стикаєтесь, якщо він існує і не є у вашій команді. Детальніше див. Вище.
    • bomb() Вбиває будь-кого на 9 квадратах навколо вас, включаючи себе.
    • landMine(num) Розміщує мінну шахту, де ви знаходитесь, а потім переміщується у вказане положення. Не робить нічого, якщо недійсний numабо у вас нічого не залишилося. Детальніше див. Вище.
    • dig() новий! Повертає масив інформації про міни в зоні 5x5, зосередженій навколо вас. Детальніше див. Вище.
    • sendMessage(recipients, team, data) recipientsможе бути або одним ботом (рядком), масивом бота, або undefined/ null. Саме ви б хотіли надіслати повідомлення. teamце рядок команди, якій ви хотіли б надіслати повідомлення. Використовуйте, "*"щоб надіслати повідомлення всім. dataце все, що може бути передано функції JS. Це відправлення одержувачам. Якщо це об'єкт або масив, він передається за посиланням , тож ви та отримувач (и) можете зберегти це до своїх, storageа будь-які зміни об'єкта впливають на копії бота. Зверніть увагу , що одержувачі , які знаходяться в будь-якому списку бот, точно боти , зазначені в рядку, або боті по команді ви вказали, він отримає повідомлення.

environment

На першому галочці

  • x: Х-позиція гравця
  • y: Y-позиція гравця
  • gridWidth: Ширина сітки (у клітинках)
  • gridHeight: Висота сітки (у клітинках)

    На всіх кліщах

  • aroundMe: Набір гравців та мін. Гравці - це об’єкти, схожі {name: "bot name", team: "bot team"}, а міни - це {team: "team of bot who placed mine"}. Індекси масиву:

    0 - верхній лівий, 1 - верхній, 2 - верхній правий, 3 - середній правий, 4 - середній лівий, 5 - нижній лівий, 6 - нижній, і 7 - нижній правий.

    Зауважте, що міни, розміщені на галочці, відмінній від поточної, не відображатимуться.

    aroundMe приклад:

    Скажімо, це сітка (ви червона):

    Сітка 9х9 із світло-блакитним кольором у верхньому лівому куті, сірим "М" у верхньому правому куті, червоним посередині, жовтим у середині ліворуч та червоним "М" у нижній лівій частині.

    Ви aroundMeбудете виглядати так:

[
    {name: "bexamplebluebot", team: "blue"},
    undefined,//sparse array, nothing in index 1
    undefined,//there is technically a landmine here, but it wasn't placed this tick, so it is not shown
    undefined,//nothing in 3
    {name: "yexampleyellowbot", team: "yellow"},
    {team: "red"},//this is a landmine, you can tell is not a bot because it has no name. mines have the team name of the player they were placed by. This mine was placed this tick, otherwise you couldn't see it
    //nothing else after index 5, so the array's length is 5.
]

Тут пояснюються індекси масиву:

0 - верхній лівий, 1 - верхній, 2 - верхній правий, 3 - середній правий, 4 - середній лівий, 5 - нижній лівий, 6 - нижній, і 7 - нижній правий.

Ваш бот ефективно бачить це:

Світло-синій ящик у верхньому лівому куті з чорним номером 0 у ньому, жовте поле у ​​лівому краї з чорним номером 4 у ньому та червоне "М" внизу зліва з чорним 5 на ньому.

  • onmessage(data, fromBot, fromTeam)

    this (коли під час повідомлення)

    • sendMessage(recipients, team, data) Стандартна функція надсилання повідомлень.
    • storage Стандартне зберігання.

    dataДані, надіслані від відправника. fromPlayerПрогравач, з якого було надіслано повідомлення. fromTeamКоманді повідомлення було надіслано.

  • onkill()

    this (коли він вбиває)

    • sendMessage(recipients, team, data) Стандартна функція надсилання повідомлень.

Зручні (постійні) глобальні масиви:

threeByThree:

[
    [0, 1, 2],
    [3, undefined, 4],
    [5, 6, 7]
]

Корисно для передачі даних функції переміщення, а також для інтерпретації aroundMe. Дивись вище.

fiveByFive :

[
    [0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9],
    [10, 11, undefined, 12, 13],
    [14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23]
]

Корисно для this.dig()функції в ontickобробнику.

Спробуй!

Контролер буде запускатися з моєї машини на localhost з міркувань продуктивності, але ви можете використовувати CodePen для тестування вашого бота.

Зауважте, що ви повинні вставити код у консоль і натиснути, Enterперш ніж натиснути запустити. Ви можете вставити скільки завгодно ботів. "Тести-боти" - це приклади для тестування. Якщо ви можете їх бити чи зав'язувати, у вас є принаймні гідний бот.

Подання

Правила

Правила (застосовуються контролером)

  • Ваш основний ontickкод не повинен зайняти більше 1 секунди. Ми не хочемо, щоб раунди тривали назавжди. Якщо ваш код займає> 1 секунду, він буде зупинений.
  • Якщо ви спробуєте виконати більше 1 дії за поворот або зробите недійсну дію (наприклад, this.move(-1)або переміщення в стіну), це буде ігноровано.
  • Більше може прийти незабаром ...

Правила (застосовувані мною, можуть призвести до DQ)

  • Не пишіть глобальні змінні ( читання добре ).
  • Ваш код повинен працювати в Nodejs (у випадку, якщо контролер переноситься на Nodejs), так JSON.parse(...)це добре, але alert()це не так.
  • Вам заборонено дзвонити createBotчи перешкоджати контролеру жодним чином .
  • Не використовуйте чужий код без дозволу та значних змін. Немає копіботів.
  • Будь ласка, без лазівки!
  • Більше може прийти незабаром ...

Мої боти

Ось кілька ботів:

Цей бот випадковим чином вибирає дію. Ну, це зважений випадковий, але все ще досить випадковий. Якщо ви зможете вбити цього бота (він врешті-решт уб'є себе, це не рахується), тоді у вас є принаймні гідний бот. Опублікуйте його і подивіться, що станеться!

Мої боти мають назву, що починається з "x", і команда "none". Ви можете скористатись цим кодом, але будь ласка, внесіть хоч якусь модифікацію. Якщо ви не зможете принаймні підробити номер, ви не виграєте.

Форматування подання

Будь ласка, використовуйте цей формат:

# rmyamazingbot

    createBot({
        ontick: function(environment) {
            return new Promise((resolve, reject)=>{
                this.move(0);//example
                resolve();//please call this when you are done
            });
        },
        onmessage: function(data, fromTeam, fromBot) {
            console.log("onMessage: " + this.name + " from " + this.team + " got message ", data, " from " + from + ", on team " + fromTeam);
            this.sendMessage(["bot", "otherbot"], "team", "some data");
        },
        team: "red",//your team
        name: "rmyteamname",//team name must begin with the first letter of your team's name
        onkill: function(){
            //say goodbye
        }
    });

Long, but cool explanation...

Запити, помилки, питання тощо?

Прокоментуйте нижче! Перевірте, чи вже є коментар до цього. Якщо такий вже є, підтвердіть його.

Хочете поговорити зі своєю командою?

Використовуйте кімнати чату для червоного та синього .

Мова

В даний час підтримується лише JS і щось, що компілюється в JS, але якщо ви знаєте спосіб отримати інші мови для роботи з Nodejs, я би радий перенести контролер до Nodejs.

Підсумкові ноти

Ідеї ​​стратегії

Допоможіть своїй команді! Створення бота, який призначений допомогти іншому боту та працювати разом. Ця стратегія добре працювала для Red vs. Blue - Pixel Team Battlebots

Шукаючі респ

Я прийму найвищу відповідь на команду-переможницю. Майте на увазі, що попередні відповіді, як правило, отримують більше голосів, але їх слабкі місця, швидше за все, будуть виявлені та використані.

Крім того, якщо ви скоро отримаєте відповідь, ви можете отримати +100 банатів.


1
Коментарі не для розширеного обговорення; ця розмова перенесена в чат .
Денніс

Чи можу я зробити кілька ботів? (Вибачте, я знаю, що розмова була перенесена, я просто балакав, так, так)
Меттью Ро

@SIGSEGV так, але хтось інший повинен опублікувати його. Ви можете опублікувати одного бота та надати код іншого комусь із вашої команди, але ви не можете двічі опублікувати.
програміст5000

Щодо позиціонування, де знаходиться [0, 0] -вкладена комірка, це клітина вліво вліво? Також, чи сповіщення споживає ваші дії (за поворот)? Спасибі.
Фракс

@Thrax так, і ні. Ви навіть можете повідомляти у відповідь на повідомлення.
програміст5000

Відповіді:


7

xscared (неконкурентоспроможний)

createBot({
    ontick: function(environment) {
        var reverse = [0, 1, 2, 3, 4, 5, 6, 7].reverse();
        return new Promise((resolve, reject)=>{
            (this.aroundMe || []).forEach((item,idx)=>{
                this.move(reverse[idx]);
                return resolve();
            });
            this.move(~~(Math.random() * 8));
            return resolve();
        });
    },
    onmessage: function() {
    },
    team: "none",
    name: "xscared",
    onkill: function(){
    }
});

Дуже злякався людей. Відходить від першої людини (або міни), яку вона бачить. В іншому випадку воно рухається випадковим чином. Зауважте, що це не конкуренція, а лише приклад. Спробуйте його перемогти!


6

резервний, синій бот

Як я попереджував у чаті, я ніколи в житті нічого не писав на JavaScript, тому якщо ви знайшли помилку, будь ласка, скажіть мені! (Завдяки @ programmer5000 за те, що він мені вже допомагав)
. Концепція цього бота полягає в тому, що він спілкується з іншими ботами з тієї ж команди та надсилає їм своє місце разом із картою знайдених мін. Він намагається приєднатись до найближчого блакитного бота (якщо один надсилає свої позиційні дані [дані як [x, y] масив]) і залишається біля нього (максимально спиною до нього), вбиваючи наближаються червоних ботів або дивлячись вперед для мін.

createBot({
    team: 'blue',
    name: 'backup',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            //if (typeof this.x != "undefined") this.storage['position'] = [this.x, this.y];
            if (typeof environment.x != "undefined") this.storage['position'] = [environment.x, environment.y]; //Modified according to @WasteD
            if (typeof this.storage['map'] == "undefined") { //Create empty map
                var map = [[]];
                //for(i=0;i<this.gridHeight;i++) map[i]=[];
                for(i=0;i<environment.gridHeight;i++) map[i]=[]; //Modified according to @WasteD
                this.storage['map'] = map;
            }
            var blue = []
            var red = []
            var x = this.storage['position'][0];
            var y = this.storage['position'][1];
            var dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1]
            var dy = [1, 1, 1, 0, 0, 0, -1, -1, -1]
            (this.aroundMe || []).forEach((item, idx) => { // Update map and list positions of surrounding blues and reds
                if (item && item.team == 'red' && typeof item.name != "undefined") red += idx;
                if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx[idx]][y+dy[idx]] = 'M';
                if (item && item.team == 'blue' && typeof item.name != "undefined") blue += idx;
            });
            this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']}); //Send to buddies my position and the map
            if (red.indexOf([1, 4, 6, 3][this.direction]) > -1) this.kill() ; //If red guy is in front of
            else if (red.indexOf([1,4,6,3]) > -1) this.rotate(red.indexOf([1,4,6,3])); //If red guy is next but not in front of
            else if (blue.indexOf(3) > -1){ //If blue buddy on the left
                if (blue.indexOf(4) > -1){ //If another one is on the right
                    if (blue.indexOf(1) > -1 && this.direction != 2) this.rotate(2); //...and a third one at the top
                    else var digging = this.dig();
                    }
                else if (this.direction != 1) this.rotate(1);
                else var digging = this.dig();
            }
            else if (blue.indexOf(1) > -1){
                if (blue.indexOf(6) > -1 && this.direction != 3) this.rotate(3);
                else if (this.direction != 2) this.rotate(2);
                else var digging = this.dig();
            }
            else if (blue.indexOf(4) > -1){
                if (this.direction != 3) this.rotate(3);
                else var digging = this.dig();
            }
            else if (blue.indexOf(6) > -1 && this.direction != 0) this.rotate(0);
            else if (blue.indexOf([0,2]) > -1){ //If no blue next to me but one in diagonal, move next
                this.move(1);
                this.storage['position'][1] = y+1; //Update position
            }
            else if (blue.indexOf([5,7]) > -1){
                this.move(6);
                this.storage['position'][1] = y-1;
            }
            else if (typeof this.storage['other_blue'] != "undefined"){ //Check if buddies said where they were, try to go near the closest one
                var dmin = 99999;
                var pos = []
                (this.storage['other_blue'] || {}).forEach((item, idx) => {
                    var d = Math.sqrt(Math.pow(item['position'][0]-x,2) + Math.pow(item['position'][1]-y,2));
                    if (d < dmin){
                        dmin = d;
                        pos = item['position'];
                        }
                });
                if (pos[0]-x > 0){
                    this.move(4);
                    this.storage['position'][0] = x+1
                }
                else if (pos[0] < 0){
                    this.move(3);
                    this.storage['position'][0] = x-1
                }
                else if (pos[1] > 0){
                    this.move(1);
                    this.storage['position'][1] = y+1
                }
                else{
                    this.move(6);
                    this.storage['position'][1] = y-1
                }
            }
            else var digging = this.dig();
            if (typeof digging != "undefined"){ //Check out surroundings if dig() was played and update the map accordingly
                var dx2 = [-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2];
                var dy2 = [2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2];
                (digging || []).forEach((item, idx) => {
                    //if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M';
                    if (item) this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M'; //previously misread what dig() returned
                });
            }
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {
        if (typeof data['position'] != "undefined" && fromTeam == 'blue') { //If position sent by a blue bot
            if (typeof this.storage['other_blue'] == "undefined") this.storage['other_blue'] = [];
            for (i in this.storage['other_blue']){
                var found = false;
                if ('name' in i){
                    if (i['name'] == fromBot){
                        i['position'] = data['position'];
                        found = true; //Update if position already known from previous ticks
                        }
                }
            }
            if (!found) this.storage['other_blue'] += {'position':data['position'], 'name':fromBot}; //Add position if previously unknown
            this.sendMessage(fromBot, undefined, "roger.");
        }
    },
    onkill: function() {this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']});}
});

Ей, тобі байдуже, якщо я також вступлю в це, але (з іншою назвою) я також синій
Крістофер

@Christopher Ні, я не заперечую, але це було б трохи цікавіше для вас і для команди, якщо ви зробите одного хоча б трохи іншого (принаймні, щоб доповнити 2 бота, які вже є).
планнапус

Зробимо це. Я його зміню
Крістофер

Якщо я спробую запустити вашого бота в codepen, він не працює, тому що ви використовуєте this.xі так далі, але це environment.xчи я помиляюся?
WasteD

@WasteD, як я вже сказав, я взагалі не знаю Javascript, тому це можливо. Але якщо це так , то я припускаю , що це повинно бути environment.gridHeightі environment.aroundMe? У такому випадку інші боти не повинні працювати ні з моменту їх використання this.aroundMe.
планнапус

5

Синій, блакитний, мій світ синій

createBot({
    team: 'blue',
    name: 'blue-blue-my-world-is-blue',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            var red = 0;
            // See who's around me
            (this.aroundMe || []).forEach((item, idx) => {
                if (item && item.team == 'red') red++;
            });
            // If surrounded, take one for the team
            if (red >= 6) this.bomb();
            else {
                // Translate direction into position
                var kill = [1, 4, 6, 3][this.direction];
                // Random values
                var move = Math.floor(Math.random() * 8);
                var nsew = Math.floor(Math.random() * 4);
                // Lay a landmine if possible
                if (this.landMines) this.landMine(move);
                // Kill if someone is in the way
                else if (this.aroundMe && this.aroundMe[kill] && this.aroundMe[kill].team == 'red' && this.aroundMe[kill].name) this.kill();
                else {
                    // Move somewhere if already in the requested direction
                    if (nsew == this.direction) this.move(move);
                    // Otherwise just rotate to the requested direction
                    else this.rotate(nsew);
                }
            }
            resolve();
        });
    },
    onmessage: function(data, from, fromBot) {},
    onkill: function() {}
});

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


Розумний! Хороший.
програміст5000

3
Йо слухайте, ось історія про маленького хлопця, який живе в блакитному світі.
Метью Ро на

3

Розслаблений-бомбардувальник

Цей бот шукає місце з принаймні по 1 вільній комірці з кожної сторони, потім встановлює шахту. Він табір на ньому, поки ворог не підійде. Коли хтось наблизиться, він відступить назад і назад на своїй шахті, щоб приманювати іншого бота на ній. Він також буде обертатись і вбивати, якщо потрібно. Коли у нього не залишиться жодної шахти, він шукатиме притулок у верхньому лівому куті спиною до стіни і помститься, якщо йому загрожують.

Тут немає спеціальних командних ігор, окрім трансляції своєї позиції своїй команді за selfключовим словом.

createBot({
    team: 'red',
    name: 'relaxed-bomber',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            if (typeof this.storage['dropped'] == "undefined") {
                this.storage['dropped'] = false;
                this.storage['covered'] = false;
                this.storage['baited'] = false;
            }
            if (typeof environment.x != "undefined" && typeof environment.y != "undefined") {
                this.storage['pos'] = [environment.x, environment.y];
            }
            if (typeof environment.gridWidth != "undefined" && typeof environment.gridHeight != "undefined") {
                this.storage['grid'] = [environment.gridWidth, environment.gridHeight];
            }
            var x = this.storage['pos'][0];
            var y = this.storage['pos'][1];
            var x0 = this.storage['grid'][0];
            var y0 = this.storage['grid'][1];
            var source = [1, 4, 6, 3];
            var dest = [6, 3, 1, 4];
            var rot = [0, 1, 2, 3];
            var movex = [-1, 0, 1, -1, 1, -1, 0, 1];
            var movey = [-1, -1, -1, 0, 0, 1, 1, 1];
            var action = false;
            if (this.landMines > 0) { 
                var move = [false, false, false, false];
                var moveIndex = -1;
                if (x <= 0) { move[1] = true; }
                if (x >= x0 - 1) { move[3] = true; }
                if (y <= 0) { move[2] = true; }
                if (y >= y0 - 1) { move[0] = true; }    
                if (move[0] && !move[1] && !move[2] && move[3]) { moveIndex = 0; }
                if (move[0] && !move[1] && !move[2] && !move[3]) { moveIndex = 1; }
                if (move[0] && move[1] && !move[2] && !move[3]) { moveIndex = 2; }
                if (!move[0] && !move[1] && !move[2] && move[3]) { moveIndex = 3; }
                if (!move[0] && move[1] && !move[2] && !move[3]) { moveIndex = 4; }
                if (!move[0] && !move[1] && move[2] && move[3]) { moveIndex = 5; }
                if (!move[0] && !move[1] && move[2] && !move[3]) { moveIndex = 6; }
                if (!move[0] && move[1] && move[2] && !move[3]) { moveIndex = 7; }  
                if (moveIndex >= 0) {
                    this.storage['pos'] = [ x + movex[moveIndex], y + movey[moveIndex]];
                    this.move(moveIndex);
                } else {
                    this.storage['dropped'] = true;
                    this.storage['covered'] = false;
                    this.landMine(1);
                }
            } else {
                if (this.storage['dropped']) {
                    this.storage['dropped'] = false;
                    this.storage['covered'] = true;
                    this.storage['pos'] = [ x + movex[6], y + movey[6]];
                    this.move(6);
                } else if (this.storage['covered']) {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            this.storage['covered'] = false;
                            this.storage['baited'] = true;
                            this.storage['mine'] = this.storage['pos'].slice();
                            this.storage['reverse'] = source[dest[i]];
                            this.storage['pos'] = [ x + movex[dest[i]], y + movey[dest[i]]];
                            this.move(dest[i]);
                            action = true;
                        }
                    }
                    if (!action) {
                        this.dig();
                    }
                } else if (this.storage['baited']) {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            if (this.direction == rot[source[i]]) {
                                this.kill();
                                this.storage['baited'] = false;
                                action = true;
                            } else {
                                this.rotate(rot[source[i]]);
                                action = true;
                            }
                        }
                    }
                    if (!action) {
                        if (this.storage['mine'][0] == this.storage['pos'][0] && this.storage['mine'][1] == this.storage['pos'][1]) {
                            this.storage['pos'] = [ x + movex[this.storage['reverse']], y + movey[this.storage['reverse']]];
                            this.move(this.storage['reverse']);
                            this.storage['reverse'] = source[this.storage['reverse']];
                        } else {
                            this.storage['pos'] = [ x + movex[this.storage['reverse']], y + movey[this.storage['reverse']]];
                            this.move(this.storage['reverse']);
                            this.storage['reverse'] = dest[this.storage['reverse']];
                        }
                    }
                } else {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            if (this.direction == rot[source[i]]) {
                                this.kill();
                                this.storage['baited'] = false;
                                action = true;
                            } else {
                                this.rotate(rot[source[i]]);
                                action = true;
                            }
                        }
                    }
                    if (!action) {
                        if (x > 0 && y > 0) {
                            this.storage['pos'] = [ x + movex[0], y + movey[0]];
                            this.move(0);
                        } else if (x > 0 && y == 0) {
                            this.storage['pos'] = [ x + movex[3], y + movey[3]];
                            this.move(3);
                        } else if (x == 0 && y > 0) {
                            this.storage['pos'] = [ x + movex[1], y + movey[1]];
                            this.move(1);
                        } else {
                            this.rotate(1);
                        }
                    }
                }
            }
            this.sendMessage(undefined, "red", {'self': this.storage['pos'] });
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {},
    onkill: function() {}
});

В якій команді ви знаходитесь?
програміст5000

@ programmer5000 Оскільки імена ботів повинні починатися з літери команди, я думаю, що я команда Red :)
Thrax

Гарний бот! Я пропоную вам також передати те, що навколо вас, у вашу команду.
програміст5000

1

Резервне копіювання 1 іншого синього бота (забув це зробити раніше)

createBot({
    team: 'blue',
    name: 'backup1',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            //if (typeof this.x != "undefined") this.storage['position'] = [this.x, this.y];
            if (typeof environment.x != "undefined") this.storage['position'] = [environment.x, environment.y]; //Modified according to @WasteD
            if (typeof this.storage['map'] == "undefined") { //Create empty map
                var map = [[]];
                //for(i=0;i<this.gridHeight;i++) map[i]=[];
                for(i=0;i<environment.gridHeight;i++) map[i]=[]; //Modified according to @WasteD
                this.storage['map'] = map;
            }
            var blue = []
            var red = []
            var x = this.storage['position'][0];
            var y = this.storage['position'][1];
            var dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1]
            var dy = [1, 1, 1, 0, 0, 0, -1, -1, -1]
            (this.aroundMe || []).forEach((item, idx) => { // Update map and list positions of surrounding blues and reds
                if (item && item.team == 'red' && typeof item.name != "undefined") red += idx;
                if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx[idx]][y+dy[idx]] = 'M';
                if (item && item.team == 'blue' && typeof item.name != "undefined") blue += idx;
            });
            this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']}); //Send to buddies my position and the map
            if (red.indexOf([1, 4, 6, 3][this.direction]) > -1) this.kill() ; //If red guy is in front of
            else if (red.indexOf([1,4,6,3]) > -1) this.rotate(red.indexOf([1,4,6,3])); //If red guy is next but not in front of
            else if (blue.indexOf(3) > -1){ //If blue buddy on the left
                if (blue.indexOf(4) > -1){ //If another one is on the right
                    if (blue.indexOf(1) > -1 && this.direction != 2) this.rotate(2); //...and a third one at the top
                    else var digging = this.dig();
                    }
                else if (this.direction != 1) this.rotate(1);
                else var digging = this.dig();
            }
            else if (blue.indexOf(1) > -1){
                if (blue.indexOf(6) > -1 && this.direction != 3) this.rotate(3);
                else if (this.direction != 2) this.rotate(2);
                else var digging = this.dig();
            }
            else if (blue.indexOf(4) > -1){
                if (this.direction != 3) this.rotate(3);
                else var digging = this.dig();
            }
            else if (blue.indexOf(6) > -1 && this.direction != 0) this.rotate(0);
            else if (blue.indexOf([0,2]) > -1){ //If no blue next to me but one in diagonal, move next
                this.move(1);
                this.storage['position'][1] = y+1; //Update position
            }
            else if (blue.indexOf([5,7]) > -1){
                this.move(6);
                this.storage['position'][1] = y-1;
            }
            else if (typeof this.storage['other_blue'] != "undefined"){ //Check if buddies said where they were, try to go near the closest one
                var dmin = 99999;
                var pos = []
                (this.storage['other_blue'] || {}).forEach((item, idx) => {
                    var d = Math.sqrt(Math.pow(item['position'][0]-x,2) + Math.pow(item['position'][1]-y,2));
                    if (d < dmin){
                        dmin = d;
                        pos = item['position'];
                        }
                });
                if (pos[0]-x > 0){
                    this.move(4);
                    this.storage['position'][0] = x+1
                }
                else if (pos[0] < 0){
                    this.move(3);
                    this.storage['position'][0] = x-1
                }
                else if (pos[1] > 0){
                    this.move(1);
                    this.storage['position'][1] = y+1
                }
                else{
                    this.move(6);
                    this.storage['position'][1] = y-1
                }
            }
            else var digging = this.dig();
            if (typeof digging != "undefined"){ //Check out surroundings if dig() was played and update the map accordingly
                var dx2 = [-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2];
                var dy2 = [2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2];
                (digging || []).forEach((item, idx) => {
                    //if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M';
                    if (item) this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M'; //previously misread what dig() returned
                });
            }
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {
        if (typeof data['position'] != "undefined" && fromTeam == 'blue') { //If position sent by a blue bot
            if (typeof this.storage['other_blue'] == "undefined") this.storage['other_blue'] = [];
            for (i in this.storage['other_blue']){
                var found = false;
                if ('name' in i){
                    if (i['name'] == fromBot){
                        i['position'] = data['position'];
                        found = true; //Update if position already known from previous ticks
                        }
                }
            }
            if (!found) this.storage['other_blue'] += {'position':data['position'], 'name':fromBot}; //Add position if previously unknown
            this.sendMessage(fromBot, undefined, "roger.");
        }
    },
    onkill: function() {this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']});}
});

1

Синій винищувач

createBot({
  team: "blue",
  name: "blue-fighter",
  ontick: function(environment) {
    return new Promise((resolve, reject)=>{
      let map = environment.aroundMe;
      let sides = [1, 4, 6, 3];
      let facing = sides[this.direction];
      let isTeam = (team,a) => a && a.team === team;
      let isRed = (a)=>isTeam("red",a);
      let isBlue = (a)=>isTeam("blue",a);
      let randomSquare = ()=>Math.floor(Math.random()*8);
      let redNum = map.filter(isRed).length;
      let blueNum =  map.filter(isBlue).length;
      if(redNum > blueNum && redNum > 2){
        this.bomb();
      }else if(isRed(map[facing])){
        this.kill();
      }else if(sides.includes(map.findIndex(isRed))){
        this.rotate(sides.indexOf(map.findIndex(isRed)));
      }else if(Math.random() < 0.5 && this.landMines > 0){
        this.landMine(randomSquare());
      }else{            
        this.move(randomSquare());
      }
      resolve();
    });
  },
  onmessage: function(data, from, fromBot) {},
  onkill: function(){}
});

Синій боєць рухається і мінить випадковим чином і обертається до гравців червоного кольору. Якщо навколишні блоки мають більше червоного, ніж синього, воно бомбить. Якщо він стикається з червоним гравцем, це вбиває його.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.