예제 #1
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
예제 #2
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
예제 #3
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]))
예제 #4
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)
예제 #5
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)
예제 #6
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
    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))
예제 #7
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]))
예제 #8
0
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))
예제 #9
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)
예제 #10
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)