Commit graph

957 commits

Author SHA1 Message Date
5f08a3c04a Give deltax(), deltay() internal linkage
External linkage unnecessary since commit 3ca88271.
2010-04-04 09:23:48 +02:00
9061ae7b9d Make CANT_HAPPEN() more obvious for static analysis
Local analysis can now easily find out what's up.  Before,
whole-program analysis was required.  The Clang Static Analyzer
complained about code that is actually fine.
2010-01-19 08:40:18 +01:00
73e25ff21e Update copyright notice 2010-01-19 08:40:17 +01:00
3a5e23a020 Rearrange struct sctstr slightly to expose commonalities with units
Nice bonus: space needed for sectors shrinks some 4%.  Size of game
state could shrink perhaps 1-2%.
2010-01-19 08:37:05 +01:00
aa659c7754 Narrow struct sctstr member sct_mobil to char
To bring it in line with unit mobility.
2010-01-19 08:37:05 +01:00
ca2dba33f0 Make struct sctstr member sct_effic signed
To bring it in line with unit efficiency.
2010-01-19 08:37:05 +01:00
2fa5f65257 Generation numbers to catch write back of stale copies
Oops when a stale copy is written back, i.e. the processor was yielded
since the copy was made.  Such bugs are difficult to spot.  Sequence
numbers catch them when they do actual harm (they also catch different
bugs).  Generation numbers catch them even when they don't.

New ef_generation to count generations.  Call new ef_make_stale() to
increment it whenever the processor may be yielded.

New struct emptypedstr member generation.  To conserve space, make it
a bit-field of twelve bits, i.e. generations are only recorded modulo
2^12.  Make sure all members of unit empobj_storage share it.  It is
only used in copies; its value on disk and in the cache is
meaningless.  Copies with generation other than ef_generation are
stale.  Stale copies that are a multiple of 2^12 generations old can't
be detected, but that is sufficiently improbable.

Set generation to ef_generation by calling new ef_mark_fresh() when
making copies in ef_read() and ef_blank().  nav_ship() and
fltp_to_list() make copies without going through ef_read(), and
therefore need to call ef_mark_fresh() as well.  Also call it in
obj_changed() to make check_sect_ok() & friends freshen their argument
when it is unchanged.

New must_be_fresh() oopses when its argument is stale.  Call it in
ef_write() to catch write back of stale copies.
2010-01-19 08:36:01 +01:00
358aee203e Store sequence numbers more compactly
Store them and ef_type in bit-fields.

Allocate eight bits for ef_type.  Values range from 0 to EF_GAME
(currently 16), so this is plenty.

Allocate twelve bits for sequence numbers.  Sequence number mismatches
are now missed when the numbers are equal modulo 2^12.  Still
sufficiently improbable.

Common machines store the bit-fields in a 32 bit word.  There are
twelve bits left in that word for future use.  Total savings 16 bits,
which is exactly what the previous commit spent on wider uids on
common machines.
2010-01-19 08:31:10 +01:00
ba2044be18 Store uids as int to support more sectors and units
Before, they were stored as short.  Wider uids use more space, but the
next commit will recover it by narrowing other members.

The use of short has always limited the number of ships, planes, land
units and nukes to SHRT_MAX (commonly 32768).  Only the most extreme
games ever came close.

Commit 49780e2c (v4.3.12) added struct sctstr member sct_uid to make
struct empobj member uid work for sectors.  This made the limit apply
to sectors as well.  We've had games with more than 32768 sectors.
2010-01-19 08:26:42 +01:00
0ba61f1714 Record news more compactly
Member nws_uid is unused since the commit before previous.  Remove it.

Member nws_seqno is of marginal value, because we write news only
through ncache[], and thus aren't prone to the errors sequence numbers
can catch.  Remove it.

Make timestamp selector virtual, computing nws_when + nws_duration,
and remove member nws_timestamp.  Impact:

* In ncache(), the removed timestamp equals nws_when + nws_duration,
  both for new news and updated news.  No change.

* delete_old_news() becomes invisible.  Before, its move of unexpired
  news to the beginning of the news file touched all the timestamps.
  That was unwanted, because the move does not change news, only their
  storage.  Improvement.

