diff --git a/.github/instructions/AI_REFACTOR_PLAN.md b/.github/instructions/AI_REFACTOR_PLAN.md new file mode 100644 index 0000000000000000000000000000000000000000..3292bc8376ca4a5f4b8309c331d55709c334a778 --- /dev/null +++ b/.github/instructions/AI_REFACTOR_PLAN.md @@ -0,0 +1,849 @@ +# 🔄 AI System Refactoring Plan + +## תוכנית ריפקטור מערכת ה-AI + +**תאריך:** January 2026 +**סטטוס:** 📋 Planning +**גרסה:** 1.0 + +--- + +## 📋 תוכן עניינים + +1. [סקירת המצב הנוכחי](#-סקירת-המצב-הנוכחי) +2. [הבעיות שצריך לפתור](#-הבעיות-שצריך-לפתור) +3. [הארכיטקטורה החדשה](#-הארכיטקטורה-החדשה) +4. [פירוט הרכיבים](#-פירוט-הרכיבים) +5. [תוכנית מימוש](#-תוכנית-מימוש) +6. [מיגרציה והגירה](#-מיגרציה-והגירה) +7. [בדיקות](#-בדיקות) + +--- + +## 🔴 סקירת המצב הנוכחי + +### מבנה קיים + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ המצב הנוכחי (בלאגן) │ +├─────────────────────────────────────────────────────────────────────┤ +│ │ +│ GameManager │ +│ │ │ +│ ▼ saves state to file │ +│ current_state.json │ +│ │ │ +│ ▼ watches file changes │ +│ play_with_prompts.py (background thread) │ +│ │ │ +│ ▼ calls │ +│ generate_prompts_from_state.py │ +│ │ │ +│ ├──► generate_what_happened_message() (guesses from state!) │ +│ │ │ +│ ▼ saves │ +│ prompt_N.json files │ +│ │ │ +│ ▼ watches files │ +│ test_ai_live.py │ +│ │ │ +│ ▼ sends to │ +│ LLM (Gemini) │ +│ │ │ +│ ▼ ??? │ +│ How do responses get back to game? ← 🚨 BROKEN │ +│ │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +### קבצים קיימים + +| קובץ | מיקום | תפקיד | +|------|-------|-------| +| `prompt_manager.py` | `pycatan/ai/` | יצירת פרומפטים | +| `llm_client.py` | `pycatan/ai/` | תקשורת עם Gemini | +| `state_filter.py` | `pycatan/ai/` | סינון state לשחקן | +| `prompt_templates.py` | `pycatan/ai/` | תבניות ו-schemas | +| `config.py` | `pycatan/ai/` | קונפיגורציה | +| `generate_prompts_from_state.py` | `examples/ai_testing/` | יצירת פרומפטים מקובץ | +| `test_ai_live.py` | `examples/ai_testing/` | שליחה ל-LLM | +| `play_with_prompts.py` | `examples/ai_testing/` | הרצת משחק עם AI | +| `web_viewer.py` | `examples/ai_testing/` | צפייה בפרומפטים | +| `user.py` | `pycatan/players/` | ממשק User מופשט | +| `human_user.py` | `pycatan/players/` | מימוש לשחקן אנושי | + +--- + +## 🚨 הבעיות שצריך לפתור + +### בעיה 1: הפרדת אחריות חסרה +``` +❌ GameManager לא צריך לדעת על AI/פרומפטים +❌ יצירת פרומפטים מפוזרת במספר מקומות +❌ אין מקום מרכזי לניהול סוכני AI +``` + +### בעיה 2: "מה קרה" מבוסס על ניחושים +``` +❌ generate_what_happened_message() מנסה לשחזר מה קרה מתוך state +❌ לא מדויק - חסר מידע על מה באמת התרחש +❌ GameManager יודע בדיוק מה קרה אבל המידע לא מועבר +``` + +### בעיה 3: אין שליטה על מתי לשלוח פרומפטים +``` +❌ פרומפטים נשלחים על כל שינוי קובץ +❌ אין בדיקה אם כבר ממתינים לתשובה (pending) +❌ צ'אט לא מעורר שליחת פרומפטים +``` + +### בעיה 4: תשובות לא חוזרות למשחק +``` +❌ אין מסלול ברור לתשובות לחזור ל-GameManager +❌ הכל עובד דרך קבצים - לא real-time +``` + +### בעיה 5: זיכרון מפוזר +``` +❌ note_to_self נשמר בקבצים, לא במקום מרכזי +❌ אירועים (events) לא נשמרים לכל סוכן +❌ סיכומי צ'אט לא קיימים +``` + +--- + +## 🟢 הארכיטקטורה החדשה + +### תרשים מבנה + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ ארכיטקטורה חדשה │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────────┐ ┌──────────────────────┐ │ +│ │ │ │ │ │ +│ │ GameManager │◄──── Actions ──────│ AIManager │ │ +│ │ │ │ │ │ +│ │ • Game Loop │ │ • Creates Prompts │ │ +│ │ • Rules │──── Events ───────►│ • Manages Agents │ │ +│ │ • State │ (notify_all) │ • Handles Chat │ │ +│ │ • Turn Flow │ │ • Tracks Pending │ │ +│ │ │ │ • Sends to LLM │ │ +│ └────────┬─────────┘ └──────────┬───────────┘ │ +│ │ │ │ +│ │ get_input() │ │ +│ ▼ ▼ │ +│ ┌──────────────────┐ ┌──────────────────────┐ │ +│ │ │ │ │ │ +│ │ HumanUser │ │ AIUser (Wrapper) │ │ +│ │ (CLI) │ │ │ │ +│ │ │ │ • Delegates to │ │ +│ │ │ │ AIManager │ │ +│ └──────────────────┘ │ │ │ +│ └──────────┬───────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────┐ │ +│ │ │ │ +│ │ AILogger │ │ +│ │ │ │ +│ │ • MD logs │ │ +│ │ • JSON files │ │ +│ │ • Web Viewer │ │ +│ │ │ │ +│ └──────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### עקרונות מנחים + +| עיקרון | פירוט | +|--------|-------| +| **הפרדת אחריות** | GameManager לא יודע על AI, AIManager לא יודע על חוקי המשחק | +| **מקום אחד לפרומפטים** | כל יצירת הפרומפטים דרך AIManager | +| **שליטה מרכזית** | `should_send_prompt()` מחליט מתי לשלוח | +| **"מה קרה" מדויק** | Events מגיעים ישירות מ-GameManager | +| **לוגים תואמים** | AILogger שומר על אותו פורמט קבצים | + +--- + +## 📦 פירוט הרכיבים + +### 1. AgentState - מצב סוכן יחיד + +```python +@dataclass +class AgentState: + """ + מצב של סוכן AI יחיד. + + כל הזיכרון והמצב של סוכן ספציפי מנוהל כאן. + """ + + # === זיהוי === + player_name: str # שם השחקן ("dudu", "shon") + player_id: int # מספר שחקן (0, 1, 2...) + player_color: str # צבע ("Red", "Blue") + + # === סטטוס בקשה === + pending_request: bool = False # האם ממתין לתשובה מ-LLM? + last_request_time: Optional[float] = None + + # === זיכרון פרטי === + memory: Optional[str] = None # note_to_self מתשובה אחרונה + + # === סיכומי צ'אט (לעתיד) === + chat_summaries: List[str] = field(default_factory=list) + # דוגמה: ["Turn 5: Dana agreed to trade wood for brick"] + + # === אירועים שקרו מאז הפרומפט האחרון === + recent_events: List[Dict[str, Any]] = field(default_factory=list) + # דוגמה: [{"type": "dice_roll", "message": "Rolled 6", "timestamp": 123}] + + # === מעקב שינויים === + last_state_hash: Optional[str] = None + last_prompt_time: Optional[float] = None + + # === סטטיסטיקות === + total_requests: int = 0 + total_tokens_used: int = 0 +``` + +**מיקום:** `pycatan/ai/agent_state.py` + +--- + +### 2. AIManager - המנהל המרכזי + +```python +class AIManager: + """ + מנהל מרכזי לכל סוכני ה-AI. + + אחריות: + - ניהול מצב כל הסוכנים + - יצירת ושליחת פרומפטים + - קבלת תשובות והמרה לפעולות + - ניהול צ'אט והיסטוריה + - החלטה מתי לשלוח פרומפטים + """ + + def __init__( + self, + game_manager: GameManager, + config: AIConfig = None, + session_dir: Path = None + ): + """ + Args: + game_manager: הפניה ל-GameManager לקריאת state + config: קונפיגורציה (ברירת מחדל אם None) + session_dir: תיקיית session ללוגים + """ + self.game_manager = game_manager + self.config = config or AIConfig() + + # רכיבים פנימיים + self.prompt_manager = PromptManager(self.config) + self.llm_client = self._create_llm_client() + self.logger = AILogger(session_dir) + + # מצב + self.agents: Dict[str, AgentState] = {} + self.chat_history: List[Dict] = [] + self.max_chat_history: int = 20 + + # === ניהול סוכנים === + + def register_agent(self, player_name: str, player_id: int, player_color: str = ""): + """רושם סוכן AI חדש""" + + def unregister_agent(self, player_name: str): + """מסיר סוכן (אם שחקן עזב)""" + + # === נקודת הכניסה הראשית === + + def process_agent_turn(self, player_name: str) -> Action: + """ + מעבד תור של סוכן AI. + + זו הפונקציה שנקראת מ-AIUser.get_input() + + Returns: + Action: הפעולה שהסוכן בחר לבצע + """ + + # === קבלת אירועים === + + def on_game_event(self, event_type: str, message: str, affected_players: List[int] = None): + """ + נקרא כשמתרחש אירוע במשחק. + + נקרא מ-AIUser.notify_game_event() עבור כל סוכן. + """ + + def on_chat_message(self, from_player: str, message: str): + """ + נקרא כשסוכן שולח הודעת צ'אט. + + מוסיף להיסטוריה ושולח פרומפטים לסוכנים אחרים. + """ + + # === לוגיקת שליחה === + + def should_send_prompt(self, player_name: str) -> bool: + """ + מחליט אם לשלוח פרומפט לסוכן. + + כללים: + 1. אין בקשה תלויה (pending_request == False) + 2. וגם אחד מאלה: + - מצב המשחק השתנה (state_hash שונה) + - הגיעה הודעת צ'אט חדשה + """ + + # === פונקציות פנימיות === + + def _create_prompt(self, agent: AgentState, is_active_turn: bool) -> Dict: + """יוצר פרומפט מלא לסוכן""" + + def _build_what_happened(self, agent: AgentState) -> str: + """בונה תיאור 'מה קרה' מהאירועים האחרונים""" + + def _get_optimized_state(self) -> Dict: + """מחזיר state ממוטב לשליחה ל-LLM""" + + def _hash_state(self) -> str: + """יוצר hash של ה-state לזיהוי שינויים""" + + def _convert_to_action(self, parsed_response: Dict, player_id: int) -> Action: + """ממיר תשובת LLM לאובייקט Action""" + + def _broadcast_chat(self, from_player: str, message: str): + """משדר הודעת צ'אט לכל הסוכנים""" +``` + +**מיקום:** `pycatan/ai/ai_manager.py` + +--- + +### 3. AIUser - Wrapper לממשק User + +```python +class AIUser(User): + """ + Wrapper שמחבר בין GameManager ל-AIManager. + + GameManager רואה את זה כ-User רגיל ומתקשר איתו + דרך get_input() ו-notify_game_event(). + """ + + def __init__(self, name: str, user_id: int, ai_manager: AIManager, color: str = ""): + """ + Args: + name: שם השחקן + user_id: מספר שחקן (0-based) + ai_manager: הפניה ל-AIManager + color: צבע השחקן + """ + super().__init__(name, user_id) + self.ai_manager = ai_manager + self.color = color + + # רושם את עצמו ב-AIManager + ai_manager.register_agent(name, user_id, color) + + def get_input( + self, + game_state: GameState, + prompt_message: str, + allowed_actions: Optional[List[str]] = None + ) -> Action: + """ + GameManager קורא לזה כשצריך פעולה. + + מעביר את הבקשה ל-AIManager לטיפול. + """ + return self.ai_manager.process_agent_turn(self.name) + + def notify_game_event( + self, + event_type: str, + message: str, + affected_players: Optional[List[int]] = None + ): + """ + GameManager קורא לזה כשמתרחש אירוע. + + מעביר ל-AIManager לשמירה. + """ + self.ai_manager.on_game_event(event_type, message, affected_players) + + def notify_action(self, action: Action, success: bool, message: str = ""): + """ + GameManager קורא לזה אחרי ביצוע פעולה. + """ + # אפשר להוסיף לוגיקה אם צריך + pass +``` + +**מיקום:** `pycatan/ai/ai_user.py` + +--- + +### 4. AILogger - ניהול לוגים + +```python +class AILogger: + """ + מנהל לוגים עבור מערכת ה-AI. + + שומר על תאימות לפורמט הקיים: + - player_X.md (לוגים קריאים) + - prompt_N.json (פרומפטים) + - response_N.json (תשובות) + + גם תומך ב-Web Viewer (לעתיד). + """ + + def __init__(self, session_dir: Path = None): + """ + Args: + session_dir: תיקיית session. אם None, יוצר אוטומטית. + """ + if session_dir is None: + session_dir = self._create_session_dir() + + self.session_dir = session_dir + self.session_dir.mkdir(parents=True, exist_ok=True) + + self.request_counters: Dict[str, int] = {} + self.start_time = datetime.now() + + # יצירת header ללוגים + self._init_session() + + # === Logging === + + def log_prompt( + self, + player_name: str, + prompt: Dict, + schema: Dict, + is_active: bool = True + ) -> Path: + """ + שומר פרומפט לקובץ. + + יוצר: + - session/player_name/prompts/prompt_N.json + - session/player_name/prompts/prompt_N.txt + + Returns: + Path: נתיב לקובץ JSON + """ + + def log_response( + self, + player_name: str, + response: LLMResponse, + parsed: Dict + ): + """ + שומר תשובה ומעדכן MD log. + + יוצר: + - session/player_name/responses/response_N.json + - מעדכן session/player_name.md + """ + + def log_chat(self, from_player: str, message: str): + """שומר הודעת צ'אט ללוג""" + + def log_error(self, player_name: str, error: str): + """שומר שגיאה ללוג""" + + # === MD Generation === + + def _init_player_md(self, player_name: str, model: str): + """יוצר header לקובץ MD של שחקן""" + + def _append_request_to_md( + self, + player_name: str, + num: int, + prompt: Dict + ): + """מוסיף request section ל-MD""" + + def _append_response_to_md( + self, + player_name: str, + num: int, + response: LLMResponse, + parsed: Dict + ): + """מוסיף response section ל-MD""" + + # === Utilities === + + def _create_session_dir(self) -> Path: + """יוצר תיקיית session עם timestamp""" + + def get_session_path(self) -> Path: + """מחזיר נתיב ה-session""" + + def save_agent_memories(self, agents: Dict[str, AgentState]): + """שומר את הזיכרונות של כל הסוכנים לקובץ""" + + def save_chat_history(self, chat_history: List[Dict]): + """שומר היסטוריית צ'אט לקובץ""" +``` + +**מיקום:** `pycatan/ai/ai_logger.py` + +--- + +## 🔄 זרימות עבודה + +### זרימה 1: תור של סוכן AI + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ AGENT TURN FLOW │ +├────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. GameManager._process_user_action() │ +│ │ │ +│ │ calls │ +│ ▼ │ +│ 2. AIUser.get_input(game_state, prompt_message, allowed_actions) │ +│ │ │ +│ │ delegates to │ +│ ▼ │ +│ 3. AIManager.process_agent_turn(player_name) │ +│ │ │ +│ ├─► Get agent state │ +│ │ │ +│ ├─► Build "what_happened" from recent_events │ +│ │ │ +│ ├─► Create prompt via PromptManager │ +│ │ │ +│ ├─► AILogger.log_prompt() → saves files │ +│ │ │ +│ ├─► Mark agent.pending_request = True │ +│ │ │ +│ ├─► LLMClient.generate(prompt) ──────► 🤖 Gemini │ +│ │ │ │ +│ │◄─── Response ◄──────────────────────────────┘ │ +│ │ │ +│ ├─► Mark agent.pending_request = False │ +│ │ │ +│ ├─► Parse response │ +│ │ │ +│ ├─► AILogger.log_response() → saves files + MD │ +│ │ │ +│ ├─► Update agent.memory (note_to_self) │ +│ │ │ +│ ├─► Clear agent.recent_events │ +│ │ │ +│ ├─► Handle chat_message if present │ +│ │ │ +│ ▼ │ +│ 4. Return Action │ +│ │ │ +│ ▼ │ +│ 5. GameManager.execute_action() │ +│ │ │ +│ ▼ │ +│ 6. GameManager._notify_all_users() ──► AIUser.notify_game_event() │ +│ │ │ +│ ▼ │ +│ AIManager.on_game_event() │ +│ │ │ +│ ▼ │ +│ Save to agent.recent_events│ +│ │ +└────────────────────────────────────────────────────────────────────┘ +``` + +### זרימה 2: הודעת צ'אט + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ CHAT MESSAGE FLOW │ +├────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. Agent A response includes chat_message: "Anyone want sheep?" │ +│ │ │ +│ ▼ │ +│ 2. AIManager._broadcast_chat("A", "Anyone want sheep?") │ +│ │ │ +│ ├─► Add to chat_history (shared) │ +│ │ │ +│ ├─► AILogger.log_chat() │ +│ │ │ +│ ▼ │ +│ 3. For each other agent (B, C, D): │ +│ │ │ +│ ├─► Check should_send_prompt(agent) │ +│ │ │ │ +│ │ ├─► if pending_request: SKIP (don't queue!) │ +│ │ │ │ +│ │ └─► if not pending: Send spectator prompt │ +│ │ │ +│ └─► Agents see chat in their next prompt │ +│ │ +└────────────────────────────────────────────────────────────────────┘ +``` + +### זרימה 3: אירוע במשחק (Event) + +``` +┌────────────────────────────────────────────────────────────────────┐ +│ GAME EVENT FLOW │ +├────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. GameManager: Something happens (dice roll, build, trade...) │ +│ │ │ +│ ▼ │ +│ 2. GameManager._notify_all_users("dice_roll", "Rolled 6 (3+3)") │ +│ │ │ +│ │ For each user: │ +│ ▼ │ +│ 3. User.notify_game_event("dice_roll", "Rolled 6 (3+3)") │ +│ │ │ +│ ├─► HumanUser: prints to console │ +│ │ │ +│ └─► AIUser: delegates to AIManager │ +│ │ │ +│ ▼ │ +│ 4. AIManager.on_game_event("dice_roll", "Rolled 6 (3+3)") │ +│ │ │ +│ ▼ │ +│ 5. For each agent: │ +│ │ │ +│ └─► agent.recent_events.append({ │ +│ "type": "dice_roll", │ +│ "message": "Rolled 6 (3+3)", │ +│ "timestamp": time.time() │ +│ }) │ +│ │ +│ 6. When agent's turn comes, recent_events → "what_happened" │ +│ │ +└────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 📁 מבנה קבצים חדש + +``` +pycatan/ +├── ai/ +│ ├── __init__.py # exports +│ │ +│ │ # === NEW FILES === +│ ├── ai_manager.py # 🆕 AIManager class +│ ├── ai_user.py # 🆕 AIUser class (wrapper) +│ ├── ai_logger.py # 🆕 AILogger class +│ ├── agent_state.py # 🆕 AgentState dataclass +│ │ +│ │ # === EXISTING (minimal changes) === +│ ├── prompt_manager.py # ✅ Keep as-is +│ ├── llm_client.py # ✅ Keep as-is +│ ├── state_filter.py # ✅ Keep as-is +│ ├── prompt_templates.py # ✅ Keep as-is +│ ├── response_parser.py # ✅ Keep as-is +│ ├── schemas.py # ✅ Keep as-is +│ └── config.py # ✅ Keep as-is +│ +├── players/ +│ ├── __init__.py +│ ├── user.py # ✅ Keep as-is (abstract interface) +│ └── human_user.py # ✅ Keep as-is +│ +├── management/ +│ └── game_manager.py # ✅ Keep as-is (no changes!) +│ +examples/ +├── ai_testing/ +│ │ # === DEPRECATED (will be replaced) === +│ ├── generate_prompts_from_state.py # ⚠️ DEPRECATED +│ ├── test_ai_live.py # ⚠️ DEPRECATED +│ ├── play_with_prompts.py # ⚠️ DEPRECATED +│ │ +│ │ # === NEW === +│ ├── play_with_ai.py # 🆕 New unified entry point +│ │ +│ │ # === KEEP === +│ ├── web_viewer.py # ✅ Keep (works with new log format) +│ └── my_games/ # ✅ Keep (session storage) +``` + +--- + +## 📋 תוכנית מימוש + +### Phase 1: יצירת רכיבים חדשים (לא שוברים קוד קיים) + +#### Step 1.1: AgentState +``` +📁 Create: pycatan/ai/agent_state.py +⏱️ Estimated: 15 min +📝 Contents: + - AgentState dataclass + - Helper methods +``` + +#### Step 1.2: AILogger +``` +📁 Create: pycatan/ai/ai_logger.py +⏱️ Estimated: 45 min +📝 Contents: + - AILogger class + - log_prompt() - saves JSON + TXT + - log_response() - saves JSON + updates MD + - MD format matching existing player_X.md +``` + +#### Step 1.3: AIManager +``` +📁 Create: pycatan/ai/ai_manager.py +⏱️ Estimated: 1.5 hours +📝 Contents: + - AIManager class + - process_agent_turn() + - on_game_event() + - on_chat_message() + - should_send_prompt() + - _broadcast_chat() +``` + +#### Step 1.4: AIUser +``` +📁 Create: pycatan/ai/ai_user.py +⏱️ Estimated: 30 min +📝 Contents: + - AIUser class extending User + - get_input() delegation + - notify_game_event() delegation +``` + +#### Step 1.5: Update __init__.py +``` +📁 Modify: pycatan/ai/__init__.py +⏱️ Estimated: 5 min +📝 Add exports for new classes +``` + +--- + +### Phase 2: Entry Point חדש + +#### Step 2.1: Create play_with_ai.py +``` +📁 Create: examples/ai_testing/play_with_ai.py +⏱️ Estimated: 45 min +📝 Contents: + - Creates GameManager with AIUsers + - Creates AIManager + - Runs game loop +``` + +--- + +### Phase 3: בדיקות ווידוא + +#### Step 3.1: Test basic flow +``` +⏱️ Estimated: 30 min +📝 Run play_with_ai.py + - Verify prompts generated + - Verify responses logged + - Verify MD files created + - Verify actions returned to GameManager +``` + +#### Step 3.2: Test chat flow +``` +⏱️ Estimated: 20 min +📝 Test chat messages + - Agent sends chat + - Other agents receive in next prompt + - Chat history saved +``` + +#### Step 3.3: Test Web Viewer +``` +⏱️ Estimated: 15 min +📝 Verify web_viewer.py works with new log format +``` + +--- + +### Phase 4: Cleanup (אופציונלי) + +#### Step 4.1: Mark deprecated files +``` +📝 Add deprecation notices to: + - generate_prompts_from_state.py + - test_ai_live.py + - play_with_prompts.py +``` + +#### Step 4.2: Update documentation +``` +📝 Update: + - README + - AI_ARCHITECTURE.md +``` + +--- + +## ⏱️ סיכום זמנים + +| Phase | Task | Time | +|-------|------|------| +| 1.1 | AgentState | 15 min | +| 1.2 | AILogger | 45 min | +| 1.3 | AIManager | 1.5 hours | +| 1.4 | AIUser | 30 min | +| 1.5 | __init__.py | 5 min | +| 2.1 | play_with_ai.py | 45 min | +| 3.x | Testing | 1 hour | +| **Total** | | **~5 hours** | + +--- + +## ✅ Checklist לפני התחלה + +- [ ] מבנה הארכיטקטורה ברור +- [ ] הבנת זרימת העבודה +- [ ] הבנת אחריות כל רכיב +- [ ] מוכן להתחיל Phase 1 + +--- + +## 🔮 תוספות עתידיות (לא בריפקטור הנוכחי) + +1. **סיכום צ'אט אוטומטי** - `_maybe_summarize_chat()` +2. **Web Viewer real-time** - WebSocket ל-AILogger +3. **Multi-LLM support** - OpenAI, Anthropic +4. **Agent personalities** - Different prompts per agent +5. **Replay system** - Play back from logs + +--- + +## 📚 קבצים קשורים + +- [AI_ARCHITECTURE.md](.github/instructions/AI_ARCHITECTURE.md) - ארכיטקטורה כללית +- [AI_AGENT_PRINCIPLES.md](.github/instructions/AI_AGENT_PRINCIPLES.md) - עקרונות עיצוב +- [WORK_PLAN.md](.github/instructions/WORK_PLAN.md) - תוכנית עבודה כללית + +--- + +**מוכן להתחיל?** 🚀 diff --git a/START.md b/START.md new file mode 100644 index 0000000000000000000000000000000000000000..d15ac8f777125b837bbb2f6c7731f8fca692ead1 --- /dev/null +++ b/START.md @@ -0,0 +1,218 @@ +# 🎮 PyCatan AI - Quick Start Guide + +## 🚀 How to Run + +### Option 1: Play with AI Agents (Recommended) +```bash +python examples/ai_testing/play_with_ai.py +``` + +This will: +1. Let you configure players (human or AI) +2. Generate AI prompts for AI players +3. Allow you to manually enter AI actions +4. Log all prompts and responses for analysis + +### Option 2: Quick Start - All AI Players +```bash +python examples/ai_testing/play_with_ai.py --players 3 --all-ai +``` + +### Option 3: Auto-LLM Mode (requires API key) +```bash +# First set your API key: +set GEMINI_API_KEY=your_api_key_here + +# Then run: +python examples/ai_testing/play_with_ai.py --auto-llm +``` + +--- + +## 📁 Project Structure + +``` +pycatan/ +├── ai/ # 🤖 AI System (NEW) +│ ├── ai_manager.py # Central AI coordinator +│ ├── ai_user.py # AI player wrapper +│ ├── ai_logger.py # Logging system +│ ├── agent_state.py # Per-agent state +│ ├── prompt_manager.py # Prompt construction +│ ├── response_parser.py # Response parsing +│ ├── llm_client.py # Gemini API client +│ ├── config.py # Configuration +│ └── schemas.py # JSON schemas +│ +├── management/ +│ └── game_manager.py # Game coordination +│ +├── players/ +│ ├── user.py # Abstract user class +│ └── human_user.py # Human player CLI +│ +└── core/ # Game logic + ├── game.py + ├── board.py + └── ... + +examples/ +└── ai_testing/ + ├── play_with_ai.py # 🆕 Main entry point + ├── play_and_capture.py # State capture utility + ├── web_viewer.py # Prompt visualization + ├── my_games/ # Session storage + └── _deprecated/ # Old files (for reference) +``` + +--- + +## 🎯 Manual Mode Commands + +When playing in manual mode, use these commands for AI players: + +### Basic Actions +| Command | Description | +|---------|-------------| +| `roll_dice` or `r` | Roll the dice | +| `end_turn` or `e` | End turn | + +### Building +| Command | Example | +|---------|---------| +| `build_settlement` | `build_settlement {"node": 14}` | +| `build_city` | `build_city {"node": 14}` | +| `build_road` | `build_road {"from": 14, "to": 15}` | + +### Shortcuts (Setup Phase) +| Command | Meaning | +|---------|---------| +| `s 14` | Place settlement at node 14 | +| `rd 14 15` | Place road from 14 to 15 | + +### Other Actions +| Command | Example | +|---------|---------| +| `buy_dev_card` | Buy a development card | +| `robber_move` | `robber_move {"hex": 5}` | +| `steal_card` | `steal_card {"target_player": "Bob"}` | +| `trade_bank` | `trade_bank {"give": "wheat", "receive": "ore"}` | + +Type `help` at any prompt for more details. + +--- + +## 📊 Logs and Sessions + +Each game session creates a folder in `examples/ai_testing/my_games/`: + +``` +session_20260108_143022/ +├── session_metadata.json # Session info +├── chat_history.json # Chat messages +├── session_summary.json # Final stats +│ +├── AI_1/ # Per-player folder +│ ├── prompts/ +│ │ ├── prompt_1.json # Full prompt +│ │ ├── prompt_1.txt # Human-readable +│ │ └── ... +│ ├── responses/ +│ │ ├── response_1.json # LLM response +│ │ └── ... +│ └── AI_1.md # Log file +│ +└── AI_2/ + └── ... +``` + +--- + +## 🔧 Configuration + +### AI Config (Optional) +Create `config_dev.yaml` in `pycatan/ai/`: + +```yaml +llm: + provider: "gemini" + model_name: "gemini-2.0-flash-exp" + temperature: 0.7 + api_key_env_var: "GEMINI_API_KEY" + +memory: + chat_history_size: 10 +``` + +### Environment Variables +```bash +# Windows +set GEMINI_API_KEY=your_api_key + +# Linux/Mac +export GEMINI_API_KEY=your_api_key +``` + +--- + +## 🏗️ Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Game Flow │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ GameManager AIManager │ +│ │ │ │ +│ │ "What action?" │ Creates prompts │ +│ ▼ │ Manages memory │ +│ ┌─────────┐ │ Logs everything │ +│ │ AIUser │◄──── delegates to ──────────►│ │ +│ │(Wrapper)│ │ │ +│ └─────────┘ ▼ │ +│ │ ┌─────────────┐ │ +│ │ Returns Action │ AILogger │ │ +│ ▼ │ (Files) │ │ +│ GameManager └─────────────┘ │ +│ executes action │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 📚 Documentation + +- [AI_REFACTOR_PLAN.md](.github/instructions/AI_REFACTOR_PLAN.md) - Detailed refactoring plan +- [AI_ARCHITECTURE.md](.github/instructions/AI_ARCHITECTURE.md) - System architecture +- [AI_AGENT_PRINCIPLES.md](.github/instructions/AI_AGENT_PRINCIPLES.md) - Design principles + +--- + +## ❓ Troubleshooting + +### "API key not found" +Make sure to set the environment variable: +```bash +set GEMINI_API_KEY=your_key_here +``` + +### "Module not found" +Run from the project root directory: +```bash +cd C:\GIT_new\PyCatan_AI +python examples/ai_testing/play_with_ai.py +``` + +### "Action not allowed" +Check the `allowed_actions` list shown in the prompt. The action must be one of those. + +--- + +## 🎉 Have Fun! + +Start a game and experiment with AI prompts. Check the generated logs to understand how the AI "thinks" about the game state. + +```bash +python examples/ai_testing/play_with_ai.py +``` diff --git a/docs/THINKING_MODE_SETUP.md b/docs/THINKING_MODE_SETUP.md new file mode 100644 index 0000000000000000000000000000000000000000..160f173d0408a10bcb234f2d08e592f664863aa3 --- /dev/null +++ b/docs/THINKING_MODE_SETUP.md @@ -0,0 +1,247 @@ +# 🧠 Thinking Mode Setup Guide + +## Overview + +Gemini 2.0 Flash introduces **thinking mode** - the model explicitly "thinks" through problems before responding. This generates higher quality responses for complex tasks like game strategy. + +--- + +## 🚀 Quick Start + +### 1. Switch to Thinking Model + +**Option A: Edit config.yaml** (Recommended) +```yaml +llm: + model_name: "gemini-2.0-flash-thinking-exp" + enable_thinking: true + thinking_budget: 16000 # Max tokens for thinking (8k-32k) +``` + +**Option B: Edit config.py** (For default settings) +```python +@dataclass +class LLMConfig: + model_name: str = "gemini-2.0-flash-thinking-exp" + enable_thinking: bool = True + thinking_budget: int = 16000 +``` + +### 2. Run Your Game + +```bash +python play_catan.py +``` + +The AI will now use thinking mode automatically! + +--- + +## 📊 How to Monitor Thinking + +### In Console Logs + +Look for thinking token counts: +``` +✅ Response received: 450 tokens (+1200 thinking), 3.5s +``` + +### In Log Files + +**JSON logs** (`examples/ai_testing/my_games/AI_Agent_1/prompt_1.json`): +```json +{ + "tokens": { + "prompt": 1523, + "completion": 450, + "thinking": 1200, + "total": 3173 + } +} +``` + +**TXT logs** (`examples/ai_testing/my_games/AI_Agent_1/prompt_1.txt`): +``` +Tokens: prompt=1523, completion=450, thinking=1200, total=3173 +``` + +### In Web Viewer + +Visit: http://localhost:5001 + +The viewer will show: +- 📊 Token breakdown including thinking tokens +- 💰 Cost calculation (thinking tokens = input cost) +- 📈 Thinking usage trends + +--- + +## ⚙️ Configuration Options + +### Model Selection + +| Model | Thinking | Speed | Quality | +|-------|----------|-------|---------| +| `gemini-2.0-flash-exp` | ❌ | ⚡ Fast | Good | +| `gemini-2.0-flash-thinking-exp` | ✅ | 🐢 Slower | Better | + +### Thinking Budget + +Controls max tokens the model can use for thinking: + +```yaml +thinking_budget: 16000 # Recommended: 8000-32000 +``` + +- **Lower (8k)**: Faster, less thorough +- **Medium (16k)**: Balanced (default) +- **Higher (32k)**: Slower, more thorough + +### Enable/Disable + +```yaml +enable_thinking: true # Turn on thinking mode +enable_thinking: false # Turn off (faster, cheaper) +``` + +--- + +## 💰 Cost Impact + +**Thinking tokens are charged as input tokens:** + +Example (16k thinking budget): +- Standard mode: ~450 output tokens = $0.000034 +- Thinking mode: ~1200 thinking + 450 output = $0.000056 + +**~1.6x cost increase for better decisions** 🎯 + +--- + +## 🔍 Viewing the Schema + +The **response schema** is logged in TXT files for debugging: + +``` +=== Prompt #1 (Active Turn) === + +--- Response Schema --- +{ + "type": "object", + "properties": { + "internal_thinking": { + "type": "string", + "description": "Your reasoning process...", + "minLength": 200 + }, + ... + } +} + +--- Prompt Content --- +{ + "meta_data": { ... } +} +``` + +Location: `examples/ai_testing/my_games/AI_Agent_1/prompt_N.txt` + +--- + +## ✅ Testing Thinking Mode + +### Quick Test + +1. Edit `pycatan/ai/config.py`: + ```python + model_name: str = "gemini-2.0-flash-thinking-exp" + enable_thinking: bool = True + ``` + +2. Run a game: + ```bash + python play_catan.py + ``` + +3. Check console output for thinking tokens: + ``` + ✅ Response received: 450 tokens (+1200 thinking), 3.5s + ``` + +4. View logs: + ```bash + # Check TXT file + cat examples/ai_testing/my_games/AI_Agent_1/prompt_1.txt + + # Or JSON + cat examples/ai_testing/my_games/AI_Agent_1/prompt_1.json + ``` + +### Web Viewer + +```bash +cd examples/ai_testing +python web_viewer.py +``` + +Visit http://localhost:5001 to see: +- Token breakdowns with thinking +- Cost calculations +- Response quality metrics + +--- + +## 🐛 Troubleshooting + +### Not Seeing Thinking Tokens? + +1. **Check model name**: Must be `gemini-2.0-flash-thinking-exp` +2. **Check enable_thinking**: Must be `true` in config +3. **Check logs**: Look for "enable_thinking" in debug output + +### Error: "thinking_config not supported" + +- Your model doesn't support thinking mode +- Switch to: `gemini-2.0-flash-thinking-exp` + +### High Costs? + +- Reduce `thinking_budget` (e.g., 8000) +- Or disable thinking: `enable_thinking: false` + +--- + +## 📚 Configuration Files + +### Location + +- **Active config**: `pycatan/ai/config_dev.yaml` +- **Example**: `pycatan/ai/config_example.yaml` +- **Defaults**: `pycatan/ai/config.py` + +### Priority + +1. Config YAML file (if exists) +2. Default values in `config.py` + +--- + +## 🎯 Summary + +**To enable thinking mode:** + +1. Set `model_name: "gemini-2.0-flash-thinking-exp"` +2. Set `enable_thinking: true` +3. Set `thinking_budget: 16000` (optional) +4. Run your game +5. Check logs for thinking token counts + +**Benefits:** +- ✅ Better strategic decisions +- ✅ More thorough reasoning +- ✅ Higher quality play + +**Trade-offs:** +- ⏱️ Slower responses (~2-5s) +- 💰 Higher costs (~1.5-2x) + diff --git a/examples/ai_testing/__init__.py b/examples/ai_testing/__init__.py index 82ba391278dff7f7ebf1ba87576414bf40a68887..26795141ebbc93a1230b1af8f74b7f0f00121255 100644 --- a/examples/ai_testing/__init__.py +++ b/examples/ai_testing/__init__.py @@ -1,8 +1,27 @@ """ AI Testing Tools ---------------- -Tools for testing AI understanding of game state via Web Visualizer. -This package helps visualize game states and capture the JSON data -that would be sent to an AI agent for decision making. +This package provides tools for testing AI agents in PyCatan. + +Main Entry Points: +- play_with_ai.py - Run a game with AI agents (manual or LLM mode) +- play_and_capture.py - Play and capture game states for analysis +- web_viewer.py - Visualize AI prompts and responses + +Key Files: +- my_games/ - Session storage for AI interactions +- sample_states/ - Example game states for testing +- templates/ - Prompt templates + +Deprecated Files (in _deprecated/): +- Old prompt generation and testing scripts +- See _deprecated/__init__.py for details + +Usage: + # Run a game with AI agents (manual mode): + python examples/ai_testing/play_with_ai.py + + # Run a game and capture states: + python examples/ai_testing/play_and_capture.py """ diff --git a/examples/ai_testing/_deprecated/__init__.py b/examples/ai_testing/_deprecated/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f3d1a60be46ee69a48d2aa6a37d8b68da8e8796f --- /dev/null +++ b/examples/ai_testing/_deprecated/__init__.py @@ -0,0 +1,49 @@ +""" +⚠️ DEPRECATED FILES - OLD AI TESTING INFRASTRUCTURE + +This folder contains the OLD AI testing files that have been replaced +by the new unified AI system in pycatan/ai/. + +These files are kept for reference but should NOT be used for new development. + +Old Files (in this folder): +- generate_prompts_from_state.py - Old prompt generation (replaced by AIManager) +- play_with_prompts.py - Old game runner (replaced by play_with_ai.py) +- test_ai_live.py - Old LLM tester (replaced by AIManager) +- request_tracker.py - Old request tracking (replaced by AILogger) +- test_optimized_prompts.py - Old prompt testing +- test_new_structure.py - Old structure tests +- example_get_latest_prompt.py - Old prompt retrieval + +New System (use these instead): +- play_with_ai.py (in examples/ai_testing/) - New unified entry point +- pycatan/ai/ai_manager.py - Central AI coordinator +- pycatan/ai/ai_user.py - AI player wrapper +- pycatan/ai/ai_logger.py - Logging system +- pycatan/ai/agent_state.py - Agent state management + +Migration: +The new system provides: +1. Cleaner separation of concerns +2. Better event tracking ("what happened" based on real events) +3. Unified logging with session management +4. Support for both manual and automatic LLM modes +5. Better parameter conversion between AI and GameManager + +To run a game with AI: + python examples/ai_testing/play_with_ai.py + +For more information, see: +- .github/instructions/AI_REFACTOR_PLAN.md +- .github/instructions/AI_ARCHITECTURE.md +""" + +__deprecated__ = True +__version__ = "1.0.0 (deprecated)" + +import warnings +warnings.warn( + "This module is deprecated. Use pycatan.ai instead.", + DeprecationWarning, + stacklevel=2 +) diff --git a/examples/ai_testing/example_get_latest_prompt.py b/examples/ai_testing/_deprecated/example_get_latest_prompt.py similarity index 100% rename from examples/ai_testing/example_get_latest_prompt.py rename to examples/ai_testing/_deprecated/example_get_latest_prompt.py diff --git a/examples/ai_testing/generate_prompts_from_state.py b/examples/ai_testing/_deprecated/generate_prompts_from_state.py similarity index 100% rename from examples/ai_testing/generate_prompts_from_state.py rename to examples/ai_testing/_deprecated/generate_prompts_from_state.py diff --git a/examples/ai_testing/play_with_prompts.py b/examples/ai_testing/_deprecated/play_with_prompts.py similarity index 100% rename from examples/ai_testing/play_with_prompts.py rename to examples/ai_testing/_deprecated/play_with_prompts.py diff --git a/examples/ai_testing/request_tracker.py b/examples/ai_testing/_deprecated/request_tracker.py similarity index 100% rename from examples/ai_testing/request_tracker.py rename to examples/ai_testing/_deprecated/request_tracker.py diff --git a/examples/ai_testing/test_ai_live.py b/examples/ai_testing/_deprecated/test_ai_live.py similarity index 100% rename from examples/ai_testing/test_ai_live.py rename to examples/ai_testing/_deprecated/test_ai_live.py diff --git a/examples/ai_testing/test_new_structure.py b/examples/ai_testing/_deprecated/test_new_structure.py similarity index 100% rename from examples/ai_testing/test_new_structure.py rename to examples/ai_testing/_deprecated/test_new_structure.py diff --git a/examples/ai_testing/test_optimized_prompts.py b/examples/ai_testing/_deprecated/test_optimized_prompts.py similarity index 100% rename from examples/ai_testing/test_optimized_prompts.py rename to examples/ai_testing/_deprecated/test_optimized_prompts.py diff --git a/examples/ai_testing/llm_logger_console.py b/examples/ai_testing/llm_logger_console.py new file mode 100644 index 0000000000000000000000000000000000000000..66965e1606f93dbcd88bd51be310b02ed5c5407c --- /dev/null +++ b/examples/ai_testing/llm_logger_console.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +LLM Logger Console - Displays real-time LLM communication logs + +This runs in a separate console window and shows: +- Prompts sent to Gemini +- Responses received +- Errors and timing +""" + +import sys +import time +import os +from pathlib import Path + +# Configure for Windows +if sys.platform == 'win32': + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + +# Color codes for Windows console +class Colors: + HEADER = '\033[95m' + BLUE = '\033[94m' + CYAN = '\033[96m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + RED = '\033[91m' + END = '\033[0m' + BOLD = '\033[1m' + +def print_header(): + """Print welcome header.""" + print("=" * 70) + print(f"{Colors.CYAN}[LLM LOGGER] Real-time Gemini Communication{Colors.END}") + print("=" * 70) + print() + print("This window shows all communication with the LLM.") + print("Keep it open while playing!") + print() + print("=" * 70) + print() + +def watch_log_file(log_file: Path): + """Watch a log file and print new lines.""" + print(f"[WATCHING] {log_file}") + print("-" * 70) + + # Wait for file to exist + while not log_file.exists(): + time.sleep(0.5) + + # Start from end of file + with open(log_file, 'r', encoding='utf-8', errors='replace') as f: + # Go to end + f.seek(0, 2) + + while True: + line = f.readline() + if line: + # Color code based on content + if '[SEND]' in line or '[PROMPT]' in line: + print(f"{Colors.BLUE}{line.rstrip()}{Colors.END}") + elif '[RECV]' in line or '[RESPONSE]' in line: + print(f"{Colors.GREEN}{line.rstrip()}{Colors.END}") + elif '[ERROR]' in line or 'Error' in line: + print(f"{Colors.RED}{line.rstrip()}{Colors.END}") + elif '[LLM]' in line: + print(f"{Colors.YELLOW}{line.rstrip()}{Colors.END}") + else: + print(line.rstrip()) + else: + time.sleep(0.1) + +def main(): + """Main entry point.""" + print_header() + + # Find session directory - use absolute path from script location + script_dir = Path(__file__).parent.absolute() + base_dir = script_dir / "my_games" + + print(f"[DEBUG] Script dir: {script_dir}") + print(f"[DEBUG] Base dir: {base_dir}") + print(f"[DEBUG] Base dir exists: {base_dir.exists()}") + + # Look for current session file + current_session_file = base_dir / "current_session.txt" + + session_name = None + log_file = None + + if current_session_file.exists(): + session_name = current_session_file.read_text().strip() + print(f"[DEBUG] Session name from file: {session_name}") + # Handle both full path and just session name + if Path(session_name).is_absolute(): + log_file = Path(session_name) / "llm_communication.log" + else: + log_file = base_dir / session_name / "llm_communication.log" + print(f"[DEBUG] Log file path: {log_file}") + print(f"[DEBUG] Log file exists: {log_file.exists()}") + else: + print(f"[DEBUG] No current_session.txt at {current_session_file}") + # Find most recent session + sessions = sorted(base_dir.glob("session_*"), key=lambda p: p.stat().st_mtime, reverse=True) + print(f"[DEBUG] Found sessions: {[s.name for s in sessions]}") + if sessions: + log_file = sessions[0] / "llm_communication.log" + + if log_file is None or not log_file.parent.exists(): + print("[!] No sessions found. Start a game first!") + print(f"[?] Looking in: {base_dir}") + input("Press Enter to exit...") + return + + print(f"[LOG FILE] {log_file}") + print() + + try: + watch_log_file(log_file) + except KeyboardInterrupt: + print("\n[STOPPED] Logger closed.") + +if __name__ == "__main__": + main() diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_shelly.md b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_shelly.md deleted file mode 100644 index e6b8225569063b5163eaebe4da9587d819e5d967..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_shelly.md +++ /dev/null @@ -1,200 +0,0 @@ -# 🤖 AI Agent Log - Player SHELLY - ---- - -**Session:** `session_20260104_215128` - -**Model:** `models/gemini-2.5-flash` - -**Started:** 2026-01-04 21:51:48 - ---- - - -## 🔄 Request #1 - -**Timestamp:** 2026-01-04 21:51:48 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} -``` -
- - -### ✅ Response Received - -- **Latency:** 21.80s -- **Tokens:** 936 (prompt: 687, completion: 249) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking": "It's the SETUP_FIRST_ROUND phase, and shon is placing their first settlement. I am shelly, the third player to place. My strategy is to secure a strong resource production, prioritizing Wheat and Ore for future cities and development cards, while also considering good numbers (6, 8, 5, 9) and resource diversity. I will also look for port access. My top preferred settlement spots are: 1. Node 50 (Wh9, O5, ?3 Port) - excellent Ore and Wheat production with a useful port. 2. Node 41 (O5, Wh9, B10) - a balanced mix of Ore, Wheat, and Brick with strong numbers. 3. Node 42 (Wh9, O5, Wh9) - very high Ore and Wheat production, though less resource diversity. 4. Node 21 (W11, B6, S8) - a strong general production spot for Wood, Brick, and Sheep, which would be a solid fallback if all high Wh/O spots are taken. I anticipate shon and ziv will take some of these prime locations, so I will select the best available option from my preferred list when it is my turn to place."} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> It's the SETUP_FIRST_ROUND phase, and shon is placing their first settlement. I am shelly, the third player to place. My strategy is to secure a strong resource production, prioritizing Wheat and Ore for future cities and development cards, while also considering good numbers (6, 8, 5, 9) and resource diversity. I will also look for port access. My top preferred settlement spots are: 1. Node 50 (Wh9, O5, ?3 Port) - excellent Ore and Wheat production with a useful port. 2. Node 41 (O5, Wh9, B10) - a balanced mix of Ore, Wheat, and Brick with strong numbers. 3. Node 42 (Wh9, O5, Wh9) - very high Ore and Wheat production, though less resource diversity. 4. Node 21 (W11, B6, S8) - a strong general production spot for Wood, Brick, and Sheep, which would be a solid fallback if all high Wh/O spots are taken. I anticipate shon and ziv will take some of these prime locations, so I will select the best available option from my preferred list when it is my turn to place. - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "It's the SETUP_FIRST_ROUND phase, and shon is placing their first settlement. I am shelly, the third player to place. My strategy is to secure a strong resource production, prioritizing Wheat and Ore for future cities and development cards, while also considering good numbers (6, 8, 5, 9) and resource diversity. I will also look for port access. My top preferred settlement spots are: 1. Node 50 (Wh9, O5, ?3 Port) - excellent Ore and Wheat production with a useful port. 2. Node 41 (O5, Wh9, B10) - a balanced mix of Ore, Wheat, and Brick with strong numbers. 3. Node 42 (Wh9, O5, Wh9) - very high Ore and Wheat production, though less resource diversity. 4. Node 21 (W11, B6, S8) - a strong general production spot for Wood, Brick, and Sheep, which would be a solid fallback if all high Wh/O spots are taken. I anticipate shon and ziv will take some of these prime locations, so I will select the best available option from my preferred list when it is my turn to place." -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-04 21:52:10 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} -``` -
- - -### ✅ Response Received - -- **Latency:** 26.38s -- **Tokens:** 871 (prompt: 687, completion: 184) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking": "Player shon is placing their first settlement. I am shelly, the third player in the first setup round. My strategy is to secure a high-yield, diverse starting position. I will prioritize nodes adjacent to 6s and 8s, aiming for Wood, Brick, Sheep, and Wheat. Good spots include N[10] (B6, S8, W12), N[20] (B6, S8, W11), N[19] (S8, B10, W11), and N[31] (Wh9, B10, W11). I anticipate shon and ziv will take some of the best W/B/S spots. My primary goal will be to pick the best remaining spot to get at least 3 core resources (W, B, S, Wh) with high production. For my second settlement, I will aim to round out my resources and potentially get access to Ore or a useful port. I am currently waiting for shon's move."} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> Player shon is placing their first settlement. I am shelly, the third player in the first setup round. My strategy is to secure a high-yield, diverse starting position. I will prioritize nodes adjacent to 6s and 8s, aiming for Wood, Brick, Sheep, and Wheat. Good spots include N[10] (B6, S8, W12), N[20] (B6, S8, W11), N[19] (S8, B10, W11), and N[31] (Wh9, B10, W11). I anticipate shon and ziv will take some of the best W/B/S spots. My primary goal will be to pick the best remaining spot to get at least 3 core resources (W, B, S, Wh) with high production. For my second settlement, I will aim to round out my resources and potentially get access to Ore or a useful port. I am currently waiting for shon's move. - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "Player shon is placing their first settlement. I am shelly, the third player in the first setup round. My strategy is to secure a high-yield, diverse starting position. I will prioritize nodes adjacent to 6s and 8s, aiming for Wood, Brick, Sheep, and Wheat. Good spots include N[10] (B6, S8, W12), N[20] (B6, S8, W11), N[19] (S8, B10, W11), and N[31] (Wh9, B10, W11). I anticipate shon and ziv will take some of the best W/B/S spots. My primary goal will be to pick the best remaining spot to get at least 3 core resources (W, B, S, Wh) with high production. For my second settlement, I will aim to round out my resources and potentially get access to Ore or a useful port. I am currently waiting for shon's move." -} -``` -
- diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_shon.md b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_shon.md deleted file mode 100644 index b5223c3ddee9b5793f56e079138ed5e808f7b7c8..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_shon.md +++ /dev/null @@ -1,371 +0,0 @@ -# 🤖 AI Agent Log - Player SHON - ---- - -**Session:** `session_20260104_215128` - -**Model:** `models/gemini-2.5-flash` - -**Started:** 2026-01-04 21:51:48 - ---- - - -## 🔄 Request #1 - -**Timestamp:** 2026-01-04 21:51:48 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 18.57s -- **Tokens:** 1002 (prompt: 830, completion: 172) - -
-📥 Raw Response from Gemini - -```json -{ - "internal_thinking": "My goal is to place the first settlement on a node that maximizes immediate resource production and provides a good mix of resources for early game expansion. I analyzed nodes based on adjacent hexes' resources and dice probabilities (prioritizing 6, 8, 5, 9). Node 10 (Brick 6, Sheep 8, Wood 12) stands out. It offers diverse resources (Wood, Brick, Sheep) essential for building roads and additional settlements, and has two high-probability numbers (6 and 8), giving it a high total pip count (12). This provides a strong foundation for the start of the game.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "10" - } - } -} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> My goal is to place the first settlement on a node that maximizes immediate resource production and provides a good mix of resources for early game expansion. I analyzed nodes based on adjacent hexes' resources and dice probabilities (prioritizing 6, 8, 5, 9). Node 10 (Brick 6, Sheep 8, Wood 12) stands out. It offers diverse resources (Wood, Brick, Sheep) essential for building roads and additional settlements, and has two high-probability numbers (6 and 8), giving it a high total pip count (12). This provides a strong foundation for the start of the game. - -#### 🎮 Action - -- **Type:** `place_settlement` - -- **Parameters:** `{'location': '10'}` - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "My goal is to place the first settlement on a node that maximizes immediate resource production and provides a good mix of resources for early game expansion. I analyzed nodes based on adjacent hexes' resources and dice probabilities (prioritizing 6, 8, 5, 9). Node 10 (Brick 6, Sheep 8, Wood 12) stands out. It offers diverse resources (Wood, Brick, Sheep) essential for building roads and additional settlements, and has two high-probability numbers (6 and 8), giving it a high total pip count (12). This provides a strong foundation for the start of the game.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "10" - } - } -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-04 21:52:10 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 26.65s -- **Tokens:** 1377 (prompt: 830, completion: 547) - -
-📥 Raw Response from Gemini - -```json -{ - "internal_thinking": "I am in the setup phase and need to place my first settlement. My strategy is to choose a node that provides a good mix of basic resources (Wood, Brick, Wheat, Sheep) with decent production numbers, prioritizing resources for expansion (roads and settlements). I will also consider potential spots for my second settlement to ensure a balanced resource income.I've analyzed several nodes:\n- Node 10 (B6, S8, W12): Produces Brick, Sheep, Wood with strong numbers (6, 8). Combined pips: 11. Lacks Wheat.\n- Node 19 (W11, B10, S8): Produces Wood, Brick, Sheep with good numbers (8, 10, 11). Combined pips: 10. Lacks Wheat.\n- Node 20 (W11, B6, S8): Produces Wood, Brick, Sheep with strong numbers (6, 8, 11). Combined pips: 12. Lacks Wheat.\n- Node 31 (Wh9, B10, W11): Produces Wheat, Brick, Wood with decent numbers (9, 10, 11). Combined pips: 9. Lacks Sheep.\n- Node 41 (O5, Wh9, B10): Produces Ore, Wheat, Brick with good numbers (5, 9, 10). Combined pips: 11. Lacks Wood, Sheep. This is good for cities but not ideal for a first settlement.\n\nComparing Node 10, 20, and 31:\nNodes 10 and 20 offer higher probability production (due to 6s and 8s) for Wood, Brick, and Sheep. However, they both lack Wheat.\nNode 31 offers Wood, Brick, and Wheat. This combination is ideal for early expansion, as Wood and Brick are needed for roads, and all three (plus Sheep) are needed for settlements. Wheat is also crucial for future city upgrades.\n\nWhile Node 10/20 have slightly higher overall production pips, Node 31's resource synergy for immediate building is more valuable for the first settlement. I can aim to get Sheep with my second settlement. For instance, Node 10 (B6, S8, W12) would be an excellent complementary second settlement to Node 31, providing Sheep and high-probability numbers, giving me all four basic resources.\n\nTherefore, I choose Node 31 for its strategic resource combination (W, B, Wh) which sets me up well for immediate expansion and future development, even if the individual production numbers are slightly lower than other options.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "31" - } - } -} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> I am in the setup phase and need to place my first settlement. My strategy is to choose a node that provides a good mix of basic resources (Wood, Brick, Wheat, Sheep) with decent production numbers, prioritizing resources for expansion (roads and settlements). I will also consider potential spots for my second settlement to ensure a balanced resource income.I've analyzed several nodes: -- Node 10 (B6, S8, W12): Produces Brick, Sheep, Wood with strong numbers (6, 8). Combined pips: 11. Lacks Wheat. -- Node 19 (W11, B10, S8): Produces Wood, Brick, Sheep with good numbers (8, 10, 11). Combined pips: 10. Lacks Wheat. -- Node 20 (W11, B6, S8): Produces Wood, Brick, Sheep with strong numbers (6, 8, 11). Combined pips: 12. Lacks Wheat. -- Node 31 (Wh9, B10, W11): Produces Wheat, Brick, Wood with decent numbers (9, 10, 11). Combined pips: 9. Lacks Sheep. -- Node 41 (O5, Wh9, B10): Produces Ore, Wheat, Brick with good numbers (5, 9, 10). Combined pips: 11. Lacks Wood, Sheep. This is good for cities but not ideal for a first settlement. - -Comparing Node 10, 20, and 31: -Nodes 10 and 20 offer higher probability production (due to 6s and 8s) for Wood, Brick, and Sheep. However, they both lack Wheat. -Node 31 offers Wood, Brick, and Wheat. This combination is ideal for early expansion, as Wood and Brick are needed for roads, and all three (plus Sheep) are needed for settlements. Wheat is also crucial for future city upgrades. - -While Node 10/20 have slightly higher overall production pips, Node 31's resource synergy for immediate building is more valuable for the first settlement. I can aim to get Sheep with my second settlement. For instance, Node 10 (B6, S8, W12) would be an excellent complementary second settlement to Node 31, providing Sheep and high-probability numbers, giving me all four basic resources. - -Therefore, I choose Node 31 for its strategic resource combination (W, B, Wh) which sets me up well for immediate expansion and future development, even if the individual production numbers are slightly lower than other options. - -#### 🎮 Action - -- **Type:** `place_settlement` - -- **Parameters:** `{'location': '31'}` - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "I am in the setup phase and need to place my first settlement. My strategy is to choose a node that provides a good mix of basic resources (Wood, Brick, Wheat, Sheep) with decent production numbers, prioritizing resources for expansion (roads and settlements). I will also consider potential spots for my second settlement to ensure a balanced resource income.I've analyzed several nodes:\n- Node 10 (B6, S8, W12): Produces Brick, Sheep, Wood with strong numbers (6, 8). Combined pips: 11. Lacks Wheat.\n- Node 19 (W11, B10, S8): Produces Wood, Brick, Sheep with good numbers (8, 10, 11). Combined pips: 10. Lacks Wheat.\n- Node 20 (W11, B6, S8): Produces Wood, Brick, Sheep with strong numbers (6, 8, 11). Combined pips: 12. Lacks Wheat.\n- Node 31 (Wh9, B10, W11): Produces Wheat, Brick, Wood with decent numbers (9, 10, 11). Combined pips: 9. Lacks Sheep.\n- Node 41 (O5, Wh9, B10): Produces Ore, Wheat, Brick with good numbers (5, 9, 10). Combined pips: 11. Lacks Wood, Sheep. This is good for cities but not ideal for a first settlement.\n\nComparing Node 10, 20, and 31:\nNodes 10 and 20 offer higher probability production (due to 6s and 8s) for Wood, Brick, and Sheep. However, they both lack Wheat.\nNode 31 offers Wood, Brick, and Wheat. This combination is ideal for early expansion, as Wood and Brick are needed for roads, and all three (plus Sheep) are needed for settlements. Wheat is also crucial for future city upgrades.\n\nWhile Node 10/20 have slightly higher overall production pips, Node 31's resource synergy for immediate building is more valuable for the first settlement. I can aim to get Sheep with my second settlement. For instance, Node 10 (B6, S8, W12) would be an excellent complementary second settlement to Node 31, providing Sheep and high-probability numbers, giving me all four basic resources.\n\nTherefore, I choose Node 31 for its strategic resource combination (W, B, Wh) which sets me up well for immediate expansion and future development, even if the individual production numbers are slightly lower than other options.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "31" - } - } -} -``` -
- diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_ziv.md b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_ziv.md deleted file mode 100644 index fc386f2e0a0d49cfbeafb71570d54c5574f980c1..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/player_ziv.md +++ /dev/null @@ -1,202 +0,0 @@ -# 🤖 AI Agent Log - Player ZIV - ---- - -**Session:** `session_20260104_215128` - -**Model:** `models/gemini-2.5-flash` - -**Started:** 2026-01-04 21:51:48 - ---- - - -## 🔄 Request #1 - -**Timestamp:** 2026-01-04 21:51:48 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} -``` -
- - -### ✅ Response Received - -- **Latency:** 18.04s -- **Tokens:** 857 (prompt: 686, completion: 171) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking": "Player shon is placing their first settlement. I need to identify the best available spots for my first settlement, prioritizing high-probability numbers (6, 8, 5, 9) and diverse resources (Wood, Brick, Wheat, Sheep, Ore). My top candidate nodes are: 1. Node 21 (W11, B6, S8) for Wood, Brick, Sheep with numbers 11,6,8. 2. Node 10 (B6, S8, W12) for Brick, Sheep, Wood with numbers 6,8,12. 3. Node 41 (O5, Wh9, B10) for Ore, Wheat, Brick with numbers 5,9,10. These spots offer a strong resource mix for early expansion and development. I will observe shon's placement and pick the best remaining spot among these, or the next best alternative if all are taken."} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> Player shon is placing their first settlement. I need to identify the best available spots for my first settlement, prioritizing high-probability numbers (6, 8, 5, 9) and diverse resources (Wood, Brick, Wheat, Sheep, Ore). My top candidate nodes are: 1. Node 21 (W11, B6, S8) for Wood, Brick, Sheep with numbers 11,6,8. 2. Node 10 (B6, S8, W12) for Brick, Sheep, Wood with numbers 6,8,12. 3. Node 41 (O5, Wh9, B10) for Ore, Wheat, Brick with numbers 5,9,10. These spots offer a strong resource mix for early expansion and development. I will observe shon's placement and pick the best remaining spot among these, or the next best alternative if all are taken. - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "Player shon is placing their first settlement. I need to identify the best available spots for my first settlement, prioritizing high-probability numbers (6, 8, 5, 9) and diverse resources (Wood, Brick, Wheat, Sheep, Ore). My top candidate nodes are: 1. Node 21 (W11, B6, S8) for Wood, Brick, Sheep with numbers 11,6,8. 2. Node 10 (B6, S8, W12) for Brick, Sheep, Wood with numbers 6,8,12. 3. Node 41 (O5, Wh9, B10) for Ore, Wheat, Brick with numbers 5,9,10. These spots offer a strong resource mix for early expansion and development. I will observe shon's placement and pick the best remaining spot among these, or the next best alternative if all are taken." -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-04 21:52:10 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} -``` -
- - -### ✅ Response Received - -- **Latency:** 9.49s -- **Tokens:** 807 (prompt: 686, completion: 121) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking": "Player shon is placing their first settlement. I am waiting for my turn. My strategy for my first settlement is to secure a node with high-probability numbers and a good mix of starting resources (wood, brick, sheep, wheat). Node 10 (B6, S8, W12) looks like a very strong candidate, providing Brick, Sheep, and Wood with 6 and 8 numbers. I will observe shon's placement and adjust if needed, but Node 10 is my primary target.","note_to_self": "","say_outloud": ""} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> Player shon is placing their first settlement. I am waiting for my turn. My strategy for my first settlement is to secure a node with high-probability numbers and a good mix of starting resources (wood, brick, sheep, wheat). Node 10 (B6, S8, W12) looks like a very strong candidate, providing Brick, Sheep, and Wood with 6 and 8 numbers. I will observe shon's placement and adjust if needed, but Node 10 is my primary target. - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "Player shon is placing their first settlement. I am waiting for my turn. My strategy for my first settlement is to secure a node with high-probability numbers and a good mix of starting resources (wood, brick, sheep, wheat). Node 10 (B6, S8, W12) looks like a very strong candidate, providing Brick, Sheep, and Wood with 6 and 8 numbers. I will observe shon's placement and adjust if needed, but Node 10 is my primary target.", - "note_to_self": "", - "say_outloud": "" -} -``` -
- diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/requests.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/requests.json deleted file mode 100644 index 1a02f26a830d217f1860dc0c42d46845dcf3bb40..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/requests.json +++ /dev/null @@ -1,276 +0,0 @@ -{ - "requests": [ - { - "request_id": "req_0001", - "timestamp": "2026-01-04T21:51:48.287782", - "player_name": "shelly", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - }, - "response": { - "internal_thinking": "It's the SETUP_FIRST_ROUND phase, and shon is placing their first settlement. I am shelly, the third player to place. My strategy is to secure a strong resource production, prioritizing Wheat and Ore for future cities and development cards, while also considering good numbers (6, 8, 5, 9) and resource diversity. I will also look for port access. My top preferred settlement spots are: 1. Node 50 (Wh9, O5, ?3 Port) - excellent Ore and Wheat production with a useful port. 2. Node 41 (O5, Wh9, B10) - a balanced mix of Ore, Wheat, and Brick with strong numbers. 3. Node 42 (Wh9, O5, Wh9) - very high Ore and Wheat production, though less resource diversity. 4. Node 21 (W11, B6, S8) - a strong general production spot for Wood, Brick, and Sheep, which would be a solid fallback if all high Wh/O spots are taken. I anticipate shon and ziv will take some of these prime locations, so I will select the best available option from my preferred list when it is my turn to place." - }, - "raw_response": "{\"internal_thinking\": \"It's the SETUP_FIRST_ROUND phase, and shon is placing their first settlement. I am shelly, the third player to place. My strategy is to secure a strong resource production, prioritizing Wheat and Ore for future cities and development cards, while also considering good numbers (6, 8, 5, 9) and resource diversity. I will also look for port access. My top preferred settlement spots are: 1. Node 50 (Wh9, O5, ?3 Port) - excellent Ore and Wheat production with a useful port. 2. Node 41 (O5, Wh9, B10) - a balanced mix of Ore, Wheat, and Brick with strong numbers. 3. Node 42 (Wh9, O5, Wh9) - very high Ore and Wheat production, though less resource diversity. 4. Node 21 (W11, B6, S8) - a strong general production spot for Wood, Brick, and Sheep, which would be a solid fallback if all high Wh/O spots are taken. I anticipate shon and ziv will take some of these prime locations, so I will select the best available option from my preferred list when it is my turn to place.\"}", - "metadata": { - "request_num": 1, - "timestamp": "2026-01-04 21:51:48", - "model": "models/gemini-2.5-flash", - "latency_seconds": 21.796142101287842, - "total_tokens": 936, - "prompt_tokens": 687, - "completion_tokens": 249, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-04T21:52:10.095963" - }, - { - "request_id": "req_0002", - "timestamp": "2026-01-04T21:51:48.288312", - "player_name": "shon", - "trigger": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - }, - "response": { - "internal_thinking": "My goal is to place the first settlement on a node that maximizes immediate resource production and provides a good mix of resources for early game expansion. I analyzed nodes based on adjacent hexes' resources and dice probabilities (prioritizing 6, 8, 5, 9). Node 10 (Brick 6, Sheep 8, Wood 12) stands out. It offers diverse resources (Wood, Brick, Sheep) essential for building roads and additional settlements, and has two high-probability numbers (6 and 8), giving it a high total pip count (12). This provides a strong foundation for the start of the game.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "10" - } - } - }, - "raw_response": "{\n \"internal_thinking\": \"My goal is to place the first settlement on a node that maximizes immediate resource production and provides a good mix of resources for early game expansion. I analyzed nodes based on adjacent hexes' resources and dice probabilities (prioritizing 6, 8, 5, 9). Node 10 (Brick 6, Sheep 8, Wood 12) stands out. It offers diverse resources (Wood, Brick, Sheep) essential for building roads and additional settlements, and has two high-probability numbers (6 and 8), giving it a high total pip count (12). This provides a strong foundation for the start of the game.\",\n \"action\": {\n \"type\": \"place_settlement\",\n \"parameters\": {\n \"location\": \"10\"\n }\n }\n}", - "metadata": { - "request_num": 1, - "timestamp": "2026-01-04 21:51:48", - "model": "models/gemini-2.5-flash", - "latency_seconds": 18.57251214981079, - "total_tokens": 1002, - "prompt_tokens": 830, - "completion_tokens": 172, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-04T21:52:06.876115" - }, - { - "request_id": "req_0003", - "timestamp": "2026-01-04T21:51:48.289012", - "player_name": "ziv", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - }, - "response": { - "internal_thinking": "Player shon is placing their first settlement. I need to identify the best available spots for my first settlement, prioritizing high-probability numbers (6, 8, 5, 9) and diverse resources (Wood, Brick, Wheat, Sheep, Ore). My top candidate nodes are: 1. Node 21 (W11, B6, S8) for Wood, Brick, Sheep with numbers 11,6,8. 2. Node 10 (B6, S8, W12) for Brick, Sheep, Wood with numbers 6,8,12. 3. Node 41 (O5, Wh9, B10) for Ore, Wheat, Brick with numbers 5,9,10. These spots offer a strong resource mix for early expansion and development. I will observe shon's placement and pick the best remaining spot among these, or the next best alternative if all are taken." - }, - "raw_response": "{\"internal_thinking\": \"Player shon is placing their first settlement. I need to identify the best available spots for my first settlement, prioritizing high-probability numbers (6, 8, 5, 9) and diverse resources (Wood, Brick, Wheat, Sheep, Ore). My top candidate nodes are: 1. Node 21 (W11, B6, S8) for Wood, Brick, Sheep with numbers 11,6,8. 2. Node 10 (B6, S8, W12) for Brick, Sheep, Wood with numbers 6,8,12. 3. Node 41 (O5, Wh9, B10) for Ore, Wheat, Brick with numbers 5,9,10. These spots offer a strong resource mix for early expansion and development. I will observe shon's placement and pick the best remaining spot among these, or the next best alternative if all are taken.\"}", - "metadata": { - "request_num": 1, - "timestamp": "2026-01-04 21:51:48", - "model": "models/gemini-2.5-flash", - "latency_seconds": 18.035075902938843, - "total_tokens": 857, - "prompt_tokens": 686, - "completion_tokens": 171, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-04T21:52:06.338155" - }, - { - "request_id": "req_0004", - "timestamp": "2026-01-04T21:52:10.813054", - "player_name": "shon", - "trigger": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - }, - "response": { - "internal_thinking": "I am in the setup phase and need to place my first settlement. My strategy is to choose a node that provides a good mix of basic resources (Wood, Brick, Wheat, Sheep) with decent production numbers, prioritizing resources for expansion (roads and settlements). I will also consider potential spots for my second settlement to ensure a balanced resource income.I've analyzed several nodes:\n- Node 10 (B6, S8, W12): Produces Brick, Sheep, Wood with strong numbers (6, 8). Combined pips: 11. Lacks Wheat.\n- Node 19 (W11, B10, S8): Produces Wood, Brick, Sheep with good numbers (8, 10, 11). Combined pips: 10. Lacks Wheat.\n- Node 20 (W11, B6, S8): Produces Wood, Brick, Sheep with strong numbers (6, 8, 11). Combined pips: 12. Lacks Wheat.\n- Node 31 (Wh9, B10, W11): Produces Wheat, Brick, Wood with decent numbers (9, 10, 11). Combined pips: 9. Lacks Sheep.\n- Node 41 (O5, Wh9, B10): Produces Ore, Wheat, Brick with good numbers (5, 9, 10). Combined pips: 11. Lacks Wood, Sheep. This is good for cities but not ideal for a first settlement.\n\nComparing Node 10, 20, and 31:\nNodes 10 and 20 offer higher probability production (due to 6s and 8s) for Wood, Brick, and Sheep. However, they both lack Wheat.\nNode 31 offers Wood, Brick, and Wheat. This combination is ideal for early expansion, as Wood and Brick are needed for roads, and all three (plus Sheep) are needed for settlements. Wheat is also crucial for future city upgrades.\n\nWhile Node 10/20 have slightly higher overall production pips, Node 31's resource synergy for immediate building is more valuable for the first settlement. I can aim to get Sheep with my second settlement. For instance, Node 10 (B6, S8, W12) would be an excellent complementary second settlement to Node 31, providing Sheep and high-probability numbers, giving me all four basic resources.\n\nTherefore, I choose Node 31 for its strategic resource combination (W, B, Wh) which sets me up well for immediate expansion and future development, even if the individual production numbers are slightly lower than other options.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "31" - } - } - }, - "raw_response": "{\n \"internal_thinking\": \"I am in the setup phase and need to place my first settlement. My strategy is to choose a node that provides a good mix of basic resources (Wood, Brick, Wheat, Sheep) with decent production numbers, prioritizing resources for expansion (roads and settlements). I will also consider potential spots for my second settlement to ensure a balanced resource income.I've analyzed several nodes:\\n- Node 10 (B6, S8, W12): Produces Brick, Sheep, Wood with strong numbers (6, 8). Combined pips: 11. Lacks Wheat.\\n- Node 19 (W11, B10, S8): Produces Wood, Brick, Sheep with good numbers (8, 10, 11). Combined pips: 10. Lacks Wheat.\\n- Node 20 (W11, B6, S8): Produces Wood, Brick, Sheep with strong numbers (6, 8, 11). Combined pips: 12. Lacks Wheat.\\n- Node 31 (Wh9, B10, W11): Produces Wheat, Brick, Wood with decent numbers (9, 10, 11). Combined pips: 9. Lacks Sheep.\\n- Node 41 (O5, Wh9, B10): Produces Ore, Wheat, Brick with good numbers (5, 9, 10). Combined pips: 11. Lacks Wood, Sheep. This is good for cities but not ideal for a first settlement.\\n\\nComparing Node 10, 20, and 31:\\nNodes 10 and 20 offer higher probability production (due to 6s and 8s) for Wood, Brick, and Sheep. However, they both lack Wheat.\\nNode 31 offers Wood, Brick, and Wheat. This combination is ideal for early expansion, as Wood and Brick are needed for roads, and all three (plus Sheep) are needed for settlements. Wheat is also crucial for future city upgrades.\\n\\nWhile Node 10/20 have slightly higher overall production pips, Node 31's resource synergy for immediate building is more valuable for the first settlement. I can aim to get Sheep with my second settlement. For instance, Node 10 (B6, S8, W12) would be an excellent complementary second settlement to Node 31, providing Sheep and high-probability numbers, giving me all four basic resources.\\n\\nTherefore, I choose Node 31 for its strategic resource combination (W, B, Wh) which sets me up well for immediate expansion and future development, even if the individual production numbers are slightly lower than other options.\",\n \"action\": {\n \"type\": \"place_settlement\",\n \"parameters\": {\n \"location\": \"31\"\n }\n }\n}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-04 21:52:10", - "model": "models/gemini-2.5-flash", - "latency_seconds": 26.654208183288574, - "total_tokens": 1377, - "prompt_tokens": 830, - "completion_tokens": 547, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-04T21:52:37.480437" - }, - { - "request_id": "req_0005", - "timestamp": "2026-01-04T21:52:10.813425", - "player_name": "shelly", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - }, - "response": { - "internal_thinking": "Player shon is placing their first settlement. I am shelly, the third player in the first setup round. My strategy is to secure a high-yield, diverse starting position. I will prioritize nodes adjacent to 6s and 8s, aiming for Wood, Brick, Sheep, and Wheat. Good spots include N[10] (B6, S8, W12), N[20] (B6, S8, W11), N[19] (S8, B10, W11), and N[31] (Wh9, B10, W11). I anticipate shon and ziv will take some of the best W/B/S spots. My primary goal will be to pick the best remaining spot to get at least 3 core resources (W, B, S, Wh) with high production. For my second settlement, I will aim to round out my resources and potentially get access to Ore or a useful port. I am currently waiting for shon's move." - }, - "raw_response": "{\"internal_thinking\": \"Player shon is placing their first settlement. I am shelly, the third player in the first setup round. My strategy is to secure a high-yield, diverse starting position. I will prioritize nodes adjacent to 6s and 8s, aiming for Wood, Brick, Sheep, and Wheat. Good spots include N[10] (B6, S8, W12), N[20] (B6, S8, W11), N[19] (S8, B10, W11), and N[31] (Wh9, B10, W11). I anticipate shon and ziv will take some of the best W/B/S spots. My primary goal will be to pick the best remaining spot to get at least 3 core resources (W, B, S, Wh) with high production. For my second settlement, I will aim to round out my resources and potentially get access to Ore or a useful port. I am currently waiting for shon's move.\"}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-04 21:52:10", - "model": "models/gemini-2.5-flash", - "latency_seconds": 26.37698984146118, - "total_tokens": 871, - "prompt_tokens": 687, - "completion_tokens": 184, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-04T21:52:37.212485" - }, - { - "request_id": "req_0006", - "timestamp": "2026-01-04T21:52:10.816681", - "player_name": "ziv", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - }, - "response": { - "internal_thinking": "Player shon is placing their first settlement. I am waiting for my turn. My strategy for my first settlement is to secure a node with high-probability numbers and a good mix of starting resources (wood, brick, sheep, wheat). Node 10 (B6, S8, W12) looks like a very strong candidate, providing Brick, Sheep, and Wood with 6 and 8 numbers. I will observe shon's placement and adjust if needed, but Node 10 is my primary target.", - "note_to_self": "", - "say_outloud": "" - }, - "raw_response": "{\"internal_thinking\": \"Player shon is placing their first settlement. I am waiting for my turn. My strategy for my first settlement is to secure a node with high-probability numbers and a good mix of starting resources (wood, brick, sheep, wheat). Node 10 (B6, S8, W12) looks like a very strong candidate, providing Brick, Sheep, and Wood with 6 and 8 numbers. I will observe shon's placement and adjust if needed, but Node 10 is my primary target.\",\"note_to_self\": \"\",\"say_outloud\": \"\"}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-04 21:52:10", - "model": "models/gemini-2.5-flash", - "latency_seconds": 9.491818189620972, - "total_tokens": 807, - "prompt_tokens": 686, - "completion_tokens": 121, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-04T21:52:20.317523" - } - ], - "total_count": 6, - "last_updated": "2026-01-04T21:52:37.480542" -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_1.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_1.json deleted file mode 100644 index 7182768ff1111af0b116d3bbc61a8528f8e68a1b..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_1.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_1.txt b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_1.txt deleted file mode 100644 index cfc17d44c1cac01cb499ca76d264976b9c93702a..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_1.txt +++ /dev/null @@ -1,56 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHELLY -Prompt #1 -Generated: 2026-01-04 21:51:47 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_2.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_2.json deleted file mode 100644 index 7182768ff1111af0b116d3bbc61a8528f8e68a1b..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_2.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_2.txt b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_2.txt deleted file mode 100644 index 7de63316da1cbf0707cb7127aeb835ed978670f5..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shelly/prompts/prompt_2.txt +++ /dev/null @@ -1,56 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHELLY -Prompt #2 -Generated: 2026-01-04 21:51:49 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shelly", - "role": "You are player 'shelly'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_1.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_1.json deleted file mode 100644 index 522136e22b157d3f4d4f47edf2641d50bb706b11..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_1.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_1.txt b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_1.txt deleted file mode 100644 index 585dd3baa86328fd561aad0fd79a9457a1719976..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_1.txt +++ /dev/null @@ -1,115 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #1 -Generated: 2026-01-04 21:51:47 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_2.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_2.json deleted file mode 100644 index 522136e22b157d3f4d4f47edf2641d50bb706b11..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_2.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_2.txt b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_2.txt deleted file mode 100644 index 603b695aa47e85c309fcf4680dfec39f561b8b1f..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/shon/prompts/prompt_2.txt +++ /dev/null @@ -1,115 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #2 -Generated: 2026-01-04 21:51:49 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_1.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_1.json deleted file mode 100644 index 282f9b8a441fc99eae68434d744b567f4f881c12..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_1.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_1.txt b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_1.txt deleted file mode 100644 index c53990b01bb647545fefc4da1a69101855b99c26..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_1.txt +++ /dev/null @@ -1,56 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER ZIV -Prompt #1 -Generated: 2026-01-04 21:51:47 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_2.json b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_2.json deleted file mode 100644 index 282f9b8a441fc99eae68434d744b567f4f881c12..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_2.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_2.txt b/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_2.txt deleted file mode 100644 index 254cdec031d455ffa43a18320d9576550a84f61b..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260104_215128/ziv/prompts/prompt_2.txt +++ /dev/null @@ -1,56 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER ZIV -Prompt #2 -Generated: 2026-01-04 21:51:49 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "ziv", - "role": "You are player 'ziv'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"ziv\":{\"vp\":0,\"res\":{}},\"shelly\":{\"vp\":0,\"res\":{}}}}" -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/agent_memories.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/agent_memories.json deleted file mode 100644 index f2cc9f0c51a670e106afb98fed0cbd97964a27d7..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/agent_memories.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "shon": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers.", - "dudu": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port." -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/chat_history.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/chat_history.json deleted file mode 100644 index 9f1c422d515f408fbc6fb1667c31eaf16b368edd..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/chat_history.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "messages": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_1.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_1.json deleted file mode 100644 index 63afb6724fc9ff84adda73704644c8e43c946d11..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_1.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_1.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_1.txt deleted file mode 100644 index 305e6da7fb60a1c3434775e47b307c9939eaca24..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_1.txt +++ /dev/null @@ -1,56 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER DUDU -Prompt #1 -Generated: 2026-01-08 13:56:41 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_2.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_2.json deleted file mode 100644 index 63afb6724fc9ff84adda73704644c8e43c946d11..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_2.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_2.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_2.txt deleted file mode 100644 index 0a3bbafd621ad36e247c00ec445ea4e0bf1b19c0..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_2.txt +++ /dev/null @@ -1,56 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER DUDU -Prompt #2 -Generated: 2026-01-08 13:56:44 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_3.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_3.json deleted file mode 100644 index 1858c2fe9378cec5a4d9ab374c6b2edd5eb2a38f..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_3.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_3.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_3.txt deleted file mode 100644 index 67007ae907f73fbba171528710a8d64ac6d6ee61..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_3.txt +++ /dev/null @@ -1,65 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER DUDU -Prompt #3 -Generated: 2026-01-08 13:57:00 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_4.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_4.json deleted file mode 100644 index 6acf31028da4e06549060203e7d5fba1cf5510fa..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_4.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_4.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_4.txt deleted file mode 100644 index 2d887a2c69640b23b4728dcd1ced0b7c7de144d5..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_4.txt +++ /dev/null @@ -1,65 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER DUDU -Prompt #4 -Generated: 2026-01-08 13:57:14 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_5.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_5.json deleted file mode 100644 index 6acf31028da4e06549060203e7d5fba1cf5510fa..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_5.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_5.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_5.txt deleted file mode 100644 index 48557ba2ef9cbb600cce72e35388b2efcfa35f0b..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_5.txt +++ /dev/null @@ -1,65 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER DUDU -Prompt #5 -Generated: 2026-01-08 13:57:26 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_6.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_6.json deleted file mode 100644 index 11c598754bd28bd6a4defe40d228e45f6a03f478..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_6.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] - }, - "system_instruction": "You are observing the game while waiting for your turn. Track what's happening, plan your strategy, and you can communicate with other players.", - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] - }, - "memory": { - "previous_note_to_self": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port." - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_6.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_6.txt deleted file mode 100644 index c05f89c8082c12d8116c4903501ccf57426e9360..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/dudu/prompts/prompt_6.txt +++ /dev/null @@ -1,73 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER DUDU -Prompt #6 -Generated: 2026-01-08 13:58:13 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] - }, - "memory": { - "previous_note_to_self": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port." - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/player_dudu.md b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/player_dudu.md deleted file mode 100644 index 3739682ecdad3b9042f934b03104749f218159bd..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/player_dudu.md +++ /dev/null @@ -1,396 +0,0 @@ -# 🤖 AI Agent Log - Player DUDU - ---- - -**Session:** `session_20260108_135628` - -**Model:** `models/gemini-2.5-flash` - -**Started:** 2026-01-08 13:56:42 - ---- - - -## 🔄 Request #1 - -**Timestamp:** 2026-01-08 13:56:42 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" -} -``` -
- - -### ✅ Response Received - -- **Latency:** 17.63s -- **Tokens:** 810 (prompt: 678, completion: 132) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking": "Player shon is placing their first settlement. I need to observe their choice to adjust my strategy. My top priority settlement spots are Node 10 (B6, S8, W12) and Node 21 (W11, B6, S8) due to their high-probability numbers and diverse resources (wood, brick, sheep). If shon takes one, I'll aim for the other or a similarly strong spot like Node 11 (B6, S5, W12). For my second settlement, I'll look to diversify resources, potentially targeting ore/wheat or a useful port.", "say_outloud": "No message."} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> Player shon is placing their first settlement. I need to observe their choice to adjust my strategy. My top priority settlement spots are Node 10 (B6, S8, W12) and Node 21 (W11, B6, S8) due to their high-probability numbers and diverse resources (wood, brick, sheep). If shon takes one, I'll aim for the other or a similarly strong spot like Node 11 (B6, S5, W12). For my second settlement, I'll look to diversify resources, potentially targeting ore/wheat or a useful port. - -#### 💬 Says Out Loud - -**"No message."** - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "Player shon is placing their first settlement. I need to observe their choice to adjust my strategy. My top priority settlement spots are Node 10 (B6, S8, W12) and Node 21 (W11, B6, S8) due to their high-probability numbers and diverse resources (wood, brick, sheep). If shon takes one, I'll aim for the other or a similarly strong spot like Node 11 (B6, S5, W12). For my second settlement, I'll look to diversify resources, potentially targeting ore/wheat or a useful port.", - "say_outloud": "No message." -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-08 13:57:00 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" -} -``` -
- - -### ✅ Response Received - -- **Latency:** 34.11s -- **Tokens:** 905 (prompt: 678, completion: 227) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking":"Player 'shon' is placing their first settlement. I need to observe their choice to inform my own strategy. I anticipate 'shon' will prioritize a spot with high-probability numbers and diverse resources. Two strong options for 'shon' are Node 20 (W11, B6, S8) with 13 pips (Wood, Brick, Sheep) or Node 41 (O5, Wh9, B10) with 11 pips (Ore, Wheat, Brick). Node 20 offers a slightly higher pip count and a balanced mix of basic resources crucial for early expansion and development cards. Node 41 is excellent for city building. I predict 'shon' will choose Node 20 for its superior overall production and versatility early game. If 'shon' picks Node 20, I will aim for a spot with Wheat and Ore, like Node 41, for my first settlement.","note_to_self":"Shon will likely pick Node 20 (W11, B6, S8). My target for first settlement will be Node 41 (O5, Wh9, B10) if available.","say_outloud":""} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> Player 'shon' is placing their first settlement. I need to observe their choice to inform my own strategy. I anticipate 'shon' will prioritize a spot with high-probability numbers and diverse resources. Two strong options for 'shon' are Node 20 (W11, B6, S8) with 13 pips (Wood, Brick, Sheep) or Node 41 (O5, Wh9, B10) with 11 pips (Ore, Wheat, Brick). Node 20 offers a slightly higher pip count and a balanced mix of basic resources crucial for early expansion and development cards. Node 41 is excellent for city building. I predict 'shon' will choose Node 20 for its superior overall production and versatility early game. If 'shon' picks Node 20, I will aim for a spot with Wheat and Ore, like Node 41, for my first settlement. - -#### 📝 Note to Self - -*"Shon will likely pick Node 20 (W11, B6, S8). My target for first settlement will be Node 41 (O5, Wh9, B10) if available."* - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "Player 'shon' is placing their first settlement. I need to observe their choice to inform my own strategy. I anticipate 'shon' will prioritize a spot with high-probability numbers and diverse resources. Two strong options for 'shon' are Node 20 (W11, B6, S8) with 13 pips (Wood, Brick, Sheep) or Node 41 (O5, Wh9, B10) with 11 pips (Ore, Wheat, Brick). Node 20 offers a slightly higher pip count and a balanced mix of basic resources crucial for early expansion and development cards. Node 41 is excellent for city building. I predict 'shon' will choose Node 20 for its superior overall production and versatility early game. If 'shon' picks Node 20, I will aim for a spot with Wheat and Ore, like Node 41, for my first settlement.", - "note_to_self": "Shon will likely pick Node 20 (W11, B6, S8). My target for first settlement will be Node 41 (O5, Wh9, B10) if available.", - "say_outloud": "" -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-08 13:57:35 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 34.66s -- **Tokens:** 945 (prompt: 702, completion: 243) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking":"Player shon is placing their first settlement. I need to identify the best available spots for my two settlements, prioritizing high-pip value and diverse resource production, while also considering future expansion and port access. My primary targets for the first settlement are Node 31 (Wh9, B10, W11, Pips: 30) for its strong W,B,Wh production, or Node 19 (W11, B10, S8, Pips: 29) for W,B,S. Node 31 is slightly preferred due to Wheat for cities/dev cards and its potential synergy with Node 41 (O5, Wh9, B10, Pips: 24, near W2 port) as a second settlement, which would provide all 5 resources. If Shon takes one of these, I will adapt my choice, aiming to secure a good mix of basic resources (Wood, Brick, Wheat, Sheep) and potentially Ore. My road placement will aim towards a complementary second settlement location.","note_to_self":"Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port.","say_outloud":""} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> Player shon is placing their first settlement. I need to identify the best available spots for my two settlements, prioritizing high-pip value and diverse resource production, while also considering future expansion and port access. My primary targets for the first settlement are Node 31 (Wh9, B10, W11, Pips: 30) for its strong W,B,Wh production, or Node 19 (W11, B10, S8, Pips: 29) for W,B,S. Node 31 is slightly preferred due to Wheat for cities/dev cards and its potential synergy with Node 41 (O5, Wh9, B10, Pips: 24, near W2 port) as a second settlement, which would provide all 5 resources. If Shon takes one of these, I will adapt my choice, aiming to secure a good mix of basic resources (Wood, Brick, Wheat, Sheep) and potentially Ore. My road placement will aim towards a complementary second settlement location. - -#### 📝 Note to Self - -*"Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port."* - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "Player shon is placing their first settlement. I need to identify the best available spots for my two settlements, prioritizing high-pip value and diverse resource production, while also considering future expansion and port access. My primary targets for the first settlement are Node 31 (Wh9, B10, W11, Pips: 30) for its strong W,B,Wh production, or Node 19 (W11, B10, S8, Pips: 29) for W,B,S. Node 31 is slightly preferred due to Wheat for cities/dev cards and its potential synergy with Node 41 (O5, Wh9, B10, Pips: 24, near W2 port) as a second settlement, which would provide all 5 resources. If Shon takes one of these, I will adapt my choice, aiming to secure a good mix of basic resources (Wood, Brick, Wheat, Sheep) and potentially Ore. My road placement will aim towards a complementary second settlement location.", - "note_to_self": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port.", - "say_outloud": "" -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-08 13:58:14 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Track what's happening. What are opponents doing? What's your strategy for next turn?", - "minLength": 30 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "Optional message to other players (max 100 chars). Propose trades or negotiate. You pay for this.", - "maxLength": 100 - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] - }, - "memory": { - "previous_note_to_self": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port." - } -} -``` -
- diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/player_shon.md b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/player_shon.md deleted file mode 100644 index 5d0ac561b4a756d27bdfeb9f30a3a2213071158f..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/player_shon.md +++ /dev/null @@ -1,721 +0,0 @@ -# 🤖 AI Agent Log - Player SHON - ---- - -**Session:** `session_20260108_135628` - -**Model:** `models/gemini-2.5-flash` - -**Started:** 2026-01-08 13:56:42 - ---- - - -## 🔄 Request #1 - -**Timestamp:** 2026-01-08 13:56:42 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 16.58s -- **Tokens:** 964 (prompt: 822, completion: 142) - -
-📥 Raw Response from Gemini - -```json -{ - "internal_thinking": "I am in the setup phase and need to place my first settlement. My strategy is to prioritize nodes with high-probability numbers (6s and 8s) and diverse resources. I've analyzed several nodes and Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong combination of Brick 6 and Sheep 8, which are excellent numbers, along with Wood 11 for good resource diversity (W, B, S). This will provide a solid foundation for early game resource generation.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - } -} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> I am in the setup phase and need to place my first settlement. My strategy is to prioritize nodes with high-probability numbers (6s and 8s) and diverse resources. I've analyzed several nodes and Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong combination of Brick 6 and Sheep 8, which are excellent numbers, along with Wood 11 for good resource diversity (W, B, S). This will provide a solid foundation for early game resource generation. - -#### 🎮 Action - -- **Type:** `place_settlement` - -- **Parameters:** `{'location': '20'}` - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "I am in the setup phase and need to place my first settlement. My strategy is to prioritize nodes with high-probability numbers (6s and 8s) and diverse resources. I've analyzed several nodes and Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong combination of Brick 6 and Sheep 8, which are excellent numbers, along with Wood 11 for good resource diversity (W, B, S). This will provide a solid foundation for early game resource generation.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - } -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-08 13:57:00 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 25.87s -- **Tokens:** 1120 (prompt: 845, completion: 275) - -
-📥 Raw Response from Gemini - -```json -{ - "internal_thinking": "I am in the setup phase and need to place my first settlement. I analyzed the available nodes and their connected hexes, prioritizing high-probability dice rolls (6, 8, 5, 9) and resource diversity. Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong production probability with 12 pips (5+5+2) and provides Wood and Brick, which are crucial for early expansion (roads and settlements), along with Sheep. This gives me a solid base for growth. Node 41 (Ore 5, Wheat 9, Brick 10) was also a strong contender, offering Ore and Wheat essential for cities and development cards, with 11 pips (4+4+3). For the first settlement, I'm prioritizing immediate expansion resources (Wood, Brick, Sheep) over later-game resources (Ore, Wheat), with the plan to secure Ore and Wheat with my second settlement.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - }, - "note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." -} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> I am in the setup phase and need to place my first settlement. I analyzed the available nodes and their connected hexes, prioritizing high-probability dice rolls (6, 8, 5, 9) and resource diversity. Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong production probability with 12 pips (5+5+2) and provides Wood and Brick, which are crucial for early expansion (roads and settlements), along with Sheep. This gives me a solid base for growth. Node 41 (Ore 5, Wheat 9, Brick 10) was also a strong contender, offering Ore and Wheat essential for cities and development cards, with 11 pips (4+4+3). For the first settlement, I'm prioritizing immediate expansion resources (Wood, Brick, Sheep) over later-game resources (Ore, Wheat), with the plan to secure Ore and Wheat with my second settlement. - -#### 📝 Note to Self - -*"My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers."* - -#### 🎮 Action - -- **Type:** `place_settlement` - -- **Parameters:** `{'location': '20'}` - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "I am in the setup phase and need to place my first settlement. I analyzed the available nodes and their connected hexes, prioritizing high-probability dice rolls (6, 8, 5, 9) and resource diversity. Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong production probability with 12 pips (5+5+2) and provides Wood and Brick, which are crucial for early expansion (roads and settlements), along with Sheep. This gives me a solid base for growth. Node 41 (Ore 5, Wheat 9, Brick 10) was also a strong contender, offering Ore and Wheat essential for cities and development cards, with 11 pips (4+4+3). For the first settlement, I'm prioritizing immediate expansion resources (Wood, Brick, Sheep) over later-game resources (Ore, Wheat), with the plan to secure Ore and Wheat with my second settlement.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - }, - "note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-08 13:57:35 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 37.86s -- **Tokens:** 1135 (prompt: 822, completion: 313) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking": "My goal is to place the first settlement on a strategic location that provides a good mix of resources for early game development and has high production probability. I've analyzed all nodes with 3 adjacent hexes, calculating their total 'pip' value (sum of pips for each number, indicating production likelihood) and resource diversity. The critical resources for early game are Wood, Brick, and Sheep for building roads and additional settlements, followed by Wheat for versatility and Ore for cities and development cards later on. I identified Node 20 as the optimal choice. It connects to Hex 9 (W11), Hex 5 (B6), and Hex 4 (S8), providing Wood, Brick, and Sheep, respectively. The total pip value is 2 (W11) + 5 (B6) + 5 (S8) = 12, which is excellent. This combination gives me all three essential early-game resources with strong production potential, setting me up well for immediate expansion. For my second settlement, I will aim for a location that provides Wheat and Ore, like Node 41 (O5, B10, Wh9), to complete my resource set and ensure a balanced economy.", "action": {"type": "place_settlement", "parameters": {"location": "20"}}, "say_outloud": "I'm starting strong with a balanced resource income. Let's build!"} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> My goal is to place the first settlement on a strategic location that provides a good mix of resources for early game development and has high production probability. I've analyzed all nodes with 3 adjacent hexes, calculating their total 'pip' value (sum of pips for each number, indicating production likelihood) and resource diversity. The critical resources for early game are Wood, Brick, and Sheep for building roads and additional settlements, followed by Wheat for versatility and Ore for cities and development cards later on. I identified Node 20 as the optimal choice. It connects to Hex 9 (W11), Hex 5 (B6), and Hex 4 (S8), providing Wood, Brick, and Sheep, respectively. The total pip value is 2 (W11) + 5 (B6) + 5 (S8) = 12, which is excellent. This combination gives me all three essential early-game resources with strong production potential, setting me up well for immediate expansion. For my second settlement, I will aim for a location that provides Wheat and Ore, like Node 41 (O5, B10, Wh9), to complete my resource set and ensure a balanced economy. - -#### 💬 Says Out Loud - -**"I'm starting strong with a balanced resource income. Let's build!"** - -#### 🎮 Action - -- **Type:** `place_settlement` - -- **Parameters:** `{'location': '20'}` - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "My goal is to place the first settlement on a strategic location that provides a good mix of resources for early game development and has high production probability. I've analyzed all nodes with 3 adjacent hexes, calculating their total 'pip' value (sum of pips for each number, indicating production likelihood) and resource diversity. The critical resources for early game are Wood, Brick, and Sheep for building roads and additional settlements, followed by Wheat for versatility and Ore for cities and development cards later on. I identified Node 20 as the optimal choice. It connects to Hex 9 (W11), Hex 5 (B6), and Hex 4 (S8), providing Wood, Brick, and Sheep, respectively. The total pip value is 2 (W11) + 5 (B6) + 5 (S8) = 12, which is excellent. This combination gives me all three essential early-game resources with strong production potential, setting me up well for immediate expansion. For my second settlement, I will aim for a location that provides Wheat and Ore, like Node 41 (O5, B10, Wh9), to complete my resource set and ensure a balanced economy.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - }, - "say_outloud": "I'm starting strong with a balanced resource income. Let's build!" -} -``` -
- - -## 🔄 Request #2 - -**Timestamp:** 2026-01-08 13:58:14 - - -
-📋 Expected Response Schema - -```json -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} -``` -
- -
-📤 Prompt Sent to Gemini - -```json -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "memory": { - "previous_note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} -``` -
- - -### ✅ Response Received - -- **Latency:** 25.27s -- **Tokens:** 1062 (prompt: 899, completion: 163) - -
-📥 Raw Response from Gemini - -```json -{"internal_thinking":"My first settlement is at node 20, providing Wood (11), Brick (6), and Sheep (8). To diversify my resource production and enable future expansion, I need to secure Ore and Wheat. My long-term plan is to aim for Node 41 (Ore 5, Wheat 9, Brick 10) for my second settlement, as identified in my previous note to self. Building a road from node 20 to node 19 is the first step towards this goal, as it opens up a path towards Node 30 and subsequently Node 41. Node 19 itself connects to good resources (Wood 11, Brick 10, Sheep 8) and is part of a promising expansion route.","action":{"type":"build_road","parameters":{"target":"19"}}} -``` -
- - -### ✅ Parse Success - - -### 🎯 AI Response - -#### 💭 Internal Thinking - -> My first settlement is at node 20, providing Wood (11), Brick (6), and Sheep (8). To diversify my resource production and enable future expansion, I need to secure Ore and Wheat. My long-term plan is to aim for Node 41 (Ore 5, Wheat 9, Brick 10) for my second settlement, as identified in my previous note to self. Building a road from node 20 to node 19 is the first step towards this goal, as it opens up a path towards Node 30 and subsequently Node 41. Node 19 itself connects to good resources (Wood 11, Brick 10, Sheep 8) and is part of a promising expansion route. - -#### 🎮 Action - -- **Type:** `build_road` - -- **Parameters:** `{'target': '19'}` - - -
-🔍 Raw JSON (Debug) - -```json -{ - "internal_thinking": "My first settlement is at node 20, providing Wood (11), Brick (6), and Sheep (8). To diversify my resource production and enable future expansion, I need to secure Ore and Wheat. My long-term plan is to aim for Node 41 (Ore 5, Wheat 9, Brick 10) for my second settlement, as identified in my previous note to self. Building a road from node 20 to node 19 is the first step towards this goal, as it opens up a path towards Node 30 and subsequently Node 41. Node 19 itself connects to good resources (Wood 11, Brick 10, Sheep 8) and is part of a promising expansion route.", - "action": { - "type": "build_road", - "parameters": { - "target": "19" - } - } -} -``` -
- diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/requests.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/requests.json deleted file mode 100644 index ef872aed61aecd459fc02ba48d0667e4dc162909..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/requests.json +++ /dev/null @@ -1,441 +0,0 @@ -{ - "requests": [ - { - "request_id": "req_0001", - "timestamp": "2026-01-08T13:56:42.513764", - "player_name": "dudu", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" - }, - "response": { - "internal_thinking": "Player shon is placing their first settlement. I need to observe their choice to adjust my strategy. My top priority settlement spots are Node 10 (B6, S8, W12) and Node 21 (W11, B6, S8) due to their high-probability numbers and diverse resources (wood, brick, sheep). If shon takes one, I'll aim for the other or a similarly strong spot like Node 11 (B6, S5, W12). For my second settlement, I'll look to diversify resources, potentially targeting ore/wheat or a useful port.", - "say_outloud": "No message." - }, - "raw_response": "{\"internal_thinking\": \"Player shon is placing their first settlement. I need to observe their choice to adjust my strategy. My top priority settlement spots are Node 10 (B6, S8, W12) and Node 21 (W11, B6, S8) due to their high-probability numbers and diverse resources (wood, brick, sheep). If shon takes one, I'll aim for the other or a similarly strong spot like Node 11 (B6, S5, W12). For my second settlement, I'll look to diversify resources, potentially targeting ore/wheat or a useful port.\", \"say_outloud\": \"No message.\"}", - "metadata": { - "request_num": 1, - "timestamp": "2026-01-08 13:56:42", - "model": "models/gemini-2.5-flash", - "latency_seconds": 17.631365299224854, - "total_tokens": 810, - "prompt_tokens": 678, - "completion_tokens": 132, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:57:00.160106" - }, - { - "request_id": "req_0002", - "timestamp": "2026-01-08T13:56:42.514013", - "player_name": "shon", - "trigger": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - }, - "response": { - "internal_thinking": "I am in the setup phase and need to place my first settlement. My strategy is to prioritize nodes with high-probability numbers (6s and 8s) and diverse resources. I've analyzed several nodes and Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong combination of Brick 6 and Sheep 8, which are excellent numbers, along with Wood 11 for good resource diversity (W, B, S). This will provide a solid foundation for early game resource generation.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - } - }, - "raw_response": "{\n \"internal_thinking\": \"I am in the setup phase and need to place my first settlement. My strategy is to prioritize nodes with high-probability numbers (6s and 8s) and diverse resources. I've analyzed several nodes and Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong combination of Brick 6 and Sheep 8, which are excellent numbers, along with Wood 11 for good resource diversity (W, B, S). This will provide a solid foundation for early game resource generation.\",\n \"action\": {\n \"type\": \"place_settlement\",\n \"parameters\": {\n \"location\": \"20\"\n }\n }\n}", - "metadata": { - "request_num": 1, - "timestamp": "2026-01-08 13:56:42", - "model": "models/gemini-2.5-flash", - "latency_seconds": 16.58264183998108, - "total_tokens": 964, - "prompt_tokens": 822, - "completion_tokens": 142, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:56:59.107025" - }, - { - "request_id": "req_0003", - "timestamp": "2026-01-08T13:57:00.975236", - "player_name": "dudu", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}" - }, - "response": { - "internal_thinking": "Player 'shon' is placing their first settlement. I need to observe their choice to inform my own strategy. I anticipate 'shon' will prioritize a spot with high-probability numbers and diverse resources. Two strong options for 'shon' are Node 20 (W11, B6, S8) with 13 pips (Wood, Brick, Sheep) or Node 41 (O5, Wh9, B10) with 11 pips (Ore, Wheat, Brick). Node 20 offers a slightly higher pip count and a balanced mix of basic resources crucial for early expansion and development cards. Node 41 is excellent for city building. I predict 'shon' will choose Node 20 for its superior overall production and versatility early game. If 'shon' picks Node 20, I will aim for a spot with Wheat and Ore, like Node 41, for my first settlement.", - "note_to_self": "Shon will likely pick Node 20 (W11, B6, S8). My target for first settlement will be Node 41 (O5, Wh9, B10) if available.", - "say_outloud": "" - }, - "raw_response": "{\"internal_thinking\":\"Player 'shon' is placing their first settlement. I need to observe their choice to inform my own strategy. I anticipate 'shon' will prioritize a spot with high-probability numbers and diverse resources. Two strong options for 'shon' are Node 20 (W11, B6, S8) with 13 pips (Wood, Brick, Sheep) or Node 41 (O5, Wh9, B10) with 11 pips (Ore, Wheat, Brick). Node 20 offers a slightly higher pip count and a balanced mix of basic resources crucial for early expansion and development cards. Node 41 is excellent for city building. I predict 'shon' will choose Node 20 for its superior overall production and versatility early game. If 'shon' picks Node 20, I will aim for a spot with Wheat and Ore, like Node 41, for my first settlement.\",\"note_to_self\":\"Shon will likely pick Node 20 (W11, B6, S8). My target for first settlement will be Node 41 (O5, Wh9, B10) if available.\",\"say_outloud\":\"\"}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-08 13:57:00", - "model": "models/gemini-2.5-flash", - "latency_seconds": 34.109519720077515, - "total_tokens": 905, - "prompt_tokens": 678, - "completion_tokens": 227, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:57:35.093482" - }, - { - "request_id": "req_0004", - "timestamp": "2026-01-08T13:57:00.975346", - "player_name": "shon", - "trigger": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - }, - "response": { - "internal_thinking": "I am in the setup phase and need to place my first settlement. I analyzed the available nodes and their connected hexes, prioritizing high-probability dice rolls (6, 8, 5, 9) and resource diversity. Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong production probability with 12 pips (5+5+2) and provides Wood and Brick, which are crucial for early expansion (roads and settlements), along with Sheep. This gives me a solid base for growth. Node 41 (Ore 5, Wheat 9, Brick 10) was also a strong contender, offering Ore and Wheat essential for cities and development cards, with 11 pips (4+4+3). For the first settlement, I'm prioritizing immediate expansion resources (Wood, Brick, Sheep) over later-game resources (Ore, Wheat), with the plan to secure Ore and Wheat with my second settlement.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - }, - "note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "raw_response": "{\n \"internal_thinking\": \"I am in the setup phase and need to place my first settlement. I analyzed the available nodes and their connected hexes, prioritizing high-probability dice rolls (6, 8, 5, 9) and resource diversity. Node 20 (Wood 11, Brick 6, Sheep 8) offers a strong production probability with 12 pips (5+5+2) and provides Wood and Brick, which are crucial for early expansion (roads and settlements), along with Sheep. This gives me a solid base for growth. Node 41 (Ore 5, Wheat 9, Brick 10) was also a strong contender, offering Ore and Wheat essential for cities and development cards, with 11 pips (4+4+3). For the first settlement, I'm prioritizing immediate expansion resources (Wood, Brick, Sheep) over later-game resources (Ore, Wheat), with the plan to secure Ore and Wheat with my second settlement.\",\n \"action\": {\n \"type\": \"place_settlement\",\n \"parameters\": {\n \"location\": \"20\"\n }\n },\n \"note_to_self\": \"My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers.\"\n}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-08 13:57:00", - "model": "models/gemini-2.5-flash", - "latency_seconds": 25.873740673065186, - "total_tokens": 1120, - "prompt_tokens": 845, - "completion_tokens": 275, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:57:26.856683" - }, - { - "request_id": "req_0005", - "timestamp": "2026-01-08T13:57:35.877718", - "player_name": "dudu", - "trigger": "Player shon is placing their first settlement.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon is placing their first settlement.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - } - }, - "response": { - "internal_thinking": "Player shon is placing their first settlement. I need to identify the best available spots for my two settlements, prioritizing high-pip value and diverse resource production, while also considering future expansion and port access. My primary targets for the first settlement are Node 31 (Wh9, B10, W11, Pips: 30) for its strong W,B,Wh production, or Node 19 (W11, B10, S8, Pips: 29) for W,B,S. Node 31 is slightly preferred due to Wheat for cities/dev cards and its potential synergy with Node 41 (O5, Wh9, B10, Pips: 24, near W2 port) as a second settlement, which would provide all 5 resources. If Shon takes one of these, I will adapt my choice, aiming to secure a good mix of basic resources (Wood, Brick, Wheat, Sheep) and potentially Ore. My road placement will aim towards a complementary second settlement location.", - "note_to_self": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port.", - "say_outloud": "" - }, - "raw_response": "{\"internal_thinking\":\"Player shon is placing their first settlement. I need to identify the best available spots for my two settlements, prioritizing high-pip value and diverse resource production, while also considering future expansion and port access. My primary targets for the first settlement are Node 31 (Wh9, B10, W11, Pips: 30) for its strong W,B,Wh production, or Node 19 (W11, B10, S8, Pips: 29) for W,B,S. Node 31 is slightly preferred due to Wheat for cities/dev cards and its potential synergy with Node 41 (O5, Wh9, B10, Pips: 24, near W2 port) as a second settlement, which would provide all 5 resources. If Shon takes one of these, I will adapt my choice, aiming to secure a good mix of basic resources (Wood, Brick, Wheat, Sheep) and potentially Ore. My road placement will aim towards a complementary second settlement location.\",\"note_to_self\":\"Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port.\",\"say_outloud\":\"\"}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-08 13:57:35", - "model": "models/gemini-2.5-flash", - "latency_seconds": 34.657498836517334, - "total_tokens": 945, - "prompt_tokens": 702, - "completion_tokens": 243, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:58:10.545464" - }, - { - "request_id": "req_0006", - "timestamp": "2026-01-08T13:57:35.878646", - "player_name": "shon", - "trigger": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - }, - "response": { - "internal_thinking": "My goal is to place the first settlement on a strategic location that provides a good mix of resources for early game development and has high production probability. I've analyzed all nodes with 3 adjacent hexes, calculating their total 'pip' value (sum of pips for each number, indicating production likelihood) and resource diversity. The critical resources for early game are Wood, Brick, and Sheep for building roads and additional settlements, followed by Wheat for versatility and Ore for cities and development cards later on. I identified Node 20 as the optimal choice. It connects to Hex 9 (W11), Hex 5 (B6), and Hex 4 (S8), providing Wood, Brick, and Sheep, respectively. The total pip value is 2 (W11) + 5 (B6) + 5 (S8) = 12, which is excellent. This combination gives me all three essential early-game resources with strong production potential, setting me up well for immediate expansion. For my second settlement, I will aim for a location that provides Wheat and Ore, like Node 41 (O5, B10, Wh9), to complete my resource set and ensure a balanced economy.", - "action": { - "type": "place_settlement", - "parameters": { - "location": "20" - } - }, - "say_outloud": "I'm starting strong with a balanced resource income. Let's build!" - }, - "raw_response": "{\"internal_thinking\": \"My goal is to place the first settlement on a strategic location that provides a good mix of resources for early game development and has high production probability. I've analyzed all nodes with 3 adjacent hexes, calculating their total 'pip' value (sum of pips for each number, indicating production likelihood) and resource diversity. The critical resources for early game are Wood, Brick, and Sheep for building roads and additional settlements, followed by Wheat for versatility and Ore for cities and development cards later on. I identified Node 20 as the optimal choice. It connects to Hex 9 (W11), Hex 5 (B6), and Hex 4 (S8), providing Wood, Brick, and Sheep, respectively. The total pip value is 2 (W11) + 5 (B6) + 5 (S8) = 12, which is excellent. This combination gives me all three essential early-game resources with strong production potential, setting me up well for immediate expansion. For my second settlement, I will aim for a location that provides Wheat and Ore, like Node 41 (O5, B10, Wh9), to complete my resource set and ensure a balanced economy.\", \"action\": {\"type\": \"place_settlement\", \"parameters\": {\"location\": \"20\"}}, \"say_outloud\": \"I'm starting strong with a balanced resource income. Let's build!\"}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-08 13:57:35", - "model": "models/gemini-2.5-flash", - "latency_seconds": 37.86154556274414, - "total_tokens": 1135, - "prompt_tokens": 822, - "completion_tokens": 313, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:58:13.747960" - }, - { - "request_id": "req_0007", - "timestamp": "2026-01-08T13:58:14.543073", - "player_name": "dudu", - "trigger": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "dudu", - "role": "You are player 'dudu'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "Player shon placed their first settlement at node 20 and is now choosing where to place their starting road.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] - }, - "memory": { - "previous_note_to_self": "Prioritize N31 or N19 for first settlement. For second, aim for all 5 resources or a port." - } - }, - "response": null, - "raw_response": null, - "metadata": { - "request_num": 2, - "timestamp": "2026-01-08 13:58:14", - "model": "models/gemini-2.5-flash" - }, - "is_new": true - }, - { - "request_id": "req_0008", - "timestamp": "2026-01-08T13:58:14.544102", - "player_name": "shon", - "trigger": "You placed your first settlement at node 20. Now place a road connecting to it.", - "game_context": { - "phase": "Unknown", - "current_player": "Unknown" - }, - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "memory": { - "previous_note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - }, - "response": { - "internal_thinking": "My first settlement is at node 20, providing Wood (11), Brick (6), and Sheep (8). To diversify my resource production and enable future expansion, I need to secure Ore and Wheat. My long-term plan is to aim for Node 41 (Ore 5, Wheat 9, Brick 10) for my second settlement, as identified in my previous note to self. Building a road from node 20 to node 19 is the first step towards this goal, as it opens up a path towards Node 30 and subsequently Node 41. Node 19 itself connects to good resources (Wood 11, Brick 10, Sheep 8) and is part of a promising expansion route.", - "action": { - "type": "build_road", - "parameters": { - "target": "19" - } - } - }, - "raw_response": "{\"internal_thinking\":\"My first settlement is at node 20, providing Wood (11), Brick (6), and Sheep (8). To diversify my resource production and enable future expansion, I need to secure Ore and Wheat. My long-term plan is to aim for Node 41 (Ore 5, Wheat 9, Brick 10) for my second settlement, as identified in my previous note to self. Building a road from node 20 to node 19 is the first step towards this goal, as it opens up a path towards Node 30 and subsequently Node 41. Node 19 itself connects to good resources (Wood 11, Brick 10, Sheep 8) and is part of a promising expansion route.\",\"action\":{\"type\":\"build_road\",\"parameters\":{\"target\":\"19\"}}}", - "metadata": { - "request_num": 2, - "timestamp": "2026-01-08 13:58:14", - "model": "models/gemini-2.5-flash", - "latency_seconds": 25.268324613571167, - "total_tokens": 1062, - "prompt_tokens": 899, - "completion_tokens": 163, - "parse_success": true - }, - "is_new": true, - "response_timestamp": "2026-01-08T13:58:39.821552" - } - ], - "total_count": 8, - "last_updated": "2026-01-08T13:58:39.821753" -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_1.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_1.json deleted file mode 100644 index 45d1e2b24fdb6090730d33be4a5c5747a083ae8f..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_1.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_1.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_1.txt deleted file mode 100644 index 27dee595995a23e89f43361996e268b5e1978f19..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_1.txt +++ /dev/null @@ -1,115 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #1 -Generated: 2026-01-08 13:56:41 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_2.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_2.json deleted file mode 100644 index 45d1e2b24fdb6090730d33be4a5c5747a083ae8f..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_2.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_2.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_2.txt deleted file mode 100644 index 123a4aaf142f941f0da9df02dd8c8c249c7b98c0..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_2.txt +++ /dev/null @@ -1,115 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #2 -Generated: 2026-01-08 13:56:44 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_3.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_3.json deleted file mode 100644 index b1ccd6a6c6edc5a0de5d697262eede365d59403b..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_3.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_3.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_3.txt deleted file mode 100644 index 039217ed2cde8473cac5649124b696c1361a7b77..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_3.txt +++ /dev/null @@ -1,124 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #3 -Generated: 2026-01-08 13:57:00 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "It's your turn in the setup phase. Place your first settlement on a strategic location.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[],\"rds\":[]},\"players\":{\"shon\":{\"vp\":0,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "place_settlement", - "description": "Place your starting settlement on an available node", - "example_parameters": { - "location": "20" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_4.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_4.json deleted file mode 100644 index 76715aaa272c9ce25c99f097d184f3a5ce73f760..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_4.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_4.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_4.txt deleted file mode 100644 index 13874e96d534ea358c11d18016f5458292ac0e79..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_4.txt +++ /dev/null @@ -1,125 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #4 -Generated: 2026-01-08 13:57:14 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_5.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_5.json deleted file mode 100644 index 9b33626a96a3c8fd406e60067838ea596c8b9b8e..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_5.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "memory": { - "previous_note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_5.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_5.txt deleted file mode 100644 index 7e7dda4d6f7eaafaceff369d33eab3158b21fcbd..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_5.txt +++ /dev/null @@ -1,128 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #5 -Generated: 2026-01-08 13:57:26 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - } - ] - }, - "memory": { - "previous_note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_6.json b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_6.json deleted file mode 100644 index dbbcb1eeae25f5dbb9b16e247f078756af9998c0..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_6.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "response_schema": { - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] - }, - "system_instruction": "You are an expert Settlers of Catan player. Analyze the game state carefully and respond in the exact JSON format specified in response_schema.", - "prompt": { - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] - }, - "memory": { - "previous_note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_6.txt b/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_6.txt deleted file mode 100644 index 492ca65968b88ce9bbdbc0d3a6a427fafb59504e..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/ai_logs/session_20260108_135628/shon/prompts/prompt_6.txt +++ /dev/null @@ -1,133 +0,0 @@ -================================================================================ -AI AGENT PROMPT - PLAYER SHON -Prompt #6 -Generated: 2026-01-08 13:58:13 -================================================================================ - -📋 RESPONSE SCHEMA (Expected LLM Output Format) --------------------------------------------------------------------------------- -{ - "type": "object", - "required": [ - "internal_thinking", - "action" - ], - "properties": { - "internal_thinking": { - "type": "string", - "description": "Private strategy. What's your plan and why?", - "minLength": 50 - }, - "note_to_self": { - "type": "string", - "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", - "maxLength": 100 - }, - "say_outloud": { - "type": "string", - "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", - "maxLength": 100 - }, - "action": { - "type": "object", - "required": [ - "type", - "parameters" - ], - "properties": { - "type": { - "type": "string", - "description": "The action type (must match one from allowed_actions in constraints)" - }, - "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "properties": { - "target": { - "type": "string", - "description": "The target of the action (if applicable)" - }, - "amount": { - "type": "number", - "description": "The amount (if applicable)" - }, - "location": { - "type": "string", - "description": "The location (if applicable)" - } - }, - "propertyOrdering": [ - "target", - "amount", - "location" - ] - } - }, - "propertyOrdering": [ - "type", - "parameters" - ] - } - }, - "propertyOrdering": [ - "internal_thinking", - "note_to_self", - "say_outloud", - "action" - ] -} - -================================================================================ -📨 PROMPT TO SEND TO LLM -================================================================================ - -{ - "meta_data": { - "agent_name": "shon", - "role": "You are player 'shon'. Play strategically to win." - }, - "task_context": { - "what_just_happened": "You placed your first settlement at node 20. Now place a road connecting to it.", - "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." - }, - "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"meta\":{\"curr\":\"shon\",\"phase\":\"SETUP_FIRST_ROUND\",\"robber\":10,\"dice\":null},\"H\":[\"\",\"W12\",\"S5\",\"W4\",\"S8\",\"B6\",\"W3\",\"Wh8\",\"B10\",\"W11\",\"D\",\"O3\",\"S4\",\"B10\",\"Wh9\",\"Wh6\",\"S11\",\"O5\",\"Wh9\",\"O2\"],\"N\":[null,[[2,9],[1]],[[1,3],[1],\"Wh2\"],[[2,4,11],[2,1],\"Wh2\"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],\"B2\"],[[6,15],[3],\"B2\"],[[9,18],[4],\"?3\"],[[8,10,1],[4,1],\"?3\"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],\"O2\"],[[18,28],[8],\"S2\"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],\"O2\"],[[26,38],[12]],[[29,17],[8],\"S2\"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],\"?3\"],[[37,27],[12],\"?3\"],[[40,29],[13]],[[39,41,48],[17,13],\"W2\"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],\"W2\"],[[48,50],[17]],[[49,51,42],[18,17],\"?3\"],[[50,52],[18],\"?3\"],[[51,53,44],[19,18]],[[52,54],[19],\"?3\"],[[53,46],[19],\"?3\"]],\"state\":{\"bld\":[[20,\"shon\",\"S\"]],\"rds\":[]},\"players\":{\"shon\":{\"vp\":1,\"res\":{}},\"dudu\":{\"vp\":0,\"res\":{}}}}", - "social_context": { - "recent_chat": [ - { - "msg": 1, - "player": "dudu", - "message": "No message." - }, - { - "msg": 2, - "player": "shon", - "message": "I'm starting strong with a balanced resource income. Let's build!" - } - ] - }, - "memory": { - "previous_note_to_self": "My next settlement should aim for Node 41 (Ore 5, Wheat 9, Brick 10) to secure Ore and Wheat, completing my resource diversity with good production numbers." - }, - "constraints": { - "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", - "allowed_actions": [ - { - "action": "build_road", - "description": "Place your starting road connecting to your settlement", - "example_parameters": { - "from": "20", - "to": "21" - } - }, - { - "action": "wait_for_response", - "description": "Do nothing on the board, just chat or wait for other players", - "example_parameters": {} - } - ] - } -} - -================================================================================ -END OF PROMPT -================================================================================ diff --git a/examples/ai_testing/my_games/current_session.txt b/examples/ai_testing/my_games/current_session.txt index 434e3ccfaf665a71c8c988f3bc7220c28d89de75..022dab2c5c43119805160b41a950b45f1f441fa0 100644 --- a/examples/ai_testing/my_games/current_session.txt +++ b/examples/ai_testing/my_games/current_session.txt @@ -1 +1 @@ -C:\GIT_new\PyCatan_AI\examples\ai_testing\my_games\ai_logs\session_20260108_135628 \ No newline at end of file +session_20260108_224242 \ No newline at end of file diff --git a/examples/ai_testing/my_games/current_state.json b/examples/ai_testing/my_games/current_state.json deleted file mode 100644 index 32b545d85740601e8abec595e243f34c6b615490..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/current_state.json +++ /dev/null @@ -1,878 +0,0 @@ -{ - "timestamp": "2026-01-08T13:57:13.275162", - "state_number": 3, - "state": { - "hexes": [ - { - "id": 1, - "type": "wood", - "number": 12, - "has_robber": false - }, - { - "id": 2, - "type": "sheep", - "number": 5, - "has_robber": false - }, - { - "id": 3, - "type": "wood", - "number": 4, - "has_robber": false - }, - { - "id": 4, - "type": "sheep", - "number": 8, - "has_robber": false - }, - { - "id": 5, - "type": "brick", - "number": 6, - "has_robber": false - }, - { - "id": 6, - "type": "wood", - "number": 3, - "has_robber": false - }, - { - "id": 7, - "type": "wheat", - "number": 8, - "has_robber": false - }, - { - "id": 8, - "type": "brick", - "number": 10, - "has_robber": false - }, - { - "id": 9, - "type": "wood", - "number": 11, - "has_robber": false - }, - { - "id": 10, - "type": "desert", - "number": null, - "has_robber": true - }, - { - "id": 11, - "type": "ore", - "number": 3, - "has_robber": false - }, - { - "id": 12, - "type": "sheep", - "number": 4, - "has_robber": false - }, - { - "id": 13, - "type": "brick", - "number": 10, - "has_robber": false - }, - { - "id": 14, - "type": "wheat", - "number": 9, - "has_robber": false - }, - { - "id": 15, - "type": "wheat", - "number": 6, - "has_robber": false - }, - { - "id": 16, - "type": "sheep", - "number": 11, - "has_robber": false - }, - { - "id": 17, - "type": "ore", - "number": 5, - "has_robber": false - }, - { - "id": 18, - "type": "wheat", - "number": 9, - "has_robber": false - }, - { - "id": 19, - "type": "ore", - "number": 2, - "has_robber": false - } - ], - "settlements": [ - { - "id": "b_20", - "vertex": 20, - "player": 1 - } - ], - "cities": [], - "roads": [], - "harbors": [ - { - "id": 1, - "type": "any", - "ratio": 3, - "point_one": 9, - "point_two": 8 - }, - { - "id": 2, - "type": "sheep", - "ratio": 2, - "point_one": 17, - "point_two": 28 - }, - { - "id": 3, - "type": "wood", - "ratio": 2, - "point_one": 40, - "point_two": 48 - }, - { - "id": 4, - "type": "any", - "ratio": 3, - "point_one": 50, - "point_two": 51 - }, - { - "id": 5, - "type": "any", - "ratio": 3, - "point_one": 53, - "point_two": 54 - }, - { - "id": 6, - "type": "any", - "ratio": 3, - "point_one": 37, - "point_two": 38 - }, - { - "id": 7, - "type": "ore", - "ratio": 2, - "point_one": 26, - "point_two": 16 - }, - { - "id": 8, - "type": "brick", - "ratio": 2, - "point_one": 7, - "point_two": 6 - }, - { - "id": 9, - "type": "wheat", - "ratio": 2, - "point_one": 3, - "point_two": 2 - } - ], - "players": [ - { - "id": 0, - "name": "shon", - "victory_points": 1, - "total_cards": 0, - "cards_list": [], - "dev_cards_list": [], - "settlements": 1, - "cities": 0, - "roads": 0, - "longest_road": 0, - "has_longest_road": false, - "knights": 0, - "knights_played": 0, - "has_largest_army": false - }, - { - "id": 1, - "name": "dudu", - "victory_points": 0, - "total_cards": 0, - "cards_list": [], - "dev_cards_list": [], - "settlements": 0, - "cities": 0, - "roads": 0, - "longest_road": 0, - "has_longest_road": false, - "knights": 0, - "knights_played": 0, - "has_largest_army": false - } - ], - "current_player": 0, - "current_phase": "SETUP_FIRST_ROUND", - "robber_position": [ - 2, - 2 - ], - "dice_result": null, - "allowed_actions": [ - "PLACE_STARTING_ROAD" - ], - "points": [ - { - "point_id": 1, - "adjacent_points": [ - 2, - 9 - ], - "adjacent_hexes": [ - 1 - ] - }, - { - "point_id": 2, - "adjacent_points": [ - 1, - 3 - ], - "adjacent_hexes": [ - 1 - ] - }, - { - "point_id": 3, - "adjacent_points": [ - 2, - 4, - 11 - ], - "adjacent_hexes": [ - 2, - 1 - ] - }, - { - "point_id": 4, - "adjacent_points": [ - 3, - 5 - ], - "adjacent_hexes": [ - 2 - ] - }, - { - "point_id": 5, - "adjacent_points": [ - 4, - 6, - 13 - ], - "adjacent_hexes": [ - 3, - 2 - ] - }, - { - "point_id": 6, - "adjacent_points": [ - 5, - 7 - ], - "adjacent_hexes": [ - 3 - ] - }, - { - "point_id": 7, - "adjacent_points": [ - 6, - 15 - ], - "adjacent_hexes": [ - 3 - ] - }, - { - "point_id": 8, - "adjacent_points": [ - 9, - 18 - ], - "adjacent_hexes": [ - 4 - ] - }, - { - "point_id": 9, - "adjacent_points": [ - 8, - 10, - 1 - ], - "adjacent_hexes": [ - 4, - 1 - ] - }, - { - "point_id": 10, - "adjacent_points": [ - 9, - 11, - 20 - ], - "adjacent_hexes": [ - 5, - 4, - 1 - ] - }, - { - "point_id": 11, - "adjacent_points": [ - 10, - 12, - 3 - ], - "adjacent_hexes": [ - 5, - 2, - 1 - ] - }, - { - "point_id": 12, - "adjacent_points": [ - 11, - 13, - 22 - ], - "adjacent_hexes": [ - 6, - 5, - 2 - ] - }, - { - "point_id": 13, - "adjacent_points": [ - 12, - 14, - 5 - ], - "adjacent_hexes": [ - 6, - 3, - 2 - ] - }, - { - "point_id": 14, - "adjacent_points": [ - 13, - 15, - 24 - ], - "adjacent_hexes": [ - 7, - 6, - 3 - ] - }, - { - "point_id": 15, - "adjacent_points": [ - 14, - 16, - 7 - ], - "adjacent_hexes": [ - 7, - 3 - ] - }, - { - "point_id": 16, - "adjacent_points": [ - 15, - 26 - ], - "adjacent_hexes": [ - 7 - ] - }, - { - "point_id": 17, - "adjacent_points": [ - 18, - 28 - ], - "adjacent_hexes": [ - 8 - ] - }, - { - "point_id": 18, - "adjacent_points": [ - 17, - 19, - 8 - ], - "adjacent_hexes": [ - 8, - 4 - ] - }, - { - "point_id": 19, - "adjacent_points": [ - 18, - 20, - 30 - ], - "adjacent_hexes": [ - 9, - 8, - 4 - ] - }, - { - "point_id": 20, - "adjacent_points": [ - 19, - 21, - 10 - ], - "adjacent_hexes": [ - 9, - 5, - 4 - ] - }, - { - "point_id": 21, - "adjacent_points": [ - 20, - 22, - 32 - ], - "adjacent_hexes": [ - 10, - 9, - 5 - ] - }, - { - "point_id": 22, - "adjacent_points": [ - 21, - 23, - 12 - ], - "adjacent_hexes": [ - 10, - 6, - 5 - ] - }, - { - "point_id": 23, - "adjacent_points": [ - 22, - 24, - 34 - ], - "adjacent_hexes": [ - 11, - 10, - 6 - ] - }, - { - "point_id": 24, - "adjacent_points": [ - 23, - 25, - 14 - ], - "adjacent_hexes": [ - 11, - 7, - 6 - ] - }, - { - "point_id": 25, - "adjacent_points": [ - 24, - 26, - 36 - ], - "adjacent_hexes": [ - 12, - 11, - 7 - ] - }, - { - "point_id": 26, - "adjacent_points": [ - 25, - 27, - 16 - ], - "adjacent_hexes": [ - 12, - 7 - ] - }, - { - "point_id": 27, - "adjacent_points": [ - 26, - 38 - ], - "adjacent_hexes": [ - 12 - ] - }, - { - "point_id": 28, - "adjacent_points": [ - 29, - 17 - ], - "adjacent_hexes": [ - 8 - ] - }, - { - "point_id": 29, - "adjacent_points": [ - 28, - 30, - 39 - ], - "adjacent_hexes": [ - 13, - 8 - ] - }, - { - "point_id": 30, - "adjacent_points": [ - 29, - 31, - 19 - ], - "adjacent_hexes": [ - 13, - 9, - 8 - ] - }, - { - "point_id": 31, - "adjacent_points": [ - 30, - 32, - 41 - ], - "adjacent_hexes": [ - 14, - 13, - 9 - ] - }, - { - "point_id": 32, - "adjacent_points": [ - 31, - 33, - 21 - ], - "adjacent_hexes": [ - 14, - 10, - 9 - ] - }, - { - "point_id": 33, - "adjacent_points": [ - 32, - 34, - 43 - ], - "adjacent_hexes": [ - 15, - 14, - 10 - ] - }, - { - "point_id": 34, - "adjacent_points": [ - 33, - 35, - 23 - ], - "adjacent_hexes": [ - 15, - 11, - 10 - ] - }, - { - "point_id": 35, - "adjacent_points": [ - 34, - 36, - 45 - ], - "adjacent_hexes": [ - 16, - 15, - 11 - ] - }, - { - "point_id": 36, - "adjacent_points": [ - 35, - 37, - 25 - ], - "adjacent_hexes": [ - 16, - 12, - 11 - ] - }, - { - "point_id": 37, - "adjacent_points": [ - 36, - 38, - 47 - ], - "adjacent_hexes": [ - 16, - 12 - ] - }, - { - "point_id": 38, - "adjacent_points": [ - 37, - 27 - ], - "adjacent_hexes": [ - 12 - ] - }, - { - "point_id": 39, - "adjacent_points": [ - 40, - 29 - ], - "adjacent_hexes": [ - 13 - ] - }, - { - "point_id": 40, - "adjacent_points": [ - 39, - 41, - 48 - ], - "adjacent_hexes": [ - 17, - 13 - ] - }, - { - "point_id": 41, - "adjacent_points": [ - 40, - 42, - 31 - ], - "adjacent_hexes": [ - 17, - 14, - 13 - ] - }, - { - "point_id": 42, - "adjacent_points": [ - 41, - 43, - 50 - ], - "adjacent_hexes": [ - 18, - 17, - 14 - ] - }, - { - "point_id": 43, - "adjacent_points": [ - 42, - 44, - 33 - ], - "adjacent_hexes": [ - 18, - 15, - 14 - ] - }, - { - "point_id": 44, - "adjacent_points": [ - 43, - 45, - 52 - ], - "adjacent_hexes": [ - 19, - 18, - 15 - ] - }, - { - "point_id": 45, - "adjacent_points": [ - 44, - 46, - 35 - ], - "adjacent_hexes": [ - 19, - 16, - 15 - ] - }, - { - "point_id": 46, - "adjacent_points": [ - 45, - 47, - 54 - ], - "adjacent_hexes": [ - 19, - 16 - ] - }, - { - "point_id": 47, - "adjacent_points": [ - 46, - 37 - ], - "adjacent_hexes": [ - 16 - ] - }, - { - "point_id": 48, - "adjacent_points": [ - 49, - 40 - ], - "adjacent_hexes": [ - 17 - ] - }, - { - "point_id": 49, - "adjacent_points": [ - 48, - 50 - ], - "adjacent_hexes": [ - 17 - ] - }, - { - "point_id": 50, - "adjacent_points": [ - 49, - 51, - 42 - ], - "adjacent_hexes": [ - 18, - 17 - ] - }, - { - "point_id": 51, - "adjacent_points": [ - 50, - 52 - ], - "adjacent_hexes": [ - 18 - ] - }, - { - "point_id": 52, - "adjacent_points": [ - 51, - 53, - 44 - ], - "adjacent_hexes": [ - 19, - 18 - ] - }, - { - "point_id": 53, - "adjacent_points": [ - 52, - 54 - ], - "adjacent_hexes": [ - 19 - ] - }, - { - "point_id": 54, - "adjacent_points": [ - 53, - 46 - ], - "adjacent_hexes": [ - 19 - ] - } - ] - } -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/current_state_optimized.txt b/examples/ai_testing/my_games/current_state_optimized.txt deleted file mode 100644 index 9d3a3b3dd4d88b4e89605771dd55b9bb0caf3414..0000000000000000000000000000000000000000 --- a/examples/ai_testing/my_games/current_state_optimized.txt +++ /dev/null @@ -1,25 +0,0 @@ -1. LOOKUP TABLES: - • "H" (Hexes): Array where Index = HexID. Value = Resource+Num. - Example: H[1]="W12" -> Hex 1 is Wood 12. - • "N" (Nodes): Array where Index = NodeID. - Format: [ [Neighbors], [HexIDs], Port? ] - Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5]. - -2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert. - ?3=Any 3:1 port, X2=Specific Resource 2:1 port. - -3. STATE: "bld"=[NodeID, Owner, Type], "rds"=[[From,To], Owner]. - -4. PLAYERS: "res"={Resource:Count}, "dev"={"h":[Hidden Cards], "r":[Revealed] (K=Knight)}, - "stat"=["LR" (Longest Road), "LA" (Largest Army)]. - -5. ROBBER: Located at HexID specified in "meta.robber". H[id] is blocked. - -JSON: -{ - "meta":{"curr":"shon","phase":"SETUP_FIRST_ROUND","robber":10,"dice":null}, - "H":["","W12","S5","W4","S8","B6","W3","Wh8","B10","W11","D","O3","S4","B10","Wh9","Wh6","S11","O5","Wh9","O2"], - "N":[null,[[2,9],[1]],[[1,3],[1],"Wh2"],[[2,4,11],[2,1],"Wh2"],[[3,5],[2]],[[4,6,13],[3,2]],[[5,7],[3],"B2"],[[6,15],[3],"B2"],[[9,18],[4],"?3"],[[8,10,1],[4,1],"?3"],[[9,11,20],[5,4,1]],[[10,12,3],[5,2,1]],[[11,13,22],[6,5,2]],[[12,14,5],[6,3,2]],[[13,15,24],[7,6,3]],[[14,16,7],[7,3]],[[15,26],[7],"O2"],[[18,28],[8],"S2"],[[17,19,8],[8,4]],[[18,20,30],[9,8,4]],[[19,21,10],[9,5,4]],[[20,22,32],[10,9,5]],[[21,23,12],[10,6,5]],[[22,24,34],[11,10,6]],[[23,25,14],[11,7,6]],[[24,26,36],[12,11,7]],[[25,27,16],[12,7],"O2"],[[26,38],[12]],[[29,17],[8],"S2"],[[28,30,39],[13,8]],[[29,31,19],[13,9,8]],[[30,32,41],[14,13,9]],[[31,33,21],[14,10,9]],[[32,34,43],[15,14,10]],[[33,35,23],[15,11,10]],[[34,36,45],[16,15,11]],[[35,37,25],[16,12,11]],[[36,38,47],[16,12],"?3"],[[37,27],[12],"?3"],[[40,29],[13]],[[39,41,48],[17,13],"W2"],[[40,42,31],[17,14,13]],[[41,43,50],[18,17,14]],[[42,44,33],[18,15,14]],[[43,45,52],[19,18,15]],[[44,46,35],[19,16,15]],[[45,47,54],[19,16]],[[46,37],[16]],[[49,40],[17],"W2"],[[48,50],[17]],[[49,51,42],[18,17],"?3"],[[50,52],[18],"?3"],[[51,53,44],[19,18]],[[52,54],[19],"?3"],[[53,46],[19],"?3"]], - "state":{"bld":[[20,"shon","S"]],"rds":[]}, - "players":{"shon":{"vp":1,"res":{}},"dudu":{"vp":0,"res":{}}} -} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_220737/A/A.md b/examples/ai_testing/my_games/session_20260108_220737/A/A.md new file mode 100644 index 0000000000000000000000000000000000000000..c3c51c8f063474d36ce6bab42ed5ace2fb8c0d0f --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_220737/A/A.md @@ -0,0 +1,33 @@ +# AI Agent Log: A + +**Session:** session_20260108_220737 +**Started:** 2026-01-08 22:07:37 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:07:39 + +### What Happened +• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players! +• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + +### Response Received ✅ + +**Latency:** 2.05s | **Tokens:** 1344 + +**Thinking:** The game is in the setup phase, and I need to place my first settlement. I will choose a node that has access to a variety of resources to maximize my chances of getting a good start. I will choose no... + +**Note to Self:** Remember to place a road after placing the settlement. + +**Says:** "I will place my settlement on node 20." + +--- diff --git a/examples/ai_testing/my_games/session_20260108_220737/A/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_220737/A/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..15c43106fa024200899a3c43df0995701fe8f15e --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_220737/A/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:07:39.994428", + "player_name": "A", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players!\n• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"13e4549e-7718-4b81-806a-055c4dbfd52d\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"mountains\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"mountains\",\"token\":6,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":10,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":5,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"pasture\",\"token\":9,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"hills\",\"token\":2,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":8,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"fields\",\"token\":12,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"forest\",\"token\":3,\"has_robber\":false}],\"robber_position\":[1,1]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 50 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players!\n• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_220737/A/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_220737/A/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..f2463d84a9dcf0533ce84f81bb8a4ce6d7556c14 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_220737/A/prompts/prompt_1.txt @@ -0,0 +1,37 @@ +=== Prompt #1 for A === +Timestamp: 2026-01-08T22:07:39.995240 +Active Turn: True + +--- What Happened --- +• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players! +• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players!\n• Game 13e4549e-7718-4b81-806a-055c4dbfd52d has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"13e4549e-7718-4b81-806a-055c4dbfd52d\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"mountains\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"mountains\",\"token\":6,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":10,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":5,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"pasture\",\"token\":9,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"hills\",\"token\":2,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":8,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"fields\",\"token\":12,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"forest\",\"token\":3,\"has_robber\":false}],\"robber_position\":[1,1]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_220737/A/responses/response_1.json b/examples/ai_testing/my_games/session_20260108_220737/A/responses/response_1.json new file mode 100644 index 0000000000000000000000000000000000000000..c9a8b7c4cb1ccb557b3185b7da9d702e4c3124c8 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_220737/A/responses/response_1.json @@ -0,0 +1,24 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:07:42.578656", + "player_name": "A", + "success": true, + "raw_content": "{\n \"internal_thinking\": \"The game is in the setup phase, and I need to place my first settlement. I will choose a node that has access to a variety of resources to maximize my chances of getting a good start. I will choose node 20 as it is adjacent to forest, pasture and fields. This placement will give me initial access to wood, sheep and wheat.\",\n \"action\": {\n \"type\": \"PLACE_STARTING_SETTLEMENT\",\n \"parameters\": \"{\\\"node\\\": 20}\"\n },\n \"note_to_self\": \"Remember to place a road after placing the settlement.\",\n \"say_outloud\": \"I will place my settlement on node 20.\"\n}", + "parsed": { + "internal_thinking": "The game is in the setup phase, and I need to place my first settlement. I will choose a node that has access to a variety of resources to maximize my chances of getting a good start. I will choose node 20 as it is adjacent to forest, pasture and fields. This placement will give me initial access to wood, sheep and wheat.", + "note_to_self": "Remember to place a road after placing the settlement.", + "say_outloud": "I will place my settlement on node 20.", + "action_type": "PLACE_STARTING_SETTLEMENT", + "parameters": { + "node": 20 + } + }, + "model": "gemini-2.0-flash-exp", + "tokens": { + "prompt": 1199, + "completion": 145, + "total": 1344 + }, + "latency_seconds": 2.0501668453216553, + "error": null +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_220737/session_metadata.json b/examples/ai_testing/my_games/session_20260108_220737/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..0ff62b8c7874a848af573c79c9dcfbadbf288e5d --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_220737/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_220737", + "start_time": "2026-01-08T22:07:37.937376", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_221328/C/C.md b/examples/ai_testing/my_games/session_20260108_221328/C/C.md new file mode 100644 index 0000000000000000000000000000000000000000..3ca0807fc4d17f9c9d16415dfbcf37d79c5c655d --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221328/C/C.md @@ -0,0 +1,31 @@ +# AI Agent Log: C + +**Session:** session_20260108_221328 +**Started:** 2026-01-08 22:13:28 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:13:30 + +### What Happened +• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players! +• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + +### Response Received ✅ + +**Latency:** 1.89s | **Tokens:** 1309 + +**Thinking:** I need to place my first settlement. I will choose a location that gives me access to a variety of resources. I will prioritize locations with high probability numbers (6 or 8) and try to get access t... + +**Note to Self:** Remember to place a road after the settlement. + +--- diff --git a/examples/ai_testing/my_games/session_20260108_221328/C/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_221328/C/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..b4128816e01ba219241770bfac66ebfaed109ffb --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221328/C/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:13:30.430700", + "player_name": "C", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "C", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players!\n• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"8e33b2b8-c462-4c82-afc3-071e8b6afbee\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"hills\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"pasture\",\"token\":12,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"hills\",\"token\":2,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"mountains\",\"token\":9,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"pasture\",\"token\":8,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"mountains\",\"token\":5,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":11,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"fields\",\"token\":10,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":5,\"has_robber\":false}],\"robber_position\":[3,3]},\"players_state\":[{\"player_id\":0,\"name\":\"C\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"D\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 200 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players!\n• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_221328/C/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_221328/C/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..8437ec63ebb4f8844454e8925521103c4fbca7c5 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221328/C/prompts/prompt_1.txt @@ -0,0 +1,37 @@ +=== Prompt #1 for C === +Timestamp: 2026-01-08T22:13:30.431892 +Active Turn: True + +--- What Happened --- +• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players! +• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "C", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players!\n• Game 8e33b2b8-c462-4c82-afc3-071e8b6afbee has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"8e33b2b8-c462-4c82-afc3-071e8b6afbee\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"hills\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"pasture\",\"token\":12,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"hills\",\"token\":2,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"mountains\",\"token\":9,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"pasture\",\"token\":8,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"mountains\",\"token\":5,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":11,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"fields\",\"token\":10,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":5,\"has_robber\":false}],\"robber_position\":[3,3]},\"players_state\":[{\"player_id\":0,\"name\":\"C\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"D\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_221328/C/responses/response_1.json b/examples/ai_testing/my_games/session_20260108_221328/C/responses/response_1.json new file mode 100644 index 0000000000000000000000000000000000000000..49ef750d378030621d6dfbbd9115f9b347580a5f --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221328/C/responses/response_1.json @@ -0,0 +1,24 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:13:32.906634", + "player_name": "C", + "success": true, + "raw_content": "{\n \"internal_thinking\": \"I need to place my first settlement. I will choose a location that gives me access to a variety of resources. I will prioritize locations with high probability numbers (6 or 8) and try to get access to ore for development cards.\",\n \"action\": {\n \"type\": \"PLACE_STARTING_SETTLEMENT\",\n \"parameters\": \"{\\\"node\\\": 21}\"\n },\n \"note_to_self\": \"Remember to place a road after the settlement.\",\n \"say_outloud\": \"\"\n}", + "parsed": { + "internal_thinking": "I need to place my first settlement. I will choose a location that gives me access to a variety of resources. I will prioritize locations with high probability numbers (6 or 8) and try to get access to ore for development cards.", + "note_to_self": "Remember to place a road after the settlement.", + "say_outloud": "", + "action_type": "PLACE_STARTING_SETTLEMENT", + "parameters": { + "node": 21 + } + }, + "model": "gemini-2.0-flash-exp", + "tokens": { + "prompt": 1199, + "completion": 110, + "total": 1309 + }, + "latency_seconds": 1.887739658355713, + "error": null +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_221328/session_metadata.json b/examples/ai_testing/my_games/session_20260108_221328/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..4a65de4083bac6af107df4d257e2d15f15ae4c25 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221328/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_221328", + "start_time": "2026-01-08T22:13:28.374102", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_221416/A/A.md b/examples/ai_testing/my_games/session_20260108_221416/A/A.md new file mode 100644 index 0000000000000000000000000000000000000000..79641ef9ce35d665d9f85591856eaa7a295025d2 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221416/A/A.md @@ -0,0 +1,33 @@ +# AI Agent Log: A + +**Session:** session_20260108_221416 +**Started:** 2026-01-08 22:14:16 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:14:18 + +### What Happened +• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players! +• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + +### Response Received ✅ + +**Latency:** 2.05s | **Tokens:** 1345 + +**Thinking:** The game is in the setup phase, and I need to place my first settlement. I will choose a node that has access to a variety of resources to maximize my chances of getting resources early in the game. L... + +**Note to Self:** Remember to place the road in the next turn. + +**Says:** "I will place my first settlement at node 20." + +--- diff --git a/examples/ai_testing/my_games/session_20260108_221416/A/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_221416/A/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..3305fa6dc141f4052ec51124205a3b37875ebc9b --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221416/A/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:14:18.829221", + "player_name": "A", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players!\n• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"3feae058-df26-4222-9f6c-c42d55d2e41d\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"pasture\",\"token\":6,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":8,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"hills\",\"token\":10,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"mountains\",\"token\":5,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"forest\",\"token\":12,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"hills\",\"token\":4,\"has_robber\":false}],\"robber_position\":[1,0]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players!\n• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_221416/A/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_221416/A/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f5c10b5fb691d896b3eb1131186d11be87d0e1d --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221416/A/prompts/prompt_1.txt @@ -0,0 +1,37 @@ +=== Prompt #1 for A === +Timestamp: 2026-01-08T22:14:18.830751 +Active Turn: True + +--- What Happened --- +• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players! +• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players!\n• Game 3feae058-df26-4222-9f6c-c42d55d2e41d has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"3feae058-df26-4222-9f6c-c42d55d2e41d\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"pasture\",\"token\":6,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":8,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"hills\",\"token\":10,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"mountains\",\"token\":5,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"forest\",\"token\":12,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"hills\",\"token\":4,\"has_robber\":false}],\"robber_position\":[1,0]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_221416/A/responses/response_1.json b/examples/ai_testing/my_games/session_20260108_221416/A/responses/response_1.json new file mode 100644 index 0000000000000000000000000000000000000000..e74bd75b2d2041137819bae698d174128d919741 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221416/A/responses/response_1.json @@ -0,0 +1,24 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:14:21.356769", + "player_name": "A", + "success": true, + "raw_content": "{\n \"internal_thinking\": \"The game is in the setup phase, and I need to place my first settlement. I will choose a node that has access to a variety of resources to maximize my chances of getting resources early in the game. Looking at the board state, node 20 seems like a good option as it is adjacent to Pasture (Sheep), Fields (Wheat), and Hills (Brick).\",\n \"action\": {\n \"type\": \"PLACE_STARTING_SETTLEMENT\",\n \"parameters\": \"{\\\"node\\\": 20}\"\n },\n \"note_to_self\": \"Remember to place the road in the next turn.\",\n \"say_outloud\": \"I will place my first settlement at node 20.\"\n}", + "parsed": { + "internal_thinking": "The game is in the setup phase, and I need to place my first settlement. I will choose a node that has access to a variety of resources to maximize my chances of getting resources early in the game. Looking at the board state, node 20 seems like a good option as it is adjacent to Pasture (Sheep), Fields (Wheat), and Hills (Brick). [Response was too brief]", + "note_to_self": "Remember to place the road in the next turn.", + "say_outloud": "I will place my first settlement at node 20.", + "action_type": "PLACE_STARTING_SETTLEMENT", + "parameters": { + "node": 20 + } + }, + "model": "gemini-2.0-flash-exp", + "tokens": { + "prompt": 1199, + "completion": 146, + "total": 1345 + }, + "latency_seconds": 2.04524564743042, + "error": null +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_221416/session_metadata.json b/examples/ai_testing/my_games/session_20260108_221416/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..f2102a6f04923da1616f433df7128c98eaff2bf6 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_221416/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_221416", + "start_time": "2026-01-08T22:14:16.761851", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_222919/A/A.md b/examples/ai_testing/my_games/session_20260108_222919/A/A.md new file mode 100644 index 0000000000000000000000000000000000000000..2a49b685898be122b3123896541fb981e57f2aee --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/A/A.md @@ -0,0 +1,22 @@ +# AI Agent Log: A + +**Session:** session_20260108_222919 +**Started:** 2026-01-08 22:29:19 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:29:21 + +### What Happened +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + diff --git a/examples/ai_testing/my_games/session_20260108_222919/A/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_222919/A/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..4cfbe017c85fc35b92779cedce32e68e4a33991c --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/A/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:29:21.092752", + "player_name": "A", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"a46aa39c-7765-4f3d-9c7a-fc1675373d56\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":6,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":10,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":4,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":2,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"hills\",\"token\":12,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"hills\",\"token\":5,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"fields\",\"token\":9,\"has_robber\":false}],\"robber_position\":[3,3]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_222919/A/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_222919/A/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..2dbc5d1de669998ac8dcee5f97e57c73a134e9ed --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/A/prompts/prompt_1.txt @@ -0,0 +1,89 @@ +=== Prompt #1 for A === +Timestamp: 2026-01-08T22:29:21.094550 +Active Turn: True + +--- What Happened --- +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"a46aa39c-7765-4f3d-9c7a-fc1675373d56\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":6,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":10,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":4,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":2,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"hills\",\"token\":12,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"hills\",\"token\":5,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"fields\",\"token\":9,\"has_robber\":false}],\"robber_position\":[3,3]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_222919/B/B.md b/examples/ai_testing/my_games/session_20260108_222919/B/B.md new file mode 100644 index 0000000000000000000000000000000000000000..70d4fe44d28b86f352c0d30769352f5f35a535e9 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/B/B.md @@ -0,0 +1,26 @@ +# AI Agent Log: B + +**Session:** session_20260108_222919 +**Started:** 2026-01-08 22:29:19 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:32:29 + +### What Happened +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. +• Player 0 ended their turn +• Player 0 ended their turn +• Turn 1: Player 1's turn begins. +• Turn 1: Player 1's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + diff --git a/examples/ai_testing/my_games/session_20260108_222919/B/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_222919/B/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..dc7512acbd29e160796fa74d77df1a9d5c9dbde7 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/B/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:32:29.514216", + "player_name": "B", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "B", + "role": null + }, + "task_context": { + "what_just_happened": "• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.\n• Player 0 ended their turn\n• Player 0 ended their turn\n• Turn 1: Player 1's turn begins.\n• Turn 1: Player 1's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"a46aa39c-7765-4f3d-9c7a-fc1675373d56\",\"turn_number\":1,\"current_player\":1,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":6,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":10,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":4,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":2,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"hills\",\"token\":12,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"hills\",\"token\":5,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"fields\",\"token\":9,\"has_robber\":false}],\"robber_position\":[3,3]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.\n• Player 0 ended their turn\n• Player 0 ended their turn\n• Turn 1: Player 1's turn begins.\n• Turn 1: Player 1's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_222919/B/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_222919/B/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..4f8660e0880cbfb0c9d91a8debd26ff6be4daaec --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/B/prompts/prompt_1.txt @@ -0,0 +1,93 @@ +=== Prompt #1 for B === +Timestamp: 2026-01-08T22:32:29.516254 +Active Turn: True + +--- What Happened --- +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. +• Player 0 ended their turn +• Player 0 ended their turn +• Turn 1: Player 1's turn begins. +• Turn 1: Player 1's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "B", + "role": null + }, + "task_context": { + "what_just_happened": "• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Game a46aa39c-7765-4f3d-9c7a-fc1675373d56 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.\n• Player 0 ended their turn\n• Player 0 ended their turn\n• Turn 1: Player 1's turn begins.\n• Turn 1: Player 1's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"a46aa39c-7765-4f3d-9c7a-fc1675373d56\",\"turn_number\":1,\"current_player\":1,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":6,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":10,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":4,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":2,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"hills\",\"token\":12,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"hills\",\"token\":5,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"fields\",\"token\":9,\"has_robber\":false}],\"robber_position\":[3,3]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_222919/session_metadata.json b/examples/ai_testing/my_games/session_20260108_222919/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..eee72f1b974504dc6f7e489a9ab28c5adc761e53 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_222919/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_222919", + "start_time": "2026-01-08T22:29:19.019276", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_223312/A/A.md b/examples/ai_testing/my_games/session_20260108_223312/A/A.md new file mode 100644 index 0000000000000000000000000000000000000000..2618df3dc41c4e65f11ff765fd91340e873a57c6 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223312/A/A.md @@ -0,0 +1,22 @@ +# AI Agent Log: A + +**Session:** session_20260108_223312 +**Started:** 2026-01-08 22:33:12 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:33:14 + +### What Happened +• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players! +• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + diff --git a/examples/ai_testing/my_games/session_20260108_223312/A/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_223312/A/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..d006acf447558e1cc4438604f9069534d14298e3 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223312/A/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:33:14.325702", + "player_name": "A", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players!\n• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"baa065b9-f08e-4c5b-a052-e7b82aee3348\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"mountains\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"forest\",\"token\":11,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"pasture\",\"token\":12,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"forest\",\"token\":5,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"pasture\",\"token\":9,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"hills\",\"token\":6,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"hills\",\"token\":11,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"mountains\",\"token\":8,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":2,\"has_robber\":false}],\"robber_position\":[1,1]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players!\n• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_223312/A/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_223312/A/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..8005ec86da92b21b1c01a9b8b73647e96e6f3479 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223312/A/prompts/prompt_1.txt @@ -0,0 +1,89 @@ +=== Prompt #1 for A === +Timestamp: 2026-01-08T22:33:14.326800 +Active Turn: True + +--- What Happened --- +• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players! +• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players!\n• Game baa065b9-f08e-4c5b-a052-e7b82aee3348 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"baa065b9-f08e-4c5b-a052-e7b82aee3348\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"mountains\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"forest\",\"token\":11,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"pasture\",\"token\":12,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"forest\",\"token\":5,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"pasture\",\"token\":9,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"hills\",\"token\":6,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"hills\",\"token\":11,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"mountains\",\"token\":8,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":2,\"has_robber\":false}],\"robber_position\":[1,1]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_223312/session_metadata.json b/examples/ai_testing/my_games/session_20260108_223312/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..46f4d63851e1c49a666866b8ad3990e32bc12b90 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223312/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_223312", + "start_time": "2026-01-08T22:33:12.255567", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_223627/A/A.md b/examples/ai_testing/my_games/session_20260108_223627/A/A.md new file mode 100644 index 0000000000000000000000000000000000000000..1d93bbdbe158471765fec776442407b81c0b89df --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223627/A/A.md @@ -0,0 +1,33 @@ +# AI Agent Log: A + +**Session:** session_20260108_223627 +**Started:** 2026-01-08 22:36:27 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:36:29 + +### What Happened +• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players! +• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + +### Response Received ✅ + +**Latency:** 2.42s | **Tokens:** 1976 + +**Thinking:** I need to place my first settlement. I should choose a location that gives me access to a variety of resources and good probabilities. Looking at the board state, I will choose node 20 as it has acces... + +**Note to Self:** Remember to place the second settlement strategically to maximize resource diversity and probabilities. + +**Says:** "I place my first settlement." + +--- diff --git a/examples/ai_testing/my_games/session_20260108_223627/A/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_223627/A/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..5fac58cd565c0e3b328b846150e36021ccfc1ed6 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223627/A/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:36:29.983283", + "player_name": "A", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players!\n• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"4f333137-6e86-40ca-99ff-cdc2141d7caa\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"hills\",\"token\":11,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"forest\",\"token\":3,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"hills\",\"token\":12,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"pasture\",\"token\":8,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":11,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"hills\",\"token\":5,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":5,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"mountains\",\"token\":9,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"mountains\",\"token\":8,\"has_robber\":false}],\"robber_position\":[4,1]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players!\n• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_223627/A/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_223627/A/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..a6b73b8467993d3c7daa6b93290bacb8180feab4 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223627/A/prompts/prompt_1.txt @@ -0,0 +1,89 @@ +=== Prompt #1 for A === +Timestamp: 2026-01-08T22:36:29.984040 +Active Turn: True + +--- What Happened --- +• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players! +• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players!\n• Game 4f333137-6e86-40ca-99ff-cdc2141d7caa has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"4f333137-6e86-40ca-99ff-cdc2141d7caa\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"hills\",\"token\":11,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"forest\",\"token\":3,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"hills\",\"token\":12,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"pasture\",\"token\":8,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"mountains\",\"token\":3,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":11,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"hills\",\"token\":5,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":4,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":5,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"fields\",\"token\":9,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"mountains\",\"token\":9,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"mountains\",\"token\":8,\"has_robber\":false}],\"robber_position\":[4,1]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_223627/A/responses/response_1.json b/examples/ai_testing/my_games/session_20260108_223627/A/responses/response_1.json new file mode 100644 index 0000000000000000000000000000000000000000..19d086414f0a65a3f251aab907150ab3cf6aaf81 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223627/A/responses/response_1.json @@ -0,0 +1,24 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:36:33.060299", + "player_name": "A", + "success": true, + "raw_content": "{\n \"internal_thinking\": \"I need to place my first settlement. I should choose a location that gives me access to a variety of resources and good probabilities. Looking at the board state, I will choose node 20 as it has access to forest (2), field (10) and pasture (15). These resources have probabilities of 11, 6 and 9 respectively.\",\n \"action\": {\n \"type\": \"PLACE_STARTING_SETTLEMENT\",\n \"parameters\": \"{\\\"node\\\": 20}\"\n },\n \"note_to_self\": \"Remember to place the second settlement strategically to maximize resource diversity and probabilities.\",\n \"say_outloud\": \"I place my first settlement.\"\n}", + "parsed": { + "internal_thinking": "I need to place my first settlement. I should choose a location that gives me access to a variety of resources and good probabilities. Looking at the board state, I will choose node 20 as it has access to forest (2), field (10) and pasture (15). These resources have probabilities of 11, 6 and 9 respectively. [Response was too brief]", + "note_to_self": "Remember to place the second settlement strategically to maximize resource diversity and probabilities.", + "say_outloud": "I place my first settlement.", + "action_type": "PLACE_STARTING_SETTLEMENT", + "parameters": { + "node": 20 + } + }, + "model": "gemini-2.0-flash-exp", + "tokens": { + "prompt": 1814, + "completion": 162, + "total": 1976 + }, + "latency_seconds": 2.420753002166748, + "error": null +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_223627/session_metadata.json b/examples/ai_testing/my_games/session_20260108_223627/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..c7eb3b9d00c95649d0827b9a63beed55dd214c80 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_223627/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_223627", + "start_time": "2026-01-08T22:36:27.930320", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224106/A/A.md b/examples/ai_testing/my_games/session_20260108_224106/A/A.md new file mode 100644 index 0000000000000000000000000000000000000000..7cd9914a5c8cf6d33f7675a33190e87368795b7d --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224106/A/A.md @@ -0,0 +1,28 @@ +# AI Agent Log: A + +**Session:** session_20260108_224106 +**Started:** 2026-01-08 22:41:06 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:41:08 + +### What Happened +• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players! +• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + +### Response Failed ❌ + +**Error:** Unknown field for GenerationConfig: thinking_config +**Latency:** 0.00s + +--- diff --git a/examples/ai_testing/my_games/session_20260108_224106/A/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_224106/A/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..3111b88705a300c19762846f3a38ff17bc30ddd8 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224106/A/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:41:08.425593", + "player_name": "A", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players!\n• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"77699780-4e48-41bf-9965-d3b9044bad48\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":8,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"fields\",\"token\":8,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"forest\",\"token\":3,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"hills\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"mountains\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"hills\",\"token\":11,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"mountains\",\"token\":9,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":12,\"has_robber\":false}],\"robber_position\":[1,2]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players!\n• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224106/A/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_224106/A/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..2551745b6ce6b9d56cb67f870210db17995968bf --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224106/A/prompts/prompt_1.txt @@ -0,0 +1,89 @@ +=== Prompt #1 for A === +Timestamp: 2026-01-08T22:41:08.426258 +Active Turn: True + +--- What Happened --- +• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players! +• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "A", + "role": null + }, + "task_context": { + "what_just_happened": "• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players!\n• Game 77699780-4e48-41bf-9965-d3b9044bad48 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"77699780-4e48-41bf-9965-d3b9044bad48\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"pasture\",\"token\":8,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":10,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"fields\",\"token\":8,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"forest\",\"token\":3,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"hills\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"mountains\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"forest\",\"token\":9,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"hills\",\"token\":11,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"mountains\",\"token\":9,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":12,\"has_robber\":false}],\"robber_position\":[1,2]},\"players_state\":[{\"player_id\":0,\"name\":\"A\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"B\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_224106/A/responses/response_1.json b/examples/ai_testing/my_games/session_20260108_224106/A/responses/response_1.json new file mode 100644 index 0000000000000000000000000000000000000000..5c33fe6b4bf25893cf9df47d04a88c184ff256c7 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224106/A/responses/response_1.json @@ -0,0 +1,16 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:41:09.033520", + "player_name": "A", + "success": false, + "raw_content": null, + "parsed": null, + "model": "gemini-2.0-flash-thinking-exp", + "tokens": { + "prompt": 0, + "completion": 0, + "total": 0 + }, + "latency_seconds": 0.0006978511810302734, + "error": "Unknown field for GenerationConfig: thinking_config" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224106/session_metadata.json b/examples/ai_testing/my_games/session_20260108_224106/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..67e36289366c8ed761a90b5297aa878def562c5d --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224106/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_224106", + "start_time": "2026-01-08T22:41:06.372030", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224242/session_metadata.json b/examples/ai_testing/my_games/session_20260108_224242/session_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..c730ce1f477398a6154a3063ee711c06b6995d7f --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/session_metadata.json @@ -0,0 +1,5 @@ +{ + "session_id": "session_20260108_224242", + "start_time": "2026-01-08T22:42:42.616283", + "version": "2.0" +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_1.json b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_1.json new file mode 100644 index 0000000000000000000000000000000000000000..fd3eabedd316d585e604398aae78db472ae9f74f --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_1.json @@ -0,0 +1,95 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:42:44.670209", + "player_name": "shon", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "shon", + "role": null + }, + "task_context": { + "what_just_happened": "• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"bef7f89a-adbf-4c0d-8160-0a0622dc18b4\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":9,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"mountains\",\"token\":12,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"mountains\",\"token\":10,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":9,\"has_robber\":false}],\"robber_position\":[4,0]},\"players_state\":[{\"player_id\":0,\"name\":\"shon\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"itay\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_1.txt b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_1.txt new file mode 100644 index 0000000000000000000000000000000000000000..1ca2ef43364964e6272dcad74f147d357cf94287 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_1.txt @@ -0,0 +1,89 @@ +=== Prompt #1 for shon === +Timestamp: 2026-01-08T22:42:44.671456 +Active Turn: True + +--- What Happened --- +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "shon", + "role": null + }, + "task_context": { + "what_just_happened": "• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"bef7f89a-adbf-4c0d-8160-0a0622dc18b4\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":9,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"mountains\",\"token\":12,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"mountains\",\"token\":10,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":9,\"has_robber\":false}],\"robber_position\":[4,0]},\"players_state\":[{\"player_id\":0,\"name\":\"shon\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"itay\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_2.json b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_2.json new file mode 100644 index 0000000000000000000000000000000000000000..2c9bc53a96d4f39fb97adb7b0376e400948d681b --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_2.json @@ -0,0 +1,95 @@ +{ + "request_number": 2, + "timestamp": "2026-01-08T22:43:32.992251", + "player_name": "shon", + "is_active_turn": true, + "prompt": { + "meta_data": { + "agent_name": "shon", + "role": null + }, + "task_context": { + "what_just_happened": "• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"bef7f89a-adbf-4c0d-8160-0a0622dc18b4\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":9,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"mountains\",\"token\":12,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"mountains\",\"token\":10,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":9,\"has_robber\":false}],\"robber_position\":[4,0]},\"players_state\":[{\"player_id\":0,\"name\":\"shon\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"itay\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } + }, + "response_schema": { + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] + }, + "what_happened": "• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_2.txt b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_2.txt new file mode 100644 index 0000000000000000000000000000000000000000..b7c757d97b043394c1c559b29c528bf8f518a9ed --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/prompts/prompt_2.txt @@ -0,0 +1,89 @@ +=== Prompt #2 for shon === +Timestamp: 2026-01-08T22:43:32.993722 +Active Turn: True + +--- What Happened --- +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +--- Response Schema --- +{ + "type": "object", + "required": [ + "internal_thinking", + "action" + ], + "properties": { + "internal_thinking": { + "type": "string", + "description": "Private strategy. What's your plan and why?", + "minLength": 1000 + }, + "note_to_self": { + "type": "string", + "description": "Important facts for when it's your turn. Use only if essential for clarity or direct user query. Omit otherwise.", + "maxLength": 100 + }, + "say_outloud": { + "type": "string", + "description": "A short message to other players (max 100 chars). Use for negotiation, threats, or table talk. Keep in mind you pay for speak outload.", + "maxLength": 100 + }, + "action": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "The action type (must match one from allowed_actions in constraints)" + }, + "parameters": { + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" + } + }, + "propertyOrdering": [ + "type", + "parameters" + ] + } + }, + "propertyOrdering": [ + "internal_thinking", + "note_to_self", + "say_outloud", + "action" + ] +} + +--- Prompt Content --- +{ + "meta_data": { + "agent_name": "shon", + "role": null + }, + "task_context": { + "what_just_happened": "• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players!\n• Turn 0: Player 0's turn begins.\n• Turn 0: Player 0's turn begins.", + "instructions": "Analyze the game state and select the optimal move from 'allowed_actions'. You have 2 possible actions. If you wish to negotiate or wait for other players, select the 'wait_for_response' action." + }, + "game_state": "\n 1. LOOKUP TABLES:\n • \"H\" (Hexes): Array where Index = HexID. Value = Resource+Num.\n Example: H[1]=\"W12\" -> Hex 1 is Wood 12.\n • \"N\" (Nodes): Array where Index = NodeID.\n Format: [ [Neighbors], [HexIDs], Port? ]\n Logic: To find yield of Node 10, check N[10]. Get HexIDs (e.g. [1,5]). Look up H[1] and H[5].\n\n2. CODES: W=Wood, B=Brick, S=Sheep, Wh=Wheat, O=Ore, D=Desert.\n ?3=Any 3:1 port, X2=Specific Resource 2:1 port.\n\n3. STATE: \"bld\"=[NodeID, Owner, Type], \"rds\"=[[From,To], Owner].\n\n4. PLAYERS: \"res\"={Resource:Count}, \"dev\"={\"h\":[Hidden Cards], \"r\":[Revealed] (K=Knight)}, \n \"stat\"=[\"LR\" (Longest Road), \"LA\" (Largest Army)].\n\n5. ROBBER: Located at HexID specified in \"meta.robber\". H[id] is blocked.\n\nJSON:\n{\"game_id\":\"bef7f89a-adbf-4c0d-8160-0a0622dc18b4\",\"turn_number\":0,\"current_player\":0,\"game_phase\":\"SETUP_FIRST_ROUND\",\"turn_phase\":\"ROLL_DICE\",\"dice_rolled\":null,\"allowed_actions\":[\"PLACE_STARTING_SETTLEMENT\"],\"board_state\":{\"tiles\":[{\"id\":1,\"position\":[0,0],\"axial_coords\":[0,-2],\"type\":\"forest\",\"token\":10,\"has_robber\":false},{\"id\":2,\"position\":[0,1],\"axial_coords\":[1,-2],\"type\":\"pasture\",\"token\":4,\"has_robber\":false},{\"id\":3,\"position\":[0,2],\"axial_coords\":[2,-2],\"type\":\"hills\",\"token\":9,\"has_robber\":false},{\"id\":4,\"position\":[1,0],\"axial_coords\":[-1,-1],\"type\":\"mountains\",\"token\":11,\"has_robber\":false},{\"id\":5,\"position\":[1,1],\"axial_coords\":[0,-1],\"type\":\"fields\",\"token\":3,\"has_robber\":false},{\"id\":6,\"position\":[1,2],\"axial_coords\":[1,-1],\"type\":\"hills\",\"token\":8,\"has_robber\":false},{\"id\":7,\"position\":[1,3],\"axial_coords\":[2,-1],\"type\":\"fields\",\"token\":4,\"has_robber\":false},{\"id\":8,\"position\":[2,0],\"axial_coords\":[-2,0],\"type\":\"forest\",\"token\":8,\"has_robber\":false},{\"id\":9,\"position\":[2,1],\"axial_coords\":[-1,0],\"type\":\"mountains\",\"token\":12,\"has_robber\":false},{\"id\":10,\"position\":[2,2],\"axial_coords\":[0,0],\"type\":\"fields\",\"token\":6,\"has_robber\":false},{\"id\":11,\"position\":[2,3],\"axial_coords\":[1,0],\"type\":\"pasture\",\"token\":11,\"has_robber\":false},{\"id\":12,\"position\":[2,4],\"axial_coords\":[2,0],\"type\":\"forest\",\"token\":6,\"has_robber\":false},{\"id\":13,\"position\":[3,0],\"axial_coords\":[-2,1],\"type\":\"fields\",\"token\":5,\"has_robber\":false},{\"id\":14,\"position\":[3,1],\"axial_coords\":[-1,1],\"type\":\"forest\",\"token\":2,\"has_robber\":false},{\"id\":15,\"position\":[3,2],\"axial_coords\":[0,1],\"type\":\"pasture\",\"token\":5,\"has_robber\":false},{\"id\":16,\"position\":[3,3],\"axial_coords\":[1,1],\"type\":\"mountains\",\"token\":10,\"has_robber\":false},{\"id\":17,\"position\":[4,0],\"axial_coords\":[-2,2],\"type\":\"desert\",\"token\":null,\"has_robber\":true},{\"id\":18,\"position\":[4,1],\"axial_coords\":[-1,2],\"type\":\"hills\",\"token\":3,\"has_robber\":false},{\"id\":19,\"position\":[4,2],\"axial_coords\":[0,2],\"type\":\"pasture\",\"token\":9,\"has_robber\":false}],\"robber_position\":[4,0]},\"players_state\":[{\"player_id\":0,\"name\":\"shon\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0},{\"player_id\":1,\"name\":\"itay\",\"cards\":[],\"dev_cards\":[],\"settlements\":[],\"cities\":[],\"roads\":[],\"victory_points\":0,\"has_longest_road\":false,\"has_largest_army\":false,\"knights_played\":0}]}", + "constraints": { + "usage_instructions": "Choose one action type from the list below. Populate the 'parameters' field in your response strictly according to the 'example_parameters' structure provided.", + "allowed_actions": [ + { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + ] + } +} diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/responses/response_1.json b/examples/ai_testing/my_games/session_20260108_224242/shon/responses/response_1.json new file mode 100644 index 0000000000000000000000000000000000000000..9c0bc7dc2e0d69aad179d98dac78fed6a4977e06 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/responses/response_1.json @@ -0,0 +1,24 @@ +{ + "request_number": 1, + "timestamp": "2026-01-08T22:42:47.096322", + "player_name": "shon", + "success": true, + "raw_content": "{\n \"internal_thinking\": \"It is the first turn of the game, and I need to place my first settlement. I will choose a location that gives me access to a variety of resources. Node 20 is connected to hexes 5, 10, and 15 which represent Fields(3), Fields(6), and Pasture(5). These are good starting resources.\",\n \"action\": {\n \"type\": \"PLACE_STARTING_SETTLEMENT\",\n \"parameters\": \"{\\\"node\\\": 20}\"\n },\n \"note_to_self\": \"Remember to place a road after placing the settlement.\",\n \"say_outloud\": \"Placing my first settlement.\"\n}", + "parsed": { + "internal_thinking": "It is the first turn of the game, and I need to place my first settlement. I will choose a location that gives me access to a variety of resources. Node 20 is connected to hexes 5, 10, and 15 which represent Fields(3), Fields(6), and Pasture(5). These are good starting resources. [Response was too brief]", + "note_to_self": "Remember to place a road after placing the settlement.", + "say_outloud": "Placing my first settlement.", + "action_type": "PLACE_STARTING_SETTLEMENT", + "parameters": { + "node": 20 + } + }, + "model": "gemini-2.0-flash-exp", + "tokens": { + "prompt": 1818, + "completion": 158, + "total": 1976 + }, + "latency_seconds": 1.8663063049316406, + "error": null +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/responses/response_2.json b/examples/ai_testing/my_games/session_20260108_224242/shon/responses/response_2.json new file mode 100644 index 0000000000000000000000000000000000000000..8ebe72de7842316e6b9ae2e0a58a60201011e3a3 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/responses/response_2.json @@ -0,0 +1,24 @@ +{ + "request_number": 2, + "timestamp": "2026-01-08T22:43:34.472659", + "player_name": "shon", + "success": true, + "raw_content": "{\n \"internal_thinking\": \"I need to place my starting settlement. I will choose a node that gives me access to a variety of resources and good dice roll probabilities. I will analyze the board state to find the best location.\",\n \"action\": {\n \"type\": \"place_starting_settlement\",\n \"parameters\": \"{\\\"node\\\": 10}\"\n },\n \"note_to_self\": \"Remember to place a road after placing the settlement.\",\n \"say_outloud\": \"Placing my first settlement.\"\n}", + "parsed": { + "internal_thinking": "I need to place my starting settlement. I will choose a node that gives me access to a variety of resources and good dice roll probabilities. I will analyze the board state to find the best location. [Response was too brief]", + "note_to_self": "Remember to place a road after placing the settlement.", + "say_outloud": "Placing my first settlement.", + "action_type": "place_starting_settlement", + "parameters": { + "node": 10 + } + }, + "model": "gemini-2.0-flash-exp", + "tokens": { + "prompt": 1818, + "completion": 121, + "total": 1939 + }, + "latency_seconds": 1.474149465560913, + "error": null +} \ No newline at end of file diff --git a/examples/ai_testing/my_games/session_20260108_224242/shon/shon.md b/examples/ai_testing/my_games/session_20260108_224242/shon/shon.md new file mode 100644 index 0000000000000000000000000000000000000000..9046818d21c35cfc5186adcf6c211a5c0dd76289 --- /dev/null +++ b/examples/ai_testing/my_games/session_20260108_224242/shon/shon.md @@ -0,0 +1,58 @@ +# AI Agent Log: shon + +**Session:** session_20260108_224242 +**Started:** 2026-01-08 22:42:42 +**Model:** gemini-2.0-flash + +--- + + +## Request #1 - 🎯 ACTIVE TURN + +**Time:** 22:42:44 + +### What Happened +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_1.json](prompts/prompt_1.json) + +### Response Received ✅ + +**Latency:** 1.87s | **Tokens:** 1976 + +**Thinking:** It is the first turn of the game, and I need to place my first settlement. I will choose a location that gives me access to a variety of resources. Node 20 is connected to hexes 5, 10, and 15 which re... + +**Note to Self:** Remember to place a road after placing the settlement. + +**Says:** "Placing my first settlement." + +--- + +## Request #2 - 🎯 ACTIVE TURN + +**Time:** 22:43:32 + +### What Happened +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Game bef7f89a-adbf-4c0d-8160-0a0622dc18b4 has started with 2 players! +• Turn 0: Player 0's turn begins. +• Turn 0: Player 0's turn begins. + +### Prompt Sent +See: [prompt_2.json](prompts/prompt_2.json) + +### Response Received ✅ + +**Latency:** 1.47s | **Tokens:** 1939 + +**Thinking:** I need to place my starting settlement. I will choose a node that gives me access to a variety of resources and good dice roll probabilities. I will analyze the board state to find the best location. ... + +**Note to Self:** Remember to place a road after placing the settlement. + +**Says:** "Placing my first settlement." + +--- diff --git a/examples/ai_testing/play_with_ai.py b/examples/ai_testing/play_with_ai.py new file mode 100644 index 0000000000000000000000000000000000000000..b3c37f336ee99a1011c02069aedb3aa90310490e --- /dev/null +++ b/examples/ai_testing/play_with_ai.py @@ -0,0 +1,273 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Play Catan with AI Agents (Manual Mode) +--------------------------------------- + +This script starts a Catan game where AI agents generate prompts +but YOU enter their moves manually. This is useful for: +- Testing the AI prompt system +- Understanding what the AI "sees" +- Debugging AI decision making +- Training data collection + +How it works: +1. AI agents are registered for each player +2. When it's an AI player's turn, a prompt is generated and saved +3. You see the prompt info and enter what action the AI should take +4. The game executes that action + +All prompts and interactions are logged for later analysis. + +Usage: + python examples/ai_testing/play_with_ai.py + + # Or with options: + python examples/ai_testing/play_with_ai.py --players 3 --auto-llm +""" + +import sys +import os +from pathlib import Path + +# Add parent directories to path for imports +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from typing import List, Optional +import webbrowser +import threading +import time +from pycatan.management.game_manager import GameManager +from pycatan.players.human_user import HumanUser +from pycatan.ai import AIManager, AIUser, AIConfig +from pycatan.visualizations.web_visualization import WebVisualization +from pycatan.visualizations.visualization import VisualizationManager + +# Configure stdout for UTF-8 on Windows +import sys +import io +if sys.platform == 'win32': + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + + +def print_banner(): + """Print the welcome banner.""" + print("=" * 70) + print("[AI] PYCATAN WITH AI AGENTS") + print("=" * 70) + print() + print("All players are AI - you enter their moves manually.") + print() + + +def setup_game() -> tuple: + """ + Simple setup - ask how many players and their names. + All players are AI agents (manual input mode). + + Returns: + Tuple of (num_players, player_configs) + """ + print_banner() + + # Default player colors and names + colors = ["Red", "Blue", "White", "Orange"] + default_names = ["Alice", "Bob", "Charlie", "Diana"] + + # Get number of players + while True: + try: + num_str = input("How many players? (2-4) [3]: ").strip() + if not num_str: + num_players = 3 + else: + num_players = int(num_str) + + if 2 <= num_players <= 4: + break + else: + print("Enter 2-4") + except ValueError: + print("Enter a number") + + # Get player names + print(f"\nEnter names (or press Enter for default):") + player_configs = [] + for i in range(num_players): + name = input(f" Player {i+1} ({colors[i]}) [{default_names[i]}]: ").strip() + if not name: + name = default_names[i] + player_configs.append({ + "name": name, + "is_ai": True, + "color": colors[i] + }) + + # Brief summary + names = [p["name"] for p in player_configs] + print(f"\nPlayers: {', '.join(names)}") + print() + + return num_players, player_configs + + +def create_game(player_configs: List[dict], send_to_llm: bool = True, manual_actions: bool = True) -> tuple: + """ + Create the game with configured players. + + Args: + player_configs: List of player configuration dicts + send_to_llm: If True, sends prompts to LLM (shows suggestions) + manual_actions: If True, user enters actions manually + + Returns: + Tuple of (game_manager, ai_manager, web_viz) + """ + # Create AIManager (shared between all AI players) + ai_manager = AIManager( + config=AIConfig(), + send_to_llm=send_to_llm, + manual_actions=manual_actions + ) + + # Create user objects + users = [] + for i, cfg in enumerate(player_configs): + if cfg["is_ai"]: + # Create AI user + user = AIUser( + name=cfg["name"], + user_id=i, + ai_manager=ai_manager, + color=cfg["color"] + ) + else: + # Create human user + user = HumanUser(cfg["name"], i) + + users.append(user) + + # Create game manager + game_manager = GameManager(users) + + # Setup web visualization + web_viz = WebVisualization(port=5000, auto_open=False, debug=False) + viz_manager = VisualizationManager() + viz_manager.add_visualization(web_viz) + game_manager.visualization_manager = viz_manager + + print(f"\n[OK] Game created!") + print(f"[LOG] Session: {ai_manager.get_session_path()}") + print() + + return game_manager, ai_manager, web_viz + + +def run_game(game_manager: GameManager, ai_manager: AIManager, web_viz: WebVisualization): + """ + Run the main game loop. + + Args: + game_manager: The GameManager instance + ai_manager: The AIManager instance + web_viz: The WebVisualization instance + """ + # Start web server in background + web_viz.start_server() + + # Open browser + webbrowser.open("http://localhost:5000") + + print("=" * 70) + print("[GAME] GAME STARTING!") + print("[WEB] Board: http://localhost:5000") + print("=" * 70) + print() + print("Commands:") + print(" s - Place settlement (e.g., s 14)") + print(" rd - Place road (e.g., rd 14 15)") + print(" r - Roll dice") + print(" e - End turn") + print(" help - Show all commands") + print() + print("=" * 70) + print() + + try: + # Initialize the game + game_manager.start_game() + + # Run the main game loop + game_manager.game_loop() + + print("\n" + "=" * 70) + print("[WIN] GAME OVER!") + print("=" * 70) + + except KeyboardInterrupt: + print("\n\n[!] Game interrupted by user") + except Exception as e: + print(f"\n\n[ERROR] Error: {e}") + import traceback + traceback.print_exc() + finally: + # Save session + print("\n[SAVE] Saving session...") + ai_manager.save_session() + print(f"[LOG] Session saved to: {ai_manager.get_session_path()}") + + # Show stats + print("\n[STATS] AI Agent Statistics:") + stats = ai_manager.get_stats() + for name, agent_stats in stats.items(): + print(f" {name}: {agent_stats['total_requests']} requests, " + f"{agent_stats['total_tokens_used']} tokens") + + +def main(): + """Main entry point.""" + import argparse + + parser = argparse.ArgumentParser(description="Play Catan with AI agents") + parser.add_argument("--no-llm", action="store_true", + help="Don't send prompts to LLM (offline mode)") + parser.add_argument("--auto", action="store_true", + help="Let AI play automatically (no manual input)") + parser.add_argument("--players", type=int, choices=[2, 3, 4], + help="Number of players (skip setup)") + parser.add_argument("--all-ai", action="store_true", + help="Make all players AI (skip setup)") + args = parser.parse_args() + + # Quick setup mode + if args.players and args.all_ai: + colors = ["Red", "Blue", "White", "Orange"] + player_configs = [ + {"name": f"AI_{i+1}", "is_ai": True, "color": colors[i]} + for i in range(args.players) + ] + print_banner() + print(f"Quick setup: {args.players} AI players") + else: + # Interactive setup + num_players, player_configs = setup_game() + + # Determine mode + send_to_llm = not args.no_llm # Default: send to LLM + manual_actions = not args.auto # Default: manual input + + print(f"[MODE] LLM: {'ON' if send_to_llm else 'OFF'} | Actions: {'Manual' if manual_actions else 'Auto'}") + + # Create game + game_manager, ai_manager, web_viz = create_game( + player_configs, + send_to_llm=send_to_llm, + manual_actions=manual_actions + ) + + # Run game + run_game(game_manager, ai_manager, web_viz) + + +if __name__ == "__main__": + main() diff --git a/examples/ai_testing/templates/viewer_dynamic.html b/examples/ai_testing/templates/viewer_dynamic.html index 57d135736167eca425914a6797be56ce7aa25f99..467ff46857e077075b9433c4226d3033aa75373c 100644 --- a/examples/ai_testing/templates/viewer_dynamic.html +++ b/examples/ai_testing/templates/viewer_dynamic.html @@ -917,16 +917,17 @@ } function generateRequestCard(req) { + const requestId = `req_${req.player_name}_${req.request_number}`; const isNew = req.is_new ? ' new' : ''; const newBadge = req.is_new ? 'NEW' : ''; // Check if this is a freshly added request (for animation) - const isJustAdded = newRequestIds.has(req.request_id); + const isJustAdded = newRequestIds.has(requestId); const fadeInClass = isJustAdded ? ' fade-in highlight-new' : ''; // Remove from newRequestIds set after first render if (isJustAdded) { - setTimeout(() => newRequestIds.delete(req.request_id), 2000); + setTimeout(() => newRequestIds.delete(requestId), 2000); } const timestamp = new Date(req.timestamp).toLocaleString(); @@ -934,32 +935,39 @@ const thinking = response.internal_thinking || ''; const note = response.note_to_self || ''; const chat = response.say_outloud || ''; - const action = response.action || null; - const metadata = req.metadata || {}; - const latency = metadata.latency_seconds ? metadata.latency_seconds.toFixed(2) + 's' : 'N/A'; + + // Handle both old (action object) and new (action_type + parameters) formats + const actionType = response.action_type || (response.action ? response.action.type : null); + const actionParams = response.parameters || (response.action ? response.action.parameters : null); + + const tokens = req.tokens || {}; + const latency = tokens.total ? `${tokens.total} tokens` : 'N/A'; + + // Extract trigger from prompt + const trigger = req.prompt?.task_context?.what_just_happened || 'No trigger info'; + const phase = req.prompt?.game_state ? 'Active' : 'Unknown'; // Create content type icons const contentIcons = []; if (thinking) contentIcons.push('💭'); if (note) contentIcons.push('📝'); if (chat) contentIcons.push('💬'); - if (action) contentIcons.push('🎮'); + if (actionType) contentIcons.push('🎮'); const contentIconsHTML = contentIcons.length > 0 ? `
${contentIcons.join('')}
` : ''; return ` -
-
-
${req.request_id}
+
+
+
#${req.request_number}
${newBadge} - ${req.player_name.toUpperCase()}: ${escapeHtml(req.trigger)} + ${req.player_name.toUpperCase()}: ${escapeHtml(trigger.substring(0, 100))}... ${contentIconsHTML}
- ⏱️ ${latency} - 🎮 ${req.game_context.phase} - 👤 Turn: ${req.game_context.current_player} + 🔢 ${latency} + ${req.success ? '✅ Success' : '❌ Failed'} 📅 ${timestamp}
@@ -988,26 +996,25 @@
` : ''} - ${action ? ` + ${actionType ? `

🎮 Action

-
${action.type || 'N/A'}
- ${action.parameters ? ` -
Parameters: ${JSON.stringify(action.parameters)}
+
${actionType}
+ ${actionParams ? ` +
Parameters: ${JSON.stringify(actionParams)}
` : ''}
` : ''} - ${metadata.total_tokens ? ` + ${tokens.total ? `
-

📊 Metadata

+

📊 Token Usage

-
Total Tokens: ${metadata.total_tokens}
-
Prompt Tokens: ${metadata.prompt_tokens || 'N/A'}
-
Completion Tokens: ${metadata.completion_tokens || 'N/A'}
-
Response Time: ${metadata.latency_seconds ? metadata.latency_seconds.toFixed(3) + 's' : 'N/A'}
+
Total Tokens: ${tokens.total}
+
Prompt Tokens: ${tokens.prompt || 'N/A'}
+
Completion Tokens: ${tokens.completion || 'N/A'}
` : ''} @@ -1015,7 +1022,7 @@
📤 Original Prompt (JSON) -
${escapeHtml(JSON.stringify(req.prompt, null, 2))}
+
${escapeHtml(formatPromptInOrder(req.prompt))}
@@ -1117,16 +1124,10 @@ const total = requests.length; const newCount = requests.filter(r => r.is_new).length; - const latencies = requests - .map(r => r.metadata?.latency_seconds) - .filter(l => l != null); - const avgLatency = latencies.length > 0 - ? (latencies.reduce((a, b) => a + b, 0) / latencies.length).toFixed(2) - : '0'; - + // Use tokens object instead of metadata const tokenCounts = requests - .map(r => r.metadata?.total_tokens) - .filter(t => t != null); + .map(r => r.tokens?.total) + .filter(t => t != null && t > 0); const avgTokens = tokenCounts.length > 0 ? Math.round(tokenCounts.reduce((a, b) => a + b, 0) / tokenCounts.length) : 0; @@ -1134,23 +1135,29 @@ const totalTokens = tokenCounts.reduce((a, b) => a + b, 0); const promptTokens = requests - .map(r => r.metadata?.prompt_tokens || 0) + .map(r => r.tokens?.prompt || 0) .reduce((a, b) => a + b, 0); const completionTokens = requests - .map(r => r.metadata?.completion_tokens || 0) + .map(r => r.tokens?.completion || 0) .reduce((a, b) => a + b, 0); + // Gemini pricing (approximate) const inputCost = (promptTokens / 1000000) * 0.075; const outputCost = (completionTokens / 1000000) * 0.30; const totalCost = (inputCost + outputCost).toFixed(4); + // Calculate success rate + const successCount = requests.filter(r => r.success).length; + const successRate = total > 0 ? Math.round((successCount / total) * 100) : 0; + return { total, new: newCount, - avgLatency, + avgLatency: 'N/A', avgTokens, totalTokens, - totalCost + totalCost, + successRate }; } @@ -1279,6 +1286,30 @@ return div.innerHTML; } + function formatPromptInOrder(prompt) { + // Define the correct order for prompt keys + const keyOrder = ['meta_data', 'task_context', 'game_state', 'social_context', 'memory', 'constraints']; + const orderedPrompt = {}; + + // Add keys in the correct order + for (const key of keyOrder) { + if (prompt && prompt[key] !== undefined) { + orderedPrompt[key] = prompt[key]; + } + } + + // Add any remaining keys that weren't in our order list + if (prompt) { + for (const key of Object.keys(prompt)) { + if (!keyOrder.includes(key)) { + orderedPrompt[key] = prompt[key]; + } + } + } + + return JSON.stringify(orderedPrompt, null, 2); + } + function refreshData() { loadData(); } diff --git a/examples/ai_testing/web_viewer.py b/examples/ai_testing/web_viewer.py index 9cae7ad467ae9c389a85cd6f088c7c6eaceaf10d..6a2a75e2295bf54a4e3596bfb32cf84cf90d3880 100644 --- a/examples/ai_testing/web_viewer.py +++ b/examples/ai_testing/web_viewer.py @@ -18,19 +18,33 @@ app = Flask(__name__, # Ensure Flask preserves JSON key order app.config['JSON_SORT_KEYS'] = False -LOGS_DIR = Path("examples/ai_testing/my_games/ai_logs") -SESSION_FILE = Path("examples/ai_testing/my_games/current_session.txt") +# Session directories - use absolute path from script location +SCRIPT_DIR = Path(__file__).parent.absolute() +LOGS_DIR = SCRIPT_DIR / "my_games" +SESSION_FILE = LOGS_DIR / "current_session.txt" def get_current_session(): """Get current session directory.""" + print(f"[DEBUG] LOGS_DIR: {LOGS_DIR}") + print(f"[DEBUG] LOGS_DIR exists: {LOGS_DIR.exists()}") + print(f"[DEBUG] SESSION_FILE: {SESSION_FILE}") + print(f"[DEBUG] SESSION_FILE exists: {SESSION_FILE.exists()}") + if SESSION_FILE.exists(): try: with open(SESSION_FILE, 'r', encoding='utf-8') as f: - session_path = f.read().strip() - session_dir = Path(session_path) + session_name = f.read().strip() + print(f"[DEBUG] Session name from file: {session_name}") + # Handle both full path and just session name + if Path(session_name).is_absolute(): + session_dir = Path(session_name) + else: + session_dir = LOGS_DIR / session_name + print(f"[DEBUG] Session dir: {session_dir}") + print(f"[DEBUG] Session dir exists: {session_dir.exists()}") if session_dir.exists(): - print(f"✓ Found current session: {session_dir.name}") + print(f"[OK] Found current session: {session_dir.name}") return session_dir except Exception as e: print(f"Error reading session file: {e}") @@ -38,11 +52,12 @@ def get_current_session(): # Fallback: get most recent session if LOGS_DIR.exists(): sessions = sorted(LOGS_DIR.glob("session_*"), reverse=True) + print(f"[DEBUG] Found sessions: {[s.name for s in sessions]}") if sessions: - print(f"✓ Using most recent session: {sessions[0].name}") + print(f"[OK] Using most recent session: {sessions[0].name}") return sessions[0] - print("⚠ No session found") + print("[!] No session found") return None @@ -72,41 +87,79 @@ def get_session_data(session_path): print(f"Loading session data from: {session_dir}") - # Get structured requests data (new format) - requests_file = session_dir / "requests.json" + # Get structured requests data requests_data = [] - if requests_file.exists(): - try: - with open(requests_file, 'r', encoding='utf-8') as f: - # Use object_pairs_hook to preserve key order - data = json.load(f, object_pairs_hook=OrderedDict) - requests_data = data.get("requests", []) - print(f" ✓ Loaded {len(requests_data)} requests") - except Exception as e: - print(f" ✗ Error loading requests: {e}") - else: - print(f" ℹ No requests file found") - # Get player logs (old format - keep for backwards compatibility) + # Try new format: player folders with prompts/responses + for player_dir in session_dir.iterdir(): + if player_dir.is_dir() and (player_dir / "prompts").exists(): + player_name = player_dir.name + prompts_dir = player_dir / "prompts" + responses_dir = player_dir / "responses" + + # Load all prompts for this player + for prompt_file in sorted(prompts_dir.glob("prompt_*.json")): + try: + with open(prompt_file, 'r', encoding='utf-8') as f: + prompt_data = json.load(f) + + req_num = prompt_data.get("request_number", 0) + + # Try to load corresponding response + response_data = None + response_file = responses_dir / f"response_{req_num}.json" + if response_file.exists(): + with open(response_file, 'r', encoding='utf-8') as f: + response_data = json.load(f) + + requests_data.append({ + "player_name": player_name, + "request_number": req_num, + "timestamp": prompt_data.get("timestamp", ""), + "prompt": prompt_data.get("prompt", {}), + "response": response_data.get("parsed", {}) if response_data else None, + "raw_response": response_data.get("raw_content", "") if response_data else None, + "tokens": response_data.get("tokens", {}) if response_data else {}, + "success": response_data.get("success", False) if response_data else False + }) + + except Exception as e: + print(f" [!] Error loading {prompt_file.name}: {e}") + + print(f" [OK] Loaded {player_name}: {len([p for p in requests_data if p['player_name'] == player_name])} requests") + + # Fallback: try old format (requests.json) + if not requests_data: + requests_file = session_dir / "requests.json" + if requests_file.exists(): + try: + with open(requests_file, 'r', encoding='utf-8') as f: + data = json.load(f, object_pairs_hook=OrderedDict) + requests_data = data.get("requests", []) + print(f" [OK] Loaded {len(requests_data)} requests (old format)") + except Exception as e: + print(f" [!] Error loading requests: {e}") + + # Sort by timestamp + requests_data.sort(key=lambda x: x.get("timestamp", "")) + + # Get player logs - check player folders players = {} - for player_file in session_dir.glob("player_*.md"): - player_name = player_file.stem.replace("player_", "").upper() - try: - with open(player_file, 'r', encoding='utf-8') as f: - content = f.read() - players[player_name] = { - "name": player_name, - "content": content, - "html": html.escape(content) - } - print(f" ✓ Loaded player: {player_name}") - except Exception as e: - print(f" ✗ Error loading {player_name}: {e}") - players[player_name] = { - "name": player_name, - "content": f"Error loading: {e}", - "html": html.escape(f"Error loading: {e}") - } + for player_dir in session_dir.iterdir(): + if player_dir.is_dir(): + player_name = player_dir.name + md_file = player_dir / f"{player_name}.md" + if md_file.exists(): + try: + with open(md_file, 'r', encoding='utf-8') as f: + content = f.read() + players[player_name] = { + "name": player_name, + "content": content, + "html": html.escape(content) + } + except Exception as e: + print(f" [!] Error loading {player_name}: {e}") # Get chat history chat_file = session_dir / "chat_history.json" @@ -116,12 +169,10 @@ def get_session_data(session_path): with open(chat_file, 'r', encoding='utf-8') as f: data = json.load(f) chat_messages = data.get("messages", []) - print(f" ✓ Loaded {len(chat_messages)} chat messages") + print(f" [OK] Loaded {len(chat_messages)} chat messages") except Exception as e: - print(f" ✗ Error loading chat: {e}") + print(f" [!] Error loading chat: {e}") chat_messages = [{"error": str(e)}] - else: - print(f" ℹ No chat history file") # Get agent memories memory_file = session_dir / "agent_memories.json" @@ -130,12 +181,10 @@ def get_session_data(session_path): try: with open(memory_file, 'r', encoding='utf-8') as f: memories = json.load(f) - print(f" ✓ Loaded memories for {len(memories)} players") + print(f" [OK] Loaded memories for {len(memories)} players") except Exception as e: - print(f" ✗ Error loading memories: {e}") + print(f" [!] Error loading memories: {e}") memories = {} - else: - print(f" ℹ No memories file") # Calculate statistics new_requests_count = sum(1 for req in requests_data if req.get("is_new", False)) @@ -283,12 +332,12 @@ def api_mark_all_viewed(session_path): if __name__ == '__main__': print("="*80) - print("🌐 AI Game Viewer Starting...") + print("[WEB] AI Game Viewer Starting...") print("="*80) - print(f"\n📁 Watching: {LOGS_DIR.absolute()}") - print(f"📄 Session file: {SESSION_FILE.absolute()}") - print(f"\n🔗 Open in browser: http://localhost:5001") - print("\n⚠️ Note: Game board is on http://localhost:5000") + print(f"\n[DIR] Watching: {LOGS_DIR.absolute()}") + print(f"[FILE] Session file: {SESSION_FILE.absolute()}") + print(f"\n[URL] Open in browser: http://localhost:5001") + print("\n[NOTE] Game board is on http://localhost:5000") print(" This viewer (5001) shows AI requests/responses") print(" Game board (5000) shows the actual Catan board") print("\n" + "="*80 + "\n") diff --git a/play_ai.bat b/play_ai.bat new file mode 100644 index 0000000000000000000000000000000000000000..50b95c61afc770b5b0ec4a7740cf776657f96df0 --- /dev/null +++ b/play_ai.bat @@ -0,0 +1,100 @@ +@echo off +REM ============================================ +REM PyCatan with AI Agents - Full System Launcher +REM ============================================ +REM This script starts: +REM 1. Web Viewer (for viewing AI prompts/responses) +REM 2. The main game with AI agents +REM ============================================ + +REM Enable DEBUG logging +set LOGLEVEL=DEBUG + +echo. +echo ================================================================================ +echo PyCatan AI System - Full Launch +echo ================================================================================ +echo. +echo Starting components: +echo 1. AI Viewer (http://localhost:5001) - Shows AI prompts and responses +echo 2. Catan Game with AI Agents +echo. +echo ================================================================================ +echo. + +cd /d "%~dp0" + +REM Check if Python is available +where python >nul 2>nul +if %ERRORLEVEL% NEQ 0 ( + echo ERROR: Python not found in PATH + pause + exit /b 1 +) + +REM Check for virtual environment +if exist ".venv\Scripts\python.exe" ( + set PYTHON_CMD=.venv\Scripts\python.exe + echo [OK] Using virtual environment +) else ( + set PYTHON_CMD=python + echo [!] No virtual environment found, using system Python +) + +echo. + +REM Start Web Viewer in a new window +echo [1/3] Starting AI Viewer... +start "AI Viewer - http://localhost:5001" cmd /k "%PYTHON_CMD% examples\ai_testing\web_viewer.py" + +REM Wait for web viewer to start +timeout /t 2 /nobreak >nul + +echo [OK] AI Viewer started at http://localhost:5001 +echo. + +REM Start LLM Logger Console in a new window +echo [2/3] Starting LLM Logger Console... +start "LLM Logger - Communication Log" cmd /k "%PYTHON_CMD% examples\ai_testing\llm_logger_console.py" +timeout /t 1 /nobreak >nul +echo [OK] LLM Logger console opened +echo. + +REM Open browser for AI Viewer +echo [BROWSER] Opening AI Viewer... +timeout /t 1 /nobreak >nul +start http://localhost:5001 + +echo. +echo [3/3] Starting game in this window... +echo. +echo ================================================================================ +echo GAME CONTROLS +echo ================================================================================ +echo - LLM sends suggestions, you approve or override +echo - Press ENTER to accept LLM suggestion +echo - Or type your own command +echo. +echo Quick commands: +echo r - Roll dice +echo e - End turn +echo s 14 - Build settlement at node 14 +echo rd 14 15 - Build road from 14 to 15 +echo. +echo Flags: +echo --no-llm - Don't send to LLM (offline mode) +echo --auto - Let AI play automatically +echo ================================================================================ +echo. + +REM Start the game +%PYTHON_CMD% examples\ai_testing\play_with_ai.py %* + +echo. +echo ================================================================================ +echo Game session complete! +echo ================================================================================ +echo. +echo Session logs saved to: examples\ai_testing\my_games\ +echo. +pause diff --git a/pycatan/ai/__init__.py b/pycatan/ai/__init__.py index 937fc29b25f458db628e1f8492c2e4e11c105f03..fad54e311b30428556f5a33a6ea2c27a60b0f480 100644 --- a/pycatan/ai/__init__.py +++ b/pycatan/ai/__init__.py @@ -4,36 +4,93 @@ AI Agent Infrastructure for PyCatan This package contains the infrastructure for building LLM-based AI agents that can play Settlers of Catan autonomously. -Components: +Main Components: +- AIManager: Central coordinator for all AI agents +- AIUser: User interface wrapper for AI agents +- AILogger: Logging and session management +- AgentState: Per-agent state tracking + +Supporting Components: - config: Configuration management for AI agents - prompt_manager: Prompt construction and game state filtering - state_filter: Game state filtering and perspective transformation - prompt_templates: Prompt structure and action templates -- response_parser: LLM response parsing and validation (TODO) -- memory: Agent memory and learning systems (TODO) -- llm_client: LLM API abstraction and client (TODO) +- response_parser: LLM response parsing and validation +- llm_client: LLM API abstraction and client +- schemas: JSON schemas for LLM responses Architecture Overview: -┌─────────────────────────────────────────────────────────┐ -│ AIAgent │ -│ (Main AI player implementation) │ -├─────────────────────────────────────────────────────────┤ -│ │ -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ -│ │ Config │ │ Prompt │ │ Response │ │ -│ │ Management │ │ Manager │ │ Parser │ │ -│ └──────────────┘ └──────────────┘ └──────────────┘ │ -│ ✅ ✅ 🚧 │ -│ │ -│ ┌──────────────┐ ┌──────────────┐ │ -│ │ Memory │ │ LLM Client │ │ -│ │ System │ │ (Multi-API) │ │ -│ └──────────────┘ └──────────────┘ │ -│ 🚧 🚧 │ -└─────────────────────────────────────────────────────────┘ +┌─────────────────────────────────────────────────────────────────────┐ +│ AI System Architecture │ +├─────────────────────────────────────────────────────────────────────┤ +│ │ +│ GameManager AIManager │ +│ │ │ │ +│ │ get_input() │ Creates prompts │ +│ ▼ │ Sends to LLM │ +│ ┌─────────┐ │ Parses responses │ +│ │ AIUser │◄──────── delegates to ──────►│ │ +│ │(Wrapper)│ │ │ +│ └─────────┘ ▼ │ +│ ┌─────────────┐ │ +│ │ AILogger │ │ +│ │ (Logging) │ │ +│ └─────────────┘ │ +│ │ +│ Components: │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Config │ │ Prompt │ │ Response │ │ +│ │ Management │ │ Manager │ │ Parser │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ✅ ✅ ✅ │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Agent State │ │ LLM Client │ │ Schemas │ │ +│ │ Tracking │ │ (Gemini) │ │ (JSON) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ✅ ✅ ✅ │ +└─────────────────────────────────────────────────────────────────────┘ Status: ✅ Complete | 🚧 In Development | ❌ Not Started """ -__version__ = "0.1.0" -__all__ = ["config", "prompt_manager", "state_filter", "prompt_templates"] +__version__ = "2.0.0" + +# Main classes +from pycatan.ai.ai_manager import AIManager +from pycatan.ai.ai_user import AIUser +from pycatan.ai.ai_logger import AILogger +from pycatan.ai.agent_state import AgentState, compute_state_hash + +# Supporting classes +from pycatan.ai.config import AIConfig +from pycatan.ai.prompt_manager import PromptManager +from pycatan.ai.response_parser import ResponseParser +from pycatan.ai.llm_client import LLMResponse, GeminiClient, create_llm_client +from pycatan.ai.schemas import ResponseType, ACTIVE_TURN_RESPONSE_SCHEMA, OBSERVING_RESPONSE_SCHEMA + +__all__ = [ + # Main classes + "AIManager", + "AIUser", + "AILogger", + "AgentState", + "compute_state_hash", + + # Configuration + "AIConfig", + + # Prompt handling + "PromptManager", + "ResponseParser", + + # LLM + "LLMResponse", + "GeminiClient", + "create_llm_client", + + # Schemas + "ResponseType", + "ACTIVE_TURN_RESPONSE_SCHEMA", + "OBSERVING_RESPONSE_SCHEMA", +] diff --git a/pycatan/ai/agent_state.py b/pycatan/ai/agent_state.py new file mode 100644 index 0000000000000000000000000000000000000000..311442c72c79518d4b0971f3e3d74ff2d48f4923 --- /dev/null +++ b/pycatan/ai/agent_state.py @@ -0,0 +1,218 @@ +""" +Agent State Management for PyCatan AI Agents + +This module defines the AgentState dataclass that holds all state information +for a single AI agent, including: +- Player identification +- Request tracking +- Memory and notes +- Event history +- Statistics + +Each AI agent has its own AgentState instance managed by the AIManager. +""" + +import time +import hashlib +from typing import Dict, Any, Optional, List +from dataclasses import dataclass, field + + +@dataclass +class AgentState: + """ + State for a single AI agent. + + Manages all agent-specific data including memory, pending requests, + recent events, and tracking information. + + Attributes: + player_name: Display name of the player + player_id: Unique player ID (0-based index) + player_color: Color assigned to player (e.g., "Red", "Blue") + pending_request: True if waiting for LLM response + last_request_time: Timestamp of last request sent + memory: Agent's note_to_self from last response + chat_summaries: List of chat summary strings + recent_events: Events since last prompt + last_state_hash: Hash of game state at last prompt + last_prompt_time: When last prompt was sent + total_requests: Total API requests made + total_tokens_used: Total tokens consumed + """ + + # === Identification === + player_name: str + player_id: int + player_color: str = "" + + # === Request Status === + pending_request: bool = False + last_request_time: Optional[float] = None + + # === Memory === + memory: Optional[str] = None # note_to_self from last response + + # === Chat Summaries (for future use) === + chat_summaries: List[str] = field(default_factory=list) + + # === Recent Events === + # Events that occurred since last prompt was sent + # Each event: {"type": str, "message": str, "timestamp": float} + recent_events: List[Dict[str, Any]] = field(default_factory=list) + + # === Change Tracking === + last_state_hash: Optional[str] = None + last_prompt_time: Optional[float] = None + last_prompt_number: int = 0 + + # === Statistics === + total_requests: int = 0 + total_tokens_used: int = 0 + successful_requests: int = 0 + failed_requests: int = 0 + + def add_event(self, event_type: str, message: str, data: Optional[Dict] = None) -> None: + """ + Add a new event to the agent's recent events. + + Args: + event_type: Type of event (e.g., "dice_roll", "build", "trade") + message: Human-readable description of the event + data: Optional additional data about the event + """ + event = { + "type": event_type, + "message": message, + "timestamp": time.time() + } + if data: + event["data"] = data + self.recent_events.append(event) + + def clear_events(self) -> List[Dict[str, Any]]: + """ + Clear recent events and return them. + + Returns: + List of events that were cleared + """ + events = self.recent_events.copy() + self.recent_events = [] + return events + + def get_events_summary(self) -> str: + """ + Generate a summary of recent events for prompt. + + Returns: + Human-readable summary string of recent events + """ + if not self.recent_events: + return "No recent events." + + # Group events by type and create summary + lines = [] + for event in self.recent_events: + lines.append(f"- {event['message']}") + + return "\n".join(lines) + + def mark_request_sent(self) -> None: + """Mark that a request has been sent to the LLM.""" + self.pending_request = True + self.last_request_time = time.time() + self.total_requests += 1 + self.last_prompt_number += 1 + + def mark_request_complete(self, success: bool = True, tokens: int = 0) -> None: + """ + Mark that a request has completed. + + Args: + success: Whether the request was successful + tokens: Number of tokens used in the request + """ + self.pending_request = False + self.total_tokens_used += tokens + if success: + self.successful_requests += 1 + else: + self.failed_requests += 1 + + def update_memory(self, note_to_self: Optional[str]) -> None: + """ + Update the agent's memory with a new note. + + Args: + note_to_self: The new note to remember + """ + if note_to_self: + self.memory = note_to_self + + def update_state_hash(self, state_hash: str) -> bool: + """ + Update the state hash and return whether it changed. + + Args: + state_hash: New hash of the game state + + Returns: + True if the state changed, False otherwise + """ + changed = self.last_state_hash != state_hash + self.last_state_hash = state_hash + return changed + + def get_stats(self) -> Dict[str, Any]: + """ + Get statistics about this agent. + + Returns: + Dictionary with agent statistics + """ + return { + "player_name": self.player_name, + "player_id": self.player_id, + "total_requests": self.total_requests, + "successful_requests": self.successful_requests, + "failed_requests": self.failed_requests, + "total_tokens_used": self.total_tokens_used, + "success_rate": ( + f"{self.successful_requests / self.total_requests * 100:.1f}%" + if self.total_requests > 0 else "N/A" + ) + } + + def to_dict(self) -> Dict[str, Any]: + """ + Convert agent state to dictionary for serialization. + + Returns: + Dictionary representation of agent state + """ + return { + "player_name": self.player_name, + "player_id": self.player_id, + "player_color": self.player_color, + "memory": self.memory, + "chat_summaries": self.chat_summaries, + "recent_events": self.recent_events, + "last_prompt_number": self.last_prompt_number, + "stats": self.get_stats() + } + + +def compute_state_hash(state: Dict[str, Any]) -> str: + """ + Compute a hash of the game state for change detection. + + Args: + state: Game state dictionary + + Returns: + Hash string + """ + import json + state_str = json.dumps(state, sort_keys=True, default=str) + return hashlib.md5(state_str.encode()).hexdigest()[:16] diff --git a/pycatan/ai/ai_logger.py b/pycatan/ai/ai_logger.py new file mode 100644 index 0000000000000000000000000000000000000000..00de1cc6ff5e13292021470f918845c9f50b69ce --- /dev/null +++ b/pycatan/ai/ai_logger.py @@ -0,0 +1,452 @@ +""" +AI Logger for PyCatan AI Agents + +This module handles all logging for the AI system: +- Prompt logging (JSON + TXT files) +- Response logging (JSON files) +- Player MD logs (human-readable) +- Session management + +Maintains compatibility with existing log formats while providing +a cleaner interface for the new AIManager. +""" + +import json +import time +from pathlib import Path +from datetime import datetime +from typing import Dict, Any, Optional, List + +from pycatan.ai.llm_client import LLMResponse + + +class AILogger: + """ + Centralized logging for AI agents. + + Creates and manages: + - Session directories with timestamps + - Per-player log files (MD format) + - Prompt and response JSON files + - Summary statistics + + Directory Structure: + session_YYYYMMDD_HHMMSS/ + ├── player_name/ + │ ├── prompts/ + │ │ ├── prompt_1.json + │ │ ├── prompt_1.txt + │ │ └── ... + │ ├── responses/ + │ │ ├── response_1.json + │ │ └── ... + │ └── player_name.md + ├── chat_history.json + └── session_summary.json + """ + + def __init__(self, session_dir: Optional[Path] = None, base_dir: Optional[Path] = None): + """ + Initialize the AI logger. + + Args: + session_dir: Explicit session directory path. If None, auto-creates. + base_dir: Base directory for sessions. Default: examples/ai_testing/my_games/ + """ + self.base_dir = base_dir or Path("examples/ai_testing/my_games") + + if session_dir is not None: + self.session_dir = Path(session_dir) + else: + self.session_dir = self._create_session_dir() + + self.session_dir.mkdir(parents=True, exist_ok=True) + + # Track request numbers per player + self.request_counters: Dict[str, int] = {} + + # Session start time + self.start_time = datetime.now() + + # Initialize session + self._init_session() + + def _create_session_dir(self) -> Path: + """Create a new session directory with timestamp.""" + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + session_dir = self.base_dir / f"session_{timestamp}" + return session_dir + + def _init_session(self) -> None: + """Initialize the session with metadata.""" + metadata = { + "session_id": self.session_dir.name, + "start_time": self.start_time.isoformat(), + "version": "2.0" + } + + metadata_file = self.session_dir / "session_metadata.json" + with open(metadata_file, 'w', encoding='utf-8') as f: + json.dump(metadata, f, indent=2) + + # Create LLM communication log file + self.llm_log_file = self.session_dir / "llm_communication.log" + with open(self.llm_log_file, 'w', encoding='utf-8') as f: + f.write(f"=== LLM Communication Log ===\n") + f.write(f"Session: {self.session_dir.name}\n") + f.write(f"Started: {self.start_time.isoformat()}\n") + f.write("=" * 50 + "\n\n") + + # Save session path for other tools (like web_viewer) + current_session_file = self.base_dir / "current_session.txt" + with open(current_session_file, 'w', encoding='utf-8') as f: + f.write(self.session_dir.name) + + def log_llm_communication(self, message: str, msg_type: str = "INFO") -> None: + """ + Log a message to the LLM communication log file. + + Args: + message: The message to log + msg_type: Type of message (SEND, RECV, ERROR, INFO) + """ + timestamp = datetime.now().strftime("%H:%M:%S") + line = f"[{timestamp}] [{msg_type}] {message}\n" + + with open(self.llm_log_file, 'a', encoding='utf-8') as f: + f.write(line) + f.flush() # Ensure immediate write + + def _ensure_player_dirs(self, player_name: str) -> Dict[str, Path]: + """ + Ensure directories exist for a player. + + Returns: + Dict with 'root', 'prompts', 'responses' paths + """ + player_dir = self.session_dir / player_name + prompts_dir = player_dir / "prompts" + responses_dir = player_dir / "responses" + + player_dir.mkdir(parents=True, exist_ok=True) + prompts_dir.mkdir(exist_ok=True) + responses_dir.mkdir(exist_ok=True) + + return { + "root": player_dir, + "prompts": prompts_dir, + "responses": responses_dir + } + + def _get_request_number(self, player_name: str) -> int: + """Get and increment request number for player.""" + if player_name not in self.request_counters: + self.request_counters[player_name] = 0 + self.request_counters[player_name] += 1 + return self.request_counters[player_name] + + def log_prompt( + self, + player_name: str, + prompt: Dict[str, Any], + schema: Optional[Dict[str, Any]] = None, + is_active: bool = True, + what_happened: str = "", + allowed_actions: Optional[List[Dict]] = None + ) -> Dict[str, Any]: + """ + Log a prompt for a player. + + Args: + player_name: Name of the player + prompt: The prompt dictionary + schema: Response schema (for reference) + is_active: Whether this is an active turn prompt + what_happened: Description of what happened + allowed_actions: List of allowed actions + + Returns: + Dict with 'number', 'json_path', 'txt_path' + """ + dirs = self._ensure_player_dirs(player_name) + num = self._get_request_number(player_name) + + # Prepare full prompt document + prompt_doc = { + "request_number": num, + "timestamp": datetime.now().isoformat(), + "player_name": player_name, + "is_active_turn": is_active, + "prompt": prompt + } + + if schema: + prompt_doc["response_schema"] = schema + if what_happened: + prompt_doc["what_happened"] = what_happened + if allowed_actions: + prompt_doc["allowed_actions"] = allowed_actions + + # Save JSON file + json_path = dirs["prompts"] / f"prompt_{num}.json" + with open(json_path, 'w', encoding='utf-8') as f: + json.dump(prompt_doc, f, indent=2, ensure_ascii=False) + + # Save TXT file (just the prompt content as string) + txt_path = dirs["prompts"] / f"prompt_{num}.txt" + prompt_str = json.dumps(prompt, indent=2, ensure_ascii=False) + schema_str = json.dumps(schema, indent=2, ensure_ascii=False) if schema else "N/A" + with open(txt_path, 'w', encoding='utf-8') as f: + f.write(f"=== Prompt #{num} for {player_name} ===\n") + f.write(f"Timestamp: {datetime.now().isoformat()}\n") + f.write(f"Active Turn: {is_active}\n") + f.write(f"\n--- What Happened ---\n{what_happened}\n") + f.write(f"\n--- Response Schema ---\n{schema_str}\n") + f.write(f"\n--- Prompt Content ---\n{prompt_str}\n") + + # Update MD log + self._append_prompt_to_md(player_name, num, prompt, is_active, what_happened) + + return { + "number": num, + "json_path": json_path, + "txt_path": txt_path + } + + def log_response( + self, + player_name: str, + request_number: int, + response: LLMResponse, + parsed: Optional[Dict[str, Any]] = None + ) -> Path: + """ + Log a response from the LLM. + + Args: + player_name: Name of the player + request_number: The request number this responds to + response: The LLMResponse object + parsed: Parsed response data + + Returns: + Path to the response JSON file + """ + dirs = self._ensure_player_dirs(player_name) + + # Prepare response document + response_doc = { + "request_number": request_number, + "timestamp": datetime.now().isoformat(), + "player_name": player_name, + "success": response.success, + "raw_content": response.content, + "parsed": parsed, + "model": response.model, + "tokens": { + "prompt": response.prompt_tokens, + "completion": response.completion_tokens, + "total": response.total_tokens + }, + "latency_seconds": response.latency_seconds, + "error": response.error + } + + # Save JSON file + json_path = dirs["responses"] / f"response_{request_number}.json" + with open(json_path, 'w', encoding='utf-8') as f: + json.dump(response_doc, f, indent=2, ensure_ascii=False) + + # Update MD log + self._append_response_to_md(player_name, request_number, response, parsed) + + return json_path + + def _init_player_md(self, player_name: str, model: str = "gemini-2.0-flash") -> None: + """Initialize MD file for a player.""" + dirs = self._ensure_player_dirs(player_name) + md_path = dirs["root"] / f"{player_name}.md" + + if md_path.exists(): + return # Already initialized + + header = f"""# AI Agent Log: {player_name} + +**Session:** {self.session_dir.name} +**Started:** {self.start_time.strftime('%Y-%m-%d %H:%M:%S')} +**Model:** {model} + +--- + +""" + with open(md_path, 'w', encoding='utf-8') as f: + f.write(header) + + def _append_prompt_to_md( + self, + player_name: str, + num: int, + prompt: Dict[str, Any], + is_active: bool, + what_happened: str + ) -> None: + """Append prompt section to MD file.""" + dirs = self._ensure_player_dirs(player_name) + md_path = dirs["root"] / f"{player_name}.md" + + # Initialize if needed + if not md_path.exists(): + self._init_player_md(player_name) + + turn_type = "🎯 ACTIVE TURN" if is_active else "👀 OBSERVING" + + section = f""" +## Request #{num} - {turn_type} + +**Time:** {datetime.now().strftime('%H:%M:%S')} + +### What Happened +{what_happened if what_happened else "(No events)"} + +### Prompt Sent +See: [prompt_{num}.json](prompts/prompt_{num}.json) + +""" + with open(md_path, 'a', encoding='utf-8') as f: + f.write(section) + + def _append_response_to_md( + self, + player_name: str, + num: int, + response: LLMResponse, + parsed: Optional[Dict[str, Any]] + ) -> None: + """Append response section to MD file.""" + dirs = self._ensure_player_dirs(player_name) + md_path = dirs["root"] / f"{player_name}.md" + + if response.success and parsed: + # Extract key fields + thinking = parsed.get("internal_thinking", "N/A") + note = parsed.get("note_to_self", "") + say = parsed.get("say_outloud", "") + action = parsed.get("action", {}) + + action_str = "" + if action: + action_str = f"**{action.get('type', 'unknown')}**" + params = action.get("parameters", {}) + if params: + action_str += f" - {json.dumps(params)}" + + section = f"""### Response Received ✅ + +**Latency:** {response.latency_seconds:.2f}s | **Tokens:** {response.total_tokens} + +**Thinking:** {thinking[:200]}{'...' if len(thinking) > 200 else ''} + +""" + if note: + section += f"**Note to Self:** {note}\n\n" + if say: + section += f'**Says:** "{say}"\n\n' + if action_str: + section += f"**Action:** {action_str}\n\n" + + else: + # Error response + section = f"""### Response Failed ❌ + +**Error:** {response.error or 'Unknown error'} +**Latency:** {response.latency_seconds:.2f}s + +""" + + section += "---\n" + + with open(md_path, 'a', encoding='utf-8') as f: + f.write(section) + + def log_chat(self, from_player: str, message: str, to_player: Optional[str] = None) -> None: + """ + Log a chat message. + + Args: + from_player: Player who sent the message + message: The chat message + to_player: Target player (None = broadcast) + """ + chat_file = self.session_dir / "chat_history.json" + + # Load existing chat + chat_history = [] + if chat_file.exists(): + with open(chat_file, 'r', encoding='utf-8') as f: + chat_history = json.load(f) + + # Add new message + chat_history.append({ + "timestamp": datetime.now().isoformat(), + "from": from_player, + "to": to_player or "all", + "message": message + }) + + # Save + with open(chat_file, 'w', encoding='utf-8') as f: + json.dump(chat_history, f, indent=2, ensure_ascii=False) + + def log_error(self, player_name: str, error: str, context: Optional[Dict] = None) -> None: + """Log an error for a player.""" + dirs = self._ensure_player_dirs(player_name) + md_path = dirs["root"] / f"{player_name}.md" + + section = f""" +### ⚠️ Error + +**Time:** {datetime.now().strftime('%H:%M:%S')} +**Error:** {error} + +""" + if context: + section += f"**Context:** {json.dumps(context, indent=2)}\n\n" + + section += "---\n" + + with open(md_path, 'a', encoding='utf-8') as f: + f.write(section) + + def save_session_summary(self, agents: Dict[str, Any], game_state: Optional[Dict] = None) -> None: + """ + Save session summary at the end. + + Args: + agents: Dictionary of AgentState objects + game_state: Final game state + """ + summary = { + "session_id": self.session_dir.name, + "start_time": self.start_time.isoformat(), + "end_time": datetime.now().isoformat(), + "duration_seconds": (datetime.now() - self.start_time).total_seconds(), + "agents": { + name: agent.to_dict() if hasattr(agent, 'to_dict') else str(agent) + for name, agent in agents.items() + } + } + + if game_state: + summary["final_game_state"] = game_state + + summary_file = self.session_dir / "session_summary.json" + with open(summary_file, 'w', encoding='utf-8') as f: + json.dump(summary, f, indent=2, ensure_ascii=False) + + def get_session_path(self) -> Path: + """Get the session directory path.""" + return self.session_dir + + def get_player_log_path(self, player_name: str) -> Path: + """Get the MD log path for a player.""" + return self.session_dir / player_name / f"{player_name}.md" diff --git a/pycatan/ai/ai_manager.py b/pycatan/ai/ai_manager.py new file mode 100644 index 0000000000000000000000000000000000000000..80c2f4237abc0df103b4073b6be614260205c515 --- /dev/null +++ b/pycatan/ai/ai_manager.py @@ -0,0 +1,726 @@ +""" +AI Manager - Central Coordinator for AI Agents + +This is the main orchestrator for all AI agent activities: +- Manages agent state and lifecycle +- Creates and sends prompts +- Processes responses from LLM +- Handles chat and game events +- Coordinates with the logging system + +The AIManager bridges between GameManager (through AIUser) and the LLM. +""" + +import json +import time +from pathlib import Path +from typing import Dict, Any, Optional, List, Callable + +from pycatan.ai.config import AIConfig +from pycatan.ai.prompt_manager import PromptManager +from pycatan.ai.llm_client import LLMResponse, create_llm_client, GeminiClient +from pycatan.ai.response_parser import ResponseParser, ParseResult +from pycatan.ai.schemas import ResponseType, ACTIVE_TURN_RESPONSE_SCHEMA, OBSERVING_RESPONSE_SCHEMA +from pycatan.ai.agent_state import AgentState, compute_state_hash +from pycatan.ai.ai_logger import AILogger +from pycatan.management.actions import Action, ActionType + + +class AIManager: + """ + Central manager for all AI agents in a game. + + Responsibilities: + - Register and manage AI agents + - Create prompts from game state + - Send prompts to LLM + - Parse and validate responses + - Track agent memory and events + - Log all interactions + + The AIManager does NOT know about game rules - it only + transforms game state into prompts and responses into actions. + """ + + def __init__( + self, + config: Optional[AIConfig] = None, + session_dir: Optional[Path] = None, + auto_send_to_llm: bool = False, + send_to_llm: bool = True, + manual_actions: bool = True + ): + """ + Initialize the AI Manager. + + Args: + config: AI configuration (uses defaults if None) + session_dir: Directory for logging (auto-creates if None) + auto_send_to_llm: DEPRECATED - use send_to_llm + manual_actions + send_to_llm: If True, sends prompts to LLM and shows response + manual_actions: If True, user enters actions manually (even if LLM responds) + """ + self.config = config or AIConfig() + self.send_to_llm = send_to_llm + self.manual_actions = manual_actions + # Legacy support + if auto_send_to_llm: + self.send_to_llm = True + self.manual_actions = False + + # Core components + self.prompt_manager = PromptManager(self.config) + self.response_parser = ResponseParser() + self.logger = AILogger(session_dir=session_dir) + + # LLM client (created lazily when needed) + self._llm_client: Optional[GeminiClient] = None + + # Agent state management + self.agents: Dict[str, AgentState] = {} + + # Chat history (shared between all agents) + self.chat_history: List[Dict[str, Any]] = [] + self.max_chat_history: int = 20 + + # Current game state (updated by AIUser) + self._current_game_state: Optional[Dict[str, Any]] = None + self._current_allowed_actions: Optional[List[str]] = None + + # Callback for manual input (when manual_actions is True) + self._input_callback: Optional[Callable[[str, Dict], str]] = None + + # Last LLM response (for display) + self._last_llm_response: Optional[Dict[str, Any]] = None + + print(f"[AI] AIManager initialized") + print(f" Session: {self.logger.get_session_path()}") + print(f" Send to LLM: {self.send_to_llm}") + print(f" Manual actions: {self.manual_actions}") + + @property + def llm_client(self) -> GeminiClient: + """Get or create the LLM client.""" + if self._llm_client is None: + api_key = self._get_api_key() + self._llm_client = create_llm_client( + provider=self.config.llm.provider, + model=self.config.llm.model_name, + api_key=api_key, + temperature=self.config.llm.temperature, + max_tokens=self.config.llm.max_tokens + ) + return self._llm_client + + def _get_api_key(self) -> str: + """Get API key from environment.""" + import os + key = os.environ.get(self.config.llm.api_key_env_var, "") + if not key: + raise ValueError( + f"API key not found! Set environment variable: {self.config.llm.api_key_env_var}" + ) + return key + + # === Agent Management === + + def register_agent( + self, + player_name: str, + player_id: int, + player_color: str = "" + ) -> AgentState: + """ + Register a new AI agent. + + Args: + player_name: Display name for the player + player_id: Player ID (0-based) + player_color: Color assigned to player + + Returns: + The created AgentState + """ + if player_name in self.agents: + print(f"[!] Agent '{player_name}' already registered, updating...") + + agent = AgentState( + player_name=player_name, + player_id=player_id, + player_color=player_color + ) + self.agents[player_name] = agent + + print(f"[AI] Registered AI agent: {player_name} (ID: {player_id}, Color: {player_color})") + return agent + + def get_agent(self, player_name: str) -> Optional[AgentState]: + """Get agent state by name.""" + return self.agents.get(player_name) + + def unregister_agent(self, player_name: str) -> None: + """Remove an agent.""" + if player_name in self.agents: + del self.agents[player_name] + print(f"[AI] Unregistered agent: {player_name}") + + # === Core Processing === + + def process_agent_turn( + self, + player_name: str, + game_state: Dict[str, Any], + prompt_message: str, + allowed_actions: List[str] + ) -> Dict[str, Any]: + """ + Process an agent's turn. + + This is the main entry point called by AIUser.get_input(). + + Args: + player_name: Name of the agent + game_state: Current game state + prompt_message: Prompt from GameManager + allowed_actions: List of allowed action types + + Returns: + Dictionary with the agent's decision: + { + "action_type": str, + "parameters": dict, + "thinking": str, + "note_to_self": str, + "say_outloud": str + } + """ + agent = self.get_agent(player_name) + if not agent: + raise ValueError(f"Agent '{player_name}' not registered!") + + # Update current state + self._current_game_state = game_state + self._current_allowed_actions = allowed_actions + + # Build "what happened" from recent events + what_happened = self._build_what_happened(agent) + + # Create prompt + prompt, schema = self._create_prompt( + agent=agent, + game_state=game_state, + what_happened=what_happened, + allowed_actions=allowed_actions, + is_active_turn=True + ) + + # Log the prompt + log_info = self.logger.log_prompt( + player_name=player_name, + prompt=prompt, + schema=schema, + is_active=True, + what_happened=what_happened, + allowed_actions=self._format_allowed_actions(allowed_actions) + ) + + # Mark request sent + agent.mark_request_sent() + + # Send to LLM if enabled + response = None + llm_suggestion = None + + if self.send_to_llm: + try: + self.logger.log_llm_communication(f"Sending prompt #{log_info['number']} for {player_name}", "SEND") + response = self._send_to_llm(prompt, schema, ResponseType.ACTIVE_TURN) + + if response and response.success and response.content: + self.logger.log_llm_communication(f"Received response for {player_name} ({response.total_tokens} tokens)", "RECV") + llm_suggestion = self._parse_response(response, ResponseType.ACTIVE_TURN) + self._last_llm_response = llm_suggestion + + # Log the action suggestion with details + if llm_suggestion: + action = llm_suggestion.get("action_type", "unknown") + params = llm_suggestion.get("parameters", {}) + thinking = llm_suggestion.get("internal_thinking", "")[:100] + self.logger.log_llm_communication(f"LLM suggests: {action} {params}", "RECV") + if thinking: + self.logger.log_llm_communication(f" Thinking: {thinking}...", "RECV") + else: + error_msg = response.error if response else "No response" + self.logger.log_llm_communication(f"LLM error: {error_msg}", "ERROR") + + # Log response + self.logger.log_response( + player_name=player_name, + request_number=log_info["number"], + response=response, + parsed=llm_suggestion + ) + + # LLM suggestion logged to communication log only + + except Exception as e: + self.logger.log_llm_communication(f"Exception: {str(e)}", "ERROR") + llm_suggestion = None + + # Get final action + if self.manual_actions: + # Manual mode - show info and wait for human input + parsed = self._wait_for_manual_input(agent, prompt, log_info["number"], llm_suggestion) + else: + # Auto mode - use LLM response directly + parsed = llm_suggestion + + # Update agent state + agent.mark_request_complete( + success=parsed is not None, + tokens=response.total_tokens if response else 0 + ) + + if parsed: + # Update memory + agent.update_memory(parsed.get("note_to_self")) + + # Clear events since they've been processed + agent.clear_events() + + # Handle chat message if present + if parsed.get("say_outloud"): + self._broadcast_chat(player_name, parsed["say_outloud"]) + + return parsed or {"action_type": "end_turn", "parameters": {}} + + def _display_llm_response( + self, + agent: AgentState, + response: Dict[str, Any], + request_number: int + ): + """Display the LLM response - minimal in main console, details in log file.""" + # All LLM communication goes to LLM Logger Console only + pass + + def _wait_for_manual_input( + self, + agent: AgentState, + prompt: Dict[str, Any], + request_number: int, + llm_suggestion: Optional[Dict[str, Any]] = None + ) -> Dict[str, Any]: + """ + Wait for manual input from terminal. + + In manual mode, we: + 1. Display the prompt info (and LLM suggestion if available) + 2. Wait for human to input the agent's decision + 3. Parse and return the response + """ + # If we have LLM suggestion, show minimal hint + if llm_suggestion: + print("[TIP] LLM suggestion available. Press ENTER to accept, or type your own command") + + # Store suggestion for later use + self._last_llm_response = llm_suggestion + return None + + def parse_manual_action(self, input_str: str) -> Dict[str, Any]: + """ + Parse a manual action input string. + + Supports both full format and shortcuts: + - Full: build_settlement {"node": 14} + - Shortcut: s 14 (settlement at node 14) + - Shortcut: rd 14 15 (road from 14 to 15) + + Args: + input_str: String like "build_settlement {\"node\": 14}" or "s 14" + + Returns: + Parsed action dict + """ + parts = input_str.strip().split() + + if not parts: + return {"action_type": "end_turn", "parameters": {}} + + action_type = parts[0].lower() + parameters = {} + + # Handle shortcuts with simple numeric parameters + shortcut_map = { + "s": ("build_settlement", "node"), + "settlement": ("build_settlement", "node"), + "c": ("build_city", "node"), + "city": ("build_city", "node"), + "r": ("roll_dice", None), + "roll": ("roll_dice", None), + "e": ("end_turn", None), + "end": ("end_turn", None), + "pass": ("end_turn", None), + "dev": ("buy_dev_card", None), + "buy": ("buy_dev_card", None), + } + + # Handle road shortcut: rd 14 15 + if action_type == "rd" and len(parts) >= 3: + try: + return { + "action_type": "build_road", + "parameters": {"from": int(parts[1]), "to": int(parts[2])}, + "internal_thinking": "(Manual input)", + "note_to_self": None, + "say_outloud": None + } + except ValueError: + pass + + # Handle simple shortcuts + if action_type in shortcut_map: + full_action, param_name = shortcut_map[action_type] + action_type = full_action + if param_name and len(parts) > 1: + try: + parameters[param_name] = int(parts[1]) + except ValueError: + parameters[param_name] = parts[1] + + # Handle JSON parameters + elif len(parts) > 1: + # Try to parse as JSON + param_str = " ".join(parts[1:]) + try: + parameters = json.loads(param_str) + except json.JSONDecodeError: + # Try simple key=value format + if "=" in param_str: + for kv in param_str.split(): + if "=" in kv: + k, v = kv.split("=", 1) + try: + parameters[k] = int(v) + except ValueError: + parameters[k] = v + else: + # Just a single value, assume it's "node" for settlements + try: + parameters["node"] = int(parts[1]) + except ValueError: + pass + + return { + "action_type": action_type, + "parameters": parameters, + "internal_thinking": "(Manual input)", + "note_to_self": None, + "say_outloud": None + } + + def _create_prompt( + self, + agent: AgentState, + game_state: Dict[str, Any], + what_happened: str, + allowed_actions: List[str], + is_active_turn: bool + ) -> tuple[Dict[str, Any], Dict[str, Any]]: + """ + Create a prompt for an agent. + + Returns: + Tuple of (prompt_dict, schema_dict) + """ + # Format allowed actions + formatted_actions = self._format_allowed_actions(allowed_actions) + + # Get agent's memory + agent_memory = None + if agent.memory: + agent_memory = {"note_from_last_turn": agent.memory} + + # Create prompt through PromptManager + prompt = self.prompt_manager.create_prompt( + player_num=agent.player_id, + player_name=agent.player_name, + player_color=agent.player_color, + game_state=game_state, + what_happened=what_happened, + available_actions=formatted_actions, + chat_history=self.chat_history[-self.max_chat_history:] if self.chat_history else None, + agent_memory=agent_memory + ) + + # Get appropriate schema + if is_active_turn: + schema = ACTIVE_TURN_RESPONSE_SCHEMA + else: + schema = OBSERVING_RESPONSE_SCHEMA + + return prompt, schema + + def _format_allowed_actions(self, allowed_actions: List[str]) -> List[Dict[str, Any]]: + """Convert action type strings to formatted action dicts.""" + # Map action type names to example parameters + action_templates = { + "BUILD_SETTLEMENT": { + "type": "build_settlement", + "description": "Build a settlement at a node", + "example_parameters": "{\"node\": 14}" + }, + "BUILD_CITY": { + "type": "build_city", + "description": "Upgrade a settlement to a city", + "example_parameters": "{\"node\": 14}" + }, + "BUILD_ROAD": { + "type": "build_road", + "description": "Build a road between two nodes", + "example_parameters": "{\"from\": 14, \"to\": 15}" + }, + "ROLL_DICE": { + "type": "roll_dice", + "description": "Roll the dice", + "example_parameters": "{}" + }, + "END_TURN": { + "type": "end_turn", + "description": "End your turn", + "example_parameters": "{}" + }, + "BUY_DEV_CARD": { + "type": "buy_dev_card", + "description": "Buy a development card", + "example_parameters": "{}" + }, + "USE_DEV_CARD": { + "type": "use_dev_card", + "description": "Play a development card", + "example_parameters": "{\"card_type\": \"knight\"}" + }, + "TRADE_BANK": { + "type": "trade_bank", + "description": "Trade resources with the bank", + "example_parameters": "{\"give\": \"wood\", \"receive\": \"brick\"}" + }, + "TRADE_PROPOSE": { + "type": "trade_propose", + "description": "Propose a trade to other players", + "example_parameters": "{\"offer\": {\"wood\": 1}, \"request\": {\"brick\": 1}}" + }, + "ROBBER_MOVE": { + "type": "robber_move", + "description": "Move the robber to a hex", + "example_parameters": "{\"hex\": 7}" + }, + "STEAL_CARD": { + "type": "steal_card", + "description": "Steal a card from a player", + "example_parameters": "{\"target_player\": \"Red\"}" + }, + "DISCARD_CARDS": { + "type": "discard_cards", + "description": "Discard cards (when 7 is rolled)", + "example_parameters": "{\"cards\": [\"wood\", \"brick\"]}" + }, + "PLACE_STARTING_SETTLEMENT": { + "type": "place_starting_settlement", + "description": "Place your starting settlement", + "example_parameters": "{\"node\": 14}" + }, + "PLACE_STARTING_ROAD": { + "type": "place_starting_road", + "description": "Place your starting road", + "example_parameters": "{\"from\": 14, \"to\": 15}" + }, + "WAIT_FOR_RESPONSE": { + "type": "wait_for_response", + "description": "Do nothing on the board, just wait or communicate. Use this when you want to talk, negotiate, or think without taking a game action.", + "example_parameters": "{}" + } + } + + result = [] + for action_name in allowed_actions: + if action_name in action_templates: + result.append(action_templates[action_name]) + else: + # Unknown action - create basic template + result.append({ + "type": action_name.lower(), + "description": action_name.replace("_", " ").title(), + "example_parameters": {} + }) + + # Always add WAIT_FOR_RESPONSE as an option (for communication) + if "WAIT_FOR_RESPONSE" not in allowed_actions: + result.append(action_templates["WAIT_FOR_RESPONSE"]) + + return result + + def _build_what_happened(self, agent: AgentState) -> str: + """ + Build the 'what happened' message from recent events. + + Args: + agent: The agent to build message for + + Returns: + Human-readable summary of recent events + """ + if not agent.recent_events: + return "Game is starting." + + lines = [] + for event in agent.recent_events: + lines.append(f"• {event['message']}") + + return "\n".join(lines) + + def _send_to_llm( + self, + prompt: Dict[str, Any], + schema: Dict[str, Any], + response_type: ResponseType + ) -> LLMResponse: + """Send prompt to LLM and get response.""" + # Convert prompt to string + prompt_str = json.dumps(prompt, indent=2, ensure_ascii=False) + + # Send to LLM with schema and thinking mode (if enabled) + kwargs = { + "response_schema": schema, + "enable_thinking": self.config.llm.enable_thinking, + } + + if self.config.llm.enable_thinking: + kwargs["thinking_budget"] = self.config.llm.thinking_budget + + response = self.llm_client.generate( + prompt_str, + **kwargs + ) + + return response + + def _parse_response( + self, + response: LLMResponse, + response_type: ResponseType + ) -> Optional[Dict[str, Any]]: + """Parse LLM response into structured data.""" + if not response.success or not response.content: + return None + + result = self.response_parser.parse( + response.content, + response_type + ) + + if result.success and result.data: + # Convert schema format to internal format + data = result.data + parsed = { + "internal_thinking": data.get("internal_thinking", ""), + "note_to_self": data.get("note_to_self"), + "say_outloud": data.get("say_outloud"), + } + + # Extract action (action.type + action.parameters) + action = data.get("action", {}) + if action: + parsed["action_type"] = action.get("type", "end_turn") + # Parameters might be JSON string or dict + params = action.get("parameters", {}) + if isinstance(params, str): + try: + params = json.loads(params) if params else {} + except json.JSONDecodeError: + params = {} + parsed["parameters"] = params if params else {} + else: + parsed["action_type"] = "end_turn" + parsed["parameters"] = {} + + # Log detailed response + self.logger.log_llm_communication( + f"Thinking: {parsed['internal_thinking'][:100]}...", + "RECV" + ) + + return parsed + else: + print(f"[!] Parse error: {result.error_message}") + return None + + # === Event Handling === + + def on_game_event( + self, + event_type: str, + message: str, + affected_players: Optional[List[int]] = None + ) -> None: + """ + Handle a game event notification. + + Called by AIUser.notify_game_event(). + Stores the event for all relevant agents. + + Args: + event_type: Type of event + message: Human-readable description + affected_players: List of affected player IDs + """ + for agent_name, agent in self.agents.items(): + # Add event to all agents (they all see what happens) + agent.add_event(event_type, message) + + def _broadcast_chat(self, from_player: str, message: str) -> None: + """ + Broadcast a chat message from an agent. + + Args: + from_player: Name of player sending message + message: The chat message + """ + # Add to chat history + chat_entry = { + "from": from_player, + "message": message, + "timestamp": time.time() + } + self.chat_history.append(chat_entry) + + # Trim history if needed + if len(self.chat_history) > self.max_chat_history * 2: + self.chat_history = self.chat_history[-self.max_chat_history:] + + # Log the chat + self.logger.log_chat(from_player, message) + + # Display to console + print(f"[CHAT] {from_player}: \"{message}\"") + + # === Utilities === + + def get_session_path(self) -> Path: + """Get the current session directory path.""" + return self.logger.get_session_path() + + def save_session(self) -> None: + """Save the session state.""" + self.logger.save_session_summary( + agents=self.agents, + game_state=self._current_game_state + ) + print(f"[SAVE] Session saved to: {self.logger.get_session_path()}") + + def get_stats(self) -> Dict[str, Any]: + """Get statistics for all agents.""" + return { + name: agent.get_stats() + for name, agent in self.agents.items() + } diff --git a/pycatan/ai/ai_user.py b/pycatan/ai/ai_user.py new file mode 100644 index 0000000000000000000000000000000000000000..b816db8bb216fd50e034f3a5edc64d6e3d4c3a13 --- /dev/null +++ b/pycatan/ai/ai_user.py @@ -0,0 +1,390 @@ +""" +AI User - Wrapper for AI Agents + +This module provides AIUser, which implements the User interface +and delegates all decision-making to the AIManager. + +AIUser is the bridge between GameManager and the AI system: +- GameManager sees AIUser as a regular User +- AIUser delegates to AIManager for actual decisions +- AIManager handles all AI logic (prompts, LLM, parsing) +""" + +from typing import List, Optional, Dict, Any, TYPE_CHECKING +from pycatan.players.user import User +from pycatan.management.actions import Action, ActionType, GameState + +if TYPE_CHECKING: + from pycatan.ai.ai_manager import AIManager + + +class AIUser(User): + """ + AI User implementation that wraps AIManager. + + This class implements the User interface expected by GameManager + and delegates all AI-related work to the AIManager. + + Key responsibilities: + - Translate GameState to dict for AIManager + - Convert AI responses back to Action objects + - Forward game events to AIManager + """ + + def __init__( + self, + name: str, + user_id: int, + ai_manager: 'AIManager', + color: str = "" + ): + """ + Initialize an AI User. + + Args: + name: Display name for this player + user_id: Player ID (0-based) + ai_manager: Reference to the shared AIManager + color: Player color for display + """ + super().__init__(name, user_id) + self.ai_manager = ai_manager + self.color = color + + # Register with AIManager + ai_manager.register_agent(name, user_id, color) + + def get_input( + self, + game_state: GameState, + prompt_message: str, + allowed_actions: Optional[List[str]] = None + ) -> Action: + """ + Get action from AI agent. + + This is called by GameManager when it's this player's turn. + + Args: + game_state: Current game state + prompt_message: Context message from GameManager + allowed_actions: List of allowed action type names + + Returns: + Action object to execute + """ + # Convert GameState to dict for AIManager + state_dict = self._game_state_to_dict(game_state) + + # Process the turn (may send to LLM) + decision = self.ai_manager.process_agent_turn( + player_name=self.name, + game_state=state_dict, + prompt_message=prompt_message, + allowed_actions=allowed_actions or [] + ) + + # If manual actions mode, get input from human + if self.ai_manager.manual_actions: + action = self._get_manual_input(allowed_actions) + return action + else: + # Auto mode - use LLM response directly + return self._decision_to_action(decision) + + def _get_manual_input(self, allowed_actions: Optional[List[str]]) -> Action: + """ + Get manual input from the human operator. + + Shows options and parses the human's input as the AI's action. + If LLM suggestion is available, pressing Enter uses it. + """ + print(f"\n>>> AI Turn for: {self.name}") + if allowed_actions: + formatted = [a.lower().replace("_", " ") for a in allowed_actions] + print(f" Allowed: {' | '.join(formatted)}") + + while True: + try: + user_input = input(f" {self.name} (AI) > ").strip() + + # If empty and we have LLM suggestion, use it + if not user_input: + llm_response = self.ai_manager._last_llm_response + if llm_response: + print(f" [OK] Using LLM suggestion") + return self._decision_to_action(llm_response) + else: + print(f" [!] No input and no LLM suggestion") + continue + + if user_input.lower() == 'help': + self._show_help() + continue + + # Parse the input + decision = self.ai_manager.parse_manual_action(user_input) + action = self._decision_to_action(decision) + + # Validate against allowed actions + if allowed_actions and action.action_type.name not in allowed_actions: + print(f" [X] '{action.action_type.name}' is not allowed right now.") + print(f" Allowed: {allowed_actions}") + continue + + return action + + except ValueError as e: + print(f" [X] Error: {e}") + except KeyboardInterrupt: + print("\n Game interrupted.") + return Action(ActionType.END_TURN, self.user_id) + + def _show_help(self): + """Show help for manual input.""" + print(""" + === Manual AI Input Help === + + Format: [parameters] + + Examples: + roll_dice - Roll the dice + end_turn - End your turn + build_settlement {"node": 14} - Build settlement at node 14 + build_road {"from": 14, "to": 15} - Build road from node 14 to 15 + build_city {"node": 14} - Upgrade settlement to city + buy_dev_card - Buy a development card + trade_bank {"give": "wheat", "receive": "ore"} + robber_move {"hex": 5} - Move robber to hex 5 + steal_card {"target_player": "Bob"} - Steal from Bob + discard_cards {"cards": ["wood", "brick"]} + + Shortcuts: + s 14 -> build_settlement {"node": 14} + rd 14 15 -> build_road {"from": 14, "to": 15} + r -> roll_dice + e -> end_turn + """) + + def _decision_to_action(self, decision: Dict[str, Any]) -> Action: + """ + Convert AI decision dict to Action object. + + Args: + decision: Dict with 'action_type' and 'parameters' + + Returns: + Action object + """ + action_type_str = decision.get("action_type", "end_turn") + parameters = decision.get("parameters", {}) + + # Map common action type strings to ActionType enum + action_map = { + "build_settlement": ActionType.BUILD_SETTLEMENT, + "build_city": ActionType.BUILD_CITY, + "build_road": ActionType.BUILD_ROAD, + "roll_dice": ActionType.ROLL_DICE, + "end_turn": ActionType.END_TURN, + "buy_dev_card": ActionType.BUY_DEV_CARD, + "use_dev_card": ActionType.USE_DEV_CARD, + "trade_bank": ActionType.TRADE_BANK, + "trade_propose": ActionType.TRADE_PROPOSE, + "trade_accept": ActionType.TRADE_ACCEPT, + "trade_reject": ActionType.TRADE_REJECT, + "robber_move": ActionType.ROBBER_MOVE, + "steal_card": ActionType.STEAL_CARD, + "discard_cards": ActionType.DISCARD_CARDS, + "place_starting_settlement": ActionType.PLACE_STARTING_SETTLEMENT, + "place_starting_road": ActionType.PLACE_STARTING_ROAD, + # Shortcuts + "s": ActionType.BUILD_SETTLEMENT, + "settlement": ActionType.BUILD_SETTLEMENT, + "c": ActionType.BUILD_CITY, + "city": ActionType.BUILD_CITY, + "rd": ActionType.BUILD_ROAD, + "road": ActionType.BUILD_ROAD, + "r": ActionType.ROLL_DICE, + "roll": ActionType.ROLL_DICE, + "e": ActionType.END_TURN, + "end": ActionType.END_TURN, + "pass": ActionType.END_TURN, + "dev": ActionType.BUY_DEV_CARD, + "buy": ActionType.BUY_DEV_CARD, + } + + # Handle setup phase shortcuts + if action_type_str.lower() in ["s", "settlement", "build_settlement"]: + # Could be either BUILD_SETTLEMENT or PLACE_STARTING_SETTLEMENT + # This will be determined by GameManager validation + pass + + action_type = action_map.get(action_type_str.lower()) + + if action_type is None: + # Try to find by enum name + try: + action_type = ActionType[action_type_str.upper()] + except KeyError: + print(f" [!] Unknown action type: {action_type_str}, using END_TURN") + action_type = ActionType.END_TURN + + # Convert parameters to expected format + converted_params = self._convert_parameters(action_type, parameters) + + return Action( + action_type=action_type, + player_id=self.user_id, + parameters=converted_params + ) + + def _convert_parameters( + self, + action_type: ActionType, + parameters: Dict[str, Any] + ) -> Dict[str, Any]: + """ + Convert AI parameters to GameManager expected format. + + Args: + action_type: The action type + parameters: Raw parameters from AI + + Returns: + Converted parameters + """ + # Map AI parameter names to GameManager names + if action_type in [ActionType.BUILD_SETTLEMENT, ActionType.BUILD_CITY, + ActionType.PLACE_STARTING_SETTLEMENT]: + # AI uses "node", GameManager uses "point_coords" + if "node" in parameters: + return {"point_coords": parameters["node"]} + elif "point_coords" in parameters: + return parameters + else: + return parameters + + elif action_type in [ActionType.BUILD_ROAD, ActionType.PLACE_STARTING_ROAD]: + # AI uses "from"/"to", GameManager uses "start_coords"/"end_coords" + result = {} + if "from" in parameters: + result["start_coords"] = parameters["from"] + elif "start_coords" in parameters: + result["start_coords"] = parameters["start_coords"] + + if "to" in parameters: + result["end_coords"] = parameters["to"] + elif "end_coords" in parameters: + result["end_coords"] = parameters["end_coords"] + + return result + + elif action_type == ActionType.ROBBER_MOVE: + # AI uses "hex", GameManager uses "tile_coords" + if "hex" in parameters: + return {"tile_coords": parameters["hex"]} + elif "tile_coords" in parameters: + return parameters + else: + return parameters + + elif action_type == ActionType.STEAL_CARD: + # AI uses "target_player" or "victim" + if "target_player" in parameters: + return {"target_player": parameters["target_player"]} + elif "victim" in parameters: + return {"target_player": parameters["victim"]} + else: + return parameters + + elif action_type == ActionType.TRADE_BANK: + # Keep give/receive format + return parameters + + elif action_type == ActionType.USE_DEV_CARD: + # Keep card_type + return parameters + + elif action_type == ActionType.DISCARD_CARDS: + # Keep cards list + return parameters + + return parameters + + def _game_state_to_dict(self, game_state: GameState) -> Dict[str, Any]: + """ + Convert GameState object to dictionary for AIManager. + + Args: + game_state: GameState object + + Returns: + Dictionary representation + """ + # Basic conversion - can be enhanced + return { + "game_id": game_state.game_id, + "turn_number": game_state.turn_number, + "current_player": game_state.current_player, + "game_phase": game_state.game_phase.name if hasattr(game_state.game_phase, 'name') else str(game_state.game_phase), + "turn_phase": game_state.turn_phase.name if hasattr(game_state.turn_phase, 'name') else str(game_state.turn_phase), + "dice_rolled": game_state.dice_rolled, + "allowed_actions": game_state.allowed_actions, + # Board state + "board_state": { + "tiles": game_state.board_state.tiles if hasattr(game_state.board_state, 'tiles') else [], + "robber_position": game_state.board_state.robber_position if hasattr(game_state.board_state, 'robber_position') else None, + } if game_state.board_state else {}, + # Players state + "players_state": [ + { + "player_id": p.player_id, + "name": p.name, + "cards": p.cards, + "dev_cards": p.dev_cards, + "settlements": p.settlements, + "cities": p.cities, + "roads": p.roads, + "victory_points": p.victory_points, + "has_longest_road": p.has_longest_road, + "has_largest_army": p.has_largest_army, + "knights_played": p.knights_played + } + for p in game_state.players_state + ] if game_state.players_state else [] + } + + def notify_game_event( + self, + event_type: str, + message: str, + affected_players: Optional[List[int]] = None + ) -> None: + """ + Notify about a game event. + + Called by GameManager to inform about dice rolls, builds, etc. + + Args: + event_type: Type of event + message: Human-readable description + affected_players: List of affected player IDs + """ + # Forward to AIManager for storage + self.ai_manager.on_game_event(event_type, message, affected_players) + + def notify_action(self, action: Action, success: bool, message: str = "") -> None: + """ + Notify about an action result. + + Args: + action: The action that was performed + success: Whether it succeeded + message: Additional message + """ + # Could be used for learning or logging + if not success and message: + print(f" [!] Action failed: {message}") + + def __str__(self) -> str: + return f"AIUser(name='{self.name}', id={self.user_id}, color='{self.color}')" diff --git a/pycatan/ai/config.py b/pycatan/ai/config.py index 44478c2bd9d8ff9a1a416bad78f160d5b5773bff..19b3c669c6d5798d138d4c364d682c5d3c5e7550 100644 --- a/pycatan/ai/config.py +++ b/pycatan/ai/config.py @@ -47,6 +47,12 @@ class LLMConfig: top_p: float = 0.95 top_k: int = 40 + # Thinking mode (Gemini 2.0+) + # NOTE: Requires google.genai SDK (not google.generativeai) + # Currently disabled - old SDK doesn't support thinking_config + enable_thinking: bool = False # Enable thinking mode + thinking_budget: int = 16000 # Max tokens for thinking (16k default) + # API settings api_key_env_var: str = "GEMINI_API_KEY" # Environment variable name api_base_url: Optional[str] = None # For custom endpoints diff --git a/pycatan/ai/config_example.yaml b/pycatan/ai/config_example.yaml index 4e38a42a90a7c9efd487a6e1c06e23eeba6c8728..2cb6aa4d976ba7a99b3829af41df67777e241446 100644 --- a/pycatan/ai/config_example.yaml +++ b/pycatan/ai/config_example.yaml @@ -21,7 +21,7 @@ llm: provider: "gemini" # Model name - # Gemini: "gemini-2.0-flash-exp", "gemini-1.5-pro", "gemini-1.5-flash" + # Gemini: "gemini-2.0-flash-exp", "gemini-2.0-flash-thinking-exp", "gemini-1.5-pro" # OpenAI: "gpt-4-turbo-preview", "gpt-4", "gpt-3.5-turbo" # Anthropic: "claude-3-opus-20240229", "claude-3-sonnet-20240229" model_name: "gemini-2.0-flash-exp" @@ -32,6 +32,12 @@ llm: top_p: 0.95 # Nucleus sampling threshold top_k: 40 # Top-k sampling (for supported models) + # Thinking mode (Gemini 2.0+ only) + # Enables the model to "think" before responding + # Use with: gemini-2.0-flash-thinking-exp + enable_thinking: false # Enable thinking mode + thinking_budget: 16000 # Max tokens for thinking (8000-32000) + # API settings # The API key is read from environment variables for security # Set GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY diff --git a/pycatan/ai/llm_client.py b/pycatan/ai/llm_client.py index 5dc634a9269f1ec90c1c7e414ba9326bf52777a5..8204e83e9379aaea87f1acfb2f0d12d097d44407 100644 --- a/pycatan/ai/llm_client.py +++ b/pycatan/ai/llm_client.py @@ -29,22 +29,27 @@ class LLMResponse: model: str = "" prompt_tokens: int = 0 completion_tokens: int = 0 + thinking_tokens: int = 0 # For thinking mode total_tokens: int = 0 latency_seconds: float = 0.0 timestamp: str = field(default_factory=lambda: datetime.now().isoformat()) def to_dict(self) -> Dict[str, Any]: """Convert to dictionary for logging.""" + tokens_dict = { + "prompt": self.prompt_tokens, + "completion": self.completion_tokens, + "total": self.total_tokens + } + if self.thinking_tokens > 0: + tokens_dict["thinking"] = self.thinking_tokens + return { "success": self.success, "content": self.content[:200] + "..." if self.content and len(self.content) > 200 else self.content, "error": self.error, "model": self.model, - "tokens": { - "prompt": self.prompt_tokens, - "completion": self.completion_tokens, - "total": self.total_tokens - }, + "tokens": tokens_dict, "latency_seconds": round(self.latency_seconds, 2), "timestamp": self.timestamp } @@ -156,6 +161,8 @@ class GeminiClient(LLMClient): prompt: Prompt text (can be JSON string or plain text) **kwargs: Override default generation parameters - response_schema: JSON schema to enforce structure + - enable_thinking: Enable thinking mode + - thinking_budget: Max tokens for thinking Returns: LLMResponse object with result @@ -170,6 +177,12 @@ class GeminiClient(LLMClient): if self.max_tokens: generation_config["max_output_tokens"] = kwargs.get("max_tokens", self.max_tokens) + # Thinking mode (Gemini 2.0+) + if kwargs.get("enable_thinking", False): + generation_config["thinking_config"] = { + "thinking_budget": kwargs.get("thinking_budget", 16000) + } + # Set response format response_format = kwargs.get("response_format", self.response_format) if response_format == "json": @@ -187,17 +200,6 @@ class GeminiClient(LLMClient): logger.info(f"Sending request to Gemini ({self.model})...") logger.debug(f"Prompt length: {len(prompt)} chars") - # DEBUG: Print what we're sending to Gemini - print("\n" + "="*80) - print("🔍 DEBUG: SENDING TO GEMINI") - print("="*80) - print(f"📤 Prompt (first 500 chars): {prompt[:500]}...") - print(f"� Response Schema Keys: {list(generation_config.get('response_schema', {}).keys())}") - if 'response_schema' in generation_config: - print(f"📋 Required Fields: {generation_config['response_schema'].get('required', [])}") - print(f"📋 Properties: {list(generation_config['response_schema'].get('properties', {}).keys())}") - print("="*80 + "\n") - # Generate response response = self.model_instance.generate_content( prompt, @@ -209,14 +211,36 @@ class GeminiClient(LLMClient): # Extract content content = response.text - # Token counting (approximate - Gemini doesn't always provide exact counts) - prompt_tokens = self._estimate_tokens(prompt) - completion_tokens = self._estimate_tokens(content) - total_tokens = prompt_tokens + completion_tokens + # Token counting + # Try to get actual usage from response, fall back to estimation + thinking_tokens = 0 + try: + if hasattr(response, 'usage_metadata'): + prompt_tokens = response.usage_metadata.prompt_token_count + completion_tokens = response.usage_metadata.candidates_token_count + total_tokens = response.usage_metadata.total_token_count + + # Extract thinking tokens if available (Gemini 2.0 thinking mode) + if hasattr(response.usage_metadata, 'thoughts_token_count'): + thinking_tokens = response.usage_metadata.thoughts_token_count + + logger.debug(f"Token counts from API: prompt={prompt_tokens}, completion={completion_tokens}, thinking={thinking_tokens}, total={total_tokens}") + else: + # Fallback to estimation + prompt_tokens = self._estimate_tokens(prompt) + completion_tokens = self._estimate_tokens(content) + total_tokens = prompt_tokens + completion_tokens + logger.debug(f"Token counts estimated: prompt={prompt_tokens}, completion={completion_tokens}") + except Exception as e: + logger.warning(f"Failed to get token counts: {e}, using estimation") + prompt_tokens = self._estimate_tokens(prompt) + completion_tokens = self._estimate_tokens(content) + total_tokens = prompt_tokens + completion_tokens - # Calculate cost (Gemini 2.5 Flash pricing - approximate) + # Calculate cost (Gemini 2.0 Flash pricing) # Input: $0.00001875 per 1K tokens, Output: $0.000075 per 1K tokens - cost = (prompt_tokens / 1000 * 0.00001875) + (completion_tokens / 1000 * 0.000075) + # Thinking tokens are charged as input tokens + cost = ((prompt_tokens + thinking_tokens) / 1000 * 0.00001875) + (completion_tokens / 1000 * 0.000075) llm_response = LLMResponse( success=True, @@ -225,13 +249,17 @@ class GeminiClient(LLMClient): model=self.model, prompt_tokens=prompt_tokens, completion_tokens=completion_tokens, + thinking_tokens=thinking_tokens, total_tokens=total_tokens, latency_seconds=latency ) self.stats.add_request(llm_response, cost) - logger.info(f"✅ Response received: {completion_tokens} tokens, {latency:.2f}s") + if thinking_tokens > 0: + logger.info(f"✅ Response received: {completion_tokens} tokens (+{thinking_tokens} thinking), {latency:.2f}s") + else: + logger.info(f"✅ Response received: {completion_tokens} tokens, {latency:.2f}s") logger.debug(f"Response preview: {content[:100]}...") return llm_response @@ -269,7 +297,7 @@ class GeminiClient(LLMClient): The Google AI Studio interface supports propertyOrdering, but the Python SDK (google-generativeai) does NOT support it and will error. - Also removes: minLength, maxLength (validation constraints not enforced by Gemini) + Also removes: minLength, maxLength, additionalProperties (not supported) Args: schema: Schema dict or any nested structure @@ -281,7 +309,7 @@ class GeminiClient(LLMClient): return schema # Fields to remove for Python SDK compatibility - unsupported = ['propertyOrdering', 'minLength', 'maxLength'] + unsupported = ['propertyOrdering', 'minLength', 'maxLength', 'additionalProperties'] cleaned = {} for key, value in schema.items(): diff --git a/pycatan/ai/response_parser.py b/pycatan/ai/response_parser.py index 3a891f1c9b5c620c0161e762c40020e94c5e0450..57a3a11703662079adda91caf701d1fbf012e6cf 100644 --- a/pycatan/ai/response_parser.py +++ b/pycatan/ai/response_parser.py @@ -131,10 +131,11 @@ class ResponseParser: # Step 3: Validate structure validation_result = self._validate_structure(data, response_type) if not validation_result[0]: - print(f"\n🔍 DEBUG - Validation failed: {validation_result[1]}") - print(f"📋 Data: {json.dumps(data, indent=2)}") - print(f"📋 Response Type: {response_type}") - print(f"📋 Schema required fields: {get_schema_for_response_type(response_type).get('required')}\n") + # Log validation errors (will appear in LLM Logger Console) + logger.warning(f"Validation failed: {validation_result[1]}") + logger.debug(f"Data: {json.dumps(data, indent=2)}") + logger.debug(f"Response Type: {response_type}") + logger.debug(f"Schema required fields: {get_schema_for_response_type(response_type).get('required')}") if self.enable_fallbacks and not self.strict_mode: # Try to repair structure data = self._try_repair_structure(data, response_type) diff --git a/pycatan/ai/schemas.py b/pycatan/ai/schemas.py index d2c32de23f484aaf319f8aee30ed4915ff70dae1..021652645fd3e7be264f663f8a0b32a7db8c530c 100644 --- a/pycatan/ai/schemas.py +++ b/pycatan/ai/schemas.py @@ -25,7 +25,7 @@ ACTIVE_TURN_RESPONSE_SCHEMA = { "internal_thinking": { "type": "string", "description": "Private strategy. What's your plan and why?", - "minLength": 50 + "minLength": 1000 }, "note_to_self": { "type": "string", @@ -39,18 +39,18 @@ ACTIVE_TURN_RESPONSE_SCHEMA = { }, "action": { "type": "object", - "required": ["type", "parameters"], + "required": ["type"], "properties": { "type": { "type": "string", "description": "The action type (must match one from allowed_actions in constraints)" }, "parameters": { - "type": "object", - "description": "Action-specific parameters. If no parameters are needed, provide an empty object.", - "additionalProperties": True # Allow flexible parameters based on action + "type": "string", + "description": "Action parameters as JSON string. Example: {\"node\": 14} or {} if no parameters needed" } - } + }, + "propertyOrdering": ["type", "parameters"] } }, "propertyOrdering": [ diff --git a/start.bat b/start.bat index 25fab224909bd77261358039ec862be3fbc07ca9..8a1240edbc9d84f912bd740d8adc3806afaea94b 100644 --- a/start.bat +++ b/start.bat @@ -1,44 +1,73 @@ @echo off -REM Start AI Tester, Web Viewer, and Game in parallel +REM ================================================================================ +REM PyCatan AI System - UPDATED VERSION +REM ================================================================================ +REM This script has been updated to use the new AI system. +REM Old files moved to: examples\ai_testing\_deprecated\ +REM ================================================================================ +echo. echo ================================================================================ -echo 🎮 Starting AI Catan System +echo PyCatan AI System echo ================================================================================ echo. -echo Opening THREE windows + TWO browser tabs: -echo 1. AI Tester (monitoring AI responses) -echo 2. AI Viewer (http://localhost:5001) - Shows AI thinking/responses -echo 3. Catan Game (the actual game) -echo + Game Board (http://localhost:5000) - Shows the Catan board +echo Starting components: +echo 1. AI Viewer (http://localhost:5001) - Shows AI prompts and responses +echo 2. Catan Game with AI Agents (manual input mode) echo. echo ================================================================================ echo. -REM Start AI Tester in a new window -start "AI Tester - Monitoring" cmd /k ".venv\Scripts\python.exe examples\ai_testing\test_ai_live.py" +cd /d "%~dp0" -REM Wait a moment for AI tester to initialize -timeout /t 2 /nobreak >nul +REM Check for virtual environment +if exist ".venv\Scripts\python.exe" ( + set PYTHON_CMD=.venv\Scripts\python.exe + echo [OK] Using virtual environment +) else ( + set PYTHON_CMD=python + echo [!] No virtual environment found, using system Python +) -echo ✅ AI Tester started in separate window echo. REM Start Web Viewer in a new window -start "AI Viewer - http://localhost:5001" cmd /k ".venv\Scripts\python.exe examples\ai_testing\web_viewer.py" +echo [1/2] Starting AI Viewer... +start "AI Viewer - http://localhost:5001" cmd /k "%PYTHON_CMD% examples\ai_testing\web_viewer.py" +REM Wait for web viewer to start timeout /t 2 /nobreak >nul -echo ✅ AI Viewer started at http://localhost:5001 +echo [OK] AI Viewer started at http://localhost:5001 echo. -echo 🌐 Opening AI Viewer in browser... -timeout /t 3 /nobreak >nul + +REM Open browser for AI Viewer +echo [BROWSER] Opening AI Viewer... +timeout /t 2 /nobreak >nul start http://localhost:5001 + +echo. +echo [2/2] Starting game... +echo. +echo ================================================================================ +echo MANUAL AI MODE +echo ================================================================================ +echo When it's an AI player's turn: +echo - A prompt is generated and saved +echo - You enter the action the AI should take echo. -echo Starting game in this window... -echo (Game board will open at http://localhost:5000) +echo Commands: r (roll), e (end turn), s 14 (settlement), rd 14 15 (road) +echo Type 'help' for full list +echo ================================================================================ echo. -REM Start the game in this window -.venv\Scripts\python.exe examples\ai_testing\play_with_prompts.py +REM Start the game with the new system +%PYTHON_CMD% examples\ai_testing\play_with_ai.py +echo. +echo ================================================================================ +echo Session Complete! +echo ================================================================================ +echo Session logs: examples\ai_testing\my_games\ +echo. pause