示例#1
0
    def test_gating_castle_at_rook_wOO(self):
        FEN = "r2qk2r/pppbbppp/4pn2/1N1p4/1n1P4/4PN2/PPPBBPPP/R2QK2R[heHE] w KQkq - 10 8"
        board = LBoard(SCHESS)
        board.applyFen(FEN)

        moves = set()
        for move in genAllMoves(board):
            moves.add(toAN(board, move))
        print("--------")
        print(board)

        self.assertIn("h1e1h", moves)
        self.assertIn("h1e1e", moves)

        self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O/Hh1'))), 'h1e1h')
        self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O/Eh1'))), 'h1e1e')

        self.assertEqual(toSAN(board, newMove(H1, E1, HAWK_GATE_AT_ROOK)), "O-O/Hh1")
        self.assertEqual(toSAN(board, newMove(H1, E1, ELEPHANT_GATE_AT_ROOK)), "O-O/Eh1")

        fen = board.asFen()
        move = parseAN(board, "h1e1e")
        board.applyMove(move)
        print("h1e1e")
        print(board)

        self.assertEqual(placement(board.asFen()), "r2qk2r/pppbbppp/4pn2/1N1p4/1n1P4/4PN2/PPPBBPPP/R2Q1RKE[heH]")

        board.popMove()
        self.assertEqual(placement(board.asFen()), placement(fen))
示例#2
0
    def test_toSAN(self):
        """ Testing toSAN() with giveaway king move """

        board = LBoard(GIVEAWAYCHESS)
        board.applyFen("4R3/8/7B/2P5/8/8/PP5k/6k1 b - - 0 28")

        self.assertEqual(toSAN(board, newMove(G1, G2)), "Kgg2")
        self.assertEqual(toSAN(board, newMove(H2, G2)), "Khg2")
示例#3
0
            def on_players_changed(game):
                # fill fools mate moves to players move queue
                p0 = game.players[0]
                p0.move_queue.put_nowait(Move(newMove(F2, F3)))
                p0.move_queue.put_nowait(Move(newMove(G2, G4)))

                p1 = gamemodel.players[1]
                p1.move_queue.put_nowait(Move(newMove(E7, E5)))
                p1.move_queue.put_nowait(Move(newMove(D8, H4)))
示例#4
0
            def on_players_changed(game):
                # fill fools mate moves to players move queue
                p0 = game.players[0]
                p0.move_queue.put_nowait(Move(newMove(F2, F3)))
                p0.move_queue.put_nowait(Move(newMove(G2, G4)))

                p1 = gamemodel.players[1]
                p1.move_queue.put_nowait(Move(newMove(E7, E5)))
                p1.move_queue.put_nowait(Move(newMove(D8, H4)))
示例#5
0
    def test_gating_san_move(self):
        board = LBoard(SCHESS)
        board.applyFen(SCHESSSTART)

        self.assertEqual(repr(Move.Move(parseSAN(board, 'Nf3/H'))), 'g1f3h')
        self.assertEqual(repr(Move.Move(parseSAN(board, 'Nf3/E'))), 'g1f3e')

        self.assertEqual(toSAN(board, newMove(G1, F3, HAWK_GATE)), "Nf3/H")
        self.assertEqual(toSAN(board, newMove(G1, F3, ELEPHANT_GATE)), "Nf3/E")
示例#6
0
    def test_gating_castle_at_rook_wOOO_SAN(self):
        FEN = "r2ek2r/5pp1/1pp1pnp1/2pp1h2/3P4/2P1PP2/PP1N2PP/R3K1HR/E w KQHEAkq - 2 16"
        board = LBoard(SCHESS)
        board.applyFen(FEN)

        self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O-O'))), 'e1c1')
        self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O-O/Ea1'))), 'a1e1e')
        self.assertEqual(repr(Move.Move(parseSAN(board, 'O-O-O/Ee1'))), 'e1c1e')

        self.assertEqual(toSAN(board, newMove(E1, C1, QUEEN_CASTLE)), "O-O-O")
        self.assertEqual(toSAN(board, newMove(A1, E1, ELEPHANT_GATE_AT_ROOK)), "O-O-O/Ea1")
        self.assertEqual(toSAN(board, newMove(E1, C1, ELEPHANT_GATE)), "O-O-O/Ee1")
示例#7
0
    def validate(self, cord0, cord1):
        if cord0 is None or cord1 is None:
            return False
        # prevent accidental NULL_MOVE creation
        if cord0 == cord1 and self.parent.variant.variant != SITTUYINCHESS:
            return False
        if self.getBoard()[cord0] is None:
            return False

        if self.parent.setup_position:
            # prevent moving pieces inside holding
            if (cord0.x < 0 or cord0.x > self.FILES - 1) and \
                    (cord1.x < 0 or cord1.x > self.FILES - 1):
                return False
            else:
                return True

        if cord1.x < 0 or cord1.x > self.FILES - 1:
            return False
        if cord0.x < 0 or cord0.x > self.FILES - 1:
            # drop
            return validate(
                self.getBoard(),
                Move(
                    lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord,
                                     DROP)))
        else:
            return validate(self.getBoard(), Move(cord0, cord1,
                                                  self.getBoard()))
示例#8
0
 def emit_move_signal (self, cord0, cord1, promotion=None):
     # Game end can change cord0 to None while dragging a piece
     if cord0 is None:
         return
         
     color = self.view.model.boards[-1].color
     board = self.view.model.getBoardAtPly(self.view.shown, self.view.shownVariationIdx)
     # Ask player for which piece to promote into. If this move does not
     # include a promotion, QUEEN will be sent as a dummy value, but not used
     
     if promotion is None and board[cord0].sign == PAWN and cord1.y in (0, self.RANKS-1):
         promotion = self.getPromotion()
         if promotion is None:
             # Put back pawn moved be d'n'd
             self.view.runAnimation(redrawMisc = False)
             return
     
     if cord0.x < 0 or cord0.x > self.FILES-1:
         move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
     else:
         move = Move(cord0, cord1, board, promotion)
     
     if self.view.model.curplayer.__type__ == LOCAL and self.view.shownIsMainLine() and \
        self.view.model.boards[-1] == board and self.view.model.status == RUNNING:
         self.emit("piece_moved", move, color)
     else:
         if board.board.next is None and not self.view.shownIsMainLine():
             self.view.model.add_move2variation(board, move, self.view.shownVariationIdx)
             self.view.shown += 1
         else:
             new_vari = self.view.model.add_variation(board, (move,))
             self.view.setShownBoard(new_vari[-1])
示例#9
0
def parsePolyglot(board, pg):
    """ Parse a 16-bit Polyglot-format move """

    tcord = TCORD(pg)
    fcord = FCORD(pg)
    flag = NORMAL_MOVE
    if pg >> 12:
        flag = FLAG_PIECE((pg >> 12) + 1)
    elif board.arBoard[fcord] == KING:
        if board.arBoard[tcord] == ROOK:
            color = board.color
            friends = board.friends[color]
            if bitPosArray[tcord] & friends:
                if board.ini_rooks[color][0] == tcord:
                    flag = QUEEN_CASTLE
                    if board.variant == NORMALCHESS:  # Want e1c1/e8c8
                        tcord += 2
                else:
                    flag = KING_CASTLE
                    if board.variant == NORMALCHESS:  # Want e1g1/e8g8
                        tcord -= 1
    elif board.arBoard[fcord] == PAWN and board.arBoard[tcord] == EMPTY and \
            FILE(fcord) != FILE(tcord) and RANK(fcord) != RANK(tcord):
        flag = ENPASSANT

    return newMove(fcord, tcord, flag)
示例#10
0
    def row_activated(self, iter, model):
        if self.mode == HINT and self.store.get_path(iter) != Gtk.TreePath(
                self.path):
            moves = self.store[iter][0][2]
            if moves is not None:
                score = self.store[iter][1][0]
                model.add_variation(self.engine.board,
                                    moves,
                                    comment="",
                                    score=score)

        if self.mode == SPY and self.store.get_path(iter) != Gtk.TreePath(
                self.path):
            moves = self.store[iter][0][2]
            if moves is not None:
                score = self.store[iter][1][0]
                board = self.engine.board.board
                # SPY analyzer has inverted color boards
                # we need to chage it to get the board in gamemodel variations board list later
                board.setColor(1 - board.color)
                king = board.kings[board.color]
                null_move = Move(newMove(king, king, NULL_MOVE))
                model.add_variation(self.engine.board, [null_move] + moves,
                                    comment="",
                                    score=score)
示例#11
0
def sittuyin_promotion_fcord(board, tcord):
    valid_promotions = list(gen_sittuyin_promotions(board))
    queenMoves = moveArray[ASEAN_QUEEN]
    for fcord in iterBits(queenMoves[tcord]):
        if board.arBoard[fcord] and board.arBoard[fcord] == PAWN:
            if newMove(fcord, tcord, QUEEN_PROMOTION) in valid_promotions:
                return fcord
示例#12
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return

        color = self.view.model.boards[-1].color
        board = self.view.model.getBoardAtPly(self.view.shown,
                                              self.view.shownVariationIdx)
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used

        if promotion is None and board[cord0].sign == PAWN and cord1.y in (
                0, self.RANKS - 1):
            promotion = self.getPromotion()
            if promotion is None:
                # Put back pawn moved be d'n'd
                self.view.runAnimation(redrawMisc=False)
                return

        if cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if self.view.model.curplayer.__type__ == LOCAL and self.view.shownIsMainLine() and \
           self.view.model.boards[-1] == board and self.view.model.status == RUNNING:
            self.emit("piece_moved", move, color)
        else:
            if board.board.next is None and not self.view.shownIsMainLine():
                self.view.model.add_move2variation(board, move,
                                                   self.view.shownVariationIdx)
                self.view.shown += 1
            else:
                new_vari = self.view.model.add_variation(board, (move, ))
                self.view.setShownBoard(new_vari[-1])
