Коллективная охота стаями в Microsoft Terrarium

Задача состоит в том, чтобы организовать охоту за травоядными с помощью объединения хищников в стаи. Вначале требуется детальное описание - постановка задачи. Главное сосредоточится на разделении данной задачи на части - подзадачи. Какие подзадачи вы здесь видите ? Каким образом охотятся стаи хищников ? Какие алгоритмы нужно реализовать вначале ? Приветствуются любые конструктивные подходы, затем мы их отточим и реализуем соответствующие алгоритмы.



## Ваши вариации

- Ну тут есть несколько вариантов, как это сделать. Вариант 1: объединить существ в стаи и уже ими управлять (наверное через новый класс). Вариант 2: объединяя существ в стаи, выбирать вожака этой стаи, который и будет охотиться, а остальные члены стаи будут просто повторять его действия. Я так понимаю, вариант 2 попроще в реализации и даже пореалистичнее. Тогда рассмотрим его поподробнее. Алгоритмы (на мой взгляд) таковы: во-первых, нужно запрограммировать отличие вожака от рядового члена стаи, во-вторых нужно прописать, что будет делать стая после смерти вожака, в третьих нужно создать алгоритм создания стаи. А вот как всё это реализовать, ума не приложу... Freelancer Alex 14:38, 15 февраля 2010 (UTC)



## Этапы решения

### Формирование стаи

При любых вариантах, начинать нужно именно с формирования стаи, так как без неё собственно не будет охоты. Ниже прошу предлагать варианты на основе чего стая будет формироваться. (Отмечаем, что кроме разделения на подзадачи, нужно выделять наиболее необходимое и расставлять приоритеты, детали и тонкости оставляя на потом) S.J. 15:18, 15 февраля 2010 (UTC)

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

#### Способы формирования стаи

- Ну, например, если в поле зрения существа попадает существо того же вида, то формируется стая, при этом выбирается вожак(либо самый большой по размеру, либо рандом). Если же на пути стаи попадается одиночное существо того же вида, то оно присоединяется к стае (при этом может проводиться проверка, является ли это существо самым большим, если да, то оно становиться вожаком). Что-то делать будет лишь сам вожак, остальные члены стаи будут повторять его действия (передвижение, атака, еда). Как-то так... Freelancer Alex 15:47, 15 февраля 2010 (UTC)
- Вопрос с вожаком можно отложить. Начать нужно с (1) определения какой вид видит существо и (2) алгоритма присоединения. Тем самым мы выделяем два метода. Попробуйте реализовать. Обдумайте входные/выходные данные и что будет внутри, можно псевдокодом, т.е. по пунктам что нужно сделать. S.J. 17:36, 15 февраля 2010 (UTC)




##### Метод «Отбор своих»

**№ 1.** Squad - массив, объявленный в начале класса.

```
public ArrayList Squad = new ArrayList();
public void FoundMySpecies()
{
try
{
ArrayList FoundAnimals = Scan();
if (foundAnimals.Count > 0)
{
foreach (OrganismState organismState in foundAnimals)
{
if (organismstate is AnimalState && IsMySpecies(organismState))
{ Squad.Add(organismState); }
}
}
}
catch (Exception exc)
{
WriteTrace(exc.ToString());
}
}
```

**№ 2.** Чем лучше/хуже эта реализация по сравнению с №1 ?

```
public ArrayList GetMySpecies()
{
ArrayList retArray = new ArrayList();
try
{
ArrayList foundAnimals = Scan();
if (foundAnimals.Count > 0)
{
foreach (OrganismState organismState in foundAnimals)
{
if (organismState is AnimalState && IsMySpecies(organismState))
{
retArray.Add(organismState);
}
}
}
}
catch (Exception exc)
{
WriteTrace(exc.ToString());
}
return retArray;
}
```

