Spaces:
Configuration error
Configuration error
| # stratego/memory_tracker.py | |
| from __future__ import annotations | |
| import datetime | |
| from typing import List, Dict, Any, Optional | |
| class GameMoveTracker: | |
| """ | |
| In-memory tracker of all moves (for both players). | |
| Does NOT reveal piece identities, only events like capture/bomb/flag. | |
| Produces a clean text summary suitable for LLM prompt injection. | |
| """ | |
| def __init__(self): | |
| self.turn: int = 0 | |
| self.history: List[Dict[str, Any]] = [] # global chronological history | |
| # --------------------------------------------------------- | |
| # RECORDING MOVES | |
| # --------------------------------------------------------- | |
| def record( | |
| self, | |
| player: int, | |
| move: str, | |
| event: Optional[str] = None, # "capture", "bomb", "flag", etc. | |
| extra: Optional[str] = None # captured piece? "explosion"? etc. | |
| ): | |
| """ | |
| Store one full move entry, but without revealing piece identities. | |
| """ | |
| entry = { | |
| "turn": self.turn, | |
| "player": player, | |
| "move": move, # e.g. "E4 F4" | |
| "event": event, # optional special event | |
| "extra": extra, # optional detail | |
| "timestamp": datetime.datetime.now().isoformat(timespec="seconds"), | |
| } | |
| self.history.append(entry) | |
| self.turn += 1 | |
| # --------------------------------------------------------- | |
| # ACCESSORS | |
| # --------------------------------------------------------- | |
| def get_player_moves(self, pid: int) -> List[Dict[str, Any]]: | |
| """Moves made by a specific player.""" | |
| return [h for h in self.history if h["player"] == pid] | |
| def get_opponent_moves(self, pid: int) -> List[Dict[str, Any]]: | |
| """Moves made by the opponent.""" | |
| return [h for h in self.history if h["player"] != pid] | |
| def last_move(self) -> Optional[Dict[str, Any]]: | |
| """Most recent move.""" | |
| return self.history[-1] if self.history else None | |
| # --------------------------------------------------------- | |
| # GENERATE STRING FOR PROMPT | |
| # --------------------------------------------------------- | |
| def to_prompt_string(self, player_id: int) -> str: | |
| """ | |
| Return a clean string that summarizes the match so far. | |
| Keeps ONLY the last 20 moves to avoid loops. | |
| """ | |
| if not self.history: | |
| return "No previous moves have been played.\n" | |
| # ➤ KEEP ONLY LAST 20 ENTRIES | |
| MAX_HISTORY = 20 | |
| if len(self.history) > MAX_HISTORY: | |
| # delete oldest until only 20 remain | |
| self.history = self.history[-MAX_HISTORY:] | |
| lines = ["Game History (most recent last):"] | |
| for entry in self.history: | |
| turn = entry["turn"] | |
| pid = entry["player"] | |
| move = entry["move"] | |
| event = entry["event"] | |
| extra = entry["extra"] | |
| if pid == player_id: | |
| prefix = f"Turn {turn}: You played {move}" | |
| else: | |
| prefix = f"Turn {turn}: Opponent played {move}" | |
| if event == "capture": | |
| prefix += " (capture occurred)" | |
| elif event == "bomb": | |
| prefix += " (bomb explosion)" | |
| elif event == "flag": | |
| prefix += " (FLAG CAPTURE — game-ending)" | |
| elif event == "invalid": | |
| prefix += " (invalid move?)" | |
| if extra: | |
| prefix += f" — {extra}" | |
| lines.append(prefix) | |
| return "\n".join(lines) + "\n" | |