Ejemplo n.º 1
0
    def main(self, view, model):
        km = KeyMap()
        ac = ActionContext(km, model, self.__stdscr)

        while model.checkProgramExecution():
            view.update(self.__stdscr)
            c = self.__stdscr.getch() 
            model.echoCommand(str(c))
            km.addCommand(ch(c))
            demands = km.translate()
            ac.do(demands)
Ejemplo n.º 2
0
    def __init__(self, window: Window):
        self._window = window
        self.population = Population(settings.CELLS_POPULATION)
        self.grave = Grave()
        self.reproduction = Reprodaction()
        self.epoch = 1
        self.step = 1

        # производим подписку на объекты травоядных клеток
        Herbivore.add_born_sub(self.population)
        Herbivore.add_death_sub(self.population)
        Herbivore.add_death_sub(self.grave)

        self._action_context = ActionContext()
        self._herb_arbiter = HerbArbiter()

        self._generate_map()
        self._generate_walls()
        self._set_cells(PlantFood, 150)
        self._set_cells(Herbivore, settings.CELLS_POPULATION)
Ejemplo n.º 3
0
 def setUp(self):
     self.model = Model()
     self.km = KeyMap()
     self.ac = ActionContext(self.km, self.model, None)
Ejemplo n.º 4
0
class TestSequenceFunctions(unittest.TestCase):
    def setUp(self):
        self.model = Model()
        self.km = KeyMap()
        self.ac = ActionContext(self.km, self.model, None)

    def test_keymap_sequence(self):
        self.km.addCommand('j')
        demands = self.km.translate()
        self.assertTrue(demands == 'cursor_down')

    def test_down(self):
        self.km.addCommand('j')
        demands = self.km.translate()
        self.ac.do(demands)
        (x, y) = self.model.getCursor().getCursor()
        self.assertTrue(x == 0 and y == 1)

    def test_left(self):
        self.km.addCommand('l')
        demands = self.km.translate()
        self.ac.do(demands)
        (x, y) = self.model.getCursor().getCursor()
        self.assertTrue(x == 1 and y == 0)

    def test_looparound(self):
        self.km.addCommand('j')
        demands = self.km.translate()
        self.ac.do(demands)

        self.km.addCommand('l')
        demands = self.km.translate()
        self.ac.do(demands)

        self.km.addCommand('k')
        demands = self.km.translate()
        self.ac.do(demands)

        self.km.addCommand('h')
        demands = self.km.translate()
        self.ac.do(demands)

        (x, y) = self.model.getCursor().getCursor()
        self.assertTrue(x == 0 and y == 0)

    def test_insert(self):
        sample_text = "This is sample text"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getRawContent() == sample_text)

    def test_discernText(self):
        sample_text = "This is sample text"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getType() == "Text")

    def test_discernNumeric(self):
        sample_text = "3.14159"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getType() == "Numeric")

    def test_discernFormula(self):
        sample_text = "=sum(A1:A10)"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getType() == "Formula")
