/// <summary> /// Executes AI move /// </summary> /// <param name="currentBoard">The current board</param> public void Execute(Board currentBoard) { if (algorithm != null) { Board next = algorithm.NextMove(currentBoard); if(IsEqual(currentBoard, next)) throw new Exception(); Game.Instance.SetBoard(next); } }
private bool IsEqual(Board boardA, Board boardB) { for (int x = 0; x < 21; x++) { for (int y = 0; y < 20; y++) { if (boardA.BoardSituation[x, y] != boardB.BoardSituation[x, y]) return false; } } return true; }
/// <summary> /// Does a random move /// </summary> /// <param name="currentBoard">Board to calculate random move</param> /// <returns>Random move</returns> public Board NextMove(Board currentBoard) { // Generate moves List<Board> nextMoves = currentBoard.GenerateMoves(Game.Instance.GetTurn()); // create random and get random number System.Random random = new System.Random(); int move = random.Next(0, nextMoves.Count); // return move if (nextMoves.Count > 0) return nextMoves[move]; else throw new Exception(); return currentBoard; }
/// <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> /// /// </summary> /// <returns></returns> public object Clone() { Board b = new Board((BoardPosition[,])this.BoardSituation.Clone()); b.WhiteItems = this.WhiteItems; b.IsTileMoved = this.IsTileMoved; b.RedItems = this.RedItems; b.MovedTilePosition = this.movedTilePosition; return b; }
/// <summary> /// /// </summary> /// <param name="turnPlayerA"></param> /// <returns></returns> public List<Board> ChangeBoardPosition(bool turnPlayerA) { List<Board> boards = new List<Board>(); BoardPosition colorHead = BoardPosition.WhiteHead; BoardPosition colorTail = BoardPosition.WhiteTail; if (turnPlayerA) { colorHead = BoardPosition.RedHead; colorTail = BoardPosition.RedTail; } for (int x = 0; x < 21; x++) { for (int y = 0; y < 20; y++) { if (boardPositions[x, y] == colorHead || boardPositions[x, y] == colorTail) { for (int j = -1; j < 2; j++) { for (int i = -1; i < 2; i++) { if (!(i == 0 && j == 0) && (x + i >= 0 && x + i < 21) && (y + j >= 0 && y + j < 20)) { // Moving a piece to a empty tile next to him if (boardPositions[x + i, y + j] == BoardPosition.Tile) { if ((this.isTileMoved && (this.movedTilePosition.X == x + i && this.movedTilePosition.Y == y + j)) || !this.isTileMoved) { BoardPosition[,] newBoardPosition = (BoardPosition[,])boardPositions.Clone(); newBoardPosition[x, y] = BoardPosition.Tile; newBoardPosition[x + i, y + j] = boardPositions[x, y]; Board newBoard = new Board(newBoardPosition); newBoard.RedItems = this.RedItems; newBoard.WhiteItems = this.WhiteItems; newBoard.IsTileMoved = false; boards.Add(newBoard); } } // Moving a piece by jumping over a other piece next to him else if (boardPositions[x + i, y + j] != BoardPosition.Empty) { if (x + i + i >= 0 && x + i + i < 21 && y + j + j >= 0 && y + j + j < 20) { if (boardPositions[x + i + i, y + j + j] == BoardPosition.Tile || (this.isTileMoved && boardPositions[x + i + i, y + j + j] == BoardPosition.Empty)) { if ((this.isTileMoved && (this.movedTilePosition.X == x + i + i && this.movedTilePosition.Y == y + j + j)) || !this.isTileMoved) { BoardPosition[,] newBoardPosition = (BoardPosition[,])boardPositions.Clone(); newBoardPosition[x, y] = BoardPosition.Tile; if (boardPositions[x, y] == colorTail) newBoardPosition[x + i + i, y + j + j] = colorHead; else newBoardPosition[x + i + i, y + j + j] = colorTail; Board newBoard = new Board(newBoardPosition); newBoard.RedItems = this.RedItems; newBoard.WhiteItems = this.WhiteItems; newBoard.IsTileMoved = false; boards.Add(newBoard); } } else if (boardPositions[x + i + i, y + j + j] == BoardPosition.Empty && !isTileMoved) { Point moveTileTo = new Point(x + i + i, y + j + j); foreach (Point movablePoint in movablePoints) { if(boardPositions[movablePoint.X, movablePoint.Y] == BoardPosition.Tile) { BoardPosition[,] newBoardPosition = (BoardPosition[,])boardPositions.Clone(); newBoardPosition[movablePoint.X, movablePoint.Y] = BoardPosition.Empty; newBoardPosition[moveTileTo.X, moveTileTo.Y] = BoardPosition.Tile; bool canBeMovedThere = false; if (newBoardPosition[moveTileTo.X + 1, moveTileTo.Y] != BoardPosition.Empty) canBeMovedThere = true; if (newBoardPosition[moveTileTo.X - 1, moveTileTo.Y] != BoardPosition.Empty) canBeMovedThere = true; if (newBoardPosition[moveTileTo.X, moveTileTo.Y + 1] != BoardPosition.Empty) canBeMovedThere = true; if (newBoardPosition[moveTileTo.X, moveTileTo.Y - 1] != BoardPosition.Empty) canBeMovedThere = true; if (canBeMovedThere) { Board newBoard = new Board(newBoardPosition); newBoard.RedItems = this.RedItems; newBoard.WhiteItems = this.WhiteItems; newBoard.IsTileMoved = true; newBoard.MovedTilePosition = moveTileTo; boards.Add(newBoard); } } } } } } else if (!isTileMoved && (boardPositions[x + i, y + j] == BoardPosition.Empty || boardPositions[x + i + i, y + j + j] == BoardPosition.Empty)) { bool isMovableTile = false; if ((i == -1 && j == -1) || (i == 1 && j == 1) || (i == -1 && j == 1) || (i == 1 && j == -1)) { int currentI = x + i; int currentJ = y + j; if (currentJ - 1 >= 0) if (boardPositions[currentI, currentJ - 1] != BoardPosition.Empty) isMovableTile = true; if (currentJ + 1 < 20) if (boardPositions[currentI, currentJ + 1] != BoardPosition.Empty) isMovableTile = true; if (currentI + 1 < 21) if (boardPositions[currentI + 1, currentJ] != BoardPosition.Empty) isMovableTile = true; if (currentI - 1 >= 0) if (boardPositions[currentI - 1, currentJ] != BoardPosition.Empty) isMovableTile = true; } else isMovableTile = true; if (isMovableTile) { Point moveTileTo = new Point(x + i, y + j); if (boardPositions[x + i, y + j] != BoardPosition.Empty) { moveTileTo.X += i; moveTileTo.Y += j; } foreach (Point movablePoint in movablePoints) { if(boardPositions[movablePoint.X, movablePoint.Y] == BoardPosition.Tile) { BoardPosition[,] newBoardPosition = (BoardPosition[,])boardPositions.Clone(); newBoardPosition[movablePoint.X, movablePoint.Y] = BoardPosition.Empty; newBoardPosition[moveTileTo.X, moveTileTo.Y] = BoardPosition.Tile; bool canBeMovedThere = false; if (newBoardPosition[moveTileTo.X + 1, moveTileTo.Y] != BoardPosition.Empty) canBeMovedThere = true; if (newBoardPosition[moveTileTo.X - 1, moveTileTo.Y] != BoardPosition.Empty) canBeMovedThere = true; if (newBoardPosition[moveTileTo.X, moveTileTo.Y + 1] != BoardPosition.Empty) canBeMovedThere = true; if (moveTileTo.Y - 1 >= 0) { if (newBoardPosition[moveTileTo.X, moveTileTo.Y - 1] != BoardPosition.Empty) canBeMovedThere = true; } if (canBeMovedThere) { Board newBoard = new Board(newBoardPosition); newBoard.RedItems = this.RedItems; newBoard.WhiteItems = this.WhiteItems; newBoard.IsTileMoved = true; newBoard.MovedTilePosition = moveTileTo; boards.Add(newBoard); } } } } } } } } } } } if (boards.Count == 0) throw new Exception(); return boards; }
public bool IsCalculatedBefore(Board board, int depth, bool isPlayerAMax, bool turnPlayerA) { Int64 hashKey = CreateHashKey(board, depth, isPlayerAMax, turnPlayerA); int position = (int)Math.Abs((hashKey % tableSize)); HashObject hashObject = tableContent[position]; if (hashObject == null) return false; if (hashObject.depth >= depth && hashObject.hashKey == hashKey && hashObject.isPlayerAMax == isPlayerAMax && hashObject.turnPlayerA == turnPlayerA) return true; return false; }
public int GetCalculatedValue(Board board, int depth, bool isPlayerAMax, bool turnPlayerA) { Int64 hashKey = CreateHashKey(board, depth, isPlayerAMax, turnPlayerA); int position = (int)Math.Abs((hashKey % tableSize)); HashObject hashObject = tableContent[position]; if (hashObject == null) throw new Exception("Board has not been calculated before and inserted into the transposition table"); if (hashObject.depth >= depth && hashObject.hashKey == hashKey && hashObject.isPlayerAMax == isPlayerAMax && hashObject.turnPlayerA == turnPlayerA) return hashObject.value; else throw new Exception("Board has not been calculated before and inserted into the transposition table"); }
/// <summary> /// starts a new game /// </summary> /// <param name="playerA">playersettings of player A</param> /// <param name="playerB">playersettings of player B</param> /// <param name="startBoard">a board to start with</param> /// <param name="startPlayer">player that turns first</param> public void StartGame(PlayerSettings playerA, PlayerSettings playerB, Board startBoard, int startPlayer) { Game.Instance.StartGame(playerA, playerB, startBoard, startPlayer); }
/// <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"); } }
/// <summary> /// move tile to a new point /// </summary> /// <param name="a">from point</param> /// <param name="b">to point</param> public void MoveTile(Point a, Point b) { Board cloneBoard = (Board)board.Clone(); cloneBoard.BoardSituation[b.X, b.Y] = BoardPosition.Tile; cloneBoard.BoardSituation[a.X, a.Y] = BoardPosition.Empty; cloneBoard.IsTileMoved = true; cloneBoard.MovedTilePosition = new Point(b.X, b.Y); cloneBoard.CalculateMovableTiles(); List<Board> possibleMoves = board.GenerateMoves(turnPlayerA); bool isInList = false; foreach (Board pm in possibleMoves) { if (pm.CompareTo(cloneBoard) == 0) isInList = true; } if (isInList) { Logger.AddLine(GetCurrentPlayerNumber() + "-> Moved tile from: " + a.X + ", " + a.Y + " to " + b.X + ", " + b.Y); board = cloneBoard; } else { Logger.AddLine(GetCurrentPlayerNumber() + "-> It's not possible to move tile from: " + a.X + ", " + a.Y + " to " + b.X + ", " + b.Y); } }
/// <summary> /// move piece to a new point and switches the turn /// </summary> /// <param name="a">from point</param> /// <param name="b">to point</param> public void MovePiece(Point a, Point b) { Board cloneBoard = (Board)board.Clone(); BoardPosition old = cloneBoard.BoardSituation[a.X, a.Y]; cloneBoard.IsTileMoved = false; if(Math.Abs(a.X - b.X)==2 || Math.Abs(a.Y - b.Y) == 2) { switch (old) { case BoardPosition.RedTail: old = BoardPosition.RedHead; break; case BoardPosition.RedHead: old = BoardPosition.RedTail; break; case BoardPosition.WhiteTail: old = BoardPosition.WhiteHead; break; case BoardPosition.WhiteHead: old = BoardPosition.WhiteTail; break; } } cloneBoard.BoardSituation[b.X, b.Y] = old; cloneBoard.BoardSituation[a.X, a.Y] = BoardPosition.Tile; cloneBoard.CalculateMovableTiles(); List<Board> possibleMoves = board.GenerateMoves(turnPlayerA); bool isInList = false; foreach (Board pm in possibleMoves) { if (pm.CompareTo(cloneBoard) == 0) isInList = true; } if(isInList) { Logger.AddLine(GetCurrentPlayerNumber() + "-> Moved piece from: " + a.X + ", " + a.Y + " to " + b.X + ", " + b.Y); board = cloneBoard; ChangePlayer(); } else { Logger.AddLine(GetCurrentPlayerNumber() + " -> It's not possible to move piece from: " + a.X + ", " + a.Y + " to " + b.X + ", " + b.Y); } }
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; }
/// <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); }
/// <summary> /// /// </summary> /// <param name="board"></param> public void IsMoveValid(Board board) { // IMPLEMENTATION NEEDED }
/// <summary> /// /// </summary> /// <param name="toChange"></param> /// <returns></returns> private List<Board> NewBoardPosition(BoardPosition toChange) { List<Board> boards = new List<Board>(); for (int x = 0; x < 21; x++) { for (int y = 0; y < 20; y++) { if (boardPositions[x, y] == BoardPosition.Tile) { BoardPosition[,] newBoardPosition = (BoardPosition[,])boardPositions.Clone(); newBoardPosition[x, y] = toChange; Board newBoard = new Board(newBoardPosition); if (toChange == BoardPosition.RedTail) { newBoard.RedItems = this.RedItems + 1; newBoard.WhiteItems = this.WhiteItems; } else { newBoard.RedItems = this.RedItems; newBoard.WhiteItems = this.WhiteItems + 1; } newBoard.IsTileMoved = false; boards.Add(newBoard); } } } return boards; }
/// <summary> /// sets the board /// </summary> /// <param name="board">the new board</param> public void SetBoard(Board board) { if (IsEqual(this.board, board)) throw new Exception(); this.board = board; }
/// <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; }
/// <summary> /// starts a new game with a startboard and a turningplayer /// </summary> /// <param name="playerA">playersettings of player A</param> /// <param name="playerB">playersettings of player B</param> /// <param name="startBoard">a board to start with</param> /// <param name="startPlayer">player that turns first</param> public void StartGame(PlayerSettings playerA, PlayerSettings playerB, Board startBoard, int startPlayer) { this.playerA = new AIPlayer(playerA); this.playerB = new AIPlayer(playerB); NumMovesA = 0; NumMovesB = 0; this.board = startBoard; this.turnPlayerA = (startPlayer == 0 ? true : false); Logger.AddLine("Start new game, with startboard and turningPlayer"); MakeAIMove(); }
public void InsertCalculatedValue(Board board, int depth, bool isPlayerAMax, bool turnPlayerA, int value) { Int64 hashKey = CreateHashKey(board, depth, isPlayerAMax, turnPlayerA); int position = (int)Math.Abs((hashKey % tableSize)); HashObject hashObject = tableContent[position]; if (hashObject == null) tableContent[position] = new HashObject(depth, hashKey, value, isPlayerAMax, turnPlayerA); else { bool collision = true; while (collision) { position = (int)Math.Abs((hashKey % tableSize)); hashObject = tableContent[position]; if (hashObject == null) collision = false; else if (hashObject.hashKey != hashKey || hashObject.isPlayerAMax != isPlayerAMax || hashObject.turnPlayerA != turnPlayerA) TableResize(); else collision = false; } tableContent[position] = new HashObject(depth, hashKey, value, isPlayerAMax, turnPlayerA); } }
/// <summary> /// starts a new game /// </summary> /// <param name="playerA">playersettings of player A</param> /// <param name="playerB">playersettings of player B</param> public void StartGame(PlayerSettings playerA, PlayerSettings playerB) { this.playerA = new AIPlayer(playerA); this.playerB = new AIPlayer(playerB); NumMovesA = 0; NumMovesB = 0; // random first player System.Random r = new System.Random(); int player = r.Next(1, 3); turnPlayerA = true; if (player == 2) turnPlayerA = false; board = new Board(); Logger.AddLine("Start new game"); MakeAIMove(); }
private Int64 CreateHashKey(Board board, int depth, bool isPlayerAMax, bool turnPlayerA) { Int64 result = 0; if (isPlayerAMax) result = result ^ playerAMax; else result = result ^ playerBMax; if (turnPlayerA) result = result ^ this.turnPlayerA; else result = result ^ turnPlayerB; for (int x = 0; x < 21; x++) { for (int y = 0; y < 20; y++) { switch (board.BoardSituation[x, y]) { case BoardPosition.Empty: result = result ^ emptySpacesKeys[x, y]; break; case BoardPosition.Tile: result = result ^ tilesKeys[x, y]; break; case BoardPosition.RedTail: result = result ^ redTailKeys[x, y]; break; case BoardPosition.RedHead: result = result ^ redheadKeys[x, y]; break; case BoardPosition.WhiteTail: result = result ^ whiteTailKeys[x, y]; break; case BoardPosition.WhiteHead: result = result ^ whiteHeadKeys[x, y]; break; } } } return result; }
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; }
public static void updateBoard() { // set calculation to true calculating = true; Thread.Sleep(50); while (boardAnimating) { Thread.Sleep(50); } newBoard = UIConnector.Instance.GetBoard(); UIConnector.Instance.MaxAIMoves(aiMoves); aiMoves++; manager.currentBoard = newBoard.BoardSituation; manager.redItems = newBoard.RedItems; manager.whiteItems = newBoard.WhiteItems; manager.SetupBoard(); // set calculation to false; calculating = false; Thread.Sleep(1450); updateBoard(); }
/// <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; }