KOTH: ทุกคนชื่นชอบโทเค็น


24

ในเกมนี้ผู้เล่นสองคนแข่งขันกันเพื่อกินคะแนนสูงสุดของโทเค็น แต่มีการบิด! การกินโทเค็นหลายชุดในแถวที่มีสีเดียวกันจะให้โบนัสที่เพิ่มขึ้นเรื่อย ๆ แต่ระวังมิฉะนั้นคู่ต่อสู้ของคุณจะขัดขวางแผนการของคุณโดยการกินโทเค็นที่คุณต้องการก่อนที่คุณจะทำได้!

กฎ:

  • 1 กับ 1
  • n โดย n board (ขนาดสุ่มระหว่าง 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 * (ความกว้างของบอร์ด) รอบได้ผ่านไปโดยไม่มีการกินที่มีประสิทธิภาพ (เพียงแค่พูดว่า "กิน" โดยไม่มีโทเค็นที่คุณไม่นับ) เกิดขึ้นโดยผู้เล่นทั้งสอง (โทเค็นใด ๆ สามารถเข้าถึงได้ใน 2 * (ความกว้าง) ย้ายดังนั้นขอบเขตนี้จะถูกค้นถ้าผู้เล่นทั้งสองไม่มีโทเค็นเป้าหมายเดียว)
  • AI ของคุณควรใช้เวลาน้อยกว่าหนึ่งวินาทีในการย้ายมิฉะนั้น PASS จะถือว่าเป็นตัวเลือกของคุณ

ทัวร์นาเมนต์จะเป็นรอบโรบินที่มีจำนวนรอบมากกล่าวคือ 100 หรือ 1,000 กระดานสุ่มจะถูกสร้างขึ้นและผู้เล่นแต่ละคู่ที่สั่งซื้อต่างกันจะถูกเรียกใช้บนกระดานนั้น หลังจากการแข่งขันเสร็จสิ้นเราจะจัดอันดับผู้คนด้วยคะแนนรวมของพวกเขา ดังนั้นแม้ว่าคุณจะเป็นผู้เล่น 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]]
}

อาเรย์โทเค็นมี "เท็จ" สำหรับช่องว่างใด ๆ และโทเค็น [a] [b] เป็นโทเค็นที่ x = a, y = b โดยมีหมายเลขเริ่มต้นจากมุมซ้ายบน

ตัวควบคุม: นี่คือลิงค์ไปยังตัวควบคุมใน GitHub มันเป็นไฟล์ html ที่คุณสามารถเรียกใช้เพื่อดูว่าเกมและ round-robin ทำงานอย่างไรและมันมาพร้อมกับ AIs สองตัวซึ่งเป็นสุ่มที่เคลื่อนที่ไปในทิศทางที่สุ่มแต่ละรอบ แต่กินโทเค็นที่ตำแหน่งและอัลกอริทึมไร้เดียงสาที่ ไปสำหรับโทเค็นที่ใกล้ที่สุดซึ่งให้คะแนนมากที่สุด ฉันจะเพิ่ม AI แต่ละอันตามที่ส่งมา

ด้านล่างนี้เป็นตัวอย่างข้อมูลที่อนุญาตให้คุณเรียกใช้คอนโทรลเลอร์บน AI ที่เป็นค่าเริ่มต้น AIs ปัจจุบัน:

  • KindaRandomAI
  • NaiveAI
  • MirrorBot
  • HungryBot


12
Yay, KOTH! มันได้รับตลอดไปตั้งแต่สุดท้าย
TheNumberOne

2
ตกลงฉันรัก KOTH ที่ดีและดูเหมือนว่าจะเป็นหลักฐานที่ดี ฉันเป็นสีเขียวเล็กน้อยสำหรับ js, สถานะเกมหนึ่งยังคงอยู่ระหว่างการเคลื่อนไหวอย่างไรถ้าเราไม่สามารถบันทึกผลลัพธ์ภายในวัตถุผู้เล่น
DoctorHeckle

ความกว้างของบอร์ดผ่านไปทุกที่ในฟังก์ชันหรือไม่
TheNumberOne

@BentNeeHumor ใช่ฟังก์ชั่นที่ใช้ในplayer1แบบบูลคือสร้างสำหรับ AI ของคุณซึ่งจะมีyourMoveฟังก์ชั่นที่ใช้ปัจจุบันคณะกรรมการเป็น input bเป็น
Fricative Melon

1
@DylanSp บางครั้งพวกเขาไม่ได้รับอนุญาตเนื่องจากความเป็นไปได้ในการสมรู้ร่วมคิด แต่ในกรณีนี้การสมรู้ร่วมคิดจะมีประโยชน์น้อยที่สุดดังนั้นฉันจะอนุญาตการส่งหลายครั้ง
Melon Fricative

คำตอบ:


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เพียงพอหรือ
Conor O'Brien

2

เส้นทาง ธ ปท

ตัวย่อย่อมาจาก Pathfinding และแผนภูมิการแก้ปัญหาต้นไม้

แก้ไข:ณ ตอนนี้ที่นี่มีการจัดอันดับสำหรับ AIs พร้อมกับคะแนน

  1. HungryBot (6422)
  2. เส้นทางบ็อต (4591)
  3. NaiveAI (3811)
  4. KindaRandomAI (618)
  5. MirrorBot (193)
  6. LazyBot (25)

เชื่อมโยงไปยังคอนโทรลเลอร์ที่สมบูรณ์บน GitHub

