Commit graph

1017 commits

Author SHA1 Message Date
81163f9f20 Fix missiles interdicting ships outside range or op area
Ship interdiction works sector by sector.  Interdicting missiles
targeted all ships not yet interdicted, not just the ones in the
current sector.  This could lead to interdiction outside missile range
or op area.
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
e043ea4531 Simplify control logic in msl_intercept() 2009-12-13 08:04:07 +01:00
0f0d785601 Don't attempt to hide owner of sub-launched satellite
The attempt was pointless, because the recipient of the message could
see the owner on skywatch, and the news reported it as well.
2009-12-13 08:03:51 +01:00
f7f3178ce2 Move msl_equip() to callers, internal linkage 2009-12-13 08:03:49 +01:00
42cc4f14e0 Move "Releasing RV's" message into detonate() 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
b0ba9022dc Remove unused missions from mission_pln_equip() 2009-12-12 16:30:32 +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
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
d3f5fee64b Penalize fighter combat value for any load, not just bombs
This can affect only planes with capabilities intercept and either
cargo or mine.  No such planes exist in the stock game.
2009-12-12 16:28:52 +01:00
7b7fe69c46 Revise rules for cargo plane loads
There are three ways to fly cargo: transport (fly command with a
commodity argument), cargo drops (drop command that isn't a sea mine
drop), and paradrops.

A cargo flight can be either an airlift or an airdrop.  Airlifts carry
more cargo than airdrops.  A cargo drop or paradrop with a non-VTOL
plane is an airdrop.  Anything else is an airlift.

Before, paradrop always behaved like an airdrop, regardless of VTOL,
and drop always like an airlift.  This made little sense.

Effect of the change on the stock game: paradrop with tc carries twice
the punch, and np/tr/jt can drop less than they can fly.  In
particular, tr can't drop guns anymore, and jt can drop only one
instead of three.
2009-12-08 08:15:51 +01:00
b2107e5301 Simplify load computation in pln_equip(), mission_pln_equip() 2009-12-08 08:15:51 +01:00
fd4da5aab3 Make bomb require capability bomber or tactical
Before, bomb selected any plane, but planes with zero load could not
be equipped.  Cargo planes could be equipped fine, and they flew bombs
to the target, where they silently vanished.

Closes#1388263.
2009-12-08 08:15:51 +01:00
df1ca95a2a Clean up outmoded tests for paradrop capability
Initially, paradrop capability was implied both by capability cargo
and by capability VTOL.  Chainsaw changed para() to require cargo, and
added compile-time option PARAFLAG to additionally require new
capability para.  The optional PARAFLAG rule became mandatory in
Empire 2.

Chainsaw left the old tests for "cargo or VTOL" in place.  Because
para() checked "cargo and para" first, the old tests for "cargo or
VTOL" always passed, so they had no effect.

Clean them up anyway.
2009-12-08 08:15:51 +01:00
062a42fb7b Make passing paradrop & mine cargo to pln_arm() & friends optional
These missions imply the cargo type, just like bombing missions.  Use
the implied type instead of cargo type parameter ip there.  Parameter
ip is now optional except for missions 't' (transport) and 'd' (drop).

Simplify para() not to pass the optional cargo type.  Leave drop()
alone, because always passing the type is simpler there.
2009-12-08 08:15:51 +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
b1dd82fa61 Fix pln_equip()'s check for foreign civilians
Check the true load instead of the ip parameter.  Makes a difference
only when callers pass a bogus ip that isn't actually used.  Happens
for escorts, but then the call can only be reached for deities,
because for mortals the transports fail before the escorts.
2009-12-08 08:15:50 +01:00
e2580b4005 Streamline missile hit chance messages
Don't print hit chance for nuclear warheads, it's always 100%.
Instead, print "Arming nuclear warheads" there.  That message is now
printed after interception instead of before.
2009-12-08 08:15:50 +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
927abead50 Simplify satmap() to avoid compiler warning 2009-12-08 08:15:50 +01:00
e5a43ebe26 Simplify detonate() to avoid compiler warning 2009-12-08 08:15:50 +01:00
e0cb1b66b3 Fix value of detonate() when target sector takes no damage
This can happen when hitting a sanctuary, or for ridiculously impotent
nukes: groundburst for dam < 5, airburst for dam < 7.  detonate()
returned unpredictable value then.

This screwed up interdiction damage, except for missiles interdicting
ships or land units.  Since nothing can move into a sanctuary, the bug
bit only with ridiculously impotent nukes.
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
c665c83ba4 Remove macro S_IRWUG
Use its expansion instead.
2009-11-30 19:45:27 +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
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
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
48ff09664b Overhaul show sect b
Print sector type mnemonic and name, like show sect s and c.  Print
"can't" instead of negative number for sectors players can't designate
(this was not an issue before the previous commit).  Show build cost
per 100%, like show ship, land, plane and nuke.  Size the columns more
sensibly.
2009-07-19 13:58:40 -04:00
be6d7ca913 Fix show sect b not to omit undesignatable sectors
show sect b needs to explain any sector players can build.
show_sect_build() omitted sectors players can't designate.  That's
wrong, because players can certainly own and thus build sectors they
can't designate.  Test for infinite mobility cost instead, like
show_sect_stats().
2009-07-19 13:52:55 -04:00
a61e673a07 Clean up poorly chosen loop control variable names
Calling a counting loop's control variable q or x is tasteless
bordering on actively misleading.
2009-05-21 09:30:05 +02:00
1329c0e544 Fix return value of s_commod() when it can't draw enough
s_commod() could incorrectly claim success when the sink ended up with
at least as many supplies than were missing initially.  This caused a
number of problems:

