Более жизненная ситуация

Чтобы сделать жизнь в нашем мирке более интересной, добавим понятия еды и размножения. У каждого живого существа появляется новое свойство, energy (энергия), которая уменьшается при совершении действий, и увеличивается при поедании еды. Когда у существа достаточно энергии, он может размножаться, создавая новое существо того же типа. Для упрощения расчётов наши существа размножаются сами по себе.

Если существа только двигаются и едят друг друга, мир вскоре поддастся возрастающей энтропии, в нём закончится энергия и он превратится в пустыню. Для предотвращения этого финала (или оттягивания), мы добавляем в него растения. Они не двигаются. Они просто занимаются фотосинтезом и растут (нарабатывают энергию), и размножаются.

Чтобы это заработало, нам нужен мир с другим методом letAct. Мы могли бы просто заменить метод прототипа World, но я привык к нашей симуляции ходящих по стенам существ и не хотел бы её разрушать.

Одно из решений – использовать наследование. Мы создаём новый конструктор, LifelikeWorld, чей прототип основан на прототипе World, но переопределяет метод letAct. Новый letAct передаёт работу по совершению действий в разные функции, хранящиеся в объекте actionTypes.

function LifelikeWorld(map, legend) {

  World.call(this, map, legend);

}

LifelikeWorld.prototype = Object.create(World.prototype);

var actionTypes = Object.create(null);

LifelikeWorld.prototype.letAct = function(critter, vector) {

  var action = critter.act(new View(this, vector));

  var handled = action &&

    action.type in actionTypes &&

    actionTypes[action.type].call(this, critter,

                                  vector, action);

  if (!handled) {

    critter.energy -= 0.2;

    if (critter.energy <= 0)

      this.grid.set(vector, null);

  }

};

Новый метод letAct проверяет, было ли передано хоть какое-то действие, затем – есть ли функция, обрабатывающая его, и в конце – возвращает ли эта функция true, показывая, что действие выполнено успешно. Обратите внимание на использование call, чтобы дать функции доступ к мировому объекту через this.

Если действие по какой-либо причине не сработало, действием по умолчанию для существа будет ожидание. Он теряет 0,2 единицы энергии, а когда его уровень энергии падает ниже нуля, он умирает и исчезает с сетки.