]> git.pond.sub.org Git - empserver/blob - src/lib/subs/fortdef.c
Indented with src/scripts/indent-emp.
[empserver] / src / lib / subs / fortdef.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  *  fortdef.c: Fort defends an area.
29  * 
30  *  Known contributors to this file:
31  *    
32  */
33 /*
34  * The base routines can also be used for general purposes.
35  * Noisy tells whther to send teles, print things, etc.
36  * Defending tells whether they are being defensive, or offensive.
37  */
38
39 #include "misc.h"
40 #include "var.h"
41 #include "xy.h"
42 #include "nat.h"
43 #include "sect.h"
44 #include "ship.h"
45 #include "land.h"
46 #include "news.h"
47 #include "nsc.h"
48 #include "file.h"
49 #include "options.h"
50 #include "optlist.h"
51 #include "prototypes.h"
52
53 #define QUIET   0
54 #define NOISY   1
55
56 extern double tfactfire(natid, double);
57
58 /*
59  * See if any nearby ships will open up on the attacker
60  * Return damage done to attacker, if any.
61  * Subtracts shells used for firing.  Responding ships
62  * require military, shells, and guns.
63  */
64 int
65 shipdef(natid att, natid own, coord x, coord y)
66 {
67     return sd(att, own, x, y, NOISY, 1, 1);
68 }
69
70 int
71 sd(natid att, natid own, coord x, coord y, int noisy, int defending,
72    int usesubs)
73 {
74     int nshot;
75     double range;
76     double eff;
77     struct shpstr ship;
78     struct nstr_item ni;
79     int vec[I_MAX + 1];
80     int dam, rel, rel2;
81
82     if (own == 0)
83         return 0;
84     if (att == own)
85         return 0;
86     eff = 1.0;
87     snxtitem_dist(&ni, EF_SHIP, x, y, 8);
88     while (nxtitem(&ni, (caddr_t)&ship) && eff > 0.30) {
89         if (ship.shp_own == att)
90             continue;
91         if (ship.shp_own == 0)
92             continue;
93
94         rel = getrel(getnatp(ship.shp_own), own);
95         rel2 = getrel(getnatp(ship.shp_own), att);
96         if ((ship.shp_own != own) && ((rel != ALLIED) || (rel2 != AT_WAR)))
97             continue;
98         if (ship.shp_effic < 60)
99             continue;
100         if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && (!usesubs))
101             continue;
102         range = techfact(ship.shp_tech,
103                          ship.shp_frnge * ship.shp_effic / 200.0);
104         range = (double)roundrange(range);
105         if (range < ni.curdist)
106             continue;
107         /* must have gun, shell, and milit to fire */
108         if (getvec(VT_ITEM, vec, (caddr_t)&ship, EF_SHIP) < 3)
109             continue;
110         if (vec[I_SHELL] < ship.shp_glim)
111             vec[I_SHELL] += supply_commod(ship.shp_own, ship.shp_x,
112                                           ship.shp_y, I_SHELL,
113                                           vec[I_SHELL] - ship.shp_glim);
114         nshot = min(min(vec[I_GUN], vec[I_SHELL]), vec[I_MILIT]);
115         nshot = min(nshot, ship.shp_glim);
116         if (nshot <= 0)
117             continue;
118         (void)putvar(V_SHELL, vec[I_SHELL] - nshot, (caddr_t)&ship,
119                      EF_SHIP);
120         putship(ship.shp_uid, &ship);
121         if (defending)
122             nreport(ship.shp_own, N_FIRE_BACK, att, 1);
123         else
124             nreport(ship.shp_own, N_FIRE_S_ATTACK, att, 1);
125         dam = seagun(ship.shp_effic, nshot);
126         eff *= (1.0 - (0.01 * dam));
127         if (noisy) {
128             pr_beep();
129             pr("Incoming shell%s %d damage!\n",
130                nshot == 1 ? " does" : "s do", dam);
131         }
132         if (noisy || (ship.shp_own != own)) {
133             if (ship.shp_own == own)
134                 wu(0, own, "%s fired on %s at %s doing %d damage.\n",
135                    prship(&ship), cname(att), xyas(x, y, own), dam);
136             else {
137                 if (defending)
138                     wu(0, ship.shp_own,
139                        "%s fired on %s at %s in defense of %s, doing %d damage.\n",
140                        prship(&ship), cname(att), xyas(x, y, ship.shp_own),
141                        cname(own), dam);
142                 else
143                     wu(0, ship.shp_own,
144                        "%s supported %s attacks against %s at %s, doing %d damage.\n",
145                        prship(&ship), cname(own), cname(att), xyas(x, y,
146                                                                    ship.
147                                                                    shp_own),
148                        dam);
149             }
150         }
151     }
152     return (int)100 - (eff * 100);
153 }
154
155 /*
156  * Determine if any nearby gun-equipped sectors are within
157  * range and able to fire at an attacker.  Firing sectors
158  * need to have guns, shells, and military.  Sector being
159  * attacked is x,y -- attacker is at ax,ay.
160  */
161 #if 0
162 /* defdef isn't called anywhere, and uses wrong
163  * number of arguments for dd */
164 int
165 defdef(att, def_own, defval, ax, ay)
166 natid att;
167 natid def_own;
168 int defval;
169 coord ax;
170 coord ay;
171 {
172     return dd(att, def_own, defval, ax, ay, NOISY, 1);
173 }
174 #endif
175
176 int
177 dd(natid att, natid def_own, coord ax, coord ay, int noisy, int defending)
178 {
179     int dam, rel, rel2;
180     double tech;
181     double range;
182     struct sctstr firing;
183     struct nstr_sect ns;
184     int vec[I_MAX + 1];
185
186     if (opt_NO_FORT_FIRE)       /* Forts can't fire! */
187         return 0;
188     if (def_own == 0)
189         return 0;
190     if (att == def_own)
191         return 0;
192     tech = tfactfire(def_own, 1.0);
193     dam = 0;
194     snxtsct_dist(&ns, ax, ay, 8);
195     while (nxtsct(&ns, &firing) && dam < 80) {
196         if (firing.sct_own == att)
197             continue;
198         if (firing.sct_own == 0)
199             continue;
200         if (firing.sct_effic < (u_char)FORTEFF)
201             continue;
202         rel = getrel(getnatp(firing.sct_own), def_own);
203         rel2 = getrel(getnatp(firing.sct_own), att);
204         if ((firing.sct_own != def_own) &&
205             ((rel != ALLIED) || (rel2 != AT_WAR)))
206             continue;
207         if (getvec(VT_ITEM, vec, (caddr_t)&firing, EF_SECTOR) < 0)
208             continue;
209
210         range = tfactfire(def_own, 7.0);
211         if (firing.sct_effic > 59)
212             range++;
213         /* Here we round down the range, and then add 1 to it
214            to determine if we could possibly hit the sector.  If
215            we do, we call sb where the range is re-calculated and
216            the percentages are checked. */
217         range = (double)((int)(range) + 1);
218         if (range < ns.curdist)
219             continue;
220         /* XXX defdef damage is additive, but ship or land unit damage isn't */
221         dam += sb(att, def_own, &firing, ax, ay, noisy, defending);
222     }
223     return dam;
224 }
225
226 /* Shoot back
227  *
228  * See if the sector being fired at will defend itself.
229  */
230 int
231 sb(natid att, natid def, struct sctstr *sp, coord tx, coord ty, int noisy,
232    int defending)
233 {
234     register int damage;
235     natid own;
236     int shell;
237     double range;
238     int range2, gun;
239
240     if (sp->sct_type != SCT_FORTR) {
241         /* XXX I don't like this restriction */
242         return 0;
243     }
244
245     if (sp->sct_effic < (u_char)FORTEFF)
246         return 0;
247
248     own = sp->sct_own;
249     if (own == 0)
250         return 0;
251     if (att == own)
252         return 0;
253     range = tfactfire(own, 7.0);
254     if (sp->sct_effic > 59)
255         range++;
256     range = (double)roundrange(range);
257     range2 = mapdist((int)sp->sct_x, (int)sp->sct_y, tx, ty);
258     if (range < range2)
259         return 0;
260     gun = getvar(V_GUN, (caddr_t)sp, EF_SECTOR);
261     if (gun == 0)
262         return 0;
263     shell = getvar(V_SHELL, (caddr_t)sp, EF_SECTOR);
264     if (shell <= 0)
265         shell += supply_commod(sp->sct_own, sp->sct_x, sp->sct_y, I_SHELL,
266                                1);
267     if (shell <= 0)
268         return 0;
269     putvar(V_SHELL, shell - 1, (caddr_t)sp, EF_SECTOR);
270     putsect(sp);
271     damage = landgun((int)sp->sct_effic, gun);
272     if (sp->sct_own != def)
273         wu(0, sp->sct_own,
274            "%s fired on %s in %s in defense of %s, doing %d damage!\n",
275            xyas(sp->sct_x, sp->sct_y, sp->sct_own), cname(att), xyas(tx,
276                                                                      ty,
277                                                                      sp->
278                                                                      sct_own),
279            cname(def), damage);
280     if (defending)
281         nreport(sp->sct_own, N_FIRE_BACK, att, 1);
282     else
283         nreport(sp->sct_own, N_FIRE_F_ATTACK, att, 1);
284     if (noisy)
285         pr("Incoming shell! %d damage done.\007\n", damage);
286     return damage;
287 }