]> git.pond.sub.org Git - empserver/commit
Make sector production more predictable
authorMarkus Armbruster <armbru@pond.sub.org>
Mon, 6 May 2013 16:58:59 +0000 (18:58 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Wed, 8 May 2013 12:23:50 +0000 (14:23 +0200)
commit6f7c93cdad5fec856f392e58c5359401ff1a4fdd
tree4fdaaa3535838b7a45a036e8d4c61b6a3b2acb9b
parent739852dd3f43fa8eb2a49cdadee2b1c66d79c22c
Make sector production more predictable

produce() limits production to how many units the workers can produce,
rounding randomly.  It charges work for the units actually produced,
discarding fractions.

If you get lucky with the random rounding, you may get a bit of extra
work done for free.  Else, you get to keep the unused work, and may
even be undercharged a tiny bit of work.  Has always been that way.

The production command assumes the random rounding rounds up if and
only if the probability to do so is at least 50%.  Thus, it's
frequently off by one for sectors producing at their worker limit.

The budget command runs the update code, and is therefore also off by
one, only differently.

Rather annoying for tech and research centers, where a single unit
matters.  A tech center with full civilian population can produce 37.5
units in 60 etus.  Given enough materials, it'll fluctuate between 37
and 38.  Production consistently predicts 38, and budget randomly
predicts either 37 or 38.  Both are off by one half the time.

Fix this as follows: limit production to the amount the workers can
produce (no rounding).  Work becomes a hard limit, not subject to
random fluctuations.  Randomly round the work charged for actual
production.  On average, this charges exactly the work that's used.

More importantly, production and budget now predict how much gets
produced more accurately.  They're still not exact, as the amount of
work available for production remains slightly random.

This also "fixes" the smoke test on a i686 Debian 6 box for me.  The
root problem is that floating-point subexpressions may either be
computed in double precision or extended precision.  Different
machines (or different compilers, or even different compiler flags)
may use different precision, and get different results.

Example: producing 108 units at one work per unit, sector p.e. 0.4
needs to charge 108 / 0.4 work.  Computed in double precision, this
gets rounded to 270.0, then truncated to 270.  In 80 bit extended
precision, it gets rounded to 269.999999999, then truncated to 269.

With random rounding instead of truncation, the probability for a
different result is vanishingly small.  However, this commit
introduces truncation in another place.  It just happens not to mess
up the smoke test there.  I doubt this is the last time this kind of
problem upsets the smoke test.
src/lib/commands/prod.c
src/lib/update/produce.c
tests/smoke/smoke.out
tests/smoke/smoke.xdump