KOTH: Herkes belirteçleri sever


24

Bu oyunda iki oyuncu belirteçleri en çok puan yemek için yarışıyor, ancak bir bükülme var! Aynı renkteki bir satırda birden fazla jeton yemek, sürekli büyüyen bir bonus verir, ancak dikkat edin veya rakibiniz yapmadan önce istediğiniz jetonları yiyerek planlarınızı engeller!

Kurallar:

  • 1'e karşı 1
  • n tarafından n kurulu (5x5 ve 15x15 arasında rastgele boyutu)
  • Siz ve rakibiniz aynı rastgele hücrede ortaya çıkacaksınız.
  • Tahta boyunca rastgele üretilen bazı hücrelerde 1-3 arasında değişen değerde sayılar olacaktır.
  • 2 * (kartın genişliği) belirteçleri üretilir, ancak geçersiz kılmalar olabilir, bu yüzden şans eseri daha az olabilir.
  • Her sayı 3 renkten biri olacaktır: kırmızı, Yeşil veya Mavi, altıgen RGB formatında
  • Her turda, oyuncu 1 hareket eder ve oyun tahtası güncellenir, ardından oyuncu 2 hareket eder ve oyun tahtası güncellenir. Böylece her oyuncu önceki durumdaki oyuncunun hangi durumdaki hareketini tahta durumundaki değişime bağlı olarak etkili bir şekilde söyleyebilir Bu daha sonra tarif edildiği gibi oyun sona erene kadar devam eder.
  • Bir dönüş için 6 olası eyleminiz vardır: YUKARI, SAĞ, AŞAĞI, SOL, YEMEK ve PASS
  • 4 hareket komutu açıklayıcıdır ve sıranızı geçebilirsiniz. Saçma sapan bir hamle yaparsanız, geçmek istediğinizi varsayacağız. Tahtanın kenarından uzaklaşmaya çalışırsanız, hareket etmeyeceksiniz. Kenarlar sarılmaz.
  • EAT, şu anda bulunduğunuz numarayı aynı alanda
  • Tükettiğiniz sayı kadar puan kazanırsınız
  • Aynı renkte bir satırda 2 sayı yerseniz, + 1 elde edersiniz.
  • Aynı renkteki bir sırada 3 sayı yerseniz, +2
  • Aynı numaraları bir satırda m numaraları yerseniz, + (m-1) olur
  • Bu bonuslar kümülatif olarak eklenir, bu nedenle arka arkaya m sayıları almak, farklı bir renk yediğiniz zaman toplam bonus olarak m * (m-1) / 2 olur.
  • Oyun sonu koşulları:
    • Tüm numaralar tüketilir
    • 4 * (kartın genişliği) dönüşler, herhangi bir oyuncu tarafından gerçekleşen (herhangi bir belirteç 2 * 'ye ulaşılabilir (genişliğe ulaşılabilir) gerçekleşen etkili bir yemek yemeyle (sadece “sayılmadığınız hiçbir simge ile“ EAT ”diyerek) söylenir. hareket ettiğinden, bu sınır yalnızca iki oyuncunun da tek bir hedef belirteci olmadığı durumlarda aşılır)
  • Harekete geçmek için AI'nızın bir saniyeden daha kısa sürmesi gerekir, aksi takdirde PASS tercihiniz olarak kabul edilir.

Turnuva 100 ya da 1000 gibi çok sayıda mermi olan yuvarlak bir robin olacak. Rastgele bir tahta oluşturulur ve her tahtada sıralanan her farklı oyuncu çifti oynanır. Turnuva tamamlandıktan sonra, insanları toplam puanlarına göre sıralayacağız. Yani bir oyunda 2. oyuncu olsanız bile, hedefiniz hala mümkün olduğunca fazla puan elde etmektir.

AI Submission: Kontrol cihazımın desteklediği dil Javascript. Birden fazla gönderiye izin verilir. Herkes böyle bir nesne için bir kurucu sunar:

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

Giriş player1, oyuncu 1 olup olmadığınızı söyleyen bir booleandır. Yapıcınız yourMoveişleve sahip olmalı , ancak herhangi bir sayıda ek işleve ya da değere sahip olabilir. Herhangi bir global değişkeni tanımlamayın, sadece bunları nesnenize değişken olarak koyun. Nesnenizin yeni bir sürümü, her bir eşleşmenin başında oluşturulacak ve yourMoveüzerinde, geçerli tahtanın girişlerinde, her dönüşünüzde çağrılacak ve geçerli bir hamle döndürmelidir.

b, giriş , geçerli tahtanın yourMovebir kopyası , işte bunlara kendiniz diyemeseniz de, giriş örnekleri ile yapıcılar:

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

Belirteç dizisi, boş kareler için "yanlış" değerine sahiptir ve belirteçler [a] [b], sol üst köşeden başlayarak numaralandırılmış x = a, y = b'deki işarettir.

Denetleyici: İşte GitHub'daki denetleyicinin bağlantısı. Oyunun ve round-robin'in nasıl çalıştığını görmek için çalıştırabileceğiniz bir html dosyasıdır ve iki AI ile birlikte gelir; rastgele bir yönde her seferinde rastgele bir yönde hareket eden fakat pozisyonunda belirteçleri yiyen rastgele bir tane En fazla puan veren en yakın belirteç için de geçerlidir. Her AI’ya gönderildiği şekliyle ekleyeceğim.

Aşağıda, denetleyiciyi varsayılan AI üzerinde çalıştırmanıza izin veren bir kod parçası. Mevcut AI'ler:

  • KindaRandomAI
  • NaiveAI
  • MirrorBot
  • HungryBot


12
Yay, bir KOTH! Sonuncusundan beri sonsuza dek sürdü.
TheNumberOne

2
Kabul, beni iyi bir KOTH seviyorum ve bu harika bir öncül gibi görünüyor. Js için biraz yeşilim, sonuçları oyuncu nesnesi içinde kaydedemezsek, hamleler arasında kalıcı bir oyun durumu nasıl olur?
DoctorHeckle

Kartın genişliği fonksiyonun herhangi bir yerine geçti mi?
TheNumberOne

@BentNeeHumor Evet, player1boolean işlevini alan işlev AI'nizin yapıcısıdır; bu yourMove, mevcut kartı olduğu gibi giriş olarak alan bir işleve sahip olacaktır b.
Sürtünme Kavun

1
@DylanSp Bazen çarpışma olasılıkları nedeniyle izin verilmez, ancak bu durumda, çarpışmanın minimum yararları olur, bu yüzden çoklu gönderime izin vereceğim.
Sürtünme Kavun,

Yanıtlar:


4

HungryBot

Her jetonu takip etme değerine ağırlık katmak için bir puan sistemi kullanır. Göz önünde bulundurulması gereken farklı faktörleri kullanır ve en iyi stratejiyi izlemesini sağlamak için her dönüşü yeniden değerlendirir.

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 programcısı mısınız?
CalculatorFeline

@CatsAreFluffy Gerçekten ...?
Mwr247

Sadece olduğunu düşündüm çünkü self:)
CalculatorFeline

