00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <config.h>
00039
00040 #include "../as/as.h"
00041 #include "file.h"
00042 #include "misc.h"
00043 #include "optlist.h"
00044 #include "path.h"
00045 #include "prototypes.h"
00046 #include "sect.h"
00047 #include "xy.h"
00048 #include <stdio.h>
00049
00050 #define BP_ASHASHSIZE 128
00051 #define BP_NEIGHBORS 6
00052
00053 struct bestp {
00054 int sctcache_hits;
00055 int sctcache_misses;
00056 int bp_mobtype;
00057 struct as_data *adp;
00058 };
00059
00060 static int bp_path(struct as_path *pp, char *buf);
00061 static int bp_neighbors(struct as_coord c, struct as_coord *cp, void *);
00062 static double bp_lbcost(struct as_coord from, struct as_coord to, void *);
00063 static double bp_realcost(struct as_coord from, struct as_coord to, void *);
00064 static double bp_seccost(struct as_coord from, struct as_coord to, void *);
00065 static int bp_coord_hash(struct as_coord c);
00066
00067
00068
00069 static struct sctstr **neighsects;
00070
00071 static struct bestp *
00072 bp_init(void)
00073 {
00074 struct bestp *bp;
00075
00076 bp = malloc(sizeof(*bp));
00077 memset(bp, 0, sizeof(*bp));
00078 bp->adp = as_init(BP_NEIGHBORS, BP_ASHASHSIZE, bp_coord_hash,
00079 bp_neighbors, bp_lbcost, bp_realcost,
00080 bp_seccost, bp);
00081
00082 if (bp->adp == NULL)
00083 return NULL;
00084
00085 if (neighsects == NULL)
00086 neighsects = calloc(WORLD_SZ() * 6, sizeof(struct sctstr *));
00087
00088 return bp;
00089 }
00090
00091
00092
00093
00094
00095 static int
00096 best_path(struct sctstr *from, struct sctstr *to, char *path,
00097 int mob_type)
00098 {
00099 static struct bestp *mybestpath;
00100 struct as_data *adp;
00101 struct as_path *ap;
00102
00103 if (mybestpath == 0)
00104 mybestpath = bp_init();
00105 adp = mybestpath->adp;
00106 ap = as_find_cachepath(from->sct_x, from->sct_y, to->sct_x, to->sct_y);
00107 if (ap == NULL) {
00108 adp->from.x = from->sct_x;
00109 adp->from.y = from->sct_y;
00110 adp->to.x = to->sct_x;
00111 adp->to.y = to->sct_y;
00112 mybestpath->bp_mobtype = mob_type;
00113
00114 if (as_search(adp) < 0)
00115 return -1;
00116 ap = adp->path;
00117 }
00118
00119 if (bp_path(ap, path) < 0)
00120 return -1;
00121
00122 #ifdef AS_STATS
00123 as_stats(adp, stderr);
00124 #endif
00125 #ifdef BP_STATS
00126 fprintf(stderr, "best path %s\n", path);
00127 fprintf(stderr, "cache hits/misses: %d/%d\n",
00128 bp->sctcache_hits, bp->sctcache_misses);
00129 #endif
00130 return 0;
00131 }
00132
00133
00134
00135
00136
00137 static int
00138 bp_path(struct as_path *pp, char *buf)
00139 {
00140 struct as_path *np;
00141 char *cp = buf;
00142 int dx, dy;
00143 int n;
00144
00145 np = pp->next;
00146 while (np) {
00147 dx = np->c.x - pp->c.x;
00148
00149 if (dx < -2)
00150 dx += WORLD_X;
00151 else if (dx > 2)
00152 dx -= WORLD_X;
00153 dy = np->c.y - pp->c.y;
00154 if (dy < -1)
00155 dy += WORLD_Y;
00156 else if (dy > 1)
00157 dy -= WORLD_Y;
00158 for (n = 1; n <= 6; n++)
00159 if (dx == diroff[n][0] && dy == diroff[n][1])
00160 break;
00161 if (n > 6)
00162 return -1;
00163
00164 *cp++ = dirch[n];
00165 pp = np;
00166 np = np->next;
00167 }
00168 *cp = '\0';
00169 return 0;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 static int
00179 bp_neighbors(struct as_coord c, struct as_coord *cp, void *pp)
00180 {
00181 struct sctstr *sectp = (void *)empfile[EF_SECTOR].cache;
00182 struct bestp *bp = pp;
00183 coord x, y;
00184 coord nx, ny;
00185 int n = 0, q;
00186 struct sctstr *sp, *from, **ssp;
00187
00188 struct sctstr *tsp[] = { 0, 0, 0, 0, 0, 0 };
00189 int sx, sy, offset;
00190
00191 x = c.x;
00192 y = c.y;
00193 sx = XNORM(x);
00194 sy = YNORM(y);
00195 offset = XYOFFSET(sx, sy);
00196 from = §p[offset];
00197
00198 if (neighsects == NULL)
00199 ssp = (struct sctstr **)&tsp[0];
00200 else
00201 ssp = (struct sctstr **)&neighsects[offset * 6];
00202 for (q = 1; q <= 6; q++, ssp++) {
00203 if (*ssp == NULL) {
00204
00205 nx = x + diroff[q][0];
00206 ny = y + diroff[q][1];
00207 sx = XNORM(nx);
00208 sy = YNORM(ny);
00209 offset = XYOFFSET(sx, sy);
00210 sp = §p[offset];
00211 *ssp = sp;
00212 } else {
00213 sp = *ssp;
00214 sx = XNORM(sp->sct_x);
00215 sy = YNORM(sp->sct_y);
00216 }
00217
00218
00219 if (dchr[sp->sct_type].d_mob0 < 0)
00220 continue;
00221 if (bp->bp_mobtype == MOB_RAIL
00222 && (!intrchr[INT_RAIL].in_enable || sp->sct_rail == 0))
00223 continue;
00224 if (sp->sct_own != from->sct_own)
00225 continue;
00226 cp[n].x = sx;
00227 cp[n].y = sy;
00228 n++;
00229 }
00230 return n;
00231 }
00232
00233
00234
00235
00236
00237 static double
00238 bp_lbcost(struct as_coord from, struct as_coord to, void *pp)
00239 {
00240 struct sctstr *sectp = (void *)empfile[EF_SECTOR].cache;
00241 struct bestp *bp = pp;
00242 int x, y, sx, sy, offset;
00243
00244 x = to.x;
00245 y = to.y;
00246 sx = XNORM(x);
00247 sy = YNORM(y);
00248 offset = XYOFFSET(sx, sy);
00249 return sector_mcost(§p[offset], bp->bp_mobtype);
00250 }
00251
00252
00253
00254
00255 static double
00256 bp_realcost(struct as_coord from, struct as_coord to, void *pp)
00257 {
00258 return bp_lbcost(from, to, pp);
00259 }
00260
00261
00262
00263
00264
00265
00266 static double
00267 bp_seccost(struct as_coord from, struct as_coord to, void *pp)
00268 {
00269 return mapdist((coord)from.x, (coord)from.y,
00270 (coord)to.x, (coord)to.y);
00271 }
00272
00273
00274
00275
00276 static int
00277 bp_coord_hash(struct as_coord c)
00278 {
00279 return ((abs(c.x) + 1) << 3) ^ abs(c.y);
00280 }
00281
00282 void
00283 bp_enable_cachepath(void)
00284 {
00285 as_enable_cachepath();
00286 }
00287
00288 void
00289 bp_disable_cachepath(void)
00290 {
00291 as_disable_cachepath();
00292 }
00293
00294 void
00295 bp_clear_cachepath(void)
00296 {
00297 as_clear_cachepath();
00298 }
00299
00300 double
00301 pathcost(struct sctstr *start, char *path, int mob_type)
00302 {
00303 struct sctstr *sectp = (void *)empfile[EF_SECTOR].cache;
00304 unsigned i;
00305 int o;
00306 int cx, cy;
00307 double cost = 0.0;
00308 struct sctstr *sp;
00309 int sx, sy, offset;
00310
00311 cx = start->sct_x;
00312 cy = start->sct_y;
00313
00314 while (*path) {
00315 if (*path == 'h') {
00316 path++;
00317 continue;
00318 }
00319 i = *path - 'a';
00320 if (CANT_HAPPEN(i >= sizeof(dirindex) / sizeof(*dirindex)))
00321 break;
00322 o = dirindex[i];
00323 if (CANT_HAPPEN(o < 0))
00324 break;
00325 cx += diroff[o][0];
00326 cy += diroff[o][1];
00327 sx = XNORM(cx);
00328 sy = YNORM(cy);
00329 offset = XYOFFSET(sx, sy);
00330 sp = §p[offset];
00331 cost += sector_mcost(sp, mob_type);
00332 path++;
00333 }
00334
00335 return cost;
00336 }
00337
00338 char *
00339 BestDistPath(char *path,
00340 struct sctstr *from,
00341 struct sctstr *to, double *cost)
00342 {
00343 return BestLandPath(path, from, to, cost, MOB_MOVE);
00344 }
00345
00346 char *
00347 BestLandPath(char *path,
00348 struct sctstr *from,
00349 struct sctstr *to, double *cost, int mob_type)
00350 {
00351 int length;
00352
00353 *path = 0;
00354 *cost = 0.0;
00355 if (best_path(from, to, path, mob_type) < 0)
00356 return NULL;
00357 *cost = pathcost(from, path, mob_type);
00358 length = strlen(path);
00359 path[length] = 'h';
00360 path[length + 1] = '\0';
00361 return path;
00362 }
00363
00364 char *
00365 BestShipPath(char *path, int fx, int fy, int tx, int ty, int owner)
00366 {
00367 char *map;
00368
00369 map = ef_ptr(EF_BMAP, owner);
00370 if (!map)
00371 return NULL;
00372 return bestownedpath(path, map, fx, fy, tx, ty, owner);
00373 }
00374
00375 char *
00376 BestAirPath(char *path, int fx, int fy, int tx, int ty)
00377 {
00378 return bestownedpath(path, NULL, fx, fy, tx, ty, -1);
00379 }