Ejemplo n.º 1
0
 def _to_san(self):
     if self.is_oo:
         san = 'O-O'
     elif self.is_ooo:
         san = 'O-O-O'
     elif self.pc in ['P', 'p']:
         san = ''
         if self.is_capture or self.is_ep:
             san += 'abcdefgh'[file_(self.fr)] + 'x'
         san += sq_to_str(self.to)
         if self.prom:
             san += '=' + self.prom.upper()
     else:
         assert (not self.is_ep)
         san = self.pc.upper()
         ambigs = self.pos.get_from_sqs(self.pc, self.to)
         assert (len(ambigs) >= 1)
         if len(ambigs) > 1:
             r = rank(self.fr)
             f = file_(self.fr)
             # try disambiguating with file
             if len(filter(lambda sq: file_(sq) == f, ambigs)) == 1:
                 san += 'abcdefgh'[f]
             elif len(filter(lambda sq: rank(sq) == r, ambigs)) == 1:
                 san += '12345678'[r]
             else:
                 san += sq_to_str(self.fr)
         if self.is_capture:
             san += 'x'
         san += sq_to_str(self.to)
     return san
Ejemplo n.º 2
0
    def detect_check(self):
        """detect whether the player to move is out of material
        (has committed suicide) or stalemated, or if the game
        is drawn by opposite color bishops"""
        self.is_suicide = not any(pc != '-' and (
            piece_is_white(pc) if self.wtm else not piece_is_white(pc))
                                  for (sq, pc) in self)

        self.is_stalemate = not self._any_legal_moves()
        if self.is_stalemate:
            white_material = sum(piece_material[pc.lower()]
                                 for (sq, pc) in self
                                 if pc != '-' and piece_is_white(pc))
            black_material = sum(piece_material[pc.lower()]
                                 for (sq, pc) in self
                                 if pc != '-' and not piece_is_white(pc))
            self.is_stalemate_white = white_material < black_material
            self.is_stalemate_black = white_material > black_material

        self.is_draw_bishops = False
        for (sq, pc) in self:
            if pc == 'B':
                if (rank(sq) ^ file_(sq)) & 1 != 0:
                    break
            elif pc == 'b':
                if (rank(sq) ^ file_(sq)) & 1 == 0:
                    break
            elif pc != '-':
                break
        else:
            self.is_draw_bishops = True
            return

        for (sq, pc) in self:
            if pc == 'B':
                if (rank(sq) ^ file_(sq)) & 1 == 0:
                    break
            elif pc == 'b':
                if (rank(sq) ^ file_(sq)) & 1 != 0:
                    break
            elif pc != '-':
                break
        else:
            self.is_draw_bishops = True
Ejemplo n.º 3
0
    def move_from_san(self, s):
        s = self.decorator_re.sub('', s)
        mv = None

        # examples: e4 e8=Q
        m = self.san_pawn_push_re.match(s)
        if m:
            to = str_to_sq(m.group(1))
            if self.board[to] != '-':
                raise IllegalMoveError('pawn push blocked')
            prom = m.group(2)
            if prom:
                if self.wtm:
                    prom = m.group(2)
                    assert (prom == prom.upper())
                else:
                    prom = m.group(2).lower()
            new_ep = None
            if self.wtm:
                fr = to - 0x10
                if rank(to) == 3 and self.board[fr] == '-':
                    new_ep = fr
                    fr = to - 0x20
                if self.board[fr] != 'P':
                    raise IllegalMoveError('illegal white pawn move')
                if prom:
                    if rank(to) == 7:
                        mv = Move(self, fr, to, prom=prom)
                    else:
                        raise IllegalMoveError('illegal promotion')
                else:
                    mv = Move(self, fr, to, new_ep=new_ep)
            else:
                fr = to + 0x10
                if rank(to) == 4 and self.board[fr] == '-':
                    new_ep = fr
                    fr = to + 0x20
                if self.board[fr] != 'p':
                    raise IllegalMoveError('illegal black pawn move')
                if prom:
                    if rank(to) == 0:
                        mv = Move(self, fr, to, prom=prom)
                    else:
                        raise IllegalMoveError('illegal promotion')
                else:
                    mv = Move(self, fr, to, new_ep=new_ep)

        # examples: dxe4 dxe8=Q
        m = None
        if not mv:
            m = self.san_pawn_capture_re.match(s)
        if m:
            to = str_to_sq(m.group(2))
            prom = m.group(3)
            if prom:
                if self.wtm:
                    assert (prom == prom.upper())
                else:
                    prom = prom.lower()

            is_ep = to == self.ep
            if is_ep:
                assert (self.board[to] == '-')
            else:
                topc = self.board[to]
                if topc == '-' or piece_is_white(topc) == self.wtm:
                    raise IllegalMoveError('bad pawn capture')

            f = 'abcdefgh'.index(m.group(1))
            if f == file_(to) - 1:
                if self.wtm:
                    fr = to - 0x11
                    if self.board[fr] != 'P':
                        raise IllegalMoveError('bad pawn capture')
                else:
                    fr = to + 0xf
                    if self.board[fr] != 'p':
                        raise IllegalMoveError('bad pawn capture')
            elif f == file_(to) + 1:
                if self.wtm:
                    fr = to - 0xf
                    if self.board[fr] != 'P':
                        raise IllegalMoveError('bad pawn capture')
                else:
                    fr = to + 0x11
                    if self.board[fr] != 'p':
                        raise IllegalMoveError('bad pawn capture')
            else:
                raise IllegalMoveError('bad pawn capture file')

            mv = Move(self, fr, to, prom=prom, is_ep=is_ep)

        # examples: Nf3 Nxf3 Ng1xf3
        m = None
        if not mv:
            m = self.san_piece_re.match(s)
        if m:
            to = str_to_sq(m.group(5))
            if m.group(4):
                # capture
                if self.board[to] == '-':
                    raise IllegalMoveError('capture on blank square')
                if piece_is_white(self.board[to]) == self.wtm:
                    raise IllegalMoveError('capture own piece')
            else:
                if self.board[to] != '-':
                    raise IllegalMoveError('missing "x" to indicate capture')

            pc = m.group(1) if self.wtm else m.group(1).lower()
            # TODO: it would be faster to disambiguate first, so we
            # do not check whether moves are legal unnecessarily
            froms = self.get_from_sqs(pc, to)

            if m.group(2):
                if len(froms) <= 1:
                    raise IllegalMoveError('unnecessary disambiguation')
                f = 'abcdefgh'.index(m.group(2))
                froms = filter(lambda sq: file_(sq) == f, froms)

            if m.group(3):
                r = '12345678'.index(m.group(3))
                if len(froms) <= 1:
                    raise IllegalMoveError('unnecessary disambiguation')
                froms = filter(lambda sq: rank(sq) == r, froms)

            if len(froms) != 1:
                raise IllegalMoveError(
                    'illegal or ambiguous move %s: %d interpretations' %
                    (s, len(froms)))

            mv = Move(self, froms[0], to)

        # Legality checking is implicitly done above, so we don't need
        # to check it here.
        '''if mv:
            try:
                mv.check_pseudo_legal()
            except IllegalMoveError:
                raise RuntimeError('san inconsistency')
            mv.check_legal()'''

        return mv
