Exemple #1
0
	def test_free_rows_and_columns(self):
		b = Board(2,2)
		self.assertEquals(free_rows_and_columns(b.data),(2,2))
		b2 = b.add_piece([("N",0,0)])
		self.assertEquals(free_rows_and_columns(b2.data),(1,1))
		b3 = b2.add_piece([("N",0,1)])
		self.assertEquals(free_rows_and_columns(b3.data),(1,0), b3)
Exemple #2
0
def repertoire(id=1):
    if request.args.get('practice'):
        print(practice(id))
    board = Board()
    form = MoveForm()
    if request.method == 'GET':
        position = Position.query.filter_by(id=id).first()
        moves = Move.query.join(User.moves).filter(User.id == current_user.id, Move.source_position_id == position.id).all()
        return render_template('tools/repertoire.html', fen=position.fen + ' 0 1', moves=moves, form=form, id=id)
    
    if request.method == 'POST':
        fen = form.append_fen.data
        san = form.append_san.data
        quality_id = form.quality.data
        board = Board(fen)
        board.push_san(san)
        source_position = Position.query.filter_by(fen=' '.join(fen.split()[:-2])).first()
        end_position_fen = ' '.join(board.fen().split()[:-2])
        end_position = Position.query.filter_by(fen=end_position_fen).first()
        if end_position is None:
            end_position = Position(fen=end_position_fen)
            db.session.add(end_position)
        move = Move.query.filter_by(source_position_id=source_position.id, destination_position_id=end_position.id).first()
        if move is None:
            move = Move(source_position_id=source_position.id, destination_position_id=end_position.id, san=san)
            um = UserMove(quality_id=quality_id)
            um.move = move
            current_user.moves.append(um)
        db.session.commit()
        moves = Move.query.join(User.moves).filter(User.id == current_user.id, Move.source_position_id == source_position.id).all()
        return render_template('tools/repertoire.html', fen=source_position.fen + ' 0 1', moves=moves, form=form, id=id)
Exemple #3
0
 def display_move_on_clock(self, move, fen, side, beep=False, left_dots=0, right_dots=0):
     bit_board = Board(fen)
     move_text = bit_board.san(move)
     if side == ClockSide.RIGHT:
         move_text = move_text.rjust(11)
     text = self.dgttranslate.move(move_text)
     self._display_on_dgt_pi(text, beep, left_dots, right_dots)
