Exemplo n.º 1
0
def analyze_position(server: Server, engine: SimpleEngine, node: GameNode, prev_score: Score, current_eval: PovScore) -> Union[Puzzle, Score]:

    board = node.board()
    winner = board.turn
    score = current_eval.pov(winner)

    if board.legal_moves.count() < 2:
        return score

    game_url = node.game().headers.get("Site")

    logger.debug("{} {} to {}".format(node.ply(), node.move.uci() if node.move else None, score))

    if prev_score > Cp(400):
        logger.debug("{} Too much of a winning position to start with {} -> {}".format(node.ply(), prev_score, score))
        return score
    if is_up_in_material(board, winner):
        logger.debug("{} already up in material {} {} {}".format(node.ply(), winner, material_count(board, winner), material_count(board, not winner)))
        return score
    elif score >= Mate(1) and not allow_one_mover:
        logger.debug("{} mate in one".format(node.ply()))
        return score
    elif score > mate_soon:
        logger.info("Mate {}#{} Probing...".format(game_url, node.ply()))
        if server.is_seen_pos(node):
            logger.info("Skip duplicate position")
            return score
        mate_solution = cook_mate(engine, copy.deepcopy(node), winner)
        server.set_seen(node.game())
        return Puzzle(node, mate_solution) if mate_solution is not None else score
    elif score >= Cp(0) and win_chances(score) > win_chances(prev_score) + 0.5:
        if score < Cp(400) and material_diff(board, winner) > -1:
            logger.info("Not clearly winning and not from being down in material, aborting")
            return score
        logger.info("Advantage {}#{} {} -> {}. Probing...".format(game_url, node.ply(), prev_score, score))
        if server.is_seen_pos(node):
            logger.info("Skip duplicate position")
            return score
        puzzle_node = copy.deepcopy(node)
        solution : Optional[List[NextMovePair]] = cook_advantage(engine, puzzle_node, winner)
        server.set_seen(node.game())
        if not solution:
            return score
        while len(solution) % 2 == 0 or not solution[-1].second:
            if not solution[-1].second:
                logger.info("Remove final only-move")
            solution = solution[:-1]
        if not solution or (len(solution) == 1 and not allow_one_mover):
            logger.info("Discard one-mover")
            return score
        last = list(puzzle_node.mainline())[len(solution)]
        gain = material_diff(last.board(), winner) - material_diff(board, winner)
        if gain > 1 or (
            len(solution) == 1 and 
            win_chances(solution[0].best.score) > win_chances(solution[0].second.score) + 0.5):
            return Puzzle(node, [p.best.move for p in solution])
        return score
    else:
        return score
Exemplo n.º 2
0
def is_valid_mate_in_one(pair: NextMovePair, engine: SimpleEngine) -> bool:
    if pair.best.score != Mate(1):
        return False
    non_mate_win_threshold = 0.6
    if not pair.second or win_chances(pair.second.score) <= non_mate_win_threshold:
        return True
    if pair.second.score == Mate(1):
        # if there's more than one mate in one, gotta look if the best non-mating move is bad enough
        logger.debug('Looking for best non-mating move...')
        info = engine.analyse(pair.node.board(), multipv = 5, limit = pair_limit)
        for score in [pv["score"].pov(pair.winner) for pv in info]:
            if score < Mate(1) and win_chances(score) > non_mate_win_threshold:
                return False
        return True
    return False
Exemplo n.º 3
0
def is_valid_mate_in_one(pair: NextMovePair, engine: YaneuraOu) -> bool:
    if pair.best.score != Mate(1):
        return False
    non_mate_win_threshold = 0.85
    if not pair.second or win_chances(
            pair.second.score) <= non_mate_win_threshold:
        return True
    return False
Exemplo n.º 4
0
def is_valid_attack(pair: NextMovePair) -> bool:
    if pair.second is None:
        return True
    if pair.best.score == Mate(1):
        return True
    if pair.best.score == Mate(2):
        return pair.second.score < Cp(500)
    if pair.best.score == Mate(3):
        return pair.second.score < Cp(300)
    if win_chances(pair.best.score) > win_chances(pair.second.score) + 0.5:
        return True
    # if best move is mate, and second move still good but doesn't win material,
    # then best move is valid attack
    if pair.best.score.is_mate() and pair.second.score < Cp(400):
        next_node = pair.node.add_variation(pair.second.move)
        return not "x" in next_node.san()
    return False
Exemplo n.º 5
0
def is_valid_attack(pair: NextMovePair, engine: SimpleEngine) -> bool:
    return (
        pair.second is None or 
        is_valid_mate_in_one(pair, engine) or 
        win_chances(pair.best.score) > win_chances(pair.second.score) + 0.7
    )
