]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - games/sail/dr_1.c
Add $FreeBSD$
[FreeBSD/FreeBSD.git] / games / sail / dr_1.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  * $FreeBSD$
34  */
35
36 #ifndef lint
37 static char sccsid[] = "@(#)dr_1.c      8.1 (Berkeley) 5/31/93";
38 #endif /* not lint */
39
40 #include "driver.h"
41
42 unfoul()
43 {
44         register struct ship *sp;
45         struct ship *to;
46         register int nat;
47         register i;
48
49         foreachship(sp) {
50                 if (sp->file->captain[0])
51                         continue;
52                 nat = capship(sp)->nationality;
53                 foreachship(to) {
54                         if (nat != capship(to)->nationality &&
55                             !toughmelee(sp, to, 0, 0))
56                                 continue;
57                         for (i = fouled2(sp, to); --i >= 0;)
58                                 if (die() <= 2)
59                                         cleanfoul(sp, to, 0);
60                 }
61         }
62 }
63
64 boardcomp()
65 {
66         int crew[3];
67         register struct ship *sp, *sq;
68
69         foreachship(sp) {
70                 if (*sp->file->captain)
71                         continue;
72                 if (sp->file->dir == 0)
73                         continue;
74                 if (sp->file->struck || sp->file->captured != 0)
75                         continue;
76                 if (!snagged(sp))
77                         continue;
78                 crew[0] = sp->specs->crew1 != 0;
79                 crew[1] = sp->specs->crew2 != 0;
80                 crew[2] = sp->specs->crew3 != 0;
81                 foreachship(sq) {
82                         if (!Xsnagged2(sp, sq))
83                                 continue;
84                         if (meleeing(sp, sq))
85                                 continue;
86                         if (!sq->file->dir
87                                 || sp->nationality == capship(sq)->nationality)
88                                 continue;
89                         switch (sp->specs->class - sq->specs->class) {
90                         case -3: case -4: case -5:
91                                 if (crew[0]) {
92                                         /* OBP */
93                                         sendbp(sp, sq, crew[0]*100, 0);
94                                         crew[0] = 0;
95                                 } else if (crew[1]){
96                                         /* OBP */
97                                         sendbp(sp, sq, crew[1]*10, 0);
98                                         crew[1] = 0;
99                                 }
100                                 break;
101                         case -2:
102                                 if (crew[0] || crew[1]) {
103                                         /* OBP */
104                                         sendbp(sp, sq, crew[0]*100+crew[1]*10,
105                                                 0);
106                                         crew[0] = crew[1] = 0;
107                                 }
108                                 break;
109                         case -1: case 0: case 1:
110                                 if (crew[0]) {
111                                         /* OBP */
112                                         sendbp(sp, sq, crew[0]*100+crew[1]*10,
113                                                 0);
114                                         crew[0] = crew[1] = 0;
115                                 }
116                                 break;
117                         case 2: case 3: case 4: case 5:
118                                 /* OBP */
119                                 sendbp(sp, sq, crew[0]*100+crew[1]*10+crew[2],
120                                         0);
121                                 crew[0] = crew[1] = crew[2] = 0;
122                                 break;
123                         }
124                 }
125         }
126 }
127
128 fightitout(from, to, key)
129 struct ship *from, *to;
130 int key;
131 {
132         struct ship *fromcap, *tocap;
133         int crewfrom[3], crewto[3], menfrom, mento;
134         int pcto, pcfrom, fromstrength, strengthto, frominjured, toinjured;
135         int topoints;
136         int index, totalfrom = 0, totalto = 0;
137         int count;
138         char message[60];
139
140         menfrom = mensent(from, to, crewfrom, &fromcap, &pcfrom, key);
141         mento = mensent(to, from, crewto, &tocap, &pcto, 0);
142         if (fromcap == 0)
143                 fromcap = from;
144         if (tocap == 0)
145                 tocap = to;
146         if (key) {
147                 if (!menfrom) {          /* if crew surprised */
148                         if (fromcap == from)
149                                 menfrom = from->specs->crew1
150                                         + from->specs->crew2
151                                         + from->specs->crew3;
152                         else
153                                 menfrom = from->file->pcrew;
154                 } else {
155                         menfrom *= 2;   /* DBP's fight at an advantage */
156                 }
157         }
158         fromstrength = menfrom * fromcap->specs->qual;
159         strengthto = mento * tocap->specs->qual;
160         for (count = 0;
161              (fromstrength < strengthto * 3 && strengthto < fromstrength * 3
162               || fromstrength == -1) && count < 4;
163              count++) {
164                 index = fromstrength/10;
165                 if (index > 8)
166                         index = 8;
167                 toinjured = MT[index][2 - die() / 3];
168                 totalto += toinjured;
169                 index = strengthto/10;
170                 if (index > 8)
171                         index = 8;
172                 frominjured = MT[index][2 - die() / 3];
173                 totalfrom += frominjured;
174                 menfrom -= frominjured;
175                 mento -= toinjured;
176                 fromstrength = menfrom * fromcap->specs->qual;
177                 strengthto = mento * tocap->specs->qual;
178         }
179         if (fromstrength >= strengthto * 3 || count == 4) {
180                 unboard(to, from, 0);
181                 subtract(from, totalfrom, crewfrom, fromcap, pcfrom);
182                 subtract(to, totalto, crewto, tocap, pcto);
183                 makesignal(from, "boarders from %s repelled", to);
184                 (void) sprintf(message, "killed in melee: %d.  %s: %d",
185                         totalto, from->shipname, totalfrom);
186                 Write(W_SIGNAL, to, 1, (long) message, 0, 0, 0);
187                 if (key)
188                         return 1;
189         } else if (strengthto >= fromstrength * 3) {
190                 unboard(from, to, 0);
191                 subtract(from, totalfrom, crewfrom, fromcap, pcfrom);
192                 subtract(to, totalto, crewto, tocap, pcto);
193                 if (key) {
194                         if (fromcap != from)
195                                 Write(W_POINTS, fromcap, 0,
196                                         fromcap->file->points -
197                                                 from->file->struck
198                                                 ? from->specs->pts
199                                                 : 2 * from->specs->pts,
200                                         0, 0, 0);
201
202 /* ptr1 points to the shipspec for the ship that was just unboarded.
203    I guess that what is going on here is that the pointer is multiplied
204    or something. */
205
206                         Write(W_CAPTURED, from, 0, to->file->index, 0, 0, 0);
207                         topoints = 2 * from->specs->pts + to->file->points;
208                         if (from->file->struck)
209                                 topoints -= from->specs->pts;
210                         Write(W_POINTS, to, 0, topoints, 0, 0, 0);
211                         mento = crewto[0] ? crewto[0] : crewto[1];
212                         if (mento) {
213                                 subtract(to, mento, crewto, tocap, pcto);
214                                 subtract(from, - mento, crewfrom, to, 0);
215                         }
216                         (void) sprintf(message, "captured by the %s!",
217                                 to->shipname);
218                         Write(W_SIGNAL, from, 1, (long) message, 0, 0, 0);
219                         (void) sprintf(message, "killed in melee: %d.  %s: %d",
220                                 totalto, from->shipname, totalfrom);
221                         Write(W_SIGNAL, to, 1, (long) message, 0, 0, 0);
222                         mento = 0;
223                         return 0;
224                 }
225         }
226         return 0;
227 }
228
229 resolve()
230 {
231         int thwart;
232         register struct ship *sp, *sq;
233
234         foreachship(sp) {
235                 if (sp->file->dir == 0)
236                         continue;
237                 for (sq = sp + 1; sq < ls; sq++)
238                         if (sq->file->dir && meleeing(sp, sq) && meleeing(sq, sp))
239                                 (void) fightitout(sp, sq, 0);
240                 thwart = 2;
241                 foreachship(sq) {
242                         if (sq->file->dir && meleeing(sq, sp))
243                                 thwart = fightitout(sp, sq, 1);
244                         if (!thwart)
245                                 break;
246                 }
247                 if (!thwart) {
248                         foreachship(sq) {
249                                 if (sq->file->dir && meleeing(sq, sp))
250                                         unboard(sq, sp, 0);
251                                 unboard(sp, sq, 0);
252                         }
253                         unboard(sp, sp, 1);
254                 } else if (thwart == 2)
255                         unboard(sp, sp, 1);
256         }
257 }
258
259 compcombat()
260 {
261         register n;
262         register struct ship *sp;
263         struct ship *closest;
264         int crew[3], men = 0, target, temp;
265         int r, guns, ready, load, car;
266         int index, rakehim, sternrake;
267         int shootat, hit;
268
269         foreachship(sp) {
270                 if (sp->file->captain[0] || sp->file->dir == 0)
271                         continue;
272                 crew[0] = sp->specs->crew1;
273                 crew[1] = sp->specs->crew2;
274                 crew[2] = sp->specs->crew3;
275                 for (n = 0; n < 3; n++) {
276                         if (sp->file->OBP[n].turnsent)
277                                 men += sp->file->OBP[n].mensent;
278                 }
279                 for (n = 0; n < 3; n++) {
280                         if (sp->file->DBP[n].turnsent)
281                                 men += sp->file->DBP[n].mensent;
282                 }
283                 if (men){
284                         crew[0] = men/100 ? 0 : crew[0] != 0;
285                         crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
286                         crew[2] = men%10 ? 0 : crew[2] != 0;
287                 }
288                 for (r = 0; r < 2; r++) {
289                         if (!crew[2])
290                                 continue;
291                         if (sp->file->struck)
292                                 continue;
293                         if (r) {
294                                 ready = sp->file->readyR;
295                                 guns = sp->specs->gunR;
296                                 car = sp->specs->carR;
297                         } else {
298                                 ready = sp->file->readyL;
299                                 guns = sp->specs->gunL;
300                                 car = sp->specs->carL;
301                         }
302                         if (!guns && !car)
303                                 continue;
304                         if ((ready & R_LOADED) == 0)
305                                 continue;
306                         closest = closestenemy(sp, r ? 'r' : 'l', 0);
307                         if (closest == 0)
308                                 continue;
309                         if (range(closest, sp) > range(sp, closestenemy(sp, r ? 'r' : 'l', 1)))
310                                 continue;
311                         if (closest->file->struck)
312                                 continue;
313                         target = range(sp, closest);
314                         if (target > 10)
315                                 continue;
316                         if (!guns && target >= 3)
317                                 continue;
318                         load = L_ROUND;
319                         if (target == 1 && sp->file->loadwith == L_GRAPE)
320                                 load = L_GRAPE;
321                         if (target <= 3 && closest->file->FS)
322                                 load = L_CHAIN;
323                         if (target == 1 && load != L_GRAPE)
324                                 load = L_DOUBLE;
325                         if (load > L_CHAIN && target < 6)
326                                 shootat = HULL;
327                         else
328                                 shootat = RIGGING;
329                         rakehim = gunsbear(sp, closest)
330                                 && !gunsbear(closest, sp);
331                         temp = portside(closest, sp, 1)
332                                 - closest->file->dir + 1;
333                         if (temp < 1)
334                                 temp += 8;
335                         if (temp > 8)
336                                 temp -= 8;
337                         sternrake = temp > 4 && temp < 6;
338                         index = guns;
339                         if (target < 3)
340                                 index += car;
341                         index = (index - 1) / 3;
342                         index = index > 8 ? 8 : index;
343                         if (!rakehim)
344                                 hit = HDT[index][target-1];
345                         else
346                                 hit = HDTrake[index][target-1];
347                         if (rakehim && sternrake)
348                                 hit++;
349                         hit += QUAL[index][capship(sp)->specs->qual - 1];
350                         for (n = 0; n < 3 && sp->file->captured == 0; n++)
351                                 if (!crew[n]) {
352                                         if (index <= 5)
353                                                 hit--;
354                                         else
355                                                 hit -= 2;
356                                 }
357                         if (ready & R_INITIAL) {
358                                 if (!r)
359                                         sp->file->readyL &= ~R_INITIAL;
360                                 else
361                                         sp->file->readyR &= ~R_INITIAL;
362                                 if (index <= 3)
363                                         hit++;
364                                 else
365                                         hit += 2;
366                         }
367                         if (sp->file->captured != 0) {
368                                 if (index <= 1)
369                                         hit--;
370                                 else
371                                         hit -= 2;
372                         }
373                         hit += AMMO[index][load - 1];
374                         temp = sp->specs->class;
375                         if ((temp >= 5 || temp == 1) && windspeed == 5)
376                                 hit--;
377                         if (windspeed == 6 && temp == 4)
378                                 hit -= 2;
379                         if (windspeed == 6 && temp <= 3)
380                                 hit--;
381                         if (hit >= 0) {
382                                 if (load != L_GRAPE)
383                                         hit = hit > 10 ? 10 : hit;
384                                 table(shootat, load, hit, closest, sp, die());
385                         }
386                 }
387         }
388 }
389
390 next()
391 {
392         if (++turn % 55 == 0) {
393                 if (alive)
394                         alive = 0;
395                 else
396                         people = 0;
397         }
398         if (people <= 0 || windspeed == 7) {
399                 register struct ship *s;
400                 struct ship *bestship;
401                 float net, best = 0.0;
402                 foreachship(s) {
403                         if (*s->file->captain)
404                                 continue;
405                         net = (float)s->file->points / s->specs->pts;
406                         if (net > best) {
407                                 best = net;
408                                 bestship = s;
409                         }
410                 }
411                 if (best > 0.0) {
412                         char *p = getenv("WOTD");
413                         if (p == 0)
414                                 p = "Driver";
415                         if (islower(*p))
416                                 *p = toupper(*p);
417                         (void) strncpy(bestship->file->captain, p,
418                                 sizeof bestship->file->captain);
419                         bestship->file->captain
420                                 [sizeof bestship->file->captain - 1] = 0;
421                         log(bestship);
422                 }
423                 return -1;
424         }
425         Write(W_TURN, SHIP(0), 0, turn, 0, 0, 0);
426         if (turn % 7 == 0 && (die() >= cc->windchange || !windspeed)) {
427                 switch (die()) {
428                 case 1:
429                         winddir = 1;
430                         break;
431                 case 2:
432                         break;
433                 case 3:
434                         winddir++;
435                         break;
436                 case 4:
437                         winddir--;
438                         break;
439                 case 5:
440                         winddir += 2;
441                         break;
442                 case 6:
443                         winddir -= 2;
444                         break;
445                 }
446                 if (winddir > 8)
447                         winddir -= 8;
448                 if (winddir < 1)
449                         winddir += 8;
450                 if (windspeed)
451                         switch (die()) {
452                         case 1:
453                         case 2:
454                                 windspeed--;
455                                 break;
456                         case 5:
457                         case 6:
458                                 windspeed++;
459                                 break;
460                         }
461                 else
462                         windspeed++;
463                 Write(W_WIND, SHIP(0), 0, winddir, windspeed, 0, 0);
464         }
465         return 0;
466 }