КОТ: Всі люблять жетони


24

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

Правила:

  • 1 проти 1
  • n дошка (випадковий розмір між 5x5 і 15x15)
  • Ви та ваш противник будете нереститися в одній випадковій комірці
  • По всій дошці будуть довільно генеруватися числа в деяких клітинках, що мають значення від 1-3
  • 2 * (ширина дошки) жетонів буде сформовано, але може бути переопрацювання, тому випадково їх може бути менше.
  • Кожне число буде одним з 3 кольорів: червоним, зеленим або синім у шестигранному форматі RGB
  • Кожен раунд, гравець 1 рухається, і дошка оновлюється, потім гравець 2 рухається, і дошка оновлюється. Таким чином, кожен гравець може ефективно підказати, який хід здійснив попередній гравець, виходячи зі зміни стану дошки. Це триває до кінця гри, як описано далі.
  • У вас є 6 можливих дій для повороту: Вгору, Вправо, Вниз, Вліво, Їжте та ПАРОЛ
  • 4 команди переміщення самі собою пояснюють, і ви МОЖЕТЕ пройти свою чергу. Якщо ви повернетеся безглуздою ходою, ми вважатимемо, що ви мали на увазі пропуск. Якщо ви спробуєте відсунутись від краю дошки, ви не рухатиметесь. Краї не загортаються.
  • EAT споживає кількість, з яким ви зараз перебуваєте в тому ж просторі, що і ви
  • Ви набираєте стільки очок, скільки спожиєте
  • Якщо ви з'їсте 2 числа підряд одного кольору, ви отримаєте +1
  • Якщо ви з'їсте 3 числа підряд одного кольору, ви отримаєте +2
  • Якщо ви їсте m чисел у рядку одного кольору, ви отримуєте + (m-1)
  • Ці бонуси додаються сукупно, тому отримання m номерів підряд призводить до загального бонусу m * (m-1) / 2 до моменту, коли ви їсте інший колір.
  • Умови закінчення гри:
    • Усі числа споживаються
    • 4 * (ширина дошки) оборотів пройшли без ефективного прийому їжі (просто кажучи "EAT" без маркіру, де вас не рахують), що відбувається будь-яким гравцем (будь-який жетон доступний у 2 * (ширина) рухається, тому ця межа буде перевершена лише в тому випадку, якщо обоє гравців не мають на увазі жодного цільового маркера)
  • Ваш AI повинен зайняти менше секунди, щоб зробити крок, інакше PASS буде вважатися вашим вибором.

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

Подання AI: мова, яку підтримує наш контролер, - JavaScript. Дозволено кілька заявок. Усі подають конструктор для такого об’єкта:

function (player1) {
    this.yourMove = function (b) {
        return "MOVE";
    }
}

Вхід player1є булевим словом, граєте ви 1 чи ні. Ваш конструктор повинен мати yourMoveфункцію, але він також може мати будь-яку кількість додаткових функцій або значень. Не визначайте жодних глобальних змінних, просто поставте їх як змінні на вашому об’єкті. Нова версія вашого об’єкта буде створена на початку кожного матчу, і yourMoveбуде викликана на ньому, з поточною дошкою як вхідним кодом, на кожному з ваших поворотів, і повинна повернути дійсний хід.

b, вхід до yourMove- це копія поточної плати, ось конструктори із прикладами введення, хоча ви не можете їх самостійно назвати:

function token(color, points) {
    this.color = color; //"#FF0000"
    this.points = points; //5
}

function player(pos, score, colorBonus, lastColor) {
    this.pos = pos; //[5, 5]
    this.score = score; //9
    this.colorBonus = colorBonus; //i.e. 2 if you just ate 3 blue tokens in a row
                                  //0 if you just ate two different colors.
    this.lastColor = lastColor; //"#00FF00", is "#000000" at start
}

function board(player1, player2, tokens) {
    this.player1 = player1; //new player([5, 5], 9, 2, "#00FF00")
    this.player2 = player2; //new player([5, 5], 9, 2, "#00FF00")
    this.tokens = tokens; //[[new token("#0000FF", 5), false],
                      // [new token("#0000FF", 5), false]]
}

