9 years agoUpdate change log again for 4.3.31 v4.3.31
Markus Armbruster [Sun, 12 May 2013 16:59:42 +0000 (18:59 +0200)]
Update change log again for 4.3.31

9 years agoFix read beyond end of conditional argument on missing operand
Markus Armbruster [Sun, 12 May 2013 09:55:42 +0000 (11:55 +0200)]
Fix read beyond end of conditional argument on missing operand

nstr_parse_val() interprets argument "" as (empty) identifier, then
returns a pointer right beyond the end of the string.

The argument points into player->argbuf[].  If another argument
follows the conditional, it gets appended to the conditional.  Else,
whatever's left there from previous commands gets appended.  If the
argument is at the very end of player->argbuf[], we parse beyond the
buffer, until we run into a syntax error, or a zero byte.

Since player->argbuf[] is followed by a bunch of pointers, a syntax
error is almost certain.  If we somehow manage to parse all the
pointers and player->lasttime, the runaway parse will end at
player->btused, because that's definitely zero when conditionals get

9 years agoDon't put broken links in HTML info pages
Markus Armbruster [Sat, 11 May 2013 14:44:40 +0000 (16:44 +0200)]
Don't put broken links in HTML info pages

Pass the valid info page names to emp2html.pl, and convert only valid
references to links there.

9 years agoTighten up emp2html's info reference recognition
Markus Armbruster [Sat, 11 May 2013 14:20:51 +0000 (16:20 +0200)]
Tighten up emp2html's info reference recognition

Combine the two loops looking for \*QNAME\*U and "info NAME" into one.
Recognize "info NAME" only with the closing '"' to be present.

No change with current info sources.

9 years agoFold subj2html.pl into emp2html.pl
Markus Armbruster [Sat, 11 May 2013 13:49:11 +0000 (15:49 +0200)]
Fold subj2html.pl into emp2html.pl

9 years agoUpdate change log for 4.3.31
Markus Armbruster [Wed, 8 May 2013 18:46:00 +0000 (20:46 +0200)]
Update change log for 4.3.31

9 years agoPermit ships that can drop depth charges, but not fire
Markus Armbruster [Wed, 8 May 2013 18:41:46 +0000 (20:41 +0200)]
Permit ships that can drop depth charges, but not fire

No such ships exist in the stock game.

9 years agoConsistently require guns for dropping depth charges
Markus Armbruster [Wed, 8 May 2013 18:37:36 +0000 (20:37 +0200)]
Consistently require guns for dropping depth charges

The fire command requires at least one gun for depth charging, but
missions and return fire don't.  Has always been that way, except
between 4.0.6 and commit a3ad623 (v4.3.12), when depth charging worked
exactly like gun fire, and guns were consistently required.

Require guns for all ways to drop depth charges.

9 years agoCover configure reporting "terminfo: no" in READMEs
Markus Armbruster [Wed, 8 May 2013 17:19:12 +0000 (19:19 +0200)]
Cover configure reporting "terminfo: no" in READMEs

9 years agoCast time_t to long for printing with %ld
Markus Armbruster [Wed, 8 May 2013 17:13:38 +0000 (19:13 +0200)]
Cast time_t to long for printing with %ld

struct timeval member tv_sec used to be long, but POSIX made it

9 years agoInclude <sys/time.h> in lwp.h
Markus Armbruster [Tue, 7 May 2013 17:06:35 +0000 (19:06 +0200)]
Include <sys/time.h> in lwp.h

Missed in commit 08b9455, v4.3.20.  Triggers compiler warnings on
NetBSD 5.1.2.

9 years agoRefresh autoconf macros from autoconf-archive-2013.04.06
Markus Armbruster [Mon, 6 May 2013 18:13:43 +0000 (20:13 +0200)]
Refresh autoconf macros from autoconf-archive-2013.04.06

9 years agoMove auxiliary build tools to build-aux/
Markus Armbruster [Mon, 6 May 2013 18:03:22 +0000 (20:03 +0200)]
Move auxiliary build tools to build-aux/

9 years agoRefresh auxiliary build tools from automake 1.11.6
Markus Armbruster [Mon, 6 May 2013 17:55:05 +0000 (19:55 +0200)]
Refresh auxiliary build tools from automake 1.11.6

9 years agoChange econfig key rollover_avail_max from 0 to 50
Markus Armbruster [Mon, 6 May 2013 17:00:54 +0000 (19:00 +0200)]
Change econfig key rollover_avail_max from 0 to 50

So you don't have to micromanage workers to maximize useful work.

