From 04363a92db7e80942c03f9dee6edca88cc3536eb Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Feb 2011 07:18:41 +0100 Subject: [PATCH] Use the new path finder for sea & air, drop bestownedpath() 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. --- include/path.h | 5 +- include/prototypes.h | 2 - src/lib/common/bestpath.c | 223 -------------------------------------- src/lib/common/path.c | 23 +++- src/lib/common/pathfind.c | 38 ++++++- 5 files changed, 57 insertions(+), 234 deletions(-) delete mode 100644 src/lib/common/bestpath.c diff --git a/include/path.h b/include/path.h index 287ec02c..eb0d950e 100644 --- a/include/path.h +++ b/include/path.h @@ -52,6 +52,8 @@ #define MOB_MOVE 0 #define MOB_MARCH 1 #define MOB_RAIL 2 +#define MOB_SAIL 3 +#define MOB_FLY 4 enum p_mode { /* How to find path to destination */ P_NONE, /* don't */ @@ -65,9 +67,6 @@ extern int diroff[DIR_MAP+1][2]; extern char dirch[DIR_MAP+2]; extern char *routech[DIR_LAST+1]; -/* src/lib/common/bestpath.c */ -extern char *bestownedpath(char *, char *, int, int, int, int, int); - /* src/lib/common/findpath.c */ extern void path_find_from(coord, coord, natid, int); extern double path_find_to(coord, coord); diff --git a/include/prototypes.h b/include/prototypes.h index 02cf823d..53a28398 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -253,8 +253,6 @@ int zdon(void); /* * src/lib/common/ *.c */ -/* bestpath.c */ -/* in path.h */ /* conftab.c */ extern int read_builtin_tables(void); extern int read_custom_tables(void); diff --git a/src/lib/common/bestpath.c b/src/lib/common/bestpath.c deleted file mode 100644 index 3907d539..00000000 --- a/src/lib/common/bestpath.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2011, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure, Markus Armbruster - * - * Empire is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * bestpath.c: Find the best path between sectors - * - * Known contributors to this file: - * Steve McClure, 1998-2000 - * Markus Armbruster, 2006 - */ - -/* - * IMPORTANT: These routines are very selectively used in the server. - * - * "bestownedpath" is only used to determine paths for ships and planes. - * - * Callers should not be calling these directly anymore. They should use - * the "BestShipPath", "BestAirPath", "BestLandPath" and "BestDistPath" - * functions. Note that those last two use the A* algorithms to find - * information. - */ - -#include - -#include "file.h" -#include "misc.h" -#include "nat.h" -#include "optlist.h" -#include "path.h" -#include "prototypes.h" -#include "sect.h" -#include "xy.h" - -static int owned_and_navigable(char *, int, int, int); - -#define MAXROUTE 100 -#define valid(x,y) ((((x) ^ (y)) & 1) == 0) - -/* - * Ok, note that here we malloc some buffers. BUT, we never - * free them. Why, you may ask? Because we want to allocate - * them based on world size which is now (or soon to be) dynamic, - * but we don't want to allocate each and every time, since that - * would be slow. And, since world size only changes at init - * time, we can do this safely. - */ -static unsigned short *mapbuf; -static unsigned short **mapindex; - -/* - * Find passable path from X, Y to EX, EY for nation OWN. - * BPATH is a buffer capable of holding at least MAXROUTE characters. - * If BIGMAP is null, all sectors are passable (useful for flying). - * Else it is taken to be a bmap. - * Sectors owned by or allied to OWN are then passable according to - * the usual rules. - * Other sectors are assumed to be passable when BIGMAP shows '.' or - * nothing. - * Return a path if found, else a null pointer. - * Wart: the path isn't terminated with 'h', except when if X,Y equals - * EX,EY. - */ -char * -bestownedpath(char *bpath, char *bigmap, - int x, int y, int ex, int ey, int own) -{ - int i, j, tx, ty, markedsectors; - int minx, maxx, miny, maxy, scanx, scany; - unsigned routelen; - - if (!mapbuf) - mapbuf = malloc(WORLD_X * WORLD_Y * sizeof(*mapbuf)); - if (!mapbuf) - return NULL; - if (!mapindex) { - mapindex = malloc(WORLD_X * sizeof(*mapindex)); - if (mapindex) { - /* Setup the map pointers */ - for (i = 0; i < WORLD_X; i++) - mapindex[i] = &mapbuf[WORLD_Y * i]; - } - } - if (!mapindex) - return NULL; - - x = XNORM(x); - y = YNORM(y); - ex = XNORM(ex); - ey = YNORM(ey); - - if (x == ex && y == ey) - return "h"; - - if (!valid(x, y) || !valid(ex, ey)) - return NULL; - if (!owned_and_navigable(bigmap, ex, ey, own)) - return NULL; - - for (i = 0; i < WORLD_X; i++) - for (j = 0; j < WORLD_Y; j++) - mapindex[i][j] = 0xFFFF; /* clear the workspace */ - - routelen = 0; /* path length is now 0 */ - mapindex[x][y] = 0; /* mark starting spot */ - minx = x - 2; /* set X scan bounds */ - maxx = x + 2; - miny = y - 1; /* set Y scan bounds */ - maxy = y + 1; - - do { - if (++routelen == MAXROUTE) - return NULL; - markedsectors = 0; - for (scanx = minx; scanx <= maxx; scanx++) { - x = XNORM(scanx); - for (scany = miny; scany <= maxy; scany++) { - y = YNORM(scany); - if (!valid(x, y)) - continue; - if (((mapindex[x][y] & 0x1FFF) == routelen - 1)) { - for (i = DIR_FIRST; i <= DIR_LAST; i++) { - tx = x + diroff[i][0]; - ty = y + diroff[i][1]; - tx = XNORM(tx); - ty = YNORM(ty); - if (mapindex[tx][ty] == 0xFFFF) { - if (owned_and_navigable(bigmap, tx, ty, own)) { - if (CANT_HAPPEN(i < DIR_FIRST || i > DIR_LAST)) - i = DIR_STOP; - mapindex[tx][ty] = - ((i - DIR_FIRST + 1) << 13) + routelen; - markedsectors++; - } - } - if (tx == ex && ty == ey) { - bpath[routelen] = 0; - while (routelen--) { - i = (mapindex[tx][ty] >> 13) - - 1 + DIR_FIRST; - bpath[routelen] = dirch[i]; - tx = tx - diroff[i][0]; - ty = ty - diroff[i][1]; - tx = XNORM(tx); - ty = YNORM(ty); - } - return bpath; - } - } - } - } - } - miny--; - maxy++; - minx -= 2; - maxx += 2; - } while (markedsectors); - - return NULL; /* no route possible */ -} - -/* - * Return non-zero if sector X, Y is passable. - * If BIGMAP is null, all sectors are passable (useful for flying). - * Else it is taken to be a bmap. - * Sectors owned by or allied to OWN are checked according to the - * usual rules, and the result is correct. - * Other sectors are assumed to be passable when BIGMAP shows '.' or - * nothing. - */ -static int -owned_and_navigable(char *bigmap, int x, int y, int own) -{ - char mapspot; - struct sctstr sect; - - if (!bigmap) - return 1; - - /* Owned or allied sector? Check the real sector. */ - getsect(x, y, §); - if (sect.sct_own && relations_with(sect.sct_own, own) == ALLIED) { - /* FIXME duplicates shp_check_nav() logic */ - switch (dchr[sect.sct_type].d_nav) { - case NAVOK: - return 1; - case NAV_CANAL: - /* FIXME return 1 when all ships have M_CANAL */ - return 0; - case NAV_02: - return sect.sct_effic >= 2; - case NAV_60: - return sect.sct_effic >= 60; - default: - return 0; - } - } - - /* Can only check bigmap */ - mapspot = bigmap[sect.sct_uid]; - return mapspot == '.' || mapspot == ' ' || mapspot == 0; -} diff --git a/src/lib/common/path.c b/src/lib/common/path.c index a5f18c73..ecd91c30 100644 --- a/src/lib/common/path.c +++ b/src/lib/common/path.c @@ -86,16 +86,29 @@ BestDistPath(char *path, char * BestShipPath(char *path, int fx, int fy, int tx, int ty, int owner) { - char *map; + size_t len; - map = ef_ptr(EF_BMAP, owner); - if (!map) + if (path_find(fx, fy, tx, ty, owner, MOB_SAIL) < 0) return NULL; - return bestownedpath(path, map, fx, fy, tx, ty, owner); + len = path_find_route(path, 100, fx, fy, tx, ty); + if (len >= 100) + return NULL; + if (len == 0) + strcpy(path, "h"); + return path; } char * BestAirPath(char *path, int fx, int fy, int tx, int ty) { - return bestownedpath(path, NULL, fx, fy, tx, ty, -1); + size_t len; + + if (path_find(fx, fy, tx, ty, 0, MOB_FLY) < 0) + return NULL; + len = path_find_route(path, 100, fx, fy, tx, ty); + if (len >= 100) + return NULL; + if (len == 0) + strcpy(path, "h"); + return path; } diff --git a/src/lib/common/pathfind.c b/src/lib/common/pathfind.c index 7316d63e..bd5cb121 100644 --- a/src/lib/common/pathfind.c +++ b/src/lib/common/pathfind.c @@ -37,6 +37,7 @@ #include #include #include "file.h" +#include "nat.h" #include "optlist.h" #include "path.h" #include "sect.h" @@ -598,8 +599,43 @@ cost_rail(natid actor, int uid) 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 }; /*