Untitled
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