KOTH: Tout le monde aime les jetons

24

Dans ce jeu, deux joueurs s'affrontent pour manger le plus de points de jetons, mais il y a une torsion! Manger plusieurs jetons dans une rangée de la même couleur donne un bonus sans cesse croissant, mais attention, ou votre adversaire déjouera vos plans en mangeant les jetons que vous voulez avant que vous puissiez!

Règles:

  • 1 contre 1
  • Tableau n par n (taille aléatoire entre 5x5 et 15x15)
  • Vous et votre adversaire apparaîtront dans la même cellule aléatoire
  • Tout au long du tableau, des nombres générés de manière aléatoire dans certaines cellules, dont la valeur va de 1 à 3
  • 2 * (la largeur du plateau) des jetons seront générés, mais il peut y avoir des remplacements, donc il peut y en avoir moins par hasard.
  • Chaque numéro sera l'une des 3 couleurs: rouge, vert ou bleu, au format RVB hexadécimal
  • À chaque tour, le joueur 1 se déplace et le plateau est mis à jour, puis le joueur 2 se déplace et le plateau est mis à jour. Ainsi, chaque joueur peut dire efficacement quel mouvement le joueur précédent a fait en fonction du changement d'état du plateau. Cela continue jusqu'à la fin du jeu, comme décrit plus loin.
  • Vous avez 6 actions possibles pour un tour: UP, RIGHT, DOWN, LEFT, EAT et PASS
  • Les 4 commandes de déplacement sont explicites et vous POUVEZ passer votre tour. Si vous retournez un coup absurde, nous supposerons que vous vouliez passer. Si vous essayez de vous éloigner du bord de la planche, vous ne bougerez pas. Les bords ne s'enroulent pas.
  • EAT consomme le nombre que vous êtes actuellement dans le même espace que
  • Vous gagnez autant de points que le nombre que vous consommez
  • Si vous mangez 2 numéros consécutifs de la même couleur, vous obtenez +1
  • Si vous mangez 3 numéros consécutifs de la même couleur, vous obtenez +2
  • Si vous mangez m nombres dans une rangée de la même couleur, vous obtenez + (m-1)
  • Ces bonus sont ajoutés cumulativement, donc obtenir un nombre m consécutif conduit à m * (m-1) / 2 en bonus total au moment où vous mangez une couleur différente.
  • Conditions de fin de partie:
    • Tous les numéros sont consommés
    • 4 * (la largeur du plateau) des tours se sont écoulés sans manger efficacement (juste dire "MANGER" sans jeton où vous êtes ne compte pas) se produisant par l'un ou l'autre joueur (n'importe quel jeton est accessible en 2 * (la largeur) mouvements, donc cette limite ne sera dépassée que si les deux joueurs n'ont pas de jeton cible unique en tête)
  • Votre IA devrait prendre moins d'une seconde pour faire un mouvement, sinon PASS sera considéré comme votre choix.

Le tournoi sera un tournoi à la ronde avec un grand nombre de tours, disons 100 ou 1000. Un plateau aléatoire est généré, et chaque paire ordonnée de joueurs différents est exécutée sur ce plateau. Une fois le tournoi terminé, nous classerons les joueurs en fonction de leur score total. Donc, même si vous êtes le joueur 2 d'un match, votre objectif est toujours d'obtenir autant de points que possible.

Soumission AI: la langue prise en charge par mon contrôleur est Javascript. Les soumissions multiples sont autorisées. Tout le monde soumet un constructeur pour un objet comme celui-ci:

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

L'entrée player1est un booléen disant si vous êtes le joueur 1 ou non. Votre constructeur doit avoir la yourMovefonction, mais il peut également avoir n'importe quel nombre de fonctions ou de valeurs supplémentaires. Ne définissez aucune variable globale, placez-les simplement en tant que variables sur votre objet. Une nouvelle version de votre objet sera créée au début de chaque match, et yourMovesera appelée dessus, avec le plateau actuel en entrée, à chacun de vos tours, et devrait retourner un coup valide.

b, l'entrée de yourMove, est une copie de la carte actuelle, voici les constructeurs, avec des exemples d'entrée, bien que vous ne puissiez pas les appeler vous-même:

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

