bestownedpath() is a rather simple-minded breadth-first search. It's
slower than the new path finder, and maintaining it in addition to the
new path finder makes no sense.
This gets rid of the memory leak mentioned in the previous commit.
To get rid of the buffer overruns for long paths mentioned in the
previous commit, make BestLandPath() fail when path length exceeds
1023 characters.
assemble_dist_paths() and move_ground() pass buffers with a different
size. Eliminate assemble_dist_paths()'s buffer. Update now works
regardless of distribution distance (the distribute command still
limits to 1023, to be fixed in a later commit). Enlarge
move_ground()'s buffers. Doubles the length of paths accepted by
explore, move, and transport.
I use two test cases to benchmark the path finders: "continental" (Hvy
Metal 2 updates) and "island" (Hvy Plastic 2 updates).
The new path finder runs my tests around 3-4 times faster than the old
A* without its caches. That's enough to meet its cached performance
for "island", but it's only half as fast for "continental". Not for
long; big speedups are coming.
struct sctstr members sct_x, sct_y are normalized, no need to
normalize them again.
The neighbor cache now speeds up distribution path assembly by about
10% without the path cache, and by about 5% with the path cache.
Mostly to measure its effectiveness. Compile with
AS_NO_NEIGHBOR_CACHE defined to disable it.
The neighbor cache turns out to be useless in my tests: it eats memory
without speeding up the update's distribution path assembly.
Mostly to measure its effectiveness. Compile with AS_NO_PATH_CACHE
defined to disable it.
Turns out the path cache is quite effective. For my continental test
case (Hvy Metal 2 updates), it reduces the number of searches by a
factor of 18.5, speeding up distribution path assembly by a factor of
7. The price is memory: it uses 135 times more memory than the A*
library. For my island test case (Hvy Plastic 2 updates), I get 4
times search reduction, 3.5 times faster distribution path assembly,
36 times more memory.
Print them when A* actually runs, not when best_path() finds a path.
Statistics for unsuccessful runs were lost, and old statistics were
printed for path cache hits.
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.
BestLandPath(), BestDistPath() and best_path() are unsafe by design:
they take a path[] argument without a size, and blindly assume there's
enough space. When that's wrong, bp_path() overruns the caller's
buffer.
move_ground() and assemble_dist_paths() provide space for 512
characters. best(), dist(), path(), att_reacting_units(), s_commod()
and do_unit_move() provide space for 1024 characters.
A malicious player can arrange paths longer than that, but it takes a
lot of land.
BestAirPath() and BestShipPath() also take a path[] argument without a
size, but they're actually safe: bestownedpath() writes at most 100
(MAXROUTE) characters, perform_mission_bomb() provides space for 512,
sorde(), getpath(), do_unit_move() and nav_ship() for 1024.
With RAILWAYS, highway-like sectors double as rail. They need to be
at least 5% efficient to be operational, and then they additionally
extend rail into adjacent sectors that are at least 60% efficient.
New opt_RAILWAYS, SCT_HAS_RAIL(), sct_rail_track(). Update
sector_mcost(), bp_neighbors(), lnd_mar_one_sector() for RAILWAYS
mobility rules. Update sinfra(), spyline(), satdisp_sect() to show
rail track instead of rail infrastructure for RAILWAYS.
New virtual sector selector track, implemented by nsc_sct_track().
(isok, ef_init, bmaps_intersect, bp_init, player_accept)
(finish_sects, main): Use it.
(bp_neighbors, bp_lbcost, pathcost): Use XYOFFSET(). No
functional change.
other. Ensure headers in include/ can be included in any order
(except for econfig-spec.h, which is special). New header types.h to
help avoid inclusion cycles. Sort include directives. Remove some
superflous includes.
by float d_mob0 and d_mob1 (straight costs). Impassable terrain now
encoded as negative d_mob0 instead of zero d_mcst. Users changed.
sect.config updated.
(dchr_ca): Replace selectors mcst and emcst by mob0 and mob1.
(show_sect_stats): Show real mobility costs.
move costs, but failed to make A* use these costs. This broke land
unit path finding. Fix:
(MOB_ROAD, MOB_MOVE, MOB_MARCH): Split MOB_ROAD into MOB_MOVE and
MOB_MARCH. Users changed.
(lnd_mobcost, sector_mcost): Move minimum mobcost logic to
sector_mcost(), where it is visible to A*. Also fixes unit reaction
path cost.
(lnd_path): Fix confusing message: don't claim there's no path when
all we really know is that there's no railway.