|
|
@@ -42,6 +42,15 @@ def generate_random_colour():
|
|
|
logger.debug(f"Generated random colour: {colour}")
|
|
|
return colour
|
|
|
|
|
|
+# Base the size on the shortest pane
|
|
|
+def determine_max_size(canvas):
|
|
|
+ if canvas.width < canvas.height:
|
|
|
+ size = random.randint(1, canvas.width)
|
|
|
+ else:
|
|
|
+ size = random.randint(1, canvas.height)
|
|
|
+
|
|
|
+ return size
|
|
|
+
|
|
|
|
|
|
"""
|
|
|
Asset functions
|
|
|
@@ -66,7 +75,7 @@ def erase_asset(asset):
|
|
|
# Erase each shape of the asset
|
|
|
for shape in asset[0].values():
|
|
|
canvas.delete(shape)
|
|
|
- logger.debug(f"Erased asset: {asset}")
|
|
|
+ logger.debug(f"Erased {asset[2]} asset: {asset}")
|
|
|
|
|
|
# Move a passed Karel on the canvas
|
|
|
"""
|
|
|
@@ -86,16 +95,17 @@ def relative_move_asset(asset, x:int=0, y:int=0):
|
|
|
|
|
|
# Replace asset
|
|
|
erase_asset(asset)
|
|
|
- new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ match asset[2]:
|
|
|
+ case "karel": new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ case "beeper": new_asset = draw_beeper(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
|
|
|
- logger.debug(f"Moved {asset} by {x} horizontally, {y} vertically, to {new_asset}")
|
|
|
+ logger.debug(f"Moved {asset[2]} by {x} horizontally, {y} vertically: {new_asset}")
|
|
|
return new_asset
|
|
|
|
|
|
# Move a passed asset in relation to her orientation
|
|
|
def orientation_move_asset(asset, direction, amount):
|
|
|
# Direction translation
|
|
|
- # East
|
|
|
- if asset[1][4].startswith("east"):
|
|
|
+ if asset[1][4].startswith("east"): # East
|
|
|
if direction.lower() == "forward" or direction.lower() == "front":
|
|
|
asset[1][1] += amount
|
|
|
if direction.lower() == "left":
|
|
|
@@ -105,8 +115,7 @@ def orientation_move_asset(asset, direction, amount):
|
|
|
if direction.lower() == "backward" or direction.lower() == "back":
|
|
|
asset[1][1] -= amount
|
|
|
|
|
|
- # North
|
|
|
- if asset[1][4].startswith("north"):
|
|
|
+ if asset[1][4].startswith("north"): # North
|
|
|
if direction.lower() == "forward" or direction.lower() == "front":
|
|
|
asset[1][2] -= amount
|
|
|
if direction.lower() == "left":
|
|
|
@@ -116,8 +125,7 @@ def orientation_move_asset(asset, direction, amount):
|
|
|
if direction.lower() == "backward" or direction.lower() == "back":
|
|
|
asset[1][2] += amount
|
|
|
|
|
|
- # West
|
|
|
- if asset[1][4].startswith("west"):
|
|
|
+ if asset[1][4].startswith("west"): # West
|
|
|
if direction.lower() == "forward" or direction.lower() == "front":
|
|
|
asset[1][1] -= amount
|
|
|
if direction.lower() == "left":
|
|
|
@@ -127,8 +135,7 @@ def orientation_move_asset(asset, direction, amount):
|
|
|
if direction.lower() == "backward" or direction.lower() == "back":
|
|
|
asset[1][1] += amount
|
|
|
|
|
|
- # South
|
|
|
- if asset[1][4].startswith("south"):
|
|
|
+ if asset[1][4].startswith("south"): # South
|
|
|
if direction.lower() == "forward" or direction.lower() == "front":
|
|
|
asset[1][2] += amount
|
|
|
if direction.lower() == "left":
|
|
|
@@ -140,10 +147,12 @@ def orientation_move_asset(asset, direction, amount):
|
|
|
|
|
|
# Replace asset
|
|
|
erase_asset(asset)
|
|
|
- new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ match asset[2]:
|
|
|
+ case "karel": new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ case "beeper": new_asset = draw_beeper(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
|
|
|
- logger.debug(f"Moved: {asset} {direction} by {amount} as {new_karel}")
|
|
|
- return new_karel
|
|
|
+ logger.debug(f"Moved: {asset[2]} {direction} by {amount}: {new_asset}")
|
|
|
+ return new_asset
|
|
|
|
|
|
# Move a passed asset to new coordinates
|
|
|
def absolute_move_asset(asset, x, y):
|
|
|
@@ -153,17 +162,18 @@ def absolute_move_asset(asset, x, y):
|
|
|
|
|
|
# Replace asset
|
|
|
erase_asset(asset)
|
|
|
- new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ match asset[2]:
|
|
|
+ case "karel": new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ case "beeper": new_asset = draw_beeper(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
|
|
|
- logger.debug(f"Moved: {asset} by {x} horizontally, {y} vertically, to {new_karel}")
|
|
|
- return new_karel
|
|
|
+ logger.debug(f"Moved: {asset[2]} by {x} horizontally, {y} vertically: {new_asset}")
|
|
|
+ return new_asset
|
|
|
|
|
|
# Change the orientation of a passed asset
|
|
|
def rotate_asset(asset, direction):
|
|
|
# Relative turn
|
|
|
if direction == "right" or direction == "left":
|
|
|
- # East
|
|
|
- if asset[1][4] == "east":
|
|
|
+ if asset[1][4] == "east": # East
|
|
|
if direction == "right":
|
|
|
asset[1][4] = "south"
|
|
|
if direction == "left":
|
|
|
@@ -174,8 +184,7 @@ def rotate_asset(asset, direction):
|
|
|
if direction == "left":
|
|
|
asset[1][4] = "north-flipped"
|
|
|
|
|
|
- # North
|
|
|
- elif asset[1][4] == "north":
|
|
|
+ elif asset[1][4] == "north": # North
|
|
|
if direction == "right":
|
|
|
asset[1][4] = "east"
|
|
|
if direction == "left":
|
|
|
@@ -186,8 +195,7 @@ def rotate_asset(asset, direction):
|
|
|
if direction == "left":
|
|
|
asset[1][4] = "west-flipped"
|
|
|
|
|
|
- # West
|
|
|
- elif asset[1][4] == "west":
|
|
|
+ elif asset[1][4] == "west": # West
|
|
|
if direction == "right":
|
|
|
asset[1][4] = "north"
|
|
|
if direction == "left":
|
|
|
@@ -198,8 +206,7 @@ def rotate_asset(asset, direction):
|
|
|
if direction == "left":
|
|
|
asset[1][4] = "south-flipped"
|
|
|
|
|
|
- # South
|
|
|
- elif asset[1][4] == "south":
|
|
|
+ elif asset[1][4] == "south": # South
|
|
|
if direction == "right":
|
|
|
asset[1][4] = "west"
|
|
|
if direction == "left":
|
|
|
@@ -220,10 +227,12 @@ def rotate_asset(asset, direction):
|
|
|
|
|
|
# Repalce asset
|
|
|
erase_asset(asset)
|
|
|
- new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ match asset[2]:
|
|
|
+ case "karel": new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ case "beeper": new_asset = draw_beeper(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
|
|
|
- logger.debug(f"Rotated Karel: {asset} by {direction} as {asset[1][4]} to {new_karel}")
|
|
|
- return new_karel
|
|
|
+ logger.debug(f"Rotated {asset[2]} by {direction} as {asset[1][4]}: {new_asset}")
|
|
|
+ return new_asset
|
|
|
|
|
|
# Recolour a passed asset on the canvas
|
|
|
"""
|
|
|
@@ -258,25 +267,38 @@ def recolour_asset(asset, colour:str="black", background:str="white"):
|
|
|
|
|
|
# Replace asset
|
|
|
erase_asset(asset)
|
|
|
- new_karel = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ match asset[2]:
|
|
|
+ case "karel": new_asset = draw_karel(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
+ case "beeper": new_asset = draw_beeper(asset[1][0], asset[1][1], asset[1][2], asset[1][3], asset[1][4], asset[1][5], asset[1][6], asset[1][7])
|
|
|
|
|
|
- logger.debug(f"Re-coloured Karel: {asset} with {colour} and {background} to {new_karel}")
|
|
|
- return new_karel
|
|
|
+ logger.debug(f"Re-coloured Karel {asset[2]} with {colour} and {background}: {new_asset}")
|
|
|
+ return new_asset
|
|
|
|
|
|
# Draw a random asset on the canvas
|
|
|
-def generate_random_asset(canvas):
|
|
|
- pass
|
|
|
+def generate_random_asset(canvas, karel_prevelance:int="3"):
|
|
|
+ asset_type = random.randint(1, karel_prevelance)
|
|
|
+ match asset_type:
|
|
|
+ case 1: asset = generate_random_beeper(canvas)
|
|
|
+ case _: asset = generate_random_karel(canvas)
|
|
|
+
|
|
|
+ return asset
|
|
|
+
|
|
|
+# Draw a random asset outside the canvas
|
|
|
+def generate_outofbounds_random_asset(canvas, side:str, karel_prevelance:int=6):
|
|
|
+ asset_type = random.randint(1, karel_prevelance)
|
|
|
+ match asset_type:
|
|
|
+ case 1: asset = generate_outofbounds_random_beeper(canvas, side)
|
|
|
+ case _: asset = generate_outofbounds_random_karel(canvas, side)
|
|
|
+
|
|
|
+ return asset
|
|
|
+
|
|
|
|
|
|
"""
|
|
|
Karel functions
|
|
|
"""
|
|
|
# Draw a random Karel outside the canvas
|
|
|
-def generate_outofbounds_random_karel(canvas, side):
|
|
|
- # Base the size on the shortest pane
|
|
|
- if canvas.width < canvas.height:
|
|
|
- size = random.randint(1, canvas.width)
|
|
|
- else:
|
|
|
- size = random.randint(1, canvas.height)
|
|
|
+def generate_outofbounds_random_karel(canvas, side:str):
|
|
|
+ size = determine_max_size(canvas)
|
|
|
|
|
|
# Generate random coordinates (Outside the canvas geometry)
|
|
|
match side:
|
|
|
@@ -301,11 +323,7 @@ def generate_outofbounds_random_karel(canvas, side):
|
|
|
|
|
|
# Draw a random Karel on the canvas
|
|
|
def generate_random_karel(canvas):
|
|
|
- # Base the size on the shortest pane
|
|
|
- if canvas.width < canvas.height:
|
|
|
- size = random.randint(1, canvas.width)
|
|
|
- else:
|
|
|
- size = random.randint(1, canvas.height)
|
|
|
+ size = determine_max_size(canvas)
|
|
|
|
|
|
# Generate random values (Inside the canvas geometry)
|
|
|
centre_x = random.randint(int(size / 2), int(canvas.width - size / 2))
|
|
|
@@ -425,7 +443,7 @@ def draw_karel(
|
|
|
match orientation.lower():
|
|
|
case "east" | "east-flipped" | "west" | "west-flipped":
|
|
|
if not transparent:
|
|
|
- # Meat
|
|
|
+ # Draw meat
|
|
|
filler = canvas.create_polygon(
|
|
|
top_left_corner[0], top_left_corner[1],
|
|
|
right_diagonal_top[0], right_diagonal_top[1],
|
|
|
@@ -444,7 +462,7 @@ def draw_karel(
|
|
|
outline = background
|
|
|
)
|
|
|
|
|
|
- # Outlines
|
|
|
+ # Draw outlines
|
|
|
top_line = canvas.create_line(
|
|
|
top_left_corner[0], top_left_corner[1],
|
|
|
right_diagonal_top[0], right_diagonal_top[1],
|
|
|
@@ -512,7 +530,7 @@ def draw_karel(
|
|
|
# X and Y coordinates swapped for these orientations
|
|
|
case "north" | "north-flipped" | "south" | "south-flipped":
|
|
|
if not transparent:
|
|
|
- # Meat
|
|
|
+ # Draw meat
|
|
|
filler = canvas.create_polygon(
|
|
|
top_left_corner[1], top_left_corner[0],
|
|
|
right_diagonal_top[1], right_diagonal_top[0],
|
|
|
@@ -531,7 +549,7 @@ def draw_karel(
|
|
|
outline = background
|
|
|
)
|
|
|
|
|
|
- # Outlines
|
|
|
+ # Draw outlines
|
|
|
top_line = canvas.create_line(
|
|
|
top_left_corner[1], top_left_corner[0],
|
|
|
right_diagonal_top[1], right_diagonal_top[0],
|
|
|
@@ -624,7 +642,129 @@ def draw_karel(
|
|
|
"eye": eye,
|
|
|
"mouth": mouth
|
|
|
}
|
|
|
-
|
|
|
arguments = [canvas, centre_x, centre_y, size, orientation.lower(), colour, background, transparent]
|
|
|
logger.debug(f"Created Karel: {shapes, arguments}")
|
|
|
- return [shapes, arguments]
|
|
|
+ return [shapes, arguments, "karel"]
|
|
|
+
|
|
|
+"""
|
|
|
+Beeper functions
|
|
|
+
|
|
|
+Even though the beeper is symmetrical in two directions and rotating wont matter,
|
|
|
+it may be useful in case of moving in relation to orientation,
|
|
|
+perhaps in coordinated group movements with Karels.
|
|
|
+"""
|
|
|
+# Draw a random Karel outside the canvas
|
|
|
+def generate_outofbounds_random_beeper(canvas, side):
|
|
|
+ size = determine_max_size(canvas)
|
|
|
+
|
|
|
+ # Generate random coordinates (Outside the canvas geometry)
|
|
|
+ match side:
|
|
|
+ case "left":
|
|
|
+ centre_x = int(0 - size / 2 - 1)
|
|
|
+ centre_y = random.randint(int(size / 2), int(canvas.height - size / 2))
|
|
|
+ case "top":
|
|
|
+ centre_x = random.randint(int(size / 2), int(canvas.height - size / 2))
|
|
|
+ centre_y = int(0 - size / 2 - 1)
|
|
|
+ case "right":
|
|
|
+ centre_x = int(0 + size / 2 + 1)
|
|
|
+ centre_y = random.randint(int(size / 2), int(canvas.height - size / 2))
|
|
|
+ case "bottom":
|
|
|
+ centre_x = random.randint(int(size / 2), int(canvas.height - size / 2))
|
|
|
+ centre_y = int(0 + size / 2 + 1)
|
|
|
+
|
|
|
+ # Generate random values
|
|
|
+ orientation = random.choice(["east", "east-flipped", "north", "north-flipped", "west", "west-flipped", "south", "south-flipped"])
|
|
|
+ transparent = random.choice((True, False, False))
|
|
|
+
|
|
|
+ return draw_beeper(canvas, centre_x, centre_y, size, orientation, "random", "random", transparent)
|
|
|
+
|
|
|
+def generate_random_beeper(canvas):
|
|
|
+ size = determine_max_size(canvas)
|
|
|
+
|
|
|
+ # Generate random values (Inside the canvas geometry)
|
|
|
+ centre_x = random.randint(int(size / 2), int(canvas.width - size / 2))
|
|
|
+ centre_y = random.randint(int(size / 2), int(canvas.height - size / 2))
|
|
|
+ orientation = random.choice(["east", "east-flipped", "north", "north-flipped", "west", "west-flipped", "south", "south-flipped"])
|
|
|
+ transparent = random.choice((True, False, False, False))
|
|
|
+
|
|
|
+ return draw_beeper(canvas, centre_x, centre_y, size, orientation, "random", "random", transparent)
|
|
|
+
|
|
|
+def draw_beeper(
|
|
|
+ canvas,
|
|
|
+ centre_x:int=25,
|
|
|
+ centre_y:int=25,
|
|
|
+ size:int=50,
|
|
|
+ orientation:str="east",
|
|
|
+ colour:str="black",
|
|
|
+ background:str="cyan",
|
|
|
+ transparent:bool=False
|
|
|
+ ):
|
|
|
+
|
|
|
+ # Random colours
|
|
|
+ if colour == "random":
|
|
|
+ colour = generate_random_colour()
|
|
|
+ if background == "random":
|
|
|
+ background = generate_random_colour()
|
|
|
+
|
|
|
+ # Borders
|
|
|
+ left = centre_x - size / 2
|
|
|
+ top = centre_y - size / 2
|
|
|
+ right = centre_x + size / 2
|
|
|
+ bottom = centre_y + size / 2
|
|
|
+
|
|
|
+ # Body coordinates
|
|
|
+ top_corner = centre_x, top
|
|
|
+ left_corner = left, centre_y
|
|
|
+ bottom_corner = centre_x, bottom
|
|
|
+ right_corner = right, centre_y
|
|
|
+
|
|
|
+ """
|
|
|
+ # Draw outlines
|
|
|
+ north_west_line = canvas.create_line(
|
|
|
+ top_corner[0], top_corner[1],
|
|
|
+ left_corner[0], left_corner[1],
|
|
|
+ colour
|
|
|
+ )
|
|
|
+ south_west_line = canvas.create_line(
|
|
|
+ left_corner[0], left_corner[1],
|
|
|
+ bottom_corner[0], bottom_corner[1],
|
|
|
+ colour
|
|
|
+ )
|
|
|
+ south_east_line = canvas.create_line(
|
|
|
+ right_corner[0], right_corner[1],
|
|
|
+ bottom_corner[0], bottom_corner[1],
|
|
|
+ colour
|
|
|
+ )
|
|
|
+ north_east_line = canvas.create_line(
|
|
|
+ top_corner[0], top_corner[1],
|
|
|
+ right_corner[0], right_corner[1],
|
|
|
+ colour
|
|
|
+ )
|
|
|
+ """
|
|
|
+
|
|
|
+ # Draw insides
|
|
|
+ filler = canvas.create_polygon(
|
|
|
+ top_corner[0] + 1, top_corner[1] + 1,
|
|
|
+ right_corner[0] - 1, right_corner[1] - 1,
|
|
|
+ bottom_corner[0] - 1, bottom_corner[1] - 1,
|
|
|
+ left_corner[0] + 1, left_corner[1] + 1,
|
|
|
+ color = background,
|
|
|
+ outline = colour
|
|
|
+ )
|
|
|
+
|
|
|
+ # Return each object so it can later be altered/destroyed
|
|
|
+ """
|
|
|
+ shapes = {
|
|
|
+ "north_west_line": north_west_line,
|
|
|
+ "south_west_line": south_west_line,
|
|
|
+ "south_east_line": south_east_line,
|
|
|
+ "north_east_line": north_east_line,
|
|
|
+ "filler": filler
|
|
|
+ }
|
|
|
+ """
|
|
|
+ shapes = {
|
|
|
+ "filler": filler
|
|
|
+ }
|
|
|
+ arguments = [canvas, centre_x, centre_y, size, orientation.lower(), colour, background, transparent]
|
|
|
+ logger.debug(f"Created beeper: {shapes, arguments}")
|
|
|
+ return [shapes, arguments, "beeper"]
|