KOTH: Jeder liebt Token

24

In diesem Spiel kämpfen zwei Spieler um die meisten Punkte, aber es gibt eine Wendung! Das Essen mehrerer Token in einer Reihe derselben Farbe bringt einen immer größeren Bonus, aber pass auf, oder dein Gegner wird deine Pläne durchkreuzen, indem er die Token isst, die du willst, bevor du kannst!

Regeln:

  • 1 gegen 1
  • n by n board (zufällige Größe zwischen 5x5 und 15x15)
  • Sie und Ihr Gegner werden in derselben zufälligen Zelle erscheinen
  • Auf dem gesamten Board werden in einigen Zellen nach dem Zufallsprinzip Zahlen im Bereich von 1 bis 3 generiert
  • 2 * -Token (die Breite des Bretts) werden generiert, es kann jedoch zu Überschreibungen kommen, sodass möglicherweise weniger zufällig vorhanden sind.
  • Jede Zahl ist eine von drei Farben: Rot, Grün oder Blau im hexadezimalen RGB-Format
  • In jeder Runde bewegt sich Spieler 1 und das Brett wird aktualisiert, dann bewegt sich Spieler 2 und das Brett wird aktualisiert. Auf diese Weise kann jeder Spieler anhand der Änderung des Board-Status effektiv erkennen, welche Bewegung der vorherige Spieler ausgeführt hat. Dies wird fortgesetzt, bis das Spiel endet, wie später beschrieben wird.
  • Sie haben 6 mögliche Aktionen für eine Runde: AUF, RECHTS, AB, LINKS, ESSEN und PASSEN
  • Die 4 Bewegungsbefehle sind selbsterklärend und Sie KÖNNEN an der Reihe sein. Wenn Sie einen unsinnigen Zug erwidern, gehen wir davon aus, dass Sie bestanden haben. Wenn Sie versuchen, sich von der Kante des Bretts zu entfernen, werden Sie sich nicht bewegen. Die Kanten werden nicht gewickelt.
  • EAT verbraucht die Nummer, mit der Sie sich gerade im selben Bereich befinden
  • Sie erhalten so viele Punkte wie Sie verbrauchen
  • Wenn Sie 2 Zahlen in einer Reihe der gleichen Farbe essen, erhalten Sie +1
  • Wenn Sie 3 Zahlen in einer Reihe der gleichen Farbe essen, erhalten Sie +2
  • Wenn Sie m Zahlen in einer Reihe der gleichen Farbe essen, erhalten Sie + (m-1)
  • Diese Boni werden kumulativ addiert. Wenn Sie also m Zahlen hintereinander erhalten, erhalten Sie einen Gesamtbonus von m * (m-1) / 2, sobald Sie eine andere Farbe essen.
  • Spielende Bedingungen:
    • Alle Nummern werden verbraucht
    • 4 * (die Breite des Brettes) Runden sind vergangen, ohne dass effektiv gegessen wurde (nur „ESSEN“ ohne Spielstein, bei dem Sie nicht zählen), was von beiden Spielern geschehen ist (jeder Spielstein ist in 2 * (der Breite) erreichbar). bewegt sich, so dass diese Grenze nur überschritten wird, wenn beide Spieler keinen einzigen Zielmarker im Sinn haben)
  • Ihre KI sollte weniger als eine Sekunde brauchen, um einen Zug zu machen, sonst wird PASS als Ihre Wahl angenommen.

Das Turnier ist ein Round-Robin-Turnier mit einer großen Anzahl von Runden, z. B. 100 oder 1000. Ein zufälliges Spielbrett wird generiert und jedes bestellte Paar verschiedener Spieler wird auf diesem Brett gespielt. Nach Beendigung des Turniers werden die Spieler nach ihrer Gesamtpunktzahl eingestuft. Selbst wenn Sie Spieler 2 für ein Spiel sind, besteht Ihr Ziel darin, so viele Punkte wie möglich zu erzielen.

AI Submission: Die Sprache, die mein Controller unterstützt, ist Javascript. Mehrfachnennungen sind zulässig. Jeder sendet einen Konstruktor für ein Objekt wie dieses:

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

Die Eingabe player1ist ein Boolescher Wert, der angibt, ob Sie Spieler 1 sind oder nicht. Ihr Konstruktor muss die yourMoveFunktion haben, kann aber auch eine beliebige Anzahl zusätzlicher Funktionen oder Werte haben. Definieren Sie keine globalen Variablen, sondern fügen Sie sie einfach als Variablen in Ihr Objekt ein. Zu Beginn eines jeden Matches yourMovewird eine neue Version Ihres Objekts erstellt und in jedem Ihrer Runden mit der aktuellen Tafel als Eingabe darauf aufgerufen, und es sollte ein gültiger Zug zurückgegeben werden.