* empdump no longer flags the imported news changed via the timestamp.
  This is somewhat unfortunate.  Document as bug.

With these members removed, struct nwsstr no longer matches struct
emptypedstr, so clear news table flag EFF_TYPED and remove union
empobj_storage member news.  This loses the automatic maintenance of
member ef_type via struct emptypedstr.  Remove ef_type as well.

This shrinks struct nwsstr from 20 to 12 bytes on common 32 bit
machines, and from 32 to 16 bytes on common 64 bit machines.  Since
the server doesn't map the whole news file (EFF_MAP is off), this
reduces I/O, while the table's memory use remains the same.

Historical note: struct nwsstr is now pretty much what it was back in
BSD Empire 1.1.  Members ef_type and nws_uid go back to Empire 3 (for
C_SYNC?).  v4.3.12 added member nws_timestamp, which doubled the size
on common 64 bit machines.  v4.3.15 added nws_seqno.
2010-01-19 08:21:56 +01:00
b719f39c0f New news selector duration
Backed by new struct nwsstr member nws_duration.  Time between first
and last occurence of the news recorded in this item, in seconds.
2010-01-19 08:21:55 +01:00
4e895465df Remove unused members of struct lndstr, lonstr, nukstr, trtstr
struct lndstr member lnd_flags is a leftover from Empire3's C_SYNC,
which was ripped out in 4.0.0.

struct lonstr member l_sel, struct nuk_str members nuk_ship, nuk_land,
and struct trtstr member trt_bond have been there basically forever
without any use.
2010-01-19 08:21:37 +01:00
d8c940ec2c Consistently use int for sector and unit uid parameters 2009-12-31 09:45:56 +01:00
c0ed527311 Consistently use int for file type parameters and locals 2009-12-29 17:23:22 +01:00
60519b3cd0 Consistently use int for mission type parameters 2009-12-29 13:06:35 +01:00
c528fcbe3e Update known contributors comments 2009-12-13 17:34:28 +01:00
fd894d9864 Fix and enable collateral damage for missing missiles
Collateral damage was disabled, because after msl_hit() reported a
miss, the missile may or may not have reached the target.

Fix by splitting msl_launch() off msl_hit().

Drop the disabled collateral damage code for sector targets, because
sectors can't be missed.  Enable it for ships and land units.

Since msl_launch() returns whether the missile is sub-launched, drop
launch_missile() parameter sublaunch, and simplify its caller.
2009-12-13 08:05:26 +01:00
0060e48ea4 Refactor missile interception code
Keep only the common part in msl_intercept(), and give it internal
linkage.  Wrap new msl_abm_intercept() and msl_asat_intercept() around
it.  They are simpler to use.
2009-12-13 08:04:07 +01:00
eace95fab8 Get rid of msl_launch_mindam()
It's awkward, especially in shp_missile_interdiction().  Inline into
callers and simplify.
2009-12-13 08:04:07 +01:00
f7f3178ce2 Move msl_equip() to callers, internal linkage 2009-12-13 08:03:49 +01:00
a269cdd7e9 Limit nukes to strategic missions
Before Empire 2, nukes could be delivered only with bomb (special
mission 'n', airburst only) and launch (targeting sectors or
satellites only).

Empire 2 made nukes available for any kind of bombing, and for any
missile strike on sectors or ships.  This included interdiction and
support missions.  Nuclear-tipped anti-sats and bomb mission n were
removed.

Unfortunately, this was done in a messy way, which led to
inconsistencies and bugs.  The problem is that ordinary damage affects
just the target, while nuke damage affects an area.  Code dealing with
plane damage was designed for the former.  Instead of rewriting it to
cope with area damage cleanly, nuke damage got shoehorned into
pln_damage(), the function to compute conventional plane damage, as a
side effect: computing damage blasted sectors in the area.

If the plane carried a nuke, pln_damage() returned zero (conventional)
damage.  Without further logic, this simply bypassed the code to apply
damage to the target.  This worked out okay when the target already
got damaged correctly by the side effect.

However, some targets are immune to the side effect: when interdicting
a move or explore command, the commodities being moved are not in any
sector.

For other targets, damage has effects other than damaging the target:
offensive and defensive support don't apply the (conventional) damage
to the target sector.  Instead, they turn it into a combat bonus.
Without further logic, nuclear damage doesn't contribute to that.