示例#13
0
    def validate(self, cord0, cord1):
        if cord0 is None or cord1 is None:
            return False
        # prevent accidental NULL_MOVE creation
        if cord0 == cord1:
            return False
        if self.getBoard()[cord0] is None:
            return False

        if self.parent.setup_position:
            # prevent moving pieces inside holding
            if (cord0.x < 0 or cord0.x > self.FILES - 1) and \
                    (cord1.x < 0 or cord1.x > self.FILES - 1):
                return False
            else:
                return True

        if cord1.x < 0 or cord1.x > self.FILES - 1:
            return False
        if cord0.x < 0 or cord0.x > self.FILES - 1:
            # drop
            return validate(self.getBoard(), Move(lmovegen.newMove(
                self.getBoard()[cord0].piece, cord1.cord, DROP)))
        else:
            return validate(self.getBoard(), Move(cord0, cord1,
                                                  self.getBoard()))
示例#14
0
文件: lmove.py 项目: btrent/knave
def parsePolyglot (board, pg):
    """ Parse a 16-bit Polyglot-format move """
    
    tcord = TCORD(pg)
    fcord = FCORD(pg)
    flag = NORMAL_MOVE
    if pg >> 12:
        flag = FLAG_PIECE( (pg >> 12) + 1 )
    elif board.arBoard[fcord] == KING:
        if board.arBoard[tcord] == ROOK:
            color = board.color
            friends = board.friends[color]
            if bitPosArray[tcord] & friends:
                if board.ini_rooks[color][0] == tcord:
                    flag = QUEEN_CASTLE
                    if board.variant == NORMALCHESS: # Want e1c1/e8c8
                        tcord += 2
                else:
                    flag = KING_CASTLE
                    if board.variant == NORMALCHESS: # Want e1g1/e8g8
                        tcord -= 1
    elif board.arBoard[fcord] == PAWN and board.arBoard[tcord] == EMPTY and \
            FILE(fcord) != FILE(tcord) and RANK(fcord) != RANK(tcord):
        flag = ENPASSANT

    return newMove (fcord, tcord, flag)
示例#15
0
    def validate (self, cord0, cord1):
        if cord0 is None or cord1 is None:
            return False
        # prevent accidental NULL_MOVE creation
        if cord0 == cord1:
            return False
        if self.getBoard()[cord0] == None:
            return False

        if self.parent.setup_position:
            to_piece = self.getBoard()[cord1]
            # prevent moving pieces inside holding
            if (cord0.x < 0 or cord0.x > self.FILES-1) and \
                (cord1.x < 0 or cord1.x > self.FILES-1):
                return False
            # prevent moving kings off board
            elif self.getBoard()[cord0].piece == KING and \
                (cord1.x < 0 or cord1.x > self.FILES-1):
                return False
            # prevent taking enemy king
            elif to_piece is not None and to_piece.piece == KING:
                return False
            else:
                return True
        
        if cord1.x < 0 or cord1.x > self.FILES-1:
            return False
        if cord0.x < 0 or cord0.x > self.FILES-1:
            # drop
            return validate(self.getBoard(), Move(lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord, DROP)))
        else:
            return validate(self.getBoard(), Move(cord0, cord1, self.getBoard()))
示例#16
0
    def row_activated(self, iter, model):
        if self.mode == HINT and self.store.get_path(iter) != Gtk.TreePath(
                self.path):
            moves = self.store[iter][0][2]
            if moves is not None:
                score = self.store[iter][1][0]
                model.add_variation(self.engine.board,
                                    moves,
                                    comment="",
                                    score=score)

        if self.mode == SPY and self.store.get_path(iter) != Gtk.TreePath(
                self.path):
            moves = self.store[iter][0][2]
            if moves is not None:
                score = self.store[iter][1][0]
                board = self.engine.board.board
                # SPY analyzer has inverted color boards
                # we need to chage it to get the board in gamemodel variations board list later
                board.setColor(1 - board.color)
                king = board.kings[board.color]
                null_move = Move(newMove(king, king, NULL_MOVE))
                model.add_variation(self.engine.board,
                                    [null_move] + moves,
                                    comment="",
                                    score=score)
示例#17
0
 def __init__ (self, cord0, cord1=None, board=None, promotion=None):
     """ Inits a new highlevel Move object.
         The object can be initialized in the follow ways:
             Move(cord0, cord1, board, [promotionPiece])
             Move(lovLevelMoveInt) """
     
     if not cord1:
         self.move = cord0
         self.flag = self.move >> 12
         self.cord0 = None if self.flag == DROP else Cord(lmove.FCORD(self.move))
         self.cord1 = Cord(lmove.TCORD(self.move))
         
     else:
         assert cord0 != None and cord1 != None, "cord0=%s, cord1=%s, board=%s" % (cord0, cord1, board)
         assert board[cord0] != None, "cord0=%s, cord1=%s, board=%s" % (cord0, cord1, board)
         self.cord0 = cord0
         self.cord1 = cord1
         if not board:
             raise ValueError("Move needs a Board object in order to investigate flags")
         
         self.flag = NORMAL_MOVE
         if board[self.cord0].piece == PAWN and  self.cord1.cord in board.PROMOTION_ZONE[board.board.color]:
             if promotion == None:
                 if board.variant == SITTUYINCHESS:
                     if cord0 == cord1:
                         self.flag = lmove.FLAG_PIECE(QUEEN)
                 else:
                     self.flag = lmove.FLAG_PIECE(QUEEN)
             else:
                 self.flag = lmove.FLAG_PIECE(promotion)
         
         elif board[self.cord0].piece == KING:
             if self.cord0 == self.cord1:
                 self.flag = NULL_MOVE
             elif board.variant == FISCHERRANDOMCHESS:
                 if (abs(self.cord0.x - self.cord1.x) > 1 and self.cord1.x==C1) or \
                     \
                     (board.board.ini_rooks[board.color][0] == self.cord1.cord and \
                     ((board.board.color == WHITE and board.board.castling & W_OOO) or \
                     (board.board.color == BLACK and board.board.castling & B_OOO))):
                     self.flag = QUEEN_CASTLE
                 elif (abs(self.cord0.x - self.cord1.x) > 1 and self.cord1.x==G1) or \
                     \
                     (board.board.ini_rooks[board.color][1] == self.cord1.cord and \
                     ((board.board.color == WHITE and board.board.castling & W_OO) or \
                     (board.board.color == BLACK and board.board.castling & B_OO))):
                     self.flag = KING_CASTLE
             elif board.variant != CAMBODIANCHESS:
                 if self.cord0.x - self.cord1.x == 2:
                     self.flag = QUEEN_CASTLE if self.cord0.x == 4 else KING_CASTLE
                 elif self.cord0.x - self.cord1.x == -2:
                     self.flag = KING_CASTLE if self.cord0.x == 4 else QUEEN_CASTLE
         
         elif board[self.cord0].piece == PAWN and \
                 board[self.cord1] == None and \
                 self.cord0.x != self.cord1.x and \
                 self.cord0.y != self.cord1.y:
             self.flag = ENPASSANT
         
         self.move = newMove(self.cord0.cord, self.cord1.cord, self.flag)
示例#18
0
    def __init__(self, cord0, cord1=None, board=None, promotion=None):
        """ Inits a new highlevel Move object.
            The object can be initialized in the follow ways:
                Move(cord0, cord1, board, [promotionPiece])
                Move(lovLevelMoveInt) """

        if not cord1:
            self.move = cord0
            self.flag = self.move >> 12
            self.cord0 = None if self.flag == DROP else Cord(
                lmove.FCORD(self.move))
            self.cord1 = Cord(lmove.TCORD(self.move))

        else:
            assert cord0 != None and cord1 != None, "cord0=%s, cord1=%s, board=%s" % (
                cord0, cord1, board)
            assert board[cord0] != None, "cord0=%s, cord1=%s, board=%s" % (
                cord0, cord1, board)
            self.cord0 = cord0
            self.cord1 = cord1
            if not board:
                raise ValueError(
                    "Move needs a Board object in order to investigate flags")

            self.flag = NORMAL_MOVE

            if board[self.cord0].piece == PAWN and self.cord1.y in (0, 7):
                if promotion == None: promotion = QUEEN
                self.flag = lmove.FLAG_PIECE(promotion)

            elif board[self.cord0].piece == KING:
                if self.cord0 == self.cord1:
                    self.flag = NULL_MOVE
                elif board.variant == FISCHERRANDOMCHESS:
                    if (abs(self.cord0.x - self.cord1.x) > 1 and self.cord1.x==C1) or \
                        \
                        (board.board.ini_rooks[board.color][0] == self.cord1.cord and \
                        ((board.board.color == WHITE and board.board.castling & W_OOO) or \
                        (board.board.color == BLACK and board.board.castling & B_OOO))):
                        self.flag = QUEEN_CASTLE
                    elif (abs(self.cord0.x - self.cord1.x) > 1 and self.cord1.x==G1) or \
                        \
                        (board.board.ini_rooks[board.color][1] == self.cord1.cord and \
                        ((board.board.color == WHITE and board.board.castling & W_OO) or \
                        (board.board.color == BLACK and board.board.castling & B_OO))):
                        self.flag = KING_CASTLE
                else:
                    if self.cord0.x - self.cord1.x == 2:
                        self.flag = QUEEN_CASTLE if self.cord0.x == 4 else KING_CASTLE
                    elif self.cord0.x - self.cord1.x == -2:
                        self.flag = KING_CASTLE if self.cord0.x == 4 else QUEEN_CASTLE

            elif board[self.cord0].piece == PAWN and \
                    board[self.cord1] == None and \
                    self.cord0.x != self.cord1.x and \
                    self.cord0.y != self.cord1.y:
                self.flag = ENPASSANT

            self.move = newMove(self.cord0.cord, self.cord1.cord, self.flag)
示例#19
0
文件: lmove.py 项目: stevexyz/pychess
def parseAN(board, an):
    """ Parse an Algebraic Notation string """

    if not 4 <= len(an) <= 6:
        raise ParsingError(an, "the move must be 4 or 6 chars long",
                           board.asFen())

    try:
        fcord = cordDic[an[:2]]
        tcord = cordDic[an[2:4]]
    except KeyError as e:
        raise ParsingError(an, "the cord (%s) is incorrect" % e.args[0],
                           board.asFen())

    flag = NORMAL_MOVE

    if len(an) > 4 and not an[-1] in "QRBNMSFqrbnmsf":
        if (board.variant != SUICIDECHESS and board.variant != GIVEAWAYCHESS) or \
            (board.variant == SUICIDECHESS or board.variant == GIVEAWAYCHESS) and not an[
                -1] in "Kk":
            raise ParsingError(an, "invalid promoted piece", board.asFen())

    if len(an) == 5:
        # The a7a8q variant
        flag = chr2Sign[an[4].lower()] + 2
    elif len(an) == 6:
        # The a7a8=q variant
        flag = chr2Sign[an[5].lower()] + 2
    elif board.arBoard[fcord] == KING:
        if fcord - tcord == 2:
            flag = QUEEN_CASTLE
            if board.variant == FISCHERRANDOMCHESS:
                tcord = board.ini_rooks[board.color][0]
        elif fcord - tcord == -2:
            flag = KING_CASTLE
            if board.variant == FISCHERRANDOMCHESS:
                tcord = board.ini_rooks[board.color][1]
        elif board.arBoard[
                tcord] == ROOK:
            color = board.color
            friends = board.friends[color]
            if bitPosArray[tcord] & friends:
                if board.ini_rooks[color][0] == tcord:
                    flag = QUEEN_CASTLE
                else:
                    flag = KING_CASTLE
        else:
            flag = NORMAL_MOVE
    elif board.arBoard[fcord] == PAWN and board.arBoard[tcord] == EMPTY and \
            FILE(fcord) != FILE(tcord) and RANK(fcord) != RANK(tcord):
        flag = ENPASSANT
    elif board.arBoard[fcord] == PAWN:
        if an[3] in "18" and board.variant != SITTUYINCHESS:
            raise ParsingError(
                an, _("promotion move without promoted piece is incorrect"),
                board.asFen())

    return newMove(fcord, tcord, flag)
示例#20
0
            def on_book_created(persp, event):
                self.assertTrue(os.path.isfile(BIN))

                testcase = testcases[0]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(
                    sorted(openings),
                    sorted([(newMove(E2, E4), 2, 0), (newMove(A2, A4), 0, 0)]))

                testcase = testcases[-1]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(openings, [])

                event.set()
示例#21
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        color = self.view.model.boards[-1].color
        board = self.view.model.getBoardAtPly(self.view.shown,
                                              self.view.shown_variation_idx)
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[
                cord0].sign == PAWN and cord1.cord in board.PROMOTION_ZONE[
                    color]:
            if self.variant.variant == SITTUYINCHESS:
                # no promotion allowed if we have queen
                if board.board.boards[color][QUEEN]:
                    promotion = None
                else:
                    # promotion is always optional
                    promotion = self.getPromotion()
                    if promotion is None and cord0 == cord1:
                        # if don't want in place promotion
                        return
            elif len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            else:
                if conf.get("autoPromote", False):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
            self.view.shownIsMainLine() and \
            self.view.model.boards[-1] == board and \
            self.view.model.status == RUNNING:
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            if board.board.next is None and not self.view.shownIsMainLine():
                self.view.model.add_move2variation(
                    board, move, self.view.shown_variation_idx)
                self.view.shown += 1
            else:
                new_vari = self.view.model.add_variation(board, (move, ))
                self.view.setShownBoard(new_vari[-1])
示例#22
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        color = self.view.model.boards[-1].color
        board = self.view.model.getBoardAtPly(self.view.shown,
                                              self.view.shown_variation_idx)
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[
                cord0].sign == PAWN and cord1.cord in board.PROMOTION_ZONE[
                    color]:
            if self.variant.variant == SITTUYINCHESS:
                # no promotion allowed if we have queen
                if board.board.boards[color][QUEEN]:
                    promotion = None
                else:
                    # promotion is always optional
                    promotion = self.getPromotion()
                    if promotion is None and cord0 == cord1:
                        # if don't want in place promotion
                        return
            elif len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            else:
                if conf.get("autoPromote", False):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                self.view.shownIsMainLine() and \
                self.view.model.boards[-1] == board and \
                self.view.model.status == RUNNING:
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            if board.board.next is None and not self.view.shownIsMainLine():
                self.view.model.add_move2variation(
                    board, move, self.view.shown_variation_idx)
                self.view.shown += 1
            else:
                new_vari = self.view.model.add_variation(board, (move, ))
                self.view.setShownBoard(new_vari[-1])
示例#23
0
            def on_book_created(persp, event):
                self.assertTrue(os.path.isfile(BIN))

                book.path = BIN
                book.bookfile = True

                testcase = testcases[0]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(sorted(openings), sorted([(newMove(E2, E4), 2, 0), (newMove(A2, A4), 0, 0)]))

                testcase = testcases[-1]
                board = LBoard(Board)
                board.applyFen(testcase[0])
                openings = book.getOpenings(board)
                self.assertEqual(openings, [])

                event.set()
示例#24
0
 def validate (self, cord0, cord1):
     assert cord0 != None and cord1 != None, "cord0: " + str(cord0) + ", cord1: " + str(cord1)
     if self.getBoard()[cord0] == None:
         return False
     if cord1.x < 0 or cord1.x > self.FILES-1:
         return False
     if cord0.x < 0 or cord0.x > self.FILES-1:
         # drop
         return validate(self.getBoard(), Move(lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord, DROP)))
     else:
         return validate(self.getBoard(), Move(cord0, cord1, self.getBoard()))
示例#25
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        board = self.getBoard()
        color = board.color
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[cord0].sign == PAWN and \
                cord1.cord in board.PROMOTION_ZONE[color] and \
                self.variant.variant != SITTUYINCHESS:
            if len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            else:
                if conf.get("autoPromote"):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if promotion is None and board[cord0].sign == PAWN and \
                cord0.cord in board.PROMOTION_ZONE[color] and \
                self.variant.variant == SITTUYINCHESS:
            # no promotion allowed if we have queen
            if board.board.boards[color][QUEEN]:
                promotion = None
            # in place promotion
            elif cord1.cord in board.PROMOTION_ZONE[color]:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
            # queen move promotion (but not a pawn capture!)
            elif board[cord1] is None and (cord0.cord + cord1.cord) % 2 == 1:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)

        if cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                self.view.shownIsMainLine() and \
                self.view.model.boards[-1] == board and \
                self.view.model.status == RUNNING:
            # emit move
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            self.play_or_add_move(board, move)
示例#26
0
 def validate (self, cord0, cord1):
     if cord0 is None or cord1 is None:
         return False
     if self.getBoard()[cord0] == None:
         return False
     if cord1.x < 0 or cord1.x > self.FILES-1:
         return False
     if cord0.x < 0 or cord0.x > self.FILES-1:
         # drop
         return validate(self.getBoard(), Move(lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord, DROP)))
     else:
         return validate(self.getBoard(), Move(cord0, cord1, self.getBoard()))
示例#27
0
    def testFRCCastling(self):
        """Testing FRC castling movegen"""
        print()

        for fen, castles in data:
            print(fen)
            board = LBoard(FISCHERRANDOMCHESS)
            board.applyFen(fen)
            # print board
            moves = [move for move in genCastles(board)]
            self.assertEqual(len(moves), len(castles))
            for i, castle in enumerate(castles):
                kfrom, kto, flag = castle
                self.assertEqual(moves[i], newMove(kfrom, kto, flag))
示例#28
0
    def testFRCCastling(self):
        """Testing FRC castling movegen"""
        print()

        for fen, castles in data:
            print(fen)
            board = LBoard(FISCHERRANDOMCHESS)
            board.applyFen(fen)
            # print board
            moves = [move for move in genCastles(board)]
            self.assertEqual(len(moves), len(castles))
            for i, castle in enumerate(castles):
                kfrom, kto, flag = castle
                self.assertEqual(moves[i], newMove(kfrom, kto, flag))
示例#29
0
 def validate (self, cord0, cord1):
     if cord0 is None or cord1 is None:
         return False
     # prevent accidental NULL_MOVE creation
     if cord0 == cord1:
         return False
     if self.getBoard()[cord0] == None:
         return False
     if cord1.x < 0 or cord1.x > self.FILES-1:
         return False
     if cord0.x < 0 or cord0.x > self.FILES-1:
         # drop
         return validate(self.getBoard(), Move(lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord, DROP)))
     else:
         return validate(self.getBoard(), Move(cord0, cord1, self.getBoard()))
示例#30
0
 def validate(self, cord0, cord1):
     if cord0 is None or cord1 is None:
         return False
     if self.getBoard()[cord0] == None:
         return False
     if cord1.x < 0 or cord1.x > self.FILES - 1:
         return False
     if cord0.x < 0 or cord0.x > self.FILES - 1:
         # drop
         return validate(
             self.getBoard(),
             Move(
                 lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord,
                                  DROP)))
     else:
         return validate(self.getBoard(), Move(cord0, cord1,
                                               self.getBoard()))
示例#31
0
 def validate(self, cord0, cord1):
     if cord0 is None or cord1 is None:
         return False
     # prevent accidental NULL_MOVE creation
     if cord0 == cord1:
         return False
     if self.getBoard()[cord0] == None:
         return False
     if cord1.x < 0 or cord1.x > self.FILES - 1:
         return False
     if cord0.x < 0 or cord0.x > self.FILES - 1:
         # drop
         return validate(
             self.getBoard(),
             Move(
                 lmovegen.newMove(self.getBoard()[cord0].piece, cord1.cord,
                                  DROP)))
     else:
         return validate(self.getBoard(), Move(cord0, cord1,
                                               self.getBoard()))
示例#32
0
    def test_pdb_database_get_bitboards(self):
        """Testing .pdb database get_bitboards"""

        db = self.load_test_pgn()

        board = LBoard()
        board.applyFen(FEN_START)

        def get_bb_candidates(board):
            bb_candidates = {}
            for lmove in genAllMoves(board):
                board.applyMove(lmove)
                if board.opIsChecked():
                    board.popMove()
                    continue
                bb_candidates[board.friends[0] | board.friends[1]] = lmove
                board.popMove()
            return bb_candidates

        # ply 1
        bitboards = db.get_bitboards(1, get_bb_candidates(board))
        print("==========")
        for row in bitboards:
            print(row)
        print("----------")
        self.assertEqual(len(bitboards), BITBOARD_COUNT[1])
        self.assertEqual(sum([row[1] for row in bitboards]), GAME_COUNT)
        self.assertEqual(bitboards[0][5], 2712)

        # ply 2
        board.applyMove(newMove(E2, E4))
        bitboards = db.get_bitboards(2, get_bb_candidates(board))
        print("==========")
        for row in bitboards:
            print(row)
        print("----------")
        self.assertEqual(len(bitboards), BITBOARD_COUNT[2])
        self.assertEqual(sum([row[1] for row in bitboards]), GAME_COUNT)
