]> git.pond.sub.org Git - empserver/blob - src/lib/subs/fortdef.c
License upgrade to GPL version 3 or later
[empserver] / src / lib / subs / fortdef.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2011, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  fortdef.c: Fort defends an area.
28  *
29  *  Known contributors to this file:
30  *
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 <config.h>
40
41 #include "file.h"
42 #include "nat.h"
43 #include "news.h"
44 #include "optlist.h"
45 #include "prototypes.h"
46 #include "sect.h"
47 #include "ship.h"
48
49 #define NOISY   1
50
51 static int sb(natid, natid, struct sctstr *, coord, coord, int, int);
52
53 /*
54  * See if any nearby ships will open up on the attacker
55  * Return damage done to attacker, if any.
56  * Subtracts shells used for firing.  Responding ships
57  * require military, shells, and guns.
58  */
59 int
60 shipdef(natid att, natid own, coord x, coord y)
61 {
62     return sd(att, own, x, y, NOISY, 1, 1);
63 }
64
65 int
66 sd(natid att, natid own, coord x, coord y, int noisy, int defending,
67    int usesubs)
68 {
69     int range;
70     double eff;
71     struct shpstr ship;
72     struct nstr_item ni;
73     int dam;
74
75     if (own == 0)
76         return 0;
77     if (att == own)
78         return 0;
79     eff = 1.0;
80     snxtitem_dist(&ni, EF_SHIP, x, y, 8);
81     while (nxtitem(&ni, &ship) && eff > 0.30) {
82         if (!feels_like_helping(ship.shp_own, own, att))
83             continue;
84
85         if ((mchr[(int)ship.shp_type].m_flags & M_SUB) && !usesubs)
86             continue;
87         range = roundrange(shp_fire_range(&ship));
88         if (range < ni.curdist)
89             continue;
90         dam = shp_fire(&ship);
91         putship(ship.shp_uid, &ship);
92         if (dam < 0)
93             continue;
94         if (defending)
95             nreport(ship.shp_own, N_FIRE_BACK, att, 1);
96         else
97             nreport(ship.shp_own, N_FIRE_S_ATTACK, att, 1);
98         eff *= (1.0 - (0.01 * dam));
99         if (noisy) {
100             pr_beep();
101             pr("Incoming shells do %d damage!\n", dam);
102         }
103         if (noisy || (ship.shp_own != own)) {
104             if (ship.shp_own == own)
105                 wu(0, own, "%s fired on %s at %s doing %d damage.\n",
106                    prship(&ship), cname(att), xyas(x, y, own), dam);
107             else {
108                 if (defending)
109                     wu(0, ship.shp_own,
110                        "%s fired on %s at %s in defense of %s, doing %d damage.\n",
111                        prship(&ship), cname(att), xyas(x, y, ship.shp_own),
112                        cname(own), dam);
113                 else
114                     wu(0, ship.shp_own,
115                        "%s supported %s attacks against %s at %s, doing %d damage.\n",
116                        prship(&ship), cname(own), cname(att),
117                        xyas(x, y, ship.shp_own), dam);
118             }
119         }
120     }
121     return (int)(100 - eff * 100);
122 }
123
124 int
125 dd(natid att, natid def_own, coord ax, coord ay, int noisy, int defending)
126 {
127     int dam;
128     struct sctstr firing;
129     struct nstr_sect ns;
130
131     if (opt_NO_FORT_FIRE)       /* Forts can't fire! */
132         return 0;
133     if (def_own == 0)
134         return 0;
135     if (att == def_own)
136         return 0;
137     dam = 0;
138     snxtsct_dist(&ns, ax, ay, 8);
139     while (nxtsct(&ns, &firing) && dam < 80) {
140         if (!feels_like_helping(firing.sct_own, def_own, att))
141             continue;
142         /* XXX defdef damage is additive, but ship or land unit damage isn't */
143         dam += sb(att, def_own, &firing, ax, ay, noisy, defending);
144     }
145     return dam;
146 }
147
148 /*
149  * Shall CN attempt to help FRIEND against FOE?
150  */
151 int
152 feels_like_helping(natid cn, natid friend, natid foe)
153 {
154     if (cn == 0)
155         return 0;               /* never helps anybody */
156     if (cn == foe)
157         return 0;               /* don't help anybody against self */
158     if (cn == friend)
159         return 1;               /* help self against anybody else */
160     /* third party helps ally if at war with foe: */
161     return relations_with(cn, friend) == ALLIED
162         && relations_with(cn, foe) == AT_WAR;
163 }
164
165 /* Shoot back
166  *
167  * See if the sector being fired at will defend itself.
168  */
169 static int
170 sb(natid att, natid def, struct sctstr *sp, coord tx, coord ty, int noisy,
171    int defending)
172 {
173     int damage;
174     natid own;
175     int range, range2;
176
177     own = sp->sct_own;
178     if (own == 0)
179         return 0;
180     if (att == own)
181         return 0;
182     range = roundrange(fortrange(sp));
183     range2 = mapdist(sp->sct_x, sp->sct_y, tx, ty);
184     if (range < range2)
185         return 0;
186     damage = fort_fire(sp);
187     putsect(sp);
188     if (damage < 0)
189         return 0;
190     if (sp->sct_own != def)
191         wu(0, sp->sct_own,
192            "%s fired on %s in %s in defense of %s, doing %d damage!\n",
193            xyas(sp->sct_x, sp->sct_y, sp->sct_own), cname(att),
194            xyas(tx, ty, sp->sct_own), cname(def), damage);
195     if (defending)
196         nreport(sp->sct_own, N_FIRE_BACK, att, 1);
197     else
198         nreport(sp->sct_own, N_FIRE_F_ATTACK, att, 1);
199     if (noisy)
200         pr("Incoming shell! %d damage done.\007\n", damage);
201     return damage;
202 }