Книга: Выразительный JavaScript

Программный интерфейс существ

Программный интерфейс существ

Перед тем, как заняться конструктором мира World, нам надо определиться с объектами существ, населяющих его. Я упомянул, что мир будет спрашивать существ, какие они хотят произвести действия. Работать это будет так: у каждого объекта существа есть метод act, который при вызове возвращает действие action. Action – объект типа property, который называет тип действия, которое хочет совершить существо, к примеру “move”. Action может содержать дополнительную информацию – такую, как направление движения.

Существа ужасно близоруки и видят только непосредственно прилегающие к ним клетки. Но и это может пригодиться при выборе действий. При вызове метода act ему даётся объект view, который позволяет существу изучить прилегающую местность. Мы называем восемь соседних клеток их направлениями по компасу: “n” на север, “ne” на северо-восток, и т. п. Вот какой объект будет использоваться для преобразования из названий направлений в смещения по координатам:

var directions = {
  "n":  new Vector( 0, -1),
  "ne": new Vector( 1, -1),
  "e":  new Vector( 1,  0),
  "se": new Vector( 1,  1),
  "s":  new Vector( 0,  1),
  "sw": new Vector(-1,  1),
  "w":  new Vector(-1,  0),
  "nw": new Vector(-1, -1)
};

У объекта view есть метод look, который принимает направление и возвращает символ, к примеру "#", если там стена, или пробел, если там ничего нет. Объект также предоставляет удобные методы find и findAll. Оба принимают один из символов, представляющих вещи на карте, как аргумент. Первый возвращает направление, в котором этот предмет можно найти рядом с существом, или же null, если такого предмета рядом нет. Второй возвращает массив со всеми возможными направлениями, где найден такой предмет. Например, существо слева от стены (на западе) получит [“ne”, “e”, “se”] при вызове findAll с аргументом “#”.

Вот простое тупое существо, которое просто идёт, пока не врезается в препятствие, а затем отскакивает в случайном направлении.

function randomElement(array) {
  return array[Math.floor(Math.random() * array.length)];
}
function BouncingCritter() {
  this.direction = randomElement(Object.keys(directions));
};
BouncingCritter.prototype.act = function(view) {
  if (view.look(this.direction) != " ")
    this.direction = view.find(" ") || "s";
  return {type: "move", direction: this.direction};
};

Вспомогательная функция randomElement просто выбирает случайный элемент массива, используя Math.random и немного арифметики, чтобы получить случайный индекс. Мы и дальше будем использовать случайность, так как она – полезная штука в симуляциях.

Конструктор BouncingCritter вызывает Object.keys. Мы видели эту функцию в предыдущей главе – она возвращает массив со всеми именами свойств объекта. Тут она получает все имена направлений из объекта directions, заданного ранее.

Конструкция || "s" в методе act нужна, чтобы this.direction не получил null, в случае если существо забилось в угол без свободного пространства вокруг – например, окружено другими существами.

Оглавление книги


Генерация: 1.296. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз