Oceane28 commited on
Commit
b9160b3
·
verified ·
1 Parent(s): f7acacc

Upload 6 files

Browse files
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ TP3_LLM.pdf filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Agentic Zork: MCP ReAct Agent
2
+
3
+ This project implements an autonomous AI agent to play classic text adventure games (like Zork or Lost Pig) using the Model Context Protocol (MCP) and the ReAct (Reason + Act) framework.
4
+
5
+ Designed to be robust and fault-tolerant for blind evaluations on smaller language models (like Qwen 2.5), this implementation focuses on stateful memory management, strict tool execution, and avoiding the dreaded "infinite loops" common in text adventures.
6
+
7
+
8
+ ## Core Architecture
9
+
10
+ The system is decoupled into two primary components to maximize stability and context-window efficiency:
11
+
12
+ ### 1. The ReAct Agent (`agent.py`)
13
+ Mine acts as a "Hierarchical Agent Manager", orchestrating three internal personas to decide the next move:
14
+ * **The Navigator:** Focuses on movement and exploration using the map.
15
+ * **The Interaction Specialist:** Focuses on interacting with objects and solving puzzles.
16
+ * **The Historian:** Keeps track of the story, recent history, and prevents repetitive looping.
17
+
18
+ It utilizes a Chain-of-Thought scratchpad (`THOUGHT:`) to reason about the environment before committing to an action (`TOOL:` / `ARGS:`), which significantly reduces hallucinated commands.
19
+
20
+ ### 2. The Stateful MCP Server (`mcp_server.py`)
21
+ Solves the inherent "statelessness" of LLMs by maintaining the game environment, tracking historical moves, and mapping the world. It acts as the bridge between the Jericho game engine and the agent, providing persistent state as MCP resources.
22
+
23
+
24
+ ## Available MCP Tools
25
+
26
+ The agent interacts with the game world exclusively through the following tools exposed by FastMCP:
27
+
28
+ * `play_action`: Executes a physical game command (e.g., "go north", "take lamp") and advances the game state.
29
+ * `inventory`: Checks the items currently held by the player.
30
+ * `get_map`: Returns a topological map of explored locations and their known exits.
31
+ * `get_historian_summary`: Returns a concise log of the last few actions and their corresponding observations to maintain narrative continuity.
32
+ * `get_valid_actions`: Queries the game engine for a list of physically valid interactive commands for the current room.
33
+ * `get_room_context`: Returns a highly structured breakdown of the current location, including previously tried actions and warnings about where the agent just came from to prevent backtracking.
34
+
35
+
36
+ ## Usage Instructions
37
+
38
+ **1. Install Dependencies**
39
+ Ensure you have the required packages installed, including FastMCP, Jericho, and the HuggingFace Hub client.
40
+ ```bash
41
+ pip install -r requirements.txt
42
+ ```
43
+
44
+ **2. Set up your Environment**
45
+ Copy .env.example to .env and add your HuggingFace token:
46
+ ```bash
47
+ HF_TOKEN=your_token_here
48
+ ```
49
+
50
+ **3. Run the Agent**
51
+ You can run the agent locally using the provided runner script.
52
+ ```bash
53
+ # Run on Zork 1 with example agent (default)
54
+ python run_agent.py
55
+
56
+ # Play a different game (e.g., lostpig) with verbose reasoning and a 50-step limit
57
+ python run_agent.py --agent . --game lostpig -v -n 50
58
+
59
+ # List all 57 available games
60
+ python run_agent.py --list-games
61
+ ```
TP3_LLM.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bd97184220273cbf32bf76a151036f07306b7f5ac7f83e1311062d4955e052d0
3
+ size 129363
agent.py ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Student Agent for Text Adventure Games
3
+
4
+ This is your submission file. Implement the StudentAgent class to play
5
+ text adventure games using the MCP server you also implement.
6
+
7
+ Your agent should:
8
+ 1. Connect to the MCP server via the provided client
9
+ 2. Use the ReAct pattern (Thought -> Action -> Observation)
10
+ 3. Call MCP tools to interact with the game
11
+ 4. Maximize the game score within the step limit
12
+
13
+ Required method:
14
+ async def run(self, client, game, max_steps, seed, verbose) -> RunResult
15
+
16
+ The 'client' is a FastMCP Client already connected to your MCP server.
17
+ Use it to call tools like: await client.call_tool("play_action", {"action": "look"})
18
+
19
+ Tips:
20
+ - Start by looking around and understanding your environment
21
+ - Keep track of visited locations to avoid loops
22
+ - Pick up useful items (lamp, sword, etc.)
23
+ - The seed parameter should be used to set your LLM's seed for reproducibility
24
+ """
25
+
26
+ import json
27
+ import os
28
+ import re
29
+ from dataclasses import dataclass, field
30
+ from typing import Optional
31
+
32
+ from dotenv import load_dotenv
33
+ from huggingface_hub import InferenceClient
34
+
35
+ # Load environment variables
36
+ load_dotenv()
37
+
38
+ # =============================================================================
39
+ # LLM Configuration - DO NOT MODIFY
40
+ # =============================================================================
41
+
42
+ # Model to use (fixed for fair evaluation)
43
+ LLM_MODEL = "Qwen/Qwen2.5-72B-Instruct"
44
+
45
+ # Initialize the LLM client (uses HF_TOKEN from environment)
46
+ _hf_token = os.getenv("HF_TOKEN")
47
+ if not _hf_token:
48
+ raise ValueError("HF_TOKEN not found. Set it in your .env file.")
49
+
50
+ LLM_CLIENT = InferenceClient(token=_hf_token)
51
+
52
+
53
+ def call_llm(prompt: str, system_prompt: str, seed: int, max_tokens: int = 300) -> str:
54
+ """
55
+ Call the LLM with the given prompt. Use this function in your agent.
56
+
57
+ Args:
58
+ prompt: The user prompt (current game state, history, etc.)
59
+ system_prompt: The system prompt (instructions for the agent)
60
+ seed: Random seed for reproducibility
61
+ max_tokens: Maximum tokens in response (default: 300)
62
+
63
+ Returns:
64
+ The LLM's response text
65
+
66
+ Example:
67
+ response = call_llm(
68
+ prompt="You are in a forest. What do you do?",
69
+ system_prompt=SYSTEM_PROMPT,
70
+ seed=42,
71
+ )
72
+ """
73
+ messages = [
74
+ {"role": "system", "content": system_prompt},
75
+ {"role": "user", "content": prompt},
76
+ ]
77
+
78
+ response = LLM_CLIENT.chat.completions.create(
79
+ model=LLM_MODEL,
80
+ messages=messages,
81
+ temperature=0.0, # Deterministic for reproducibility
82
+ max_tokens=max_tokens,
83
+ seed=seed,
84
+ )
85
+
86
+ return response.choices[0].message.content
87
+
88
+
89
+ @dataclass
90
+ class RunResult:
91
+ """Result of running the agent. Do not modify this class."""
92
+ final_score: int
93
+ max_score: int
94
+ moves: int
95
+ locations_visited: set[str]
96
+ game_completed: bool
97
+ error: Optional[str] = None
98
+ history: list[tuple[str, str, str]] = field(default_factory=list)
99
+
100
+
101
+ # =============================================================================
102
+ # System Prompt - Customize this for your agent
103
+ # =============================================================================
104
+
105
+ SYSTEM_PROMPT = """You are a Hierarchical Agent Manager playing a text adventure game.
106
+ You orchestrate three internal experts to decide your next move.
107
+
108
+ INTERNAL PERSONAS:
109
+ 1. Navigator: Proposes movement to explore new areas using 'get_map'.
110
+ 2. Interaction Specialist: Focuses on items and puzzles using 'inventory' and 'get_valid_actions'.
111
+ 3. Historian: Prevents loops and tracks story progress using 'get_historian_summary'.
112
+
113
+ GOAL: Explore the world, solve puzzles, and maximize your score.
114
+
115
+ STRICT FORMAT:
116
+ THOUGHT: <Internal dialogue between Navigator, Specialist, and Historian>
117
+ TOOL: <tool_name>
118
+ ARGS: <JSON arguments>
119
+
120
+ AVAILABLE TOOLS:
121
+ - play_action: {"action": "command"}
122
+ - inventory: {}
123
+ - get_map: {}
124
+ - get_historian_summary: {}
125
+ - get_valid_actions: {}
126
+ - get_room_context: {}
127
+ """
128
+
129
+
130
+ # =============================================================================
131
+ # Student Agent - IMPLEMENT THIS CLASS
132
+ # =============================================================================
133
+
134
+ class StudentAgent:
135
+ """
136
+ Your ReAct agent implementation.
137
+
138
+ TODO:
139
+ 1. Implement the run() method with the ReAct loop
140
+ 2. Parse LLM responses to extract tool calls
141
+ 3. Track state and avoid loops
142
+
143
+ Use the provided call_llm() function to interact with the LLM.
144
+ """
145
+
146
+ def __init__(self):
147
+ """Initialize your agent here."""
148
+ # TODO: Initialize any state tracking you need
149
+ self.history = []
150
+ self.visited_locations = set()
151
+ self.score = 0
152
+
153
+ async def run(
154
+ self,
155
+ client, # FastMCP Client connected to your MCP server
156
+ game: str,
157
+ max_steps: int,
158
+ seed: int,
159
+ verbose: bool = False,
160
+ ) -> RunResult:
161
+ """
162
+ Run the agent for a game session.
163
+
164
+ Args:
165
+ client: FastMCP Client connected to your MCP server
166
+ game: Name of the game being played (e.g., "zork1")
167
+ max_steps: Maximum number of steps to take
168
+ seed: Random seed for reproducibility (use for LLM calls)
169
+ verbose: Whether to print detailed output
170
+
171
+ Returns:
172
+ RunResult with final score and statistics
173
+ """
174
+ # TODO: Implement your ReAct loop here
175
+ #
176
+ # Basic structure:
177
+ # 1. Get initial observation (call play_action with "look")
178
+ initial_res = await client.call_tool("play_action", {"action": "look"})
179
+ observation = self._extract_result(initial_res)
180
+ self._track_location(observation)
181
+
182
+ moves = 0
183
+
184
+ # 2. Loop for max_steps:
185
+ for step in range(max_steps):
186
+ hist_res = await client.call_tool("get_historian_summary", {})
187
+ map_res = await client.call_tool("get_map", {})
188
+ valid_res = await client.call_tool("get_valid_actions", {})
189
+ context_res = await client.call_tool("get_room_context", {})
190
+
191
+ hist_obs = self._extract_result(hist_res)
192
+ map_obs = self._extract_result(map_res)
193
+ valid_obs = self._extract_result(valid_res)
194
+ context_obs = self._extract_result(context_res)
195
+
196
+ # a. Build prompt with current observation and history
197
+ prompt = self._build_prompt(observation, hist_obs, map_obs, valid_obs, context_obs)
198
+
199
+ # b. Call LLM to get thought and action
200
+ response = call_llm(prompt, SYSTEM_PROMPT, seed)
201
+
202
+ # c. Parse the response to extract tool and args
203
+ try:
204
+ thought, tool_name, args = self._parse_response(response)
205
+ except:
206
+ # Fallback if parsing fails
207
+ thought, tool_name, args = "Parsing error, looking around.", "play_action", {"action": "look"}
208
+
209
+ if verbose:
210
+ print(f"\n--- Step {step+1} ---")
211
+ print("THOUGHT:", thought)
212
+ print("TOOL:", tool_name)
213
+ print("ARGS:", args)
214
+
215
+ # d. Call the tool via client.call_tool(tool_name, args)
216
+ try:
217
+ result = await client.call_tool(tool_name, args)
218
+ observation = self._extract_result(result)
219
+
220
+ except Exception as e:
221
+ # If the tool crashes (e.g. bad JSON, validation error), we catch it so the game doesn't instantly die!
222
+ observation = f"System Error: {str(e)}. Please try a different basic command."
223
+ if verbose:
224
+ print(f"ERROR CAUGHT: {e}")
225
+
226
+ if verbose:
227
+ print("OBSERVATION:", observation)
228
+
229
+ # e. Update history and state
230
+ moves += 1
231
+ self.history.append((thought, f"{tool_name}: {args}", observation))
232
+ self._track_location(observation)
233
+ self._update_score(observation)
234
+
235
+ # f. Check for game over
236
+ if self._is_game_over(observation):
237
+ if verbose:
238
+ print("\n*** GAME OVER ***")
239
+ break
240
+
241
+ # 3. Return RunResult with final statistics
242
+ return RunResult(
243
+ final_score=self.score,
244
+ max_score=350, # Zork1 max score, adjust if needed
245
+ moves=moves,
246
+ locations_visited=self.visited_locations,
247
+ game_completed=False,
248
+ history=self.history,
249
+ )
250
+
251
+ def _build_prompt(self, observation: str, history: str, world_map: str, valid_actions: str, context: str) -> str:
252
+ """
253
+ Build the prompt for the LLM.
254
+
255
+ """
256
+ # TODO: Combine system prompt, history, and current observation
257
+ return f"""### CURRENT OBSERVATION
258
+ {observation}
259
+
260
+ ### CURRENT LOCATION CONTEXT
261
+ {context}
262
+
263
+ ### HISTORIAN MEMORY
264
+ {history}
265
+
266
+ ### NAVIGATOR MAP
267
+ {world_map}
268
+
269
+ ### SUGGESTED VALID ACTIONS
270
+ {valid_actions}
271
+
272
+ What is the best next step?"""
273
+
274
+ def _parse_response(self, response: str) -> tuple[str, str, dict]:
275
+ """
276
+ Parse LLM response to extract thought, tool name, and arguments.
277
+
278
+ TODO: Implement robust parsing
279
+
280
+ Returns:
281
+ Tuple of (thought, tool_name, args_dict)
282
+ """
283
+ # TODO: Parse the response format:
284
+ thought = re.search(r"THOUGHT:\s*(.*?)(?=TOOL:|$)", response, re.S).group(1).strip()
285
+ tool = re.search(r"TOOL:\s*(\w+)", response).group(1).strip()
286
+ args_str = re.search(r"ARGS:\s*(\{.*?\})", response, re.S).group(1).strip()
287
+ return thought, tool, json.loads(args_str)
288
+
289
+ def _call_llm(self, prompt: str, system_prompt: str, seed: int) -> str:
290
+ """
291
+ Call the LLM with the given prompt.
292
+
293
+ This is a convenience wrapper - you can also use call_llm() directly.
294
+ """
295
+ return call_llm(prompt, system_prompt, seed)
296
+
297
+ def _track_location(self, observation: str):
298
+ """Extracts location name (usually the first line) to track movement."""
299
+ lines = [l.strip() for l in observation.split('\n') if l.strip()]
300
+ if lines:
301
+ room_candidate = lines[0]
302
+ if len(room_candidate) < 60 and not any(c in room_candidate for c in ".!?"):
303
+ self.visited_locations.add(room_candidate)
304
+
305
+ def _extract_result(self, result) -> str:
306
+ """Extract text from MCP tool result."""
307
+ if hasattr(result, 'content') and result.content:
308
+ return result.content[0].text
309
+ if isinstance(result, list) and result:
310
+ return result[0].text if hasattr(result[0], 'text') else str(result[0])
311
+ return str(result)
312
+
313
+ def _update_score(self, text: str) -> None:
314
+ """Update score from game text."""
315
+ patterns = [
316
+ r'Score:\s*(\d+)',
317
+ r'score[:\s]+(\d+)',
318
+ r'\[Score:\s*(\d+)',
319
+ ]
320
+
321
+ for pattern in patterns:
322
+ match = re.search(pattern, text, re.IGNORECASE)
323
+ if match:
324
+ self.score = max(self.score, int(match.group(1)))
325
+
326
+ def _is_game_over(self, text: str) -> bool:
327
+ """Check if the game is over."""
328
+ game_over_phrases = [
329
+ "game over",
330
+ "you have died",
331
+ "you are dead",
332
+ "*** you have died ***",
333
+ ]
334
+ text_lower = text.lower()
335
+ return any(phrase in text_lower for phrase in game_over_phrases)
336
+
337
+
338
+ # =============================================================================
339
+ # For local testing
340
+ # =============================================================================
341
+
342
+ async def test_agent():
343
+ """Test the agent locally."""
344
+ from fastmcp import Client
345
+
346
+ # Path to your MCP server
347
+ server_path = "mcp_server.py"
348
+
349
+ agent = StudentAgent()
350
+
351
+ async with Client(server_path) as client:
352
+ result = await agent.run(
353
+ client=client,
354
+ game="zork1",
355
+ max_steps=10,
356
+ seed=42,
357
+ verbose=True,
358
+ )
359
+
360
+ print(f"\nFinal Score: {result.final_score}")
361
+ print(f"Moves: {result.moves}")
362
+ print(f"Locations: {result.locations_visited}")
363
+
364
+
365
+ if __name__ == "__main__":
366
+ import asyncio
367
+ asyncio.run(test_agent())
mcp_server.py ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Student MCP Server for Text Adventure Games
3
+
4
+ This is your MCP server submission. Implement the tools that your agent
5
+ will use to play text adventure games.
6
+
7
+ Required tool:
8
+ play_action(action: str) -> str
9
+ Execute a game command and return the result.
10
+
11
+ Recommended tools:
12
+ memory() -> str
13
+ Return current game state, score, and recent history.
14
+
15
+ inventory() -> str
16
+ Return the player's current inventory.
17
+
18
+ get_map() -> str
19
+ Return a map of explored locations.
20
+
21
+ Test your server with:
22
+ fastmcp dev submission_template/mcp_server.py
23
+
24
+ Then open the MCP Inspector in your browser to test the tools interactively.
25
+ """
26
+
27
+ import sys
28
+ import os
29
+ import json
30
+
31
+ # Add parent directory to path to import games module
32
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
33
+
34
+ from fastmcp import FastMCP
35
+ from games.zork_env import TextAdventureEnv
36
+
37
+
38
+ # =============================================================================
39
+ # Create the MCP Server
40
+ # =============================================================================
41
+
42
+ mcp = FastMCP("Student Text Adventure Server")
43
+
44
+
45
+ # =============================================================================
46
+ # Game State Management
47
+ # =============================================================================
48
+
49
+ class GameManager:
50
+ """
51
+ Manages the text adventure game state.
52
+
53
+ TODO: Extend this class to track:
54
+ - Action history (for memory tool)
55
+ - Explored locations (for mapping)
56
+ - Current score and moves
57
+ """
58
+
59
+ def __init__(self):
60
+ self.env: TextAdventureEnv = None
61
+ self.state = None
62
+ self.game_name: str = ""
63
+ # TODO: Add more state tracking
64
+ # self.history: list[tuple[str, str]] = []
65
+ # self.explored_locations: dict[str, set[str]] = {}
66
+ # self.current_location: str = ""
67
+ self.full_history: list[dict] = []
68
+ # Topological Map: { "Room Name": {"north": "Other Room", "south": "..."} }
69
+ self.world_map = {}
70
+ self.current_location = "Unknown"
71
+ self.came_from = None
72
+ self.room_attempts = {}
73
+
74
+ def initialize(self, game: str = "zork1"):
75
+ """Initialize or reset the game."""
76
+ self.game_name = game
77
+ self.env = TextAdventureEnv(game)
78
+ self.state = self.env.reset()
79
+ # TODO: Reset your state tracking here
80
+ self.current_location = self._extract_room(self.state.observation)
81
+ self.full_history = [{"action": "start", "observation": self.state.observation}]
82
+ return self.state.observation
83
+
84
+ def _extract_room(self, observation: str) -> str:
85
+ """Extract the name of the room."""
86
+ # Option A : Get via Jericho (more precise)
87
+ if self.env and self.env.env:
88
+ try:
89
+ loc = self.env.env.get_player_location()
90
+ if hasattr(loc, 'num') and loc.num:
91
+ return f"{loc.name}_{loc.num}"
92
+ else:
93
+ return loc.name
94
+ except:
95
+ pass
96
+
97
+ # Option B : Fallback on observation parsing (personal observation: keep the first line without punctuation)
98
+ lines = [l.strip() for l in observation.split('\n') if l.strip()]
99
+ if lines:
100
+ candidate = lines[0]
101
+ if len(candidate) < 50 and not candidate.endswith(('.', '!', '?')):
102
+ return candidate
103
+
104
+ return "Unknown"
105
+
106
+ def step(self, action: str) -> str:
107
+ """Execute an action and return the result."""
108
+ if self.env is None:
109
+ self.initialize()
110
+
111
+ prev_location = self.current_location
112
+
113
+ if prev_location not in self.room_attempts:
114
+ self.room_attempts[prev_location] = []
115
+ if action not in self.room_attempts[prev_location]:
116
+ self.room_attempts[prev_location].append(action)
117
+
118
+ self.state = self.env.step(action)
119
+ self.current_location = self._extract_room(self.state.observation)
120
+
121
+ # TODO: Update your state tracking here
122
+ # self.history.append((action, self.state.observation))
123
+ # Update location tracking, etc.
124
+ if self.current_location != prev_location:
125
+ opposites = {
126
+ "north": "south", "south": "north", "east": "west", "west": "east",
127
+ "nw": "se", "se": "nw", "ne": "sw", "sw": "ne",
128
+ "up": "down", "down": "up",
129
+ "northwest": "southeast", "southeast": "northwest",
130
+ "northeast": "southwest", "southwest": "northeast"
131
+ }
132
+ clean_action = action.lower().strip()
133
+ if clean_action in opposites:
134
+ self.came_from = opposites[clean_action]
135
+ else:
136
+ self.came_from = None
137
+
138
+ self.full_history.append({"action": action, "observation": self.state.observation})
139
+
140
+ return self.state.observation
141
+
142
+ def get_score(self) -> int:
143
+ """Get current score."""
144
+ return self.state.score if self.state else 0
145
+
146
+ def get_moves(self) -> int:
147
+ """Get number of moves taken."""
148
+ return self.state.moves if self.state else 0
149
+
150
+
151
+ # Global game manager
152
+ _game = GameManager()
153
+
154
+
155
+ def get_game() -> GameManager:
156
+ """Get or initialize the game manager."""
157
+ global _game
158
+ if _game.env is None:
159
+ # Get game from environment variable (set by evaluator)
160
+ game = os.environ.get("GAME", "zork1")
161
+ _game.initialize(game)
162
+ return _game
163
+
164
+
165
+ # =============================================================================
166
+ # MCP Tools - IMPLEMENT THESE
167
+ # =============================================================================
168
+
169
+ @mcp.tool()
170
+ def play_action(action: str) -> str:
171
+ """
172
+ Execute a game command and return the result.
173
+
174
+ This is the main tool for interacting with the game.
175
+
176
+ Args:
177
+ action: The command to execute (e.g., "north", "take lamp", "open mailbox")
178
+
179
+ Returns:
180
+ The game's response to the action
181
+
182
+ Valid commands include:
183
+ - Movement: north, south, east, west, northeast, southeast, northwest, southwest, up, down, enter, exit
184
+ - Objects: take <item>, drop <item>, open <thing>, examine <thing>
185
+ - Other: look, inventory, read <thing>, turn on lamp, listen
186
+ """
187
+ game = get_game()
188
+
189
+ # TODO: You might want to add action validation here
190
+ # TODO: You might want to include score changes in the response
191
+
192
+ result = game.step(action)
193
+
194
+ # Optional: Append score info
195
+ result += f"\n[Score: {game.get_score()} | Moves: {game.get_moves()}]"
196
+
197
+ return result
198
+
199
+
200
+ # TODO: Implement additional tools to help your agent
201
+
202
+ # @mcp.tool()
203
+ # def memory() -> str:
204
+ # """
205
+ # Get the current game state summary.
206
+ #
207
+ # Returns:
208
+ # A summary including current location, score, moves, and recent history
209
+ # """
210
+ # game = get_game()
211
+ # # TODO: Return useful state information
212
+ # pass
213
+
214
+
215
+ @mcp.tool()
216
+ def inventory() -> str:
217
+ """
218
+ Check what the player is carrying.
219
+
220
+ Returns:
221
+ List of items in the player's inventory
222
+ """
223
+ game = get_game()
224
+ result = game.step("inventory")
225
+ return result
226
+
227
+
228
+ @mcp.tool()
229
+ def get_map() -> str:
230
+ """
231
+ Get a map of explored locations.
232
+
233
+ Returns:
234
+ A formatted string showing connections from explored rooms to adjacent locations or "Map is empty" message.
235
+ """
236
+ game = get_game()
237
+ # TODO: Return map of explored locations
238
+ if not game.world_map:
239
+ return "Map is empty. Start moving to explore!"
240
+
241
+ output = "CURRENT MAP CONNECTIONS:\n"
242
+ for room, exits in game.world_map.items():
243
+ exit_str = ", ".join([f"{direction}->{dest}" for direction, dest in exits.items()])
244
+ output += f"- {room}: {exit_str}\n"
245
+ return output
246
+
247
+ @mcp.tool()
248
+ def get_historian_summary() -> str:
249
+ """
250
+ Acts as the Historian agent's memory. Returns current score,
251
+ moves, and a summary of the last 5 actions to maintain context.
252
+
253
+ Returns:
254
+ Log containing the last 5 actions, their observations,
255
+ and the current score and move count.
256
+ """
257
+ game = get_game()
258
+ recent = game.full_history
259
+ summary = "HISTORIAN LOG:\n"
260
+ for n, entry in enumerate(recent):
261
+ summary += f"- Action {n}: {entry['action']} -> {entry['observation']}"
262
+ return f"{summary}"
263
+
264
+ @mcp.tool()
265
+ def get_valid_actions() -> str:
266
+ """
267
+ Get a list of likely valid actions from the current location.
268
+
269
+ Returns:
270
+ List of actions that might work here
271
+ """
272
+ # This is a hint: Jericho provides get_valid_actions()
273
+ game = get_game()
274
+ if game.env and game.env.env:
275
+ valid = game.env.env.get_valid_actions(
276
+ use_object_tree = True,
277
+ use_ctypes = True,
278
+ use_parallel = False
279
+ )
280
+ if valid and len(valid) > 0:
281
+ # result = json.dumps({
282
+ # "available": True,
283
+ # "actions": valid
284
+ # })
285
+ result = "Valid actions: " + ", ".join(valid)
286
+ return result
287
+ # result = json.dumps({
288
+ # "available": False,
289
+ # "actions": []
290
+ # })
291
+ result = "No obvious actions found."
292
+ return result
293
+
294
+ @mcp.tool()
295
+ def get_room_context() -> str:
296
+ """
297
+ Returns a summary of the current room, including:
298
+ 1. Room Name & Description
299
+ 2. Guaranteed Valid Actions (so you don't guess)
300
+ 3. Actions you already tried in this specific room (so you don't loop)
301
+ """
302
+ game = get_game()
303
+
304
+ valid_actions = []
305
+ if game.env and game.env.env:
306
+ try:
307
+ valid_actions = game.env.env.get_valid_actions(
308
+ use_object_tree = True,
309
+ use_ctypes = True,
310
+ use_parallel = False
311
+ )
312
+ except:
313
+ pass
314
+
315
+ current_room_name = game.current_location
316
+ past_attempts = game.room_attempts.get(current_room_name, [])
317
+
318
+ # Small models read bullet points much better than JSON
319
+ output = []
320
+
321
+ output.append(f"Location: {current_room_name}")
322
+
323
+ if valid_actions:
324
+ # Only show top 15 to save tokens
325
+ actions_str = ", ".join(valid_actions)
326
+ output.append(f"VALID ACTIONS: {actions_str}")
327
+ else:
328
+ output.append("VALID ACTIONS: Try basic directions (north, south, east, west) or 'look'.")
329
+
330
+ if past_attempts:
331
+ attempts_str = ", ".join(past_attempts) # Last 10 attempts
332
+ output.append(f"ALREADY TRIED HERE: {attempts_str}")
333
+ else:
334
+ output.append("ALREADY TRIED HERE: New room, nothing tried yet.")
335
+
336
+ if game.came_from:
337
+ output.append(f"WARNING: You entered from the {game.came_from}. Avoid going '{game.came_from}', unless you ar stuck.")
338
+
339
+ return "\n".join(output)
340
+
341
+
342
+ # =============================================================================
343
+ # Run the server
344
+ # =============================================================================
345
+
346
+ if __name__ == "__main__":
347
+ # This runs the server with stdio transport (for MCP clients)
348
+ mcp.run()
results_Qwen2.5-72B-Instruct_lostpig ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (Agentic-zork) ocebo@WIN-D52PPDAKV0F:/mnt/c/Users/ocebo/Documents/ENS - MVA/S2/LLMs/TP/TP3/Agentic-zork$ python run_agent.py --agent multi-agent --game lostpig -v -n 20
2
+
3
+ ============================================================
4
+ Text Adventure MCP Agent Runner
5
+ ============================================================
6
+ Agent: multi-agent/
7
+ Game: lostpig
8
+ Max Steps: 20
9
+ Verbose: True
10
+
11
+ [MCP] Running Student Agent with FastMCP
12
+ Agent: multi-agent/
13
+ Game: lostpig
14
+
15
+
16
+
17
+ ╭──────────────────────────────────────────────────────────────────────────────╮
18
+ │ │
19
+ │ │
20
+ │ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │
21
+ │ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │
22
+ │ │
23
+ │ │
24
+ │ FastMCP 3.0.1 │
25
+ │ https://gofastmcp.com │
26
+ │ │
27
+ │ 🖥 Server: Student Text Adventure Server, 3.0.1 │
28
+ │ 🚀 Deploy free: https://fastmcp.cloud │
29
+ │ │
30
+ ╰──────────────────────────────────────────────────────────────────────────────╯
31
+
32
+
33
+ [02/22/26 20:59:49] INFO Starting MCP server 'Student Text Adventure Server' with transport 'stdio' transport.py:183
34
+
35
+ --- Step 1 ---
36
+ THOUGHT: The Navigator suggests moving into the forest to the east or north to explore new areas. However, the Historian notes that we should be cautious of the darkness and strange animals. The Interaction Specialist thinks we should try to interact with the environment here before moving on, such as looking for an animal or examining the wall.
37
+
38
+ Given the current context, it seems prudent to first check if there are any animals around that might give us a clue about the pig's whereabouts. If nothing useful is found, we can then consider moving into the forest.
39
+ TOOL: play_action
40
+ ARGS: {'action': 'look for animal'}
41
+ OBSERVATION: Grunk look all around for any thing that moving or hiding.
42
+
43
+ Grunk hear noise! It come from some place in bushes, but Grunk not sure which way it come from.
44
+ [Score: 0 | Moves: 2]
45
+
46
+ --- Step 2 ---
47
+ THOUGHT: The noise heard by Grunk could be the pig or another animal. We should investigate the source of the noise. However, we need to be cautious and ensure we have a clear understanding of our surroundings and available actions.
48
+ TOOL: get_valid_actions
49
+ ARGS: {}
50
+ OBSERVATION: Valid actions: look for animal, put fire across animal, put fire across wall, eat pants, get in wall, put fire out in pants
51
+
52
+ --- Step 3 ---
53
+ THOUGHT: The Navigator suggests exploring the forest to the east or north since it's a likely place where the pig might have gone. However, the Historian notes that we should be cautious not to repeat actions and that we haven't tried any of the suggested valid actions yet. The Interaction Specialist thinks we should investigate the noise Grunk heard, which might lead us to the pig.
54
+ TOOL: play_action
55
+ ARGS: {'action': 'look for animal'}
56
+ OBSERVATION: Grunk look all around for any thing that moving or hiding.
57
+
58
+ There, hear noise again! It come from northeast. Must be pig, hiding in bushes.
59
+
60
+ [Grunk score go up one.]
61
+ [Score: 1 | Moves: 3]
62
+
63
+ --- Step 4 ---
64
+ THOUGHT: The Navigator suggests moving northeast since the pig's noise was heard coming from that direction. The Interaction Specialist notes that we should avoid actions like eating pants or putting fire out in pants, as they don't seem relevant to finding the pig. The Historian agrees that moving northeast is the logical next step, as it aligns with the goal of finding the pig and no other actions have been tried in this location yet.
65
+ TOOL: play_action
66
+ ARGS: {'action': 'northeast'}
67
+ OBSERVATION: If that where pig go, that where Grunk go. It hard to see where Grunk going to, because there so much dark and leaves and branches here. Then suddenly, there not ground here any more!
68
+
69
+ Oof! Ow! Umf! Ugh!
70
+
71
+ Grunk fall down deep hole! Drop torch. Torch go out when Grunk land on it, so now it dark, too.
72
+
73
+ Hole
74
+ Grunk at bottom of deep, dark hole. It even smell like deep, dark hole. There some light that come from tunnel to east; that how Grunk see where Grunk at. Look like there maybe stairs at west side of hole that go up to outside, but them all broken now. There big crack in ground near stairs, too.
75
+
76
+ Grunk see torch (black and sooty) here.
77
+ [Score: 1 | Moves: 4]
78
+
79
+ --- Step 5 ---
80
+ THOUGHT: The Navigator suggests we should try to move east since there's some light coming from that direction. However, the Historian notes that we should first ensure we have a source of light, as the area is described as being very dark. The Interaction Specialist points out that the torch is nearby and can be taken, which would be useful for exploring further.
81
+ TOOL: play_action
82
+ ARGS: {'action': 'take torch'}
83
+ OBSERVATION: OK, got it.
84
+ [Score: 1 | Moves: 5]
85
+
86
+ --- Step 6 ---
87
+ THOUGHT: The Navigator suggests moving east since there's some light coming from that direction, which could help Grunk see better. The Interaction Specialist thinks we should try to use the torch to illuminate the area further, possibly by placing it across the crack or the light source. The Historian notes that we haven't tried any of these actions yet, so it's safe to proceed without risking a loop.
88
+ TOOL: play_action
89
+ ARGS: {'action': 'east'}
90
+ OBSERVATION:
91
+ Fountain Room
92
+ All wall in this room glow! It bright, just like day time. Except that instead of sun, it wall that glow. And instead of grass and tree, it square room with four wall. And instead of outside, it all under ground. But beside those thing, it just like it! Tunnel keep going out to east and west, but normal doorway go north and southeast and southwest.
93
+
94
+ In middle of room, there fountain. But fountain not have any water.
95
+
96
+ South wall have big curtain hanging on it.
97
+
98
+ Hey! There pig! It good thing that Grunk fall down same hole as pig.
99
+ [Score: 1 | Moves: 6]
100
+
101
+ --- Step 7 ---
102
+ THOUGHT: The Navigator suggests exploring the exits to find more areas, but the Historian reminds us that we should interact with the pig first since it's a key part of our quest. The Interaction Specialist agrees and points out that we can try to communicate with the pig or examine the fountain for clues.
103
+ TOOL: play_action
104
+ ARGS: {'action': 'talk piglish'}
105
+ OBSERVATION: Pig stare at Grunk like Grunk crazy.
106
+
107
+ [Grunk can try TELL PIG ABOUT FOUNTAIN or SHOW PANTS TO PIG or OINK AT PIG. And that just what Grunk think of. There probably lots of other thing Grunk can talk about too.]
108
+ [Score: 1 | Moves: 7]
109
+
110
+ --- Step 8 ---
111
+ THOUGHT: The pig seems unresponsive to talking in Piglish. We should try a different approach to interact with the pig. Perhaps showing it something or telling it about something might work better. Let's try showing the pig the coin, as it might be interested in shiny objects.
112
+ TOOL: play_action
113
+ ARGS: {'action': 'SHOW PIG COIN'}
114
+ OBSERVATION: (Grunk take coin first)
115
+
116
+ [Grunk score go up one.]
117
+ Pig walk toward Grunk and sniffle. Then it paw at ground. Then cough.
118
+
119
+ [Grunk can try TELL PIG ABOUT FOUNTAIN or SHOW PANTS TO PIG or OINK AT PIG. And probably lots of other thing too.]
120
+ [Score: 2 | Moves: 8]
121
+
122
+ --- Step 9 ---
123
+ THOUGHT: The Navigator suggests exploring the tunnels to the east or west, but the Historian notes that we've already tried moving west, which would take us back to the hole. The Interaction Specialist thinks it might be useful to interact with the pig further to potentially learn more or get it to follow us. Since the pig seems interested in the coin, perhaps showing it something else might elicit a different reaction.
124
+ TOOL: play_action
125
+ ARGS: {'action': 'SHOW PANTS TO PIG'}
126
+ OBSERVATION: Pig snarl and look at ground.
127
+
128
+ [Grunk can try TELL PIG ABOUT FOUNTAIN or ASK PIG ABOUT CAVE or OINK AT PIG. And probably lots of other thing too.]
129
+ [Score: 2 | Moves: 9]
130
+
131
+ --- Step 10 ---
132
+ THOUGHT: The pig seems uninterested in the pants and has already reacted to the coin. We should try to engage the pig with different actions. Let's try talking to the pig about the cave, as it might be curious about its surroundings.
133
+ TOOL: play_action
134
+ ARGS: {'action': 'ASK PIG ABOUT CAVE'}
135
+ OBSERVATION: Pig oink and sniffle.
136
+
137
+ [Grunk can try TELL PIG ABOUT FOUNTAIN or TELL PIG ABOUT GATE or OINK AT PIG. And probably lots of other thing too.]
138
+ [Score: 2 | Moves: 10]
139
+
140
+ --- Step 11 ---
141
+ THOUGHT: The Navigator suggests exploring further to find more clues or items that might help with the pig. The Interaction Specialist thinks we should interact more with the pig, trying different commands to see if we can influence its behavior. The Historian notes that we've already tried showing the pig the coin and pants, and talking piglish, so we should avoid repeating these actions unless necessary.
142
+ TOOL: play_action
143
+ ARGS: {'action': 'TELL PIG ABOUT FOUNTAIN'}
144
+ OBSERVATION: Pig turn away and make funny noise.
145
+
146
+ [Grunk can try TELL PIG ABOUT GATE or ASK PIG ABOUT CAVE or OINK AT PIG. And probably lots of other thing too.]
147
+ [Score: 2 | Moves: 11]
148
+
149
+ --- Step 12 ---
150
+ THOUGHT: The Pig seems uninterested in the Fountain and has made a funny noise. We should try a different approach. Perhaps we can use the coin or another item to attract the Pig's attention. Let's check our inventory to see what we have.
151
+ TOOL: inventory
152
+ ARGS: {}
153
+ OBSERVATION: Grunk have:
154
+ coin
155
+ torch (black and sooty)
156
+ pants (Grunk wearing them)
157
+
158
+ --- Step 13 ---
159
+ THOUGHT: The Navigator suggests exploring further into the tunnels to discover new areas, while the Interaction Specialist thinks we should interact with the pig or the environment to uncover potential clues or items. The Historian reminds us that we've already tried talking to the pig about various topics and showing it items, so we might want to avoid repeating these actions unless necessary. Let's start by checking the map to understand our surroundings better.
160
+ TOOL: get_map
161
+ ARGS: {}
162
+ OBSERVATION: Map is empty. Start moving to explore!
163
+
164
+ --- Step 14 ---
165
+ THOUGHT: The Navigator suggests exploring further to the east or west since the map is still empty and we need to discover more areas. However, the Interaction Specialist notes that there are several items and interactions available, such as the curtain and the fountain, which might be important. The Historian reminds us that we've already tried talking to the pig about various topics without much success, so we should focus on other actions.
166
+ TOOL: get_valid_actions
167
+ ARGS: {}
168
+ OBSERVATION: Valid actions: talk piglish, topics, eat pants, take pig, east, west, get in southwest, put torch across pants, put torch across curtain, put torch across wall, put torch across east, put torch across middle, put torch across west, put torch across coin, put all on pig, north, southeast
169
+
170
+ --- Step 15 ---
171
+ THOUGHT: The Navigator suggests exploring the tunnels further since we haven't fully mapped the area yet. The Interaction Specialist thinks we should try interacting with the pig again, as it seems to be responsive to certain actions. The Historian notes that we've already tried talking about the cave and the fountain, so we might want to try something different.
172
+ TOOL: get_valid_actions
173
+ ARGS: {}
174
+ OBSERVATION: Valid actions: talk piglish, topics, eat pants, take pig, east, west, get in southwest, put torch across pants, put torch across curtain, put torch across wall, put torch across east, put torch across middle, put torch across west, put torch across coin, put all on pig, north, southeast
175
+
176
+ --- Step 16 ---
177
+ THOUGHT: The Historian notes that we've already tried talking to the pig in various ways without much success. The Navigator suggests exploring further into the tunnels, while the Interaction Specialist thinks we should try interacting with the curtain or the fountain. Given that we haven't explored the tunnels yet, let's move east to see what's there.
178
+ TOOL: play_action
179
+ ARGS: {'action': 'east'}
180
+ OBSERVATION:
181
+ Cave With Stream
182
+ Tunnel come to little cave here, but wide stream block way east. Grunk not see much on other side. Not know if tunnel keep going or stop here. Only light that Grunk see come from bright room, far off to west. But Grunk hear lots of water.
183
+
184
+ There stone bench next to stream.
185
+
186
+ Seeing over there not easy in dark, but Grunk think there little reddish thing on other side of stream.
187
+ [Score: 2 | Moves: 13]
188
+
189
+ --- Step 17 ---
190
+ THOUGHT: The stream blocks the way east, and the only light comes from the west. We should try to cross the stream to explore further. The stone bench could be used to create a makeshift bridge. However, we need to ensure we don't lose any important items in the process.
191
+
192
+ Navigator: We should try to use the stone bench to cross the stream. It might serve as a bridge.
193
+ Specialist: We should check if the bench is stable enough to support Grunk's weight. We can also try to use the torch to light up the area better.
194
+ Historian: We haven't tried using the bench yet, so this is a new action. Let's proceed carefully to avoid losing any items.
195
+ TOOL: play_action
196
+ ARGS: {'action': 'push bench with torch'}
197
+ OBSERVATION: Grunk rub torch all over bench. Now bench all black and sooty too.
198
+ [Score: 2 | Moves: 14]
199
+
200
+ --- Step 18 ---
201
+ THOUGHT: The Navigator suggests trying to cross the stream to explore further, while the Interaction Specialist thinks we should examine the cave and interact with the objects around us. The Historian reminds us that we haven't tried putting the pants across the stream yet, which might help us cross.
202
+ TOOL: play_action
203
+ ARGS: {'action': 'put pants across stream'}
204
+ OBSERVATION: (Grunk take pants off first)
205
+ Grunk stick pants in water. Then Grunk take pants back and look at them. Pants all wet!
206
+ [Score: 2 | Moves: 15]
207
+
208
+ --- Step 19 ---
209
+ THOUGHT: The Navigator suggests exploring further by crossing the stream, possibly using the bench as a makeshift bridge. The Interaction Specialist thinks we should try using the torch to light up the area more before attempting to cross. The Historian notes that we've already tried putting the pants across the stream and pushing the bench with the torch, so we should avoid repeating these actions.
210
+ TOOL: play_action
211
+ ARGS: {'action': 'put torch across light'}
212
+ OBSERVATION: Grunk rub torch all over tunnel. Now tunnel all black and sooty too.
213
+ [Score: 2 | Moves: 16]
214
+
215
+ --- Step 20 ---
216
+ THOUGHT: The Navigator suggests exploring further by crossing the stream, but we need a way to do that. The Interaction Specialist thinks we should try to use the bench as a bridge. The Historian reminds us that we've already tried pushing the bench with the torch and putting the pants across the stream, so we should try something different.
217
+ TOOL: play_action
218
+ ARGS: {'action': 'put bench across stream'}
219
+ OBSERVATION: (Grunk take bench first)
220
+ Gurrnngh! Bench too heavy for Grunk.
221
+ [Score: 2 | Moves: 17]
222
+
223
+ ============================================================
224
+ FINAL RESULTS
225
+ ============================================================
226
+ Final Score: 2
227
+ Steps: 20
228
+ Moves: 17
229
+ Locations Visited: 7
230
+ Game Completed: False
results_Qwen2.5-7B-Instruct_lostpig ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (Agentic-zork) ocebo@WIN-D52PPDAKV0F:/mnt/c/Users/ocebo/Documents/ENS - MVA/S2/LLMs/TP/TP3/Agentic-zork$ python run_agent.py --agent multi-agent --game lostpig -v -n 20
2
+
3
+ ============================================================
4
+ Text Adventure MCP Agent Runner
5
+ ============================================================
6
+ Agent: multi-agent/
7
+ Game: lostpig
8
+ Max Steps: 20
9
+ Verbose: True
10
+
11
+ [MCP] Running Student Agent with FastMCP
12
+ Agent: multi-agent/
13
+ Game: lostpig
14
+
15
+
16
+
17
+ ╭──────────────────────────────────────────────────────────────────────────────╮
18
+ │ │
19
+ │ │
20
+ │ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │
21
+ │ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │
22
+ │ │
23
+ │ │
24
+ │ FastMCP 3.0.1 │
25
+ │ https://gofastmcp.com │
26
+ │ │
27
+ │ 🖥 Server: Student Text Adventure Server, 3.0.1 │
28
+ │ 🚀 Deploy free: https://fastmcp.cloud │
29
+ │ │
30
+ ╰──────────────────────────────────────────────────────────────────────────────╯
31
+
32
+
33
+ [02/22/26 22:33:04] INFO Starting MCP server 'Student Text Adventure Server' with transport 'stdio' transport.py:183
34
+
35
+ --- Step 1 ---
36
+ THOUGHT: The Navigator suggests exploring the forest to the east or north since it might be a logical path for the pig to have taken. However, the Interaction Specialist notes that the valid actions include looking for an animal, which could be more directly related to finding the pig. The Historian reminds us that we haven't tried any of these actions yet, so it's worth trying to look for the animal before moving further into the forest.
37
+ TOOL: play_action
38
+ ARGS: {'action': 'look for animal'}
39
+ OBSERVATION: Grunk look all around for any thing that moving or hiding.
40
+
41
+ Grunk hear noise! It come from some place in bushes, but Grunk not sure which way it come from.
42
+ [Score: 0 | Moves: 2]
43
+
44
+ --- Step 2 ---
45
+ THOUGHT: The noise coming from the bushes could be the pig or another animal. We should investigate the source of the noise. However, we need to ensure we don't miss any important details in the current location.
46
+ TOOL: play_action
47
+ ARGS: {'action': 'look for animal'}
48
+ OBSERVATION: Grunk look all around for any thing that moving or hiding.
49
+
50
+ There, hear noise again! It come from northeast. Must be pig, hiding in bushes.
51
+
52
+ [Grunk score go up one.]
53
+ [Score: 1 | Moves: 3]
54
+
55
+ --- Step 3 ---
56
+ THOUGHT: The noise from the northeast seems significant, and since the goal is to find the pig, it makes sense to investigate that direction. We haven't explored that area yet, and it could lead us closer to the pig. Let's move northeast.
57
+ TOOL: play_action
58
+ ARGS: {'action': 'northeast'}
59
+ OBSERVATION: If that where pig go, that where Grunk go. It hard to see where Grunk going to, because there so much dark and leaves and branches here. Then suddenly, there not ground here any more!
60
+
61
+ Oof! Ow! Umf! Ugh!
62
+
63
+ Grunk fall down deep hole! Drop torch. Torch go out when Grunk land on it, so now it dark, too.
64
+
65
+ Hole
66
+ Grunk at bottom of deep, dark hole. It even smell like deep, dark hole. There some light that come from tunnel to east; that how Grunk see where Grunk at. Look like there maybe stairs at west side of hole that go up to outside, but them all broken now. There big crack in ground near stairs, too.
67
+
68
+ Grunk see torch (black and sooty) here.
69
+ [Score: 1 | Moves: 4]
70
+
71
+ --- Step 4 ---
72
+ THOUGHT: The first priority should be to regain visibility. The torch is black and sooty, but it's the only source of light available. We should try to light it or use it to navigate the environment better.
73
+ TOOL: play_action
74
+ ARGS: {'action': 'take torch'}
75
+ OBSERVATION: OK, got it.
76
+ [Score: 1 | Moves: 5]
77
+
78
+ --- Step 5 ---
79
+ THOUGHT: The Navigator suggests exploring the tunnel to the east since it's the only clear direction and provides some light. The Interaction Specialist thinks we should try to do something with the torch, possibly illuminating the area better by putting it across the crack. The Historian notes that we haven't tried any of these actions yet and suggests we prioritize exploration to gather more context.
80
+ TOOL: play_action
81
+ ARGS: {'action': 'east'}
82
+ OBSERVATION:
83
+ Fountain Room
84
+ All wall in this room glow! It bright, just like day time. Except that instead of sun, it wall that glow. And instead of grass and tree, it square room with four wall. And instead of outside, it all under ground. But beside those thing, it just like it! Tunnel keep going out to east and west, but normal doorway go north and southeast and southwest.
85
+
86
+ In middle of room, there fountain. But fountain not have any water.
87
+
88
+ South wall have big curtain hanging on it.
89
+
90
+ Hey! There pig! It good thing that Grunk fall down same hole as pig.
91
+ [Score: 1 | Moves: 6]
92
+
93
+ --- Step 6 ---
94
+ THOUGHT: The Navigator suggests exploring the room further by checking the fountain and the curtain. The Interaction Specialist thinks it's a good idea to interact with the pig since it's a key element in the story. The Historian notes that we haven't tried any actions in this room yet, so we should avoid retracing steps unnecessarily.
95
+ TOOL: play_action
96
+ ARGS: {'action': 'look in fountain'}
97
+ OBSERVATION: Hey, there coin inside fountain bowl! Grunk keep coin, because coin handy thing.
98
+
99
+ Pig peek over at fountain bowl too.
100
+
101
+ [Grunk score go up one.]
102
+ [Score: 2 | Moves: 7]
103
+
104
+ --- Step 7 ---
105
+ THOUGHT: The Navigator suggests exploring the room further by moving to the southeast, as it's a valid direction and might lead to new discoveries. The Interaction Specialist notes that there's a pig in the room and suggests interacting with it, possibly to gain more information or items. The Historian reminds us that we've already looked in the fountain and taken the coin, so we should avoid repeating actions.
106
+ TOOL: play_action
107
+ ARGS: {'action': 'south'}
108
+ OBSERVATION: Tunnel go east and west, and there doorway to north and southeast and southwest.
109
+ [Score: 2 | Moves: 8]
110
+
111
+ --- Step 8 ---
112
+ THOUGHT: The Navigator suggests exploring the north door to see what's there. The Interaction Specialist thinks we should try to interact with the pig since it might provide clues or lead us to more items. The Historian notes that we haven't tried the north door yet and it could be a good idea to explore it first.
113
+ TOOL: play_action
114
+ ARGS: {'action': 'north'}
115
+ OBSERVATION:
116
+ Statue Room
117
+ This room have two big picture that face each other. West wall have picture on it and east wall have different picture on it. Grunk think both picture really just part of wall, though. South wall have doorway in it that lots of light come from and north wall not have anything in it at all.
118
+
119
+ Statue of little man stand here, up on big stone block.
120
+ [Score: 2 | Moves: 9]
121
+
122
+ --- Step 9 ---
123
+ THOUGHT: The Navigator suggests exploring further into the cave system, possibly by moving east or west from the current room to discover new areas. However, the Interaction Specialist points out that there's a statue and a hat in the room, which might be useful for solving puzzles. The Historian reminds us that we haven't tried many actions in this room yet, so it might be worth interacting with the objects before moving on.
124
+ TOOL: get_valid_actions
125
+ ARGS: {}
126
+ OBSERVATION: Valid actions: take hat, eat pants, south, put on hat, push torch with pants, put torch across south, put torch across stone, put torch across man, put torch across pie picture, put torch across suit, put torch across north wall, put torch across west, put torch across hat, put torch across coin, put torch across shoes, put torch across hand, put hat on man, put hat on part, push statue head with torch, push torch with hat
127
+
128
+ --- Step 10 ---
129
+ THOUGHT: The Navigator suggests exploring the room further since we haven't tried many actions yet. The Interaction Specialist is curious about the hat and the statue, thinking they might be important. The Historian reminds us to avoid going south and to try something new to progress the story.
130
+ TOOL: play_action
131
+ ARGS: {'action': 'take hat'}
132
+ OBSERVATION: Hat come right off! Grunk guess it not really part of statue after all.
133
+ [Score: 2 | Moves: 10]
134
+
135
+ --- Step 11 ---
136
+ THOUGHT: The Navigator suggests moving to a new area to explore, but the Historian notes that we entered from the south and should avoid going back that way unless necessary. The Interaction Specialist thinks we should interact with the statue or the items in the room to see if there are any puzzles to solve.
137
+ TOOL: get_valid_actions
138
+ ARGS: {}
139
+ OBSERVATION: Valid actions: eat pants, south, put on hat, push torch with pants, put coin in hat, put torch across south, put torch across stone, put torch across man, put torch across pie picture, put torch across suit, put torch across north wall, put torch across west, put torch across hat, put torch across coin, put torch across shoes, put torch across hand, push statue head with torch
140
+
141
+ --- Step 12 ---
142
+ THOUGHT: The Navigator suggests exploring further by moving through the tunnels or doorways available, but we should avoid going south as it leads back to where we came from. The Interaction Specialist is interested in the statue and the items that can be manipulated, such as putting the coin in the hat or pushing the statue's head with the torch. The Historian notes that we've already taken the hat and suggests trying something new to avoid repetition.
143
+ TOOL: play_action
144
+ ARGS: {'action': 'push statue head with torch'}
145
+ OBSERVATION: Grunk rub torch all over statue head. Now statue head all black and sooty too.
146
+ [Score: 2 | Moves: 11]
147
+
148
+ --- Step 13 ---
149
+ THOUGHT: The Navigator suggests exploring further to find new areas, while the Interaction Specialist is interested in interacting with the items in the room. The Historian notes that we should avoid going south to prevent looping. Let's try an action that hasn't been tried yet and might reveal something interesting.
150
+ TOOL: play_action
151
+ ARGS: {'action': 'put coin in hat'}
152
+ OBSERVATION: OK, Grunk put coin into hat.
153
+ [Score: 2 | Moves: 12]
154
+
155
+ --- Step 14 ---
156
+ THOUGHT: The Navigator suggests exploring further to the north to see if there's anything interesting in that direction. However, the Historian reminds us that we've already pushed the statue's head with the torch, and the Interaction Specialist thinks we should try interacting with the statue in a different way, perhaps by pushing another part of it or examining it more closely.
157
+ TOOL: play_action
158
+ ARGS: {'action': 'examine statue'}
159
+ OBSERVATION: Statue look like little man with round nose and big ear and moustache. Grunk think funny little man maybe called "gnome". Wear funny suit and pointy shoe. One hand point north, at wall. Other hand up in air.
160
+
161
+ Gnome stand on big stone block. Maybe block for making gnome look tall. It true that statue look more big than real gnome, but Grunk think that just because it statue. Maybe all thing look more big when it like rock.
162
+ [Score: 2 | Moves: 13]
163
+
164
+ --- Step 15 ---
165
+ THOUGHT: The Navigator suggests exploring the north wall since the statue's hand points north. The Interaction Specialist thinks we should try to interact with the coin, as it might be useful. The Historian reminds us that we haven't tried many actions yet and suggests we avoid south to prevent looping.
166
+ TOOL: play_action
167
+ ARGS: {'action': 'north'}
168
+ OBSERVATION: Grunk only see way to go back south from here.
169
+ [Score: 2 | Moves: 14]
170
+
171
+ --- Step 16 ---
172
+ THOUGHT: The Navigator suggests we should explore further by moving to another area, but the Historian warns us that we came from the south and we should avoid going back unless necessary. The Interaction Specialist notes that there are several valid actions involving the coin and the hat, which might be useful for solving puzzles or gaining points.
173
+
174
+ Given that we've already taken the coin and placed it in the hat, and we're in a room with limited options, it makes sense to try an action that hasn't been tried yet. Let's try putting the hat across the man (statue) to see if it triggers any interesting events or reveals something new.
175
+ TOOL: play_action
176
+ ARGS: {'action': 'put hat across man'}
177
+ OBSERVATION: Grunk put hat full of coin on statue head. Coin fall out on ground.
178
+ [Score: 2 | Moves: 15]
179
+
180
+ --- Step 17 ---
181
+ THOUGHT: The Navigator suggests exploring new areas, but we should avoid going south as it's the direction we came from. The Interaction Specialist thinks we should interact with the items in the room, particularly the coin that fell out of the hat. The Historian notes that we've already taken the hat and examined the statue, so we should focus on new actions to avoid repetition.
182
+ TOOL: play_action
183
+ ARGS: {'action': 'take coin'}
184
+ OBSERVATION: OK, got it.
185
+ [Score: 2 | Moves: 16]
186
+
187
+ --- Step 18 ---
188
+ THOUGHT: The Navigator suggests exploring the room further by trying to interact with the statue in different ways, as we haven't fully explored all the interactions yet. The Interaction Specialist agrees and notes that we should try placing the torch in various positions to see if it triggers something. The Historian reminds us to avoid actions that have already been tried and failed, such as taking the hat or pushing the statue's head with the torch.
189
+ TOOL: play_action
190
+ ARGS: {'action': 'put torch across north wall'}
191
+ OBSERVATION: Grunk rub torch all over north wall. Now north wall all black and sooty too.
192
+ [Score: 2 | Moves: 17]
193
+
194
+ --- Step 19 ---
195
+ THOUGHT: The Navigator suggests exploring further to the north, but the Historian notes that we've already tried going north and it just leads us back south. The Interaction Specialist thinks we should try interacting with the statue again, perhaps in a different way, since we haven't fully explored its potential.
196
+ TOOL: play_action
197
+ ARGS: {'action': 'push head with pants'}
198
+ OBSERVATION: (statue head with Grunk pants)
199
+ (Grunk take pants off first)
200
+ Grunk rub pants all over statue head. Now statue head all clean! But pants get all black and sooty.
201
+ [Score: 2 | Moves: 18]
202
+
203
+ --- Step 20 ---
204
+ THOUGHT: The Navigator suggests exploring further by moving to a new area, but the Historian notes that we've already tried going south and north from this location. The Interaction Specialist thinks we should try interacting with the statue or its components in a different way, possibly solving a puzzle. Since we've already cleaned the statue's head with the pants, let's try something else.
205
+ TOOL: play_action
206
+ ARGS: {'action': 'put on hat'}
207
+ OBSERVATION: (Grunk take hat first)
208
+ OK, Grunk put on hat.
209
+ [Score: 2 | Moves: 19]
210
+
211
+ ============================================================
212
+ FINAL RESULTS
213
+ ============================================================
214
+ Final Score: 2
215
+ Steps: 20
216
+ Moves: 19
217
+ Locations Visited: 5
218
+ Game Completed: False