tBKwtWS 1 місяць тому
батько
коміт
703c9abe17
1 змінених файлів з 232 додано та 618 видалено
  1. 232 618
      main.py

+ 232 - 618
main.py

@@ -1,634 +1,248 @@
-import operator
-import logging
-import random
-
-# Logging to console
-logger = logging.getLogger(__name__)
-logging.basicConfig(level=logging.INFO) # Set loglevel to INFO or higher to prevent console spam.
-
-
-"""
-Helper functions
+from karel.stanfordkarel import *
 """
-# Return some hex colour
-"""
-Waiting for Stanford to fix a bug in the environment
-CIP bug: https://codeinplace.stanford.edu/cip6/report?post=ac7c4ffd-1f90-475a-b4ee-2e5b73c5348f
+Inspired by John Conways "Game of Life" and "Biogenesis" by Joan Queralt Molina.
 
-from matplotlib import colors
-import decimal
+The three phases of life start with Karel seeding a few fountains of youth, represented by beepers on black patches of "land".
 
-def get_random_colour():
-    return decimal.Decimal(random.randrange(0,10)/10), decimal.Decimal(random.randrange(0,10)/10), decimal.Decimal(random.randrange(0,10)/10)
+Than the circle of life commences, with Karel being the fickle hand of god that moves randomly over the board,
+at certain times deciding to bless or smite the life she passes.
+Being blessed means growth and changing colour, while smiting leads to permanent death or being composted.
+After several steps of growth it is possible for life to reproduce, and spread to other patches of land;
+possible in the process overwhelming neighboring life.
 
-colour = colors.rgb2hex((get_random_colour()))
-background = colors.rgb2hex((get_random_colour()))
-"""
-def generate_random_colour():
-    rgb_values = [random.randrange(256), random.randrange(256), random.randrange(256)]
-    hex_colours = [hex(value)[2:] for value in rgb_values]  # Strip the '0x' prefix
-    for i in range(len(hex_colours)):
-        if len(str(hex_colours[i])) == 1:
-            hex_colours[i] = f"0{hex_colours[i]}"
-    return '#' + ''.join(hex_colours)
+After an ungodly amount of divine acts, in the final ascension phase, the fountains are collected by their creatress Karel;
+leaving only the result of the onslaught of the competition that is life.
 
+TIP: Run at top speed to spare your own life from wasting away...
 """
-Karel functions
-"""
-# Erase a passed Karel from the canvas
-def erase_asset(asset):
-    canvas = asset[1][0]
 
