Created
August 25, 2017 03:25
-
-
Save luyao795/6ca43b5334a4307717040d1f219d76a0 to your computer and use it in GitHub Desktop.
This class defines variable depth AI behavior by using MiniMax with Alpha-Beta Pruning.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
public class MoveStatus { | |
public int row, col; | |
public int score; | |
public MoveStatus(int Row, int Col, int Score) | |
{ | |
row = Row; | |
col = Col; | |
score = Score; | |
} | |
} | |
public class AIReversi { | |
public GameController gameController = new GameController (); | |
public int[,] evalFun = { | |
{ 30, -25, 10, 5, 5, 10, -25, 30 }, | |
{ -25, -25, 1, 1, 1, 1, -25, -25 }, | |
{ 10, 1, 5, 2, 2, 5, 1, 10 }, | |
{ 5, 1, 2, 1, 1, 2, 1, 5 }, | |
{ 5, 1, 2, 1, 1, 2, 1, 5 }, | |
{ 10, 1, 5, 2, 2, 5, 1, 10 }, | |
{ -25, -25, 1, 1, 1, 1, -25, -25 }, | |
{ 30, -25, 10, 5, 5, 10, -25, 30 } | |
}; | |
// evaluate the board | |
public int EvaluateBoard(int[,] board, int color) | |
{ | |
List<Vector2> playerMoves = gameController.MoveList (board, 1); | |
List<Vector2> AIMoves = gameController.MoveList (board, 2); | |
int playerScore = 0; | |
int AIScore = 0; | |
foreach (Vector2 move in playerMoves) { | |
playerScore += evalFun [(int)move.x, (int)move.y]; | |
} | |
foreach (Vector2 move in AIMoves) { | |
AIScore += evalFun [(int)move.x, (int)move.y]; | |
} | |
//int playerPieces = gameController.CountPieces (board, 1); | |
//int AIPieces = gameController.CountPieces (board, 2); | |
int result = 0; | |
if (color == 1) { | |
result = playerScore - AIScore; | |
} | |
if (color == 2) { | |
result = AIScore - playerScore; | |
} | |
return result; | |
} | |
// Minimax algorithm without alpha-beta pruning | |
public MoveStatus MiniMax(int[,] board, int color, int maxDepth, int currentDepth) | |
{ | |
if (gameController.IsGameOver () || currentDepth == maxDepth) { | |
return new MoveStatus (-1, -1, EvaluateBoard (board, color)); | |
} | |
MoveStatus ms = new MoveStatus (-1, -1, 0); | |
if (color == 2) { | |
ms.score = int.MinValue; | |
} else | |
ms.score = int.MaxValue; | |
List<Vector2> allNextMoves; | |
// this is the AI turn right now | |
if (color == 2) { | |
allNextMoves = gameController.MoveList (board, 2); | |
foreach (Vector2 move in allNextMoves) { | |
int[,] newBoard = gameController.GetNextBoard (board, 2, (int)move.x, (int)move.y); | |
int score = MiniMax (newBoard, 1, maxDepth, currentDepth + 1).score; | |
if (score > ms.score) { | |
ms.row = (int)move.x; | |
ms.col = (int)move.y; | |
ms.score = score; | |
} | |
} | |
// this is the human turn right now | |
} else { | |
allNextMoves = gameController.MoveList (board, 1); | |
foreach (Vector2 move in allNextMoves) { | |
int[,] newBoard = gameController.GetNextBoard (board, 1, (int)move.x, (int)move.y); | |
int score = MiniMax (newBoard, 2, maxDepth, currentDepth + 1).score; | |
if (score < ms.score) { | |
ms.row = (int)move.x; | |
ms.col = (int)move.y; | |
ms.score = score; | |
} | |
} | |
} | |
return ms; | |
} | |
// Minimax algorithm with alpha-beta pruning | |
public MoveStatus MiniMaxAlphaBeta(int[,] board, int color, int maxDepth, int currentDepth, int alpha, int beta) | |
{ | |
if (gameController.IsGameOver () || currentDepth == maxDepth) { | |
return new MoveStatus (-1, -1, EvaluateBoard (board, color)); | |
} | |
MoveStatus ms = new MoveStatus (-1, -1, 0); | |
if (color == 2) { | |
ms.score = int.MinValue; | |
} else | |
ms.score = int.MaxValue; | |
List<Vector2> allNextMoves; | |
// this is the AI turn right now | |
if (color == 2) { | |
allNextMoves = gameController.MoveList (board, 2); | |
foreach (Vector2 move in allNextMoves) { | |
int[,] newBoard = gameController.GetNextBoard (board, 2, (int)move.x, (int)move.y); | |
int score = MiniMaxAlphaBeta (newBoard, 1, maxDepth, currentDepth + 1, alpha, beta).score; | |
if (score > ms.score) { | |
ms.row = (int)move.x; | |
ms.col = (int)move.y; | |
ms.score = score; | |
if (ms.score > alpha) | |
alpha = ms.score; | |
if (alpha >= beta) | |
break; | |
} | |
} | |
// this is the human turn right now | |
} else { | |
allNextMoves = gameController.MoveList (board, 1); | |
foreach (Vector2 move in allNextMoves) { | |
int[,] newBoard = gameController.GetNextBoard (board, 1, (int)move.x, (int)move.y); | |
int score = MiniMaxAlphaBeta (newBoard, 2, maxDepth, currentDepth + 1, alpha, beta).score; | |
if (score < ms.score) { | |
ms.row = (int)move.x; | |
ms.col = (int)move.y; | |
ms.score = score; | |
if (ms.score < beta) | |
beta = ms.score; | |
if (beta <= alpha) | |
break; | |
} | |
} | |
} | |
return ms; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment