def three_tone(img: Cimpl.Image, col1: str, col2: str,
               col3: str) -> Cimpl.Image:
    """
    Returns a three-toned Cimpl.Image object, based on the colors col1, col2
    and col3 passed. 
    
    img is the original Cimpl.Image object passed
    
    col1, col2 and col3 are the strings representing the image.
    
    >>>three_tone(Cimpl.load_image("image.jpg"), "col1", "col2", "col3")
    returns image with a three toned filter

    """
    COLORS = {
        "black": Cimpl.Color(0, 0, 0),  # black
        "white": Cimpl.Color(255, 255, 255),  # white
        "gray": Cimpl.Color(128, 128, 128),  # gray
        "red": Cimpl.Color(255, 0, 0),  # red
        "lime": Cimpl.Color(0, 255, 0),  # lime
        "blue": Cimpl.Color(0, 0, 255),  # blue
        "yellow": Cimpl.Color(255, 255, 0),  # yellow
        "cyan": Cimpl.Color(0, 255, 255),  # cyan
        "magenta": Cimpl.Color(255, 0, 255)  # magenta
    }

    newimage = Cimpl.copy(img)

    for x, y, (r, g, b) in img:
        bright = _brightness(r, g, b)

        if bright <= 84:
            # if brightness is below or equal to 84 change the color at said pixel to
            # col1
            Cimpl.set_color(newimage, x, y, COLORS[col1])

        elif 84 < bright <= 170:
            # if brightness is below or equal to 170 but higher than 84 change the
            # color at said pixel to col2
            Cimpl.set_color(newimage, x, y, COLORS[col2])

        else:
            # else set color to col3
            Cimpl.set_color(newimage, x, y, COLORS[col3])

    return newimage
def set_pixel(image: Cimpl.Image, res: int, color: Cimpl.Color, x: int, y: int, state: bool) -> None:
    '''Modifies the input image by filling in a block (i.e. 15x15) with a color 
    determined by a provided state; white (dead) or black (live). The origin 
    is specified using the "true" coordinates (given by real_coords).
    '''
    if state:
        stateColor = color
    else:
        stateColor = Cimpl.Color(255,255,255)
        
    for yPix in range(res - 1):
        for xPix in range (res - 1):
            Cimpl.set_color(image, x + xPix, y + yPix, stateColor)
def two_tone(img: Cimpl.Image, col1: str, col2: str) -> Cimpl.Image:
    """
    Author: Himanshu Singh
    Returns a two-toned Cimpl.Image object, based on the colors col1 and col2
    passed. 
    
    img is the original Cimpl.Image object passed
    
    col1 and col2 are the strings representing the image.
    
    >>>two_tone(Cimpl.load_image("image.jpg"), "col1", "col2")
    returns image with a two toned filter

    """

    COLORS = {
        "black": Cimpl.Color(0, 0, 0),  # black
        "white": Cimpl.Color(255, 255, 255),  # white
        "gray": Cimpl.Color(128, 128, 128),  # gray
        "red": Cimpl.Color(255, 0, 0),  # red
        "lime": Cimpl.Color(0, 255, 0),  # lime
        "blue": Cimpl.Color(0, 0, 255),  # blue
        "yellow": Cimpl.Color(255, 255, 0),  # yellow
        "cyan": Cimpl.Color(0, 255, 255),  # cyan
        "magenta": Cimpl.Color(255, 0, 255)  # magenta
    }

    # image = load_image(FILENAME)
    newimage = Cimpl.copy(img)

    for x, y, (r, g, b) in img:
        bright = _brightness(r, g, b)

        if bright <= 127:
            # if calculated brightness at said pixel is below 127 set color to col[1]
            black = Cimpl.create_color(0, 0, 0)
            Cimpl.set_color(newimage, x, y, COLORS[col1])

        else:
            # else set color to col2 at said pixel
            Cimpl.set_color(newimage, x, y, COLORS[col2])

    return newimage
def create_empty_board(res: int, wBlocks: int, hBlocks: int) -> Tuple[Cimpl.Image, List[list]]:
    '''Returns an empty grid (board) as well as a list of all starting states 
    (dead).
    '''
    width, height = real_coords(res, wBlocks, hBlocks)    
    
    emptyBoard = Cimpl.create_image(width, height, Cimpl.Color(255,255,255))
    
    for pixel in emptyBoard:
        x, y = pixel[0], pixel[1]
        if x % res == 0 or y % res == 0:
            Cimpl.set_color(emptyBoard, x, y, Cimpl.Color(170,170,170))
    
    totalStateList = []
    
    for y in range(hBlocks):
        xStateList = []
        
        for x in range(wBlocks):
            xStateList += [0]
            
        totalStateList += [xStateList]
    
    return emptyBoard, totalStateList
                 '4':[EX_LRG_SPACESHIP,'Extra-Large'],
                 '5':[GLIDER_GUN, 'Glider Gun'],
                 },'Spaceships'],
           '4':[{'1':[R_PENTOMINO,'R-Pentomino (P??)'],
                 '2':[DIEHARD,'Diehard (P130)'],
                 '3':[ACORN,'Acorn (P5206)'],
                 }, 'Methuselahs']
           }

# DEFAULT VALUES --------------------------------------------------------------
width, height = DEF_WIDTH, DEF_HEIGHT = 40, 40
maxFrames = DEF_MAX_FRAMES = 50
res = DEF_RES = 16
duration = DEF_DURATION = 150
gifFile = DEF_GIF_FILE = "simulation.gif"
blockColor = DEF_BLOCK_COLOR = Cimpl.Color(0, 0, 0)

# LOADING ---------------------------------------------------------------------
print("Game of Life GIF Creator v1.0; by Julian Nicolai")

gameBoard, updatedStateList = create_empty_board(DEF_RES, DEF_WIDTH, DEF_HEIGHT)

# USER INTERFACE --------------------------------------------------------------
interfaceLoop = True
while interfaceLoop == True:
    print("\nTo go back, enter 'q' into the selection prompt.")
    print("Select one of the following options:")
    print("1: Place Item")
    print("2: Load/Save/Clear Board")
    print("3: Display Game Board")
    print("4: Run Simulation")