Adaptive Stockfish

Tom 7’s 30 Weird Chess Algorithms: Elo World inspired me to implment what I’m calling Adaptive Stockfish. It’s a chess algorithm that tries to match its current advantage with a given target. With a target of 0, it tries to play as well as its opponent. No better, no worse. Tuned up to +100 and it tries to get a little leg up on you, but doesn’t get carried away.

Code

#!/usr/bin/env python3
import argparse
import chess
import chess.engine
import chess.pgn


STOCKFISH_ENGINE = "/usr/games/stockfish"
MULTIPV_MAX = 500  # Capped by Stockfish's ucioption.cpp
SCORE_THRESHOLD = 5000  # To convert mates to centi-pawns


def get_adaptive_stockfish_move(board, engine, time_limit, target):
    return min(
        engine.analyse(board, limit=time_limit, multipv=MULTIPV_MAX),
        key=lambda move: abs(move["score"].relative.score(mate_score=SCORE_THRESHOLD) - target),
    )


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("white", type=int, help="In centi-pawns")
    parser.add_argument("black", type=int, help="In centi-pawns")
    parser.add_argument("--time-limit", type=float, default=3)
    args = parser.parse_args()

    try:
        board = chess.Board()
        engine = chess.engine.SimpleEngine.popen_uci(STOCKFISH_ENGINE)
        time_limit = chess.engine.Limit(time=args.time_limit)
        while board.legal_moves:
            target = args.white if board.turn == chess.WHITE else args.black
            move = get_adaptive_stockfish_move(board, engine, time_limit, target)
            board.push(move["pv"][0])
            print(f"{move['pv'][0]} {move['score']}")
    finally:
        engine.quit()
        game = chess.pgn.Game.from_board(board)
        game.headers["White"] = f"Adaptive Stockfish ({args.white:+d})"
        game.headers["Black"] = f"Adaptive Stockfish ({args.black:+d})"
        print(game)

Edit: Updated to allow it to be capable of winning. The previous code considered a mating move to be so good that it would avoid it at all costs.

Example games

Notes