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:
parent
6ab05ae8a1
commit
5ad86bc7ce
11 changed files with 46 additions and 59 deletions
|
@ -179,8 +179,9 @@ extern struct dchrstr bigcity_dchr;
|
||||||
#define FORTEFF 5 /* forts must be 5% efficient to fire. */
|
#define FORTEFF 5 /* forts must be 5% efficient to fire. */
|
||||||
|
|
||||||
#define MOB_NONE 0
|
#define MOB_NONE 0
|
||||||
#define MOB_ROAD 1
|
#define MOB_MOVE 1
|
||||||
#define MOB_RAIL 2
|
#define MOB_MARCH 2
|
||||||
|
#define MOB_RAIL 3
|
||||||
|
|
||||||
#define INT_ROAD 0
|
#define INT_ROAD 0
|
||||||
#define INT_RAIL 1
|
#define INT_RAIL 1
|
||||||
|
|
|
@ -76,7 +76,7 @@ sinfra(void)
|
||||||
pr(" ");
|
pr(" ");
|
||||||
pr("%4d%% ", sect.sct_effic);
|
pr("%4d%% ", sect.sct_effic);
|
||||||
pr("%4d%% ", sect.sct_road);
|
pr("%4d%% ", sect.sct_road);
|
||||||
pr("%4.3f ", sector_mcost(§, MOB_ROAD));
|
pr("%4.3f ", sector_mcost(§, MOB_MOVE));
|
||||||
pr("%4d%% ", sect.sct_rail);
|
pr("%4d%% ", sect.sct_rail);
|
||||||
pr("%4.3f ", sector_mcost(§, MOB_RAIL));
|
pr("%4.3f ", sector_mcost(§, MOB_RAIL));
|
||||||
pr("%4d%% ", SCT_DEFENSE(§));
|
pr("%4d%% ", SCT_DEFENSE(§));
|
||||||
|
|
|
@ -45,12 +45,11 @@ sector_mcost(struct sctstr *sp, int do_bonus)
|
||||||
{
|
{
|
||||||
double d;
|
double d;
|
||||||
|
|
||||||
if (!(d = dchr[sp->sct_type].d_mcst))
|
d = dchr[sp->sct_type].d_mcst;
|
||||||
|
if (d <= 0)
|
||||||
return -1.0;
|
return -1.0;
|
||||||
|
|
||||||
/* Note, the best you can get is a 1.0 here. */
|
if (do_bonus == MOB_MOVE || do_bonus == MOB_MARCH) {
|
||||||
|
|
||||||
if (do_bonus == MOB_ROAD) {
|
|
||||||
d = d / (1.0 + sp->sct_road / 122.0);
|
d = d / (1.0 + sp->sct_road / 122.0);
|
||||||
} else if (do_bonus == MOB_RAIL) {
|
} else if (do_bonus == MOB_RAIL) {
|
||||||
if (sp->sct_rail <= 0)
|
if (sp->sct_rail <= 0)
|
||||||
|
@ -64,11 +63,13 @@ sector_mcost(struct sctstr *sp, int do_bonus)
|
||||||
d = 1.0;
|
d = 1.0;
|
||||||
if (dchr[sp->sct_type].d_mcst < 25)
|
if (dchr[sp->sct_type].d_mcst < 25)
|
||||||
d = (d * 100.0 - sp->sct_effic) / 500.0;
|
d = (d * 100.0 - sp->sct_effic) / 500.0;
|
||||||
/* d = (200.0 + (d - 3.0) * sp->sct_effic) / 500.0;*/
|
|
||||||
else
|
else
|
||||||
d = (d * 10.0 - sp->sct_effic) / 115;
|
d = (d * 10.0 - sp->sct_effic) / 115;
|
||||||
|
|
||||||
if (d <= 0.0 || d < MIN_MOBCOST)
|
if (do_bonus == MOB_MOVE)
|
||||||
return MIN_MOBCOST;
|
return MAX(d, MIN_MOBCOST);
|
||||||
return d;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -342,7 +342,7 @@ BestDistPath(char *path,
|
||||||
struct sctstr *from,
|
struct sctstr *from,
|
||||||
struct sctstr *to, double *cost)
|
struct sctstr *to, double *cost)
|
||||||
{
|
{
|
||||||
return BestLandPath(path, from, to, cost, MOB_ROAD);
|
return BestLandPath(path, from, to, cost, MOB_MOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
|
|
@ -793,7 +793,7 @@ get_mob_support(int combat_mode, struct combat *off, struct combat *def)
|
||||||
switch (combat_mode) {
|
switch (combat_mode) {
|
||||||
case A_ATTACK:
|
case A_ATTACK:
|
||||||
mob_support = off->mob / sector_mcost(getsectp(def->x, def->y),
|
mob_support = off->mob / sector_mcost(getsectp(def->x, def->y),
|
||||||
MOB_ROAD);
|
MOB_MOVE);
|
||||||
if (mob_support < 0)
|
if (mob_support < 0)
|
||||||
mob_support = 0;
|
mob_support = 0;
|
||||||
/* mob_support = off->mob / sector_mcost(def->sct_type, def->eff);*/
|
/* 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 +=
|
off->mobcost +=
|
||||||
MAX(1,
|
MAX(1,
|
||||||
(int)(attacking_mil *
|
(int)(attacking_mil *
|
||||||
sector_mcost(getsectp(def->x, def->y), MOB_ROAD)));
|
sector_mcost(getsectp(def->x, def->y), MOB_MOVE)));
|
||||||
break;
|
break;
|
||||||
case A_LBOARD:
|
case A_LBOARD:
|
||||||
off->mobcost += MAX(1, attacking_mil / 5);
|
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;
|
continue;
|
||||||
|
|
||||||
getsect(def->x, def->y, &dsect);
|
getsect(def->x, def->y, &dsect);
|
||||||
if (!BestLandPath(buf, §, &dsect, &move_cost, MOB_ROAD))
|
if (!BestLandPath(buf, §, &dsect, &move_cost, MOB_MARCH))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mobcost = land.lnd_effic * 0.01 * lchr[(int)land.lnd_type].l_spd;
|
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;
|
return;
|
||||||
if (off->own != player->cnum)
|
if (off->own != player->cnum)
|
||||||
return;
|
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)
|
if ((mob_support = MIN(off->troops, (int)(off->mob / d))) <= 0)
|
||||||
return;
|
return;
|
||||||
sprintf(prompt, "How many mil to move in from %s (%d max)? ",
|
sprintf(prompt, "How many mil to move in from %s (%d max)? ",
|
||||||
|
|
|
@ -242,7 +242,7 @@ lnd_take_casualty(int combat_mode, struct llist *llp, int cas)
|
||||||
llp->land.lnd_x = bx;
|
llp->land.lnd_x = bx;
|
||||||
llp->land.lnd_y = by;
|
llp->land.lnd_y = by;
|
||||||
getsect(bx, by, &rsect);
|
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;
|
mob = llp->land.lnd_mobil - (int)mobcost;
|
||||||
if (mob < -127)
|
if (mob < -127)
|
||||||
mob = -127;
|
mob = -127;
|
||||||
|
@ -996,38 +996,20 @@ lnd_hit_mine(struct lndstr *lp, struct lchrstr *lcp)
|
||||||
double
|
double
|
||||||
lnd_mobcost(struct lndstr *lp, struct sctstr *sp, int mobtype)
|
lnd_mobcost(struct lndstr *lp, struct sctstr *sp, int mobtype)
|
||||||
{
|
{
|
||||||
double mobcost;
|
double effspd;
|
||||||
double smobcost;
|
|
||||||
|
|
||||||
/* supply unit's speed depends on their eff, since
|
effspd = lp->lnd_spd;
|
||||||
that is their purpose */
|
|
||||||
if (lchr[(int)lp->lnd_type].l_flags & L_SUPPLY)
|
if (lchr[(int)lp->lnd_type].l_flags & L_SUPPLY)
|
||||||
mobcost = lp->lnd_effic * 0.01 * lp->lnd_spd;
|
effspd *= lp->lnd_effic * 0.01;
|
||||||
else
|
|
||||||
mobcost = lp->lnd_spd;
|
|
||||||
if (mobcost < 0.01)
|
|
||||||
mobcost = 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.
|
* The return value must be sector_mcost(...) times a factor that
|
||||||
bridge heads, bridges and highways have built-in highways bonus
|
* depends only on the land unit. Anything else breaks path
|
||||||
because they are a 1, and this will discount that. */
|
* finding. In particular, you can't add or enforce a minimum
|
||||||
|
* cost here. Do it in sector_mcost().
|
||||||
smobcost = sector_mcost(sp, mobtype);
|
*/
|
||||||
if (smobcost < 0.01)
|
return sector_mcost(sp, mobtype) * 5.0 * 480.0
|
||||||
smobcost = 0.01;
|
/ (effspd + techfact(lp->lnd_tech, effspd));
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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) {
|
if (lchr[(int)llp->land.lnd_type].l_flags & L_TRAIN) {
|
||||||
llp->mobil -= lnd_mobcost(&llp->land, §, MOB_RAIL);
|
llp->mobil -= lnd_mobcost(&llp->land, §, MOB_RAIL);
|
||||||
} else {
|
} else {
|
||||||
llp->mobil -= lnd_mobcost(&llp->land, §, MOB_ROAD);
|
llp->mobil -= lnd_mobcost(&llp->land, §, MOB_MARCH);
|
||||||
}
|
}
|
||||||
llp->land.lnd_mobil = (int)llp->mobil;
|
llp->land.lnd_mobil = (int)llp->mobil;
|
||||||
llp->land.lnd_harden = 0;
|
llp->land.lnd_harden = 0;
|
||||||
|
@ -1282,6 +1264,7 @@ lnd_path(int together, struct lndstr *lp, char *buf)
|
||||||
struct sctstr d_sect, sect;
|
struct sctstr d_sect, sect;
|
||||||
char *cp;
|
char *cp;
|
||||||
double dummy;
|
double dummy;
|
||||||
|
int mtype;
|
||||||
|
|
||||||
if (!sarg_xy(buf, &destx, &desty))
|
if (!sarg_xy(buf, &destx, &desty))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1295,11 +1278,13 @@ lnd_path(int together, struct lndstr *lp, char *buf)
|
||||||
}
|
}
|
||||||
getsect(lp->lnd_x, lp->lnd_y, §);
|
getsect(lp->lnd_x, lp->lnd_y, §);
|
||||||
if (lchr[(int)lp->lnd_type].l_flags & L_TRAIN)
|
if (lchr[(int)lp->lnd_type].l_flags & L_TRAIN)
|
||||||
cp = BestLandPath(buf, §, &d_sect, &dummy, MOB_RAIL);
|
mtype = MOB_RAIL;
|
||||||
else
|
else
|
||||||
cp = BestLandPath(buf, §, &d_sect, &dummy, MOB_ROAD);
|
mtype = MOB_MARCH;
|
||||||
|
cp = BestLandPath(buf, §, &d_sect, &dummy, mtype);
|
||||||
if (!cp) {
|
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(lp->lnd_x, lp->lnd_y, player->cnum),
|
||||||
xyas(d_sect.sct_x, d_sect.sct_y, player->cnum));
|
xyas(d_sect.sct_x, d_sect.sct_y, player->cnum));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -85,7 +85,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
|
||||||
}
|
}
|
||||||
pr("Looking for best path to %s\n", path);
|
pr("Looking for best path to %s\n", path);
|
||||||
path = BestLandPath(buf2, start, &ending_sect, &total_mcost,
|
path = BestLandPath(buf2, start, &ending_sect, &total_mcost,
|
||||||
MOB_ROAD);
|
MOB_MOVE);
|
||||||
if (exploring && path) /* take off the 'h' */
|
if (exploring && path) /* take off the 'h' */
|
||||||
path[strlen(path) - 1] = '\0';
|
path[strlen(path) - 1] = '\0';
|
||||||
if (!path)
|
if (!path)
|
||||||
|
@ -126,7 +126,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
|
||||||
if (movstr && sarg_xy(movstr, &dx, &dy)) {
|
if (movstr && sarg_xy(movstr, &dx, &dy)) {
|
||||||
if (getsect(dx, dy, &dsect)) {
|
if (getsect(dx, dy, &dsect)) {
|
||||||
movstr = BestLandPath(buf2, §, &dsect, &mv_cost,
|
movstr = BestLandPath(buf2, §, &dsect, &mv_cost,
|
||||||
MOB_ROAD);
|
MOB_MOVE);
|
||||||
} else {
|
} else {
|
||||||
pr("Invalid destination sector!\n");
|
pr("Invalid destination sector!\n");
|
||||||
movstr = NULL;
|
movstr = NULL;
|
||||||
|
@ -190,7 +190,7 @@ move_ground(struct sctstr *start, struct sctstr *end,
|
||||||
*movstr = 0;
|
*movstr = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sect_mcost = sector_mcost(&next, MOB_ROAD);
|
sect_mcost = sector_mcost(&next, MOB_MOVE);
|
||||||
if ((!player->owner && (!exploring
|
if ((!player->owner && (!exploring
|
||||||
|| next.sct_item[I_MILIT]
|
|| next.sct_item[I_MILIT]
|
||||||
|| next.sct_item[I_CIVIL]))
|
|| next.sct_item[I_CIVIL]))
|
||||||
|
|
|
@ -471,7 +471,7 @@ retreat_land1(struct lndstr *lp, char code, int orig)
|
||||||
putland(lp->lnd_uid, lp);
|
putland(lp->lnd_uid, lp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mobcost = lnd_mobcost(lp, §, MOB_ROAD);
|
mobcost = lnd_mobcost(lp, §, MOB_MARCH);
|
||||||
lp->lnd_x = newx;
|
lp->lnd_x = newx;
|
||||||
lp->lnd_y = newy;
|
lp->lnd_y = newy;
|
||||||
lp->lnd_mobil -= mobcost;
|
lp->lnd_mobil -= mobcost;
|
||||||
|
|
|
@ -200,7 +200,7 @@ s_commod(int own, int x, int y, i_type type, int total_wanted,
|
||||||
continue;
|
continue;
|
||||||
if (sect.sct_effic < 60)
|
if (sect.sct_effic < 60)
|
||||||
continue;
|
continue;
|
||||||
if (!BestLandPath(buf, &dest, §, &move_cost, MOB_ROAD))
|
if (!BestLandPath(buf, &dest, §, &move_cost, MOB_MOVE))
|
||||||
continue;
|
continue;
|
||||||
if (!opt_NOFOOD && type == I_FOOD)
|
if (!opt_NOFOOD && type == I_FOOD)
|
||||||
minimum = 1 + (int)ceil(food_needed(sect.sct_item,
|
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;
|
continue;
|
||||||
if (sect.sct_effic < 2)
|
if (sect.sct_effic < 2)
|
||||||
continue;
|
continue;
|
||||||
if (!BestLandPath(buf, &dest, §, &move_cost, MOB_ROAD))
|
if (!BestLandPath(buf, &dest, §, &move_cost, MOB_MOVE))
|
||||||
continue;
|
continue;
|
||||||
if (!opt_NOFOOD && type == I_FOOD)
|
if (!opt_NOFOOD && type == I_FOOD)
|
||||||
minimum = 1 + (int)ceil(food_needed(ship.shp_item,
|
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;
|
continue;
|
||||||
|
|
||||||
getsect(land.lnd_x, land.lnd_y, §);
|
getsect(land.lnd_x, land.lnd_y, §);
|
||||||
if (!BestLandPath(buf, &dest, §, &move_cost, MOB_ROAD))
|
if (!BestLandPath(buf, &dest, §, &move_cost, MOB_MOVE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((land.lnd_ship >= 0) && (sect.sct_type != SCT_HARBR))
|
if ((land.lnd_ship >= 0) && (sect.sct_type != SCT_HARBR))
|
||||||
|
|
|
@ -100,7 +100,7 @@ deliver(struct sctstr *from, struct ichrstr *ip, int dir,
|
||||||
* calculate unit movement cost; decrease amount if
|
* calculate unit movement cost; decrease amount if
|
||||||
* there isn't enough mobility.
|
* 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;
|
mcost /= DELIVER_BONUS;
|
||||||
|
|
||||||
if (mobility < mcost * amt_moved) {
|
if (mobility < mcost * amt_moved) {
|
||||||
|
|
|
@ -220,7 +220,7 @@ assemble_dist_paths(struct distinfo *distptrs)
|
||||||
p = ReversePath(path);
|
p = ReversePath(path);
|
||||||
/* And walk the path back to the dist center to get the export
|
/* And walk the path back to the dist center to get the export
|
||||||
cost */
|
cost */
|
||||||
infptr->excost = pathcost(sp, p, MOB_ROAD);
|
infptr->excost = pathcost(sp, p, MOB_MOVE);
|
||||||
#ifdef SAVE_FINISH_PATHS
|
#ifdef SAVE_FINISH_PATHS
|
||||||
memcpy(infptr->path, p, len);
|
memcpy(infptr->path, p, len);
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue