Skip to content

Commit bcc0384

Browse files
committed
Reinforcement Learning: Coin Catcher custom environment with Gym toolkit
1 parent 401bcfe commit bcc0384

File tree

7 files changed

+253
-1
lines changed

7 files changed

+253
-1
lines changed
896 Bytes
Loading
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Learner: Nguyen Truong Thinh
2+
# Contact me: [email protected] || +84393280504
3+
#
4+
# Topic: Reinforcement Learning (RL): Coin Catcher RL problem
5+
import collections
6+
import sys
7+
from math import ceil
8+
from random import random, randint
9+
from time import sleep
10+
11+
import gym
12+
13+
from coin_catcher_screen import CoinCatcherScreen
14+
15+
16+
class CoinCatcherEnv(gym.Env):
17+
"""
18+
Coin Catcher environment in Gym
19+
"""
20+
metadata = {"render.modes": ["human", "ascii"]}
21+
22+
def __init__(self, display_width=10, display_height=10, density=.8):
23+
self.display_width = display_width
24+
self.display_height = display_height
25+
self.density = density
26+
self.display = collections.deque(maxlen=display_height)
27+
self.last_action = None
28+
self.last_reward = None
29+
self.total_score = 0
30+
self.v_position = 0
31+
self.game_scr = None
32+
33+
def step(self, action):
34+
self.last_action = action
35+
self.v_position = min(max(self.v_position + action, 0), self.display_width - 1)
36+
reward = self.display[0][self.v_position]
37+
self.last_reward = reward
38+
self.total_score += reward
39+
self.display.append(self.line_generator())
40+
state = self.display, self.v_position
41+
done = False
42+
info = {}
43+
44+
return state, reward, done, info
45+
46+
def _render_human(self):
47+
"""
48+
The Pygame's Graphic environment rendering
49+
"""
50+
if not self.game_scr:
51+
self.game_scr = CoinCatcherScreen(
52+
h=self.display_height,
53+
w=self.display_width
54+
)
55+
56+
if self.last_reward:
57+
self.game_scr.plus()
58+
sleep(.1)
59+
60+
self.game_scr.update(
61+
self.display,
62+
self.v_position,
63+
self.total_score
64+
)
65+
66+
def _render_ascii(self):
67+
"""
68+
The ASCII environment rendering
69+
"""
70+
outfile = sys.stdout
71+
area = []
72+
for i in range(self.display_height):
73+
line = self.display[self.display_height - 1 - i]
74+
row = []
75+
for j in range(len(line)):
76+
p = line[j]
77+
if p > 0:
78+
row.append(str(p))
79+
if i > 0 and area[-1][j] == ' ':
80+
area[-1][j] = '|'
81+
if i > 1 and area[-2][j] == ' ':
82+
area[-2][j] = '.'
83+
else:
84+
row.append(' ')
85+
86+
area.append(row)
87+
88+
pos_line = (['_'] * self.display_width)
89+
pos_line[self.v_position] = str(self.last_reward) if self.last_reward else 'V'
90+
91+
area.append(pos_line)
92+
outfile.write(f"\nTotal score: {self.total_score} \n")
93+
outfile.write("\n".join(" ".join(line) for line in area) + "\n")
94+
95+
def render(self, mode="ascii"):
96+
if mode == "human":
97+
self._render_human()
98+
elif mode == "ascii":
99+
self._render_ascii()
100+
else:
101+
raise Exception("Not Implemented!")
102+
103+
def line_generator(self):
104+
line = [0] * self.display_width
105+
if random() > (1 - self.density):
106+
ran = random()
107+
if ran < .6:
108+
v = 1
109+
elif ran < .9:
110+
v = 2
111+
else:
112+
v = 3
113+
114+
line[randint(0, self.display_width - 1)] = v
115+
return line
116+
117+
def reset(self):
118+
for _ in range(self.display_height):
119+
self.display.append(self.line_generator())
120+
121+
self.v_position = ceil(self.display_width / 2)
122+
state = self.display, self.v_position
123+
return state
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Learner: Nguyen Truong Thinh
2+
# Contact me: [email protected] || +84393280504
3+
#
4+
# Topic: Reinforcement Learning (RL): Coin Catcher RL problem
5+
# Ref: https://www.pygame.org/docs
6+
7+
import os
8+
9+
import pygame as game
10+
11+
# Setting up the colors
12+
BLACK = (0, 0, 0)
13+
RED = (255, 0, 0)
14+
GREEN = (0, 255, 0)
15+
BLUE = (0, 0, 255)
16+
WHITE = (255, 255, 255)
17+
18+
19+
class CoinCatcherScreen:
20+
"""
21+
Drawing the game screen
22+
"""
23+
img_path = os.path.dirname(os.path.realpath(__file__)) + '/airplane.png'
24+
rct_size = 50
25+
26+
def __init__(self, h=5, w=5) -> None:
27+
game.init()
28+
self.h = h
29+
self.w = w
30+
scr_size = ((w + 2) * self.rct_size, (h + 3) * self.rct_size)
31+
self.scr = game.display.set_mode(scr_size, 0, 32)
32+
self.img = game.image.load(CoinCatcherScreen.img_path)
33+
self.font = game.font.SysFont("arial", 48)
34+
game.display.set_caption('Catch Coins Game')
35+
super().__init__()
36+
37+
def plus(self):
38+
self.scr.fill(GREEN)
39+
game.display.update()
40+
41+
def update(self, display, plane_pos, total_score):
42+
self.scr.fill(WHITE)
43+
for i in range(len(display)):
44+
line = display[len(display) - 1 - i]
45+
for j in range(len(line)):
46+
p = line[j]
47+
if p > 0:
48+
coord = ((j + 1) * self.rct_size, (i + 1) * self.rct_size)
49+
self.scr.blit(self.font.render(str(p), True, BLACK), coord)
50+
51+
self.scr.blit(self.font.render(f'Total: {total_score}', True, BLACK), (10, 10))
52+
self.scr.blit(self.img, (self.rct_size * plane_pos + 30, (self.h + 1) * self.rct_size))
53+
game.display.update()
54+
55+
@classmethod
56+
def render(cls, display, plane_pos, total_score):
57+
scr = CoinCatcherScreen()
58+
scr.update(display, plane_pos, total_score)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Learner: Nguyen Truong Thinh
2+
# Contact me: [email protected] || +84393280504
3+
#
4+
# Topic: Reinforcement Learning (RL): Coin Catcher RL problem
5+
6+
import random
7+
from coin_catcher_rl_problem import CoinCatcherEnv
8+
from ml.rl_in_robotics.utility import gym_rl_custom_tasks
9+
10+
# Hyperparameters we can adjust
11+
EPISODES = 1000
12+
MODE = "human" # "ascii"
13+
SLEEP = .3 # 1
14+
15+
env = CoinCatcherEnv()
16+
17+
# -1: left
18+
# 0: stay
19+
# +1: right
20+
action_space = [-1, 0, 1]
21+
action = random.choice(action_space)
22+
23+
gym_rl_custom_tasks(env, EPISODES, action, MODE, SLEEP)

