Команда Холма!

27

Этот вызов был вдохновлен великолепным испытанием @HelkaHomba Red Battle против Blue - Pixel Team Battlebots . Этот вызов был, вероятно, лучшим, который я видел на этом сайте. Когда-либо.

Моя задача по-прежнему сильно отличается, но @HelkaHomba заслуживает похвалы за вдохновение.

обзор

Это командный где ваша команда побеждает, имея в живых всех игроков. Другими словами, побеждает последний командный зачет. Розыгрыши будут повторены.

Вы находитесь на доске. Вы знаете свою позицию в первом раунде (отметьте 0). Вы также знаете, кто находится вокруг вас:

Один красный квадрат в сетке 9х9, окруженный белыми клетками.

В этом случае вы совсем одни (или вы так думаете), рядом никого нет. Вы можете увидеть окружающие элементы в первом аргументе вашего ontickобработчика. Подробнее об API позже.

Твоя команда

Ваша команда определяется вашим идентификатором пользователя. Чтобы узнать это, нажмите на картинку профиля:

Моя аватарка

Затем найдите свой идентификатор пользователя в адресной строке:

Это между / users / и / 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). Num - это направление, которое вы хотите повернуть:

    0 вверху, 1 справа, 2 внизу, 3 слева

    Вращение абсолютно.

  • Убийство

    Если другой игрок (из другой команды) находится в клетке, с которой вы сталкиваетесь, вы можете позвонить this.kill()и убить его. Если там никого нет, или они в вашей команде, это ничего не делает. Пример:

    Те же числа, что и выше, ячейка 0 зеленого цвета, цифра 1 синего цвета, цифра 2 оранжевого цвета и цифра 3 желтого цвета.

    Если вы обратились к 0, вы можете убить зеленый. Если вы обращены в 1, вы можете убить синий. Если вам выпало 2, вы можете убить апельсин. Если вам повернули на 3, вы можете убить желтый.

  • Бомбить

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

    В каждой ячейке есть сетка 9x9 с символом «х».

    Зачем тебе это делать? Камикадзе . Если в 9 ячейках вокруг вас больше игроков, чем в вашей команде, то в вашей команде, вы можете подумать о бомбардировке. (Предлагаю сначала уведомить своих товарищей!)

  • Поместите мины

    Это создает квадрат смерти для других, не входящих в вашу команду. Когда вы устанавливаете наземную шахту, вы также двигаетесь, чтобы не наступать на нее. Вы звоните, this.landMine(num)где Num - это квадрат, на который вы хотите пойти. Пример:

    Один красный квадрат в сетке 9х9, окруженный белыми клетками.

    Тогда вы звоните this.landMine(4):

    [Сетка 9x9, с красной буквой «М» в центре и красной ячейкой в ​​центре справа.

    Видишь что "М"? Это мина. Другие могут видеть это ... пока. Любой, даже те, кто не входит в вашу команду, может увидеть мины на галочке, которую они поставили. Но после того, как этот тик закончится, никто, даже ты не сможешь его увидеть. Но он взорвется, как только враг пройдет по нему. Пример:

    Две сетки 9x9, синяя ячейка в середине слева в первой, красная буква «М» в середине первой, красная буква «Х» в середине второй и стрелка между ними.

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

    За каждые 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)

    Вызывается, когда твоя очередь. Должен вернуть a, Promiseкоторый разрешается за 1 секунду или меньше, иначе он будет проигнорирован. Это из соображений производительности и имеет приятный побочный эффект - отсутствие зависания вкладки.

    this (когда оник)

    • 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 пример:

    Допустим, это сетка (вы красный):

    Сетка 9x9, со светло-синим цветом в верхнем левом углу, серой буквой «М» в правом верхнем углу, красным в середине, желтым в середине слева и красным «М» в левом нижнем углу.

    Вы 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обработчике.

Попробуйте!

Контроллер будет запускаться с моей машины на локальном хосте из соображений производительности, но вы можете использовать CodePen для тестирования своего бота.

Обратите внимание, что вы должны вставить свой код в консоль и нажать, Enterпрежде чем нажать Run. Вы можете вставить столько ботов, сколько захотите. «Испытательные боты» - это примеры для тестирования. Если вы можете победить или связать их всех, у вас есть хотя бы приличный бот.

Материалы

правила

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

  • Ваш основной 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 к награде.

programmer5000
источник
1
Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Деннис
Могу ли я сделать больше, чем один бот? (извините, я знаю, что разговор был перенесен, я просто поболтал, так что да)
Мэтью Ро
@SIGSEGV да, но кто-то должен опубликовать это. Вы можете опубликовать один бот и передать код другого кому-то в вашей команде, но вы не можете опубликовать дважды.
programmer5000
О позиционировании, где находится [0, 0] -индексированная ячейка, это верхняя левая ячейка? Кроме того, обмен сообщениями потребляет ваше действие (за ход)? Спасибо.
Thrax
@ Thrax да, и нет. Вы можете даже сообщение в ответ на сообщение.
programmer5000

Ответы:

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

Очень боится людей. Уходит от первого лица (или мины), которое он видит. В противном случае он движется случайно. Обратите внимание, что это не соревнование, просто пример. Попробуйте побить это!

programmer5000
источник
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']});}
});
plannapus
источник
Эй, тебя волнует, если я тоже введу это, но (под другим именем) я тоже на синем
Кристофер,
@Christopher Нет, я не против, но это было бы немного более интересно для вас и для команды, если вы сделаете один хотя бы немного другим (по крайней мере, чтобы дополнить 2 бота, которые уже существуют).
plannapus
Сделаем это. Я изменю это
Кристофер
Если я пытаюсь запустить ваш бот в codepen, он не работает, потому что вы используете this.xи так далее, но это так environment.xили я не прав?
WasteD
@WasteD, как я уже сказал, я вообще не знаю Javascript, так что это возможно. Но если это так, то я думаю, что это также должно быть environment.gridHeightи environment.aroundMe? В этом случае другие боты не должны работать, так как они используют this.aroundMe.
plannapus
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() {}
});

В основном случайные, но бомбят, если окружены, и предпочитают проверять и убивать при движении.


источник
Умная! Хороший.
programmer5000
3
Слушай, вот история о маленьком парне, который живет в голубом мире.
Мэтью Ро
3

Расслабление-Bomber

Этот бот ищет место с как минимум 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() {}
});
Thrax
источник
В какой команде ты?
programmer5000
@ programmer5000 Так как имена ботов должны начинаться с буквы команды, я думаю, что я Team Red :)
Thrax
Хороший бот! Я предлагаю вам транслировать то, что вас окружает, и вашей команде.
programmer5000
1

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

Синий боец ​​перемещается и мины случайно и вращается в сторону красных игроков. Если окружающие блоки имеют больше красного, чем синего, то это бомбы. Если он сталкивается с красным игроком, он убивает его.

SuperStormer
источник