คำอธิบาย: เช่นเดียวกับ NaiveAI บ็อตนี้จะค้นหาโทเค็นที่ใกล้ที่สุดซึ่งจะให้คะแนนมากที่สุด อย่างไรก็ตามมันยังจำลองผลลัพธ์ของการเคลื่อนไหวแต่ละครั้งได้มากถึง 6 เท่า

เหตุผล: เนื่องจาก NaiveAI ค่อนข้างดีอยู่แล้ว แต่ฉันก็อยากทำให้ดีขึ้น โดยไม่ได้ดูรหัสก่อน (ความผิดพลาดครั้งใหญ่)

Beats: All ยกเว้น HungryBot
Looses เป็น: None ยกเว้น 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 กำลังชะลอความเร็วรอบตัวลงและกิน CPU ของฉัน 15% ... D: EDIT: และยังไม่กินอะไรเลยเหรอ?
Mwr247

@ Mwr247 ความเร็วใช่มันมีความเป็นไปได้ ~ 2500 ทุกเห็บ แต่สำหรับสิ่งที่กินฉันไม่รู้ว่าทำไม อย่างที่ฉันพูดในคำถามมันแค่เคลื่อนย้ายมวล (อาคาเคลื่อนที่หลายช่องว่างในรอบเดียว) และนั่งอยู่ตรงนั้นโดยไม่ทำอะไรเลย ฉันใส่การแจ้งเตือนก่อนการกลับมาและดูเหมือนว่าจะให้คำแนะนำที่ถูกต้องทุกครั้ง
บลู

อาจเป็นเช่นนี้: "AI ของคุณควรใช้เวลาน้อยกว่าหนึ่งวินาทีในการเคลื่อนย้ายมิฉะนั้น PASS จะถือว่าเป็นตัวเลือกของคุณ" ฉันไม่ได้อ่านคอนโทรลเลอร์ แต่ถ้าผ่านไปหนึ่งวินาทีมันจะถือว่า PASS หรือไม่?
Mwr247

@ Mwr247 ฉันจะตรวจสอบสิ่งนั้น แต่ดูเหมือนว่าไม่น่าเป็นไปได้ที่จะใช้เวลา <1 วินาที (หรืออย่างนั้นฉันคิดว่า) บนเครื่องของฉัน ยังไม่เคยเจ็บที่จะมอง ขอขอบคุณ!
บลู

@ Mwr247 หลังจากการทดสอบเพิ่มเติมบางอย่างที่ไม่ได้ มันกำลังตัดสินใจอย่างรวดเร็วเกือบเท่า (อย่างน้อยสำหรับฉัน) เหมือนกับ NaiveAi นอกจากนี้คุณมีโอกาสที่จะได้พบกับการส่งผ่านทางไกลบนแผนที่ขนาดใหญ่
สีน้ำเงิน

1

NaiveAI

เริ่มต้นด้วยr=0ดูโทเค็นทั้งหมดที่มีระยะrห่างจากรถแท็กซี่ของคุณ ถ้ามีให้เลือกหนึ่งตัวที่จะให้คะแนนสูงสุดถ้าคุณได้ตอนนี้ มิฉะนั้นเพิ่มขึ้นr1 และลองอีกครั้ง

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
ทุก ๆ koth มี EmoWolf ...
บลู

3
@Blue ไม่ใช่อีโม 100% แต่ก็พยายามกิน
Bálint


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

รหัสของคุณมีปัญหาเล็กน้อย ขวาและซ้ายไม่ตรงข้ามและนิยามฟังก์ชันของคุณสำหรับ yourMove ไม่ใช่ไวยากรณ์ที่ถูกต้อง รหัสของฉันเสียก่อนเช่นกันดังนั้นในกระบวนการค้นหาและแก้ไขปัญหาในรหัสของฉันฉันได้แก้ไขรหัสของคุณด้วย คุณสามารถดูรหัสคงที่ในสคริปต์ของฉัน
Melon Fricative

@FricativeMelon ฉันแก้ไขนิยามฟังก์ชั่นที่ใช้งานไม่ได้ ฉันต้องตอบโต้การอ้างสิทธิ์ว่าไม่ตรงข้าม
บลู

0,0 คือมุมบนซ้ายดังนั้นบวก x ถูกต้องและลบ x ทิ้ง หาก x-pos ใหม่มีมูลค่ามากกว่า x-pos เก่าผู้เล่นคนอื่นก็ย้ายไปทางขวาดังนั้นคุณควรเลื่อนไปทางซ้ายและในทางกลับกัน นอกจากนี้คุณควรใช้var out = "EAT";แทนout = "EAT";เนื่องจากภายหลังกำหนดตัวแปรส่วนกลาง Nitpicking นิดหน่อยบรรทัดที่สามและสี่จะไม่ทำอะไรเลยและสามารถลบออกได้เช่นกันและopอาจเป็นตัวแปรท้องถิ่นเช่นoutแทนที่จะเป็นคุณสมบัติ
Melon Fricative

@FricativeMelon อ่าฉันได้รับสิ่งที่คุณพูด ฉันได้อัปเดตรหัสแล้ว ขอขอบคุณ!
บลู

ฉันใส่รหัสใหม่ของคุณลงในสคริปต์และมันก็ใช้ได้แล้ว ไม่ชนะ RandomAI แม้ว่า :(
Melon Fricative

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

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

}

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.