To make all that work, pln_damage() returned the nuclear damage for
ground zero as well.  Because a plane does either conventional or
nuclear damage, one of them is always zero.

Most callers simply ignored the nuclear damage, and applied only the
conventional damage.

Bug: land units and ships failed to retreat when pin-bombed or
missiled with a nuke.  That's because they received zero conventional
damage.

The mission code flies planes and missiles and tallies their damage.
This mission damage included nuclear damage at ground zero (except for
missiles sometimes, see below), to make support and commodity
interdiction work.  Unfortunately, this broke other things.

Bug: when bombers interdicted ships or land units, nukes first damaged
the ships or land units by the side effect, then again through mission
damage.  Interdicting missiles had a special case to avoid this.

Bug: when interdicting move, explore or transport, nukes first damaged
the sector by the side effect, then again through mission damage's
collateral damage.

There may well be more bugs hiding in this mess.

The mess is not worth fixing.  While the idea of interdicting and
supporting with nukes sounds kind of cool, I believe it's pretty
irrelevant in actual play.

Instead, go back to a variation of the original rules: nukes can be
delivered only through bomb mission 's' and launch at sectors.

Make arm reject marine missiles in addition to satellites, ABMs and
SAMs, and clear the mission.  Make mission reject planes armed with
nukes.  Oops when they show up in mission_pln_equip() anyway.

Make pln_equip() allow planes with nukes only for missions 's' and
't'.

Clean up pln_damage() to just compute damage, without side effect.
Change strat_bomb() and launch_missile() to detonate nukes.  Simplify
the other callers.  Parameter mission of msl_launch_mindam() is now
unused, remove it.

Missiles exploding on launch no longer set off their nukes.  That was
pretty ridiculous anyway.
2009-12-13 07:46:00 +01:00
528df9acba Improve launch diagnostic messages, switch off supply
msl_equip() used mission_pln_equip(), which is for automatic defenses,
and therefore silent.  Its users launch_as(), launch_missile() and
launch_sat() printed failure diagnostics based on assumptions on what
could go wrong.

Switch to the appropriate function for commands, pln_equip(), and
remove the guesswork.  Implement mission 'i' there.  When launching
from a foreign base, its owner now gets informed.  Unimportant at this
time, as players can't easily deploy missiles in foreign bases.

This change also switches off automatic supply for launch.  Consistent
with bomb.
2009-12-12 16:28:52 +01:00
3a4b50b815 Comment fix 2009-12-12 16:28:52 +01:00
61233e47e8 Drop capabilities stealth and half-stealth
These were leftovers from Chainsaw, and their only remaining effect
was a flak bonus.

The got replaced except for flak by plane selector stealth under
Chainsaw option STEALTHV, which became mandatory in Empire 2.  It is
unclear why STEALTHV didn't cover flak.  No planes with these
capabilities have existed in the stock game since Empire 2.
2009-12-12 16:28:52 +01:00
54b1c04686 Simplify how plane cargo is tracked
Fold struct plist members bombs (used for bombing runs) and misc (used
for everything else) into a single member load.
2009-12-12 16:28:52 +01:00
0fe43096bc Simplify calling of pln_arm() & friends
pln_arm(), pln_equip(), mission_pln_arm() mission_pln_equip() took a
mission parameter encoding the kind of sortie (strategic bomb,
pinpoint bomb, transport, ...), a flag parameter to further specify
the plane's role, and a parameter ip to specify the load.

The flags argument was always either P_F (intercept), P_F | P_ESC
(escort), or zero (any other role).

With non-zero flags, mission and ip argument were not used in any way.

Use mission 'e' and null load for escorts, and remove flags.
Intercept can still be identified by mission zero.

