From 9459cde45d1a7ef72615ba058acf2ec563084e59 Mon Sep 17 00:00:00 2001 From: Coding with Tom <146443103+hcsalmon1@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:56:27 +0000 Subject: [PATCH] Create Perft_Debug.cs --- C#/Cleaner and slower version/Perft_Debug.cs | 323 +++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 C#/Cleaner and slower version/Perft_Debug.cs diff --git a/C#/Cleaner and slower version/Perft_Debug.cs b/C#/Cleaner and slower version/Perft_Debug.cs new file mode 100644 index 0000000..8c4b374 --- /dev/null +++ b/C#/Cleaner and slower version/Perft_Debug.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using static CEngineCopy.Debugging; +using static CEngineCopy.Board; + + +namespace CEngineCopy +{ + internal class Perft_Debug + { + + struct ErrorInt { + public Error? Error { get; } + public int Value { get; set; } + + private ErrorInt(Error? error, int value) { + Error = error; + Value = value; + } + public static ErrorInt FromValue(int value) { + return new ErrorInt(null, value); + } + public static ErrorInt FromError(Error error) { + return new ErrorInt(error, default); + } + public static void PrintError(Error error) { + Console.WriteLine(error); + } + } + + enum Error + { + White_King_Captured, + Black_King_Captured, + Too_Many_Moves, + White_King_In_Check_On_BlackMove, + Black_King_In_Check_On_White_Move, + Copy_Boards_Not_Same, + Invalid_Starting_Square, + Invalid_Target_Square, + Invalid_Tag, + Invalid_Piece, + Capture_Index_Invalid, + Capture_Piece_Not_Found, + Starting_Depth_Too_High, + Starting_Depth_Zero, + Depth_Less_Than_Zero, + Starting_Square_And_Target_Square_The_Same, + Ep_Not_Target_Square, + Promotion_When_Not_Expected, + Side_Not_Changed, + Side_Not_Changed_Back, + Piece_On_Same_Square, + } + + static ulong CombineBitboardsGlobal() + { + return Board.bitboard_array_global[0] | + Board.bitboard_array_global[1] | + Board.bitboard_array_global[2] | + Board.bitboard_array_global[3] | + Board.bitboard_array_global[4] | + Board.bitboard_array_global[5] | + Board.bitboard_array_global[6] | + Board.bitboard_array_global[7] | + Board.bitboard_array_global[8] | + Board.bitboard_array_global[9] | + Board.bitboard_array_global[10] | + Board.bitboard_array_global[11]; + } + + struct DebugInfo + { + public int CallCount; + public int LastStarting; + public int LastTarget; + public int LastTag; + public bool PromotionExpected; + } + + static ulong GetWhiteOccs() + { + return Board.bitboard_array_global[0] | Board.bitboard_array_global[1] | Board.bitboard_array_global[2] | Board.bitboard_array_global[3] | Board.bitboard_array_global[4] | Board.bitboard_array_global[5]; + } + static ulong GetBlackOccs() + { + return Board.bitboard_array_global[6] | Board.bitboard_array_global[7] | Board.bitboard_array_global[8] | Board.bitboard_array_global[9] | Board.bitboard_array_global[10] | Board.bitboard_array_global[11]; + } + + static ErrorInt InitialDebugChecks(int depth) + { + if (depth < 0) + { + return ErrorInt.FromError(Error.Depth_Less_Than_Zero); + } + if (Board.bitboard_array_global[Constants.WK] == 0) + { + return ErrorInt.FromError(Error.White_King_Captured); + } + if (Board.bitboard_array_global[Constants.BK] == 0) + { + return ErrorInt.FromError(Error.Black_King_Captured); + } + ulong COMBINED_OCCUPANCIES = CombineBitboardsGlobal(); + if (Board.is_white_global == true) + { + int blackKingPosition = MoveUtils.BitScanForward(Board.bitboard_array_global[Constants.BK]); + if (MoveUtils.Is_Square_Attacked_By_White_Global(blackKingPosition, COMBINED_OCCUPANCIES) == true) + { + return ErrorInt.FromError(Error.Black_King_In_Check_On_White_Move); + } + } + else + { + int whiteKingPosition = MoveUtils.BitScanForward(Board.bitboard_array_global[Constants.WK]); + if (MoveUtils.Is_Square_Attacked_By_Black_Global(whiteKingPosition, COMBINED_OCCUPANCIES) == true) + { + return ErrorInt.FromError(Error.White_King_In_Check_On_BlackMove); + } + } + return ErrorInt.FromValue(0); + } + + static ErrorInt MoveErrorChecking(ref DebugInfo debugInfo, int startingSquareCopy, int targetSquareCopy, int piece, int tag) + { + if (startingSquareCopy < 0 || startingSquareCopy > 63) + { + return ErrorInt.FromError(Error.Invalid_Starting_Square); + } + if (targetSquareCopy < 0 || targetSquareCopy > 63) + { + return ErrorInt.FromError(Error.Invalid_Target_Square); + } + if (piece < 0 || piece > 11) + { + return ErrorInt.FromError(Error.Invalid_Piece); + } + if (tag < 0 || tag > 27) + { + return ErrorInt.FromError(Error.Invalid_Tag); + } + if (startingSquareCopy == targetSquareCopy) + { + return ErrorInt.FromError(Error.Starting_Square_And_Target_Square_The_Same); + } + if (tag == Constants.TAG_WHITE_EP || tag == Constants.TAG_BLACK_EP) + { + if (Board.ep_global != targetSquareCopy) + { + return ErrorInt.FromError(Error.Ep_Not_Target_Square); + } + } + if (debugInfo.PromotionExpected == false) + { + if (tag >= Constants.TAG_B_N_PROMOTION && tag <= Constants.TAG_W_R_PROMOTION_CAP) + { + Debugging.PrintAllDebug(startingSquareCopy, targetSquareCopy, piece, tag, -1); + return ErrorInt.FromError(Error.Promotion_When_Not_Expected); + } + } + return ErrorInt.FromValue(0); + } + + static ErrorInt PerftFunctionsDebug(int depth, int ply, ref DebugInfo debugInfo) + { + + ErrorInt checkResult = InitialDebugChecks(depth); + if (checkResult.Error.HasValue) { + return checkResult; + } + + debugInfo.CallCount += 1; + if (depth == 0) + { + return ErrorInt.FromValue(1); + } + + //Same as move list, span to avoid heap allocation + Span startingSquares = stackalloc int[50]; + Span targetSquares = stackalloc int[50]; + Span tags = stackalloc int[50]; + Span pieces = stackalloc int[50]; + + int moveCount = GenMoves.GetMoves(ref startingSquares, ref targetSquares, ref tags, ref pieces); + + ErrorInt nodes = ErrorInt.FromValue(0); + + int copyEp = Board.ep_global; + Span copy_castle = stackalloc bool[4]; + copy_castle[0] = Board.castle_rights_global[0]; + copy_castle[1] = Board.castle_rights_global[1]; + copy_castle[2] = Board.castle_rights_global[2]; + copy_castle[3] = Board.castle_rights_global[3]; + + ulong[] bitboardCopy = new ulong[12] + { + Board.bitboard_array_global[0], + Board.bitboard_array_global[1], + Board.bitboard_array_global[2], + Board.bitboard_array_global[3], + Board.bitboard_array_global[4], + Board.bitboard_array_global[5], + Board.bitboard_array_global[6], + Board.bitboard_array_global[7], + Board.bitboard_array_global[8], + Board.bitboard_array_global[9], + Board.bitboard_array_global[10], + Board.bitboard_array_global[11], + }; + + for (int move_index = 0; move_index < moveCount; ++move_index) + { + int startingSquareCopy = startingSquares[move_index]; + int targetSquareCopy = targetSquares[move_index]; + int piece = pieces[move_index]; + int tag = tags[move_index]; + + ErrorInt moveCheckResult = MoveErrorChecking(ref debugInfo, startingSquareCopy, targetSquareCopy, piece, tag); + if (moveCheckResult.Error.HasValue) { + return moveCheckResult; + } + + bool sideBefore = Board.is_white_global; + + int captureIndex = Make_Move.MakeMove(startingSquareCopy, targetSquareCopy, tag, piece); + + if (Board.is_white_global == sideBefore) { + return ErrorInt.FromError(Error.Side_Not_Changed); + } + + ulong WHITE_OCCS = GetWhiteOccs(); + ulong BLACK_OCCS = GetBlackOccs(); + if ((WHITE_OCCS & BLACK_OCCS) != 0) + { + PrintAllBitboards(); + PrintAllDebug(startingSquareCopy, targetSquareCopy, piece, tag, captureIndex); + return ErrorInt.FromError(Error.Piece_On_Same_Square); + } + + ErrorInt priorNodes = ErrorInt.FromValue(nodes.Value); + ErrorInt nodesToAdd = PerftFunctionsDebug(depth - 1, ply + 1, ref debugInfo); + if (nodesToAdd.Error.HasValue) + { + return nodesToAdd; + } + nodes.Value += nodesToAdd.Value; + + #region Unmakemove + + bool newSide = Board.is_white_global; + + Make_Move.UnmakeMove(startingSquareCopy, targetSquareCopy, piece, tag, captureIndex); + + if (Board.is_white_global == newSide) + { + return ErrorInt.FromError(Error.Side_Not_Changed_Back); + } + + castle_rights_global[0] = copy_castle[0]; + castle_rights_global[1] = copy_castle[1]; + castle_rights_global[2] = copy_castle[2]; + castle_rights_global[3] = copy_castle[3]; + ep_global = copyEp; + + ulong WHITE_OCCS_2 = GetWhiteOccs(); + ulong BLACK_OCCS_2 = GetBlackOccs(); + if ((WHITE_OCCS_2 & BLACK_OCCS_2) != 0) + { + PrintAllBitboards(); + PrintAllDebug(startingSquareCopy, targetSquareCopy, piece, tag, captureIndex); + return ErrorInt.FromError(Error.Piece_On_Same_Square); + } + + for (int i = 0; i < 12; i++) + { + if (Board.bitboard_array_global[i] != bitboardCopy[i]) + { + PrintAllBitboards(); + Console.WriteLine($"global {i}"); + PrintBitboard(Board.bitboard_array_global[i]); + Console.WriteLine($"copy {i}"); + PrintBitboard(bitboardCopy[i]); + PrintAllDebug(startingSquareCopy, targetSquareCopy, piece, tag, captureIndex); + return ErrorInt.FromError(Error.Copy_Boards_Not_Same); + } + } + + #endregion + + if (ply == 0) + { + PrintMoveNoNL(startingSquareCopy, targetSquareCopy, tag); + Console.Write($": {nodes.Value - priorNodes.Value}\n"); + } + } + + return nodes; + } + + public static void RunPerftFunctionsDebug(int depth) + { + DateTime start = DateTime.Now; + DebugInfo debugInfo = new(); + debugInfo.PromotionExpected = false; + + ErrorInt nodes = PerftFunctionsDebug(depth, 0, ref debugInfo); + if (nodes.Error.HasValue) + { + Console.Write("ERROR: "); + ErrorInt.PrintError(nodes.Error.Value); + } + + DateTime end = DateTime.Now; + TimeSpan elapsed = end - start; + int elapsedTimeInMs = (int)elapsed.TotalMilliseconds; ; + Console.WriteLine($"Nodes: {nodes.Value}"); + + Console.WriteLine($"Elapsed time: {elapsedTimeInMs}ms"); + } + + + } +}