Масив лексеми має значення "false" для будь-яких порожніх квадратів, а лексеми [a] [b] - маркер у x = a, y = b, пронумерований починаючи з лівого верхнього кута.

Контролер: Ось посилання на контролер у GitHub. Це HTML-файл, який ви можете запустити, щоб побачити, як працює гра та круговий робін, і він постачається з двома AI, випадковим, який рухається у випадковому напрямку кожен поворот, але їсть жетони на своєму положенні, та наївним алгоритмом, який йде на найближчий жетон, який дає найбільшу кількість балів. Я додаватиму в кожен ШІ по мірі подання.

Нижче представлений фрагмент, який дозволяє запустити контролер на AI за замовчуванням. Поточні ІС:

  • KindaRandomAI
  • NaiveAI
  • MirrorBot
  • HungryBot


12
Так, КОТА! Це було назавжди з останнього.
TheNumberOne

2
Домовились, я люблю мене гарну КОТУ, і це, здається, є чудовою умовою. Я трохи зелений до js, як зберігається одна гра між рухами, якщо ми не можемо зберегти результати в об'єкті гравця?
DoctorHeckle

Чи передається ширина плати де-небудь у функції?
TheNumberOne

@BentNeeHumor Так, функція, яка приймає player1булеву функцію, є конструктором для вашого AI, який матиме yourMoveфункцію, яка приймає поточну плату як вхідну b.
Фрикативна диня

1
@DylanSp Іноді вони заборонені через можливості змови, але в цьому випадку змова матиме мінімальні переваги, тому я дозволю кілька заявок.
Фрикативна диня

Відповіді:


4

HungryBot

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

function hungryBot(first) {
  // Set up "self"
  var self = this;

  // Determine player order
  this.player = -(first - 2);
  this.enemy = first + 1;

  // Action associative array
  this.actions = ['EAT', 'LEFT', 'RIGHT', 'UP', 'DOWN'];

  //Logic handler
  this.yourMove = function(board) {
    // Determine player object
    var player = board['player' + self.player];
    var enemy = board['player' + self.enemy];

    // Point value action grid
    var actions = [0, 0, 0, 0, 0]; // Associative with "this.actions"

    // Board dimensions
    var size = board.tokens.length;
    var maxDist = size * 2;

    // Colors remaining
    var colors = {
      '#FF0000': 0,
      '#00FF00': 0,
      '#0000FF': 0
    };

    // Averaged value weight
    var average = [0, 0];

    // Total points
    var points = 0;

    // Token holder
    var tokens = [];

    // Token parser
    for (var i = 0, x = 0, y = 0; i < size * size; i += 1, x = i % size, y = i / size | 0) {
      if (!board.tokens[x][y]) {
        continue;
      } else {
        var token = {};
        token.points = board.tokens[x][y].points;
        token.color = board.tokens[x][y].color;
        token.x = x - player.pos[0];
        token.y = y - player.pos[1];
        token.distX = Math.abs(token.x);
        token.distY = Math.abs(token.y);
        token.dist = token.distX + token.distY;
        token.distE = Math.abs(x - enemy.pos[0]) + Math.abs(y - enemy.pos[1]);
        token.value = -token.points - (player.colorBonus + 1) * (token.color == player.lastColor) * ((token.dist == 0) + 1) * 1.618 - (enemy.colorBonus + 1) * (token.color == enemy.lastColor);
        tokens.push(token);
        colors[token.color] += 1;
        points += token.points;
        average[0] += x * token.points;
        average[1] += y * token.points;
      }
    }

    // Determine actual average
    average[0] = average[0] / points | 0;
    average[1] = average[1] / points | 0;

    // Pick best token
    var best = 0;

    // Calculate point values of tokens
    for (i = 0; i < tokens.length; i++) {
      var token = tokens[i];
      // Add remaining numbers of tokens of color as factor
      token.value -= (colors[token.color] / tokens.length) * 1.618;
      // Subtract distance as a factor
      token.value += token.dist;
      // Add distance to average to value
      token.value += (Math.abs(average[0] - (token.x + player.pos[0])) + Math.abs(average[1] - (token.y + player.pos[1]))) / Math.sqrt(2);
      // Consider them higher value if we are closer, and lower if they are
      token.value += ((token.dist - token.distE) / (token.dist + token.distE + 0.001)) * token.dist;
      // Don't go for it if enemy is already there
      token.value += (token.distE == 0 && token.dist > 0) * 100;

      if (tokens[best].value > tokens[i].value || (tokens[best].value === tokens[i].value && Math.round(Math.random()))) {
        best = i;
      }
    }

    // Set token to best token
    var token = tokens[best];

    // What to respond with
    var response = 'PASS';

    // Find best action to get token
    if (token.dist == 0) {
      response = 'EAT'; // We're on the token
    } else if (token.distX >= token.distY) { // Token is more horizontal
      if (token.x < 0) { // Token is left
        response = 'LEFT';
      } else if (token.x > 0) { // Token is right
        response = 'RIGHT';
      }
    } else if (token.distX < token.distY) { // Token is more vertical
      if (token.y < 0) { // Token is above
        response = 'UP';
      } else if (token.y > 0) { // Token is below
        response = 'DOWN';
      }
    }

    // Return response
    return response;
  }
};