Le tableau de jetons a "faux" pour tous les carrés vides, et les jetons [a] [b] sont les jetons à x = a, y = b, numérotés à partir du coin supérieur gauche.

Contrôleur: voici un lien vers le contrôleur dans GitHub. C'est un fichier html que vous pouvez exécuter pour voir comment le jeu et le tournoi à la ronde fonctionnent, et il est livré avec deux IA, une aléatoire qui se déplace dans une direction aléatoire à chaque tour mais mange des jetons à sa position, et un algorithme naïf qui va pour le jeton le plus proche qui donne le plus de points. J'ajouterai chaque IA au fur et à mesure de sa soumission.

Vous trouverez ci-dessous un extrait qui vous permet d'exécuter le contrôleur sur l'IA par défaut. IA actuelles:

  • KindaRandomAI
  • NaiveAI
  • MirrorBot
  • HungryBot

Melon fricatif
la source
12
Ouais, un KOTH! Cela fait une éternité depuis le dernier.
TheNumberOne
2
D'accord, je m'aime un bon KOTH et cela semble être une excellente prémisse. Je suis un peu vert pour js, comment persiste-t-on un état de jeu entre les coups si nous ne pouvons pas enregistrer les résultats dans l'objet joueur?
DoctorHeckle
La largeur de la carte est-elle transmise n'importe où dans la fonction?
TheNumberOne
@BentNeeHumor Oui, la fonction qui prend le player1booléen est le constructeur de votre IA, qui aura une yourMovefonction qui prend la carte actuelle en entrée, comme b.
Fricative Melon
1
@DylanSp Parfois, ils ne sont pas autorisés en raison des possibilités de collusion, mais dans ce cas, la collusion aurait des avantages minimes, donc je vais autoriser plusieurs soumissions.
Fricative Melon

Réponses:

4

HungryBot

Utilise un système de points pour ajouter du poids à la valeur de la poursuite de chaque jeton. Utilise une variété de facteurs différents dans son examen et les réévalue à chaque tour pour s'assurer qu'il suit la meilleure stratégie.

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;
  }
};
Mwr247
la source
Êtes-vous un programmeur Python?
CalculatorFeline
@CatsAreFluffy Pas vraiment ...?
Mwr247
Je pensais que tu étais parce que self:)
CalculatorFeline
Pourquoi utiliser self? N'est-ce pas thissuffisant?
Conor O'Brien
2

Bot PATH

Acronyme signifie Bot Pathfinding et Tree Heuristics

EDIT: Pour l'instant, voici le classement des IA, avec les points

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

Lien vers le contrôleur complet sur github

Description: Comme NaiveAI, ce bot trouve le jeton le plus proche qui lui donnera le plus de points. Cependant, il simule également les résultats de chacun de ses mouvements, jusqu'à 6 fois.

Justification: Parce que NaiveAI est déjà assez bon, je pensais que je ferais mieux. Sans regarder d'abord le code (grosse erreur).

Battements: tous sauf HungryBot
Perd à: aucun sauf HungryBot

Problèmes:

  • Impossible de simuler une séquence accrue
  • Se bloque lors du calcul du meilleur jeton
  • Peut se téléporter

Je ne sais toujours pas pourquoi il se téléportait, mais je l'ai corrigé. Ancienne vidéo ici: https://youtu.be/BIhSKycF9iA

