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