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