Планеры
и планерные ружья
Поскольку
существовали объекты, которые в процессе эволюции спонтанно генерировали
планеры, возникла идея создания объекта, который мог бы сам генерировать
эти планеры - некоего планерного ружья
(glider gun).
Первое
планерное ружье было изобретено Биллом Госпером (Bill Gosper) в 1970 г.,
и явилось первым примером объекта Жизни с неограниченно возрастающим числом
элементов.Планерное ружье Госпера (Рис.13)
продуцировало из себя (периодически выстреливало) планеры с периодом в
30 шагов. Следует отметить, что тут же был придуман объект, который эти
самые планеры поглощал. Объект назвали просто и без претензий - "поглотитель
планеров" и разместили на определенном расстоянии от ружья. Первым поглотителем
планеров оказался уже знакомый нам пентадекатрон. Поглощая планеры объект
вовсе не разрастался, как это было бы с объектами биологической эволюции,
а снова приходил в исходное состояние.
Пентадекатрон является динамическим поглотителем планеров и его форма постоянно
меняется от шага к шагу с периодом 15. Поэтому расположение этого поглотителя
по отношению к ружью Госпера имеет огромное значение, так как процесс поглощения
происходит лишь при определенном взаимном расположении поглотителя и подлетающего
планера.
На рис.14. приведен
пример генерации и поглощения планеров другой разновидностью поглотителей
- стационарным поглотителем.
На рисунке чуть ниже ружья можно увидеть планер, который из него вылетел,
а в правом нижнем углу рисунка - один из стационарных поглотителей планеров.
Данный стационарный поглотитель, в отличие от такого динамического поглотителя,
как пентадекатрон, не меняет свою форму вплоть до момента подлета к нему
планера. Когда планер приближается на достаточно близкое расстояние к поглотителю,
он проникает в него и бесследно растворяется. Одним из достаточно простых
поглотителей является также фигура, называемая «пожиратель»
(Eater) (Рис.2). Это наиболее простая стационарная фигура, выполняющая
функции поглощения планеров.
На рисунке 14 представлен лишь один планер, который вылетел из ружья и
приближается к поглотителю. Однако такое близкое расположение поглотителя
и ружья вовсе не обязательно. Поглотитель может быть установлен на любом
расстоянии и тогда от ружья потянется к нему длинная непрерывная цепочка
планеров. Это же утверждение справедливо и для динамического поглотителя.
Вдохнем
"Жизнь" в РС
Вспомнив,
как выручала эта игра на скучных лекциях в институте (хотя такие парные
игры как крестики-нолики по пять в ряд и японская игра "го" привлекали
не меньше энтузиастов), автор решил написать простую программу для РС,
чтобы воочию увидеть процесс "Жизни" на экране компьютера. Причина такого
решения заключалась в том, что эволюция фигур, собранных на шахматной доске
или специально нарисованном поле, как показал опыт, происходит слишком
медленно, неэффективно и чревата ошибками.
Первая
версия программы была написана в образовательных целях на языке Turbo Pascal.
Автор счел возможных все-же привести версию программы на Borland C/C++.
Программа сознательно сделана очень простой. Она формирует игровое поле
размера NxN клеток, позволяет нарисовать любой начальный объект используя
курсор для перемещения по экрану и клавишу пробела для создания фишки.
Клавиши "Delete" и "Backspace" удаляют ошибочно нарисованный элемент. Перемещение
к левой и правой границе поля осуществляется клавишами "Home" и "End",
а к верхней и нижней - клавишами "PageUp" и "PageDown".
Запуск
в автоматическом режиме прозводится по нажатии "Enter". Запуск в пошаговом
режиме - "Ctrl Enter". Для пошагового выполнения используется клавиша "Пробел".
Выход из игры - по "Esc".
На листинге
приведена одна из основных функций программы - функция Step_Game(), которая
выполняет анализ состояния ячеек игрового поля, определяет места рождения
новых фишек, отмечает гибнущие фишки, а также рисует на экране новые фишки
и удаляет "погибшие".
В заголовочном
файле "evolut.h" определена структура игрового поля (struct base), а также
прототипы функций.
Переменная
field определяет игровое поле в виде матрицы размера NxN. В начале игры
происходит выделение памяти под двойной указатель char** field, тем самым
формируется двумерный массив, предназначенный для хранения состояния ячеек
игрового поля. В начальном состоянии все ячейки поля обнулены - field[j][i]==0.
Структура
basepar определяет характеристики игрового поля и заполняется в фунциях
main() и Num().
Функция
Step_Game() вызывается после установки начальной конфигурации, т.е. формирования
на поле некоторой начальной фигуры. Ячейки, заполненные фишками принимают
значения field[j][i]=1. В течении каждого цикла игры функция Step_Game()
анализирует состояние игрового поля (матрицу field[j][i]) за три прохода.
При первом
проходе игрового поля происходит просмотр всех ячеек (переменная field).
Завершающий оператор этого прохода
if (summa==3) filed [j][i]=2;
определяет, что если ячейка граничит
ровно с тремя активными ячейками, то на очередном шаге игры на ней должна
быть установлена фишка. Сразу установить фишку (присвоить field[j][i]=1)
в данной ячейке нельзя потому, что при проходе производится анализ окрестности
каждой ячейки (8 соседних ячеек) и новорожденная ячейка может повлиять
на подсчет количества соседей для других ячеек, что приведет к ошибке.
Второй
проход предназначен для определения кандидатов на вымирание. Если такие
кандидаты найдены (заполненная ячейка одинока или соседствует больше, чем
с 3 активными ячейками), то выпоняется оператор
if ( (summa<2)||(summa>3) )
field [j][i]=3;
При третьем
проходе игрового поля осуществляется "истинное" рождение и умирание фишек.
При этом, происходит замена временных значений переменной field (2 и 3)
на постоянные (для данного шага игры) значения (0 и 1):
if (field[j][i]==2) field[j][i]=1;
if (field[j][i]==3) field[j][i]=0;
Одновременно
происходит прорисовка элементов игрового поля. Для этого используется функция
Draw_Element(), которой передается цвет, которым закрашивается ячейка.
Если фишку необходимо удалить, то цвет должен совпадать с цветом фона (basepar.field_color).
Если необходимо прорисовать новую фишку, то цвет устанавливается равным
активному цвету элемента (basepar.el_color).
Полное
описание Игры с исходными текстами программ доступно в электронной версии
журнала, а также на данной Web-странице.
Продукт
является бесплатным и открыт автором для доработки и усовершенствования.
Общий размер файлов в архиве составляет около 30 Кбайт. Автор c благодарностью
примет любые замечания и мнения, равно как и пожелания вступить в
клуб любителей игры "Жизнь", открываемый при редакции журнала "Компьютеры+Программы".