]> git.pond.sub.org Git - empserver/blob - src/lib/subs/bridgefall.c
Update copyright notice
[empserver] / src / lib / subs / bridgefall.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2015, 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  *  bridgefall.c: Knock a bridge down
28  *
29  *  Known contributors to this file:
30  *     Steve McClure, 1998
31  *     Markus Armbruster, 2004-2014
32  */
33
34 #include <config.h>
35
36 #include "file.h"
37 #include "land.h"
38 #include "misc.h"
39 #include "nsc.h"
40 #include "nuke.h"
41 #include "optlist.h"
42 #include "path.h"
43 #include "plague.h"
44 #include "plane.h"
45 #include "prototypes.h"
46 #include "sect.h"
47 #include "xy.h"
48
49 static void knockdown(struct sctstr *);
50
51 /*
52  * Is there support for a bridge at SP?
53  * Ignore support coming from direction IGNORE_DIR.
54  */
55 int
56 bridge_support_at(struct sctstr *sp, int ignore_dir)
57 {
58     int i, nx, ny;
59     struct sctstr sect;
60
61     for (i = 1; i <= 6; i++) {
62         if (i == ignore_dir)
63             continue;
64         nx = sp->sct_x + diroff[i][0];
65         ny = sp->sct_y + diroff[i][1];
66         getsect(nx, ny, &sect);
67         if (opt_EASY_BRIDGES
68             && sect.sct_type != SCT_WATER && sect.sct_type != SCT_BSPAN)
69             return 1;
70         if (sect.sct_effic < 20)
71             continue;
72         if (sect.sct_type == SCT_BHEAD && sect.sct_newtype == SCT_BHEAD)
73             return 1;
74         if (sect.sct_type == SCT_BTOWER)
75             return 1;
76     }
77     return 0;
78 }
79
80 /*
81  * Check bridges at and around SP after damage to SP.
82  * If SP is an inefficent bridge, splash it.
83  * If SP can't support a bridge, splash unsupported adjacent bridges.
84  * Write back splashed bridges, except for SP; writing that one is
85  * left to the caller.
86  */
87 void
88 bridge_damaged(struct sctstr *sp)
89 {
90     int des;
91
92     if (sp->sct_effic >= SCT_MINEFF)
93         return;
94
95     des = sp->sct_type;
96     if (des == SCT_BSPAN || des == SCT_BTOWER)
97         knockdown(sp);
98     if ((des == SCT_BHEAD && !opt_EASY_BRIDGES) || des == SCT_BTOWER)
99         bridgefall(sp);
100 }
101
102 void
103 bridgefall(struct sctstr *sp)
104 {
105     int i;
106     struct sctstr sect;
107     int nx;
108     int ny;
109
110     for (i = 1; i <= 6; i++) {
111         nx = sp->sct_x + diroff[i][0];
112         ny = sp->sct_y + diroff[i][1];
113         getsect(nx, ny, &sect);
114         if (sect.sct_type == SCT_BSPAN
115             && !bridge_support_at(&sect, DIR_BACK(i))) {
116             knockdown(&sect);
117             putsect(&sect);
118         }
119     }
120 }
121
122 /* Knock down a bridge span.  Note that this does NOT write the
123  * sector out to the database, it's up to the caller to do that. */
124 static void
125 knockdown(struct sctstr *sp)
126 {
127     struct lndstr land;
128     struct plnstr plane;
129     struct nukstr nuke;
130     struct nstr_item ni;
131
132     mpr(sp->sct_own,
133         "Crumble... SCREEEECH!  Splash! Bridge%s falls at %s!\n",
134         sp->sct_type == SCT_BTOWER ? " tower" : "",
135         xyas(sp->sct_x, sp->sct_y, sp->sct_own));
136     if (!SCT_MINES_ARE_SEAMINES(sp))
137         sp->sct_mines = 0;
138     sp->sct_type = SCT_WATER;
139     sp->sct_newtype = SCT_WATER;
140     sp->sct_own = 0;
141     sp->sct_oldown = 0;
142     sp->sct_mobil = 0;
143     sp->sct_effic = 0;
144
145     /* Sink all the units */
146     snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y);
147     while (nxtitem(&ni, &land)) {
148         if (land.lnd_own == 0)
149             continue;
150         if (land.lnd_ship >= 0)
151             continue;
152         mpr(land.lnd_own, "     AARGH! %s tumbles to its doom!\n",
153             prland(&land));
154         land.lnd_effic = 0;
155         putland(land.lnd_uid, &land);
156     }
157     /* Sink all the planes */
158     snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y);
159     while (nxtitem(&ni, &plane)) {
160         if (plane.pln_own == 0)
161             continue;
162         if (plane.pln_flags & PLN_LAUNCHED)
163             continue;
164         if (plane.pln_ship >= 0)
165             continue;
166         mpr(plane.pln_own, "     AARGH! %s tumbles to its doom!\n",
167             prplane(&plane));
168         plane.pln_effic = 0;
169         putplane(plane.pln_uid, &plane);
170     }
171     /* Sink all the nukes */
172     snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y);
173     while (nxtitem(&ni, &nuke)) {
174         if (nuke.nuk_own == 0)
175             continue;
176         if (nuke.nuk_plane >= 0)
177             continue;
178         mpr(nuke.nuk_own, "     %s sinks to the bottom of the sea!\n",
179             prnuke(&nuke));
180         nuke.nuk_effic = 0;
181         putnuke(nuke.nuk_uid, &nuke);
182     }
183     memset(sp->sct_item, 0, sizeof(sp->sct_item));
184     memset(sp->sct_del, 0, sizeof(sp->sct_del));
185     memset(sp->sct_dist, 0, sizeof(sp->sct_dist));
186     sp->sct_pstage = PLG_HEALTHY;
187     sp->sct_ptime = 0;
188     sp->sct_che = 0;
189     sp->sct_che_target = 0;
190 }