]> git.pond.sub.org Git - empserver/blob - src/lib/commands/look.c
(bzero, bcopy): Obsolete BSDisms; remove. Remove some calls without
[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     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 = getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR);
96             mil = getvar(V_MILIT, (s_char *)&sect, EF_SECTOR);
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     extern int ship_max_interdiction_range;
122     struct sctstr sect;
123     int range;
124     int vrange;
125     int i;
126     int dist;
127
128     range = (int)techfact(lookship->shp_tech,
129                           (double)mchr[(int)lookship->shp_type].m_vrnge);
130     range = range * (lookship->shp_effic / 100.0);
131     smcp = &mchr[(int)lookship->shp_type];
132     if (smcp->m_flags & M_SUB)
133         range = min(range, 1);
134     for (i = 0; NULL != (sp = getshipp(i)); i++) {
135         if (sp->shp_own == player->cnum || sp->shp_own == 0)
136             continue;
137         dist = mapdist(sp->shp_x, sp->shp_y,
138                        lookship->shp_x, lookship->shp_y);
139         if (dist > ship_max_interdiction_range)
140             continue;
141         tmcp = &mchr[(int)sp->shp_type];
142         if (smcp->m_flags & M_SUB)
143             vrange = (int)(sp->shp_visib * range / 30.0);
144         else
145             vrange = (int)(sp->shp_visib * range / 20.0);
146         getsect(sp->shp_x, sp->shp_y, &sect);
147         if (sect.sct_type != SCT_WATER)
148             vrange = max(1, vrange);
149         if (dist > vrange)
150             continue;
151         if (smcp->m_flags & M_SUB) {
152             if (tmcp->m_flags & M_SONAR && dist < 2) {
153                 if (sp->shp_own != 0)
154                     wu(0, sp->shp_own,
155                        "%s detected surfacing noises in %s.\n",
156                        prship(sp),
157                        xyas(lookship->shp_x, lookship->shp_y,
158                             sp->shp_own));
159             }
160             if (dist == 0 && (tmcp->m_flags & M_SUB) == 0)
161                 if (sp->shp_own != 0)
162                     wu(0, sp->shp_own,
163                        "Periscope spotted in %s by %s\n",
164                        xyas(lookship->shp_x, lookship->shp_y,
165                             sp->shp_own), prship(sp));
166         }
167         /* subs at sea only seen by sonar */
168         if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
169             continue;
170         pr("%s (#%d) %s @ %s\n",
171            cname(sp->shp_own), sp->shp_own, prship(sp),
172            xyas(sp->shp_x, sp->shp_y, player->cnum));
173     }
174 }
175
176 static void look_land(register struct lndstr *lookland);
177
178 int
179 llook(void)
180 {
181     register int i;
182     struct nstr_item ni;
183     struct lndstr myland;
184     struct sctstr sect;
185     int x, y;
186     int civ;
187     int mil;
188     u_char *bitmap;
189     int changed = 0;
190
191     if (!snxtitem(&ni, EF_LAND, player->argp[1]))
192         return RET_SYN;
193     if ((bitmap = (u_char *)malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
194         logerror("malloc failed in llook\n");
195         pr("Memory error.  Tell the deity.\n");
196         return RET_FAIL;
197     }
198     memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
199     while (nxtitem(&ni, (s_char *)&myland)) {
200         if (!player->owner)
201             continue;
202         if (myland.lnd_ship >= 0)
203             continue;
204         if (myland.lnd_land >= 0)
205             continue;
206         /* Spies don't need military to do a "llook".  Other
207            units do */
208         if ((lnd_getmil(&myland) <= 0) &&
209             !(lchr[(int)myland.lnd_type].l_flags & L_SPY))
210             continue;
211         look_land(&myland);
212         for (i = 0; i <= 6; i++) {
213             x = diroff[i][0] + myland.lnd_x;
214             y = diroff[i][1] + myland.lnd_y;
215             if (emp_getbit(x, y, bitmap))
216                 continue;
217             emp_setbit(x, y, bitmap);
218             getsect(x, y, &sect);
219             if (sect.sct_type == SCT_WATER)
220                 continue;
221             if (player->owner)
222                 pr("Your ");
223             else
224                 pr("%s (#%d) ", cname(sect.sct_own), sect.sct_own);
225             pr(dchr[sect.sct_type].d_name);
226             changed += map_set(player->cnum, x, y,
227                                dchr[sect.sct_type].d_mnem, 0);
228             pr(" %d%% efficient ", player->owner ? sect.sct_effic :
229                roundintby((int)sect.sct_effic, 10));
230             civ = getvar(V_CIVIL, (s_char *)&sect, EF_SECTOR);
231             mil = getvar(V_MILIT, (s_char *)&sect, EF_SECTOR);
232             if (civ)
233                 pr("with %s%d civ ", player->owner ? "" :
234                    "approx ", player->owner ? civ : roundintby(civ, 10));
235             if (mil)
236                 pr("with %s%d mil ", player->owner ? "" :
237                    "approx ", player->owner ? mil : roundintby(mil, 10));
238             pr("@ %s\n", xyas(x, y, player->cnum));
239             if (opt_HIDDEN) {
240                 setcont(player->cnum, sect.sct_own, FOUND_LOOK);
241             }
242         }
243     }
244     if (changed)
245         writemap(player->cnum);
246     free((s_char *)bitmap);
247     return RET_OK;
248 }
249
250 static void
251 look_land(register struct lndstr *lookland)
252 {
253     register struct plnstr *pp;
254     register struct lndstr *lp;
255     double drange;
256     int range;
257     int vrange;
258     int i;
259     int dist;
260     double techfact(int, double);
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     }
294     for (i = 0; NULL != (pp = getplanep(i)); i++) {
295         if (pp->pln_own == player->cnum || pp->pln_own == 0)
296             continue;
297         if (pp->pln_ship >= 0)
298             continue;
299         if (pp->pln_flags & PLN_LAUNCHED)
300             continue;
301         vrange = ldround((double)((10 * range) / 20.0), 1);
302         dist = mapdist(pp->pln_x, pp->pln_y,
303                        lookland->lnd_x, lookland->lnd_y);
304         if (dist > vrange)
305             continue;
306
307         pr("%s (#%d) %s @ %s\n",
308            cname(pp->pln_own), pp->pln_own,
309            prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum));
310     }
311 }