Untitled

 avatar
unknown
csharp
a year ago
8.5 kB
14
Indexable
using UnityEngine;
using System.Linq;
using System;
using System.Collections;
using Unity.Mathematics;

public class MiniMaxAI : MonoBehaviour
{
    float bestScore;
    public GameManager gameManager;
    float score;
    Vector2Int bestMove;
    Piece bestPiece;
    [SerializeField] bool isActive;
    bool isProcessing;
    [SerializeField] int depth; 
    void Update()
    {
        if (isActive && !isProcessing && GameManager.turn == "black")
        {
            StartCoroutine(ExecuteAIMove());
        }
    }
    IEnumerator ExecuteAIMove()
    {
        float startTime = Time.realtimeSinceStartup;
        // Appel à ChooseBestMove()
        
        isProcessing = true;

        yield return new WaitForSeconds(0.2f);

        var resultat = ChooseBestMove(gameManager.board, depth);

        Piece pieceToPlay = resultat.Item2;
        Vector2Int moveToPlay = resultat.Item1;

        if (pieceToPlay != null)
        {
            pieceToPlay.SetPosition(moveToPlay.x, moveToPlay.y);
        }

        isProcessing = false;
    }
    // isMaximising est egal a true si c'est l'ia qui joue car elle veut maximiser son score et a false lorsque c'est le joueur car elle veut minimiser son score
    float MiniMax(Piece[,] board, int depth,float alpha,float beta, bool isMaximising)
    {
        if (depth == 0 || gameManager.isGameEnd(board))
        {
            return actualScore(board);
        }
        if (isMaximising)
        {
            float bestScore = Mathf.NegativeInfinity;

            for (int y = 0; y < gameManager.height; y++)
            {
                for (int x = 0; x < gameManager.width; x++)
                {
                    if (board[x, y] != null && board[x, y].color == Piece.PieceColor.black) 
                    {
                        Piece newPiece = board[x, y];
                        bool[,] moves = newPiece.GetValidMoves(board);

                        if (!moves.Cast<bool>().Any()) continue;

                        for (int newY = 0; newY < gameManager.height; newY++)
                        {
                            for (int newX = 0; newX < gameManager.width; newX++)
                            {
                                if (moves[newX, newY])
                                {
                                    Piece[,] newBoard = new Piece[board.GetLength(0), board.GetLength(1)];
                                    Copy(board, newBoard);
                                    newBoard[x, y] = null;
                                    newBoard[newX, newY] = (Piece)newPiece.Clone();

                                    float score = MiniMax(newBoard, depth - 1,alpha,beta, false);
                                    bestScore = Mathf.Max(bestScore, score);
                                    alpha = Mathf.Max(alpha, score);
                                    if (beta <= alpha)
                                    {
                                        return bestScore;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return bestScore;
        }
        else
        {
            float worstScore = Mathf.Infinity;

            for (int y = 0; y < gameManager.height; y++)
            {
                for (int x = 0; x < gameManager.width; x++)
                {
                    if (board[x, y] != null && board[x, y].color == Piece.PieceColor.white)
                    {
                        Piece newPiece = board[x, y];
                        bool[,] moves = newPiece.GetValidMoves(board);

                        if (!moves.Cast<bool>().Any()) continue;

                        for (int newY = 0; newY < gameManager.height; newY++)
                        {
                            for (int newX = 0; newX < gameManager.width; newX++)
                            {
                                if (moves[newX, newY])
                                {
                                    Piece[,] newBoard = new Piece[board.GetLength(0), board.GetLength(1)];
                                    Copy(board, newBoard);
                                    newBoard[x, y] = null;
                                    newBoard[newX, newY] = (Piece)newPiece.Clone();

                                    float score = MiniMax(newBoard, depth - 1, alpha, beta, true);
                                    worstScore = Mathf.Min(worstScore, score);
                                    beta = Mathf.Min((float)score, beta);
                                    if(beta <= alpha)
                                    {
                                        return worstScore;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return worstScore;
        }
        
    }


    (Vector2Int, Piece) ChooseBestMove(Piece[,] board, int maxDepth)
    {
        float bestScore = Mathf.NegativeInfinity;
        Vector2Int bestMove = new Vector2Int(-1, -1);
        Piece bestPiece = null;

        for (int y = 0; y < gameManager.height; y++)
        {
            for (int x = 0; x < gameManager.width; x++)
            {
                if (board[x, y] != null && board[x, y].color == Piece.PieceColor.black)
                {
                    Piece newPiece = board[x, y];
                    bool[,] moves = newPiece.GetValidMoves(board);

                    if (!moves.Cast<bool>().Any()) continue;

                    for (int newY = 0; newY < gameManager.height; newY++)
                    {
                        for (int newX = 0; newX < gameManager.width; newX++)
                        {
                            if (moves[newX, newY])
                            {
                                Piece[,] newBoard = new Piece[board.GetLength(0), board.GetLength(1)];
                                Copy(board, newBoard);
                                newBoard[x, y] = null;
                                newBoard[newX, newY] = (Piece)newPiece.Clone();

                                float score = MiniMax(newBoard, maxDepth - 1,Mathf.NegativeInfinity,Mathf.Infinity, false);

                                if (score > bestScore)
                                {
                                    bestScore = score;
                                    bestMove = new Vector2Int(newX, newY);
                                    bestPiece = newPiece;
                                }
                            }
                        }
                    }
                }
            }
        }

        return (bestMove, bestPiece);
    }



    float actualScore(Piece[,] newBoard) {

        if (gameManager.IsCheckmate(Piece.PieceColor.white, newBoard)) {
            return Mathf.Infinity;
        }
        else if (gameManager.IsCheckmate(Piece.PieceColor.black, newBoard)) {
            return Mathf.NegativeInfinity;
        }
        else if (gameManager.IsPat(newBoard)) {
            return 0f;
        }


        float score = 0f;
        for (int y = 0; y < gameManager.height; y++)
        {
            for (int x = 0; x < gameManager.width; x++)
            {
                if (newBoard[x, y] != null)
                {
                    Piece newPiece = newBoard[x, y];
                    score += newPiece.value * (newPiece.color == Piece.PieceColor.black ? 1 : -1);
                    if(gameManager.height == 8 && gameManager.width == 8)
                    {
                        score += newPiece.pointForPosition[x, y];
                    }
                }
            }
        }
        return score;
    }

    static void Copy<T>(T[,] from, T[,] to) where T : ICloneable
    {
        int width = from.GetLength(0);
        int height = from.GetLength(1);

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                if (from[x, y] != null)
                    to[x, y] = (T)from[x, y].Clone();
                else
                    to[x, y] = default;
            }
        }
    }


}

Editor is loading...
Leave a Comment