Spaces:
Sleeping
Sleeping
| 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) |