Ejemplo n.º 4
0
def sq_to_str(sq):
    return 'abcdefgh'[file_(sq)] + '12345678'[rank(sq)]
Ejemplo n.º 5
0
 def ep_hash(self, ep):
     return self._ep[file_(ep)]
Ejemplo n.º 6
0
    def to_style12(self, user):
        """ returns a style12 string for a given user """
        # <12> rnbqkbnr pppppppp -------- -------- -------- -------- PPPPPPPP RNBQKBNR W -1 1 1 1 1 0 473 GuestPPMD GuestCWVQ -1 1 0 39 39 60000 60000 1 none (0:00.000) none 1 0 0
        board_str = ''
        for r in range(7, -1, -1):
            board_str += ' '
            for f in range(8):
                board_str += self.pos.board[0x10 * r + f]
        side_str = 'W' if self.pos.wtm else 'B'
        ep = -1 if not self.pos.ep else file_(self.pos.ep)
        w_oo = int(self.pos.check_castle_flags(True, True))
        w_ooo = int(self.pos.check_castle_flags(True, False))
        b_oo = int(self.pos.check_castle_flags(False, True))
        b_ooo = int(self.pos.check_castle_flags(False, False))
        if self.game.gtype == EXAMINED:
            flip = 0
            if user in self.game.players:
                relation = 2
            elif user in self.game.observers:
                relation = -2
            else:
                relation = -3
            white_clock = 0
            black_clock = 0
            white_name = list(self.game.players)[0].name
            black_name = list(self.game.players)[0].name
            clock_is_ticking = 0
        elif self.game.gtype == PLAYED:
            if self.game.white == user:
                relation = 1 if self.pos.wtm else -1
                flip = 0
            elif self.game.black == user:
                relation = 1 if not self.pos.wtm else -1
                flip = 1
            elif user in self.game.observers:
                relation = 0
                flip = 0
            else:
                relation = -3
                flip = 0
            if user.session.ivars['ms']:
                white_clock = int(
                    round(1000 * self.game.clock.get_white_time()))
                black_clock = int(
                    round(1000 * self.game.clock.get_black_time()))
            else:
                white_clock = int(round(self.game.clock.get_white_time()))
                black_clock = int(round(self.game.clock.get_black_time()))
            white_name = self.game.white.name
            black_name = self.game.black.name
            clock_is_ticking = int(self.game.clock.is_ticking)
        else:
            assert (False)
        if user.vars_['flip']:
            flip = 0 if flip else 1
        full_moves = self.pos.ply // 2 + 1
        last_mv = self.pos.get_last_move()
        if last_mv is None:
            last_move_time_str = time_format.hms(0.0, user)
            last_move_san = 'none'
            last_move_verbose = 'none'
            last_move_lag = 0
        else:
            assert (last_mv.time is not None)
            last_move_time_str = time_format.hms(last_mv.time, user)
            last_move_san = last_mv.to_san()
            last_move_verbose = last_mv.to_verbose_alg()
            last_move_lag = last_mv.lag

        # board_str begins with a space
        s = '\n<12>%s %s %d %d %d %d %d %d %d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d %d %d\n' % (
            board_str, side_str, ep, w_oo, w_ooo, b_oo, b_ooo,
            self.pos.fifty_count, self.game.number, white_name, black_name,
            relation, self.game.white_time, self.game.inc,
            self.pos.material[1], self.pos.material[0], white_clock,
            black_clock, full_moves, last_move_verbose, last_move_time_str,
            last_move_san, flip, clock_is_ticking, last_move_lag)

        if self.name in ['crazyhouse', 'bughouse']:
            # print <b1> lines
            s += self.get_b1()

        return s