Простой AI - JavaScript (с использованием jQuery для анимации) - PullRequest
22 голосов
/ 26 мая 2011

Прежде всего, я хотел бы сообщить вам, что я занимаюсь программированием в течение нескольких лет (в основном на языках C, разработке для iOS, веб-технологиях и т. Д.) В качестве хобби, и сейчас у меня развивается интерес к созданию простогоИИ (большинство людей начинают с игры в крестики-нолики, да, но я заинтересован в том, чтобы сделать что-то, используя принципы генетического программирования).Причина, по которой я хотел бы, чтобы читатели знали об этом, заключается в том, что я был бы признателен, если бы ответы не были слишком сложными (не слишком сложными для понимания ребенком, поскольку я еще не посещал курсы информатики в колледже).

Вот моя цель:

Условия

organim: CSS div
популяция: группа организмов (5 или 10)
источник пищи: еще один CSS div

Процесс

  1. Создается популяция, каждая из которых изначально обладает одинаковыми фенотипическими признаками, но отличается по своим навыкам(для этого скорость)
  2. Создается один источник пищи (каждый раз один и тот же)
  3. Примерно через 5 секунд после настройки среды (шаги 1 и 2) населениеорганизмам необходимо найти способ получить доступ к источнику пищи на конкурентной основе
  4. Только один организм может достичь предмета питания.При достижении этого, среда сбрасывается , за исключением организма, который обнаружил продукт в предыдущий раз, теперь получает выгоду, и его уровень скорости может увеличиться, в то время как другие, которые сделали особенно ужасные, могут стать еще медленнее или быть прекращенными
  5. Процесс повторяется;пользователь может наблюдать особенности населения и видеть, какие из них преуспевают эволюционно и т. д.

Дополнительная информация

Таким образом, как вы можете видеть, вышеупомянутые шаги почти симулируют эволюцию, но вочень простой способ (меньше условий по сравнению с реальными жизненными ситуациями для животных);Теперь вот почему я спрашиваю здесь: я полностью потерян.Я действительно понятия не имею, с чего начать (кроме генерации населения, я, скорее всего, могу это сделать, а также заставить их перемещаться с помощью анимации jQuery).Но я не могу сейчас сделать так, чтобы их привлекли к источнику пищи.Итак, я бы хотел помочь в этом правильном направлении.

Ответы [ 3 ]

12 голосов
/ 26 мая 2011

Живой пример

Имейте в виду, это использует Рафаэль для рендеринга и подчеркивание для семантического сахара.

Я написал очень маленькую программу, которая соответствует вашим требованиям. (Это было весело).

1 Создается популяция, каждая из которых изначально обладает одними и теми же фенотипическими признаками, но различается по своим навыкам (для этого скорость).

var Critter = function() {
    // default the speed to something random.
    this.speed = SPEED + Math.random()*SPEED;

    // logic module
    var logic = function() { ... }
}

...
// initialize an array of critters.
critters: _.map(_.range(0,COUNT), function() {
    return new Critter;    
})

Создайте функцию конструктора для вашего члена группы, а затем заполните массив этих парней. Я сопоставил массив длины с массивом тварей. (Дерзкий за петлей).

Каждый созданный вами криттер будет похож, но у него будут разные навыки (на основе Math.random()), но они будут содержать одну и ту же логическую единицу.

2 Генерируется один источник пищи (каждый раз один и тот же)

// trivial Food object.
var Food = function() {
    // rectangle with random x, random y, and SIZE as width / height
    this.el = paper.rect(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE, SIZE);    
};

Конструктор объекта питания просто размещает квадрат на экране случайным образом

3 Примерно через 5 секунд после настройки среды (шаги 1 и 2) популяция организмов должна найти способ добраться до источника пищи на конкурентной основе

Настройка среды:

_.invoke(this.critters, "start", this.food.el.getBBox(), out_of_bounds);

Для каждого твари вы вызываете метод старта.

this.start = function(food) {
    // create a player (circle);
    this.el = paper.circle(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE / 2);  
    // set an interval to run the logic over and over.
    loop = setInterval(_.bind(logic, this, food), 25);    
};

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