-    for shape in asset[0].values():
-        canvas.delete(shape)
-    logger.debug(f"Erased asset: {asset}")
-
-# Move a passed Karel on the canvas
-"""
-Waiting for Stanford to fix a bug in the environment
-CIP bug: https://codeinplace.stanford.edu/cip6/report?post=7043ece9-7653-4e39-8a63-5f4544b1d74b
-
-def move_karel(canvas, karel, x, y):
-    for shape in karel[0].values():
-        canvas.move(shape, x, y)
-    logger.debug(f"Moved: {karel} by {x} horizontally, {y} vertically")
-"""
-# Move a passed Karel relative to previous position
-def relative_move_asset(asset, x:int=0, y:int=0):
-    # Update coordinates in list
-    asset[1][1] += x
-    asset[1][2] += y
-
-    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])
-
-    logger.debug(f"Moved: {asset} by {x} horizontally, {y} vertically, to {new_asset}")
-    return new_asset
-
-# Move a passed Karel in relation to her orientation
-def orientation_move_asset(asset, direction, amount):
-    # Direction translation
-    if asset[1][4].startswith("east"):
-        if direction.lower() == "forward" or direction.lower() == "front":
-            asset[1][1] += amount
-        if direction.lower() == "left":
-            asset[1][2] -= amount
-        if direction.lower() == "right":
-            asset[1][2] += amount
-        if direction.lower() == "backward" or direction.lower() == "back":
-            asset[1][1] -= amount
-    if asset[1][4].startswith("north"):
-        if direction.lower() == "forward" or direction.lower() == "front":
-            asset[1][2] -= amount
-        if direction.lower() == "left":
-            asset[1][1] -= amount
-        if direction.lower() == "right":
-            asset[1][1] += amount
-        if direction.lower() == "backward" or direction.lower() == "back":
-            asset[1][2] += amount
-    if asset[1][4].startswith("west"):
-        if direction.lower() == "forward" or direction.lower() == "front":
-            asset[1][1] -= amount
-        if direction.lower() == "left":
-            asset[1][2] += amount
-        if direction.lower() == "right":
-            asset[1][2] -= amount
-        if direction.lower() == "backward" or direction.lower() == "back":
-            asset[1][1] += amount
-    if asset[1][4].startswith("south"):
-        if direction.lower() == "forward" or direction.lower() == "front":
-            asset[1][2] += amount
-        if direction.lower() == "left":
-            asset[1][1] += amount
-        if direction.lower() == "right":
-            asset[1][1] -= amount
-        if direction.lower() == "backward" or direction.lower() == "back":
-            asset[1][2] -= amount
-
-    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])
-
-    logger.debug(f"Moved: {asset} {direction} by {amount} as {new_karel}")
-    return new_karel
-
-# Move a passed Karel to new coordinates
-def absolute_move_karel(asset, x:int=0, y:int=0):
-    # Update coordinates in list
-    asset[1][1] = x
-    asset[1][2] = y
-
-    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])
-
-    logger.debug(f"Moved: {asset} by {x} horizontally, {y} vertically, to {new_karel}")
-    return new_karel
-
-# Change the orientation of a passed Karel
-def rotate_karel(asset, direction):
-    # Relative turn
-    if direction == "right" or direction == "left":
-        # East
-        if asset[1][4] == "east":
-            if direction == "right":
-                asset[1][4] = "south"
-            if direction == "left":
-                asset[1][4] = "north"
-        elif asset[1][4] == "east-flipped":
-            if direction == "right":
-                asset[1][4] = "south-flipped"
-            if direction == "left":
-                asset[1][4] = "north-flipped"
-
-        # North
-        elif asset[1][4] == "north":
-            if direction == "right":
-                asset[1][4] = "east"
-            if direction == "left":
-                asset[1][4] = "west"
-        elif asset[1][4] == "north-flipped":
-            if direction == "right":
-                asset[1][4] = "east-flipped"
-            if direction == "left":
-                asset[1][4] = "west-flipped"
-
-        # West
-        elif asset[1][4] == "west":
-            if direction == "right":
-                asset[1][4] = "north"
-            if direction == "left":
-                asset[1][4] = "soutch"
-        elif asset[1][4] == "west-flipped":
-            if direction == "right":
-                asset[1][4] = "north-flipped"
-            if direction == "left":
-                asset[1][4] = "south-flipped"
-
-        # South
-        elif asset[1][4] == "south":
-            if direction == "right":
-                asset[1][4] = "west"
-            if direction == "left":
-                asset[1][4] = "east"
-        elif asset[1][4] == "north-flipped":
-            if direction == "right":
-                asset[1][4] = "west-flipped"
-            if direction == "left":
-                asset[1][4] = "east-flipped"
-    
-    # Absolute rotation
-    elif direction == "east" or direction == "east-flipped" or direction == "north" or direction == "north-flipped" or direction == "west" or direction == "west-flipped" or direction == "south" or direction == "south-flipped":
-        asset[1][4] = direction
+## Helper functions:
+# Turn left trice:
+def turn_right():
+    for i in range(3):  
+        turn_left()
+
+# Keep moving while not blocked:
+def move_till_end():
+    while front_is_clear():
+        move()
+
+# 20% chance to move:
+def perhaps_move():
+    if random(0.2): 
+        move()
+
+def pick_if_present():
+    if beepers_present():
+        pick_beeper()
+
+# Move to next row:
+def next_row():
+    # Turn west:
+    if facing_east():
+        turn_left()
+        if front_is_clear():
+            move()
+            turn_left()
+        
+    # Turn east
+    else:   # Facing west
+        turn_right()
+        if front_is_clear():
+            move()
+            turn_right()
+
+def wall_check():
+    if front_is_blocked():    # End of row
+        next_row()
+
+# Move to southeast corner:
+def genesis_position():
+    # Move south:
+    while not_facing_south():
+        turn_left()
+    move_till_end()
+
+    # Move west:
+    while not_facing_west():
+        turn_left()
+    move_till_end()
+
+    # Turn:
+    while not_facing_east():
+        turn_left()
+
+# Do not face walls, and sometimes change direction:
+def orient():
+
+    # Perhaps turn
+    if random(0.1): # 10% chance to turn
+        if random(0.5): # 50% chance to go right or left
+            turn_left()
+        else:
+            turn_right()
     