示例#33
0
def defencive_moves_tactic(model, ply, phase):

    # ------------------------------------------------------------------------ #
    # Test if we threat something, or at least put more pressure on it         #
    # ------------------------------------------------------------------------ #

    # We set bishop value down to knight value, as it is what most people expect
    bishopBackup = PIECE_VALUES[BISHOP]
    PIECE_VALUES[BISHOP] = PIECE_VALUES[KNIGHT]

    board = model.getBoardAtPly(ply).board
    oldboard = model.getBoardAtPly(ply - 1).board
    move = model.getMoveAtPly(ply - 1).move
    fcord = FCORD(move)
    tcord = TCORD(move)

    found_threatens = []
    found_increases = []

    # What do we attack now?
    board.setColor(1 - board.color)
    for ncap in genCaptures(board):

        # getCaptures also generate promotions
        if FLAG(ncap) in PROMOTIONS:
            continue

        # We are only interested in the attacks of the piece we just moved
        if FCORD(ncap) != TCORD(move):
            continue

        # We don't want to move back
        if TCORD(ncap) == FCORD(move):
            continue

        # We don't thread the king. We check him! (in another function)
        if board.arBoard[TCORD(ncap)] == KING:
            continue

        # If we also was able to attack that cord last time, we don't care
        if validateMove(oldboard, newMove(FCORD(move), TCORD(ncap))):
            continue

        # Test if we threats our enemy, at least more than before
        see0 = staticExchangeEvaluate(oldboard, TCORD(ncap),
                                      1 - oldboard.color)
        see1 = staticExchangeEvaluate(board, TCORD(ncap), 1 - oldboard.color)
        if see1 > see0:

            # If a new winning capture has been created
            if see1 > 0:
                # Find the easiest attack
                attacks = getAttacks(board, TCORD(ncap), board.color)
                v, cord = min((PIECE_VALUES[board.arBoard[fc]], fc)
                              for fc in iterBits(attacks))
                easiestAttack = newMove(cord, TCORD(ncap))
                found_threatens.append(toSAN(board, easiestAttack, True))

            # Even though we might not yet be strong enough, we might still
            # have strengthened another friendly attack
            else:
                found_increases.append(reprCord[TCORD(ncap)])

    board.setColor(1 - board.color)

    # -------------------------------------------------------------------- #
    # Test if we defend a one of our pieces                                #
    # -------------------------------------------------------------------- #

    found_defends = []

    # Test which pieces were under attack
    used = []
    for ncap in genCaptures(board):

        # getCaptures also generate promotions
        if FLAG(ncap) in PROMOTIONS:
            continue

        # We don't want to know about the same cord more than once
        if TCORD(ncap) in used:
            continue
        used.append(TCORD(ncap))

        # If the attack was poining on the piece we just moved, we ignore it
        if TCORD(ncap) == FCORD(move) or TCORD(ncap) == TCORD(move):
            continue

        # If we were already defending the piece, we don't send a new
        # message
        if defends(oldboard, FCORD(move), TCORD(ncap)):
            continue

        # If the attack was not strong, we ignore it
        see = staticExchangeEvaluate(oldboard, ncap)
        if see < 0:
            continue

        v = defends(board, TCORD(move), TCORD(ncap))

        # If the defend didn't help, it doesn't matter. Like defending a
        # bishop, threatened by a pawn, with a queen.
        # But on the other hand - it might still be a defend...
        # newsee = staticExchangeEvaluate(board, ncap)
        # if newsee <= see: continue

        if v:
            found_defends.append(reprCord[TCORD(ncap)])

    # ------------------------------------------------------------------------ #
    # Test if we are rescuing an otherwise exposed piece                       #
    # ------------------------------------------------------------------------ #

    # Rescuing is only an option, if our own move wasn't an attack
    if oldboard.arBoard[tcord] == EMPTY:
        see0 = staticExchangeEvaluate(oldboard, fcord, oldboard.color)
        see1 = staticExchangeEvaluate(board, tcord, oldboard.color)
        if see1 > see0 and see1 > 0:
            yield _("rescues a %s") % reprPiece[board.arBoard[tcord]].lower()

    if found_threatens:
        yield _("threatens to win material by %s") % join(found_threatens)
    if found_increases:
        yield _("increases the pressure on %s") % join(found_increases)
    if found_defends:
        yield _("defends %s") % join(found_defends)

    PIECE_VALUES[BISHOP] = bishopBackup
示例#34
0
 def on_game_started(game):
     p1 = gamemodel.players[1]
     p1.move_queue.put_nowait(Move(newMove(G8, F6)))
示例#35
0
from pychess.compat import basestring
from pychess.Utils.const import DROP
from pychess.Utils.lutils.lmovegen import newMove

MAXMOVE = newMove(63, 63, DROP)
COMMENT, VARI_START, VARI_END, NAG = (MAXMOVE + i + 1 for i in range(4))


def walk(node, arr, txt):
    """Prepares a game data for databse.
       Recursively walks the node tree to collect moves and comments.
       Arguments:
       node - list (a tree of lboards created by the pgn parser)
       arr - array("H") (2 byte unsigned ints representing lmove objects
                        or COMMENT, VARI_START, VARI_END, NAG+nag)
       txt - list (comment strings)"""

    arr_append = arr.append
    while True:
        if node is None:
            break

        # Initial game or variation comment
        if node.prev is None:
            for child in node.children:
                if isinstance(child, basestring):
                    arr_append(COMMENT)
                    txt.append(child)
            node = node.next
            continue
示例#36
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        gating = None
        board = self.getBoard()
        color = board.color
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[cord0].sign == PAWN and \
                cord1.cord in board.PROMOTION_ZONE[color] and \
                self.variant.variant != SITTUYINCHESS:
            if len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            elif self.variant.variant == LIGHTBRIGADECHESS:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION if color ==
                                                WHITE else KNIGHT_PROMOTION)
            else:
                if conf.get("autoPromote"):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if promotion is None and board[cord0].sign == PAWN and \
                cord0.cord in board.PROMOTION_ZONE[color] and \
                self.variant.variant == SITTUYINCHESS:
            # no promotion allowed if we have queen
            if board.board.boards[color][QUEEN]:
                promotion = None
            # in place promotion
            elif cord1.cord in board.PROMOTION_ZONE[color]:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
            # queen move promotion (but not a pawn capture!)
            elif board[cord1] is None and (cord0.cord + cord1.cord) % 2 == 1:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)

        holding = board.board.holding[color]
        if self.variant.variant == SCHESS:
            moved = board[cord0].sign
            hawk = holding[HAWK] > 0
            elephant = holding[ELEPHANT] > 0
            if (hawk or elephant) and cord0.cord in iterBits(
                    board.board.virgin[color]):
                castling = moved == KING and abs(cord0.x - cord1.x) == 2
                gating = self.getGating(castling, hawk, elephant)

        if gating is not None:
            if gating in (HAWK_GATE_AT_ROOK, ELEPHANT_GATE_AT_ROOK):
                side = 0 if cord0.x - cord1.x == 2 else 1
                rcord = board.board.ini_rooks[color][side]
                move = Move(lmovegen.newMove(rcord, cord0.cord, gating))
            else:
                move = Move(lmovegen.newMove(cord0.cord, cord1.cord, gating))
        elif cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                self.view.shownIsMainLine() and \
                self.view.model.boards[-1] == board and \
                self.view.model.status == RUNNING:
            # emit move
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            self.play_or_add_move(board, move)
示例#37
0
from pychess.Utils.const import DROP
from pychess.Utils.lutils.lmovegen import newMove

MAXMOVE = newMove(63, 63, DROP)
COMMENT, VARI_START, VARI_END, NAG = (MAXMOVE + i + 1 for i in range(4))


def walk(node, arr, txt):
    """Prepares a game data for databse.
       Recursively walks the node tree to collect moves and comments.
       Arguments:
       node - list (a tree of lboards created by the pgn parser)
       arr - array("H") (2 byte unsigned ints representing lmove objects
                        or COMMENT, VARI_START, VARI_END, NAG+nag)
       txt - list (comment strings)"""

    arr_append = arr.append
    while True:
        if node is None:
            break

        # Initial game or variation comment
        if node.prev is None:
            for child in node.children:
                if isinstance(child, str):
                    arr_append(COMMENT)
                    txt.append(child)
            node = node.next
            continue

        arr_append(node.lastMove)
示例#38
0
 def scoreAllMoves (self, board, probeSoft=False):
     global URL, expression, PROMOTION_FLAGS
     fen = board.asFen().split()[0] + " w - - 0 1"
     if (fen,board.color) in self.table:
         return self.table[(fen,board.color)]
     
     if probeSoft or not conf.get("online_egtb_check", True):
         return []
     
     # Request the page
     url = (URL + fen).replace(" ", "%20")
     try:
         f = urlopen(url)
     except IOError as e:
         log.warning("Unable to read endgame tablebase from the Internet: %s" % repr(e))
         return []
     data = f.read()
     
     # Parse
     for color, move_data in enumerate(data.split("\nNEXTCOLOR\n")):
         try:
             moves = []
             for fcord, tcord, promotion, result in expression.findall(move_data):
                 fcord = int(fcord)
                 tcord = int(tcord)
                 
                 if promotion:
                     flag = PROMOTION_FLAGS[int(promotion)]
                 elif RANK(fcord) != RANK(tcord) and FILE(fcord) != FILE(tcord) and \
                         board.arBoard[fcord] == PAWN and board.arBoard[tcord] == EMPTY:
                     flag = ENPASSANT
                 else: flag = NORMAL_MOVE
                 
                 move = newMove(fcord, tcord, flag)
                 
                 if result == "Draw":
                     state = DRAW
                     steps = 0
                 else:
                     s, steps = result.split(" in ")
                     steps = int(steps)
                 
                 if result.startswith("Win"):
                     if color == WHITE:
                         state = WHITEWON
                     else: state = BLACKWON
                 elif result.startswith("Lose"):
                     if color == WHITE:
                         state = BLACKWON
                     else: state = WHITEWON
                 
                 moves.append( (move,state,steps) )
             
             if moves:
                 self.table[(fen,color)] = moves
             elif color == board.color and board.opIsChecked():
                 log.warning("Asked endgametable for a won position: %s" % fen)
             elif color == board.color:
                 log.warning("Couldn't get %s data for position %s.\nData was: %s" %
                          (reprColor[color], fen, repr(data)))
         except (KeyError, ValueError):
             log.warning("Couldn't parse %s data for position %s.\nData was: %s" %
                      (reprColor[color], fen, repr(data)))
             self.table[(fen, color)] = [] # Don't try again.
     
     if (fen,board.color) in self.table:
         return self.table[(fen,board.color)]
     return []
