/// <summary> /// Evaluates the board /// </summary> /// <param name="board">Provided board</param> /// <param name="isRed">Is player red's turn</param> /// <returns></returns> public static int Evaluate(Board board, bool isRed) { // evaluation value int lEvaluationValue = 0; // starttime DateTime lStartTime = DateTime.Now; // if won, we don't have to do things if (board.IsWon()) lEvaluationValue = 1000000; else { if (board.IsTileMoved) { List<Board> nextMoves = board.GenerateMoves(isRed); if (nextMoves.Count == 1) { return nextMoves[0].Evaluation(isRed, isRed); } } // temp values int lEmptySpots = 0; int lOwnHead = 0; // temp value for storing the to be checked head position BoardPosition lHead = BoardPosition.RedHead; if (!isRed) lHead = BoardPosition.WhiteHead; // loop trough board for (int x = 0; x < 21; x++) { for (int y = 0; y < 20; y++) { //if (boardPositions[x, y] == lHead) // lOwnHead++; #region "Check if piece belongs to current player" bool lCheck = false; if (board.BoardSituation[x, y] != BoardPosition.Empty && board.BoardSituation[x, y] != BoardPosition.Tile) { if (isRed) { if (board.BoardSituation[x, y] == BoardPosition.RedHead || board.BoardSituation[x, y] == BoardPosition.RedTail) lCheck = true; } else if (!isRed) { if (board.BoardSituation[x, y] == BoardPosition.WhiteHead || board.BoardSituation[x, y] == BoardPosition.WhiteTail) lCheck = true; } } #endregion if (lCheck) { #region "Left Column" // x - - // x - - // x - - if (x > 0) { // x - - // - - - // - - - if (y > 0) { if (board.BoardSituation[x - 1, y - 1] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x - 1, y - 1] == lHead) lOwnHead++; } // - - - // x - - // - - - if (board.BoardSituation[x - 1, y] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x - 1, y] == lHead) lOwnHead++; // - - - // - - - // x - - if (y < (20 - 1)) { if (board.BoardSituation[x - 1, y + 1] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x - 1, y + 1] == lHead) lOwnHead++; } } #endregion #region "Middle column" // - x - // - x - // - x - // - x - // - - - // - - - if (y > 0) { if (board.BoardSituation[x, y - 1] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x, y - 1] == lHead) lOwnHead++; } // - - - // - x - // - - - // needs no check, is this position // - - - // - - - // - x - if (y < (20 - 1)) { if (board.BoardSituation[x, y + 1] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x, y + 1] == lHead) lOwnHead++; } #endregion #region "Right column" // - - x // - - x // - - x if (x < (21 - 1)) { // - - x // - - - // - - - if (y > 0) { if (board.BoardSituation[x + 1, y - 1] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x + 1, y - 1] == lHead) lOwnHead++; } // - - - // - - x // - - - if (board.BoardSituation[x + 1, y] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x + 1, y] == lHead) lOwnHead++; // - - - // - - - // - - x if (y < (20 - 1)) { if (board.BoardSituation[x + 1, y + 1] == BoardPosition.Tile) lEmptySpots++; else if (board.BoardSituation[x + 1, y + 1] == lHead) lOwnHead++; } } #endregion } } } // calculate evalution value int evalAdd = 0; if (Game.Instance.CurrentPlayerNumPieces() > 0) { //evalAdd = (lEmptySpots * (lOwnHead / Game.Instance.CurrentPlayerNumPieces())); evalAdd = lEmptySpots * (lOwnHead ^ 2); } lEvaluationValue = lEmptySpots + evalAdd; } #region "debug" //DateTime lStopTime = DateTime.Now; //TimeSpan lDiff = lStopTime - lStartTime; //Logger.AddLine("Board -> Evaluation value: " + lEvaluationValue + " (calculated in: " + lDiff.TotalMilliseconds + " ms)"); #endregion return lEvaluationValue; }
private int MiniMaxFunction(Board node, int depth, bool isPlayerAMax, bool turnPlayerA) { if (depth <= 0 || node.IsWon()) { return node.Evaluation(isPlayerAMax, turnPlayerA); } if (this.transtable) { if(table.IsCalculatedBefore(node, depth, isPlayerAMax, turnPlayerA)) return table.GetCalculatedValue(node, depth, isPlayerAMax, turnPlayerA); } int alpha = Int32.MinValue; List<Board> possibleMoves = node.GenerateMoves(turnPlayerA); turnPlayerA = !turnPlayerA; if (possibleMoves.Count == 0) throw new Exception(); foreach (Board board in possibleMoves) { if (turnPlayerA == isPlayerAMax) { if(board.IsTileMoved) alpha = Math.Max(alpha, MiniMaxFunction(board, depth - 1, isPlayerAMax, !turnPlayerA)); else alpha = Math.Max(alpha, MiniMaxFunction(board, depth - 1, isPlayerAMax, turnPlayerA)); } else { if(board.IsTileMoved) alpha = Math.Max(alpha, -MiniMaxFunction(board, depth - 1, isPlayerAMax, !turnPlayerA)); else alpha = Math.Max(alpha, -MiniMaxFunction(board, depth - 1, isPlayerAMax, turnPlayerA)); } } if(this.transtable) { table.InsertCalculatedValue(node, depth, isPlayerAMax, !turnPlayerA, alpha); } return alpha; }
private int AlphaBetaFunction(Board node, int depth, bool isPlayerAMax, bool turnPlayerA, int alphaEval, int betaEval) { if (node.IsWon() || depth <= 0) { return node.Evaluation(isPlayerAMax, turnPlayerA); } if (this.transtable) { if (table.IsCalculatedBefore(node, depth, isPlayerAMax, turnPlayerA)) return table.GetCalculatedValue(node, depth, isPlayerAMax, turnPlayerA); } int value = Int32.MinValue; List<Board> possibleMoves = node.GenerateMoves(turnPlayerA); turnPlayerA = !turnPlayerA; if (isPlayerAMax == turnPlayerA) possibleMoves = Order(possibleMoves, true, true); else possibleMoves = Order(possibleMoves, false, false); foreach (Board board in possibleMoves) { if (turnPlayerA == isPlayerAMax) { if(board.IsTileMoved) value = Math.Max(value, AlphaBetaFunction(board, depth - 1, isPlayerAMax, !turnPlayerA, alphaEval, betaEval)); else value = Math.Max(value, AlphaBetaFunction(board, depth - 1, isPlayerAMax, turnPlayerA, alphaEval, betaEval)); alphaEval = Math.Max(value, alphaEval); if (betaEval <= alphaEval) { if (this.transtable) table.InsertCalculatedValue(node, depth, isPlayerAMax, !turnPlayerA, alphaEval); return alphaEval; } } else { if(board.IsTileMoved) value = Math.Max(value, -AlphaBetaFunction(board, depth - 1, isPlayerAMax, !turnPlayerA, alphaEval, betaEval)); else value = Math.Max(value, -AlphaBetaFunction(board, depth - 1, isPlayerAMax, turnPlayerA, alphaEval, betaEval)); betaEval = Math.Min(value, betaEval); if (betaEval <= alphaEval) { if (this.transtable) table.InsertCalculatedValue(node, depth, isPlayerAMax, !turnPlayerA, betaEval); return betaEval; } } } if (this.transtable) table.InsertCalculatedValue(node, depth, isPlayerAMax, !turnPlayerA, value); return value; }
/// <summary> /// Evaluates the board /// </summary> /// <param name="board">Provided board</param> /// <param name="isRed">Is player red's turn</param> /// <returns></returns> public static int Evaluate(Board board, bool isPlayerAMax, bool turnPlayerA) { // evaluation value int lEvaluationValue = 0; // starttime DateTime lStartTime = DateTime.Now; // if won, we don't have to do things if (board.IsWon()) if (isPlayerAMax == turnPlayerA) lEvaluationValue = -140; else lEvaluationValue = 140; else { // check if tile moved, if so, return evaluation value of next board of tile moved if (board.IsTileMoved) { List<Board> nextMoves = board.GenerateMoves(turnPlayerA); if (nextMoves.Count > 0) { return nextMoves[0].Evaluation(isPlayerAMax, !turnPlayerA); } } else { // tiles not moves, so we can continue here List<PieceSituation> goodSituations = FindSituations(board.BoardSituation, turnPlayerA); List<PieceSituation> badSituations = FindSituations(board.BoardSituation, !turnPlayerA); if (goodSituations.Count > 0) { IOrderedEnumerable<PieceSituation> orderedGood = from e in goodSituations orderby e select e; if (orderedGood.First() == PieceSituation.ThreeHeads) lEvaluationValue = 100; else if (orderedGood.First() == PieceSituation.ThreeHeadsWithSpace) lEvaluationValue = 60; else if (orderedGood.First() == PieceSituation.ThreeHeadsBlocked) lEvaluationValue = 20; } else if (badSituations.Count > 0) { IOrderedEnumerable<PieceSituation> orderedBad = from e in badSituations orderby e select e; if (orderedBad.First() == PieceSituation.ThreeHeads) lEvaluationValue = -100; else if (orderedBad.First() == PieceSituation.ThreeHeadsWithSpace) lEvaluationValue = -60; else if (orderedBad.First() == PieceSituation.ThreeHeadsBlocked) lEvaluationValue = -20; } } } // add amount of head times 5 to eval value int addToEval = 0; if (turnPlayerA) addToEval += 5 * board.RedHeads; else addToEval += 5 * board.WhiteHeads; return (lEvaluationValue + addToEval); }