-    # Syntax error
-    else:
-        logger.error(f"Invalid rotation direction: {direction}")
+    # Make sure not to face an obstruction
+    while front_is_blocked():
+        turn_left()
 
-    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])
 
-    logger.debug(f"Rotated Karel: {asset} by {direction} as {asset[1][4]} to {new_karel}")
-    return new_karel
+## Main functions:
+# According to biologists, the sole goal of life.
+def reproduce():
+    move()
+    if no_beepers_present():    # Unseeded tile
 
-# Recolour a passed Karel on the canvas
-"""
-Waiting for Stanford to fix a bug in the environment
-CIP bug: https://codeinplace.stanford.edu/cip6/report?post=c36ed931-3019-4830-8ba6-655c1a513471
-
-def recolour_karel(canvas, karel, colour:str="black", background:str="white"):
-    for name, shape in karel[0].items():   # Loop over Karel dict
-        if name.endswith("_fill"): # Background shape
-            canvas.set_color(shape, background)
-            canvas.set_outline_color(shape, background)
-        else:   # Foreground shape
-            if name.endswith("_line") or name.endswith("_corner") or name == "mouth":
-                canvas.set_color(shape, colour)
-            elif name == "eye":
-                #canvas.set_color(shape, "transparent")
-                canvas.set_outline_color(shape, colour)
-            else:   # Legs and feet
-                canvas.set_color(shape, colour)
-                canvas.set_outline_color(shape, colour)
-"""
-def recolour_asset(asset, colour:str="black", background:str="white"):
-    # Random colours
-    if colour == "random":
-        colour = generate_random_colour()
-    if background == "random":
-        background = generate_random_colour()
-
-    # Update colours in list
-    asset[1][5] = colour
-    asset[1][6] = background
-
-    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])
-
-    logger.debug(f"Re-coloured Karel: {asset} with {colour} and {background} to {new_karel}")
-    return new_karel
-
-# Draw a Karel
-def draw_karel(
-        canvas,
-        centre_x:int=25,
-        centre_y:int=25,
-        size:int=50,
-        orientation:str="east",
-        colour:str="black",
-        background:str="white",
-        transparent:bool=False
-    ):
+        # Seed life
+        paint_corner("black")   
+        put_beeper()
     
-    # Body constants
-    MARGIN = size / 8
-    APPENDAGE_MULTIPLIER = MARGIN * 0.6
+    else:   # Seeded tile
+        if random(0.5): # 50% chance
+            paint_corner("orange")  # Accelerate life or overtake another life.
+        else:   # Remainder 50% chance
+            die()   # Compete, cancelling each other out.
     
