xref: /original-bsd/games/sail/pl_3.c (revision 94c97675)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)pl_3.c	5.3 (Berkeley) 06/18/88";
20 #endif /* not lint */
21 
22 #include "player.h"
23 
24 acceptcombat()
25 {
26 	int men = 0;
27 	int target, temp;
28 	int n, r;
29 	int index, rakehim, sternrake;
30 	int hhits = 0, ghits = 0, rhits = 0, chits = 0;
31 	int crew[3];
32 	int load;
33 	int guns, car, ready, shootat, hit;
34 	int roll;
35 	struct ship *closest;
36 
37 	crew[0] = mc->crew1;
38 	crew[1] = mc->crew2;
39 	crew[2] = mc->crew3;
40 	for (n = 0; n < 3; n++) {
41 		if (mf->OBP[n].turnsent)
42 			men += mf->OBP[n].mensent;
43 	}
44 	for (n = 0; n < 3; n++) {
45 		if (mf->DBP[n].turnsent)
46 			men += mf->DBP[n].mensent;
47 	}
48 	if (men) {
49 		crew[0] = men/100 ? 0 : crew[0] != 0;
50 		crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
51 		crew[2] = men%10 ? 0 : crew[2] != 0;
52 	}
53 	for (r = 0; r < 2; r++) {
54 		if (r) {
55 			ready = mf->readyR;
56 			load = mf->loadR;
57 			guns = mc->gunR;
58 			car = mc->carR;
59 		} else {
60 			ready = mf->readyL;
61 			load = mf->loadL;
62 			guns = mc->gunL;
63 			car = mc->carL;
64 		}
65 		if (!guns && !car || load == L_EMPTY || (ready & R_LOADED) == 0)
66 			goto cant;
67 		if (mf->struck || !crew[2])
68 			goto cant;
69 		closest = closestenemy(ms, (r ? 'r' : 'l'), 1);
70 		if (closest == 0)
71 			goto cant;
72 		if (closest->file->struck)
73 			goto cant;
74 		target = range(ms, closest);
75 		if (target > rangeofshot[load] || !guns && target >= 3)
76 			goto cant;
77 		Signal("%s (%c%c) within range of %s broadside.",
78 			closest, r ? "right" : "left");
79 		if (load > L_CHAIN && target < 6) {
80 			switch (sgetch("Aim for hull or rigging? ",
81 				(struct ship *)0, 1)) {
82 			case 'r':
83 				shootat = RIGGING;
84 				break;
85 			case 'h':
86 				shootat = HULL;
87 				break;
88 			default:
89 				shootat = -1;
90 				Signal("'Avast there! Hold your fire.'",
91 					(struct ship *)0);
92 			}
93 		} else {
94 			if (sgetch("Fire? ", (struct ship *)0, 1) == 'n') {
95 				shootat = -1;
96 				Signal("Belay that! Hold your fire.",
97 					(struct ship *)0);
98 			} else
99 				shootat = RIGGING;
100 		}
101 		if (shootat == -1)
102 			continue;
103 		fired = 1;
104 		rakehim = gunsbear(ms, closest) && !gunsbear(closest, ms);
105 		temp = portside(closest, ms, 1) - closest->file->dir + 1;
106 		if (temp < 1)
107 			temp += 8;
108 		else if (temp > 8)
109 			temp -= 8;
110 		sternrake = temp > 4 && temp < 6;
111 		if (rakehim)
112 			if (!sternrake)
113 				Signal("Raking the %s!", closest);
114 			else
115 				Signal("Stern Rake! %s splintering!", closest);
116 		index = guns;
117 		if (target < 3)
118 			index += car;
119 		index = (index - 1)/3;
120 		index = index > 8 ? 8 : index;
121 		if (!rakehim)
122 			hit = HDT[index][target-1];
123 		else
124 			hit = HDTrake[index][target-1];
125 		if (rakehim && sternrake)
126 			hit++;
127 		hit += QUAL[index][mc->qual-1];
128 		for (n = 0; n < 3 && mf->captured == 0; n++)
129 			if (!crew[n])
130 				if (index <= 5)
131 					hit--;
132 				else
133 					hit -= 2;
134 		if (ready & R_INITIAL)
135 			if (index <= 3)
136 				hit++;
137 			else
138 				hit += 2;
139 		if (mf->captured != 0)
140 			if (index <= 1)
141 				hit--;
142 			else
143 				hit -= 2;
144 		hit += AMMO[index][load - 1];
145 		if (((temp = mc->class) >= 5 || temp == 1) && windspeed == 5)
146 			hit--;
147 		if (windspeed == 6 && temp == 4)
148 			hit -= 2;
149 		if (windspeed == 6 && temp <= 3)
150 			hit--;
151 		if (hit >= 0) {
152 			roll = die();
153 			if (load == L_GRAPE)
154 				chits = hit;
155 			else {
156 				struct Tables *t;
157 				if (hit > 10)
158 					hit = 10;
159 				t = &(shootat == RIGGING ? RigTable : HullTable)
160 					[hit][roll-1];
161 				chits = t->C;
162 				rhits = t->R;
163 				hhits = t->H;
164 				ghits = t->G;
165 				if (closest->file->FS)
166 					rhits *= 2;
167 				if (load == L_CHAIN) {
168 					ghits = 0;
169 					hhits = 0;
170 				}
171 			}
172 			table(shootat, load, hit, closest, ms, roll);
173 		}
174 		Signal("Damage inflicted on the %s:",
175 			(struct ship *)0, closest->shipname);
176 		Signal("\t%d HULL, %d GUNS, %d CREW, %d RIGGING",
177 			(struct ship *)0, hhits, ghits, chits, rhits);
178 		if (!r) {
179 			mf->loadL = L_EMPTY;
180 			mf->readyL = R_EMPTY;
181 		} else {
182 			mf->loadR = L_EMPTY;
183 			mf->readyR = R_EMPTY;
184 		}
185 		continue;
186 	cant:
187 		Signal("Unable to fire %s broadside",
188 			(struct ship *)0, r ? "right" : "left");
189 	}
190 	blockalarm();
191 	draw_stat();
192 	unblockalarm();
193 }
194 
195 grapungrap()
196 {
197 	register struct ship *sp;
198 	register int i;
199 
200 	foreachship(sp) {
201 		if (sp == ms || sp->file->dir == 0)
202 			continue;
203 		if (range(ms, sp) > 1 && !grappled2(ms, sp))
204 			continue;
205 		switch (sgetch("Attempt to grapple or ungrapple %s (%c%c): ",
206 			sp, 1)) {
207 		case 'g':
208 			if (die() < 3
209 			    || ms->nationality == capship(sp)->nationality) {
210 				Write(W_GRAP, ms, 0, sp->file->index, 0, 0, 0);
211 				Write(W_GRAP, sp, 0, player, 0, 0, 0);
212 				Signal("Attempt succeeds!", (struct ship *)0);
213 				makesignal(ms, "grappled with %s (%c%c)", sp);
214 			} else
215 				Signal("Attempt fails.", (struct ship *)0);
216 			break;
217 		case 'u':
218 			for (i = grappled2(ms, sp); --i >= 0;) {
219 				if (ms->nationality
220 					== capship(sp)->nationality
221 				    || die() < 3) {
222 					cleangrapple(ms, sp, 0);
223 					Signal("Attempt succeeds!",
224 						(struct ship *)0);
225 					makesignal(ms,
226 						"ungrappling with %s (%c%c)",
227 						sp);
228 				} else
229 					Signal("Attempt fails.",
230 						(struct ship *)0);
231 			}
232 			break;
233 		}
234 	}
235 }
236 
237 unfoulplayer()
238 {
239 	register struct ship *to;
240 	register i;
241 
242 	foreachship(to) {
243 		if (fouled2(ms, to) == 0)
244 			continue;
245 		if (sgetch("Attempt to unfoul with the %s (%c%c)? ", to, 1) != 'y')
246 			continue;
247 		for (i = fouled2(ms, to); --i >= 0;) {
248 			if (die() <= 2) {
249 				cleanfoul(ms, to, 0);
250 				Signal("Attempt succeeds!", (struct ship *)0);
251 				makesignal(ms, "Unfouling %s (%c%c)", to);
252 			} else
253 				Signal("Attempt fails.", (struct ship *)0);
254 		}
255 	}
256 }
257