2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2004, 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 the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * maps.c: Map routines
30 * Known contributors to this file:
52 static int bmnxtsct(register struct nstr_sect *);
53 static s_char map_char(u_char type, natid own, int owner_or_god);
56 draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp,
67 /* Note this is not re-entrant anyway, so we keep the buffers
69 static u_char *bitmap = (u_char *)0;
70 static s_char *wmapbuf = (s_char *)0;
71 static s_char **wmap = (s_char **)0;
75 (s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char));
77 wmap = (s_char **)malloc(WORLD_Y * sizeof(s_char *));
78 if (wmap && wmapbuf) {
79 for (i = 0; i < WORLD_Y; i++)
80 wmap[i] = &wmapbuf[MAPWIDTH(1) * i];
87 bitmap = (u_char *)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");
94 if (bmap == EF_MAP + EF_BMAP) {
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(country);
104 /* zap any conditionals */
106 xyrelrange(np, &nsp->range, &range);
107 border(&range, " ", "");
108 blankfill((s_char *)wmapbuf, &nsp->range, 1);
113 while (bmnxtsct(nsp) && !player->aborted) {
114 if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
115 wmap[nsp->dy][nsp->dx] = c;
119 while (bmnxtsct(nsp) && !player->aborted) {
120 if (0 != (c = player->map[sctoff(nsp->x, nsp->y)]))
121 wmap[nsp->dy][nsp->dx] = c;
124 case (EF_MAP + EF_BMAP):
125 while (bmnxtsct(nsp) && !player->aborted) {
126 player->bmap[sctoff(nsp->x, nsp->y)] =
127 player->map[sctoff(nsp->x, nsp->y)];
128 if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
129 wmap[nsp->dy][nsp->dx] = c;
131 ef_write(EF_BMAP, player->cnum, player->bmap);
137 if ((!player->god || country)) {
138 memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
139 bitinit2(nsp, bitmap, country);
141 while (nxtsct(nsp, §) && !player->aborted) {
142 if ((!player->god || country) &&
143 !emp_getbit(nsp->x, nsp->y, bitmap)) {
147 wmap[nsp->dy][nsp->dx]
148 = map_char(sect.sct_newtype, sect.sct_own,
149 sect.sct_own == country || player->god);
159 if ((!player->god || country)) {
160 memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
161 bitinit2(nsp, bitmap, country);
163 while (nxtsct(nsp, §) && !player->aborted) {
164 if ((!player->god || country)
165 && !emp_getbit(nsp->x, nsp->y, bitmap)) {
169 mapch = map_char(sect.sct_type, sect.sct_own,
170 sect.sct_own == country || player->god);
171 wmap[nsp->dy][nsp->dx] = mapch;
172 changed |= map_set(player->cnum, nsp->x, nsp->y, mapch, 0);
175 writemap(player->cnum);
179 if (map_flags & MAP_PLANE) {
180 snxtitem_all(&ni, EF_PLANE);
181 while (nxtitem(&ni, &plane)) {
182 if (plane.pln_own == 0)
184 if (plane.pln_own != player->cnum && !player->god)
186 if (!xyinrange(plane.pln_x, plane.pln_y, &nsp->range))
189 x = xnorm(plane.pln_x - nsp->range.lx);
190 y = ynorm(plane.pln_y - nsp->range.ly);
191 wmap[y][x] = (*plchr[(int)plane.pln_type].pl_name) & ~0x20;
194 if (map_flags & MAP_SHIP) {
195 snxtitem_all(&ni, EF_SHIP);
196 while (nxtitem(&ni, &ship)) {
197 if (ship.shp_own == 0)
199 if (ship.shp_own != player->cnum && !player->god)
201 if (!xyinrange(ship.shp_x, ship.shp_y, &nsp->range))
204 x = xnorm(ship.shp_x - nsp->range.lx);
205 y = ynorm(ship.shp_y - nsp->range.ly);
206 wmap[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
209 if (map_flags & MAP_LAND) {
210 snxtitem_all(&ni, EF_LAND);
211 while (nxtitem(&ni, &land)) {
212 if (land.lnd_own == 0)
214 if (land.lnd_own != player->cnum && !player->god)
216 if (!xyinrange(land.lnd_x, land.lnd_y, &nsp->range))
219 x = xnorm(land.lnd_x - nsp->range.lx);
220 y = ynorm(land.lnd_y - nsp->range.ly);
221 wmap[y][x] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
224 if (map_flags & MAP_HIGH) {
225 register s_char *ptr;
229 if ((!player->god || country)) {
230 memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
231 bitinit2(nsp, bitmap, country);
233 while (nxtsct(nsp, §) && !player->aborted) {
234 if ((!player->god || country) &&
235 !emp_getbit(nsp->x, nsp->y, bitmap)) {
239 ptr = &wmap[nsp->dy][nsp->dx];
240 if (sect.sct_own == player->cnum)
245 wmap[5][10] = origin & ~0x20;
246 for (y = nsp->range.ly, i = 0; i < nsp->range.height; y++, i++) {
250 wmap[i][nsp->range.width] = '\0';
251 pr("%4d %s %-4d\n", yval, wmap[i], yval);
255 border(&range, " ", "");
260 * get the next sector in the range
263 bmnxtsct(register struct nstr_sect *np)
268 if (np->x >= WORLD_X)
270 if (np->dx >= np->range.width) {
272 np->x = np->range.lx;
274 if (np->dy >= np->range.height)
277 if (np->y >= WORLD_Y)
280 if ((np->y + np->x) & 01)
282 if (np->type == NS_DIST) {
283 np->curdist = mapdist(np->x, np->y, np->cx, np->cy);
284 if (np->curdist > np->dist)
287 np->id = sctoff(np->x, np->y);
294 * Return character to use in maps for sector type TYPE owned by OWN.
295 * If OWNER_OR_GOD, the map is for the sector's owner or a deity.
298 map_char(u_char type, natid own, int owner_or_god)
300 if (type > SCT_MAXDEF) {
301 logerror("bad sector type %d\n", type);
305 || type == SCT_WATER || type == SCT_MOUNT || type == SCT_WASTE
306 || (!own && (type == SCT_RURAL || type == SCT_PLAINS)))
307 return dchr[type].d_mnem;
312 unit_map(int unit_type, int i, struct nstr_sect *nsp, s_char *originp)
320 np = getnatp(player->cnum);
321 if (unit_type == EF_LAND) {
322 if (!getland(i, &origl) ||
323 (origl.lnd_own != player->cnum && !player->god) ||
324 (origl.lnd_own == 0))
326 sprintf(what, "%d:%d,%d:%d", xrel(np, origl.lnd_x - 10),
327 xrel(np, origl.lnd_x + 10),
328 yrel(np, origl.lnd_y - 5), yrel(np, origl.lnd_y + 5));
329 *originp = *lchr[(int)origl.lnd_type].l_name;
330 } else if (unit_type == EF_PLANE) {
331 if (!getplane(i, &origp) ||
332 (origp.pln_own != player->cnum && !player->god) ||
333 (origp.pln_own == 0))
335 sprintf(what, "%d:%d,%d:%d", xrel(np, origp.pln_x - 10),
336 xrel(np, origp.pln_x + 10),
337 yrel(np, origp.pln_y - 5), yrel(np, origp.pln_y + 5));
338 *originp = *plchr[(int)origp.pln_type].pl_name;
340 if (!getship(i, &origs) ||
341 (origs.shp_own != player->cnum && !player->god) ||
342 (origs.shp_own == 0))
344 sprintf(what, "%d:%d,%d:%d", xrel(np, origs.shp_x - 10),
345 xrel(np, origs.shp_x + 10),
346 yrel(np, origs.shp_y - 5), yrel(np, origs.shp_y + 5));
348 *originp = *mchr[(int)origs.shp_type].m_name;
350 if (!snxtsct(nsp, what))
356 bmaps_intersect(natid a, natid b)
358 s_char *mapa = ef_ptr(EF_MAP, a);
359 s_char *mapb = ef_ptr(EF_MAP, b);
362 for (i = 0; i < WORLD_X * WORLD_Y / 2; ++i, ++mapa, ++mapb)
363 if (*mapa && *mapa != ' ' && *mapb && *mapb != ' ')
368 /* Note that this requires that the BMAP is mapped into memory */
371 share_bmap(natid from, natid to, struct nstr_sect *ns, s_char des,
374 s_char *from_bmap = ef_ptr(EF_BMAP, from);
375 s_char *to_bmap = ef_ptr(EF_BMAP, to);
380 s_char from_des = *from_name;
382 if (isalpha(from_des))
385 while (nxtsct(ns, §)) {
386 if (!(fromdes = from_bmap[sctoff(ns->x, ns->y)]))
388 todes = to_bmap[sctoff(ns->x, ns->y)];
391 todes != '.' && todes != ' ' && todes != from_des)
393 if (sect.sct_own == from) {
394 if (fromdes != '=' && fromdes != 'h' && fromdes != des)
397 if (todes == fromdes)
399 n += map_set(to, ns->x, ns->y, fromdes, 1);