Ejemplo n.º 5
0
class World:
    """Класс Реализация для управления миром, в котором существуют клетки."""

    GRID = [
        [-1] * settings.COL for g in range(settings.ROW)
    ]  # представление мира в виде матрицы, все манипуляции с миром сперва делаются с матрицей

    def __init__(self, window: Window):
        self._window = window
        self.population = Population(settings.CELLS_POPULATION)
        self.grave = Grave()
        self.reproduction = Reprodaction()
        self.epoch = 1
        self.step = 1

        # производим подписку на объекты травоядных клеток
        Herbivore.add_born_sub(self.population)
        Herbivore.add_death_sub(self.population)
        Herbivore.add_death_sub(self.grave)

        self._action_context = ActionContext()
        self._herb_arbiter = HerbArbiter()

        self._generate_map()
        self._generate_walls()
        self._set_cells(PlantFood, 150)
        self._set_cells(Herbivore, settings.CELLS_POPULATION)

    def _generate_map(self):
        """Метод вызывается для первичной генерации мира, заполняет его пустыми клетками."""
        y1 = 0
        y2 = settings.CELL_Y
        for i, row in enumerate(self.GRID):
            x1 = 0
            x2 = settings.CELL_X
            for j, _ in enumerate(row):
                empty = Empty()
                map_id = self._window.create_rectangle(x1, y1, x2, y2)
                empty.set_id(map_id)
                self.GRID[i][j] = empty
                x1 += settings.CELL_X
                x2 += settings.CELL_X
            y1 += settings.CELL_Y
            y2 += settings.CELL_Y

    def _generate_walls(self):
        """Метод для первичного вызова, генерирует в пустом мире стены, за пределы которого клетки не могут выйти."""
        new_grid = copy.deepcopy(self.GRID)
        first_row = new_grid[0]
        last_row = new_grid[-1]

        def _fill_row(Cell: BaseCell, row: List[BaseCell],
                      row_index: int) -> None:
            for i, cell in enumerate(row):
                new_cell = Cell()
                new_cell.set_id(cell.get_id)
                new_grid[row_index][i] = new_cell

        _fill_row(Wall, first_row, 0)
        _fill_row(Wall, last_row, -1)

        self._update_world(new_grid)

    def _remove_all_cells(self):
        """Метод приводит мир к чистому состоянию."""
        new_grid = copy.deepcopy(self.GRID)

        for i, row in enumerate(new_grid):
            for j, cell in enumerate(row):
                empty = Empty()
                empty.set_id(cell.get_id)
                new_grid[i][j] = empty

        self._update_world(new_grid)

    def _set_cells(self, Cell: BaseCell, count: int, **kwargs) -> None:
        """Метод генерирует определенное количество клеток в мире в рандомные, пустых местах.

        Args:
            Cell (BaseCell): класс ячейки которыми будет заполняться мир
            count (int): количество ячеек, которыми нужно заполнить мир
        """
        new_grid = copy.deepcopy(self.GRID)

        coefficient = 0.1
        if count < 100:
            coefficient /= 10

        while True:
            for i, row in enumerate(new_grid):
                for j, cell in enumerate(row):
                    if not cell.is_solid:
                        # из-за низкой вероятности создания клетки растительной пищи и бесконечного цикла, достигается
                        # равномерное покрытие
                        if random.random() < coefficient:
                            new_cell = Cell(**kwargs)
                            new_cell.set_id(cell.get_id)
                            new_grid[i][j] = new_cell

                            count -= 1

                            if count <= 0:
                                self._update_world(new_grid)
                                return

    def _make_step(self):
        """Метод для совершения одной итерации мира."""
        new_grid = copy.deepcopy(self.GRID)

        for i, row in enumerate(self.GRID):
            for j, cell in enumerate(row):
                if cell.can_move:
                    cells_around = self._get_round_cost(i, j)
                    cells_around.append(cell.get_health / 100)
                    # сперва клетка делает действие и затем арбитер с учетом типа клетки изменяет внешнее состояние мира
                    cell.make_move(cells_around)
                    if isinstance(cell, Herbivore):
                        self._action_context.set_strategy(self._herb_arbiter)
                    self._action_context.execute(cell, [j, i], self.GRID,
                                                 new_grid)

        if self.is_end_epoch():
            self.reload_world()
        else:
            self._update_world(new_grid)

        self._update_helpfull_text()

    def _update_helpfull_text(self):
        """Метод для обновления вспомогательного текста."""
        self.step += 1
        self._window.change_steps_count(self.step)
        self._window.change_epoch_count(self.epoch)

    def is_end_epoch(self) -> bool:
        """Метод проверяет, является ли данная итерация концом эпохи."""
        return self.population.total_count == 0

    def _clear_world(self) -> None:
        """Метод для полной очистки мира."""
        self._remove_all_cells()
        self._generate_walls()
        self._set_cells(PlantFood, 175)

    def _fill_new_generation(self, best_epoch_cells: list[Herbivore], children,
                             best_mutation, second_mutation,
                             children_mutation) -> None:
        """Метод производит заполнение нового мира клетками с новым геномом.

        Args:
            best_epoch_cells (list): Массив содержащий в себе две лучшие клетки предыдущего поколения
            children (matrix): Скрещенный геном двух лучших клеток предыдущего поколения
            best_mutation (matrix): Измененный геном лучшей клетки предыдущего поколения
            second_mutation (matrix): Измененный геном второй лучшей клетки предыдущего поколения
            children_mutation (matrix): Измененный геном ребенка лучших клеток
        """
        best = best_epoch_cells[0]
        second = best_epoch_cells[1]
        self._set_cells(Herbivore,
                        8,
                        genome=best.save_genome(),
                        clan=best.get_clan_name,
                        color=settings.BEST)
        self._set_cells(Herbivore,
                        8,
                        genome=second.save_genome(),
                        clan=second.get_clan_name,
                        color=settings.SECOND)
        self._set_cells(Herbivore, 8, genome=children, color=settings.CHILDREN)
        self._set_cells(Herbivore, 8, genome=best_mutation)
        self._set_cells(Herbivore, 8, genome=second_mutation)
        self._set_cells(Herbivore, 8, genome=children_mutation)

    def reload_world(self) -> None:
        """Метод производит перезапуск мира, если был конец эпохи."""
        self._window.change_past_steps_count(self.step)
        self.epoch += 1
        self.step = 0

        self._clear_world()

        best_epoch_cells = self.grave.get_best()
        children_genome = self.reproduction.crossing(*best_epoch_cells)
        best_genome = best_epoch_cells[0].save_genome()
        second_genome = best_epoch_cells[1].save_genome()

        best_mutated_genome = list()
        second_mutated_genome = list()
        mutated_children = list()
        for genome in best_genome:
            best_mutated_genome.append(self.reproduction.mutation(genome))
        for genome in second_genome:
            second_mutated_genome.append(
                self.reproduction.mutation(genome, 0.4))
        for genome in children_genome:
            mutated_children.append(self.reproduction.mutation(genome))

        self._fill_new_generation(best_epoch_cells, children_genome,
                                  best_mutated_genome, second_mutated_genome,
                                  mutated_children)
        # обновлять популяцию нужно после того как мир был заново заселен клетками
        self.grave.clear()
        self.population.update_population(self.GRID)

    def _get_round_cost(self, i: int, j: int) -> list:
        """Метод возвращает значения всех клеток вокруг той, что должна совершить движение двигается.

        Args:
            i (int): Расположение клетки совершающей движение по оси y
            j (int): Расположение клетки совершающей движение клетки по оси x

        Returns:
            list: Массив содержащий все веса клеток, окружающие движущуюся, начиная с левого верхнего угла и по часовой.
        """
        # т.к. мир замкнут по горизонтали, смотрим с другой стороны
        if j == 0:
            return [
                self.GRID[i - 1][settings.COL - 1].get_cost,
                self.GRID[i - 1][j].get_cost,
                self.GRID[i - 1][j + 1].get_cost,
                self.GRID[i][settings.COL - 1].get_cost,
                self.GRID[i][j + 1].get_cost,
                self.GRID[i + 1][settings.COL - 1].get_cost,
                self.GRID[i + 1][j].get_cost,
                self.GRID[i + 1][j + 1].get_cost,
            ]
        if j == settings.COL - 1:
            return [
                self.GRID[i - 1][j - 1].get_cost,
                self.GRID[i - 1][j].get_cost,
                self.GRID[i - 1][0].get_cost,
                self.GRID[i][j - 1].get_cost,
                self.GRID[i][0].get_cost,
                self.GRID[i + 1][j - 1].get_cost,
                self.GRID[i + 1][j].get_cost,
                self.GRID[i + 1][0].get_cost,
            ]
        return [
            self.GRID[i - 1][j - 1].get_cost,
            self.GRID[i - 1][j].get_cost,
            self.GRID[i - 1][j + 1].get_cost,
            self.GRID[i][j - 1].get_cost,
            self.GRID[i][j + 1].get_cost,
            self.GRID[i + 1][j - 1].get_cost,
            self.GRID[i + 1][j].get_cost,
            self.GRID[i + 1][j + 1].get_cost,
        ]

    def _update_world(self, new_world: List[List[BaseCell]]):
        """Метод производит перерисовку мира.

        Принимается обновленное состояние мира, сравнивается со старым состоянием, если положение клеток поменялось,
        производится точечная перерисовка, и старое состояние мира заменяется на новое.

        Args:
            new_world (List[List[BaseCell]]): Матрица содержащая обновленное состояние мира, новое положение клеток.
        """
        for i, row in enumerate(self.GRID):
            # оптимизация позволяющая пропускать строки в которых визуально ничего не изменилось
            if not duck_typing_lists_equals(row, new_world[i]):
                for j, cell in enumerate(row):
                    # оптимизация позволяющая пропускать элементы в которых ничего не изменилось
                    if not duck_typing_elements_equals(cell, new_world[i][j]):
                        self._window.change_cell_color(
                            new_world[i][j].get_id, new_world[i][j].get_color)
        self.GRID = copy.deepcopy(new_world)

        self._window.change_cells_count(self.population.total_count)

    def execute(self):
        """Метод запуска мира."""
        while True:
            self._make_step()
            self._window.update()
