]> git.pond.sub.org Git - empserver/blob - src/lib/subs/satmap.c
4e95a1c36e6a8097d06c2650cce9b44ff0ce6a1b
[empserver] / src / lib / subs / satmap.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2005, 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  *  satmap.c: Do a satellite map given an x,y location, effic and other
29  * 
30  *  Known contributors to this file:
31  *     Steve McClure, 2000
32  *     
33  */
34
35 #include "misc.h"
36 #include "player.h"
37 #include "xy.h"
38 #include "sect.h"
39 #include "ship.h"
40 #include "land.h"
41 #include "plane.h"
42 #include "nsc.h"
43 #include "nat.h"
44 #include "file.h"
45 #include "prototypes.h"
46 #include "optlist.h"
47
48 static s_char **rad;
49 static s_char *radbuf;
50
51 void
52 satmap(int x, int y, int eff, int range, int flags, int type)
53 {
54     int acc;
55     struct sctstr sect;
56     struct shpstr ship;
57     struct lndstr land;
58     int count;
59     struct nstr_item ni;
60     struct nstr_sect ns;
61     int rx, ry;
62     int row;
63     int n;
64     int changed = 0;
65     long crackle;
66     s_char noise[100];
67     s_char selection[1024];
68
69     if (!eff)
70         return;
71
72     if (!radbuf)
73         radbuf = (s_char *)malloc((WORLD_Y * (WORLD_X + 1)) *
74                                   sizeof(s_char));
75     if (!rad) {
76         rad = (s_char **)malloc(WORLD_Y * sizeof(s_char *));
77         if (rad && radbuf) {
78             for (rx = 0; rx < WORLD_Y; rx++)
79                 rad[rx] = &radbuf[(WORLD_X + 1) * rx];
80         }
81     }
82
83     if (!radbuf || !rad) {
84         pr("Memory error in satmap, tell the deity.\n");
85         return;
86     }
87
88     range = range * (eff / 100.0);
89     pr("%s efficiency %d%%, max range %d\n", xyas(x, y, player->cnum),
90        eff, range);
91     memset(noise, 0, sizeof(noise));
92     if (eff < 100) {
93         pr("Some noise on the transmission...\n");
94         for (n = 0; n < (100 - eff); ++n)
95             noise[100 * n / (100 - eff)] = 1;
96     }
97
98     /* Have to convert to player coords, since it gets converted
99        back from there */
100     sprintf(selection, "@%s:%d", xyas(x, y, player->cnum), range);
101
102     if (type == EF_BAD || type == EF_SECTOR) {
103         if (type == EF_SECTOR)  /* Use ?conditionals */
104             snxtsct(&ns, selection);
105         else
106             snxtsct_dist(&ns, x, y, range);
107
108         blankfill((s_char *)radbuf, &ns.range, 1);
109         if (flags & P_S) {
110             pr("Satellite sector report\n");
111             prdate();
112             sathead();
113             acc = (flags & P_I) ? 5 : 50;
114         }
115         crackle = count = 0;
116         while (nxtsct(&ns, &sect)) {
117             if (++crackle == 100)
118                 crackle = 0;
119             if (noise[crackle])
120                 continue;
121             if (flags & P_S) {
122                 if (sect.sct_own && sect.sct_own != player->cnum) {
123                     satdisp(&sect, acc, 0);
124                     ++count;
125                 }
126                 if (opt_HIDDEN) {
127                     setcont(player->cnum, sect.sct_own, FOUND_FLY);
128                 }
129             }
130             if ((flags & P_I) ||
131                 sect.sct_type == SCT_WATER || sect.sct_type == SCT_MOUNT) {
132                 rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem;
133             } else
134                 rad[ns.dy][ns.dx] = '?';
135             changed +=
136                 map_set(player->cnum, ns.x, ns.y, rad[ns.dy][ns.dx], 0);
137         }
138         if (changed)
139             writemap(player->cnum);
140         if (flags & P_S)
141             pr("  %d sectors\n\n", count);
142     }
143
144     if ((type == EF_BAD || type == EF_SHIP) &&
145         (flags & P_S || flags & P_I)) {
146         if (type == EF_SHIP)
147             snxtitem(&ni, EF_SHIP, selection);
148         else
149             snxtitem_dist(&ni, EF_SHIP, x, y, range);
150
151         crackle = count = 0;
152         if (flags & P_S) {
153             pr("Satellite ship report\n");
154             prdate();
155             if (opt_SHIPNAMES) {
156                 pr(" own  shp# ship type                                  sector   eff\n");
157             } else {
158                 pr(" own  shp# ship type         sector   eff\n");
159             }
160         }
161         while (nxtitem(&ni, &ship)) {
162             if (ship.shp_own == 0)
163                 continue;
164             if ((mchr[(int)ship.shp_type].m_flags & M_SUB) &&
165                 ((flags & (P_S | P_I)) != (P_S | P_I)))
166                 continue;
167             if (++crackle == 100)
168                 crackle = 0;
169             if (noise[crackle])
170                 continue;
171             if (flags & P_S) {
172                 pr("%4d %4d %-16.16s ",
173                    ship.shp_own, ship.shp_uid,
174                    mchr[(int)ship.shp_type].m_name);
175                 if (opt_SHIPNAMES)
176                     pr("%-25.25s ", ship.shp_name);
177                 prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum);
178                 pr("%3d%%\n", ship.shp_effic);
179                 ++count;
180                 if (opt_HIDDEN) {
181                     setcont(player->cnum, ship.shp_own, FOUND_FLY);
182                 }
183             }
184             /* If we are imaging *and* drawing the map */
185             if ((flags & P_I) && (type == EF_BAD)) {
186                 /* Figure out where to put the ship */
187                 /* First, figure out the distance from the two */
188                 rx = diffx((int)ship.shp_x, x);
189                 ry = diffy((int)ship.shp_y, y);
190                 /* Next, determine which direction to add it to the center */
191                 /* We can only do this if imaging and we have gotten the center
192                    up above by imaging the sectors. */
193                 rx = deltax(x, ns.range.lx) + rx;
194                 ry = deltay(y, ns.range.ly) + ry;
195                 /* &~0x20 makes it a cap letter */
196                 rad[ry][rx] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
197             }
198         }
199         if (flags & P_S)
200             pr("  %d ships\n\n", count);
201     }
202
203     if ((type == EF_BAD || type == EF_LAND) &&
204         (flags & P_S || flags & P_I)) {
205         if (type == EF_LAND)
206             snxtitem(&ni, EF_LAND, selection);
207         else
208             snxtitem_dist(&ni, EF_LAND, x, y, range);
209
210         crackle = count = 0;
211         if (flags & P_S) {
212             pr("Satellite unit report\n");
213             prdate();
214             pr(" own  lnd# unit type         sector   eff\n");
215         }
216         while (nxtitem(&ni, &land)) {
217             if (land.lnd_own == 0)
218                 continue;
219             if (!chance((double)land.lnd_effic / 20.0))
220                 continue;
221             if (++crackle == 100)
222                 crackle = 0;
223             if (noise[crackle])
224                 continue;
225             if (flags & P_S) {
226                 pr("%4d %4d %-16.16s ",
227                    land.lnd_own, land.lnd_uid,
228                    lchr[(int)land.lnd_type].l_name);
229                 prxy("%4d,%-4d", land.lnd_x, land.lnd_y, player->cnum);
230                 pr("%3d%%\n", land.lnd_effic);
231                 ++count;
232             }
233             /* If we are imaging *and* drawing the map */
234             if ((flags & P_I) && (type == EF_BAD)) {
235                 /* Figure out where to put the unit */
236                 /* First, figure out the distance from the two */
237                 rx = diffx((int)land.lnd_x, x);
238                 ry = diffy((int)land.lnd_y, y);
239                 /* Next, determine which direction to add it to the center */
240                 /* We can only do this if imaging and we have gotten the center
241                    up above by imaging the sectors. */
242                 rx = deltax(x, ns.range.lx) + rx;
243                 ry = deltay(y, ns.range.ly) + ry;
244                 /* &~0x20 makes it a cap letter */
245                 rad[ry][rx] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
246             }
247         }
248         if (flags & P_S)
249             pr("  %d units\n\n", count);
250     }
251
252     /* Ok, have we made the map?  If so, display it */
253     if (type == EF_BAD) {
254         /*
255          * print out the map
256          * We have to make the center a '0' for ve
257          * ve needs a garbage line to terminate the map
258          */
259         rad[deltay(y, ns.range.ly)][deltax(x, ns.range.lx)] = '0';
260
261         pr("Satellite radar report\n");
262 #ifdef HAY
263         /* This is wrong for small, hitech worlds. */
264         n = deltay(ns.range.hy, ns.range.ly);
265 #else
266         /* This is already available, so why not use it. */
267         n = ns.range.height;
268 #endif
269         for (row = 0; row < n; row++)
270             pr("%s\n", rad[row]);
271         pr("\n(c) 1989 Imaginative Images Inc.\n");
272     }
273 }
274
275 void
276 sathead(void)
277 {
278     pr("                    sct rd  rl  def\n");
279     pr("   sect   type own  eff eff eff eff  civ  mil  shl  gun iron  pet  food\n");
280 }
281
282 void
283 satdisp(struct sctstr *sp, int acc, int showstuff)
284 {
285     int first;
286     struct nstr_item ni;
287     struct shpstr ship;
288     struct lndstr land;
289
290     prxy("%4d,%-4d   ", sp->sct_x, sp->sct_y, player->cnum);
291     pr("%c  %3d  %3d %3d %3d %3d %4d %4d %4d %4d %4d %4d %5d\n",
292        dchr[sp->sct_type].d_mnem,
293        sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
294        roundintby((int)sp->sct_road, acc / 2),
295        roundintby((int)sp->sct_rail, acc / 2),
296        roundintby((int)sp->sct_defense, acc / 2),
297        roundintby(sp->sct_item[I_CIVIL], acc),
298        roundintby(sp->sct_item[I_MILIT], acc),
299        roundintby(sp->sct_item[I_SHELL], acc),
300        roundintby(sp->sct_item[I_GUN], acc),
301        roundintby(sp->sct_item[I_IRON], acc),
302        roundintby(sp->sct_item[I_PETROL], acc),
303        roundintby(sp->sct_item[I_FOOD], acc));
304     map_set(player->cnum, sp->sct_x, sp->sct_y, dchr[sp->sct_type].d_mnem,
305             0);
306     if (!showstuff)
307         return;
308     snxtitem_xy(&ni, EF_SHIP, sp->sct_x, sp->sct_y);
309     first = 1;
310     while (nxtitem(&ni, &ship)) {
311         if (ship.shp_own == 0)
312             continue;
313         if (mchr[(int)ship.shp_type].m_flags & M_SUB)
314             continue;
315         if (first) {
316             if (opt_SHIPNAMES) {
317                 pr("\t own  shp# ship type                                  sector   eff\n");
318             } else {
319                 pr("\t own  shp# ship type         sector   eff\n");
320             }
321             first = 0;
322         }
323         pr("\t%4d %4d %-16.16s ", ship.shp_own, ship.shp_uid,
324            mchr[(int)ship.shp_type].m_name);
325         if (opt_SHIPNAMES)
326             pr("%-25.25s ", ship.shp_name);
327         prxy("%4d,%-4d ", ship.shp_x, ship.shp_y, player->cnum);
328         pr("%3d%%\n", ship.shp_effic);
329     }
330
331     if (!first)
332         pr("\n");
333
334     snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
335     first = 1;
336
337     while (nxtitem(&ni, &land)) {
338         if (land.lnd_own == 0)
339             continue;
340         if (!chance((double)land.lnd_effic / 20.0))
341             continue;
342
343         if (first) {
344             pr("\t own  lnd# unit type         sector   eff\n");
345             first = 0;
346         }
347
348         pr("\t%4d %4d %-16.16s ", land.lnd_own, land.lnd_uid,
349            lchr[(int)land.lnd_type].l_name);
350         prxy("%4d,%-4d ", land.lnd_x, land.lnd_y, player->cnum);
351         pr("%3d%%\n", land.lnd_effic);
352     }
353
354     if (!first)
355         pr("\n");
356 }