Browse code

Initial commit

haywalk authored on 01/12/2021 01:47:42
Showing 2 changed files

... ...
@@ -1,2 +1,11 @@
1
-# conway
2
-An implementation of Conway's Game of Life in Python using Pygame
1
+# Conway's Game of Life
2
+
3
+This is an implementation of [Conway's Game of Life](https://www.conwaylife.com/wiki/Conway%27s_Game_of_Life), a cellular automaton. I first implemented this in August 2019, when I was first learning Python. Over two years later, I was looking for a way to waste some time, so I decided to write a more polished implementation of the algorithm.
4
+
5
+The simulation runs on a grid of 'cells,' which are either alive or dead. Each cycle of the simulation is called a 'generation.' Which cells live into the next generation, die, or are born, is determined by the following three rules:
6
+
7
+* If a living cell has 2 or 3 living neighbours, it will live into the next generation.
8
+* If a living cell has less than 2 or more than 3 living neighbours, it will die.
9
+* If a dead cell has exactly three living neighbours, it will become alive.
10
+
11
+This implementation is written in Python 3.9 and requires the [Pygame](https://www.pygame.org/) library. This program is licensed under the [GNU GPL, version 3](https://www.gnu.org/licenses/gpl-3.0.en.html). It was written by Hayden Walker ([www.haywalk.ca](https://www.haywalk.ca/)) on 2021-11-30. 
3 12
new file mode 100644
... ...
@@ -0,0 +1,174 @@
1
+'''
2
+conway.py
3
+
4
+Copyright 2021 Hayden D. Walker <planethaywalk@aol.com>
5
+ 
6
+This program is free software: you can redistribute it and/or modify
7
+it under the terms of the GNU General Public License as published by
8
+the Free Software Foundation, either version 3 of the License, or
9
+(at your option) any later version.
10
+
11
+This program is distributed in the hope that it will be useful,
12
+but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+GNU General Public License for more details.
15
+
16
+You should have received a copy of the GNU General Public License
17
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
+'''
19
+
20
+'''
21
+Conway's Game of Life
22
+Implemented by Hayden Walker (www.haywalk.ca)
23
+2021-11-30
24
+'''
25
+
26
+import random
27
+
28
+# Attempt to import Pygame
29
+try:
30
+    import pygame
31
+except:
32
+    print('This program requires the Pygame library to be installed.')
33
+    quit()
34
+
35
+
36
+class Cell:
37
+    '''
38
+    One cell in Conway's Game of Life
39
+    '''
40
+    def __init__(self, is_living, col, row):
41
+        '''
42
+        Class constructor
43
+        '''
44
+        self.is_living = is_living
45
+        self.col = col
46
+        self.row = row
47
+        self.neighbours = 0
48
+
49
+    def get_neighbours(self, cell_array):
50
+        '''
51
+        Given the array of cells, count this cell's living neighbours
52
+        '''
53
+
54
+        # Check if cell is on an edge
55
+        l_edge = self.col == 0
56
+        r_edge = self.col == len(cell_array) - 1
57
+        t_edge = self.row == 0
58
+        b_edge = self.row == len(cell_array) - 1
59
+
60
+        # Count neighbours
61
+        num_of_neighbours = 0
62
+
63
+        # Check left
64
+        if not l_edge:
65
+            if cell_array[self.row][self.col - 1].is_living:
66
+                num_of_neighbours += 1
67
+        # Check top-left
68
+        if not l_edge and not t_edge:
69
+            if cell_array[self.row - 1][self.col - 1].is_living:
70
+                num_of_neighbours += 1
71
+        # Check bottom-left
72
+        if not l_edge and not b_edge:
73
+            if cell_array[self.row + 1][self.col - 1].is_living:
74
+                num_of_neighbours += 1
75
+        # Check top
76
+        if not t_edge:
77
+            if cell_array[self.row - 1][self.col].is_living:
78
+                num_of_neighbours += 1
79
+        # Check bottom
80
+        if not b_edge:
81
+            if cell_array[self.row + 1][self.col].is_living:
82
+                num_of_neighbours += 1
83
+        # Check right
84
+        if not r_edge:
85
+            if cell_array[self.row][self.col + 1].is_living:
86
+                num_of_neighbours += 1
87
+        # Check top-right
88
+        if not r_edge and not t_edge:
89
+            if cell_array[self.row - 1][self.col + 1].is_living:
90
+                num_of_neighbours += 1
91
+        # Check bottom-right
92
+        if not r_edge and not b_edge:
93
+            if cell_array[self.row + 1][self.col + 1].is_living:
94
+                num_of_neighbours += 1
95
+
96
+        self.neighbours = num_of_neighbours
97
+
98
+    def evolve(self):
99
+        '''
100
+        Decide if the cell will live to next generation
101
+        '''
102
+        if self.is_living:
103
+            if self.neighbours < 2 or self.neighbours > 3:
104
+                self.is_living = False
105
+        else:
106
+            if self.neighbours == 3:
107
+                self.is_living = True
108
+
109
+    def draw(self, win):
110
+        '''
111
+        Draw the cell
112
+        '''
113
+        if self.is_living:
114
+            pygame.draw.rect(win, (255, 255, 0), (self.col * 10, self.row * 10, 10, 10))
115
+        else:
116
+            pygame.draw.rect(win, (0, 0, 0), (self.col * 10, self.row * 10, 10, 10))
117
+
118
+# Get number of rows and columns
119
+dimensions = int(input('Number of rows and columns: '))
120
+delay = int(input('Delay between cycles (ms): '))
121
+
122
+# Initialize the pygame window
123
+pygame.init()
124
+screen = pygame.display.set_mode((dimensions * 10, dimensions * 10))
125
+pygame.display.set_caption("Life")
126
+
127
+# Create array of rows of cells
128
+cell_array = list()
129
+
130
+# Add rows of cells to the array
131
+for row in range(dimensions):
132
+    # Create the row as a list of cells
133
+    this_row = list()
134
+
135
+    # Add cells to the row
136
+    for col in range(dimensions):
137
+        this_row.append(Cell(random.randint(0, 1), col, row))
138
+
139
+    # Add row to list of rows
140
+    cell_array.append(this_row)
141
+
142
+# Main loop
143
+while True:
144
+    # Check for quit
145
+    for event in pygame.event.get():
146
+        if event.type == pygame.QUIT:
147
+            quit()
148
+    
149
+    # Clear screen
150
+    screen.fill((0, 0, 0))
151
+
152
+    # Draw each cell
153
+    for row in cell_array:
154
+        for cell in row:
155
+            cell.draw(screen)
156
+
157
+    # Update the screen
158
+    pygame.display.update()
159
+
160
+    # Make each cell count its neighbours
161
+    for row in cell_array:
162
+        for cell in row:
163
+            cell.get_neighbours(cell_array)
164
+
165
+    # Make each cell evolve
166
+    for row in cell_array:
167
+        for cell in row:
168
+            cell.evolve()
169
+
170
+    # Wait a second
171
+    pygame.time.delay(delay)
172
+
173
+
174
+