game_logic.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import logging
  2. import uuid
  3. from typing import Dict, List, Optional, Any
  4. from datetime import datetime
  5. from config import get_config
  6. logger = logging.getLogger("game.logic")
  7. class GameSession:
  8. """游戏会话管理类"""
  9. def __init__(self):
  10. self.session_id = str(uuid.uuid4())
  11. self.created_at = datetime.now()
  12. self.updated_at = datetime.now()
  13. # 游戏状态
  14. self.current_figure: Optional[Dict] = None
  15. self.hints: List[str] = [] # pre-generated hints by agent
  16. self.questions_asked = 0
  17. self.hints_used = 0
  18. self.is_game_over = False
  19. self.is_correct = False
  20. self.guess_history: List[str] = []
  21. # 配置
  22. _config = get_config()
  23. self.max_questions = _config.MAX_QUESTIONS
  24. self.max_hints = _config.MAX_HINTS
  25. # 初始化游戏状态(current_figure 由 Agent 初始化时填充)
  26. self._reset_state()
  27. def _reset_state(self):
  28. """重置游戏状态(不加载事物,由 Agent 负责填充)"""
  29. self.current_figure = None
  30. self.hints = []
  31. self.questions_asked = 0
  32. self.hints_used = 0
  33. self.is_game_over = False
  34. self.is_correct = False
  35. self.guess_history = []
  36. self.updated_at = datetime.now()
  37. def ask_question(self) -> bool:
  38. """记录提问,返回是否还可以继续提问"""
  39. self.questions_asked += 1
  40. self.updated_at = datetime.now()
  41. if self.questions_asked >= self.max_questions:
  42. self.is_game_over = True
  43. return False
  44. return True
  45. def make_guess(self, guess_name: str, semantic_match_fn=None) -> Dict[str, Any]:
  46. """进行猜测,返回猜测结果"""
  47. self.updated_at = datetime.now()
  48. self.guess_history.append(guess_name)
  49. actual_name = self.current_figure["name"]
  50. # First try exact match, then fall back to semantic match via injected fn
  51. is_correct = guess_name.strip().lower() == actual_name.lower()
  52. if not is_correct and semantic_match_fn is not None:
  53. is_correct = semantic_match_fn(guess_name, actual_name)
  54. if is_correct:
  55. self.is_correct = True
  56. self.is_game_over = True
  57. return {
  58. "correct": True,
  59. "message": "恭喜你猜对了!",
  60. "figure_info": self.current_figure
  61. }
  62. else:
  63. # 检查是否达到提问上限
  64. if self.questions_asked >= self.max_questions:
  65. self.is_game_over = True
  66. return {
  67. "correct": False,
  68. "message": "游戏结束!正确答案是:{}".format(self.current_figure["name"]),
  69. "figure_info": self.current_figure
  70. }
  71. else:
  72. return {
  73. "correct": False,
  74. "message": "猜错了,请继续提问或猜测",
  75. "remaining_questions": self.max_questions - self.questions_asked
  76. }
  77. def get_hint(self) -> Optional[Dict[str, Any]]:
  78. """获取提示(从预生成的 hints 列表中按序返回)"""
  79. if self.hints_used >= self.max_hints:
  80. return {
  81. "available": False,
  82. "message": "提示次数已用完"
  83. }
  84. hint_index = self.hints_used
  85. self.hints_used += 1
  86. self.updated_at = datetime.now()
  87. hint_text = (
  88. self.hints[hint_index]
  89. if self.hints and hint_index < len(self.hints)
  90. else "这是一个广为人知的事物"
  91. )
  92. return {
  93. "available": True,
  94. "hint_level": self.hints_used,
  95. "hint": hint_text,
  96. "remaining_hints": self.max_hints - self.hints_used
  97. }
  98. def get_game_status(self) -> Dict[str, Any]:
  99. """获取当前游戏状态"""
  100. return {
  101. "session_id": self.session_id,
  102. "questions_asked": self.questions_asked,
  103. "hints_used": self.hints_used,
  104. "remaining_questions": self.max_questions - self.questions_asked,
  105. "remaining_hints": self.max_hints - self.hints_used,
  106. "is_game_over": self.is_game_over,
  107. "is_correct": self.is_correct,
  108. "guess_history": self.guess_history
  109. }
  110. def reset_game(self):
  111. """重置游戏状态(由 Agent 重新生成填充)"""
  112. self._reset_state()
  113. def get_figure_for_prompt(self) -> Dict[str, str]:
  114. """获取用于Agent提示的事物信息"""
  115. if not self.current_figure:
  116. return {}
  117. return {
  118. "name": self.current_figure.get("name", ""),
  119. "bio": self.current_figure.get("bio", ""),
  120. }
  121. class GameManager:
  122. """游戏会话管理器"""
  123. def __init__(self):
  124. self.active_sessions: Dict[str, GameSession] = {}
  125. def create_session(self) -> GameSession:
  126. """创建新游戏会话"""
  127. session = GameSession()
  128. self.active_sessions[session.session_id] = session
  129. return session
  130. def get_session(self, session_id: str) -> Optional[GameSession]:
  131. """获取游戏会话"""
  132. return self.active_sessions.get(session_id)
  133. def end_session(self, session_id: str):
  134. """结束游戏会话"""
  135. if session_id in self.active_sessions:
  136. del self.active_sessions[session_id]
  137. def cleanup_old_sessions(self, max_age_minutes: int = 60):
  138. """清理过期会话"""
  139. now = datetime.now()
  140. expired_sessions = []
  141. for session_id, session in self.active_sessions.items():
  142. if (now - session.updated_at).total_seconds() > max_age_minutes * 60:
  143. expired_sessions.append(session_id)
  144. for session_id in expired_sessions:
  145. del self.active_sessions[session_id]
  146. # 全局游戏管理器实例
  147. game_manager = GameManager()