Browse Source

+ beepers

draw_beeper(), generate_random_beeper(), generate_outofbounds_random_beeper(), generate_random_asset(), generate_outofbounds_random_asset()
tBKwtWS 1 month ago
parent
commit
8cef4ec470
1 changed files with 190 additions and 50 deletions
  1. 190 50
      karel_asset.py

+ 190 - 50
karel_asset.py

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