Description

You are to implement a text-based biological simulation: Conway's "Game of Life". Given a starting pattern of life forms in the simulation ('biosphere') the program will update the pattern according to new births and deaths that occur during that time period (turn). Each location in a biosphere (element in a 2D list) either contains: an empty space or a life form ("critter"). As each turn passes in the simulation a new critter may be born into an empty square or an existing critter may die off in an occupied location. To get any credit for your submission your program must be able to initialize the two lists to any of the 6 starting patterns and it must display the before/afterstate of the world with the same appearance as the code provided in the display function.

Initialization of the program

One requirement in order to get any credit for this assignment your program must, at a minimum, use the six starting patterns: oneEmpty(), twoSingleCritter(),threeSingleBirth(), fourthSimpleBirth(),fifthCreateListEdgeCases() and sixthComplexCases(). The more of the initial six cases that your program can correctly process, the higher will be your grade. Each of the functions will produce a 10x10 list. Your program does not have to handle lists of other sizes. When it first runs your program must allow the user to choose via a menu which of the 6 starting patterns will be used for the simulation. The choice will only appear once at the beginning. If you wish you can write additional functions with different initial patterns. Although additional test cases won't increase your grade it may reduce the likelihood of bugs in your program.

Important grading point: Your program functionality marks will only be awarded if your program produces the same results as these outputs. For example, function "oneEmpty()" starts out empty and should therefore never contain a Critter in the pattern. Function "sixthComplexCases()" will produce a stable pattern of 4 Critters in a square by turn 20. Partial marks will not be awarded if your pattern of Critters is "close" to the pattern produced my program. In addition you need to correctly and comprehensively document which starting patterns that your program will handle. Both of these requirements (producing the same patterns in your output and documenting which cases that your program correctly handles are necessary to make the marking process reasonable - don't expect the marker to spend hours tracing code to figure out if things are working). However, providing the results that your program must display is also an advantage for you. You will know if your program is "working or not" based on the pattern match (immediate and continuous feedback). But looking at the patterns is not a substitute for implementing and employing a debugging mode. The debugging mode can be very useful for helping you determine why and how your program is malfunctioning (if you have good debugging output messages)

The code in the starting program is extremely simple and just initializes the references to the lists ('newWorld' and 'oldWorld') to an empty world and displays the result for the latter two lists. The program that you will submit will not do things this way. The old world is the state of the biosphere before the birth/death rules have been applied during that turn while the new world is the state after those rules were applied. The starting code does apply those rules, you need to write the code yourself to get credit.

Displaying the state of the world (before and after) during the simulation.

As mentioned another requirement to get any credit for your assignment is that the display of the grid must be done using the display() function provided or you must write your own function yourself that produces the same output. Even the grid is required because it makes the display of world easier to read and interpret for both you and the marker.

Running the simulation

After initializing the starting positions, the program will simulate the births and deaths of the critters over time on a turn-by-turn basis. The user can either hit to advance the simulation by another turn, 'q' or 'Q' to end the simulation. A hidden feature (not displayed as an option), the [debug mode] can be toggled by entering 'd' or 'D' when prompted to proceed to another turn.

Rules of births and deaths

The births and deaths of critters is based solely upon the number of neighbors in adjacent/neighboring squares. Each square will have from 3 - 8 neighboring squares (inner squares have 8, outer squares can have 3 at the corners or 5 on the top/bottom/left/right edges). The square where the possibility of a birth or death is being examined is marked with a question mark ? in the examples below.

?

Bottom right corner

?

An inner square

Births (square is currently empty)

A birth can occur in an empty square if that square has exactly 3 neighbors, some (non-exhaustive) examples:

*
* ?
*

*
?
* *

Deaths (square currently contains a Critter).

A Critter can die of loneliness if it has zero or only one neighbor.

?

?
*

A Critter can die of overcrowding if it has four or more neighbors (non-exhaustive number of examples below):

*
* ? *
*

* ? *
* * *

The Critter will remain living if it has 2 or 3 neighbors.

? *
* *

Births and deaths will occur simultaneously in the simulation. How do the rules of births and deaths relate to the 10x10 world? Each turn the check for births and deaths must be made in each of the 100 squares. So as mentioned the 'old' world contains the state of the biosphere for that turn before the rules have been applied and the 'new' world will track the after state.

Debugging mode

Entering 'd' or 'D' will toggle debugging mode (on becomes off, off becomes on). The flag 'debugOn' will track whether debugging message are to appear or not:

debugOn = False

When the flag is set to 'True' debugging messages will appear, otherwise they will not:

if(debugOn == True):
print("<<>>")

This global variable for the debugging flag is the sole exception on the prohibition on the use of global variables in your program. No penalty will be applied for using this debugging flag but the usual penalty will be applied for other global variables. Global constants should be used when appropriate. Penalties for lack of constants may be applied when it's appropriate to define one and one hasn't been defined for that program.

The exact content of the debugging messages is left to your discretion. As the name implies the debugging tool should be used to help you test and debug your program. Here are examples of debugging messages[1) Display greater details: the neighbor count as well as births and deaths for each square 2) More sparse annoucements specifying only where births and deaths have occurred. Again you are not bound to produce these exact messages in order to get credit for the debugging feature but they are provided to give you an idea of how you can use this feature to test your program.

Starter Code

SIZE = 10
debugOn = False

#Game of Life simulation
#Author:
#Version:
#This version of the program initializes the oldWorld (during the turn)
#and the newWorld (appearance of the world after the turn) as well as
#displaying the two versions side by side. Since the original state of
#the biosphere was empty the state of the new state is correct. However,
#no rules of births and deaths was applied in this version of the
#simulation.

