f26cd73359b22d1d11da8df34e08e6a4c7c05a6b
[dragonfly.git] / games / sail / assorted.c
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. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)assorted.c       8.1 (Berkeley) 5/31/93
34  * $FreeBSD: src/games/sail/assorted.c,v 1.5 1999/11/30 03:49:31 billf Exp $
35  * $DragonFly: src/games/sail/assorted.c,v 1.3 2006/09/03 17:33:13 pavalos Exp $
36  */
37
38 #include "externs.h"
39
40 static void     strike(struct ship *, struct ship *);
41
42 void
43 table(int rig, int shot, int hittable,
44       struct ship *on, struct ship *from, int roll)
45 {
46         int hhits = 0, chits = 0, ghits = 0, rhits = 0;
47         int Ghit = 0, Hhit = 0, Rhit = 0, Chit = 0;
48         int guns, car, pc, hull;
49         int crew[3];
50         int n;
51         int rigg[4];
52         const char *message = NULL;
53         struct Tables *tp;
54
55         pc = on->file->pcrew;
56         hull = on->specs->hull;
57         crew[0] = on->specs->crew1;
58         crew[1] = on->specs->crew2;
59         crew[2] = on->specs->crew3;
60         rigg[0] = on->specs->rig1;
61         rigg[1] = on->specs->rig2;
62         rigg[2] = on->specs->rig3;
63         rigg[3] = on->specs->rig4;
64         if (shot == L_GRAPE)
65                 Chit = chits = hittable;
66         else {
67                 tp = &(rig ? RigTable : HullTable)[hittable][roll-1];
68                 Chit = chits = tp->C;
69                 Rhit = rhits = tp->R;
70                 Hhit = hhits = tp->H;
71                 Ghit = ghits = tp->G;
72                 if (on->file->FS)
73                         rhits *= 2;
74                 if (shot == L_CHAIN) {
75                         Ghit = ghits = 0;
76                         Hhit = hhits = 0;
77                 }
78         }
79         if (on->file->captured != 0) {
80                 pc -= (chits + 1) / 2;
81                 chits /= 2;
82         }
83         for (n = 0; n < 3; n++)
84                 if (chits > crew[n]) {
85                         chits -= crew[n];
86                         crew[n] = 0;
87                 } else {
88                         crew[n] -= chits;
89                         chits = 0;
90                 }
91         for (n = 0; n < 3; n++)
92                 if (rhits > rigg[n]){
93                         rhits -= rigg[n];
94                         rigg[n] = 0;
95                 } else {
96                         rigg[n] -= rhits;
97                         rhits = 0;
98                 }
99         if (rigg[3] != -1 && rhits > rigg[3]) {
100                 rhits -= rigg[3];
101                 rigg[3] = 0;
102         } else if (rigg[3] != -1) {
103                 rigg[3] -= rhits;
104         }
105         if (rig && !rigg[2] && (!rigg[3] || rigg[3] == -1))
106                 makesignal(on, "dismasted!", (struct ship *)0);
107         if (portside(from, on, 0)) {
108                 guns = on->specs->gunR;
109                 car = on->specs->carR;
110         } else {
111                 guns = on->specs->gunL;
112                 car = on->specs->carL;
113         }
114         if (ghits > car) {
115                 ghits -= car;
116                 car = 0;
117         } else {
118                 car -= ghits;
119                 ghits = 0;
120         }
121         if (ghits > guns){
122                 ghits -= guns;
123                 guns = 0;
124         } else {
125                 guns -= ghits;
126                 ghits = 0;
127         }
128         hull -= ghits;
129         if (Ghit)
130                 Write(portside(from, on, 0) ? W_GUNR : W_GUNL,
131                         on, guns, car, 0, 0);
132         hull -= hhits;
133         hull = hull < 0 ? 0 : hull;
134         if (on->file->captured != 0 && Chit)
135                 Write(W_PCREW, on, pc, 0, 0, 0);
136         if (Hhit)
137                 Write(W_HULL, on, hull, 0, 0, 0);
138         if (Chit)
139                 Write(W_CREW, on, crew[0], crew[1], crew[2], 0);
140         if (Rhit)
141                 Write(W_RIGG, on, rigg[0], rigg[1], rigg[2], rigg[3]);
142         switch (shot) {
143         case L_ROUND:
144                 message = "firing round shot on %s (%c%c)";
145                 break;
146         case L_GRAPE:
147                 message = "firing grape shot on %s (%c%c)";
148                 break;
149         case L_CHAIN:
150                 message = "firing chain shot on %s (%c%c)";
151                 break;
152         case L_DOUBLE:
153                 message = "firing double shot on %s (%c%c)";
154                 break;
155         case L_EXPLODE:
156                 message = "exploding shot on %s (%c%c)";
157         }
158         makesignal(from, message, on);
159         if (roll == 6 && rig) {
160                 switch(Rhit) {
161                 case 0:
162                         message = "fore topsail sheets parted";
163                         break;
164                 case 1:
165                         message = "mizzen shrouds parted";
166                         break;
167                 case 2:
168                         message = "main topsail yard shot away";
169                         break;
170                 case 4:
171                         message = "fore topmast and foremast shrouds shot away";
172                         break;
173                 case 5:
174                         message = "mizzen mast and yard shot through";
175                         break;
176                 case 6:
177                         message = "foremast and spritsail yard shattered";
178                         break;
179                 case 7:
180                         message = "main topmast and mizzen mast shattered";
181                         break;
182                 }
183                 makesignal(on, message, (struct ship *)0);
184         } else if (roll == 6) {
185                 switch (Hhit) {
186                 case 0:
187                         message = "anchor cables severed";
188                         break;
189                 case 1:
190                         message = "two anchor stocks shot away";
191                         break;
192                 case 2:
193                         message = "quarterdeck bulwarks damaged";
194                         break;
195                 case 3:
196                         message = "three gun ports shot away";
197                         break;
198                 case 4:
199                         message = "four guns dismounted";
200                         break;
201                 case 5:
202                         message = "rudder cables shot through";
203                         Write(W_TA, on, 0, 0, 0, 0);
204                         break;
205                 case 6:
206                         message = "shot holes below the water line";
207                         break;
208                 }
209                 makesignal(on, message, (struct ship *)0);
210         }
211         if (!hull)
212                 strike(on, from);
213 }
214
215 void
216 Cleansnag(struct ship *from, struct ship *to, char all, char flag)
217 {
218         if (flag & 1) {
219                 Write(W_UNGRAP, from, to->file->index, all, 0, 0);
220                 Write(W_UNGRAP, to, from->file->index, all, 0, 0);
221         }
222         if (flag & 2) {
223                 Write(W_UNFOUL, from, to->file->index, all, 0, 0);
224                 Write(W_UNFOUL, to, from->file->index, all, 0, 0);
225         }
226         if (!snagged2(from, to)) {
227                 if (!snagged(from)) {
228                         unboard(from, from, 1);         /* defense */
229                         unboard(from, from, 0);         /* defense */
230                 } else
231                         unboard(from, to, 0);           /* offense */
232                 if (!snagged(to)) {
233                         unboard(to, to, 1);             /* defense */
234                         unboard(to, to, 0);             /* defense */
235                 } else
236                         unboard(to, from, 0);           /* offense */
237         }
238 }
239
240 static void
241 strike(struct ship *ship, struct ship *from)
242 {
243         int points;
244
245         if (ship->file->struck)
246                 return;
247         Write(W_STRUCK, ship, 1, 0, 0, 0);
248         points = ship->specs->pts + from->file->points;
249         Write(W_POINTS, from, points, 0, 0, 0);
250         unboard(ship, ship, 0);         /* all offense */
251         unboard(ship, ship, 1);         /* all defense */
252         switch (die()) {
253         case 3:
254         case 4:         /* ship may sink */
255                 Write(W_SINK, ship, 1, 0, 0, 0);
256                 break;
257         case 5:
258         case 6:         /* ship may explode */
259                 Write(W_EXPLODE, ship, 1, 0, 0, 0);
260                 break;
261         }
262         Writestr(W_SIGNAL, ship, "striking her colours!");
263 }