2Functions & classes that extend the gymnasium library
6from .misc
import RedirectStd
9from time
import sleep, time
as now
10from .imports
import lazy_import, ensure_imported
14gym = lazy_import(
'gymnasium')
17pygame = lazy_import(
'pygame')
28 """ A simplified Gymnasium enviorment that uses pygame and handles some stuff for you, like rendering
29 keeping track of steps, returning the right things from the right functions, event handling,
30 including some default keyboard shortcuts,
and some debugging features. Includes easy ways
31 to
print to the screen.
34 By default, it
's set to render the enviorment according to the function render_pygame, which
35 should render everything to self.surf. If you would like to specify other rendering methods,
36 define them as `render_{method_name}`,
and render() will handle it
for you. There
's no need
37 to manually overwrite the render() method.
40 There are 3 ways to print to the screen:
41 `show_vars`: accessable either via the constructor
or as a member
42 This
is a dictionary of {name: member} of members you want to have printed
43 on the screen. The keys can be any string,
and the values must be valid members
44 of this
class. The screen
is updated
as the member changes.
45 `show_strings`: accessable either via the constructor,
as a member,
or the
show() function
46 This
is a list of strings that are printed to the screen. They won
't change.
47 Useful for showing config options
and the like. They are always printed first.
48 `
print`: a dictionary member. The keys are arbitrary
and not printed. The values
49 are printed to the screen. The reason it
's a dictionary and not a list is simply
50 for easy indexing: you can change this
in the middle of the running loop,
and
51 it will get added to the screen. Just make sure to reuse the keys.
52 Attempting to set an item on an instance will also set it to
print
53 (i.e. `env[
'a'] =
'string'`
is the same
as `env.print[
'a'] =
'string'`)
58 i increments a single frame
59 u runs the debug_button()
60 r runs
reset() immediately
61 f toggles whether we
're limiting ourselves to FPS or not
62 h shows a help menu on screen
63 >/< increase and decrease the FPS
65 In order to use this effectively, you need to overload:
66 __init__(),
if you want to add any members
69 _step(action), don
't overload step(), step() calls _step
70 _reset(seed=None, options=
None),
if you need any custom reset code (don
't overload reset())
71 render_pygame(), render to self.surf
73 _get_terminated(),
if you want to use custom terminated criteria other than just max_steps
74 You *don
't* need to call super()._get_terminated()
75 _get_info(), if you want to include info
76 handle_event(event),
for handling events
77 debug_button(),
for debugging when you press the u key
78 _get_truncated(),
if you want to include truncated
80 Helpful members provided:
81 `width`, `height`: the dimentions of the screen
82 `size`: set to self.width,
for compatibility
's sake
83 `just_reset`: is set to
True by
reset()
and False by
step()
84 `steps`: the number of steps
in the current episode
85 `total_steps`: the total number of steps taken
86 `reset_count`: a count of the number of times
reset() has been called
87 `surf`: the surface to draw to
in render_pygame()
88 `paused`:
True if paused
89 `increment`: set to
True internally to denote a single step
while paused.
step() sets
94 SHOW_HELP_FADE_TIME = 10
99 i: increment a single frame
100 u: run debug_button()
104 h: show/hide this menu
111 name='SimpleGym Enviorment',
115 render_mode='pygame',
116 assert_valid_action=True,
117 background_color=(20, 20, 20),
118 print_color=(200, 20, 20, 0),
122 """ This should be called first, if you want to use the members like self.size
124 `max_steps`: if positive, sets the maximum number of steps before the env resets
125 itself. If
None or negative, no limit
126 `screen_size`: the size of the pygame window. Can be a 2 item tuple of (width, height)
127 or a single int
if the window
is to be square
128 `fps`: controls how fast the simulation runs. Set to negative
or None to have no limit
129 `name`: the name of the enviorment shown on the window title
130 `show_vars`: a dictionary of {name: member} of members you want to have printed
131 on the screen. The keys can be any string,
and the values must be valid members
133 `show_strings`: a list of strings you want to have printed on the screen
134 `start_paused`: self-explanitory
135 `show_events`: prints events, other than mouse movements,
for debugging purpouses
136 `render_mode`: part of the gymnasium specification. Must be either
None or 'pygame',
137 unless you manually override the render() method
138 `assert_valid_action`: ensures that actions given to
step() are within the action_space
139 `background_color`: a 3 item tuple specifying the background color
140 `print_color`: a 4 item tuple (the 4th index being alpha) specifying the color of
141 the extra data printed to the screen
142 `verbose`: when set to
True, it simply adds `fps`, `reset_count`, `steps`, `total_steps`
143 to `show_vars`. Also shows the help menu
for the first few seconds
145 self.metadata = {"render_modes": list({
'pygame', render_mode}),
"render_fps": fps}
146 assert render_mode
is None or render_mode
in self.
metadata[
"render_modes"], render_mode
157 self.
paused = start_paused
163 self.
screen_size = screen_size
if isinstance(screen_size, (tuple, list))
else (screen_size, screen_size)
165 self.
size = self.width
175 self.
show_vars[
'Episode'] =
'reset_count'
177 self.
show_vars[
'Total Steps'] =
'total_steps'
188 raise NotImplementedError
193 def _get_truncated(self):
196 def __default_get_terminated(self):
197 """ Called internally so max_steps still works even if _get_terminated is overloaded """
206 """ By default this just terminates after max_steps have been reached """
209 def _get_reward(self):
210 raise NotImplementedError
212 def reset(self, seed=None, options=None):
213 """ This sets the self.np_random to use the seed given, resets the steps, and returns the
214 observation and info. Needs to be called first,
if you
're depending on self.np_random,
215 or steps equalling 0, but also needs to
return what this returns.
218 super().
reset(seed=seed)
220 self.
_reset(seed=seed, options=options)
228 def _reset(seed=None, options=None):
229 raise NotImplementedError()
232 """ Call this last, and return it """
233 assert self.
reset_count > 0,
"step() called before reset(). reset() must be called first."
237 assert self.action_space.contains(action),
"Action given not within action_space"
262 raise NotImplementedError()
264 @ensure_imported(pygame)
265 def _init_pygame(self):
268 pygame.display.init()
269 pygame.display.set_caption(self.
name)
272 if self.
font is None:
275 if self.
surf is None:
302 length = len(max(self.
show_vars.keys(), key=len))
304 f
'{name}: {" "*(length - len(name))} {getattr(self, var, f"{var} is not a member")}'
309 strings += list(self.
print.values())
312 for offset, string
in enumerate(strings):
317 max_width = max(self.
_rendered_helps, key=
lambda h: h.get_size()[0]).get_size()[0]
318 self.
surf.blit(string, (self.width - max_width, offset*(self.
FONT_SIZE + 2)))
326 pygame.display.flip()
329 if hasattr(self, f
'render_{self.render_mode}'):
330 getattr(self, f
'render_{self.render_mode}')()
332 raise AttributeError(f
"No render_{self.render_mode} function provided")
334 def debug_button(self):
337 def _handle_events(self):
338 for e
in pygame.event.get():
344 if e.key == pygame.K_ESCAPE:
347 elif e.key == pygame.K_SPACE:
348 self.paused =
not self.paused
357 self.increment =
True
364 self.fps = self._original_fps
366 self._original_fps = self.fps
369 self.fps += self.FPS_STEP
371 self.fps -= self.FPS_STEP
373 self._show_help =
not self._show_help
378 if self.show_events
and e.type != pygame.MOUSEMOTION:
382 def handle_event(self, event):
386 """ Sets a given string to be shown on the pygame window """
387 self.show_strings.append(string)
389 def __setitem__(self, index, string):
390 self.print[index] = string
393 if self.screen
is not None:
394 pygame.display.quit()
402 def __new__(*args, **kwargs):
403 raise ImportError(
"gymnasium not installed. Run `pip install gymnasium` before importing SimpleGym.")
def _reset(seed=None, options=None)
def reset(self, seed=None, options=None)
This sets the self.np_random to use the seed given, resets the steps, and returns the observation and...
def show(self, string)
Sets a given string to be shown on the pygame window.
def step(self, action)
Call this last, and return it.
def _get_terminated(self)
By default this just terminates after max_steps have been reached.
def __init__(self, max_steps=None, screen_size=300, fps=None, name='SimpleGym Enviorment', show_vars={}, show_strings=[], start_paused=False, render_mode='pygame', assert_valid_action=True, background_color=(20, 20, 20), print_color=(200, 20, 20, 0), show_events=False, verbose=True)
This should be called first, if you want to use the members like self.size Parameters: max_steps: if ...
A simplified Gymnasium enviorment that uses pygame and handles some stuff for you,...
def __default_get_terminated(self)