/// <summary> /// Returns string with text representations of all history boards from left to right. /// </summary> /// <returns></returns> public string BoardPictures() { string[] rows = new string[] { "", "", "", "", "", "", "", "", "", "" }; for (int i = 0; i < EncodedPositionBoards.NUM_MOVES_HISTORY; i++) { EncodedPositionBoard planes = GetPlanesForHistoryBoard(i); string lines = planes.GetBoardPicture(true); string[] parsed = lines.Split('\n'); for (int line = 0; line < parsed.Length; line++) { rows[line] += parsed[line] + " "; } } // Concatenate the lines across all boards StringBuilder allLines = new StringBuilder(); for (int i = 0; i < rows.Length; i++) { allLines.AppendLine(rows[i]); } return(allLines.ToString()); }
/// <summary> /// Runs CPU benchmark and outputs summary results, /// with an overall statistic provided (index to 100 on a Intel Skylake 6142). /// </summary> /// <returns>Relative CPU index (baseline 100)</returns> static int DumpCPUBenchmark() { Console.WriteLine("-----------------------------------------------------------------------------------"); Console.WriteLine("CPU BENCHMARK"); Position ps = Position.StartPosition; EncodedPositionBoard zb = default; MGMove nmove = ConverterMGMoveEncodedMove.EncodedMoveToMGChessMove(new EncodedMove("e2e4"), MGChessPositionConverter.MGChessPositionFromFEN(ps.FEN)); float ops1 = Benchmarking.DumpOperationTimeAndMemoryStats(() => MGPosition.FromPosition(ps), "MGPosition.FromPosition"); float ops2 = Benchmarking.DumpOperationTimeAndMemoryStats(() => MGChessPositionConverter.MGChessPositionFromFEN(ps.FEN), "MGChessPositionFromFEN"); float ops3 = Benchmarking.DumpOperationTimeAndMemoryStats(() => ConverterMGMoveEncodedMove.MGChessMoveToEncodedMove(nmove), "MGChessMoveToLZPositionMove"); float ops4 = Benchmarking.DumpOperationTimeAndMemoryStats(() => EncodedBoardZobrist.ZobristHash(zb), "ZobristHash"); // Performance metric is against a baseline system (Intel Skylake 6142) const float REFERENCE_BM1_OPS = 2160484; const float REFERENCE_BM2_OPS = 448074; const float REFERENCE_BM3_OPS = 157575582; const float REFERENCE_BM4_OPS = 112731351; float relative1 = ops1 / REFERENCE_BM1_OPS; float relative2 = ops2 / REFERENCE_BM2_OPS; float relative3 = ops3 / REFERENCE_BM3_OPS; float relative4 = ops4 / REFERENCE_BM4_OPS; float avg = StatUtils.Average(relative1, relative2, relative3, relative4); Console.WriteLine(); Console.WriteLine($"CERES CPU BENCHMARK SCORE: {avg*100,4:F0}"); return((int)MathF.Round(avg * 100, 0)); }
/// <summary> /// Returns the FEN string correpsonding to the position at specified history board. /// </summary> /// <param name="historyIndex"></param> /// <returns></returns> public string FENForHistoryBoard(int historyIndex) { EncodedPositionBoard planes = GetPlanesForHistoryBoard(historyIndex); // KQkq - 0 1 bool weAreWhite = MiscInfo.InfoPosition.SideToMove == 0; string fen = MiscInfo.InfoPosition.SideToMove == 0 ? planes.GetFEN(weAreWhite) : planes.Reversed.GetFEN(weAreWhite); if (historyIndex != 0) { return(fen); } fen = fen + (weAreWhite ? " w" : " b"); fen = fen + " "; string castling = ""; if ((weAreWhite ? MiscInfo.InfoPosition.Castling_US_OO : MiscInfo.InfoPosition.Castling_Them_OO) > 0) { castling += "K"; } if ((weAreWhite ? MiscInfo.InfoPosition.Castling_US_OOO : MiscInfo.InfoPosition.Castling_Them_OOO) > 0) { castling += "Q"; } if ((weAreWhite ? MiscInfo.InfoPosition.Castling_Them_OO : MiscInfo.InfoPosition.Castling_US_OO) > 0) { castling += "k"; } if ((weAreWhite ? MiscInfo.InfoPosition.Castling_Them_OOO : MiscInfo.InfoPosition.Castling_US_OOO) > 0) { castling += "q"; } if (castling == "") { castling = "-"; } PositionMiscInfo.EnPassantFileIndexEnum enPassant = PositionMiscInfo.EnPassantFileIndexEnum.FileNone; if (historyIndex < 7) { EncodedPositionBoard planesPriorBoard = GetPlanesForHistoryBoard(historyIndex + 1); enPassant = EncodedPositionBoards.EnPassantOpportunityBetweenBoards(planes, planesPriorBoard); } string epTarget = "-"; if (enPassant != PositionMiscInfo.EnPassantFileIndexEnum.FileNone) { epTarget = PositionMiscInfo.EPFileChars[(int)enPassant] + (weAreWhite ? "6" : "3"); } fen = fen + castling + " " + epTarget + " " + MiscInfo.InfoPosition.Rule50Count + " " + (1 + MiscInfo.InfoPosition.MoveCount); // Sometimes 2 dashes? return(fen); }
/// <summary> /// Returns the piece character for a FEN corresponding to specified square. /// </summary> /// <param name="planes"></param> /// <param name="index"></param> /// <param name="weAreWhite"></param> /// <param name="emptySquareChar"></param> /// <returns></returns> internal static string FENCharAt(EncodedPositionBoard planes, int index, bool weAreWhite, string emptySquareChar) { if (planes.OurPawns.BitIsSet(index)) { return(weAreWhite ? "P" : "p"); } if (planes.OurKnights.BitIsSet(index)) { return(weAreWhite ? "N" : "n"); } if (planes.OurBishops.BitIsSet(index)) { return(weAreWhite ? "B" : "b"); } if (planes.OurRooks.BitIsSet(index)) { return(weAreWhite ? "R" : "r"); } if (planes.OurQueens.BitIsSet(index)) { return(weAreWhite ? "Q" : "q"); } if (planes.OurKing.BitIsSet(index)) { return(weAreWhite ? "K" : "k"); } if (planes.TheirPawns.BitIsSet(index)) { return(weAreWhite ? "p" : "P"); } if (planes.TheirKnights.BitIsSet(index)) { return(weAreWhite ? "n" : "N"); } if (planes.TheirBishops.BitIsSet(index)) { return(weAreWhite ? "b" : "B"); } if (planes.TheirRooks.BitIsSet(index)) { return(weAreWhite ? "r" : "R"); } if (planes.TheirQueens.BitIsSet(index)) { return(weAreWhite ? "q" : "Q"); } if (planes.TheirKing.BitIsSet(index)) { return(weAreWhite ? "k" : "K"); } return(emptySquareChar); }
/// <summary> /// Gets the part of a FEN string corrrespondong to a specifid row on a specified plane in this position. /// </summary> /// <param name="startIndex"></param> /// <param name="planes"></param> /// <param name="weAreWhite"></param> /// <returns></returns> internal static string GetRowString(int startIndex, EncodedPositionBoard planes, bool weAreWhite) { string ret = ""; for (int i = 7; i >= 0; i--) { string thisChar = FENCharAt(planes, startIndex + i, weAreWhite, "."); ret += thisChar; } return(ret); }
/// <summary> /// Constructor. /// </summary> /// <param name="store"></param> /// <param name="context"></param> /// <param name="maxNodesBound"></param> /// <param name="positionCache"></param> public MCTSTree(MCTSNodeStore store, MCTSIterator context, int maxNodesBound, int estimatedNumNodes, PositionEvalCache positionCache) { if (context.ParamsSearch.DrawByRepetitionLookbackPlies > MAX_LENGTH_POS_HISTORY) { throw new Exception($"DrawByRepetitionLookbackPlies exceeds maximum length of {MAX_LENGTH_POS_HISTORY}"); } Store = store; Context = context; PositionCache = positionCache; ChildCreateLocks = new LockSet(128); const int ANNOTATION_MIN_CACHE_SIZE = 50_000; int annotationCacheSize = Math.Min(maxNodesBound, context.ParamsSearch.Execution.NodeAnnotationCacheSize); if (annotationCacheSize < ANNOTATION_MIN_CACHE_SIZE && annotationCacheSize < maxNodesBound) { throw new Exception($"NODE_ANNOTATION_CACHE_SIZE is below minimum size of {ANNOTATION_MIN_CACHE_SIZE}"); } if (maxNodesBound <= annotationCacheSize && !context.ParamsSearch.TreeReuseEnabled) { // We know with certainty the maximum size, and it will fit inside the cache // without purging needed - so just use a simple fixed size cache cache = new MCTSNodeCacheArrayFixed(this, maxNodesBound); } else { cache = new MCTSNodeCacheArrayPurgeableSet(this, annotationCacheSize, estimatedNumNodes); } // Populate EncodedPriorPositions with encoded boards // corresponding to possible prior moves (before the root of this search) EncodedPriorPositions = new List <EncodedPositionBoard>(); Position[] priorPositions = new Position[9]; // Get prior positions (last position has highest index) priorPositions = PositionHistoryGatherer.DoGetHistoryPositions(PriorMoves, priorPositions, 0, 8, false).ToArray(); for (int i = priorPositions.Length - 1; i >= 0; i--) { EncodedPositionBoard thisBoard = EncodedPositionBoard.GetBoard(in priorPositions[i], priorPositions[i].MiscInfo.SideToMove, false); EncodedPriorPositions.Add(thisBoard); } }
/// <summary> /// Returns string with text representations of a specified history board. /// </summary> /// <param name="historyIndex"></param> /// <returns></returns> public string BoardPictureForHistoryBoard(int historyIndex) { EncodedPositionBoard planes = GetPlanesForHistoryBoard(historyIndex); return(planes.GetBoardPicture(true)); }