Compare commits

..

94 commits

Author SHA1 Message Date
7e63185007 commands: Rename the command functions
Command functions are traditionally named like the command shortened
to four characters.  When this name collides with a keyword or library
function, we abbreviate more: brea(), rea().  A few are unabbreviated,
e.g.  execute().  A few have different names, e.g. explain(), not
list().

Commit 23726b379 (v4.3.0) suppressed a GCC warning about carg()
colliding with its built-in function.

Ron Koenderink reported Microsoft Visual Studio 2019 fails to link:
"_carg already defined in ucrtd.lib(ucrtbased.dll)".

Time to clean this up: rename the functions to c_FOO(), where FOO is
the unabbreviated name of the command.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-18 06:16:26 +01:00
af143ac597 info/Empire4.4: Update change log for 4.4.1
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
20986a480e buy: Fix bogus error when lot gets reused at the last prompt
When the lot being bid for goes away and gets reused while the player
is at the prompt for the destination sector, comm.com_amount gets
stale.  We use it before we detect the change and fail the command
This can lead to a misleading ""You don't have that much to spend!"
error.  Messed up when the code was fixed to deal with lot changes in
4.0.2.

Fix by checking for lot change earlier.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
6a30258d31 buy: Don't continue when lot changes while asking for bid
When the lot being bid for changes while the player is at the "How
much" prompt, we report "Commodity #%d has changed!", and continue
with the changed lot.

If continuing is okay, we should keep quiet.  We did that until commit
40b11c098 "Fix buy not to wipe out concurrent updates", v4.3.27.  Okay
when only the lot's price changed.

However, the lot could have gone away, or even be reused for something
else.  Failing the command seems safest for the player, so do that.
It's how we use the check_FOO_ok() elsewhere.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
37af1d7eb9 work: Don't let embarked engineers work
Engineers can work even when loaded on a ship or land unit.  They
happily raise sea sector efficiency.  That's just wrong.  It's
questionable even on land, because unloading need not be possible.
Has been that way since the command was added in Empire 2.

Add the missing check.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
589bc1ed1a neweff production work: Fix crash for sea sector
The work required for building sea sectors is zero in sect.config.
When a deity runs neweff or production on a sea sector, e.g. with
"neweff *", buildeff() divides by zero.  Same when a player or deity
runs work with an engineer in a sea sector.  Broken in commit
2ffd7b948 "config: Make work to build sectors configurable", v4.4.0

Fix buildeff() to avoid the division.  Change the required work to 100
in sect.config for good measure.

Cover deity use of neweff and production in tests/update.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
88bd68b88b config: Increase mountain process efficiency from 75% to 100%
Each point of gold resource is worth 5d.  Except for mountains, where
it's just 3.75d.  This is because a mountain's process efficiency is
only 75%.  Has been that way since Empire 3 made mountains mine gold.

This is actually a needless complication: a sector with 75% process
efficiency produces just like one with 100% process efficiency and 75%
of the resource.

Increase mountain process efficiency to 100%.  Deities may want to
compensate by adjusting mountains' gold resources.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
9b84153038 config: Make product work independently configurable
The work required for a product is traditionally the amount of raw
materials, plus 1 for resource usage, or 1 if using neither.  Make it
independently configurable instead, via new product selector bwork,
backed by new struct pchrstr member p_bwork.  Keep the required work
exactly the same in the default configuration.

Clients that compute work from materials need to be updated.  Easy,
since build work is now exposed in xdump.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
d7a9593f35 tests/version: Cover show product and show news
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
301656771b update: Give a few helpers internal linkage
External use of prod_materials_cost(), prod_resource_limit() went away
in commit 4a714a37d "production: Use update code instead of
duplicating it", v4.4.0.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
70542a0cb5 info/power: Fix commodity power formula
Messed up in commit 1307a3be6 "show: Extend show item to show the
power value", v4.4.0.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
0adf2e890e info/Products: Don't call sector p.e. "level p.e."
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
e5ea07b61a arm: Rework "cannot carry nukes" test for robustness
We reject satellites, ABMs, anti-ship missiles, and SAMs.  That's
enumerating badness.  More robust replacement: accept only bomber,
tactical, cargo, except for anti-ship missiles.

Throw in PLN_LAUNCHED sanity checking while there.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
0d6130246c ef_verify: Reject invalid plane flag combinations
Any plane may have capabilities VTOL, helo, light.

Capability missile requires VTOL.

Anti-ballistic missiles have capabilities missile, SDI.

Anti-satellite missiles have capabilities missile, satellite.

Surface-to-air missiles have capabilities missile, intercept.

Anti-ship missiles have capabilities missile, marine, and may have
tactical.

Surface-to-surface missiles have capability missile, and may have
tactical.

Satellites have capability satellite, and may have spy, image.

Ordinary planes may have capabilities bomber, tactical, intercept,
cargo, spy, image, ASW, para, escort, mine, sweep.  Capability para
requires cargo; see para().

Only "missile requires VTOL" is enforced.  Enforce the rest.

