-
Notifications
You must be signed in to change notification settings - Fork 0
/
Map.py
231 lines (205 loc) · 8.68 KB
/
Map.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import numpy as np
np.set_printoptions(threshold=np.inf, linewidth=300)
import pandas as pd
import time
from PIL import Image
class Map_Obj():
def __init__(self, task=1):
self.start_pos, self.goal_pos, self.end_goal_pos, self.path_to_map = self.fill_critical_positions(task)
self.int_map, self.str_map = self.read_map(self.path_to_map)
self.tmp_cell_value = self.get_cell_value(self.goal_pos)
self.set_cell_value(self.start_pos, ' S ')
self.set_cell_value(self.goal_pos, ' G ')
self.tick_counter = 0
#self.set_start_pos_str_marker(start_pos, self.str_map)
#self.set_goal_pos_str_marker(goal_pos, self.str_map)
def read_map(self, path):
"""
Reads maps specified in path from file, converts them to a numpy array and a string array. Then replaces
specific values in the string array with predefined values more suitable for printing.
:param path: Path to .csv maps
:return: the integer map and string map
"""
# Read map from provided csv file
df = pd.read_csv(path, index_col=None, header=None)#,error_bad_lines=False)
# Convert pandas dataframe to numpy array
data = df.values
# Convert numpy array to string to make it more human readable
data_str = data.astype(str)
# Replace numeric values with more human readable symbols
data_str[data_str == '-1'] = ' # '
data_str[data_str == '1'] = ' . '
data_str[data_str == '2'] = ' , '
data_str[data_str == '3'] = ' : '
data_str[data_str == '4'] = ' ; '
return data, data_str
def fill_critical_positions(self, task):
"""
Fills the important positions for the current task. Given the task, the path to the correct map is set, and the
start, goal and eventual end_goal positions are set.
:param task: The task we are currently solving
:return: Start position, Initial goal position, End goal position, path to map for current task.
"""
if task == 1:
start_pos = [27, 18]
goal_pos = [40, 32]
end_goal_pos = goal_pos
path_to_map = 'Samfundet_map_1.csv'
elif task == 2:
start_pos = [40, 32]
goal_pos = [8, 5]
end_goal_pos = goal_pos
path_to_map = 'Samfundet_map_1.csv'
elif task == 3:
start_pos = [28, 32]
goal_pos = [6, 32]
end_goal_pos = goal_pos
path_to_map = 'Samfundet_map_2.csv'
elif task == 4:
start_pos = [28, 32]
goal_pos = [6, 32]
end_goal_pos = goal_pos
path_to_map = 'Samfundet_map_Edgar_full.csv'
elif task == 5:
start_pos = [14, 18]
goal_pos = [6, 36]
end_goal_pos = [6, 7]
path_to_map = 'Samfundet_map_2.csv'
return start_pos, goal_pos, end_goal_pos, path_to_map
def get_cell_value(self, pos):
return self.int_map[pos[0], pos[1]]
def get_goal_pos(self):
return self.goal_pos
def get_start_pos(self):
return self.start_pos
def get_end_goal_pos(self):
return self.end_goal_pos
def get_maps(self):
# Return the map in both int and string format
return self.int_map, self.str_map
def move_goal_pos(self, pos):
"""
Moves the goal position towards end_goal position. Moves the current goal position and replaces its previous
position with the previous values for correct printing.
:param pos: position to move current_goal to
:return: nothing.
"""
tmp_val = self.tmp_cell_value
tmp_pos = self.goal_pos
self.tmp_cell_value = self.get_cell_value(pos)
self.goal_pos = [pos[0], pos[1]]
self.replace_map_values(tmp_pos, tmp_val, self.goal_pos)
def set_cell_value(self, pos, value, str_map = True):
if str_map:
self.str_map[pos[0], pos[1]] = value
else:
self.int_map[pos[0], pos[1]] = value
def print_map(self, map_to_print):
# For every column in provided map, print it
for column in map_to_print:
print(column)
def pick_move(self):
"""
A function used for moving the goal position. It moves the current goal position towards the end_goal position.
:return: Next coordinates for the goal position.
"""
if self.goal_pos[0] < self.end_goal_pos[0]:
return [self.goal_pos[0]+1, self.goal_pos[1]]
elif self.goal_pos[0] > self.end_goal_pos[0]:
return [self.goal_pos[0]-1, self.goal_pos[1]]
elif self.goal_pos[1] < self.end_goal_pos[1]:
return [self.goal_pos[0], self.goal_pos[1]+1]
else:
return [self.goal_pos[0], self.goal_pos[1]-1]
def replace_map_values(self, pos, value, goal_pos):
"""
Replaces the values in the two maps at the coordinates provided with the values provided.
:param pos: coordinates for where we want to change the values
:param value: the value we want to change to
:param goal_pos: The coordinate of the current goal
:return: nothing.
"""
if value == 1:
str_value = ' . '
elif value == 2:
str_value = ' , '
elif value == 3:
str_value = ' : '
elif value == 4:
str_value = ' ; '
else:
str_value = str(value)
self.int_map[pos[0]][pos[1]] = value
self.str_map[pos[0]][pos[1]] = str_value
self.str_map[goal_pos[0], goal_pos[1]] = ' G '
def tick(self):
"""
Moves the current goal position every 4th call if current goal position is not already at the end_goal position.
:return: current goal position
"""
# For every 4th call, actually do something
if self.tick_counter % 4 == 0:
# The end_goal_pos is not set
if self.end_goal_pos is None:
return self.goal_pos
# The current goal is at the end_goal
elif self.end_goal_pos == self.goal_pos:
return self.goal_pos
else:
# Move current goal position
move = self.pick_move()
self.move_goal_pos(move)
#print(self.goal_pos)
self.tick_counter +=1
return self.goal_pos
def set_start_pos_str_marker(self, start_pos, map):
# Attempt to set the start position on the map
if self.int_map[start_pos[0]][start_pos[1]] == -1:
self.print_map(self.str_map)
print('The selected start position, '+str(start_pos) + ' is not a valid position on the current map.')
exit()
else:
map[start_pos[0]][start_pos[1]] = ' S '
def set_goal_pos_str_marker(self, goal_pos, map):
# Attempt to set the goal position on the map
if self.int_map[goal_pos[0]][goal_pos[1]] == -1:
self.print_map(self.str_map)
print('The selected goal position, '+ str(goal_pos) + ' is not a valid position on the current map.')
exit()
else:
map[goal_pos[0]][goal_pos[1]] = ' G '
def show_map(self, map=None):
"""
A function used to draw the map as an image and show it.
:param map: map to use
:return: nothing.
"""
# If a map is provided, set the goal and start positions
if map is not None:
self.set_start_pos_str_marker(self.start_pos, map)
self.set_goal_pos_str_marker(self.goal_pos, map)
# If no map is provided, use string_map
else:
map = self.str_map
# Define width and height of image
width = map.shape[1]
height = map.shape[0]
# Define scale of the image
scale = 20
# Create an all-yellow image
image = Image.new('RGB', (width * scale, height * scale), (255, 255, 0))
# Load image
pixels = image.load()
# Define what colors to give to different values of the string map (undefined values will remain yellow, this is
# how the yellow path is painted)
colors = {' # ': (255, 0, 0), ' . ': (215, 215, 215), ' , ': (166, 166, 166), ' : ': (96, 96, 96),
' ; ': (36, 36, 36), ' S ': (255, 0, 255), ' G ': (0, 128, 255)}
# Go through image and set pixel color for every position
for y in range(height):
for x in range(width):
if map[y][x] not in colors: continue
for i in range(scale):
for j in range(scale):
pixels[x * scale + i, y * scale + j] = colors[map[y][x]]
# Show image
image.show()