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