/// <summary> /// Does the next move /// </summary> /// <param name="currentBoard">Board to calculate best move</param> /// <returns>Best boardsituation</returns> public Board NextMove(Board currentBoard) { Board evaluationBoard = new Board(); bool evaluationBoardSet = false; int valuelast = Int32.MinValue; List<Board> sameHighest = new List<Board>(); List<Board> moves = currentBoard.GenerateMoves(Game.Instance.GetTurn()); foreach (Board board in moves) { int value = 0; if(board.IsTileMoved) value = MiniMaxFunction(board, plieDepth, Game.Instance.GetTurn(), Game.Instance.GetTurn()); else value = MiniMaxFunction(board, plieDepth, Game.Instance.GetTurn(), !Game.Instance.GetTurn()); if (value > valuelast || !evaluationBoardSet) { sameHighest = new List<Board>(); sameHighest.Add(board); evaluationBoard = board; valuelast = value; evaluationBoardSet = true; } else if (value == valuelast) { sameHighest.Add(board); } } if (sameHighest.Count > 1 && sameHighest.Contains(evaluationBoard)) { System.Random random = new System.Random(); evaluationBoard = sameHighest[random.Next(0, sameHighest.Count - 1)]; while (evaluationBoard.IsTileMoved) evaluationBoard = sameHighest[random.Next(0, sameHighest.Count - 1)]; } if (IsEqual(evaluationBoard, currentBoard)) throw new Exception(); //Logger.AddLine("MiniMax: boards with same value: " + sameHighest.Count + " of " + moves.Count + " moves"); Logger.AddLine("Board -> Evaluation value: " + evaluationBoard.Evaluation(Game.Instance.GetTurn(), Game.Instance.GetTurn())); return evaluationBoard; }
/// <summary> /// Does the next move /// </summary> /// <param name="currentBoard">Board to calculate best move</param> /// <returns>Best boardsituation</returns> public Board NextMove(Board currentBoard) { Board evaluationBoard = new Board(); bool evaluationBoardSet = false; evaluationBoard.BoardSituation[0, 0] = BoardPosition.RedTail; int valuelast = Int32.MinValue; List<Board> sameHighest = new List<Board>(); int alpha = Int32.MinValue + 10; int beta = Int32.MaxValue; List<Board> moves = currentBoard.GenerateMoves(Game.Instance.GetTurn()); foreach (Board board in moves) { if (board.IsTileMoved) alpha = AlphaBetaFunction(board, plieDepth, Game.Instance.GetTurn(), Game.Instance.GetTurn(), alpha, beta); else alpha = AlphaBetaFunction(board, plieDepth, Game.Instance.GetTurn(), !Game.Instance.GetTurn(), alpha, beta); if (alpha > valuelast || !evaluationBoardSet) { sameHighest = new List<Board>(); sameHighest.Add(board); evaluationBoard = board; valuelast = alpha; evaluationBoardSet = true; } else if (alpha == valuelast) { sameHighest.Add(board); } } if (sameHighest.Count > 1 && sameHighest.Contains(evaluationBoard)) { int highest = Int32.MinValue; List<Board> highestOfTheHighest = new List<Board>(); foreach (Board board in sameHighest) { int eval = Int32.MinValue; if(board.IsTileMoved) eval = board.Evaluation(Game.Instance.GetTurn(), Game.Instance.GetTurn()); else eval = board.Evaluation(Game.Instance.GetTurn(), !Game.Instance.GetTurn()); if (eval > highest) { highest = eval; highestOfTheHighest = new List<Board>(); highestOfTheHighest.Add(board); } else if (eval == highest) highestOfTheHighest.Add(board); } System.Random random = new System.Random(); evaluationBoard = highestOfTheHighest[random.Next(0, highestOfTheHighest.Count - 1)]; } if (IsEqual(evaluationBoard, currentBoard)) throw new Exception(); Logger.AddLine("AB: boards with same value: " + sameHighest.Count + " of " + moves.Count + " moves"); Logger.AddLine("Board -> Evaluation value: " + evaluationBoard.Evaluation(Game.Instance.GetTurn(), Game.Instance.GetTurn())); return evaluationBoard; }
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> /// place pace to a point and switches the turn /// </summary> /// <param name="point">point for piece</param> public void PlacePiece(Point point) { Board b = (Board)board.Clone(); b.BoardSituation[point.X, point.Y] = (turnPlayerA ? BoardPosition.RedTail : BoardPosition.WhiteTail); if (turnPlayerA) b.RedItems++; else b.WhiteItems++; bool isInList = false; b.CalculateMovableTiles(); List<Board> possibleMoves = board.GenerateMoves(turnPlayerA); foreach (Board pm in possibleMoves) { if(pm.CompareTo(b)==0) isInList = true; } if (isInList) { board = b; Logger.AddLine(GetCurrentPlayerNumber() + "-> Placed piece on: " + point.X + ", " + point.Y); Logger.AddLine("Board -> Evaluationvalue: " + board.Evaluation(turnPlayerA, turnPlayerA)); ChangePlayer(); } else { Logger.AddLine(GetCurrentPlayerNumber() + "-> Placing piece on: " + point.X + ", " + point.Y + " is not a valid move"); } }
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; }