2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個性と多様性を持つ AIチェスマシーン 。「どうしてAIには多様な戦略がないのだろうか?」

Last updated at Posted at 2024-10-31

ショートストーリー 「どうしてAIには多様な戦略がないのだろうか?」

東京のプログラマー、健太はAIにチェスを教える新たな手法に取り組んでいた。AIによるプレイがどれも同じパターンを繰り返すことに不満を覚えていた彼は、ある日、考えを巡らせていた。

「どうしてAIには多様な戦略がないのだろうか?」健太は自問する。人間のチェスプレイヤーであれば、経験や価値観が違うためにプレイスタイルが異なる。ある者はポーンの重要性を高く評価し、慎重に盤を支配する。一方で、別の者は大胆にクイーンを犠牲にしてでも相手の隙を突こうとする。この「違い」が、チェスというゲームを奥深くしているのだ。

そこで健太が思いついたのは、駒の表現方法を変えるという大胆なアイデアだった。「もし各駒を、ただの記号ではなく、それぞれの特質を表すベクトルで表現したらどうだろう?」健太は考えた。駒に「重み」や「価値」を持たせることで、AIが自然と異なる戦略を生み出すのではないかと期待したのだ。

スクリーンショット 2024-11-01 051129.png

彼はプログラムに手を加え、各駒にランダムな8次元のベクトルを割り当てるようにした。これにより、盤上の計算は一変した。AIはそれぞれの駒に独自の意味を見出し、それに応じて動きを決めるようになった。チェス盤の上では、まるでAIが「性格」を持ち、それぞれ異なる視点から戦略を繰り出すように見える。

健太がコードを実行すると、彼のAIたちは多様なプレイを始めた。あるAIはナイトを犠牲にしてでも早々に攻め込む一方で、別のAIはポーンを大切にしつつ、じっくりと盤を支配しようとした。どのAIも微妙に異なる「価値観」を持ち、まるで人間のような個性を持ってプレイしている。

image.png

「これだ!」健太は胸を高鳴らせた。「AIがこの違いを理解し、様々な戦略を取ることで、チェスの魅力がさらに広がる。」健太の目には、ゲームを超えた新たなAIの未来が見えた気がした。それは、ただの最適な一手を探すAIではなく、個性と多様性を持つAI。彼は、次のゲームの展開を楽しみにしながら、さらに改良の手を進めていった。

image.png

修正したコードでは、各チェスの駒に対して8次元のランダムベクトルが割り当てられています。このランダムなベクトルにより、各コマの状態や特性が異なり、ゲームのプレイやトレーニングデータが多様化されます。

具体的には、以下の点が実現されます:

ランダムベクトルの生成: 各コマに対して8次元のランダムベクトルが生成され、駒を識別するためのユニークな表現として使用されます。

異なる展開のゲームプレイ: 各実行時に異なるベクトルが割り当てられるため、ゲームプレイの展開やAIの戦略が毎回異なります。これにより、AIが学習する際の多様性が増し、より効果的なトレーニングが期待できます。

