কোথ: গোমোকু (একের পর এক পাঁচ)


10

পর পর গোমোকু বা পাঁচটি একটি বোর্ড গেম যা দুটি খেলোয়াড় একটি গ্রিডে কালো এবং সাদা পাথর দিয়ে খেলেছে । যে কেউ এক সারিতে 5 টি পাথর রাখতে সক্ষম (অনুভূমিক, উল্লম্ব বা তির্যক) গেমটি জিতবে।15×155

বিধি

এই কোথিতে আমরা অদলবদল বিধি খেলব, যার অর্থ একটি গেমটি দুটি ধাপ নিয়ে গঠিত: প্রাথমিক পর্যায়ে দুই খেলোয়াড় নির্ধারণ করে যে কে প্রথমে যায় / কে কালো খেলেন, তার পরে তারা খেলোয়াড়ের সাথে শুরু করে প্রতিটি রাউন্ডে একটি করে পাথর রাখবেন কে কালো বেছে নিয়েছে।

প্রাথমিক পর্যায়ে

খেলোয়াড়দের A & B হতে দিন এবং A গেমটি খুলবে:

  • একটি বোর্ডে দুই কালো এবং এক সাদা পাথর স্থাপন
  • বি নিম্নলিখিত তিনটি পদক্ষেপের মধ্যে একটি চয়ন করতে পারেন:
    • প্লেয়ার বি কালো খেলতে সিদ্ধান্ত নিয়েছে: প্রাথমিক পর্ব শেষ
    • প্লেয়ার বি একটি সাদা পাথর স্থাপনের সিদ্ধান্ত নিয়েছে এবং সাদা খেলবে: প্রাথমিক পর্ব শেষ
    • প্লেয়ার বি একটি কালো এবং একটি সাদা পাথর খেলার সিদ্ধান্ত নিয়েছে: রঙটি বেছে নেবে

গেম পর্ব

প্রতিটি খেলোয়াড় তাদের রঙের একটি পাথর বোর্ডে রাখে, যে প্লেয়ারটি কালো খেলেন তার সাথে শুরু করে, খেলতে যাওয়ার মতো আরও মুক্ত জায়গা না পাওয়া (এটি ক্ষেত্রে এটি একটি টাই) বা একজন খেলোয়াড় একটিতে পাথর খেলতে সক্ষম হন সারি (যে ক্ষেত্রে খেলোয়াড় জিতেছে)।5

একটি সারি অর্থ হয় অনুভূমিক, উল্লম্ব বা তির্যক। একটি জয় একটি জয় - প্লেয়ার একাধিক সারি স্কোর করতে সক্ষম হয়েছিল তা বিবেচ্য নয়।

কোথ গেম বিধি

  • প্রতিটি খেলোয়াড় দু'জন একে অপরের খেলোয়াড়ের বিরুদ্ধে খেলে:
    • প্রথমে কে প্রথমে যায় তা এলোমেলোভাবে সিদ্ধান্ত নেওয়া হবে
    • পরের খেলায় যে খেলোয়াড় সর্বশেষে খেলতে পারা যায় সে প্রথমে যায়
  • একটি জয় মূল্য 2 পয়েন্ট, একটি টাই 1 এবং একটি হার 0
  • লক্ষ্যটি যতটা সম্ভব পয়েন্ট করা

আপনার বট

এই চ্যালেঞ্জটিকে যতটা সম্ভব ইনপুট / আউটপুট যতটা ভাষার পক্ষে অ্যাক্সেসযোগ্য করে তুলতে হবে স্টিডিন / স্টাডআউট (লাইন-ভিত্তিক) এর মাধ্যমে। বিচারক প্রোগ্রামটি আপনার বট এর স্টিডিনে একটি লাইন মুদ্রণ করে আপনার প্রোগ্রামটি প্রম্পট করবে এবং আপনার বট স্টাডআউটে একটি লাইন মুদ্রণ করবে ।

একবার আপনি কোনও EXITবার্তা পেলে বিচারক প্রক্রিয়াটি মেরে ফেলার আগে আপনাকে ফাইলগুলিতে লেখা শেষ করতে অর্ধেক সেকেন্ড দেওয়া হবে।

লক্ষ্যহীনতা

টুর্নামেন্টগুলি যাচাইযোগ্য করার জন্য বিচারক বীজযুক্ত র্যান্ডমাইজেশন ব্যবহার করেন এবং একই কারণে আপনার বটও অবশ্যই করতে হবে। বটকে কমান্ড-লাইন আর্গুমেন্টের মাধ্যমে একটি বীজ দেওয়া হবে যা এটি ব্যবহার করা উচিত, দয়া করে পরবর্তী বিভাগটি পড়ুন।

