В 40-е годы XX века работа Фон Неймана в области самовоспроизводящихся машин привела к появлению теории клеточных автоматов. Оттуда же берёт своё начало не безызвестная "Game of Life" - математическая модель примитивной жизни захватывающая умы простотой своего описании и сложностью порождаемых ею систем.
Футуристы тех лет считали, что эти исследования помогут в ближайшем будущем покорить Марс - где даже одного самореплицирующегося автомата хватит, чтобы он, скрупулёзно следуя алгоритму заложенному при его создании, смог основать целую колонию таких машин. Которые занялись бы терраформингом и приготовлением планеты к прибытию колонистов из плоти и крови.
Мы же предлагаем вам приобщиться к этому делу в игровой форме. Вы можете попробовать себя в роли разработчика таких машин в TorLand и положить начало новой искусственной жизни, более того всё это можно сделать в пределах окна вашего браузера.

Бот - модель примитивного организма
Боты населяют клетчатое квадратное поле с замкнутыми сторонами. Подобно почти всем живым существам они обладают:
Памятью;
Потребностью в энергии;
Ориентацией в пространстве;
Возрастом;
Органами чувств.
И самое главное они обладают генами. В TorLand'е геном - это результат компиляции Assembly-like кода, который описывает поведение бота. Язык описания генома бота называется BotLang подробнее о деталях его синтаксиса можно почитать вот здесь.
Мы же рассмотрим пример простого генома - JXELCCIAIAEAGQH72HBF5RH545ZBQAYKDI4EEIWUBEYGASHJJ5U6H4GPP3JQK
. Который был скомпилирован из следующего кода
start: // объявление метки
eatsun // поглощение энергии солнца
cmpv en 1500 // сравнение уровня энергии с константой
jle start // переход на метку start, если En <= 1500
fork right start // деление с созданием новой колонии справо,
// новый бот начинает выполнение кода с метки start
mov front // пройти на 1 клетку вперёд относительно "лица" бота
Этот простой организм ждёт накопления достаточного уровня энергии, которую он получает из солнца. После чего размножается делением, порождая нового бота справа, а затем делает один шаг вперёд. Так как fork
это довольно энергоёмкая операция, старый бот тут же погибает после передвижения в новую клетку. Создавая тем самым ощущение бегущей волны.

В симуляции первое время всё идёт согласно нашему замыслу элегантно описанному в коде. Но в конце один из ботов неожиданно покидает стройные ряды своих собратьев и отправляется на встречу к неизведанному.
Это не что иное как эволюция - случайное изменение генома нового бота, которое может произойти с некоторой вероятностью при каждом использовании команды fork
.
Если же вам не по душе такая непредсказуемость вы всегда можете использовать аналогичную команду split
, которая гарантирует отсутствие мутаций в новом организме. Или же вообще отключить возможность случайной мутации, установив её вероятность равной нулю в настройках мира.
NiLang
В романе "Мир-Кольцо" Ларри Нивен описывает массивную супер-структуру - кольцо опоясывающее звезду и являющееся домом для множества биологических видов собранных по всей галактики загадочными создателями этого чуда света.

С точки зрения топологии мир в котором существуют боты аналогичен Миру-кольцу. Квадрат с замкнутыми сторонами представляет из себя двухмерную проекцию поверхности Тора.

NiLang - это высокоуровневый язык программирования ботов TorLand'а, получивший своё название от первых слогов имени и фамилии автора "Мир-Кольцо" - Ларри Нивена.
Геном бота из нашего первого примера можно описать следующей программой на NiLang'е.
Using bot
Fun Charge$ energy Int:
While GetEnergy < energy:
ConsumeSunlight # function call without arguments
Charge$1500
Fork$dir::right
Move$dir::front
Как видите, синтаксически NiLang очень похож на Python, хотя в отличие от него является статически типизированным языком. Если вам интересно полное описание синтаксиса NiLang'а и другая информация о нём, то вы можете найти её здесь.
А теперь давайте перейдём к примерам куда более комплексных организмов.
Примеры
Шахматная доска
Начнём с простого, заполним тор ботами в шахматном порядке. Алгоритм здесь довольно простой:
Зарядиться энергией;
Если клетка справа спереди свободна, породить нового бота там;
Повернуться на право;
Обойдя все четыре стороны перейти в режим "растения" - вечный цикл накопления энергии.