Neden kullanılmalı self? thisYeterli değil mi?
Conor O'Brien,

2

PATH bot

Kısaltma Pathfinding ve Ağaç Sezgisel Bot anlamına gelir.

EDIT: Şu an itibariyle, işte AI'ların sıralaması, puanlarla birlikte

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

Github'daki kontrol ünitesine bağlantı

Açıklama: NaiveAI gibi, bu bot da en çok puan verecek en yakın jetonu bulur. Ancak, aynı zamanda her hareketinin sonuçlarını 6 kata kadar simüle eder.

Gerekçe: NaiveAI zaten oldukça iyi olduğu için daha iyisini yapabileceğimi düşündüm. Önce koda bakmadan (büyük hata).

Beats: HungryBot dışındaki herkes
Kaybediyor: HungryBot hariç Yok

sorunlar:

  • Artan çizgiyi simüle edemiyorum
  • En iyi belirteci hesaplanırken kilitleniyor
  • Işınlanabilir miyim

Neden teleporting olduğunu hala bilmiyorum ama düzelttim. Buradaki eski video: https://youtu.be/BIhSKycF9iA

Tam kod:

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 dönüş hızını düşürüyor ve CPU'mun% 15'ini yiyor ... D: EDIT: Ayrıca hiçbir şey yemiyor musun?
Mwr247