b, die Eingabe für yourMove, ist eine Kopie der aktuellen Karte. Hier sind die Konstruktoren mit Eingabebeispielen, die Sie jedoch nicht selbst aufrufen können:

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

Das Token-Array hat für alle leeren Quadrate "false" und Token [a] [b] ist das Token bei x = a, y = b, beginnend mit der oberen linken Ecke.

Controller: Hier ist ein Link zum Controller in GitHub. Es ist eine HTML-Datei, die Sie ausführen können, um zu sehen, wie das Spiel und das Round-Robin funktionieren. Sie enthält zwei AIs, eine zufällige, die sich in jeder Runde in eine zufällige Richtung bewegt, aber an ihrer Position Jetons frisst, und einen naiven Algorithmus, der dies ermöglicht geht für den nächsten Token, der die meisten Punkte gibt. Ich werde jede KI hinzufügen, wenn sie eingereicht wird.

Unten finden Sie einen Ausschnitt, mit dem Sie den Controller auf der Standard-AI ausführen können. Aktuelle AIs:

  • KindaRandomAI
  • NaiveAI
  • MirrorBot
  • HungryBot

Frikative Melone
quelle
12
Ja, ein KOTH! Es ist für immer seit dem letzten gewesen.
TheNumberOne
2
Einverstanden, ich liebe mich ein gutes KOTH und das scheint eine großartige Voraussetzung zu sein. Ich bin js gegenüber ein bisschen grün, wie kann man den Spielstatus zwischen den Zügen beibehalten, wenn wir die Ergebnisse nicht innerhalb des Spielerobjekts speichern können?
DoctorHeckle
Wird die Platinenbreite irgendwo in die Funktion übernommen?
TheNumberOne
@BentNeeHumor Ja, die Funktion, die den player1Booleschen Wert annimmt, ist der Konstruktor für Ihre KI, die eine yourMoveFunktion hat, die das aktuelle Board als Eingabe annimmt b.
Fricative Melone
1
@DylanSp Manchmal sind sie aufgrund von Kollusionsmöglichkeiten nicht zulässig. In diesem Fall hätte Kollusion jedoch nur minimale Vorteile, sodass ich mehrere Einreichungen zulasse.
Fricative Melone

Antworten:

4

HungryBot

Verwendet ein Punktesystem, um den Wert der Verfolgung jedes Tokens zu gewichten. Verwendet eine Vielzahl verschiedener Faktoren in seiner Überlegung und bewertet sie in jeder Runde neu, um sicherzustellen, dass die beste Strategie verfolgt wird.

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
quelle
Sind Sie ein Python-Programmierer?
CalculatorFeline
@CatsAreFluffy Nicht wirklich ...?
Mwr247
Ich dachte du wärst weil self:)
CalculatorFeline
Warum benutzen self? Ist nicht thisausreichend
Conor O'Brien
2

PFAD bot

Akronym steht für Pathfinding And Tree Heuristics Bot

EDIT: Ab sofort sind hier die Ranglisten für die AIs mit den Punkten

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

Link zum kompletten Controller auf Github

Beschreibung: Wie NaiveAI findet dieser Bot den nächsten Token, der ihm die meisten Punkte gibt. Es simuliert jedoch auch die Ergebnisse jeder seiner Bewegungen, bis zu sechsmal.

Begründung: Da NaiveAI bereits ziemlich gut ist, würde ich es besser machen. Ohne zuerst auf den Code zu schauen (großer Fehler).

Beats: Alle außer HungryBot
Niederlagen gegen: Keine außer HungryBot

Probleme:

  • Erhöhte Streifen können nicht simuliert werden
  • Hängt bei der Berechnung des besten Tokens
  • Kann teleportieren

Ich weiß immer noch nicht, warum es teleportiert wurde, aber ich habe es behoben. Altes Video hier: https://youtu.be/BIhSKycF9iA