Also change pln_mobcost() to take a mission parameter instead of
flags, so that pln_arm() and mission_pln_arm() can simply pass on
their mission.
2009-12-08 08:15:51 +01:00
2b31f644db Enable marine msl. unconditionally, remove option PINPOINTMISSILE
Deities can still control them by customizing table plane-chr.
2009-12-08 08:15:50 +01:00
ad296698f9 Factor new lnd_sabo() out of sabo()
This permits giving seagun(), fortgun() and landunitgun() internal
linkage.
2009-12-05 15:19:37 +01:00
58e34ebe3d Include <windows.h> from service.h to make it self-contained
Remove now superfluous includes elsewhere.
2009-11-30 19:45:27 +01:00
c665c83ba4 Remove macro S_IRWUG
Use its expansion instead.
2009-11-30 19:45:27 +01:00
ee01ac1912 Fix accepting connections from hosts with "long" IPv6 address
This could fail because struct player member hostaddr had insufficient
space.  Should have been enlarged in commit 19d88af3.
2009-11-30 19:43:47 +01:00
0a4d77e919 Simplify checks whether player thread may sleep
A player thread may sleep on input or output, except:

(1) While it is executing a C_MOD command, it may only sleep on input.

(2) While it is being aborted by the update or shutdown, it may not
    sleep at all.

To find out whether a player thread may sleep on input, code has to
check condition (2).  It needs do to that in recvclient().

To find out whether it may sleep on output, it has to check both
conditions.  It needs to do that in pr_player() and upr_player().

The code tracked condition (1) in global variable play_lock_wanted.
It checked condition (2) by examining struct player member command.

Replace all that by new struct player member may_sleep.  Initialize it
in player_new(), update it in dispatch(), shutdwn() and update_run().
This makes the tests in recvclient(), pr_player() and upr_player()
obvious.  play_wrlock_wanted() is now unused, remove it.
2009-11-30 19:43:18 +01:00
1b4496253d Move queue flush out of io.c
Player threads may only sleep under certain conditions.  In
particular, they must not sleep while a command is being aborted by
the update or shutdown.

io.c should not know about that.  Yet io_output_all() does, because it
needs to give up when update or shutdown interrupt it.  The function
was introduced in Empire 2, but it didn't give up then.  Fixed in
commit a7fa7dee, v4.2.22.  The fix dragged unwanted knowledge of
command abortion into io.c.

To clean up this mess, io_output_all() has to go.

First user is io_write().  io_write() automatically flushes the queue.
In wait-mode, it calls io_output_all() when the queue is longer than
the bufsize, to attempt flushing the queue completely.  In
no-wait-mode, it calls io_output() every bufsize bytes.  Except the
test for that is screwy, so it actually misses some of the flush
conditions.

The automatic flush makes io_write() differ from io_gets(), which is
ugly.  It wasn't present in BSD Empire 1.1.  Remove it again, dropping
io_write()'s last argument.

Flush the queue in its callers pr_player() and upr_player() instead.
Provide new io_output_if_queue_long() for them.  Requires new struct
iop member last_out to keep track of queue growth.  pr_player() and
upr_player() call repeatedly until it makes no more progress.  This
flushes a bit less eagerly in wait-mode, and a bit more eagerly in
non-wait mode.

Second user is recvclient().  It needs to flush the queue before
potentially sleeping in io_input().  Do that with a simple loop around
io_output().  No functional change there.
2009-07-19 14:11:53 -04:00
d052239a7a Make empth_rwlock_t prefer writers
LWP and Windows implementations already did that.  Rewrite the
pthreads implementation.

The write-bias makes the stupid play_wrlock_wanted busy wait in
dispatch() unnecessary.  Remove it.
2009-07-19 14:11:52 -04:00
2e4f63c270 Remove IO_NOWAIT, IO_WAIT
They make the code slightly clearer in some places, and more
complicated in others.  Not worth it.
2009-07-19 14:11:52 -04:00
55c53b9add Hide struct io and implementation of struct ioqueue
Move struct io and struct ioqueue from ioqueue.h to ioqueue.c.
Declare incomplete struct ioqueue in ioqueue.h.
2009-07-19 14:11:52 -04:00
3805548b3e Remove blocking struct iop operation
The blocking I/O option makes no sense in the server, because it
blocks the server process instead of the thread.  In fact, it's been
unused since Empire 2, except for one place, where it was used
incorrectly, and got removed in the previous commit.

