/// <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> /// Constructs a test batch of specified size. /// </summary> /// <param name="evaluator"></param> /// <param name="count"></param> /// <param name="fen"></param> /// <returns></returns> public static EncodedPositionBatchFlat MakeTestBatch(NNEvaluator evaluator, int count, string fen = null) { EncodedPositionBatchFlat batch; if (fen == null) { fen = Position.StartPosition.FEN; } Position rawPos = Position.FromFEN(fen); MGPosition mgPos = MGPosition.FromPosition(rawPos); EncodedPositionWithHistory position = EncodedPositionWithHistory.FromFEN(fen); EncodedPositionWithHistory[] positions = new EncodedPositionWithHistory[count]; Array.Fill(positions, position); batch = new EncodedPositionBatchFlat(positions, count); bool hasPositions = evaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Positions); bool hasMoves = evaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Moves); bool hasHashes = evaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Hashes); bool hasBoards = evaluator.InputsRequired.HasFlag(NNEvaluator.InputTypes.Boards); if (fen != null) { if (hasPositions) { batch.Positions = new MGPosition[count]; } if (hasHashes) { batch.PositionHashes = new ulong[count]; } if (hasMoves) { batch.Moves = new MGMoveList[count]; } for (int i = 0; i < count; i++) { if (hasPositions) { batch.Positions[i] = MGChessPositionConverter.MGChessPositionFromFEN(fen); } if (hasHashes) { batch.PositionHashes[i] = (ulong)i + (ulong)batch.Positions[i].GetHashCode(); } if (hasMoves) { MGMoveList moves = new MGMoveList(); MGMoveGen.GenerateMoves(in mgPos, moves); batch.Moves[i] = moves; } } } return(batch); }
static void TestZZ(string fen) { MGPosition curPosition = MGChessPositionConverter.MGChessPositionFromFEN(fen); // Generate moves MGMoveList moves = new MGMoveList(); MGMoveGen.GenerateMoves(in curPosition, moves); foreach (var move in moves) { Console.WriteLine(move + " " + MoveStr(curPosition.AsPosition, move)); } }
/// <summary> /// Generates the set of moves and positions possible as the next move in a position. /// </summary> /// <param name="startPos"></param> /// <param name="moveToIncludeFilter"></param> /// <returns></returns> public static IEnumerable <(MGMove, Position)> GenPositions(Position startPos, Predicate <MGMove> moveToIncludeFilter = null) { MGPosition posMG = MGChessPositionConverter.MGChessPositionFromFEN(startPos.FEN); // TODO: more efficient? MGMoveList moves = new MGMoveList(); MGMoveGen.GenerateMoves(in posMG, moves); for (int i = 0; i < moves.NumMovesUsed; i++) { // Only consider captures (would reduce number of pieces into range of tablebase) if (moveToIncludeFilter == null || moveToIncludeFilter(moves.MovesArray[i])) { // Make this move and get new Position MGPosition newPosMG = new MGPosition(posMG); newPosMG.MakeMove(moves.MovesArray[i]); Position newPos = MGChessPositionConverter.PositionFromMGChessPosition(in newPosMG); yield return(moves.MovesArray[i], newPos); } } }
public static string AlgebraicMoveString(MGMove mgMove, Position pos) { string ret = null; bool white = pos.MiscInfo.SideToMove == SideType.White; MGPosition curPosition = MGChessPositionConverter.MGChessPositionFromFEN(pos.FEN); // Generate moves MGMoveList moves = new MGMoveList(); MGMoveGen.GenerateMoves(in curPosition, moves); //if (white) mgMove = new MGMove(mgMove, true); MGPosition newPosition = MGChessPositionConverter.MGChessPositionFromFEN(pos.FEN); newPosition.MakeMove(mgMove); bool isCheck = MGMoveGen.IsInCheck(newPosition, white); if (mgMove.CastleShort) { ret = "O-O"; } else if (mgMove.CastleLong) { ret = "O-O-O"; } else { Square fromSquare = mgMove.FromSquare; Square toSquare = mgMove.ToSquare; Piece fromType = pos.PieceOnSquare(fromSquare); Piece toPiece = pos.PieceOnSquare(toSquare); if (fromType.Type == PieceType.Pawn) { string promoteChar = ""; if (mgMove.PromoteQueen) { promoteChar = "Q"; } if (mgMove.PromoteBishop) { promoteChar = "B"; } if (mgMove.PromoteRook) { promoteChar = "R"; } if (mgMove.PromoteKnight) { promoteChar = "N"; } if (mgMove.EnPassantCapture) { int newRank = white ? 6 : 3; char newFile = char.ToLower(toSquare.FileChar); ret = fromSquare.ToString().Substring(0, 1).ToLower() + "x" + newFile + newRank; } else if (toPiece.Type == PieceType.None) { ret = toSquare.ToString().ToLower() + promoteChar; } else { ret = fromSquare.ToString().Substring(0, 1).ToLower() + "x" + toSquare.ToString().ToLower() + promoteChar; } } else { string captureChar = toPiece.Type == PieceType.None ? "" : "x"; List <MGMove> matchingCaptures = MovesByPieceTypeThatTakeOnSquare(mgMove.Piece, mgMove.ToSquareIndex, moves); if (matchingCaptures.Count == 1) { ret = char.ToUpper(fromType.Char) + captureChar + toSquare.ToString().ToLower(); } else { // Disambiguate DifferBy differBy = MoveDifferFromAllOthersBy(matchingCaptures, mgMove); string fileChar = fromSquare.FileChar.ToString().ToLower(); string rankChar = fromSquare.RankChar.ToString().ToLower(); if (differBy == DifferBy.File) { ret = char.ToUpper(fromType.Char) + fileChar + captureChar + toSquare.ToString().ToLower(); } else if (differBy == DifferBy.Rank) { ret = char.ToUpper(fromType.Char) + rankChar + captureChar + toSquare.ToString().ToLower(); } else { ret = char.ToUpper(fromType.Char) + fileChar + rankChar + captureChar + toSquare.ToString().ToLower(); } } } } if (isCheck) { return(ret + "+"); } else { return(ret); } }