Code complet:

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;
    }
}
Bleu
la source
SLaNTbot ralentit la vitesse de rotation et consomme 15% de mon processeur ... D: EDIT: Et aussi ne mange rien?
Mwr247
@ Mwr247 la vitesse, oui, il modélise ~ 2500 possibilités à chaque tick. Mais pour ce qui est de manger, je ne sais pas exactement pourquoi. Comme je l'ai dit dans la question, il se téléporte simplement (alias déplace plusieurs espaces en 1 tour) et reste assis sans rien faire. J'ai mis une alerte juste avant le retour et il semble donner à chaque fois les bonnes instructions.
Blue
Peut-être ceci: "Votre IA devrait prendre moins d'une seconde pour faire un mouvement, sinon PASS sera supposé être votre choix.". Je n'ai pas lu le contrôleur, mais s'il prend plus d'une seconde, suppose-t-il PASS?
Mwr247
@ Mwr247 J'examinerai cela, mais cela semble peu probable étant donné que cela prenait <1 seconde (ou du moins je le pensais) sur ma machine. Pourtant, jamais mal à regarder. Merci!
Blue
@ Mwr247 Après quelques tests supplémentaires, ce n'est pas tout. Il prend des décisions presque aussi rapidement (au moins pour moi) que NaiveAi. En outre, vous êtes plus susceptible de faire l'expérience de la téléportation sur de grandes cartes
Bleu
1

NaiveAI

Commencez par r=0regarder tous les jetons dont la distance en taxi est réloignée de votre position. S'il y en a, choisissez-en un qui vous donnerait le meilleur score si vous l'aviez déjà. Sinon, augmentez rde 1 et réessayez.

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";
    }
  }
}
Melon fricatif
la source
1

KindaRandomAI

À chaque tour, procédez comme suit: S'il y a un jeton à votre position, "EAT". Sinon, déplacez-vous dans une direction viable aléatoire, c'est-à-dire que si vous êtes sur le bord gauche, ne dites pas "GAUCHE".

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;
    }
}
Melon fricatif
la source
-1 pas complètement aléatoire
CalculatorFeline
C'est mieux!.
CalculatorFeline
1

LazyBot

Ne mange quelque chose que s'il apparaît dessus. Cela n'a aucune chance de gagner, mais le défi n'en avait pas, alors pourquoi pas.

lazyBot = function (player1) {
    this.yourMove = function(b) {
        return "EAT";
    }
}
Bálint
la source
1
Chaque koth a un EmoWolf ...
Blue
3
@Blue Ce n'est pas 100% emo, il essaie de manger.
Bálint
1

MirrorBot

Doit être appelé "chair à canon"

Description: déplace exactement le contraire de ce que l'autre joueur a fait

Justification: Je voulais à nouveau obtenir une programmation confortable dans JS. Cela ne devrait pas gagner

Will beat: Personne

Perdra face à: Tout le monde

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;
    }
}
Bleu
la source
Il y a quelques problèmes avec votre code. Droite et Gauche ne sont pas opposées, et la définition de votre fonction pour yourMove n'est pas une syntaxe valide. Mon code a également été cassé auparavant, donc dans le processus de recherche et de résolution du problème dans mon code, j'ai également corrigé votre code. Vous pouvez regarder le code fixe dans mon script.
Fricative Melon
@FricativeMelon J'ai corrigé la définition de fonction cassée. Je dois contrer l'affirmation selon laquelle le droit n'est pas opposé.
Blue
0,0 est le coin supérieur gauche, donc x positif est à droite et x négatif est à gauche. si le nouveau x-pos a une valeur supérieure à l'ancien x-pos, l'autre joueur s'est déplacé vers la droite, vous devez donc vous déplacer vers la gauche et vice-versa. En outre, vous devez utiliser à la var out = "EAT";place de out = "EAT";, car ce dernier définit une variable globale. Nitpicking un peu, les troisième et quatrième lignes ne font rien et peuvent également être supprimées, et oppeuvent être une variable locale comme outau lieu d'une propriété.
Fricative Melon
@FricativeMelon ah, je comprends ce que vous dites. J'ai mis à jour le code. Merci!
Blue
J'ai mis votre nouveau code dans le script, et cela fonctionne maintenant. Ne bat pas RandomAI cependant :(
Fricative Melon
0

OneTarget

Trouve le jeton qui donnera le plus de points en moins de temps et ira pour celui-là. Classe les jetons de même couleur un peu plus haut en raison de l'effet cumulatif.

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);
    }
}
MegaTom
la source
0

QuantityPlayer

Tout ce que QuantityPlayer se soucie est la quantité de points qu'il mange, pas la valeur ou la couleur des points. Il sait que même si tous les points sont différents, ils doivent être traités de la même manière.

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

}

}
Benjamin Philippe
la source