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