src/lib/commands/look.c

Go to the documentation of this file.
00001 /*
00002  *  Empire - A multi-player, client/server Internet based war game.
00003  *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
00004  *                           Ken Stevens, Steve McClure
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  *  ---
00021  *
00022  *  See files README, COPYING and CREDITS in the root of the source
00023  *  tree for related information and legal notices.  It is expected
00024  *  that future projects/authors will amend these files as needed.
00025  *
00026  *  ---
00027  *
00028  *  look.c: Lookout from a ship or land unit
00029  * 
00030  *  Known contributors to this file:
00031  *     Ron Koenderink, 2006-2007
00032  */
00033 
00034 #include <config.h>
00035 
00036 #include "commands.h"
00037 #include "empobj.h"
00038 #include "map.h"
00039 #include "optlist.h"
00040 #include "path.h"
00041 
00042 static void look_ship(struct shpstr *lookship);
00043 static void look_land(struct lndstr *lookland);
00044 
00045 int
00046 look(void)
00047 {
00048     return do_look(EF_SHIP);
00049 }
00050 
00051 int
00052 llook(void)
00053 {
00054     return do_look(EF_LAND);
00055 }
00056 
00057 int
00058 do_look(short type)
00059 {
00060     int i;
00061     struct nstr_item ni;
00062     union empobj_storage unit;
00063     struct sctstr sect;
00064     int x, y;
00065     int civ;
00066     int mil;
00067     unsigned char *bitmap;
00068     int changed = 0;
00069 
00070     if (!snxtitem(&ni, type, player->argp[1]))
00071         return RET_SYN;
00072     if ((bitmap = malloc((WORLD_X * WORLD_Y) / 8)) == 0) {
00073         logerror("malloc failed in do_look\n");
00074         pr("Memory error.  Tell the deity.\n");
00075         return RET_FAIL;
00076     }
00077     memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8);
00078     while (nxtitem(&ni, &unit)) {
00079         if (!player->owner)
00080             continue;
00081         if (type == EF_LAND) {
00082             if (unit.land.lnd_ship >= 0)
00083                 continue;
00084             if (unit.land.lnd_land >= 0)
00085                 continue;
00086             /* Spies don't need military to do a "llook".  Other
00087                units do */
00088             if ((unit.land.lnd_item[I_MILIT] <= 0) &&
00089                 !(lchr[(int)unit.land.lnd_type].l_flags & L_SPY))
00090                 continue;
00091             look_land(&unit.land);
00092         } else
00093             look_ship(&unit.ship);
00094         for (i = 0; i <= 6; i++) {
00095             x = diroff[i][0] + unit.gen.x;
00096             y = diroff[i][1] + unit.gen.y;
00097             if (emp_getbit(x, y, bitmap))
00098                 continue;
00099             emp_setbit(x, y, bitmap);
00100             getsect(x, y, &sect);
00101             if (sect.sct_type == SCT_WATER)
00102                 continue;
00103             if (player->owner)
00104                 pr("Your ");
00105             else
00106                 pr("%s (#%d) ", cname(sect.sct_own), sect.sct_own);
00107             pr("%s", dchr[sect.sct_type].d_name);
00108             changed += map_set(player->cnum, x, y,
00109                                dchr[sect.sct_type].d_mnem, 0);
00110             pr(" %d%% efficient ", player->owner ? sect.sct_effic :
00111                roundintby((int)sect.sct_effic, 10));
00112             civ = sect.sct_item[I_CIVIL];
00113             mil = sect.sct_item[I_MILIT];
00114             if (civ)
00115                 pr("with %s%d civ ",
00116                    player->owner ? "" : "approx ",
00117                    player->owner ? civ : roundintby(civ, 10));
00118             if (mil)
00119                 pr("with %s%d mil ",
00120                    player->owner ? "" : "approx ",
00121                    player->owner ? mil : roundintby(mil, 10));
00122             pr("@ %s\n", xyas(x, y, player->cnum));
00123             if (opt_HIDDEN) {
00124                 setcont(player->cnum, sect.sct_own, FOUND_LOOK);
00125             }
00126         }
00127     }
00128     if (changed)
00129         writemap(player->cnum);
00130     free(bitmap);
00131     return RET_OK;
00132 }
00133 
00134 static void
00135 look_ship(struct shpstr *lookship)
00136 {
00137     struct shpstr *sp;
00138     struct mchrstr *smcp;
00139     struct mchrstr *tmcp;
00140     struct sctstr sect;
00141     int range;
00142     int vrange;
00143     int i;
00144     int dist;
00145 
00146     range = (int)techfact(lookship->shp_tech,
00147                           mchr[(int)lookship->shp_type].m_vrnge);
00148     range = range * (lookship->shp_effic / 100.0);
00149     smcp = &mchr[(int)lookship->shp_type];
00150     if (smcp->m_flags & M_SUB)
00151         range = MIN(range, 1);
00152     for (i = 0; NULL != (sp = getshipp(i)); i++) {
00153         if (sp->shp_own == player->cnum || sp->shp_own == 0)
00154             continue;
00155         dist = mapdist(sp->shp_x, sp->shp_y,
00156                        lookship->shp_x, lookship->shp_y);
00157         if (dist > ship_max_interdiction_range)
00158             continue;
00159         tmcp = &mchr[(int)sp->shp_type];
00160         if (smcp->m_flags & M_SUB)
00161             vrange = (int)(sp->shp_visib * range / 30.0);
00162         else
00163             vrange = (int)(sp->shp_visib * range / 20.0);
00164         getsect(sp->shp_x, sp->shp_y, &sect);
00165         if (sect.sct_type != SCT_WATER)
00166             vrange = MAX(1, vrange);
00167         if (dist > vrange)
00168             continue;
00169         if (smcp->m_flags & M_SUB) {
00170             if (tmcp->m_flags & M_SONAR && dist < 2) {
00171                 if (sp->shp_own != 0)
00172                     wu(0, sp->shp_own,
00173                        "%s detected surfacing noises in %s.\n",
00174                        prship(sp),
00175                        xyas(lookship->shp_x, lookship->shp_y,
00176                             sp->shp_own));
00177             }
00178             if (dist == 0 && (tmcp->m_flags & M_SUB) == 0)
00179                 if (sp->shp_own != 0)
00180                     wu(0, sp->shp_own,
00181                        "Periscope spotted in %s by %s\n",
00182                        xyas(lookship->shp_x, lookship->shp_y,
00183                             sp->shp_own), prship(sp));
00184         }
00185         /* subs at sea only seen by sonar */
00186         if (tmcp->m_flags & M_SUB && sect.sct_type == SCT_WATER)
00187             continue;
00188         pr("%s (#%d) %s @ %s\n",
00189            cname(sp->shp_own), sp->shp_own, prship(sp),
00190            xyas(sp->shp_x, sp->shp_y, player->cnum));
00191         if (opt_HIDDEN)
00192             setcont(player->cnum, sp->shp_own, FOUND_LOOK);
00193     }
00194 }
00195 
00196 static void
00197 look_land(struct lndstr *lookland)
00198 {
00199     struct plnstr *pp;
00200     struct lndstr *lp;
00201     double drange;
00202     int range;
00203     int vrange;
00204     int i;
00205     int dist;
00206 
00207     drange = techfact(lookland->lnd_tech, lookland->lnd_spy);
00208     drange *= lookland->lnd_effic / 100.0;
00209     range = ldround(drange, 1);
00210 
00211     if (range == 0)
00212         return;
00213 
00214     for (i = 0; NULL != (lp = getlandp(i)); i++) {
00215         if (lp->lnd_own == player->cnum || lp->lnd_own == 0)
00216             continue;
00217         if (lp->lnd_ship >= 0)
00218             continue;
00219         /* Don't always see spies */
00220         if (lchr[(int)lp->lnd_type].l_flags & L_SPY) {
00221             /* If it's on a ship or unit, assume it's hidden
00222                enough not to be seen */
00223             if (lp->lnd_ship >= 0 || lp->lnd_land >= 0)
00224                 continue;
00225             if (!(chance(LND_SPY_DETECT_CHANCE(lp->lnd_effic))))
00226                 continue;
00227         }
00228         vrange = ldround((lp->lnd_vis * range) / 20.0, 1);
00229         dist = mapdist(lp->lnd_x, lp->lnd_y,
00230                        lookland->lnd_x, lookland->lnd_y);
00231         if (dist > vrange)
00232             continue;
00233 
00234         pr("%s (#%d) %s (approx %d mil) @ %s\n",
00235            cname(lp->lnd_own), lp->lnd_own,
00236            prland(lp), roundintby(lp->lnd_item[I_MILIT], 20),
00237            xyas(lp->lnd_x, lp->lnd_y, player->cnum));
00238         if (opt_HIDDEN)
00239             setcont(player->cnum, lp->lnd_own, FOUND_LOOK);
00240     }
00241     for (i = 0; NULL != (pp = getplanep(i)); i++) {
00242         if (pp->pln_own == player->cnum || pp->pln_own == 0)
00243             continue;
00244         if (pp->pln_ship >= 0)
00245             continue;
00246         if (pp->pln_flags & PLN_LAUNCHED)
00247             continue;
00248         vrange = ldround((10 * range) / 20.0, 1);
00249         dist = mapdist(pp->pln_x, pp->pln_y,
00250                        lookland->lnd_x, lookland->lnd_y);
00251         if (dist > vrange)
00252             continue;
00253 
00254         pr("%s (#%d) %s @ %s\n",
00255            cname(pp->pln_own), pp->pln_own,
00256            prplane(pp), xyas(pp->pln_x, pp->pln_y, player->cnum));
00257         if (opt_HIDDEN)
00258             setcont(player->cnum, pp->pln_own, FOUND_LOOK);
00259     }
00260 }

Generated on Fri Mar 28 11:01:12 2008 for empserver by  doxygen 1.5.2