-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmilestone.py
154 lines (121 loc) · 4.37 KB
/
milestone.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
import random
# Dimensions of the world
HEIGHT = 25
WIDTH = 25
# Limit of states
NUMSTATES = 5
POSSIBLE_SURROUNDINGS = ['xxxx', 'Nxxx', 'NExx', 'NxWx', 'xxxS', 'xExS', 'xxWS', 'xExx', 'xxWx']
class Program:
"""Run of a single picobot
"""
def __init__(self):
"""Creates a program with empty rules
"""
# Dictionary of conditions as keys and outcomes as values
self.rules = {}
def __repr__(self):
"""Prints the rules of the program
"""
unsorted_conditions = list(self.rules.keys())
sorted_conditions = sorted(unsorted_conditions)
formated_rules = ''
current_state = 0
for condition in sorted_conditions:
formated_rule = f'{condition[0]} {condition[1]} -> {self.rules[condition][0]} {self.rules[condition][1]} \n'
# Adds empty line transitioning before new state
if current_state != condition[0]:
current_state = condition[0]
formated_rule = '\n' + formated_rule
formated_rules += formated_rule
return formated_rules
def randomize(self):
"""Creates random set of legal rules
"""
for state in range(NUMSTATES):
for surroundings in POSSIBLE_SURROUNDINGS:
possible_steps = []
for step in 'NEWS':
if step not in surroundings:
possible_steps += [step]
condition = (state, surroundings)
outcome = (random.choice(possible_steps), random.randint(0, NUMSTATES - 1))
self.rules[condition] = outcome
def get_move(self, state, surroundings):
"""Returns a move that can be made if possible
"""
outcome = self.rules[(state, surroundings)]
return outcome
class World:
"""Environment of picobot
"""
def __init__(self, initial_row, initial_column, program):
"""Creates an environment for picobot and places picobot in it
"""
self.row = initial_row
self.column = initial_column
self.state = 0
self.program = program
self.room = [[' ']*WIDTH for row in range(HEIGHT)]
def __repr__(self):
"""Prints the environment of picobot
"""
w = ''
for col in range(WIDTH):
self.room[0][col] = '+'
self.room[WIDTH - 1][col] = '+'
for row in range(HEIGHT):
self.room[row][0] = '+'
self.room[row][HEIGHT - 1] = '+'
self.room[self.row][self.column] = 'P'
for row in range(HEIGHT):
for col in range(WIDTH):
w += self.room[row][col]
w += '\n'
return w
def get_current_surroundings(self):
"""Returns the surroundings of picobot at the instance
"""
if self.room[self.row - 1][self.column] != '+':
north = 'x'
else:
north = 'N'
if self.room[self.row + 1][self.column] != '+':
south = 'x'
else:
south = 'S'
if self.room[self.row][self.column - 1] != '+':
west = 'x'
else:
west = 'W'
if self.room[self.row][self.column + 1] != '+':
east = 'x'
else:
east = 'E'
current_surroundings = f'{north}{east}{west}{south}'
return current_surroundings
def step(self):
"""Makes one movement of picobot in the world
"""
surroundings = self.get_current_surroundings()
outcomes = self.program.get_move(self.state, surroundings)
#update previous position to o
self.room[self.row][self.column] = 'o'
self.state = outcomes[1]
# make new position P
if outcomes[0] == "N":
self.row = self.row - 1
self.room[self.row][self.column] = 'P'
if outcomes[0] == "S":
self.row = self.row + 1
self.room[self.row][self.column] = 'P'
if outcomes[0] == "W":
self.column = self.column - 1
self.room[self.row][self.column] = 'P'
if outcomes[0] == "E":
self.column = self.column + 1
self.room[self.row][self.column] = 'P'
def run(self, steps):
"""Executes specified number of steps for picobot
"""
for i in range(steps):
self.step()