Spaces:
Sleeping
Sleeping
File size: 8,240 Bytes
100a6dd |
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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# chess_engine/api/cli.py
import chess
import argparse
import sys
import os
from typing import Optional, Dict, Any
import time
from chess_engine.api.game_controller import GameController, GameOptions
from chess_engine.ai.stockfish_wrapper import DifficultyLevel
class ChessCLI:
"""Command-line interface for chess engine"""
def __init__(self):
self.controller = None
self.options = None
def setup_game(self, args):
"""Setup game with command line arguments"""
# Parse color
player_color = chess.WHITE
if args.color and args.color.lower() == 'black':
player_color = chess.BLACK
# Parse difficulty
difficulty_map = {
'beginner': DifficultyLevel.BEGINNER,
'easy': DifficultyLevel.EASY,
'medium': DifficultyLevel.MEDIUM,
'hard': DifficultyLevel.HARD,
'expert': DifficultyLevel.EXPERT,
'master': DifficultyLevel.MASTER
}
difficulty = difficulty_map.get(args.difficulty.lower(), DifficultyLevel.MEDIUM)
# Create options
self.options = GameOptions(
player_color=player_color,
difficulty=difficulty,
time_limit=args.time,
use_opening_book=not args.no_book,
enable_analysis=not args.no_analysis,
stockfish_path=args.stockfish_path
)
# Create controller
self.controller = GameController(self.options)
def print_board(self, unicode: bool = True):
"""Print chess board to console"""
board = self.controller.board.board
# Get board as string
if unicode:
board_str = str(board)
else:
board_str = board.unicode()
print("\n" + board_str + "\n")
# Print whose turn it is
turn = "White" if board.turn == chess.WHITE else "Black"
print(f"{turn} to move")
# Print check status
if board.is_check():
print("CHECK!")
def print_analysis(self, analysis: Dict[str, Any]):
"""Print position analysis"""
if not analysis:
return
eval_data = analysis.get("evaluation", {})
best_moves = analysis.get("best_moves", [])
print("\nPosition Analysis:")
print(f"Evaluation: {eval_data.get('total', 0):.2f} pawns")
print(f"Stockfish: {eval_data.get('stockfish', 0):.2f} pawns")
if best_moves:
print("\nBest moves:")
for i, (move, eval_score) in enumerate(best_moves[:3], 1):
print(f"{i}. {move} ({eval_score:.2f})")
def run(self):
"""Run the CLI game loop"""
# Start new game
result = self.controller.start_new_game()
if result["status"] == "error":
print(f"Error: {result['message']}")
return
print("Chess game started!")
print("Enter moves in UCI notation (e.g., 'e2e4') or SAN (e.g., 'e4')")
print("Commands: 'quit', 'help', 'hint', 'undo', 'board', 'resign'")
self.print_board()
# Game loop
while True:
# Get user input
try:
user_input = input("\nYour move: ").strip()
except (KeyboardInterrupt, EOFError):
print("\nGame terminated.")
break
# Process commands
if user_input.lower() in ('quit', 'exit', 'q'):
print("Game terminated.")
break
elif user_input.lower() == 'help':
print("\nCommands:")
print(" <move> - Make a move (e.g., 'e2e4' or 'e4')")
print(" board - Display the board")
print(" hint - Get a move suggestion")
print(" undo - Undo last move")
print(" resign - Resign the game")
print(" quit - Exit the game")
continue
elif user_input.lower() == 'board':
self.print_board()
continue
elif user_input.lower() == 'hint':
hint_result = self.controller.get_hint()
if hint_result["status"] == "success":
print(f"\nHint: {hint_result['hint']}")
print(f"Explanation: {hint_result['explanation']}")
else:
print(f"Error: {hint_result['message']}")
continue
elif user_input.lower() == 'undo':
undo_result = self.controller.undo_move()
if undo_result["status"] in ("success", "partial"):
print("Move undone.")
self.print_board()
else:
print(f"Error: {undo_result['message']}")
continue
elif user_input.lower() == 'resign':
resign_result = self.controller.resign()
print("You resigned. Game over.")
break
# Process move
move_result = self.controller.make_player_move(user_input)
if move_result["status"] == "error":
print(f"Error: {move_result['message']}")
continue
# Print board after move
self.print_board()
# Print AI's move
if "ai_move" in move_result and move_result["ai_move"]:
print(f"AI plays: {move_result['ai_move']}")
# Print analysis if available
if "analysis" in move_result and move_result["analysis"]:
self.print_analysis(move_result["analysis"])
# Check if game is over
if move_result["status"] == "game_over":
result = move_result["result"]
reason = move_result["reason"]
print("\nGame over!")
if result == "draw":
print(f"Result: Draw ({reason})")
else:
winner = move_result["winner"].capitalize()
print(f"Result: {winner} wins by {reason}")
break
# Clean up
if self.controller:
self.controller.close()
def main(args=None):
"""
Main entry point for CLI
Args:
args: Command-line arguments (optional, parsed from sys.argv if None)
"""
if args is None:
# Parse arguments only if not provided
parser = argparse.ArgumentParser(description="Chess Engine CLI")
parser.add_argument("--color", "-c", choices=["white", "black"], default="white",
help="Player's color (default: white)")
parser.add_argument("--difficulty", "-d",
choices=["beginner", "easy", "medium", "hard", "expert", "master"],
default="medium", help="AI difficulty level (default: medium)")
parser.add_argument("--time", "-t", type=float, default=1.0,
help="Time limit for AI moves in seconds (default: 1.0)")
parser.add_argument("--stockfish-path", "-s", type=str, default=None,
help="Path to Stockfish executable")
parser.add_argument("--no-book", action="store_true",
help="Disable opening book")
parser.add_argument("--no-analysis", action="store_true",
help="Disable position analysis")
args = parser.parse_args()
cli = ChessCLI()
cli.setup_game(args)
cli.run()
if __name__ == "__main__":
main() |