Skip to content

Commit 4389744

Browse files
basic UI
1 parent 00fd8ad commit 4389744

File tree

2 files changed

+204
-12
lines changed

2 files changed

+204
-12
lines changed

Core/CMazeEnviroment.py

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from enum import Enum
22
import numpy as np
3+
import random
34

45
class MazeActions(Enum):
56
LEFT = (-1, 0)
@@ -9,44 +10,75 @@ class MazeActions(Enum):
910

1011
class CMazeEnviroment:
1112
def __init__(self, maze, pos, FOV):
12-
self._maze = np.pad(np.array(maze), FOV, constant_values=(1,))
13-
self._pos = np.array(pos) + FOV
13+
self.maze = np.pad(np.array(maze), FOV, constant_values=(1,))
1414
self._fov = FOV
1515

16-
self._fog = np.zeros_like(self._maze)
16+
x, y = np.array(pos) + FOV
17+
self.spawnAt(x, y)
18+
return
19+
20+
def spawnAt(self, x, y):
21+
self.pos = np.array([y, x])
22+
self.fog = np.zeros_like(self.maze)
1723
self._updateFog()
24+
return
25+
26+
def respawn(self):
27+
w, h = self.maze.shape
28+
while True:
29+
x = random.randint(0, w - 1)
30+
y = random.randint(0, h - 1)
31+
if self.maze[x, y] <= 0:
32+
self.spawnAt(x, y)
33+
break
34+
return
1835

