Exemple #1
0
def get_attackers(board, square, color):
    retval = []
    for name, pos in chess.Pieces(board, color):
        if chess.LUT.att[name][pos][square] and \
                (chess.LUT.btw[pos][square] & board.interferers).is_zero():
            retval.append((name, pos))
    return retval
Exemple #2
0
def check(problem, board, solution):
    visitor = FinalesVisitor()
    solution.traverse(board, visitor)
    if len(visitor.by_hash) > 0:
        problem['pure-finales'] = [key for key in visitor.by_hash]
    retval = {}
    for keyword in provides():
        retval[keyword] = False

    mm, msm, im, ism = 0, 0, 0, 0
    for dif in visitor.different:
        mm_, msm_, im_, ism_ = 0, 0, 0, 0
        for info in visitor.different[dif]:
            if info['model'] and info['stale']:
                msm_ = 1
            if info['model'] and not info['stale']:
                mm_ = 1
            if info['ideal'] and info['stale']:
                ism_ = 1
            if info['ideal'] and not info['stale']:
                im_ = 1
            if info['octet']:
                retval['Octet'] = True
            if info['pins'] > 0:
                retval['Models with pin'] = True
            if info['pins'] > 1:
                retval['Models with two pins'] = True
            if info['pins'] > 2:
                retval['Models with three pins'] = True
        mm, msm, im, ism = mm + mm_, msm + msm_, im + im_, ism + ism_
    retval['Model mates'], retval['Model stalemates'], retval[
        'Ideal mates'], retval[
            'Ideal satelemates'] = mm > 1, msm > 1, im > 1, ism > 1

    if retval['Model mates']:
        octet = ''
        for piece, pos in chess.Pieces(board, chess.WHITE):
            if piece in 'QRSB':
                octet = octet + piece
        retval['Octet'] = ''.join(sorted(octet)) == 'BBQRRSS'

    # now echoes
    for hash in visitor.by_hash:
        if len(visitor.by_hash[hash]) < 2:
            continue
        for info1, info2 in common.tuples(visitor.by_hash[hash], 2, False):
            if info1['mated'] != info2['mated'] or info1['traversal'] != info2[
                    'traversal']:
                retval['Echo'] = True
            if square_color(info1['mated']) != square_color(info2['mated']):
                retval['Chameleon echo'] = True

    return retval
Exemple #3
0
def _analyze(board, mated):
    retval = {
        'ideal': False,
        'model': False,
        'pure': False,
        'hash': 0,
        'traversal': -1,
        'mated': board.kings[mated],
        'octet': False,
        'pins': 0
    }

    mating = [chess.WHITE, chess.BLACK][mated == chess.WHITE]
    mated_king = 'kK'[mated == chess.WHITE]
    participants, attackers = chess.BitBoard(), {}

    king_area = chess.BitBoard(
        chess.LUT.att[mated_king][board.kings[mated]].v[0],
        chess.LUT.att[mated_king][board.kings[mated]].v[1])
    king_area[board.kings[mated]] = 1

    for square in chess.SetBits(king_area):
        attackers[square] = get_attackers(board, square, mating)
        if len(attackers[square]) > 1:
            return retval
        if len(attackers[square]) == 1:
            participants[attackers[square][0][1]] = 1
        if square == board.kings[mated]:
            continue
        blocker = board.board[square][chess.NAME]
        if (blocker == '') or chess.Board.is_of(blocker, mating):
            continue
        participants[square] = 1
        # both blocked & once attacked => need to check pinning
        if (len(attackers[square]) == 1):
            if not chess.LUT.btw[attackers[square][0][1]][
                    board.kings[mated]][square]:
                return retval
            # checking that mate exploits pinning - black must have legal moves
            # if pinner is removed
            # nice bug: bk is transparent!
            board.interferers[board.kings[mated]] = 1
            id = board.board[attackers[square][0][1]][chess.ID]
            board.drop(attackers[square][0][1])
            if not board.has_legal_moves(mated):
                board.add(attackers[square][0][0], attackers[square][0][1], id)
                board.interferers[board.kings[mated]] = 0
                return retval
            board.interferers[board.kings[mated]] = 0
            board.add(attackers[square][0][0], attackers[square][0][1], id)
            retval['pins'] = retval['pins'] + 1

    retval['model'], retval['pure'] = True, True
    for name, pos in chess.Pieces(board, mating):
        if (not name in ['pk', 'PK'
                         ][mating == chess.WHITE]) and (not participants[pos]):
            retval['model'] = False
            break
    retval['ideal'] = retval['model'] and (participants == board.interferers)

    # checking unit has id = 0
    init_id_map, retval['hash'] = {}, 999999999999
    if len(attackers[board.kings[mated]]) > 0:
        init_id_map[attackers[board.kings[mated]][0][1]] = 0  # checking unit
    # id of other participants depend on traversal
    for i in xrange(len(traversals)):
        # if i <> 2: continue
        id_map, hash, pinmask, next_id = copy.deepcopy(init_id_map), 0, 0, 1
        for j in xrange(len(traversals[i])):
            participant_id = -1
            square = add(board.kings[mated], traversals[i][j])
            if -1 == square:  # board edge
                id_map, participant_id, next_id = inc_id(id_map, -1, next_id)
            elif board.board[square][chess.NAME] != '' and \
                    chess.Board.is_of(board.board[square][chess.NAME], mated):  # blocked
                # blockers have same id as board edge
                id_map, participant_id, next_id = inc_id(id_map, -1, next_id)
                if len(attackers[square]) > 0:  # additionally pinned
                    pinmask = pinmask | (1 << j)
            else:  # the square is once attacked
                id_map, participant_id, next_id = inc_id(
                    id_map, attackers[square][0][1], next_id)
            hash = (hash << 3) + participant_id
        hash = hash | (pinmask << 24)
        if int(hash) < int(retval['hash']):
            retval['hash'] = hash
            retval['traversal'] = i
    if retval['hash'] == 2739136:
        retval['hash'] = 0
    return retval