1 /* $OpenBSD: pl_3.c,v 1.6 2016/01/08 20:26:33 mestre Exp $ */
2 /* $NetBSD: pl_3.c,v 1.3 1995/04/22 10:37:09 cgd Exp $ */
3
4 /*
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <signal.h>
34 #include <stdlib.h>
35
36 #include "extern.h"
37 #include "machdep.h"
38 #include "player.h"
39
40 void
acceptcombat(void)41 acceptcombat(void)
42 {
43 int men = 0;
44 int target, temp;
45 int n, r;
46 int index, rakehim, sternrake;
47 int hhits = 0, ghits = 0, rhits = 0, chits = 0;
48 int crew[3];
49 int load;
50 int guns, car, ready, shootat, hit;
51 int roll;
52 struct ship *closest;
53
54 crew[0] = mc->crew1;
55 crew[1] = mc->crew2;
56 crew[2] = mc->crew3;
57 for (n = 0; n < 3; n++) {
58 if (mf->OBP[n].turnsent)
59 men += mf->OBP[n].mensent;
60 }
61 for (n = 0; n < 3; n++) {
62 if (mf->DBP[n].turnsent)
63 men += mf->DBP[n].mensent;
64 }
65 if (men) {
66 crew[0] = men/100 ? 0 : crew[0] != 0;
67 crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
68 crew[2] = men%10 ? 0 : crew[2] != 0;
69 }
70 for (r = 0; r < 2; r++) {
71 if (r) {
72 ready = mf->readyR;
73 load = mf->loadR;
74 guns = mc->gunR;
75 car = mc->carR;
76 } else {
77 ready = mf->readyL;
78 load = mf->loadL;
79 guns = mc->gunL;
80 car = mc->carL;
81 }
82 if ((!guns && !car) || load == L_EMPTY || (ready & R_LOADED) == 0)
83 goto cant;
84 if (mf->struck || !crew[2])
85 goto cant;
86 closest = closestenemy(ms, (r ? 'r' : 'l'), 1);
87 if (closest == 0)
88 goto cant;
89 if (closest->file->struck)
90 goto cant;
91 target = range(ms, closest);
92 if (target > rangeofshot[load] || (!guns && target >= 3))
93 goto cant;
94 Signal("$$ within range of %s broadside.",
95 closest, r ? "right" : "left");
96 if (load > L_CHAIN && target < 6) {
97 switch (sgetch("Aim for hull or rigging? ",
98 (struct ship *)0, 1)) {
99 case 'r':
100 shootat = RIGGING;
101 break;
102 case 'h':
103 shootat = HULL;
104 break;
105 default:
106 shootat = -1;
107 Msg("'Avast there! Hold your fire.'");
108 }
109 } else {
110 if (sgetch("Fire? ", (struct ship *)0, 1) == 'n') {
111 shootat = -1;
112 Msg("Belay that! Hold your fire.");
113 } else
114 shootat = RIGGING;
115 }
116 if (shootat == -1)
117 continue;
118 fired = 1;
119 rakehim = gunsbear(ms, closest) && !gunsbear(closest, ms);
120 temp = portside(closest, ms, 1) - closest->file->dir + 1;
121 if (temp < 1)
122 temp += 8;
123 else if (temp > 8)
124 temp -= 8;
125 sternrake = temp > 4 && temp < 6;
126 if (rakehim) {
127 if (!sternrake)
128 Msg("Raking the %s!", closest->shipname);
129 else
130 Msg("Stern Rake! %s splintering!",
131 closest->shipname);
132 }
133 index = guns;
134 if (target < 3)
135 index += car;
136 index = (index - 1)/3;
137 index = index > 8 ? 8 : index;
138 if (!rakehim)
139 hit = HDT[index][target-1];
140 else
141 hit = HDTrake[index][target-1];
142 if (rakehim && sternrake)
143 hit++;
144 hit += QUAL[index][mc->qual-1];
145 for (n = 0; n < 3 && mf->captured == 0; n++)
146 if (!crew[n]) {
147 if (index <= 5)
148 hit--;
149 else
150 hit -= 2;
151 }
152 if (ready & R_INITIAL) {
153 if (index <= 3)
154 hit++;
155 else
156 hit += 2;
157 }
158 if (mf->captured != 0) {
159 if (index <= 1)
160 hit--;
161 else
162 hit -= 2;
163 }
164 hit += AMMO[index][load - 1];
165 if (((temp = mc->class) >= 5 || temp == 1) && windspeed == 5)
166 hit--;
167 if (windspeed == 6 && temp == 4)
168 hit -= 2;
169 if (windspeed == 6 && temp <= 3)
170 hit--;
171 if (hit >= 0) {
172 roll = die();
173 if (load == L_GRAPE)
174 chits = hit;
175 else {
176 const struct Tables *t;
177 if (hit > 10)
178 hit = 10;
179 t = &(shootat == RIGGING ? RigTable : HullTable)
180 [hit][roll-1];
181 chits = t->C;
182 rhits = t->R;
183 hhits = t->H;
184 ghits = t->G;
185 if (closest->file->FS)
186 rhits *= 2;
187 if (load == L_CHAIN) {
188 ghits = 0;
189 hhits = 0;
190 }
191 }
192 table(shootat, load, hit, closest, ms, roll);
193 }
194 Msg("Damage inflicted on the %s:", closest->shipname);
195 Msg("\t%d HULL, %d GUNS, %d CREW, %d RIGGING",
196 hhits, ghits, chits, rhits);
197 if (!r) {
198 mf->loadL = L_EMPTY;
199 mf->readyL = R_EMPTY;
200 } else {
201 mf->loadR = L_EMPTY;
202 mf->readyR = R_EMPTY;
203 }
204 continue;
205 cant:
206 Msg("Unable to fire %s broadside", r ? "right" : "left");
207 }
208 blockalarm();
209 draw_stat();
210 unblockalarm();
211 }
212
213 void
grapungrap(void)214 grapungrap(void)
215 {
216 struct ship *sp;
217 int i;
218
219 foreachship(sp) {
220 if (sp == ms || sp->file->dir == 0)
221 continue;
222 if (range(ms, sp) > 1 && !grappled2(ms, sp))
223 continue;
224 switch (sgetch("Attempt to grapple or ungrapple $$: ",
225 sp, 1)) {
226 case 'g':
227 if (die() < 3
228 || ms->nationality == capship(sp)->nationality) {
229 Write(W_GRAP, ms, sp->file->index, 0, 0, 0);
230 Write(W_GRAP, sp, player, 0, 0, 0);
231 Msg("Attempt succeeds!");
232 makesignal(ms, "grappled with $$", sp);
233 } else
234 Msg("Attempt fails.");
235 break;
236 case 'u':
237 for (i = grappled2(ms, sp); --i >= 0;) {
238 if (ms->nationality
239 == capship(sp)->nationality
240 || die() < 3) {
241 cleangrapple(ms, sp, 0);
242 Msg("Attempt succeeds!");
243 makesignal(ms, "ungrappling with $$",
244 sp);
245 } else
246 Msg("Attempt fails.");
247 }
248 break;
249 }
250 }
251 }
252
253 void
unfoulplayer(void)254 unfoulplayer(void)
255 {
256 struct ship *to;
257 int i;
258
259 foreachship(to) {
260 if (fouled2(ms, to) == 0)
261 continue;
262 if (sgetch("Attempt to unfoul with the $$? ", to, 1) != 'y')
263 continue;
264 for (i = fouled2(ms, to); --i >= 0;) {
265 if (die() <= 2) {
266 cleanfoul(ms, to, 0);
267 Msg("Attempt succeeds!");
268 makesignal(ms, "Unfouling $$", to);
269 } else
270 Msg("Attempt fails.");
271 }
272 }
273 }
274