File size: 4,795 Bytes
6036825
 
 
a97f2da
 
 
 
 
 
 
 
65f55ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a97f2da
 
 
 
 
 
 
 
65f55ff
 
 
a97f2da
65f55ff
 
 
 
 
a97f2da
65f55ff
 
4235d5e
65f55ff
6036825
 
a97f2da
 
65f55ff
a97f2da
 
4235d5e
a97f2da
 
91db6aa
 
a97f2da
65f55ff
a97f2da
 
6036825
a97f2da
 
6036825
91db6aa
a97f2da
 
 
 
 
 
 
91db6aa
a97f2da
91db6aa
 
 
 
 
 
 
 
 
 
 
a97f2da
 
 
 
 
37187f8
 
 
 
 
 
 
 
91db6aa
 
37187f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91db6aa
37187f8
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import gradio as gr
import chess
import chess.svg
import os
import google.generativeai as genai

# Configure the Google Generative AI client
genai.configure(api_key=os.environ["API_KEY"])

board = chess.Board()

def describe_board_position(board):
    """
    Returns a human-readable description of the chessboard for the AI.
    Args:
        board (chess.Board): The current board position.
    Returns:
        str: A human-readable description of the chessboard.
    """
    description = []
    pieces = ['P', 'N', 'B', 'R', 'Q', 'K', 'p', 'n', 'b', 'r', 'q', 'k']
    for square in chess.SQUARES:
        piece = board.piece_at(square)
        if piece:
            piece_description = f"{'White' if piece.color == chess.WHITE else 'Black'} {piece.symbol().upper()} on {chess.square_name(square)}"
            description.append(piece_description)
    return ", ".join(description)

def get_ai_move(fen):
    """
    Gets the AI's next move using Google Gemini via google.generativeai.
    Args:
        fen (str): The current board position in FEN notation.
    Returns:
        str or None: The AI's move in UCI format, or None if an error occurs.
    """
    # Get human-readable board position
    board_description = describe_board_position(board)

    # Prepare the prompt for the AI
    prompt = f"""
You are playing a game of chess. The current board position is described below:
{board_description}

In addition, here is the board's FEN notation for precise positioning:
{fen}

It is your turn to make a move. You should provide the best legal move following the rules of chess. 
The move should be in UCI format, which represents the starting and ending squares (for example, 'e2e4'). 
Please ensure that the move is valid for the current position."""

    try:
        # Generate the response from the AI model
        response = genai.generate_text(
            model="gemini-1.5-flash",  # Use the Gemini model
            prompt=prompt,
            temperature=0,  # To make the output more deterministic
            max_output_tokens=10
        )
        ai_move = response.result.strip()
        print(f"AI move: {ai_move}")

        # Validate the move
        legal_moves = [move.uci() for move in board.legal_moves]
        if ai_move in legal_moves:
            return ai_move
        else:
            print(f"Invalid move received from the AI: {ai_move}")
            return None
    except Exception as e:
        print(f"Error occurred in get_ai_move: {e}")
        return None

def board_to_svg(board):
    return chess.svg.board(board=board)

def make_move(user_move):
    global board
    print(f"User move input: {user_move}")
    try:
        # Try UCI move first
        board.push_uci(user_move)
    except ValueError as e_uci:
        try:
            # Try SAN move
            board.push_san(user_move)
        except ValueError as e_san:
            print(f"UCI ValueError: {e_uci}, SAN ValueError: {e_san}")
            return gr.update(value=board_to_svg(board)), "Invalid move. Try again."
    except Exception as e:
        print(f"Unexpected error: {e}")
        return gr.update(value=board_to_svg(board)), "Invalid move. Try again."

    # Check for game over
    if board.is_game_over():
        result = board.result()
        board_svg = board_to_svg(board)
        return gr.update(value=board_svg), f"Game over: {result}"

    # AI's move
    ai_move = get_ai_move(board.fen())
    if ai_move:
        try:
            board.push_uci(ai_move)
        except ValueError as e:
            print(f"AI made an invalid move: {ai_move}, Error: {e}")
            return gr.update(value=board_to_svg(board)), "AI made an invalid move. Game over."
    else:
        return gr.update(value=board_to_svg(board)), "AI failed to make a move. Game over."

    # Check for game over again
    if board.is_game_over():
        result = board.result()
        board_svg = board_to_svg(board)
        return gr.update(value=board_svg), f"Game over: {result}"

    # Continue game
    return gr.update(value=board_to_svg(board)), "Your move"

def reset_game():
    global board
    board.reset()
    return gr.update(value=board_to_svg(board)), "Game reset. Your move"

with gr.Blocks() as demo:
    gr.Markdown("# Chess Game with Google Gemini AI")

    with gr.Row():
        board_output = gr.HTML(board_to_svg(board))
        move_input = gr.Textbox(label="Your Move (e.g., e2e4, e4, Nf3)")
    message_output = gr.Textbox(value="Your move", interactive=False)

    with gr.Row():
        move_button = gr.Button("Make Move")
        reset_button = gr.Button("Reset Game")

    move_button.click(make_move, inputs=move_input, outputs=[board_output, message_output])
    reset_button.click(reset_game, outputs=[board_output, message_output])

demo.launch()