Ds0uz4 commited on
Commit
4f76cc3
Β·
1 Parent(s): 7f0ac57
Files changed (1) hide show
  1. app.py +68 -147
app.py CHANGED
@@ -1,175 +1,96 @@
1
  import gradio as gr
 
 
2
  import random
3
- from collections import defaultdict
4
 
5
- # ---------------- RADAR ----------------
6
- RADAR_ENCODING = {
7
- "EMPTY": 0,
8
- "WALL": 1,
9
- "GOAL": 2,
10
- "ICE": 3,
11
- "MUD": 4,
12
- "DANGER": 5,
13
- "CHARGER": 6,
14
- "ENEMY": 7
15
- }
16
 
17
- # ---------------- ENV ----------------
18
  class MegaWorldEnv:
19
  def __init__(self):
20
- self.start = (1, 1)
21
- self.goal = (18, 18)
22
-
23
  self.walls = self._generate_walls()
24
  self.ice = [(5,y) for y in range(5,15)] + [(15,y) for y in range(5,15)]
25
  self.mud = [(x,10) for x in range(2,18)]
26
-
27
- self.traps = [(3,3), (8,8), (12,12), (17,17), (9,10), (11,10)]
28
- random.shuffle(self.traps)
29
-
30
- self.chargers = [(18,2), (10,10)]
31
-
32
- self.enemies = [
33
- {"pos": [5, 5]},
34
- {"pos": [15, 5]},
35
- {"pos": [12, 12]},
36
- {"pos": [16, 16]},
37
- {"pos": [8, 14]}
38
- ]
39
 
40
  def _generate_walls(self):
41
- walls = []
42
- for i in range(20):
43
- if i % 4 == 0:
44
- for j in range(5, 15):
45
- walls.append((i, j))
46
- walls += [(6,6), (7,7), (13,13), (14,14)]
47
- return walls
48
-
49
- def shaped_reward(self, old_pos, new_pos):
50
- old_d = abs(old_pos[0]-self.goal[0]) + abs(old_pos[1]-self.goal[1])
51
- new_d = abs(new_pos[0]-self.goal[0]) + abs(new_pos[1]-self.goal[1])
52
- return 3.0 * (old_d - new_d)
53
 
54
  def get_radar(self, pos):
55
  x, y = pos
56
  radar = {}
57
- dirs = {"up":(x,y+1),"down":(x,y-1),"left":(x-1,y),"right":(x+1,y)}
58
-
59
- for d,(nx,ny) in dirs.items():
60
- info = "EMPTY"
61
- if not (0<=nx<20 and 0<=ny<20): info="WALL"
62
- elif (nx,ny) in self.walls: info="WALL"
63
  elif (nx,ny)==self.goal: info="GOAL"
64
- elif (nx,ny) in self.ice: info="ICE"
65
- elif (nx,ny) in self.mud: info="MUD"
66
  elif (nx,ny) in self.traps: info="DANGER"
67
- elif (nx,ny) in self.chargers: info="CHARGER"
68
- for e in self.enemies:
69
- if tuple(e["pos"])==(nx,ny):
70
- info="ENEMY"
71
- radar[d]=RADAR_ENCODING[info]
72
  return radar
73
 
74
  def update_enemies(self):
75
  for e in self.enemies:
76
- x,y = e["pos"]
77
- moves=[]
78
- for nx,ny in [(x,y+1),(x,y-1),(x-1,y),(x+1,y)]:
79
- if 0<=nx<20 and 0<=ny<20 and (nx,ny) not in self.walls:
80
- moves.append((nx,ny))
81
- if moves:
82
- e["pos"]=list(random.choice(moves))
83
-
84
- def render(self, player_pos, history, battery, score):
85
- html = "<div style='background:#000;padding:10px;border-radius:10px;font-family:monospace'>"
86
- html += f"<div style='color:white'>πŸ”‹ {battery}% | πŸ† {score:.1f}</div>"
87
- html += "<div style='display:grid;grid-template-columns:repeat(20,22px);gap:1px'>"
88
-
89
- enemy_pos = [tuple(e["pos"]) for e in self.enemies]
90
 
 
 
 
91
  for y in range(19,-1,-1):
92
  for x in range(20):
