Skip to content

Commit 3fcc1b2

Browse files
authored
Create xy_vacuum_environment.py
1 parent 5ea213d commit 3fcc1b2

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import os.path
2+
from tkinter import *
3+
4+
from agents import *
5+
6+
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
7+
8+
9+
class Gui(VacuumEnvironment):
10+
"""This is a two-dimensional GUI environment. Each location may be
11+
dirty, clean or can have a wall. The user can change these at each step.
12+
"""
13+
xi, yi = (0, 0)
14+
perceptible_distance = 1
15+
16+
def __init__(self, root, width=7, height=7, elements=None):
17+
super().__init__(width, height)
18+
if elements is None:
19+
elements = ['D', 'W']
20+
self.root = root
21+
self.create_frames()
22+
self.create_buttons()
23+
self.create_walls()
24+
self.elements = elements
25+
26+
def create_frames(self):
27+
"""Adds frames to the GUI environment."""
28+
self.frames = []
29+
for _ in range(7):
30+
frame = Frame(self.root, bg='grey')
31+
frame.pack(side='bottom')
32+
self.frames.append(frame)
33+
34+
def create_buttons(self):
35+
"""Adds buttons to the respective frames in the GUI."""
36+
self.buttons = []
37+
for frame in self.frames:
38+
button_row = []
39+
for _ in range(7):
40+
button = Button(frame, height=3, width=5, padx=2, pady=2)
41+
button.config(
42+
command=lambda btn=button: self.display_element(btn))
43+
button.pack(side='left')
44+
button_row.append(button)
45+
self.buttons.append(button_row)
46+
47+
def create_walls(self):
48+
"""Creates the outer boundary walls which do not move."""
49+
for row, button_row in enumerate(self.buttons):
50+
if row == 0 or row == len(self.buttons) - 1:
51+
for button in button_row:
52+
button.config(text='W', state='disabled',
53+
disabledforeground='black')
54+
else:
55+
button_row[0].config(
56+
text='W', state='disabled', disabledforeground='black')
57+
button_row[len(button_row) - 1].config(text='W',
58+
state='disabled', disabledforeground='black')
59+
# Place the agent in the centre of the grid.
60+
self.buttons[3][3].config(
61+
text='A', state='disabled', disabledforeground='black')
62+
63+
def display_element(self, button):
64+
"""Show the things on the GUI."""
65+
txt = button['text']
66+
if txt != 'A':
67+
if txt == 'W':
68+
button.config(text='D')
69+
elif txt == 'D':
70+
button.config(text='')
71+
elif txt == '':
72+
button.config(text='W')
73+
74+
def execute_action(self, agent, action):
75+
"""Determines the action the agent performs."""
76+
xi, yi = (self.xi, self.yi)
77+
if action == 'Suck':
78+
dirt_list = self.list_things_at(agent.location, Dirt)
79+
if dirt_list:
80+
dirt = dirt_list[0]
81+
agent.performance += 100
82+
self.delete_thing(dirt)
83+
self.buttons[xi][yi].config(text='', state='normal')
84+
xf, yf = agent.location
85+
self.buttons[xf][yf].config(
86+
text='A', state='disabled', disabledforeground='black')
87+
88+
else:
89+
agent.bump = False
90+
if action == 'TurnRight':
91+
agent.direction += Direction.R
92+
elif action == 'TurnLeft':
93+
agent.direction += Direction.L
94+
elif action == 'Forward':
95+
agent.bump = self.move_to(agent, agent.direction.move_forward(agent.location))
96+
if not agent.bump:
97+
self.buttons[xi][yi].config(text='', state='normal')
98+
xf, yf = agent.location
99+
self.buttons[xf][yf].config(
100+
text='A', state='disabled', disabledforeground='black')
101+
102+
if action != 'NoOp':
103+
agent.performance -= 1
104+
105+
def read_env(self):
106+
"""Reads the current state of the GUI environment."""
107+
for i, btn_row in enumerate(self.buttons):
108+
for j, btn in enumerate(btn_row):
109+
if (i != 0 and i != len(self.buttons) - 1) and (j != 0 and j != len(btn_row) - 1):
110+
agt_loc = self.agents[0].location
111+
if self.some_things_at((i, j)) and (i, j) != agt_loc:
112+
for thing in self.list_things_at((i, j)):
113+
self.delete_thing(thing)
114+
if btn['text'] == self.elements[0]:
115+
self.add_thing(Dirt(), (i, j))
116+
elif btn['text'] == self.elements[1]:
117+
self.add_thing(Wall(), (i, j))
118+
119+
def update_env(self):
120+
"""Updates the GUI environment according to the current state."""
121+
self.read_env()
122+
agt = self.agents[0]
123+
previous_agent_location = agt.location
124+
self.xi, self.yi = previous_agent_location
125+
self.step()
126+
xf, yf = agt.location
127+
128+
def reset_env(self, agt):
129+
"""Resets the GUI environment to the initial state."""
130+
self.read_env()
131+
for i, btn_row in enumerate(self.buttons):
132+
for j, btn in enumerate(btn_row):
133+
if (i != 0 and i != len(self.buttons) - 1) and (j != 0 and j != len(btn_row) - 1):
134+
if self.some_things_at((i, j)):
135+
for thing in self.list_things_at((i, j)):
136+
self.delete_thing(thing)
137+
btn.config(text='', state='normal')
138+
self.add_thing(agt, location=(3, 3))
139+
self.buttons[3][3].config(
140+
text='A', state='disabled', disabledforeground='black')
141+
142+
143+
def XYReflexAgentProgram(percept):
144+
"""The modified SimpleReflexAgentProgram for the GUI environment."""
145+
status, bump = percept
146+
if status == 'Dirty':
147+
return 'Suck'
148+
149+
if bump == 'Bump':
150+
value = random.choice((1, 2))
151+
else:
152+
value = random.choice((1, 2, 3, 4)) # 1-right, 2-left, others-forward
153+
154+
if value == 1:
155+
return 'TurnRight'
156+
elif value == 2:
157+
return 'TurnLeft'
158+
else:
159+
return 'Forward'
160+
161+
162+
class XYReflexAgent(Agent):
163+
"""The modified SimpleReflexAgent for the GUI environment."""
164+
165+
def __init__(self, program=None):
166+
super().__init__(program)
167+
self.location = (3, 3)
168+
self.direction = Direction("up")
169+
170+
171+
# TODO: Check the coordinate system.
172+
# TODO: Give manual choice for agent's location.
173+
if __name__ == "__main__":
174+
root = Tk()
175+
root.title("Vacuum Environment")
176+
root.geometry("420x440")
177+
root.resizable(0, 0)
178+
frame = Frame(root, bg='black')
179+
reset_button = Button(frame, text='Reset', height=2,
180+
width=6, padx=2, pady=2)
181+
reset_button.pack(side='left')
182+
next_button = Button(frame, text='Next', height=2,
183+
width=6, padx=2, pady=2)
184+
next_button.pack(side='left')
185+
frame.pack(side='bottom')
186+
env = Gui(root)
187+
agt = XYReflexAgent(program=XYReflexAgentProgram)
188+
env.add_thing(agt, location=(3, 3))
189+
next_button.config(command=env.update_env)
190+
reset_button.config(command=lambda: env.reset_env(agt))
191+
root.mainloop()

0 commit comments

Comments
 (0)