]> git.pond.sub.org Git - empserver/blob - src/lib/commands/look.c
Line breaks and other formatting issues. No functional changes.
[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     unsigned 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("%s", 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 ",
101                    player->owner ? "" : "approx ",
102                    player->owner ? civ : roundintby(civ, 10));
103             if (mil)
104                 pr("with %s%d mil ",
105                    player->owner ? "" : "approx ",
106                    player->owner ? mil : roundintby(mil, 10));
107             pr("@ %s\n", xyas(x, y, player->cnum));
108             if (opt_HIDDEN) {
109                 setcont(player->cnum, sect.sct_own, FOUND_LOOK);
110             }
111         }
112     }
113     if (changed)
114         writemap(player->cnum);
115     free(bitmap);
116     return RET_OK;
117 }
118
119 static void
120 look_ship(struct shpstr *lookship)
121 {
122     struct shpstr *sp;
123     struct mchrstr *smcp;
124     struct mchrstr *tmcp;
125     struct sctstr sect;
126     int range;
127     int vrange;
128     int i;
129     int dist;
130
131     range = (int)techfact(lookship->shp_tech,
132                           mchr[(int)lookship->shp_type].m_vrnge);
133     range = range * (lookship->shp_effic / 100.0);
134     smcp = &mchr[(int)lookship->shp_type];
135     if (smcp->m_flags & M_SUB)
136         range = MIN(range, 1);
137     for (i = 0; NULL != (sp = getshipp(i)); i++) {
138         if (sp->shp_own == player->cnum || sp->shp_own == 0)
139             continue;
140         dist = mapdist(sp->shp_x, sp->shp_y,
141                        lookship->shp_x, lookship->shp_y);
142         if (dist > ship_max_interdiction_range)
143             continue;
144         tmcp = &mchr[(int)sp->shp_type];
145         if (smcp->m_flags & M_SUB)
146             vrange = (int)(sp->shp_visib * range / 30.0);
147         else
148             vrange = (int)(sp->shp_visib * range / 20.0);
149         getsect(sp->shp_x, sp->shp_y, &sect);
150         if (sect.sct_type != SCT_WATER)
151             vrange = MAX(1, vrange);
152         if (dist > vrange)
153             continue;
154         if (smcp->m_flags & M_SUB) {
155             if (tmcp->m_flags & M_SONAR && dist < 2) {
156                 if (sp->shp_own != 0)
157                     wu(0, sp->shp_own,
158                        "%s detected surfacing noises in %s.\n",
159                        prship(sp),
160                        xyas(lookship->shp_x, lookship->shp_y,
161                             sp->shp_own));
162             }
163             if (dist == 0 && (tmcp->m_flags & M_SUB) == 0)
164                 if (sp->shp_own != 0)
165                     wu(0, sp->shp_own,
166                        "Periscope spotted in %s by %s\n",
167                        xyas(lookship->shp_x, lookship->shp_y,
168                             sp->shp_own), prship(sp));
169         }
170         /* subs at sea only seen by sonar */
171         if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
172             continue;
173         pr("%s (#%d) %s @ %s\n",
174            cname(sp->shp_own), sp->shp_own, prship(sp),
175            xyas(sp->shp_x, sp->shp_y, player->cnum));
176         if (opt_HIDDEN)
177             setcont(player->cnum, sp->shp_own, FOUND_LOOK);
178     }
179 }
180
181 int
182 llook(void)
183 {
184     int i;
185     struct nstr_item ni;
186     struct lndstr myland;
187     struct sctstr sect;
188     int x, y;
189     int civ;
190     int mil;
191     unsigned char *bitmap;
192     int changed = 0;
193
194     if (!snxtitem(&ni, EF_LAND, player->argp[1]))
195         return RET_SYN;
196     if ((bitmap = malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
197         logerror("malloc failed in llook\n");
198         pr("Memory error.  Tell the deity.\n");
199         return RET_FAIL;
200     }
201     memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
202     while (nxtitem(&ni, &myland)) {
203         if (!player->owner)
204             continue;
205         if (myland.lnd_ship >= 0)
206             continue;
207         if (myland.lnd_land >= 0)
208             continue;
209         /* Spies don't need military to do a "llook".  Other
210            units do */
211         if ((myland.lnd_item[I_MILIT] <= 0) &&
212             !(lchr[(int)myland.lnd_type].l_flags & L_SPY))
213             continue;
214         look_land(&myland);
215         for (i = 0; i <= 6; i++) {
216             x = diroff[i][0] + myland.lnd_x;
217             y = diroff[i][1] + myland.lnd_y;
218             if (emp_getbit(x, y, bitmap))
219                 continue;
220             emp_setbit(x, y, bitmap);
221             getsect(x, y, &sect);
222             if (sect.sct_type == SCT_WATER)
223                 continue;
224             if (player->owner)
225                 pr("Your ");
226             else
227                 pr("%s (#%d) ", cname(sect.sct_own), sect.sct_own);
228             pr("%s", 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 = sect.sct_item[I_CIVIL];
234             mil = sect.sct_item[I_MILIT];
235             if (civ)
236                 pr("with %s%d civ ", player->owner ? "" :
237                    "approx ", player->owner ? civ : roundintby(civ, 10));
238             if (mil)
239                 pr("with %s%d mil ", player->owner ? "" :
240                    "approx ", player->owner ? mil : roundintby(mil, 10));
241             pr("@ %s\n", xyas(x, y, player->cnum));
242             if (opt_HIDDEN) {
243                 setcont(player->cnum, sect.sct_own, FOUND_LOOK);
244             }
245         }
246     }
247     if (changed)
248         writemap(player->cnum);
249     free(bitmap);
250     return RET_OK;
251 }
252
253 static void
254 look_land(struct lndstr *lookland)
255 {
256     struct plnstr *pp;
257     struct lndstr *lp;
258     double drange;
259     int range;
260     int vrange;
261     int i;
262     int dist;
263
264     drange = techfact(lookland->lnd_tech, lookland->lnd_spy);
265     drange *= lookland->lnd_effic / 100.0;
266     range = ldround(drange, 1);
267
268     if (range == 0)
269         return;
270
271     for (i = 0; NULL != (lp = getlandp(i)); i++) {
272         if (lp->lnd_own == player->cnum || lp->lnd_own == 0)
273             continue;
274         if (lp->lnd_ship >= 0)
275             continue;
276         /* Don't always see spies */
277         if (lchr[(int)lp->lnd_type].l_flags & L_SPY) {
278             /* If it's on a ship or unit, assume it's hidden
279                enough not to be seen */
280             if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
281                 continue;
282             if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic))))
283                 continue;
284         }
285         vrange = ldround((lp->lnd_vis * range) / 20.0, 1);
286         dist = mapdist(lp->lnd_x, lp->lnd_y,
287                        lookland->lnd_x, lookland->lnd_y);
288         if (dist > vrange)
289             continue;
290
291         pr("%s (#%d) %s (approx %d mil) @ %s\n",
292            cname(lp->lnd_own), lp->lnd_own,
293            prland(lp), roundintby(lp->lnd_item[I_MILIT], 20),
294            xyas(lp->lnd_x, lp->lnd_y, player->cnum));
295         if (opt_HIDDEN)
296             setcont(player->cnum, lp->lnd_own, FOUND_LOOK);
297     }
298     for (i = 0; NULL != (pp = getplanep(i)); i++) {
299         if (pp->pln_own == player->cnum || pp->pln_own == 0)
300             continue;
301         if (pp->pln_ship >= 0)
302             continue;
303         if (pp->pln_flags & PLN_LAUNCHED)
304             continue;
305         vrange = ldround((10 * range) / 20.0, 1);
306         dist = mapdist(pp->pln_x, pp->pln_y,
307                        lookland->lnd_x, lookland->lnd_y);
308         if (dist > vrange)
309             continue;
310
311         pr("%s (#%d) %s @ %s\n",
312            cname(pp->pln_own), pp->pln_own,
313            prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum));
314         if (opt_HIDDEN)
315             setcont(player->cnum, pp->pln_own, FOUND_LOOK);
316     }
317 }