]> git.pond.sub.org Git - empserver/blob - src/lib/subs/satmap.c
Update copyright notice
[empserver] / src / lib / subs / satmap.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2017, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  satmap.c: Do a satellite map given an x,y location, effic and other
28  *
29  *  Known contributors to this file:
30  *     Steve McClure, 2000
31  *     Markus Armbruster, 2004-2013
32  */
33
34 #include <config.h>
35
36 #include <stdlib.h>
37 #include "chance.h"
38 #include "land.h"
39 #include "map.h"
40 #include "misc.h"
41 #include "nat.h"
42 #include "nsc.h"
43 #include "optlist.h"
44 #include "plane.h"
45 #include "player.h"
46 #include "prototypes.h"
47 #include "sect.h"
48 #include "ship.h"
49 #include "xy.h"
50
51 static char **rad;
52 static char *radbuf;
53
54 int
55 satmap(int x, int y, int eff, int range, int flags, int type)
56 {
57     struct sctstr sect;
58     struct shpstr ship;
59     struct lndstr land;
60     int count, crackle;
61     struct nstr_item ni;
62     struct nstr_sect ns;
63     int rx, ry;
64     int row;
65     int n;
66     int changed = 0;
67     signed char noise[100];
68
69     if (!eff)
70         return RET_OK;
71
72     if (!radbuf)
73         radbuf = malloc(WORLD_Y * MAPWIDTH(1));
74     if (!rad) {
75         rad = malloc(WORLD_Y * sizeof(char *));
76         if (rad && radbuf) {
77             for (rx = 0; rx < WORLD_Y; rx++)
78                 rad[rx] = &radbuf[(WORLD_X + 1) * rx];
79         }
80     }
81
82     if (!radbuf || !rad) {
83         pr("Memory error in satmap, tell the deity.\n");
84         return RET_FAIL;
85     }
86
87     range = range * (eff / 100.0);
88     pr("%s efficiency %d%%, max range %d\n",
89        xyas(x, y, player->cnum), eff, range);
90     memset(noise, 0, sizeof(noise));
91     if (eff < 100) {
92         pr("Some noise on the transmission...\n");
93         for (n = 0; n < (100 - eff); ++n)
94             noise[100 * n / (100 - eff)] = 1;
95     }
96
97     if (type == EF_BAD || type == EF_SECTOR) {
98         snxtsct_dist(&ns, x, y, range);
99         if (type == EF_SECTOR && !snxtsct_use_condarg(&ns))
100             return RET_SYN;
101
102         blankfill(radbuf, &ns.range, 1);
103         if (flags & P_S) {
104             pr("Satellite sector report\n");
105             prdate();
106             sathead();
107         }
108         crackle = count = 0;
109         while (nxtsct(&ns, &sect)) {
110             if (++crackle == 100)
111                 crackle = 0;
112             if (noise[crackle])
113                 continue;
114             if (flags & P_S) {
115                 if (sect.sct_own && sect.sct_own != player->cnum) {
116                     satdisp_sect(&sect, (flags & P_I) ? 5 : 50);
117                     changed += map_set(player->cnum, sect.sct_x, sect.sct_y,
118                                        dchr[sect.sct_type].d_mnem, 0);
119                     ++count;
120                     if (opt_HIDDEN)
121                         setcont(player->cnum, sect.sct_own, FOUND_FLY);
122                 }
123             }
124             if ((flags & P_I) ||
125                 sect.sct_type == SCT_WATER || sect.sct_type == SCT_MOUNT) {
126                 rad[ns.dy][ns.dx] = dchr[sect.sct_type].d_mnem;
127             } else
128                 rad[ns.dy][ns.dx] = '?';
129             changed +=
130                 map_set(player->cnum, ns.x, ns.y, rad[ns.dy][ns.dx], 0);
131         }
132         if (changed)
133             writemap(player->cnum);
134         if (flags & P_S)
135             pr("  %d sectors\n\n", count);
136     }
137
138     if ((type == EF_BAD || type == EF_SHIP) &&
139         (flags & P_S || flags & P_I)) {
140         snxtitem_dist(&ni, EF_SHIP, x, y, range);
141         if (type == EF_SHIP && !snxtitem_use_condarg(&ni))
142             return RET_SYN;
143
144         crackle = count = 0;
145         if (flags & P_S) {
146             pr("Satellite ship report\n");
147             prdate();
148             pr(" own shp# ship type                                   sector   eff\n");
149         }
150         while (nxtitem(&ni, &ship)) {
151             if (ship.shp_own == 0)
152                 continue;
153             if ((mchr[(int)ship.shp_type].m_flags & M_SUB) &&
154                 ((flags & (P_S | P_I)) != (P_S | P_I)))
155                 continue;
156             if (++crackle == 100)
157                 crackle = 0;
158             if (noise[crackle])
159                 continue;
160             if (flags & P_S) {
161                 pr("%4d %4d %-16.16s %-25.25s ",
162                    ship.shp_own, ship.shp_uid,
163                    mchr[(int)ship.shp_type].m_name, ship.shp_name);
164                 prxy("%4d,%-4d ", ship.shp_x, ship.shp_y);
165                 pr("%3d%%\n", ship.shp_effic);
166                 ++count;
167                 if (opt_HIDDEN)
168                     setcont(player->cnum, ship.shp_own, FOUND_FLY);
169             }
170             /* If we are imaging *and* drawing the map */
171             if ((flags & P_I) && (type == EF_BAD)) {
172                 rx = deltx(&ns.range, ship.shp_x);
173                 ry = delty(&ns.range, ship.shp_y);
174                 /* &~0x20 makes it a cap letter */
175                 rad[ry][rx] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
176             }
177         }
178         if (flags & P_S)
179             pr("  %d ships\n\n", count);
180     }
181
182     if ((type == EF_BAD || type == EF_LAND) &&
183         (flags & P_S || flags & P_I)) {
184         snxtitem_dist(&ni, EF_LAND, x, y, range);
185         if (type == EF_LAND && !snxtitem_use_condarg(&ni))
186             return RET_SYN;
187
188         crackle = count = 0;
189         if (flags & P_S) {
190             pr("Satellite unit report\n");
191             prdate();
192             pr(" own lnd# unit type         sector   eff\n");
193         }
194         while (nxtitem(&ni, &land)) {
195             if (land.lnd_own == 0)
196                 continue;
197             if (lchr[(int)land.lnd_type].l_flags & L_SPY)
198                 continue;
199             if (!chance(land.lnd_effic / 20.0))
200                 continue;
201             if (++crackle == 100)
202                 crackle = 0;
203             if (noise[crackle])
204                 continue;
205             if (flags & P_S) {
206                 pr("%4d %4d %-16.16s ",
207                    land.lnd_own, land.lnd_uid,
208                    lchr[(int)land.lnd_type].l_name);
209                 prxy("%4d,%-4d ", land.lnd_x, land.lnd_y);
210                 pr("%3d%%\n", land.lnd_effic);
211                 ++count;
212                 if (opt_HIDDEN)
213                     setcont(player->cnum, land.lnd_own, FOUND_FLY);
214             }
215             /* If we are imaging *and* drawing the map */
216             if ((flags & P_I) && (type == EF_BAD)) {
217                 rx = deltx(&ns.range, land.lnd_x);
218                 ry = delty(&ns.range, land.lnd_y);
219                 /* &~0x20 makes it a cap letter */
220                 rad[ry][rx] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
221             }
222         }
223         if (flags & P_S)
224             pr("  %d units\n\n", count);
225     }
226
227     /* Ok, have we made the map?  If so, display it */
228     if (type == EF_BAD) {
229         /*
230          * print out the map
231          * We have to make the center a '0' for ve
232          * ve needs a garbage line to terminate the map
233          */
234         rad[delty(&ns.range, y)][deltx(&ns.range, y)] = '0';
235
236         pr("Satellite radar report\n");
237         n = ns.range.height;
238         for (row = 0; row < n; row++)
239             pr("%s\n", rad[row]);
240         pr("\n(c) 1989 Imaginative Images Inc.\n");
241     }
242     return RET_OK;
243 }
244
245 void
246 sathead(void)
247 {
248     pr("                    sct rd  rl  def\n");
249     pr("   sect   type own  eff eff eff eff  civ  mil  shl  gun iron  pet  food\n");
250 }
251
252 void
253 satdisp_sect(struct sctstr *sp, int acc)
254 {
255     prxy("%4d,%-4d   ", sp->sct_x, sp->sct_y);
256     pr("%c  %3d  %3d %3d %3d %3d %4d %4d %4d %4d %4d %4d %5d\n",
257        dchr[sp->sct_type].d_mnem,
258        sp->sct_own, roundintby((int)sp->sct_effic, acc / 2),
259        roundintby((int)sp->sct_road, acc / 2),
260        opt_RAILWAYS ? !!sct_rail_track(sp) : roundintby(sp->sct_rail, acc / 2),
261        roundintby((int)sp->sct_defense, acc / 2),
262        roundintby(sp->sct_item[I_CIVIL], acc),
263        roundintby(sp->sct_item[I_MILIT], acc),
264        roundintby(sp->sct_item[I_SHELL], acc),
265        roundintby(sp->sct_item[I_GUN], acc),
266        roundintby(sp->sct_item[I_IRON], acc),
267        roundintby(sp->sct_item[I_PETROL], acc),
268        roundintby(sp->sct_item[I_FOOD], acc));
269 }
270
271 void
272 satdisp_units(coord x, coord y)
273 {
274     int first;
275     struct nstr_item ni;
276     struct shpstr ship;
277     struct lndstr land;
278
279     snxtitem_xy(&ni, EF_SHIP, x, y);
280     first = 1;
281     while (nxtitem(&ni, &ship)) {
282         if (ship.shp_own == 0)
283             continue;
284         if (mchr[(int)ship.shp_type].m_flags & M_SUB)
285             continue;
286         if (first) {
287             pr("\t own shp# ship type                                   sector   eff\n");
288             first = 0;
289         }
290         pr("\t%4d %4d %-16.16s %-25.25s ",
291            ship.shp_own, ship.shp_uid,
292            mchr[(int)ship.shp_type].m_name, ship.shp_name);
293         prxy("%4d,%-4d ", ship.shp_x, ship.shp_y);
294         pr("%3d%%\n", ship.shp_effic);
295     }
296
297     if (!first)
298         pr("\n");
299
300     snxtitem_xy(&ni, EF_LAND, x, y);
301     first = 1;
302
303     while (nxtitem(&ni, &land)) {
304         if (land.lnd_own == 0)
305             continue;
306         if (land.lnd_ship >= 0 || land.lnd_land >= 0)
307             continue;
308         if (lchr[(int)land.lnd_type].l_flags & L_SPY)
309             continue;
310         if (!chance(land.lnd_effic / 20.0))
311             continue;
312
313         if (first) {
314             pr("\t own lnd# unit type         sector   eff\n");
315             first = 0;
316         }
317
318         pr("\t%4d %4d %-16.16s ",
319            land.lnd_own, land.lnd_uid, lchr[(int)land.lnd_type].l_name);
320         prxy("%4d,%-4d ", land.lnd_x, land.lnd_y);
321         pr("%3d%%\n", land.lnd_effic);
322     }
323
324     if (!first)
325         pr("\n");
326 }