Update move validation script

This commit is contained in:
Mattia Giambirtone 2023-10-30 15:26:48 +01:00
parent 75869357cc
commit 2c58488c61
1 changed files with 55 additions and 40 deletions

View File

@ -33,7 +33,7 @@ def main(args: Namespace) -> int:
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
encoding="u8") encoding="u8")
print(f"Setting position to {args.fen!r}") print(f"Setting position to {(args.fen if args.fen else 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1')!r}")
if args.fen: if args.fen:
nimfish_process.stdin.write(f"position fen {args.fen}\n") nimfish_process.stdin.write(f"position fen {args.fen}\n")
stockfish_process.stdin.write(f"position fen {args.fen}\n") stockfish_process.stdin.write(f"position fen {args.fen}\n")
@ -65,19 +65,23 @@ def main(args: Namespace) -> int:
positions["all"][move].append(int(nodes)) positions["all"][move].append(int(nodes))
positions["nimfish"][move] = int(nodes) positions["nimfish"][move] = int(nodes)
differences = { missing = {
# Are in nimfish but not in stockfish # Are in nimfish but not in stockfish
"nimfish": [], "nimfish": [],
# Are in stockfish but not in nimfish # Are in stockfish but not in nimfish
"stockfish": [] "stockfish": []
} }
# What mistakes did Nimfish do?
mistakes = set()
for move, nodes in positions["all"].items(): for move, nodes in positions["all"].items():
if move in positions["stockfish"]: if move not in positions["stockfish"]:
if move not in positions["nimfish"] or positions["stockfish"][move] != positions["nimfish"][move]: missing["nimfish"].append(move)
differences["stockfish"].append(move) continue
elif move in positions["nimfish"]: elif move not in positions["nimfish"]:
if move not in positions["stockfish"] or positions["nimfish"][move] != positions["stockfish"][move]: missing["stockfish"].append(move)
differences["nimfish"].append(move) continue
if nodes[0] != nodes[1]:
mistakes.add(move)
total_nodes = {"stockfish": sum(positions["stockfish"][move] for move in positions["stockfish"]), total_nodes = {"stockfish": sum(positions["stockfish"][move] for move in positions["stockfish"]),
"nimfish": sum(positions["nimfish"][move] for move in positions["nimfish"])} "nimfish": sum(positions["nimfish"][move] for move in positions["nimfish"])}
@ -88,46 +92,58 @@ def main(args: Namespace) -> int:
print(f"Stockfish searched {total_difference} more nodes than Nimfish") print(f"Stockfish searched {total_difference} more nodes than Nimfish")
elif total_difference != 0: elif total_difference != 0:
print(f"Nimfish searched {-total_difference} more nodes than Stockfish") print(f"Nimfish searched {-total_difference} more nodes than Stockfish")
if differences["stockfish"] or differences["nimfish"]: else:
pattern = re.compile(r"(?:\s\s-\sCaptures:\s(?P<captures>[0-9]+))\n" print("Node count is identical")
r"(?:\s\s-\sChecks:\s(?P<checks>[0-9]+))\n" pattern = re.compile(r"(?:\s\s-\sCaptures:\s(?P<captures>[0-9]+))\n"
r"(?:\s\s-\sE\.P:\s(?P<enPassant>[0-9]+))\n" r"(?:\s\s-\sChecks:\s(?P<checks>[0-9]+))\n"
r"(?:\s\s-\sCheckmates:\s(?P<checkmates>[0-9]+))\n" r"(?:\s\s-\sE\.P:\s(?P<enPassant>[0-9]+))\n"
r"(?:\s\s-\sCastles:\s(?P<castles>[0-9]+))\n" r"(?:\s\s-\sCheckmates:\s(?P<checkmates>[0-9]+))\n"
r"(?:\s\s-\sPromotions:\s(?P<promotions>[0-9]+))", r"(?:\s\s-\sCastles:\s(?P<castles>[0-9]+))\n"
re.MULTILINE) r"(?:\s\s-\sPromotions:\s(?P<promotions>[0-9]+))",
data: re.Match | None = None re.MULTILINE)
extra: re.Match | None = None
if args.bulk:
print("Note: Nimfish was run in bulk-counting mode, so a detailed breakdown of each move type is not available. "
"To fix this, re-run the program without the --bulk option")
else:
extra = pattern.search(nimfish_output)
if missing["stockfish"] or missing["nimfish"] or mistakes:
print(f"Found {len(missing['stockfish']) + len(missing['nimfish'])} missed moves and {len(mistakes)} counting mistakes, more info below: ")
if args.bulk: if args.bulk:
print("Note: Nimfish was run in bulk-counting mode, so a detailed breakdown of each move type is not available. " print("Note: Nimfish was run in bulk-counting mode, so a detailed breakdown of each move type is not available. "
"To fix this, re-run the program without the --bulk option") "To fix this, re-run the program without the --bulk option")
else: if extra:
data = pattern.search(nimfish_output) print(f" Breakdown by move type:")
print(f"Found {len(differences)} mismatches, more info below: ") print(f" - Captures: {extra.group('captures')}")
if data: print(f" - Checks: {extra.group('checks')}")
print(f" - Breakdown by move type:") print(f" - En Passant: {extra.group('enPassant')}")
print(f" - Captures: {data.group('captures')}") print(f" - Checkmates: {extra.group('checkmates')}")
print(f" - Checks: {data.group('checks')}") print(f" - Castles: {extra.group('castles')}")
print(f" - En Passant: {data.group('enPassant')}") print(f" - Promotions: {extra.group('promotions')}")
print(f" - Checkmates: {data.group('checkmates')}") print(f" - Total: {total_nodes['nimfish']}")
print(f" - Castles: {data.group('castles')}")
print(f" - Promotions: {data.group('promotions')}")
elif not args.bulk: elif not args.bulk:
print("Unable to locate move breakdown in Nimfish output") print("Unable to locate move breakdown in Nimfish output")
if differences["stockfish"]: if missing["stockfish"] or missing["nimfish"]:
print(" - Legal moves missed by Nimfish: ") print("\n Missed moves:")
for difference in differences["stockfish"]: if missing["stockfish"]:
print(f" - {difference}: {positions['stockfish'][difference]}") print(" Legal moves missed by Nimfish: ")
if differences["nimfish"]: for move in missing["stockfish"]:
print(" - Illegal moves missed by Nimfish: ") print(f" - {move}: {positions['stockfish'][move]}")
for difference in differences["stockfish"]: if missing["nimfish"]:
print(f" - {difference}: {positions['nimfish'][difference]}") print(" Illegal moves missed by Nimfish: ")
for move in missing["nimfish"]:
print(f" - {move}: {positions['nimfish'][move]}")
if mistakes:
print(" Mistakes:")
for move in mistakes:
print(f" - {move}: expected {positions['stockfish'][move]}, got {positions['nimfish'][move]}")
else: else:
print("No mismatches in node count or moves were found") print("No mistakes were detected")
if __name__ == "__main__": if __name__ == "__main__":
parser = ArgumentParser(description="Automatically compare perft results between our engine and Stockfish") parser = ArgumentParser(description="Automatically compare perft results between our engine and Stockfish")
parser.add_argument("--fen", "-f", type=str, default="", help="The FEN string of the position to start from (empty string means the initial one). Defaults to ''") parser.add_argument("--fen", "-f", type=str, default="", help="The FEN string of the position to start from (empty string means the initial one). Defaults to ''")
@ -135,5 +151,4 @@ if __name__ == "__main__":
parser.add_argument("--bulk", action="store_true", help="Enable bulk-counting for Nimfish (faster, less debuggable)", default=False) parser.add_argument("--bulk", action="store_true", help="Enable bulk-counting for Nimfish (faster, less debuggable)", default=False)
parser.add_argument("--stockfish", type=Path, help="Path to the stockfish executable. Defaults to '' (detected automatically)", default=None) parser.add_argument("--stockfish", type=Path, help="Path to the stockfish executable. Defaults to '' (detected automatically)", default=None)
parser.add_argument("--nimfish", type=Path, help="Path to the nimfish executable. Defaults to 'nimfish'", default=Path("nimfish")) parser.add_argument("--nimfish", type=Path, help="Path to the nimfish executable. Defaults to 'nimfish'", default=Path("nimfish"))
sys.exit(main(parser.parse_args())) sys.exit(main(parser.parse_args()))