The previous commit made the problem a bit worse.  If you had a few
workers too many before, you perhaps produced an extra unit.  Now, you
get to keep the extra work instead.  Useless, unless it rolls over.

9 years agoMake sector production more predictable
Markus Armbruster [Mon, 6 May 2013 16:58:59 +0000 (18:58 +0200)]
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.

9 years agoRearrange produce() and prod() a bit to make them more similar
Markus Armbruster [Sun, 5 May 2013 20:34:59 +0000 (22:34 +0200)]
Rearrange produce() and prod() a bit to make them more similar

9 years agoFactor prod_resource_limit() out of produce() and prod()
Markus Armbruster [Sun, 5 May 2013 15:09:00 +0000 (17:09 +0200)]
Factor prod_resource_limit() out of produce() and prod()

9 years agoAvoid double rounding materials when limiting products made
Markus Armbruster [Sat, 4 May 2013 15:54:37 +0000 (17:54 +0200)]
Avoid double rounding materials when limiting products made

We can make actual = roundavg(material_consume * prodeff) products.

When we reduce actual, we have to reduce material_consume, too.  Code
does that like this:

    material_consume = roundavg(actual' * material_consume / actual)

Double rounding.  Do this instead:

    material_consume = roundavg(actual' / prodeff)

9 years agoUse ITEM_MAX instead of 9999 as production material limit
Markus Armbruster [Sat, 4 May 2013 06:53:03 +0000 (08:53 +0200)]
Use ITEM_MAX instead of 9999 as production material limit

No functional change, as ITEM_MAX is 9999, just cleaner.

9 years agoprod() duplicates materials_cost(), clean up
Markus Armbruster [Fri, 3 May 2013 18:52:02 +0000 (20:52 +0200)]
prod() duplicates materials_cost(), clean up

Rename materials_cost() to prod_materials_cost(), give external
linkage, use it in prod().

9 years agoClean up redundant code in prod()
Markus Armbruster [Fri, 3 May 2013 18:42:51 +0000 (20:42 +0200)]
Clean up redundant code in prod()

9 years agoFix "info Products" on how to query sector type p.e.
Markus Armbruster [Fri, 3 May 2013 18:11:07 +0000 (20:11 +0200)]
Fix "info Products" on how to query sector type p.e.

It's show sect capabilities, not stats.

9 years agoFix xdump nat column ip for connections from "long" IPv6 addresses
Markus Armbruster [Mon, 29 Apr 2013 19:29:51 +0000 (21:29 +0200)]
Fix xdump nat column ip for connections from "long" IPv6 addresses

Broken in commit 3a7d7fa, which enlarged struct natstr member
nat_hostaddr[] from 32 to 46 characters, but neglected to update the
ca_len in nat_ca[].  Consequently, the address is truncated in xdump.
Can also break country * ?ip=... and such, but that's exotic.

9 years agoFix five year old show stopper bugs on big endian hosts
Markus Armbruster [Mon, 29 Apr 2013 19:28:17 +0000 (21:28 +0200)]
Fix five year old show stopper bugs on big endian hosts

emp_server and empdump refuse to start on most big endian hosts,
because ef_verify_config() chokes on mdchr_ca[]:

Config meta uid 0 field type: value 0 is not in symbol table meta-type
Config meta uid 1 field type: value 0 is not in symbol table meta-type
Config meta uid 2 field type: value 0 is not in symbol table meta-type
Config meta uid 3 field type: value 0 is not in symbol table meta-type
Config meta uid 4 field type: value 0 is not in symbol table meta-type

Broken in commit 06a0036 (v4.3.12), which changed struct castr member
ca_type from packed_nsc_type (typedef'ed to char) to enum nsc_type,
but neglected to update the ca_type in mdchr_ca[].

On little endian hosts, the selector reads the least significant byte,
with sign extension.  Happens to work, because the type values are all
sufficiently small integers.

On big endian hosts, the selector reads the most signiciant byte.
which is always zero (NSC_NOTYPE).  Makes ef_verify_config() fail.

Except when sizeof(enum nsc_notype) == 1.  Then selector type works
fine, and ef_verify_config() succeeds, but we run into the next
problem: the same commit also changed member ca_flags from nsc_flags
(typedef'ed to unsigned char) to int without updating the ca_type in
mdchr_ca[].  This breaks "only" xdump meta column flags.

v4.3.12 was released in April 2008.  Either nobody has tried to run a
game on a big endian host since, or all who did gave up quietly,
without reporting the problem.

We clearly need to test on a wider range of machines.

9 years agoFix xdump trade column type on big endian hosts
Markus Armbruster [Mon, 29 Apr 2013 19:24:51 +0000 (21:24 +0200)]
Fix xdump trade column type on big endian hosts

Broken in commit 14ea670 (v4.3.8), which changed struct trdstr member
trd_type from char to short, but neglected to update the ca_type in

On little endian hosts, the selector reads the least significant byte,
with sign extension.  Happens to work, because the type values are all
sufficiently small integers.

On big endian hosts, the selector reads the most signiciant byte,
which is always zero (EF_SECTOR).  Messes up xdump trade badly.

9 years agoFix xdump lost column type on big endian hosts
Markus Armbruster [Mon, 29 Apr 2013 19:23:13 +0000 (21:23 +0200)]
Fix xdump lost column type on big endian hosts

Broken in commit 09248d0 (v4.3.8), which changed struct loststr member
lost_type from char to short, but neglected to update the ca_type in

On little endian hosts, the selector reads the least significant byte,
with sign extension.  Happens to work, because the type values are all
sufficiently small integers.

On big endian hosts, the selector reads the most signiciant byte,
which is always zero (EF_SECTOR).  Messes up xdump lost badly.  Also
breaks lost * ?type=..., but that's exotic.

9 years agoImprove how mksubj.pl reports malformed .SA argument
Markus Armbruster [Sun, 28 Apr 2013 16:30:41 +0000 (18:30 +0200)]
Improve how mksubj.pl reports malformed .SA argument

9 years ago.SA should come last, make mksubj.pl enforce it
Markus Armbruster [Sun, 28 Apr 2013 16:29:36 +0000 (18:29 +0200)]
.SA should come last, make mksubj.pl enforce it

9 years agoSubject pages confuse topics and subjects, fix
Markus Armbruster [Sun, 28 Apr 2013 16:06:14 +0000 (18:06 +0200)]
Subject pages confuse topics and subjects, fix

Confused since they were added in Empire 2.

9 years agoSlightly less crude "info page is long" decision
Markus Armbruster [Sun, 28 Apr 2013 16:00:25 +0000 (18:00 +0200)]
Slightly less crude "info page is long" decision

"Unusually long" topics are marked with a "!" in subject indexes.
This should use the line count of the formatted page, but that's too
much trouble, so commit 4c0b4c0 (v4.3.27) approximated it by "source
file has more than 9999 bytes".  Change that to "source file has more
than 300 lines".

9 years agoSimplify how mksubj.pl keeps track of the subjects' topics
Markus Armbruster [Sun, 28 Apr 2013 15:45:05 +0000 (17:45 +0200)]
Simplify how mksubj.pl keeps track of the subjects' topics

Extend global variable %Subjects to hold topics.  Drop global
variables %subject and %largest.

9 years agoSimplify how mksubj.pl parses argument of .SA
Markus Armbruster [Sun, 28 Apr 2013 15:05:10 +0000 (17:05 +0200)]
Simplify how mksubj.pl parses argument of .SA

Call parse_see_also() immediately.  Permits eliminating global
variables %see_also and %sanr.

9 years agoMake mksubj.pl touch subject files only when it needs to change
Markus Armbruster [Sun, 28 Apr 2013 13:22:11 +0000 (15:22 +0200)]
Make mksubj.pl touch subject files only when it needs to change

Avoids unnecessary reformatting of subject pages again.

9 years agoDeclare subjects instead of picking them up automatically
Markus Armbruster [Sun, 28 Apr 2013 12:38:50 +0000 (14:38 +0200)]
Declare subjects instead of picking them up automatically

Since subjects were added in Empire 2, we've always picked them up
from .SA requests.  If you mistype a subject there, you get a "is a
NEW subject" warning, and incorrect subject pages.  When building a
pristine tree, you get bogus "is a NEW subject" warnings for all
subjects.  If you somehow delete the generated subjects.mk, but not
the generated subject files, the build breaks.

Declare subjects in Make variable subjects.  Drop generated makefile

Treat unknown topics in .SA arguments as errors.  This replaces the
"$subj is a NEW subject" warning.

Treat subjects without member pages as errors.  This replaces the "The
subject $subj has been removed" warning.

Safer and simpler.

9 years agoFix remaking of info subject pages
Markus Armbruster [Sun, 28 Apr 2013 11:44:51 +0000 (13:44 +0200)]
Fix remaking of info subject pages

We used to do all the info indexing work in info.pl: find subjects,
create subjects.mk (to tell make the list of subjects), the subject
pages, and TOP.t.  Worked, but touching an info page triggered a full
rebuild of all subject pages and TOP.t.

Commit 2f14064 (v4.3.0) tried to avoid that by splitting info.pl into
findsubj.pl, mksubj.pl, mktop.pl.  findsubj.pl puts not just the
subjects into subjects.mk, but also make rules for the subject pages,
to guide their remaking.  mksubj.pl creates a single subject page.
mktop.pl creates TOP.t.

Unfortunately, this doesn't work so well.  Since subjects.mk doesn't
exist in a virgin tree, we use -include.  Unwanted consequence:
findsubj.pl failure doesn't stop make.  Moreover, the complex make
machinery breaks down when info sources get removed or subjects get

Go back to the old method, except keep mktop.pl separate, as that part
works just fine, and use simpler make rules.  mksubj.pl now creates
subjects.mk and all subject pages, like info.pl did.

This effectively reverts most of commit 2f14064.  I'll address the
excessive rebuilding of subject pages in a different way shortly.

9 years agoPass subjects instead of subject filenames to info/mktop.pl
Markus Armbruster [Sat, 27 Apr 2013 15:03:34 +0000 (17:03 +0200)]
Pass subjects instead of subject filenames to info/mktop.pl

mktop.pl doesn't actually use the files, so this is simpler and

9 years agoFix remaking of config.h and config.h.in
Markus Armbruster [Sat, 27 Apr 2013 13:32:53 +0000 (15:32 +0200)]
Fix remaking of config.h and config.h.in

Remaking config.h and config.h.in updates the target only when its
contents actually changes.  This is important, because after updating
config.h we need to recompile everything.

The make rules to do that are straight from the Autoconf manual.  But
they don't work: the rules that connect config.h and config.h.in to
stamp-h and stamp-h.in don't have recipes.  Since make doesn't have an
implicit rule either, it concludes that the target remains unchanged.
It still updates the prerequisites.  The recipe for updating the stamp
files then change the the targetes behind make's back.  Make misses
the change of config.h and/or config.h.in, and we get an incomplete

The rules need empty recipes instead.  This Autoconf manual was fixed
accordingly in autoconf.git commit 6b42b38.

9 years agoUpdate info lost example to current output
Markus Armbruster [Sun, 21 Apr 2013 11:29:37 +0000 (13:29 +0200)]
Update info lost example to current output

Looks like this hasn't been done since Peter Langston's days...

9 years agoDrop trailing space in output of financial
Markus Armbruster [Sun, 21 Apr 2013 11:22:01 +0000 (13:22 +0200)]
Drop trailing space in output of financial

9 years agoClean up some trailing whitespace
Markus Armbruster [Sun, 21 Apr 2013 10:58:26 +0000 (12:58 +0200)]
Clean up some trailing whitespace

9 years agoReplace .SA Obsolete by .LV Obsolete
Markus Armbruster [Fri, 29 Mar 2013 20:33:39 +0000 (21:33 +0100)]
Replace .SA Obsolete by .LV Obsolete

Mark obsolete pages with '+' in subject pages.  Drop the separate
"Obsolete" subject page: move "info Innards" to subject "Server", and
"info update" to "Updates" (where it came from in commit a5764534,

9 years agoSuppress explanation of '*' flag in subject pages when not used
Markus Armbruster [Fri, 29 Mar 2013 19:32:36 +0000 (20:32 +0100)]
Suppress explanation of '*' flag in subject pages when not used

9 years agoReplace 'our' by 'my' in Perl scripts
Markus Armbruster [Fri, 29 Mar 2013 18:51:56 +0000 (19:51 +0100)]
Replace 'our' by 'my' in Perl scripts

9 years agoInclude <process.h> in w32/unistd.h for getpid()
Markus Armbruster [Wed, 10 Apr 2013 19:41:09 +0000 (21:41 +0200)]
Include <process.h> in w32/unistd.h for getpid()

getpid() is used since commit 773019e.

9 years agoFix missing include "arpa/inet.h" in w32sockets.c
Markus Armbruster [Wed, 10 Apr 2013 19:36:41 +0000 (21:36 +0200)]
Fix missing include "arpa/inet.h" in w32sockets.c

Missed in commit afedb8c.

9 years agoDefine EWOULDBLOCK for w32 only if it's missing
Markus Armbruster [Wed, 10 Apr 2013 19:34:33 +0000 (21:34 +0200)]
Define EWOULDBLOCK for w32 only if it's missing

My version of MinGW provides it.

9 years agoUse IPv4 format for IPv4-mapped addresses
Markus Armbruster [Mon, 8 Apr 2013 17:34:37 +0000 (19:34 +0200)]
Use IPv4 format for IPv4-mapped addresses

For instance, use "" for IPv4 loopback instead of

Simplifies use of econfig key privip: plain dotted decimal now just
works regardless of IPv6 use, no need to add the IPv4-mapped form.

Also affects how addresses are logged and shown to players, and nation
selector ip.  Nicer that way.

9 years agoDrop extra blank line in output of pconfig
Markus Armbruster [Mon, 8 Apr 2013 17:23:58 +0000 (19:23 +0200)]
Drop extra blank line in output of pconfig

9 years agoDocument GNU libc lossage in listen_addr doc string
Markus Armbruster [Sun, 7 Apr 2013 18:40:29 +0000 (20:40 +0200)]
Document GNU libc lossage in listen_addr doc string

Systems using GNU libc such as Linux are frequently configured in a
way getaddrinfo(NULL, ...) put the IPv4 wildcard "" *before*
the IPv6 wildcard "::" in the result.  Because of that, listen_addr ""
listens only on all IPv4 addresses.  Workaround: listen_addr "::".

Document it in listen_addr's doc string.

9 years agoLog connection attempts
Markus Armbruster [Sun, 7 Apr 2013 18:19:10 +0000 (20:19 +0200)]
Log connection attempts

9 years agoFix wildcard bind to at least bind IPv4 or else IPv6 on OpenBSD
Markus Armbruster [Sun, 7 Apr 2013 17:30:17 +0000 (19:30 +0200)]
Fix wildcard bind to at least bind IPv4 or else IPv6 on OpenBSD

OpenBSD refuses to implement IPV6_V6ONLY, in violation of RFC 3493.
RFC 4038 frowningly recognizes this practice.  The only way to bind
both IPv4 and IPv4 there is two separate sockets.  Requires more
surgery than I can do now.

Since we can't have both IPv6 and IPv6 on OpenBSD with our single
socket, prefer IPv4, but if that doesn't work, do IPv6.

To prefer IPv6 instead, put 'listen_addr "::"' into econfig.  Document
that in listen_addr's doc string.

9 years agoFix wildcard bind to bind both IPv6 and IPv4 on Windows & BSD
Markus Armbruster [Sun, 7 Apr 2013 17:16:09 +0000 (19:16 +0200)]
Fix wildcard bind to bind both IPv6 and IPv4 on Windows & BSD

We rely on AF_INET6 wildcard bind() binding the AF_INET port, too,
i.e. IPV6_V6ONLY off.  This should be the default according to RFC
3493 section 5.3, but isn't on Windows and BSD.  RFC 4038 recognizes
this fact in section 4.2.

When IPV6_V6ONLY is on, an AF_INET6 wildcard bind only accepts
connections from IPv6 addresses.  Thus, IPv4 doesn't work when
getaddrinfo() returns an AF_INET6 address first (which it should do
when the system has an IPv6 address configured).

Switch off IPV6_V6ONLY explicitly instead of relying on the default.
This makes IPv6 work on systems where IPV6_V6ONLY is on by default,
such as Windows and BSD.

Except for OpenBSD, which does not support switching it off.  To be
addressed in the next commit.

9 years agoIgnore error setting socket option SO_REUSEADDR
Markus Armbruster [Sun, 7 Apr 2013 17:14:57 +0000 (19:14 +0200)]
Ignore error setting socket option SO_REUSEADDR

Shouldn't fail.  If it fails, but bind() works, the failure doesn't
matter.  If bind() fails, we can just as well report that failure
instead of setsockopt()'s.

9 years agoClean up tcp_listen()'s addrinfo loop some
Markus Armbruster [Sun, 7 Apr 2013 17:13:44 +0000 (19:13 +0200)]
Clean up tcp_listen()'s addrinfo loop some

9 years agoLog the server's listening address
Markus Armbruster [Sun, 7 Apr 2013 11:52:48 +0000 (13:52 +0200)]
Log the server's listening address

9 years agoFactor sockaddr_ntop() out of player_accept()
Markus Armbruster [Sun, 7 Apr 2013 11:27:43 +0000 (13:27 +0200)]
Factor sockaddr_ntop() out of player_accept()

Oops on inet_ntop() failure instead of merely logging it.

9 years agoFix a comment in tcp_connect()
Markus Armbruster [Sun, 7 Apr 2013 11:25:02 +0000 (13:25 +0200)]
Fix a comment in tcp_connect()

9 years agoMake power sort countries of equal power predictably
Markus Armbruster [Sat, 6 Apr 2013 07:46:51 +0000 (09:46 +0200)]
Make power sort countries of equal power predictably

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.

9 years agoChange fairland island size probability distribution
Markus Armbruster [Sun, 31 Mar 2013 09:05:32 +0000 (11:05 +0200)]
Change fairland island size probability distribution

Island size is randomly chosen from the interval [1..2*is+1], with
expected value is.  Use two dice to roll the size instead of one.
This makes extreme sizes much less likely.

9 years agoMake fairland record the island number in the deity territory
Markus Armbruster [Wed, 27 Mar 2013 15:58:40 +0000 (16:58 +0100)]
Make fairland record the island number in the deity territory

Can be useful for deities when further customizing their game setup.

9 years agoMake smoke test time out instead of hang when server misbehaves
Markus Armbruster [Mon, 25 Mar 2013 15:58:25 +0000 (16:58 +0100)]
Make smoke test time out instead of hang when server misbehaves

The smoke test waits for the server completing startup by trying to
connect until it works.  Hangs if the server doesn't complete startup
for some reason.  Make it give up after 5s.

Likewise, The smoke test waits for the server to terminate by trying
kill -0 until it fails.  Hangs if the server doesn't terminate.  Make
it give up after 5s.

9 years agoRemove superfluous #include "nuke.h"
Markus Armbruster [Mon, 14 Jan 2013 21:28:22 +0000 (22:28 +0100)]
Remove superfluous #include "nuke.h"

9 years agoSimplify market time left handling in a few places
Markus Armbruster [Mon, 14 Jan 2013 20:03:51 +0000 (21:03 +0100)]
Simplify market time left handling in a few places

9 years agoFix extension of market bidding time when high bidder changes
Markus Armbruster [Mon, 14 Jan 2013 19:59:04 +0000 (20:59 +0100)]
Fix extension of market bidding time when high bidder changes

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

Instead of extending bidding time by five minutes, set it to expire in
five minutes, both for commodities and for units.

9 years agoFix pre-tax unit market price loss of precision
Markus Armbruster [Mon, 14 Jan 2013 19:52:04 +0000 (20:52 +0100)]
Fix pre-tax unit market price loss of precision

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.

9 years agoUse int instead of long for money
Markus Armbruster [Sun, 13 Jan 2013 16:59:29 +0000 (17:59 +0100)]
Use int instead of long for money

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.

9 years agoFix melting of big piles of stuff by ridiculously heavy fallout
Markus Armbruster [Sun, 13 Jan 2013 16:17:44 +0000 (17:17 +0100)]
Fix melting of big piles of stuff by ridiculously heavy fallout

meltitems() computes #items * etus per update * fallout in type long.
Theoretical maximum is ITEM_MAX * etus * FALLOUT_MAX = 99980001 *
etus.  Can overflow 32 bits for etus > 21.  Has been broken since the
introduction of fallout in KSU.

Compute the product in double instead.

9 years agoClean up silly use of long in satmap()
Markus Armbruster [Sun, 13 Jan 2013 16:09:25 +0000 (17:09 +0100)]
Clean up silly use of long in satmap()

crackle's value is betwen 0 and 100, so change it to int.

9 years agoUse int instead of long for military reserves
Markus Armbruster [Sun, 13 Jan 2013 15:13:15 +0000 (16:13 +0100)]
Use int instead of long for military reserves

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.

9 years agoUse int instead of long to count people
Markus Armbruster [Sun, 13 Jan 2013 14:04:24 +0000 (15:04 +0100)]
Use int instead of long to count people

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.

9 years agoUse int instead of signed char for pln_flags
Markus Armbruster [Sun, 13 Jan 2013 13:16:01 +0000 (14:16 +0100)]
Use int instead of signed char for pln_flags

Just for consistency with other flags members.  Rearrange struct
plnstr to avoid holes.

9 years agoUse int instead of long for flags
Markus Armbruster [Sun, 13 Jan 2013 13:11:43 +0000 (14:11 +0100)]
Use int instead of long for flags

As long as symbol_by_value(), show_capab() and togg() support only
int, flags need to fit into int.

Not a problem in practice, because no machine capable of running
Empire has int narrower than 32 bits, and 32 bits suffice.

Some flags members are long instead of int: struct lchrstr member
l_flags, struct natstr member nat_flags, struct mchrstr member m_flags
are long.  Waste of space on machines with long wider than int.
Change them to int.

Rearrange struct lchrstr and struct natstr to avoid holes.

9 years agoAbridge a few overly verbose declarations
Markus Armbruster [Sun, 13 Jan 2013 12:19:37 +0000 (13:19 +0100)]
Abridge a few overly verbose declarations

9 years agoClean up redundant forward declarations
Markus Armbruster [Sun, 13 Jan 2013 12:13:55 +0000 (13:13 +0100)]
Clean up redundant forward declarations

9 years agoFix crash on edit s, p, u key 'U' with negative argument
Markus Armbruster [Sun, 13 Jan 2013 09:32:54 +0000 (10:32 +0100)]
Fix crash on edit s, p, u key 'U' with negative argument

ef_ensure_space() oopses on negative ID, but succeeds anyway.  edit()
proceeds to ef_write(), which neglects to check for negative ID.
Since the ID isn't in the cache, it then passes a NULL old element to
callback prewrite(), which crashes.

Fix ef_ensure_space() to fail on negative ID.  Commit 5173f8cd
(v4.3.0) made it oops, but neglected to make it fail.

Fix ef_write() to oops and fail on negative ID.

ef_write() still passes NULL old element to prewrite() when the ID
isn't in the cache.  Doesn't actually happen, because we use
prewrite() callbacks only with fully cached tables.  Fragile.  Make
ef_open() fail when that assumption is violated.

9 years agoUnify owner of units built by deities in foreign sectors
Markus Armbruster [Sun, 13 Jan 2013 09:06:50 +0000 (10:06 +0100)]
Unify owner of units built by deities in foreign sectors

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.

9 years agoAdd Travis CI configuration
Markus Armbruster [Sat, 12 Jan 2013 16:45:52 +0000 (17:45 +0100)]
Add Travis CI configuration

Travis CI is a hosted, continuous integration service.  Let's see how
it works out for us.

9 years agoUse unsigned instead of unsigned long for fairland's random seed
Markus Armbruster [Thu, 3 Jan 2013 15:32:08 +0000 (16:32 +0100)]
Use unsigned instead of unsigned long for fairland's random seed

seed_prng() wants unsigned.  Server uses unsigned already.

9 years agoRemove a blank line before "fairland rips open"
Markus Armbruster [Sat, 29 Dec 2012 14:47:12 +0000 (15:47 +0100)]
Remove a blank line before "fairland rips open"

One blank line before and after now, looks better.

9 years agoDon't reprint "fairland rips open" and PRNG seed on each retry
Markus Armbruster [Sat, 29 Dec 2012 14:45:05 +0000 (15:45 +0100)]
Don't reprint "fairland rips open" and PRNG seed on each retry

9 years agoFix PRNG seeding to resist guessing
Markus Armbruster [Sat, 29 Dec 2012 14:06:29 +0000 (15:06 +0100)]
Fix PRNG seeding to resist guessing

We seed it with value of time().  It's the traditional way, but it
provides only a few bits of effective entropy when an attacker has a
rough idea when the program started.

Instead, seed with a kernel random number.  If we can't get one, fall
back to a hash of gettimeofday() and getpid().  This should happen
only on old systems or Windows.  Far worse than a kernel random
number, but far better than using time().

Note that fairland used to seed with time() + getpid() until commit
331aac2a (v4.2.20) dropped the getpid(), claiming it didn't improve
the randomness.  Perhaps it didn't under Windows then, but it
certainly did elsewhere, so it was a regression.

9 years agoSwitch PRNG from BSD random() to Mersenne Twister
Markus Armbruster [Sat, 25 Aug 2012 15:21:10 +0000 (17:21 +0200)]
Switch PRNG from BSD random() to Mersenne Twister

random() may yield different pseudo-random number sequences for the
same seed on another system.  For instance, at least some versions of
MinGW provide a random() in -liberty that differs from traditional BSD
(see commit c8231b12).  Rather inconvenient for regression testing.

MT19937 Mersenne Twister is a proven, high-quality PRNG.  Actual code
is reference code provided by the inventors[*].  Quick tests show
performance comparable to random().

Like random(), MT is not cryptographically secure: observing enough of
its output permits guessing its state, and thus its future output.  I
don't think players can do that.

Drop the copy of BSD random() we added for Windows.

Like the previous commit, this changes the server's die rolls, and
makes fairland create a different random map for the same seed.  Update
expected smoke test results accordingly.

[*] mt19937ar.sep.tgz downloaded from

9 years agoFix tiny error in distribution of die rolls
Markus Armbruster [Sun, 19 Aug 2012 10:19:04 +0000 (12:19 +0200)]
Fix tiny error in distribution of die rolls

"random() % n" is sound only when n is a power of two.  The error is
hardly relevant in Empire, because random() yields 31 bits, and our n
are always much smaller than 2^31.  Fix it anyway.

Use smallest the 2^m >= n instead of n, and discard numbers exceeding

Bonus: faster for me even in the worst case n = 2^m+1.

Like the recent change to damage(), this changes some of the server's
die rolls, only this time the effect is pretty pervasive.  Worse,
fairland now creates a completely different random map for the same
seed.  Update expected smoke test results accordingly.

9 years agoNew pct_chance(), for clarity, and symmetry with chance()
Markus Armbruster [Thu, 16 Aug 2012 19:05:42 +0000 (21:05 +0200)]
New pct_chance(), for clarity, and symmetry with chance()

9 years agoMake move_ground() use roundavg()
Markus Armbruster [Thu, 27 Dec 2012 08:33:10 +0000 (09:33 +0100)]
Make move_ground() use roundavg()

No functional change.

9 years agoMake damage() use roundavg()
Markus Armbruster [Tue, 14 Aug 2012 19:51:22 +0000 (21:51 +0200)]
Make damage() use roundavg()

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.

9 years agoConvert "info Damage" from random(N) to 1dN notation
Markus Armbruster [Tue, 14 Aug 2012 18:50:25 +0000 (20:50 +0200)]
Convert "info Damage" from random(N) to 1dN notation

9 years agoFix "info Damage" for shells, depth charges and torpedoes
Markus Armbruster [Tue, 14 Aug 2012 18:45:54 +0000 (20:45 +0200)]
Fix "info Damage" for shells, depth charges and torpedoes

Each random() is off by one there.

9 years agoReplace "roll0(N) + M" by "roll(N) + M-1"
Markus Armbruster [Tue, 14 Aug 2012 18:33:51 +0000 (20:33 +0200)]
Replace "roll0(N) + M" by "roll(N) + M-1"

9 years agoFairland's rnd() wrapper is trivial now, drop it
Markus Armbruster [Tue, 14 Aug 2012 17:54:34 +0000 (19:54 +0200)]
Fairland's rnd() wrapper is trivial now, drop it

9 years agoEncapsulate direct use of random(), srandom() in chance.c
Markus Armbruster [Tue, 14 Aug 2012 17:23:12 +0000 (19:23 +0200)]
Encapsulate direct use of random(), srandom() in chance.c

Wrap roll0() around random(), and seed_prng() around srandom().  In
preparation of replacing the PRNG.

9 years agoMove declarations for chance.c to new chance.h
Markus Armbruster [Tue, 14 Aug 2012 16:57:17 +0000 (18:57 +0200)]
Move declarations for chance.c to new chance.h

9 years agoFix prod_eff() function comment
Markus Armbruster [Thu, 16 Aug 2012 19:05:16 +0000 (21:05 +0200)]
Fix prod_eff() function comment

It returns product's level p.e. time sector type p.e, not just the
level p.e.  See "info Products".

9 years agoClean up land unit retreat chance and fix its documentation
Markus Armbruster [Thu, 16 Aug 2012 18:54:59 +0000 (20:54 +0200)]
Clean up land unit retreat chance and fix its documentation

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.

9 years agoClean up and document nuclear damage's chance to destroy nuke
Markus Armbruster [Thu, 16 Aug 2012 06:24:15 +0000 (08:24 +0200)]
Clean up and document nuclear damage's chance to destroy nuke

Change chance in percent from damage-1 to damage.  It's always been
damage-1, but I can't bring myself to document the silly -1.

9 years agoClean up launch_sat() random direction pick
Markus Armbruster [Tue, 14 Aug 2012 18:33:36 +0000 (20:33 +0200)]
Clean up launch_sat() random direction pick

Use DIR_FIRST rather than literal 1.

9 years agoMake smoke test's tech production more robust
Markus Armbruster [Sun, 5 May 2013 17:31:49 +0000 (19:31 +0200)]
Make smoke test's tech production more robust

The tech center doesn't have enough workers to use all materials in
some updates.  How much get made depends on a die roll then.  Tech
variations are inconvenient because they ripple through the rest of
the smoke test.

9 years agoLimit che action in smoke test some
Markus Armbruster [Fri, 28 Dec 2012 13:53:56 +0000 (14:53 +0100)]
Limit che action in smoke test some

Too easily upset by random variations.  Kill them off with anti after
two updates, and occupy with a few more military.

While there, enlist the military in a highway rather than an lcm

9 years agoEnlarge news cache from 5 to 8 entries per country
Markus Armbruster [Thu, 27 Dec 2012 13:48:06 +0000 (14:48 +0100)]
Enlarge news cache from 5 to 8 entries per country