empserver/tests
Markus Armbruster fdd55428c3 fairland: Rewrite complicated, buggy & boring elevation code
Land elevation is computed by first placing mountains, then elevating
land to fit.

Mountains placement is a weighted random sampling.  A sector's weight
is its distance to sea capped at five and squared.

Non-mountain, non-capital sectors get assigned equidistant elevations
from 1 up to 97 rounded to integer in an order that depends on
distance to mountain and distance to sea, both capped at 5.  Mountains
get equidistant elevations starting at 98 (see recent commit
"fairland: Fair mountain resources").  Capitals get 36.

Sea elevation is randomly chosen from a range that depends on the
sector's distance to land.  The range increases from [-27,-1] next to
land to [-127,-1] for distance 5 and up.

Without mountains, the result is boring: elevation increases pretty
much linearly with the distance from the coast, i.e. each islands is a
single cone.  With mountains, we get one cone per mountain.  The sea
sea elevations are basically noise.

Worse, it's buggy: mountain placement can place fewer mountains than
requested.  The weighted random sampling assigns weights even to
sectors that cannot be picked (capitals and sectors that have been
picked already).  When the dice land on such a sector, it instead
picks the next one (in island growth order) that can be picked.  If
there is no next one, the mountain is not placed.  This is a fairness
issue.

Impact varies with fairland parameters.  For 60 sector islands with 5%
mountains, around one in 10000 islands is short one mountain in my
testing.  For 10 sector islands with 50% mountains, some 760 out of
10000 islands are short one sector, 80 short two, and five short
three.  The numbers get worse as spikiness increases.

Undocumented misfeature: the placement loop is limited to 1000
iterations, supposedly to catch a runaway loop.  Since the loop
iterates exactly once per mountain, all this accomplishes it limiting
mountains to 1000 per island.

When too few mountains are placed, the loop assigning elevations to
non-mountain, non-capital decrements elevations below 1.  Since
Chainsaw 3, such elevations then get mapped to 1, plastering over the
bug.  We get non-mountain sectors with elevation 1 instead of
mountains.

Rewrite as follows.

Use a simple random hill algorithm to assign raw elevations:
initialize elevation to zero, then randomly raise circular hills on
land / lower circular depressions at sea.  Their size and height
depends on the distance to the coast, capped at 3.  After a sufficient
number of iterations, the resulting terrain has a "natural" look.
This is elevate_prep().

elevate_land() then sorts non-capital sectors by raw elevation.  The
highest become mountains.  Sectors get assigned the same equidistant
elevations as before, just in raw elevation order.

elevate_sea() simply normalizes raw elevation to [-127,-1].

Elevations now show a nice undulating pattern independent of mountain
percentage.

Implementation detail: replace elev[x][y] by elev[XYOFFSET(x, y)], and
narrow the element type from int to short.  Takes a fourth the space.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
..
actofgod subs: Maintain plane and land unit fortification invariant 2021-01-05 10:40:34 +01:00
bridgefall relations: Move relations state from struct natstr to relatstr 2017-08-06 20:09:22 +02:00
build Spell harbor consistently 2017-08-07 10:08:31 +02:00
empdump config: Generalize infrastructure build materials storage 2017-08-06 20:09:19 +02:00
fairland fairland: Rewrite complicated, buggy & boring elevation code 2021-01-17 21:24:28 +01:00
files relations: Move relations state from struct natstr to relatstr 2017-08-06 20:09:22 +02:00
fire damage: Shield embarked planes and land units from sector damage 2021-01-05 10:41:28 +01:00
info tests/info: New; checks info and code agree on commands 2014-01-06 20:50:06 +01:00
load-tend load: Factor out plane_loadable(), land_loadable() 2021-01-05 07:25:18 +01:00
navi-march edit: Fix fortification limit of embarked planes and land units 2021-01-05 10:38:57 +01:00
retreat damage: Shield embarked planes and land units from sector damage 2021-01-05 10:41:28 +01:00
smoke Correct spelling as one word and as two words 2017-08-07 10:08:31 +02:00
torpedo Correct spelling as one word and as two words 2017-08-07 10:08:31 +02:00
update update/revolt: Fix land unit casualties 2018-04-29 10:33:48 +02:00
version Update copyright notice 2021-01-05 10:41:28 +01:00
actofgod-test tests: Define and use some abbreviations 2015-02-01 16:52:59 +01:00
bridgefall-test tests: Define and use some abbreviations 2015-02-01 16:52:59 +01:00
build-test tests: Define and use some abbreviations 2015-02-01 16:52:59 +01:00
empdump-test tests/empdump: Fix to honor "make check-accept" 2021-01-05 10:41:35 +01:00
fairland-test fairland: Make actual island sizes fair 2021-01-05 10:41:37 +01:00
files-test tests/files tests/fairland: Check stderr and exit status 2015-02-01 16:52:59 +01:00
fire-test tests: Define and use some abbreviations 2015-02-01 16:52:59 +01:00
info-test tests: Define and use some abbreviations 2015-02-01 16:52:59 +01:00
load-tend-test tests/load-tend: New; exercises load and tend commands 2021-01-05 07:25:15 +01:00
navi-march-test navigate: Require all ships to start in the same sector 2015-02-28 16:13:14 +01:00
normalize.pl Make: Support shallow git clones for testing 2017-09-02 17:51:37 +02:00
retreat-test tests/retreat: Cover trains 2015-03-02 08:20:48 +01:00
smoke-test tests: Define and use some abbreviations 2015-02-01 16:52:59 +01:00
test-common.sh tests: Make "make check-accept" accept new files 2021-01-05 10:41:35 +01:00
torpedo-test tests/torpedo: New; exercises torpedo command 2015-03-02 08:20:52 +01:00
update-test tests/update: New; exercises the update 2017-08-06 14:04:15 +02:00
version-test tests/version: New; exercises config introspection commands 2017-08-06 14:03:55 +02:00