src/lib/subs/fortdef.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  *  fortdef.c: Fort defends an area.
00029  * 
00030  *  Known contributors to this file:
00031  *    
00032  */
00033 
00034 /*
00035  * The base routines can also be used for general purposes.
00036  * Noisy tells whther to send teles, print things, etc.
00037  * Defending tells whether they are being defensive, or offensive.
00038  */
00039 
00040 #include <config.h>
00041 
00042 #include "file.h"
00043 #include "nat.h"
00044 #include "news.h"
00045 #include "optlist.h"
00046 #include "prototypes.h"
00047 #include "sect.h"
00048 #include "ship.h"
00049 
00050 #define NOISY   1
00051 
00052 static int sb(natid, natid, struct sctstr *, coord, coord, int, int);
00053 
00054 /*
00055  * See if any nearby ships will open up on the attacker
00056  * Return damage done to attacker, if any.
00057  * Subtracts shells used for firing.  Responding ships
00058  * require military, shells, and guns.
00059  */
00060 int
00061 shipdef(natid att, natid own, coord x, coord y)
00062 {
00063     return sd(att, own, x, y, NOISY, 1, 1);
00064 }
00065 
00066 int
00067 sd(natid att, natid own, coord x, coord y, int noisy, int defending,
00068    int usesubs)
00069 {
00070     int nshot;
00071     int range;
00072     double eff;
00073     struct shpstr ship;
00074     struct nstr_item ni;
00075     int shell;
00076     int dam, rel, rel2;
00077 
00078     if (own == 0)
00079         return 0;
00080     if (att == own)
00081         return 0;
00082     eff = 1.0;
00083     snxtitem_dist(&ni, EF_SHIP, x, y, 8);
00084     while (nxtitem(&ni, &ship) && eff > 0.30) {
00085         if (ship.shp_own == att)
00086             continue;
00087         if (ship.shp_own == 0)
00088             continue;
00089 
00090         rel = getrel(getnatp(ship.shp_own), own);
00091         rel2 = getrel(getnatp(ship.shp_own), att);
00092         if ((ship.shp_own != own) && ((rel != ALLIED) || (rel2 != AT_WAR)))
00093             continue;
00094         if (ship.shp_effic < 60)
00095             continue;
00096         if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && !usesubs)
00097             continue;
00098         range = roundrange(effrange(ship.shp_frnge, ship.shp_tech));
00099         if (range < ni.curdist)
00100             continue;
00101         /* must have gun, shell, and milit to fire */
00102         shell = ship.shp_item[I_SHELL];
00103         if (shell < ship.shp_glim)
00104             shell += supply_commod(ship.shp_own, ship.shp_x, ship.shp_y,
00105                                    I_SHELL, shell - ship.shp_glim);
00106         nshot = MIN(MIN(ship.shp_item[I_GUN], shell), ship.shp_item[I_MILIT]);
00107         nshot = MIN(nshot, ship.shp_glim);
00108         if (nshot <= 0)
00109             continue;
00110         ship.shp_item[I_SHELL] = shell - nshot;
00111         putship(ship.shp_uid, &ship);
00112         if (defending)
00113             nreport(ship.shp_own, N_FIRE_BACK, att, 1);
00114         else
00115             nreport(ship.shp_own, N_FIRE_S_ATTACK, att, 1);
00116         dam = seagun(ship.shp_effic, nshot);
00117         eff *= (1.0 - (0.01 * dam));
00118         if (noisy) {
00119             pr_beep();
00120             pr("Incoming shell%s %d damage!\n",
00121                nshot == 1 ? " does" : "s do", dam);
00122         }
00123         if (noisy || (ship.shp_own != own)) {
00124             if (ship.shp_own == own)
00125                 wu(0, own, "%s fired on %s at %s doing %d damage.\n",
00126                    prship(&ship), cname(att), xyas(x, y, own), dam);
00127             else {
00128                 if (defending)
00129                     wu(0, ship.shp_own,
00130                        "%s fired on %s at %s in defense of %s, doing %d damage.\n",
00131                        prship(&ship), cname(att), xyas(x, y, ship.shp_own),
00132                        cname(own), dam);
00133                 else
00134                     wu(0, ship.shp_own,
00135                        "%s supported %s attacks against %s at %s, doing %d damage.\n",
00136                        prship(&ship), cname(own), cname(att),
00137                        xyas(x, y, ship.shp_own), dam);
00138             }
00139         }
00140     }
00141     return (int)(100 - eff * 100);
00142 }
00143 
00144 int
00145 dd(natid att, natid def_own, coord ax, coord ay, int noisy, int defending)
00146 {
00147     int dam, rel, rel2;
00148     struct sctstr firing;
00149     struct nstr_sect ns;
00150 
00151     if (opt_NO_FORT_FIRE)       /* Forts can't fire! */
00152         return 0;
00153     if (def_own == 0)
00154         return 0;
00155     if (att == def_own)
00156         return 0;
00157     dam = 0;
00158     snxtsct_dist(&ns, ax, ay, 8);
00159     while (nxtsct(&ns, &firing) && dam < 80) {
00160         if (firing.sct_own == att)
00161             continue;
00162         if (firing.sct_own == 0)
00163             continue;
00164         rel = getrel(getnatp(firing.sct_own), def_own);
00165         rel2 = getrel(getnatp(firing.sct_own), att);
00166         if (firing.sct_own != def_own && (rel != ALLIED || rel2 != AT_WAR))
00167             continue;
00168         /* XXX defdef damage is additive, but ship or land unit damage isn't */
00169         dam += sb(att, def_own, &firing, ax, ay, noisy, defending);
00170     }
00171     return dam;
00172 }
00173 
00174 /* Shoot back
00175  *
00176  * See if the sector being fired at will defend itself.
00177  */
00178 static int
00179 sb(natid att, natid def, struct sctstr *sp, coord tx, coord ty, int noisy,
00180    int defending)
00181 {
00182     int damage;
00183     natid own;
00184     int shell;
00185     int range;
00186     int range2, gun;
00187 
00188     own = sp->sct_own;
00189     if (own == 0)
00190         return 0;
00191     if (att == own)
00192         return 0;
00193     range = roundrange(fortrange(sp));
00194     range2 = mapdist(sp->sct_x, sp->sct_y, tx, ty);
00195     if (range < range2)
00196         return 0;
00197     gun = sp->sct_item[I_GUN];
00198     if (gun == 0)
00199         return 0;
00200     shell = sp->sct_item[I_SHELL];
00201     if (shell <= 0)
00202         shell += supply_commod(sp->sct_own, sp->sct_x, sp->sct_y,
00203                                I_SHELL, 1);
00204     if (shell <= 0)
00205         return 0;
00206     sp->sct_item[I_SHELL] = shell - 1;
00207     putsect(sp);
00208     damage = landgun((int)sp->sct_effic, gun);
00209     if (sp->sct_own != def)
00210         wu(0, sp->sct_own,
00211            "%s fired on %s in %s in defense of %s, doing %d damage!\n",
00212            xyas(sp->sct_x, sp->sct_y, sp->sct_own), cname(att),
00213            xyas(tx, ty, sp->sct_own), cname(def), damage);
00214     if (defending)
00215         nreport(sp->sct_own, N_FIRE_BACK, att, 1);
00216     else
00217         nreport(sp->sct_own, N_FIRE_F_ATTACK, att, 1);
00218     if (noisy)
00219         pr("Incoming shell! %d damage done.\007\n", damage);
00220     return damage;
00221 }

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