Compare commits

..

113 commits

Author SHA1 Message Date
b44abaf9d4 client: Unbreak standalone build
Broken in commit 8447fc1cd "w32: Provide getopt() for Visual Studio".

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-21 15:46:28 +01:00
89dc5f6d0a info/Empire4.4: Improve a few change log entries
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-21 15:10:53 +01:00
774ae95997 info/Empire4.4: Update change log again for 4.4.1
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:26:01 +01:00
Ron Koenderink
3abb8bff60 w32: Drop snprintf(), vsnprintf() macros for Visual Studio
The Visual Studio ANSI C compatibility flag now covers these functions
so now the defines create a conflict.

Signed-off-by: Ron Koenderink <rkoenderink@gmail.com>
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
3aa4f7404c w32: Drop a warning suppression pragma we no longer need
Signed-off-by: Ron Koenderink <rkoenderink@gmail.com>
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
Ron Koenderink
ca801dec14 w32: Work around a Visual Studio deprecation warning
Visual Studio warns on use of certain POSIX functions.  Compiler
option /D_CRT_NONSTDC_NO_WARNINGS suppresses this, except for variable
tzname.  Work around with a macro.

Signed-off-by: Ron Koenderink <rkoenderink@gmail.com>
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
Ron Koenderink
3af4a32def .gitignore: Add Visual Studio directories for building
Signed-off-by: Ron Koenderink <rkoenderink@gmail.com>
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
Ron Koenderink
8447fc1cd2 w32: Provide getopt() for Visual Studio
getopt() does not exist in the Visual Studio 2019 CRT.  Provide one.

Signed-off-by: Ron Koenderink <rkoenderink@gmail.com
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
a164390d1f w32: Modernize for MinGW 6.0.0, and clean up
We provide gettimeofday() only #ifdef _MSC_VER, but declare it
unconditionally in our own sys/time.h.  This is asking for trouble.
Declare it only #ifdef _MSC_VER, else pull in MinGW's sys/time.h with
#include_next.

Likewise, define macros ftruncate(), S_IRUSR & friends in our own
unistd.h only #ifdef _MSC_VER, else pull in MinGW's unistd.h with
#include_next.  The #include <getopt.h> is now useless, drop.

src/lib/commands/info.c relies on sys/time.h including windows.h.
Unclean, and no longer the case with MinGW.  Include it directly.

MinGW provides EWOULDBLOCK.  Drop our replacement.

MinGW provides inet_ntop() in ws2tcpip.h, but only if feature test
macro _WIN32_WINNT >= 0x600, i.e. Windows Vista or later.  It defaults
to 0x0502 (Windows Server 2003).  Make configure #define _WIN32_WINNT
0x0601 in config.h.  This requests Windows 7.  Trying to support Vista
feels unwise.  Include ws2tcpip.h, and drop our replacement.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
598669673e show: Drop Windows-specific fmttime2822() code
fmttime2822() works around Windows strftime() lacking %z and %T.  This
is no longer the case, although MinGW still warns about %T.  Replace
%T by the %H:%M:%S, and drop the work-around.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
b19aa1c13f chance: Avoid abuse of O_NONBLOCK for Windows
O_NONBLOCK from src/lib/w32/w32misc.h is stricly for use with our
fcntl().  pick_seed() passes it to open(), which is wrong.  With any
luck, open() fails as it should anyway (the files being opened are not
expected to exist under Windows).  Messed up in commit 9102ecce5 "Fix
PRNG seeding to resist guessing", v4.3.31.

Clean up: guard with #ifndef _WIN32.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-13 19:25:18 +01:00
f69db5e413 ship: Unbreak MOB_ACCESS real-time mobility update for ships
Ships owned by countries with even country number don't gain mobility
in real-time.  This is due to a classic brown-paperbag typo in the
condition guarding mob_inc_ship() in shp_postread(): & instead of &&.
Fix it.

