What does this do?
If you have a collection of games in PGN format, this script will sort each game by how it ended. Unique files will be created for games that ended in Checkmate, Stalemate, 3 Move Repetition, 50 move rule, or insufficient material.
You can use this to test your end game logic, for instance 3 move repetition. You can isolate millions of games that end in 3 move repetition and then feed them into your chess engine. If all the games are recognized as 3 move repetition draws by your engine, then you can be confident your end game logic is working similar to PyChess.
How do I use it?
You must have Python and PyChess installed to use this. Copy this script into the PyChess folder and invoke it with the path of the PGN file you want to audit. 5 PGN files will be created to store each type of game ending. The script appends to these files so you can call it over and over on many PGN's to build a collection of endings. The game termination priority for these files is checkmate, stalemate, 50 move rule, 3-fold repetition, insufficient material.
Where do I get random games?
The best way to generate random games is by implementing a command called rgstat in your engine. The rgstat command is a good tool for benchmarking and for debugging end game logic.
import sys from imp import load_module, find_module pychess = load_module("pychess", *find_module("pychess",["lib"])) from pychess.Savers import pgn from pychess.Utils.lutils import lmovegen from pychess.Utils.lutils import ldraw from pychess.Utils.const import * def getStatus (board): lboard = board.board board_clone = lboard.clone() hasMove = False for move in lmovegen.genAllMoves (board_clone): board_clone.applyMove(move) if board_clone.opIsChecked(): board_clone.popMove() continue board_clone.popMove() hasMove = True break if not hasMove: if lboard.isChecked(): if board.color == WHITE: status = BLACKWON else: status = WHITEWON return status, WON_MATE else: return DRAW, DRAW_STALEMATE if ldraw.testFifty (lboard): return DRAW, DRAW_50MOVES if ldraw.repetitionCount (lboard) >= 3: return DRAW, DRAW_REPITITION return RUNNING, UNKNOWN_REASON if len(sys.argv) != 2: sys.exit("must provide pgn file as parameter") source_file = sys.argv cntr = 0 gf = open(source_file, 'r') checkmates = 0 stalemates = 0 fiftymoves = 0 repetitions = 0 f = pgn.load(gf) for i in range(len(f)): m = f.loadToModel(i,-1,None,False) m.players = ["-", "-"] status, reason = getStatus(m.boards[-1]) if (reason == WON_MATE): checkmates += 1 filename = 'checkmates.pgn' elif (reason == DRAW_STALEMATE): stalemates += 1 filename = 'stalemates.pgn' elif (reason == DRAW_50MOVES): fiftymoves += 1 filename = 'fiftymove.pgn' elif (reason == DRAW_REPITITION): repetitions += 1 filename = 'repetition.pgn' else: filename = 'unknown_results.pgn' if (reason == DRAW_CALLFLAG): print "DRAW_CALLFLAG" if (reason == DRAW_INSUFFICIENT): print "Insufficient Material" if (reason == DRAW_LENGTH): print "DRAW LENGTH" savefile = open(filename, 'a') print >> savefile pgn.save(savefile, m) print str(i) + ": " + str(checkmates) + " checkmates, " + str(stalemates) + " stalemates, " + str(fiftymoves) + " fifty moves, " + str(repetitions) + " repetitions, status: " + str(status) + " reson: " + str(reason)