93
- pos=(x,y)
94
- color="#111"; char=""
95
- if pos in self.walls: color="#555"
96
- elif pos in self.ice: color="#29b6f6"
97
- elif pos in self.mud: color="#4e342e"
98
- elif pos in history: color="#263238"
99
- if pos==self.goal: char="🏁"; color="#4caf50"
100
- if pos in self.chargers: char="⚑"; color="#fdd835"
101
- if pos in enemy_pos: char="πŸ‘Ύ"; color="#d500f9"
102
- if pos==player_pos:
103
- char="πŸ€–"
104
- color="#2196f3" if battery>20 else "#ff6f00"
105
- html += f"<div style='width:22px;height:22px;background:{color};display:flex;align-items:center;justify-content:center'>{char}</div>"
106
- html += "</div></div>"
107
- return html
108
-
109
- # ---------------- SAFE AGENT ----------------
110
- def safe_agent_action(pos, radar, battery):
111
- """
112
- Simple greedy agent toward goal.
113
- No dynamic code execution (Spaces-safe).
114
- """
115
- preferences = [0,3,1,2] # up, right, down, left
116
- for a in preferences:
117
- if list(radar.values())[a] not in (RADAR_ENCODING["WALL"], RADAR_ENCODING["ENEMY"]):
118
- return a
119
- return random.randint(0,3)
120
-
121
- # ---------------- SIM ----------------
122
- def run_mega_simulation():
123
  env = MegaWorldEnv()
124
- pos=list(env.start)
125
- battery=100
126
- score=0
127
- history=[]
128
-
129
- for step in range(300):
130
- radar=env.get_radar(pos)
131
- action=safe_agent_action(pos, radar, battery)
132
-
133
- dx,dy=[(0,1),(0,-1),(-1,0),(1,0)][action]
134
- prev=pos[:]
135
- nx,ny=pos[0]+dx,pos[1]+dy
136
- if not (0<=nx<20 and 0<=ny<20) or (nx,ny) in env.walls:
137
- nx,ny=pos
138
- pos=[nx,ny]
139
-
140
  env.update_enemies()
141
- history.append(tuple(pos))
142
- battery-=1
143
- if tuple(pos) in env.mud: battery-=5
144
-
145
- reward=env.shaped_reward(tuple(prev),tuple(pos))
146
- if prev==pos: reward-=5
147
- if tuple(pos) in env.traps: reward-=10; battery-=10
 
 
 
148
 
149
- done=False
150
- if battery<=0 or tuple(pos) in [tuple(e["pos"]) for e in env.enemies]:
151
- reward-=20; done=True
152
- if tuple(pos)==env.goal:
153
- reward+=1000; done=True
154
-
155
- reward=max(reward,-10)
156
- score+=reward
157
-
158
- yield env.render(tuple(pos),history,battery,score), {
159
- "step":step,
160
- "reward":round(reward,2),
161
- "battery":battery
162
- }
163
-
164
- if done:
165
- return
166
-
167
- # ---------------- UI ----------------
168
  with gr.Blocks() as demo:
169
- gr.Markdown("# 🌍 Super RL World (Spaces Safe)")
170
- game=gr.HTML()
171
- log=gr.JSON()
172
- btn=gr.Button("πŸš€ Run Simulation")
173
- btn.click(run_mega_simulation, outputs=[game,log])
174
-
175
- demo.launch()
 
 
 
 
1
  import gradio as gr
2
+ import importlib.util
3
+ import time
4
  import random
 
5
 
6
+ RADAR_ENCODING = {"EMPTY":0, "WALL":1, "GOAL":2, "ICE":3, "MUD":4, "DANGER":5, "CHARGER":6, "ENEMY":7}
 
 
 
 
 
 
 
 
 
 
7
 
 
8
  class MegaWorldEnv:
9
  def __init__(self):
10
+ self.start, self.goal = (1, 1), (18, 18)
 
 
11
  self.walls = self._generate_walls()
12
  self.ice = [(5,y) for y in range(5,15)] + [(15,y) for y in range(5,15)]
13
  self.mud = [(x,10) for x in range(2,18)]
14
+ self.traps = [(3,3),(8,8),(12,12),(17,17),(9,10),(11,10)]
15
+ self.chargers = [(18,2),(10,10)]
16
+ self.enemies = [{"pos":[5,5]}, {"pos":[15,5]}, {"pos":[12,12]}, {"pos":[16,16]}]
 
 
 
 
 
 
 
 
 
 
17
 
18
  def _generate_walls(self):
19
+ w = [(i,j) for i in range(0,20,4) for j in range(5,15)]
20
+ w += [(6,6),(7,7),(13,13),(14,14)]
21
+ return w
 
 
 
 
 
 
 
 
 
22
 
23
  def get_radar(self, pos):
24
  x, y = pos
25
  radar = {}