Fixes: dd9e393b3 "subs: Simplify MOB_ACCESS mobility update", v4.4.0
Reported-by: Phil Miron <Philthy74@hotmail.com>
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
e23882161e subs/wu: Avoid "may be used uninitialized" warnings
typed_wu() either sends a telegram to a single recipient @to, or an
announcement.  It initializes @np to getnatp(to) only when sending a
telegram.  It also uses it only then.  Clang is cool with this, but
GCC gets confused and warns "‘np’ may be used uninitialized".  Ron
Koenderink reports Visual Studio 2019 even flags it as an error.

Time to clean this up.  Initialize @np to NULL when sending an
announcement.  Fuse conditionals while there.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
4914daa587 fire launch: Avoid "may be used uninitialized" warnings
launch_missile() initializes @n to the target ship number only when
the target is a ship.  It also uses it only then, to re-get the ship.
Clang is cool with this, but GCC gets confused and warns "‘n’ may be
used uninitialized".

Use target_ship.shp_uid instead of @n to avoid the warning.

Similar issue in c_fire(): use vship.shp_uid instead of for @vhsipno.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
1f6b79dd10 load tend: Avoid "may be used uninitialized" warnings
c_load() initializes @ich only when @type is EF_SECTOR.  It also uses
it only then.  Clang is cool with this, but GCC gets confused and
warns "‘ich’ may be used uninitialized".  Ron Koenderink reports
Visual Studio 2019 even flags it as an error.  Same for c_lload() and
c_tend().

Time to clean this up.  Rearrange the code to avoid the warning and
also improve readability a bit.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
b770ac4ba8 pathfind: Delete write-only variable in path_find_visualize()
A useless variable crept into commit 2fc9dfc52 "New
path_find_visualize(), to aid debugging" (v4.3.27).  Delete it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
dc793ea0a1 journal: Don't immediately flush output events to disk
Commit 478566258 'New journal event "output"' (v4.3.27) claims "Output
events are *not* flushed to disk immediately."  They are.  Accident.
Implement the missing bit.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
bfac52eb6d move_ground: Fix getsect() error checking
move_ground() has code to handle getsect() failure.  It's dead,
because it assumes getsect() returns a negative value on failure.  It
actually returns zero then.  The mistake can be traced back all the
way back to BSD Empire 1.1.  Fix it.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
539c44a13a takeover: Don't stop nukes on takeover
Nukes can't be repaired, started or stopped.  Except takeover_unit()
stops them.  Don't.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-02-06 16:55:37 +01:00
c6ec6a41c2 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-23 08:39:14 +01:00
a6c46316e9 info/Empire4.4: Update change log for 4.4.1
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:14 +01:00
a021a20e55 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-23 08:39:14 +01:00
1b677a4578 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-23 08:39:14 +01:00
e23e4cd738 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-23 08:39:14 +01:00
5f3c64c062 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-23 08:39:14 +01:00
223add6a92 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-23 08:39:14 +01:00
1d8451e87b 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-23 08:39:14 +01:00
8c9a383fa1 tests/version: Cover show product and show news
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:14 +01:00
992ab36b59 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-23 08:39:14 +01:00
9e9355da41 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-23 08:39:14 +01:00
5d23a13fef info/Products: Don't call sector p.e. "level p.e."
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:14 +01:00
c347db0551 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-23 08:39:14 +01:00
0b46e31d60 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-23 08:39:14 +01:00
61f0762eaa 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-23 08:39:14 +01:00
f8ccf1d918 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-23 08:39:13 +01:00
bdd2a7a764 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-23 08:39:13 +01:00
7b24e312e3 mission: Fix an error message pasto going back to Chainsaw 3
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:13 +01:00
da9d5c6404 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-23 08:39:13 +01:00
628e2e8e82 info/Plane-types: Document SAM, ABM and a-sat missile abilities
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:13 +01:00
df7e8b3d21 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-23 08:39:13 +01:00
125b5df9af 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-23 08:39:13 +01:00
52e540d62a lwp: Include signal.h instead of ucontext.h where possible
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:13 +01:00
cadb6e7f29 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-23 08:39:13 +01:00
e14c5326e3 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-23 08:39:13 +01:00
06487a46a3 Update copyright notice
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:13 +01:00
87952c7f7c 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-23 08:39:13 +01:00
7714a8cb82 doc/coding: Improve section "Portability" a bit
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 08:39:13 +01:00
c48abacad2 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-23 08:39:13 +01:00
a0d1f63729 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-23 08:39:13 +01:00
ae421dafc2 configure: Move terminfo check next to readline check
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:21 +01:00
55ff9cce09 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-23 07:08:21 +01:00
55c1d29efe 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-23 07:08:21 +01:00
9556c6bd65 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-23 07:08:21 +01:00
18e392c470 Make: Slighly less verbose "make check" output
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:21 +01:00
fef643031c 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-23 07:08:21 +01:00
ec4004b4d4 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-23 07:08:21 +01:00
a830df0553 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-23 07:08:21 +01:00
9d87eb9e22 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-23 07:08:21 +01:00
37c69a3a7a 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-23 07:08:21 +01:00
d6c5c263b9 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-23 07:08:03 +01:00
8e00a61812 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-23 07:08:03 +01:00
54b1e7e167 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-23 07:08:03 +01:00
691d0a27c1 client: Factor set_echo_if_tty() out of get_password()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
c1f1344afe client: Move get_password() from login.c to getpass.c
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
f7ae50261f 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-23 07:08:03 +01:00
2ae769bec4 client: Reorder misc.h, and point to the .c
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
37f2076a7d 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-23 07:08:03 +01:00
40cee426b7 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-23 07:08:03 +01:00
2e4793408c 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-23 07:08:03 +01:00
460cc9e2ee 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-23 07:08:03 +01:00
aae823507c 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-23 07:08:03 +01:00
f15bb68b63 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-23 07:08:03 +01:00
2c12238ecb 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-23 07:08:03 +01:00
7b9e579408 info: Use S_ISREG() instead of S_IFREG for readability
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
566b9fdbbe 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-23 07:08:03 +01:00
168db3b248 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-23 07:08:03 +01:00
10356f9ecf build-aux/git-version-gen: Refresh from Gnulib commit 4f78c231f4
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
53591e85d5 build-aux INSTALL: Refresh from automake 1.16.3
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
015b93b71c m4: Refresh macros from autoconf-archive commit fd1d25c148
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:08:03 +01:00
f57c71da92 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-23 07:08:03 +01:00
e7583a519e config: Slightly neater configuration table size macros
Macro SHP_TYPE_MAX is the largest possible ship type number.  It is
only used to size mchr[], and we need + 2 there.  Replace by MCHR_SZ
for simplicity.

