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.
How qsort() sorts members that compare equal is unspecified. Can
upset the smoke test. Observed under FreeBSD 8.3.
Break ties in power by comparing country numbers. Countries equal in
power are now sorted by increasing country number.
Lots stay on the market until there's a bid and bidding time expires.
When the highest bidder changes, and less than five minutes of bidding
time are left, it gets extended by five minutes (since 4.0.7, actually
works since 4.0.9).
Normally, this ensures that the competition has at least five minutes
to react. Except when this is the first bid, bidding time may have
expired already. If it expired less than five minutes ago, the
competition still gets time to react, just less than it should. If it
expired earlier, the sale is executed immediately for units. For
commodities, the bidding time is set to expire in five minutes (since
4.2.0).
Instead of extending bidding time by five minutes, set it to expire in
five minutes, both for commodities and for units.
check_trade() converts the price to float, which can lose precision,
although only for ridiculously high prices. Has been broken since
4.0.0 introduced the market.
Avoid the conversion. Bulletins now show pre-tax price as $N instead
of $N.00.
Code dealing with money mixes int and long pretty haphazardly.
Harmless, because practical amounts of money fit into int on any
machine capable of running the server. Clean up anyway.
Code dealing with reserves mixes int and long pretty haphazardly.
Harmless, because practical reserves fit easily on any machine capable
of running the server. Clean up anyway.
Code dealing with counting people mixes int and long pretty
haphazardly. Harmless, because practical populations fit into int
easily on any machine capable of running the server. Clean up anyway.
Newly built ships and land units are given to the player, planes and
nukes to the sector owner. Matters only for deities, because only
deities can build in foreign sectors. Stupid all the same.
This has always been inconsistent. Empire 1 gave ships and nukes to
the player, and planes to the sector owner. Chainsaw 3 added land
units, and gave them to the player. Empire 2 changed build to give
nukes to the sector owner.
Building doesn't work when the unit built is given to POGO, because
giving a unit to POGO destroys it. When build gives to the sector
owner, deities can't build in unowned sectors. When build gives to
the player, POGO can't build at all. That's more limiting, so change
build to always give to the sector owner.
setsector() and setres() continue after check_sect_ok() fails.
Clobbers the updates that made check_sect_ok() fail, triggering a
seqno mismatch oops.
Commit 04a332a8 (v4.3.27) claimed to fix this, but actually only
suppressed the generation oops.
give() continues after check_sect_ok() fails. Clobbers the updates
that made check_sect_ok() fail, triggering a seqno mismatch oops.
Commit b58c37e2 (v4.3.27) claimed to fix this, but actually only
suppressed the generation oops.
When the deity sets the number of mines with setsector, the sector
owner (if any) is told the resulting number of mines. Even for
occupied sectors, where mines belong to the old owner, and thus
shouldn't be disclosed. Oops.
Fix setsector not to tell the sector owner anything then.
Capital takes a <SECTS> argument, and picks the first suitable sector
it finds there. It fails if none can be found, or if the first one
found already is the capital (even when more suitable sectors follow).
Has always worked that way, but never documented.
I don't think the search feature is really useful, and documenting it
isn't worth my while. Change the command to take a <SECT> argument
instead, as documented.
bomb, drop, fly, paradrop, recon and sweep fail when given a
destination sector equal to the assembly point. Broken in commit
404a76f7, v4.3.27. Reported by Tom Johnson.
Before that commit, getpath() returned NULL on error, "" when input is
an empty path, "h" when it's coordinates of the assembly point, and a
non-empty path otherwise.
The commit accidentally changed it to return "" instead of "h".
Instead of changing it back, make it return NULL when input is an
empty path, and change bomb() & friends to accept empty flight paths.
This also affects sail: it now fails when you give it an empty path,
just like bomb & friends. Path "h" still works.
Deities can customize which commodities can be sold in table item.
Default is to allow anything but civilians and military. However,
this applies only to the commodity market, not to the unit market:
cargo of ships and land units is not restricted.
Make the two markets consistent: permit selling military by default,
forbid selling units carrying unsalable commodities. This outlaws
selling units carrying civilians by default.
Planes flying one-way with crew or cargo spread plague from their old
base to their new base. Planes dropping cargo spread plague from
their base to the drop's target sector.
msl_equip(), find_escorts() and perform_mission() memset() the plist,
then assign to all members but load. Just zero load instead, like
getilists(), msl_sel() and pln_sel() do.
Flying them to a foreign destination magically changes their
allegiance. Prohibit that.
Equivalent change was already in commit 35887222 (v4.2.17) but got
reverted immediately (commit 20199b22), because fly and drop should
stay consistent with load, which let you give away civilians then. No
more since commit 92a366ce (v4.3.20). This change makes fly and drop
consistent with load again.
New function reads and returns target sector/ship. Avoids reading the
target sector unnecessarily. Callers receive the target ship, not
just its number. Next commit will put it to use.
Tending a negative number of commodities takes from the target ships.
The target ships must be owned. Tend complains when the target
doesn't have the commodity loaded. It does that even for friendly
foreign ships. Don't.
Broken when Chainsaw 2 added tending to allies.
Tending a negative number of commodities takes from the target ships.
When a target ship is foreign, tend silently stops. This is wrong.
Fix it to skip foreign target ships instead.
Broken when Chainsaw 2 added tending to allies.