Game of Life

Conway's Game of Life

I have created The Game of Life in Python and Pygame. The Game of Life was first devised by the British mathematician John Conway in 1970. It is a zero-player game, meaning that its evolution is determined by its initial state. It is Turing complete and can simulate a universal constructor or any other Turing machine.

The Game of Life is a two-dimensional grid consisting of cells, each with one of two possible stages, alive or dead. Each cell interacts with its eight neighboring cells. Each step in time, the following happens:

Link to my Python version of Conway's Game of Life.

Source code:

1  """Game of life | Sondre Nesje 2020"""

2  

3  import sys

4  from random import randint

5  

6  import pygame

7  

8  #Screen settings

9  FPS = 10

10  SCREEN_WIDTH = SCREEN_HEIGHT = 600

11  

12  #Cell settings

13  CELL_SIZE = 3

14  CELL_WIDTH = int(SCREEN_WIDTH / CELL_SIZE)

15  CELL_HEIGHT = int(SCREEN_HEIGHT / CELL_SIZE)

16  

17  #Grid size

18  GRID_WIDTH = int(SCREEN_WIDTH / CELL_SIZE)

19  GRID_HEIGHT = int(SCREEN_HEIGHT / CELL_SIZE)

20  

21  #Chance to make a cell at the beginning.

22  #In percent (%)

23  CELL_CHANCE = 20

24  

25  #Color settings

26  BACKGROUND_COLOR = (128, 0, 128)

27  CELL_COLOR = (255, 255, 0)

28  

29  def main():

30      """Main game function"""

31      global FPS_CLOCK, SCREEN, CELLS

32  

33      pygame.init()

34      FPS_CLOCK = pygame.time.Clock()

35      SCREEN = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

36      pygame.display.set_caption("Game of life | Sondre Nesje 2020")

37  

38      CELLS = create_cells()

39  

40      run_game()

41  

42  def run_game():

43      """The main loop for the game"""

44      global CELLS

45  

46      while True:

47          check_events()

48  

49          update_cells()

50  

51          update_screen()

52  

53  def check_events():

54      """Respond to events"""

55      for event in pygame.event.get():

56          if event.type == pygame.QUIT:

57              sys.exit()

58  

59  def create_cells():

60      """Create a set of alive cells"""

61  

62      cells = set()

63  

64      for column in range(CELL_WIDTH):

65          for row in range(CELL_HEIGHT):

66  

67              #The cell's x and y coordinates

68              cell_x = column * CELL_SIZE

69              cell_y = row * CELL_SIZE

70              cell = (cell_x, cell_y)

71  

72              if CELL_CHANCE > randint(0, 100):

73                  cells.add(cell)

74  

75      return cells

76  

77  def update_cells():

78      """Update the state of the cells"""

79      global CELLS

80  

81      #One set for new cells for the next generation,

82      #and one for dead neighbor cells

83      new_cells = set()

84      dead_neighbor_cells = set()

85  

86      for cells_alive in (True, False):

87  

88          #Go through both living cells and dead neighbor cells

89          if cells_alive:

90              cells = CELLS.copy()

91          else:

92              cells = dead_neighbor_cells.copy()

93  

94          for cell in cells:

95  

96              #A set of neighbor cells

97              neighbor_cells = check_neighbor_cells(cell)

98  

99              #A variable for live neighbor cells

100              live_cell_neighbors = 0

101  

102              #Count neighboring cells

103              #and make a set of dead neighbor cells

104              for neighbor_cell in neighbor_cells:

105                  if neighbor_cell in CELLS:

106                      #Count how many neighboring cells are alive

107                      live_cell_neighbors += 1

108                  elif cells_alive:

109                      #Create a set of dead neighbor cells,

110                      #but only if the main cell is alive

111                      dead_neighbor_cells.add(neighbor_cell)

112  

113              #Cellular automaton rule

114              if cells_alive and 2 <= live_cell_neighbors <= 3:

115                  #The cell survives

116                  new_cells.add(cell)

117              elif not cells_alive and live_cell_neighbors == 3:

118                  #The cell comes alive

119                  new_cells.add(cell)

120              #else:

121              #    The cell dies, or remains dead

122  

123      CELLS = new_cells.copy()

124  

125  def check_neighbor_cells(cell):

126      """Function to check for neighbor cells"""

127  

128      #The cell's x and y coordinates

129      cell_x = cell[0]

130      cell_y = cell[1]

131  

132      #Make a set of neighbor cells

133      neighbor_cells = {

134          tuple((cell_x - 1 * CELL_SIZE, cell_y - 1 * CELL_SIZE)),

135          tuple((cell_x + 0 * CELL_SIZE, cell_y - 1 * CELL_SIZE)),

136          tuple((cell_x + 1 * CELL_SIZE, cell_y - 1 * CELL_SIZE)),

137          tuple((cell_x - 1 * CELL_SIZE, cell_y + 0 * CELL_SIZE)),

138          tuple((cell_x + 1 * CELL_SIZE, cell_y + 0 * CELL_SIZE)),

139          tuple((cell_x - 1 * CELL_SIZE, cell_y + 1 * CELL_SIZE)),

140          tuple((cell_x + 0 * CELL_SIZE, cell_y + 1 * CELL_SIZE)),

141          tuple((cell_x + 1 * CELL_SIZE, cell_y + 1 * CELL_SIZE))}

142  

143      return neighbor_cells

144  

145  def update_screen():

146      """Update the screen, and flip to the new screen"""

147  

148      SCREEN.fill(BACKGROUND_COLOR)

149  

150      #Draw each alive cells

151      for cell in CELLS:

152          living_cell = pygame.Rect(cell[0], cell[1], CELL_SIZE, CELL_SIZE)

153          pygame.draw.rect(SCREEN, CELL_COLOR, living_cell)

154  

155      #Make the most recently drawn screen visible.

156      pygame.display.flip()

157  

158      FPS_CLOCK.tick(FPS)

159  

160  if __name__ == "__main__":

161      #Run the game.

162      main()

163