On 17/09/2011 14:03, [email protected] wrote:
All,

I had a very enjoyable evening on Thursday.  Many thanks to all who
attended.  In particular, thanks to all for showing us your code and
subjecting it to "friendly scrutiny"!

For those that were unable to attend, you can find some brief meeting
notes at http://pynw.org.uk/MeetingNotes/2011-09-15 ...

Next month's session is a talks session on Thursday 20th October.  As
always, contributions of talks to our group on that day are always
welcome ... :)

Best regards,

Safe


In the spirit of friendly scrutiny here's the infinite plane game of life we discussed near the end of the meeting. I've added a couple of (untested) sub classes to show how to bend space into a donut and how to use complex numbers for position tracking. More complex shapes of space, along with input and output to the code is left as an exercise for the reader ;)

Ed

--
To post: [email protected]
To unsubscribe: [email protected]
Feeds: http://groups.google.com/group/python-north-west/feeds
More options: http://groups.google.com/group/python-north-west
from gameoflife import *

def test_initialise_empty_world():
    w = World()
    assert len(w) == 0

def test_initialise_simple_world():
    w = World((0, 0), (1, 1))
    assert len(w) == 2

#####
# unit tests
def test_add_items_to_world():
    w = World()
    w += 0, 0
    assert len(w) == 0
    assert list(w) == []
    assert (0, 0) not in w
    w.step_time()
    assert len(w) == 1
    assert list(w) == [(0, 0)]
    assert (0, 0) in w

def test_remove_items_from_world():
    w = World((1, 1))
    w -= 1, 1
    assert len(w) == 1
    w.step_time()
    assert len(w) == 0

def test_step_time():
    w = World()
    w += 0, 0
    assert len(w) == 0
    assert list(w) == []
    w.step_time()
    assert len(w) == 1
    assert list(w) == [(0, 0)]
    w += 0, 0
    assert len(w) == 1
    assert list(w) == [(0, 0)]
    w.step_time()
    assert len(w) == 1
    assert list(w) == [(0, 0)]
    w.step_time()
    assert len(w) == 1
    assert list(w) == [(0, 0)]

def test_infinite_world_neighbours():
    w = World()
    n = list(w.neighbours((1, 1)))
    assert n == [(0, 0), (0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1), (2, 2)]

def test_evolve():
    w = World((1, 1))
    w.evolve()
    assert len(w) == 1
    w.step_time()
    assert len(w) == 0

# TODO: test live_neighbours

#####
# Functional tests
def test_lone_cell_dies():
    w = World((1, 1))
    w.tick()
    assert len(w) == 0

def test_square_lives():
    w = World(*[(x, y) for x in (1, 2) for y in (1, 2)])
    w.tick()
    assert len(w) == 4

def test_triangle_breeds():
    w = World((1, 1), (2, 2), (1, 2))
    w.tick()
    assert len(w) == 4

def test_line_moves():
    w = World((2, 1), (2, 2), (2, 3))
    w.tick()
    assert len(w) == 3
    assert (2, 1) not in w
    assert (1, 2) in w
    assert (2, 3) not in w
    assert (3, 2) in w
    assert (2, 2) in w

def test_beacon():
    w = World((1, 1), (1, 2), (2, 1), (4, 4), (4, 3), (3, 4))
    w.tick()
    assert len(w) == 8
    assert (2, 2) in w
    w.tick()
    assert len(w) == 6
    assert (2, 2) not in w
    w.tick()
    assert len(w) == 8
    assert (2, 2) in w

# TODO: test alternate GoL like worlds
# TODO: graphical output
# TODO: create and test von Neumann automata
# TODO: alternate world shapes
class World(object):
    """ Default world, infinate in all dimensons
        Neighbours looked for in 2d square grid plain
        Defaults to standard Conways Game of Life rules
    """

    def __init__(self, *positions, **rules):
        self.b = rules.get('b', set([3])) # born if b neighbours
        self.s = rules.get('s', set([2, 3])) # surivies if s neighbours
        self.cells = {}
        for p in positions:
            self += p
        self.step_time()

    def tick(self):
        self.evolve()
        self.step_time()

    def __len__(self):
        return len(list(self))

    def __iter__(self):
        for position in self.cells:
            if position in self:
                yield position

    ####
    # manipulate state
    def step_time(self):
        for position in dict(self.cells):
            if self[position] == 'child':
                self[position] = 'adult'
            elif self[position] == 'wounded':
                del self[position]

    def __iadd__(self, position):
        if position not in self:
            self[position] = 'child'
        return self

    def __isub__(self, position):
        if position in self:
            self[position] = 'wounded'
        return self

    def __contains__(self, position):
        """ Check if the cell at position is currently
            an alive adult
        """
        return self.cells.get(position) in ('adult', 'wounded')

    ######
    # shape of space
    def neighbours(self, (x, y)):
        for dx in (-1, 0, 1):
            for dy in (-1, 0, 1):
                if dx or dy:
                    yield (x+dx, y+dy)

    def __getitem__(self, position):
        return self.cells[position]
    
    def __setitem__(self, position, state):
        self.cells[position] = state

    def __delitem__(self, position):
        del self.cells[position]

    ######
    # rules of life
    def live_neighbours(self, position):
        return sum(1 for p in self.neighbours(position) if p in self)

    def evolve(self):
        for position in self:
            if self.live_neighbours(position) not in self.s:
                self -= position
        for position in set(p for c in self for p in self.neighbours(c) if p not in self):
            if self.live_neighbours(position) in self.b:
                self += position


class ToridLife(World):
    def __init__(self, (width, height), *args, **kwargs):
        self.width = width
        self.height = height
        super(ToridLife, self).__init__(*args, **kwargs)

    def neighbours(self, (x, y)):
        for nx, ny in super(ToridLife, self).neighbours((x, y)):
            yield nx%self.width, ny%self.height


class ComplexWorld(World):
    def neighbours(self, position):
        for dx in (-1, 0, 1):
            for dy in(-1j, 0, 1j):
                if dx or dy:
                    yield position + dx + dy

Reply via email to