chess / app.py
doctorlinux's picture
Upload 3 files
5c1db90 verified
import gradio as gr
import chess
import chess.engine
import tempfile
import os
from PIL import Image, ImageDraw
import requests
import io
# Configuración
BOARD_SIZE = 400
SQUARE_SIZE = BOARD_SIZE // 8
class ChessGame:
def __init__(self):
self.board = chess.Board()
self.selected_square = None
self.valid_moves = []
self.game_over = False
self.player_turn = True
def create_board_image(self):
"""Crear imagen del tablero con las piezas"""
# Colores
light_square = (238, 238, 210)
dark_square = (118, 150, 86)
highlight = (186, 202, 68)
# Crear imagen
img = Image.new('RGB', (BOARD_SIZE, BOARD_SIZE), color='white')
draw = ImageDraw.Draw(img)
# Dibujar tablero
for row in range(8):
for col in range(8):
color = light_square if (row + col) % 2 == 0 else dark_square
x1 = col * SQUARE_SIZE
y1 = row * SQUARE_SIZE
x2 = x1 + SQUARE_SIZE
y2 = y1 + SQUARE_SIZE
draw.rectangle([x1, y1, x2, y2], fill=color)
# Dibujar piezas (usaremos emojis como texto)
piece_chars = {
'r': '♜', 'n': '♞', 'b': '♝', 'q': '♛', 'k': '♚', 'p': '♟',
'R': '♖', 'N': '♘', 'B': '♗', 'Q': '♕', 'K': '♔', 'P': '♙'
}
for square in chess.SQUARES:
piece = self.board.piece_at(square)
if piece:
col = chess.square_file(square)
row = 7 - chess.square_rank(square)
x = col * SQUARE_SIZE + SQUARE_SIZE // 2
y = row * SQUARE_SIZE + SQUARE_SIZE // 2
# Usar emoji para la pieza
piece_char = piece_chars[piece.symbol()]
draw.text((x-10, y-15), piece_char, fill='black', font_size=30)
return img
def get_move_suggestion(self):
"""Obtener sugerencia de Stockfish usando API"""
try:
# Usar API de stockfish.js como fallback
fen = self.board.fen()
url = f"https://stockfish.online/api/s/v2.php?fen={fen}&depth=10"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
if 'bestmove' in data:
return data['bestmove']
except:
pass
# Fallback: elegir el primer movimiento legal
legal_moves = list(self.board.legal_moves)
return str(legal_moves[0]) if legal_moves else None
def make_move(self, move_uci):
"""Realizar movimiento"""
try:
move = chess.Move.from_uci(move_uci)
if move in self.board.legal_moves:
self.board.push(move)
self.player_turn = False
return True
except:
pass
return False
def ai_move(self):
"""Movimiento de la IA"""
if not self.player_turn and not self.board.is_game_over():
best_move = self.get_move_suggestion()
if best_move:
self.board.push(chess.Move.from_uci(best_move))
self.player_turn = True
def get_game_status(self):
"""Obtener estado del juego"""
if self.board.is_checkmate():
return "¡Jaque mate! " + ("Ganaste" if self.player_turn else "Stockfish gana")
elif self.board.is_stalemate():
return "Tablas por ahogado"
elif self.board.is_insufficient_material():
return "Tablas por material insuficiente"
elif self.board.is_check():
return "¡Jaque!"
else:
return "Tu turno" if self.player_turn else "Pensando..."
# Instancia global del juego
game = ChessGame()
def update_interface():
"""Actualizar la interfaz completa"""
board_img = game.create_board_image()
status = game.get_game_status()
# Generar lista de movimientos legales
legal_moves = [str(move) for move in game.board.legal_moves]
return board_img, status, "\n".join(legal_moves[:10]) # Mostrar primeros 10 movimientos
def handle_move(move_input):
"""Manejar movimiento del jugador"""
if game.player_turn and not game.board.is_game_over():
if game.make_move(move_input):
# Movimiento de la IA después de un breve delay
game.ai_move()
return update_interface()
def handle_suggestion():
"""Obtener sugerencia de movimiento"""
if game.player_turn:
suggestion = game.get_move_suggestion()
return suggestion if suggestion else "No hay sugerencias disponibles"
return "Es el turno de Stockfish"
def reset_game():
"""Reiniciar juego"""
global game
game = ChessGame()
return update_interface()
# Crear interfaz Gradio
with gr.Blocks(theme=gr.themes.Soft(), title="Ajedrez con Stockfish") as demo:
gr.Markdown("""
# ♟️ Ajedrez con Stockfish
Juega contra Stockfish, uno de los motores de ajedrez más fuertes del mundo.
""")
with gr.Row():
with gr.Column():
board_image = gr.Image(label="Tablero", interactive=False)
status_text = gr.Textbox(label="Estado del Juego", interactive=False)
with gr.Column():
move_input = gr.Textbox(
label="Ingresa tu movimiento (ej: e2e4)",
placeholder="Formato: casilla_origen casilla_destino"
)
with gr.Row():
submit_btn = gr.Button("Realizar Movimiento", variant="primary")
suggest_btn = gr.Button("Sugerencia")
reset_btn = gr.Button("Nuevo Juego")
suggestion_text = gr.Textbox(label="Sugerencia de Stockfish", interactive=False)
legal_moves_text = gr.Textbox(
label="Movimientos Legales (primeros 10)",
lines=10,
interactive=False
)
# Conexiones de eventos
submit_btn.click(
fn=handle_move,
inputs=move_input,
outputs=[board_image, status_text, legal_moves_text]
)
suggest_btn.click(
fn=handle_suggestion,
outputs=suggestion_text
)
reset_btn.click(
fn=reset_game,
outputs=[board_image, status_text, legal_moves_text]
)
# Inicializar interfaz
demo.load(
fn=update_interface,
outputs=[board_image, status_text, legal_moves_text]
)
# Para Hugging Face Spaces
if __name__ == "__main__":
demo.launch(share=True)