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

From
Anton Zykov (2:5066/40)
To
Andrey Trubitsyn
Date
2000-02-26T10:51:15Z
Area
RU.ALGORITHMS
Thrive, thou glory Andrey!

Monday February 21 2000 20:59, you wrote to All:

 AT>          Алгоритм подскажите, может есть какой !
    Не самый сложный, из всех, выдуманных мной, для стратегических игр дает
весьма неплохой результат, без учета тактики игры, по крайней мере я им почти
всегда пользуюсь:

    Есть массив Map[MxN] - карта. Он заполняется случайными значениями из
интервала [-K1..K2-1], где соотношение K1/K2 - суша/вода, К1+К2, как правило,
зависит от размера разрядной сетки (я беру 256 - этого более, чем достаточно,
К1=96, К2=160).

    Затем проводится цикл из L итераций, L=sqrt3(K1+K2)+0.5, (в д.с. L=7),
каждая итерация - это непереполняющая интерполяция ("сглаживание") соседних
значений массива.
Map[i,j] = round(Sum(Map[i'',j''])/9),        _______       _______
                                       где i'=i-1,i+1, а j'=j-1,j+1.
    В случае, если карта должна быть
    1. сферической, переполнение координат считаем: i''=i'%M, j''=j'%N (% -
остаток от деления),
    2. цилиндрической по одной из координат: Map[i'',j'']=0 для (i''<0 ||
i''>M-1) или (j''<0 || j''>N-1) соответственно, i''=i', j''=j'.
    3. плоской: Map[i'',j'']=0 для (i''<0 || j''<0 || i''>M-1 || j''>N-1),
i''=i', j''=j'.
    В результате получается карта суши и морей(океанов, озер). Суша, если
Map[i,j]>=0, иначе - водоем (озеро, море, океан, ...)

    Реки строятся следующим образом: На суше (Map[i,j]>=0) случайным образом
находится точка с координатами (i,j), затем методом перебора соседних точек
находятся такие Map[i',j'], что разница Map[i,j]-Map[i',j'] наибольшая для всех
   _______     _______
i'=i-1,j-1, j'=j-1,j+1. Если найдется несколько i',j' таких, что
Map[i,j]-Map[i',j'] для них одинакова, то река раздваивается/растраивается
(обтекает препятствия). Затем считаем i=i',j=j'. И так в цикле до тех пор, пока
Map[i',j'] не окажется меньше 0 (речка влилась в водоем) или не окажется, что в
этой точке уже есть другая река.

    Леса: строится еще один массив Map'[MxN] значений из интервала [0..P],
интерполируется аналогичным способом, но количество итераций L= sqrt4(P), pfntv
считаем (я считаю, можешь попробовать свои значения):
    1. Map[i,j]<0
    1.1. 0<=Map'[i,j]<(P/4) - концентрация водорослей на дне водоема,
    2. Map[i,j]>=0
    2.1. 0<=Map'[i,j]<(P/4) - пустыня,
    2.2. (P/4)<=Map'[i,j]<(P*3/4) - поля, луга, камень... - определишь любым
         понравившимся способом,
    2.3. (P*3/4)<=Map'[i,j]<P - лес.
    На этом этапе я обычно прохожусь по карте Map' и заменяю ее значения на
т.н. "тип земли"=0..3. Затем накладываю значения Map'[i,j] на значения
Map[i,j], естественно, учитывая последние (море, земля, река).  Хотя все
зависит от настроения в момент написания генератора. Иногда иду более сложным и
интересным путем. Но в большинстве случаев достаточно и этого.

    Вот, в общем-то и все. ;)

ЗЫ  Серьезный недостаток этого способа: требовательность к вычислительной
мощности. Для карты 1024х1024 (это очень большая карта для большинства случаев)
- ожидание уже очень грустно выглядит. :(

ЗЗЫ Для ускорения расчетов я иногда при интерполяции пренебрегаю одним из
соседних значений Map[i'',j''] (например, i''=i+1, j''=j+1). При этом формула
заменяется на Map[i,j]=trunc((Sum(Map[i'',j''])+4)/8), что работает намного
быстрее на ассемблере (N/8 = N>>3).

ЗЗЫ В некоторых случаях необходима большая точность. В таких случаях я создаю
карту размера [M/U,N/U], где U - погрешность (например, U=16). Получается
карта, состоящая из "квадратов". Для получения точных значений на карте
используется какая-нибудь шумовая функция с простой реализацией и
интерполируется с краевыми значениями нужного "квадрата".

                                    Ave, Andrey!
    ·-─═╦═════════───-──--··· · ··--──-───────── Crystal Falcon ──-──--··  ·
--- -──═╩══╦═─ GoldEd/W32 ──--·· ·
 * Origin: ╚════── Dare to LIVE, dare to DREAM ─────-──-─---··  · (2:5066/40)