feat: added live coding features - obstacles and half-directions.

This commit is contained in:
Chris Davoren 2023-11-15 12:32:08 +10:00
parent aff508d835
commit 9abe516ec7
4 changed files with 87 additions and 14 deletions

11
example_e.txt Normal file
View File

@ -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

6
example_f.txt Normal file
View File

@ -0,0 +1,6 @@
BLOCK 0,4,ghjghjhg,hjghjgjhdts
PLACE 1,2,NORTHWEST
MOVE
RIGHT
MOVE
REPORT

View File

@ -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])
)

View File

@ -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()