Ви програміст Python?
CalculatorFeline

@CatsAreFluffy Не дуже ...?
Mwr247

Просто подумав, що ти тому, що self:)
CalculatorFeline

Навіщо використовувати self? Чи не thisдосить?
Конор О'Браєн

2

PATH бот

Акронім означає Bot Heuristics Bot

РЕДАКТИКА: На сьогоднішній день тут рейтинги ІС з балами

  1. HungryBot (6422)
  2. PATH бот (4591)
  3. NaiveAI (3811)
  4. KindaRandomAI (618)
  5. MirrorBot (193)
  6. LazyBot (25)

Посилання на повний контролер на github

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

Обгрунтування: Оскільки NaiveAI вже досить хороший, я хоч би зробив це краще. Не дивлячись спочатку на код (велика помилка).

Удари: Усі, крім HungryBot
: Ні, крім HungryBot

Проблеми:

  • Неможливо імітувати посилену смугу
  • Висить під час обчислення найкращого маркера
  • Можна телепортувати

Я досі не знаю, чому це було телепортуванням, але я це виправив. Тут старе відео: https://youtu.be/BIhSKycF9iA

Повний код:

pathBot = function (player1)
{
    this.pathNode = function(pos,ppt,parents,par)
    {
        this.pos = pos;this.ppt = ppt;this.parents = parents;this.par=par;
        this.childs=[];
    }
    this.addChildren = function (pn,children)
    {
        pn.childs=[];
        for(var i=0; i<children.length; i=i+1)
        {
            if(pn.parents.indexOf(children[i].pos)==-1&&pn.pos!=children[i].pos)
                pn.childs.push(
                    new this.pathNode(
                        children[i].pos,
                        children[i].ppt*pn.ppt,
                        pn.parents.concat([pn.pos]),
                        pn
                    )
                );
        }
    }
    this.orderTokensByPPT = function(b,pos){
        var tokens = [];
        for(var y=0; y<b.tokens.length; y=y+1)
        {
            for(var x=0; x<b.tokens[y].length; x=x+1)
            {
                var tok = b.tokens[y][x];
                if(tok)
                {
                    tokens.push(
                        new this.pathNode(
                            [y,x],
                            (tok.points+(tok.color==this.color ? this.streak : 0)) / this.lenOfMovesTo(pos,[y,x]),
                            [],
                            undefined
                        )
                    );
                }
            }
        }
        tokens.sort(function(a,b){
            return b.ppt - a.ppt;
        });
        return tokens;
    }
    this.lenOfMovesTo = function(cur,pos)
    {
        return Math.abs(cur[0]-pos[0])+Math.abs(cur[1]-pos[1])+1;
    }
    this.startAndGoalToCommand = function (start, goal) {
        var diff = [goal[0] - start[0], goal[1] - start[1]];
        if (diff[0] > 0) { return "RIGHT"; }
        else if (diff[1] > 0) { return "DOWN"; }
        else if (diff[1] < 0) { return "UP"; }
        else if (diff[0] < 0) { return "LEFT"; }
        else { return "EAT"; }
    }
    this.color = 0;
    this.streak = 0;
    this.eatTok = function(b)
    {
        if(b.tokens[this.me.pos[0]][this.me.pos[1]].color==this.color)
        {
            this.streak++;
        }
        else{
            this.streak = 0;
            this.color = b.tokens[this.me.pos[0]][this.me.pos[1]].color;
        }
        this.bestToken = false;
        return "EAT";
    }

    this.recurLen = 6;
    this.include = 4;
    this.recurDown = function(b,pn,level)
    {
        if(level==0) return pn;
        this.addChildren(pn,this.orderTokensByPPT(b,pn.pos));
        var newChilds = [];
        for(var i=0; i<pn.childs.length&&i<this.include; i=i+1)
        {
            newChilds.push(this.recurDown(b,pn.childs[i],level-1));
        }
        pn.childs = newChilds;
        return pn;
    }
    this.findMax = function(pn)
    {
        if(pn.childs)
        {
            var maxList = [];
            for(var i=0; i<pn.childs.length; i=i+1)
                maxList.push(this.findMax(pn.childs[i]));
            maxList.sort(
                function(a,b)
                {
                    return b.ppt-a.ppt;
                }
            );
            return maxList[0];
        }
        return pn;
    }
    this.findMaxList = function(pnList)
    {
        for(var i=0; i<pnList.lenght; i=i+1)
        {
            pnList[i] = this.findMax(pnList[i]);
        }
        pnList.sort(function(a,b){return b.ppt-a.ppt;});
        return pnList[0];
    }
    this.bestToken=false;
    this.yourMove = function(b){
        this.op = player1 ? b.player2 : b.player1;
        this.me = player1 ? b.player1 : b.player2;
        if(this.bestToken)
        {
            if(b.tokens[this.bestToken.pos[0]][this.bestToken.pos[1]]==undefined)
                this.bestToken = false;
        }
        if(!this.bestToken)
        {
            var paths = this.orderTokensByPPT(b,this.me.pos);
            for(var i=0; i<paths.length; i++)
            {
                paths[i] = this.recurDown(b,paths[i],this.recurLen);
            }
            var max = this.findMaxList(paths);
            while(max.par)
            {
                max = max.par;
            }
            this.bestToken = max;
        }
        var move = this.startAndGoalToCommand(this.me.pos,this.bestToken.pos);
        if(move=="EAT") return this.eatTok(b);
        else return move;
    }
}

SLaNTbot уповільнює швидкість повороту і з'їдає 15% мого процесора ... D: EDIT: І також нічого не їсти?
Mwr247

@ Mwr247 швидкість, так, він моделює ~ 2500 можливостей кожного галочки. Але щодо їжі я точно не знаю, чому. Як я вже сказав у запитанні, він просто телепортується (він же переміщує декілька пробілів за 1 хід) і сидить там, не роблячи нічого. Я поставив попередження безпосередньо перед поверненням і, здається, щоразу дає правильні вказівки.
Блакитний

Можливо, це: "Ваш AI повинен пройти менше секунди, щоб зробити крок, інакше PASS буде вважатися вашим вибором." Я не читав контролер, але якщо це забирає секунду, чи передбачається це PASS?
Mwr247

@ Mwr247 Я розберуся в цьому, але, мабуть, мабуть, враховуючи, що на моїй машині він займав <1 секунду (або я так хотів). Все-таки ніколи не боляче виглядати. Дякую!
Блакитний

@ Mwr247 Після ще одного тестування, це не все. Він приймає рішення майже так само швидко (принаймні для мене), як NaiveAi. Крім того, ви швидше відчуєте телепортацію на великих картах
Blue Blue

1

NaiveAI

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

naiveAI = function(player1) {
  this.player1 = player1;
  this.yourMove = function(b) {
    var me;
    if (this.player1) {
      me = b.player1;
    } else {
      me = b.player2;
    }
    var d = 0;
    var tokenP;
    while (tokenP == undefined) {
      var arr = this.findTokensAtDistance(me.pos, d)
      tokenP = this.findBestToken(arr, b.tokens, me);
      d += 1;
    }
    return this.startAndGoalToCommand(me.pos, tokenP);
  }
  this.findTokensAtDistance = function(p, d) {
    if (d == 0) {
      return [
        [p[0], p[1]]
      ];
    }
    var myArr = [];
    for (i = 0; i <= d; i++) {
      myArr[i] = [i, d - i];
    }
    var mySecArr = [];
    for (i = 0; i <= d; i++) {
      mySecArr[i] = [myArr[i][0] + p[0], myArr[i][1] + p[1]];
    }
    mySecArr[mySecArr.length] = [myArr[0][0] + p[0], -myArr[0][1] + p[1]];
    for (i = 1; i < myArr.length - 1; i++) {
      mySecArr[mySecArr.length] = [-myArr[i][0] + p[0], myArr[i][1] + p[1]]
      mySecArr[mySecArr.length] = [myArr[i][0] + p[0], -myArr[i][1] + p[1]]
      mySecArr[mySecArr.length] = [-myArr[i][0] + p[0], -myArr[i][1] + p[1]]
    }
    mySecArr[mySecArr.length] = [-myArr[myArr.length - 1][0] + p[0], myArr[myArr.length - 1][1] + p[1]];
    return mySecArr;
  }
  this.findBestToken = function(arr, t, player) {
    var tokenPos;
    for (i = 0; i < arr.length; i++) {
      if (arr[i][0] >= 0 && arr[i][0] < t.length && arr[i][1] >= 0 && arr[i][1] < t.length) {
        if (t[arr[i][0]][arr[i][1]] != false && ((tokenPos == undefined) || (this.tokenScore(player, t[arr[i][0]][arr[i][1]]) > this.tokenScore(player, t[tokenPos[0]][tokenPos[1]])))) {
          tokenPos = [arr[i][0],
            [arr[i][1]]
          ];
        }
      }
    }
    return tokenPos;
  }
  this.tokenScore = function(player, token) {
    if (player.lastColor == token.color) {
      return player.colorBonus + 1 + token.points;
    } else {
      return token.points;
    }
  }
  this.startAndGoalToCommand = function(start, goal) {
    var diff = [goal[0] - start[0], goal[1] - start[1]];
    if (diff[0] > 0) {
      return "RIGHT";
    } else if (diff[1] > 0) {
      return "DOWN";
    } else if (diff[1] < 0) {
      return "UP";
    } else if (diff[0] < 0) {
      return "LEFT";
    } else {
      return "EAT";
    }
  }
}