Excluding P_O when asking for P_N is now redundant.  Drop that from
msl_abm_intercept().

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
0d53d1a6e9 launch interception: Drop support for ABM, a-sat consuming shells
Their impact on the target does not depend on shell load (it sometimes
did for a-sats until commit cf960a573 "Make anti-sat launch consistent
with interception", v4.3.23).  The shell use is logistical busy-work,
and economically irrelevant.  Remove it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
10060390f5 config: Change asat not to consume shells
The asat's impact on the target does not depend on its shell load (it
sometimes did until commit cf960a573 "Make anti-sat launch consistent
with interception", v4.3.23).  The shell use is logistical busy-work,
and economically irrelevant.  Remove it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
a677cc31d7 mission: Don't permit marine missiles on support missions
Marine missiles can't actually support, see perform_mission().  Make
the mission command reject them.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
8a65621275 mission: Fix an error message pasto going back to Chainsaw 3
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
6f3f78481d mission: Don't permit SAMs on escort missions
The mission code doesn't treat SAMs specially: they take off, fly out,
maybe fight, fly home, and land.  Landing triggers the oops in
pln_put1().

Letting SAMs escort makes no sense.  Fix the mission command to reject
them.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
1c7d9a67f6 info/Plane-types: Document SAM, ABM and a-sat missile abilities
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
9dfe007701 info: Clean up references to long-gone options
Option DEFENSE_INFRA was replaced in commit 4d1dd6fa6, v4.3.6.  Point
to the replacement instead.

Options SHIPCHOPPERS and XLIGHT were made non-optional in Empire 2.
Don't mention them.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
75e9b97ba0 retreat: Drop unused parameter @code
Unused since commit beedf8dce "retreat: Rewrite automatic retreat code
to fix its many bugs", v4.3.33.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
16f0a07725 lwp: Include signal.h instead of ucontext.h where possible
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
eb0721507e subs/attsub: Drop a stale comment
Stale since commit 6ac9ad66e (v4.3.20) silently dropped dead code for
supply of military.  Dead since commit 689f435af (v4.2.14) dropped
option GRAB_THINGS.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
e5bccdd52e assault attack board lboard paradrop: Fix defending land unit supply
get_dlist() collects defending land units in a list, and resupplies
them.  Bug: it uses a local copy instead of the one in the list.  When
att_fight() writes back the list, the commodities supplied get wiped
out, triggering a seqno oops.  Broken in commit 62b9399cd "subs:
Factor lnd_insque() out of lnd_sel(), ask_olist(), ...", v4.3.33.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
8fc2c0ffa2 Update copyright notice
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
1e64ece1f5 Drop macros AGREE_FREE, AGREE_PROPOSED, AGREE_SIGNED
Commit 555de3100 (v4.3.0) added these macros so xdump tables loan and
treaty can share an agreement_statuses table.  Treaties are gone since
commit a109de948 (v4.3.33).  Drop the macros.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
5ed11ffd57 doc/coding: Improve section "Portability" a bit
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:29 +01:00
259200777e include: Move sarg.c stuff to nsc.h to avoid incomplete enum
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>
2021-01-17 21:24:29 +01:00
528d644f02 common/pathfind: A more portable DPRINTF()
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>
2021-01-17 21:24:29 +01:00
e18d1dc589 configure: Move terminfo check next to readline check
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
e23d0f6259 m4/my_lib_readline: Fix check for additional libraries
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>
2021-01-17 21:24:28 +01:00
882379f883 Make: Use SHELL to run test scripts, since /bin/sh may suck
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>
2021-01-17 21:24:28 +01:00
3f0718885a Make: Get SHELL from Autoconf
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>
2021-01-17 21:24:28 +01:00
f3c1edf8d2 Make: Slighly less verbose "make check" output
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
1a10b41ae8 info/Empire4.3: Work around "nroff: Out of temp file space"
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>
2021-01-17 21:24:28 +01:00
13362acc46 configure: Test GCC-specific compiler flags only when using GCC
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>
2021-01-17 21:24:28 +01:00
6cff488537 bomb: Pass NULL instead of 0 to pln_damage()
Neglected in commit 820d755e5 "subs: Change pln_damage()'s parameter
noisy to string prefix", v4.3.33.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
e312e4f8d6 bomb launch interdiction: Fix crash on bombs missing target
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>
2021-01-17 21:24:28 +01:00
77d3da4f09 Clarify build requirements
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>
2021-01-17 21:24:28 +01:00
deee99a01d Fix build for systems that don't provide POSIX.1-2001 by default
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>
2021-01-17 21:24:28 +01:00
ab93877534 client: Drop use of getpass()
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>
2021-01-17 21:24:28 +01:00
53b2271d1d client: Make get_password() not echo with POSIX && !HAVE_GETPASS
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>
2021-01-17 21:24:28 +01:00
ea762c1f08 client: Factor set_echo_if_tty() out of get_password()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
e551b6198d client: Move get_password() from login.c to getpass.c
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
f98747ae0e client: New get_password()
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>
2021-01-17 21:24:28 +01:00
057ca5b340 client: Reorder misc.h, and point to the .c
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
8a04586048 lwp: Simplify lwpSigWait() interface
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>
2021-01-17 21:24:28 +01:00
d89bda9998 lwp: Rename two variables for clarity
Rename LwpSigCaught to LwpPendingSig, and lwpCatchAwaitedSig() to
lwpHandleAwaitedSig().

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
8a1d9fbb4b lwp: Rewrite signal wait code for portability and safety
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>
2021-01-17 21:24:28 +01:00
bfb558dee3 lwp: Fix signal wait screwup for multiple different signals
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>
2021-01-17 21:24:28 +01:00
7481482656 lwp: Fix handling of sigismember() failure
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>
2021-01-17 21:24:28 +01:00
5315db952d lwp: Fix unsafe update of LwpSigCaught
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>
2021-01-17 21:24:28 +01:00
85ad194648 lwp: Drop inappropriate oops in lwpSigWait()
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>
2021-01-17 21:24:28 +01:00
1ebee96036 info: Use S_ISREG() instead of S_IFREG for readability
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
e91b4e3b6e info: Add #include <strings.h> for portability
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>
2021-01-17 21:24:28 +01:00
c3eb998396 Make: Fix build with tool chains that require depcomp
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>
2021-01-17 21:24:28 +01:00
f06473fbb4 build-aux/git-version-gen: Refresh from Gnulib commit 4f78c231f4
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
d5ce86dfc8 build-aux INSTALL: Refresh from automake 1.16.3
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
5a828769de m4: Refresh macros from autoconf-archive commit fd1d25c148
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
ada4678128 config: Enlarge configuration tables that have variable size
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>
2021-01-17 21:24:28 +01:00
e379edc648 config: Drop configuration table size macros
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>
2021-01-17 21:24:28 +01:00
a374e6435d Avoid SCT_TYPE_MAX, use ARRAY_SIZE() instead
The next commit will get rid of SCT_TYPE_MAX.  Prepare.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
5e45859979 New macro ARRAY_SIZE()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
50d84c025b econfig: Fix documentation of key assault_penalty
Messed up when keys got documented in 4.2.0.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
46ab8b59e6 info/Empire4.4: Fix more 4.4.0 change log entry typos
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
56ce1eaada fairland: Tidy up comments
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>
2021-01-17 21:24:28 +01:00
ae85142a68 fairland: Rename fl_move() to drift_capital()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
200059b65b fairland: Move qprint() and NUMTRIES
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>
2021-01-17 21:24:28 +01:00
d8db5b7308 fairland: Fuse capx[], capy[] into cap[]
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
9c9e0ff8d5 fairland: Fuse sectx[], secty[] into sect[]
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
4413a8e1b2 fairland: Simplify how write_sect() iterates over sectors
Iterating over IDs is slightly simpler than iterating over
coordinates, so do that.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
7039ef6767 fairland: Represent sector ownership more efficiently
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>
2021-01-17 21:24:28 +01:00
8a40b6b15c fairland: Tweak rural iron, fert, oil for simplicity
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>
2021-01-17 21:24:28 +01:00
5b5e2cdfa8 fairland: Compute resources by interpolating tables
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>
2021-01-17 21:24:28 +01:00
39ef156f00 fairland: Tweak sea oil & mountain gold for simplicity
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>
2021-01-17 21:24:28 +01:00
fdd55428c3 fairland: Rewrite complicated, buggy & boring elevation code
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>
2021-01-17 21:24:28 +01:00
2105ed3fa1 fairland: Tweak rural elevations for simplicity
elevate_land() computes the sequence of elevations 97, 97 - delta,
... in fixed point with a scaling factor of 100.  Switch to
floating-point, because it's simpler.  Elevations (and thus resources)
change slightly due to reduced rounding errors.

Note that we map elevations less than 1 to 1 both before and after the
patch.  Odd.  Turns out this mitigates a bug: mountain placement can
place fewer mountains than it should, and when that happens,
elevations go below 1 here.  The next commit will fix this.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
7a3af61016 fairland: Drop unused elevation band for coastal mountains
Elevations 34 and 35 are reserved for coastal mountains.  When an
elevation computed for a non-mountain falls in that band, it's
adjusted to 36.

This is unnecessary since the previous commit; drop.  Test output
shows the dropped elevation adjustment.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
7502a2c4c9 fairland: Fair mountain resources
For fairness, fairland aims to make islands of the same size consist
of the exact same sectors, just individually arranged.

It fails to achieve its aim for mountains: their elevation is random,
34 or 35 for coastal mountains, and between 98 and 254 (two dice) for
non-coastal ones.  Elevation determines resources.  Mountains get 89
gold on average (between 80 and 93), except for coastal mountains,
which get none.  It didn't really matter until Empire 3 made mountains
produce gold dust.  Since then, it's unfair.

Set mountain elevation to 98 + i * delta, where i is the mountain
number (starting at zero), delta is (127 - 98) / max_mn, and max_mn is
the maximum number of mountains an island could have.  This puts the
highest mountains on the largest islands.

Non-coastal mountains have slightly less gold than before, coastal
mountains have much more.

Mountains can still be unfair, because fairland can screw up their
number.  To be fixed soon.

Avoid elevations 34 and 35 for non-mountain, non-capital sectors
doesn't make sense anymore.  The next commit will get rid of it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
fd64db89d2 fairland: Use zero elevation for "not yet elevated"
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
54782fb4c1 fairland: Eliminate sectc[][], use adj_land[] instead
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
51bf9f7822 fairland: Replace distance_to_land(), distance_to_sea()
distance_to_land() searches for closest land sector, and
distance_to_sea() for the closest sea sector.  We already have a more
efficient alternative: the breadth-first search recently added for
spheres of influence can precompute these distances.  Put it to use,
and retire distance_to_land() and distance_to_sea().

distance_to_what() could now be simplified.  Don't bother, because
it'll soon be deleted entirely.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
60a89a83c7 fairland: Eliminate macro ELEV, it's an abomination
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
fe86ea430a fairland: Prefer placing islands away from the edge of the sphere
When an island gets placed too close to the edge of the sphere of
influence, its side facing the edge will likely be formed by the edge.
Looks unnatural, and can give a clue on the location of the other
continent.

Make place_island() prefer sectors away from the edge: instead of
picking one of the admissible sectors with equal probability, reduce
the probability as we get closer to the edge.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
4fca4dfddd fairland: Try harder to deliver the requested amount of land
Planned island sizes are random with an expected value that matches
the average size requested by the user.  Can be off quite a bit when
the number of islands is small.  Also, actual island size can be
smaller than planned size when space is tight.

Instead of picking random island sizes independently, pick a random
split of their requested total size.

To reduce the probability of islands not growing to their planned
size, grow large islands before smaller ones.

To compensate for inability to grow, carry the difference over to the
next island size.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-17 21:24:28 +01:00
08ca6ace12 fairland: Make actual island sizes fair
The previous commit reduced the difference in island size within the
same batch of islands to at most one.  Eliminate the remaining
difference by shrinking the bigger islands by one sector.

This invalidates the precomputed exclusive zones, so recompute them.

fairland-test needs a tweak to avoid loss of test coverage.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:37 +01:00
212c7ddcef fairland: Grow islands interleaved
The previous commits changed grow_island() to create islands in
batches consisting of one island per continent, all of the same
planned size.  grow_island() still places and grows one island after
the other.  When an island can't grow to the actual size, the others
in the same batch are not affected.  Island size can therefore differ
a lot within the same batch.

Change grow_island() to interleave the work on a batch's island: first
place them all, then add one sector to each in turn.  Stop after all
reached the planned size, or one or more could not be grown further.

This is similar to how we grow continents: drift() places them all,
and grow_continent() adds one sector to each continent in turn.

Island size within the same batch can now differ at most by one
sector.  The next commit will eliminate that remaining difference.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
ca110e55ed fairland: Make planned island sizes fair
The previous two commits put the same number of islands closest to
each continent.  This one makes their planned sizes match: instead of
rolling dice separately for each island's size, we roll dice only for
the first continent's islands.  The other continent's islands get the
same sizes.

Actual island sizes still differ when islands can't be grown to their
planned size.  To be addressed next.

fairland-test needs a tweak to avoid loss of test coverage.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
18687315ac fairland: Fail when island can't be placed, for fairness
The previous commit made island distribution more fair by placing
islands close to a continent in turn.  This is still unfair when
fairland can't place all the islands.

Make grow_islands() fail when it can't place all islands, and main()
start over then, just like it does when grow_continents() fails.

Deities can no longer fill the world with islands by asking for a
impossibly high number of islands.  Tolerable loss, I think.

fairland-test needs a tweak to avoid loss of test coverage.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
74bc8adb63 fairland: Distribute islands more fairly among continents
fairland places islands of random size in random places, subject to
minimum distances.  Results are often less than fair, in particular
when the number of islands per continent is low: some continents have
more land nearby than others.  Increasing distances between islands
doesn't help much.  Deities commonly run fairland until they find the
result acceptable.

The next few commits will tackle this issue.  As a first step, this
one places islands closest to continents in turn, so that each
continent is closest to the same number of islands.  A continent is
closest to an island when it is closest to each of its sectors.

The number of islands must be a multiple of the number of continents
now.

Since fairland may be unable to place all islands, a continent may
still get fewer islands than it should.  The next commit will address
that.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
446005f84c fairland: Compute spheres of influence
A continent's sphere of influence is the set of sectors closer to it
than to any other continent.  The next commit needs this.  Compute the
spheres with a breadth-first search.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
5a13bef8e2 fairland: Eliminate dirx[], diry[]
dirx[] and diry[] are redundant with diroff[][].  Convert the
remaining uses, and drop the arrays.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
73c103e9df fairland: Fix island growth and correct its bias
grow_one_sector() picks a coastal start sector, then moves along the
coast trying to add an adjacent sector to the island.

It operates in spiking mode with a chance of @sp percent.

When spiking, the neighbors with sea on both sides are preferred.  For
instance, when the area around the sector being considered looks like
this

     - .
    - - .
     - .

then the neighbor in direction j is preferred, because it has sea in
directions u and n.  No other neighbor is preferred.

The start sector is the first coastal sector found in a linear search
in growth order, starting at the last sector grown when spiking, or
else at a random sector.  This is new_try().

grow_one_sector() tries adding a neighbor in clockwise order, starting
with a random direction.  When spiking, it goes around the clock two
times, trying only preferred sectors in the first round.

When it can't add a neighbor, it moves to the next coastal sector with
next_coast().

Taken together, this randomly picks one element from the set of
pairs (S, D) where the sector in direction D off base sector S can be
added to the island.  How does the probability distribution look like?

Bias: a sector's probability to be added to the island land increases
with the number of base sectors it is adjacent to.  This tends to fill
in bays and lakes, which is fine.

Bias: coastal sectors following runs of non-coastal ones are more
likely to be picked as start sector.  Perhaps less of an issue when
spiking, where the pick is not intended to be random.

Bias: a pair (S, D) is more likely to be picked when base sector S
follows a run of coastal sectors that aren't base sectors, or
direction D follows a a run of directions that don't permit growth.

The impact of these two biases is not obvious.  I suspect they are the
reason behind the tendency of large islands to curve around obstacles
in a counterclockwise direction.  This can result in multiple islands
wrapping around a central one like layers of an onion.

Bug: the move along the coast is broken.  next_coast() searches for
the first adjacent sea in clockwise order, starting in direction g,
then from there clockwise for a sector belonging to the island.
Amazingly, this does move along the coast in a clockwise direction.
It can get caught in a loop, though.  Consider this island:

        -
     - - -
      -

If we start at the central sector (marked 0), the search along the
coast progresses like this:

        1
     - 0 2
      -

It reaches the central sector again after three moves (to 1, to 2,
back to 0), and stops without having reached the two sectors on the
left.

If we start with the leftmost sector, the search loops: 0, 1, 2, 3, 1,
...

        2
     0 1 3
      -

grow_one_sector() ensures termination by giving up after 200 moves.
Nuts!

Because of this, grow_one_sector() can fail when it shouldn't, either
because the search along the coast stops early, or goes into a loop,
or simply because there's too much coast.  The latter should not
happen in common usage, where island sizes are in the tens, not the
hundreds.

Clean up this hot mess by rewriting grow_one_sector() to pick a sector
adjacent to the island with a clearly defined probability, as follows.

Use weighted random sampling to pick one sector from the set of
possible adjacent sectors.

When spiking, a sector's weight increases with number of adjacent sea
sectors.  This directs the growth away from land, resulting in spikes.

When not spiking, the weight increases with the number of adjacent
land sectors.  This makes the island more rounded.

To visit the adjacent sectors, grow_one_sector() iterates over the
neighbors of all island sectors, skipping neighbors that have been
visited already.

This produces comparable results for low spike percentages.  The weird
onions are gone, though.

Noticeable differences emerge as the spike percentage grows.  Whereas
the old one produces long snakes that tend to curve into themselves,
the new one produces shorter spikes extending from a core, a bit like
tentacles.  Moreover, islands are more centered on their first sector
now.  The probability for coastal capitals is lower, in particular for
moderate spike percentages.

I consider this improvements.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-05 10:41:36 +01:00
45 changed files with 163 additions and 281 deletions

4
.gitignore vendored
View file

@ -60,7 +60,3 @@
*.orig
*.rej
*~
# Visual Studio Directories for building
/.vs
/Empire

View file

@ -81,8 +81,8 @@ edatadir := $(datadir)/empire
builtindir := $(edatadir)/builtin
einfodir := $(edatadir)/info.nr
ehtmldir := $(edatadir)/info.html
client/w32 := arpa/inet.h getopt.c netdb.h netinet/in.h sys/time.h \
sys/socket.h sys/uio.h unistd.h w32io.c w32sockets.c w32types.h
client/w32 := arpa/inet.h netdb.h netinet/in.h sys/time.h sys/socket.h \
sys/uio.h unistd.h w32io.c w32sockets.c w32types.h
# Abbreviate make output
# Run make with a V=1 parameter for full output.

View file

@ -27,7 +27,7 @@
* item.h: Definitions for item characteristics stuff
*
* Known contributors to this file:
* Markus Armbruster, 2004-2020
* Markus Armbruster, 2004-2016
*/
#ifndef ITEM_H
@ -80,8 +80,7 @@ struct ichrstr {
/* variables using this structure */
#define ICHR_SZ (I_MAX + 2)
extern struct ichrstr ichr[ICHR_SZ];
extern struct ichrstr ichr[I_MAX + 2];
/* procedures using/returning this struct */

View file

@ -124,8 +124,7 @@ struct lchrstr {
#define putland(n, p) ef_write(EF_LAND, (n), (p))
#define getlandp(n) ((struct lndstr *)ef_ptr(EF_LAND, (n)))
#define LCHR_SZ 128
extern struct lchrstr lchr[LCHR_SZ];
extern struct lchrstr lchr[128];
enum {
LND_AIROPS_EFF = 50 /* min. efficiency for air ops */

View file

@ -82,8 +82,7 @@ struct nchrstr {
#define putnuke(n, p) ef_write(EF_NUKE, (n), (p))
#define getnukep(n) ((struct nukstr *)ef_ptr(EF_NUKE, (n)))
#define NCHR_SZ 64
extern struct nchrstr nchr[NCHR_SZ];
extern struct nchrstr nchr[64];
/* src/lib/common/cargo.c */
extern void nuk_carrier_change(struct nukstr *, int, int, int);

View file

@ -134,8 +134,7 @@ struct plist {
#define putplane(n, p) ef_write(EF_PLANE, (n), (p))
#define getplanep(n) ((struct plnstr *)ef_ptr(EF_PLANE, (n)))
#define PLCHR_SZ 128
extern struct plchrstr plchr[PLCHR_SZ];
extern struct plchrstr plchr[128];
struct shiplist {
int uid;

View file

@ -58,7 +58,6 @@ struct pchrstr {
char *p_sname; /* short (7 char or less) name of product */
};
#define PCHR_SZ 32
extern struct pchrstr pchr[PCHR_SZ];
extern struct pchrstr pchr[32];
#endif

View file

@ -165,9 +165,7 @@ struct dchrstr {
#define getsectp(x, y) ((struct sctstr *)ef_ptr(EF_SECTOR, sctoff((x), (y))))
#define getsectid(id) ((struct sctstr *)ef_ptr(EF_SECTOR, (id)))
#define DCHR_SZ 64
extern struct dchrstr dchr[DCHR_SZ];
extern struct dchrstr dchr[64];
#define IS_BIG_CITY(type) (dchr[(type)].d_pkg == UPKG)
/* Minimal efficiency of sectors that can be knocked down (bridges) */
@ -223,8 +221,7 @@ struct sctintrins {
unsigned char in_enable; /* enabled iff non-zero */
};
#define INTRCHR_SZ INT_DEF + 2
extern struct sctintrins intrchr[INTRCHR_SZ];
extern struct sctintrins intrchr[INT_DEF + 2];
extern int fort_fire(struct sctstr *);
extern int sct_rail_track(struct sctstr *);

View file

@ -126,8 +126,7 @@ struct mchrstr {
#define putship(n, p) ef_write(EF_SHIP, (n), (p))
#define getshipp(n) ((struct shpstr *)ef_ptr(EF_SHIP, (n)))
#define MCHR_SZ 128
extern struct mchrstr mchr[MCHR_SZ];
extern struct mchrstr mchr[128];
enum {
SHP_AIROPS_EFF = 50, /* min. efficiency for air ops */

View file

@ -5,7 +5,7 @@
This document outlines the various changes to the game and how they
will affect you, the player. These were coded as the Wolfpack project.
.NF
Changes to Empire 4.4.1 - Sat Feb 21 2021
Changes to Empire 4.4.1 - Sun Jan 17 2021
* Fix land unit casualties in guerrilla fighting. Broken in 4.4.0.
* Changes to edit:
- You can now edit bars on ships and land units, and missile
@ -61,7 +61,7 @@ Changes to Empire 4.4.1 - Sat Feb 21 2021
when it can't place all the islands the deity asks for. You
can't fill the world with islands anymore by asking for
impossibly many of them.
- Fix silent failure to place mountains. Fairness issue.
- Fix silent failure to place place mountains. Fairness issue.
- Fix unfair mountain resources. Neglected when Empire 3 made
mountains produce gold dust.
- Drop undocumented, silent limit of 1000 mountains per island.
@ -74,8 +74,8 @@ Changes to Empire 4.4.1 - Sat Feb 21 2021
- Manual page improvements.
- Code refactoring and cleanup.
* Test suite improvements:
- Fix empdump-test for "make check-accept". Has been broken since
its addition in 4.3.33.
- Fix empdump-test for "make check-accept". Has been broken its
addition in 4.3.33.
- Improve give and edit coverage.
- Cover load and tend. There are known gaps.
- Improve fairland coverage.
@ -97,8 +97,8 @@ Changes to Empire 4.4.1 - Sat Feb 21 2021
systems: read from standard input in canonical mode with echo
turned off. Before, it commonly read from /dev/tty in noncanonical
mode.
* The server crashed on some systems when bomb, launch and
interdiction missed the target. Fix that.
* The server crashed on systems when bomb, launch and interdiction
miss the target. Fix that.
* Fix truncated "info Empire4.3" on systems with a losing nroff.
* Make client's fancy line editing and persistent history work on
more systems.
@ -118,14 +118,9 @@ Changes to Empire 4.4.1 - Sat Feb 21 2021
third more than before.
* Fix crash when a deity runs neweff or production on a sea sector.
Broken in 4.4.0.
* Don't let embarked engineers work. Screwed up when the work
command was added in Empire 2.
* Fix buy to handle concurrent lot change more robustly. The flawed
handling goes back to 4.0.0 and 4.0.2.
* Fix MOB_ACCESS mobility update for ships owned by countries with
even country number. Broken in 4.4.0.
* Journal entries for output are no longer flushed to disk right
away.
* Don't let embarked engineers work. Screwed up when the command was
added in Empire 2.
* Fix buy error messages on concurrent lot change.
* Code refactoring and cleanup.
* Info page, manual page and documentation fixes and clarifications.

View file

@ -12,8 +12,6 @@ AC_DEFUN([MY_WINDOWS_API],
AC_DEFINE([WINDOWS], 1, [Define if compiling for Windows API])
AC_DEFINE([WIN32_LEAN_AND_MEAN], 1,
[Define to make Windows includes pull in less junk])
AC_DEFINE([_WIN32_WINNT], 0x0601,
[Request Windows 7])
LIBS_SOCKETS="-lws2_32"
else
LIBS_SOCKETS=

View file

@ -101,6 +101,5 @@ host.$O: w32/sys/socket.h w32/netinet/in.h w32/arpa/inet.h w32/netdb.h w32/unist
main.$O: w32/sys/socket.h w32/unistd.h w32/w32types.h
play.$O: w32/sys/socket.h w32/unistd.h w32/w32types.h
ringbuf.$O: w32/sys/uio.h w32/w32types.h
w32/getopt.$O:
w32/w32io.$O: misc.h w32/sys/uio.h w32/w32types.h
w32/w32sockets.$O: w32/sys/socket.h w32/unistd.h w32/w32types.h

View file

@ -30,7 +30,7 @@
* Dave Pare, 1986
* Ken Stevens, 1995
* Steve McClure, 2000
* Markus Armbruster, 2006-2018
* Markus Armbruster, 2006-2021
*/
#include <config.h>

View file

@ -30,7 +30,7 @@
* Dave Pare, 1986
* Pat Loney, 1992
* Steve McClure, 1996-2000
* Markus Armbruster, 2004-2021
* Markus Armbruster, 2004-2018
*/
#include <config.h>

View file

@ -40,9 +40,7 @@
#include <errno.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#if !defined(_WIN32)
#include <strings.h>
#include <dirent.h>
#endif
@ -273,7 +271,7 @@ c_apropos(void)
#else /* _WIN32 */
int
c_info(void)
info(void)
{
char buf[255];
FILE *fp;
@ -386,7 +384,7 @@ c_info(void)
}
int
c_apropos(void)
apro(void)
{
HANDLE hDir;
WIN32_FIND_DATA fData;

View file

@ -263,8 +263,7 @@ launch_missile(struct plnstr *pp)
target_ship.shp_x, target_ship.shp_y,
target_ship.shp_own, &sublaunch) < 0)
return RET_OK;
/* @target_ship may have expended shells defending */
getship(target_ship.shp_uid, &target_ship);
getship(n, &target_ship);
if (!msl_hit(pp, shp_hardtarget(&target_ship), EF_SHIP,
N_SHP_MISS, N_SHP_SMISS, sublaunch,
target_ship.shp_own)) {

View file

@ -30,7 +30,7 @@
* David Sharnoff, 1987
* Ken Stevens, 1995 (rewritten)
* Steve McClure, 1998-2000
* Markus Armbruster, 2004-2021
* Markus Armbruster, 2004-2018
*/
#include <config.h>
@ -79,12 +79,12 @@ c_load(void)
"What commodity (or 'plane' or 'land')? ", buf);
if (!p || !*p)
return RET_SYN;
ich = item_by_name(p);
if (!strncmp(p, "plane", 5))
type = EF_PLANE;
else if (!strncmp(p, "land", 4))
type = EF_LAND;
else if (ich)
else if (NULL != (ich = item_by_name(p)))
type = EF_SECTOR;
else {
pr("Can't %sload '%s'\n", loading ? "" : "un", p);
@ -208,12 +208,11 @@ c_lload(void)
"What commodity (or 'plane' or 'land')? ", buf);
if (!p || !*p)
return RET_SYN;
ich = item_by_name(p);
if (!strncmp(p, "plane", 5))
type = EF_PLANE;
else if (!strncmp(p, "land", 4))
type = EF_LAND;
else if (ich)
else if (NULL != (ich = item_by_name(p)))
type = EF_SECTOR;
else {
pr("Can't %sload '%s'\n", loading ? "" : "un", p);

View file

@ -393,7 +393,7 @@ c_fire(void)
putsect(&vsect);
break;
default:
getship(vship.shp_uid, &vship);
getship(vshipno, &vship);
shipdamage(&vship, dam);
if (vship.shp_effic < SHIP_MINEFF)
pr("%s sunk!\n", prsub(&vship));

View file

@ -30,7 +30,7 @@
* Dave Pare, 1986
* Thomas Ruschak, 1992
* Steve McClure, 2000
* Markus Armbruster, 2004-2021
* Markus Armbruster, 2004-2017
*/
#include <config.h>
@ -70,10 +70,10 @@ c_tend(void)
buf);
if (!p || !*p)
return RET_SYN;
ip = item_by_name(p);
if (!strncmp(p, "land", 4))
type = EF_LAND;
else if (ip)
else if (NULL != (ip = item_by_name(p)))
type = EF_SECTOR;
else {
pr("Can't tend '%s'\n", p);

View file

@ -27,7 +27,7 @@
* work.c: Implementation of the work command
*
* Known contributors to this file:
* Markus Armbruster, 2009-2021
* Markus Armbruster, 2009-2016
*/
#include <config.h>

View file

@ -42,7 +42,7 @@
#include "sect.h"
#ifdef PATH_FIND_DEBUG
#define DPRINTF(...) ((void)fprintf(stdout, ## __VA_ARGS__))
#define DPRINTF(...) ((void)printf(## __VA_ARGS__))
#else
#define DPRINTF(...) ((void)0)
#endif
@ -490,11 +490,12 @@ path_find_visualize(coord sx, coord sy, coord dx, coord dy)
{
int uid;
int xmin, xmax, ymin, ymax, x, y, odd, ch;
double c, cost;
double c, u, cost;
char buf[1024];
assert(pf_cost(XYOFFSET(sx, sy)) == 0.0);
c = pf_cost(XYOFFSET(dx, dy));
u = c / 10.0;
/* find bounding box */
xmin = xmax = 0;

View file

@ -27,7 +27,7 @@
* chance.c: Roll dice
*
* Known contributors to this file:
* Markus Armbruster, 2006-2021
* Markus Armbruster, 2006-2012
*/
#include <config.h>
@ -140,12 +140,11 @@ djb_hash(unsigned hash, void *buf, size_t sz)
unsigned
pick_seed(void)
{
int fd;
unsigned seed;
int got_seed = 0;
struct timeval tv;
pid_t pid;
#ifndef _WIN32
int fd;
/*
* Modern systems provide random number devices, but the details
@ -165,7 +164,6 @@ pick_seed(void)
got_seed = read(fd, &seed, sizeof(seed)) == sizeof(seed);
close(fd);
}
#endif
if (!got_seed) {
/* Kernel didn't provide, fall back to hashing time and PID */

View file

@ -38,4 +38,4 @@
* Table of item types
* Initialized on startup from item.config and deity custom config (if any).
*/
struct ichrstr ichr[ICHR_SZ];
struct ichrstr ichr[I_MAX + 2];

View file

@ -43,7 +43,7 @@
* Initialized on startup from land.config and deity custom config (if any).
* Terminated by a sentinel with null l_name.
*/
struct lchrstr lchr[LCHR_SZ];
struct lchrstr lchr[];
#define logx(a, b) (log((a)) / log((b)))
#define LND_ATTDEF(b, t) (((b) * (1.0 + ((sqrt((t)) / 100.0) * 4.0))) \

View file

@ -38,4 +38,4 @@
* Table of nuke types
* Initialized on startup from nuke.config and deity custom config (if any).
*/
struct nchrstr nchr[NCHR_SZ];
struct nchrstr nchr[];

View file

@ -45,7 +45,7 @@
* Initialized on startup from plane.config and deity custom config (if any).
* Terminated by a sentinel with null pl_name.
*/
struct plchrstr plchr[PLCHR_SZ];
struct plchrstr plchr[];
#define logx(a, b) (log((a)) / log((b)))
#define PLN_ATTDEF(b, t) (b + ((b?1:0) * ((t/20)>10?10:(t/20))))

View file

@ -38,4 +38,4 @@
* Table of product types
* Initialized on startup from product.config and deity custom config (if any).
*/
struct pchrstr pchr[PCHR_SZ];
struct pchrstr pchr[];

View file

@ -43,10 +43,10 @@
* Initialized on startup from sect.config and deity custom config (if any).
* Terminated by a sentinel with null d_name.
*/
struct dchrstr dchr[DCHR_SZ];
struct dchrstr dchr[];
/*
* Table of infrastructure types
* Initialized on startup from infra.config and deity custom config (if any).
*/
struct sctintrins intrchr[INTRCHR_SZ];
struct sctintrins intrchr[INT_DEF + 2];

View file

@ -45,7 +45,7 @@
* Initialized on startup from ship.config and deity custom config (if any).
* Terminated by a sentinel with null m_name.
*/
struct mchrstr mchr[MCHR_SZ];
struct mchrstr mchr[];
#define logx(a, b) (log((a)) / log((b)))
#define SHP_DEF(b, t) (t ? (b * (logx(t, 40.0) < 1.0 ? 1.0 : \

View file

@ -128,8 +128,7 @@ journal_entry_end(int newline, int flush)
if (!newline)
fputc('\\', journal);
fputc('\n', journal);
if (flush)
fflush(journal);
fflush(journal);
if (ferror(journal)) {
logerror("Error writing journal (%s)", strerror(errno));
clearerr(journal);

View file

@ -111,7 +111,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
curx = start->sct_x;
cury = start->sct_y;
total_mcost = 0.0;
if (!getsect(curx, cury, &sect)) {
if (getsect(curx, cury, &sect) < 0) {
logerror("move_path: getsect %d,%d", curx, cury);
return -1;
}
@ -191,7 +191,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
*/
tmpx = curx + diroff[dir][0];
tmpy = cury + diroff[dir][1];
if (!getsect(tmpx, tmpy, &next)) {
if (getsect(tmpx, tmpy, &next) < 0) {
pr("You can't go there...\n");
*movstr = 0;
continue;

View file

@ -56,7 +56,7 @@ shp_postread(int n, void *ptr)
player->owner = (player->god || sp->shp_own == player->cnum);
if (opt_MOB_ACCESS && sp->shp_own && !update_running)
if (opt_MOB_ACCESS & sp->shp_own && !update_running)
mob_inc_ship(sp, game_tick_to_now(&sp->shp_access));
}

View file

@ -31,7 +31,7 @@
* Jeff Bailey, 1990
* Steve McClure, 1996
* Ron Koenderink, 2005-2009
* Markus Armbruster, 2006-2021
* Markus Armbruster, 2006-2020
*/
#include <config.h>
@ -615,10 +615,34 @@ static char *
fmttime2822(time_t t)
{
static char buf[32];
size_t n = strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z",
#if defined(_WIN32)
size_t n;
int nn;
TIME_ZONE_INFORMATION tzi;
long time_offset;
struct tm *time;
time = localtime(&t);
n = strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S", time);
if (CANT_HAPPEN(n == 0)) {
buf[0] = 0;
return buf;
}
GetTimeZoneInformation(&tzi);
time_offset = -(tzi.Bias +
(time->tm_isdst ? tzi.DaylightBias : tzi.StandardBias));
nn = _snprintf(buf + n, sizeof(buf) - n, " %+03ld%02ld",
time_offset / 60, labs(time_offset) % 60);
if (CANT_HAPPEN(nn <= 0 || nn + n >= sizeof(buf)))
buf[0] = 0;
#else
size_t n = strftime(buf, sizeof(buf), "%a, %d %b %Y %T %z",
localtime(&t));
if (CANT_HAPPEN(n == 0))
buf[0] = 0;
#endif
return buf;
}

View file

@ -233,6 +233,7 @@ takeover_unit(struct empobj *unit, natid newown)
struct shpstr *sp;
struct plnstr *pp;
struct lndstr *lp;
struct nukstr *np;
int type;
struct nstr_item ni;
union empobj_storage cargo;
@ -261,6 +262,8 @@ takeover_unit(struct empobj *unit, natid newown)
lp->lnd_harden = 0;
break;
case EF_NUKE:
np = (struct nukstr *)unit;
np->nuk_off = 1;
break;
default:
CANT_REACH();

View file

@ -28,7 +28,7 @@
*
* Known contributors to this file:
* Steve McClure, 2000
* Markus Armbruster, 2005-2021
* Markus Armbruster, 2005-2016
*/
#include <config.h>
@ -110,16 +110,14 @@ typed_wu(natid from, natid to, char *message, int type)
char box[1024];
struct player *other;
if (type == TEL_ANNOUNCE) {
if (type == TEL_ANNOUNCE)
strcpy(box, annfil);
np = NULL;
} else {
else
mailbox(box, to);
np = getnatp(to);
if (!np || np->nat_stat < STAT_SANCT)
return -1;
}
if (type != TEL_ANNOUNCE)
if (!(np = getnatp(to)) || np->nat_stat < STAT_SANCT)
return -1;
#if !defined(_WIN32)
if ((fd = open(box, O_WRONLY | O_APPEND, 0)) < 0) {
#else

View file

@ -29,7 +29,7 @@
* Known contributors to this file:
* Dave Pare, 1986
* Steve McClure, 1996
* Markus Armbruster, 2004-2021
* Markus Armbruster, 2004-2016
*/
#include <config.h>

View file

@ -33,6 +33,9 @@
#ifndef ARPA_INET_H
#define ARPA_INET_H
#include "ws2tcpip.h"
#include "sys/socket.h"
extern const char *inet_ntop(int af, const void *src, char *dst,
socklen_t cnt);
#endif /* ARPA_INET_H */

View file

@ -1,150 +0,0 @@
#ifdef _MSC_VER
#define __UNCONST(a) ((void *)(a))
#define _DIAGASSERT(cond) assert((cond))
#define getprogname() ((const char *)nargv[0])
/* $NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#include <sys/cdefs.h>
__RCSID("$NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $");
#include "namespace.h"
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __weak_alias
__weak_alias(getopt,_getopt)
#endif
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(int nargc, char * const nargv[], const char *ostr)
{
static const char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(ostr != NULL);
if (optreset || *place == 0) { /* update scanning pointer */
optreset = 0;
place = nargv[optind];
if (optind >= nargc || *place++ != '-') {
/* Argument is absent or is not an option */
place = EMSG;
return (-1);
}
optopt = *place++;
if (optopt == '-' && *place == 0) {
/* "--" => end of options */
++optind;
place = EMSG;
return (-1);
}
if (optopt == 0) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
place = EMSG;
if (strchr(ostr, '-') == NULL)
return -1;
optopt = '-';
}
} else
optopt = *place++;
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*place == 0)
++optind;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: unknown option -- %c\n", getprogname(),
optopt);
return (BADCH);
}
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (*place == 0)
++optind;
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*place)
optarg = __UNCONST(place);
else if (oli[2] == ':')
/*
* GNU Extension, for optional arguments if the rest of
* the argument is empty, we return NULL
*/
optarg = NULL;
else if (nargc > ++optind)
optarg = nargv[optind];
else {
/* option-argument absent */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
getprogname(), optopt);
return (BADCH);
}
place = EMSG;
++optind;
}
return (optopt); /* return option letter */
}
#endif

View file

@ -33,7 +33,7 @@
#include <config.h>
#include <windows.h>
#include <errno.h>
#include "sys/resource.h"
int

View file

@ -4,9 +4,6 @@
*/
#include "w32misc.h"
#ifdef _MSC_VER
#define tzname _tzname
#endif
typedef unsigned char u_char;
typedef unsigned int uint;

View file

@ -33,15 +33,9 @@
#ifndef SYS_TIME_H
#define SYS_TIME_H
#ifdef _MSC_VER
/* include winsock2.h thru sys/socket.h to get struct timeval */
#include "sys/socket.h"
extern int gettimeofday(struct timeval *tv, void *tz);
#else /* !_MSC_VER */
#include_next <sys/time.h>
#endif
#endif /* SYS_TIME_H */

View file

@ -27,7 +27,7 @@
* unistd.h: POSIX emulation for Windows
*
* Known contributors to this file:
* Ron Koenderink, 2007-2021
* Ron Koenderink, 2007
* Markus Armbruster, 2007-2013
*/
@ -46,6 +46,7 @@
* here. Major name space pollution, can't be helped.
*/
#include <direct.h>
#include <getopt.h>
#include <io.h>
#include <process.h>
#include <sys/stat.h>
@ -59,7 +60,6 @@
extern int w32_mkdir(const char *dirname, mode_t perm);
/* Should be in sys/stat.h */
#ifdef _MSC_VER
#ifndef S_IRUSR
#define S_IRUSR _S_IREAD
#define S_IWUSR _S_IWRITE
@ -78,34 +78,22 @@ extern int w32_mkdir(const char *dirname, mode_t perm);
#define S_IXOTH 0
#define S_IRWXO S_IROTH | S_IWOTH | S_IXOTH
#endif
#endif
/* Should be in fcntl.h */
/* HACK, for use with fcntl() on a socket only, see w32sockets.c */
#define O_NONBLOCK 1
#define F_GETFL 1
#define F_SETFL 2
extern int fcntl(int fd, int cmd, ...);
/* Stuff that actually belongs here */
#define close(fd) w32_close_function((fd))
extern int (*w32_close_function)(int);
#define ftruncate(fd, length) _chsize((fd), (length))
#define read(fd, buf, sz) w32_read_function((fd), (buf), (sz))
extern int (*w32_read_function)(int, void *, unsigned);
#define write(fd, buf, sz) w32_write_function((fd), (buf), (sz))
extern int (*w32_write_function)(int, const void *, unsigned);
#ifdef _MSC_VER
#define ftruncate(fd, length) _chsize((fd), (length))
#endif
#ifdef _MSC_VER
extern int getopt(int, char * const [], const char *);
extern char *optarg;
extern int opterr;
extern int optind;
extern int optopt;
#else /* !_MSC_VER */
#include_next <unistd.h>
#endif
#endif /* UNISTD_H */

View file

@ -28,7 +28,7 @@
*
* Known contributors to this file:
* Ron Koenderink, 2007
* Markus Armbruster, 2007-2021
* Markus Armbruster, 2007-2013
*/
/*
@ -41,16 +41,30 @@
#include <stddef.h>
/* strings.h */
#ifdef _MSC_VER
/* integral mismatch, due to misuse of sector short */
#pragma warning (disable : 4761 )
/* strings.h */
#define strncasecmp(s1, s2, s3) _strnicmp((s1), (s2), (s3))
#endif /* _MSC_VER */
/* errno.h */
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
/* fcntl.h */
#ifdef _MSC_VER
#define O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR)
#endif
/* stdio.h */
#ifdef _MSC_VER
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#endif
/* time.h */
struct tm;
extern char *strptime(const char *buf, const char *fmt, struct tm *tm);

View file

@ -232,6 +232,43 @@ w32_socket(int domain, int type, int protocol)
return W32_SOCKET_TO_FD(sock);
}
#ifdef HAVE_GETADDRINFO
const char *
inet_ntop(int af, const void *src, char *dst, socklen_t len)
{
struct sockaddr *sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
size_t salen;
if (af == AF_INET) {
memset(&sin, 0, sizeof(sin));
sin.sin_family = af;
memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
sa = (struct sockaddr *)&sin;
salen = sizeof(sin);
} else if (af == AF_INET6) {
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = af;
memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
sa = (struct sockaddr *)&sin6;
salen = sizeof(sin6);
} else {
WSASetLastError(WSAEAFNOSUPPORT);
w32_set_winsock_errno();
return NULL;
}
if (getnameinfo(sa, salen, dst, len, NULL, 0, NI_NUMERICHOST)) {
WSASetLastError(WSAEAFNOSUPPORT);
w32_set_winsock_errno();
return NULL;
}
return dst;
}
#endif
/*
* POSIX equivalent for fcntl().
* Horrible hacks, just good enough support Empire's use of fcntl().

View file

@ -193,6 +193,9 @@ struct resource_point uran_conf[] = {
{ 98, 0 },
{ 127, 0 } };
static void qprint(const char * const fmt, ...)
ATTRIBUTE((format (printf, 1, 2)));
/*
* Program arguments and options
*/
@ -302,26 +305,25 @@ static int bfs_queue_head, bfs_queue_tail;
static const char *numletter =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static void print_vars(void);
static void qprint(const char * const fmt, ...)
ATTRIBUTE((format (printf, 1, 2)));
static void help(char *);
static void usage(void);
static void parse_args(int argc, char *argv[]);
static void allocate_memory(void);
static void init(void);
static int drift(void);
static int stable(int);
static void drift_capital(int);
static int grow_continents(void);
static int grow_islands(void);
static void create_elevations(void);
static void elevate_prep(void);
static void elevate_land(void);
static void elevate_sea(void);
static void write_sects(void);
static void output(void);
static int write_newcap_script(void);
static int stable(int);
static void elevate_prep(void);
static void elevate_land(void);
static void elevate_sea(void);
static void print_vars(void);
static void drift_capital(int);
static int grow_islands(void);
/* Debugging aids: */
void print_own_map(void);
@ -1053,8 +1055,7 @@ add_sector(int c, int x, int y)
adj_land_update(x, y);
}
static int
grow_weight(int c, int x, int y, int spike)
static int grow_weight(int c, int x, int y, int spike)
{
int n, b;