def main(): logging.basicConfig(filename='sunfish.log', level=logging.DEBUG) out = Unbuffered(sys.stdout) def output(line): print(line, file=out) logging.debug(line) pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = True stack = [] while True: if stack: smove = stack.pop() else: smove = input() logging.debug(f'>>> {smove} ') if smove == 'quit': break elif smove == 'uci': output('id name Sunfish') output('id author Thomas Ahle & Contributors') output('uciok') elif smove == 'isready': output('readyok') elif smove == 'ucinewgame': stack.append('position fen ' + tools.FEN_INITIAL) elif smove.startswith('position fen'): _, _, fen = smove.split(' ', 2) pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK elif smove.startswith('position startpos'): params = smove.split(' ') pos = tools.parseFEN(tools.FEN_INITIAL) color = WHITE if len(params) > 2 and params[2] == 'moves': for move in params[3:]: pos = pos.move(tools.mparse(color, move)) color = 1 - color elif smove.startswith('go'): # default options depth = 1000 movetime = -1 _, *params = smove.split(' ') for param, val in zip(*2*(iter(params),)): if param == 'depth': depth = int(val) if param == 'movetime': movetime = int(val) if param == 'wtime': our_time = int(val) if param == 'btime': opp_time = int(val) moves_remain = 40 start = time.time() ponder = None for sdepth, _move, _score in searcher.search(pos): moves = tools.pv(searcher, pos, include_scores=False) if show_thinking: entry = searcher.tp_score.get((pos, sdepth, True)) score = int(round((entry.lower + entry.upper)/2)) usedtime = int((time.time() - start) * 1000) moves_str = moves if len(moves) < 15 else '' output('info depth {} score cp {} time {} nodes {} pv {}'.format(sdepth, score, usedtime, searcher.nodes, moves_str)) if len(moves) > 5: ponder = moves[1] if movetime > 0 and (time.time() - start) * 1000 > movetime: break if (time.time() - start) * 1000 > our_time/moves_remain: break if sdepth >= depth: break entry = searcher.tp_score.get((pos, sdepth, True)) m, s = searcher.tp_move.get(pos), entry.lower # We only resign once we are mated.. That's never? if s == -sunfish.MATE_UPPER: output('resign') else: moves = moves.split(' ') if len(moves) > 1: output(f'bestmove {moves[0]} ponder {moves[1]}') else: output('bestmove ' + moves[0]) elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) else: pass
def main(): pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = False options = {} history = [] stack = [] while True: if stack: smove = stack.pop() else: smove = input() print('>>>', smove, file=sys.stderr) sys.stderr.flush() # For Python 2.7 support if smove == 'quit': break elif smove == 'protover 2': print('feature done=0') print('feature myname="Sunfish"') print('feature usermove=1') print('feature setboard=1') print('feature ping=1') print('feature sigint=0') print('feature variants="normal"') print('feature option="qs_limit -spin {} -100 1000"'.format( sunfish.QS_LIMIT)) print('feature option="eval_roughness -spin {} 1 1000"'.format( sunfish.EVAL_ROUGHNESS)) print('feature option="draw_test -spin {} 0 1"'.format( int(sunfish.DRAW_TEST))) print('feature done=1') elif smove == 'new': stack.append('setboard ' + tools.FEN_INITIAL) # Clear out the old searcher, including the tables searcher = sunfish.Searcher() del history[:] elif smove.startswith('setboard'): _, fen = smove.split(' ', 1) pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK del history[:] elif smove == 'force': forced = True elif smove.startswith('option'): _, aeqb = smove.split(maxsplit=1) if '=' in aeqb: name, val = aeqb.split('=') else: name, val = aeqb, True if name == 'qs_limit': sunfish.QS_LIMIT = int(val) if name == 'eval_roughness': sunfish.EVAL_ROUGHNESS = int(val) if name == 'draw_test': sunfish.DRAW_TEST = bool(int(val)) options[name] = val elif smove == 'go': forced = False moves_remain = 40 use = our_time / moves_remain # Let's follow the clock of our opponent if our_time >= 100 and opp_time >= 100: use *= our_time / opp_time start = time.time() for ply, move, score in searcher.search(pos, history): entry = searcher.tp_score.get((pos, ply, True)) score = int(round((entry.lower + entry.upper) / 2)) if show_thinking: used = int((time.time() - start) * 100 + .5) moves = tools.pv(searcher, pos, include_scores=False) seldepth = 0 nps = int(searcher.nodes / (time.time() - start) + .5) print('{:>3} {:>8} {:>8} {:>13} {:>1} {:>4} \t{}'.format( ply, score, used, searcher.nodes, seldepth, nps, moves)) print('# Hashfull: {:.3f}%; {} <= score < {}'.format( len(searcher.tp_score) / sunfish.TABLE_SIZE * 100, entry.lower, entry.upper)) # If found mate, just stop if entry.lower >= sunfish.MATE_UPPER: break if time.time() - start > use / 100: break # We sometimes make illegal moves when we're losing, # so it's safer to just resign. if score == -sunfish.MATE_UPPER: print('resign') else: print('move', tools.mrender(pos, move)) pos = pos.move(move) history.append(pos) color = 1 - color elif smove.startswith('ping'): _, N = smove.split() print('pong', N) elif smove.startswith('usermove'): _, smove = smove.split() m = tools.mparse(color, smove) pos = pos.move(m) history.append(pos) color = 1 - color if not forced: stack.append('go') elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) elif smove.startswith('perft'): start = time.time() for d in range(1, 10): res = sum(1 for _ in tools.collect_tree_depth( tools.expand_position(pos), d)) print('{:>8} {:>8}'.format(res, time.time() - start)) elif smove.startswith('post'): show_thinking = True elif smove.startswith('nopost'): show_thinking = False elif any( smove.startswith(x) for x in ('xboard', 'random', 'hard', 'accepted', 'level', 'easy', 'st', 'result', '?')): print('# Ignoring command {}.'.format(smove)) elif smove.startswith('reject'): _, feature = smove.split( )[:2] # split(maxsplit=2) doesnt work in python2.7 print( '# Warning ({} rejected): Might not work as expected.'.format( feature)) else: print('# Warning (unkown command): {}. Treating as move.'.format( smove)) stack.append('usermove {}'.format(smove))
def main(): parser = argparse.ArgumentParser() parser.add_argument('module', help='sunfish.py file (without .py)', type=str, default='sunfish_nnue', nargs='?') parser.add_argument('--tables', metavar='pst', help='alternative pst table', type=str, default=None) args = parser.parse_args() sunfish = importlib.import_module(args.module) if args.tables is not None: pst_module = importlib.import_module(args.tables) sunfish.pst = pst_module.pst logging.basicConfig(filename='sunfish.log', level=logging.DEBUG) out = Unbuffered(sys.stdout) def output(line): print(line, file=out) logging.debug(line) pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = True stack = [] while True: if stack: smove = stack.pop() else: smove = input() logging.debug(f'>>> {smove} ') if smove == 'quit': break elif smove == 'uci': output('id name Sunfish') output('id author Thomas Ahle & Contributors') output('uciok') elif smove == 'isready': output('readyok') elif smove == 'ucinewgame': stack.append('position fen ' + tools.FEN_INITIAL) # syntax specified in UCI # position [fen | startpos ] moves .... elif smove.startswith('position'): params = smove.split(' ') idx = smove.find('moves') if idx >= 0: moveslist = smove[idx:].split()[1:] else: moveslist = [] if params[1] == 'fen': if idx >= 0: fenpart = smove[:idx] else: fenpart = smove _, _, fen = fenpart.split(' ', 2) elif params[1] == 'startpos': fen = tools.FEN_INITIAL else: pass pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK for move in moveslist: pos = pos.move(tools.mparse(color, move)) color = 1 - color elif smove.startswith('go'): # default options depth = 1000 movetime = -1 _, *params = smove.split(' ') for param, val in zip(*2 * (iter(params), )): if param == 'depth': depth = int(val) if param == 'movetime': movetime = int(val) if param == 'wtime': our_time = int(val) if param == 'btime': opp_time = int(val) moves_remain = 40 start = time.time() ponder = None for sdepth, _move, _score in searcher.search(pos): moves = tools.pv(searcher, pos, include_scores=False) if show_thinking: entry = searcher.tp_score.get((pos, sdepth, True)) score = int(round((entry.lower + entry.upper) / 2)) usedtime = int((time.time() - start) * 1000) moves_str = moves if len(moves) < 15 else '' output('info depth {} score cp {} time {} nodes {} pv {}'. format(sdepth, score, usedtime, searcher.nodes, moves_str)) if len(moves) > 5: ponder = moves[1] if movetime > 0 and (time.time() - start) * 1000 > movetime: break if (time.time() - start) * 1000 > our_time / moves_remain: break if sdepth >= depth: break entry = searcher.tp_score.get((pos, sdepth, True)) m, s = searcher.tp_move.get(pos), entry.lower # We only resign once we are mated.. That's never? # if s == -sunfish.MATE_UPPER: # output('resign') # else: moves = moves.split(' ') if len(moves) > 1: output(f'bestmove {moves[0]} ponder {moves[1]}') else: output('bestmove ' + moves[0]) elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) else: pass
def main(): logging.basicConfig(filename='sunfish.log', level=logging.DEBUG) pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = True # print name of chess engine print('Sunfish') stack = [] while True: if stack: smove = stack.pop() else: smove = input() logging.debug(smove) if smove == 'quit': break elif smove == 'uci': print('id name Sunfish') print('id author Thomas Ahle') print('uciok') elif smove == 'isready': print('readyok') elif smove == 'ucinewgame': stack.append('position fen ' + tools.FEN_INITIAL) elif smove.startswith('position fen'): params = smove.split(' ', 2) if params[1] == 'fen': fen = params[2] pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK elif smove.startswith('position startpos'): params = smove.split(' ') #startpos pos = tools.parseFEN(tools.FEN_INITIAL) color = WHITE i = 0 while i < len(params): param = params[i] if param == 'moves': i += 1 while i < len(params): mymove = params[i] logging.debug(mymove) m = tools.mparse(color, mymove) logging.debug(m) pos = pos.move(m) color = 1 - color i += 1 i += 1 elif smove.startswith('go'): # default options depth = 1000 movetime = -1 # parse parameters params = smove.split(' ') if len(params) == 1: continue i = 0 while i < len(params): param = params[i] if param == 'depth': i += 1 depth = int(params[i]) if param == 'movetime': i += 1 movetime = int(params[i]) if param == 'wtime': i += 1 our_time = int(params[i]) if param == 'btime': i += 1 opp_time = int(params[i]) i += 1 forced = False moves_remain = 40 start = time.time() ponder = None for _ in searcher._search(pos): moves = tools.pv(searcher, pos, include_scores=False) if show_thinking: entry = searcher.tp_score.get((pos, searcher.depth, True)) score = int(round((entry.lower + entry.upper) / 2)) usedtime = int((time.time() - start) * 1000) moves_str = moves if len(moves) < 15 else '' print('info depth {} score cp {} time {} nodes {} pv {}'. format(searcher.depth, score, usedtime, searcher.nodes, moves_str)) logging.debug( 'info depth {} score cp {} time {} nodes {} pv {}'. format(searcher.depth, score, usedtime, searcher.nodes, moves_str)) if len(moves) > 5: ponder = moves[1] if movetime > 0 and (time.time() - start) * 1000 > movetime: break if (time.time() - start) * 1000 > our_time / moves_remain: break if searcher.depth >= depth: break entry = searcher.tp_score.get((pos, searcher.depth, True)) m, s = searcher.tp_move.get(pos), entry.lower # We only resign once we are mated.. That's never? if s == -sunfish.MATE_UPPER: print('resign') logging.debug('resign') else: moves = moves.split(' ') if len(moves) > 1: #print('bestmove ' + moves[0] + ' ponder ' + moves[1]) print('bestmove ' + moves[0]) logging.debug('bestmove ' + moves[0]) else: print('bestmove ' + moves[0]) logging.debug('bestmove ' + moves[0]) elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) else: pass
def main(eng): parser = argparse.ArgumentParser() parser.add_argument('module', help='chessEngine.py file (without .py)', type=str, default='crapbox', nargs='?') args = parser.parse_args() ''' look at this later sunfish = importlib.import_module(args.module) if args.tables is not None: pst_module = importlib.import_module(args.tables) sunfish.pst = pst_module.pst logging.basicConfig(filename='sunfish.log', level=logging.DEBUG) ''' out = Unbuffered(sys.stdout) def output(line): print(line) #print(line, file=out) #logging.debug(line) pos = tools.parseFEN(tools.FEN_INITIAL) ''' searcher = sunfish.Searcher() ''' color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = False stack = [] while True: if stack: smove = stack.pop() else: smove = input() logging.debug(f'>>> {smove} ') if smove == 'quit': break elif smove == 'uci': output('id name Cristiceps') output('id author Benjamin Christie') output('uciok') elif smove == 'isready': output('readyok') elif smove == 'ucinewgame': stack.append('position fen ' + tools.FEN_INITIAL) # syntax specified in UCI # position [fen | startpos ] moves .... elif smove.startswith('position'): params = smove.split(' ') idx = smove.find('moves') if idx >= 0: moveslist = smove[idx:].split()[1:] else: moveslist = [] if params[1] == 'fen': if idx >= 0: fenpart = smove[:idx] else: fenpart = smove _, _, fen = fenpart.split(' ', 2) elif params[1] == 'startpos': fen = tools.FEN_INITIAL else: pass pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK for move in moveslist: pos = pos.move(tools.mparse(color, move)) color = 1 - color elif smove.startswith('go'): # default options depth = 1000 movetime = -1 _, *params = smove.split(' ') for param, val in zip(*2 * (iter(params), )): if param == 'depth': depth = int(val) if param == 'movetime': movetime = int(val) if param == 'wtime': our_time = int(val) if param == 'btime': opp_time = int(val) moves_remain = 40 start = time.time() ponder = None renderedFen = tools.renderFEN(pos) ''' eng = customEngine.Engine() currMove = str(eng.getRandomMove(renderedFen)) ''' currMove = str(eng.getMove(renderedFen)) output("info currmove " + currMove) time.sleep(0.1) output("bestmove " + currMove) ''' if sdepth >= depth: break ''' elif smove.startswith('stop'): output("bestmove " + currMove) elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) else: pass
def main(): parser = argparse.ArgumentParser() parser.add_argument('module', help='sunfish.py file (without .py)', type=str, default='sunfish', nargs='?') parser.add_argument('--tables', metavar='pst', help='alternative pst table', type=str, default=None) args = parser.parse_args() sunfish = importlib.import_module(args.module) if args.tables is not None: pst_module = importlib.import_module(args.tables) sunfish.pst = pst_module.pst sunfish.QS_LIMIT = pst_module.QS_LIMIT sunfish.EVAL_ROUGHNESS = pst_module.EVAL_ROUGHNESS sys.stdout = tools.Unbuffered(sys.stdout) now = datetime.now() path = 'sunfish-' + now.strftime("%d:%m:%Y-%H:%M:%S:%f") + '.log' sys.stderr = open(path, 'a') pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = False options = {} history = [] stack = [] while True: if stack: smove = stack.pop() else: smove = input() print('>>>', smove, file=sys.stderr) sys.stderr.flush() # For Python 2.7 support if smove == 'quit': break elif smove == 'protover 2': print('feature done=0') print('feature myname="Sunfish"') print('feature usermove=1') print('feature setboard=0' ) # Removing setboard because of lichess bug print('feature ping=1') print('feature sigint=0') print('feature nps=0') print('feature variants="normal"') print('feature option="qs_limit -spin {} -100 1000"'.format( sunfish.QS_LIMIT)) print('feature option="eval_roughness -spin {} 1 1000"'.format( sunfish.EVAL_ROUGHNESS)) print('feature option="draw_test -spin {} 0 1"'.format( int(sunfish.DRAW_TEST))) print('feature done=1') elif smove == 'new': stack.append('setboard ' + tools.FEN_INITIAL) # Clear out the old searcher, including the tables searcher = sunfish.Searcher() del history[:] elif smove.startswith('setboard'): _, fen = smove.split(' ', 1) pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK del history[:] elif smove == 'force': forced = True elif smove.startswith('option'): _, aeqb = smove.split(maxsplit=1) if '=' in aeqb: name, val = aeqb.split('=') else: name, val = aeqb, True if name == 'qs_limit': sunfish.QS_LIMIT = int(val) if name == 'eval_roughness': sunfish.EVAL_ROUGHNESS = int(val) if name == 'draw_test': sunfish.DRAW_TEST = bool(int(val)) options[name] = val elif smove == 'go': forced = False moves_remain = 40 use = our_time / moves_remain # Let's follow the clock of our opponent if our_time >= 100 and opp_time >= 100: use *= our_time / opp_time start = time.time() for ply, move, score in searcher.search(pos, history): entry = searcher.tp_score.get((pos, ply, True)) score = int(round((entry.lower + entry.upper) / 2)) if show_thinking: seconds = time.time() - start used_ms = int(seconds * 100 + .5) moves = tools.pv(searcher, pos, include_scores=False) print('{:>3} {:>8} {:>8} {:>13} \t{}'.format( ply, score, used_ms, searcher.nodes, moves)) print('# {} n/s'.format(round(searcher.nodes / seconds))) print('# Hashfull: {:.3f}%; {} <= score < {}'.format( len(searcher.tp_score) / sunfish.TABLE_SIZE * 100, entry.lower, entry.upper)) # If found mate, just stop if entry.lower >= sunfish.MATE_UPPER: break if time.time() - start > use / 100: break # We sometimes make illegal moves when we're losing, # so it's safer to just resign. if score == -sunfish.MATE_UPPER: print('resign') else: print('move', tools.mrender(pos, move)) pos = pos.move(move) history.append(pos) color = 1 - color elif smove.startswith('ping'): _, N = smove.split() print('pong', N) elif smove.startswith('usermove'): _, smove = smove.split() m = tools.mparse(color, smove) pos = pos.move(m) history.append(pos) color = 1 - color if not forced: stack.append('go') elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) elif smove.startswith('perft'): start = time.time() for d in range(1, 10): res = sum(1 for _ in tools.collect_tree_depth( tools.expand_position(pos), d)) print('{:>8} {:>8}'.format(res, time.time() - start)) elif smove.startswith('post'): show_thinking = True elif smove.startswith('nopost'): show_thinking = False elif any( smove.startswith(x) for x in ('xboard', 'random', 'hard', 'accepted', 'level', 'easy', 'st', 'result', '?', 'name', 'rating')): print('# Ignoring command {}.'.format(smove)) elif smove.startswith('reject'): _, feature = smove.split( )[:2] # split(maxsplit=2) doesnt work in python2.7 if feature == 'sigint': signal.signal(signal.SIGINT, signal.SIG_IGN) print( '# Warning ({} rejected): Might not work as expected.'.format( feature)) else: print('# Warning (unkown command): {}. Treating as move.'.format( smove)) stack.append('usermove {}'.format(smove))
def main(): pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = False stack = [] while True: if stack: smove = stack.pop() else: smove = input() if smove == 'quit': break elif smove == 'protover 2': print('feature done=0') print('feature myname="Sunfish"') print('feature usermove=1') print('feature setboard=1') print('feature ping=1') print('feature sigint=0') print('feature variants="normal"') print('feature done=1') elif smove == 'new': stack.append('setboard ' + tools.FEN_INITIAL) elif smove.startswith('setboard'): _, fen = smove.split(' ', 1) pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK elif smove == 'force': forced = True elif smove == 'go': forced = False moves_remain = 40 use = our_time/moves_remain # Let's follow the clock of our opponent if our_time >= 100 and opp_time >= 100: use *= our_time/opp_time start = time.time() for _ in searcher._search(pos): if show_thinking: ply = searcher.depth entry = searcher.tp_score.get((pos, ply, True)) score = int(round((entry.lower + entry.upper)/2)) dual_score = '{}:{}'.format(entry.lower, entry.upper) used = int((time.time() - start)*100 + .5) moves = tools.pv(searcher, pos, include_scores=False) print('{:>3} {:>8} {:>8} {:>13} \t{}'.format( ply, score, used, searcher.nodes, moves)) if time.time() - start > use/100: break entry = searcher.tp_score.get((pos, searcher.depth, True)) m, s = searcher.tp_move.get(pos), entry.lower # We only resign once we are mated.. That's never? if s == -sunfish.MATE_UPPER: print('resign') else: print('move', tools.mrender(pos, m)) pos = pos.move(m) color = 1-color elif smove.startswith('ping'): _, N = smove.split() print('pong', N) elif smove.startswith('usermove'): _, smove = smove.split() m = tools.mparse(color, smove) pos = pos.move(m) color = 1-color if not forced: stack.append('go') elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) elif smove.startswith('perft'): start = time.time() for d in range(1,10): res = sum(1 for _ in tools.collect_tree_depth(tools.expand_position(pos), d)) print('{:>8} {:>8}'.format(res, time.time()-start)) elif smove.startswith('post'): show_thinking = True elif smove.startswith('nopost'): show_thinking = False elif any(smove.startswith(x) for x in ('xboard','random','hard','accepted','level')): pass else: print("Error (unkown command):", smove)
def main(): pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = True # print name of chess engine print('Sunfish') while True: smove = input() if smove == 'quit' or smove == 'stop': break elif smove == 'uci': print('id name Sunfish') print('uciok') elif smove == 'isready': print('readyok') elif smove == 'ucinewgame': pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = True elif smove.startswith('position'): params = smove.split(' ', 2) if params[1] == 'fen': fen = params[2] pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK else: params = smove.split(' ') if len(params) == 1: continue i = 1 while i < len(params): param = params[i] if param == 'startpos': pos = tools.parseFEN(tools.FEN_INITIAL) color = WHITE elif param == 'moves': i += 1 # rest are moves while i < len(params): m0 = params[i] m = tools.mparse(color, m0) pos = pos.move(m) color = 1 - color i += 1 i += 1 elif smove.startswith('go'): # default options depth = 1000 movetime = -1 moves_remain = 40 tc = 0 # parse parameters params = smove.split(' ') if len(params) == 1: continue i = 0 while i < len(params): param = params[i] if param == 'depth': i += 1 depth = int(params[i]) elif param == 'movetime': i += 1 movetime = int(params[i]) elif param == 'wtime': i += 1 if color == WHITE: movetime = int(params[i]) tc = 1 elif param == 'btime': i += 1 if color == BLACK: movetime = int(params[i]) tc = 1 elif param == 'movestogo': i += 1 moves_remain = int(params[i]) i += 1 if tc == 1 and moves_remain > 0: movetime = movetime / moves_remain forced = False start = time.time() ponder = None for _ in searcher._search(pos): moves = tools.pv(searcher, pos, include_scores=False) if show_thinking: entry = searcher.tp_score.get((pos, searcher.depth, True)) score = int(round((entry.lower + entry.upper) / 2)) usedtime = int((time.time() - start) * 1000) moves_str = moves if len(moves) < 15 else '' print('info depth {} score {} time {} nodes {} {}'.format( searcher.depth, score, usedtime, searcher.nodes, moves_str)) if len(moves) > 5: ponder = moves[1] if movetime > 0 and (time.time() - start) * 1000 > movetime: break if searcher.depth >= depth: break entry = searcher.tp_score.get((pos, searcher.depth, True)) m, s = searcher.tp_move.get(pos), entry.lower moves = moves.split(' ') if len(moves) > 1: print('bestmove ' + moves[0] + ' ponder ' + moves[1]) else: print('bestmove ' + moves[0]) elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) else: pass
def main(): pos = tools.parseFEN(tools.FEN_INITIAL) searcher = sunfish.Searcher() forced = False color = WHITE our_time, opp_time = 1000, 1000 # time in centi-seconds show_thinking = False stack = [] while True: if stack: smove = stack.pop() else: smove = input() if smove == 'quit': break elif smove == 'protover 2': print('feature done=0') print('feature myname="Sunfish"') print('feature usermove=1') print('feature setboard=1') print('feature ping=1') print('feature sigint=0') print('feature variants="normal"') print('feature done=1') elif smove == 'new': stack.append('setboard ' + tools.FEN_INITIAL) elif smove.startswith('setboard'): _, fen = smove.split(' ', 1) pos = tools.parseFEN(fen) color = WHITE if fen.split()[1] == 'w' else BLACK elif smove == 'force': forced = True elif smove == 'go': forced = False moves_remain = 40 use = our_time / moves_remain # Let's follow the clock of our opponent if our_time >= 100 and opp_time >= 100: use *= our_time / opp_time start = time.time() for _ in searcher._search(pos): if show_thinking: ply = searcher.depth entry = searcher.tp_score.get((pos, ply, True)) score = int(round((entry.lower + entry.upper) / 2)) dual_score = '{}:{}'.format(entry.lower, entry.upper) used = int((time.time() - start) * 100 + .5) moves = tools.pv(searcher, pos, include_scores=False) print('{:>3} {:>8} {:>8} {:>13} \t{}'.format( ply, score, used, searcher.nodes, moves)) if time.time() - start > use / 100: break entry = searcher.tp_score.get((pos, searcher.depth, True)) m, s = searcher.tp_move.get(pos), entry.lower # We only resign once we are mated.. That's never? if s == -sunfish.MATE_UPPER: print('resign') else: print('move', tools.mrender(pos, m)) pos = pos.move(m) color = 1 - color elif smove.startswith('ping'): _, N = smove.split() print('pong', N) elif smove.startswith('usermove'): _, smove = smove.split() m = tools.mparse(color, smove) pos = pos.move(m) color = 1 - color if not forced: stack.append('go') elif smove.startswith('time'): our_time = int(smove.split()[1]) elif smove.startswith('otim'): opp_time = int(smove.split()[1]) elif smove.startswith('perft'): start = time.time() for d in range(1, 10): res = sum(1 for _ in tools.collect_tree_depth( tools.expand_position(pos), d)) print('{:>8} {:>8}'.format(res, time.time() - start)) elif smove.startswith('post'): show_thinking = True elif smove.startswith('nopost'): show_thinking = False elif any( smove.startswith(x) for x in ('xboard', 'random', 'hard', 'accepted', 'level')): pass else: print("Error (unkown command):", smove)