Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aimacode
GitHub Repository: aimacode/aima-python
Path: blob/master/gui/xy_vacuum_environment.py
621 views
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()
192
193