#!/usr/bin/env python # # Author : Ahmed Obied (amaobied@ucalgary.ca) # Date : Jan. 17th 2008 # Purpose : Simple implementation of Conway's "Game of Life" # # import the sys module for proper console output import sys # import the random module for generating random numbers import random # constants DEAD_CELL = 0 ALIVE_CELL = 1 # a constant to avoid going outside the environment when we check the neighbours OFFSET = 2 MAX_ROW = 10 + OFFSET MAX_COL = 20 + OFFSET def draw_environment(curr_step, max_step): """ Purpose : draws the environment Parameters : the current step and the maximum number of steps """ sys.stdout.write('Step : %d of %d\n' % (curr_step, max_step)) # draw a line at the top for i in range(MAX_COL): sys.stdout.write('=') sys.stdout.write('\n') # print out the environment for i in range(1, MAX_ROW - 1): sys.stdout.write('|') for j in range(1, MAX_COL - 1): # alive cells are shows as '*' in the environment if env[i][j] == ALIVE_CELL: sys.stdout.write('*') else: sys.stdout.write(' ') sys.stdout.write('|\n') # draw a line at the bottom for i in range(MAX_COL): sys.stdout.write('=') sys.stdout.write('\n') # wait for the user to hit enter sys.stdout.write('') sys.stdin.readline() def count_neighbours(row, col): """ Purpose : counts the number of neighbours Parameters : the current row and column Returns : the total number of neighbours for a given cell """ neb_count = 0 # initialize the offset lists row_offset = [0 for i in range(8)] col_offset = [0 for i in range(8)] # hard code the values for the offsets used to check the neighbours - 8 in total row_offset[0], col_offset[0] = 0, -1 row_offset[1], col_offset[1] = -1, -1 row_offset[2], col_offset[2] = -1, 0 row_offset[3], col_offset[3] = -1, 1 row_offset[4], col_offset[4] = 0, 1 row_offset[5], col_offset[5] = 1, 1 row_offset[6], col_offset[6] = 1, 0 row_offset[7], col_offset[7] = 1, -1 # count how many alive cells we have as neighbors by checking every offset for i in range(8): if env[row + row_offset[i]][col + col_offset[i]] == ALIVE_CELL: neb_count = neb_count + 1 return neb_count def step(): """ Purpose : make one step in the simulation and update the environment """ # go through the environment applying the rules for i in range(1, MAX_ROW - 1): for j in range(1, MAX_COL - 1): neb_count = count_neighbours(i, j) # if the cell is alive if env[i][j] == ALIVE_CELL: # if the cell has 1 neighbour or less then it dies of loneliness if neb_count < 2: env[i][j] = DEAD_CELL # if the cell has more than 3 neighbours then it dies from the crowd elif neb_count > 3: env[i][j] = DEAD_CELL # else if the cell is dead then we check the neighbours count # if it's 3 then the cell becomes alive elif env[i][j] == DEAD_CELL and neb_count == 3: env[i][j] = ALIVE_CELL def read_int(message, low, high): """ Purpose : displays a message to the user and reads the input Parameters : message - the message to print to the console low - the lowest possible value high - the highest possible value Returns : the value entered by the user """ # flag to end the loop when needed end_loop = False while not end_loop: sys.stdout.write('%s between %d and %d: ' % (message, low, high)) val = int(sys.stdin.readline()) # check if the input given by the user is between the low and high if val < low or val > high: sys.stdout.write('Error: The number is not within the proper range\n') else: end_loop = True return val def random_init(num_alive): """ Purpose : creates alive cells in random locations in the environment Parameters : the total number of alive cells to generate """ for i in range(num_alive): # get random x and y x = random.randint(1, MAX_ROW - OFFSET) y = random.randint(1, MAX_COL - OFFSET) # switch the cell from dead to alive for a given x and y env[x][y] = ALIVE_CELL if __name__ == '__main__': """ Main Entry """ # initialize the environment - all the cells are set to dead env = [[DEAD_CELL for i in range(MAX_COL)] for i in range(MAX_ROW)] # read the number of alive cells to generate and the total number of steps from the user num_alive = read_int('Number of alive cells', 1, 150) num_steps = read_int('Number of steps', 1, 1000) # generate random alive cells random_init(num_alive) # iterate until the maxium number of steps is reached for i in range(num_steps + 1): draw_environment(i, num_steps) step() sys.stdout.write('Done.\n')