method __missing__ not working for dictionary in Conway's game of life

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
Tatito
Posts: 5
Joined: Tue Apr 27, 2021 3:58 pm

method __missing__ not working for dictionary in Conway's game of life

Post by Tatito » Tue Apr 27, 2021 4:30 pm

Apologies for my ignorance, I am completely new to micropython. As such my first foray is trying to implement code for Conway's game of life on a Raspberry Pi Pico using an 128x128 oled. I figured out how to do this using "brute force" (i.e., 128x128 matrices) but the optimized speed, even overclocking the Pi, is not what I would like (some ~2 sec between steps in the game). I ported to circuitpython, hoping to profit from ulab handling of matrices, but ended up with a slower end product (reasons not important, but I decided to go back to micropython).

I found online a separate approach using a dictionary of live cells that should accelerate matters greatly, as it only deals in each iteration strictly with those cells that need watching, neglecting the majority of cells that cannot evolve in a given step of the game. For this it relies on the use of the __missing__ method to return zero values for any cell not presently in the dictionary. The (steamlined) code is below. It returns the error

Traceback (most recent call last):
File "<stdin>", line 62, in <module>
File "<stdin>", line 46, in play_game
File "<stdin>", line 18, in check_cell
KeyError: (24, 13)

Which seems to indicate that __missing__ is not working as it should (that Key indeed corresponds to the coordinates of a cell being accessed that is not present in the dictionary up front). I have tried a couple of things by importing defaultdict etc, to no avail. Can anyone help? Thanks in advance.

Code: Select all

import time

class Life(dict):

    def __init__(self, *args, **kwargs):
        super(Life, self).__init__(*args, **kwargs)

    def __missing__(self, *args, **kwargs):
        return 0

    def check_cell(self, x: int, y: int): #determine if cell lives or dies
        x_coords = (x-1, x, x+1)
        y_coords = (y-1, y, y+1)
        total = 0

        for x_coord in x_coords:
            for y_coord in y_coords:
                total += self[x_coord, y_coord]

        live, dead = [], []
        cell = self[x, y]
        if total == 3 and not cell:
            live.append((x, y))
        elif total < 3 or total > 4 and cell:
            dead.append((x, y))
        elif cell:
            pass
        return live, dead

    def queue_cells(self):
        cells = []
        for x, y in self.keys():
            # Add all cell neighbors to the function.
            x_coords = (x-1, x, x+1)
            y_coords = (y-1, y, y+1)
            for x_coord in x_coords:
                for y_coord in y_coords:
                    cells.append((x_coord, y_coord))
#        print(cells)
        return cells

    def play_game(self):
        live, dead = [], []
        # Create all the transitions for the turn
        for x, y in self.queue_cells():
            step_live, step_dead = self.check_cell(x, y)
            live += step_live
            dead += step_dead
        # Apply all transitions. Remember that in Life, the state of the board
        # doesn't change until every cell is accounted for.
        for x, y in dead:
            if self[x, y]:
                del self[x, y]
        for x, y in live:
            self[x, y] = 1


game = Life({(25, 15): 1, (26, 15): 1, (25, 16): 1, (24, 16): 1, (25, 17): 1,})

while 1:
#    display.fill(0)
    game.play_game()
#    screen.refresh()
    time.sleep(.1)


Tatito
Posts: 5
Joined: Tue Apr 27, 2021 3:58 pm

Re: method __missing__ not working for dictionary in Conway's game of life

Post by Tatito » Wed Apr 28, 2021 3:03 pm

PS: in another forum someone tested the code against CPython, and the error was not reproduced. If this is micropython specific, why is there no complain when invoking the __missing__ method, but instead it just does not work? Unfortunately the information about micropython's treatment of dictionaries that I can find is very limited, and my knowledge not enough to see through something that is probably obvious.

Tatito
Posts: 5
Joined: Tue Apr 27, 2021 3:58 pm

Re: method __missing__ not working for dictionary in Conway's game of life

Post by Tatito » Thu Apr 29, 2021 2:55 am

For reference, I solved the issue by dropping __missing__ and using instead

Code: Select all

    def __getitem__(self, key):
        return self.get(key,0)
A similar approach with __missing__ did not work. Whatevs.

Post Reply