/// <summary> /// Alpha beta fail hard version /// </summary> /// <param name="arrState"></param> /// <param name="arrposition"></param> /// <param name="depth"></param> /// <param name="side"></param> /// <param name="alpha"></param> /// <param name="beta"></param> /// <returns></returns> public static int AlphaBeta(ChessState[,] arrState, Dictionary <string, int> arrposition, int depth, eChessSide side, int alpha, int beta) { int bestScore = EvaluateChessBoard(arrState, side); if (depth == 0) { return(bestScore); } if (bestScore < _lowestScore) { return(bestScore); } bestScore = alpha; ChessMove bestMove = null; //Find all possible moves of this side => sort this to make alpha beta be faster ArrayList arrCanMoves = new ArrayList(); if (depth > 1) { arrCanMoves = SortChessMoves(arrState, FindAllPosibleMovesNotRule(arrState, side, _ownSide), side); } else { arrCanMoves = FindAllPosibleMovesNotRule(arrState, side, _ownSide); } //If no more moves if (arrCanMoves.Count == 0) { //opSide win if (Checked(arrState, _mySide, _ownSide) == true) { if (side == _mySide) { return(_lowestScore); } else { return(-_lowestScore); } } //mySide win if (Checked(arrState, _opSide, _ownSide) == true) { if (side == _mySide) { return(-_lowestScore); } else { return(_lowestScore); } } //Draw return(0); } while (arrCanMoves.Count > 0 && bestScore < beta) { //Pop a ChessMove ChessMove m = (ChessMove)arrCanMoves[arrCanMoves.Count - 1]; arrCanMoves.RemoveAt(arrCanMoves.Count - 1); //Compute new State after move PredictMove(arrState, m); //Add this Position string newPosition = MakePosition(arrState); if (arrposition.ContainsKey(newPosition)) { arrposition[newPosition]++; } else { arrposition.Add(newPosition, 1); } //Another side's move eChessSide newSide = eChessSide.Black; if (newSide == side) { newSide = eChessSide.White; } //Next move genneration int value = 0; if (arrposition[newPosition] < 3) { value = -AlphaBeta(arrState, arrposition, depth - 1, newSide, -beta, -alpha); } UnPredictMove(arrState, m); //Undo this Position if (arrposition[newPosition] > 1) { arrposition[newPosition] -= 1; } else { arrposition.Remove(newPosition); } //Update best if (value > bestScore) { bestScore = value; bestMove = m; if (depth == _maxDepth) { if (_myBestScore < bestScore) { _myBestScore = bestScore; _myBestMove = bestMove; } } if (value > alpha) { alpha = value; } if (value >= beta) { bestScore = beta; beta = bestScore - 1; } } } //_myBestMove = bestMove; return(bestScore); }
/// <summary> /// Unpredict a move - return a ChessState[,] /// </summary> /// <param name="A"></param> /// <param name="m"></param> /// <returns></returns> public static void UnPredictMove(ChessState[,] A, ChessMove m) { A[m.MoveFrom.X, m.MoveFrom.Y].Side = A[m.MoveTo.X, m.MoveTo.Y].Side; A[m.MoveFrom.X, m.MoveFrom.Y].Type = A[m.MoveTo.X, m.MoveTo.Y].Type; A[m.MoveFrom.X, m.MoveFrom.Y].Moves = m.FromMoves; A[m.MoveTo.X, m.MoveTo.Y].Type = eChessPieceType.Null; if (m.ChessPieceEated != eChessPieceType.Null) { A[m.MoveEated.X, m.MoveEated.Y].Side = eChessSide.Black; if (A[m.MoveFrom.X, m.MoveFrom.Y].Side == eChessSide.Black) { A[m.MoveEated.X, m.MoveEated.Y].Side = eChessSide.White; } A[m.MoveEated.X, m.MoveEated.Y].Type = m.ChessPieceEated; A[m.MoveEated.X, m.MoveEated.Y].Moves = m.Moves; } if (m.HowMove == eMove.Castling) { if (m.MoveFrom.X == m.MoveTo.X) { if (m.MoveFrom.Y < m.MoveTo.Y) { //King side castling A[m.MoveFrom.X, 8].Side = A[m.MoveTo.X, 6].Side; A[m.MoveFrom.X, 8].Type = A[m.MoveTo.X, 6].Type; A[m.MoveFrom.X, 8].Moves = A[m.MoveTo.X, 6].Moves - 1; A[m.MoveTo.X, 6].Type = eChessPieceType.Null; } else { //Queen side castling A[m.MoveFrom.X, 1].Side = A[m.MoveTo.X, 4].Side; A[m.MoveFrom.X, 1].Type = A[m.MoveTo.X, 4].Type; A[m.MoveFrom.X, 1].Moves = A[m.MoveTo.X, 4].Moves - 1; A[m.MoveTo.X, 4].Type = eChessPieceType.Null; } } else { //promotion side castling if (m.MoveFrom.X == 1) { //Black A[8, 5].Side = A[2, 5].Side; A[8, 5].Type = A[2, 5].Type; A[8, 5].Moves = A[2, 5].Moves - 1; A[2, 5].Type = eChessPieceType.Null; } else { //White A[1, 5].Side = A[7, 5].Side; A[1, 5].Type = A[7, 5].Type; A[1, 5].Moves = A[7, 5].Moves - 1; A[7, 5].Type = eChessPieceType.Null; } } } else if (m.HowMove == eMove.Promotion) { A[m.MoveFrom.X, m.MoveFrom.Y].Type = eChessPieceType.Pawn; } }