]> git.pond.sub.org Git - empserver/blobdiff - src/lib/common/maps.c
Update copyright notice.
[empserver] / src / lib / common / maps.c
index 3ae28c2778909d043dd4b59134da3f5e796d9f16..9b028e903f9a97e0d0040aa49ae69ffe89925898 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -19,9 +19,9 @@
  *
  *  ---
  *
- *  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.
  *
  *  ---
  *
  *     Steve McClure, 1998
  */
 
+#include <config.h>
+
+#include <ctype.h>
+#include "com.h"
+#include "empobj.h"
+#include "file.h"
+#include "land.h"
+#include "map.h"
 #include "misc.h"
+#include "nat.h"
+#include "nsc.h"
+#include "nuke.h"
+#include "optlist.h"
+#include "plane.h"
 #include "player.h"
+#include "prototypes.h"
 #include "sect.h"
-#include "xy.h"
-#include "nsc.h"
-#include "file.h"
-#include "nat.h"
-#include "map.h"
 #include "ship.h"
-#include "land.h"
-#include "plane.h"
-#include "common.h"
-#include "gen.h"
-#include "subs.h"
-#include "optlist.h"
+#include "xy.h"
 
 static int bmnxtsct(struct nstr_sect *);
-static s_char map_char(u_char type, natid own, int owner_or_god);
+static char map_char(unsigned char type, natid own, int owner_or_god);
+
+int
+do_map(int bmap, int unit_type, char *arg, char *map_flags_arg)
+{
+    struct nstr_sect ns;
+    char origin = '\0';
+    char *b;
+    int map_flags = 0;
+
+    if (!snxtsct(&ns, arg)) {
+       if (unit_map(unit_type, atoi(arg), &ns, &origin))
+           return RET_FAIL;
+    }
+    for (b = map_flags_arg; b && *b; b++) {
+       switch (*b) {
+       case 's':
+       case 'S':
+           map_flags |= MAP_SHIP;
+           break;
+       case 'l':
+       case 'L':
+           map_flags |= MAP_LAND;
+           break;
+       case 'p':
+       case 'P':
+           map_flags |= MAP_PLANE;
+           break;
+       case 'n':
+       case 'N':
+           map_flags |= MAP_NUKE;
+           break;
+       case 'h':
+       case 'H':
+           map_flags |= MAP_HIGH;
+           break;
+       case '*':
+           map_flags |= MAP_ALL;
+           break;
+       case 't':
+           if (bmap != 'b')
+               goto bad_flag;
+           bmap = 't';
+           *(b + 1) = 0;
+           break;
+       case 'r':
+           if (bmap != 'b')
+               goto bad_flag;
+           bmap = 'r';
+           *(b + 1) = 0;
+           break;
+       default:
+       bad_flag:
+           pr("Bad flag %c!\n", *b);
+           break;
+       }
+    }
+    return draw_map(bmap, origin, map_flags, &ns);
+}
 
 int
-draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp,
-        int country)
+draw_map(int bmap, char origin, int map_flags, struct nstr_sect *nsp)
 {
     struct natstr *np;
     struct range range;
     struct nstr_item ni;
-    struct shpstr ship;
-    struct lndstr land;
-    struct plnstr plane;
+    union empobj_storage unit;
     coord x, y;
     int i;
     /* Note this is not re-entrant anyway, so we keep the buffers
        around */
-    static u_char *bitmap = (u_char *)0;
-    static s_char *wmapbuf = (s_char *)0;
-    static s_char **wmap = (s_char **)0;
+    static unsigned char *bitmap = NULL;
+    static char *wmapbuf = NULL;
+    static char **wmap = NULL;
+    static int ef_mappable[] = { EF_PLANE, EF_SHIP, EF_LAND, EF_NUKE, EF_BAD };
+    static int ef_unit_map[] = { MAP_PLANE, MAP_SHIP, MAP_LAND, MAP_NUKE };
+    char *name;
 
     if (!wmapbuf)
-       wmapbuf =
-           (s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char));
+       wmapbuf = malloc(WORLD_Y * MAPWIDTH(1));
     if (!wmap) {
-       wmap = (s_char **)malloc(WORLD_Y * sizeof(s_char *));
+       wmap = malloc(WORLD_Y * sizeof(char *));
        if (wmap && wmapbuf) {
            for (i = 0; i < WORLD_Y; i++)
                wmap[i] = &wmapbuf[MAPWIDTH(1) * i];
        } else if (wmap) {
-           free((s_char *)wmap);
-           wmap = (s_char **)0;
+           free(wmap);
+           wmap = NULL;
        }
     }
     if (!bitmap)
