Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

def main(): opts = get_commandline_options() world = generate_world(opts) report

ID: 3744767 • Letter: D

Question

def main():
opts = get_commandline_options()
world = generate_world(opts)
report_options(opts)

blit(world, patterns.glider, 20, 20)

run_simulation(opts, world)


if __name__ == '__main__':
main()

def run_simulation(opts, world):
"""
Accepts: opts -- a populated command line options class instance
world -- a 2D world pixel buffer generated by generate_world()

Returns: (Nothing)

Description: This function generates the plot that we will use as a
rendering surfance. 'Living' cells (represented as 1s in
the 2D world matrix) will be rendered as black pixels and
'dead' cells (represetned as 0s) will be rendered as
white pixels. The method FuncAnimation() accepts 4
parameters: the figure, the frame update function, a
tuple containing arguments to pass to the update function,
and the frame update interval (in milliseconds). Once the
show() method is called to display the plot, the frame
update function will be called every 'interval'
milliseconds to update the plot image (img).
"""
if not world:
print ("The 'world' was never created. Exiting")
sys.exit()

fig = plt.figure()
img = plt.imshow(world, interpolation='none', cmap='Greys', vmax=1, vmin=0)
ani = animation.FuncAnimation(fig,
update_frame,
fargs=(opts, world, img),
interval=opts.framedelay)

plt.show()

