empserver/tests
Markus Armbruster 73c103e9df fairland: Fix island growth and correct its bias
grow_one_sector() picks a coastal start sector, then moves along the
coast trying to add an adjacent sector to the island.

It operates in spiking mode with a chance of @sp percent.

When spiking, the neighbors with sea on both sides are preferred.  For
instance, when the area around the sector being considered looks like
this

     - .
    - - .
     - .

then the neighbor in direction j is preferred, because it has sea in
directions u and n.  No other neighbor is preferred.

The start sector is the first coastal sector found in a linear search
in growth order, starting at the last sector grown when spiking, or
else at a random sector.  This is new_try().

grow_one_sector() tries adding a neighbor in clockwise order, starting
with a random direction.  When spiking, it goes around the clock two
times, trying only preferred sectors in the first round.

When it can't add a neighbor, it moves to the next coastal sector with
next_coast().

Taken together, this randomly picks one element from the set of
pairs (S, D) where the sector in direction D off base sector S can be
added to the island.  How does the probability distribution look like?

Bias: a sector's probability to be added to the island land increases
with the number of base sectors it is adjacent to.  This tends to fill
in bays and lakes, which is fine.

Bias: coastal sectors following runs of non-coastal ones are more
likely to be picked as start sector.  Perhaps less of an issue when
spiking, where the pick is not intended to be random.

Bias: a pair (S, D) is more likely to be picked when base sector S
follows a run of coastal sectors that aren't base sectors, or
direction D follows a a run of directions that don't permit growth.

The impact of these two biases is not obvious.  I suspect they are the
reason behind the tendency of large islands to curve around obstacles
in a counterclockwise direction.  This can result in multiple islands
wrapping around a central one like layers of an onion.

Bug: the move along the coast is broken.  next_coast() searches for
the first adjacent sea in clockwise order, starting in direction g,
then from there clockwise for a sector belonging to the island.
Amazingly, this does move along the coast in a clockwise direction.
It can get caught in a loop, though.  Consider this island:

        -
     - - -
      -

If we start at the central sector (marked 0), the search along the
coast progresses like this:

        1
     - 0 2
      -

It reaches the central sector again after three moves (to 1, to 2,
back to 0), and stops without having reached the two sectors on the
left.

If we start with the leftmost sector, the search loops: 0, 1, 2, 3, 1,
...

        2
     0 1 3
      -

grow_one_sector() ensures termination by giving up after 200 moves.
Nuts!

Because of this, grow_one_sector() can fail when it shouldn't, either
because the search along the coast stops early, or goes into a loop,
or simply because there's too much coast.  The latter should not
happen in common usage, where island sizes are in the tens, not the
hundreds.

Clean up this hot mess by rewriting grow_one_sector() to pick a sector
adjacent to the island with a clearly defined probability, as follows.

Use weighted random sampling to pick one sector from the set of
possible adjacent sectors.

When spiking, a sector's weight increases with number of adjacent sea
sectors.  This directs the growth away from land, resulting in spikes.

When not spiking, the weight increases with the number of adjacent
land sectors.  This makes the island more rounded.

To visit the adjacent sectors, grow_one_sector() iterates over the
neighbors of all island sectors, skipping neighbors that have been
visited already.

This produces comparable results for low spike percentages.  The weird
onions are gone, though.

Noticeable differences emerge as the spike percentage grows.  Whereas
the old one produces long snakes that tend to curve into themselves,
the new one produces shorter spikes extending from a core, a bit like
tentacles.  Moreover, islands are more centered on their first sector
now.  The probability for coastal capitals is lower, in particular for
moderate spike percentages.

I consider this improvements.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +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: Fix island growth and correct its bias 2021-01-05 10:41:36 +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 tests/fairland: Cover "plenty of space" better 2021-01-05 10:41:35 +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