I'm currently writing a game of life with small extra features but I ran into a problem - in my first try i decided to use simple list of Cell objects:

class Cell:
    def __init__(self, x, y, is_alive):
        self.is_alive = is_alive
        self.x = x
        self.y = y
        self.will_be_alive = False
        self.neighbours = 0

    def kill(self):
        self.will_be_alive = False

    def revive(self):
        self.will_be_alive = True

    def iterate(self):
        self.is_alive = self.will_be_alive

but now I'm using different approach:

class Cells:
    def __init__(self, width, height):
        self.current_states = [[False for i in range(width)] for j in range(height)]
        self.next_states = [[False for i in range(width)] for j in range(height)]
        self.neighbours = [[0 for i in range(width)] for j in range(height)]

as you can see, instead of list of objects it's now object with lists. I expected my program to run slightly faster, but it's totally opposite - it's 20 fps less. I think, that problem may be in iterate method in second way:

def next_state(cells):
    for i, row in enumerate(cells.current_states):
        for j, cell in enumerate(row):
            if cells.neighbours[i][j] > 0:
                count_state(cells, j, i)
            elif cells.neighbours[i][j] == 0 and cells.current_states[i][j]:
                cells.next_states[i][j] = False
    for i, row in enumerate(cells.current_states):
        for j, cell in enumerate(row):
            neigh_iterate(cells, j, i)

def count_state(cells, x, y):
    nei = neighboors(cells.current_states, x, y)
    if (nei > 3 or nei < 2) and cells.current_states[y][x]:
        cells.next_states[y][x] = False
    elif nei == 3 and not cells.current_states[y][x]:
        cells.next_states[y][x] = True

def neigh_iterate(cells, x, y):
    prev = cells.current_states[y][x]
    iterate(cells, x, y)
    if cells.current_states[y][x] != prev:
        if cells.current_states[y][x]:
            add_neighbour(cells.neighbours, x, y, 1)
            add_neighbour(cells.neighbours, x, y, -1)

def neighboors(current_states, x, y):
    how_many = -1 if current_states[y][x] else 0
    for i in range(-1, 2):
        for j in range(-1, 2):
            if current_states[(y + i) % BOARD_HEIGHT][(x + j) % BOARD_WIDTH]:
                how_many += 1
    return how_many

def iterate(cells, x, y):
    cells.current_states[y][x] = cells.next_states[y][x]

Do you have any ideas guys?

  • \$\begingroup\$ What do you mean by "20 fps less"? Are you recreating an array every frame? There are several possible causes starting with some Python implementation details and up to CPU cache. I have 2 recommendations: 1. don't assume something being faster for you code - check it. 2. Read about data-driven development. \$\endgroup\$ Jun 23, 2021 at 15:14
  • \$\begingroup\$ I've already profiled code with cProfile. Despite the smaller number of calls to iterating functions, they last over 120ms longer in second approach. App dropped from average 62 to 41-42 frames, so it's over 33% waste of performance. \$\endgroup\$
    – kucu
    Jun 23, 2021 at 17:04


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.