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