]> git.pond.sub.org Git - empserver/blob - src/lib/common/maps.c
Import of Empire 4.2.12
[empserver] / src / lib / common / maps.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
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.
10  *
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.
15  *
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
19  *
20  *  ---
21  *
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.
25  *
26  *  ---
27  *
28  *  maps.c: Map routines
29  * 
30  *  Known contributors to this file:
31  *     Ken Stevens, 1995
32  *     Steve McClure, 1998
33  */
34
35 #include "misc.h"
36 #include "player.h"
37 #include "var.h"
38 #include "sect.h"
39 #include "xy.h"
40 #include "nsc.h"
41 #include "file.h"
42 #include "deity.h"
43 #include "nat.h"
44 #include "map.h"
45 #include "ship.h"
46 #include "land.h"
47 #include "plane.h"
48 #include "common.h"
49 #include "gen.h"
50 #include "subs.h"
51 #include "optlist.h"
52
53 int
54 draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp, int country)
55 {
56     struct      natstr *np;
57     struct      range range;
58     struct      nstr_item ni;
59     struct      shpstr ship;
60     struct      lndstr land;
61     struct      plnstr plane;
62     coord       x,y;
63     int i;
64     /* Note this is not re-entrant anyway, so we keep the buffers
65        around */
66     static u_char      *bitmap = (u_char *)0;
67     static s_char      *wmapbuf = (s_char *)0;
68     static s_char      **wmap = (s_char **)0;
69     
70     if (!wmapbuf)
71                 wmapbuf = (s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char));
72     if (!wmap) {
73                 wmap = (s_char **)malloc(WORLD_Y * sizeof(s_char *));
74                 if (wmap && wmapbuf) {
75                         for (i = 0; i < WORLD_Y; i++)
76                                 wmap[i] = &wmapbuf[MAPWIDTH(1) * i];
77                 } else if (wmap) {
78                         free((s_char *)wmap);
79                         wmap = (s_char **)0;
80                 }
81     }
82     if (!bitmap)
83                 bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8);
84     if (!wmapbuf || !wmap || !bitmap) {
85                 pr("Memory error, tell the deity.\n");
86                 logerror("malloc failed in draw_map\n");
87                 return RET_FAIL;
88     }
89         
90     if (bmap == EF_MAP + EF_BMAP) {
91         if (!confirm("Are you sure you want to revert your bmap? "))
92                 return RET_OK;
93     }
94     if (!player->command->c_flags & C_MOD) {
95         logerror("%s command needs C_MOD flag set",player->command->c_form);
96         player->command->c_flags |= C_MOD;
97     }
98     np = getnatp(country);
99     /* zap any conditionals */
100     nsp->ncond = 0;
101     xyrelrange(np, &nsp->range, &range);
102     border(&range, "     ", "");
103     blankfill((s_char *)wmapbuf, &nsp->range, 1);
104     if (bmap) {
105                 register int c;
106                 switch (bmap) {
107                 case EF_BMAP:
108                         while (bmnxtsct(nsp) && !player->aborted) {
109                                 if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
110                                         wmap[nsp->dy][nsp->dx] = c;
111                         }
112                         break;
113                 case EF_MAP:
114                         while (bmnxtsct(nsp) && !player->aborted) {
115                                 if (0 != (c = player->map[sctoff(nsp->x, nsp->y)]))
116                                         wmap[nsp->dy][nsp->dx] = c;
117                         }
118                         break;
119                 case (EF_MAP + EF_BMAP):
120                         while (bmnxtsct(nsp) && !player->aborted) {
121                                 player->bmap[sctoff(nsp->x, nsp->y)] =
122                                         player->map[sctoff(nsp->x, nsp->y)];
123                                 if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
124                                         wmap[nsp->dy][nsp->dx] = c;
125                         }
126                         ef_write(EF_BMAP, player->cnum, player->bmap);
127                         break;
128                 case EF_NMAP:
129                         do {
130                                 register s_char *ptr;
131                                 struct  sctstr sect;
132                                 
133                                 if ((!player->god || country)) {
134                                         bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8);
135                                         bitinit2(nsp, bitmap, country);
136                                 }
137                                 while (nxtsct(nsp, &sect) && !player->aborted) {
138                                         if ((!player->god || country) &&
139                                                 !emp_getbit(nsp->x, nsp->y, bitmap)) {
140                                                 if (!player->god)
141                                                         continue;
142                                         }
143                                         ptr = &wmap[nsp->dy][nsp->dx];
144                                         if (sect.sct_newtype > SCT_MAXDEF) {
145                                                 *ptr = '?';
146                                         } else {
147                                                 *ptr = dchr[sect.sct_newtype].d_mnem;
148                                                 switch (sect.sct_newtype) {
149                                                 case SCT_WATER:
150                                                 case SCT_RURAL:
151                                                 case SCT_MOUNT:
152                                                 case SCT_WASTE:
153                                                 case SCT_PLAINS:
154                                                         break;
155                                                 default:
156                                                         if (sect.sct_own != country &&
157                                                                 (!player->god || country)) {
158                                                                 if (!player->god)       
159                                                                         *ptr = '?';
160                                                         } 
161                                                         break;
162                                                 }
163                                         }
164                                 }
165                         } while (0);
166                         break;
167                 }
168     } else {
169                 register s_char *ptr;
170                 struct  sctstr sect;
171                 int     changed = 0;
172                 
173                 if ((!player->god || country)) {
174                         bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8);
175                         bitinit2(nsp, bitmap, country);
176                 }
177                 while (nxtsct(nsp, &sect) && !player->aborted) {
178                         if ((!player->god || country) && !emp_getbit(nsp->x, nsp->y, bitmap)) {
179                                 if (!player->god)
180                                         continue;
181                         }
182                         ptr = &wmap[nsp->dy][nsp->dx];
183                         if (sect.sct_type > SCT_MAXDEF) {
184                                 *ptr = '?';
185                         } else {
186                                 *ptr = dchr[sect.sct_type].d_mnem;
187                                 switch (sect.sct_type) {
188                                 case SCT_WATER:
189                                 case SCT_RURAL:
190                                 case SCT_MOUNT:
191                                 case SCT_WASTE:
192                                 case SCT_PLAINS:
193                                         break;
194                                 default:
195                                         if (sect.sct_own != country &&
196                                                 (!player->god || country)) {
197                                                 if(!player->god)        
198                                                         *ptr = '?';
199                                         } 
200                                         break;
201                                 }
202                                 changed += map_set(player->cnum, nsp->x, nsp->y, *ptr, 0);
203                         }
204                 }
205                 if (changed)
206                         writemap(player->cnum);
207     }
208     if (player->aborted)
209                 return RET_OK;
210     if (map_flags & MAP_PLANE){
211                 snxtitem_all(&ni, EF_PLANE);
212                 while (nxtitem(&ni, (caddr_t)&plane)) {
213                         if (plane.pln_own == 0)
214                                 continue;
215                         if (plane.pln_own != player->cnum && !player->god)
216                                 continue;
217                         if (!xyinrange(plane.pln_x, plane.pln_y, &nsp->range))
218                                 continue;
219                         
220                         x = xnorm(plane.pln_x-nsp->range.lx);
221                         y = ynorm(plane.pln_y-nsp->range.ly);
222                         wmap[y][x] = (*plchr[(int)plane.pln_type].pl_name) & ~0x20;
223                 }
224     }
225     if (map_flags & MAP_SHIP){
226                 snxtitem_all(&ni, EF_SHIP);
227                 while (nxtitem(&ni, (caddr_t)&ship)) {
228                         if (ship.shp_own == 0)
229                                 continue;
230                         if (ship.shp_own != player->cnum && !player->god)
231                                 continue;
232                         if (!xyinrange(ship.shp_x, ship.shp_y, &nsp->range))
233                                 continue;
234                         
235                         x = xnorm(ship.shp_x-nsp->range.lx);
236                         y = ynorm(ship.shp_y-nsp->range.ly);
237                         wmap[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
238                 }
239     }
240     if (map_flags & MAP_LAND){
241                 snxtitem_all(&ni, EF_LAND);
242                 while (nxtitem(&ni, (caddr_t)&land)) {
243                         if (land.lnd_own == 0)
244                                 continue;
245                         if (land.lnd_own != player->cnum && !player->god)
246                                 continue;
247                         if (!xyinrange(land.lnd_x, land.lnd_y, &nsp->range))
248                                 continue;
249                         
250                         x = xnorm(land.lnd_x-nsp->range.lx);
251                         y = ynorm(land.lnd_y-nsp->range.ly);
252                         wmap[y][x] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
253                 }
254     }
255     if (origin)
256                 wmap[5][10] = origin & ~0x20;
257     for (y=nsp->range.ly, i=0; i < nsp->range.height; y++, i++) {
258                 int yval;
259                 
260                 yval = yrel(np, y);
261                 wmap[i][nsp->range.width] = '\0';
262                 pr("%4d %s %-4d\n", yval, wmap[i], yval);
263                 if (y >= WORLD_Y)
264                         y -= WORLD_Y;
265     }
266     border(&range, "     ", "");
267     return RET_OK;
268 }
269
270 /*
271  * get the next sector in the range
272  */
273 int
274 bmnxtsct(register struct nstr_sect *np)
275 {
276     while (1) {
277                 np->dx++;
278                 np->x++;
279                 if (np->x >= WORLD_X)
280                         np->x = 0;
281                 if (np->dx >= np->range.width) {
282                         np->dx = 0;
283                         np->x = np->range.lx;
284                         np->dy++;
285                         if (np->dy >= np->range.height)
286                                 return 0;
287                         np->y++;
288                         if (np->y >= WORLD_Y)
289                                 np->y = 0;
290                 }
291                 if ((np->y + np->x) & 01)
292                         continue;
293                 if (np->type == NS_DIST) {
294                         np->curdist = mapdist(np->x, np->y, np->cx, np->cy);
295                         if (np->curdist > np->dist)
296                                 continue;
297                 }
298                 np->id = sctoff(np->x, np->y);
299                 return 1;
300     }
301     /*NOTREACHED*/
302 }
303
304 void
305 bitinit2(struct nstr_sect *np, u_char *bitmap, int country)
306 {
307     extern  int *bitmaps[];
308     struct  sctstr sect;
309     int     eff;
310     
311     while (nxtsct(np, &sect)) {
312                 if (sect.sct_own != country)
313                         continue;
314                 eff = sect.sct_effic / 20;
315                 if (eff > 4)
316                         eff = 4;
317                 emp_setbitmap(np->x, np->y, bitmap, bitmaps[eff]);
318     }
319     snxtsct_rewind(np);
320 }
321
322 int
323 unit_map(int unit_type, int i, struct nstr_sect *nsp, s_char *originp)
324 {
325     struct      shpstr origs;
326     struct      lndstr origl;
327     struct      plnstr origp;
328     s_char      what[64];
329     struct      natstr *np;
330     
331     np = getnatp(player->cnum);
332     if (unit_type == EF_LAND){
333                 if (!getland(i, &origl) ||
334                         (origl.lnd_own != player->cnum && !player->god) ||
335                         (origl.lnd_own == 0))
336                         return RET_FAIL;
337                 sprintf(what, "%d:%d,%d:%d",xrel(np,origl.lnd_x-10),
338                                 xrel(np,origl.lnd_x+10),
339                                 yrel(np,origl.lnd_y-5), yrel(np,origl.lnd_y+5));
340                 *originp = *lchr[(int)origl.lnd_type].l_name;
341     } else if (unit_type == EF_PLANE){
342                 if (!getplane(i, &origp) ||
343                         (origp.pln_own != player->cnum && !player->god) || 
344                         (origp.pln_own == 0))
345                         return RET_FAIL;
346                 sprintf(what, "%d:%d,%d:%d",xrel(np,origp.pln_x-10),
347                                 xrel(np,origp.pln_x+10),
348                                 yrel(np,origp.pln_y-5), yrel(np,origp.pln_y+5));
349                 *originp = *plchr[(int)origp.pln_type].pl_name;
350     } else {
351                 if (!getship(i, &origs) ||
352                         (origs.shp_own != player->cnum && !player->god) || 
353                         (origs.shp_own == 0))
354                         return RET_FAIL;
355                 sprintf(what, "%d:%d,%d:%d",xrel(np,origs.shp_x-10),
356                                 xrel(np,origs.shp_x+10),
357                                 yrel(np,origs.shp_y-5), yrel(np,origs.shp_y+5));
358                 unit_type = EF_SHIP;
359                 *originp = *mchr[(int)origs.shp_type].m_name;
360     }
361     if (!snxtsct(nsp, what))
362                 return RET_FAIL;
363     return RET_OK;
364 }
365
366 int
367 bmaps_intersect(natid a, natid b)
368 {
369     s_char      *mapa = ef_ptr(EF_MAP, a);
370     s_char      *mapb = ef_ptr(EF_MAP, b);
371     int i;
372     
373     for (i = 0; i < WORLD_X*WORLD_Y/2; ++i, ++mapa, ++mapb)
374                 if (*mapa && *mapa != ' ' && *mapb && *mapb != ' ')
375                         return 1;
376     return 0;
377 }
378
379 /* Note that this requires that the BMAP is mapped into memory */
380
381 int
382 share_bmap(natid from, natid to, struct nstr_sect *ns, s_char des, s_char *from_name)
383 {
384     s_char      *from_bmap = ef_ptr(EF_BMAP, from);
385     s_char      *to_bmap = ef_ptr(EF_BMAP, to);
386     int n = 0;
387     struct      sctstr  sect;
388     s_char      fromdes;
389     s_char      todes;
390     s_char      from_des = *from_name;
391     
392     if (isalpha(from_des))
393                 from_des &= ~0x20;
394     
395     while (nxtsct(ns, &sect)) {
396                 if (!(fromdes = from_bmap[sctoff(ns->x, ns->y)]))
397                         continue;
398                 todes = to_bmap[sctoff(ns->x, ns->y)];
399                 if (todes &&
400                         todes != '?' &&
401                         todes != '.' &&
402                         todes != ' ' &&
403                         todes != from_des)
404                         continue;
405                 if (sect.sct_own == from) {
406                         if (fromdes != '=' &&
407                                 fromdes != 'h' &&
408                                 fromdes != des)
409                                 fromdes = from_des;
410                 }
411                 if (todes == fromdes)
412                         continue;
413                 n += map_set(to, ns->x, ns->y, fromdes, 1);
414     }
415     
416     if (n)
417                 writebmap(to);
418     return n;
419 }
420