Portability issue: prototypes.h uses enum ns_seltype, defined in
nsc.h. GCC is fine with that; it supports incomplete enum types as an
extension. Broken in commit 157ae8ec2 "Clean up superfluous include
of nsc.h in prototypes.h", v4.3.27. Moving sarg.c stuff to nsc.h
fixes it.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
C99 requires at least one argument for the "..." in a variadic macro.
GCC and Clang don't care, but warn with -pedantic. Solaris cc warns.
The warning is easy to avoid, so do it.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
MY_LIB_READLINE tries each readline-compatible library with a sequence
of additional libraries, starting with none. If the check with none
fails, all the others checks reuse the cached result, and also fail.
Broken in commit 1cbda2c7d "client: Rewrite readline configuration",
v4.4.0.
Avoid the unwanted chaching.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The test scripts need a POSIX-compliant Bourne shell. /bin/sh isn't
on some systems, such as Solaris. Run them with $(SHELL).
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The default SHELL isn't POSIX on some systems, such as Solaris. Use
the one Autoconf chooses instead of the default.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Solaris 10's nroff can't deal with the lengthy .NF ... .FI: it
complains, writes truncated output, and terminates
successfully (*boggle*). Split the .NF ... .FI in two.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Commit 23373d01d "configure: Test compiler flags" (v4.4.0) made
configure test whether compiler flags work, to let us use flags that
work only for some compilers.
Unfortunately, the Sun C compiler accepts invalid options with a
warning, breaking the test. Observed on Solaris 10.
Fix by testing the compiler flags only when AC_PROG_CC detected GCC.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
plane damage() prints @noisy with snprintf() even when it's null. It
doesn't actually use the output then. Some systems (GNU, Windows)
deal gracefully with printing null strings, others crash. @noisy is
null when bombers or missiles miss and do collateral damage. Affects
bomb, launch, and interdiction missions. Broken in commit 820d755e5
"subs: Change pln_damage()'s parameter noisy to string prefix",
v4.3.33.
Fix by guarding the snprintf().
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Document the need for the XSI Extension. Don't list curses as
required, it's actually optional. Correct advice for Solaris. Add
advice for AIX. Drop references to C89; we actually require C99, and
POSIX.1-2001 provides it.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
We require POSIX.1-2001. Some systems provide it only with feature
test macro _POSIX_C_SOURCE defined to 200112L. Since we don't define
it, the build fails there. Observed on Solaris 10.
We actually require the XSI extension. The GNU C Library provides it
by default. With _POSIX_C_SOURCE 200112L, however, you have to define
feature test macro _XOPEN_SOURCE to get it. But then _POSIX_C_SOURCE
is redundant.
Make configure put #define _XOPEN_SOURCE 600 into config.h. Drop the
two existing #define _XOPEN_SOURCE 500 in .c files.
Now Solaris cc refuses to play ball unless switched to C99. Replace
AC_PROG_CC by AC_PROG_CC_STDC to mollify it.
Unfortunately, use of _XOPEN_SOURCE exposes bugs in AIX libc and old
versions of GNU libc:
* AIX defines struct in6_addr's member s6_addr as a macro expanding
into the actual member. Without _ALL_SOURCE (the default), the
expansion is wrong and doesn't compile. Observed with AIX V7.2.
* GNU lib's IN6_IS_ADDR_V4MAPPED() is unusable without
_DEFAULT_SOURCE (default) or _GNU_SOURCE. Observed with Debian 8.
Tracked at <https://sourceware.org/bugzilla/show_bug.cgi?id=16421>,
fixed in version 2.25.
Affects just sockaddr_ntop()'s special case from commit 372cdb136 "Use
IPv4 format for IPv4-mapped addresses", v4.3.31. Disable the special
case and use IPv6 format on such systems. This is a very minor
usability regression. Could be avoided, I guess, but it's not worth
the trouble.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
getpass() is traditional Unix, but has been withdrawn from POSIX. We
still use it when it's available, and fall back to portable code only
when it's not.
The portable code behaves differently: it reads stdin instead of
/dev/tty, and in noncanonical mode.
Simplify things: always use the replacement.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
getpass() is traditional Unix, but has been withdrawn from POSIX. We
provide a replacement in case it's missing. The one for Windows
suppresses echo, like getpass() does. Implement that for POSIX. The
other differences to getpass() remain.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
I'm going to drop use of getpass(). As a first step, weaken the bond
by hiding it in a separate function.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
lwpSigWait() was designed to resemble sigwait(). It doesn't anymore.
Drop the awkward argument, and use the return value instead.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
LWP's use of sigset_t is problematic.
To iterate over a sigset_t, it uses NSIG, which is not portable: BSD
and System V provide it, but it's not POSIX.
To record signals caught, it updates a sigset_t variable from a signal
handler. The variable isn't volatile, because we'd have to cast away
volatile for sigaddset().
Replace sigset_t by an array of signal numbers terminated with 0.
Since lwpInitSigWait() needs to store the signal set for
lwpCatchAwaitedSig() anyway, there is no need to pass it to
lwpSigWait(). Drop its parameter.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
lwpSigWait() clears LwpSigCheck even when signals remain in
LwpSigCaught. The next empth_wait_for_signal() will then wait until
another one gets caught. Broken in commit fe2de3d74, v4.3.10.
Fix by clearing it only when LwpSigCaught is empty.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
sigismember() fails when passed an invalid or unsupported signal
number. lwpInitSigWait() and lwpGetSig() treat sigismember() failure
like "is a member". lwpInitSigWait() will then sigaction()
unsuccessfully. Harmless. lwpGetSig() returns the bad signal number
when it's greater than any caught signal's number. The bad signal
number then gets returned to main(), which shuts down the server.
Fix by treating failure like "is not a member".
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
lwpCatchAwaitedSig() is not reentrant. lwpInitSigWait() attempts to
protect it by setting an appropriate signal mask, but screws up. This
could conceivably lose signals. Messed up when it got added in commit
7183516d9, v4.3.6. Fix it.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
lwpSigWait()'s contract specifies failure, which means oopsing is
wrong. Harmless, as its only caller empth_wait_for_signal() oopses on
failure. Drop it anyway.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
We get strncasecmp() from <string.h>. This is a BSDism; POSIX
provides it in <strings.h>. Missed in commit 8fdd0259f2, v4.2.19.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Commit fad8e7f7b "Move auxiliary build tools to build-aux/" moved
depcomp, but neglected to adjust Make.mk. This broke the build with
tool chains that actually use depcomp. Modern GCC and Clang don't.
Fix the obvious way.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Configuration tables product, sect-chr, ship-chr, plane-chr, land-chr,
nuke-chr have a bit of extra space deities can use for customizing
their games. Give them more: enlarge product from 23 to 31
entries (plus one sentinel), sect-chr from 39 to 63, ship-chr from 47
to 127, plane-chr from 47 to 127, land-chr from 31 to 127, and
nuke-chr from 20 to 63.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Macros LND_TYPE_MAX, N_MAXNUKE, PLN_TYPE_MAX, P_MAX, SCT_TYPE_MAX,
SHP_TYPE_MAX are only used to size a single array each. Eliminate.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Don't use ALL CAPS for headings. Reformat them in the style
recommended by doc/coding. Drop a few comments that aren't pulling
their weight, and fix the odd typo.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
qprint() was carelessly added at the end of the file in Empire 2,
where it's under the "Write a script for placing capitals" headline.
Move it to a more sensible place.
NUMTRIES was added behind the global variables in Empire 2. Move it
before them, and reformat its comment.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Replace own[x][y] by own[XYOFFSET(x, y)], and narrow the element type
from int to short. Takes a fourth the space.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The previous commit's interpolation tables reproduce the historical
linear functions faithfully. This exact fit requires an awkward data
point in each of the tables for iron fertility and oil. Drop them.
No double-valued data points remain. Adjust struct resource_point
member @res to int.
This results in slightly less rural iron (33 elevations down one
point), fertility (10 elevations down one point) and oil (14
elevations down one point, 5 down two points). Only resource values
less than 100 are affected.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The functions mapping elevation to resources are piecewise linear.
Replace them by linear interpolation on data points defined in tables.
Tables are easier to tweak for deities than code.
The data points are a bit awkward because the functions they replace
are. The next commit will tweak them to address that.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
The functions mapping elevation to resources are piecewise linear,
except for set_oil(), which randomly adds 1 to sea oil, and
set_gold(), which is isn't linear for mountains, but very close.
Drop the random oil bit, and replace the non-liner gold function by a
linear one. Both resources decrease at most by one point.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
Land elevation is computed by first placing mountains, then elevating
land to fit.
Mountains placement is a weighted random sampling. A sector's weight
is its distance to sea capped at five and squared.
Non-mountain, non-capital sectors get assigned equidistant elevations
from 1 up to 97 rounded to integer in an order that depends on
distance to mountain and distance to sea, both capped at 5. Mountains
get equidistant elevations starting at 98 (see recent commit
"fairland: Fair mountain resources"). Capitals get 36.
Sea elevation is randomly chosen from a range that depends on the
sector's distance to land. The range increases from [-27,-1] next to
land to [-127,-1] for distance 5 and up.
Without mountains, the result is boring: elevation increases pretty
much linearly with the distance from the coast, i.e. each islands is a
single cone. With mountains, we get one cone per mountain. The sea
sea elevations are basically noise.
Worse, it's buggy: mountain placement can place fewer mountains than
requested. The weighted random sampling assigns weights even to
sectors that cannot be picked (capitals and sectors that have been
picked already). When the dice land on such a sector, it instead
picks the next one (in island growth order) that can be picked. If
there is no next one, the mountain is not placed. This is a fairness
issue.
Impact varies with fairland parameters. For 60 sector islands with 5%
mountains, around one in 10000 islands is short one mountain in my
testing. For 10 sector islands with 50% mountains, some 760 out of
10000 islands are short one sector, 80 short two, and five short
three. The numbers get worse as spikiness increases.
Undocumented misfeature: the placement loop is limited to 1000
iterations, supposedly to catch a runaway loop. Since the loop
iterates exactly once per mountain, all this accomplishes it limiting
mountains to 1000 per island.
When too few mountains are placed, the loop assigning elevations to
non-mountain, non-capital decrements elevations below 1. Since
Chainsaw 3, such elevations then get mapped to 1, plastering over the
bug. We get non-mountain sectors with elevation 1 instead of
mountains.
Rewrite as follows.
Use a simple random hill algorithm to assign raw elevations:
initialize elevation to zero, then randomly raise circular hills on
land / lower circular depressions at sea. Their size and height
depends on the distance to the coast, capped at 3. After a sufficient
number of iterations, the resulting terrain has a "natural" look.
This is elevate_prep().
elevate_land() then sorts non-capital sectors by raw elevation. The
highest become mountains. Sectors get assigned the same equidistant
elevations as before, just in raw elevation order.
elevate_sea() simply normalizes raw elevation to [-127,-1].
Elevations now show a nice undulating pattern independent of mountain
percentage.
Implementation detail: replace elev[x][y] by elev[XYOFFSET(x, y)], and
narrow the element type from int to short. Takes a fourth the space.
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>