| import chess, chess.svg, math |
| from autogen import ConversableAgent, register_function |
| from typing_extensions import Annotated |
|
|
| board = None |
| board_svgs = None |
|
|
| made_move = None |
|
|
| def get_legal_moves() -> Annotated[str, "A list of legal moves in UCI format"]: |
| return "Legal moves are: " + ",".join( |
| [str(move) for move in board.legal_moves] |
| ) + "." |
|
|
| def make_move(move: Annotated[str, "A move in UCI format."]) -> Annotated[str, "Result of the move."]: |
| move = chess.Move.from_uci(move) |
| board.push_uci(str(move)) |
|
|
| global made_move |
| made_move = True |
|
|
| board_svgs.append(chess.svg.board( |
| board, |
| arrows=[(move.from_square, move.to_square)], |
| fill={move.from_square: "gray"}, |
| size=600 |
| )) |
|
|
| piece = board.piece_at(move.to_square) |
| piece_symbol = piece.unicode_symbol() |
| piece_name = ( |
| chess.piece_name(piece.piece_type).capitalize() |
| if piece_symbol.isupper() |
| else chess.piece_name(piece.piece_type) |
| ) |
| |
| return f"Moved {piece_name} ({piece_symbol}) from "\ |
| f"{chess.SQUARE_NAMES[move.from_square]} to "\ |
| f"{chess.SQUARE_NAMES[move.to_square]}." |
|
|
| def check_made_move(msg): |
| global made_move |
| |
| if made_move: |
| made_move = False |
| return True |
| else: |
| return False |
|
|
| def get_num_turns(num_moves): |
| |
| |
| |
|
|
| num_turns = math.ceil(num_moves / 2) |
| |
| if num_moves % 2 == 0: |
| num_turns += 1 |
| |
| return num_turns |
|
|
| def initialize(): |
| global board, board_svgs, made_move |
|
|
| board = chess.Board() |
| board_svgs = [] |
| |
| made_move = False |
|
|
| def run_multi_agent(llm_white, llm_black, num_moves): |
| initialize() |
| |
| llm_config_white = {"model": llm_white} |
| llm_config_black = {"model": llm_black} |
| |
| board_proxy = ConversableAgent( |
| name="Board Proxy", |
| llm_config=False, |
| is_termination_msg=check_made_move, |
| default_auto_reply="Please make a move.", |
| human_input_mode="NEVER", |
| ) |
| |
| player_white = ConversableAgent( |
| name="Player White", |
| system_message="You are a chess Grandmaster and you play as white. " |
| "First call get_legal_moves() to get a list of legal moves. " |
| "Then study the returned moves and call make_move(move) to make the best move. " |
| "Finally analyze the move: **Analysis:** move in UCI format, emoji of piece, unordered list of 3 items.", |
| llm_config=llm_config_white, |
| ) |
| |
| player_black = ConversableAgent( |
| name="Player Black", |
| system_message="You are a chess Grandmaster and you play as black. " |
| "First call get_legal_moves() to get a list of legal moves. " |
| "Then study the returned moves and call make_move(move) to make the best move. " |
| "Finally analyze the move: **Analysis:** move in UCI format, emoji of piece, unordered list of 3 items.", |
| llm_config=llm_config_black, |
| ) |
| |
| for caller in [player_white, player_black]: |
| register_function( |
| get_legal_moves, |
| caller=caller, |
| executor=board_proxy, |
| name="get_legal_moves", |
| description="Call this tool to get legal moves.", |
| ) |
| |
| register_function( |
| make_move, |
| caller=caller, |
| executor=board_proxy, |
| name="make_move", |
| description="Call this tool to make a move.", |
| ) |
| |
| player_white.register_nested_chats( |
| trigger=player_black, |
| chat_queue=[ |
| { |
| "sender": board_proxy, |
| "recipient": player_white, |
| "summary_method": "last_msg", |
| "silent": False, |
| } |
| ], |
| ) |
| |
| player_black.register_nested_chats( |
| trigger=player_white, |
| chat_queue=[ |
| { |
| "sender": board_proxy, |
| "recipient": player_black, |
| "summary_method": "last_msg", |
| "silent": False, |
| } |
| ], |
| ) |
|
|
| chat_result = None |
| chat_history = [] |
| |
| try: |
| chat_result = player_black.initiate_chat( |
| player_white, |
| message="Let's play chess!", |
| max_turns=get_num_turns(num_moves), |
| verbose=True |
| ) |
| except Exception as e: |
| print(f"Error: {e}") |
| finally: |
| if chat_result != None: |
| chat_history = chat_result.chat_history |
| |
| result = "" |
| num_move = 0 |
|
|
| for chat in chat_history: |
| player = "" |
| |
| if num_move % 2 == 0: |
| player = "Player Black" |
| else: |
| player = "Player White" |
|
|
| if num_move > 0: |
| result += f"**{player}, Move {num_move}**\n{chat.get('content')}\n{board_svgs[num_move - 1]}\n\n" |
| |
| num_move += 1 |
|
|
| if num_moves % 2 == 0 and num_move == num_moves + 1: |
| break |
| |
| return result |