Моделирование предыдущей модели показывает, что развитие популяции дает колонию растений с плотным равномерный в разные стороны (анизотропным) заселением. При этом пространство захватывается слабо и медленно.
Возникает вопрос, можно ли применение простых алгоритмов расселения с более активным захватом территории.
Первый способ - изотропия. выбирать для расселения в первую очередь сначала по направлению вверх-вниз и слева-направо, а затем, если не найдется - по диагональным направлениям.
Скопируем модуль как u004_Jungle_anisotropic1.pas и подключим его в u_frmMain.pas. Свойства двух видов сделаем одинаковыми.
constructor TPlant.Create(AOwner: TComponent);
begin
inherited;
FPaintedAs := paSimpleFigure;
FPaintedAsFigure := acfSquare;
FColor := clGreen;
FReactionPeriod := 15 + Random(10);
FLimitLifeExpectancy := (1 + Random(3)) * FReactionPeriod + Random(3);
end;
Изменим TPlant2.Iterate таким образом, чтобы сначала выбиралось случайно из вертикально-горизонтальных направлений, потом из диагональных.
Запуск (004_Jungle_anisotropic_rass1.exe) к полезным результатам не приводит. Поразмыслив, приходим к выводу, что это правильно, потому что случайные расселения вверх-вних и слева-направо в среднем дают также и движение по диагонали.
Как заставить популяцию для скорейшего расселения сначала идьти по максимуму вдаль, а потом вширь? Придется отказаться от равномерного случайного расселения и перейти к логике.
Одно из решений, возможно - анализировать соседные клетки. Если с какой-то стороны есть растение, то высаживать новое растение с противоположной стороны. Не будем рассчитывать плотность, среднее арифметическое и заниматься прочим матаном. Мы овощ! Создаем список занятых соседних клеток. Выбираем случайную и садим на противоположной стороне. Если там занято, выбираем следующую случайную.
Скопируем модуль как u004_Jungle_anisotropic2.pas и подключием его в u_frmMain.pas. Свойства двух видов сделаем одиковыми.
constructor TPlant.Create(AOwner: TComponent);
begin
inherited;
FPaintedAs := paSimpleFigure;
FPaintedAsFigure := acfSquare;
FColor := clGreen;
FReactionPeriod := 15 + Random(10);
FLimitLifeExpectancy := (1 + Random(3)) * FReactionPeriod + Random(3);
end;
Обычное растение будет зеленым, растение с расселением преимущественно в свободную сторону - оливковым.
procedure TPlant2.Iterate;
var
gw: TGamingWorldChessed;
sg: TRandomIntSequenceGenerator;
dir, dirOpposite: TDirection;
firstTimes: array[0..7] of TDirection;
free: array[0..7] of TDirection;
countFirst, countFree: integer;
i: Integer;
begin
Inherited;
gw := (GamingWorld as TGamingWorldChessed);
if
(FAge <> 0)
and(FAge > FLimitLifeExpectancy)
then begin
gw.KillObject(Self);
Exit;
end;
if (FAge mod FReactionPeriod) = 0 then begin
sg := TRandomIntSequenceGenerator.Create;
try
//Определяем занятые и свободные клетки
countFirst := 0;
countFree := 0;
for dir := dLeft to dLeftDown do begin
dirOpposite := gw.Opposite(dir);
if
gw.ChessOccupee(Row, Col, dir)
then begin
if not gw.ChessOccupee(Row, Col, dirOpposite) then begin
firstTimes[countFirst] := dirOpposite;
Inc(countFirst);
end;
end
else begin
free[countFree] := dir;
Inc(countFree);
end;
end;
if countFirst > 0 then begin
dir := firstTimes[Random(countFirst)];
gw.PlaceObject(Clone(), Row, Col, dir);
end
else begin
if countFree > 0 then begin
dir := free[Random(countFree)];
gw.PlaceObject(Clone(), Row, Col, dir);
end;
end;
finally
sg.Free;
end;
end;
end;
Запуск (004_Jungle_anisotropic_rass2.exe) демонстрирует, что да, оливковое растение более агрессивно расселяется и довольно быстро побеждает зеленое.
Далее: Далее: Создание мира со многим количеством объектов. Создание тупого живого объекта, который может перемещаться и обходить препятствия. Это еще будет реализовано. Далее в задумках - моделирование муравьиной колонии, ориентация муравьев по запаху.
Ранее: dennis-pandemonium