public void TestMakingMoves() { Board board2 = new Board(); TestingHelper.MakeSomeMoves(board2); Debug.WriteLine(board2.ToString()); }
public void TestEnPassantCapture() { Board board2 = new Board(); TestingHelper.MakeSomeMoves(board2); board2.MakeUserMove("c5d6"); Debug.WriteLine(board2.ToString()); }
public void TestFirstMoveGeneration() { Board board = new Board(); TestingHelper.MakeSomeMoves(board); int movesCount; UInt16[] moves = board.GenerateMoves(out movesCount); Console.WriteLine(movesCount); }
public void TestCastling() { Board board2 = new Board(); TestingHelper.MakeSomeMoves(board2); board2.MakeUserMove("e1c1"); board2.MakeUserMove("e8c8"); Debug.WriteLine(board2.ToString()); }
static void TestAlphaBetaParallel() { Board board = new Board(); // TestingHelper.MakeSomeMoves(board); Evaluation2.Initialise(); Stopwatch sw = new Stopwatch(); sw.Start(); Tuple<UInt16, int, long, int> bestMoveAndScore = AlphaBeta2.IterativeDeepeningParallel(board, Side.White); // AlphaBeta2.IDASParallel(board, Side.White); //Tuple<UInt16, int> bestMoveAndScore = AlphaBeta2.RootAlphaBetaTTParallel(board, Side.White, 7, -120, -60); sw.Stop(); //Console.WriteLine("Best Move For White: {0}. Depth: {1}. Score:{2}. TIME: {3} milliseconds", // board.ConvertToAlgebraicNotation(bestMoveAndScore.Item1), 7, bestMoveAndScore.Item2, sw.ElapsedMilliseconds); Console.WriteLine("Best Move For White: {0}. Depth: {1}. Score:{2}. TIME: {3} milliseconds", board.ConvertToAlgebraicNotation(bestMoveAndScore.Item1), bestMoveAndScore.Item2, bestMoveAndScore.Item4, sw.ElapsedMilliseconds); }
public void TestPawnPromotion() { Board board2 = new Board(); TestingHelper.MakeSomeMoves(board2); board2.MakeUserMove("d2e3"); bool success = board2.MakeUserMove("d5d4"); success = board2.MakeUserMove("e1g1"); success = board2.MakeUserMove("d4d3"); success = board2.MakeUserMove("a1c1"); success = board2.MakeUserMove("d3d2"); success = board2.MakeUserMove("f1e1"); success = board2.MakeUserMove("d2e1q"); }
static void Main(string[] args) { // variables sbyte ownSide; Board board = new Board(); Stack<BoardState> undoStack = new Stack<BoardState>(); UInt16 move; Tuple<UInt16, int, long, int> moveDepthTimeAndScore; string userMove, filthyMindMove = "INVALID_MOVE"; File.Delete(LogFileName); string guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "\nGUI: " + guiMessage + Environment.NewLine); Console.WriteLine("id name Shutranj"); Console.WriteLine("id author Okash Khawaja"); Console.WriteLine("uciok"); guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); Console.WriteLine("readyok"); guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); /********** this is when the game begins **************/ guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); if (guiMessage == "quit" || guiMessage == "stop") { return; } userMove = ParseOutLastMove(guiMessage); guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); // if empty then engine is playing white so make move first if (String.IsNullOrWhiteSpace(userMove)) { ownSide = Side.White; moveDepthTimeAndScore = AlphaBeta2.IDASParallel(board, ownSide); move = moveDepthTimeAndScore.Item1; if (board.MakeMove(move)) { filthyMindMove = board.ConvertToAlgebraicNotation(move); File.AppendAllText(LogFileName, String.Format( "Filthy Mind: {0} (Depth: {1} plies; Time: {2}ms; Score: {3}){4}", filthyMindMove, moveDepthTimeAndScore.Item2, moveDepthTimeAndScore.Item3, moveDepthTimeAndScore.Item4, Environment.NewLine)); } // communicate move back to gui Console.WriteLine(BestMoveStringFormat, filthyMindMove); } else { ownSide = Side.Black; } while (true) { guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); if (guiMessage == "quit" || guiMessage == "stop") { break; } userMove = ParseOutLastMove(guiMessage); guiMessage = Console.ReadLine(); File.AppendAllText(LogFileName, "GUI: " + guiMessage + Environment.NewLine); board.MakeUserMove(userMove); moveDepthTimeAndScore = AlphaBeta2.IDASParallel(board, ownSide); move = moveDepthTimeAndScore.Item1; if (board.MakeMove(move)) { filthyMindMove = board.ConvertToAlgebraicNotation(move); File.AppendAllText(LogFileName, String.Format( "Filthy Mind: {0} (Depth: {1} plies; Time: {2}ms; Score: {3}){4}", filthyMindMove, moveDepthTimeAndScore.Item2, moveDepthTimeAndScore.Item3, moveDepthTimeAndScore.Item4, Environment.NewLine)); } // communicate move back to gui Console.WriteLine(BestMoveStringFormat, filthyMindMove); } }
private static int Quiescence(Board board, sbyte side, int alpha, int beta) { // from: http://chessprogramming.wikispaces.com/Quiescence+Search int standingPat = Evaluation2.EvaluateFromPerspectiveOf(board, side); if (standingPat >= beta) { return beta; } if (alpha < standingPat) { alpha = standingPat; } sbyte oppositeSide = (sbyte)(-1 * side); int movesCount; UInt16[] moves = board.GenerateCaptureMoves(out movesCount); int score; BoardState state; for (int i = 0; i < movesCount; i++) { state = board.GetBoardState(); if (!board.MakeMove(moves[i])) { continue; } score = -Quiescence(board, oppositeSide, -beta, -alpha); board.RestoreState(state); if (score >= beta) { return beta; } if (score > alpha) { alpha = score; } } return alpha; }
// a depth limited quiescence to prevent this from going on and on... private static int Quiescence_Limited(Board board, sbyte side, int alpha, int beta, int depthLeft) { int standingPat = Evaluation2.EvaluateFromPerspectiveOf(board, side); if (depthLeft == 0) { return standingPat; } if (standingPat >= beta) { return beta; } if (alpha < standingPat) { alpha = standingPat; } sbyte oppositeSide = (sbyte)(-1 * side); int movesCount; UInt16[] moves = board.GenerateCaptureMoves(out movesCount); int score; BoardState state; for (int i = 0; i < movesCount; i++) { state = board.GetBoardState(); if (!board.MakeMove(moves[i])) { continue; } score = -Quiescence_Limited(board, oppositeSide, -beta, -alpha, depthLeft - 1); board.RestoreState(state); if (score >= beta) { return beta; } if (score > alpha) { alpha = score; } } return alpha; }
public static Tuple<UInt16, int> RootAlphaBetaTT(Board board, sbyte side, int depth) { int movesCount; UInt16[] moves = board.GenerateMoves(out movesCount); //nodesCount = moves.Count; UInt16 bestMove = moves[0]; int maxScore = Constants.NegativeInfinity; int score; sbyte oppositeSide = (sbyte)(side * -1); BoardState state; // Search search = new Search(); for (int i = 0; i < movesCount; i++) { state = board.GetBoardState(); if (!board.MakeMove(moves[i])) { continue; } score = -AlphaBetaTT(board, Constants.NegativeInfinity, Constants.PositiveInfinity, (byte)(depth - 1), oppositeSide, new UInt16[depth], 0); board.RestoreState(state); if (score > maxScore) { maxScore = score; bestMove = moves[i]; } } return new Tuple<UInt16, int>(bestMove, maxScore); }
public static Tuple<UInt16, int> RootAlphaBetaTTParallel(Board board, sbyte side, int depth, int alpha = Constants.NegativeInfinity, int beta = Constants.PositiveInfinity) { int movesCount; UInt16[] moves = board.GenerateMoves(out movesCount); UInt16 bestMove = moves[0]; int maxScore = Constants.NegativeInfinity; sbyte oppositeSide = (sbyte)(side * -1); int[] scores = new int[movesCount]; Board[] boards = new Board[movesCount]; // Search[] searches = new Search[moves.Count]; Parallel.For(0, movesCount, i => { boards[i] = new Board(board.GetBoardState()); }); Parallel.For(0, movesCount, i => { if (!boards[i].MakeMove(moves[i])) { scores[i] = Constants.NegativeInfinity; return; } scores[i] = -AlphaBetaTT(boards[i], -beta, -alpha, (byte)(depth - 1), oppositeSide, new UInt16[depth], 0); }); for (int i = 0; i < scores.Length; i++) { if (scores[i] > maxScore) { maxScore = scores[i]; bestMove = moves[i]; } } return new Tuple<UInt16, int>(bestMove, maxScore); }
public void Game6VsTitan_BadMoveLostQueen() { Board board = new Board(); board.MakeUserMove("b1c3 "); board.MakeUserMove("d7d5"); board.MakeUserMove("e2e3 "); board.MakeUserMove("b8c6"); board.MakeUserMove("f1b5 "); board.MakeUserMove("a7a6"); board.MakeUserMove("b5c6 "); board.MakeUserMove("b7c6"); board.MakeUserMove("d2d4"); board.MakeUserMove("e7e5"); board.MakeUserMove("d4e5 "); board.MakeUserMove("d8g5"); board.MakeUserMove("e1f1 "); board.MakeUserMove("g5e5"); board.MakeUserMove("g1f3 "); board.MakeUserMove("e5h5"); board.MakeUserMove("d1d4 "); board.MakeUserMove("c8f5"); board.MakeUserMove("d4a4 "); board.MakeUserMove("f5d7"); board.MakeUserMove("a4b3 "); board.MakeUserMove("a6a5"); board.MakeUserMove("b3b7 "); board.MakeUserMove("a8c8"); board.MakeUserMove("c3e2 "); board.MakeUserMove("f8d6"); board.MakeUserMove("e2f4 "); board.MakeUserMove("h5f5"); board.MakeUserMove("f3d4 "); board.MakeUserMove("f5f6 "); board.MakeUserMove("d4c6 "); board.MakeUserMove("d6f4"); board.MakeUserMove("c6a7 "); board.MakeUserMove("f4e3"); board.MakeUserMove("c1e3 "); board.MakeUserMove("c8d8"); board.MakeUserMove("a1e1 "); board.MakeUserMove("g8e7"); board.MakeUserMove("e3c5 "); board.MakeUserMove("d7e6"); board.MakeUserMove("c5e7 "); board.MakeUserMove("e8e7"); board.MakeUserMove("b7c7 "); board.MakeUserMove("e7e8"); board.MakeUserMove("a7c6 "); board.MakeUserMove("d5d4"); board.MakeUserMove("h1g1 "); board.MakeUserMove("g7g6"); board.MakeUserMove("c2c3 "); board.MakeUserMove("d8a8"); board.MakeUserMove("c7b7 "); board.MakeUserMove("a8d8"); board.MakeUserMove("c6d8 "); board.MakeUserMove("f6d8"); board.MakeUserMove("b7b5 "); board.MakeUserMove("e8f8"); board.MakeUserMove("e1d1 "); board.MakeUserMove("e6a2"); board.MakeUserMove("d1d4 "); board.MakeUserMove("d8c7"); board.MakeUserMove("b5a6 "); board.MakeUserMove("f8g7"); board.MakeUserMove("f2f4 "); board.MakeUserMove("h8d8"); // Generate move here for white to play Tuple<UInt16, int> moveAndScore = AlphaBeta2.RootAlphaBetaTTParallel(board, 1, 7); board.MakeMove(moveAndScore.Item1); // following was bad move by FM board.MakeUserMove("d4d8"); board.MakeUserMove("a2c4"); }
public static Tuple<UInt16, int, long, int> IterativeDeepeningParallel(Board board, sbyte side) { // NOTE: following are dummy values to prevent compiler error. Tuple<UInt16, int> moveAndScore = new Tuple<UInt16, int>(0, -10000000); Stopwatch sw = new Stopwatch(); int depth; sw.Start(); for (depth = MinDepth; depth <= MaxDepth; depth++) { moveAndScore = RootAlphaBetaTTParallel(board, side, depth); if (sw.ElapsedMilliseconds >= TimeLimitInMilliseconds) { sw.Stop(); break; } } return new Tuple<ushort, int, long, int>(moveAndScore.Item1, depth, sw.ElapsedMilliseconds, moveAndScore.Item2); }
public void Game7VsTitan_NotCheckmating() { Board board = new Board(); board.MakeUserMove("d2d4 "); board.MakeUserMove("d7d5"); board.MakeUserMove("c2c3 "); board.MakeUserMove("g8f6"); board.MakeUserMove("g2g3 "); board.MakeUserMove("e7e6"); board.MakeUserMove("c1g5 "); board.MakeUserMove("f8d6"); board.MakeUserMove("e2e4 "); board.MakeUserMove("d5e4"); board.MakeUserMove("b1d2 "); board.MakeUserMove("d6e7"); board.MakeUserMove("d1a4 "); board.MakeUserMove("d8d7"); board.MakeUserMove("a4c2 "); board.MakeUserMove("e8g8"); board.MakeUserMove("f1h3 "); board.MakeUserMove("b8c6"); board.MakeUserMove("g5f6 "); board.MakeUserMove("g7f6"); board.MakeUserMove("c2e4 "); board.MakeUserMove("f6f5"); board.MakeUserMove("e4e3 "); board.MakeUserMove("b7b5"); board.MakeUserMove("h3g2 "); board.MakeUserMove("c8b7"); board.MakeUserMove("g1f3 "); board.MakeUserMove("f7f6"); board.MakeUserMove("f3h4 "); board.MakeUserMove("f8b8 "); board.MakeUserMove("d2b3 "); board.MakeUserMove("b5b4"); board.MakeUserMove("b3c5 "); board.MakeUserMove("e7c5"); board.MakeUserMove("d4c5 "); board.MakeUserMove("a7a5"); board.MakeUserMove("a2a3 "); board.MakeUserMove("e6e5"); board.MakeUserMove("a1d1 "); board.MakeUserMove("d7e6"); board.MakeUserMove("g2d5 "); board.MakeUserMove("e6d5"); board.MakeUserMove("d1d5 "); board.MakeUserMove("c6e7"); board.MakeUserMove("d5d7 "); board.MakeUserMove("b7h1"); board.MakeUserMove("d7e7 "); board.MakeUserMove("b4a3 "); board.MakeUserMove("e3h6 "); board.MakeUserMove("g8h8"); // Generate move here for white to play Tuple<UInt16, int> moveAndScore = AlphaBeta2.RootAlphaBetaTT(board, 1, 6); // AlphaBeta2.RootAlphaBetaTTParallel(board, 1, 6); board.MakeMove(moveAndScore.Item1); // following was bad move by FM board.MakeUserMove("d4d8"); board.MakeUserMove("a2c4"); }
public void Defect2VsTitan() { Board board = new Board(); board.MakeUserMove("e2e4"); board.MakeUserMove("c7c6"); board.MakeUserMove("b1c3"); board.MakeUserMove("d7d5"); board.MakeUserMove("e4d5"); board.MakeUserMove("c6d5"); board.MakeUserMove("f1b5"); board.MakeUserMove("b8c6"); board.MakeUserMove("d2d4"); board.MakeUserMove("a7a6"); board.MakeUserMove("b5c6"); board.MakeUserMove("b7c6"); board.MakeUserMove("a2a3"); board.MakeUserMove("g8f6"); board.MakeUserMove("g1e2"); board.MakeUserMove("e7e6"); board.MakeUserMove("e1g1"); board.MakeUserMove("f8e7"); board.MakeUserMove("c1g5"); board.MakeUserMove("e8g8"); board.MakeUserMove("d1d3"); board.MakeUserMove("c8b7"); board.MakeUserMove("h2h3"); board.MakeUserMove("f8e8"); board.MakeUserMove("a3a4"); board.MakeUserMove("h7h6"); board.MakeUserMove("g5f6"); board.MakeUserMove("e7f6"); board.MakeUserMove("c3d1"); board.MakeUserMove("e6e5"); board.MakeUserMove("d4e5"); board.MakeUserMove("f6e5"); board.MakeUserMove("c2c3"); board.MakeUserMove("c6c5"); board.MakeUserMove("d3c2"); board.MakeUserMove("d5d4"); board.MakeUserMove("c2b3"); board.MakeUserMove("b7d5"); board.MakeUserMove("c3c4"); board.MakeUserMove("a8b8"); board.MakeUserMove("b3d3"); board.MakeUserMove("d5e4"); board.MakeUserMove("d3d2"); board.MakeUserMove("d8d6"); board.MakeUserMove("f2f4"); board.MakeUserMove("d6g6"); board.MakeUserMove("g2g4"); board.MakeUserMove("e5d6"); board.MakeUserMove("a1a3"); board.MakeUserMove("g6e6"); board.MakeUserMove("b2b3"); board.MakeUserMove("e4c6"); board.MakeUserMove("e2g3"); board.MakeUserMove("f7f6"); board.MakeUserMove("d2c1"); board.MakeUserMove("a6a5"); board.MakeUserMove("c1d2"); board.MakeUserMove("d6c7"); board.MakeUserMove("d2c1"); board.MakeUserMove("c7d6"); board.MakeUserMove("c1d2"); board.MakeUserMove("b8a8"); board.MakeUserMove("a3a1"); board.MakeUserMove("g7g6"); board.MakeUserMove("d2c2"); board.MakeUserMove("e6f7"); board.MakeUserMove("c2d2"); board.MakeUserMove("f7b7"); board.MakeUserMove("d2b2"); board.MakeUserMove("b7d7"); // Generate move here for white to play Tuple<UInt16, int> moveAndScore = AlphaBeta2.RootAlphaBetaTTParallel(board, 1, 6); board.MakeMove(moveAndScore.Item1); }
static void Main(string[] args) { // variables sbyte ownSide; Board board = new Board(); Stack<BoardState> undoStack = new Stack<BoardState>(); // int depth = 6; UInt16 move; Tuple<UInt16, int, long, int> moveDepthTimeAndScore; string opponentMoveString; Console.WriteLine("Filthy Mind Chess"); Console.WriteLine(); /*********** Input opponent side ************/ while (true) { Console.Write("Choose your side (w/b): "); char opponentSideChar = Console.ReadKey().KeyChar; Console.WriteLine(); if (opponentSideChar == 'w') { ownSide = Side.Black; break; } else if (opponentSideChar == 'b') { ownSide = Side.White; break; } else { Console.WriteLine("Invalid side."); } } /*************** End of input opponent side ******************/ /*************** Start game *******************/ Console.WriteLine("Start playing."); Console.WriteLine(); if (ownSide == Side.White) { moveDepthTimeAndScore = AlphaBeta2.IDASParallel(board, ownSide); // AlphaBeta2.IterativeDeepeningParallel(board, ownSide); // AlphaBeta2.RootAlphaBetaTTParallel(board, ownSide, depth).Item1; move = moveDepthTimeAndScore.Item1; if (board.MakeMove(move)) { Console.WriteLine("Filthy Mind: {0} (Depth: {1} plies; Time: {2}ms; Score: {3})", board.ConvertToAlgebraicNotation(move), moveDepthTimeAndScore.Item2, moveDepthTimeAndScore.Item3, moveDepthTimeAndScore.Item4); } } while (true) { Console.Write("You: "); opponentMoveString = Console.ReadLine(); if (opponentMoveString.ToLower() == "exit") { break; } if (opponentMoveString.ToLower() == "fen") { Console.WriteLine("Board Position: {0}", board.ToString()); continue; } if (opponentMoveString.Trim().ToLower() == "undo") { if (undoStack.Count > 0) { board.RestoreState(undoStack.Pop()); Console.WriteLine("Undid last move."); } else { Console.WriteLine("Nothing to undo!"); } continue; } try { undoStack.Push(board.GetBoardState()); if (!board.MakeUserMove(opponentMoveString)) { Console.WriteLine("Failed to make move. Try again."); undoStack.Pop(); continue; } } catch (Exception ex) { undoStack.Pop(); Console.WriteLine("ERROR: {0}", ex.Message); continue; } // make move for own side moveDepthTimeAndScore = AlphaBeta2.IDASParallel(board, ownSide); // AlphaBeta2.IterativeDeepeningParallel(board, ownSide); // AlphaBeta2.RootAlphaBetaTTParallel(board, ownSide, depth).Item1; move = moveDepthTimeAndScore.Item1; if (board.MakeMove(move)) { Console.WriteLine("Filthy Mind: {0} (Depth: {1} plies; Time: {2}ms; Score: {3})", board.ConvertToAlgebraicNotation(move), moveDepthTimeAndScore.Item2, moveDepthTimeAndScore.Item3, moveDepthTimeAndScore.Item4); } } Console.WriteLine("End of the game. Press any key to close the window."); Console.ReadKey(); /*************** End of game ******************/ }
private static int EvaluateForWhite(Board board) { int score = 0; // pawns byte[] pieceIndices = BitHelper.GetSetBitIndexes2(board.PieceToBitboard[Constants.WhitePawnNumber + 6]); int opponentPiecesCount = BitHelper.GetNumberOfSetBits(board.PieceToBitboard[Constants.BlackPawnNumber + 6]); score += CalculateScore(pieceIndices, opponentPiecesCount, PawnValue, WhitePawnSquareTable); // rooks pieceIndices = BitHelper.GetSetBitIndexes2(board.PieceToBitboard[Constants.WhiteRookNumber + 6]); opponentPiecesCount = BitHelper.GetNumberOfSetBits(board.PieceToBitboard[Constants.BlackRookNumber + 6]); score += CalculateScore(pieceIndices, opponentPiecesCount, RookValue, WhiteRookSquareTable); // knights pieceIndices = BitHelper.GetSetBitIndexes2(board.PieceToBitboard[Constants.WhiteKnightNumber + 6]); opponentPiecesCount = BitHelper.GetNumberOfSetBits(board.PieceToBitboard[Constants.BlackKnightNumber + 6]); score += CalculateScore(pieceIndices, opponentPiecesCount, KnightValue, WhiteKnightSquareTable); // bishops pieceIndices = BitHelper.GetSetBitIndexes2(board.PieceToBitboard[Constants.WhiteBishopNumber + 6]); opponentPiecesCount = BitHelper.GetNumberOfSetBits(board.PieceToBitboard[Constants.BlackBishopNumber + 6]); score += CalculateScore(pieceIndices, opponentPiecesCount, BishopValue, WhiteBishopSquareTable); // queens pieceIndices = BitHelper.GetSetBitIndexes2(board.PieceToBitboard[Constants.WhiteQueenNumber + 6]); opponentPiecesCount = BitHelper.GetNumberOfSetBits(board.PieceToBitboard[Constants.BlackQueenNumber + 6]); score += CalculateScore(pieceIndices, opponentPiecesCount, QueenValue, WhiteQueenSquareTable); // king int[] kingSquareTable = (board.GetGameStage() == Constants.GameStage_Middle) ? WhiteKingMiddleGameSquareTable : WhiteKingEndGameSquareTable; pieceIndices = BitHelper.GetSetBitIndexes2(board.PieceToBitboard[Constants.WhiteKingNumber + 6]); opponentPiecesCount = BitHelper.GetNumberOfSetBits(board.PieceToBitboard[Constants.BlackKingNumber + 6]); score += CalculateScore(pieceIndices, opponentPiecesCount, KingValue, kingSquareTable); return score; }
public static int EvaluateFromPerspectiveOf(Board board, int side) { if (side == Side.White) { return EvaluateForWhite(board); } else { return EvaluateForBlack(board); } }
public void WhenPlayingAgainstHammad() { Board board = new Board(); board.MakeUserMove("d2d4"); board.MakeUserMove("g8f6"); board.MakeUserMove("g1f3"); board.MakeUserMove("d7d5"); board.MakeUserMove("b1c3"); board.MakeUserMove("b8c6"); board.MakeUserMove("c1g5"); board.MakeUserMove("f6e4"); board.MakeUserMove("d1d2"); board.MakeUserMove("e4d2"); board.MakeUserMove("e1d2"); board.MakeUserMove("h7h6"); board.MakeUserMove("g5f4"); board.MakeUserMove("e7e6"); board.MakeUserMove("f4e5"); board.MakeUserMove("f8b4"); // now do search Tuple<UInt16, int> moveAndScore = AlphaBeta2.RootAlphaBetaTTParallel(board, -1, 6); board.MakeMove(moveAndScore.Item1); }
public void TestQuiescenceDepth() { Board board = new Board(); // Generate move here for white to play Tuple<UInt16, int> moveAndScore = AlphaBeta2.RootAlphaBetaTT(board, 1, 6); // AlphaBeta2.RootAlphaBetaTTParallel(board, 1, 6); board.MakeMove(moveAndScore.Item1); // following was bad move by FM board.MakeUserMove("d4d8"); board.MakeUserMove("a2c4"); }
// Iterative Deepening Aspiration Search Parallel public static Tuple<UInt16, int, long, int> IDASParallel(Board board, sbyte side) { // threshold value of one-third of a pawn value (100) based on http://www.frayn.net/beowulf/theory.html#aspiration int threshold = 30; // NOTE: following are dummy values to prevent compiler error. Tuple<UInt16, int> moveAndScore = new Tuple<UInt16, int>(0, -10000000); Stopwatch sw = new Stopwatch(); int depth, depthSearched = 0; moveAndScore = RootAlphaBetaTTParallel(board, side, MinDepth, Constants.NegativeInfinity, Constants.PositiveInfinity); int best = moveAndScore.Item2; sw.Start(); for (depth = MinDepth + 1; depth <= MaxDepth; depth++) { moveAndScore = RootAlphaBetaTTParallel(board, side, depth, best - threshold, best + threshold); if (moveAndScore.Item2 <= (best - threshold)) // failed low { moveAndScore = RootAlphaBetaTTParallel(board, side, depth, Constants.NegativeInfinity, moveAndScore.Item2); } else if (moveAndScore.Item2 >= (best + threshold)) // failed high { moveAndScore = RootAlphaBetaTTParallel(board, side, depth, moveAndScore.Item2, Constants.PositiveInfinity); } //else //{ best = moveAndScore.Item2; //} depthSearched = depth; if (sw.ElapsedMilliseconds >= TimeLimitInMilliseconds) { sw.Stop(); break; } } return new Tuple<ushort, int, long, int>(moveAndScore.Item1, depthSearched, sw.ElapsedMilliseconds, best); }
public void Defect3VsTitan_Quiesc() { Board board = new Board(); board.MakeUserMove("g1f3"); board.MakeUserMove("g8f6"); board.MakeUserMove("d2d4"); board.MakeUserMove("e7e6"); board.MakeUserMove("c1g5"); board.MakeUserMove("c7c5"); board.MakeUserMove("b1c3"); board.MakeUserMove("c5d4"); board.MakeUserMove("f3d4"); board.MakeUserMove("e6e5"); board.MakeUserMove("d4b3"); board.MakeUserMove("f8e7"); board.MakeUserMove("g5f6"); board.MakeUserMove("e7f6"); board.MakeUserMove("e2e4"); board.MakeUserMove("e8g8"); board.MakeUserMove("f1c4"); board.MakeUserMove("b8c6"); board.MakeUserMove("e1g1"); board.MakeUserMove("d7d6"); board.MakeUserMove("f1e1"); board.MakeUserMove("f6g5"); board.MakeUserMove("d1d3"); bool success = board.MakeUserMove("d1d3"); // Generate move here for white to play Tuple<UInt16, int> moveAndScore = AlphaBeta2.RootAlphaBetaTTParallel(board, 1, 6); board.MakeMove(moveAndScore.Item1); }
public static int AlphaBetaTT(Board board, int alpha, int beta, byte depthLeft, sbyte side, UInt16[] killers, int level) { int score; TranspositionTableEntry entry = transpositionTable.Retrieve(board.ZobristHash); if (entry.IsValid() && (TranspositionTableEntryHelper.GetDepthSearched(entry.Data) >= depthLeft)) { if (TranspositionTableEntryHelper.GetEntryType(entry.Data) == TranspositionTableEntryHelper.EntryTypeExactValue) { return TranspositionTableEntryHelper.GetScore(entry.Data); } if ((TranspositionTableEntryHelper.GetEntryType(entry.Data) == TranspositionTableEntryHelper.EntryTypeLowerBound) && (TranspositionTableEntryHelper.GetScore(entry.Data) > alpha)) { alpha = TranspositionTableEntryHelper.GetScore(entry.Data); } else if ((TranspositionTableEntryHelper.GetEntryType(entry.Data) == TranspositionTableEntryHelper.EntryTypeUpperBound) && (TranspositionTableEntryHelper.GetScore(entry.Data) < beta)) { beta = TranspositionTableEntryHelper.GetScore(entry.Data); } if (alpha >= beta) { return TranspositionTableEntryHelper.GetScore(entry.Data); } } if (depthLeft == 0) { score = Quiescence_Limited(board, side, alpha, beta, (level + 1) % 2); // the last arg ensures that quiescence evaluates opponent's move as the last one. // Quiescence(board, side, alpha, beta); // Evaluation2.EvaluateFromPerspectiveOf(board, side); if (score <= alpha) { transpositionTable.Add(new TranspositionTableEntry(board.ZobristHash, TranspositionTableEntryHelper.ComposeData(score, TranspositionTableEntryHelper.InvalidMove, depthLeft, TranspositionTableEntryHelper.EntryTypeLowerBound))); } else if (score >= beta) { transpositionTable.Add(new TranspositionTableEntry(board.ZobristHash, TranspositionTableEntryHelper.ComposeData(score, TranspositionTableEntryHelper.InvalidMove, depthLeft, TranspositionTableEntryHelper.EntryTypeUpperBound))); } else { transpositionTable.Add(new TranspositionTableEntry(board.ZobristHash, TranspositionTableEntryHelper.ComposeData(score, TranspositionTableEntryHelper.InvalidMove, depthLeft, TranspositionTableEntryHelper.EntryTypeExactValue))); } return score; } int movesCount; UInt16[] moves = board.GenerateMoves(out movesCount); #region Move Ordering // this is the index with which a good move will be swapped with... int indexToSwapWith = 0; /*************** Transposition Table Reordering **************/ // NOTE (17 Jul 2013): There appears to be no gain from transposition table re-ordering, therefore // commenting it out. //if (entry.IsValid()) //{ // UInt16 bestMoveFromTable = TranspositionTableEntryHelper.GetBestMove(entry.Data); // if (bestMoveFromTable != TranspositionTableEntryHelper.InvalidMove) // { // for (int i = 0; i < movesCount; i++) // { // if (moves[i] == bestMoveFromTable) // { // // swap... // UInt16 temp = moves[i]; // moves[i] = moves[indexToSwapWith]; // moves[indexToSwapWith] = temp; // indexToSwapWith++; // break; // } // } // } //} /*************** End of Transposition Table Reordering **************/ /*************** Killer Heuristic Reordering *****************/ if (killers[level] != 0) { for (int i = 0; i < movesCount; i++) { if (killers[level] == moves[i]) { // if killer move found then swap that with the first move. UInt16 temp = moves[i]; moves[i] = moves[indexToSwapWith]; moves[indexToSwapWith] = temp; indexToSwapWith++; break; } } } // set killer for next level to 0 killers[level + 1] = 0; /*************** End of Killer Heuristic Reordering *****************/ #endregion // NOTE: diluting negative infinity by level so that the farther away the checkmate is from current // board position the lower will be the score. this is to get the engine to checkmate opponent // as soon as possible rather than wasting time in capture or other moves which ultimately lead to // checkmate but are not the fastest route to checkmakte. int bestScore = Constants.NegativeInfinity + level; UInt16 bestMove = TranspositionTableEntryHelper.InvalidMove; BoardState state; sbyte oppositeSide = (sbyte)(-1 * side); for (int i = 0; i < movesCount; i++) { state = board.GetBoardState(); if (!board.MakeMove(moves[i])) { continue; } score = -AlphaBetaTT(board, -beta, -alpha, (byte)(depthLeft - 1), oppositeSide, killers, level + 1); board.RestoreState(state); if (score > bestScore) { bestScore = score; bestMove = moves[i]; } if (bestScore > alpha) { alpha = bestScore; } if (bestScore >= beta) { // beta-cutoff, therefore update killer for this level killers[level] = moves[i]; break; } } // following nested ifs check for stalemate. if (bestScore == (Constants.NegativeInfinity + level)) { if (!board.IsInCheck(side)) { bestScore = Constants.DrawScore; } } if (bestScore <= alpha) // lower bound value { transpositionTable.Add(new TranspositionTableEntry(board.ZobristHash, TranspositionTableEntryHelper.ComposeData(bestScore, bestMove, depthLeft, TranspositionTableEntryHelper.EntryTypeLowerBound))); } else if (bestScore >= beta) // upper bound value { transpositionTable.Add(new TranspositionTableEntry(board.ZobristHash, TranspositionTableEntryHelper.ComposeData(bestScore, bestMove, depthLeft, TranspositionTableEntryHelper.EntryTypeUpperBound))); } else // true minimax value { transpositionTable.Add(new TranspositionTableEntry(board.ZobristHash, TranspositionTableEntryHelper.ComposeData(bestScore, bestMove, depthLeft, TranspositionTableEntryHelper.EntryTypeExactValue))); } return bestScore; }
public static Tuple<UInt16, int> IterativeDeepening(Board board, sbyte side, int depth) { // NOTE: following are dummy values to prevent compiler error. Tuple<UInt16, int> moveAndScore = new Tuple<UInt16, int>(0, -10000000); for (int i = 2; i <= depth; i++) { moveAndScore = RootAlphaBetaTT(board, side, i); } return moveAndScore; }
public static void MakeSomeMoves(Board board) { List<UInt64> hashesSoFar = new List<UInt64>(); hashesSoFar.Add(board.ZobristHash); bool success; board.MakeUserMove("e2e4"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); string fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("c7c5"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("g1f3"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("b8c6"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("d2d4"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("e7e6"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("c1e3"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("g7g6"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("d4c5"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); board.MakeUserMove("f8g7"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); board.MakeUserMove("f1c4"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); board.MakeUserMove("g8f6"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); board.MakeUserMove("b1c3"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); board.MakeUserMove("b7b6"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); board.MakeUserMove("d1d2"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); board.MakeUserMove("c8b7"); board.MakeUserMove("e3f4"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); success = board.MakeUserMove("d8e7"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); success = board.MakeUserMove("e4e5"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); success = board.MakeUserMove("d7d5"); if (hashesSoFar.Contains(board.ZobristHash)) { throw new InvalidOperationException("Hash Already Included!!"); } hashesSoFar.Add(board.ZobristHash); fenString = board.ToString(); Debug.WriteLine(fenString); }
static void Main(string[] args) { // variables sbyte opponentSide, ownSide; Board board = new Board(); Move move; int depth = 4; string opponentMoveString; Console.WriteLine("Filthy Mind Chess"); Console.WriteLine(); /*********** Input opponent side ************/ while (true) { Console.Write("Choose your side (w/b): "); char opponentSideChar = Console.ReadKey().KeyChar; Console.WriteLine(); if (opponentSideChar == 'w') { opponentSide = Side.White; ownSide = Side.Black; break; } else if (opponentSideChar == 'b') { opponentSide = Side.Black; ownSide = Side.White; break; } else { Console.WriteLine("Invalid side."); } } /*************** End of input opponent side ******************/ /*************** Start game *******************/ Console.WriteLine("Start playing."); Console.WriteLine(); if (ownSide == Side.White) { move = Search.RootAlphaBetaParallel(board, ownSide, depth).Item1; if (board.MakeMove(move)) { Console.WriteLine("Filthy Mind: {0}", move.ToString()); } } while (true) { Console.Write("You: "); opponentMoveString = Console.ReadLine(); if (opponentMoveString.ToLower() == "exit") { break; } try { move = new Move(opponentSide, opponentMoveString); } catch (Exception ex) { Console.WriteLine("ERROR: {0}", ex.Message); continue; } if (!board.MakeMove(move)) { Console.WriteLine("Failed to make move. Try again."); continue; } // make move for own side move = Search.RootAlphaBetaParallel(board, ownSide, depth).Item1; if (board.MakeMove(move)) { Console.WriteLine("Filthy Mind: {0}", move.ToString()); } } Console.WriteLine("End of the game. Press any key to close the window."); Console.ReadKey(); /*************** End of game ******************/ }