@ Mwr247 hız, evet, her kene ~ 2500 olasılık modelleri. Ama yemek için nedenini tam olarak bilmiyorum. Soruda söylediğim gibi, sadece teleports (aka 1 turda birden fazla boşluk taşır) ve orada hiçbir şey yapmadan oturuyor. İadeden hemen önce bir uyarı verdim ve her seferinde doğru talimatları veriyor gibiyim.
Mavi

Belki de şudur: "AI'nız bir hamle yapmak için bir saniyeden daha kısa sürmelidir, aksi halde PASS tercihiniz olarak kabul edilir." Kontrol cihazını okumamıştım, ancak bir saniye sürerse, PASS varsayıyor mu?
Mwr247

@ Mwr247 Buna göz atacağım, ancak makinemde <1 saniye (ya da öylesine olsa) alması pek mümkün görünmüyor. Yine de bakmak için asla acıyor. Teşekkür ederim!
Mavi

@ Mwr247 Biraz daha test ettikten sonra, bu o değil. Kararları neredeyse NaiveAi kadar hızlı (en azından benim için) alıyor. Ayrıca, büyük haritalarda ışınlanma deneyiminiz daha yüksektir
Blue

1

NaiveAI

İle başlayarak r=0, tüm belirteçleri rkonumunuzdan uzakta taksonik mesafeli olarak görün . Eğer varsa, şu anda alırsanız size en yüksek puanı verecek olanı seçin. Aksi takdirde, r1 artarak tekrar deneyin.

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

Her turda, aşağıdakileri yapın: Konumunuzda bir belirteç varsa, "EAT". Aksi takdirde, rastgele uygulanabilir bir yöne doğru hareket edin, yani sol kenardaysanız "SOL" demeyin.

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 tamamen rastgele değil
CalculatorFeline

Bu daha iyi!.
CalculatorFeline


1

MirrorBot

"Top yemi" olarak adlandırılmalıdır.

Açıklama: Diğer oyuncunun yaptıklarının tam aksini hareket ettirir.

Gerekçe: Yine JS'de rahat programlama yapmak istedim. Bu kazanmamalı

Yenecek: Kimse

Kaybedecek: Herkes

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

Kodunuzla ilgili birkaç sorun var. Sağ ve Sol tam tersi değildir ve YourMove için fonksiyon tanımınız geçerli bir sözdizimi değildir. Kodum daha önce de kırılmıştı, bu yüzden kodumdaki sorunu bulma ve çözme sürecinde kodunuzu da düzelttim. Senaryomdaki sabit koda bakabilirsiniz.
Sürtünme Kavun

@FricativeMelon Bozuk fonksiyon tanımını düzelttim. Hakkın ters olmadığı iddiasına karşı çıkmam gerekiyor.
Mavi,

0,0, sol üst köşedir, bu nedenle pozitif x sağ ve negatif x soldur. Eğer yeni x-pos eski x-pos'dan daha büyükse, diğer oyuncu sağa doğru hareket ettiğinden sola doğru hareket etmelisiniz. Ayrıca, daha sonra bir global değişken tanımladığından, var out = "EAT";bunun yerine kullanmalısınız out = "EAT";. Nitpicking biraz, üçüncü ve dördüncü satır hiçbir şey yapmaz ve aynı zamanda kaldırılabilir ve bir özellik yerine opgibi yerel bir değişken olabilir out.
Sürtünmeli Kavun

@FricativeMelon ah, söylediklerini anlıyorum. Kodu güncelledim. Teşekkür ederim!
Mavi,

Yeni kodunuzu komut dosyasına koydum ve şimdi çalışıyor. RandomAI olsa da yenmez :(
Sürtünme Kavun,

0

OneTarget

En az zamanda en çok puan verecek ve bunun için gidecek olan jetonu bulur. Kümülatif etki nedeniyle aynı renk belirteçlerini biraz daha yükseğe yerleştirir.

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

Bütün QuantityPlayer'ın umurunda olduğu şey, noktaların değeri veya rengi değil yediği noktaların miktarıdır. Bütün noktaların farklı olmasına rağmen, aynı şekilde muamele görmeleri gerektiğini biliyor.

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

}

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.