* shp_torp() let a ship with two shells fire a torpedo, resulting in
  -1 shells, which then made item_prewrite() oops.  Affected missions
  and return fire, but not the torpedo command.

* shp_missile_defense() let a ship with one shell use missile defense,
  resulting in -1 shells, and the same item_prewrite() oops.

* Land units were considered in supply even when they had not quite
  enough supplies.  Such land units could defend without penalty,
  attack and react.  Commands load and lload weren't affected, because
  they use lnd_in_supply(), which doesn't use s_commod().

Broken in 98f24d5c, v4.3.20.
2009-04-16 13:06:32 +02:00
df62b8604d Remove dead EASY_BRIDGES code from bridgefall()
Dead since commit 40eb78eb, v4.3.12.
2009-03-31 23:03:42 +02:00
3ea4e1ac60 Simplify retreat_ship1() and retreat_land1() slightly
No functional change.
2009-03-31 23:03:41 +02: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
6ae4eca045 Don't use 0 as null pointer constant, part 3
This part replaces E == 0 by !E, where E has pointer type.
2009-03-24 21:46:01 +01:00
90f8f2b099 Don't use 0 as null pointer constant, part 2
This part replaces E != 0 by E, where E has pointer type.
2009-03-24 21:46:01 +01:00
615681ce16 Don't use 0 as null pointer constant, part 1
Use NULL instead of 0, for clarity.  Except in pointer comparisons;
leave that to the next two commits.
2009-03-24 21:45:44 +01:00
a2ed975ec2 Clean up more unreadable assignments within if conditionals 2009-03-23 23:11:14 +01:00
d1b801b90b Make non-static function definitions match static declarations
Just to avoid confusion.
2009-03-22 17:47:14 +01:00
5dcd748f9d Don't advertize ^D as means to end a telegram
getele() aborts the telegram on EOF since commit bc8a4432 (v4.2.21).
Besides, ^D may not work with some clients.
2009-03-22 09:52:06 +01:00
57717b5bc1 Clean up unreadable assignments within if conditionals
Pinpointed assignments within if conditionals with spatch -sp_file
tests/bad_assign.cocci (from coccinelle-0.1.4).  Cherry-picked diff
hunks affecting conditionals split over multiple lines, and cleaned
them up.
2009-03-21 09:24:45 +01:00
f760150d8f Rename plane_caps() to pln_caps() and give it external linkage 2009-03-08 17:14:59 +01:00
e03eaeae23 Fix a bug in attack that could wipe out land unit updates
A victorious attacker can move attacking land units into the newly
conquered sector or leave them behind.  Normally, the player is asked
what to do, but when the land unit's army has already been told to
stay behind, or the command has been aborted, the land unit stays
behind without asking.  In that case, a copy of the land unit made
right after the victory was written back.  Any updates since the
victory were wiped out, triggering a seqno mismatch oops.

Fix by moving the re-read of the land unit in ask_move_in() out of the
prompt conditional.
2009-03-08 11:54:04 +01:00
6b75c21e3c Factor obj_changed() out of check_sect_ok() & friends 2009-03-08 09:01:56 +01:00
940092ffb9 Ignore timestamps in check_loan_ok() & friends
check_loan_ok(), check_comm_ok() and check_trade_ok() should have been
changed to ignore timestamps when timestamps were added to their files
in commit a680c811, v4.3.12.
2009-03-08 09:01:40 +01:00
ee20a9cd34 Update known contributors comments 2009-02-18 21:11:33 +01:00
59c3913b2f Take care not to supply from self
Change s_commod() not to use the supply sink as source.  As explained
in the message of the commit before the previous one, using the sink
as source makes it impossible for callers to safely keep a copy of the
sink across a supply call.  All current users do that.  Some were safe
anyway, some were not:

* fort_fire() was safe, because a fort draws shells only when it has
  none.

* shp_fire() was unsafe for ships with capability supply and ammo use
  greater than 1.  No such ship exists in the stock game.

* shp_dchrg() was unsafe for ships with both capabilities dchrg and
  supply.  Same for shp_torp() and capability torp, and
  shp_missile_defense() and capability anti-missile.  No such ship
  exists in the stock game.

* lnd_fire(), supp() and get_dlist() were safe, because they draw
  shells only when they have less than their ammo need, and then they
  don't supply any.

* mission_pln_equip() was unsafe when equipping planes with shells in
  supply sources.

* landmine() was unsafe for land units with both capability engineer
  and supply.  No such land units exist in the stock game.

* load() and lload() were unsafe for loadable supply units, but the
  supply use there was disabled in commit 65410d16 because of another
  bug.

* ask_olist() and att_reacting_units() were safe, because
  lnd_can_attack() excludes supply units.

In the stock game, planes flying interception or support missions,
abms intercepting ballistic missiles, launch of missiles or anti-sats
could conjure up shells, triggering a seqno mismatch oops.

In games with unusual customizations, this could also happen with
supply ships firing guns or torpedoes, dropping depth charges, or
shooting down marine missiles, and in the lmine command.
2009-02-17 19:32:14 +01:00