Доброго времени чтения, уважаемые пользователи Хабра! Игра Жизнь предложена Джоном Конвеем в 1970 году, и неоднократно обсуждалась на habrahabr.ru. Основные использованные теги приведены в метках к данной статье.
Предлагается ряд изменений, которые могут привести к новому направлению в развитии.
Предложение 1. В оригинальной игре предложено бесконечное поле, однако в реализациях обычно используется правило развертки тора — горизонтали и вертикали замкнуты в циклы.
Предлагается вариант, при котором горизонтали прямоугольного поля конечного размера замкнуты в цилиндр, а вертикали попарно соединены с шагом в половину размера поля по горизонтали. Таким образом можно получить легкий для расчетов аналог сферы.
Для моделирования изотропии предлагается использовать треугольную сетку, которая в расчетах подменяется оценкой близости по горизонтали, вертикали, и одной из диагоналей.
Для изменения среды могут использоваться горизонтальные слои:
один слой высотой 20% у экватора — с хорошими условиями жизни (3-4 соседа для сохранения, 4 для зарождения)
два слоя по 10% — с плохими условиями для жизни (1-2 соседа для сохранения, 2 — для зарождения жизни)
для остальной части действуют обычные правила (2-3 соседа для сохранения, 3 — для зарождения жизни)
Предложение 2. Для организмов предлагается добавление уровней сложности, возможностей объединения, генетической модификации и обучения. Каждому организму назначается до 10-ти уровней сложности, каждый уровень представлен как в материальной, так и в абстрактной области.
Уровень сложности в материальной области влияет на максимальную скорость (количество клеток, на которые организм передвигается в одном направлении за один ход). Таким образом, организмы с первым уровнем сложности (индекс массива 0) неподвижны. Целостный организм передвигается целиком.
Уровень сложности в абстрактной области влияет на количество обозреваемых по прямой соседних клеток. Предлагается удвоенный по сравнению с возможностью перемещения радиус обзора: для первого уровня — 1, для второго уровня — 3 и т.д. Видимость определяется от самых крайних клеток организма.
Реализация подобных игр может быть интересна современным студентам, изучающим обработку больших данных и алгоритмы обучения. Собственного варианта реализации на данный момент нет.
Рекомендуется генетическая эволюция алгоритмов из верховного алгоритма
Upd: вариант в разрезе групп сложности туннельного моделирования https://habrahabr.ru/post/259291/:
в разрезе природных систем
вероятностный вывод (Байес) — хаотическое
генетический поиск (эволюция) — фрактальное
оптимизация с ограничениями (аналогии) — энергетическое
обратная дедукция (символисты) — информационное
градиентный спуск (коннекционисты) — статическое
далее системы начинают проявлять поведение, и цепочка повторяется на уровне живого:
вероятностный вывод (Байес) — динамическое (процессы)
генетический поиск (эволюция) — синергетическое (рынок)
оптимизация с ограничениями (аналогии) — корпоративное (роды)
обратная дедукция (символисты) — бюрократическое (регламенты)
градиентный спуск (коннекционисты) — экологическое
Литература: Педро Домингос, Верховный алгоритм. Как машинное обучение изменит наш мир.
Ссылки:
https://habr.com/ru/post/435670/ — Верховный алгоритм — распределение алгоритмов по уровням сложности
Исходники на Python:
life.py
import pygame
import field
import numpy as np
running = True
v = field.area()
step=0
pygame.init()
screen = pygame.display.set_mode([640, 550])
font = pygame.font.Font(None, 50)
while running:
screen.fill([0, 0, 0])
clr = 0
for r in range(1, v.height):
for c in range(1, v.width):
if v.val[r, c] != 0:
clr=clr+64
if r % 2 == 0 and c % 2 == 0:
if clr > 255:
clr = 255
screen.set_at([r/2, c/2], [clr, clr, clr])
clr = 0
step_text = font.render(str(step),1, (255, 255, 0))
screen.blit(step_text, [10, 520])
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
v.generate()
step=step+1
pygame.quit()
print "Done"
field.py
import numpy as np
import random
class area:
def __init__(self):
self.width = 1000
self.height = 1000
self.debug = False
self.val = np.zeros((self.height, self.width), dtype = int)
self.val1 = np.zeros((self.height, self.width), dtype = int)
self.val[250, 140] = 1
self.val[250, 141] = 1
self.val[251, 140] = 1
self.val[251, 141] = 1
self.val[252, 140] = 1
self.val[252, 141] = 1
self.rw = range(1, self.width-2)
self.rh = range(1, self.height-2)
self.r3 = range(-1, 2)
self.dh = int(self.height/10)
self.h1 = [self.dh*2, self.height-self.dh*2]
self.h2 = [self.dh, self.height-self.dh]
def generate(self):
for cnt in self.r3:
c = random.randint(0, self.width-1)
r = random.randint(0, self.height-1)
self.val[r, c] = 1
c = random.randint(0, self.width-1)
r = random.randint(0, self.height-1)
self.val[r, c] = 0
for c in self.rw:
for r in self.rh:
self.val1[r, c] = 0
cnt = 0
for r1 in self.r3:
for c1 in self.r3:
if not ((r1 == 0) and (c1 == 0)) and not (r1==-1 and c1==1) and not (r1==1 and c1==-1):
if self.val[r+r1, c+c1] != 0:
cnt = cnt + 1
self.val1[r, c] = self.store_value(c, cnt, self.val[r, c])
for r in self.rh:
for c in self.rw:
self.val[r, c] = self.val1[r, c]
for c in self.rh:
if self.val[c, self.width-2] == 1:
self.val[0, c] = self.val[self.width-2, c]
if self.val[1, c] == 1:
self.val[self.width-1, c] = self.val[2, c]
def store_value(self, c, cnt, cur):
val = 0
if self.h1[0] < c < self.h1[1]:
if 1 <= cnt <= 4:
val = 1
if cur == 1 and cnt < 3:
val = 1
else:
if self.h2[0] < c < self.h2[1]:
if 2 <= cnt <= 3:
val = 1
if cur == 1 and 2 <= cnt <= 3:
val = 1
else:
if cnt == 2:
val = 1
if cur == 1 and 1 <= cnt <= 2:
val = 1
return val
Результат: