Exemplo n.º 1
0
def test_cells():
    """
    Create a Cells object
    """
    from pica.cells import Cells

    cells = Cells(3, 2, 'state')

    assert_equals(cells.width, 3)
    assert_equals(cells.height, 2)

    for x in range(3):
        for y in range(2):
            assert_equals(cells.cell(x, y), 'state')

    for x, y in ((-1, -1), (0, 4), (3, 2)):
        assert_is_none(cells.cell(x, y))

    for y in (-1, 2, 3):
        with assert_raises(ValueError):
            # because row is a generator, we can't just call cells.row,
            # as the ValueError won't be thrown until access.
            list(cells.row(y))

    for y in range(2):
        for cell in cells.row(y):
            assert_equals(cell, 'state')

    for x, y in ((-1, -1), (0, 4), (3, 2)):
        with assert_raises(ValueError):
            cells.update(x, y, 'new state')

    for y in range(2):
        for cell in cells.row(y):
            assert_equals(cell, 'state')

    for x in range(3):
        for y in range(2):
            assert_equals(cells.cell(x, y), 'state')

            cells.update(x, y, (x, y))

            assert_equals(cells.cell(x, y), (x, y))

    for y in range(2):
        for x, cell in enumerate(cells.row(y)):
            assert_equals(cell, (x, y))
Exemplo n.º 2
0
Arquivo: automata.py Projeto: bcj/pica
class Automata:
    """
    A cellular automata.
    """
    def __init__(self, width, height, initial_state, *rules):
        self._cells = Cells(width, height, initial_state)
        self._rules = rules

    @property
    def cells(self):
        return self._cells

    def randomize(self, states):
        """
        randomize the automata.

        states: an iterable of possible states.
        """
        if not states:
            raise ValueError(states)

        for x in range(self._cells.width):
            for y in range(self._cells.height):
                self._cells.update(x, y, choice(states))

    def step(self):
        """
        Take a step in the simulation. Returns a set of Changes.
        """
        changes = set()

        for x in range(self._cells.width):
            for y in range(self._cells.height):
                possibilities = Counter()
                forbidden = set()

                for rule in self._rules:
                    rule.reset()

                    result = rule(self._cells, x, y)

                    if result:
                        if result.difference is None:
                            forbidden.add(result.state)
                        else:
                            possibilities[result.state] += result.difference

                for state in forbidden:
                    del possibilities[state]  # works even if state not a key

                total = sum(possibilities.values())

                if total:  # at least one possibility
                    value = total * random()

                    tally = 0
                    for state, probability in possibilities.items():
                        tally += probability

                        if value < tally:
                            if self._cells.cell(x, y) != state:  # new state
                                changes.add(Change(x, y, state))

                            break

        for change in changes:
            self._cells.update(change.x, change.y, change.state)

        return changes