def from_x88(cls, source, target, promotion=''): if not cls._x88_moves: raise ValueError # try to use the cache if not promotion: return cls._x88_moves[(source, target)] return Move(Square.from_x88(source), Square.from_x88(target), promotion)
def get_all(cls): '''Yield all moves combinations that do not have promotion.''' #FIXME add in promotion for source in Square.get_all(): for target in Square.get_all(): if source != target: move = cls(Square.from_x88(source.x88), Square.from_x88(target.x88)) yield(move)
def ep_square(self): '''The possible en passant square if available. http://en.wikipedia.org/wiki/En_passant ''' if not self._ep: return self.null return Square.from_x88(self._ep)
def get_pseudo_legal_moves(self, source=None): """:yield: Pseudo legal moves in the current position. :param source: The source square to limit moves or None for all possible moves. """ tomove = self.fen._to_move for x88 in [ x88 for x88 in Square._x88_squares.keys() if self._pieces[x88] and Piece.color(self._pieces[x88]) == tomove and (source is None or x88 == source._x88) ]: piece = self._pieces[x88] klass = Piece.klass(piece) # pawn moves if klass == PAWN: single, double, capleft, capright = X88.PAWN_OFFSETS[tomove] # Single square ahead. Do not capture. offset = x88 + single if not self._pieces[offset]: # Promotion. if X88.is_backrank(offset, tomove): for promote_to in Piece.promote_to: yield Move.from_x88(x88, offset, promote_to) else: yield Move.from_x88(x88, offset) # Two squares ahead. Do not capture. if X88.is_secondrank(x88, tomove): offset = x88 + double if not self._pieces[offset]: yield Move.from_x88(x88, offset) # Pawn captures. for cap in [capleft, capright]: offset = x88 + cap if offset & X88.X88: continue target = self._pieces[offset] if target and Piece.color(target) != tomove: # Promotion. if X88.is_backrank(offset, tomove): for promote_to in Piece.promote_to: yield Move.from_x88(x88, offset, promote_to) else: yield Move.from_x88(x88, offset) # En-passant. elif not target and offset == self.fen._ep: yield Move.from_x88(target, self.fen._ep) #piece moves else: # for each a direction a piece moves in for offset in X88.PIECE_OFFSETS[Piece.klass(piece)]: t_x88 = x88 + offset # while we do not fall off the board while not t_x88 & 0x88: # if there was not piece to attack then yield a quiet move if not self._pieces[t_x88]: yield Move.from_x88(x88, t_x88) # do not break out # else there is a piece there else: # if we can attack generate a move if Piece.color(self._pieces[t_x88]) != tomove: yield Move.from_x88(x88, t_x88) # we hit something so break out break # Knight and king do not go multiple times in their direction. if klass in [KNIGHT, KING]: break # travel down the board in the direction t_x88 += offset # castling moves opponent = Piece.opposite_color(tomove) ok = True # get possible castling for the side to move for castle in [ c for c in self.fen._castle_rights if Piece.color(c) == tomove ]: (square, enum), _ = Piece.castle_squares[castle] king = Square(square) if Piece.klass(castle) == KING: direc = 1 else: direc = -1 # for offset in the squares the king will travel for offset in range(0, 3): s = Square.from_x88(king._x88 + (offset * direc)) # if we are not the king square and we are occuppied if offset and self._pieces[s._x88]: ok = False break # if we are trying to travel through check if self.is_attacked(opponent, s): ok = False break # kludge: we have to check occupancy for one more square on the queen side if direc == -1 and self._pieces[s._x88 - 1]: ok = False if ok: yield Move(king, s)
def target(self): """The target square.""" return Square.from_x88(self._target_x88)
def source(self): """The source square.""" return Square.from_x88(self._source_x88)
def get_pseudo_legal_moves(self, source=None): """:yield: Pseudo legal moves in the current position. :param source: The source square to limit moves or None for all possible moves. """ tomove = self.fen._to_move for x88 in [ x88 for x88 in Square._x88_squares.keys() if self._pieces[x88] and Piece.color(self._pieces[x88]) == tomove and (source is None or x88 == source._x88)]: piece = self._pieces[x88] klass = Piece.klass(piece) # pawn moves if klass == PAWN: single, double, capleft, capright = X88.PAWN_OFFSETS[tomove] # Single square ahead. Do not capture. offset = x88 + single if not self._pieces[offset]: # Promotion. if X88.is_backrank(offset, tomove): for promote_to in Piece.promote_to: yield Move.from_x88(x88, offset, promote_to) else: yield Move.from_x88(x88, offset) # Two squares ahead. Do not capture. if X88.is_secondrank(x88, tomove): offset = x88 + double if not self._pieces[offset]: yield Move.from_x88(x88, offset) # Pawn captures. for cap in [capleft, capright]: offset = x88 + cap if offset & X88.X88: continue target = self._pieces[offset] if target and Piece.color(target) != tomove: # Promotion. if X88.is_backrank(offset, tomove): for promote_to in Piece.promote_to: yield Move.from_x88(x88, offset, promote_to) else: yield Move.from_x88(x88, offset) # En-passant. elif not target and offset == self.fen._ep: yield Move.from_x88(target, self.fen._ep) #piece moves else: # for each a direction a piece moves in for offset in X88.PIECE_OFFSETS[Piece.klass(piece)]: t_x88 = x88 + offset # while we do not fall off the board while not t_x88 & 0x88: # if there was not piece to attack then yield a quiet move if not self._pieces[t_x88]: yield Move.from_x88(x88, t_x88) # do not break out # else there is a piece there else: # if we can attack generate a move if Piece.color(self._pieces[t_x88]) != tomove: yield Move.from_x88(x88, t_x88) # we hit something so break out break # Knight and king do not go multiple times in their direction. if klass in [KNIGHT, KING]: break # travel down the board in the direction t_x88 += offset # castling moves opponent = Piece.opposite_color(tomove) ok = True # get possible castling for the side to move for castle in [c for c in self.fen._castle_rights if Piece.color(c) == tomove]: (square, enum), _ = Piece.castle_squares[castle] king = Square(square) if Piece.klass(castle) == KING: direc = 1 else: direc = -1 # for offset in the squares the king will travel for offset in range(0, 3): s = Square.from_x88(king._x88 + (offset * direc)) # if we are not the king square and we are occuppied if offset and self._pieces[s._x88]: ok = False break # if we are trying to travel through check if self.is_attacked(opponent, s): ok = False break # kludge: we have to check occupancy for one more square on the queen side if direc == -1 and self._pieces[s._x88 - 1]: ok = False if ok: yield Move(king, s)
def test_from_x88(self): square = Square.from_x88(0) self.assertEqual('a1', str(square))