1936
def _updateFog(self):
20-
y, x = self._pos
21-
self._fog[
37+
y, x = self.pos
38+
self.fog[
2239
x - self._fov:x + self._fov + 1,
2340
y - self._fov:y + self._fov + 1
2441
] = 1
2542
return
2643

2744
def apply(self, action):
28-
self._pos += action.value
45+
self.pos += action.value
2946
self._updateFog()
3047
return
3148

3249
def vision(self):
33-
y, x = self._pos
34-
return self._maze[
50+
y, x = self.pos
51+
return self.maze[
3552
x - self._fov:x + self._fov + 1,
3653
y - self._fov:y + self._fov + 1
3754
]
3855

3956
@property
4057
def state(self):
41-
return ((self.vision(), self._fog, ), self.score, self.done)
58+
return ((self.vision(), self.fog, ), self.score, self.done)
4259

4360
@property
4461
def done(self):
4562
y, x = self._pos
46-
return 1 < self._maze[x, y]
63+
return 1 < self.maze[x, y]
4764

4865
@property
4966
def score(self):
50-
h, w = self._fog.shape
67+
h, w = self.fog.shape
5168
total = h * w
52-
return np.count_nonzero(self._fog) / total
69+
return np.count_nonzero(self.fog) / total
70+
71+
def copy(self):
72+
# dirty copy
73+
res = CMazeEnviroment(self.maze, self.pos, self._fov)
74+
res.maze = self.maze.copy()
75+
res.fog = self.fog.copy()
76+
res.pos = self.pos.copy()
77+
return res
78+
79+
def isPossible(self, action):
80+
y, x = self.pos + action.value
81+
return self.maze[x, y] <= 0
82+
83+
def validActions(self):
84+
return [ act for act in MazeActions if self.isPossible(act) ]

view_maze.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
from Core.CMazeEnviroment import CMazeEnviroment, MazeActions
4+
import numpy as np
5+
import pygame
6+
import pygame.locals as G
7+
import random
8+
9+
def createMaze():
10+
sz = 64
11+
maze = (0.8 < np.random.rand(sz, sz)).astype(np.float32)
12+
res = CMazeEnviroment(
13+
maze=maze,
14+
pos=(0, 0),
15+
FOV=3
16+
)
17+
res.respawn()
18+
return res
19+
20+
class Colors:
21+
BLACK = (0, 0, 0)
22+
SILVER = (192, 192, 192)
23+
WHITE = (255, 255, 255)
24+
BLUE = (0, 0, 255)
25+
GREEN = (0, 255, 0)
26+
RED = (255, 0, 0)
27+
PURPLE = (255, 0, 255)
28+
29+
class App:
30+
MODES = ['manual', 'random']
31+
def __init__(self):
32+
self._running = True
33+
self._display_surf = None
34+
self._createMaze()
35+
self._mode = 'manual'
36+
self._paused = True
37+
self._speed = 20
38+
39+
def _createMaze(self):
40+
self._maze = createMaze()
41+
self._initMaze = self._maze.copy()
42+
return
43+
44+
def on_init(self):
45+
pygame.init()
46+
47+
self._display_surf = pygame.display.set_mode((800, 650), pygame.HWSURFACE)
48+
pygame.display.set_caption('Deep maze')
49+
self._font = pygame.font.Font(pygame.font.get_default_font(), 16)
50+
self._running = True
51+
52+
def on_event(self, event):
53+
if event.type == G.QUIT:
54+
self._running = False
55+
56+
if event.type == G.KEYDOWN:
57+
if G.K_m == event.key:
58+
mode = next((i for i, x in enumerate(self.MODES) if x == self._mode))
59+
self._mode = self.MODES[(mode + 1) % len(self.MODES)]
60+
self._paused = True
61+
62+
if G.K_SPACE == event.key:
63+
self._paused = not self._paused
64+
65+
if G.K_ESCAPE == event.key:
66+
self._running = False
67+
68+
if 'manual' == self._mode:
69+
if G.K_r == event.key:
70+
self._createMaze()
71+
72+
if G.K_i == event.key:
73+
self._maze = self._initMaze.copy()
74+
75+
if G.K_y == event.key:
76+
self._maze.respawn()
77+
78+
actMapping = {
79+
G.K_LEFT: MazeActions.LEFT,
80+
G.K_RIGHT: MazeActions.RIGHT,
81+
G.K_UP: MazeActions.UP,
82+
G.K_DOWN: MazeActions.DOWN
83+
}
84+
85+
act = actMapping.get(event.key, False)
86+
if act and self._maze.isPossible(act):
87+
self._maze.apply(act)
88+
#####
89+
return
90+
91+
def on_loop(self):
92+
if ('random' == self._mode) and not self._paused:
93+
for _ in range(self._speed):
94+
actions = self._maze.validActions()
95+
if actions:
96+
self._maze.apply(random.choice(actions))
97+
pass
98+
99+
def _renderMaze(self):
100+
fog = self._maze.fog
101+
maze = self._maze.maze
102+
h, w = maze.shape
103+
dx, dy = delta = np.array([640, 640]) / np.array([w, h])
104+
for ix in range(w):
105+
for iy in range(h):
106+
isDiscovered = 0 < fog[ix, iy]
107+
isWall = 0 < maze[ix, iy]
108+
y, x = delta * np.array([ix, iy])
109+
110+
clr = Colors.PURPLE if isWall else Colors.WHITE
111+
if not isDiscovered:
112+
clr = np.array(clr) * .3
113+
pygame.draw.rect(self._display_surf, clr, [x, y, dx - 1, dy - 1], 0)
114+
# current pos
115+
x, y = delta * self._maze.pos
116+
pygame.draw.rect(self._display_surf, Colors.RED, [x, y, dx - 1, dy - 1], 0)
117+
return
118+
119+
def _renderInfo(self):
120+
self._display_surf.blit(
121+
self._font.render(
122+
'Score: %.2f' % (self._maze.score),
123+
False, Colors.BLUE
124+
), (655, 15)
125+
)
126+
127+
self._display_surf.blit(
128+
self._font.render(
129+
'Mode: %s' % (self._mode),
130+
False, Colors.BLUE
131+
), (655, 35)
132+
)
133+
return
134+
135+
def on_render(self):
136+
self._display_surf.fill(Colors.SILVER)
137+
self._renderMaze()
138+
self._renderInfo()
139+
pygame.display.flip()
140+
141+
def run(self):
142+
if self.on_init() == False:
143+
self._running = False
144+
145+
while self._running:
146+
for event in pygame.event.get():
147+
self.on_event(event)
148+
149+
self.on_loop()
150+
self.on_render()
151+
152+
pygame.quit()
153+
154+
def main():
155+
app = App()
156+
app.run()
157+
pass
158+
159+
if __name__ == '__main__':
160+
main()

0 commit comments

Comments
 (0)