]> git.pond.sub.org Git - empserver/blobdiff - src/lib/commands/retr.c
Update copyright notice
[empserver] / src / lib / commands / retr.c
index 0812141b5f907b77af060b3b14b3a9b7ae9588b5..39c14d65194f4c1abe4bd254805d248827129518 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-2015, 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.
  *
  *  ---
  *
- *  retr.c: Set retreat conditionals for ships
- * 
+ *  retr.c: Set retreat conditionals for ships and land units
+ *
  *  Known contributors to this file:
  *     Ken Stevens, 1995
  *     Steve McClure, 2000
+ *     Markus Armbruster, 2008-2014
  */
 
-#include "options.h"
-#include "misc.h"
-#include "player.h"
-#include "var.h"
-#include "xy.h"
-#include "sect.h"
-#include "retreat.h"
-#include "ship.h"
+#include <config.h>
+
+#include <ctype.h>
+#include "commands.h"
+#include "empobj.h"
 #include "land.h"
-#include "nat.h"
-#include "nsc.h"
-#include "deity.h"
-#include "file.h"
 #include "path.h"
-#include "commands.h"
+#include "retreat.h"
+#include "ship.h"
+
+/*
+ * Retreat flag characters
+ * 'X' means flag is not available
+ * Must agree with RET_ defines.
+ */
+static char shp_rflagsc[] = "Xitshbdu";
+static char lnd_rflagsc[] = "XiXXhbXX";
+
+static int retreat(int);
 
 int
 retr(void)
 {
-    s_char *pq, *fl;
-    int nships;
-    struct nstr_item ni;
-    struct shpstr ship;
-    int isfleet = 0, rflags = (-2), zero;
-    unsigned int x;
-    s_char buf1[1024];
-    s_char buf2[1024];
-
-    if (!snxtitem(&ni, EF_SHIP, player->argp[1]))
-       return RET_SYN;
-    nships = 0;
-    if (player->argp[1] != (s_char *)0)
-       if (isalpha(player->argp[1][0]))
-           isfleet = 1;
-    if (player->argp[2] != (s_char *)0)
-       pq = getstarg(player->argp[2], "Retreat path? ", buf1);
-    else
-       pq = (s_char *)0;
-
-    if (pq != (s_char *)0) {
-       fl = getstarg(player->argp[3],
-                     "Retreat conditions [i|t|s|h|b|d|u|c]? ", buf2);
-       if (!fl)
-           return RET_SYN;
-       rflags = 0 | isfleet;
-
-       for (x = 0; x < strlen(fl); x++)
-           switch (*(fl + x)) {
-           case 'I':
-           case 'i':
-               rflags |= RET_INJURED;
-               break;
-           case 'T':
-           case 't':
-               rflags |= RET_TORPED;
-               break;
-           case 'S':
-           case 's':
-               rflags |= RET_SONARED;
-               break;
-           case 'H':
-           case 'h':
-               rflags |= RET_HELPLESS;
-               break;
-           case 'B':
-           case 'b':
-               rflags |= RET_BOMBED;
-               break;
-           case 'D':
-           case 'd':
-               rflags |= RET_DCHRGED;
-               break;
-           case 'U':
-           case 'u':
-               rflags |= RET_BOARDED;
-               break;
-           case 'C':
-           case 'c':
-               rflags = -1;
-               break;
-           default:
-               pr("bad condition\n");
-           case '?':
-               pr("i\tretreat when injured\n");
-               pr("t\tretreat when torped\n");
-               pr("s\tretreat when sonared\n");
-               pr("h\tretreat when helpless\n");
-               pr("b\tretreat when bombed\n");
-               pr("d\tretreat when depth-charged\n");
-               pr("u\tretreat when boarded\n");
-           }
-       if (rflags == isfleet) {
-           pr("Must give retreat conditions!\n");
-           return RET_FAIL;
-       }
-    }
-
-    if (rflags == -1)
-       pq = (s_char *)0;
-
-    zero = (rflags == -1);
-    if (zero)
-       rflags = 0;
-
-    while (nxtitem(&ni, (s_char *)&ship)) {
-       if (!player->owner || ship.shp_own == 0)
-           continue;
-       if (ship.shp_type < 0 || ship.shp_type > shp_maxno) {
-           pr("bad ship type %d (#%d)\n", ship.shp_type, ni.cur);
-           continue;
-       }
-       if (zero)
-           bzero(ship.shp_rpath, RET_LEN);
-
-       if (pq != (s_char *)0) {
-           bzero(ship.shp_rpath, RET_LEN);
-           bcopy(pq, ship.shp_rpath, strlen(pq));
-           putship(ship.shp_uid, &ship);
-       }
-       if (rflags >= 0) {
-           ship.shp_rflags = rflags;
-           putship(ship.shp_uid, &ship);
-       }
-       if (nships++ == 0) {
-           if (player->god)
-               pr("own ");
-           pr("shp#     ship type       x,y   fl path       as flt? flags\n");
-       }
-       if (player->god)
-           pr("%3d ", ship.shp_own);
-       pr("%4d ", ni.cur);
-       pr("%-16.16s ", mchr[(int)ship.shp_type].m_name);
-       prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum);
-       pr("%1c", ship.shp_fleet);
-       pr(" %-11s", ship.shp_rpath);
-       if (ship.shp_rflags & RET_GROUP)
-           pr("Yes     ");
-       else
-           pr("        ");
-       if (ship.shp_rflags & RET_INJURED)
-           pr("I");
-       if (ship.shp_rflags & RET_TORPED)
-           pr("T");
-       if (ship.shp_rflags & RET_SONARED)
-           pr("S");
-       if (ship.shp_rflags & RET_HELPLESS)
-           pr("H");
-       if (ship.shp_rflags & RET_BOMBED)
-           pr("B");
-       if (ship.shp_rflags & RET_DCHRGED)
-           pr("D");
-       if (ship.shp_rflags & RET_BOARDED)
-           pr("U");
-       pr("\n");
-    }
-    if (nships == 0) {
-       if (player->argp[1])
-           pr("%s: No ship(s)\n", player->argp[1]);
-       else
-           pr("%s: No ship(s)\n", "");
-       return RET_FAIL;
-    } else
-       pr("%d ship%s\n", nships, splur(nships));
-    return RET_OK;
+    return retreat(EF_SHIP);
 }
 
 int
 lretr(void)
 {
-    s_char *pq, *fl;
+    return retreat(EF_LAND);
+}
+
+static int
+retreat(int type)
+{
+    char *pq, *fl;
     int nunits;
     struct nstr_item ni;
-    struct lndstr land;
-    int isarmy = 0, rflags = (-2), zero;
-    s_char buf1[1024];
-    s_char buf2[1024];
-    unsigned int x;
-
-    if (!snxtitem(&ni, EF_LAND, player->argp[1]))
+    union empobj_storage unit;
+    int rflags, ch, j;
+    unsigned i;
+    char *rflagsc, *p, *name, *rpath, *what;
+    int *rflagsp;
+    char buf1[1024];
+    char buf2[1024];
+
+    if (CANT_HAPPEN(type != EF_LAND && type != EF_SHIP))
+       type = EF_SHIP;
+    rflagsc = type == EF_SHIP ? shp_rflagsc : lnd_rflagsc;
+
+    if (!snxtitem(&ni, type, player->argp[1], NULL))
        return RET_SYN;
     nunits = 0;
-    if (player->argp[1] != (s_char *)0)
-       if (isalpha(player->argp[1][0]))
-           isarmy = 1;
-    if (player->argp[2] != (s_char *)0)
+    if (player->argp[2] != NULL) {
        pq = getstarg(player->argp[2], "Retreat path? ", buf1);
-    else
-       pq = (s_char *)0;
-    if (pq != (s_char *)0) {
-       fl = getstarg(player->argp[3], "Retreat conditions [i|h|b|c]? ",
+       for (i = 0; i < RET_LEN - 1 && pq[i]; i++) {
+           if (chkdir(pq[i], DIR_STOP, DIR_LAST) < 0) {
+               pr("'%c' is not a valid direction...\n", pq[i]);
+               direrr(NULL, NULL, NULL);
+               return RET_SYN;
+           }
+       }
+    } else
+       pq = NULL;
+
+    rflags = 0;
+    if (pq != NULL) {
+    again:
+       fl = getstarg(player->argp[3],
+                     "Retreat conditions ('?' to list available ones)? ",
                      buf2);
        if (!fl)
            return RET_SYN;
-       rflags = 0 | isarmy;
 
-       for (x = 0; x < strlen(fl); x++)
-           switch (*(fl + x)) {
-           case 'I':
-           case 'i':
-               rflags |= RET_INJURED;
-               break;
-           case 'H':
-           case 'h':
-               rflags |= RET_HELPLESS;
-               break;
-           case 'B':
-           case 'b':
-               rflags |= RET_BOMBED;
+       for (i = 0; fl[i]; i++) {
+           ch = tolower(fl[i]);
+           if (ch == 'c') {
+               *pq = 0;
                break;
-           case 'C':
-           case 'c':
-               rflags = -1;
-               break;
-           default:
-               pr("bad condition\n");
-           case '?':
-               pr("i\tretreat when injured\n");
-               pr("h\tretreat when helpless\n");
-               pr("b\tretreat when bombed\n");
            }
-       if (rflags == isarmy) {
-           pr("Must give retreat conditions!\n");
-           return RET_FAIL;
+           if (ch == '?' && !player->argp[3]) {
+               for (j = 1; rflagsc[j]; j++) {
+                   if (rflagsc[j] != 'X')
+                       pr("%c\tretreat when %s\n",
+                          rflagsc[j],
+                          symbol_by_value(1 << j, retreat_flags));
+               }
+               pr("c\tcancel retreat order\n");
+               goto again;
+           }
+           p = strchr(rflagsc, ch);
+           if (!p) {
+               pr("Bad retreat condition '%c'\n", fl[i]);
+               return RET_SYN;
+           }
+           rflags |= 1 << (p - rflagsc);
        }
+       if (*pq && !rflags)
+           return RET_SYN;
+       if (ni.sel == NS_GROUP && ni.group)
+           rflags |= RET_GROUP;
+       if (!*pq)
+           rflags = 0;
     }
 
-    if (rflags == -1)
-       pq = (s_char *)0;
-
-    zero = (rflags == -1);
-    if (zero)
-       rflags = 0;
-
-    while (nxtitem(&ni, (s_char *)&land)) {
-       if (!player->owner || land.lnd_own == 0)
-           continue;
-       if (land.lnd_type < 0 || land.lnd_type > lnd_maxno) {
-           pr("bad unit type %d (#%d)\n", land.lnd_type, ni.cur);
+    while (nxtitem(&ni, &unit)) {
+       if (!player->owner || unit.gen.own == 0)
            continue;
+       if (type == EF_SHIP) {
+           if (nunits++ == 0) {
+               if (player->god)
+                   pr("own ");
+               pr("shp#     ship type       x,y   fl path       as flt?  flags\n");
+           }
+           name = mchr[unit.ship.shp_type].m_name;
+           rpath = unit.ship.shp_rpath;
+           rflagsp = &unit.ship.shp_rflags;
+       } else {
+           if (nunits++ == 0) {
+               if (player->god)
+                   pr("own ");
+               pr("lnd#     unit type       x,y   ar path       as army? flags\n");
+           }
+           name = lchr[unit.land.lnd_type].l_name;
+           rpath = unit.land.lnd_rpath;
+           rflagsp = &unit.land.lnd_rflags;
        }
-       if (zero)
-           bzero(land.lnd_rpath, RET_LEN);
-
-       if (pq != (s_char *)0) {
-           bzero(land.lnd_rpath, RET_LEN);
-           bcopy(pq, land.lnd_rpath, strlen(pq));
-           putland(land.lnd_uid, &land);
-       }
-       if (rflags >= 0) {
-           land.lnd_rflags = rflags;
-           putland(land.lnd_uid, &land);
-       }
-
-       if (nunits++ == 0) {
-           if (player->god)
-               pr("own ");
-           pr("lnd#     unit type       x,y   ar path       as army? flags\n");
+       if (pq) {
+           strncpy(rpath, pq, RET_LEN - 1);
+           *rflagsp = rflags;
+           put_empobj(type, unit.gen.uid, &unit);
        }
        if (player->god)
-           pr("%3d ", land.lnd_own);
+           pr("%3d ", unit.gen.own);
        pr("%4d ", ni.cur);
-       pr("%-16.16s ", lchr[(int)land.lnd_type].l_name);
-       prxy("%4d,%-4d ", land.lnd_x, land.lnd_y, player->cnum);
-       pr("%1c", land.lnd_army);
-       pr(" %-11s", land.lnd_rpath);
-       if (land.lnd_rflags & RET_GROUP)
+       pr("%-16.16s ", name);
+       prxy("%4d,%-4d ", unit.gen.x, unit.gen.y);
+       pr("%1.1s", &unit.gen.group);
+       pr(" %-11s", rpath);
+       rflags = *rflagsp;
+       if (rflags & RET_GROUP)
            pr("Yes      ");
        else
            pr("         ");
-       if (land.lnd_rflags & RET_INJURED)
-           pr("I");
-       if (land.lnd_rflags & RET_TORPED)
-           pr("T");
-       if (land.lnd_rflags & RET_SONARED)
-           pr("S");
-       if (land.lnd_rflags & RET_HELPLESS)
-           pr("H");
-       if (land.lnd_rflags & RET_BOMBED)
-           pr("B");
-       if (land.lnd_rflags & RET_DCHRGED)
-           pr("D");
-       if (land.lnd_rflags & RET_BOARDED)
-           pr("U");
+       for (j = 1; rflagsc[j]; j++) {
+           if ((1 << j) & rflags) {
+               if (CANT_HAPPEN(rflagsc[j] == 'X'))
+                   continue;
+               pr("%c", rflagsc[j]);
+           }
+       }
        pr("\n");
     }
+    what = type == EF_SHIP ? "ship" : "unit";
     if (nunits == 0) {
        if (player->argp[1])
-           pr("%s: No unit(s)\n", player->argp[1]);
+           pr("%s: No %s(s)\n", player->argp[1], what);
        else
-           pr("%s: No unit(s)\n", "");
+           pr("%s: No %s(s)\n", "", what);
        return RET_FAIL;
-    }
-    pr("%d unit%s\n", nunits, splur(nunits));
+    } else
+       pr("%d %s%s\n", nunits, what, splur(nunits));
     return RET_OK;
 }