-    # Random colours
-    if colour == "random":
-        colour = generate_random_colour()
-    if background == "random":
-        background = generate_random_colour()
-
-    ''' Flipper case
-    In order to be able to flip Karel, the operands in the forumlas must be able to switch around.
-    Orientations are in relation to the centre of Karel.
-    '''
-    match orientation.lower():     
-        case "east" | "south-flipped":
-            left_operand = operator.sub     # Left / Top
-            top_operand = operator.sub      # Top / Left
-            right_operand = operator.add    # Right / Bottom
-            bottom_operand = operator.add   # Bottom / Right
-        case "east-flipped" | "south":
-            left_operand = operator.sub     # Left / Top
-            top_operand = operator.add      # Bottom / Right
-            right_operand = operator.add    # Right / Bottom
-            bottom_operand = operator.sub   # Top / Left
-        case "west" | "north-flipped":
-            left_operand = operator.add     # Right 
-            top_operand = operator.add      # Bottom
-            right_operand = operator.sub    # Left
-            bottom_operand = operator.sub   # Top
-        case "west-flipped" | "north":
-            left_operand = operator.add     # Right / Bottom
-            top_operand = operator.sub      # Top / Left
-            right_operand = operator.sub    # Left / Top
-            bottom_operand = operator.add   # Bottom / Right
+    # Never leave Karel facign a wall:
+    orient()
+
+def die():
+    # Permanent death:
+    if random(0.2): # 20% chance
+        paint_corner("white")
+        pick_beeper()
     
-    # Coords case
-    if orientation.lower() == "north" or orientation.lower() == "north-flipped" or orientation.lower() == "south" or orientation.lower() == "south-flipped":
-        temp_x = centre_x
-        centre_x = centre_y
-        centre_y = temp_x
-        #pass
-
-    # Borders
-    left = left_operand(centre_x, size / 2)
-    top = top_operand(centre_y, size / 2)
-    right = right_operand(centre_x, size / 2)
-    bottom = bottom_operand(centre_y, size / 2)
-    margin = size / 8
-    appendage_multiplier = margin * 0.6
-
-    # Body borders
-    body_left = left_operand(centre_x, size / 3)
-    body_top = top
-    body_right = right_operand(centre_x, size / 3)
-    body_bottom = bottom_operand(centre_y, size / 2.6)
-    eye_left = right_operand(body_left, margin)
-    eye_top = bottom_operand(body_top, margin)
-    eye_right = left_operand(body_right, margin)
-    eye_bottom = top_operand(body_bottom, margin * 2)
-
-    # Body coordinates
-    top_left_corner = body_left, body_top
-    left_diagonal_top = body_left, top_operand(body_bottom, margin)
-    left_diagonal_bottom = eye_left, body_bottom
-    right_diagonal_top = eye_right, body_top
-    right_diagonal_bottom = body_right, bottom_operand(body_top, margin)
-    bottom_right_corner = body_right, body_bottom
-    mouth_left_corner = centre_x, bottom_operand(eye_bottom, margin)
-    mouth_right_corner = eye_right, mouth_left_corner[1]
-
-    # Left appendage borders
-    leftLeg_left = left_operand(body_left, margin)
-    leftLeg_top = eye_bottom
-    leftLeg_right = body_left
-    leftLeg_bottom = bottom_operand(leftLeg_top, appendage_multiplier)
-    leftFoot_left = leftLeg_left
-    leftFoot_top = leftLeg_bottom
-    leftFoot_right = right_operand(leftLeg_left, appendage_multiplier)
-    leftFoot_bottom = bottom_operand(leftFoot_top, appendage_multiplier)
-
-    # Right appendage borders
-    rightLeg_left = centre_x
-    rightLeg_top = body_bottom
-    rightLeg_right = right_operand(rightLeg_left, appendage_multiplier)
-    rightLeg_bottom = bottom
-    rightFoot_left = rightLeg_right
-    rightFoot_top = top_operand(bottom, appendage_multiplier)
-    rigthFoot_right = right_operand(rightLeg_right, appendage_multiplier)
-    rightFoot_bottom = bottom
-
-    # Draw Karel
-    match orientation.lower():
-        case "east" | "east-flipped" | "west" | "west-flipped":
-            if not transparent:
-                # Meat
-                top_fill = canvas.create_rectangle(
-                    top_left_corner[0],
-                    top_left_corner[1],
-                    right_diagonal_top[0],
-                    eye_top,
-                    background,
-                    background
-                )
-                top_corner_fill = canvas.create_polygon(
-                    right_diagonal_top[0] , right_diagonal_top[1],
-                    right_diagonal_bottom[0], right_diagonal_bottom[1],
-                    eye_right, eye_top,
-                    color = background,
-                    outline = background
-                )
-                left_fill = canvas.create_rectangle(
-                    top_left_corner[0],
-                    eye_top,
-                    eye_left,
-                    left_diagonal_top[1],
-                    background,
-                    background
-                )
-                right_fill = canvas.create_rectangle(
-                    eye_right,
-                    eye_top,
-                    right_diagonal_bottom[0],
-                    eye_bottom,
-                    background,
-                    background
-                )
-                bottom_fill = canvas.create_rectangle(
-                    eye_left,
-                    eye_bottom,
-                    bottom_right_corner[0],
-                    bottom_right_corner[1],
-                    background,
-                    background
-                )
-                bottom_corner_fill = canvas.create_polygon(
-                    left_diagonal_top[0], left_diagonal_top[1],
-                    eye_left, left_diagonal_top[1],
-                    left_diagonal_bottom[0], left_diagonal_bottom[1],
-                    color = background,
-                    outline = background
-                )
+    # Seed for rebirth | Composting:
+    else:   # Remainder 80% chance
+        paint_corner("black")
+
+# Grow, die or reproduce:
+def paint_life():
+    # In reverse order, since "elif" is not available.
+    #if corner_color_is("pink"):    # End condition, but "quit()" is not available
+    #    quit()
+
+    if corner_color_is("cyan"):
+        if random(0.8):    # 80% chance
+            paint_corner("pink")    # Evolve
             
