/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2011, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
* Ken Stevens, Steve McClure, Markus Armbruster
*
* Empire is free software: you can redistribute it and/or modify
* pathfind.c: Find cheapest paths
*
* Known contributors to this file:
- * Markus Armbruster, 2011
+ * Markus Armbruster, 2014
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include "file.h"
+#include "nat.h"
#include "optlist.h"
#include "path.h"
#include "sect.h"
pf_check();
}
+/* silence "not used" warning */
+#ifdef PATH_FIND_DEBUG
+/*
+ * Return cost from source to sector with uid UID.
+ * It must be visited, i.e. open or closed.
+ */
+static double
+pf_cost(int uid)
+{
+ assert(!pf_is_unvisited(uid));
+ return pf_map[uid].cost;
+}
+#endif
+
static coord
x_in_dir(coord x, int dir)
{
return yy;
}
-static int
-rev_dir(int dir)
-{
- assert(DIR_FIRST <= dir && dir <= DIR_LAST);
- return dir >= DIR_FIRST + 3 ? dir - 3 : dir + 3;
-}
-
/*
* Set the current source and cost function.
* SX,SY is the source.
double
path_find_to(coord dx, coord dy)
{
- int duid;
- int uid, nuid, i;
+ int duid, nuid, i;
double cost, c1;
coord x, y, nx, ny;
return pf_map[duid].cost;
}
- while (pf_nheap > 0 && (uid = pf_heap[0].uid) != duid) {
+ while (pf_nheap > 0 && pf_heap[0].uid != duid) {
x = pf_heap[0].x;
y = pf_heap[0].y;
cost = pf_heap[0].cost;
i = bufsz;
buf[--i] = dirch[d];
len++;
- x = x_in_dir(x, rev_dir(d));
- y = y_in_dir(y, rev_dir(d));
+ assert(DIR_FIRST <= d && d <= DIR_LAST);
+ x = x_in_dir(x, DIR_BACK(d));
+ y = y_in_dir(y, DIR_BACK(d));
}
assert(x == sx && y == sy);
return buf;
}
+#ifdef PATH_FIND_DEBUG
+void
+path_find_visualize(coord sx, coord sy, coord dx, coord dy)
+{
+ int uid;
+ int xmin, xmax, ymin, ymax, x, y, odd, ch;
+ double c, u, cost;
+ char buf[1024];
+
+ assert(pf_cost(XYOFFSET(sx, sy)) == 0.0);
+ c = pf_cost(XYOFFSET(dx, dy));
+ u = c / 10.0;
+
+ /* find bounding box */
+ xmin = xmax = 0;
+ ymin = ymax = 0;
+ for (y = -WORLD_Y / 2; y < WORLD_Y / 2; y++) {
+ odd = ((sx + -WORLD_X / 2) ^ (sy + y)) & 1;
+ for (x = -WORLD_X / 2 + odd; x < WORLD_X / 2; x += 2) {
+ uid = XYOFFSET(XNORM(sx + x), YNORM(sy + y));
+ if (pf_is_unvisited(uid))
+ continue;
+ if (xmin > x)
+ xmin = x;
+ if (xmax < x)
+ xmax = x;
+ if (ymin > y)
+ ymin = y;
+ if (ymax < y)
+ ymax = y;
+ }
+ }
+ printf("bbox %d:%d,%d:%d origin %d,%d\n",
+ xmin, xmax, ymin, ymax, sx, sy);
+
+ for (y = ymin; y <= ymax; y++) {
+ odd = ((sx + xmin) ^ (sy + y)) & 1;
+ if (odd)
+ printf(" ");
+ for (x = xmin + odd; x <= xmax; x += 2) {
+ uid = XYOFFSET(XNORM(sx + x), YNORM(sy + y));
+ if (pf_is_unvisited(uid))
+ ch = ' ';
+ else if (uid == XYOFFSET(dx, dy))
+ ch = 'D';
+ else if (uid == XYOFFSET(sx, sy))
+ ch = 'S';
+ else {
+ cost = pf_cost(uid);
+ ch = cost > c ? '+' : '0' + (int)(10 * (cost / c));
+ }
+ printf(" %c", ch);
+ }
+ printf("\n");
+ }
+ path_find_route(buf, sizeof(buf), sx, sy, dx, dy);
+ printf("%s %g\n", buf, pf_cost(XYOFFSET(dx, dy)));
+}
+#endif
+
#ifdef PATH_FIND_STATS
void
path_find_print_stats(void)
cost_land(natid actor, int uid, int mobtype)
{
/*
- * Non-negative cost must not depend on ACTOR, see BestLandPath().
+ * Non-negative cost must not depend on ACTOR, see unit_path().
*/
struct sctstr *sp = (void *)empfile[EF_SECTOR].cache;
return cost_land(actor, uid, MOB_RAIL);
}
+static double
+cost_sail(natid actor, int uid)
+{
+ struct sctstr *sp = (void *)empfile[EF_SECTOR].cache;
+ natid sctown = sp[uid].sct_own;
+ char *bmap;
+
+ if (sctown && relations_with(sctown, actor) == ALLIED) {
+ /* FIXME duplicates shp_check_nav() logic */
+ switch (dchr[sp[uid].sct_type].d_nav) {
+ case NAVOK:
+ return 1.0;
+ case NAV_CANAL:
+ /* FIXME return 1.0 when all ships have M_CANAL */
+ return -1.0;
+ case NAV_02:
+ return sp[uid].sct_effic >= 2 ? 1.0 : -1.0;
+ case NAV_60:
+ return sp[uid].sct_effic >= 60 ? 1.0 : -1.0;
+ default:
+ return -1.0;
+ }
+ }
+
+ bmap = ef_ptr(EF_BMAP, actor);
+ return bmap[uid] == '.' || bmap[uid] == ' ' || bmap[uid] == 0
+ ? 1.0 : -1.0;
+}
+
+static double
+cost_fly(natid actor, int uid)
+{
+ return 1.0;
+}
+
static double (*cost_tab[])(natid, int) = {
- cost_move, cost_march, cost_rail
+ cost_move, cost_march, cost_rail, cost_sail, cost_fly
};
/*