トレーニングデータの多様化: ランダムなベクトルによって生成されたトレーニングデータは、毎回異なるため、AIがより広範な局面を学ぶことができます。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chess AI Training Simulation</title>
    <style>
        /* チェス盤のデザイン設定 */
        table { border-collapse: collapse; margin: 20px auto; }
        td { width: 50px; height: 50px; text-align: center; font-size: 24px; }
        .black { background-color: #769656; }
        .white { background-color: #eeeed2; }
    </style>
</head>
<body>

    <h2 style="text-align: center;">Chess AI Training Simulation</h2>
    <!-- チェス盤を表示するためのテーブル -->
    <table id="chessBoard"></table>
    <!-- トレーニング開始ボタン -->
    <button onclick="startTraining()">AIがゲームを行う(トレーニング)</button>
    <!-- AI同士でのプレイを開始するボタン -->
    <button onclick="startAIGame()" disabled id="playButton">AI同士のゲームを開始</button>

    <!-- chess.jsライブラリの読み込み -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.2/chess.min.js"></script>
    
    <script>
        // チェスの駒を文字で表現するオブジェクト
        const pieces = {
            'r': '', 'n': '', 'b': '', 'q': '', 'k': '', 'p': '',
            'R': '', 'N': '', 'B': '', 'Q': '', 'K': '', 'P': ''
        };
        const chess = new Chess(); // チェスゲームを初期化
        let trainingData = []; // トレーニングデータを格納する配列
        let isTrainingComplete = false; // トレーニングが完了したかどうかのフラグ

        // チェス盤をHTMLテーブルに描画する関数
        function createChessBoard() {
            const chessBoard = document.getElementById('chessBoard');
            chessBoard.innerHTML = ''; // 既存の盤面をクリア
            const boardFen = chess.fen().split(' ')[0];
            const rows = boardFen.split('/');
            for (let i = 0; i < rows.length; i++) {
                const row = document.createElement('tr');
                let col = 0;
                for (const char of rows[i]) {
                    const cell = document.createElement('td');
                    cell.className = (i + col) % 2 === 0 ? 'white' : 'black';
                    if (isNaN(char)) {
                        // 駒が存在する場合、対応する文字を表示
                        cell.textContent = pieces[char] || '';
                        col += 1;
                    } else {
                        // 空白のマスの場合、数字分だけカウントを進める
                        col += parseInt(char);
                    }
                    row.appendChild(cell);
                }
                chessBoard.appendChild(row);
            }
        }

        // ランダムなベクトルを生成する関数
        function generateRandomVector() {
            return Array.from({ length: 8 }, () => Math.random());
        }

        // ランダムな合法手を指す関数(トレーニングデータとして使用)
        function playRandomMove() {
            const moves = chess.moves(); // 現在の局面での合法手を取得
            if (moves.length > 0) {
                // ランダムに次の手を選ぶ
                const randomMove = moves[Math.floor(Math.random() * moves.length)];
                // 現在の盤面を行列形式に変換してトレーニングデータとして保存
                const boardMatrix = boardToMatrix(chess.fen());
                const moveVector = generateRandomVector(); // 駒ごとにランダムベクトルを生成
                trainingData.push({ board: boardMatrix, move: randomMove, vector: moveVector });
                // 選んだ手を実行
                chess.move(randomMove);
                createChessBoard(); // 新しい局面を描画
            }
        }

        // FEN表現から盤面を数値行列に変換する関数
        function boardToMatrix(fen) {
            const pieceMap = { 'r': -5, 'n': -3, 'b': -3, 'q': -9, 'k': -10, 'p': -1, 'R': 5, 'N': 3, 'B': 3, 'Q': 9, 'K': 10, 'P': 1 };
            const board = Array(8).fill().map(() => Array(8).fill(0));
            const rows = fen.split(' ')[0].split('/');
            rows.forEach((row, rowIndex) => {
                let colIndex = 0;
                for (const char of row) {
                    if (isNaN(char)) {
                        board[rowIndex][colIndex] = pieceMap[char] || 0; // 駒の種類に対応する値を格納
                        colIndex++;
                    } else {
                        colIndex += parseInt(char); // 空白マスの数だけ進める
                    }
                }
            });
            return board;
        }

        // トレーニングを開始する関数
        function startTraining() {
            trainingData = []; // トレーニングデータを初期化
            for (let i = 0; i < 10; i++) { // 10ゲームのシミュレーション
                chess.reset();
                while (!chess.game_over()) {
                    playRandomMove();
                }
            }
            console.log("トレーニングデータ:", trainingData);
            alert("10ゲームのトレーニングデータ収集完了");
            isTrainingComplete = true; // トレーニングが完了したことを示す
            document.getElementById("playButton").disabled = false; // ゲーム開始ボタンを有効化
        }

        // 現在の盤面から次の手を予測する関数
        function predictMove(currentBoard) {
            let bestMove = null;
            let minDifference = Infinity;

            // トレーニングデータを元に、現在の局面に最も近い手を見つける
            for (const data of trainingData) {
                let difference = 0;
                for (let i = 0; i < 8; i++) {
                    for (let j = 0; j < 8; j++) {
                        difference += Math.abs(currentBoard[i][j] - data.board[i][j]);
                    }
                }
                // 最小差分が見つかった場合、その手を最良手とする
                if (difference < minDifference) {
                    minDifference = difference;
                    bestMove = data.move;
                }
            }
            return bestMove;
        }

        // AIが次の手を指す関数
        function playAIMove() {
            const currentBoard = boardToMatrix(chess.fen());
            const predictedMove = predictMove(currentBoard);
            if (predictedMove) {
                chess.move(predictedMove); // 予測された最良手を指す
                createChessBoard(); // 新しい局面を描画
            } else {
                alert("合法手が見つかりません");
            }
        }

        // トレーニングが完了した後にAI同士でゲームをプレイする関数
        function startAIGame() {
            if (!isTrainingComplete) {
                alert("トレーニングが完了していません。");
                return;
            }
            chess.reset(); // 盤面をリセット
            createChessBoard(); // 初期盤面を表示
            // AIが自動で手を指す間隔を設定
            const aiGameInterval = setInterval(() => {
                if (chess.game_over()) {
                    clearInterval(aiGameInterval); // ゲーム終了でインターバルをクリア
                    alert("AI同士のゲームが終了しました。");
                } else {
                    playAIMove(); // AIが次の手を指す
                }
            }, 500); // 各手の間隔を0.5秒に設定
        }

        createChessBoard(); // 初期盤面を表示
    </script>

</body>
</html>

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?