-            # Outlines
-            top_line = canvas.create_line(
-                top_left_corner[0], top_left_corner[1],
-                right_diagonal_top[0], right_diagonal_top[1],
-                colour
-            )
-            top_corner = canvas.create_line(
-                right_diagonal_top[0], right_diagonal_top[1],
-                right_diagonal_bottom[0], right_diagonal_bottom[1],
-                colour
-            )
-            left_line = canvas.create_line(
-                top_left_corner[0], top_left_corner[1],
-                left_diagonal_top[0], left_diagonal_top[1],
-                colour
-            )
-            bottom_corner = canvas.create_line(
-                left_diagonal_top[0], left_diagonal_top[1],
-                left_diagonal_bottom[0], left_diagonal_bottom[1],
-                colour
-            )
-            bottom_line = canvas.create_line(
-                left_diagonal_bottom[0], left_diagonal_bottom[1],
-                bottom_right_corner[0], bottom_right_corner[1],
-                colour
-            )
-            right_line = canvas.create_line(
-                right_diagonal_bottom[0], right_diagonal_bottom[1],
-                bottom_right_corner[0], bottom_right_corner[1],
-                colour
-            )
-            left_leg = canvas.create_rectangle(
-                leftLeg_left,
-                leftLeg_top,
-                leftLeg_right,
-                leftLeg_bottom,
-                colour,
-                colour
-            )
-            left_foot = canvas.create_rectangle(
-                leftFoot_left,
-                leftFoot_top,
-                leftFoot_right,
-                leftFoot_bottom,
-                colour,
-                colour
-            )
-            right_leg = canvas.create_rectangle(
-                rightLeg_left,
-                rightLeg_top,
-                rightLeg_right,
-                rightLeg_bottom,
-                colour,
-                colour
-            )
-            right_foot = canvas.create_rectangle(
-                rightFoot_left,
-                rightFoot_top,
-                rigthFoot_right,
-                rightFoot_bottom,
-                colour,
-                colour
-            )
-            eye = canvas.create_rectangle(
-                eye_left,
-                eye_top,
-                eye_right,
-                eye_bottom,
-                "transparent",
-                colour,
-            )
-            mouth = canvas.create_line(
-                mouth_left_corner[0], mouth_left_corner[1],
-                mouth_right_corner[0], mouth_right_corner[1],
-                colour
-            )
-        
-        case "north" | "north-flipped" | "south" | "south-flipped":
-            if not transparent:
-                # Meat
-                top_fill = canvas.create_rectangle(
-
-                    top_left_corner[1],             # Top Y
-                    right_diagonal_top[0],          # Right X
-                    eye_top,                        # Bottom Y
-                    top_left_corner[0],             # Left X
-                    background,
-                    background
-                )
-                top_corner_fill = canvas.create_polygon(
-                    right_diagonal_top[1] , right_diagonal_top[0],
-                    right_diagonal_bottom[1], right_diagonal_bottom[0],
-                    eye_top, eye_right,
-                    color = background,
-                    outline = background
-                )
-                left_fill = canvas.create_rectangle(
-                    
-                    eye_top,
-                    eye_left,
-                    left_diagonal_top[1],
-                    top_left_corner[0],
-                    background,
-                    background
-                )
-                right_fill = canvas.create_rectangle(
-                    
-                    eye_top,
-                    right_diagonal_bottom[0],
-                    eye_bottom,
-                    eye_right,
-                    background,
-                    background
-                )
-                bottom_fill = canvas.create_rectangle(
-                    
-                    eye_bottom,
-                    bottom_right_corner[0],
-                    bottom_right_corner[1],
-                    eye_left,
-                    background,
-                    background
-                )
-                bottom_corner_fill = canvas.create_polygon(
-                    left_diagonal_top[1], left_diagonal_top[0],
-                    left_diagonal_top[1], eye_left,
-                    left_diagonal_bottom[1], left_diagonal_bottom[0],
-                    color = background,
-                    outline = background
-                )
+            # Reproduce quadrice:
+            for i in range(4):
+                reproduce()
             
-            # Outlines
-            top_line = canvas.create_line(
-                top_left_corner[1], top_left_corner[0],
-                right_diagonal_top[1], right_diagonal_top[0],
-                colour
-            )
-            top_corner = canvas.create_line(
-                right_diagonal_top[1], right_diagonal_top[0],
-                right_diagonal_bottom[1], right_diagonal_bottom[0],
-                colour
-            )
-            left_line = canvas.create_line(
-                top_left_corner[1], top_left_corner[0],
-                left_diagonal_top[1], left_diagonal_top[0],
-                colour
-            )
-            bottom_corner = canvas.create_line(
-                left_diagonal_top[1], left_diagonal_top[0],
-                left_diagonal_bottom[1], left_diagonal_bottom[0],
-                colour
-            )
-            bottom_line = canvas.create_line(
-                left_diagonal_bottom[1], left_diagonal_bottom[0],
-                bottom_right_corner[1], bottom_right_corner[0],
-                colour
-            )
-            right_line = canvas.create_line(
-                right_diagonal_bottom[1], right_diagonal_bottom[0],
-                bottom_right_corner[1], bottom_right_corner[0],
-                colour
-            )
-            left_leg = canvas.create_rectangle(
-                leftLeg_top,
-                leftLeg_right,
-                leftLeg_bottom,
-                leftLeg_left,
-                colour,
-                colour
-            )
-            left_foot = canvas.create_rectangle(
-                leftFoot_top,
-                leftFoot_right,
-                leftFoot_bottom,
-                leftFoot_left,
-                colour,
-                colour
-            )
-            right_leg = canvas.create_rectangle(
-                rightLeg_top,
-                rightLeg_right,
-                rightLeg_bottom,
-                rightLeg_left,
-                colour,
-                colour
-            )
-            right_foot = canvas.create_rectangle(
-                rightFoot_top,
-                rigthFoot_right,
-                rightFoot_bottom,
-                rightFoot_left,
-                colour,
-                colour
-            )
-            eye = canvas.create_rectangle(
-                eye_top,
-                eye_right,
-                eye_bottom,
-                eye_left,
-                "transparent",
-                colour,
-            )
-            mouth = canvas.create_line(
-                mouth_left_corner[1], mouth_left_corner[0],
-                mouth_right_corner[1], mouth_right_corner[0],
-                colour
-            )
-
-    # Return each object so it can later be altered/destroyed
-    if transparent:
-        shapes = {
-            "top_line": top_line,
-            "top_corner": top_corner,
-            "left_line": left_line,
-            "bottom_corner": bottom_corner,
-            "bottom_line": bottom_line,
-            "right_line": right_line,
-            "left_leg": left_leg,
-            "left_foot": left_foot,
-            "right_foot": right_foot,
-            "right_leg": right_leg,
-            "right_foot": right_foot,
-            "eye": eye,
-            "mouth": mouth
-        }
-    else:   # Not transparent
-        shapes = {
-            "top_fill": top_fill,
-            "top_corner_fill": top_corner_fill,
-            "left_fill": left_fill,
-            "right_fill": right_fill,
-            "bottom_fill": bottom_fill,
-            "bottom_corner_fill": bottom_corner_fill,
-            "top_line": top_line,
-            "top_corner": top_corner,
-            "left_line": left_line,
-            "bottom_corner": bottom_corner,
-            "bottom_line": bottom_line,
-            "right_line": right_line,
-            "left_leg": left_leg,
-            "left_foot": left_foot,
-            "right_foot": right_foot,
-            "right_leg": right_leg,
-            "right_foot": right_foot,
-            "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]
+        else:   # Remainder 20% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("green"):
+        if random(0.8):    # 80% chance
+            paint_corner("cyan")    # Evolve
+
+            # Reproduce thrice:
+            for i in range(3):
+                reproduce()
+            
+        else:   # Remainder 20% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("blue"):
+        if random(0.8):    # 80% chance
+            paint_corner("green")   # Evolve
+
+            # Reproduce twice:
+            for i in range(2):
+                reproduce()
+            
+        else:   # Remainder 20% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("olive"):
+        if random(0.6):    # 60% chance
+            paint_corner("blue")    # Evolve
+            reproduce()
+        else:   # Remainder 40% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("orange"):
+        if random(0.5):    # 50% chance
+            paint_corner("olive")    # Evolve
+        else:   # Remainder 50% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("red"):  # Adolescence
+        if random(0.4):    # 40% chance
+            paint_corner("orange")  # Evolve
+        else:   # Remainder 60% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("purple"):   # Early stage
+        if random(0.3):    # 30% chance
+            paint_corner("red") # Evolve
+        else:  # Remainder 70% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("brown"):    # Infancy
+        if random(0.2):    # 20% chance
+            paint_corner("purple")  # Evolve
+        else:   # Remainder 80% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("gray"): # Prenatal
+        if random(0.1):    # 10% chance
+            paint_corner("brown")   # Evolve
+        else:   # Remainder 90% chance
+            if random(0.2): # 20% chance of death, else stagnation.
+                die()   # Death
+    if corner_color_is("black"):    # Field is seeded
+        paint_corner("gray")    # Sprout life
+
+# Prepare the world with habitable patches.
+def seed():
+    genesis_position()
+
+    while front_is_clear():
+
+        # Perhaps seed a fountain of life
+        if random(0.3): # 30% chance
+            paint_corner("black")
+            put_beeper()
+        
+        move()
+        wall_check()
+    
+    # Face away from the wall
+    orient()
+
+# The circle of life                
+def life_loop():
+    for i in range(9999):   # Incubation period
+
+        # Path of god, played by karel:
+        for step in range(9):  # Travel period
+            perhaps_move()
+            orient()
+        paint_life()
+
+# End the game neatly:
+def ascension():
+    genesis_position()
+
+    # Remove seeds
+    while front_is_clear():
+        pick_if_present()
+        move()
+        pick_if_present()
+        wall_check()
+    
+    genesis_position()
+
+
+ # The three phases of life:
+def main():
+    seed()
+    life_loop()
+    ascension() # The script should not run forever, making some unintended biblical implications...
+
+
+# don't change this code
+if __name__ == '__main__':
+    main()