]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/move.c
Use the new path finder for land paths, drop old A*
[empserver] / src / lib / subs / move.c
index d20175e7443819fe27d7bd5eafe8bd91d914907a..57abc754388357f26a291ef6dff92d78ce9694fe 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2011, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  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 2 of the License, or
+ *  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,
  *  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, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  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.
  *
  *  ---
  *
  *  move.c: Move something somewhere.
- * 
+ *
  *  Known contributors to this file:
- *     
+ *
  */
 
-#include "misc.h"
-#include "player.h"
-#include "var.h"
-#include "sect.h"
-#include "item.h"
+#include <config.h>
+
+#include <ctype.h>
+#include "damage.h"
 #include "file.h"
-#include "deity.h"
-#include "xy.h"
-#include "path.h"
-#include "nat.h"
 #include "map.h"
-#include "nsc.h"
-#include "damage.h"
+#include "path.h"
+#include "player.h"
 #include "prototypes.h"
+#include "sect.h"
 
-static int move_map(s_char *what, coord curx, coord cury, s_char *arg);
+static int move_map(coord curx, coord cury, char *arg);
 
 int
-move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
-           double mobility, double weight, s_char *path,
-           int (*map) (s_char *, coord, coord, s_char *), int exploring,
+move_ground(struct sctstr *start, struct sctstr *end,
+           double weight, char *path,
+           int (*map)(coord, coord, char *), int exploring,
            int *dam)
-
-
-                               /* RESULT */
 {
     struct sctstr sect, ending_sect;
     struct sctstr next, dsect;
-    int vec[I_MAX + 1];
     coord curx, cury, oldx, oldy;
     coord tmpx, tmpy;
     coord dx, dy;
-    s_char *movstr, *BestLandPath(s_char *, struct sctstr *,
-                                 struct sctstr *, double *, int);
+    char *movstr;
     double sect_mcost;
     double total_mcost;
     double mv_cost;
+    double mobility = start->sct_mobil;
     int dir;
     int intcost;
-    int takedam = (*dam), out = 0;
-    s_char bpath[512];
-    s_char buf2[512];
-    s_char prompt[128];
-    s_char buf[1024];
+    int takedam = *dam;
+    int out = 0;
+    char bpath[1024];
+    char buf2[1024];
+    char prompt[128];
+    char buf[1024];
 
     *end = *start;
     if (mobility <= 0.0)
@@ -87,12 +79,11 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
            return -1;
        }
        pr("Looking for best path to %s\n", path);
-       path =
-           BestLandPath(buf2, start, &ending_sect, &total_mcost,
-                        MOB_ROAD);
-       if (exploring && (path != (s_char *)0)) /* take off the 'h' */
-           *(path + strlen(path) - 1) = '\0';
-       if (path == (s_char *)0)
+       path = BestLandPath(buf2, start, &ending_sect, &total_mcost,
+                           MOB_MOVE);
+       if (exploring && path)  /* take off the 'h' */
+           path[strlen(path) - 1] = '\0';
+       if (!path)
            pr("No owned path exists!\n");
        else {
            pr("Using best path '%s', movement cost %1.3f\n",
@@ -106,25 +97,21 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
        }
     }
     movstr = path;
