Find the food

Рубрика: Development | 24 December 2006, 04:17 | juriy

Зверек, который получился в прошлой заметке, был не слишком жизнеспособным: побегав некоторое время вокруг – он погибал от голода. В этой заметке я постараюсь сделать так, чтобы зверь мог найти корм, хотя бы под собственным носом.
Перед тем, как приступить к написанию кода, надо рассмотреть два важных вопроса: как зверь может получить сведения о внешнем мире, и как на основании этих сведений узнать, что в клетке есть источник пищи.
Начнем по порядку.
Общие сведения о мире, которые не меняются на протяжении игры, можно получить, воспользовавшись классом universum.bi.Constants. К таким сведениям относится, к примеру, размер “джунглей” (ширина и высота). Кроме того, в этом классе “живут” константы, которые определяют механику игры: какое минимальное число энергии необходимо, чтобы произвести потомство, сколько энергии необходимо потратить на атаку, сколько на перемещение. Полный список констант можно посмотреть прямо в исходниках класса.
Информацию о том, по каким правилам проводится игра (тип игры: “дуэль”, “блицкриг” или “джунгли”) можно получить из объекта класса UserGameInfo, который передается в метод reinit вашего зверя.
Последний, и самый важный тип данных: это данные о том, как воспринимает себя и окружающий мир ваш зверек непосредственно в момент хода. К примеру: количество энергии зверька, или данные о клетке, на которой он стоит, или список клеток, на которые зверь может перейти за ход. Всю эту информацию можно получить из объекта класса BeingInterface, который передается в метод makeTurn вашего зверя.
Ниже – пример кода, который получает различные сведения о текущем состоянии джунглей.
[java]

public void printInfo() {
  // Сколько у зверя энергии (на момент хода)
  float currentHealth = world.getEnergy(this);
  // У Грокка не самый лучший английский :-)
  System.out.println("Grokk hav da " + currentHealth + " energi");

  // Получаем координаты клетки в которой находится зверь
  int myPositionX = world.getLocation(this).getX();
  int myPositionY = world.getLocation(this).getY();
  System.out.println("I standin in " + myPositionX + ":" + myPositionY);

  // Получаем данные о клетке, в которой мы находимся
  PointInfo pointInfo = world.getPointInfo(this);
  // получаем данные о том, есть ли в клетке еда!
  float foodCount = pointInfo.getCount(this);
  if (foodCount > 0)
    System.out.println("Yumi, yum! Got " + foodCount + " food");
  else
    System.out.println("Oh, no food!");
}
public Event makeTurn(BeingInterface world) {
  this.world = world;
  printInfo();
  return makeRandomMove();
}

[/java]
Таким образом – есть все необходимые инструменты для того, чтобы “научить” зверя “видеть” еду, если она лежит прямо под ногами.
Остановимся немного на том, как “действует” еда в электронных джунглях. Вы уже запускали эмулятор джунглей, поэтому не могли не заметить маленькие “яблочки” разбросанные по полю. Это и есть источники еды. Каждый источник характеризуется тремя величинами: количеством еды, доступным сейчас, максимальным возможным количеством еды и приростом еды за ход. Получить эти значения для каждой клетки можно, используя функции PointInfo.getCount, PointInfo.getMaxCount, PointInfo.getGrowthRate.
Есть два вида источников: “обычные” и “золотые”. “Золотые” отличаются от “обычных” тем, что все три описанных параметра для них существенно выше (и заполучить такой источник, соответственно, намного приятнее).
Все что осталось – запрограммировать зверька таким образом, чтобы он искал “еду”.
Напишем одну простую функцию, которая будет определять: достаточно ли хорош источник для того, чтобы остановиться на нем:
[java]
private boolean isHive(PointInfo pointInfo) {
return (pointInfo.getCount(this) > 0);
}
[/java]
Создадим маленькую функцию, которая будет форировать событие ACTION_EAT:
[java]
private Event doEat() {
return new Event(EventKind.ACTION_EAT, MASS*Constants.K_bite);
}
[/java]
Теперь остается модифицировать функцию makeTurn:
[java]
public Event makeTurn(BeingInterface world) {
this.world = world;

if (isHive(world.getPointInfo(this)))
return doEat();
else
return makeRandomMove();
}
[/java]
Все готово к тестовому запуску. В этот раз эмулятор джунглей лучше запустить так:
java -jar ejungle_distr.jar -altui -debug
В “альтернативном интерфейсе” можно выбрать View->Show Grid, чтобы отображались границы клеток (так легче контролировать, что зверь действует “по плану”), а опция -debug будет выводить в консоль описания всех событий с параметрами.
Ниже – код того, что получилось:
[java]
package ua.net.lab.beings;
import java.util.List;
import universum.bi.Being;
import universum.bi.BeingInterface;
import universum.bi.BeingParams;
import universum.bi.Constants;
import universum.bi.Event;
import universum.bi.EventKind;
import universum.bi.Location;
import universum.bi.PointInfo;
import universum.bi.UserGameInfo;
import universum.util.Util;
public class Grokk implements Being {

private final static float MASS = 10f;
private final static float SPEED = 2f;

private BeingInterface world;

public String getName() {
return “Grokk”;
}
public String getOwnerName() {
return “Juriy”;
}
public BeingParams getParams() {
return new BeingParams(MASS, SPEED);
}
public void reinit(UserGameInfo info) {
}
public Event makeTurn(BeingInterface world) {
this.world = world;

if (isHive(world.getPointInfo(this)))
return doEat();
else
return makeRandomMove();
}

private boolean isHive(PointInfo pointInfo) {
return (pointInfo.getCount(this) > 0);
}

private Event doEat() {
return new Event(EventKind.ACTION_EAT, MASS*Constants.K_bite);
}

public Event stepOneRight() {
Location myLocation = world.getLocation(this);
Location targetLocation = new Location(myLocation.getX() + 1, myLocation.getY());
return new Event(EventKind.ACTION_MOVE_TO, targetLocation);
}
private Event makeRandomMove() {
// Получаем список клеток, в которые можно попасть за ход
List<Location> canReach = world.getReachableLocations(this);

// Выбираем клетку случайным образом и создаем событие – движение
// в выбранную клетку.
return new Event(
EventKind.ACTION_MOVE_TO,
canReach.get(
Util.rnd(canReach.size())));
}
public void processEvent(BeingInterface bi, Event e) {
}
}
[/java]

Комментариев: 4

4 Responses to “Find the food”

Комментарии:

  1. x[82]

    Привет. Спасибо за статью. Хоть чуть-чуть разобрался. С документацией там действительно туго :) Стоит ждать продолжения?

  2. Tamerlan

    Привет! Отличный пост! И про груви тоже! Большое спасибо!

  3. vadim

    За отзывы о “What is groovy” – спасибо.
    А “зверьками” – это у нас Юра занимается, он любитель разных программерских игр.

  4. Юра

    Спасибо за отзывы.
    Я думаю, я напишу еще несколько статей про “виртуальных зверьков” сразу после того, как расчитаюсь со своим любимым универом :-) Я рад что статья вам понравилась!

Leave a Reply