コード例 #1
0
ファイル: test.py プロジェクト: mekhami/sunfish
def findbest(f, times):
    pos = tools.parseFEN(tools.FEN_INITIAL)
    searcher = sunfish.Searcher()

    print('Printing best move after seconds', times)
    print('-'*60)
    totalpoints = 0
    totaltests = 0
    for line in f:
        fen, opts = tools.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 = tools.parseFEN(fen)
        # am -> avoid move; bm -> best move
        am = tools.parseSAN(pos,opts['am']) if 'am' in opts else None
        bm = tools.parseSAN(pos,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, _ = searcher.search(pos, t)
            mark = tools.renderSAN(pos,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)
コード例 #2
0
def findbest(f, times):
    pos = tools.parseFEN(tools.FEN_INITIAL)
    searcher = sunfish.Searcher()

    print('Printing best move after seconds', times)
    print('-' * 60)
    totalpoints = 0
    totaltests = 0
    for line in f:
        fen, opts = tools.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 = tools.parseFEN(fen)
        # am -> avoid move; bm -> best move
        am = tools.parseSAN(pos, opts['am']) if 'am' in opts else None
        bm = tools.parseSAN(pos, 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, _, _ = tools.search(searcher, pos, t)
            mark = tools.renderSAN(pos, 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)
コード例 #3
0
ファイル: test.py プロジェクト: mekhami/sunfish
def allperft(f, depth=4, verbose=True):
    import gc
    lines = f.readlines()
    for d in range(1, depth+1):
        if verbose:
            print("Going to depth {}/{}".format(d, depth))
        for line in lines:
            parts = line.split(';')
            if verbose:
                print(parts[0])

            pos, score = tools.parseFEN(parts[0]), int(parts[d])
            res = sum(1 for _ in tools.collect_tree_depth(tools.expand_position(pos), d))
            if res != score:
                print('=========================================')
                print('ERROR at depth %d. Gave %d rather than %d' % (d, res, score))
                print('=========================================')
                print(tools.renderFEN(pos,0))
                for move in pos.gen_moves():
                    split = sum(1 for _ in tools.collect_tree_depth(tools.expand_position(pos.move(move)),1))
                    print('{}: {}'.format(tools.mrender(pos, move), split))
                return False
        if verbose:
            print('')
    return True
コード例 #4
0
def allperft(f, depth=4, verbose=True):
    import gc
    lines = f.readlines()
    for d in range(1, depth+1):
        if verbose:
            print("Going to depth {}/{}".format(d, depth))
        for line in lines:
            parts = line.split(';')
            if len(parts) <= d:
                continue
            if verbose:
                print(parts[0])

            pos, score = tools.parseFEN(parts[0]), int(parts[d])
            res = sum(1 for _ in tools.collect_tree_depth(tools.expand_position(pos), d))
            if res != score:
                print('=========================================')
                print('ERROR at depth %d. Gave %d rather than %d' % (d, res, score))
                print('=========================================')
                print(tools.renderFEN(pos,0))
                for move in pos.gen_moves():
                    split = sum(1 for _ in tools.collect_tree_depth(tools.expand_position(pos.move(move)),1))
                    print('{}: {}'.format(tools.mrender(pos, move), split))
                return False
        if verbose:
            print('')
    return True
コード例 #5
0
ファイル: test.py プロジェクト: mekhami/sunfish
 def test_selfplay(self):
     pos = tools.parseFEN(tools.FEN_INITIAL)
     for d in range(200):
         m, score = sunfish.Searcher().search(pos, .1)
         if m is None:
             self.assertTrue(score == 0 or abs(score) >= sunfish.MATE_LOWER)
             break
         pos = pos.move(m)
コード例 #6
0
 def __init__(self):
     # print name of chess engine
     self.pos = tools.parseFEN('2ba3r1/5k3/b8/1n3N2C/4p4/3R2R2/9/5p1r1/4p4/5K3 w moves d4d8 d9e8 f6d7 b6d7 g4f4 d7f6 f4f6')#tools.FEN_INITIAL)
     self.searcher = Searcher()
     self.forced = False
     self.our_time, self.opp_time = 1000, 1000 # time in centi-seconds
     self.stack = []
     print('Moonfish')
コード例 #7
0
ファイル: test.py プロジェクト: mekhami/sunfish
 def test_fen(self):
     fen_file = os.path.join(os.path.dirname(__file__), 'tests/chessathome_openings.fen')
     for fen in open(fen_file):
         fen = fen.strip()
         pos = tools.parseFEN(fen)
         fen1 = tools.renderFEN(pos)
         self.assertEqual(fen, fen1, "Sunfish didn't correctly reproduce the FEN."
                 + repr(pos))
コード例 #8
0
 def test_selfplay(self):
     pos = tools.parseFEN(tools.FEN_INITIAL)
     for d in range(200):
         m, score, _ = tools.search(sunfish.Searcher(), pos, .1)
         if m is None:
             self.assertTrue(score == 0 or abs(score) >= sunfish.MATE_LOWER)
             break
         pos = pos.move(m)
コード例 #9
0
 def test_fen(self):
     fen_file = os.path.join(os.path.dirname(__file__),
                             'tests/chessathome_openings.fen')
     for fen in open(fen_file):
         fen = fen.strip()
         pos = tools.parseFEN(fen)
         fen1 = tools.renderFEN(pos)
         self.assertEqual(
             fen, fen1,
             "Sunfish didn't correctly reproduce the FEN." + repr(pos))
コード例 #10
0
def main():
    # test fen
    pos = tools.parseFEN(tools.FEN_INITIAL)
    assert (pos.board == elephantfish.initial)
    fen = tools.renderFEN(pos)
    assert (fen == tools.FEN_INITIAL)

    benchmark(5, 6)

    self_arena("elephantfish", "algorithms.elephantfish_improve", 100, 20, .1)
コード例 #11
0
def allmate(path):
    with open(path) as f:
        for line in f:
            line = line.strip()
            print(line)

            pos = tools.parseFEN(line)
            _, score, _ = tools.search(sunfish.Searcher(), pos, secs=3600)
            if score < sunfish.MATE_LOWER:
                print("Unable to find mate. Only got score = %d" % score)
                break
コード例 #12
0
ファイル: test.py プロジェクト: mekhami/sunfish
def allmate(path):
    with open(path) as f:
        for line in f:
            line = line.strip()
            print(line)

            pos = tools.parseFEN(line)
            _, score = sunfish.Searcher().search(pos, secs=3600)
            if score < sunfish.MATE_LOWER:
                print("Unable to find mate. Only got score = %d" % score)
                break
コード例 #13
0
 def setUp(self):
     # We don't bother about closing files, since they are just part of the test
     warnings.simplefilter("ignore", ResourceWarning)
     self.perft_file = os.path.join(os.path.dirname(__file__),
                                    'tests/queen.fen')
     test_trees = [
         tools.expand_position(tools.parseFEN(tools.parseEPD(line)[0]))
         for line in open(self.perft_file)
     ]
     self.positions = list(
         itertools.chain(
             *[tools.flatten_tree(tree, depth=2) for tree in test_trees]))
コード例 #14
0
def selfplay(secs=1):
    """ Start a game amwafish vs. amwafish """
    pos = tools.parseFEN(tools.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, _, _ = tools.search(amwafish.Searcher(), pos, secs)
        if m is None:
            print("Game over")
            break
        print("\nmove", tools.mrender(pos, m))
        pos = pos.move(m)
コード例 #15
0
ファイル: test.py プロジェクト: mekhami/sunfish
def selfplay(secs=1):
    """ Start a game sunfish vs. sunfish """
    pos = tools.parseFEN(tools.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.Searcher().search(pos, secs)
        if m is None:
            print("Game over")
            break
        print("\nmove", tools.mrender(pos, m))
        pos = pos.move(m)
コード例 #16
0
ファイル: test.py プロジェクト: mekhami/sunfish
 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]
         pos = tools.parseFEN(tools.FEN_INITIAL)
         for i, msan in enumerate(msans):
             move = tools.parseSAN(pos, msan)
             if re.search('=[BNR]', msan):
                 # Sunfish doesn't support underpromotion
                 break
             msan_back = tools.renderSAN(pos, move)
             self.assertEqual(msan_back, msan,
                              "Sunfish didn't correctly reproduce the SAN move")
             pos = pos.move(move)
コード例 #17
0
ファイル: test.py プロジェクト: mekhami/sunfish
 def test_fen2(self):
     initial = sunfish.Position(sunfish.initial, 0, (True,True), (True,True), 0, 0)
     for pos in tools.flatten_tree(tools.expand_position(initial),3):
         fen = tools.renderFEN(pos)
         self.assertEqual(fen.split()[1], 'wb'[tools.get_color(pos)], "Didn't read color correctly")
         pos1 = tools.parseFEN(fen)
         self.assertEqual(pos.board, pos1.board, "Sunfish didn't correctly reproduce the board")
         self.assertEqual(pos.wc, pos1.wc)
         self.assertEqual(pos.bc, pos1.bc)
         ep =  pos.ep  if not pos.board[pos.ep].isspace() else 0
         ep1 = pos1.ep if not pos1.board[pos1.ep].isspace() else 0
         kp =  pos.kp  if not pos.board[pos.kp].isspace() else 0
         kp1 = pos1.kp if not pos1.board[pos1.kp].isspace() else 0
         self.assertEqual(ep, ep1)
         self.assertEqual(kp, kp1)
コード例 #18
0
 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]
         pos = tools.parseFEN(tools.FEN_INITIAL)
         for i, msan in enumerate(msans):
             if re.search('=[BNR]', msan):
                 # Sunfish doesn't support underpromotion
                 break
             move = tools.parseSAN(pos, msan)
             msan_back = tools.renderSAN(pos, move)
             self.assertEqual(
                 msan_back, msan,
                 "Sunfish didn't correctly reproduce the SAN move")
             pos = pos.move(move)
コード例 #19
0
ファイル: test.py プロジェクト: mekhami/sunfish
def unstable():
    secs = 1
    unstables, total = 0, 0
    path = os.path.join(os.path.dirname(__file__), 'tests/unstable_positions2')
    for line in open(path):
        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        start = time.time()
        for _ in searcher._search(pos):
            if searcher.was_unstable or time.time() - start > secs:
                break
        #list(zip(range(depth), searcher._search(pos)))
        total += 1
        if searcher.was_unstable:
            #print('got one at depth', searcher.depth)
            unstables += 1
        print('{} / {}, at depth {}'.format(unstables, total, searcher.depth))
コード例 #20
0
def unstable():
    secs = 1
    unstables, total = 0, 0
    path = os.path.join(os.path.dirname(__file__), 'tests/unstable_positions2')
    for line in open(path):
        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        start = time.time()
        for depth, _, _ in searcher.search(pos):
            if searcher.was_unstable or time.time() - start > secs:
                break
        #list(zip(range(depth), searcher._search(pos)))
        total += 1
        if searcher.was_unstable:
            #print('got one at depth', searcher.depth)
            unstables += 1
        print('{} / {}, at depth {}'.format(unstables, total, depth))
コード例 #21
0
 def test_fen2(self):
     initial = sunfish.Position(sunfish.initial, 0, (True, True),
                                (True, True), 0, 0)
     for pos in tools.flatten_tree(tools.expand_position(initial), 3):
         fen = tools.renderFEN(pos)
         self.assertEqual(fen.split()[1], 'wb'[tools.get_color(pos)],
                          "Didn't read color correctly")
         pos1 = tools.parseFEN(fen)
         self.assertEqual(pos.board, pos1.board,
                          "Sunfish didn't correctly reproduce the board")
         self.assertEqual(pos.wc, pos1.wc)
         self.assertEqual(pos.bc, pos1.bc)
         ep = pos.ep if not pos.board[pos.ep].isspace() else 0
         ep1 = pos1.ep if not pos1.board[pos1.ep].isspace() else 0
         kp = pos.kp if not pos.board[pos.kp].isspace() else 0
         kp1 = pos1.kp if not pos1.board[pos1.kp].isspace() else 0
         self.assertEqual(ep, ep1)
         self.assertEqual(kp, kp1)
コード例 #22
0
def quickmate(f, min_depth=1):
    """ Similar to allmate, but uses the `bound` function directly to only
    search for moves that will win us the game """
    for line in f:
        line = line.strip()
        print(line)

        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        for d in range(min_depth, 99):
            score = searcher.bound(pos, sunfish.MATE_LOWER, d, root=True)
            if score >= sunfish.MATE_LOWER:
                #print(tools.pv(searcher, 0, pos))
                break
            print('Score at depth {}: {}'.format(d, score))
        else:
            print("Unable to find mate. Only got score = %d" % score)
            return
        print(tools.pv(searcher, pos, include_scores=False))
コード例 #23
0
ファイル: test.py プロジェクト: mekhami/sunfish
def quickmate(f, min_depth=1):
    """ Similar to allmate, but uses the `bound` function directly to only
    search for moves that will win us the game """
    for line in f:
        line = line.strip()
        print(line)

        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        for d in range(min_depth, 99):
            score = searcher.bound(pos, sunfish.MATE_LOWER, d, root=True)
            if score >= sunfish.MATE_LOWER:
                #print(tools.pv(searcher, 0, pos))
                break
            print('Score at depth {}: {}'.format(d, score))
        else:
            print("Unable to find mate. Only got score = %d" % score)
            return
        print(tools.pv(searcher, pos, include_scores=False))
コード例 #24
0
ファイル: test.py プロジェクト: mekhami/sunfish
def benchmark(cnt=20, depth=3):
    path = os.path.join(os.path.dirname(__file__), 'tests/chessathome_openings.fen')
    random.seed(0)
    start = time.time()
    nodes = 0
    for i, line in enumerate(random.sample(list(open(path)), cnt)):
        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        start1 = time.time()
        for _ in searcher._search(pos):
            speed = int(round(searcher.nodes/(time.time()-start1)))
            print('Benchmark: {}/{}, Depth: {}, Speed: {:,}N/s'.format(
                i+1, cnt, searcher.depth, speed), end='\r')
            sys.stdout.flush()
            if searcher.depth == depth:
                nodes += searcher.nodes
                break
    print()
    total_time = time.time() - start
    speed = int(round(nodes/total_time))
    print('Total time: {}, Total nodes: {}, Average speed: {:,}N/s'.format(
        total_time, nodes, speed))
コード例 #25
0
ファイル: test.py プロジェクト: mekhami/sunfish
def quickdraw(f, depth):
    k, n = 0, 0
    for line in f:
        line = line.strip()
        print(line)
        n += 1

        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        for d in range(depth, 10):
            s0 = searcher.bound(pos, 0, d, root=True)
            s1 = searcher.bound(pos, 1, d, root=True)
            if s0 >= 0 and s1 < 1:
                k += 1
                break
            else:
                print('depth {}, s0 {}, s1 {}'.format(d, s0, s1))
            #print(d, s0, s1, tools.pv(0, pos))
        else:
            print("Fail: Unable to find draw!")
            #return
        print(tools.pv(searcher, pos, False))
    print('Found {}/{} draws'.format(k,n))
コード例 #26
0
def quickdraw(f, depth):
    k, n = 0, 0
    for line in f:
        line = line.strip()
        print(line)
        n += 1

        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        for d in range(depth, 10):
            s0 = searcher.bound(pos, 0, d, root=True)
            s1 = searcher.bound(pos, 1, d, root=True)
            if s0 >= 0 and s1 < 1:
                k += 1
                break
            else:
                print('depth {}, s0 {}, s1 {}'.format(d, s0, s1))
            #print(d, s0, s1, tools.pv(0, pos))
        else:
            print("Fail: Unable to find draw!")
            #return
        print(tools.pv(searcher, pos, False))
    print('Found {}/{} draws'.format(k, n))
コード例 #27
0
def benchmark(cnt=20, depth=3):
    path = os.path.join(os.path.dirname(__file__),
                        'tests/chessathome_openings.fen')
    random.seed(0)
    start = time.time()
    nodes = 0
    for i, line in enumerate(random.sample(list(open(path)), cnt)):
        pos = tools.parseFEN(line)
        searcher = sunfish.Searcher()
        start1 = time.time()
        for search_depth, _, _ in searcher.search(pos):
            speed = int(round(searcher.nodes / (time.time() - start1)))
            print('Benchmark: {}/{}, Depth: {}, Speed: {:,}N/s'.format(
                i + 1, cnt, search_depth, speed),
                  end='\r')
            sys.stdout.flush()
            if search_depth == depth:
                nodes += searcher.nodes
                break
    print()
    total_time = time.time() - start
    speed = int(round(nodes / total_time))
    print('Total time: {}, Total nodes: {}, Average speed: {:,}N/s'.format(
        total_time, nodes, speed))
コード例 #28
0
def generate_random_opening():
    pos = tools.parseFEN(tools.FEN_INITIAL)
    steps = 6
    for i in range(steps):
        pos = pos.move(random_move(pos))
    return pos
コード例 #29
0
    def get_move(self, position = "rCbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/7C1/9/RNBAKABNR", 
                 player = "b", times = 1000, depth = 6, show_thinking = 1):   
        
        smove = "position fen " + position + " " + player + " - - 0 1"
        params = smove.split(' ', 2)
        if params[1] == 'fen':
            fen = params[2]
            pos = tools.parseFEN(fen)
            color = RED if fen.split()[1] == 'w' else BLACK

        smove = "go time " + str(times) + " depth " + str(depth)
          
        if smove.startswith('go'):
            #  default options
            # depth = depth
            movetime = -1

            # parse parameters
            params = smove.split(' ')
            if len(params) == 1: return

            i = 0
            while i < len(params):
                param = params[i]
                if param == 'depth':
                    i += 1
                    depth = int(params[i])
                if param == 'time':
                    i += 1
                    movetime = int(params[i])
                i += 1

            forced = False

            moves_remain = 40

            start = time.time()
            ponder = None
            for s_score in self.searcher._search(pos):
                moves = tools.pv(self.searcher, pos, include_scores=False)

                if show_thinking:
                    entry = self.searcher.tp_score.get((pos, self.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 {} pv {}'.format(self.searcher.depth, score, usedtime, self.searcher.nodes, moves_str))

                if len(moves) > 5:
                    ponder = moves[1]
                
                #将军死和被将军死 才会出现MATE_UPPER的值
                if (s_score >= MATE_UPPER) or (s_score <= -MATE_UPPER): 
                    break
            
                if movetime > 0 and (time.time() - start) * 1000 > movetime:
                    break

                if self.searcher.depth >= depth:
                    break

            entry = self.searcher.tp_score.get((pos, self.searcher.depth, True))
            m, s = self.searcher.tp_move.get(pos), entry.lower
            # We only resign once we are mated.. That's never?
            if s == -MATE_UPPER:
                print('resign')
            else:
                moves = moves.split(' ')
                if show_thinking:
                    if len(moves) > 1:
                        print('bestmove ' + moves[0] + ' ponder ' + moves[1])
                    else:
                        print('bestmove ' + moves[0])
        return moves[0]
コード例 #30
0
ファイル: uci.py プロジェクト: tshen17/ChessBot
def main():
    # parser = argparse.ArgumentParser()
    # parser.add_argument('module', help='play.py', type=str, default='play', nargs='?')
    # parser.add_argument('--tables', metavar='pst', help='alternative pst table', type=str, default=None)
    # args = parser.parse_args()
    #
    # engine = 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)

    board = tools.parseFEN(tools.FEN_INITIAL)
    e = engine.Engine()
    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 fisherman')
            output('id author Tyler Shen')
            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

            board = tools.parseFEN(fen)
            play.display_pos(board)
            color = WHITE if fen.split()[1] == 'w' else BLACK

            for move in moveslist:
                if color == WHITE:
                    # WARNING! to_move Does not work properly
                    board = board.move(tools.to_move(move))
                else:
                    board = board.move(tools.to_move(tools.flip_move(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 _move, _score in engine.search(board):
            #     moves = tools.pv(searcher, pos, include_scores=False)
            #
            #     if show_thinking:
            #         node = engine.tp_score.get((pos, sdepth, True))
            #         score = int(round((node.lower + node.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

            move, score = e.search(board)

            # We only resign once we are mated.. That's never?
            if score == -eval.MATE_UPPER:
                output('resign')
            else:
                output('bestmove ' + move)
            # 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
コード例 #31
0
ファイル: uci.py プロジェクト: kennyfrc/sunfishNNUE
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
コード例 #32
0
ファイル: test.py プロジェクト: mekhami/sunfish
 def setUp(self):
     # We don't bother about closing files, since they are just part of the test
     warnings.simplefilter("ignore", ResourceWarning)
     self.perft_file = os.path.join(os.path.dirname(__file__), 'tests/queen.fen')
     test_trees = [tools.expand_position(tools.parseFEN(tools.parseEPD(line)[0])) for line in open(self.perft_file)]
     self.positions = list(itertools.chain(*[tools.flatten_tree(tree, depth=2) for tree in test_trees]))
コード例 #33
0
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)
コード例 #34
0
ファイル: xboard.py プロジェクト: sebastianrevuelta/sunfish
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))
コード例 #35
0
ファイル: uci.py プロジェクト: benjaminchristie/Cristiceps
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
コード例 #36
0
ファイル: uci.py プロジェクト: zhyack/SCC
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
コード例 #37
0
ファイル: xboard.py プロジェクト: teacoffee2017/sunfish
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)
コード例 #38
0
def play(version1_version2_secs_plus_fen):
    ''' returns 1 if fish1 won, 0 for draw and -1 otherwise '''
    version1, version2, secs, plus, fen = version1_version2_secs_plus_fen
    modules = [importlib.import_module(version1), importlib.import_module(version2)]
    searchers = []
    for module in modules:
        if hasattr(module, 'Searcher'):
            searchers.append(module.Searcher())
        else: searchers.append(module)
    times = [secs, secs]
    efactor = [1, 1]
    pos = tools.parseFEN(fen)
    seen = set()
    for d in range(200):
        moves_remain = 30
        use = times[d%2]/moves_remain + plus
        # Use a bit more time, if we have more on the clock than our opponent
        use += (times[d%2] - times[(d+1)%2])/10
        use = max(use, plus)
        t = time.time()
        m, score, depth = tools.search(searchers[d%2], pos, use*efactor[d%2])
        efactor[d%2] *= (use/(time.time() - t))**.5
        times[d%2] -= time.time() - t
        times[d%2] += plus
        #print('Used {:.2} rather than {:.2}. Off by {:.2}. Remaining: {}'
            #.format(time.time()-t, use, (time.time()-t)/use, times[d%2]))
        if times[d%2] < 0:
            print('{} ran out of time'.format(version2 if d%2 == 1 else version1))
            return version1 if d%2 == 1 else version2
            pass

        if m is None:
            print('Game not done, but no move? Score', score)
            name = version1 if d%2 == 0 else version2
            print(version1, tools.renderFEN(pos))
            assert False

        # Test move
        is_dead = lambda pos: any(pos.value(m) >= amwafish.MATE_LOWER for m in pos.gen_moves())
        if is_dead(pos.move(m)):
            name = version1 if d%2 == 0 else version2
            print('{} made an illegal move {} in position {}. Depth {}, Score {}'.
                    format(name, tools.mrender(pos,m), tools.renderFEN(pos), depth, score))
            return version2 if d%2 == 0 else version1
            #assert False

        # Make the move
        pos = pos.move(m)

        # Test repetition draws
        # This is by far the most common type of draw
        if pos in seen:
            #print('Rep time at end', times)
            return None
        seen.add(pos)

        any_moves = not all(is_dead(pos.move(m)) for m in pos.gen_moves())
        in_check = is_dead(pos.nullmove())
        if not any_moves:
            if not in_check:
                # This is actually a bit interesting. Why would we ever throw away a win like this?
                name = version1 if d%2 == 0 else version2
                print('{} stalemated? depth {} {}'.format(
                    name, depth, tools.renderFEN(pos)))
                if score != 0:
                    print('it got the wrong score: {} != 0'.format(score))
                return None
            else:
                name = version1 if d%2 == 0 else version2
                if score < amwafish.MATE_LOWER:
                    print('{} mated, but did not realize. Only scored {} in position {}, depth {}'.format(name, score, tools.renderFEN(pos), depth))
                return name
    print('Game too long', tools.renderFEN(pos))
    return None
コード例 #39
0
def parseFen(fen):
    return tools.parseFEN(fen)
コード例 #40
0
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
コード例 #41
0
ファイル: test.py プロジェクト: mekhami/sunfish
def play(version1_version2_secs_plus_fen):
    ''' returns 1 if fish1 won, 0 for draw and -1 otherwise '''
    version1, version2, secs, plus, fen = version1_version2_secs_plus_fen
    modules = [importlib.import_module(version1), importlib.import_module(version2)]
    searchers = []
    for module in modules:
        if hasattr(module, 'Searcher'):
            searchers.append(module.Searcher())
        else: searchers.append(module)
    times = [secs, secs]
    efactor = [1, 1]
    pos = tools.parseFEN(fen)
    seen = set()
    for d in range(200):
        moves_remain = 30
        use = times[d%2]/moves_remain + plus
        # Use a bit more time, if we have more on the clock than our opponent
        use += (times[d%2] - times[(d+1)%2])/10
        use = max(use, plus)
        t = time.time()
        m, score = searchers[d%2].search(pos, use*efactor[d%2])
        efactor[d%2] *= (use/(time.time() - t))**.5
        times[d%2] -= time.time() - t
        times[d%2] += plus
        #print('Used {:.2} rather than {:.2}. Off by {:.2}. Remaining: {}'
            #.format(time.time()-t, use, (time.time()-t)/use, times[d%2]))
        if times[d%2] < 0:
            print('{} ran out of time'.format(version2 if d%2 == 1 else version1))
            return version1 if d%2 == 1 else version2
            pass

        if m is None:
            print('Game not done, but no move? Score', score)
            name = version1 if d%2 == 0 else version2
            print(version1, tools.renderFEN(pos))
            assert False

        # Test move
        is_dead = lambda pos: any(pos.value(m) >= sunfish.MATE_LOWER for m in pos.gen_moves())
        if is_dead(pos.move(m)):
            name = version1 if d%2 == 0 else version2
            print('{} made an illegal move {} in position {}. Depth {}, Score {}'.
                    format(name, tools.mrender(pos,m), tools.renderFEN(pos), searchers[d%2].depth, score))
            assert False

        # Make the move
        pos = pos.move(m)

        # Test repetition draws
        # This is by far the most common type of draw
        if pos in seen:
            #print('Rep time at end', times)
            return None
        seen.add(pos)

        any_moves = not all(is_dead(pos.move(m)) for m in pos.gen_moves())
        in_check = is_dead(pos.nullmove())
        if not any_moves:
            if not in_check:
                # This is actually a bit interesting. Why would we ever throw away a win like this?
                name = version1 if d%2 == 0 else version2
                print('{} stalemated? depth {} {}'.format(
                    name, searchers[d%2].depth, tools.renderFEN(pos)))
                if score != 0:
                    print('it got the wrong score: {} != 0'.format(score))
                return None
            else:
                name = version1 if d%2 == 0 else version2
                if score < sunfish.MATE_LOWER:
                    print('{} mated, but did not realize. Only scored {} in position {}, depth {}'.format(name, score, tools.renderFEN(pos), searchers[d%2].depth))
                return name
    print('Game too long', tools.renderFEN(pos))
    return None
コード例 #42
0
def positionInitial():
    return tools.parseFEN(tools.FEN_INITIAL)
コード例 #43
0
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
コード例 #44
0
ファイル: xboard.py プロジェクト: LucaHermes/sunfish
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))
コード例 #45
0
ファイル: moonfish_ucci.py プロジェクト: walker8088/moonfish
def main():
    pos = tools.parseFEN(
        '2ba3r1/5k3/b8/1n3N2C/4p4/3R2R2/9/5p1r1/4p4/5K3 w moves d4d8 d9e8 f6d7 b6d7 g4f4 d7f6 f4f6'
    )  #tools.FEN_INITIAL)
    searcher = Searcher()
    forced = False
    color = RED
    our_time, opp_time = 1000, 1000  # time in centi-seconds
    show_thinking = True

    # print name of chess engine
    print('Moonfish')

    stack = []
    while True:
        if stack:
            smove = stack.pop()
        else:
            smove = input()

        if smove == 'quit':
            break

        elif smove == 'ucci':
            print('ucciok')

        elif smove == 'isready':
            print('readyok')

        elif smove == 'newgame':
            stack.append('position fen ' + tools.FEN_INITIAL)

        elif smove.startswith('position'):
            params = smove.split(' ', 2)
            if params[1] == 'fen':
                fen = params[2]
                pos = tools.parseFEN(fen)
                color = RED if fen.split()[1] == 'w' else BLACK

        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])
                i += 1

            forced = False

            moves_remain = 40

            start = time.time()
            ponder = None
            for s_score 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 {} pv {}'.format(
                            searcher.depth, score, usedtime, searcher.nodes,
                            moves_str))

                if len(moves) > 5:
                    ponder = moves[1]

                #将军死和被将军死 才会出现MATE_UPPER的值
                if (s_score >= MATE_UPPER) or (s_score <= -MATE_UPPER):
                    break

                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
            # We only resign once we are mated.. That's never?
            if s == -MATE_UPPER:
                print('resign')
            else:
                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