示例#39
0
def _get_move(from_coord, to_coord, board: Board) -> Move:
    move = Move(newMove(from_coord, to_coord))
    move = Move(move.cord0, move.cord1, board)
    return move
示例#40
0
 def on_game_started(game):
     p1 = gamemodel.players[1]
     p1.move_queue.put_nowait(Move(newMove(G8, F6)))
示例#41
0
文件: lmove.py 项目: btrent/knave
def parseSAN (board, san):
    """ Parse a Short/Abbreviated Algebraic Notation string """
    notat = san

    color = board.color
    
    if notat == "--":
        return newMove(board.kings[color], board.kings[color], NULL_MOVE)

    if notat[-1] in ("+", "#"):
        notat = notat[:-1]
        # If '++' was used in place of #
        if notat[-1] == "+":
            notat = notat[:-1]
    
    flag = NORMAL_MOVE
    
    # If last char is a piece char, we assue it the promote char
    c = notat[-1]
    if c in ("K", "Q", "R", "B", "N", "k", "q", "r", "b", "n"):
        c = c.lower()
        if c == "k" and board.variant != SUICIDECHESS:
            raise ParsingError, (san, "invalid promoted piece", board.asFen())
            
        flag = chr2Sign[c] + 2
        if notat[-2] == "=":
            notat = notat[:-2]
        else: notat = notat[:-1]
    
    if len(notat) < 2:
        raise ParsingError, (san, _("the move needs a piece and a cord"), board.asFen())
    
    if notat[0] in "O0o":
        fcord = board.ini_kings[color]
        flag = KING_CASTLE if notat == "O-O" or notat == "0-0" or notat == "o-o" else QUEEN_CASTLE
        side = flag -QUEEN_CASTLE
        if FILE(fcord) == 3 and board.variant in (WILDCASTLECHESS, WILDCASTLESHUFFLECHESS):
            side = 0 if side == 1 else 1
        if board.variant == FISCHERRANDOMCHESS:
            tcord = board.ini_rooks[color][side]
        else:
            tcord = board.fin_kings[color][side]
        return newMove (fcord, tcord, flag)

    # LAN is not allowed in pgn spec, but sometimes it occures
    if "-" in notat:
        notat = notat.replace("-", "")

    if "@" in notat:
        tcord = cordDic[notat[-2:]]
        if notat[0].islower():
            # Sjeng-ism
            piece = chr2Sign[notat[0]]
        else:
            piece = chrU2Sign[notat[0]]
        return newMove(piece, tcord, DROP)
    
    if notat[0] in ("Q", "R", "B", "K", "N"):
        piece = chrU2Sign[notat[0]]
        notat = notat[1:]
    else:
        piece = PAWN
        if notat[-1] in ("1", "8") and flag == NORMAL_MOVE:
            raise ParsingError, (
                    san, _("promotion move without promoted piece is incorrect"), board.asFen())
    
    if "x" in notat:
        notat, tcord = notat.split("x")
        if not tcord in cordDic:
            raise ParsingError, (
                    san, _("the captured cord (%s) is incorrect") % tcord, board.asFen())

        tcord = cordDic[tcord]

        if piece == PAWN:
            # If a pawn is attacking an empty cord, we assue it an enpassant
            if board.arBoard[tcord] == EMPTY:
                flag = ENPASSANT
    else:
        if not notat[-2:] in cordDic:
            raise ParsingError, (
                    san, "the end cord (%s) is incorrect" % notat[-2:], board.asFen())
        
        tcord = cordDic[notat[-2:]]
        notat = notat[:-2]
    
    # In suicide promoting to king is valid, so
    # more than 1 king per side can exist !
    if board.variant != SUICIDECHESS and piece == KING:
        return newMove(board.kings[color], tcord, flag)

    # If there is any extra location info, like in the move Bexd1 or Nh3f4 we
    # want to know
    frank = None
    ffile = None
    if notat and notat[0] in reprRank:
        frank = int(notat[0])-1
        notat = notat[1:]
    if notat and notat[0] in reprFile:
        ffile = ord(notat[0]) - ord("a")
        notat = notat[1:]
    if notat and notat[0] in reprRank:
        frank = int(notat[0])-1
        notat = notat[1:]
        # we know all we want
        return newMove(frank*8+ffile, tcord, flag)

    if piece == PAWN:
        if (ffile is not None) and ffile != FILE(tcord):
            # capture
            if color == WHITE:
                fcord = tcord-7 if ffile > FILE(tcord) else tcord-9
            else:
                fcord = tcord+7 if ffile < FILE(tcord) else tcord+9
        else:
            if color == WHITE:
                pawns = board.boards[WHITE][PAWN]
                fcord = tcord-16 if RANK(tcord)==3 and not (pawns & fileBits[FILE(tcord)] & rankBits[2]) else tcord-8
            else:
                pawns = board.boards[BLACK][PAWN]
                fcord = tcord+16 if RANK(tcord)==4 and not (pawns & fileBits[FILE(tcord)] & rankBits[5]) else tcord+8
        return newMove(fcord, tcord, flag)
    else:
        if board.pieceCount[color][piece] == 1:
            # we have only one from this kind if piece, so:
            fcord = firstBit(board.boards[color][piece])
            return newMove(fcord, tcord, flag)
        else:
            # We find all pieces who could have done it. (If san was legal, there should
            # never be more than one)
            moves = genPieceMoves(board, piece, tcord)
            if len(moves) == 1:
                return moves.pop()
            else:
                for move in moves:
                    f = FCORD(move)
                    if frank != None and frank != RANK(f):
                        continue
                    if ffile != None and ffile != FILE(f):
                        continue
                    board_clone = board.clone()
                    board_clone.applyMove(move)
                    if board_clone.opIsChecked():
                        continue
                    return move
    
    errstring = "no %s is able to move to %s" % (reprPiece[piece], reprCord[tcord])
    raise ParsingError, (san, errstring, board.asFen())
示例#42
0
文件: lmove.py 项目: btrent/knave
                    flag = KING_CASTLE
                
        elif fcord - tcord == 2:
            flag = QUEEN_CASTLE
        elif fcord - tcord == -2:
            flag = KING_CASTLE
        else:
            flag = NORMAL_MOVE
    elif board.arBoard[fcord] == PAWN and board.arBoard[tcord] == EMPTY and \
            FILE(fcord) != FILE(tcord) and RANK(fcord) != RANK(tcord):
        flag = ENPASSANT
    elif board.arBoard[fcord] == PAWN and an[3] in ("1", "8"):
            raise ParsingError, (
                    an, _("promotion move without promoted piece is incorrect"), board.asFen())

    return newMove (fcord, tcord, flag)

################################################################################
# toFAN                                                                        #
################################################################################

san2WhiteFanDic = {
    ord(u"K"): FAN_PIECES[WHITE][KING],
    ord(u"Q"): FAN_PIECES[WHITE][QUEEN],
    ord(u"R"): FAN_PIECES[WHITE][ROOK],
    ord(u"B"): FAN_PIECES[WHITE][BISHOP],
    ord(u"N"): FAN_PIECES[WHITE][KNIGHT],
    ord(u"+"): u"†",
    ord(u"#"): u"‡"
}
示例#43
0
文件: dbwalk.py 项目: zuzak/pychess
from pychess.compat import basestring
from pychess.Utils.const import NULL_MOVE
from pychess.Utils.lutils.lmovegen import newMove

MAXMOVE = newMove(63, 63, NULL_MOVE)
COMMENT, VARI_START, VARI_END, NAG = (MAXMOVE + i + 1 for i in range(4))


def walk(node, arr, txt):
    """Prepares a game data for databse.
       Recursively walks the node tree to collect moves and comments.
       Arguments:
       node - list (a tree of lboards created by the pgn parser)
       arr - array("H") (2 byte unsigned ints representing lmove objects
                        or COMMENT, VARI_START, VARI_END, NAG+nag)
       txt - list (comment strings)"""

    arr_append = arr.append
    while True:
        if node is None:
            break

        # Initial game or variation comment
        if node.prev is None:
            for child in node.children:
                if isinstance(child, basestring):
                    arr_append(COMMENT)
                    txt.append(child)
            node = node.next
            continue
