byte-vortex commited on
Commit
5f327fc
·
verified ·
1 Parent(s): ac97b38

Delete ui/demo_roam.py

Browse files
Files changed (1) hide show
  1. ui/demo_roam.py +0 -254
ui/demo_roam.py DELETED
@@ -1,254 +0,0 @@
1
- """
2
- demo_roam.py — Myco autonomous roaming demo.
3
-
4
- Myco walks the 3x3 grid by itself, spawning mushrooms and reacting to them.
5
- The LLM (engine._llm) is only called for narration, NOT for movement decisions.
6
- All movement and game logic is pure Python.
7
-
8
- Run: python demo_roam.py
9
- """
10
-
11
- import threading
12
- import time
13
- import random
14
- import copy
15
- import gradio as gr
16
- from typing import Any, cast
17
-
18
- from ui.renderers import (
19
- forest_scene, dex_markdown, game_status_markdown,
20
- mushroom_card, progress_markdown, EMPTY_DEX,
21
- )
22
- from game.engine import (
23
- discover_mushroom, collect_current, study_current,
24
- _is_poisonous, _score_collection,
25
- )
26
- from game.state import welcome_history
27
-
28
- # ---------------------------------------------------------------------------
29
- # Shared roam state — all mutations go through _STATE_LOCK
30
- # ---------------------------------------------------------------------------
31
- _STATE_LOCK = threading.Lock()
32
-
33
- STATE = {
34
- "position": (1, 1),
35
- "current": None, # active mushroom dict
36
- "active_mushrooms": [], # list of mushroom dicts with mush_x, mush_y
37
- "collection": [],
38
- "history": list(welcome_history()),
39
- "thought": "The forest is waking up...",
40
- "score": 0,
41
- "health": 3,
42
- "ticks": 0,
43
- "visited": set(),
44
- }
45
-
46
- POISONOUS = {"Ghost Gill", "Pepper Pixie", "Ruby Knuckle", "Clockwork Chanterelle"}
47
-
48
- # ---------------------------------------------------------------------------
49
- # Pure Python roam logic — NO LLM decisions
50
- # ---------------------------------------------------------------------------
51
-
52
- def _next_pos(x, y, visited):
53
- candidates = []
54
- for dx, dy in [(0,-1),(0,1),(-1,0),(1,0)]:
55
- nx, ny = x+dx, y+dy
56
- if 0 <= nx <= 2 and 0 <= ny <= 2:
57
- weight = 1 if (nx,ny) in visited else 4
58
- candidates.extend([(nx,ny)] * weight)
59
- return random.choice(candidates) if candidates else (x, y)
60
-
61
-
62
- def _roam_tick():
63
- """One autonomous tick — pure Python decision, optional LLM narration."""
64
- with _STATE_LOCK:
65
- x, y = STATE["position"]
66
- collection = list(STATE["collection"])
67
- current = STATE["current"]
68
- mushrooms = list(STATE["active_mushrooms"])
69
- visited = set(STATE["visited"])
70
- ticks = STATE["ticks"]
71
- STATE["ticks"] += 1
72
-
73
- # --- Decision logic ---
74
- action = "move"
75
-
76
- # If there's a mushroom at our position
77
- at_pos = [m for m in mushrooms if int(m.get("mush_x",-1)) == x
78
- and int(m.get("mush_y",-1)) == y
79
- and m.get("picked") != "Yes"]
80
- if at_pos:
81
- m = at_pos[0]
82
- if m.get("poison") == "Yes":
83
- action = "flee" # move away from poison
84
- elif m.get("studied") != "Yes":
85
- action = "study"
86
- else:
87
- action = "collect"
88
-
89
- # If clearing is empty and we haven't searched here recently
90
- elif (x, y) not in visited or ticks % 6 == 0:
91
- action = "search"
92
-
93
- # --- Execute ---
94
- new_current = current
95
- new_mushrooms = mushrooms
96
- new_collection = collection
97
- new_history = STATE["history"]
98
- thought = STATE["thought"]
99
-
100
- if action == "move" or action == "flee":
101
- nx, ny = _next_pos(x, y, visited)
102
- with _STATE_LOCK:
103
- STATE["position"] = (nx, ny)
104
- STATE["visited"].add((nx, ny))
105
- return
106
-
107
- if action == "search":
108
- try:
109
- mushroom, new_current, new_history = discover_mushroom(collection)
110
- # Assign a grid position for the roaming sprite
111
- new_current["mush_x"] = x
112
- new_current["mush_y"] = y
113
- new_current["picked"] = "No"
114
- new_mushrooms = [m for m in mushrooms if not (
115
- int(m.get("mush_x",-1)) == x and int(m.get("mush_y",-1)) == y
116
- )] + [new_current]
117
- thought = f"Found {new_current.get('name','?')}! 🍄"
118
- except Exception as e:
119
- thought = "Something stirs in the moss..."
120
-
121
- elif action == "study":
122
- try:
123
- studied_current, new_history = study_current(at_pos[0], STATE["history"])
124
- if studied_current:
125
- new_mushrooms = [studied_current if (
126
- m.get("name") == at_pos[0].get("name")
127
- ) else m for m in mushrooms]
128
- new_current = studied_current
129
- thought = f"Studied {studied_current.get('name','?')}. ✨"
130
- except Exception as e:
131
- thought = "Myco examines the mushroom carefully..."
132
-
133
- elif action == "collect":
134
- try:
135
- new_collection, new_history = collect_current(at_pos[0], collection, STATE["history"])
136
- # Mark as picked in the mushrooms list
137
- new_mushrooms = [
138
- {**m, "picked": "Yes"} if m.get("name") == at_pos[0].get("name") else m
139
- for m in mushrooms
140
- ]
141
- new_current = {**at_pos[0], "picked": "Yes"}
142
- thought = f"Collected {at_pos[0].get('name','?')}! +{at_pos[0].get('score_delta','?')} spores 🎉"
143
- except Exception as e:
144
- thought = "Added to the MycoDex..."
145
-
146
- # Move after acting
147
- nx, ny = _next_pos(x, y, visited)
148
-
149
- with _STATE_LOCK:
150
- STATE["position"] = (nx, ny)
151
- STATE["visited"].add((nx, ny))
152
- STATE["current"] = new_current
153
- STATE["active_mushrooms"] = [m for m in new_mushrooms if m.get("picked") != "Yes"]
154
- STATE["collection"] = new_collection
155
- STATE["history"] = new_history[-20:] if new_history else []
156
- STATE["thought"] = thought
157
-
158
-
159
- def _roam_loop(interval=3.0):
160
- while True:
161
- try:
162
- _roam_tick()
163
- except Exception as e:
164
- print(f"[Roam] tick error: {e}")
165
- time.sleep(interval)
166
-
167
-
168
- def start_roaming(interval=3.0):
169
- t = threading.Thread(target=_roam_loop, args=(interval,), daemon=True)
170
- t.start()
171
- print("[Roam] Myco is now roaming autonomously.")
172
-
173
-
174
- # ---------------------------------------------------------------------------
175
- # Gradio poll functions
176
- # ---------------------------------------------------------------------------
177
-
178
- def poll_scene():
179
- with _STATE_LOCK:
180
- pos = STATE["position"]
181
- current = STATE["current"]
182
- mushrooms = list(STATE["active_mushrooms"])
183
- coll = list(STATE["collection"])
184
- return forest_scene(current, coll, pos, active_mushrooms=mushrooms)
185
-
186
-
187
- def poll_status():
188
- with _STATE_LOCK:
189
- pos = STATE["position"]
190
- current = STATE["current"]
191
- coll = list(STATE["collection"])
192
- return game_status_markdown(current, coll, pos)
193
-
194
-
195
- def poll_thought():
196
- with _STATE_LOCK:
197
- return STATE["thought"]
198
-
199
-
200
- def poll_dex():
201
- with _STATE_LOCK:
202
- coll = list(STATE["collection"])
203
- return dex_markdown(coll) if coll else EMPTY_DEX
204
-
205
-
206
- def poll_progress():
207
- with _STATE_LOCK:
208
- coll = list(STATE["collection"])
209
- return progress_markdown(coll)
210
-
211
-
212
- # ---------------------------------------------------------------------------
213
- # Gradio UI
214
- # ---------------------------------------------------------------------------
215
-
216
- def build_roam_demo():
217
- start_roaming(interval=3.0)
218
-
219
- with gr.Blocks(title="Myco — Autonomous Roam Demo") as demo:
220
- gr.HTML("""
221
- <style>
222
- .gradio-container { background: #1a1a2e !important; color: #f0ffe0; }
223
- .progress-level, .progress-level-inner { display: none !important; }
224
- </style>
225
- """)
226
-
227
- gr.Markdown("## 🍄 Myco — Autonomous Roam Demo")
228
- gr.Markdown(
229
- "Myco walks the 3×3 grid by itself every 3 seconds. "
230
- "It searches clearings, studies mushrooms, and collects them — "
231
- "all using pure Python logic. The LLM only adds narration text."
232
- )
233
-
234
- scene = gr.HTML(poll_scene())
235
- thought = gr.Textbox(label="💬 Myco's thought", interactive=False, value=poll_thought())
236
-
237
- with gr.Row():
238
- status = gr.Markdown(poll_status())
239
- with gr.Column():
240
- dex = gr.Markdown(poll_dex())
241
- progress = gr.Markdown(poll_progress())
242
-
243
- # Poll every 1.5s — fast enough to feel live, not so fast it hammers the server
244
- demo.load(fn=poll_scene, outputs=scene, every=1.5)
245
- demo.load(fn=poll_status, outputs=status, every=1.5)
246
- demo.load(fn=poll_thought, outputs=thought, every=1.5)
247
- demo.load(fn=poll_dex, outputs=dex, every=3.0)
248
- demo.load(fn=poll_progress, outputs=progress, every=3.0)
249
-
250
- return demo
251
-
252
- if __name__ == "__main__":
253
- demo = build_roam_demo()
254
- demo.launch(server_name="0.0.0.0", server_port=7860, share=False)