]> git.pond.sub.org Git - empserver/blob - src/lib/commands/look.c
Import of Empire 4.2.12
[empserver] / src / lib / commands / look.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  *  look.c: Lookout from a ship or land unit
29  * 
30  *  Known contributors to this file:
31  *     
32  */
33
34 #include "misc.h"
35 #include "player.h"
36 #include "var.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 "path.h"
45 #include "file.h"
46 #include <fcntl.h>
47 #include "commands.h"
48 #include "optlist.h"
49
50 static  void look_ship(register struct shpstr *lookship);
51
52 int
53 look(void)
54 {
55         register int i;
56         struct  nstr_item ni;
57         struct  shpstr myship;
58         struct  sctstr sect;
59         int     x, y;
60         int     civ;
61         int     mil;
62         u_char  *bitmap;
63         int     changed = 0;
64
65         if (!snxtitem(&ni, EF_SHIP, player->argp[1]))
66                 return RET_SYN;
67         if ((bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
68             logerror("malloc failed in look\n");
69             pr("Memory error.  Tell the deity.\n");
70             return RET_FAIL;
71         }
72         bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8);
73         while (nxtitem(&ni, (s_char *)&myship)) {
74                 if (!player->owner)
75                         continue;
76                 look_ship(&myship);
77                 for (i = 0; i <= 6; i++) {
78                         x = diroff[i][0] + myship.shp_x;
79                         y = diroff[i][1] + myship.shp_y;
80                         if (emp_getbit(x, y, bitmap))
81                                 continue;
82                         emp_setbit(x, y, bitmap);
83                         getsect(x, y, &sect);
84                         if (sect.sct_type == SCT_WATER)
85                                 continue;
86                         if (player->owner)
87                                 pr("Your ");
88                         else
89                                 pr("%s (#%d) ", cname(sect.sct_own),
90                                         sect.sct_own);
91                         pr(dchr[sect.sct_type].d_name);
92                         changed += map_set(player->cnum, x, y,
93                                 dchr[sect.sct_type].d_mnem, 0);
94                         pr(" %d%% efficient ", player->owner ? sect.sct_effic :
95                                 roundintby((int)sect.sct_effic, 10));
96                         civ = getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR);
97                         mil = getvar(V_MILIT, (s_char *)&sect, EF_SECTOR);
98                         if (civ)
99                                 pr("with %s%d civ ", player->owner ? "" : "approx ",
100                                         player->owner ? civ : roundintby(civ, 10));
101                         if (mil)
102                                 pr("with %s%d mil ", player->owner ? "" : "approx ",
103                                         player->owner ? mil : roundintby(mil, 10));
104                         pr("@ %s\n", xyas(x, y, player->cnum));
105                         if (opt_HIDDEN) {
106                             setcont(player->cnum, sect.sct_own, FOUND_LOOK);
107                         }
108                 }
109         }
110         if (changed)
111                 writemap(player->cnum);
112         free((s_char *)bitmap);
113         return RET_OK;
114 }
115
116 static void
117 look_ship(register struct shpstr *lookship)
118 {
119         register struct shpstr *sp;
120         register struct mchrstr *smcp;
121         register struct mchrstr *tmcp;
122         extern  int     ship_max_interdiction_range;
123         struct  sctstr sect;
124         int     range;
125         int     vrange;
126         int     i;
127         int     dist;
128
129         range = (int) techfact(lookship->shp_tech,
130                 (double) mchr[(int)lookship->shp_type].m_vrnge);
131         range = range * (lookship->shp_effic / 100.0);
132         smcp = &mchr[(int)lookship->shp_type];
133         if (smcp->m_flags & M_SUB)
134                 range = min(range, 1);
135         for (i=0; NULL != (sp = getshipp(i)); i++) {
136                 if (sp->shp_own == player->cnum || sp->shp_own == 0)
137                         continue;
138                 dist = mapdist(sp->shp_x, sp->shp_y,
139                         lookship->shp_x, lookship->shp_y);
140                 if (dist > ship_max_interdiction_range)
141                         continue;
142                 tmcp = &mchr[(int)sp->shp_type];
143                 if (smcp->m_flags & M_SUB)
144                         vrange = (int)(sp->shp_visib * range/30.0);
145                 else
146                         vrange = (int)(sp->shp_visib * range/20.0);
147                 getsect(sp->shp_x, sp->shp_y, &sect);
148                 if (sect.sct_type != SCT_WATER)
149                         vrange = max(1, vrange);
150                 if (dist > vrange)
151                         continue;
152                 if (smcp->m_flags & M_SUB) {
153                         if (tmcp->m_flags & M_SONAR && dist < 2) {
154                                 if(sp->shp_own != 0)
155                                 wu(0, sp->shp_own,
156                                    "%s detected surfacing noises in %s.\n",
157                                    prship(sp),
158                                    xyas(lookship->shp_x, lookship->shp_y,
159                                         sp->shp_own));
160                         }
161                         if (dist == 0 && (tmcp->m_flags & M_SUB) == 0)
162                                 if(sp->shp_own != 0)
163                                 wu(0, sp->shp_own,
164                                 "Periscope spotted in %s by %s\n",
165                                    xyas(lookship->shp_x, lookship->shp_y,
166                                         sp->shp_own),
167                                    prship(sp));
168                 }
169                 /* subs at sea only seen by sonar */
170                 if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
171                         continue;
172                 pr("%s (#%d) %s @ %s\n",
173                    cname(sp->shp_own), sp->shp_own, prship(sp),
174                    xyas(sp->shp_x, sp->shp_y, player->cnum));
175         }
176 }
177
178 static  void look_land(register struct lndstr *lookland);
179
180 int
181 llook(void)
182 {
183         register int i;
184         struct  nstr_item ni;
185         struct  lndstr myland;
186         struct  sctstr sect;
187         int     x, y;
188         int     civ;
189         int     mil;
190         u_char  *bitmap;
191         int     changed = 0;
192
193         if (!snxtitem(&ni, EF_LAND, player->argp[1]))
194                 return RET_SYN;
195         if ((bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
196             logerror("malloc failed in llook\n");
197             pr("Memory error.  Tell the deity.\n");
198             return RET_FAIL;
199         }
200         bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8);
201         while (nxtitem(&ni, (s_char *)&myland)) {
202                 if (!player->owner)
203                         continue;
204                 if (myland.lnd_ship >= 0)
205                         continue;
206                 if (myland.lnd_land >= 0)
207                     continue;
208                 /* Spies don't need military to do a "llook".  Other
209                    units do */
210                 if ((lnd_getmil(&myland) <= 0) && 
211                     !(lchr[(int)myland.lnd_type].l_flags & L_SPY))
212                     continue;
213                 look_land(&myland);
214                 for (i = 0; i <= 6; i++) {
215                         x = diroff[i][0] + myland.lnd_x;
216                         y = diroff[i][1] + myland.lnd_y;
217                         if (emp_getbit(x, y, bitmap))
218                                 continue;
219                         emp_setbit(x, y, bitmap);
220                         getsect(x, y, &sect);
221                         if (sect.sct_type == SCT_WATER)
222                                 continue;
223                         if (player->owner)
224                                 pr("Your ");
225                         else
226                                 pr("%s (#%d) ", cname(sect.sct_own),
227                                         sect.sct_own);
228                         pr(dchr[sect.sct_type].d_name);
229                         changed += map_set(player->cnum, x, y,
230                                 dchr[sect.sct_type].d_mnem, 0);
231                         pr(" %d%% efficient ", player->owner ? sect.sct_effic :
232                                 roundintby((int)sect.sct_effic, 10));
233                         civ = getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR);
234                         mil = getvar(V_MILIT, (s_char *)&sect, EF_SECTOR);
235                         if (civ)
236                                 pr("with %s%d civ ", player->owner ? "" :
237                                         "approx ",
238                                         player->owner ? civ : roundintby(civ, 10));
239                         if (mil)
240                                 pr("with %s%d mil ", player->owner ? "" :
241                                         "approx ",
242                                         player->owner ? mil : roundintby(mil, 10));
243                         pr("@ %s\n", xyas(x, y, player->cnum));
244                         if (opt_HIDDEN) {
245                             setcont(player->cnum, sect.sct_own, FOUND_LOOK);
246                         }
247                 }
248         }
249         if (changed)
250                 writemap(player->cnum);
251         free((s_char *)bitmap);
252         return RET_OK;
253 }
254
255 static void
256 look_land(register struct lndstr *lookland)
257 {
258         register struct plnstr *pp;
259         register struct lndstr *lp;
260         double  drange;
261         int     range;
262         int     vrange;
263         int     i;
264         int     dist;
265         double  techfact(int, double);
266         double odds;
267
268         drange = techfact(lookland->lnd_tech,
269                 (double) lookland->lnd_spy);
270         drange = (drange * ((double)lookland->lnd_effic / 100.0));
271         range = ldround(drange,1);
272
273         if (range == 0)
274                 return;
275
276         for (i=0; NULL != (lp = getlandp(i)); i++) {
277                 if (lp->lnd_own == player->cnum || lp->lnd_own == 0)
278                         continue;
279                 if (lp->lnd_ship >= 0)
280                     continue;
281                 /* Don't always see spies */
282                 if (lchr[(int)lp->lnd_type].l_flags & L_SPY) {
283                     /* If it's on a ship or unit, assume it's hidden
284                        enough not to be seen */
285                     if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
286                         continue;
287                     odds = (double)(100 - lp->lnd_effic) + 0.10;
288                     if (!(chance(odds)))
289                         continue;
290                 }
291                 vrange = ldround((double)((lp->lnd_vis
292                                 * range)/20.0),1);
293                 dist = mapdist(lp->lnd_x, lp->lnd_y,
294                         lookland->lnd_x, lookland->lnd_y);
295                 if (dist > vrange)
296                         continue;
297
298                 pr("%s (#%d) %s (approx %d mil) @ %s\n",
299                    cname(lp->lnd_own), lp->lnd_own,
300                    prland(lp), ldround((double)total_mil(lp), 20),
301                    xyas(lp->lnd_x, lp->lnd_y, player->cnum));
302         }
303         for (i=0; NULL != (pp = getplanep(i)); i++) {
304                 if (pp->pln_own == player->cnum || pp->pln_own == 0)
305                         continue;
306                 if (pp->pln_ship >= 0)
307                         continue;
308                 if (pp->pln_flags & PLN_LAUNCHED)
309                     continue;
310                 vrange = ldround((double)((10* range)/20.0),1);
311                 dist = mapdist(pp->pln_x, pp->pln_y,
312                         lookland->lnd_x, lookland->lnd_y);
313                 if (dist > vrange)
314                         continue;
315
316                 pr("%s (#%d) %s @ %s\n",
317                         cname(pp->pln_own), pp->pln_own,
318                         prplane(pp),
319                         xyas(pp->pln_x, pp->pln_y, player->cnum));
320         }
321 }