Найти тему
Invariant World

Population(Популяция)

Оглавление

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

Для работы с населением я ввел два новых объекта: Population(Популяция) и Checkpoint(чекпоинт).

В этой статье я опишу что такое Популяция.

Описание:

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

Популяция имеет ряд своих параметров и методов работы с ней.

Параметры:

Раса:

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

А также важно количество полов в этой расе для соединения в группы для создания потомства.

Поколение:

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

Параметры полов и Возрастных групп:

Далее у нас идут параметры для каждого пола и его возрастных групп, указанных в поколении популяции.

Для каждой возрастной группы задаются два параметра:

  • Количество - численность представителей популяции в возрастной группе.
  • Заполняемость - период появления первого и последнего представителя популяции в этой возрастной группе от начала периода рождения поколения. Это важный параметр для расчета взросления представителей популяции.

Методы работы с популяцией:

Популяция имеет ряд функций и процедур для работы с ней и для изменения её параметров.

Процедура отработки смертности:

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

Единственный нюанс заключается в округлении. Для последней возрастной группы округлять нужно до верхнего целого числа, так как если смертность у неё будет меньше 50%, то один или несколько представителей этой возрастной группы будут просто бессмертными. Для остальных возрастных групп это не подойдет, так как в этом случае при малых количествах их представителей смертность будет 100%. В остальных возрастных группах округление идет до ближайшего целого.

Процедура взросления:

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

Тут нам помогает параметр "Заполняемость", который имеет начало появления первого и время последнего нового представителя возрастной группы. Как это работает?

Если с момента появления первого представителя не прошло нужное количество лет для прохождения этого представителя по всему промежутку возрастов группы (начало заполняемости + длительность возрастной группы), то еще ни один из представителей не успел повзрослеть и некому переходить в следующую группу.

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

Для промежуточного же состояния я высчитываю сколько лет осталось самому младшему представителю и рассчитываю процент повзрослевших.

//Отрабатываем переход в следующую возрастную группу повзрослевших
//берем количество представителей возрастной группы
var members = populationSex.AgeGroupCounts[ii];
//если там никого нет, то с ними делать нечего
if (members <= 0) continue;
//высчитываем количество повзрослевших
uint migrationCount = 0;
//заполняемость возрастной группы
var period = populationSex.AgeGroupFilling[ii];
//возраст группы
var age = generationSexAgeGroup.Age;

//если еще никто не повзрослел
if (yearsFromStart < age.Count + period.StartYear) continue;
//если повзрослели все
if (yearsFromStart >= age.Count + period.StopYear)
{
migrationCount = members;
}
else //в промежутке
{
//прошедшее время с момента последнего нового представителя
var d = period.StopYear != 0 ? yearsFromStart - period.StopYear : 0;
//из количества возрастов отнимаем прошедшее время
//получаем сколько лет осталось самому младшему представителю + 1
var c = age.Count - d;
migrationCount = members / c;
}

Соответственно все повзрослевшие переходят в следующую группу, обновляя у неё период заполнения.

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

Функция расчета новорожденных:

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

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

Процедура заполнения новорожденными:

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

Процедура конвертации в другое поколение:

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

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

Итого:

Получился очень интересный объект и он будет использоваться много где теперь. Как? Читайте дальше ;)

P.S. Ставьте лайки, подписывайтесь, пишите комментарии. Это позволит развить блог и делиться в нем всем интересным в моих проектах. А на этапах тестирования гипотез и прототипов мнение большого числа людей будет очень важно.

P.P.S. для лучшего понимания статьи рекомендую прочитать предыдущие:
Идея первого проекта
Карта Хронологии
Теория поколений