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