Vollständiger Code:

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;
    }
}
Blau
quelle
SLaNTbot verlangsamt die Umdrehungsgeschwindigkeit und frisst 15% meiner CPU auf ... D: EDIT: Und auch nichts zu essen?
Mwr247
@ Mwr247 die Geschwindigkeit, ja, es modelliert ~ 2500 Möglichkeiten pro Tick. Aber was das Essen angeht, ich weiß nicht genau warum. Wie ich in der Frage gesagt habe, teleportiert es sich einfach (auch bekannt als bewegt es mehrere Felder in einer Runde) und sitzt da und tut nichts. Ich warne kurz vor der Rückkehr und es scheint, dass es jedes Mal die richtigen Anweisungen gibt.
Blau
Vielleicht das: "Ihre KI sollte weniger als eine Sekunde brauchen, um einen Zug zu machen, sonst wird PASS als Ihre Wahl angenommen." Ich habe den Controller nicht gelesen, aber wenn er länger als eine Sekunde dauert, wird PASS vorausgesetzt?
Mwr247
@ Mwr247 Ich werde das untersuchen, aber es scheint unwahrscheinlich, dass es <1 Sekunde (oder so, obwohl ich) auf meinem Computer gedauert hat. Trotzdem tut es nie weh zu schauen. Vielen Dank!
Blau
@ Mwr247 Nach ein paar weiteren Tests ist das nicht alles. Es trifft Entscheidungen fast so schnell (zumindest für mich) wie NaiveAi. Außerdem ist es wahrscheinlicher, dass Sie auf großen Karten teleportiert werden
Blue
1

NaiveAI

Beginnend mit r=0, Blick auf alle Token mit taxicab Entfernung rvon Ihrer Position entfernt. Wenn es welche gibt, wähle eine aus, die dir die höchste Punktzahl bringen würde, wenn du sie jetzt hast. Ansonsten um r1 erhöhen und erneut versuchen.

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";
    }
  }
}
Frikative Melone
quelle
1

KindaRandomAI

Führen Sie in jeder Runde die folgenden Schritte aus: Wenn sich an Ihrer Position ein Token befindet, klicken Sie auf "EAT". Andernfalls bewegen Sie sich in eine zufällige Richtung, dh wenn Sie sich am linken Rand befinden, sagen Sie nicht "LINKS".

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;
    }
}
Frikative Melone
quelle
-1 nicht ganz zufällig
CalculatorFeline
Das ist besser!.
CalculatorFeline
1

LazyBot

Isst nur etwas, wenn er darauf laicht. Dies hat keine Chance zu gewinnen, aber die Herausforderung hatte keine von diesen, also warum nicht.

lazyBot = function (player1) {
    this.yourMove = function(b) {
        return "EAT";
    }
}
Bálint
quelle
1
Jeder Koth hat einen EmoWolf ...
Blue
3
@Blue Es ist nicht 100% emo, es versucht zu essen.
Bálint
1

MirrorBot

Sollte "Kanonenfutter" genannt werden

Beschreibung: Bewegt das genaue Gegenteil von dem, was der andere Spieler getan hat

Begründung: Ich wollte mich wieder mit der Programmierung in JS vertraut machen. Dies sollte nicht gewinnen

Wird schlagen: Niemand

Verliert gegen: Alle

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;
    }
}
Blau
quelle
Es gibt einige Probleme mit Ihrem Code. Rechts und Links sind nicht gegensätzlich und Ihre Funktionsdefinition für yourMove ist keine gültige Syntax. Mein Code war zuvor ebenfalls fehlerhaft, daher habe ich beim Auffinden und Beheben des Problems in meinem Code auch Ihren Code korrigiert. Sie können den festen Code in meinem Skript ansehen.
Fricative Melone
@FricativeMelon Ich habe die kaputte Funktionsdefinition behoben. Ich muss der Behauptung widersprechen, dass Recht nicht entgegengesetzt ist.
Blau
0,0 ist die linke obere Ecke, also ist positives x rechts und negatives x links. Wenn die neue x-pos einen höheren Wert hat als die alte x-pos, hat sich der andere Spieler nach rechts bewegt. Sie sollten sich also nach links bewegen und umgekehrt. Außerdem sollten Sie var out = "EAT";anstelle von verwenden out = "EAT";, da die später eine globale Variable definiert. Die dritte und die vierte Zeile tun nichts und können auch entfernt werden. Sie opkönnen auch eine lokale Variable wie outanstelle einer Eigenschaft sein.
Fricative Melone
@FricativeMelon ah, ich verstehe, was du sagst. Ich habe den Code aktualisiert. Vielen Dank!
Blau
Ich habe Ihren neuen Code in das Skript eingefügt und er funktioniert jetzt. Aber RandomAI nicht schlagen :(
Fricative Melon
0

OneTarget

Findet das Token, das in kürzester Zeit die meisten Punkte bringt, und greift danach. Ranggleiche Farbmarker werden aufgrund des kumulativen Effekts etwas höher eingestuft.

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
quelle
0

QuantityPlayer

Alles, was QuantityPlayer interessiert, ist die Menge der Punkte, die er isst, nicht der Wert oder die Farbe der Punkte. Er weiß, dass obwohl alle Punkte unterschiedlich sind, sie gleich behandelt werden sollten.

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
quelle