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