Same for LND_TYPE_MAX, PLN_TYPE_MAX, P_MAX, and SCT_TYPE_MAX: replace
by LCHR_SZ, PLCHR_SZ, PCHR_SZ, and DCHR_SZ.

Same for N_MAXNUKE, except that one is more than the largest type
number.  Replace by NCHR_SZ.

For consistency, define ICHR_SZ and INTRCHR_SZ for sizing ichr[] and
intrchr_sz[].

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-23 07:07:58 +01:00
6bad464348 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-19 08:56:38 +01:00
d1b844c6eb New macro ARRAY_SIZE()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:56:38 +01:00
c506cd7ed2 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-19 08:56:38 +01:00
2e95ea6d80 info/Empire4.4: Fix more 4.4.0 change log entry typos
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:56:38 +01:00
90bb0f7fa3 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-19 08:56:38 +01:00
6babfefdb0 fairland: Rename fl_move() to drift_capital()
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:56:35 +01:00
82ed4c9d25 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.

The order of forward declarations of static functions looks random.
Reorder them to match the order of definitions.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:55:21 +01:00
8dab67c116 fairland: Fuse capx[], capy[] into cap[]
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:27:35 +01:00
ec9633b901 fairland: Fuse sectx[], secty[] into sect[]
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:27:35 +01:00
524c70659c 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-19 08:27:35 +01:00
e59451f0d9 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-19 08:27:34 +01:00
6642878d5f 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-19 08:27:34 +01:00
8c15a3fe32 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-19 08:27:34 +01:00
b6b32f02be 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-19 08:27:34 +01:00
6880908937 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-19 08:27:34 +01:00
dd9bda62eb 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-19 08:27:34 +01:00
7ce7440a34 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-19 08:27:34 +01:00
aed94594f1 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-19 08:27:34 +01:00
b3d564c8ae fairland: Use zero elevation for "not yet elevated"
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:27:34 +01:00
72f88eefd8 fairland: Eliminate sectc[][], use adj_land[] instead
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:27:34 +01:00
fb2bd2408e 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-19 08:27:34 +01:00
7f1bbcad94 fairland: Eliminate macro ELEV, it's an abomination
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2021-01-19 08:27:34 +01:00
fd164c5860 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-19 08:27:34 +01:00
56c014806e 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-19 08:27:34 +01:00
696d31460c 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-19 08:27:34 +01:00
8d0c196c8b 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-19 08:27:34 +01:00
ae988c00ba 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-19 08:27:34 +01:00
00bfeb833e 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-19 08:27:34 +01:00
d434e0cc87 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-19 08:27:34 +01:00
d9425bb5da 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-19 08:27:34 +01:00
96c57d5ad7 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-19 08:27:34 +01:00
494ab8dc07 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-19 08:21:02 +01:00
45 changed files with 282 additions and 164 deletions