Exemple #4
0
 def pv_to_san(self):
     if(self.san_arr == None):
         return ""
     else:
         try:
             pv_san = []
             board = Board(self.san_arr[0])
             moves = self.san_arr[1]
             for uci in moves:
                 move = Move.from_uci(uci)
                 if(move in board.pseudo_legal_moves):
                     pv_san.append(board.san(move))
                     board.push(move)
             if(len(pv_san) > 0):
                 s = ""
                 white_moves = True
                 move_no = (self.no_game_halfmoves//2)+1
                 if(self.no_game_halfmoves % 2 == 1):
                     white_moves = False
                     s += str(move_no)+". ... "
                     move_no += 1
                 for san in pv_san:
                     if(white_moves):
                         s += " "+str(move_no)+". "+san
                         move_no +=1
                     else:
                         s += " "+san
                     white_moves = not white_moves
                 return s
             else:
                 return ""
         except ValueError:
             return ""
Exemple #5
0
 def display_move_on_clock(self, move, fen, beep=False):
     if self.enable_dgt_3000:
         bit_board = Board(fen)
         text = self.dgttranslate.move(bit_board.san(move))
         self._display_on_dgt_3000(text, beep)
     else:
         text = ' ' + move.uci()
         self._display_on_dgt_xl(text, beep)
Exemple #6
0
	def test_eq(self):
		a = Board(2,2)
		b = Board(2,2)
		c = a.add_piece([("N",0,0)])
		self.assertTrue(a == a)
		self.assertTrue(a == b)
		self.assertTrue(b == a)
		self.assertTrue(a != c)
Exemple #7
0
	def test_rotations(self):
		b = Board(2,2) #.add_piece([("N",0,0)])
		print b.__dict__
		rots = list(b.rotations())
		for r in rots:
			print r.__dict__
		self.assertTrue(all(a==b for a in rots for b in rots))
		self.assertItemsEqual(rots, [b])	
Exemple #8
0
 def display_move_on_clock(self, move, fen, beep=BeepLevel.CONFIG):
     beep = self.get_beep_level(beep)
     if self.enable_dgt_3000:
         bit_board = Board(fen)
         text = bit_board.san(move)
         self._display_on_dgt_3000(text, beep)
     else:
         text = ' ' + move.uci()
         self._display_on_dgt_xl(text, beep)
Exemple #9
0
 def run_engine(self, fen, move_time):
     #self.base_engine.setoption({'Clear': 'Hash'})
     board = Board()
     board.set_fen(fen)
     self.base_engine.position(board)
     self.base_engine.go(movetime=move_time, async_callback=False)
     while self.base_engine.bestmove is None:
         pass
     return self.info_handler_base.info["score"][1].cp
Exemple #10
0
 def _oldstyle_fen(game: chess.Board):
     builder = []
     builder.append(game.board_fen())
     builder.append('w' if game.turn == chess.WHITE else 'b')
     builder.append(game.castling_xfen())
     builder.append(chess.SQUARE_NAMES[game.ep_square] if game.ep_square else '-')
     builder.append(str(game.halfmove_clock))
     builder.append(str(game.fullmove_number))
     return ' '.join(builder)
Exemple #11
0
	def test_board(self):
		# ..    NN
		# .. => NN
		b = Board(2,2)
		print b.free
		self.assertTrue(b.add_piece([("N",0,0)]))
		b2 = b.add_piece([("N",0,0),("N",0,1),("N",1,0),("N",1,1)])
		self.assertTrue(b2)
		self.assertEquals(len(b2.free), 0, "\n%s\n\nfree:%s"%(b2, b2.free))
		self.assertFalse(b.add_piece([("Q",0,0),("Q",1,1)]))
 def deep_copy_board_pos(self, board):
     fresh = Board()
     for i in range(0, 8):
         for j in range(0, 8):
             piece = board.piece_at(j * 8 + i)
             if piece:
                 sym = piece.symbol()
                 fresh.set_piece_at(j * 8 + i, Piece.from_symbol(sym))
             else:
                 fresh.remove_piece_at(j * 8 + i)
     return fresh
Exemple #13
0
 def run_engine(self, epd, max_depth=0, move_time=0):
     self.modified_engine.setoption({'Clear': 'Hash'})
     board = Board()
     board.set_epd(epd)
     self.modified_engine.position(board)
     if max_depth != 0:
         self.modified_engine.go(depth=max_depth, async_callback=False)
     else:
         self.modified_engine.go(movetime=move_time, async_callback=False)
     while self.modified_engine.bestmove is None:
         pass
     result = self.info_handler_modified.info["score"][1].cp
     return result
Exemple #14
0
 def test_get_fen(self):
     #test castling
     self.my_board = Board('rn1qkbnr/ppp2ppp/3p4/4p3/2B1P1b1/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 4')
     self.my_board.move_algebraic('Rg1')
     self.assertEqual(self.my_board.get_fen(), 'rn1qkbnr/ppp2ppp/3p4/4p3/2B1P1b1/5N2/PPPP1PPP/RNBQK1R1 b Qkq - 0 4')
     #test helper
     self.my_board = Board('8/8/4kr2/3p4/8/1N1K1N2/8/8 w - - 0 1')
     self.my_board.move_algebraic('Nbd4+')
     self.assertEqual(self.my_board.get_fen(), '8/8/4kr2/3p4/3N4/3K1N2/8/8 b - - 0 1')
     #test enpassant
     self.my_board = Board('r1bqkbnr/p1pp1ppp/n7/1p1PpP2/8/8/PPP1P1PP/RNBQKBNR w KQkq e6 0 5')
     self.my_board.move_algebraic('dxe6')
     self.assertEqual(self.my_board.get_fen(), 'r1bqkbnr/p1pp1ppp/n3P3/1p3P2/8/8/PPP1P1PP/RNBQKBNR b KQkq - 0 5')
Exemple #15
0
    def from_board(cls: Type[GameT], board: chess.Board) -> GameT:
        """Creates a game from the move stack of a :class:`~chess.Board()`."""
        # Setup the initial position.
        game = cls()
        game.setup(board.root())
        node = game  # type: GameNode

        # Replay all moves.
        for move in board.move_stack:
            node = node.add_variation(move)

        game.headers["Result"] = board.result()
        return game
Exemple #16
0
 def setUp(self):
     self.notation = [["WR", "WN", "WB", "WQ", "WK", "WB", "WN", "WR"],
                      ["WP", "WP", "WP", "WP",   "", "WP", "WP", "WP"], 
                      [  "",   "",   "",   "",   "",   "",   "",   ""],
                      [  "",   "",   "",   "", "WP",   "",   "",   ""],
                      [  "",   "",   "",   "", "BP",   "",   "",   ""],
                      [  "",   "",   "",   "",   "",   "",   "",   ""],
                      ["BP", "BP", "BP", "BP",   "", "BP", "BP", "BP"], 
                      ["BR", "BN", "BB", "BQ", "BK", "BB", "BN", "BR"]]
     self.flat_notation = list(itertools.chain(*self.notation))
     self.num_pieces = len([square for square in self.flat_notation if square != ""])
     self.empty_board = Board()
     self.board = Board.from_notation(self.notation)
Exemple #17
0
 def display_move_on_clock(self, move, fen, side, beep=False, left_dots=0, right_dots=0):
     if self.enable_dgt_3000:
         bit_board = Board(fen)
         move_text = bit_board.san(move)
         if side == ClockSide.RIGHT:
             move_text = move_text.rjust(8)
         text = self.dgttranslate.move(move_text)
         self._display_on_dgt_3000(text, beep, left_dots, right_dots)
     else:
         move_text = move.uci()
         if side == ClockSide.RIGHT:
             move_text = move_text.rjust(6)
         self._display_on_dgt_xl(move_text, beep, left_dots, right_dots)
Exemple #18
0
    def hash_castling(self, board: chess.Board) -> int:
        zobrist_hash = 0

        # Hash in the castling flags.
        if board.has_kingside_castling_rights(chess.WHITE):
            zobrist_hash ^= self.array[768]
        if board.has_queenside_castling_rights(chess.WHITE):
            zobrist_hash ^= self.array[768 + 1]
        if board.has_kingside_castling_rights(chess.BLACK):
            zobrist_hash ^= self.array[768 + 2]
        if board.has_queenside_castling_rights(chess.BLACK):
            zobrist_hash ^= self.array[768 + 3]

        return zobrist_hash
Exemple #19
0
    def _accept_node(self, parent_board: chess.Board, visitor: "BaseVisitor[ResultT]") -> None:
        if self.starting_comment:
            visitor.visit_comment(self.starting_comment)

        visitor.visit_move(parent_board, self.move)

        parent_board.push(self.move)
        visitor.visit_board(parent_board)
        parent_board.pop()

        for nag in sorted(self.nags):
            visitor.visit_nag(nag)

        if self.comment:
            visitor.visit_comment(self.comment)
Exemple #20
0
 def display_move_on_clock(self, message):
     left_dots = message.ld if hasattr(message, 'ld') else ClockDots.NONE
     right_dots = message.rd if hasattr(message, 'rd') else ClockDots.NONE
     display_m = self.enable_dgt_3000 and not self.dgtserial.enable_revelation_leds
     if display_m:
         bit_board = Board(message.fen)
         move_text = bit_board.san(message.move)
         if message.side == ClockSide.RIGHT:
             move_text = move_text.rjust(8)
         text = self.dgttranslate.move(move_text)
         self._display_on_dgt_3000(text, message.beep, left_dots, right_dots)
     else:
         move_text = message.move.uci()
         if message.side == ClockSide.RIGHT:
             move_text = move_text.rjust(6)
         self._display_on_dgt_xl(move_text, message.beep, left_dots, right_dots)
Exemple #21
0
def main():
    args = docopt(__doc__)
    game, title = choose_game(args["<PGNfile>"])
    b = Board()
    moves, annotations = [], []
    for i, move in enumerate(game.mainline_moves()):
        if i % 2 == 0:
            moves.append(f"{int(i/2)+1}. {b.san(move)}")
        else:
            moves[-1] += f" {b.san(move)} "
        b.push(move)
        display(b, title, moves)
        annotate = input("> ")
        if annotate:
            annotations.append((int(i / 2) + 1, annotate))
    print(annotate)
    print("FINISHED")
    def __init__(self, board=None, parent=None):
        super(QWidget, self).__init__()
        policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setSizePolicy(policy)

        if board == None:
            board = Board()
            board.castling_rights = 0

        self.board = board

        self.parent = parent

        self.borderWidth = 12
        self.pieceImages = PieceImages()

        self.selected_xy = None
        self.pcs = [["P", "R", "B", "N", "Q", "K"], ["p", "r", "b", "n", "q", "k"]]

        self.initUI()
Exemple #23
0
    def visit_move(self, board: chess.Board, move: chess.Move) -> None:
        if self.variations or not self.variation_depth:
            # Write the move number.
            if board.turn == chess.WHITE:
                self.write_token(str(board.fullmove_number) + ". ")
            elif self.force_movenumber:
                self.write_token(str(board.fullmove_number) + "... ")

            # Write the SAN.
            self.write_token(board.san(move) + " ")

            self.force_movenumber = False
Exemple #24
0
    def get_san(self, message, is_xl=False):
        """Create a chess.board plus a text ready to display on clock."""

        def move(text: str, language: str, capital: bool, short: bool):
            """Return move text for clock display."""
            if short:
                directory = {}
                if language == 'de':
                    directory = {'R': 'T', 'N': 'S', 'B': 'L', 'Q': 'D'}
                if language == 'nl':
                    directory = {'R': 'T', 'N': 'P', 'B': 'L', 'Q': 'D'}
                if language == 'fr':
                    directory = {'R': 'T', 'N': 'C', 'B': 'F', 'Q': 'D', 'K': '@'}
                if language == 'es':
                    directory = {'R': 'T', 'N': 'C', 'B': 'A', 'Q': 'D', 'K': '@'}
                if language == 'it':
                    directory = {'R': 'T', 'N': 'C', 'B': 'A', 'Q': 'D', 'K': '@'}
                for i, j in directory.items():
                    text = text.replace(i, j)
                text = text.replace('@', 'R')  # replace the King "@" from fr, es, it languages
            if capital:
                return text.upper()
            else:
                return text

        bit_board = Board(message.fen, chess960=message.uci960)
        if bit_board.is_legal(message.move):
            if message.long:
                move_text = message.move.uci()
            else:
                move_text = bit_board.san(message.move)
        else:
            logging.warning('[%s] illegal move %s found - uci960: %s fen: %s', self.get_name(), message.move,
                            message.uci960, message.fen)
            move_text = 'er{}' if is_xl else 'err {}'
            move_text = move_text.format(message.move.uci()[:4])

        if message.side == ClockSide.RIGHT:
            move_text = move_text.rjust(6 if is_xl else 8)
        return bit_board, move(move_text, message.lang, message.capital and not is_xl, not message.long)
Exemple #25
0
class PawnTest(unittest.TestCase):

    def setUp(self):
        self.board = Board()
        self.wpawn = self.board.add(Color.white, Pawn, Position(1,4))
        self.bpawn = self.board.add(Color.black, Pawn, Position(2,3))

    def test_possible_moves(self):
        self.assertListEqual(self.wpawn.possible_moves, [Position(2, 4), Position(3, 4)])
        self.assertListEqual(self.bpawn.possible_moves, [Position(1, 3)])

    def test_possible_attacks(self):
        self.assertListEqual(self.wpawn.possible_attacks, [self.bpawn.position])
        self.assertListEqual(self.bpawn.possible_attacks, [self.wpawn.position])
Exemple #26
0
 def setUp(self):
     self.board = Board.from_notation([[  "",   "",   "",   "",   "",   "",   "",   ""],
                                       [  "", "WR",   "",   "",   "",   "",   "",   ""], 
                                       [  "",   "",   "",   "",   "",   "",   "",   ""],
                                       [  "",   "",   "",   "",   "",   "",   "",   ""],
                                       [  "", "WR",   "", "BR",   "", "WR",   "",   ""],
                                       [  "",   "",   "",   "",   "",   "",   "",   ""],
                                       [  "",   "",   "",   "",   "",   "",   "", "BR"], 
                                       [  "",   "",   "",   "",   "",   "",   "",   ""]])
     self.upper_rook = self.board[1][1]
     self.left_rook = self.board[4][1]
     self.right_rook = self.board[4][5]
     self.middle_rook = self.board[4][3]
     self.lower_rook = self.board[6][7]
Exemple #27
0
def read(f):
	format = Algebra()
	board = Board()
	player = 'white'
	for move in parse_pgn(f):
		if type(move) == types.TupleType and move[0] == "done":
			print "winner", move[1]
			board = Board()
			player = 'white'
			continue
		elif type(move) == types.TupleType and move[0] == 'metadata':
			print move[1]
			continue
		parsed = format.interpret(move, board, player)
		print '...' if player == 'black' else '', move, parsed
#		legal_moves = [x for x in board.legal_moves(player)]
#		if not parsed in legal_moves:
#			raise Exception, "%s is not legal: not in %s" % (repr(parsed), repr(sorted([board.format_move(m) for m in legal_moves])))
		board.apply_move(parsed)
		if player == 'white':
			player = 'black'
		else:
			player = 'white'
Exemple #28
0
    def parse_san(self, board: chess.Board, san: str) -> chess.Move:
        """
        When the visitor is used by a parser, this is called to parse a move
        in standard algebraic notation.

        You can override the default implementation to work around specific
        quirks of your input format.
        """
        # Replace zeros with correct castling notation.
        if san == "0-0":
            san = "O-O"
        elif san == "0-0-0":
            san = "O-O-O"

        return board.parse_san(san)
Exemple #29
0
 def test_board(self):
     self.my_board = Board()
     moves = [
         ['e4', 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1'],
         ['e5', 'rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq e6 0 2'],
         ['Nf3', 'rnbqkbnr/pppp1ppp/8/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 0 2'],
         ['d6', 'rnbqkbnr/ppp2ppp/3p4/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 0 3'],
         ['Bc4', 'rnbqkbnr/ppp2ppp/3p4/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R b KQkq - 0 3'],
         ['Nf6', 'rnbqkb1r/ppp2ppp/3p1n2/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 0 4'],
         ['O-O', 'rnbqkb1r/ppp2ppp/3p1n2/4p3/2B1P3/5N2/PPPP1PPP/RNBQ1RK1 b kq - 0 4']
     ]
     for move in moves:
         self.my_board.move_algebraic(move[0])
         fen = self.my_board.get_fen()
         self.assertEqual(fen, move[1],
             'erro no movimento %s \n esperado: %s \n recebido: %s' % (move[0], move[1], fen))
Exemple #30
0
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
        self.font = QtGui.QFont("times", 24)
        self.chess_piece_font = QtGui.QFont("console", 30)
        self.fm = QtGui.QFontMetrics(self.font)
        self.chess_piece_fm = QtGui.QFontMetrics(self.chess_piece_font)
        self.vertical_lines_x_corrds = []
        self.horizontal_lines_y_coords = []

        self.board = Board(knorre_vs_neumann())

        self.pieces_images = {}
        self.load_pieces(self.img_path)

        self.active_cell = None
        self.selected_piece = None
Exemple #31
0
def give_score(board: chess.Board):
    value = 0
    for piece in chess.PIECE_TYPES:
        value += len(board.pieces(piece, chess.WHITE)) * VALUE[piece]
        value -= len(board.pieces(piece, chess.BLACK)) * VALUE[piece]
    return 0 if value < 0 else 0.5 if value == 0 else 1
Exemple #32
0
 def minimax_nn(self, board: chess.Board, depth, maximimize_white,
                limit_time):
     """Minimax algorithm from Wikipedia with NN."""
     self.nodes += 1
     if depth == 0 or board.is_game_over():
         evaluation = self.evaluate(board)
         # evaluation = self.evaluate(board)
         """attackers = board.attackers(board.turn, board.peek().to_square)
         if len(attackers) > 0:
             # Quiescent
             if board.turn == chess.WHITE:
                 evaluation += PIECES_VALUES[board.piece_map()
                                             [board.peek().to_square].
                                             symbol().lower()]
             else:
                 evaluation -= PIECES_VALUES[board.piece_map()
                                             [board.peek().to_square].
                                             symbol().lower()]"""
         return evaluation, chess.Move.from_uci("0000")
     if maximimize_white:
         book_move = None
         if self.own_book and board.fullmove_number < 15 and (
                 book_move := self.get_book_move(board)):
             self.obhits += 1
             return 10000, book_move
         if self.syzygy_online and len(board.piece_map()) <= 7:
             formatted_fen = board.fen().replace(" ", "_")
             data = requests.get(
                 f"http://tablebase.lichess.ovh/standard?fen={formatted_fen}"
             ).json()
             good_move = chess.Move.from_uci(data["moves"][0]["uci"])
             if data["category"] in ("win", "maybe_win", "cursed-win"):
                 self.tbhits += 1
                 return 10000, good_move
             elif data["category"] in ("loss", "maybe-loss",
                                       "blessed-loss"):
                 self.tbhits += 1
                 return -10000, good_move
             elif data["category"] == "draw":
                 self.tbhits += 1
                 return 0, good_move
             else:
                 pass
         if self.syzygy_tb and len(board.piece_map()) <= 6:
             try:
                 return self.get_syzygy(board)
             except chess.syzygy.MissingTableError:
                 pass
         value = -float("inf")
         legal_moves = list(board.legal_moves)
         list_best_moves = [legal_moves[0]]
         for move in self.nn_select_best_moves(board):
             if time.time() > limit_time:
                 return float("inf"), chess.Move.from_uci("0000")
             test_board = chess.Board(fen=board.fen())
             test_board.push(move)
             hash = chess.polyglot.zobrist_hash(test_board)
             if hash in self.tb and self.tb[hash][0] >= depth:
                 evaluation: int = self.tb[hash][1]
             else:
                 evaluation = self.minimax_nn(test_board, depth - 1, False,
                                              limit_time)[0]
                 self.tb[hash] = (copy.copy(depth), copy.copy(evaluation))
                 if int(sys.getsizeof(self.tb) / 1024 /
                        1024) >= self.hashlimit / 2:
                     del self.tb[list(self.tb.keys())[0]]
                     self.hashfull += 1
             if value == evaluation:
                 list_best_moves.append(move)
             elif value < evaluation:
                 value = evaluation
                 list_best_moves = [move]
         return value, random.choice(list_best_moves)
 def __init__(self,
              fen: Optional[str] = STARTING_FEN,
              *,
              chess960: bool = False):
     Board.__init__(self)
Exemple #34
0
 def __init__(self, board_fen: str = None):
     if board_fen:
         self.b = Board(board_fen)
     else:
         # Not sure why this is needed.
         self.b = Board()
Exemple #35
0
 def from_board(cls, board: chess.Board):
     return cls(board.fen())
Exemple #36
0
def get_fen(board: chess.Board) -> str:
    return board.fen()  # type: ignore
Exemple #37
0
def chess_plugin(client, channel, nick, message, cmd, args):
    """

    Command for helga-chess.

    Usage:

    <bigjust> !chess board
    <helga> <url to dpaste.com>

    <bigjust> !chess newgame
    <helga> I chose black, white to move
    <helga> I chose white, e5

    Between each move, the game is saved and persisted on file.

    board and move commands always assume latest game in the
    gamefile. Multiple games will be stored per channel/user in
    history.
    """

    engine = uci.popen_engine(ENGINE)
    headers = OrderedDict()
    current_game = None

    game = load_game(channel)

    if not game:
        game = pgn.Game()

    board = game.end().board()

    if args[0] in ['newgame', 'move', 'board']:
        if args[0] == 'board':
            return 'http://localhost:8080/chess/{}/'.format(channel)

        if args[0] == 'move':
            if len(args) < 2:
                return 'usage: move e3e5'

            try:
                board.push(Move.from_uci(args[1]))
            except ValueError:
                return 'not a valid move. valid moves: {}'.format(', '.join(
                    [str(move) for move in board.legal_moves]))

            engine.position(board)
            move = engine.go(movetime=THINK_TIME).bestmove
            client.msg(channel, 'my move: {}'.format(str(move)))
            board.push(move)

        if args[0] == 'newgame':

            # setup a new game, choose a random side, persist after
            # setup(), and possibly first move
            engine.ucinewgame()
            board = Board()
            engine.position(board)

            next_round, stockfish_level = next_game_stats(channel)

            bot_turn = randrange(2)

            if not bot_turn:
                # we're white
                headers.update({
                    'White': NICK,
                    'Black': channel,
                })

                best_move = engine.go(movetime=THINK_TIME).bestmove
                board.push(best_move)
                next_turn = 'Black'

            else:
                headers.update({
                    'Black': NICK,
                    'White': channel,
                })
                next_turn = 'White'

            now = datetime.datetime.now()
            headers.update({
                'Date':
                '{}.{}.{}'.format(now.year, now.month, now.day),
                'Round':
                next_round,
                'Event':
                stockfish_level,
            })

            client.msg(channel, '{} to move'.format(next_turn))

        # persist the game
        game = pgn.Game.from_board(board)
        game.headers = headers
        save_game(channel, game)
Exemple #38
0
def board_to_planes(board: chess.Board,
                    board_occ,
                    normalize=True,
                    last_moves=None):
    """
    Gets the plane representation of a given board state.

    ## Chess:

    Feature | Planes

    --- | ---

    P1 piece | 6 (pieces are ordered: PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING)

    P2 piece | 6 (pieces are ordered: PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING)

    Repetitions | 2 (two planes (full zeros/ones) indicating how often the board positions has occurred)

    En-passant square | 1 (Binary map indicating the square where en-passant capture is possible)

    ---
    15 planes

    * * *

    P1 castling | 2 (One if castling is possible, else zero)

    P2 castling | 2 (One if castling is possible, else zero)

    No-progress count | 1 (Setting the no progress counter as integer values, (described by uci halfmoves format)

    ---
    5 planes

    * * *

    Last 8 moves | 16 (indicated by origin and destination square, the most recent move is described by first 2 planes)

    ---
    16 planes

    * * *

    is960 = | 1 (boolean, 1 when active)

    ---
    1 plane

    ---

    P1 pieces | 1 | A grouped mask of all WHITE pieces |
    P2 pieces | 1 | A grouped mask of all BLACK pieces |
    Checkerboard | 1 | A chess board pattern |
    P1 Material Diff | 5 | (pieces are ordered: PAWN, KNIGHT, BISHOP, ROOK, QUEEN), normalized with 8, + means positive, - means negative |
    Opposite Color Bishops | 1 | Indicates if they are only two bishops and the bishops are opposite color |
    Checkers | 1 | Indicates all pieces giving check |
    P1 Material Count | 5 | (pieces are ordered: PAWN, KNIGHT, BISHOP, ROOK, QUEEN), normalized with 8 |
    ---
    15 planes

    The total number of planes is calculated as follows:
    # --------------
    15 + 5 + 16 + 1 + 15
    Total: 52 planes

    :param board: Board handle (Python-chess object)
    :param board_occ: Number of board occurences
    :param normalize: True if the inputs shall be normalized to the range [0.-1.]
    :param last_moves: List of last last moves. The most recent move is the first entry.
    :return: planes - the plane representation of the current board state
    """

    # return the plane representation of the given board
    # return variants.board_to_planes(board, board_occ, normalize, mode=MODE_CHESS)
    planes = np.zeros((NB_CHANNELS_TOTAL, BOARD_HEIGHT, BOARD_WIDTH))

    # channel will be incremented by 1 at first plane
    channel = 0
    me = board.turn
    you = not board.turn
    colors = [me, you]

    # mirror all bitboard entries for the black player
    mirror = board.turn == chess.BLACK

    assert channel == CHANNEL_PIECES
    # Fill in the piece positions
    # Channel: 0 - 11
    # Iterate over both color starting with WHITE
    for color in colors:
        # the PIECE_TYPE is an integer list in python-chess
        for piece_type in chess.PIECE_TYPES:
            # iterate over the piece mask and receive every position square of it
            for pos in board.pieces(piece_type, color):
                row, col = get_row_col(pos, mirror=mirror)
                # set the bit at the right position
                planes[channel, row, col] = 1
            channel += 1

    assert channel == CHANNEL_REPETITION
    # Channel: 12 - 13
    # set how often the position has already occurred in the game (default 0 times)
    # this is used to check for claiming the 3 fold repetition rule
    if board_occ >= 1:
        planes[channel, :, :] = 1
        if board_occ >= 2:
            planes[channel + 1, :, :] = 1
    channel += 2

    # Channel: 14
    # En Passant Square
    assert channel == CHANNEL_EN_PASSANT
    if board.ep_square and board.has_legal_en_passant():  # is not None:
        row, col = get_row_col(board.ep_square, mirror=mirror)
        planes[channel, row, col] = 1
    channel += 1

    # Channel: 15 - 18
    assert channel == CHANNEL_CASTLING
    for color in colors:
        # check for King Side Castling
        if board.has_kingside_castling_rights(color):
            planes[channel, :, :] = 1
        channel += 1
        # check for Queen Side Castling
        if board.has_queenside_castling_rights(color):
            planes[channel, :, :] = 1
        channel += 1

    # Channel: 19
    # (IV.4) No Progress Count
    # define a no 'progress' counter
    # it gets incremented by 1 each move
    # however, whenever a piece gets dropped, a piece is captured or a pawn is moved, it is reset to 0
    # halfmove_clock is an official metric in fen notation
    #  -> see: https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
    # check how often the position has already occurred in the game
    assert channel == CHANNEL_NO_PROGRESS
    planes[
        channel, :, :] = board.halfmove_clock / NORMALIZE_50_MOVE_RULE if normalize else board.halfmove_clock
    channel += 1

    # Channel: 20 - 35
    assert channel == CHANNEL_LAST_MOVES
    # Last 8 moves
    if last_moves:
        assert (len(last_moves) == NB_LAST_MOVES)
        for move in last_moves:
            if move:
                from_row, from_col = get_row_col(move.from_square,
                                                 mirror=mirror)
                to_row, to_col = get_row_col(move.to_square, mirror=mirror)
                planes[channel, from_row, from_col] = 1
                channel += 1
                planes[channel, to_row, to_col] = 1
                channel += 1
            else:
                channel += 2
    else:
        channel += NB_LAST_MOVES * NB_CHANNELS_PER_HISTORY_ITEM

    # Channel: 36
    # Chess960
    assert channel == CHANNEL_IS_960
    if board.chess960:
        planes[channel + 1, :, :] = 1
    channel += 1

    # Channel: 37 - 38
    # All white pieces and black pieces in a single map
    assert channel == CHANNEL_PIECE_MASK
    for color in colors:
        # the PIECE_TYPE is an integer list in python-chess
        for piece_type in chess.PIECE_TYPES:
            # iterate over the piece mask and receive every position square of it
            for pos in board.pieces(piece_type, color):
                row, col = get_row_col(pos, mirror=mirror)
                # set the bit at the right position
                planes[channel, row, col] = 1
        channel += 1

    # Channel: 39
    # Checkerboard
    assert (channel == CHANNEL_CHECKERBOARD)
    planes[channel, :, :] = checkerboard()
    channel += 1

    # Channel: 40 - 44
    # Relative material difference (negative if less pieces than opponent and positive if more)
    # iterate over all pieces except the king
    assert channel == CHANNEL_MATERIAL_DIFF
    for piece_type in chess.PIECE_TYPES[:-1]:
        material_count = len(board.pieces(piece_type, me)) - len(
            board.pieces(piece_type, you))
        planes[
            channel, :, :] = material_count / NORMALIZE_PIECE_NUMBER if normalize else material_count
        channel += 1

    # Channel: 45
    # Opposite color bishops
    assert (channel == CHANNEL_OPP_BISHOPS)
    if opposite_colored_bishops(board):
        planes[channel, :, :] = 1
    channel += 1

    # Channel: 46
    # Checkers
    assert channel == CHANNEL_CHECKERS
    board_checkers = checkers(board)
    if board_checkers:
        # iterate over the piece mask and receive every position square of it
        for pos in chess.SquareSet(board_checkers):
            row, col = get_row_col(pos, mirror=mirror)
            # set the bit at the right position
            planes[channel, row, col] = 1
    channel += 1

    # Channel: 47 - 51
    # Material
    assert channel == CHANNEL_MATERIAL_COUNT
    for piece_type in chess.PIECE_TYPES[:-1]:
        material_count = len(board.pieces(piece_type, me))
        planes[
            channel, :, :] = material_count / NORMALIZE_PIECE_NUMBER if normalize else material_count
        channel += 1

    assert channel == NB_CHANNELS_TOTAL

    return planes
Exemple #39
0
    def make_gif( self, gif_file_path:str = 'chess.gif' ):
        '''
        Makes the gif of the loaded pgn at the specified destination file path.

        Parameters
        ----------
        gif_file_path : str
            Destination directory to store the gif file.

        '''
        
        pgn_file = open(self.pgn_file_path)

        chess_game = pgn_reader.read_game(pgn_file)

        # Stores the headers in the pgn
        self.header_info = chess_game.headers

        # self.white_player = self.header_info['White']
        # self.black_player = self.header_info['Black']
        # self.BlackElo = self.header_info['BlackElo']
        # self.WhiteElo = self.header_info['WhiteElo']

        # print('White Player:',self.white_player)
        # print('Black Player:',self.black_player,'\n')

        # print( 'WhiteElo:', self.WhiteElo )
        # print( 'BlackElo:', self.BlackElo )

        # get string notation of the game
        # print(str( chess_game.game()).replace('\n','') )

        #get the start position
        # print(chess_game.board() )

        self.white_timeline = []
        self.black_timeline = []
        self.board_states = [Board()]

        main_line_itr = chess_game.mainline()
        for node in main_line_itr:
            if node.parent is not None:
                current_move = node.san()
                time_left = node.clock()

                current_board = node.board()
                self.board_states.append(current_board)
                
                if current_board.turn:
                    self.white_timeline.append(time_left)
                else:
                    self.black_timeline.append(time_left)

                # White's perspective
                # print('\n',current_board)  

                # # Black's perspective
                # print( '\n',current_board.transform( flip_vertical ))
        
        obj = Chess_Image(
                        colors = self.kwargs['colors'],
                        side = self.kwargs['side'], 
                        piece_theme = self.kwargs['piece_theme'],
                        h_margin=self.kwargs['h_margin'],
                        v_margin=self.kwargs['v_margin']
            )
        

        frames =  list( map(lambda x:obj.create_position(x) , self.board_states ) )

        mimwrite( 
            gif_file_path,
            frames, 
            duration = self.kwargs['delay'],
            subrectangles = True ,
            palettesize = 256 # default = 256
        )
        
        optimize_gif(gif_file_path)
Exemple #40
0
import os
from time import clock
import random
import numpy as np

from chess import Board, Move
from stockfish import Stockfish


# Learning to beat stockfish
# Fra hver posisjon et steg fram spill sf vs sf til slutt og se resultatet. 

# Tren opp paa stockfish til stockfish er representert som policy
# Deretter tren med rf learning

board = Board()
stockfish = Stockfish(path='{}/stockfish-10-linux/stockfish_10_x64_modern'.format(os.getcwd()), depth=)
stockfish.set_fen_position(board.fen())
#print([str(p) for p in board.piece_map().values()])


def play_stockfish_move():
    stockfish.set_fen_position(board.fen())
    uci = stockfish.get_best_move()
    if uci:
        move = Move.from_uci(uci)
        board.push(move)

def play_random_move():
    uci = str(random.choice(list(board.legal_moves)))
    if uci:
Exemple #41
0
def game_over(fen: str) -> bool:
    """
    Determine if the game is over and why
    """
    return Board(fen=fen).is_game_over()
def norm_fen(fen):
    return Board(fen).fen(en_passant='fen')
Exemple #43
0
# -*- coding: utf-8 -*-

import os
import bottle
from chess import Board, Moves, Piece

gameboard = Board()
gameboard.start_game()

path = os.path.abspath("views")


@bottle.route('/static/<filepath:path>')
def server_static(filepath):
    return bottle.static_file(filepath, root=path)


@bottle.get('/')
def print_board():
    return bottle.template('test_web.tpl', playboard=gameboard)


@bottle.get('/move_end')
def print_board1():
    return bottle.template('test_web_end.tpl', playboard=gameboard)


@bottle.get('/promote')
def print_promotion():
    return bottle.template('test_web_promotion.tpl')
    def say_last_move(game: chess.Board):
        """Take a chess.BitBoard instance and speaks the last move from it."""
        move_parts = {
            'K': 'king.ogg',
            'B': 'bishop.ogg',
            'N': 'knight.ogg',
            'R': 'rook.ogg',
            'Q': 'queen.ogg',
            'P': 'pawn.ogg',
            '+': '',
            '#': '',
            'x': 'takes.ogg',
            '=': 'promote.ogg',
            'a': 'a.ogg',
            'b': 'b.ogg',
            'c': 'c.ogg',
            'd': 'd.ogg',
            'e': 'e.ogg',
            'f': 'f.ogg',
            'g': 'g.ogg',
            'h': 'h.ogg',
            '1': '1.ogg',
            '2': '2.ogg',
            '3': '3.ogg',
            '4': '4.ogg',
            '5': '5.ogg',
            '6': '6.ogg',
            '7': '7.ogg',
            '8': '8.ogg'
        }

        bit_board = game.copy()
        move = bit_board.pop()
        san_move = bit_board.san(move)
        voice_parts = []

        if san_move.startswith('O-O-O'):
            voice_parts += ['castlequeenside.ogg']
        elif san_move.startswith('O-O'):
            voice_parts += ['castlekingside.ogg']
        else:
            for part in san_move:
                try:
                    sound_file = move_parts[part]
                except KeyError:
                    logging.warning('unknown char found in san: [%s : %s]',
                                    san_move, part)
                    sound_file = ''
                if sound_file:
                    voice_parts += [sound_file]

        if game.is_game_over():
            if game.is_checkmate():
                wins = 'whitewins.ogg' if game.turn == chess.BLACK else 'blackwins.ogg'
                voice_parts += ['checkmate.ogg', wins]
            elif game.is_stalemate():
                voice_parts += ['stalemate.ogg']
            else:
                if game.is_seventyfive_moves():
                    voice_parts += ['75moves.ogg', 'draw.ogg']
                elif game.is_insufficient_material():
                    voice_parts += ['material.ogg', 'draw.ogg']
                elif game.is_fivefold_repetition():
                    voice_parts += ['repetition.ogg', 'draw.ogg']
                else:
                    voice_parts += ['draw.ogg']
        elif game.is_check():
            voice_parts += ['check.ogg']

        if bit_board.is_en_passant(move):
            voice_parts += ['enpassant.ogg']

        return voice_parts
Exemple #45
0
    def launchSf(
        self,
        pars,
        fen,
        tablebases,
    ):
        board = Board(fen, chess960=False)
        wdl = None
        drawPlyCnt, resignPlyCnt = 0, 0
        whiteIdx = 1
        turnIdx = whiteIdx ^ (board.turn == chess.BLACK)
        uciEngines = init_engines(pars)
        info_handler = uci.InfoHandler()
        for u in uciEngines:
            u.info_handlers.append(info_handler)
            u.ucinewgame()

        try:
            while (not board.is_game_over(claim_draw=True)):

                if board.castling_rights == 0:
                    if len(re.findall(r"[rnbqkpRNBQKP]",
                                      board.board_fen())) < 6:
                        wdl = tablebases.probe_wdl(board)
                        if wdl is not None:
                            break

                uciEngines[turnIdx].position(board)
                bestmove, score = uciEngines[turnIdx].go(depth=9)
                score = info_handler.info["score"][1].cp
                #        print(score)

                if score is not None:
                    # Resign adjudication
                    if abs(score) >= Resign['score']:
                        resignPlyCnt += 1
                        if resignPlyCnt >= 2 * Resign['movecount']:
                            break
                    else:
                        resignPlyCnt = 0

                    # Draw adjudication
                    if abs(score
                           ) <= Draw['score'] and board.halfmove_clock > 0:
                        drawPlyCnt += 1
                        if drawPlyCnt >= 2 * Draw['movecount'] \
                                and board.fullmove_number >= Draw['movenumber']:
                            break
                    else:
                        drawPlyCnt = 0
                else:
                    # Disable adjudication over mate scores
                    drawPlyCnt, resignPlyCnt = 0, 0

                board.push(bestmove)
                turnIdx ^= 1

            result = board.result(True)
            if result == '*':
                if resignPlyCnt >= 2 * Resign['movecount']:
                    if score > 0:
                        result = '1-0' if board.turn == chess.WHITE else '0-1'
                    else:
                        result = '0-1' if board.turn == chess.WHITE else '1-0'
                elif wdl is not None:
                    if wdl <= -1:
                        result = '1-0' if board.turn == chess.WHITE else '0-1'
                    elif wdl >= 1:
                        result = '0-1' if board.turn == chess.WHITE else '1-0'
                    else:
                        result = '1/2-1/2'
#            print('tb draw')
                else:
                    result = '1/2-1/2'
#          print('draw')

#    print(board.fen())
#    print(re.findall(r"[rnbqkpRNBQKP]", board.board_fen()))
            for u in uciEngines:
                u.quit(0)
        except (MemoryError, SystemError, KeyboardInterrupt, OverflowError,
                OSError, ResourceWarning):
            for u in uciEngines:
                u.quit(1)
        return result
        #    print(result)
        exit(0)
Exemple #46
0
 def set_position(self, fen):
     self.node = Board(fen)
Exemple #47
0
def evaluate_position(board: chess.Board):
    # collect material of players
    white_material = 0
    black_material = 0

    white_pawns = board.pieces(chess.PAWN, chess.WHITE)
    white_knights = board.pieces(chess.KNIGHT, chess.WHITE)
    white_bishops = board.pieces(chess.BISHOP, chess.WHITE)
    white_rooks = board.pieces(chess.ROOK, chess.WHITE)
    white_queen = board.pieces(chess.QUEEN, chess.WHITE)

    for square in white_pawns:
        square_value = get_positional_value_for_piece('pawn', square,
                                                      chess.WHITE)
        white_material += piece_values[chess.PAWN] + square_value
    for square in white_knights:
        square_value = get_positional_value_for_piece('knight', square,
                                                      chess.WHITE)
        white_material += piece_values[chess.KNIGHT] + square_value
    for square in white_bishops:
        square_value = get_positional_value_for_piece('bishop', square,
                                                      chess.WHITE)
        white_material += piece_values[chess.BISHOP] + square_value
    for square in white_rooks:
        square_value = get_positional_value_for_piece('rook', square,
                                                      chess.WHITE)
        white_material += piece_values[chess.ROOK] + square_value
    for square in white_queen:
        square_value = get_positional_value_for_piece('queen', square,
                                                      chess.WHITE)
        white_material += piece_values[chess.QUEEN] + square_value

    black_pawns = board.pieces(chess.PAWN, chess.BLACK)
    black_knights = board.pieces(chess.KNIGHT, chess.BLACK)
    black_bishops = board.pieces(chess.BISHOP, chess.BLACK)
    black_rooks = board.pieces(chess.ROOK, chess.BLACK)
    black_queen = board.pieces(chess.QUEEN, chess.BLACK)

    for square in black_pawns:
        square_value = get_positional_value_for_piece('pawn', square,
                                                      chess.BLACK)
        black_material += piece_values[chess.PAWN] + square_value
    for square in black_knights:
        square_value = get_positional_value_for_piece('knight', square,
                                                      chess.BLACK)
        black_material += piece_values[chess.KNIGHT] + square_value
    for square in black_bishops:
        square_value = get_positional_value_for_piece('bishop', square,
                                                      chess.BLACK)
        black_material += piece_values[chess.BISHOP] + square_value
    for square in black_rooks:
        square_value = get_positional_value_for_piece('rook', square,
                                                      chess.BLACK)
        black_material += piece_values[chess.ROOK] + square_value
    for square in black_queen:
        square_value = get_positional_value_for_piece('queen', square,
                                                      chess.BLACK)
        black_material += piece_values[chess.QUEEN] + square_value

    # add kings
    white_material += piece_values[
        chess.KING] + get_positional_value_for_piece(
            'king', board.king(chess.WHITE), chess.WHITE, board)
    black_material += piece_values[
        chess.KING] + get_positional_value_for_piece(
            'king', board.king(chess.BLACK), chess.BLACK, board)

    evaluation = white_material - black_material

    if board.turn == chess.BLACK:
        evaluation = evaluation * -1

    return evaluation
Exemple #48
0
from flask import Flask
from flask import render_template, redirect, request
from chess import WebInterface, Board, InputError, Move, MoveHistory

app = Flask(__name__)
ui = WebInterface()
game = Board()
movehis = MoveHistory()


@app.route('/')
def root():
    return render_template('index.html')


@app.route('/newgame')
def newgame():
    # Note that in Python, objects and variables
    # in the global space are available to
    # top-level functions
    game.start()
    ui.board = game.display()
    ui.inputlabel = f'{game.turn} player: '
    ui.errmsg = None
    ui.btnlabel = 'Move'
    return redirect('/play')


@app.route('/undo', methods=["POST", "GET"])
def undo():
    try:
Exemple #49
0
 def tt_store(self, board: Board, entry: TTEntry):
     key = board._transposition_key()    
     self.hashtable[key] = entry
Exemple #50
0
            'q': 'bQ',
            'n': 'bN',
            'k': 'bK',
            'p': 'bP',
            'b': 'bB',
            'R': 'wR',
            'Q': 'wQ',
            'N': 'wN',
            'K': 'wK',
            'P': 'wP',
            'B': 'wB'
        }

        # Reads the available piece theme's .svg images and save them as .png images of appropraite size
        for piece in self.pieces_map:
            piece_path = os.path.join(piece_dir,
                                      self.pieces_map[piece] + '.svg')
            image = VipsImage.thumbnail(piece_path, size, height=size)
            image.write_to_file(f"Images/{ self.pieces_map[piece]}.png")

        #: Dictionary where pieces are the keys and corresponding PIL Images are the values
        self.piece_imgs = dict()
        for piece in self.pieces_map:
            self.piece_imgs[piece] = Image.open(
                f"Images/{ self.pieces_map[piece]}.png")


if __name__ == "__main__":
    obj = Chess_Image(('#ffe0b3', '#802b00'), side='2', piece_theme='dog')
    obj.create_position(Board())
Exemple #51
0
 def tt_lookup(self, board: Board) -> "TTEntry":
     key = board._transposition_key()
     return self.hashtable.get(key, TTEntry.default())
Exemple #52
0
			if v[0] < cur_move_pair[0]:
				cur_move_pair = v

	return cur_move_pair

# c_depth is the current depth
# depth is the search tree depth
def max_f(board, c_depth, depth, top_level_move=None):
	if board.is_game_over() or c_depth == 0:
		return w.evaluation(board), top_level_move
	else:
		boards = [(create_new_board_with_move(board, move), move) for move in board.legal_moves]
		cur_move_pair = (-1001, None)
		for b, m in boards:
			if c_depth != depth:
				m = top_level_move

			v = min_f(b, c_depth-1, depth, m)

			if v[0] > cur_move_pair[0]:
				cur_move_pair = v

	return cur_move_pair


if __name__ == '__main__':
	board = Board('rnb1kbnr/ppp2ppp/8/3P4/4p3/5P2/PPPQ2PP/RNB1KB1R b KQkq - 0 6')
	print(max_f(board, 5, 5))
	print(min_f(board, 2, 2))

Exemple #53
0
class ChessGUI(App):
    def __init__(self, model_path, verbose=False, **kwargs):
        super().__init__(**kwargs)
        self.board_size = 8
        self.button_positions = {}
        self.board = Board()

        moves_folder = Path("moves/")
        if not moves_folder.exists():
            moves_folder.mkdir(exist_ok=False)
        svg2png(bytestring=chess.svg.board(self.board, size=350),
                write_to=f'moves/chess.png')
        self.move_str = ""

        self.engine = ChessModel(model_path, verbose=verbose)

    def build(self):
        self.layout = GridLayout(cols=self.board_size, padding="31px")

        with self.layout.canvas:
            self.rect = Rectangle(source='chess.png')

        Clock.schedule_interval(self.update, 1)
        self.add_board_buttons()
        return self.layout

    def update(self, *args):
        self.rect.size = self.root.size
        self.rect.pos = self.root.pos
        self.rect.size = (self.rect.size[0] + 0.1, self.rect.size[1])

    def reset_board(self):
        [
            Path(m).unlink(missing_ok=True)
            for m in list(Path("moves/").glob("chess*"))
        ]
        self.board = Board()
        self.move_str = ""
        save_name = 'chess.png'
        svg2png(bytestring=chess.svg.board(self.board, size=350),
                write_to=save_name)
        self.rect.source = save_name

    def check_pawn_promotion(self, move):
        move_str = str(move)
        move_from = move_str[:2]
        piece_to_move = str(self.board.piece_at(chess.parse_square(move_from)))
        if piece_to_move not in ["p", "P"]:
            return move
        move_to = move_str[2:]
        if move_from[1] in ["2", "7"] and move_to[1] in ["1", "8"]:
            move.promotion = chess.QUEEN
        return move

    def update_button(self, button):
        self.move_str += button.id
        # print(self.move_str)

        if len(self.move_str) == 4:
            Cache.remove('kv.image')
            Cache.remove('kv.texture')
            move = chess.Move(from_square=chess.parse_square(
                self.move_str[:2]),
                              to_square=chess.parse_square(self.move_str[2:4]))
            move = self.check_pawn_promotion(move)
            print(f"Your move: {move}")
            if move in self.board.legal_moves:
                self.board.push(move)
                [
                    Path(m).unlink(missing_ok=True)
                    for m in list(Path("moves/").glob("chess*"))
                ]
                save_name = f'moves/chess_{str(move)}_{self.board.turn}.png'
                svg2png(bytestring=chess.svg.board(self.board, size=350),
                        write_to=save_name)
                self.rect.source = save_name

                if self.board.is_game_over():
                    return self.declare_winner()

                # ai_move = np.random.choice(list(self.board.legal_moves))
                # ai_move = list(self.board.legal_moves)[0]
                # print(ai_move)
                ai_move = self.engine.make_move(self.board)
                print(f"AI move: {ai_move}")

                if isinstance(ai_move, chess.Move):
                    self.board.push(ai_move)
                else:
                    return self.declare_winner()

                if self.board.is_game_over():
                    return self.declare_winner()
                [
                    Path(m).unlink(missing_ok=True)
                    for m in list(Path("moves/").glob("chess*"))
                ]
                save_name = f'moves/chess_{str(move)}_{self.board.turn}.png'
                svg2png(bytestring=chess.svg.board(self.board, size=350),
                        write_to=save_name)
                self.rect.source = save_name
            self.move_str = ""

    def board_to_game(self):
        board = self.board
        game = chess.pgn.Game()

        # Undo all moves.
        switchyard = collections.deque()
        while board.move_stack:
            switchyard.append(board.pop())

        game.setup(board)
        node = game

        # Replay all moves.
        while switchyard:
            move = switchyard.pop()
            node = node.add_variation(move)
            board.push(move)

        game.headers["Result"] = board.result()
        Path("games").open("a").write(str(game))
        return game

    def declare_winner(self):
        popup = Popup(title='Test popup',
                      content=Label(text=f"{self.board.result()}"),
                      size_hint=(None, None),
                      size=(400, 400))
        popup.open()
        self.board_to_game()
        self.reset_board()

    def add_board_buttons(self):
        for i in reversed(range(8)):
            for j in range(8):
                k = i * 8 + j
                self.layout.add_widget(
                    ChessButton(id=str(target_to_move(k))[:2],
                                background_color=(0.1, 0.1, 0.1, 0.6),
                                on_press=self.update_button))
Exemple #54
0
class Viridithas():
    def __init__(
        self,
        human: bool = False,
        fen: str = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
        pgn: str = '',
        time_limit: float = 15,
        fun: bool = False,
        contempt: int = 3000,
        book: bool = True,
        advancedTC: list = [],
    ):
        if pgn == '':
            self.node = Board(fen)
        else:
            self.node = Board()
            for move in pgn.split():
                try:
                    self.node.push_san(move)
                except Exception:
                    continue
        self.time_limit = time_limit
        if advancedTC:
            self.endpoint = time.time()+advancedTC[0]*60
            self.increment = advancedTC[1]
        else:
            self.endpoint = 0
            self.increment = 0
        self.fun = fun
        self.contempt = contempt
        self.human = human
        self.nodes = 0
        self.advancedTC = advancedTC
        self.hashtable: dict[Hashable, TTEntry] = dict()
        self.inbook = book

    def set_position(self, fen):
        self.node = Board(fen)

    def __repr__(self) -> str:
        return str(self.node) + '\n' + self.__class__.__name__+"-engine at position " + str(self.node.fen())

    def __str__(self) -> str:
        return self.__class__.__name__

    def user_setup(self):
        if input("Do you want to configure the bot? (Y/N) ").upper() != 'Y':
            return

        myname = self.__class__.__name__.upper()

        print(f"BEGINNING USER CONFIGURATION OF {myname}-BOT")

        datadict = get_engine_parameters()

        self.__init__(
            human=datadict["human"],
            fen=datadict["fen"],
            pgn=datadict["pgn"],
            time_limit=datadict["time_limit"],
            fun=datadict["fun"],
            contempt=datadict["contempt"],
            book=datadict["book"],
            advancedTC=datadict["advancedTC"]
        )

    def gameover_check_info(self):
        checkmate = self.node.is_checkmate()
        draw = self.node.is_stalemate() or \
            self.node.is_insufficient_material( ) or \
            self.node.is_repetition(2) or self.node.is_seventyfive_moves() or not any(self.node.generate_legal_moves())
        return checkmate or draw, checkmate, draw

    # @profile
    def evaluate(self, depth: float, checkmate: bool, draw: bool) -> float:
        self.nodes += 1

        if checkmate:
            return MATE_VALUE * int(max(depth+1, 1)) * (1 if self.node.turn else -1)
        if draw:
            return -self.contempt * (1 if self.node.turn else -1)

        rating: float = 0

        rating += pst_eval(self.node)
        # rating += see_eval(self.node)

        # rating += mobility(self.node) * MOBILITY_FACTOR
        
        # rating += piece_attack_counts(self.node) * ATTACK_FACTOR

        # rating += king_safety(self.node) * KING_SAFETY_FACTOR

        # rating += space(self.node) * SPACE_FACTOR

        return rating

    def single_hash_iterator(self, best):
        yield best

    def captures_piece(self, p):  # concentrate on MVV, then LVA
        return itertools.chain(
            self.node.generate_pseudo_legal_moves(self.node.pawns, p),
            self.node.generate_pseudo_legal_moves(self.node.knights, p),
            self.node.generate_pseudo_legal_moves(self.node.bishops, p),
            self.node.generate_pseudo_legal_moves(self.node.rooks, p),
            self.node.generate_pseudo_legal_moves(self.node.queens, p),
            self.node.generate_pseudo_legal_moves(self.node.kings, p),
        )

    #@profile
    def captures(self):  # (MVV/LVA)
        return (m for m in itertools.chain(
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.queens),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.rooks),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.bishops),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.knights),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.pawns),
        ) if self.node.is_legal(m))

    def winning_captures(self):  # (MVV/LVA)
        target_all = self.node.occupied_co[not self.node.turn]
        target_3 = target_all & ~self.node.pawns
        target_5 = target_3 & (~self.node.bishops | ~self.node.knights)
        target_9 = target_5 & ~self.node.rooks
        return itertools.chain(
            self.node.generate_pseudo_legal_moves(self.node.pawns, target_all),
            self.node.generate_pseudo_legal_moves(self.node.knights, target_3),
            self.node.generate_pseudo_legal_moves(self.node.bishops, target_3),
            self.node.generate_pseudo_legal_moves(self.node.rooks, target_5),
            self.node.generate_pseudo_legal_moves(self.node.queens, target_9),
            self.node.generate_pseudo_legal_moves(self.node.kings, target_9),
        )

    def losing_captures(self):  # (MVV/LVA)
        target_pawns = self.node.pawns
        target_pnb = target_pawns | self.node.bishops | self.node.knights
        target_pnbr = target_pnb | self.node.rooks
        return itertools.chain(
            self.node.generate_pseudo_legal_moves(self.node.knights, target_pawns),
            self.node.generate_pseudo_legal_moves(self.node.bishops, target_pawns),
            self.node.generate_pseudo_legal_moves(self.node.rooks, target_pnb),
            self.node.generate_pseudo_legal_moves(self.node.queens, target_pnbr),
            self.node.generate_pseudo_legal_moves(self.node.kings, target_pnbr),
        )

    def ordered_moves(self):
        return (m for m in itertools.chain(
            # self.winning_captures(),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.queens),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.rooks),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.bishops),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.knights),
            self.captures_piece(
                self.node.occupied_co[not self.node.turn] & self.node.pawns),
            self.node.generate_pseudo_legal_moves(
                0xffff_ffff_ffff_ffff, ~self.node.occupied_co[not self.node.turn]),
            # self.losing_captures()
        ) if self.node.is_legal(m))

    def pass_turn(self) -> None:
        self.node.push(Move.from_uci("0000"))

    #@profile
    def qsearch(self, alpha: float, beta: float, depth: float, colour: int, gameover: bool, checkmate: bool, draw: bool) -> float:

        val = self.evaluate(1, checkmate, draw) * colour
        if gameover:
            return val
        if val >= beta:
            return beta
        if (val < alpha - QUEEN_VALUE):
            return alpha
        
        alpha = max(val, alpha)

        for capture in self.captures():
            self.node.push(capture)
            gameover, checkmate, draw = self.gameover_check_info()
            score = -self.qsearch(-beta, -alpha, depth - 1, -colour, gameover, checkmate, draw)
            self.node.pop()
            if score >= beta:
                return score
            alpha = max(score, alpha)

        return alpha

    def tt_lookup(self, board: Board) -> "TTEntry":
        key = board._transposition_key()
        return self.hashtable.get(key, TTEntry.default())

    def tt_store(self, board: Board, entry: TTEntry):
        key = board._transposition_key()    
        self.hashtable[key] = entry

    #@profile
    def negamax(self, depth: float, colour: int, alpha: float, beta: float) -> float:
        initial_alpha = alpha

        # (* Transposition Table Lookup; self.node is the lookup key for ttEntry *)
        tt_entry = self.tt_lookup(self.node)
        if not tt_entry.is_null() and tt_entry.depth >= depth:
            if tt_entry.type == EXACT:
                return tt_entry.value
            elif tt_entry.type == LOWERBOUND:
                alpha = max(alpha, tt_entry.value)
            elif tt_entry.type == UPPERBOUND:
                beta = min(beta, tt_entry.value)

            if alpha >= beta:
                return tt_entry.value
            
            if self.node.is_legal(tt_entry.best):
                moves = itertools.chain([tt_entry.best], filter(lambda x: x != tt_entry.best, self.ordered_moves()))
            else:
                moves = self.ordered_moves()
        else:
            moves = self.ordered_moves()

        gameover, checkmate, draw = self.gameover_check_info()

        if gameover:
            return colour * self.evaluate(depth, checkmate, draw)

        if depth < 1:
            return self.qsearch(alpha, beta, depth, colour, gameover, checkmate, draw)

        current_pos_is_check = self.node.is_check()
        if not current_pos_is_check and depth >= 3 and abs(alpha) < MATE_VALUE and abs(beta) < MATE_VALUE:
            # MAKE A NULL MOVE
            self.node.push(Move.null())  
            # PERFORM A LIMITED SEARCH
            value = - self.negamax(depth - 3, -colour, -beta, -beta + 1)
            # UNMAKE NULL MOVE
            self.node.pop()

            if value >= beta:
                return beta

        do_prune = self.pruning(depth, colour, alpha, beta, current_pos_is_check)

        best_move = Move.null()
        search_pv = True
        value = float("-inf")
        for move_idx, move in enumerate(moves):
            if move_idx == 0:
                best_move = move
            gives_check = self.node.gives_check(move)
            is_capture = self.node.is_capture(move)
            is_promo = bool(move.promotion)
            depth_reduction = search_reduction_factor(
                move_idx, current_pos_is_check, gives_check, is_capture, is_promo, depth)
                
            if do_prune:
                if not gives_check and not is_capture: 
                    continue

            self.node.push(move)
            
            if search_pv:
                r = -self.negamax(depth - depth_reduction, -colour, -beta, -alpha)
                value = max(value, r)
            else:
                r = -self.negamax(depth - depth_reduction, -colour, -alpha-1, -alpha)
                if (r > alpha): # // in fail-soft ... & & value < beta) is common
                    r = -self.negamax(depth - depth_reduction, -colour, -beta, -alpha) #// re-search
                value = max(value, r)

            self.node.pop()

            if value > alpha:
                alpha = value
                best_move = move
            alpha = max(alpha, value)
            if alpha >= beta:
                break
            search_pv = False

        # (* Transposition Table Store; self.node is the lookup key for ttEntry *)
        # ttEntry = TTEntry()
        tt_entry.value = value
        if value <= initial_alpha:
            tt_entry.type = UPPERBOUND
        elif value >= beta:
            tt_entry.type = LOWERBOUND
        else:
            tt_entry.type = EXACT
        tt_entry.depth = depth
        tt_entry.best = best_move
        tt_entry.null = False
        self.tt_store(self.node, tt_entry)

        return value

    def pruning(self, depth, colour, alpha, beta, current_pos_is_check):
        if not (not current_pos_is_check and abs(
                alpha) < MATE_VALUE / 2 and abs(beta) < MATE_VALUE / 2) or depth > 2:
            return False

        see = see_eval(self.node) * colour

        DO_D1_PRUNING = depth <= 1 and see + FUTILITY_MARGIN < alpha

        DO_D2_PRUNING = depth <= 2 and see + FUTILITY_MARGIN_2 < alpha

        return DO_D1_PRUNING or DO_D2_PRUNING

    def move_sort(self, moves: list, ratings: list):
        pairs = zip(*sorted(zip(moves, ratings), key=operator.itemgetter(1)))
        moves, ratings = [list(pair) for pair in pairs]
        return moves, ratings

    def pv_string(self):
        count = 0
        moves = []
        while True:
            e = self.tt_lookup(self.node)
            if e.is_null() or not self.node.is_legal(e.best):
                break

            # print(self.node.__str__())
            # print(self.node.__repr__())
            # print(e.best)
            # print(self.node.san(e.best))

            moves.append(self.node.san(e.best))
            self.node.push(e.best)
            count += 1
        
        for _ in moves:
            self.node.pop()

        if count == 0: return ""
        return " ".join(moves)

    def turnmod(self) -> int:
        return -1 if self.node.turn else 1

    def show_iteration_data(self, moves: list, values: list, depth: float, start: float) -> tuple:
        t = round(time.time()-start, 2)
        print(f"{self.node.san(moves[0])} | {-round((self.turnmod()*values[0])/1000, 3)} | {str(t)}s at depth {str(depth + 1)}, {str(self.nodes)} nodes processed, at {str(int(self.nodes / (t+0.00001)))}NPS.\n", f"PV: {self.pv_string()}\n", end="")
        return (self.node.san(moves[0]), self.turnmod()*values[0], self.nodes, depth+1, t)

    def search(self, ponder: bool = False, readout: bool = True):
        val = float("-inf")
        start_time = time.time()
        self.nodes = 0
        moves = [next(self.ordered_moves())]
        saved_position = deepcopy(self.node)

        alpha, beta = float("-inf"), float("inf")
        valWINDOW = PAWN_VALUE / 4

        WINDOW_FAILED = False

        try:
            depth = 1
            while depth < 40:
                best = self.tt_lookup(self.node).best
                time_elapsed = time.time() - start_time
                # check if we aren't going to finish the next search in time
                if time_elapsed > 0.5 * self.time_limit and not ponder and not WINDOW_FAILED:
                    return best, val

                val = self.negamax(
                    depth, self.turnmod(), alpha=alpha, beta=beta)
                # print(val)
                if ((val <= alpha) or (val >= beta)):
                    # We fell outside the window, so try again with a
                    # full-width window (and the same depth).
                    alpha = float("-inf")
                    beta = float("inf")
                    WINDOW_FAILED = True
                    continue
                WINDOW_FAILED = False

                best = self.tt_lookup(self.node).best
                # check if we've run out of time
                if time_elapsed > self.time_limit and not ponder:
                    return best, val

                moves = [self.tt_lookup(self.node).best]
                values = [self.tt_lookup(self.node).value]

                if readout:
                    self.show_iteration_data(moves, values, depth, start_time)

                alpha = val - valWINDOW # Set up the window for the next iteration.
                beta = val + valWINDOW
                depth += 1
        except KeyboardInterrupt:
            self.node = saved_position
            pass
        return moves[0], val

    def ponder(self) -> None:
        self.origin = self.node.copy()
        self.search(ponder=True)

    def get_book_move(self):
        # book = chess.polyglot.open_reader(
        #     r"ProDeo292/ProDeo292/books/elo2500.bin")
        book = chess.polyglot.open_reader(
            r"books/elo2500.bin")
        main_entry = book.find(self.node)
        choice = book.weighted_choice(self.node)
        book.close()
        return main_entry.move, choice.move

    def engine_move(self) -> Move:
        # add flag_func for egtb mode
        if self.advancedTC:
            self.time_limit = (self.endpoint-time.time())/20
        print("Time for move: " + str(round(self.time_limit, 2)) + "s")
        if self.inbook:
            try:
                best, choice = self.get_book_move()
                if self.fun:
                    self.node.push(choice)
                    return choice
                else:
                    self.node.push(best)
                print(chess.pgn.Game.from_board(self.node)[-1])
            except IndexError:
                self.time_limit = self.time_limit*2
                best, _ = self.search()
                self.node.push(best)
                print(chess.pgn.Game.from_board(self.node)[-1])
                self.inbook = False
                self.time_limit = self.time_limit/2
        else:
            best, _ = self.search()
            self.node.push(best)
            print(chess.pgn.Game.from_board(self.node)[-1])
        # self.record_stack()
        self.endpoint += self.increment
        return best

    def user_move(self) -> str:
        move = input("enter move: ")
        while True:
            try:
                self.node.push_san(move)
                break
            except Exception:
                move = input("enter move: ")
        return move

    def display_ending(self) -> None:
        if self.node.is_stalemate():
            print('END BY STALEMATE')
        elif self.node.is_insufficient_material():
            print('END BY INSUFFICIENT MATERIAL')
        elif self.node.is_fivefold_repetition():
            print('END BY FIVEFOLD REPETITION')
        elif self.node.is_checkmate:
            print("BLACK" if self.node.turn == BLACK else "WHITE", 'WINS ON TURN',
                  self.node.fullmove_number)
        else:
            print('END BY UNKNOWN REASON')

    def run_game(self, indefinite=True) -> str:
        while not self.node.is_game_over():
            print(self.__repr__())
            if self.human and self.node.turn:
                try:
                    self.ponder()
                except KeyboardInterrupt:
                    self.node = self.origin
                    self.user_move()

            else:  # SWAP THESE ASAP

                self.engine_move()
            if not indefinite:
                break
        self.display_ending()
        try:
            return str(chess.pgn.Game.from_board(self.node)[-1])
        except Exception:
            return "PGN ERROR"

    def play_viri(self, fen=None):
        player_colour = input(
            "Enter the human player's colour in the form b/w\n--> ")
        while player_colour not in ['b', 'w']:
            player_colour = input(
                "Enter the human player's colour in the form b/w\n--> ")
        player_colour = WHITE if player_colour == 'w' else BLACK
        timeControl = int(
            input("how many seconds should viri get per move?\n--> "))
        self.__init__(human=True, time_limit=timeControl, fen=fen, book=True, fun=False)
        self.fun = False
        while not self.node.is_game_over():
            print(self.__repr__())
            if player_colour == self.node.turn:
                # try:
                #     self.ponder()
                # except KeyboardInterrupt:
                #     self.node = self.origin
                #     self.user_move()
                self.user_move()
            else:
                self.engine_move()
        self.display_ending()

    def perftx(self, n):
        if n == 0:
            self.nodes += 1
        else:
            for move in self.ordered_moves():
                self.node.push(move)
                self.perftx(n - 1)
                self.node.pop()

    def perft(self, n):
        self.nodes = 0
        self.perftx(n)
        print(self.nodes)

    def uci(self):
        start = input()
        while start != "uci":
            start = input()
        print("id", end="")
        while True:
            command = input()
            if command == "ucinewgame":
                board = Board()
            elif command.split()[0] == "position":
                fen = command[command.index(
                    "fen") + 3: command.index("moves") - 1]
                moves = command[command.index("moves"):].split()
                if fen == "startpos":
                    fen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
                board = Board(fen)
                for move in moves:
                    board.push(Move.from_uci(move))
