Commit graph

162 commits

Author SHA1 Message Date
bb467c335d Update copyright notice
Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
2014-01-02 14:33:48 +01:00
54ddcd0f5a New pct_chance(), for clarity, and symmetry with chance() 2013-05-08 06:55:20 +02:00
8eb78a5a80 Move declarations for chance.c to new chance.h 2013-05-08 06:55:20 +02:00
df4925d696 Update copyright notice 2013-01-12 17:45:01 +01:00
612ec6257d Pilots and air cargo now spread the plague
Planes flying one-way with crew or cargo spread plague from their old
base to their new base.  Planes dropping cargo spread plague from
their base to the drop's target sector.
2012-07-13 20:15:33 +02:00
bad2fd5aac Streamline plist initialization
msl_equip(), find_escorts() and perform_mission() memset() the plist,
then assign to all members but load.  Just zero load instead, like
getilists(), msl_sel() and pln_sel() do.
2012-07-13 20:15:33 +02:00
1118f1c0ca Update copyright notice 2012-06-10 10:52:22 +02:00
786e2a99d5 Clean up superfluous includes 2012-04-26 19:57:19 +02:00
a2386edc01 Clean up superfluous include of news.h in empobj.h
Missed in commit 0ba61f17, v4.3.24.
2011-04-14 19:46:05 +02:00
74b08563af Clean up path finding in perform_mission_bomb()
Support missions up to 1023 sectors away from the airfield, up from
99.

Don't bother to call mapdist() for distance to target, just use the
path length.
2011-04-12 21:51:32 +02:00
e450c31ddb Inline BestShipPath(), BestAirPath() glue
Following commits will simplify the resulting code.
2011-04-12 21:51:32 +02:00
7e2008e7f4 License upgrade to GPL version 3 or later
Why upgrade?  I'm not a lawyer, but here's my take on the differences
to version 2:

* Software patents: better protection against abuse of patents to
  prevent users from exercising the rights under the GPL.  I doubt
  we'll get hit with a patent suit, but it's a good move just on
  general principles.

* License compatibility: compatible with more free licenses, i.e. can
  "steal" more free software for use in Empire.  I don't expect to steal
  much, but it's nice to have the option.

* Definition of "source code": modernization of some details for today's
  networked world, to make it easier to distribute the software.  Not
  really relevant to us now, as we normally distribute full source code.

* Tivoization: this is about putting GPL-licensed software in hardware,
  then make the hardware refuse to run modified software.  "Neat" trick
  to effectively deny its users their rights under the GPL.  Abuse was
  "pioneered" by TiVo (popular digital video recorders).  GPLv3 forbids
  it.  Unlikely to become a problem for us.

* Internationalization: more careful wording, to harden the license
  outside the US.  The lawyers tell us it better be done that way.

* License violations: friendlier way to deal with license violations.
  This has come out of past experience enforcing the GPL.

* Additional permissions: Probably not relevant to us.

Also include myself in the list of principal authors.
2011-04-12 21:20:58 +02:00
928e9a4cc3 Use relations_with() in unit_interdict()
No functional change, because the value of rel only matters when cn !=
victim, and then it's the same as before.

The new value of rel permits simplifying cn != victim && rel <=
NEUTRAL to just rel <= NEUTRAL
2011-02-18 18:46:04 +01:00
6807cd91b5 Use relations_with() where its different value doesn't matter
Switching from getrel() to relations_with() can change the value from
NEUTRAL to ALLIED.  The change doesn't matter when the value's only
compared to HOSTILE, as both old and new value are greater than
HOSTILE.  Likewise for >= NEUTRAL.
2011-02-16 07:52:25 +01:00
89bc9c4d5b Use feels_like_helping() in dosupport(), lnd_support()
feels_like_helping() case cn == foe is missing in the code it
replaces.  No difference in behavior, because:

* cn == foe && cn == friend can't happen.  Because you can't get into
  ground combat against yourself (assault, attack and paradrop don't
  let you), friend != foe for support.

* cn == foe && cn != friend behaves the same: no support.
  feels_like_helping() returns 0 because of the explicit case.  The
  replaced code doesn't support because cn can't be at war with
  itself.
2011-02-13 16:06:22 +01:00
7374002fd7 Plug memory leaks in mission execution code
Mission execution first builds lists of eligible units, one list per
country.  These lists are passed to perform_mission() one by one,
where they get freed.