4
.gitignore vendored
View file

@ -60,3 +60,7 @@
*.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 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 getopt.c 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-2016
* Markus Armbruster, 2004-2020
*/
#ifndef ITEM_H
@ -80,7 +80,8 @@ struct ichrstr {
/* variables using this structure */
extern struct ichrstr ichr[I_MAX + 2];
#define ICHR_SZ (I_MAX + 2)
extern struct ichrstr ichr[ICHR_SZ];
/* procedures using/returning this struct */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -126,7 +126,8 @@ struct mchrstr {
#define putship(n, p) ef_write(EF_SHIP, (n), (p))
#define getshipp(n) ((struct shpstr *)ef_ptr(EF_SHIP, (n)))
extern struct mchrstr mchr[128];
#define MCHR_SZ 128
extern struct mchrstr mchr[MCHR_SZ];
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 - Sun Jan 17 2021
Changes to Empire 4.4.1 - Sat Feb 21 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 - Sun Jan 17 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 place mountains. Fairness issue.
- Fix silent failure to 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 - Sun Jan 17 2021
- Manual page improvements.
- Code refactoring and cleanup.
* Test suite improvements:
- Fix empdump-test for "make check-accept". Has been broken its
addition in 4.3.33.
- Fix empdump-test for "make check-accept". Has been broken since
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 - Sun Jan 17 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 systems when bomb, launch and interdiction
miss the target. Fix that.
* The server crashed on some systems when bomb, launch and
interdiction missed 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,9 +118,14 @@ Changes to Empire 4.4.1 - Sun Jan 17 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 command was
added in Empire 2.
* Fix buy error messages on concurrent lot change.
* 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.
* Code refactoring and cleanup.
* Info page, manual page and documentation fixes and clarifications.

View file

@ -12,6 +12,8 @@ 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,5 +101,6 @@ 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-2021
* Markus Armbruster, 2006-2018
*/
#include <config.h>

View file

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

View file

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

View file

@ -263,7 +263,8 @@ launch_missile(struct plnstr *pp)
target_ship.shp_x, target_ship.shp_y,
target_ship.shp_own, &sublaunch) < 0)
return RET_OK;
getship(n, &target_ship);
/* @target_ship may have expended shells defending */
getship(target_ship.shp_uid, &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-2018
* Markus Armbruster, 2004-2021
*/
#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 (NULL != (ich = item_by_name(p)))
else if (ich)
type = EF_SECTOR;
else {
pr("Can't %sload '%s'\n", loading ? "" : "un", p);
@ -208,11 +208,12 @@ 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 (NULL != (ich = item_by_name(p)))
else if (ich)
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(vshipno, &vship);
getship(vship.shp_uid, &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-2017
* Markus Armbruster, 2004-2021
*/
#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 (NULL != (ip = item_by_name(p)))
else if (ip)
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-2016
* Markus Armbruster, 2009-2021
*/
#include <config.h>

View file

@ -42,7 +42,7 @@
#include "sect.h"
#ifdef PATH_FIND_DEBUG
#define DPRINTF(...) ((void)printf(## __VA_ARGS__))
#define DPRINTF(...) ((void)fprintf(stdout, ## __VA_ARGS__))
#else
#define DPRINTF(...) ((void)0)
#endif
@ -490,12 +490,11 @@ path_find_visualize(coord sx, coord sy, coord dx, coord dy)
{
int uid;
int xmin, xmax, ymin, ymax, x, y, odd, ch;
double c, u, cost;
double c, 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-2012
* Markus Armbruster, 2006-2021
*/
#include <config.h>
@ -140,11 +140,12 @@ 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
@ -164,6 +165,7 @@ 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[I_MAX + 2];
struct ichrstr ichr[ICHR_SZ];

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[];
struct lchrstr lchr[LCHR_SZ];
#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[];
struct nchrstr nchr[NCHR_SZ];

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[];
struct plchrstr plchr[PLCHR_SZ];
#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[];
struct pchrstr pchr[PCHR_SZ];

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[];
struct dchrstr dchr[DCHR_SZ];
/*
* Table of infrastructure types
* Initialized on startup from infra.config and deity custom config (if any).
*/
struct sctintrins intrchr[INT_DEF + 2];
struct sctintrins intrchr[INTRCHR_SZ];

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[];
struct mchrstr mchr[MCHR_SZ];
#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,6 +128,7 @@ journal_entry_end(int newline, int flush)
if (!newline)
fputc('\\', journal);
fputc('\n', journal);
if (flush)
fflush(journal);
if (ferror(journal)) {
logerror("Error writing journal (%s)", strerror(errno));

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) < 0) {
if (!getsect(curx, cury, &sect)) {
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) < 0) {
if (!getsect(tmpx, tmpy, &next)) {
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-2020
* Markus Armbruster, 2006-2021
*/
#include <config.h>
@ -615,34 +615,10 @@ static char *
fmttime2822(time_t t)
{
static char buf[32];
#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",
size_t n = strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z",
localtime(&t));
if (CANT_HAPPEN(n == 0))
buf[0] = 0;
#endif
return buf;
}

View file

@ -233,7 +233,6 @@ 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;
@ -262,8 +261,6 @@ 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-2016
* Markus Armbruster, 2005-2021
*/
#include <config.h>
@ -110,14 +110,16 @@ 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);
else
np = NULL;
} else {
mailbox(box, to);
if (type != TEL_ANNOUNCE)
if (!(np = getnatp(to)) || np->nat_stat < STAT_SANCT)
np = getnatp(to);
if (!np || 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-2016
* Markus Armbruster, 2004-2021
*/
#include <config.h>

View file

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

150
src/lib/w32/getopt.c Normal file
View file

@ -0,0 +1,150 @@
#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 <errno.h>
#include <windows.h>
#include "sys/resource.h"
int

View file

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

View file

@ -33,9 +33,15 @@
#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
* Ron Koenderink, 2007-2021
* Markus Armbruster, 2007-2013
*/
@ -46,7 +46,6 @@
* 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>
@ -60,6 +59,7 @@
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,22 +78,34 @@ 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-2013
* Markus Armbruster, 2007-2021
*/
/*
@ -41,30 +41,16 @@
#include <stddef.h>
#ifdef _MSC_VER
/* integral mismatch, due to misuse of sector short */
#pragma warning (disable : 4761 )
/* strings.h */
#ifdef _MSC_VER
#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,43 +232,6 @@ 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,9 +193,6 @@ 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
*/
@ -305,25 +302,26 @@ 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 grow_continents(void);
static void create_elevations(void);
static void write_sects(void);
static void output(void);
static int write_newcap_script(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 print_vars(void);
static void drift_capital(int);
static int grow_islands(void);
static void write_sects(void);
static void output(void);
static int write_newcap_script(void);
/* Debugging aids: */
void print_own_map(void);
@ -1055,7 +1053,8 @@ 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;