ml/rl_in_robotics/gym_environments/right_mountain_car.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from ml.rl_in_robotics.utility import gym_rl_tasks, init_environment
1010

1111
# Hyperparameters we can adjust
12-
EPISODES = 30
12+
EPISODES = 10
1313

1414
env = init_environment("MountainCar-v0")
1515

3.68 MB
Loading

ml/rl_in_robotics/utility.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,39 @@
99
from time import sleep
1010

1111
import gym
12+
import pygame
13+
14+
15+
def gym_rl_custom_tasks(env, episodes, action, mode, duration):
16+
"""
17+
Unifying all RL tasks by Gym toolkit with seeding
18+
"""
19+
init_reset_environment(env)
20+
21+
gym_customize_tasks(env, episodes, action, mode, duration)
22+
23+
env.close()
24+
25+
26+
def init_reset_environment(env):
27+
env = env
28+
init_state = env.reset()
29+
return env
30+
31+
32+
def gym_customize_tasks(env, episodes, action, mode="human", duration=1):
33+
"""
34+
Unifying RL tasks by Gym toolkit
35+
"""
36+
for _ in range(episodes):
37+
if mode == "human":
38+
env.render(mode)
39+
else:
40+
env.render()
41+
42+
action = action
43+
state, reward, done, debug = env.step(action)
44+
sleep(duration)
1245

1346

1447
def gym_rl_tasks_with_seed(env, episodes, action):
@@ -59,6 +92,21 @@ def init_environment(rl_problem):
5992
return env
6093

6194

95+
# Utilities function
96+
97+
98+
def get_system_fonts():
99+
"""
100+
Get all available fonts.
101+
:return: A list of all the fonts available on the system.
102+
"""
103+
fonts = pygame.font.get_fonts()
104+
index = 1
105+
for font in fonts:
106+
print(f'{index}. {font},')
107+
index += 1
108+
109+
62110
def check_list_of_environments():
63111
"""
64112
Get a list of all pre-installed environments of Gym Toolkit

0 commit comments

Comments
 (0)