Ejemplo n.º 6
0
 def setUp(self):
     self.model = Model()
     self.km = KeyMap()
     self.ac = ActionContext(self.km, self.model, None)
Ejemplo n.º 7
0
class TestSequenceFunctions(unittest.TestCase):

    def setUp(self):
        self.model = Model()
        self.km = KeyMap()
        self.ac = ActionContext(self.km, self.model, None)

    def test_keymap_sequence(self):
        self.km.addCommand('j')
        demands = self.km.translate()
        self.assertTrue(demands == 'cursor_down')

    def test_down(self):
        self.km.addCommand('j')
        demands = self.km.translate()
        self.ac.do(demands)
        (x, y) = self.model.getCursor().getCursor()
        self.assertTrue(x == 0 and y == 1)

    def test_left(self):
        self.km.addCommand('l')
        demands = self.km.translate()
        self.ac.do(demands)
        (x, y) = self.model.getCursor().getCursor()
        self.assertTrue(x == 1 and y == 0)

    def test_looparound(self):
        self.km.addCommand('j')
        demands = self.km.translate()
        self.ac.do(demands)

        self.km.addCommand('l')
        demands = self.km.translate()
        self.ac.do(demands)

        self.km.addCommand('k')
        demands = self.km.translate()
        self.ac.do(demands)

        self.km.addCommand('h')
        demands = self.km.translate()
        self.ac.do(demands)

        (x, y) = self.model.getCursor().getCursor()
        self.assertTrue(x == 0 and y == 0)

    def test_insert(self):
        sample_text = "This is sample text"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getRawContent() == sample_text)

    def test_discernText(self):
        sample_text = "This is sample text"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getType() == "Text")

    def test_discernNumeric(self):
        sample_text = "3.14159"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getType() == "Numeric")

    def test_discernFormula(self):
        sample_text = "=sum(A1:A10)"
        sheet = self.model.getSheet()
        cursor = self.model.getCursor()
        cursor.setCellAtCursor(sheet, sample_text)
        cell = cursor.getCell(sheet)
        self.assertTrue(cell.getType() == "Formula")