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