4.0.2 made land unit mobility costs differ significantly from normal

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.
This commit is contained in:
Markus Armbruster 2006-06-04 17:41:12 +00:00
parent 6ab05ae8a1
commit 5ad86bc7ce
11 changed files with 46 additions and 59 deletions

View file

@ -179,8 +179,9 @@ extern struct dchrstr bigcity_dchr;
#define FORTEFF 5 /* forts must be 5% efficient to fire. */
#define MOB_NONE 0
#define MOB_ROAD 1
#define MOB_RAIL 2
#define MOB_MOVE 1
#define MOB_MARCH 2
#define MOB_RAIL 3
#define INT_ROAD 0
#define INT_RAIL 1

View file

@ -76,7 +76,7 @@ sinfra(void)
pr(" ");
pr("%4d%% ", sect.sct_effic);
pr("%4d%% ", sect.sct_road);
pr("%4.3f ", sector_mcost(&sect, MOB_ROAD));
pr("%4.3f ", sector_mcost(&sect, MOB_MOVE));
pr("%4d%% ", sect.sct_rail);
pr("%4.3f ", sector_mcost(&sect, MOB_RAIL));
pr("%4d%% ", SCT_DEFENSE(&sect));

View file

@ -45,12 +45,11 @@ sector_mcost(struct sctstr *sp, int do_bonus)
{
double d;
if (!(d = dchr[sp->sct_type].d_mcst))
d = dchr[sp->sct_type].d_mcst;
if (d <= 0)
return -1.0;
/* Note, the best you can get is a 1.0 here. */
if (do_bonus == MOB_ROAD) {
if (do_bonus == MOB_MOVE || do_bonus == MOB_MARCH) {
d = d / (1.0 + sp->sct_road / 122.0);
} else if (do_bonus == MOB_RAIL) {
if (sp->sct_rail <= 0)
@ -64,11 +63,13 @@ sector_mcost(struct sctstr *sp, int do_bonus)
d = 1.0;
if (dchr[sp->sct_type].d_mcst < 25)
d = (d * 100.0 - sp->sct_effic) / 500.0;
/* d = (200.0 + (d - 3.0) * sp->sct_effic) / 500.0;*/
else
d = (d * 10.0 - sp->sct_effic) / 115;
if (d <= 0.0 || d < MIN_MOBCOST)
return MIN_MOBCOST;
return d;
if (do_bonus == MOB_MOVE)
return MAX(d, MIN_MOBCOST);
if (sp->sct_own != sp->sct_oldown && sp->sct_mobil <= 0
&& do_bonus != MOB_RAIL)
return MAX(d, LND_MINMOBCOST);
return MAX(d, 0.01);
}

View file

@ -342,7 +342,7 @@ BestDistPath(char *path,
struct sctstr *from,
struct sctstr *to, double *cost)
{
return BestLandPath(path, from, to, cost, MOB_ROAD);
return BestLandPath(path, from, to, cost, MOB_MOVE);
}
char *

View file

@ -793,7 +793,7 @@ get_mob_support(int combat_mode, struct combat *off, struct combat *def)
switch (combat_mode) {
case A_ATTACK:
mob_support = off->mob / sector_mcost(getsectp(def->x, def->y),
MOB_ROAD);
MOB_MOVE);
if (mob_support < 0)
mob_support = 0;
/* mob_support = off->mob / sector_mcost(def->sct_type, def->eff);*/
@ -854,7 +854,7 @@ calc_mobcost(int combat_mode, struct combat *off, struct combat *def,
off->mobcost +=
MAX(1,
(int)(attacking_mil *
sector_mcost(getsectp(def->x, def->y), MOB_ROAD)));
sector_mcost(getsectp(def->x, def->y), MOB_MOVE)));
break;
case A_LBOARD:
off->mobcost += MAX(1, attacking_mil / 5);
@ -1506,7 +1506,7 @@ att_reacting_units(struct combat *def, struct emp_qelem *list, int a_spy,
continue;
getsect(def->x, def->y, &dsect);
if (!BestLandPath(buf, &sect, &dsect, &move_cost, MOB_ROAD))
if (!BestLandPath(buf, &sect, &dsect, &move_cost, MOB_MARCH))
continue;
mobcost = land.lnd_effic * 0.01 * lchr[(int)land.lnd_type].l_spd;
@ -2445,7 +2445,7 @@ ask_move_in_off(struct combat *off, struct combat *def)
return;
if (off->own != player->cnum)
return;
d = sector_mcost(getsectp(def->x, def->y), MOB_ROAD);
d = sector_mcost(getsectp(def->x, def->y), MOB_MOVE);
if ((mob_support = MIN(off->troops, (int)(off->mob / d))) <= 0)
return;
sprintf(prompt, "How many mil to move in from %s (%d max)? ",

View file

@ -242,7 +242,7 @@ lnd_take_casualty(int combat_mode, struct llist *llp, int cas)
llp->land.lnd_x = bx;
llp->land.lnd_y = by;
getsect(bx, by, &rsect);
mobcost = lnd_mobcost(&llp->land, &rsect, MOB_ROAD);
mobcost = lnd_mobcost(&llp->land, &rsect, MOB_MARCH);
mob = llp->land.lnd_mobil - (int)mobcost;
if (mob < -127)
mob = -127;
@ -996,38 +996,20 @@ lnd_hit_mine(struct lndstr *lp, struct lchrstr *lcp)
double
lnd_mobcost(struct lndstr *lp, struct sctstr *sp, int mobtype)
{
double mobcost;
double smobcost;
double effspd;
/* supply unit's speed depends on their eff, since
that is their purpose */
effspd = lp->lnd_spd;
if (lchr[(int)lp->lnd_type].l_flags & L_SUPPLY)
mobcost = lp->lnd_effic * 0.01 * lp->lnd_spd;
else
mobcost = lp->lnd_spd;
if (mobcost < 0.01)
mobcost = 0.01;
effspd *= lp->lnd_effic * 0.01;
/* sector_mcost now takes 2 different arguments, a sector pointer, and
whether or not to figure in the highway bonus, rail bonus or none.
bridge heads, bridges and highways have built-in highways bonus
because they are a 1, and this will discount that. */
smobcost = sector_mcost(sp, mobtype);
if (smobcost < 0.01)
smobcost = 0.01;
/* marching through 0 mobility conquered sectors takes lots of mobility,
unless you are a train. Capturing railways is a good thing. */
if (sp->sct_own != sp->sct_oldown && sp->sct_mobil <= 0 &&
smobcost < LND_MINMOBCOST && mobtype != MOB_RAIL)
smobcost = LND_MINMOBCOST;
mobcost = smobcost * 5.0 * 480.0 /
(mobcost + techfact(lp->lnd_tech, mobcost));
return mobcost;
/*
* The return value must be sector_mcost(...) times a factor that
* depends only on the land unit. Anything else breaks path
* finding. In particular, you can't add or enforce a minimum
* cost here. Do it in sector_mcost().
*/
return sector_mcost(sp, mobtype) * 5.0 * 480.0
/ (effspd + techfact(lp->lnd_tech, effspd));
}
int
@ -1122,7 +1104,7 @@ lnd_mar_one_sector(struct emp_qelem *list, int dir, natid actor,
if (lchr[(int)llp->land.lnd_type].l_flags & L_TRAIN) {
llp->mobil -= lnd_mobcost(&llp->land, &sect, MOB_RAIL);
} else {
llp->mobil -= lnd_mobcost(&llp->land, &sect, MOB_ROAD);
llp->mobil -= lnd_mobcost(&llp->land, &sect, MOB_MARCH);
}
llp->land.lnd_mobil = (int)llp->mobil;
llp->land.lnd_harden = 0;
@ -1282,6 +1264,7 @@ lnd_path(int together, struct lndstr *lp, char *buf)
struct sctstr d_sect, sect;
char *cp;
double dummy;
int mtype;
if (!sarg_xy(buf, &destx, &desty))
return 0;
@ -1295,11 +1278,13 @@ lnd_path(int together, struct lndstr *lp, char *buf)
}
getsect(lp->lnd_x, lp->lnd_y, &sect);
if (lchr[(int)lp->lnd_type].l_flags & L_TRAIN)
cp = BestLandPath(buf, &sect, &d_sect, &dummy, MOB_RAIL);
mtype = MOB_RAIL;
else
cp = BestLandPath(buf, &sect, &d_sect, &dummy, MOB_ROAD);
mtype = MOB_MARCH;
cp = BestLandPath(buf, &sect, &d_sect, &dummy, mtype);
if (!cp) {
pr("No owned path from %s to %s!\n",
pr("No owned %s from %s to %s!\n",
mtype == MOB_RAIL ? "railway" : "path",
xyas(lp->lnd_x, lp->lnd_y, player->cnum),
xyas(d_sect.sct_x, d_sect.sct_y, player->cnum));
return 0;

View file

@ -85,7 +85,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
}
pr("Looking for best path to %s\n", path);
path = BestLandPath(buf2, start, &ending_sect, &total_mcost,
MOB_ROAD);
MOB_MOVE);
if (exploring && path) /* take off the 'h' */
path[strlen(path) - 1] = '\0';
if (!path)
@ -126,7 +126,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
if (movstr && sarg_xy(movstr, &dx, &dy)) {
if (getsect(dx, dy, &dsect)) {
movstr = BestLandPath(buf2, &sect, &dsect, &mv_cost,
MOB_ROAD);
MOB_MOVE);
} else {
pr("Invalid destination sector!\n");
movstr = NULL;
@ -190,7 +190,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
*movstr = 0;
continue;
}
sect_mcost = sector_mcost(&next, MOB_ROAD);
sect_mcost = sector_mcost(&next, MOB_MOVE);
if ((!player->owner && (!exploring
|| next.sct_item[I_MILIT]
|| next.sct_item[I_CIVIL]))

View file

@ -471,7 +471,7 @@ retreat_land1(struct lndstr *lp, char code, int orig)
putland(lp->lnd_uid, lp);
return 0;
}
mobcost = lnd_mobcost(lp, &sect, MOB_ROAD);
mobcost = lnd_mobcost(lp, &sect, MOB_MARCH);
lp->lnd_x = newx;
lp->lnd_y = newy;
lp->lnd_mobil -= mobcost;

View file

@ -200,7 +200,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
continue;
if (sect.sct_effic < 60)
continue;
if (!BestLandPath(buf, &dest, &sect, &move_cost, MOB_ROAD))
if (!BestLandPath(buf, &dest, &sect, &move_cost, MOB_MOVE))
continue;
if (!opt_NOFOOD && type == I_FOOD)
minimum = 1 + (int)ceil(food_needed(sect.sct_item,
@ -273,7 +273,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
continue;
if (sect.sct_effic < 2)
continue;
if (!BestLandPath(buf, &dest, &sect, &move_cost, MOB_ROAD))
if (!BestLandPath(buf, &dest, &sect, &move_cost, MOB_MOVE))
continue;
if (!opt_NOFOOD && type == I_FOOD)
minimum = 1 + (int)ceil(food_needed(ship.shp_item,
@ -347,7 +347,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
continue;
getsect(land.lnd_x, land.lnd_y, &sect);
if (!BestLandPath(buf, &dest, &sect, &move_cost, MOB_ROAD))
if (!BestLandPath(buf, &dest, &sect, &move_cost, MOB_MOVE))
continue;
if ((land.lnd_ship >= 0) && (sect.sct_type != SCT_HARBR))

View file

@ -100,7 +100,7 @@ deliver(struct sctstr *from, struct ichrstr *ip, int dir,
* calculate unit movement cost; decrease amount if
* there isn't enough mobility.
*/
mcost = sector_mcost(to, MOB_ROAD) * ip->i_lbs / ip->i_pkg[packing];
mcost = sector_mcost(to, MOB_MOVE) * ip->i_lbs / ip->i_pkg[packing];
mcost /= DELIVER_BONUS;
if (mobility < mcost * amt_moved) {

View file

@ -220,7 +220,7 @@ assemble_dist_paths(struct distinfo *distptrs)
p = ReversePath(path);
/* And walk the path back to the dist center to get the export
cost */
infptr->excost = pathcost(sp, p, MOB_ROAD);
infptr->excost = pathcost(sp, p, MOB_MOVE);
#ifdef SAVE_FINISH_PATHS
memcpy(infptr->path, p, len);
#else