feat: added live coding features - obstacles and half-directions.
This commit is contained in:
parent
aff508d835
commit
9abe516ec7
|
@ -0,0 +1,11 @@
|
||||||
|
BLOCK 2,2
|
||||||
|
BLOCK 3,2
|
||||||
|
PLACE 1,2,EAST
|
||||||
|
BLOCK 1,2
|
||||||
|
MOVE
|
||||||
|
LEFT
|
||||||
|
MOVE
|
||||||
|
REPORT
|
||||||
|
PLACE 3,1
|
||||||
|
MOVE
|
||||||
|
REPORT
|
|
@ -0,0 +1,6 @@
|
||||||
|
BLOCK 0,4,ghjghjhg,hjghjgjhdts
|
||||||
|
PLACE 1,2,NORTHWEST
|
||||||
|
MOVE
|
||||||
|
RIGHT
|
||||||
|
MOVE
|
||||||
|
REPORT
|
|
@ -26,12 +26,17 @@ class Robot:
|
||||||
# Directions ordered such that adding 1 corresponds to RIGHT turn
|
# Directions ordered such that adding 1 corresponds to RIGHT turn
|
||||||
DIRECTIONS = {
|
DIRECTIONS = {
|
||||||
"NORTH": 0,
|
"NORTH": 0,
|
||||||
"EAST": 1,
|
"NORTHEAST": 1,
|
||||||
"SOUTH": 2,
|
"EAST": 2,
|
||||||
"WEST": 3,
|
"SOUTHEAST": 3,
|
||||||
|
"SOUTH": 4,
|
||||||
|
"SOUTHWEST": 5,
|
||||||
|
"WEST": 6,
|
||||||
|
"NORTHWEST": 7
|
||||||
}
|
}
|
||||||
|
|
||||||
VALID_COMMANDS = [
|
VALID_COMMANDS = [
|
||||||
|
"BLOCK",
|
||||||
"PLACE",
|
"PLACE",
|
||||||
"MOVE",
|
"MOVE",
|
||||||
"LEFT",
|
"LEFT",
|
||||||
|
@ -45,9 +50,13 @@ class Robot:
|
||||||
# positive y is EAST)
|
# positive y is EAST)
|
||||||
_MOVEMENT_VECTORS = {
|
_MOVEMENT_VECTORS = {
|
||||||
0: {"x": 0, "y": 1},
|
0: {"x": 0, "y": 1},
|
||||||
1: {"x": 1, "y": 0},
|
1: {"x": 1, "y": 1},
|
||||||
2: {"x": 0, "y": -1},
|
2: {"x": 1, "y": 0},
|
||||||
3: {"x": -1, "y": 0},
|
3: {"x": 1, "y": -1},
|
||||||
|
4: {"x": 0, "y": -1},
|
||||||
|
5: {"x": -1, "y": -1},
|
||||||
|
6: {"x": -1, "y": 0},
|
||||||
|
7: {"x": -1, "y": 1},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, max_x: int = DEFAULT_MAX_X, max_y: int = DEFAULT_MAX_Y):
|
def __init__(self, max_x: int = DEFAULT_MAX_X, max_y: int = DEFAULT_MAX_Y):
|
||||||
|
@ -79,6 +88,8 @@ class Robot:
|
||||||
self._position_y = None
|
self._position_y = None
|
||||||
self._direction = None
|
self._direction = None
|
||||||
|
|
||||||
|
self._blocks = []
|
||||||
|
|
||||||
def valid_position(self, x: int, y: int) -> bool:
|
def valid_position(self, x: int, y: int) -> bool:
|
||||||
"""
|
"""
|
||||||
Calculates whether the given coordinates are valid for the limits set
|
Calculates whether the given coordinates are valid for the limits set
|
||||||
|
@ -95,7 +106,18 @@ class Robot:
|
||||||
bool: True if given coordinates are within limits, otherwise False.
|
bool: True if given coordinates are within limits, otherwise False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return x >= 0 and y >= 0 and x <= self._max_x and y <= self._max_y
|
within_limits = x >= 0 and y >= 0 and x <= self._max_x and y <= self._max_y
|
||||||
|
on_block = (x, y) in self._blocks
|
||||||
|
# print(self._blocks)
|
||||||
|
# print(within_limits)
|
||||||
|
# print(on_block)
|
||||||
|
return within_limits and not on_block
|
||||||
|
|
||||||
|
def add_block(self, x: int, y: int):
|
||||||
|
if x == self._position_x and y == self._position_y:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._blocks.append((x, y))
|
||||||
|
|
||||||
def is_initialized(self):
|
def is_initialized(self):
|
||||||
"""
|
"""
|
||||||
|
@ -159,8 +181,10 @@ class Robot:
|
||||||
|
|
||||||
# Must be careful not to make any state changes until all inputs
|
# Must be careful not to make any state changes until all inputs
|
||||||
# have been validated
|
# have been validated
|
||||||
|
# print('Checking position...')
|
||||||
if not self.valid_position(position_x, position_y):
|
if not self.valid_position(position_x, position_y):
|
||||||
return
|
return
|
||||||
|
# print('Position check passed.')
|
||||||
|
|
||||||
if direction_name is not None:
|
if direction_name is not None:
|
||||||
direction_name = direction_name.upper()
|
direction_name = direction_name.upper()
|
||||||
|
@ -220,7 +244,7 @@ class Robot:
|
||||||
if not self.is_initialized():
|
if not self.is_initialized():
|
||||||
return
|
return
|
||||||
|
|
||||||
self._direction = (self._direction - 1) % 4
|
self._direction = (self._direction - 1) % len(Robot.DIRECTIONS)
|
||||||
|
|
||||||
def rotate_right(self):
|
def rotate_right(self):
|
||||||
"""
|
"""
|
||||||
|
@ -234,7 +258,7 @@ class Robot:
|
||||||
if not self.is_initialized():
|
if not self.is_initialized():
|
||||||
return
|
return
|
||||||
|
|
||||||
self._direction = (self._direction + 1) % 4
|
self._direction = (self._direction + 1) % len(Robot.DIRECTIONS)
|
||||||
|
|
||||||
def interpret_command(self, command: str):
|
def interpret_command(self, command: str):
|
||||||
"""
|
"""
|
||||||
|
@ -252,11 +276,32 @@ class Robot:
|
||||||
command = command.upper()
|
command = command.upper()
|
||||||
command_tokens = [x.strip() for x in command.split(' ') if len(x) > 0]
|
command_tokens = [x.strip() for x in command.split(' ') if len(x) > 0]
|
||||||
|
|
||||||
|
# This is not strictly necessary as case
|
||||||
if len(command_tokens) == 0 or not command_tokens[0] in \
|
if len(command_tokens) == 0 or not command_tokens[0] in \
|
||||||
Robot.VALID_COMMANDS:
|
Robot.VALID_COMMANDS:
|
||||||
return
|
return
|
||||||
|
|
||||||
match command_tokens[0]:
|
match command_tokens[0]:
|
||||||
|
case "BLOCK":
|
||||||
|
# print('Found block...')
|
||||||
|
try:
|
||||||
|
if len(command_tokens) < 2:
|
||||||
|
# print('Insufficient tokens...')
|
||||||
|
return
|
||||||
|
|
||||||
|
parameter_tokens = [x.strip() for x in command_tokens[1].split(',')]
|
||||||
|
|
||||||
|
if len(parameter_tokens) < 2:
|
||||||
|
# print('Insufficient parameters...')
|
||||||
|
return
|
||||||
|
block_x = int(parameter_tokens[0])
|
||||||
|
block_y = int(parameter_tokens[1])
|
||||||
|
|
||||||
|
# print("Adding block: {} {}".format(block_x, block_y))
|
||||||
|
self.add_block(block_x, block_y)
|
||||||
|
except ValueError as ve:
|
||||||
|
# print('Integer parsing error...')
|
||||||
|
return
|
||||||
case "PLACE":
|
case "PLACE":
|
||||||
try:
|
try:
|
||||||
# Must have parameters
|
# Must have parameters
|
||||||
|
@ -276,6 +321,7 @@ class Robot:
|
||||||
# Direction parameter is optional on second and subsequent
|
# Direction parameter is optional on second and subsequent
|
||||||
# placements. The place() method accounts for an absent
|
# placements. The place() method accounts for an absent
|
||||||
# direction on first call and fails silently.
|
# direction on first call and fails silently.
|
||||||
|
# print("PLACE command parsed: {}, {}".format(place_x, place_y))
|
||||||
if len(parameter_tokens) > 2:
|
if len(parameter_tokens) > 2:
|
||||||
place_direction = parameter_tokens[2]
|
place_direction = parameter_tokens[2]
|
||||||
self.place(place_x, place_y, place_direction)
|
self.place(place_x, place_y, place_direction)
|
||||||
|
@ -305,8 +351,9 @@ class Robot:
|
||||||
if not self.is_initialized():
|
if not self.is_initialized():
|
||||||
return "Uninitialized"
|
return "Uninitialized"
|
||||||
|
|
||||||
return "{},{},{}".format(
|
return "{},{},{} | BLOCKS : {}".format(
|
||||||
self._position_x,
|
self._position_x,
|
||||||
self._position_y,
|
self._position_y,
|
||||||
self.get_direction()
|
self.get_direction(),
|
||||||
|
":".join([str(x) for x in self._blocks])
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import toyrobot
|
import toyrobot
|
||||||
|
|
||||||
|
|
||||||
def feed_file(filename: str, robot: toyrobot.Robot):
|
def feed_file(filename: str, robot: toyrobot.Robot):
|
||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
|
@ -9,6 +10,7 @@ def feed_file(filename: str, robot: toyrobot.Robot):
|
||||||
print(line)
|
print(line)
|
||||||
robot.interpret_command(line)
|
robot.interpret_command(line)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print('a)')
|
print('a)')
|
||||||
feed_file('example_a.txt', toyrobot.Robot())
|
feed_file('example_a.txt', toyrobot.Robot())
|
||||||
|
@ -26,5 +28,12 @@ def main():
|
||||||
feed_file('example_d.txt', toyrobot.Robot())
|
feed_file('example_d.txt', toyrobot.Robot())
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
print('e)')
|
||||||
|
feed_file('example_e.txt', toyrobot.Robot())
|
||||||
|
print()
|
||||||
|
|
||||||
|
print('f)')
|
||||||
|
feed_file('example_f.txt', toyrobot.Robot())
|
||||||
|
print()
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in New Issue