Turns damage() into a one-liner.
damage() now uses random() % 32768 in chance() instead of random() %
100 inline, therefore can round differently for the same pseudo-random
number. Update expected smoke test results accordingly.
Aside: "random() % n" distributes evenly only when n is a power of
two. 100 isn't. However, because random() yields at least 31 bits,
and 100 is so much smaller than 2^31, the error is vanishingly small.
Change chance in percent lnd_retreat - lnd_effic - 1 to lnd_retreat -
lnd_effic. It's been that way since Empire 2, but I can't bring
myself to document the silly -1.
"info morale" wasn't updated when the retreat chance was changed in
Empire 2. Fix that.
News reporting merges news items into recent items with same contents.
For that purpuse, we keep a small cache of recent items. When a new
item can't be merged into an item in the cache, the oldest item gets
evicted to make space for the new one.
ncache() evicts the first item with the smallest timestamp (struct
nwsstr member nws_when). Timestamps are in seconds, therefore clashes
are common, and eviction depends on exact timing. Such indeterminism
can make the smoke test fail.
Moreover, ncache() assumes timestamps cannot exceed 0x7fffffff. If
they do, it always evicts the slot 0. They will in 2038.
Fix by evicting round robin. This always evicts the oldest item.
Just a smoke test so far, extracted from src/scripts/nightly/. This
makes the existing smoke test more easily accessible. Noteworthy
differences:
* Instead of patching the code to make output more stable, postprocess
the output to normalize it.
* Compare actual results to expected results instead of the previous
test run's results.
* Much faster. The old test harness used sleep liberally to "ensure"
things always happen in the same order.
Known shortcomings:
* The smoke test hangs when the server fails to complete startup, or
fails to terminate.
* Normalization of xdump hardcodes columns instead of getting them
from xdump meta.
* Normalization of time values in xdump is an ugly hack.
* xdump meta column type isn't normalized. Actual values can vary
between systems, because the width of enumeration types is
implementation-defined. The smoke test works only when they're
represented as int, which is the case on common systems.
* Currently expected to work only with thread package LWP and a
random() that behaves exactly like the one on my development system,
because:
- Thread scheduling is reliably deterministic only with LWP
- The PRN sequence produced by random() isn't portable
- Shell builtin kill appears not to do the job in MinGW
- The Windows server tries to run as service when -d isn't
specified
Further work is needed to address these shortcomings.
Getting C programs behave exactly the same on all systems is hard.
We'll likely run into system-dependent differences that upset the
smoke test. Floating-point computation seems particularly vulnerable.
Instead of updating src/scripts/nightly/ to use "make check", retire
it. It hasn't been used in quite a while. Investing more into our
homegrown auto-builder doesn't make sense, as canned auto-builders
such as Travis CI and Jenkins are readily available.
The shell scripts src/scripts/nightly/tests/?? become Empire batch
files tests/smoke/. The shell scripts are actually shell boilerplate
around Empire batch files. To make sure git recognizes the move, this
commit moves them unchanged. tests/smoke-test strips the boilerplate
before it feeds the batch files to the client. The next commit will
get rid fo that.
Due to a typo, shp_missile_interdiction() picks the admissible target
with highest efficiency instead of the one with highest efficiency *
build cost.
Broken in commit cd8d7423, v4.3.8.
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.
Option GODNEWS controls news reports give's N_GIFT, N_TAKE, and edit's
and setsector's N_AIDS, N_HURTS.
They affect news headlines because of their non-zero r_good_will.
N_TAKE and N_HURTS can downgrade relations because of their negative
r_good_will. All tolerable, except N_TAKE has actor and victim
reverted: the deity running the give command is the victim, and the
sector owner is the actor. Because of that, give with a negative
amount downgrades the deity's relations towards the sector owner.
Inappropriate.
Has always been that way. Chainsaw disabled these news at
compile-time; to enable you had to define GODNEWS (not documented
anywhere). Empire 4.2.0 made GODNEWS a proper option, enabled by
default.
Fix by setting their r_good_will to zero.
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.
Assigning to tp->trd_owner is unclean. Can be dropped safely, because
it has no effect: prior check_trade() drops all trades where the
assignment would change anything.
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.