Using bot
Fun Charge$ energy Int:
While GetEnergy < energy:
ConsumeSunlight
Int i = 0
While i < 4:
Using dir
Charge$1500
If IsEmpty$frontRight:
Fork$frontRight
Face$right
i = i + 1
While True:
ConsumeSunlight
Поле цветов
Переходя к более сложным организмам, мы можем воспользоваться генетической памятью - возможностью бота передавать своему потомку информацию. Для создания цветка нам потребуется три роли:
Корень - основания от которого будут расти ветки нашего цветка;
Ветка - кусок цветка, который породит семечку;
Семечко - подвижная часть организма, которая отвечает за создание нового цветка.

Using bot
Int _ENERGY = 1500
Int _BRANCH_LENGTH = 5
Int _SPREAD_DISTANCE = 45
Fun Charge$ energy Int:
While GetEnergy < energy:
ConsumeSunlight
Fun PlantLoop:
While True:
ConsumeSunlight
Fun Root:
Int i = 0
While i < 4:
Charge$_ENERGY
Face$dir::left
Fork$dir::front
i = i + 1
Fun Seed:
Int d = 0
While d < _SPREAD_DISTANCE:
Charge$100
Move$dir::frontRight
d = d + 1
WriteMemory$1
Root
Fun Branch:
Charge$_ENERGY
Fork$dir::front
Int stage = 0
If IsMemoryReady:
stage = ReadMemory
WriteMemory$stage+1
If stage < 1:
Root
Elif stage >= 1 And stage <= _BRANCH_LENGTH:
Branch
Elif stage > _BRANCH_LENGTH:
Seed
PlantLoop
Змейка
До сих пор наши боты существовали в мире с равномерным распределением ресурсов. Но в TorLand'е также можно создать мир разделённый на кластеры, где количество доступного солнечного света и минералов из которых бот получает энергию варьируется (жёлтые участки богаты солнцем, а синие минералами).
Змейка использует свои органы чувств, чтобы расти только в сторону участков карты богатых на солнечное излучение.

Using bot
Using dir
Int _ENERGY_PER_SPLIT = 1000
Int _INT_MIN = -2000
Fun Charge$ energy Int:
While GetEnergy < energy:
AbsorbMinerals
ConsumeSunlight
Fun GetEn::Int$dir Dir:
If IsEmpty$dir:
Return -GetLuminosity$dir
Return _INT_MIN
Int ft = GetEn$front
Int fr = GetEn$frontRight
Int rt = GetEn$right
Int br = GetEn$backRight
Int bt = GetEn$back
Int bl = GetEn$backLeft
Int lt = GetEn$left
Int fl = GetEn$frontLeft
Fun IsMax::Bool$x Int:
Return x >= ft And x >= fr And x >= rt And x >= br And x >= bt And x >= bl And x >= lt And x >= fl
Charge$_ENERGY_PER_SPLIT + _ENERGY_PER_SPLIT/2
If IsMax$ft:
Split$front
Elif IsMax$rt:
Split$right
Elif IsMax$bt:
Split$back
Elif IsMax$lt:
Split$left
Elif IsMax$bl:
Split$backLeft
Elif IsMax$br:
Split$backRight
Elif IsMax$fl:
Split$frontLeft
Elif IsMax$fr:
Split$frontRight
While True:
ConsumeSunlight
Песок и платформа
Как ни странно, но при помощи ботов можно сделать простой симулятор частиц. Правда для этого понадобиться отключить старение (сделать очень большим параметр мира Штраф к энергии за возраст
), а также понизить Расход энергия за деление
и Расход энергии за шаг
.

Код бота платформы
Using bot
Using dir
While True:
If IsEmpty$back:
Move$back
Elif IsEmpty$backRight:
Move$backRight
Elif IsEmpty$backLeft:
Move$backLeft
Else:
While True:
ConsumeSunlight
Код бота частицы
Using bot
Using dir
While True:
If IsEmpty$back:
Move$back
Elif IsEmpty$backRight:
Move$backRight
Elif IsEmpty$backLeft:
Move$backLeft
Else:
While True:
ConsumeSunlight
Ссылки
Страница TorLand на GitHub;
Документация к BotLang;
Страница NiLang на GitHub;
Онлайн-Компилятор BotLang и NiLang, а также онлайн версия TorLand'а.