示例#44
0
def parseSAN(board, san):
    """ Parse a Short/Abbreviated Algebraic Notation string """
    notat = san

    color = board.color

    if notat == "--":
        return newMove(board.kings[color], board.kings[color], NULL_MOVE)

    if notat[-1] in "+#":
        notat = notat[:-1]
        # If '++' was used in place of #
        if notat[-1] == "+":
            notat = notat[:-1]

    flag = NORMAL_MOVE

    # If last char is a piece char, we assue it the promote char
    c = notat[-1]
    if c in "KQRBNSMFkqrbnsmf.":
        c = c.lower()
        if c == "k" and board.variant != SUICIDECHESS and board.variant != GIVEAWAYCHESS:
            raise ParsingError(san, _("invalid promoted piece"), board.asFen())
        elif c == "." and board.variant in (CAMBODIANCHESS, MAKRUKCHESS,
                                            SITTUYINCHESS):
            # temporary hack for xboard bug
            flag = QUEEN_PROMOTION
        else:
            flag = chr2Sign[c] + 2

        if notat[-2] == "=":
            notat = notat[:-2]
        else:
            notat = notat[:-1]

    if len(notat) < 2:
        raise ParsingError(san, _("the move needs a piece and a cord"),
                           board.asFen())

    if notat[0] in "O0o":
        fcord = board.ini_kings[color]
        flag = KING_CASTLE if notat in ("O-O", "0-0", "o-o", "OO", "00", "oo") else QUEEN_CASTLE
        side = flag - QUEEN_CASTLE
        if FILE(fcord) == 3 and board.variant in (WILDCASTLECHESS,
                                                  WILDCASTLESHUFFLECHESS):
            side = 0 if side == 1 else 1
        if board.variant == FISCHERRANDOMCHESS:
            tcord = board.ini_rooks[color][side]
        else:
            tcord = board.fin_kings[color][side]
        return newMove(fcord, tcord, flag)

    # LAN is not allowed in pgn spec, but sometimes it occures
    if "-" in notat:
        notat = notat.replace("-", "")

    if "@" in notat:
        tcord = cordDic[notat[-2:]]
        if notat[0].islower():
            # Sjeng-ism
            piece = chr2Sign[notat[0]]
        else:
            piece = chrU2Sign[notat[0]]
        return newMove(piece, tcord, DROP)

    # standard piece letters
    if notat[0] in "QRBKNSMF":
        piece = chrU2Sign[notat[0]]
        notat = notat[1:]
    # unambigious lowercase piece letters
    elif notat[0] in "qrknsm":
        piece = chr2Sign[notat[0]]
        notat = notat[1:]
    # a lowercase bishop letter or a pawn capture
    elif notat[0] == "b" and len(notat) > 2 and board.variant == NORMALCHESS:
        tcord = cordDic[notat[-2:]]
        trank = int(notat[-1])
        # if from and to lines are not neighbours -> Bishop
        if abs(ord(notat[0]) - ord(notat[-2])) > 1:
            piece = chr2Sign[notat[0]]
            notat = notat[1:]
        # if from and to lines are neighbours (or the same) but to is an empty square
        # which can't be en-passant square target -> Bishop
        elif board.arBoard[tcord] == EMPTY and ((color == BLACK and trank != 3) or (color == WHITE and trank != 6)):
            piece = chr2Sign[notat[0]]
            notat = notat[1:]
        # elif "ba3", "bc3" ,"ba6", "bc6"
        # these can be Bishop or Pawn moves, but we don't try to introspect them (sorry)
        else:
            piece = PAWN
    else:
        piece = PAWN
        if notat[-1] in "18" and flag == NORMAL_MOVE and board.variant != SITTUYINCHESS:
            raise ParsingError(
                san, _("promotion move without promoted piece is incorrect"),
                board.asFen())

    if "x" in notat:
        notat, tcord = notat.split("x")
        if tcord not in cordDic:
            raise ParsingError(san, _("the captured cord (%s) is incorrect") %
                               tcord, board.asFen())

        tcord = cordDic[tcord]

        if piece == PAWN:
            # If a pawn is attacking an empty cord, we assue it an enpassant
            if board.arBoard[tcord] == EMPTY:
                if (color == BLACK and 2 * 8 <= tcord < 3 * 8) or (color == WHITE and 5 * 8 <= tcord < 6 * 8):
                    flag = ENPASSANT
                else:
                    raise ParsingError(
                        san, _("pawn capture without target piece is invalid"),
                        board.asFen())
    else:
        if not notat[-2:] in cordDic:
            raise ParsingError(san, _("the end cord (%s) is incorrect") %
                               notat[-2:], board.asFen())

        tcord = cordDic[notat[-2:]]
        notat = notat[:-2]

    # In suicide promoting to king is valid, so
    # more than 1 king per side can exist !
    if board.variant != SUICIDECHESS and board.variant != GIVEAWAYCHESS and piece == KING:
        return newMove(board.kings[color], tcord, flag)

    # If there is any extra location info, like in the move Bexd1 or Nh3f4 we
    # want to know
    frank = None
    ffile = None
    if notat and notat[0] in reprRank:
        frank = int(notat[0]) - 1
        notat = notat[1:]
    if notat and notat[0] in reprFile:
        ffile = ord(notat[0]) - ord("a")
        notat = notat[1:]
    if notat and notat[0] in reprRank:
        frank = int(notat[0]) - 1
        notat = notat[1:]
        # we know all we want
        return newMove(frank * 8 + ffile, tcord, flag)

    if piece == PAWN:
        if (ffile is not None) and ffile != FILE(tcord):
            # capture
            if color == WHITE:
                fcord = tcord - 7 if ffile > FILE(tcord) else tcord - 9
            else:
                fcord = tcord + 7 if ffile < FILE(tcord) else tcord + 9
        else:
            if color == WHITE:
                pawns = board.boards[WHITE][PAWN]
                # In horde white pawns on first rank may move two squares also
                if board.variant == HORDECHESS and RANK(tcord) == 2 and not (
                        pawns & fileBits[FILE(tcord)] & rankBits[1]):
                    fcord = tcord - 16
                else:
                    fcord = tcord - 16 if RANK(tcord) == 3 and not (
                        pawns & fileBits[FILE(tcord)] & rankBits[2]) else tcord - 8
            else:
                pawns = board.boards[BLACK][PAWN]
                fcord = tcord + 16 if RANK(tcord) == 4 and not (
                    pawns & fileBits[FILE(tcord)] & rankBits[5]) else tcord + 8
            if board.variant == SITTUYINCHESS and flag == QUEEN_PROMOTION and \
                    (pawns & fileBits[FILE(tcord)] & rankBits[RANK(tcord)]):
                    return newMove(tcord, tcord, flag)
        return newMove(fcord, tcord, flag)
    else:
        if board.pieceCount[color][piece] == 1:
            # we have only one from this kind if piece, so:
            fcord = firstBit(board.boards[color][piece])
            return newMove(fcord, tcord, flag)
        else:
            # We find all pieces who could have done it. (If san was legal, there should
            # never be more than one)
            moves = genPieceMoves(board, piece, tcord)
            if len(moves) == 1:
                return moves.pop()
            else:
                for move in moves:
                    f = FCORD(move)
                    if frank is not None and frank != RANK(f):
                        continue
                    if ffile is not None and ffile != FILE(f):
                        continue
                    board_clone = board.clone()
                    board_clone.applyMove(move)
                    if board_clone.opIsChecked():
                        continue
                    return move

    errstring = "no %s is able to move to %s" % (reprPiece[piece],
                                                 reprCord[tcord])
    raise ParsingError(san, errstring, board.asFen())
示例#45
0
def parseSAN(board, san):
    """ Parse a Short/Abbreviated Algebraic Notation string """
    notat = san

    color = board.color

    if notat == "--":
        return newMove(board.kings[color], board.kings[color], NULL_MOVE)

    if notat[-1] in "+#":
        notat = notat[:-1]
        # If '++' was used in place of #
        if notat[-1] == "+":
            notat = notat[:-1]

    flag = NORMAL_MOVE

    # If last char is a piece char, we assue it the promote char
    c = notat[-1]
    if c in "KQRBNSMFkqrbnsmf.":
        c = c.lower()
        if c == "k" and board.variant != SUICIDECHESS and board.variant != GIVEAWAYCHESS:
            raise ParsingError(san, _("invalid promoted piece"), board.asFen())
        elif c == ".":
            if board.variant in (CAMBODIANCHESS, MAKRUKCHESS, SITTUYINCHESS):
                # temporary hack for xboard bug
                flag = QUEEN_PROMOTION
            else:
                raise ParsingError(san, "invalid san", board.asFen())
        else:
            flag = chr2Sign[c] + 2

        if notat[-2] == "=":
            notat = notat[:-2]
        else:
            notat = notat[:-1]

    if len(notat) < 2:
        raise ParsingError(san, _("the move needs a piece and a cord"),
                           board.asFen())

    if notat[0] in "O0o":
        fcord = board.ini_kings[color]
        flag = KING_CASTLE if notat in ("O-O", "0-0", "o-o", "OO", "00",
                                        "oo") else QUEEN_CASTLE
        side = flag - QUEEN_CASTLE
        if FILE(fcord) == 3 and board.variant in (WILDCASTLECHESS,
                                                  WILDCASTLESHUFFLECHESS):
            side = 0 if side == 1 else 1
        if board.variant == FISCHERRANDOMCHESS:
            tcord = board.ini_rooks[color][side]
        else:
            tcord = board.fin_kings[color][side]
        return newMove(fcord, tcord, flag)

    # LAN is not allowed in pgn spec, but sometimes it occures
    if "-" in notat:
        notat = notat.replace("-", "")

    if "@" in notat:
        tcord = cordDic[notat[-2:]]
        if notat[0].islower():
            # Sjeng-ism
            piece = chr2Sign[notat[0]]
        else:
            piece = chrU2Sign[notat[0]]
        return newMove(piece, tcord, DROP)

    # standard piece letters
    if notat[0] in "QRBKNSMF":
        piece = chrU2Sign[notat[0]]
        notat = notat[1:]
    # unambigious lowercase piece letters
    elif notat[0] in "qrknsm":
        piece = chr2Sign[notat[0]]
        notat = notat[1:]
    # a lowercase bishop letter or a pawn capture
    elif notat[0] == "b" and len(notat) > 2 and board.variant == NORMALCHESS:
        tcord = cordDic[notat[-2:]]
        trank = int(notat[-1])
        # if from and to lines are not neighbours -> Bishop
        if abs(ord(notat[0]) - ord(notat[-2])) > 1:
            piece = chr2Sign[notat[0]]
            notat = notat[1:]
        # if from and to lines are neighbours (or the same) but to is an empty square
        # which can't be en-passant square target -> Bishop
        elif board.arBoard[tcord] == EMPTY and (
            (color == BLACK and trank != 3) or
            (color == WHITE and trank != 6)):
            piece = chr2Sign[notat[0]]
            notat = notat[1:]
        # elif "ba3", "bc3" ,"ba6", "bc6"
        # these can be Bishop or Pawn moves, but we don't try to introspect them (sorry)
        else:
            piece = PAWN
    else:
        piece = PAWN
        if notat[
                -1] in "18" and flag == NORMAL_MOVE and board.variant != SITTUYINCHESS:
            flag = QUEEN_PROMOTION

    if "x" in notat:
        notat, tcord = notat.split("x")
        if tcord not in cordDic:
            raise ParsingError(
                san,
                _("the captured cord (%s) is incorrect") % tcord,
                board.asFen())

        tcord = cordDic[tcord]

        if piece == PAWN:
            # If a pawn is attacking an empty cord, we assue it an enpassant
            if board.arBoard[tcord] == EMPTY:
                if (color == BLACK and 2 * 8 <= tcord < 3 * 8) or (
                        color == WHITE and 5 * 8 <= tcord < 6 * 8):
                    flag = ENPASSANT
                else:
                    raise ParsingError(
                        san, _("pawn capture without target piece is invalid"),
                        board.asFen())
    else:
        if not notat[-2:] in cordDic:
            raise ParsingError(
                san,
                _("the end cord (%s) is incorrect") % notat[-2:],
                board.asFen())

        tcord = cordDic[notat[-2:]]
        notat = notat[:-2]

    # In suicide promoting to king is valid, so
    # more than 1 king per side can exist !
    if board.variant != SUICIDECHESS and board.variant != GIVEAWAYCHESS and piece == KING:
        return newMove(board.kings[color], tcord, flag)

    # If there is any extra location info, like in the move Bexd1 or Nh3f4 we
    # want to know
    frank = None
    ffile = None
    if notat and notat[0] in reprRank:
        frank = int(notat[0]) - 1
        notat = notat[1:]
    if notat and notat[0] in reprFile:
        ffile = ord(notat[0]) - ord("a")
        notat = notat[1:]
    if notat and notat[0] in reprRank:
        frank = int(notat[0]) - 1
        notat = notat[1:]
        # we know all we want
        return newMove(frank * 8 + ffile, tcord, flag)

    if piece == PAWN:
        if (ffile is not None) and ffile != FILE(tcord):
            # capture
            if color == WHITE:
                fcord = tcord - 7 if ffile > FILE(tcord) else tcord - 9
            else:
                fcord = tcord + 7 if ffile < FILE(tcord) else tcord + 9
        else:
            if color == WHITE:
                pawns = board.boards[WHITE][PAWN]
                # In horde white pawns on first rank may move two squares also
                if board.variant == HORDECHESS and RANK(tcord) == 2 and not (
                        pawns & fileBits[FILE(tcord)] & rankBits[1]):
                    fcord = tcord - 16
                else:
                    fcord = tcord - 16 if RANK(tcord) == 3 and not (
                        pawns & fileBits[FILE(tcord)]
                        & rankBits[2]) else tcord - 8
            else:
                pawns = board.boards[BLACK][PAWN]
                fcord = tcord + 16 if RANK(tcord) == 4 and not (
                    pawns & fileBits[FILE(tcord)] & rankBits[5]) else tcord + 8

            if board.variant == SITTUYINCHESS and flag == QUEEN_PROMOTION:
                if pawns & fileBits[FILE(tcord)] & rankBits[RANK(tcord)]:
                    # in place promotion
                    return newMove(tcord, tcord, flag)
                else:
                    # queen move promotion (fcord have to be the closest cord of promotion zone)
                    fcord = sittuyin_promotion_fcord(board, tcord)
                    return newMove(fcord, tcord, flag)
        return newMove(fcord, tcord, flag)
    else:
        if board.pieceCount[color][piece] == 1:
            # we have only one from this kind if piece, so:
            fcord = firstBit(board.boards[color][piece])
            return newMove(fcord, tcord, flag)
        else:
            # We find all pieces who could have done it. (If san was legal, there should
            # never be more than one)
            moves = genPieceMoves(board, piece, tcord)
            if len(moves) == 1:
                return moves.pop()
            else:
                for move in moves:
                    f = FCORD(move)
                    if frank is not None and frank != RANK(f):
                        continue
                    if ffile is not None and ffile != FILE(f):
                        continue
                    board_clone = board.clone()
                    board_clone.applyMove(move)
                    if board_clone.opIsChecked():
                        continue
                    return move

    errstring = _("no %(piece)s is able to move to %(cord)s") % {
        "piece": reprPiece[piece],
        "cord": reprCord[tcord]
    }
    raise ParsingError(san, errstring, board.asFen())
示例#46
0
    def __init__(self, cord0, cord1=None, board=None, promotion=None):
        """ Inits a new highlevel Move object.
            The object can be initialized in the follow ways:
                Move(cord0, cord1, board, [promotionPiece])
                Move(lovLevelMoveInt) """

        if not cord1:
            self.move = cord0
            self.flag = self.move >> 12
            self.cord0 = None if self.flag == DROP else Cord(lmove.FCORD(
                self.move))
            self.cord1 = Cord(lmove.TCORD(self.move))

        else:
            assert cord0 is not None and cord1 is not None, "cord0=%s, cord1=%s, board=%s" % (
                cord0, cord1, board)
            assert board[cord0] is not None, "cord0=%s, cord1=%s, board=%s" % (
                cord0, cord1, board)
            self.cord0 = cord0
            self.cord1 = cord1
            if not board:
                raise ValueError(
                    "Move needs a Board object in order to investigate flags")

            self.flag = NORMAL_MOVE
            if board[self.cord0].piece == PAWN and \
                    self.cord1.cord in board.PROMOTION_ZONE[board.board.color] and \
                    board.variant != SITTUYINCHESS:
                if promotion is None:
                    self.flag = lmove.FLAG_PIECE(QUEEN)
                else:
                    self.flag = lmove.FLAG_PIECE(promotion)

            elif board[self.cord0].piece == PAWN and board.variant == SITTUYINCHESS:
                    if cord0 == cord1:
                        # in place promotion
                        self.flag = lmove.FLAG_PIECE(QUEEN)
                    elif board[self.cord1] is None and \
                            (self.cord0.cord + self.cord1.cord) % 2 == 1 and \
                            (self.cord0.cord in board.PROMOTION_ZONE[board.board.color] or board.board.pieceCount[board.color][PAWN] == 1):
                        # queen move promotion
                        self.flag = lmove.FLAG_PIECE(QUEEN)

            elif board[self.cord0].piece == KING:
                if self.cord0 == self.cord1:
                    self.flag = NULL_MOVE

                if self.cord0.x - self.cord1.x == 2 and board.variant not in (CAMBODIANCHESS, FISCHERRANDOMCHESS):
                    self.flag = QUEEN_CASTLE if self.cord0.x == 4 else KING_CASTLE
                elif self.cord0.x - self.cord1.x == -2 and board.variant not in (CAMBODIANCHESS, FISCHERRANDOMCHESS):
                    self.flag = KING_CASTLE if self.cord0.x == 4 else QUEEN_CASTLE
                else:
                    if (abs(self.cord0.x - self.cord1.x) > 1 and self.cord1.x == C1) or (
                            board.board.ini_rooks[board.color][0] == self.cord1.cord and (
                                (board.board.color == WHITE and board.board.castling & W_OOO) or (
                            board.board.color == BLACK and board.board.castling & B_OOO))):
                        self.flag = QUEEN_CASTLE
                    elif (abs(self.cord0.x - self.cord1.x) > 1 and self.cord1.x == G1) or (
                            board.board.ini_rooks[board.color][1] == self.cord1.cord and (
                                (board.board.color == WHITE and board.board.castling & W_OO) or (
                            board.board.color == BLACK and board.board.castling & B_OO))):
                        self.flag = KING_CASTLE
            elif board[self.cord0].piece == PAWN and \
                    board[self.cord1] is None and \
                    self.cord0.x != self.cord1.x and \
                    self.cord0.y != self.cord1.y:
                self.flag = ENPASSANT

            self.move = newMove(self.cord0.cord, self.cord1.cord, self.flag)
示例#47
0
    def scoreAllMoves(self, board, probeSoft=False):
        global URL, expression, PROMOTION_FLAGS
        fen = board.asFen().split()[0] + " w - - 0 1"
        if (fen, board.color) in self.table:
            return self.table[(fen, board.color)]

        if probeSoft or not conf.get("online_egtb_check"):
            return []

        def get_data(URL, fen):
            # Request the page
            url = (URL + fen).replace(" ", "%20")
            try:
                f = urlopen(url)
            except IOError as e:
                log.warning(
                    "Unable to read endgame tablebase from the Internet: %s" %
                    repr(e))
                data = b""
            data = f.read()
            return data

        loop = asyncio.get_event_loop()
        future = loop.run_in_executor(None, get_data, URL, fen)
        data = yield from future

        # Parse
        for color, move_data in enumerate(data.split(b"\nNEXTCOLOR\n")):
            try:
                moves = []
                for fcord, tcord, promotion, result in expression.findall(
                        move_data.decode()):
                    fcord = int(fcord)
                    tcord = int(tcord)

                    if promotion:
                        flag = PROMOTION_FLAGS[int(promotion)]
                    elif RANK(fcord) != RANK(tcord) and FILE(fcord) != FILE(tcord) and \
                            board.arBoard[fcord] == PAWN and board.arBoard[tcord] == EMPTY:
                        flag = ENPASSANT
                    else:
                        flag = NORMAL_MOVE

                    move = newMove(fcord, tcord, flag)

                    if result == "Draw":
                        state = DRAW
                        steps = 0
                    else:
                        s, steps = result.split(" in ")
                        steps = int(steps)

                    if result.startswith("Win"):
                        if color == WHITE:
                            state = WHITEWON
                        else:
                            state = BLACKWON
                    elif result.startswith("Lose"):
                        if color == WHITE:
                            state = BLACKWON
                        else:
                            state = WHITEWON

                    moves.append((move, state, steps))

                if moves:
                    self.table[(fen, color)] = moves
                elif color == board.color and board.opIsChecked():
                    log.warning("Asked endgametable for a won position: %s" %
                                fen)
                elif color == board.color:
                    log.warning(
                        "Couldn't get %s data for position %s.\nData was: %s" %
                        (reprColor[color], fen, repr(data)))
            except (KeyError, ValueError):
                log.warning(
                    "Couldn't parse %s data for position %s.\nData was: %s" %
                    (reprColor[color], fen, repr(data)))
                self.table[(fen, color)] = []  # Don't try again.

        if (fen, board.color) in self.table:
            return self.table[(fen, board.color)]
        return []
示例#48
0
def defencive_moves_tactic(model, ply, phase):

    # ------------------------------------------------------------------------ #
    # Test if we threat something, or at least put more pressure on it         #
    # ------------------------------------------------------------------------ #

    # We set bishop value down to knight value, as it is what most people expect
    bishopBackup = PIECE_VALUES[BISHOP]
    PIECE_VALUES[BISHOP] = PIECE_VALUES[KNIGHT]

    board = model.getBoardAtPly(ply).board
    oldboard = model.getBoardAtPly(ply - 1).board
    move = model.getMoveAtPly(ply - 1).move
    fcord = FCORD(move)
    tcord = TCORD(move)

    found_threatens = []
    found_increases = []

    # What do we attack now?
    board.setColor(1 - board.color)
    for ncap in genCaptures(board):

        # getCaptures also generate promotions
        if FLAG(ncap) in PROMOTIONS:
            continue

        # We are only interested in the attacks of the piece we just moved
        if FCORD(ncap) != TCORD(move):
            continue

        # We don't want to move back
        if TCORD(ncap) == FCORD(move):
            continue

        # We don't thread the king. We check him! (in another function)
        if board.arBoard[TCORD(ncap)] == KING:
            continue

        # If we also was able to attack that cord last time, we don't care
        if validateMove(oldboard, newMove(FCORD(move), TCORD(ncap))):
            continue

        # Test if we threats our enemy, at least more than before
        see0 = staticExchangeEvaluate(oldboard, TCORD(ncap),
                                      1 - oldboard.color)
        see1 = staticExchangeEvaluate(board, TCORD(ncap), 1 - oldboard.color)
        if see1 > see0:

            # If a new winning capture has been created
            if see1 > 0:
                # Find the easiest attack
                attacks = getAttacks(board, TCORD(ncap), board.color)
                v, cord = min((PIECE_VALUES[board.arBoard[fc]], fc)
                              for fc in iterBits(attacks))
                easiestAttack = newMove(cord, TCORD(ncap))
                found_threatens.append(toSAN(board, easiestAttack, True))

            # Even though we might not yet be strong enough, we might still
            # have strengthened another friendly attack
            else:
                found_increases.append(reprCord[TCORD(ncap)])

    board.setColor(1 - board.color)

    # -------------------------------------------------------------------- #
    # Test if we defend a one of our pieces                                #
    # -------------------------------------------------------------------- #

    found_defends = []

    # Test which pieces were under attack
    used = []
    for ncap in genCaptures(board):

        # getCaptures also generate promotions
        if FLAG(ncap) in PROMOTIONS:
            continue

        # We don't want to know about the same cord more than once
        if TCORD(ncap) in used:
            continue
        used.append(TCORD(ncap))

        # If the attack was poining on the piece we just moved, we ignore it
        if TCORD(ncap) == FCORD(move) or TCORD(ncap) == TCORD(move):
            continue

        # If we were already defending the piece, we don't send a new
        # message
        if defends(oldboard, FCORD(move), TCORD(ncap)):
            continue

        # If the attack was not strong, we ignore it
        see = staticExchangeEvaluate(oldboard, ncap)
        if see < 0:
            continue

        v = defends(board, TCORD(move), TCORD(ncap))

        # If the defend didn't help, it doesn't matter. Like defending a
        # bishop, threatened by a pawn, with a queen.
        # But on the other hand - it might still be a defend...
        # newsee = staticExchangeEvaluate(board, ncap)
        # if newsee <= see: continue

        if v:
            found_defends.append(reprCord[TCORD(ncap)])

    # ------------------------------------------------------------------------ #
    # Test if we are rescuing an otherwise exposed piece                       #
    # ------------------------------------------------------------------------ #

    # Rescuing is only an option, if our own move wasn't an attack
    if oldboard.arBoard[tcord] == EMPTY:
        see0 = staticExchangeEvaluate(oldboard, fcord, oldboard.color)
        see1 = staticExchangeEvaluate(board, tcord, oldboard.color)
        if see1 > see0 and see1 > 0:
            yield _("rescues a %s") % reprPiece[board.arBoard[tcord]].lower()

    if found_threatens:
        yield _("threatens to win material by %s") % join(found_threatens)
    if found_increases:
        yield _("increases the pressure on %s") % join(found_increases)
    if found_defends:
        yield _("defends %s") % join(found_defends)

    PIECE_VALUES[BISHOP] = bishopBackup
示例#49
0
def parseSAN(board, san, full=True):
    """ Parse a Short/Abbreviated Algebraic Notation string """
    notat = san

    color = board.color

    if notat == "--":
        return newMove(board.kings[color], board.kings[color], NULL_MOVE)

    if notat[-1] in "+#":
        notat = notat[:-1]
        # If '++' was used in place of #
        if notat[-1] == "+":
            notat = notat[:-1]

    flag = NORMAL_MOVE

    # If last char is a piece char, we assue it the promote char
    c = notat[-1]
    if c in "KQRBNSMFkqrbnsmf.":
        c = c.lower()
        if c == "k" and board.variant != SUICIDECHESS:
            raise ParsingError(san, _("invalid promoted piece"), board.asFen())
        elif c == "." and board.variant in (CAMBODIANCHESS, MAKRUKCHESS,
                                            SITTUYINCHESS):
            # temporary hack for xboard bug
            flag = QUEEN_PROMOTION
        else:
            flag = chr2Sign[c] + 2

        if notat[-2] == "=":
            notat = notat[:-2]
        else:
            notat = notat[:-1]

    if len(notat) < 2:
        raise ParsingError(san, _("the move needs a piece and a cord"),
                           board.asFen())

    if notat[0] in "O0o":
        fcord = board.ini_kings[color]
        flag = KING_CASTLE if notat == "O-O" or notat == "0-0" or notat == "o-o" else QUEEN_CASTLE
        side = flag - QUEEN_CASTLE
        if FILE(fcord) == 3 and board.variant in (WILDCASTLECHESS,
                                                  WILDCASTLESHUFFLECHESS):
            side = 0 if side == 1 else 1
        if board.variant == FISCHERRANDOMCHESS:
            tcord = board.ini_rooks[color][side]
        else:
            tcord = board.fin_kings[color][side]
        return newMove(fcord, tcord, flag)

    # LAN is not allowed in pgn spec, but sometimes it occures
    if "-" in notat:
        notat = notat.replace("-", "")

    if "@" in notat:
        tcord = cordDic[notat[-2:]]
        if notat[0].islower():
            # Sjeng-ism
            piece = chr2Sign[notat[0]]
        else:
            piece = chrU2Sign[notat[0]]
        return newMove(piece, tcord, DROP)

    if notat[0] in "QRBKNSMF":
        piece = chrU2Sign[notat[0]]
        notat = notat[1:]
    else:
        piece = PAWN
        if notat[
                -1] in "18" and flag == NORMAL_MOVE and board.variant != SITTUYINCHESS:
            raise ParsingError(
                san, _("promotion move without promoted piece is incorrect"),
                board.asFen())

    if "x" in notat:
        notat, tcord = notat.split("x")
        if tcord not in cordDic:
            raise ParsingError(
                san,
                _("the captured cord (%s) is incorrect") % tcord,
                board.asFen())

        tcord = cordDic[tcord]

        if piece == PAWN:
            # If a pawn is attacking an empty cord, we assue it an enpassant
            if board.arBoard[tcord] == EMPTY:
                if (color == BLACK and 2 * 8 <= tcord < 3 * 8) or (
                        color == WHITE and 5 * 8 <= tcord < 6 * 8):
                    flag = ENPASSANT
                else:
                    raise ParsingError(
                        san, _("pawn capture without target piece is invalid"),
                        board.asFen())
    else:
        if not notat[-2:] in cordDic:
            raise ParsingError(
                san,
                _("the end cord (%s) is incorrect") % notat[-2:],
                board.asFen())

        tcord = cordDic[notat[-2:]]
        notat = notat[:-2]

    # In suicide promoting to king is valid, so
    # more than 1 king per side can exist !
    if board.variant != SUICIDECHESS and piece == KING:
        return newMove(board.kings[color], tcord, flag)

    # If there is any extra location info, like in the move Bexd1 or Nh3f4 we
    # want to know
    frank = None
    ffile = None
    if notat and notat[0] in reprRank:
        frank = int(notat[0]) - 1
        notat = notat[1:]
    if notat and notat[0] in reprFile:
        ffile = ord(notat[0]) - ord("a")
        notat = notat[1:]
    if notat and notat[0] in reprRank:
        frank = int(notat[0]) - 1
        notat = notat[1:]
        # we know all we want
        return newMove(frank * 8 + ffile, tcord, flag)

    if piece == PAWN:
        if (ffile is not None) and ffile != FILE(tcord):
            # capture
            if color == WHITE:
                fcord = tcord - 7 if ffile > FILE(tcord) else tcord - 9
            else:
                fcord = tcord + 7 if ffile < FILE(tcord) else tcord + 9
        else:
            if color == WHITE:
                pawns = board.boards[WHITE][PAWN]
                fcord = tcord - 16 if RANK(tcord) == 3 and not (
                    pawns & fileBits[FILE(tcord)] & rankBits[2]) else tcord - 8
            else:
                pawns = board.boards[BLACK][PAWN]
                fcord = tcord + 16 if RANK(tcord) == 4 and not (
                    pawns & fileBits[FILE(tcord)] & rankBits[5]) else tcord + 8
            if board.variant == SITTUYINCHESS and flag == QUEEN_PROMOTION and \
                    (pawns & fileBits[FILE(tcord)] & rankBits[RANK(tcord)]):
                return newMove(tcord, tcord, flag)
        return newMove(fcord, tcord, flag)
    else:
        if board.pieceCount[color][piece] == 1:
            # we have only one from this kind if piece, so:
            fcord = firstBit(board.boards[color][piece])
            return newMove(fcord, tcord, flag)
        else:
            # We find all pieces who could have done it. (If san was legal, there should
            # never be more than one)
            moves = genPieceMoves(board, piece, tcord)
            if len(moves) == 1:
                return moves.pop()
            else:
                for move in moves:
                    f = FCORD(move)
                    if frank is not None and frank != RANK(f):
                        continue
                    if ffile is not None and ffile != FILE(f):
                        continue
                    board_clone = board.clone(full)
                    board_clone.applyMove(move, full)
                    if board_clone.opIsChecked():
                        continue
                    return move

    errstring = "no %s is able to move to %s" % (reprPiece[piece],
                                                 reprCord[tcord])
    raise ParsingError(san, errstring, board.asFen())