2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See files README, COPYING and CREDITS in the root of the source
23 * tree for related information and legal notices. It is expected
24 * that future projects/authors will amend these files as needed.
28 * maps.c: Map routines
30 * Known contributors to this file:
53 static int bmnxtsct(struct nstr_sect *);
54 static char map_char(unsigned char type, natid own, int owner_or_god);
57 draw_map(int bmap, char origin, int map_flags, struct nstr_sect *nsp)
68 /* Note this is not re-entrant anyway, so we keep the buffers
70 static unsigned char *bitmap = NULL;
71 static char *wmapbuf = NULL;
72 static char **wmap = NULL;
75 wmapbuf = malloc(WORLD_Y * MAPWIDTH(1));
77 wmap = malloc(WORLD_Y * sizeof(char *));
78 if (wmap && wmapbuf) {
79 for (i = 0; i < WORLD_Y; i++)
80 wmap[i] = &wmapbuf[MAPWIDTH(1) * i];
87 bitmap = malloc((WORLD_X * WORLD_Y) / 8);
88 if (!wmapbuf || !wmap || !bitmap) {
89 pr("Memory error, tell the deity.\n");
90 logerror("malloc failed in draw_map\n");
95 if (!confirm("Are you sure you want to revert your bmap? "))
98 if (!(player->command->c_flags & C_MOD)) {
99 logerror("%s command needs C_MOD flag set",
100 player->command->c_form);
101 player->command->c_flags |= C_MOD;
103 np = getnatp(player->cnum);
104 /* zap any conditionals */
106 xyrelrange(np, &nsp->range, &range);
107 border(&range, " ", "");
108 blankfill(wmapbuf, &nsp->range, 1);
117 while (bmnxtsct(nsp) && !player->aborted) {
118 if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
119 wmap[nsp->dy][nsp->dx] = c;
123 while (bmnxtsct(nsp) && !player->aborted) {
124 if (0 != (c = player->map[sctoff(nsp->x, nsp->y)]))
125 wmap[nsp->dy][nsp->dx] = c;
129 while (bmnxtsct(nsp) && !player->aborted) {
130 player->bmap[sctoff(nsp->x, nsp->y)] =
131 player->map[sctoff(nsp->x, nsp->y)];
132 if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
133 wmap[nsp->dy][nsp->dx] = c;
135 ef_write(EF_BMAP, player->cnum, player->bmap);
142 memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
143 bitinit2(nsp, bitmap, player->cnum);
145 while (nxtsct(nsp, §) && !player->aborted) {
146 if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap))
148 wmap[nsp->dy][nsp->dx]
149 = map_char(sect.sct_newtype, sect.sct_own,
161 memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
162 bitinit2(nsp, bitmap, player->cnum);
164 while (nxtsct(nsp, §) && !player->aborted) {
165 if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap))
167 mapch = map_char(sect.sct_type, sect.sct_own, player->owner);
168 wmap[nsp->dy][nsp->dx] = mapch;
169 changed |= map_set(player->cnum, nsp->x, nsp->y, mapch, 0);
172 writemap(player->cnum);
176 if (map_flags & MAP_PLANE) {
177 snxtitem_all(&ni, EF_PLANE);
178 while (nxtitem(&ni, &plane)) {
179 if (plane.pln_own == 0)
181 if (plane.pln_own != player->cnum && !player->god)
183 if (!xyinrange(plane.pln_x, plane.pln_y, &nsp->range))
186 x = xnorm(plane.pln_x - nsp->range.lx);
187 y = ynorm(plane.pln_y - nsp->range.ly);
188 wmap[y][x] = (*plchr[(int)plane.pln_type].pl_name) & ~0x20;
191 if (map_flags & MAP_SHIP) {
192 snxtitem_all(&ni, EF_SHIP);
193 while (nxtitem(&ni, &ship)) {
194 if (ship.shp_own == 0)
196 if (ship.shp_own != player->cnum && !player->god)
198 if (!xyinrange(ship.shp_x, ship.shp_y, &nsp->range))
201 x = xnorm(ship.shp_x - nsp->range.lx);
202 y = ynorm(ship.shp_y - nsp->range.ly);
203 wmap[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
206 if (map_flags & MAP_LAND) {
207 snxtitem_all(&ni, EF_LAND);
208 while (nxtitem(&ni, &land)) {
209 if (land.lnd_own == 0)
211 if (land.lnd_own != player->cnum && !player->god)
213 if (!xyinrange(land.lnd_x, land.lnd_y, &nsp->range))
216 x = xnorm(land.lnd_x - nsp->range.lx);
217 y = ynorm(land.lnd_y - nsp->range.ly);
218 wmap[y][x] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
221 if (map_flags & MAP_NUKE) {
222 snxtitem_all(&ni, EF_NUKE);
223 while (nxtitem(&ni, &nuke)) {
224 if (nuke.nuk_own == 0)
226 if (nuke.nuk_own != player->cnum && !player->god)
228 if (!xyinrange(nuke.nuk_x, nuke.nuk_y, &nsp->range))
231 x = xnorm(nuke.nuk_x - nsp->range.lx);
232 y = ynorm(nuke.nuk_y - nsp->range.ly);
236 if (map_flags & MAP_HIGH) {
242 memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
243 bitinit2(nsp, bitmap, player->cnum);
245 while (nxtsct(nsp, §) && !player->aborted) {
246 if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap))
248 ptr = &wmap[nsp->dy][nsp->dx];
249 if (sect.sct_own == player->cnum)
254 wmap[5][10] = origin & ~0x20;
255 for (y = nsp->range.ly, i = 0; i < nsp->range.height; y++, i++) {
259 wmap[i][nsp->range.width] = '\0';
260 pr("%4d %s %-4d\n", yval, wmap[i], yval);
264 border(&range, " ", "");
269 * get the next sector in the range
272 bmnxtsct(struct nstr_sect *np)
277 if (np->x >= WORLD_X)
279 if (np->dx >= np->range.width) {
281 np->x = np->range.lx;
283 if (np->dy >= np->range.height)
286 if (np->y >= WORLD_Y)
289 if ((np->y + np->x) & 01)
291 if (np->type == NS_DIST) {
292 np->curdist = mapdist(np->x, np->y, np->cx, np->cy);
293 if (np->curdist > np->dist)
296 np->id = sctoff(np->x, np->y);
303 * Return character to use in maps for sector type TYPE owned by OWN.
304 * If OWNER_OR_GOD, the map is for the sector's owner or a deity.
307 map_char(unsigned char type, natid own, int owner_or_god)
309 if (CANT_HAPPEN(type > SCT_TYPE_MAX || !dchr[type].d_mnem))
312 || type == SCT_WATER || type == SCT_MOUNT || type == SCT_WASTE
313 || (!own && (type == SCT_RURAL || type == SCT_PLAINS)))
314 return dchr[type].d_mnem;
319 unit_map(int unit_type, int uid, struct nstr_sect *nsp, char *originp)
328 if (unit_type == EF_LAND) {
329 if (!getland(uid, &origl) || !player->owner || origl.lnd_own == 0)
331 gp = (struct genitem *)&origl;
332 *originp = *lchr[(int)origl.lnd_type].l_name;
333 } else if (unit_type == EF_PLANE) {
334 if (!getplane(uid, &origp) || !player->owner || origp.pln_own == 0)
336 gp = (struct genitem *)&origp;
337 *originp = *plchr[(int)origp.pln_type].pl_name;
338 } else if (unit_type == EF_NUKE) {
339 if (!getnuke(uid, &orign) || !player->owner || orign.nuk_own == 0)
341 gp = (struct genitem *)&orign;
344 if (!getship(uid, &origs) || !player->owner || origs.shp_own == 0)
346 gp = (struct genitem *)&origs;
347 *originp = *mchr[(int)origs.shp_type].m_name;
350 range.lx = xnorm(gp->x - 10);
351 range.hx = xnorm(gp->x + 11);
352 range.ly = ynorm(gp->y - 5);
353 range.hy = ynorm(gp->y + 6);
354 xysize_range(&range);
355 snxtsct_area(nsp, &range);
360 bmaps_intersect(natid a, natid b)
362 char *mapa = ef_ptr(EF_MAP, a);
363 char *mapb = ef_ptr(EF_MAP, b);
366 for (i = 0; i < WORLD_X * WORLD_Y / 2; ++i, ++mapa, ++mapb)
367 if (*mapa && *mapa != ' ' && *mapb && *mapb != ' ')
372 /* Note that this requires that the BMAP is mapped into memory */
375 share_bmap(natid from, natid to, struct nstr_sect *ns, char des,
378 char *from_bmap = ef_ptr(EF_BMAP, from);
379 char *to_bmap = ef_ptr(EF_BMAP, to);
384 char from_des = *from_name;
386 if (isalpha(from_des))
389 while (nxtsct(ns, §)) {
390 if (!(fromdes = from_bmap[sctoff(ns->x, ns->y)]))
392 todes = to_bmap[sctoff(ns->x, ns->y)];
395 todes != '.' && todes != ' ' && todes != from_des)
397 if (sect.sct_own == from) {
398 if (fromdes != '=' && fromdes != 'h' && fromdes != des)
401 if (todes == fromdes)
403 n += map_set(to, ns->x, ns->y, fromdes, 1);