]> git.pond.sub.org Git - empserver/blob - src/lib/subs/landgun.c
Factor out common torpedo fire code into shp_torp()
[empserver] / src / lib / subs / landgun.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2008, 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 files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  landgun.c: Return values for land and ship gun firing damages
29  * 
30  *  Known contributors to this file:
31  *     Markus Armbruster, 2006
32  */
33
34 #include <config.h>
35
36 #include "damage.h"
37 #include "file.h"
38 #include "nat.h"
39 #include "optlist.h"
40 #include "prototypes.h"
41 #include "sect.h"
42 #include "ship.h"
43
44 double
45 fortgun(int effic, int guns)
46 {
47     double d;
48     double g = MIN(guns, 7);
49
50     d = (random() % 30 + 20.0) * (g / 7.0);
51     d *= effic / 100.0;
52     return d;
53 }
54
55 double
56 seagun(int effic, int guns)
57 {
58     double d;
59
60     d = 0.0;
61     while (guns--)
62         d += 10.0 + random() % 6;
63     d *= effic * 0.01;
64     return d;
65 }
66
67 double
68 landunitgun(int effic, int shots, int guns, int ammo, int shells)
69 {
70     double d = 0.0;
71
72     shots = MIN(shots, guns);
73     while (shots-- > 0)
74         d += 5.0 + random() % 6;
75     d *= effic * 0.01;
76     if (shells < ammo && ammo != 0)
77         d *= (double)shells / (double)ammo;
78     return d;
79 }
80
81 /*
82  * Fire from fortress SP.
83  * Use ammo, resupply if necessary.
84  * Return damage if the fortress fires, else -1.
85  */
86 int
87 fort_fire(struct sctstr *sp)
88 {
89     int guns = sp->sct_item[I_GUN];
90     int shells;
91
92     if (sp->sct_type != SCT_FORTR || sp->sct_effic < FORTEFF)
93         return -1;
94     if (sp->sct_item[I_MILIT] < 5 || guns == 0)
95         return -1;
96     shells = sp->sct_item[I_SHELL];
97     shells += supply_commod(sp->sct_own, sp->sct_x, sp->sct_y,
98                             I_SHELL, 1 - shells);
99     if (shells == 0)
100         return -1;
101     sp->sct_item[I_SHELL] = shells - 1;
102     return (int)fortgun(sp->sct_effic, guns);
103 }
104
105 /*
106  * Fire from ship SP.
107  * Use ammo, resupply if necessary.
108  * Return damage if the ship fires, else -1.
109  */
110 int
111 shp_fire(struct shpstr *sp)
112 {
113     int guns, shells;
114
115     if (sp->shp_effic < 60)
116         return -1;
117     guns = sp->shp_glim;
118     guns = MIN(guns, sp->shp_item[I_GUN]);
119     guns = MIN(guns, (sp->shp_item[I_MILIT] + 1) / 2);
120     if (guns == 0)
121         return -1;
122     shells = sp->shp_item[I_SHELL];
123     shells += supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
124                            I_SHELL, (guns + 1) / 2 - shells);
125     guns = MIN(guns, shells * 2);
126     if (guns == 0)
127        return -1;
128     sp->shp_item[I_SHELL] = shells - (guns + 1) / 2;
129     return (int)seagun(sp->shp_effic, guns);
130 }
131
132 /*
133  * Drop depth-charges from ship SP.
134  * Use ammo, resupply if necessary.
135  * Return damage if the ship drops depth-charges, else -1.
136  */
137 int
138 shp_dchrg(struct shpstr *sp)
139 {
140     int shells;
141
142     if (sp->shp_effic < 60 || (mchr[sp->shp_type].m_flags & M_DCH) == 0)
143         return -1;
144     if (sp->shp_item[I_MILIT] == 0)
145         return -1;
146     shells = sp->shp_item[I_SHELL];
147     shells += supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
148                            I_SHELL, 2 - shells);
149     if (shells < 2)
150        return -1;
151     sp->shp_item[I_SHELL] = shells - 2;
152     return (int)seagun(sp->shp_effic, 3);
153 }
154
155 /*
156  * Fire torpedo from ship SP.
157  * Use ammo and mobility, resupply if necessary.
158  * Return damage if the ship fires, else -1.
159  */
160 int
161 shp_torp(struct shpstr *sp, int usemob)
162 {
163     int shells;
164
165     if (sp->shp_effic < 60 || (mchr[sp->shp_type].m_flags & M_TORP) == 0)
166         return -1;
167     if (sp->shp_item[I_MILIT] == 0 || sp->shp_item[I_GUN] == 0)
168         return -1;
169     if (usemob && sp->shp_mobil <= 0)
170         return -1;
171     shells = sp->shp_item[I_SHELL];
172     shells += supply_commod(sp->shp_own, sp->shp_x, sp->shp_y,
173                            I_SHELL, SHP_TORP_SHELLS - shells);
174     if (shells < SHP_TORP_SHELLS)
175        return -1;
176     sp->shp_item[I_SHELL] = shells - SHP_TORP_SHELLS;
177     if (usemob)
178         sp->shp_mobil -= (int)shp_mobcost(sp) / 2.0;
179     return TORP_DAMAGE();
180 }
181
182 /*
183  * Return effective firing range for range factor RNG at tech TLEV.
184  */
185 double
186 effrange(int rng, double tlev)
187 {
188     /* FIXME don't truncate TLEV */
189     return techfact((int)tlev, rng / 2.0);
190 }
191
192 /*
193  * Return torpedo range for ship SP.
194  */
195 double
196 torprange(struct shpstr *sp)
197 {
198     return effrange(sp->shp_frnge * 2, sp->shp_tech)
199         * sp->shp_effic / 100.0;
200 }
201
202 /*
203  * Return firing range for sector SP.
204  */
205 double
206 fortrange(struct sctstr *sp)
207 {
208     struct natstr *np = getnatp(sp->sct_own);
209     double rng;
210
211     if (sp->sct_type != SCT_FORTR || sp->sct_effic < FORTEFF)
212         return -1.0;
213
214     rng = effrange(14.0 * fire_range_factor, np->nat_level[NAT_TLEV]);
215     if (sp->sct_effic > 59)
216         rng++;
217     return rng;
218 }
219
220 int
221 roundrange(double r)
222 {
223     return roundavg(r);
224 }