Make I/O non-blocking in io_open() unconditionally.  Remove IO_NBLOCK
and io_noblocking().
2009-07-19 14:11:52 -04:00
0025f24f1e Remove long defunct IO_NEWSOCK
Chainsaw used this together with the notify callback to make the iop
data type usable for sockets it listened on, so that io_select() could
multiplex them along with the sockets used for actual I/O.
io_select() became unused in Empire 2, and finally got removed in
commit 875d72a0, v4.2.13.  That made the IO_NEWSOCK and the notify
callback defunct.  The latter got removed in commit 7d5a6b81, v4.3.1.
2009-07-19 14:11:52 -04:00
44c36fa7d5 Make sector maintenance cost configurable
Replace the fixed $1 per ETU maintenance for capital/city sectors that
are at least 60% efficient by a configurable maintenance cost, payable
regardless of efficiency.  The only change in the default
configuration is that inefficient capitals now pay maintenance.
Charging sector maintenance regardless of efficiency is consistent
with unit maintenance.

New struct dchrstr member d_maint and sector-chr selector maint.  Make
show_sect_build() show it.  Change produce_sect() to record
maintenance in new slot p_sect[SCT_MAINT] instead of abusing
p_sect[SCT_CAPIT].  Replace the "Capital maintenance" line in budget
by "Sector maintenance".
2009-07-19 13:58:47 -04:00
1f60baf818 New SCT_BUDG_MAX 2009-07-19 13:58:47 -04:00
3722bafaf7 Fix confusion of landmines with seamines
Seamines and landmines share storage.  Sea and bridge span sectors can
hold only sea mines, other sector types only landmines.  Sector type
checks were missing or incorrect in several places:

* Seamines under bridge spans were mistaken for landmines in several
  places:

  - ground combat mine defense bonus, in get_mine_dsupport() and
    stre(),

  - land units retreating from bombs, in retreat_land1(),

  - non-land unit ground movement (commands explore, move, transport,
    and INTERDICT_ATT of military), in check_lmines(),

  Fix them to check the sector type with new SCT_MINES_ARE_SEAMINES(),
  SCT_LANDMINES().

* plane_sweep() mistook landmines for seamines in harbors.  Bug could
  not bite, because it's only called for sea sectors.  Drop the bogus
  check for harbor.

* Collapsing a bridge tower magically converted landmines into
  seamines.  Make knockdown() clear landmines.

Also use SCT_MINES_ARE_SEAMINES() and SCT_LANDMINES() in mine(),
landmine(), lnd_sweep() and lnd_check_mines().  No functional change
there.

Keep checking only for sea in pln_mine(), plane_sweep(),
retreat_ship1(), shp_sweep() and shp_check_one_mines().  This means
seamines continue not to work under bridges.  Making them work there
is tempting, but as long as finding seamines clobbers the sector
designation in the bmap, it's better to have them in sea sectors only.

Historical notes:

Mines started out simple enough: you could mine sea and bridge spans,
and ships hit and swept mines in foreign sectors.

Chainsaw 2 introduced aerial mining and sweeping.  Unlike ships,
planes could not mine bridge spans.  plane_sweep() could sweep
harbors, which was wrong, but it was never called there, so the bug
could not bite.

Chainsaw 3 introduced landmines.  The idea was to permit only seamines
in some sector types, and only landmines in the others, so they can
share storage.  To figure out whether a sector has a particular kind
of mines, you need to check the sector type.  Such checks already
existed in mine, drop and sweep, and they were kept unchanged.  The
new lmine command also got the check.  Everything else did not.
Ground movement and combat could hit and sweep seamines in bridge
spans.  Ships could hit and sweep landmines in harbors.

Empire 2 fixed land unit movement (march, INTERDICT_ATT) not to
mistake seamines for landmines on bridge spans.  It fixed ships not to
mistake landmines for seamines.  The fix also neutered seamines under
bridge spans: ships could neither hit nor sweep them anymore.  Both
fixes missed retreat.

Commit 5663713b (v4.3.1) made ship retreat consistent with other ship
movement.
2009-03-31 22:52:03 +02:00
8cbcfefda1 Clean up useless declarations
Commit fbf9f15b removed SO, SE, but left their declarations behind.
Ditto commit 3aea20e1 for bigcity_dchr, and commit 08b94556 for
player_kill_idle.

Commit afa65c8f accidentally added a declaration for xedit().
2009-03-28 13:04:48 +01:00
f760150d8f Rename plane_caps() to pln_caps() and give it external linkage 2009-03-08 17:14:59 +01:00
eea9e76bf8 Don't log out player when update aborts a command with pthreads
pthread.c's empth_select() returned -1 when empth_wakeup() interrupted
select().  The failure then got propagated all the way up, and the
player got logged out.  Fix by returning 0 in that case.  While there,
retry on EINTR, to match LWP.  Also clarify comments.
2009-03-01 13:04:48 +01:00
5073b022fd Remove unused empth_terminate()
Unused since 4.3.10.  Can be used safely only in very special
circumstances.

Removal allows simplifying pthread.c and ntthread.c some.  liblwp left
alone.
2009-03-01 10:49:48 +01:00
ee20a9cd34 Update known contributors comments 2009-02-18 21:11:33 +01:00
322f96ecb7 Redesign automatic supply interface
The automatic supply interface has design flaws that make it hard to
use correctly.  Its current uses are in fact all wrong (until commit
0179fd86, the update had a few uses that might have been correct).
Some of the bugs can only bite with land unit capability combinations
that don't exist in the stock game, though.

Automatic supply draws supplies from supply sources in range.  Since
that can update any supply source in range, all copies of potential
supply sources a caller may keep can get invalidated.  Writing back
such an invalid copy wipes out the deduction of supplies and mobility
from a source, triggering a seqno mismatch oops.

This commit redesigns the interface so that callers can safely keep a
copy of the object drawing the supplies (the "supply sink").  The idea
is to pass the sink to the supply code, so it can avoid using it as
source.  The actual avoiding will be implemented in a later commit.

Copies other than the supply sink still need to be eliminated.  See
commit 65410d16 for an example.

Other improvements to help avoid common errors:

* Supply functions are commonly used to ensure the sink has a certain
  amount of supplies.  A common error is to fetch that amount
  regardless of how many the sink already has.  It's more convenient
  for such users to pass how many they need to have instead of how
  many to get.

* A common use of supply functions is to get supplies for immediate
  use.  If that use turns out not to be possible after all, the
  supplies need to be added somewhere, which is all too easy to
  forget.  Many bugs of this kind have been fixed over time, and there
  are still some left.  This class of bugs can be avoided by adding
  the supplies to the sink automatically.

In fact, this commit fixes precisely such bugs in mission_pln_equip()
and shp_missile_defense(): plane interception and support missions,
missile interception (abms), launch of ballistic missiles and
anti-sats could all lose shells, or supply more than needed.

Replace supply_commod() by new sct_supply(), shp_supply(),
lnd_supply(), and resupply_all() by new lnd_supply_all().  Simplify
users accordingly.

There's just one use of resupply_commod() left, in landmine().  Use
lnd_supply_all() there, and remove resupply_commod().
2009-02-17 19:31:37 +01:00
5ea0d19c20 Fix automatic supply of defending and reacting units
Being in supply is relevant for defending and reacting units.  The
code used has_supply() to check that.

Contrary to its name, has_supply() does not check whether the land
unit has enough supplies to be in supply, but whether it has or could
draw enough.  So, defending and reacting units did not actually draw
any missing supplies.

Fix that in get_dlist() and att_reacting_units() by calling
resupply_all(), then checking with new lnd_in_supply() instead of
has_supply().  The fix of att_reacting_units() is complicated by the
fact that it is also used in the strength command, and should keep not
drawing supplies there.

Rename has_supply() to lnd_could_be_supplied().  Replace its uses
immediately after resupply_all() by lnd_in_supply().
2009-02-17 19:30:35 +01:00
9ff2c62309 Avoid repeated hours and game down status notifications
may_play_now() tells deities about hours restriction and game down
status.  It runs at login and before and after each command.  Getting
notified that often is annoying.

Avoid repetition by remembering notification in new player flags
PF_HOURS and PF_DOWN.  Add a notification when hours restriction has
been lifted.  Ensure the notification is printed before the prompt,
not before the command, by calling may_play_now() from command() only
for mortals.  Safe, because may_play_now() always returns true for
deities anyway.
2009-02-08 14:59:26 +01:00
e8926559d1 Move show_first_tel() from player.c to rea.c 2009-02-08 14:21:15 +01:00