# Author:
# This function was created entirely by the above author and is
# used with permission.
"""
@oneEmpty()
@Arguments: None
@The biosphere is initialized to a completely empty state.
@Return value: A reference to a 2D list, the initialized biosphere.
"""
def oneEmpty():
world = []
world = [
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "]
]
return(world)

# Author:
# This function was created entirely by the above author and is
# used with permission.
"""
@twoSingleCritter()
@Arguments: None
@The biosphere is empty except for one location which contains a
@Critter.
@Return value: A reference to a 2D list, the initialized biosphere.
"""
def twoSingleCritter():
world = []
world = [
["*"," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "]
]
return(world)

# Author:
# This function was created entirely by the above author and is
# used with permission.
"""
@threeSingleBirth()
@Arguments: None
@The biosphere is empty except for 3 locations which contain Critters.
@The 3 Critters are all in proximity to a single location in the
@biosphere.
@Return value: A reference to a 2D list, the initialized biosphere.
"""
def threeSingleBirth():
world = []
world = [
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" ","*", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " ","*", " ", " ", " ", " ", " ", " "],
[" ","*", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "]
]
return(world)

# Author:
# This function was created entirely by the above author and is
# used with permission.
"""
@fourthSimpleBirth()
@Arguments: None
@The biosphere contains a number of Critters which are close enough
@proximity to produce new births for a number of turns.
@Return value: A reference to a 2D list, the initialized biosphere.
"""
def fourthSimpleBirth():
world = []
world = [
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" ","*", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", "*","*", " ", " ", " ", " ", " ", " "],
[" ","*", " ","*", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
["*"," ", " "," ", " ", " ", " ", " ", " ", " "]
]
return(world)

# Author:
# This function was created entirely by the above author and is
# used with permission.
"""
@fifthCreateListEdgeCases()
@Arguments: None
@The biosphere has a Critter located at the edge of the biosphere at
@each of the 4 compass ponts. Also there is a Critter in each of the
@corners.
@Return value: A reference to a 2D list, the initialized biosphere.
"""
def fifthCreateListEdgeCases():
world = []
world = [
["*"," ", "*"," ", " ", " ", " ", " ", " ", "*"],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" ","*", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
["*"," ", " "," ", " ", " ", " ", " ", " ", " "],
[" ","*", " "," ", " ", " ", " ", " ", " ", " "],
["*"," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", "*"],
[" "," ", " "," ", " ", " ", " ", " ", "*", " "],
["*","*", " "," ", " ", " ", " ", " ", " ", "*"]
]
return(world)

# Author:
# This function was created entirely by the above author and is
# used with permission.
"""
@sixthComplexCases()
@Arguments: None
@The biosphere contains a starting pattern that will require a
@program to handle births, deaths and edge cases.
@Return value: A reference to a 2D list, the initialized biosphere.
"""
def sixthComplexCases():
world = []
world = [
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", "*", " ", " ", " ", " ", " "],
[" ","*", " "," ", " ", "*", " ", " ", " ", " "],
[" "," ", " ","*", "*", "*", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
[" "," ", " "," ", " ", " ", " ", " ", " ", " "],
["*"," ", " "," ", " ", " ", " ", " ", " ", " "]
]
return(world)

# Author:
# This function was created entirely by the above author and is
# used with permission.
# '''
# @ This function works in conjunction with readFromFile()
# @intialize()
# @Argument: None
# @Return value: the game world in the form of a 2D list (each element
# @is set to an exclamation mark).
# '''
def initialize():
world = []
for r in range (0, SIZE, 1):
world.append ([])
for c in range (0, SIZE, 1):
world[r].append ("!")
return(world)


# Author:
# This function was created entirely by the above author and is
# used with permission.
# '''
# @display()
# @Argument: two references to the 2D list which is game world.
# @The list must be already created and properly initialized
# @prior to calling this function!
# @Return value: None
# @Displays each element of the world with each row all on one line
# @Each element is bound: above, left, right and below with a bar (to
# @make elements easier to see.
# @Each list is displayed side by side
# #
# '''
def display(turn,oldWorld,newWorld):
# Displays a row at a time of each list
print("Turn #%d" %turn)
print("BEFOREtttAFTER")
for r in range (0,SIZE,1):

# Row of dashes before each row of old and new list
# (Dashes for old list)
for i in range (0, SIZE, 1):
print("%s" %(" -"), end="")
print("#t",end="")
# (Dashes for new list)
for i in range (0, SIZE, 1):
print("%s" %(" -"), end="")
print()

# Display one row of old world list
for c in range (0,SIZE,1):
# Display: A vertical bar and then element (old list)
print("|%s" %(oldWorld[r][c]), end = "")
# Separate the lists with a number sign and a tab
print("", end = "#t")

# Display one row of new world list
for c in range (0,SIZE,1):
# Display: A vertical bar and then element (new list)
print("|%s" %(newWorld[r][c]), end = "")
print("|")

# Row of dashes after end of last row (old world list)
for i in range (0, SIZE, 1):
print("%s" %(" -"), end="")
print("#t",end="")

# Row of dashes after end of each row (new world list)
for i in range (0, SIZE, 1):
print("%s" %(" -"), end="")
print()

#################################################################
# Author:
# This function was created entirely by the above author and is
# used with permission.
def start():
choice = ""
oldWorld = []
newWorld = []
turn = 0

world = oneEmpty()
oldWorld = oneEmpty()
newWorld = oneEmpty()
display(turn,oldWorld,newWorld)
start()
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.