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 = {
|
||||
"NORTH": 0,
|
||||
"EAST": 1,
|
||||
"SOUTH": 2,
|
||||
"WEST": 3,
|
||||
"NORTHEAST": 1,
|
||||
"EAST": 2,
|
||||
"SOUTHEAST": 3,
|
||||
"SOUTH": 4,
|
||||
"SOUTHWEST": 5,
|
||||
"WEST": 6,
|
||||
"NORTHWEST": 7
|
||||
}
|
||||
|
||||
VALID_COMMANDS = [
|
||||
"BLOCK",
|
||||
"PLACE",
|
||||
"MOVE",
|
||||
"LEFT",
|
||||
|
@ -45,9 +50,13 @@ class Robot:
|
|||
# positive y is EAST)
|
||||
_MOVEMENT_VECTORS = {
|
||||
0: {"x": 0, "y": 1},
|
||||
1: {"x": 1, "y": 0},
|
||||
2: {"x": 0, "y": -1},
|
||||
3: {"x": -1, "y": 0},
|
||||
1: {"x": 1, "y": 1},
|
||||
2: {"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):
|
||||
|
@ -79,6 +88,8 @@ class Robot:
|
|||
self._position_y = None
|
||||
self._direction = None
|
||||
|
||||
self._blocks = []
|
||||
|
||||
def valid_position(self, x: int, y: int) -> bool:
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
|
||||
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):
|
||||
"""
|
||||
|
@ -159,8 +181,10 @@ class Robot:
|
|||
|
||||
# Must be careful not to make any state changes until all inputs
|
||||
# have been validated
|
||||
# print('Checking position...')
|
||||
if not self.valid_position(position_x, position_y):
|
||||
return
|
||||
# print('Position check passed.')
|
||||
|
||||
if direction_name is not None:
|
||||
direction_name = direction_name.upper()
|
||||
|
@ -220,7 +244,7 @@ class Robot:
|
|||
if not self.is_initialized():
|
||||
return
|
||||
|
||||
self._direction = (self._direction - 1) % 4
|
||||
self._direction = (self._direction - 1) % len(Robot.DIRECTIONS)
|
||||
|
||||
def rotate_right(self):
|
||||
"""
|
||||
|
@ -234,7 +258,7 @@ class Robot:
|
|||
if not self.is_initialized():
|
||||
return
|
||||
|
||||
self._direction = (self._direction + 1) % 4
|
||||
self._direction = (self._direction + 1) % len(Robot.DIRECTIONS)
|
||||
|
||||
def interpret_command(self, command: str):
|
||||
"""
|
||||
|
@ -252,11 +276,32 @@ class Robot:
|
|||
command = command.upper()
|
||||
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 \
|
||||
Robot.VALID_COMMANDS:
|
||||
return
|
||||
|
||||
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":
|
||||
try:
|
||||
# Must have parameters
|
||||
|
@ -276,6 +321,7 @@ class Robot:
|
|||
# Direction parameter is optional on second and subsequent
|
||||
# placements. The place() method accounts for an absent
|
||||
# direction on first call and fails silently.
|
||||
# print("PLACE command parsed: {}, {}".format(place_x, place_y))
|
||||
if len(parameter_tokens) > 2:
|
||||
place_direction = parameter_tokens[2]
|
||||
self.place(place_x, place_y, place_direction)
|
||||
|
@ -305,8 +351,9 @@ class Robot:
|
|||
if not self.is_initialized():
|
||||
return "Uninitialized"
|
||||
|
||||
return "{},{},{}".format(
|
||||
return "{},{},{} | BLOCKS : {}".format(
|
||||
self._position_x,
|
||||
self._position_y,
|
||||
self.get_direction()
|
||||
self.get_direction(),
|
||||
":".join([str(x) for x in self._blocks])
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import toyrobot
|
||||
|
||||
|
||||
def feed_file(filename: str, robot: toyrobot.Robot):
|
||||
with open(filename) as f:
|
||||
for line in f:
|
||||
|
@ -9,6 +10,7 @@ def feed_file(filename: str, robot: toyrobot.Robot):
|
|||
print(line)
|
||||
robot.interpret_command(line)
|
||||
|
||||
|
||||
def main():
|
||||
print('a)')
|
||||
feed_file('example_a.txt', toyrobot.Robot())
|
||||
|
@ -26,5 +28,12 @@ def main():
|
|||
feed_file('example_d.txt', toyrobot.Robot())
|
||||
print()
|
||||
|
||||
print('e)')
|
||||
feed_file('example_e.txt', toyrobot.Robot())
|
||||
print()
|
||||
|
||||
print('f)')
|
||||
feed_file('example_f.txt', toyrobot.Robot())
|
||||
print()
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue