def findbest(f, times): print('Calibrating search speed...') pos = xboard.parseFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') CAL_NODES = 10000 start = time.time() _ = sunfish.search(pos, CAL_NODES) factor = CAL_NODES/(time.time()-start) print('Running benchmark with %.1f nodes per second...' % factor) print('-'*60) totalpoints = 0 totaltests = 0 for k, line in enumerate(f): fen, opts = parseEPD(line) pos = xboard.parseFEN(fen) color = 0 if fen.split()[1] == 'w' else 1 # am -> avoid move; bm -> best move am = parseSAN(pos,color,opts['am']) if 'am' in opts else None bm = parseSAN(pos,color,opts['bm']) if 'bm' in opts else None points = 0 print(opts['id'], end=' ', flush=True) for t in times: move, _ = sunfish.search(pos, factor*t) mark = renderSAN(pos, move) if am and move != am or bm and move == bm: mark += '(1)' points += 1 totalpoints += 1 else: mark += '(0)' print(mark, end=' ', flush=True) totaltests + 1 print(points) print('-'*60) print('Total Points: %d/%d', totalpoints, totaltests)
def play(version1_version2_maxn_rand): ''' returns 1 if fish1 won, 0 for draw and -1 otherwise ''' version1, version2, maxn, rand = version1_version2_maxn_rand fish1 = importlib.import_module(version1) fish2 = importlib.import_module(version2) pos = xboard.parseFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') old = None tdelta = 0 for d in range(200): nodes = maxn nodes *= (1+abs(tdelta)/5) if (tdelta<0)==(d%2==0) else 1 nodes *= .75+random.random()/2 before = time.time() m, score = (fish1 if d%2==0 else fish2).search(pos, nodes) tdelta += (time.time()-before)*(1 if d%2==0 else -1) if m is not None: pos = pos.move(m) # Test repetition draws if d%4==0: if pos.board == old: return 0 old = pos.board else: assert score < -1000 return 1 if d%2 == 1 else -1 else: print('200 moves reached') return 0
def play(version1_version2_secs_fen): ''' returns 1 if fish1 won, 0 for draw and -1 otherwise ''' version1, version2, secs, fen = version1_version2_secs_fen fish = [importlib.import_module(version1), importlib.import_module(version2)] nodes = [5000, 5000] times = [0, 0] pos = xboard.parseFEN(fen) old = None for d in range(200): t = time.time() maxn = nodes[d%2] * (times[(d+1)%2]+secs) / (times[d%2]+secs) m, score = fish[d%2].search(pos, maxn) times[d%2] += time.time() - t nodes[d%2] *= (secs/(time.time()-t))**.3 if m is not None: pos = pos.move(m) # Test repetition draws if d%4==0: if pos.board == old: return None old = pos.board else: if score > 30000: assert False # This means we move and kill the opponent king. # But then the opponent made an illegal move last time??? return version1 if d%2 == 0 else version2 if score > -1000: print("How did we get here, if we didn't lose?") print(pos, m, score) return None return version1 if d%2 == 1 else version2 return None
def play(version1_version2_maxn_rand): ''' returns 1 if fish1 won, 0 for draw and -1 otherwise ''' version1, version2, maxn, rand = version1_version2_maxn_rand fish1 = importlib.import_module(version1) fish2 = importlib.import_module(version2) pos = xboard.parseFEN( 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') old = None tdelta = 0 for d in range(200): nodes = maxn nodes *= (1 + abs(tdelta) / 5) if (tdelta < 0) == (d % 2 == 0) else 1 nodes *= .75 + random.random() / 2 before = time.time() m, score = (fish1 if d % 2 == 0 else fish2).search(pos, nodes) tdelta += (time.time() - before) * (1 if d % 2 == 0 else -1) if m is not None: pos = pos.move(m) # Test repetition draws if d % 4 == 0: if pos.board == old: return 0 old = pos.board else: assert score < -1000 return 1 if d % 2 == 1 else -1 else: print('200 moves reached') return 0
def allmate(path): with open(path) as f: for line in f: line = line.strip() print(line) pos = xboard.parseFEN(line) _, score = sunfish.search(pos, maxn=1e9) if score < sunfish.MATE_VALUE: print("Unable to find mate. Only got score = %d" % score) break
def findbest(f, times): print('Calibrating search speed...') pos = xboard.parseFEN(xboard.FEN_INITIAL) CAL_NODES = 100000 start = time.time() _ = sunfish.search(pos, CAL_NODES) factor = sunfish.nodes/(time.time()-start) print('Running benchmark with %.1f nodes per second...' % factor) print('Printing best move after seconds', times) print('-'*60) totalpoints = 0 totaltests = 0 for line in f: fen, opts = parseEPD(line, opt_dict=True) if type(opts) != dict or ('am' not in opts and 'bm' not in opts): print("Line didn't have am/bm in opts", line, opts) continue pos = xboard.parseFEN(fen) color = xboard.WHITE if fen.split()[1] == 'w' else xboard.BLACK # am -> avoid move; bm -> best move am = parseSAN(pos,color,opts['am']) if 'am' in opts else None bm = parseSAN(pos,color,opts['bm']) if 'bm' in opts else None print('Looking for am/bm', opts.get('am'), opts.get('bm')) points = 0 print(opts.get('id','unnamed'), end=' ', flush=True) for t in times: move, _ = sunfish.search(pos, factor*t) mark = renderSAN(pos,color,move) if am and move != am or bm and move == bm: mark += '(1)' points += 1 else: mark += '(0)' print(mark, end=' ', flush=True) totaltests += 1 print(points) totalpoints += points print('-'*60) print('Total Points: %d/%d', totalpoints, totaltests)
def selfplay(maxn=200): """ Start a game sunfish vs. sunfish """ pos = xboard.parseFEN(xboard.FEN_INITIAL) for d in range(200): # Always print the board from the same direction board = pos.board if d % 2 == 0 else pos.rotate().board print(' '.join(board)) m, _ = sunfish.search(pos, maxn) if m is None: print("Game over") break print("\nmove", xboard.mrender(d%2, pos, m)) pos = pos.move(m)
def test_san(self): pgn_file = os.path.join(os.path.dirname(__file__), 'tests/pgns.pgn') for line in open(pgn_file): msans = [msan for i, msan in enumerate(line.split()[:-1]) if i%3!=0] pos = xboard.parseFEN(xboard.FEN_INITIAL) for i, msan in enumerate(msans): move = parseSAN(pos, i%2, msan) if re.search('=[BNR]', msan): # Sunfish doesn't support underpromotion break msan_back = renderSAN(pos, i%2, move) self.assertEqual(msan_back, msan, "Sunfish didn't correctly reproduce the SAN move") pos = pos.move(move)
def selfplay(): """ Start a game sunfish vs. sunfish """ pos = xboard.parseFEN('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') for d in range(200): # Always print the board from the same direction board = pos.board if d % 2 == 0 else pos.rotate().board print(' '.join(board)) m, _ = sunfish.search(pos, maxn=200) if m is None: print("Game over") break print("\nmove", xboard.mrender(d%2, pos, m)) pos = pos.move(m)
def findbest(path, times): print('Calibrating search speed...') pos = xboard.parseFEN( 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') CAL_NODES = 10000 start = time.time() _ = sunfish.search(pos, CAL_NODES) factor = CAL_NODES / (time.time() - start) print('Running benchmark with %.1f nodes per second...' % factor) print('-' * 60) totalpoints = 0 totaltests = 0 with open(path) as f: for k, line in enumerate(f): fen, opts = parseEPD(line) pos = xboard.parseFEN(fen) color = 0 if fen.split()[1] == 'w' else 1 # am -> avoid move; bm -> best move am = parseSAN(pos, color, opts['am']) if 'am' in opts else None bm = parseSAN(pos, color, opts['bm']) if 'bm' in opts else None points = 0 print(opts['id'], end=' ', flush=True) for t in times: move, _ = sunfish.search(pos, factor * t) mark = renderSAN(pos, move) if am and move != am or bm and move == bm: mark += '(1)' points += 1 totalpoints += 1 else: mark += '(0)' print(mark, end=' ', flush=True) totaltests + 1 print(points) print('-' * 60) print('Total Points: %d/%d', totalpoints, totaltests)
def selfplay(maxn=200): """ Start a game sunfish vs. sunfish """ pos = xboard.parseFEN( 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') for d in range(200): # Always print the board from the same direction board = pos.board if d % 2 == 0 else pos.rotate().board print(' '.join(board)) m, _ = sunfish.search(pos, maxn) if m is None: print("Game over") break print("\nmove", xboard.mrender(d % 2, pos, m)) pos = pos.move(m)
def quickdraw(f, depth): for line in f: line = line.strip() print(line) pos = xboard.parseFEN(line) for d in range(depth, 99): s0 = sunfish.bound(pos, 0, d) s1 = sunfish.bound(pos, 1, d) if s0 >= 0 and s1 < 1: break print(d, s0, s1, xboard.pv(0, pos)) else: print("Fail: Unable to find draw!") return
def allperft(f, depth=4): lines = f.readlines() for d in range(1, depth+1): print("Going to depth {}/{}".format(d, depth)) for line in lines: parts = line.split(';') print(parts[0]) pos, score = xboard.parseFEN(parts[0]), int(parts[d]) res = sum(1 for _ in collect_tree_depth(expand_position(pos), d)) if res != score: print('=========================================') print("ERROR at depth %d. Gave %d rather than %d" % (d, res, score)) print('=========================================') return print('')
def quickmate(path, depth): """ Similar to allmate, but uses the `bound` function directly to only search for moves that will win us the game """ with open(path) as f: for line in f: line = line.strip() print(line) pos = xboard.parseFEN(line) for d in range(depth, 99): score = sunfish.bound(pos, sunfish.MATE_VALUE, d) if score >= sunfish.MATE_VALUE: break print(d, score) else: print("Unable to find mate. Only got score = %d" % score) return
def selfplay(): """ Start a game sunfish vs. sunfish """ wa, ba = (['C', 'N', 'E', 'R', 'T', 'A'])[random.randint(0, 5)], (['c', 'n', 'e', 'r', 't', 'a'])[random.randint(0, 5)] #pos = xboard.parseFEN('{}{} 33 rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'.format(wa, ba)) pos = xboard.parseFEN( 'Ca 33 rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') print(' '.join(pos.board)) print('#' * 10) for d in range(100): move, score = sunfish.search(pos, maxn=1e3) pos = pos.move(move) # Always print the board from the same direction board = pos.rotate().board if pos.color else pos.board #board = pos.board print(' '.join(board)) print("{}. {}: {}".format(d + 1, (['w', 'b'])[not pos.color], xboard.mrender(pos, move))) print("\n" + str(xboard.printFEN(pos))) if pos.second: print("second initiated") move, score = sunfish.search(pos, maxn=1e2) if move: print("move found") board = pos.rotate().board if pos.color else pos.board print(' '.join(board)) print("{}. {}: {}".format(d + 1, (['w', 'b'])[not pos.color], xboard.mrender(pos, move))) print("\n" + str(xboard.printFEN(pos))) pos = pos.move(move) else: score = 0 pos = sunfish.Position(pos.board, pos.color, False, pos.score, pos.wa, pos.ba, pos.ws, pos.bs, pos.wc, pos.bc, pos.ep, pos.kp) pos = pos.rotate() if score <= -30000: print("Game over. White wins.") break if score >= 30000: print("Game over. Black wins.") break print('#' * 10)
def quickmate(f, min_depth=1, draw=False): """ Similar to allmate, but uses the `bound` function directly to only search for moves that will win us the game """ if draw: return quickdraw(f, min_depth) for line in f: line = line.strip() print(line) pos = xboard.parseFEN(line) for d in range(min_depth, 99): score = sunfish.bound(pos, sunfish.MATE_VALUE, d) if score >= sunfish.MATE_VALUE: break print('Score at depth {}: {}'.format(d, score)) else: print("Unable to find mate. Only got score = %d" % score) return
def allperft(path, depth=4): for d in range(1, depth+1): print("Going to depth %d" % d) with open(path) as f: for line in f: parts = line.split(';') print(parts[0]) pos, score = xboard.parseFEN(parts[0]), int(parts[d]) res = perft(pos, d) if res != score: print('=========================================') print("ERROR at depth %d. Gave %d rather than %d" % (d, res, score)) print('=========================================') if d == 1: print(pos) perft(pos, d, divide=True) return print('')
def allperft(f, depth=4): lines = f.readlines() for d in range(1, depth + 1): print("Going to depth %d" % d) for line in lines: parts = line.split(';') print(parts[0]) pos, score = xboard.parseFEN(parts[0]), int(parts[d]) res = perft(pos, d) if res != score: print('=========================================') print("ERROR at depth %d. Gave %d rather than %d" % (d, res, score)) print('=========================================') if d == 1: print(pos) perft(pos, d, divide=True) return print('')
def selfplay(): """ Start a game sunfish vs. sunfish """ wa, ba = (['C', 'N', 'E', 'R', 'T', 'A'])[random.randint(0, 5)], (['c', 'n', 'e', 'r', 't', 'a'])[random.randint(0, 5)] #pos = xboard.parseFEN('{}{} 33 rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'.format(wa, ba)) pos = xboard.parseFEN('Ca 33 rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') print(' '.join(pos.board)) print('#' * 10) for d in range(100): move, score = sunfish.search(pos, maxn=1e3) pos = pos.move(move) # Always print the board from the same direction board = pos.rotate().board if pos.color else pos.board #board = pos.board print(' '.join(board)) print("{}. {}: {}".format(d+1, (['w', 'b'])[not pos.color], xboard.mrender(pos, move))) print("\n" + str(xboard.printFEN(pos))) if pos.second: print("second initiated") move, score = sunfish.search(pos, maxn=1e2) if move: print("move found") board = pos.rotate().board if pos.color else pos.board print(' '.join(board)) print("{}. {}: {}".format(d+1, (['w', 'b'])[not pos.color], xboard.mrender(pos, move))) print("\n" + str(xboard.printFEN(pos))) pos = pos.move(move) else: score = 0 pos = sunfish.Position( pos.board, pos.color, False, pos.score, pos.wa, pos.ba, pos.ws, pos.bs, pos.wc, pos.bc, pos.ep, pos.kp) pos = pos.rotate() if score <= -30000: print("Game over. White wins.") break if score >= 30000: print("Game over. Black wins.") break print('#' * 10)
def setUp(self): perft_file = os.path.join(os.path.dirname(__file__), 'tests/queen.fen') test_trees = [expand_position(xboard.parseFEN(parseEPD(line)[0])) for line in open(perft_file)] self.positions = list(itertools.chain(*[flatten_tree(tree, depth=2) for tree in test_trees]))