Bugs:

* unit_interdict() didn't pass the list for the submarine's owner, but
  build_mission_list_type() built one.  Any submarine movement within
  own submarine interdiction mission op areas leaked memory.

* dosupport() passed only lists for countries that actually support
  (ally at war with victim), but build_mission_list_type() built lists
  for all countries hostile to the victim.  Ground combat within
  support mission op areas countries that are hostile to one of the
  party without actually supporting the other leaked memory.

* perform_mission() failed to free missiles targeting units.

Fixing the latter is straightforward.

Fix the first two by deciding whether a country acts on a mission
trigger before building any lists, in ground_interdict(),
unit_interdict(), dosupport().  Remove the code dealing with that from
build_mission_list_type() and the loops around perform_mission().
2011-02-13 16:06:22 +01:00
6a35432346 Move code from def_support(), off_support() to dosupport() 2011-02-13 16:06:22 +01:00
439f111f98 Remove option SLOW_WAR
SLOW_WAR has issues:

* The check whether the attacker old-owns the attacked sector is
  broken, because att_abort() uses sect.sct_oldown uninitialized.

  Spotted by the Clang Static Analyzer.

* Its implementation in setrel() is somewhat scary.  It's actually
  okay, because that part of setrel() only runs within decl().  Other
  callers don't reach it: update_main() because player->god != 0
  there, and the rest because they never pass a rel < HOSTILE.

* Documentation is a bit vague.

SLOW_WAR hasn't been used in a public game in years.  Fixing it is not
worth it, so remove it instead.
2011-02-13 15:59:49 +01:00
243a15052f Convert spaces to tabs 2010-06-20 18:36:44 +02:00
373651359e Coding style fixes, mostly indentation and whitespace 2010-06-20 18:36:38 +02:00
b8f5eaff0b Clean up dead stores
Does not change optimized code (gcc -O).

Spotted by the Clang Static Analyzer.
2010-01-19 08:40:42 +01:00
73e25ff21e Update copyright notice 2010-01-19 08:40:17 +01:00
227854bca2 Stop ship and land unit movement on interdiction with no damage
Movement stops when shp_interdict() or lnd_interdict() report
interdiction.  However, they reported it only when there was
interdiction damage.

Zero interdiction damage commonly happens when interdicting missiles
miss, or all bombers abort.  Stopping regardless of damage makes more
sense there.

Moreover, not stopping is buggy: do_unit_move() needs to take care not
to wipe out updates made by interdiction to the moving ships or land
units.  It does so only when it stops.  Updates made by interdiction
without interdiction damage could get wiped out, triggering a seqno
mismatch oops.

Known ways moving ships and land units can get updated by interdiction
despite there is no interdiction damage:

* Interdicting bombers get intercepted by planes based on a navigating
  carrier, carrier gets charged petrol.  The bug wipes out the petrol
  use.

* Marching land units get interdicted by planes, but all planes miss.
  Sufficiently large collateral damage to the sector can still damage
  the land units.  The bug wipes out the damage to land units.

To make shp_interdict() and lnd_interdict() report interdiction
regardless of damage, change lnd_missile_interdiction(),
lnd_fort_interdiction(), lnd_mission_interdiction(),
shp_missile_interdiction(), shp_fort_interdiction(),
shp_mission_interdiction() to return whether there was interdiction.
Before, they returned whether there was damage.

Change unit_interdict(), perform_mission(), perform_mission_land(),
perform_mission_ship(), perform_mission_msl(), and
perform_mission_bomb() to return -1 for no interdiction, so that
callers can distinguish no interdiction from interdiction with no
damage.
2010-01-19 08:38:18 +01:00
05b56fa942 Clean up poorly chosen loop control variable names
Calling a counting loop's control variable q or z is tasteless
bordering on actively misleading.
2010-01-19 08:38:16 +01:00
3ce3b2e387 Simplify perform_mission() 2010-01-19 08:38:16 +01:00
5e77193cf0 Remove struct genlist member cp 2010-01-19 08:38:16 +01:00
2e69a24402 Remove perform_mission_land(), perform_mission_ship() parameter md 2010-01-19 08:38:16 +01:00
d471d684be Split up perform_mission()
Move code out of perform_mission() into new perform_mission_land(),
perform_mission_ship(), perform_mission_msl(), perform_mission_bomb().
2010-01-19 08:38:16 +01:00
60519b3cd0 Consistently use int for mission type parameters 2009-12-29 13:06:35 +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
4dbee9a388 Clarify how perform_mission() uses missiles
Interdiction of ships and land units with missiles happens elsewhere.
Oops when perform_mission() strays on that turf.
2009-12-13 08:04:08 +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
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
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
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
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
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
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
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
35ef345ecb Update copyright notice 2009-02-08 09:33:18 +01:00
6564ff2240 Integrate air defense missions into interception
The ancients designed interception dead simple: when you overfly a
sector, you get intercepted by the sector owner.  Fine print
interception rules govern which planes intercept.

