Forkei's picture
Upload folder using huggingface_hub
52a4f3c verified
#!/usr/bin/env python
"""
Play chess against the Chess Master agent.
A full interactive CLI game with the complete trigger system,
personality, and memory integration.
"""
import asyncio
import traceback
from datetime import datetime
from typing import Optional
from agent.main_agent import ChessMaster
from agent.subconscious import Subconscious
from agent.scheduler import MatchScheduler, TriggerPoint
from db.database import get_db_manager, get_or_create_player
from chess_engine import ChessGame, choose_move
async def display_board(scheduler: MatchScheduler) -> None:
"""Display the chess board with context."""
game = scheduler.chess_game
print("\n" + "=" * 70)
print(game.get_ascii_board())
print("=" * 70)
status = game.get_game_status()
if status["is_checkmate"]:
winner = "White" if status["is_check"] else "Black"
print(f"♞ CHECKMATE! {winner} wins!")
elif status["is_stalemate"]:
print("♞ STALEMATE! Draw!")
elif status["is_check"]:
print(f"♞ CHECK! {game.get_current_player()} is in check!")
print(f"Move count: {status['moves_count']} | Phase: {game.get_game_phase()}")
print()
def show_legal_moves(scheduler: MatchScheduler) -> None:
"""Show available moves."""
moves = scheduler.chess_game.get_legal_moves()
print(f"Legal moves ({len(moves)}): {', '.join(moves[:15])}", end="")
if len(moves) > 15:
print(f", ... (+{len(moves) - 15} more)", end="")
print("\n")
def show_help() -> None:
"""Show command help."""
print("""
Commands:
<move> - Make a move (e.g., e4, Nf3, O-O for castling)
resign - Resign the game
draw - Offer a draw
board - Show the board again
moves - Show all legal moves
history - Show move history
help - Show this help
quit - Exit
""")
async def get_player_move(scheduler: MatchScheduler, player_name: str) -> Optional[str]:
"""Get and validate a player move."""
while True:
try:
move_input = input(f"\n{player_name}'s move (or 'help'): ").strip()
if not move_input:
print("Please enter a move or command")
continue
move_lower = move_input.lower()
# Commands
if move_lower == "help":
show_help()
continue
elif move_lower == "board":
await display_board(scheduler)
continue
elif move_lower == "moves":
show_legal_moves(scheduler)
continue
elif move_lower == "history":
history = scheduler.chess_game.get_move_history()
if history:
moves_str = " ".join([m["move_san"] for m in history])
print(f"Move history: {moves_str}\n")
else:
print("No moves yet.\n")
continue
elif move_lower in ["resign", "draw"]:
return move_lower
elif move_lower == "quit":
return "quit"
# Try to make the move
success, error = scheduler.chess_game.make_move(move_input)
if success:
return move_input
else:
print(f"❌ {error}")
print("Try 'moves' to see legal moves.")
continue
except KeyboardInterrupt:
return "quit"
except Exception as e:
print(f"Error: {e}")
continue
async def make_agent_move(scheduler: MatchScheduler) -> bool:
"""Make agent's move with trigger system."""
game = scheduler.chess_game
if not game.get_legal_moves_uci():
return False
response = await scheduler.trigger(TriggerPoint.BEFORE_AGENT_MOVE)
if response and response.get("action") == "send_message":
print(f"\n🎭 Chess Master: {response.get('content')}")
if response.get("tone"):
print(f" (tone: {response.get('tone')})")
mv = choose_move(game.board, depth=2)
if mv is None:
return False
san = game.board.san(mv) # compute before pushing
result = scheduler.make_agent_move(mv.uci())
if result["success"]:
print(f"\n♘ Chess Master played: {san}")
return True
return False
async def play_game() -> None:
"""Main game loop."""
print("\n" + "=" * 70)
print("♟️ METROPOLIS CHESS CLUB ♟️")
print(" Play Against the Chess Master")
print("=" * 70)
# Get player info
player_name = input("\nWhat's your name? ").strip()
if not player_name:
player_name = "Player"
print(f"\nWelcome, {player_name}!")
# Initialize database
db = get_db_manager()
db.initialize()
player = get_or_create_player(player_name, player_name)
print(f"Games played: {player.total_games} | Wins: {player.wins_against_agent}")
# Initialize agents
print("\n🔄 Initializing Chess Master...", end="", flush=True)
chess_master = ChessMaster()
subconscious = Subconscious()
print(" Ready!")
# Create match
match_id = f"match-{datetime.now().timestamp()}"
scheduler = MatchScheduler(
match_id=match_id,
player_id=player.player_id,
main_agent=chess_master,
subconscious_agent=subconscious,
player_name=player_name,
agent_name="Chess Master",
)
# Start match
scheduler.start_match()
# Before match trigger
print("\n🎭 Triggering before_match...\n")
response = await scheduler.trigger(TriggerPoint.BEFORE_MATCH)
if response and response.get("action") == "send_message":
print(f"Chess Master: {response.get('content')}")
if response.get("tone"):
print(f"(tone: {response.get('tone')})")
show_help()
# Game loop
while not scheduler.chess_game.is_game_over():
await display_board(scheduler)
show_legal_moves(scheduler)
# Get player move
player_move = await get_player_move(scheduler, player_name)
if player_move == "quit":
print("\nGame abandoned.")
return
elif player_move == "resign":
result = scheduler.resign_player()
print(f"\n{player_name} resigned.")
print(f"Result: {result.get('result')}")
break
elif player_move == "draw":
result = scheduler.offer_draw()
print(f"\nDraw accepted.")
print(f"Result: {result.get('result')}")
break
# Trigger on_user_move
response = await scheduler.trigger(
TriggerPoint.ON_USER_MOVE,
{"move": player_move}
)
if response and response.get("action") == "send_message":
print(f"\n🎭 Chess Master: {response.get('content')}")
if response.get("tone"):
print(f" (tone: {response.get('tone')})")
if scheduler.chess_game.is_game_over():
break
# Agent move
await make_agent_move(scheduler)
if scheduler.chess_game.is_game_over():
break
# Game over
await display_board(scheduler)
game_result = scheduler.chess_game.get_game_result()
if game_result:
if game_result == "1-0":
print("🎉 White wins!")
elif game_result == "0-1":
print("🎉 Black wins!")
else:
print("🤝 Draw!")
# After match — fires AFTER_MATCH trigger and records outcome to DB
print("\n🎭 Triggering after_match...\n")
response = await scheduler.end_match()
if response and response.get("action") == "send_message":
print(f"Chess Master: {response.get('content')}")
if response.get("tone"):
print(f"(tone: {response.get('tone')})")
# Show stats
stats = scheduler.get_stats()
print("\n" + "=" * 70)
print("MATCH STATS")
print("=" * 70)
print(f"Match ID: {stats['match_id']}")
print(f"Duration: {stats['duration_seconds']:.1f}s")
print(f"Moves: {stats['moves_count']}")
print(f"Messages: {stats['conversation_count']}")
print(f"Triggers: {stats['trigger_count']}")
print("=" * 70 + "\n")
async def main():
"""Entry point."""
try:
await play_game()
except KeyboardInterrupt:
print("\n\nGame interrupted.")
except Exception as e:
print(f"\nError: {e}")
traceback.print_exc()
if __name__ == "__main__":
asyncio.run(main())