-    tmpx = start->sct_x;
-    curx = tmpx;
-    tmpy = start->sct_y;
-    cury = tmpy;
+    curx = start->sct_x;
+    cury = start->sct_y;
     total_mcost = 0.0;
     if (getsect(curx, cury, &sect) < 0) {
        logerror("move_path: getsect %d,%d", curx, cury);
        return -1;
     }
     for (;;) {
-       tmpx = curx;
-       tmpy = cury;
        oldx = curx;
        oldy = cury;
-       if (movstr == 0 || *movstr == 0) {
+       if (!movstr || *movstr == 0) {
            if (exploring) {
-               map(what, curx, cury, (s_char *)0);
+               map(curx, cury, NULL);
            } else {
-               move_map(what, curx, cury, (s_char *)0);
+               move_map(curx, cury, NULL);
            }
            sprintf(prompt, "<%.1f: %c %s> ", mobility,
                    dchr[sect.sct_type].d_mnem,
@@ -133,21 +120,20 @@ move_ground(s_char *what, 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);
+               movstr = BestLandPath(buf2, &sect, &dsect, &mv_cost,
+                                     MOB_MOVE);
            } else {
                pr("Invalid destination sector!\n");
-               movstr = (s_char *)0;
+               movstr = NULL;
            }
 
-           if (movstr == (s_char *)0) {
+           if (movstr == NULL) {
                pr("Can't get to %s from here!\n",
                   xyas(dx, dy, player->cnum));
-               movstr = (s_char *)0;
            } else {
                if ((mv_cost * weight) > mobility) {
                    pr("Not enough mobility to go all the way. Nothing moved.\n");
-                   movstr = (s_char *)0;
+                   movstr = NULL;
                } else {
                    pr("Using best path '%s', movement cost %1.3f\n",
                       movstr, mv_cost);
@@ -156,26 +142,28 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
                }
            }
        }
-       if (movstr == 0 || *movstr == 0)
-           movstr = dirch;
+       if (!movstr || *movstr == 0) {
+           buf2[0] = dirch[DIR_STOP];
+           buf2[1] = 0;
+           movstr = buf2;
+       }
        if ((dir = chkdir(*movstr, DIR_STOP, DIR_MAP)) < 0) {
            pr("\"%c\" is not legal...", *movstr);
            direrr("'%c' to stop ", "'%c' to view ", "& '%c' to map\n");
            *movstr = 0;
            continue;
        }
-       movstr++;
+       do  movstr++; while (isspace(*movstr));
        if (dir == DIR_MAP) {
            if (!exploring)
-               map(what, curx, cury, movstr + 1);
+               map(curx, cury, movstr);
            *movstr = 0;
            continue;
        } else if (dir == DIR_STOP)
            break;
        else if (dir == DIR_VIEW) {
            pr("%d%% %s with %d civilians.\n", sect.sct_effic,
-              dchr[sect.sct_type].d_name,
-              getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR));
+              dchr[sect.sct_type].d_name, sect.sct_item[I_CIVIL]);
            continue;
        }
        /*
@@ -183,8 +171,8 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
         * next sector.  Mobility, terrain,
         * or ownership may prevent us.
         */
-       tmpx += diroff[dir][0];
-       tmpy += diroff[dir][1];
+       tmpx = curx + diroff[dir][0];
+       tmpy = cury + diroff[dir][1];
        if (getsect(tmpx, tmpy, &next) < 0) {
            pr("You can't go there...\n");
            *movstr = 0;
@@ -194,17 +182,14 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
            if ((next.sct_type == SCT_SANCT) &&
                (next.sct_own != player->cnum)) {
                pr("Converts, huh?\n");
-               *end = next;
-               intcost = (int)total_mcost;
-               if (chance(total_mcost - intcost))
-                   intcost++;
-               return intcost;
+               *movstr = 0;
+               continue;
            }
-           getvec(VT_ITEM, vec, (s_char *)&next, EF_SECTOR);
-           sect_mcost = sector_mcost(&next, MOB_ROAD);
-           if ((!player->owner && (!exploring ||
-                                   (vec[I_MILIT] || vec[I_CIVIL]))) ||
-               sect_mcost == -1.0) {
+           sect_mcost = sector_mcost(&next, MOB_MOVE);
+           if ((!player->owner && (!exploring
+                                   || next.sct_item[I_MILIT]
+                                   || next.sct_item[I_CIVIL]))
+               || sect_mcost == -1.0) {
                /* already-owned, or prohibited terrain */
                pr("You can't go there...\n");
                *movstr = 0;
@@ -220,8 +205,8 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
            mobility -= sect_mcost;
            total_mcost += sect_mcost;
        }
-       curx = tmpx;
-       cury = tmpy;
+       curx = next.sct_x;
+       cury = next.sct_y;
        if (cury != start->sct_y)
            out = 1;
        if (curx != start->sct_x)
@@ -238,8 +223,8 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
         */
        if (takedam && chance(weight / 100.0) &&
            ((curx != oldx) || (cury != oldy)))
-           (*dam) +=
-               ground_interdict(curx, cury, player->cnum, "commodities");
+           *dam += ground_interdict(curx, cury, player->cnum,
+                                    "commodities");
        if (*dam >= 100)
            break;
     }
@@ -259,32 +244,18 @@ move_ground(s_char *what, struct sctstr *start, struct sctstr *end,
 
 /*ARGSUSED*/
 static int
-move_map(s_char *what, coord curx, coord cury, s_char *arg)
+move_map(coord curx, coord cury, char *arg)
 {
     struct nstr_sect ns;
-    struct natstr *np;
     struct sctstr sect;
-    coord rel_x, rel_y;
-    s_char range[128];
-    s_char view[7];
+    char view[7];
     int i;
-    int vec[I_MAX + 1];
     int changed = 0;
 
-    np = getnatp(player->cnum);
-    rel_x = xrel(np, curx);
-    rel_y = yrel(np, cury);
-    sprintf(range, "%d:%d,%d:%d", rel_x - 2, rel_x + 2, rel_y - 1,
-           rel_y + 1);
-    player->condarg = 0;
-    /* This is necessary, otherwise move_map would attempt to pay */
-    /* attention to the conditional arguments left behind by such */
-    /* a command as "tran p -1,-1 ?eff=100".. It'd then only see  */
-    /* 100% efficienct sects, and get all screwed up         --ts */
-    if (!snxtsct(&ns, range))
-       return RET_FAIL;
+    snxtsct_dist(&ns, curx, cury, 1);
     i = 0;
     while (i < 7 && nxtsct(&ns, &sect)) {
+       /* Nasty: this relies on the iteration order */
        view[i] = dchr[sect.sct_type].d_mnem;
        switch (sect.sct_type) {
        case SCT_WATER:
@@ -305,13 +276,13 @@ move_map(s_char *what, coord curx, coord cury, s_char *arg)
        writemap(player->cnum);
     if (!getsect(curx, cury, &sect))
        return RET_FAIL;
-    getvec(VT_ITEM, vec, (s_char *)&sect, EF_SECTOR);
     pr("    %c %c      eff   mob   civ  mil   uw food  work  avail\n",
        view[0], view[1]);
     pr("   %c %c %c     %3d   %3d  %4d %4d %4d %4d   %3d   %3d\n",
        view[2], view[3], view[4],
-       sect.sct_effic, sect.sct_mobil, vec[I_CIVIL], vec[I_MILIT],
-       vec[I_UW], vec[I_FOOD], sect.sct_work, sect.sct_avail);
+       sect.sct_effic, sect.sct_mobil,
+       sect.sct_item[I_CIVIL], sect.sct_item[I_MILIT], sect.sct_item[I_UW],
+       sect.sct_item[I_FOOD], sect.sct_work, sect.sct_avail);
     pr("    %c %c\n", view[5], view[6]);
     return RET_OK;
 }
@@ -320,29 +291,15 @@ int
 fly_map(coord curx, coord cury)
 {
     struct nstr_sect ns;
-    struct natstr *np;
     struct sctstr sect;
-    coord rel_x, rel_y;
-    s_char view[7];
+    char view[7];
     int i;
-    s_char range[128];
 
-    np = getnatp(player->cnum);
-    rel_x = xrel(np, curx);
-    rel_y = yrel(np, cury);
-    sprintf(range, "%d:%d,%d:%d", rel_x - 2, rel_x + 2, rel_y - 1,
-           rel_y + 1);
-    player->condarg = 0;
-    /* This is necessary, otherwise move_map would attempt to pay */
-    /* attention to the conditional arguments left behind by such */
-    /* a command as "tran p -1,-1 ?eff=100".. It'd then only see  */
-    /* 100% efficienct sects, and get all screwed up         --ts */
-
-    if (!snxtsct(&ns, range))
-       return RET_FAIL;
+    snxtsct_dist(&ns, curx, cury, 1);
     i = 0;
     while (i < 7 && nxtsct(&ns, &sect)) {
-       if (!(view[i] = player->bmap[sctoff(ns.x, ns.y)]))
+       /* Nasty: this relies on the iteration order */
+       if (!(view[i] = player->bmap[sect.sct_uid]))
            view[i] = ' ';
        i++;
     }
@@ -357,20 +314,17 @@ int
 check_lmines(coord x, coord y, double weight)
 {
     struct sctstr sect;
-    int mines;
     int dam = 0;
 
     getsect(x, y, &sect);
-    mines = getvar(V_MINE, (s_char *)&sect, EF_SECTOR);
-    if (mines > 0 &&
+    if (SCT_LANDMINES(&sect) > 0 &&
        sect.sct_oldown != player->cnum &&
-       chance(DMINE_LHITCHANCE(mines)) && chance(weight / 100.0)) {
+       chance(DMINE_LHITCHANCE(sect.sct_mines)) && chance(weight / 100.0)) {
        pr_beep();
        pr("Blammo! Landmines detected! in %s  ",
           xyas(sect.sct_x, sect.sct_y, player->cnum));
        dam = roll(20);
-       --mines;
-       putvar(V_MINE, mines, (s_char *)&sect, EF_SECTOR);
+       --sect.sct_mines;
        putsect(&sect);
        pr("%d damage sustained.\n", dam);
     }