Then complexity got piled on top of it.

Chainsaw 2 added an extra interception by surface ship owners, in the
target sector only.

Chainsaw 3 added an extra interception by land unit owners, in the
target sector only (Empire 4 later merged this extra land unit
interception with the extra surface ship interception).

Chainsaw 3 added an entirely separate kind of interception: air
defense missions.  When you enter a sector in some air defense op
area, you get intercepted.  Fine print air defense rules govern which
planes intercept.  These rules differ significantly from the
interception fine print.

Additional complexity comes from these facts:

* Air defense mission interception happens in addition to non-mission
  interception.  You can boost your total interception by setting up
  air defense.  Which means you must set it up, or forgo an advantage.

* Air defense planes are not available for non-mission interception
  duty.  You need to decide on a split.

* In contrast to non-mission interception, interceptors flying air
  defense get intercepted.

Moreover, the air defense code breaks one of the plane code's design
assumptions, namely that just one plane sortie is active at a time.
The air defense sortie runs while the sortie it intercepts is in
progress.  This leads to two interceptions being active at the same
time: the one intercepting the original sortie, and the one
intercepting the air defense sortie.  The same plane can fly in both
interceptions, and damage received in the interception of the air
defense sortie is wiped out, triggering a seqno mismatch oops.

The previous commit already simplified non-mission interception: you
get intercepted by anyone who owns the sector, or a surface ship or a
land unit there, whether it's the target sector or not.

Now simplify mission interception, by merging air defense back into
ordinary interception: when you overfly a sector, you get intercepted
by anyone who owns the sector, or a surface ship or land unit there,
or has an air defense mission covering the sector.  That's all.  No
multiple interceptions, no separate air defense rules.

Remove air_defense().  Simplify ac_encounter() and sam_intercept()
accordingly; both lose their last parameter.

Change sam_intercept() and ac_intercept() to intercept in mission op
areas.  New parameter only_mission to suppress non-mission
interception.  Pass zero when the intercepting country owns the sector
or a surface ship or land unit in the sector.

ac_encounter() can't efficiently predict whether a country intercepts,
so it needs to call ac_intercept() unconditionally.  This kills the
optimization to collect interceptors only when needed; simplify
accordingly, replacing getilist() by getilists().
2009-02-01 17:14:39 +01:00
b624ce30dd Pass only PM_* mission flags to ac_encounter()
Since the previous two commits, ac_encounter() checks its
mission_flags argument only for proper mission flags PM_R and PM_S,
not for plane flags P_A, P_S, P_I.

This makes the code to put plane flags into mission flags useless.
Remove it from bomb(), drop(), fly(), para(), reco(),
perform_mission(), mission_pln_arm(), air_defense(), pln_arm().

Much of that code was useless even before: P_X and P_H since Chainsaw
3 option STEALTHV became mandatory in Empire 2, and P_MINE since
commit cc0c3e4f (v4.3.0) cleaned up mine drops.
2009-02-01 17:14:38 +01:00
4ea1d3acff Fix mixed ASW patrols
A reconnaissance patrol (recon and sweep) uses sonar when ASW planes
participate.  ac_encounter() enabled sonar when P_A was in
mission_flags.  These get computed by pln_arm() and callers.  However,
they set P_A only when *all* planes were capable, including escorts.

Fix by checking actual plane capabilities instead.  Closes #1389451.
2009-02-01 17:14:38 +01:00
d5f371cc1d Remove oprange()'s mission parameter
Use the current mission instead.  Make mission() set it before calling
oprange(), and clean up somewhat.
2008-12-25 11:47:32 +01:00
7ac151acac Move show_mission() to sole caller, give it internal linkage 2008-12-25 11:47:32 +01:00