Выразительный JavaScript (Хавербеке) - страница 76

просто притворяется, что там стена – если вы зададите мир без окружающих стен, существа не смогут сойти с края.

Оно двигается

Мы создали экземпляр мирового объекта. Теперь, когда все необходимые методы готовы, у нас должно получиться заставить его двигаться.

>for (var i = 0; i < 5; i++) {

>  world.turn();

>  console.log(world.toString());

>}

>// → … пять ходов

Просто выводить пять копий карты – не очень удобный способ наблюдения за миром. Поэтому в песочнице для книги (или в файлах для скачивания) есть волшебная функция >animateWorld, которая показывает мир как анимацию на экране, делая по три шага в секунду, пока вы не нажмёте стоп.

>animateWorld(world);

>// → … заработало!

Реализация >animateWorld пока останется тайной, но после прочтения следующих глав книги, обсуждающих интеграцию JavaScript в браузеры, она уже не будет выглядеть так загадочно.

Больше форм жизни

Одна из интересных ситуаций, происходящих в мире, случается, когда два существа отскакивают друг от друга. Можете придумать другую интересную форму взаимодействий?

Я придумал существо, двигающееся по стенке. Оно держит свою левую руку (лапу, щупальце, что угодно) на стене и двигается вдоль неё. Это, как оказалось, не так-то просто запрограммировать.

Нам нужно будет вычислять, используя направления в пространстве. Так как направления заданы набором строк, нам надо задать свою операцию >dirPlus для подсчёта относительных направлений. >dirPlus("n", 1) означает поворот по часовой на 45 градусов на север, что приводит к >“ne”. >dirPlus("s", -2) означает поворот против часовой с юга, то есть на восток.

>var directionNames = Object.keys(directions);

>function dirPlus(dir, n) {

>  var index = directionNames.indexOf(dir);

>  return directionNames[(index + n + 8) % 8];

>}


>function WallFollower() {

>  this.dir = "s";

>}


>WallFollower.prototype.act = function(view) {

>  var start = this.dir;

>  if (view.look(dirPlus(this.dir, -3)) != " ")

>    start = this.dir = dirPlus(this.dir, -2);

>  while (view.look(this.dir) != " ") {

>    this.dir = dirPlus(this.dir, 1);

>    if (this.dir == start) break;

>  }

>  return {type: "move", direction: this.dir};

>};

Метод >act только сканирует окружение существа, начиная с левой стороны и дальше по часовой, пока не находит пустую клетку. Затем он двигается в направлении этой клетки.

Усложняет ситуацию то, что существо может оказаться вдали от стен на пустом пространстве — либо обходя другое существо, либо изначально оказавшись там. Если мы оставим описанный алгоритм, несчастное существо будет каждый ход поворачивать налево, и бегать по кругу.