1

KindaRandomAI

Кожен поворот виконайте наступне: Якщо у вашому положенні є маркер, "EAT". В іншому випадку рухайтесь у випадковому життєздатному напрямку, тобто, якщо ви знаходитесь у лівому краї, не кажіть "ВЛИВО".

kindaRandomAI = function(player1) {
    this.player1 = player1;
    this.yourMove = function(b) {
        var me;
        if (this.player1) {
            me = b.player1;
        } else {
            me = b.player2;
        }
        if (b.tokens[me.pos[0]][me.pos[1]] != false) {
            return "EAT";
        } else {
            var dirs = this.getViableDirections(b, me.pos);
            var rand = Math.floor(Math.random() * dirs.length);
            return dirs[rand];
        }
    }
    this.getViableDirections = function(b, p) {
        var dirs = [];
        if (p[0] > 0) {
            dirs.push("LEFT");
        }
        if (p[1] > 0) {
            dirs.push("UP");
        }
        if (p[1] < b.tokens.length - 1) {
            dirs.push("DOWN");
        }
        if (p[0] < b.tokens.length - 1) {
            dirs.push("RIGHT");
        }
        return dirs;
    }
}

-1 не зовсім випадковий
CalculatorFeline

Так краще!.
CalculatorFeline

1

LazyBot

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

lazyBot = function (player1) {
    this.yourMove = function(b) {
        return "EAT";
    }
}

1
У кожного кота є EmoWolf ...
Синій

3
@Blue Це не 100% емоція, вона намагається їсти.
Балінт


1

MirrorBot

Слід називати "гарматним кормом"

Опис: Переміщує точну протилежність тому, що робив інший гравець

Обгрунтування: Я хотів знову отримати зручне програмування в JS. Це не повинно перемагати

Битимуть: Ніхто

Втратить: Кожен

function mirror(player1) {
    this.hasStarted=false;
    this.player1 = player1;
    this.opl=[0,0];
    this.yourMove = function(b){
        this.op = this.player1 ? b.player2.pos : b.player1.pos;
        out = "EAT";
        console.log(this.op);
        console.log(this.opl);
        if(this.hasStarted){
            if(this.opl[0] < this.op[0]) out = "RIGHT";
            if(this.opl[0] > this.op[0]) out = "LEFT";
            if(this.opl[1] < this.op[1]) out = "UP";
            if(this.opl[1] > this.op[1]) out = "DOWN";
        }
        this.opl = [this.op[0],this.op[1]];
        this.hasStarted = true;
        return out;
    }
}

Є кілька проблем з вашим кодом. Праворуч і ліворуч не протилежні, і визначення функції для вашогоMove не є синтаксисом. Мій код також був порушений, тому в процесі пошуку та виправлення проблеми в моєму коді я також виправила ваш код. Ви можете подивитися фіксований код у моєму сценарії.
Фрикативна диня

@FricativeMelon Я виправив визначення зламаної функції. Я повинен протидіяти твердженню, що право не протилежне.
Блакитний

0,0 - верхній лівий кут, тому позитивний х - правий, а мінус - лівий. якщо новий x-pos має більше значення, ніж старий x-pos, інший гравець перемістився праворуч, тож слід рухатись вліво і навпаки. Також слід використовувати var out = "EAT";замість out = "EAT";, оскільки пізніше визначається глобальна змінна. Трохи потріскавши, третій та четвертий рядки нічого не роблять і їх також можна видалити, і вони opможуть бути локальною змінною, як outзамість властивості.
Фрикативна диня

@FricativeMelon ах, я розумію, що ти кажеш. Я оновив код. Дякую!
Блакитний

Я помістив ваш новий код у сценарій, і він працює зараз. Не перемагає RandomAI, хоча :(
Фрикативна диня

0

OneTarget

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

function (player1) {
    this.yourMove = function (b) {
        var me = player1? b.player1: b.player2;
        var him= player1? b.player2: b.player1;
        var x = me.pos[0];
        var y = me.pos[1];
        var maxVal = -1;
        var maxX = 0;
        var maxY = 0;
        for(var i = 0;i < b.tokens.length;i++){
            for(var j = 0;j < b.tokens.length;j++){
                if(b.tokens[i][j]){
                    var dist = Math.abs(x-i) + Math.abs(y-j);
                    var val = this.valueOf(b.tokens[i][j]);
                    val /= (dist + 1);
                    if(val > maxVal){
                        maxVal = val;
                        maxX = i;
                        maxY = j;
                    }
                }
            }
        }
        if(maxY < y)
            return "UP";
        if(maxX < x)
            return "LEFT";
        if(maxY > y)
            return "DOWN";
        if(maxX > x)
            return "RIGHT";
        return "EAT";
    }
    this.valueOf = function(t){
        //how many points would it give you?
        return t.points + (this.lastColor == t.color? 2 * this.colorBonus + 1 : 0);
    }
}

0

Кількість гравця

Все, що турбує QuantityPlayer, - це кількість точок, які він їсть, а не значення та колір крапок. Він знає, що хоч усі крапки різні, до них слід ставитися однаково.

QuantityBot = function(playernum) {

this.dist = function(token) {
    return (Math.abs(token[0])+Math.abs(token[1]))
}

this.yourMove = function(game_board) {

    board_size = game_board.tokens.length
    board_area = board_size * board_size
    fete = board_size = size * 2

    token_list = []
    count = curr_x = curr_y = 0
    while(count < board_area) {
        if(game_board.tokens[x][y]) {
        token_list.push([x-player.pos[0],y-player.pos[1]])
        }
        count++; x = count % board_size; y = Math.floor(count / size)
    }

    closest_token = token_list[0]
    count = 1
    while(count < token_list.length) {
        curr_token = token_list[count]
        if(dist(curr_token) < dist(closest_token)){closest_token = curr_token}

        count++
    }

    if(dist(closest_token)==0){return 'EAT'}
    else{
    if(closest_token[0] >= closest_token[1]) {if(closest_token[0]<0) {return 'LEFT'} {return 'RIGHT'}}
    else{if(closest_token[1]<0) {return 'UP'} {return 'DOWN'}}
    }

}

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