4 Только один организм может достичь предмета питания. При достижении этого условия сбрасываются, за исключением того, что организм, обнаруживший продукт питания в предыдущий раз, теперь получает выгоду, и его уровень скорости может увеличиваться, в то время как другие, совершившие особенно ужасные действия, могут становиться еще медленнее или прекращаться

var logic = function(food) {
    // if you hit food you win
    if (this.el.collision(food)) {
        this.win();
    }
}

// you won
this.win = function() {
    console.log("win");
    // increase speed
    this.speed += Math.random()*5;  
    // end round
    Game.end();
};

Твари обнаружат, есть ли у них еда в логической петле. Получив еду, он вызывает свой собственный метод победы. Это завершает текущий раунд игры.

Когда зверь побеждает, он получает повышение скорости.

Игра перезапустится при вызове .end (после удаления всех текущих тварей)

end: function () {
    // tell all critters to end their round
    _.invoke(this.critters, "remove");
    // remove the food
    this.food.el.remove();
    // start again !
    this.start();
},

5 Процесс повторяется; пользователь может наблюдать особенности населения и видеть, какие из них преуспевают эволюционно и т. д.

Смотрите живой пример:)

6 Что дальше:

  • Настройка глобальных номеров и других жестко закодированных номеров
  • Реализация ИИ в функции logic.
  • Пройдите все jsfiddles от / 1 до / 180 и посмотрите, как это было сделано.
  • Пожаловаться, что комментарии недостаточно подробны
  • Выбросьте мой код и начните с нуля, теперь, когда вы видели пример.
  • Код рождения просто создает «базового» Криттера. Это не размножается из двух существующих твари и не имеет повышенных навыков. Это означает отсутствие эволюции.

Бонус:

Путешествие к еде

Предупреждение: Приведенная выше ссылка действительно движется к еде, но она делает что-то не так, я думаю, там есть хитрая ошибка. Я не думаю, что смогу исправить это.

Я объясню логику путешествия к еде

    // angle between critter and food
    var angle = Raphael.angle(
        this.el.getBBox().x,
        this.el.getBBox().y,
        food.x,
        food.y) - 135; // the 135 is the default direction (bottom right)
    // get a random speed
    var rand = Math.random()*this.speed;
    // travel towards the food box by rotating your vector by the angle
    var points = this.rotateVector([rand, rand], angle);

    // move towards the box
    this.el.translate(points[0], points[1]);

Сначала rand создает случайный вектор, который выглядит следующим образом:

enter image description here

Math.random() определяет, насколько далеко / быстро движется твари. Это указывает на нижний правый угол.

Поскольку он указывает на правый нижний угол, мы должны удалить 135 градусов от угла для этого вектора

enter image description here

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

enter image description here

Теперь у нас есть угол, и мы хотим повернуть наш вектор движения на этот угол. Вектор движения в данный момент направлен вверх (черный цвет), и мы хотим повернуть его на угол до новой позиции (красный цвет). В коде это this.rotateVector

enter image description here

Теперь указывали в правильном направлении! Мы можем просто позвонить this.el.translate(points[0], points[1])

0 голосов
/ 26 мая 2011

Вы можете взглянуть на различные реализации LIFE Конвея для вдохновения. Я полагаю, вы, возможно, уже видели нечто подобное?

Интересное чтение: Сотовые автоматы

0 голосов
/ 26 мая 2011

Вы должны разбить вашу проблему на две части:

Часть 1: организмы должны иметь возможность двигаться в направлении указанной вами точки. Что потребует таймера и некоторой математики, чтобы определить координаты, вы должны перемещать каждый организм, чтобы приблизить его на один шаг ближе к его цели для каждого такта таймера.

Google должен помочь вам найти математику для выполнения этой работы.

Часть 2. Организмам необходимо выбрать источник пищи (возможно, ближайший) и нацелиться на него, а затем использовать метод перемещения, описанный в части 1.

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

Опять же математика для определения расстояния между двумя наборами координат может быть найдена в Google.

Я не думаю, что могу изложить этот материал проще, чем я, но, надеюсь, это даст вам представление о том, в каком направлении двигаться дальше.

...