Task 3: Implementing the Update Rule Once the world has been generated and you have added a pattern or two using the blitter, you are ready to start the simulation this is done by calling run.simulation) run simulation (opts, vorld) This function creates a figure using matplotlib and plots each pixel in the world grid using the imshow function. Subsequently, FuncAnimation) is called fig ing ani pit. figure() plt, imshow(world, interpolation«,none, cmaP",Greys, vmax-1, vmin-o) = animation FuncAnimation(fig, undate-frama fargs-(opts, world, ing), interval-opts.framedelay) pltO The fourth argument supplied to FuncAnimation () specifies how frequently the plot should be automatically updated (in milliseconds. As you can see, this is set on the command line using the framedelay option (See Section 3 and get.commandline.options) in gameoflife.py). The second argument supplied to FuncAnimation) specifies the function that is called for each frame update. The third argument allows you to pass function parameters to the update function in the form of a tuple. In this case we are passing the opts, world, and img parameters to the update.frame ) function. This means that all you need to do to implement the update rule is implement the function update.frame() i def update frame (frame num, opts, orld, img): Accepts: frame num(automatically passed in) current frame number a populated command line options instance world -the 2D world p12el buffer img the plot image img. set array (world) new world 0 for row in world newworld. append (rou:) I YOUR CODE GOES HERE # Copy the contents of the new-world gnto the uorld # (i.e. make the future the present) worldl:] nw world: return img, Here, world contains the current world state, and nev.world will be used to hold the solution to applying If you look at the definition of the update function update.frame), you will notice that it accepts 4 parameters instead of 3. This is because the frame number is automatically passed in as the first argument when the update function is called. Any arguments passed in as a tuple through the third argument of FuncAnination) are passed in after the frame number argument

Explanation / Answer

#!/usr/bin/python
import patterns
import sys
import argparse
import random
from matplotlib import pyplot as plt
from matplotlib import animation


def generate_world(opts):
    """
    Accepts: opts -- parsed command line options
    Returns: world -- a list of lists that forms a 2D pixel buffer

    Description: This function generates a 2D pixel buffer with dimensions
                 opts.cols x opts.rows (in pixels). The initial contents
                 of the generated world is determined by the value provided
                 by opts.world_type: either 'random' or 'empty' A 'random'
                 world has 10% 'living' pixels and 90% 'dead' pixels. An
                 'empty' world has 100% 'dead' pixels.
    """
    world = []

    ## TASK 1 #############################################################
    #
    #

    if opts.world_type == 'random':
        for col in range(opts.cols):
            #create temporary row before it's written to the world
            tmp_row = []
            #create requested number of rows
            for row in range(opts.rows):
                #each cell has a 10% probability of being alive
                if random.random() <= 0.1:
                    tmp_row.append(1)
                else:
                    tmp_row.append(0)
            #append the temporary row to the world
            world.append(tmp_row)

    elif opts.world_type == 'empty':
        #create empty world of requested dimensions
        world = [[0 for i in range(opts.cols)] for j in range(opts.rows)]

    #
    #
    #######################################################################

    return world


def update_frame(frame_num, opts, world, img):
    """
    Accepts: frame_num -- (automatically passed in) current frame number
             opts       -- a populated command line options instance
             world      -- the 2D world pixel buffer
             img        -- the plot image
    """

    # set the current plot image to display the current 2D world matrix
    img.set_array(world)

    # Create a *copy* of 'world' called 'new_world' -- 'new_world' will be
    # our offscreen drawing buffer. We will draw the next frame to
    # 'new_world' so that we may maintain an in-tact copy of the current
    # 'world' at the same time.
    new_world = []

    for row in world:
        new_world.append(row[:])

    ## TASK 3 #############################################################
    #
    #

    for row_idx, row in enumerate(world):
        for col_idx, col in enumerate(row):
            #index values of rows and colums surrounding current cell
            # useful for calculating indexes of surrounding cells
            # compensate for possibility of wrap-around
            last_row_idx = (row_idx - 1) % len(world)
            next_row_idx = (row_idx + 1) % len(world)
            last_col_idx = (col_idx - 1) % len(row)
            next_col_idx = (col_idx + 1) % len(row)

            #get values of all 8 surrounding cells
            top = world[last_row_idx][col_idx]
            bottom = world[next_row_idx][col_idx]
            left = world[row_idx][last_col_idx]
            right = world[row_idx][next_col_idx]
            top_left = world[last_row_idx][last_col_idx]
            bottom_left = world[next_row_idx][last_col_idx]
            top_right = world[last_row_idx][next_col_idx]
            bottom_right = world[next_row_idx][next_col_idx]
          
            #sum values of surrounding cells
            cell_sum = top + bottom + left + right + top_left + bottom_left + top_right + bottom_right
          
            curr_cell = world[row_idx][col_idx]
            #use sum of surrounding cells to determine if cell lives or dies
            if cell_sum > 3 or cell_sum < 2:
                curr_cell = 0
            elif cell_sum is 3:
                curr_cell = 1
          
            #write value to new_world (the frame buffer)
            new_world[row_idx][col_idx] = curr_cell
    #
    #######################################################################

    # Copy the contents of the new_world into the world
    # (i.e. make the future the present)
    world[:] = new_world[:]
    return img,


def blit(world, sprite, x, y):
  
    """
    Accepts: world -- a 2D world pixel buffer generated by generate_world()
             sprite -- a 2D matrix containing a pattern of 1s and 0s
             x      -- x world coord where left edge of sprite will be placed
             y      -- y world coord where top edge of sprite will be placed

    Returns: (Nothing)

    Description: Copies a 2D pixel pattern (i.e sprite) into the larger 2D
                 world. The sprite will be copied into the 2D world with
                 its top left corner being located at world coordinate (x,y)
    """
    ## TASK 2 #############################################################
    #
    #

    #iterate through each row in world
    for row_idx, sprite_row in enumerate(sprite):
        #iterate through each column in current row
        for col_idx, curr_val in enumerate(sprite_row):
            #find target indexes in world, and compensate for wrap-around
            target_row = (row_idx + x) % len(world)
            target_col = (col_idx + y) % len(world[0])
            #assign value of current position in sprite to target position in world
            world[target_row][target_col] = curr_val

    #
    #
    #######################################################################


def run_simulation(opts, world):
    """
    Accepts: opts -- a populated command line options class instance
             world -- a 2D world pixel buffer generated by generate_world()

    Returns: (Nothing)

    Description: This function generates the plot that we will use as a
                 rendering surfance. 'Living' cells (represented as 1s in
                 the 2D world matrix) will be rendered as black pixels and
                 'dead' cells (represetned as 0s) will be rendered as
                 white pixels. The method FuncAnimation() accepts 4
                 update_frameters: the figure, the frame update function, a
                 tuple containing arguments to pass to the update function,
                 and the frame update interval (in milliseconds). Once the
                 show() method is called to display the plot, the frame
                 update function will be called every 'interval'
                 milliseconds to update the plot image (img).
    """
    if not world:
        print "The 'world' was never created. Exiting"
        sys.exit()

    fig = plt.figure()
    img = plt.imshow(world, interpolation='none', cmap='Greys', vmax=1, vmin=0)
    ani = animation.FuncAnimation(fig,
                                  update_frame,
                                  fargs=(opts, world, img),
                                  interval=opts.framedelay)

    plt.show()


def report_options(opts):
    """
    Accepts: opts -- a populated command line options class instance

    Returns: (Nothing)

    Descrption: This function simply prints the parameters used to
                start the 'Game of Life' simulation.
    """

    print "Conway's Game of Life"
    print "====================="
    print "   World Size: %i x %i" % (opts.rows, opts.cols)
    print "   World Type: %s" % (opts.world_type)
    print " Frame Delay: %i (ms)" % (opts.framedelay)


def get_commandline_options():
    parser = argparse.ArgumentParser()

    parser.add_argument('-r', '--rows',
                        help='set # of rows in the world',
                        action='store',
                        type=int,
                        dest='rows',
                        default=50)

    parser.add_argument('-c', '--columns',
                        help='set # of columns in the world',
                        action='store',
                        type=int,
                        dest='cols',
                        default=50)

    parser.add_argument('-w', '--world',
                        help='type of world to generate',
                        action='store',
                        type=str,
                        dest='world_type',
                        default='empty')

    parser.add_argument('-d', '--framedelay',
                        help='time (in milliseconds) between frames',
                        action='store',
                        type=int,
                        dest='framedelay',
                        default=100)

    opts = parser.parse_args()

    return opts


def main():
    """
    The main function -- everything starts here!
    """
    opts = get_commandline_options()
    world = generate_world(opts)
    report_options(opts)

    blit(world, patterns.glider, 20, 20)

    run_simulation(opts, world)


if __name__ == '__main__':
    main()