-       bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8);
+       bitmap = malloc((WORLD_X * WORLD_Y) / 8);
     if (!wmapbuf || !wmap || !bitmap) {
        pr("Memory error, tell the deity.\n");
        logerror("malloc failed in draw_map\n");
        return RET_FAIL;
     }
 
-    if (bmap == EF_MAP + EF_BMAP) {
+    if (bmap == 'r') {
        if (!confirm("Are you sure you want to revert your bmap? "))
            return RET_OK;
     }
@@ -99,28 +160,32 @@ draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp,
                 player->command->c_form);
        player->command->c_flags |= C_MOD;
     }
-    np = getnatp(country);
+    np = getnatp(player->cnum);
     /* zap any conditionals */
     nsp->ncond = 0;
     xyrelrange(np, &nsp->range, &range);
     border(&range, "     ", "");
-    blankfill((s_char *)wmapbuf, &nsp->range, 1);
+    blankfill(wmapbuf, &nsp->range, 1);
     if (bmap) {
        int c;
        switch (bmap) {
-       case EF_BMAP:
+       default:
+           CANT_REACH();
+           bmap = 'b';
+           /* fall through */
+       case 'b':
            while (bmnxtsct(nsp) && !player->aborted) {
                if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
                    wmap[nsp->dy][nsp->dx] = c;
            }
            break;
-       case EF_MAP:
+       case 't':
            while (bmnxtsct(nsp) && !player->aborted) {
                if (0 != (c = player->map[sctoff(nsp->x, nsp->y)]))
                    wmap[nsp->dy][nsp->dx] = c;
            }
            break;
-       case (EF_MAP + EF_BMAP):
+       case 'r':
            while (bmnxtsct(nsp) && !player->aborted) {
                player->bmap[sctoff(nsp->x, nsp->y)] =
                    player->map[sctoff(nsp->x, nsp->y)];
@@ -129,44 +194,37 @@ draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp,
            }
            ef_write(EF_BMAP, player->cnum, player->bmap);
            break;
-       case EF_NMAP:
+       case 'n':
            {
                struct sctstr sect;
 
-               if ((!player->god || country)) {
+               if (!player->god) {
                    memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
-                   bitinit2(nsp, bitmap, country);
+                   bitinit2(nsp, bitmap, player->cnum);
                }
                while (nxtsct(nsp, &sect) && !player->aborted) {
-                   if ((!player->god || country) &&
-                       !emp_getbit(nsp->x, nsp->y, bitmap)) {
-                       if (!player->god)
-                           continue;
-                   }
+                   if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap))
+                       continue;
                    wmap[nsp->dy][nsp->dx]
                        = map_char(sect.sct_newtype, sect.sct_own,
-                                  sect.sct_own == country || player->god);
+                                  player->owner);
                }
                break;
            }
        }
     } else {
        struct sctstr sect;
-       s_char mapch;
+       char mapch;
        int changed = 0;
 
-       if ((!player->god || country)) {
+       if (!player->god) {
            memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
-           bitinit2(nsp, bitmap, country);
+           bitinit2(nsp, bitmap, player->cnum);
        }
        while (nxtsct(nsp, &sect) && !player->aborted) {
-           if ((!player->god || country)
-               && !emp_getbit(nsp->x, nsp->y, bitmap)) {
-               if (!player->god)
-                   continue;
-           }
-           mapch = map_char(sect.sct_type, sect.sct_own,
-                            sect.sct_own == country || player->god);
+           if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap))
+               continue;
+           mapch = map_char(sect.sct_type, sect.sct_own, player->owner);
            wmap[nsp->dy][nsp->dx] = mapch;
            changed |= map_set(player->cnum, nsp->x, nsp->y, mapch, 0);
        }
@@ -175,69 +233,46 @@ draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp,
     }
     if (player->aborted)
        return RET_OK;
-    if (map_flags & MAP_PLANE) {
-       snxtitem_all(&ni, EF_PLANE);
-       while (nxtitem(&ni, &plane)) {
-           if (plane.pln_own == 0)
-               continue;
-           if (plane.pln_own != player->cnum && !player->god)
-               continue;
-           if (!xyinrange(plane.pln_x, plane.pln_y, &nsp->range))
-               continue;
 
-           x = xnorm(plane.pln_x - nsp->range.lx);
-           y = ynorm(plane.pln_y - nsp->range.ly);
-           wmap[y][x] = (*plchr[(int)plane.pln_type].pl_name) & ~0x20;
-       }
-    }
-    if (map_flags & MAP_SHIP) {
-       snxtitem_all(&ni, EF_SHIP);
-       while (nxtitem(&ni, &ship)) {
-           if (ship.shp_own == 0)
-               continue;
-           if (ship.shp_own != player->cnum && !player->god)
-               continue;
-           if (!xyinrange(ship.shp_x, ship.shp_y, &nsp->range))
-               continue;
+    i = 0;
+    while (ef_mappable[i] != EF_BAD) {
+       if (map_flags & ef_unit_map[i]) {
+           snxtitem_all(&ni, ef_mappable[i]);
+           while (nxtitem(&ni, &unit)) {
+               if (unit.gen.own == 0)
+                   continue;
+               if (unit.gen.own != player->cnum && !player->god)
+                   continue;
+               if (!xyinrange(unit.gen.x, unit.gen.y, &nsp->range))
+                   continue;
 
-           x = xnorm(ship.shp_x - nsp->range.lx);
-           y = ynorm(ship.shp_y - nsp->range.ly);
-           wmap[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
-       }
-    }
-    if (map_flags & MAP_LAND) {
-       snxtitem_all(&ni, EF_LAND);
-       while (nxtitem(&ni, &land)) {
-           if (land.lnd_own == 0)
-               continue;
-           if (land.lnd_own != player->cnum && !player->god)
-               continue;
-           if (!xyinrange(land.lnd_x, land.lnd_y, &nsp->range))
-               continue;
+               x = xnorm(unit.gen.x - nsp->range.lx);
+               y = ynorm(unit.gen.y - nsp->range.ly);
 
-           x = xnorm(land.lnd_x - nsp->range.lx);
-           y = ynorm(land.lnd_y - nsp->range.ly);
-           wmap[y][x] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
+               if (ef_mappable[i] == EF_NUKE)
+                   wmap[y][x] = 'N';
+               else {
+                   if ((name = emp_obj_chr_name(&unit.gen)) == NULL)
+                       return RET_FAIL;
+                   wmap[y][x] = *name & ~0x20;
+               }
+           }
        }
+       i++;
     }
     if (map_flags & MAP_HIGH) {
-       s_char *ptr;
        struct sctstr sect;
 
        snxtsct_rewind(nsp);
-       if ((!player->god || country)) {
+       if (!player->god) {
            memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
-           bitinit2(nsp, bitmap, country);
+           bitinit2(nsp, bitmap, player->cnum);
        }
        while (nxtsct(nsp, &sect) && !player->aborted) {
-           if ((!player->god || country) &&
-               !emp_getbit(nsp->x, nsp->y, bitmap)) {
-               if (!player->god)
-                   continue;
-           }
-           ptr = &wmap[nsp->dy][nsp->dx];
+           if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap))
+               continue;
            if (sect.sct_own == player->cnum)
-                *ptr |= 0x80;
+                wmap[nsp->dy][nsp->dx] |= 0x80;
        }
     }
     if (origin)
@@ -293,13 +328,11 @@ bmnxtsct(struct nstr_sect *np)
  * Return character to use in maps for sector type TYPE owned by OWN.
  * If OWNER_OR_GOD, the map is for the sector's owner or a deity.
  */
-static s_char
-map_char(u_char type, natid own, int owner_or_god)
+static char
+map_char(unsigned char type, natid own, int owner_or_god)
 {
-    if (type > SCT_MAXDEF) {
-       logerror("bad sector type %d\n", type);
+    if (CANT_HAPPEN(type > SCT_TYPE_MAX || !dchr[type].d_mnem))
        return '?';
-    }
     if (owner_or_god
        || type == SCT_WATER || type == SCT_MOUNT || type == SCT_WASTE
        || (!own && (type == SCT_RURAL || type == SCT_PLAINS)))
@@ -308,54 +341,65 @@ map_char(u_char type, natid own, int owner_or_god)
 }
 
 int
-unit_map(int unit_type, int i, struct nstr_sect *nsp, s_char *originp)
+unit_map(int unit_type, int uid, struct nstr_sect *nsp, char *originp)
 {
-    struct shpstr origs;
-    struct lndstr origl;
-    struct plnstr origp;
-    s_char what[64];
-    struct natstr *np;
+    struct empobj *gp;
+    struct range range;
+    char *name;
 
-    np = getnatp(player->cnum);
-    if (unit_type == EF_LAND) {
-       if (!getland(i, &origl) ||
-           (origl.lnd_own != player->cnum && !player->god) ||
-           (origl.lnd_own == 0))
-           return RET_FAIL;
-       sprintf(what, "%d:%d,%d:%d", xrel(np, origl.lnd_x - 10),
-               xrel(np, origl.lnd_x + 10),
-               yrel(np, origl.lnd_y - 5), yrel(np, origl.lnd_y + 5));
-       *originp = *lchr[(int)origl.lnd_type].l_name;
-    } else if (unit_type == EF_PLANE) {
-       if (!getplane(i, &origp) ||
-           (origp.pln_own != player->cnum && !player->god) ||
-           (origp.pln_own == 0))
-           return RET_FAIL;
-       sprintf(what, "%d:%d,%d:%d", xrel(np, origp.pln_x - 10),
-               xrel(np, origp.pln_x + 10),
-               yrel(np, origp.pln_y - 5), yrel(np, origp.pln_y + 5));
-       *originp = *plchr[(int)origp.pln_type].pl_name;
-    } else {
-       if (!getship(i, &origs) ||
-           (origs.shp_own != player->cnum && !player->god) ||
-           (origs.shp_own == 0))
+    gp = get_empobjp(unit_type, uid);
+    if (!gp || (gp->own != player->cnum && !player->god) || gp->own == 0)
+       return RET_FAIL;
+
+    if (unit_type == EF_NUKE)
+       *originp = 'n';
+    else {
+       if ((name = emp_obj_chr_name(gp)) == NULL)
            return RET_FAIL;
-       sprintf(what, "%d:%d,%d:%d", xrel(np, origs.shp_x - 10),
-               xrel(np, origs.shp_x + 10),
-               yrel(np, origs.shp_y - 5), yrel(np, origs.shp_y + 5));
-       unit_type = EF_SHIP;
-       *originp = *mchr[(int)origs.shp_type].m_name;
+       *originp = *name;
     }
-    if (!snxtsct(nsp, what))
-       return RET_FAIL;
+
+    range.lx = xnorm(gp->x - 10);
+    range.hx = xnorm(gp->x + 11);
+    range.ly = ynorm(gp->y - 5);
+    range.hy = ynorm(gp->y + 6);
+    xysize_range(&range);
+    snxtsct_area(nsp, &range);
     return RET_OK;
 }
 
+int
+display_region_map(int bmap, int unit_type, coord curx, coord cury,
+                  char *arg)
+{
+    char coordinates[80];
+    char *map_flag_arg;
+
+    if (!arg || !*arg) {
+       struct natstr *np;
+
+       np = getnatp(player->cnum);
+       sprintf(coordinates, "%d:%d,%d:%d",
+           xrel(np, curx - 10), xrel(np, curx + 11),
+           yrel(np, cury - 5), yrel(np, cury + 6));
+       arg = coordinates;
+       map_flag_arg = NULL;
+    } else {
+       map_flag_arg = strchr(arg, ' ');
+       if (map_flag_arg != NULL) {
+           *map_flag_arg++  = '\0';
+           while (isspace(*map_flag_arg)) map_flag_arg++;
+       }
+    }
+    player->condarg = NULL;
+    return do_map(bmap, unit_type, arg, map_flag_arg);
+}
+
 int
 bmaps_intersect(natid a, natid b)
 {
-    s_char *mapa = ef_ptr(EF_MAP, a);
-    s_char *mapb = ef_ptr(EF_MAP, b);
+    char *mapa = ef_ptr(EF_MAP, a);
+    char *mapb = ef_ptr(EF_MAP, b);
     int i;
 
     for (i = 0; i < WORLD_X * WORLD_Y / 2; ++i, ++mapa, ++mapb)
@@ -367,16 +411,16 @@ bmaps_intersect(natid a, natid b)
 /* Note that this requires that the BMAP is mapped into memory */
 
 int
-share_bmap(natid from, natid to, struct nstr_sect *ns, s_char des,
-          s_char *from_name)
+share_bmap(natid from, natid to, struct nstr_sect *ns, char des,
+          char *from_name)
 {
-    s_char *from_bmap = ef_ptr(EF_BMAP, from);
-    s_char *to_bmap = ef_ptr(EF_BMAP, to);
+    char *from_bmap = ef_ptr(EF_BMAP, from);
+    char *to_bmap = ef_ptr(EF_BMAP, to);
     int n = 0;
     struct sctstr sect;
-    s_char fromdes;
-    s_char todes;
-    s_char from_des = *from_name;
+    char fromdes;
+    char todes;
+    char from_des = *from_name;
 
     if (isalpha(from_des))
        from_des &= ~0x20;