Exemplo n.º 6
0
def analyze_position(
        server: Server, engine: YaneuraOu, node: Node, prev_score: Score,
        current_eval: PovScore,
        args: argparse.Namespace) -> Tuple[Score, Optional[Puzzle]]:

    board = node.board()
    winner = board.turn
    score = current_eval.pov(winner)

    logger.debug("\nAnalyzing position, scores: {} -> {}".format(
        prev_score, score))

    if sum(1 for i in board.legal_moves) < 2:
        logger.debug("Not enough legal moves.")
        return score, None

    logger.debug("{} {} to {}".format(node.current_board.move_number,
                                      node.move() if node.move() else None,
                                      score))

    if prev_score > Cp(3000) and score < mate_soon:
        logger.debug(
            "{} Too much of a winning position to start with {} -> {}".format(
                node.current_board.move_number, prev_score, score))
        return score, None
    if is_up_in_material(board, winner) and prev_score > Cp(2200):
        logger.debug("{} already up in material {} {} {}".format(
            node.current_board.move_number, winner,
            material_count(board, winner), material_count(board, not winner)))
        return score, None
    elif score >= Mate(1) and not allow_one_mater:
        logger.debug("{} mate in one".format(node.current_board.move_number))
        return score, None
    elif score > mate_soon:
        logger.debug("Mate {}. {} Probing...".format(
            node.current_board.move_number, score))
        if server.is_seen_pos(node):
            logger.debug("Skip duplicate position")
            return score, None
        mate_solution = cook_mate(engine, copy.deepcopy(node), winner)
        server.set_seen(node)
        return score, Puzzle(node, mate_solution,
                             999999999) if mate_solution is not None else None
    elif win_chances(score) > win_chances(prev_score) + 0.40:
        if score < Cp(750) and win_chances(
                score) < win_chances(prev_score) + 0.50:
            logger.debug(
                "Not clearly winning and not equalizing enough, aborting")
            return score, None
        logger.debug("Advantage {}. {} -> {}. Probing...".format(
            node.current_board.move_number, prev_score, score))
        if server.is_seen_pos(node):
            logger.debug("Skip duplicate position")
            return score, None
        puzzle_node = copy.deepcopy(node)
        solution: Optional[List[NextMovePair]] = cook_advantage(
            engine, puzzle_node, winner)
        server.set_seen(node)
        if not solution:
            return score, None
        while len(solution) % 2 == 0 or not solution[-1].second:
            if not solution[-1].second:
                logger.debug("Remove final only-move")
            solution = solution[:-1]
        if not solution or len(solution) == 1:
            logger.debug("Discard one-mover")
            return score, None
        cp = solution[len(solution) - 1].best.score.score()
        return score, Puzzle(node, [p.best.move for p in solution],
                             999999998 if cp is None else cp)
    else:
        logger.debug("Nothing, {}, {}".format(score, win_chances(score)))
        return score, None
Exemplo n.º 7
0
def is_valid_defense(pair: NextMovePair) -> bool:
    return True
    if pair.second is None or pair.second.score == Mate(1):
        return True
    return win_chances(pair.second.score) > win_chances(pair.best.score) + 0.25
Exemplo n.º 8
0
 def is_valid_attack(self, pair: NextMovePair) -> bool:
     return (pair.second is None or self.is_valid_mate_in_one(pair)
             or win_chances(
                 pair.best.score) > win_chances(pair.second.score) + 0.7)
Exemplo n.º 9
0
    def analyze_position(self, node: ChildNode, prev_score: Score,
                         current_eval: PovScore,
                         tier: int) -> Union[Puzzle, Score]:

        board = node.board()
        winner = board.turn
        score = current_eval.pov(winner)

        if board.legal_moves.count() < 2:
            return score

        game_url = node.game().headers.get("Site")

        logger.debug("{} {} to {}".format(
            node.ply(),
            node.move.uci() if node.move else None, score))

        if prev_score > Cp(300) and score < mate_soon:
            logger.debug(
                "{} Too much of a winning position to start with {} -> {}".
                format(node.ply(), prev_score, score))
            return score
        if is_up_in_material(board, winner):
            logger.debug("{} already up in material {} {} {}".format(
                node.ply(), winner, material_count(board, winner),
                material_count(board, not winner)))
            return score
        elif score >= Mate(1) and tier < 3:
            logger.debug("{} mate in one".format(node.ply()))
            return score
        elif score > mate_soon:
            logger.debug("Mate {}#{} Probing...".format(game_url, node.ply()))
            if self.server.is_seen_pos(node):
                logger.debug("Skip duplicate position")
                return score
            mate_solution = self.cook_mate(copy.deepcopy(node), winner)
            if mate_solution is None or (tier == 1
                                         and len(mate_solution) == 3):
                return score
            return Puzzle(node, mate_solution, 999999999)
        elif score >= Cp(200) and win_chances(
                score) > win_chances(prev_score) + 0.6:
            if score < Cp(400) and material_diff(board, winner) > -1:
                logger.debug(
                    "Not clearly winning and not from being down in material, aborting"
                )
                return score
            logger.debug("Advantage {}#{} {} -> {}. Probing...".format(
                game_url, node.ply(), prev_score, score))
            if self.server.is_seen_pos(node):
                logger.debug("Skip duplicate position")
                return score
            puzzle_node = copy.deepcopy(node)
            solution: Optional[List[NextMovePair]] = self.cook_advantage(
                puzzle_node, winner)
            self.server.set_seen(node.game())
            if not solution:
                return score
            while len(solution) % 2 == 0 or not solution[-1].second:
                if not solution[-1].second:
                    logger.debug("Remove final only-move")
                solution = solution[:-1]
            if not solution or len(solution) == 1:
                logger.debug("Discard one-mover")
                return score
            if tier < 3 and len(solution) == 3:
                logger.debug("Discard two-mover")
                return score
            cp = solution[len(solution) - 1].best.score.score()
            return Puzzle(node, [p.best.move for p in solution],
                          999999998 if cp is None else cp)
        else:
            return score