- Тем №1 хуже, что при каждом вызове метода №2, массив создаётся по новой, и, соответственно, очищается (этого как раз я и не учёл). Ещё тем, что в №2 можно использовать функцию, и не вводить глобальную переменную, которая, как я понимаю, будет затормаживать программу. Freelancer Alex 15:31, 16 февраля 2010 (UTC)
- Практически все верно. Единственно, скорость тут не столько важна. Просто стоит минимизировать использование глобальных переменных (хоть это и не совсем глобальная (а уровня класса), чисто глобальные создать в C# невозможно - за что спасибо авторам языка), из-за них сложно выделять и потом работать с методами, нужно стараться сделать метод самодостаточным. Но при некоторых условиях, ваш вариант тоже мог бы быть, но не в этих. Например, если бы мы хотели реализовать память существа, то это было бы именно так, но тогда нужно было бы подумать о том, чтобы чистить память от устаревших сведений. S.J. 22:00, 16 февраля 2010 (UTC)


### Передвижение стаи

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

#### Метод «Следование за своими»

???

Нужные свойства:

- OrganismState.Point Position - Возвращает местоположение существа в данный момент в виде точечной структуры. Возвращаемое значение: System.Drawing.Point, представляющее местоположение существа в данный момент.
- OrganismState.Boolean IsStopped - Определяет, двигается существо или полностью остановилось. Возвращаемое значение: True, если существо двигается, в противном случае - False.
- OrganismState.Int32 Speed - Определяет скорость, с которой существо перемещается.
- OrganismState.Int32 ActualDirection - Определяет в градусах направление, в котором движется существо. При использовании вместе со Speed позволяет рассчитать местоположения существа в будущем.

- Прежде всего, извиняюсь за долгое отсутствие, некоторое время не было возможности продолжать обучение. Вопрос: как (и можно ли) преобразовать тип object в тип OrganismState? Т.е. получая список из функции GetMySpecies, необходимо выделить оттуда существ, для работы с их атрибутами (скорость, направление и т.п.), а привести типы не получается (наверное, я мыслю не в том направлении( ) Freelancer Alex 17:33, 27 февраля 2010 (UTC).
- Действительно массив, получаемый из GetMySpecies, имеющий тип ArrayList хранит элементы как object. Т.е. любые объекты. Если мы сохраняли тип OrganismState как object (методом Add), то сможем получить и обратно (иначе нет). Есть несколько способов. Если мы уверены, что там хранится OrganismState, то можно делать прямое приведение типов. Делается так OrganismState locState = (OrganismState) MyArray[index]; S.J. 18:03, 27 февраля 2010 (UTC)
- В процессе обдумывания возник ещё такой вопрос: вот например, одно существо увидело другое. Как первое "поймёт", одиночка ли второе существо, или уже следует за кем-то? Ведь первое существо может не увидеть остальных членов стаи. Freelancer Alex 08:55, 28 февраля 2010 (UTC)
- Думаю, на данном уровне это не актуально, нужно ориентироваться только на то, что видит существо. После чего сделаем вариант с памятью (учитывая что он потерял из виду). И тогда уже встанет задача сравнения - а это уже интересно. S.J. 22:09, 2 марта 2010 (UTC)


- В процессе обдумывания возник ещё такой вопрос: вот например, одно существо увидело другое. Как первое "поймёт", одиночка ли второе существо, или уже следует за кем-то? Ведь первое существо может не увидеть остальных членов стаи. Freelancer Alex 08:55, 28 февраля 2010 (UTC)

- Действительно массив, получаемый из GetMySpecies, имеющий тип ArrayList хранит элементы как object. Т.е. любые объекты. Если мы сохраняли тип OrganismState как object (методом Add), то сможем получить и обратно (иначе нет). Есть несколько способов. Если мы уверены, что там хранится OrganismState, то можно делать прямое приведение типов. Делается так OrganismState locState = (OrganismState) MyArray[index]; S.J. 18:03, 27 февраля 2010 (UTC)

#### Способы передвижения стаи

- Двигается только вожак по тем же функциям, что и простое одиночное существо. Остальные члены стаи повторяют его действия. Я думаю, что передвижение нужно сделать рандомно, до встречи с другими существами. При встрече с ними, атаковать (реализовывать, я думаю, нужно примерно так, как реализован поиск растений у травоядного). Freelancer Alex 15:47, 15 февраля 2010 (UTC)