# https://gist.github.com/bennuttall/6952575 # modified a lot import random, simplegui # cells width = 15 height = 15 scale = 9 # pixels per cell neighbour_cells = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)] def evolve_cell(alive, neighbours): return neighbours == 3 or (alive and neighbours == 2) def count_neighbours(grid, position): x,y = position count = 0 for ox,oy in neighbour_cells: dx = x + ox dy = y + oy if True: # wrap if dx < 0: dx = dx + width if dx >= width: dx = dx - width if dy < 0: dy = dy + height if dy >= width: dy = dy - height count += grid[dx][dy] else: # no wrap if dx >= 0 and dx < width and dy >= 0 and dy < height: count += grid[dx][dy] return count def make_empty_grid(x, y): grid = [] for r in range(x): row = [] for c in range(y): row.append(0) grid.append(row) return grid def make_random_grid(x, y): grid = [] for r in range(x): row = [] for c in range(y): row.append(random.randint(0,1)) grid.append(row) return grid # use the old grid as the new one def evolve(grid, new_grid): x = len(grid) y = len(grid[0]) for r in range(x): for c in range(y): cell = grid[r][c] neighbours = count_neighbours(grid, (r, c)) new_grid[r][c] = 1 if evolve_cell(cell, neighbours) else 0 # store the outgoing world for next time return (new_grid, grid) slowdown = 0 # Handler to draw on canvas def draw(canvas): global world, oldworld global slowdown for x in range(width): for y in range(height): alive = world[x][y] col = 'black' if alive else 'white' try: # canvas.draw_circle(center_point, radius, line_width, line_color, fill_color) canvas.draw_circle([x * scale + scale//2, y * scale + scale//2], scale//2, 1, '#ccc', col) except Exception as e: # I don't get this! col = 'red' canvas.draw_circle([x * scale + scale//2, y * scale + scale//2], scale//2, 1, col, col) # only change the world every N steps slowdown += 1 if slowdown >= 3 and enable: slowdown = 0 # store the outgoing world for next time world, oldworld = evolve(world, oldworld) def button_handler_stop(): global enable enable = False label.set_text('Stopped') def button_handler_go(): global enable enable = True label.set_text('Running') def mouse_handler_click(position): global mouse_click_new_val x, y = position x = x // scale y = y // scale # 0 <--> 1 world[x][y] = 1 - world[x][y] mouse_click_new_val = world[x][y] def mouse_handler_drag(position): x, y = position x = x // scale y = y // scale world[x][y] = mouse_click_new_val def init(): global world, oldworld global enable # make two arrays which we use alternately world = make_random_grid(width, height) oldworld = make_empty_grid(width, height) enable = False def main(): # Create a frame and assign callbacks to event handlers frame = simplegui.create_frame("Conway Life", width * scale, height * scale) frame.set_canvas_background('white') frame.set_draw_handler(draw) frame.set_mouseclick_handler(mouse_handler_click) frame.set_mousedrag_handler(mouse_handler_drag) frame.add_button('Stop', button_handler_stop) frame.add_button('Go', button_handler_go) global label label = frame.add_label('Stopped') init() # Start the frame animation frame.start() if __name__ == '__main__': main()