]> git.pond.sub.org Git - empserver/blob - src/lib/commands/look.c
COPYING duplicates information from README. Remove. Move GPL from
[empserver] / src / lib / commands / look.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2006, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future 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 <config.h>
35
36 #include "misc.h"
37 #include "player.h"
38 #include "xy.h"
39 #include "sect.h"
40 #include "ship.h"
41 #include "land.h"
42 #include "plane.h"
43 #include "nsc.h"
44 #include "nat.h"
45 #include "path.h"
46 #include "file.h"
47 #include <fcntl.h>
48 #include "commands.h"
49 #include "optlist.h"
50
51 static void look_ship(struct shpstr *lookship);
52 static void look_land(struct lndstr *lookland);
53
54 int
55 look(void)
56 {
57     int i;
58     struct nstr_item ni;
59     struct shpstr myship;
60     struct sctstr sect;
61     int x, y;
62     int civ;
63     int mil;
64     u_char *bitmap;
65     int changed = 0;
66
67     if (!snxtitem(&ni, EF_SHIP, player->argp[1]))
68         return RET_SYN;
69     if ((bitmap = malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
70         logerror("malloc failed in look\n");
71         pr("Memory error.  Tell the deity.\n");
72         return RET_FAIL;
73     }
74     memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
75     while (nxtitem(&ni, &myship)) {
76         if (!player->owner)
77             continue;
78         look_ship(&myship);
79         for (i = 0; i <= 6; i++) {
80             x = diroff[i][0] + myship.shp_x;
81             y = diroff[i][1] + myship.shp_y;
82             if (emp_getbit(x, y, bitmap))
83                 continue;
84             emp_setbit(x, y, bitmap);
85             getsect(x, y, &sect);
86             if (sect.sct_type == SCT_WATER)
87                 continue;
88             if (player->owner)
89                 pr("Your ");
90             else
91                 pr("%s (#%d) ", cname(sect.sct_own), sect.sct_own);
92             pr(dchr[sect.sct_type].d_name);
93             changed += map_set(player->cnum, x, y,
94                                dchr[sect.sct_type].d_mnem, 0);
95             pr(" %d%% efficient ", player->owner ? sect.sct_effic :
96                roundintby((int)sect.sct_effic, 10));
97             civ = sect.sct_item[I_CIVIL];
98             mil = sect.sct_item[I_MILIT];
99             if (civ)
100                 pr("with %s%d civ ", player->owner ? "" : "approx ",
101                    player->owner ? civ : roundintby(civ, 10));
102             if (mil)
103                 pr("with %s%d mil ", player->owner ? "" : "approx ",
104                    player->owner ? mil : roundintby(mil, 10));
105             pr("@ %s\n", xyas(x, y, player->cnum));
106             if (opt_HIDDEN) {
107                 setcont(player->cnum, sect.sct_own, FOUND_LOOK);
108             }
109         }
110     }
111     if (changed)
112         writemap(player->cnum);
113     free(bitmap);
114     return RET_OK;
115 }
116
117 static void
118 look_ship(struct shpstr *lookship)
119 {
120     struct shpstr *sp;
121     struct mchrstr *smcp;
122     struct mchrstr *tmcp;
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), prship(sp));
167         }
168         /* subs at sea only seen by sonar */
169         if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
170             continue;
171         pr("%s (#%d) %s @ %s\n",
172            cname(sp->shp_own), sp->shp_own, prship(sp),
173            xyas(sp->shp_x, sp->shp_y, player->cnum));
174         if (opt_HIDDEN)
175             setcont(player->cnum, sp->shp_own, FOUND_LOOK);
176     }
177 }
178
179 int
180 llook(void)
181 {
182     int i;
183     struct nstr_item ni;
184     struct lndstr myland;
185     struct sctstr sect;
186     int x, y;
187     int civ;
188     int mil;
189     u_char *bitmap;
190     int changed = 0;
191
192     if (!snxtitem(&ni, EF_LAND, player->argp[1]))
193         return RET_SYN;
194     if ((bitmap = malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
195         logerror("malloc failed in llook\n");
196         pr("Memory error.  Tell the deity.\n");
197         return RET_FAIL;
198     }
199     memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
200     while (nxtitem(&ni, &myland)) {
201         if (!player->owner)
202             continue;
203         if (myland.lnd_ship >= 0)
204             continue;
205         if (myland.lnd_land >= 0)
206             continue;
207         /* Spies don't need military to do a "llook".  Other
208            units do */
209         if ((lnd_getmil(&myland) <= 0) &&
210             !(lchr[(int)myland.lnd_type].l_flags & L_SPY))
211             continue;
212         look_land(&myland);
213         for (i = 0; i <= 6; i++) {
214             x = diroff[i][0] + myland.lnd_x;
215             y = diroff[i][1] + myland.lnd_y;
216             if (emp_getbit(x, y, bitmap))
217                 continue;
218             emp_setbit(x, y, bitmap);
219             getsect(x, y, &sect);
220             if (sect.sct_type == SCT_WATER)
221                 continue;
222             if (player->owner)
223                 pr("Your ");
224             else
225                 pr("%s (#%d) ", cname(sect.sct_own), sect.sct_own);
226             pr(dchr[sect.sct_type].d_name);
227             changed += map_set(player->cnum, x, y,
228                                dchr[sect.sct_type].d_mnem, 0);
229             pr(" %d%% efficient ", player->owner ? sect.sct_effic :
230                roundintby((int)sect.sct_effic, 10));
231             civ = sect.sct_item[I_CIVIL];
232             mil = sect.sct_item[I_MILIT];
233             if (civ)
234                 pr("with %s%d civ ", player->owner ? "" :
235                    "approx ", player->owner ? civ : roundintby(civ, 10));
236             if (mil)
237                 pr("with %s%d mil ", player->owner ? "" :
238                    "approx ", player->owner ? mil : roundintby(mil, 10));
239             pr("@ %s\n", xyas(x, y, player->cnum));
240             if (opt_HIDDEN) {
241                 setcont(player->cnum, sect.sct_own, FOUND_LOOK);
242             }
243         }
244     }
245     if (changed)
246         writemap(player->cnum);
247     free(bitmap);
248     return RET_OK;
249 }
250
251 static void
252 look_land(struct lndstr *lookland)
253 {
254     struct plnstr *pp;
255     struct lndstr *lp;
256     double drange;
257     int range;
258     int vrange;
259     int i;
260     int dist;
261
262     drange = techfact(lookland->lnd_tech, (double)lookland->lnd_spy);
263     drange = (drange * ((double)lookland->lnd_effic / 100.0));
264     range = ldround(drange, 1);
265
266     if (range == 0)
267         return;
268
269     for (i = 0; NULL != (lp = getlandp(i)); i++) {
270         if (lp->lnd_own == player->cnum || lp->lnd_own == 0)
271             continue;
272         if (lp->lnd_ship >= 0)
273             continue;
274         /* Don't always see spies */
275         if (lchr[(int)lp->lnd_type].l_flags & L_SPY) {
276             /* If it's on a ship or unit, assume it's hidden
277                enough not to be seen */
278             if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
279                 continue;
280             if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic))))
281                 continue;
282         }
283         vrange = ldround((double)((lp->lnd_vis * range) / 20.0), 1);
284         dist = mapdist(lp->lnd_x, lp->lnd_y,
285                        lookland->lnd_x, lookland->lnd_y);
286         if (dist > vrange)
287             continue;
288
289         pr("%s (#%d) %s (approx %d mil) @ %s\n",
290            cname(lp->lnd_own), lp->lnd_own,
291            prland(lp), ldround((double)total_mil(lp), 20),
292            xyas(lp->lnd_x, lp->lnd_y, player->cnum));
293         if (opt_HIDDEN)
294             setcont(player->cnum, lp->lnd_own, FOUND_LOOK);
295     }
296     for (i = 0; NULL != (pp = getplanep(i)); i++) {
297         if (pp->pln_own == player->cnum || pp->pln_own == 0)
298             continue;
299         if (pp->pln_ship >= 0)
300             continue;
301         if (pp->pln_flags & PLN_LAUNCHED)
302             continue;
303         vrange = ldround((double)((10 * range) / 20.0), 1);
304         dist = mapdist(pp->pln_x, pp->pln_y,
305                        lookland->lnd_x, lookland->lnd_y);
306         if (dist > vrange)
307             continue;
308
309         pr("%s (#%d) %s @ %s\n",
310            cname(pp->pln_own), pp->pln_own,
311            prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum));
312         if (opt_HIDDEN)
313             setcont(player->cnum, pp->pln_own, FOUND_LOOK);
314     }
315 }