26
+ for name, (nx, ny) in {"up":(x,y+1),"down":(x,y-1),"left":(x-1,y),"right":(x+1,y)}.items():
27
+ if not (0<=nx<20 and 0<=ny<20) or (nx,ny) in self.walls: info="WALL"
 
 
 
 
28
  elif (nx,ny)==self.goal: info="GOAL"
 
 
29
  elif (nx,ny) in self.traps: info="DANGER"
30
+ elif any(e["pos"]==[nx,ny] for e in self.enemies): info="ENEMY"
31
+ elif (nx,ny) in self.mud: info="MUD"
32
+ else: info="EMPTY"
33
+ radar[name] = RADAR_ENCODING[info]
 
34
  return radar
35
 
36
  def update_enemies(self):
37
  for e in self.enemies:
38
+ moves = [(e["pos"][0]+dx, e["pos"][1]+dy) for dx,dy in [(0,1),(0,-1),(1,0),(-1,0)]]
39
+ valid = [m for m in moves if 0<=m[0]<20 and 0<=m[1]<20 and m not in self.walls]
40
+ if valid: e["pos"] = list(random.choice(valid))
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ def render(self, p_pos, history, bat, score):
43
+ html = f"<div style='background:#000;padding:10px;border-radius:10px;color:#fff;font-family:monospace;'>πŸ”‹ {bat} | πŸ† {score:.1f}<div style='display:grid;grid-template-columns:repeat(20,20px);gap:1px;background:#222;'>"
44
+ e_pos = [tuple(e["pos"]) for e in self.enemies]
45
  for y in range(19,-1,-1):
46
  for x in range(20):
47
+ c = "#111"; char = ""
48
+ if (x,y) in self.walls: c="#444"
49
+ elif (x,y) == self.goal: c="#2e7d32"; char="🏁"
50
+ elif (x,y) in e_pos: c="#c62828"; char="πŸ‘Ύ"
51
+ elif (x,y) == p_pos: c="#1565c0"; char="πŸ€–"
52
+ elif (x,y) in history: c="#222"
53
+ html += f"<div style='width:20px;height:20px;background:{c};display:flex;justify-content:center;align-items:center;'>{char}</div>"
54
+ return html + "</div></div>"
55
+
56
+ def run_sim(file):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  env = MegaWorldEnv()
58
+ if not file: yield env.render(env.start,[],100,0), "Upload Agent"; return
59
+ spec = importlib.util.spec_from_file_location("agent", file.name)
60
+ agent = importlib.util.module_from_spec(spec)
61
+ spec.loader.exec_module(agent)
62
+
63
+ if hasattr(agent, "train"): agent.train(env)
64
+
65
+ pos, bat, score, hist = list(env.start), 100, 0, []
66
+ for s in range(300):
67
+ radar = env.get_radar(pos)
68
+ action = agent.get_action(pos, radar, bat)
69
+ dx, dy = [(0,1),(0,-1),(-1,0),(1,0)][action]
70
+ old_pos = tuple(pos)
71
+ nx, ny = pos[0]+dx, pos[1]+dy
72
+ if 0<=nx<20 and 0<=ny<20 and (nx,ny) not in env.walls: pos = [nx,ny]
73
+
74
  env.update_enemies()
75
+ bat -= (5 if tuple(pos) in env.mud else 1)
76
+ reward = (abs(old_pos[0]-18)+abs(old_pos[1]-18)) - (abs(pos[0]-18)+abs(pos[1]-18))
77
+ if tuple(pos)==env.goal: reward+=1000; score+=1000
78
+ if any(e["pos"]==pos for e in env.enemies) or bat<=0: yield env.render(tuple(pos),hist,0,score), "Game Over"; return
79
+
80
+ if hasattr(agent, "observe"): agent.observe(reward, pos, radar, bat, tuple(pos)==env.goal)
81
+ score += reward
82
+ hist.append(tuple(pos))
83
+ yield env.render(tuple(pos),hist,bat,score), f"Step {s}"
84
+ time.sleep(0.08)
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  with gr.Blocks() as demo:
87
+ gr.Markdown("# πŸ’€ Super RL World: Chaos Edition")
88
+ with gr.Row():
89
+ board = gr.HTML(MegaWorldEnv().render((1,1),[],100,0))
90
+ with gr.Column():
91
+ in_file = gr.File(label="Agent.py")
92
+ run_btn = gr.Button("πŸš€ Start Run")
93
+ txt = gr.Textbox(label="Log")
94
+ run_btn.click(run_sim, in_file, [board, txt])
95
+
96
+ demo.launch()