যুক্তি

বট দুটি কমান্ড-লাইন আর্গুমেন্ট গ্রহণ করে:

  1. প্রতিপক্ষের নাম
  2. এলোমেলো জন্য বীজ

ব্যবহারকারী অবস্থা

কারণ প্রতিটি প্রোগ্রামের জন্য আপনার প্রোগ্রামটি সর্বদা নতুনভাবে শুরু করা হবে কারণ আপনি যে তথ্য রাখতে চান তা বজায় রাখতে আপনার ফাইলগুলি ব্যবহার করতে হবে। আপনাকে আপনার বর্তমান ডিরেক্টরিতে কোনও ফাইল পড়তে / লিখতে বা সাব-ফোল্ডারগুলি তৈরি / সরানোর অনুমতি দেওয়া হয়। আপনাকে কোনও পিতামাতার ডিরেক্টরিতে কোনও ফাইল অ্যাক্সেস করার অনুমতি নেই!

ইনপুট / আউটপুট ফর্ম্যাট

BOARD((X,Y),COLOR)XY[0,15)COLOR"B""W"

SPXY(X,Y)[0,15)|

প্রাথমিক পর্যায়ে তিনটি বিভিন্ন ধরণের বার্তা রয়েছে:

Prompt (judge) -> Answer (bot)
"A" SP "[]"  -> XY XY XY
"B" SP BOARD -> "B" | "W" SP XY | XY XY
"C" SP BOARD -> "B" | "W"
  • প্রথম বার্তায় তিনটি টিপল জিজ্ঞাসা করা হয়েছে, প্রথম দুটি কালো পাথরের অবস্থান এবং তৃতীয়টি সাদাটির অবস্থান করবে।
  • দ্বিতীয় বার্তাটি এর জন্য জিজ্ঞাসা করে:
    • "B" -> কালো বাছাই করুন
    • "W" SP XY -> সাদা চয়ন করুন এবং একটি সাদা পাথর স্থাপন করুন XY
    • XY XY -> দুটি পাথর রাখুন (প্রথমটি একটি কালো এবং দ্বিতীয়টি সাদা)
  • শেষটি কেবল আপনি কোন রঙ খেলতে চান তা জিজ্ঞাসা করে

এর পরে নিয়মিত খেলা শুরু হবে এবং বার্তাগুলি আরও সহজ হয়ে উঠবে

N BOARD -> XY

N0XY


একটি অতিরিক্ত বার্তা রয়েছে যা উত্তর আশা করে না

"EXIT" SP NAME | "EXIT TIE"

NAMEযে বট জিতেছে তার নাম কোথায় ? দ্বিতীয়টি বার্তা প্রেরণ করা হবে যদি খেলাটি কেউ না জেতে এবং পাথর স্থাপনের জন্য আরও মুক্ত জায়গা না দেয় (এটি বোঝায় যে আপনার বটের নাম দেওয়া যায় না TIE)।

বিন্যাস করা

যেহেতু বট থেকে প্রাপ্ত বার্তাগুলি কোনও ফাঁকা ছাড়াই ডিকোড করা যায়, তাই সমস্ত স্থান উপেক্ষা করা হবে (যেমন। (0 , 0) (0,12)একইরূপে বিবেচিত হবে (0,0)(0,12))। বিচারকের বার্তাগুলিতে কেবল আলাদা বিভাগ (যেমন উপরে উল্লিখিত হিসাবে SP) পৃথক করার জন্য একটি স্থান থাকে যা আপনাকে ফাঁকের ফাঁকে রেখাটি বিভক্ত করতে দেয়।

যে কোনও অবৈধ প্রতিক্রিয়ার ফলে সেই রাউন্ডের ক্ষতি হবে (আপনি এখনও একটি EXITবার্তা পাবেন ), বিধিগুলি দেখুন।

উদাহরণ

এখানে প্রকৃত বার্তাগুলির কয়েকটি উদাহরণ রয়েছে:

A []
B [((0,0),"B"),((0,1),"W"),((14,14),"B")]
1 [((0,0),"B"),((0,1),"W"),((1,0),"B"),((1,1),"W"),((14,14),"B")]

বিচারক

আপনি বিচারক প্রোগ্রাম জানতে পারেন এখানে এটি সহজভাবে একটি নতুন ফোল্ডার তৈরি করতে একটি বট জুড়তে: bots, ফোল্ডার সেখানে আপনার ফাইল স্থাপন এবং একটি ফাইল যোগ metaধারণকারী নাম , কমান্ড , আর্গুমেন্ট এবং একটি পতাকা 0/1 (অক্ষম / সক্ষম করুন দ্বারা stderr প্রতিটি) একটি পৃথক লাইনে

একটি টুর্নামেন্ট চালাতে কেবল রান করুন ./gomokuএবং একটি একক বট রান ডিবাগ করুন ./gomoku -d BOT

দ্রষ্টব্য: গিথুব সংগ্রহস্থলে বিচারককে কীভাবে সেটআপ এবং ব্যবহার করতে হয় সে সম্পর্কে আপনি আরও তথ্য পেতে পারেন। এছাড়াও তিনটি উদাহরণ বট রয়েছে ( হাস্কেল , পাইথন এবং জাভাস্ক্রিপ্ট )।

বিধি

  • প্রতিটি বট পরিবর্তনের উপর * টুর্নামেন্টটি আবার চালু হবে এবং সর্বাধিক পয়েন্ট প্লেয়ারের খেলোয়াড় (টাই-ব্রেকার প্রথম জমা দেওয়া)
  • যতক্ষণ না তারা একটি সাধারণ কৌশল না খেলে আপনি একাধিক বট জমা দিতে পারেন
  • আপনি আপনার ডিরেক্টরি বাইরে ফাইল স্পর্শ করার অনুমতি নেই (যেমন। অন্যান্য প্লেয়ার ফাইল ম্যানিপুলেট)
  • যদি আপনার বট ক্র্যাশ হয়ে যায় বা একটি অবৈধ প্রতিক্রিয়া প্রেরণ করে, বর্তমান গেমটি বন্ধ হয়ে যায় এবং আপনি এই রাউন্ডটি হারাবেন
  • যদিও বিচারক (বর্তমানে) প্রতি রাউন্ডের সময়সীমা প্রয়োগ করে না, আপনাকে সময় কম রাখার পরামর্শ দেওয়া হয় কারণ এটি সমস্ত দাখিল পরীক্ষা করার পক্ষে অনিবার্য হয়ে উঠতে পারে **
  • বিচারক প্রোগ্রামে বাগ আপত্তিজনক লুফোল হিসাবে গণনা করা হয়

* আপনার বটকে সরাসরি botsডিরেক্টরিতে জমা দেওয়ার জন্য গিথুবকে ব্যবহার করতে উত্সাহিত করা হয় (এবং সম্ভাব্যভাবে সংশোধন করতে পারেন util.sh)!

** এটি যদি সমস্যা হয়ে যায় তবে আপনাকে অবহিত করা হবে, আমি 500 মিমির নীচে কিছু বলতে চাই (এটি অনেক বেশি!) আপাতত ঠিক করা উচিত।

চ্যাট

আপনার যদি প্রশ্ন থাকে বা এই কোথার বিষয়ে কথা বলতে চান তবে চ্যাটে যোগ দিতে নির্দ্বিধায় !



আপনার উদাহরণগুলিতে শূন্যস্থান থাকা একটি মেটা স্পেস অক্ষর আমার মনকে উড়িয়ে দিচ্ছে। আরও কিছু উদাহরণ সুন্দর হবে।
ভেসকাঃ

@ ভেসকাঃ তিনটি উদাহরণ বট সংযুক্ত রয়েছে, আমি বার্তাগুলির জন্য কয়েকটি উদাহরণ যুক্ত করব।
ბიმო

@ ভেসকাহ: কয়েকটি উদাহরণ যুক্ত করা হয়েছে। BTW। তারা কোন ফর্ম্যাটে থাকবে তা দেখার জন্য এবং একটি বৈধ প্রতিক্রিয়া কী তা পরীক্ষা করতে আপনি উদাহরণ বটকে ডিবাগ করার চেষ্টা করতে পারেন।
ბიმო

আপনি ধাক্কা দেওয়ার অনুমতি দেন নি তাই আমি আমার বটকে
গিটে ঠেলাতে

উত্তর:


3

KaitoBot

এটি মিনিম্যাক্স নীতিগুলির একটি খুব অশোধিত বাস্তবায়ন ব্যবহার করে। অনুসন্ধানের গভীরতাও খুব কম, কারণ অন্যথায় এটি দীর্ঘ সময় নেয়।

পরে উন্নতি করতে পারে সম্পাদনা।

