Javier-Jimenez99 commited on
Commit
18f4e71
·
1 Parent(s): 7208e3d

Actualizar README.md con secciones de demostración y arquitectura, y mejorar la interfaz de usuario en app.py para manejar bloques HTML. También se corrigen comentarios y traducciones en obr.py y test.py.

Browse files
Files changed (4) hide show
  1. README.md +181 -1
  2. app.py +31 -8
  3. tools/obr.py +3 -3
  4. tools/test.py +34 -37
README.md CHANGED
@@ -12,4 +12,184 @@ tags:
12
  - mcp-server-track
13
  ---
14
 
15
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  - mcp-server-track
13
  ---
14
 
15
+ # 🧙‍♂️ LLM Game Master MCP Server 🐉
16
+
17
+ ## 🎥 Video Demo
18
+
19
+ ```html
20
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/SlbW-kjekBg?si=r6x8GeVnKLipriZL" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
21
+ ```
22
+
23
+ Video Demo: [https://www.youtube.com/watch?v=SlbW-kjekBg&ab_channel=AlejandroGarcíaAmador](https://www.youtube.com/watch?v=SlbW-kjekBg&ab_channel=AlejandroGarcíaAmador)
24
+
25
+ ## 🧩 Complete Architecture Overview
26
+ ![Architecture Overview](https://huggingface.co/spaces/Agents-MCP-Hackathon/LLM-GameMaster-Agent/resolve/main/media/architecture.png)
27
+
28
+ ## 🔗 Useful Links:
29
+ - [Owlbear Rodeo Chat Interface](https://github.com/Agamador/OwlBear-llm-chat)
30
+ - [MCP server](https://huggingface.co/spaces/Agents-MCP-Hackathon/LLM-GameMaster-MPC-Server)
31
+ - [Video Demo](https://www.youtube.com/watch?v=SlbW-kjekBg&ab_channel=AlejandroGarcíaAmador)
32
+
33
+ ## 🌟 Introduction
34
+
35
+ The **OwlBear Rodeo MCP Server** is a revolutionary Model Context Protocol (MCP) server implementation that bridges the gap between AI agents and tabletop gaming experiences. This sophisticated system transforms the popular OwlBear Rodeo virtual tabletop platform into a fully programmable environment, enabling AI Game Masters to create, manipulate, and orchestrate dynamic D&D sessions with unprecedented precision and creativity.
36
+
37
+ Built using Gradio's cutting-edge MCP server capabilities, this application showcases the power of combining modern AI infrastructure with traditional gaming platforms. The server exposes a comprehensive suite of tools that allow AI agents to interact with virtual tabletops in real-time, creating immersive gaming experiences that adapt dynamically to player actions and narrative requirements.
38
+
39
+ Unlike static gaming interfaces, this MCP server provides AI agents with the ability to programmatically control every aspect of the virtual tabletop experience, from token placement and movement to map management and atmospheric effects like fog of war and lighting systems.
40
+
41
+ ## 🎯 Core Functionality
42
+
43
+ ### 🗺️ Dynamic Map Management
44
+ The server provides powerful map manipulation capabilities that allow AI agents to create diverse gaming environments on demand. Through the integrated map system, agents can instantly deploy various pre-configured environments including mystical forests with winding paths, quaint villages with detailed buildings, isolated cabin settings, and epic battle arenas designed for climactic encounters.
45
+
46
+ The map insertion system works seamlessly with OwlBear Rodeo's rendering engine, ensuring that each environment is properly scaled and optimized for tactical gameplay. Maps can be swapped dynamically during sessions, allowing for seamless transitions between different scenes and locations as the narrative unfolds.
47
+
48
+ ### 🎭 Intelligent Token System
49
+ The token creation and management system represents one of the most sophisticated aspects of the MCP server. AI agents can spawn a diverse array of characters and objects, from heroic knights and mystical archers to fearsome dragons and cunning goblins. Each token type corresponds to carefully selected visual assets that enhance the immersive experience.
50
+
51
+ The system supports dynamic token properties including customizable sizes, precise positioning using grid-based coordinates, and intelligent naming conventions that help track multiple entities throughout complex encounters. Tokens can be moved programmatically, allowing AI Game Masters to orchestrate tactical movements, dramatic reveals, and coordinated battle sequences.
52
+
53
+ ### 🌫️ Advanced Fog of War
54
+ The fog of war implementation provides AI agents with sophisticated tools for controlling information flow and creating suspenseful gaming moments. The system can instantly fill entire maps with fog, creating mysterious environments where only illuminated areas remain visible to players.
55
+
56
+ The clear fog functionality allows for dramatic reveals, while the selective fog management enables AI Game Masters to control exactly what players can see at any given moment. This creates opportunities for strategic gameplay and narrative tension that rivals traditional tabletop experiences.
57
+
58
+ ### 💡 Dynamic Lighting System
59
+ The lighting system adds another layer of tactical depth and atmospheric immersion to gaming sessions. AI agents can attach light sources to any token, creating realistic illumination effects that interact with the fog of war system. Torches, magical auras, and character-based light sources can be programmatically managed to enhance both gameplay mechanics and visual storytelling.
60
+
61
+ Light sources move automatically with their attached tokens, ensuring that the lighting environment remains consistent as characters navigate through the virtual space. This feature is particularly powerful for creating tension in dungeon exploration scenarios or highlighting important story elements.
62
+
63
+ ### 🔧 Utility Tools Integration
64
+ Beyond the OwlBear Rodeo specific features, the MCP server includes a comprehensive suite of utility tools that enhance AI agent capabilities. These include mathematical functions for dice rolling simulations, coin flip mechanics for random decision making, prime factorization for complex calculations, and text analysis tools for processing player input.
65
+
66
+ These utility functions demonstrate the extensibility of the MCP architecture, showing how specialized gaming tools can be combined with general-purpose utilities to create a comprehensive AI assistant platform.
67
+
68
+ ## 🛠️ MCP Tools Reference
69
+
70
+ This section provides the complete technical reference for all tools available through the Model Context Protocol server. Each tool is documented with its exact function name, required parameters, and expected behavior to facilitate seamless integration with MCP clients.
71
+
72
+ ### 🎲 General Utility Tools
73
+
74
+ The server includes essential utility tools that provide mathematical and randomization capabilities commonly needed in gaming scenarios. These tools demonstrate the extensibility of the MCP architecture and can be used independently or in conjunction with the OwlBear Rodeo specific functionality.
75
+
76
+ **letter_counter**
77
+ - Parameters: `word` (string), `letter` (string)
78
+ - Description: Counts occurrences of a specific letter within any text string
79
+ - Use case: Text analysis and word games integration
80
+
81
+ **prime_factors**
82
+ - Parameters: `n` (integer, must be > 1)
83
+ - Description: Computes the complete prime factorization of any positive integer
84
+ - Use case: Mathematical puzzles and complex calculations
85
+
86
+ **roll_dice**
87
+ - Parameters: `faces` (integer), `rolls` (integer)
88
+ - Description: Simulates dice rolling with customizable faces and number of rolls
89
+ - Use case: Random number generation for game mechanics
90
+
91
+ **coin_flip**
92
+ - Parameters: `flips` (integer)
93
+ - Description: Simulates multiple coin flips returning "Heads" or "Tails" results
94
+ - Use case: Binary random decisions and probability demonstrations
95
+
96
+ ### 🗺️ OwlBear Rodeo Map Management
97
+
98
+ The map management system provides comprehensive control over virtual tabletop environments, enabling dynamic scene transitions and environmental storytelling through programmatic map manipulation.
99
+
100
+ **insert_map**
101
+ - Parameters: `tab_id` (string), `map_type` (string)
102
+ - Description: Inserts pre-configured map environments into the gaming session
103
+ - Available map types: `FOREST`, `VILLAGE`, `LONELY_CABIN`, `BATTLE_ARENA`, `CABIN`
104
+ - Use case: Setting scenes and creating immersive environments
105
+
106
+ **clean_map**
107
+ - Parameters: `tab_id` (string)
108
+ - Description: Removes all tokens, shapes, and objects from the current map
109
+ - Use case: Resetting the playing field for new encounters
110
+
111
+ ### 🎭 Token and Character Management
112
+
113
+ The token system provides sophisticated character and object management capabilities, allowing AI Game Masters to populate virtual spaces with interactive entities that enhance storytelling and tactical gameplay.
114
+
115
+ **create_token**
116
+ - Parameters: `name` (string), `type` (string), `x` (integer), `y` (integer), `size` (integer), `tab_id` (string)
117
+ - Description: Creates character or item tokens with specified visual assets
118
+ - Available token types: `BOOK`, `CHEST`, `SWORD`, `TORCH`, `ARCHER`, `HUMAN`, `WOMAN`, `CHILD`, `ORC`, `KNIGHT`, `DRAGON`, `GOBLIN`, `GOLEM`
119
+ - Use case: Populating scenes with characters, items, and interactive objects
120
+
121
+ **move_item**
122
+ - Parameters: `tab_id` (string), `item_id` (string), `x` (integer), `y` (integer)
123
+ - Description: Moves any existing token or shape to new grid coordinates
124
+ - Use case: Orchestrating movement during combat or narrative sequences
125
+
126
+ **delete_item**
127
+ - Parameters: `tab_id` (string), `item_id` (string)
128
+ - Description: Permanently removes a specific token or shape from the map
129
+ - Use case: Cleaning up defeated enemies or consumed items
130
+
131
+ ### 🎨 Shape and Visual Elements
132
+
133
+ The shape creation system enables the addition of geometric elements that can serve as terrain features, area markers, or visual indicators to enhance tactical understanding and environmental storytelling.
134
+
135
+ **create_shape**
136
+ - Parameters: `width` (integer), `height` (integer), `x` (integer), `y` (integer), `shape_type` (string), `fill_color` (hex string), `stroke_color` (hex string), `tab_id` (string)
137
+ - Description: Creates geometric shapes with customizable appearance and positioning
138
+ - Available shape types: `RECTANGLE`, `CIRCLE`, `TRIANGLE`, `HEXAGON`
139
+ - Use case: Creating terrain features, spell areas, or visual markers
140
+
141
+ ### 🌫️ Fog of War and Visibility Control
142
+
143
+ The fog of war system provides sophisticated visibility management tools that enable AI Game Masters to control information flow and create suspenseful moments through strategic revelation of map areas.
144
+
145
+ **fill_fog**
146
+ - Parameters: `tab_id` (string)
147
+ - Description: Covers the entire map with fog of war, hiding all areas from player view
148
+ - Use case: Creating mystery and controlling information revelation
149
+
150
+ **clear_fog**
151
+ - Parameters: `tab_id` (string)
152
+ - Description: Removes all fog of war from the map, revealing the complete environment
153
+ - Use case: Dramatic reveals and full area illumination
154
+
155
+ ### 💡 Lighting and Atmosphere
156
+
157
+ The lighting system adds tactical depth and atmospheric immersion by providing programmable light sources that interact dynamically with the fog of war system to create realistic illumination effects.
158
+
159
+ **add_token_light**
160
+ - Parameters: `tab_id` (string), `item_id` (string), `light_radius` (integer)
161
+ - Description: Attaches a light source to any token with specified illumination radius
162
+ - Use case: Creating torch effects, magical auras, or character-based lighting
163
+
164
+ ### 🎥 Camera and Viewport Control
165
+
166
+ The viewport management system enables cinematic control over player perspective, allowing AI Game Masters to direct attention and create dramatic focus during key narrative moments.
167
+
168
+ **animate_token_viewport**
169
+ - Parameters: `tab_id` (string), `item_id` (string)
170
+ - Description: Smoothly animates the camera to focus on a specific token
171
+ - Use case: Directing player attention during important events
172
+
173
+ ### 📊 State Management
174
+
175
+ The state management tool provides essential functionality for monitoring and retrieving the current status of all elements within the virtual tabletop environment.
176
+
177
+ **game_state**
178
+ - Parameters: `tab_id` (string)
179
+ - Description: Returns complete current state including all tokens, shapes, and map information
180
+ - Use case: Monitoring session status and making informed decisions
181
+
182
+ ### 🔧 Testing and Demonstration
183
+
184
+ **test_function**
185
+ - Parameters: `tab_id` (string)
186
+ - Description: Executes a comprehensive demonstration of all OwlBear Rodeo functionality
187
+ - Use case: System validation and feature showcase
188
+
189
+ All tools require a `tab_id` parameter that identifies the specific OwlBear Rodeo session. Coordinates are specified in grid cells, with the origin (0,0) typically located at the top-left corner of the map. Colors must be specified in hexadecimal format (e.g., "#FF0000" for red).
190
+
191
+ ## 🔗 Links & Resources
192
+ - [Model Context Protocol (MCP)](https://github.com/microsoft/model-context-protocol) - The foundational protocol enabling AI agent tool integration
193
+ - [Gradio Documentation](https://www.gradio.app/) - The web framework powering the user interface and MCP server implementation
194
+ - [OwlBear Rodeo](https://www.owlbear.rodeo/) - The virtual tabletop platform integrated through this MCP server
195
+ - [MCP Server Documentation](https://modelcontextprotocol.io/docs/) - Comprehensive guides for MCP server development and deployment
app.py CHANGED
@@ -21,20 +21,43 @@ from tools.obr import (
21
  from tools.test import test_function
22
  from dotenv import load_dotenv
23
  import os
 
24
 
25
  load_dotenv()
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  # === GRADIO INTERFACE ===
28
  demo = gr.TabbedInterface(
29
- [ # Pestaña de pruebas (sin api_name)
30
- gr.Interface(
31
  test_function,
32
  [
33
  gr.Textbox(label="Tab ID"),
34
  ],
35
- gr.JSON(label="Resultados de la prueba"),
36
- title="Ventana de Pruebas de OBR",
37
- description="Esta ventana demuestra todas las funcionalidades de OwlBear Rodeo disponibles.",
38
  api_name=False
39
  ),
40
  gr.Interface(letter_counter, [gr.Textbox(), gr.Textbox()], gr.Textbox(), api_name="letter_counter"),
@@ -148,9 +171,9 @@ demo = gr.TabbedInterface(
148
  gr.JSON(),
149
  api_name="clean_map"
150
  )
151
- ],
152
- [
153
- "🧪 Pruebas",
154
  "Letter Counter",
155
  "Prime Factors",
156
  "Roll Dice",
 
21
  from tools.test import test_function
22
  from dotenv import load_dotenv
23
  import os
24
+ import re
25
 
26
  load_dotenv()
27
 
28
+ with open("README.md", "r", encoding="utf-8") as f:
29
+ readme = f.read()
30
+ if readme.startswith("---"):
31
+ parts = readme.split("---", 2)
32
+ if len(parts) >= 3:
33
+ readme = parts[2]
34
+
35
+ html_blocks = re.findall(r'```html\n(.*?)\n```', readme, re.DOTALL)
36
+ for i, html_block in enumerate(html_blocks):
37
+ readme = readme.replace(f"```html\n{html_block}\n```", f"{{HTML_BLOCK_{i}}}")
38
+
39
+ with gr.Blocks() as intro_demo:
40
+ parts = re.split(r'({HTML_BLOCK_\d+})', readme)
41
+
42
+ for part in parts:
43
+ if part.startswith("{HTML_BLOCK_"):
44
+ block_idx = int(part.replace("{HTML_BLOCK_", "").replace("}", ""))
45
+ gr.HTML(html_blocks[block_idx])
46
+ else:
47
+ if part.strip():
48
+ gr.Markdown(part)
49
+
50
  # === GRADIO INTERFACE ===
51
  demo = gr.TabbedInterface(
52
+ [
53
+ intro_demo, gr.Interface(
54
  test_function,
55
  [
56
  gr.Textbox(label="Tab ID"),
57
  ],
58
+ gr.JSON(label="Test Results"),
59
+ title="OBR Test Window",
60
+ description="This window demonstrates all available OwlBear Rodeo functionalities.",
61
  api_name=False
62
  ),
63
  gr.Interface(letter_counter, [gr.Textbox(), gr.Textbox()], gr.Textbox(), api_name="letter_counter"),
 
171
  gr.JSON(),
172
  api_name="clean_map"
173
  )
174
+ ], [
175
+ "🧙‍♂️ Introduction",
176
+ "🧪 Tests",
177
  "Letter Counter",
178
  "Prime Factors",
179
  "Roll Dice",
tools/obr.py CHANGED
@@ -2,7 +2,7 @@ import requests as request
2
  import os
3
  import urllib3
4
 
5
- # Suprimir advertencias sobre conexiones SSL inseguras
6
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
7
 
8
  ASSETS_NAMES = {
@@ -227,10 +227,10 @@ def animate_token_viewport(tab_id:str, item_id:str) -> dict:
227
 
228
  return execute_action(tab_id=tab_id, action="animateViewport", params=params)
229
 
230
- def insert_map(tab_id:str, map_type:str) -> dict:
231
  """
232
  Insert a map into the game.
233
- The avaulablr maps are:
234
  - FOREST: A forest with multiple paths and trees.
235
  - VILLAGE: A small village with 3 houses and a well in the middle.
236
  - LONELY_CABIN: A lonely cabin in the middle of a plain.
 
2
  import os
3
  import urllib3
4
 
5
+ # Suppress warnings about insecure SSL connections
6
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
7
 
8
  ASSETS_NAMES = {
 
227
 
228
  return execute_action(tab_id=tab_id, action="animateViewport", params=params)
229
 
230
+ def insert_map(tab_id:str, map_type:str) -> dict:
231
  """
232
  Insert a map into the game.
233
+ The available maps are:
234
  - FOREST: A forest with multiple paths and trees.
235
  - VILLAGE: A small village with 3 houses and a well in the middle.
236
  - LONELY_CABIN: A lonely cabin in the middle of a plain.
tools/test.py CHANGED
@@ -13,25 +13,25 @@ from tools.obr import (
13
  )
14
  import time
15
 
16
- # === FUNCIÓN DE PRUEBA ===
17
  def test_function(tab_id):
18
- """Función de prueba que demuestra todas las funcionalidades de OBR"""
19
  results = []
20
 
21
  try:
22
- # 1. Limpiar el mapa
23
- results.append({"step": "1. Limpiando mapa", "result": clean_map(tab_id)})
24
  time.sleep(1)
25
 
26
- # 2. Limpiar niebla
27
- results.append({"step": "2. Limpiando niebla", "result": clear_fog(tab_id)})
28
  time.sleep(1)
29
 
30
- # 3. Insertar mapa
31
- results.append({"step": "3. Insertando mapa", "result": insert_map(tab_id, "FOREST")})
32
  time.sleep(1)
33
 
34
- # 4. Crear formas geométricas (círculos rojos en diagonal)
35
  for i in range(0, 30, 6):
36
  shape_result = create_shape(
37
  width=2,
@@ -43,10 +43,10 @@ def test_function(tab_id):
43
  stroke_color="#FF0000",
44
  tab_id=tab_id
45
  )
46
- results.append({"step": f"4. Creando círculo en ({i},{i})", "result": shape_result})
47
  time.sleep(0.5)
48
 
49
- # 5. Crear token principal (Knight)
50
  knight_result = create_token(
51
  name="Knight",
52
  type="KNIGHT",
@@ -55,21 +55,20 @@ def test_function(tab_id):
55
  size=1,
56
  tab_id=tab_id
57
  )
58
- knight_id = [i for i in knight_result['result']["gameState"]['images'] if i["name"] == "Knight"][0]["id"]
59
-
60
- results.append({"step": "5. Creando Knight", "result": knight_result, "token_id": knight_id})
61
  time.sleep(1)
62
 
63
- # 6. Mover el knight a posición intermedia
64
  if knight_id:
65
- results.append({"step": "6. Moviendo Knight a (14,14)", "result": move_item(tab_id, knight_id, 14, 14)})
66
  time.sleep(1)
67
 
68
- # 7. Mover el knight a posición final
69
- results.append({"step": "7. Moviendo Knight a (29,29)", "result": move_item(tab_id, knight_id, 29, 29)})
70
  time.sleep(1)
71
 
72
- # 8. Crear token dragón
73
  dragon_result = create_token(
74
  name="Red Dragon",
75
  type="DRAGON",
@@ -79,43 +78,41 @@ def test_function(tab_id):
79
  tab_id=tab_id
80
  )
81
  dragon_id = [i for i in dragon_result['result']["gameState"]['images'] if i["name"] == "Red Dragon"][0]["id"]
82
- results.append({"step": "8. Creando Red Dragon", "result": dragon_result, "token_id": dragon_id})
83
  time.sleep(1)
84
 
85
- # 9. Animar viewport al dragón
86
  if dragon_id:
87
- results.append({"step": "9. Animando viewport al dragón", "result": animate_token_viewport(tab_id, dragon_id)})
88
  time.sleep(1)
89
 
90
- # 10. Llenar con niebla
91
- results.append({"step": "10. Llenando con niebla", "result": fill_fog(tab_id)})
92
- time.sleep(1)
93
-
94
- # 11. Añadir luz al knight
95
  if knight_id:
96
- results.append({"step": "11. Añadiendo luz al Knight", "result": add_token_light(tab_id, knight_id, 5)})
97
  time.sleep(1)
98
 
99
- # 12. Mover knight de vuelta al centro
100
- results.append({"step": "12. Moviendo Knight de vuelta a (14,14)", "result": move_item(tab_id, knight_id, 14, 14)})
101
  time.sleep(1)
102
 
103
- # 13. Animar viewport al knight
104
- results.append({"step": "13. Animando viewport al Knight", "result": animate_token_viewport(tab_id, knight_id)})
105
  time.sleep(1)
106
 
107
- # 14. Obtener estado final del juego
108
  final_state = game_state(tab_id)
109
- results.append({"step": "14. Estado final del juego", "result": final_state})
110
  time.sleep(5)
111
 
112
- #15. Limpiar mapa al final
113
- results.append({"step": "15. Limpiando mapa", "result": clean_map(tab_id)})
114
 
115
 
116
  return {
117
  "success": True,
118
- "message": "Prueba completada exitosamente",
119
  "total_steps": len(results),
120
  "results": results
121
  }
 
13
  )
14
  import time
15
 
16
+ # === TEST FUNCTION ===
17
  def test_function(tab_id):
18
+ """Test function that demonstrates all OBR functionalities"""
19
  results = []
20
 
21
  try:
22
+ # 1. Clean the map
23
+ results.append({"step": "1. Cleaning map", "result": clean_map(tab_id)})
24
  time.sleep(1)
25
 
26
+ # 2. Clear fog
27
+ results.append({"step": "2. Clearing fog", "result": clear_fog(tab_id)})
28
  time.sleep(1)
29
 
30
+ # 3. Insert map
31
+ results.append({"step": "3. Inserting map", "result": insert_map(tab_id, "FOREST")})
32
  time.sleep(1)
33
 
34
+ # 4. Create geometric shapes (red circles in diagonal)
35
  for i in range(0, 30, 6):
36
  shape_result = create_shape(
37
  width=2,
 
43
  stroke_color="#FF0000",
44
  tab_id=tab_id
45
  )
46
+ results.append({"step": f"4. Creating circle at ({i},{i})", "result": shape_result})
47
  time.sleep(0.5)
48
 
49
+ # 5. Create main token (Knight)
50
  knight_result = create_token(
51
  name="Knight",
52
  type="KNIGHT",
 
55
  size=1,
56
  tab_id=tab_id
57
  )
58
+ knight_id = [i for i in knight_result['result']["gameState"]['images'] if i["name"] == "Knight"][0]["id"]
59
+ results.append({"step": "5. Creating Knight", "result": knight_result, "token_id": knight_id})
 
60
  time.sleep(1)
61
 
62
+ # 6. Move the knight to intermediate position
63
  if knight_id:
64
+ results.append({"step": "6. Moving Knight to (14,14)", "result": move_item(tab_id, knight_id, 14, 14)})
65
  time.sleep(1)
66
 
67
+ # 7. Move the knight to final position
68
+ results.append({"step": "7. Moving Knight to (29,29)", "result": move_item(tab_id, knight_id, 29, 29)})
69
  time.sleep(1)
70
 
71
+ # 8. Create dragon token
72
  dragon_result = create_token(
73
  name="Red Dragon",
74
  type="DRAGON",
 
78
  tab_id=tab_id
79
  )
80
  dragon_id = [i for i in dragon_result['result']["gameState"]['images'] if i["name"] == "Red Dragon"][0]["id"]
81
+ results.append({"step": "8. Creating Red Dragon", "result": dragon_result, "token_id": dragon_id})
82
  time.sleep(1)
83
 
84
+ # 9. Animate viewport to dragon
85
  if dragon_id:
86
+ results.append({"step": "9. Animating viewport to dragon", "result": animate_token_viewport(tab_id, dragon_id)})
87
  time.sleep(1)
88
 
89
+ # 10. Fill with fog
90
+ results.append({"step": "10. Filling with fog", "result": fill_fog(tab_id)})
91
+ time.sleep(1) # 11. Add light to knight
 
 
92
  if knight_id:
93
+ results.append({"step": "11. Adding light to Knight", "result": add_token_light(tab_id, knight_id, 5)})
94
  time.sleep(1)
95
 
96
+ # 12. Move knight back to center
97
+ results.append({"step": "12. Moving Knight back to (14,14)", "result": move_item(tab_id, knight_id, 14, 14)})
98
  time.sleep(1)
99
 
100
+ # 13. Animate viewport to knight
101
+ results.append({"step": "13. Animating viewport to Knight", "result": animate_token_viewport(tab_id, knight_id)})
102
  time.sleep(1)
103
 
104
+ # 14. Get final game state
105
  final_state = game_state(tab_id)
106
+ results.append({"step": "14. Final game state", "result": final_state})
107
  time.sleep(5)
108
 
109
+ #15. Clean map at the end
110
+ results.append({"step": "15. Cleaning map", "result": clean_map(tab_id)})
111
 
112
 
113
  return {
114
  "success": True,
115
+ "message": "Test completed successfully",
116
  "total_steps": len(results),
117
  "results": results
118
  }