Exemple #55
0
def material_count(board: Board, side: Color) -> int:
    values = { chess.PAWN: 1, chess.KNIGHT: 3, chess.BISHOP: 3, chess.ROOK: 5, chess.QUEEN: 9 }
    return sum(len(board.pieces(piece_type, side)) * value for piece_type, value in values.items())
Exemple #56
0
The chess motor reads Polyglot (.bin) files,
and uses Stockfish to analyze legal moves' scores.
"""
from typing import List, Dict
import random
import chess
import chess.engine
import chess.polyglot
import chess.svg
from chess import Board

import backend.database as database

engine = chess.engine.SimpleEngine.popen_uci('/usr/bin/stockfish')

b: Board = Board()
cursor = database.find_cursor(b.fen())


def board_step(move_uci: str):
    """ Updates board and cursor to step by given UCI """
    global cursor
    print('Stepping from:')
    print(cursor)
    found = False
    for reply in cursor['theory'] + cursor['moves']:
        if reply['uci'] == move_uci:
            old_cursor = cursor.copy()
            cursor = database.find_cursor(reply['leads_to'])
            if cursor is None or \
               'score' not in cursor or \
Exemple #57
0
from chess import Board, King, Queen, Bishop, Knight, Rook, Pawn
from interface import ConsoleInterface, TextInterface

ui = TextInterface()
game = Board(debug=False,
             outputf=ui.set_msg,
             inputf=ui.get_player_input,
             setboardf=ui.set_board)
game.start()
while game.winner is None:
    game.display()
    start, end = game.prompt()
    game.update(start, end)
    game.next_turn()
print(f"Game over. {game.winner} player wins!")
Exemple #58
0
def minimax(
    depth: int,
    board: chess.Board,
    alpha: float,
    beta: float,
    is_maximising_player: bool,
) -> float:
    """
    Core minimax logic.
    https://en.wikipedia.org/wiki/Minimax
    """
    debug_info["nodes"] += 1

    if board.is_checkmate():
        # The previous move resulted in checkmate
        return -MATE_SCORE if is_maximising_player else MATE_SCORE
    # When the game is over and it's not a checkmate it's a draw
    # In this case, don't evaluate. Just return a neutral result: zero
    elif board.is_game_over():
        return 0

    if depth == 0:
        return evaluate_board(board)

    if is_maximising_player:
        best_move = -float("inf")
        moves = get_ordered_moves(board)
        for move in moves:
            board.push(move)
            curr_move = minimax(depth - 1, board, alpha, beta,
                                not is_maximising_player)
            # Each ply after a checkmate is slower, so they get ranked slightly less
            # We want the fastest mate!
            if curr_move > MATE_THRESHOLD:
                curr_move -= 1
            elif curr_move < -MATE_THRESHOLD:
                curr_move += 1
            best_move = max(
                best_move,
                curr_move,
            )
            board.pop()
            alpha = max(alpha, best_move)
            if beta <= alpha:
                return best_move
        return best_move
    else:
        best_move = float("inf")
        moves = get_ordered_moves(board)
        for move in moves:
            board.push(move)
            curr_move = minimax(depth - 1, board, alpha, beta,
                                not is_maximising_player)
            if curr_move > MATE_THRESHOLD:
                curr_move -= 1
            elif curr_move < -MATE_THRESHOLD:
                curr_move += 1
            best_move = min(
                best_move,
                curr_move,
            )
            board.pop()
            beta = min(beta, best_move)
            if beta <= alpha:
                return best_move
        return best_move
Exemple #59
0
    def write_json(self, board: chess.Board):
        """
        Writes all of the board info in json
        """

        best_move = self.get_best_move(board)

        output = OrderedDict([
            ('fen', board.fen()),
            ('fullmoveNumber', board.fullmove_number),
            ('result', board.result()),
            ('isGameOver', board.is_game_over()),
            ('isCheckmate', board.is_checkmate()),
            ('isStalemate', board.is_stalemate()),
            ('isInsufficientMaterial', board.is_insufficient_material()),
            ('isSeventyfiveMoves', board.is_seventyfive_moves()),
            ('isFivefoldRepetition', board.is_fivefold_repetition()),
            ('white',
             OrderedDict([
                 ('hasKingsideCastlingRights',
                  board.has_kingside_castling_rights(chess.WHITE)),
                 ('hasQueensideCastlingRights',
                  board.has_queenside_castling_rights(chess.WHITE)),
             ])),
            ('black',
             OrderedDict([
                 ('hasKingsideCastlingRights',
                  board.has_kingside_castling_rights(chess.BLACK)),
                 ('hasQueensideCastlingRights',
                  board.has_queenside_castling_rights(chess.BLACK)),
             ])),
            ('turn',
             OrderedDict([
                 ('color', 'white' if board.turn is chess.WHITE else 'black'),
                 ('isInCheck', board.is_check()),
                 ('bestMove', best_move),
                 ('legalMoves', [move.uci() for move in board.legal_moves]),
                 ('canClaimDraw', board.can_claim_draw()),
                 ('canClaimFiftyMoves', board.can_claim_fifty_moves()),
                 ('canClaimThreefoldRepetition',
                  board.can_claim_threefold_repetition()),
             ])),
        ])

        self.finish(output)
Exemple #60
0
    configure_logging(level=logging.INFO)
else:
    configure_logging(level=logging.DEBUG)


def print_puzzle_pgn(puzzle, pgn_headers=None):
    puzzle_pgn = puzzle.to_pgn(pgn_headers=pgn_headers)
    log(Color.MAGENTA, "NEW PUZZLE GENERATED\n")
    print(Color.CYAN + puzzle_pgn + "\n\n" + Color.ENDC)


# load a FEN and try to create a puzzle from it

if settings.fen:
    log(Color.DIM, AnalysisEngine.name())
    puzzle = Puzzle(Board(settings.fen))
    puzzle.generate(depth=settings.search_depth)
    if puzzle.is_complete():
        print_puzzle_pgn(puzzle)
    engine.quit()
    exit(0)

# load games from a PGN and scan them for puzzles

n_positions = 0  # number of positions considered
n_puzzles = 0  # number of puzzles generated
game_id = 0
pgn = open(settings.pgn, "r")

while game_id < settings.start_index:
    game = chess.pgn.read_game(pgn)