এটি সম্ভব হলে ব্ল্যাককে খেলানোর চেষ্টাও করে, কারণ উইকিপিডিয়া বলে মনে হচ্ছে যে কালোর একটি সুবিধা আছে।

আমি নিজেও গোমোকু খেলিনি, তাই আরও ভাল ধারণার অভাবে আমি এলোমেলোভাবে প্রথম তিনটি পাথর স্থাপন করেছি।

const readline = require('readline');
const readLine = readline.createInterface({ input: process.stdin });

var debug = true;
var myColor = '';
var opponentColor = '';
var board = [];
var seed = parseInt(process.argv[3]);

function random(min, max) {
    changeSeed();
    var x = Math.sin(seed) * 10000;
    var decimal = x - Math.floor(x);
    var chosen = Math.floor(min + (decimal * (max - min)));
    return chosen;
}

function changeSeed() {
    var x = Math.sin(seed++) * 10000;
    var decimal = x - Math.floor(x);
    seed = Math.floor(100 + (decimal * 9000000));
}

function KaitoBot(ln) {
    var ws = ln.split(' ');

    if (ws[0] === 'A') {
        // Let's play randomly, we don't care.
        var nums = [];
        nums[0] = [ random(0, 15), random(0, 15) ];
        nums[1] = [ random(0, 15), random(0, 15) ];
        nums[2] = [ random(0, 15), random(0, 15) ];
        while (nums[1][0] == nums[0][0] && nums[1][1] == nums[0][1])
        {
            nums[1] = [ random(0, 15), random(0, 15) ];
        }
        while ((nums[2][0] == nums[0][0] && nums[2][1] == nums[0][1]) || (nums[2][0] == nums[1][0] && nums[2][1] == nums[1][1]))
        {
            nums[2] = [ random(0, 15), random(0, 15) ];
        }
        console.log('(' + nums[0][0] + ',' + nums[0][1] + ') (' + nums[1][0] + ',' + nums[1][1] + ') (' + nums[2][0] + ',' + nums[2][1] + ')');
    }
    else if (ws[0] === 'B') {
        // we're second to play, let's just pick black
        myColor = 'B';
        opponentColor = 'W';
        console.log('B');
    }
    else if (ws[0] === 'C') {
        // the other player chose to play 2 stones more, we need to pick..
        // I would prefer playing Black
        myColor = 'B';
        opponentColor = 'W';
        console.log('B');
    }
    else if (ws[0] === 'EXIT') {
        process.exit();
    }
    else {
        board = [];
        var json = JSON.parse(ws[1].replace(/\(\(/g,'{"xy":[')
                .replace(/"\)/g,'"}')
                .replace(/\),/g,'],"colour":'));
        // loop over all XYs and make a board object I can use
        for (var x = 0; x < 15; x++) {
            var newRow = []
            for (var y = 0; y < 15; y++) {
                var contains = false;
                json.forEach(j => {
                    if (j.xy[0] == x && j.xy[1] == y) {
                        contains = true;
                        newRow[newRow.length] = j.colour;
                    }
                });
                if (!contains) {
                    newRow[newRow.length] = ' ';
                }
            }
            board[board.length] = newRow;
        }
        // If we never picked Black, I assume we're White
        if (myColor == '') {
            myColor = 'W';
            opponentColor = 'B';
        }
        var bestMoves = ChooseMove(board, myColor, opponentColor);
        var chosenMove = bestMoves[random(0, bestMoves.length)];
        console.log('(' + chosenMove.X + ',' + chosenMove.Y + ')');
    }
}

function IsSquareRelevant(board, x, y) {
    return (board[x][y] == ' ' && 
        ((x > 0 && board[x - 1][y] != ' ') 
        || (x < 14 && board[x + 1][y] != ' ') 
        || (y > 0 && board[x][y - 1] != ' ') 
        || (y < 14 && board[x][y + 1] != ' ')
        || (x > 0 && y > 0 && board[x - 1][y - 1] != ' ') 
        || (x < 14 && y < 14 && board[x + 1][y + 1] != ' ') 
        || (y > 0 && x < 14 && board[x + 1][y - 1] != ' ') 
        || (y < 14 && x > 0 && board[x - 1][y + 1] != ' ')));
}

function ChooseMove(board, colorMe, colorOpponent) {
    var possibleMoves = [];
    for (var x = 0; x < 15; x++) {
        for (var y = 0; y < 15; y++) {
            if (IsSquareRelevant(board, x, y)) {
                possibleMoves[possibleMoves.length] = {X:x, Y:y};
            }
        }
    }
    var bestValue = -9999;
    var bestMoves = [possibleMoves[0]];
    for (var k in possibleMoves) {
        var changedBoard = JSON.parse(JSON.stringify(board));
        changedBoard[possibleMoves[k].X][possibleMoves[k].Y] = colorMe;
        var value = analyseBoard(changedBoard, colorMe, colorOpponent, colorOpponent, 2);
        if (value > bestValue) {
            bestValue = value;
            bestMoves = [possibleMoves[k]];
        } else if (value == bestValue) {
            bestMoves[bestMoves.length] = possibleMoves[k];
        }
    }
    return bestMoves;
}

function analyseBoard(board, color, opponent, nextToPlay, depth) {
    var tBoard = board[0].map((x,i) => board.map(x => x[i]));
    var score = 0.0;
    for (var x = 0; x < board.length; x++) {
        var inARow = 0;
        var tInARow = 0;
        var opponentInARow = 0;
        var tOpponentInARow = 0;
        var inADiago1 = 0;
        var opponentInADiago1 = 0;
        var inADiago2 = 0;
        var opponentInADiago2 = 0;

        for (var y = 0; y < board.length; y++) {
            if (board[x][y] == color) {
                inARow++;
                score += Math.pow(2, inARow);
            } else {
                inARow = 0;
            }
            if (board[x][y] == opponent) {
                opponentInARow++;
                score -= Math.pow(2, opponentInARow);
            } else {
                opponentInARow = 0;
            }
            if (tBoard[x][y] == color) {
                tInARow++;
                score += Math.pow(2, tInARow);
            } else {
                tInARow = 0;
            }
            if (tBoard[x][y] == opponent) {
                tOpponentInARow++;
                score -= Math.pow(2, tOpponentInARow);
            } else {
                tOpponentInARow = 0;
            }

            var xy = (y + x) % 15;
            var xy2 = (x - y + 15) % 15;
            if (xy == 0) {
                inADiago1 = 0;
                opponentInADiago1 = 0;
            }
            if (xy2 == 0) {
                inADiago2 = 0;
                opponentInADiago2 = 0;
            }

            if (board[xy][y] == color) {
                inADiago1++;
                score += Math.pow(2, inADiago1);
            } else {
                inADiago1 = 0;
            }
            if (board[xy][y] == opponent) {
                opponentInADiago1++;
                score -= Math.pow(2, opponentInADiago1);
            } else {
                opponentInADiago1 = 0;
            }
            if (board[xy2][y] == color) {
                inADiago2++;
                score += Math.pow(2, inADiago2);
            } else {
                inADiago2 = 0;
            }
            if (board[xy2][y] == opponent) {
                opponentInADiago2++;
                score -= Math.pow(2, opponentInADiago2);
            } else {
                opponentInADiago2 = 0;
            }


            if (inARow == 5 || tInARow == 5) {
                return 999999999.0;
            } else if (opponentInARow == 5 || tOpponentInARow == 5) {
                return -99999999.0;
            }
            if (inADiago1 == 5 || inADiago2 == 5) {
                return 999999999.0;
            } else if (opponentInADiago1 == 5 || opponentInADiago2 == 5) {
                return -99999999.0;
            }
        }
    }

    if (depth > 0) {
        var bestMoveValue = 999999999;
        var nextNextToPlay = color;
        if (nextToPlay == color) {
            nextNextToPlay = opponent;
            bestMoveValue = -999999999;
        }
        for (var x = 0; x < board.length; x++) {
            for (var y = 0; y < board.length; y++) {
                if (IsSquareRelevant(board, x, y)) {
                    var changedBoard = JSON.parse(JSON.stringify(board));
                    changedBoard[x][y] = nextToPlay;
                    var NextMoveValue = (analyseBoard(changedBoard, color, opponent, nextNextToPlay, depth - 1) * 0.1);

                    if (nextToPlay == color) {
                        if (NextMoveValue > bestMoveValue) {
                            bestMoveValue = NextMoveValue;
                        }
                    } else {
                        if (NextMoveValue < bestMoveValue) {
                            bestMoveValue = NextMoveValue;
                        }
                    }
                }
            }
        }
        score += bestMoveValue * 0.1;
    }
    return score;
}

readLine.on('line', (ln) => {

    KaitoBot(ln);

});

সম্পাদনা: বীজ পরিবর্তনকে পরিবর্তনশীল করে তোলে কারণ অন্যথায় যখন বীজ 2 ^ 52 ছাড়িয়ে যায় জাভাস্ক্রিপ্ট সঠিকভাবে বর্ধন পরিচালনা করতে পারে না

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.