1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 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. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)dr_1.c 5.3 (Berkeley) 06/18/88"; 20 #endif /* not lint */ 21 22 #include "driver.h" 23 24 unfoul() 25 { 26 register struct ship *sp; 27 struct ship *to; 28 register int nat; 29 register i; 30 31 foreachship(sp) { 32 if (sp->file->captain[0]) 33 continue; 34 nat = capship(sp)->nationality; 35 foreachship(to) { 36 if (nat != capship(to)->nationality && 37 !toughmelee(sp, to, 0, 0)) 38 continue; 39 for (i = fouled2(sp, to); --i >= 0;) 40 if (die() <= 2) 41 cleanfoul(sp, to, 0); 42 } 43 } 44 } 45 46 boardcomp() 47 { 48 int crew[3]; 49 register struct ship *sp, *sq; 50 51 foreachship(sp) { 52 if (*sp->file->captain) 53 continue; 54 if (sp->file->dir == 0) 55 continue; 56 if (sp->file->struck || sp->file->captured != 0) 57 continue; 58 if (!snagged(sp)) 59 continue; 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; 97 } 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; 105 } 106 } 107 } 108 } 109 110 fightitout(from, to, key) 111 struct ship *from, *to; 112 int key; 113 { 114 struct ship *fromcap, *tocap; 115 int crewfrom[3], crewto[3], menfrom, mento; 116 int pcto, pcfrom, fromstrength, strengthto, frominjured, toinjured; 117 int topoints; 118 int index, totalfrom = 0, totalto = 0; 119 int count; 120 char message[60]; 121 122 menfrom = mensent(from, to, crewfrom, &fromcap, &pcfrom, key); 123 mento = mensent(to, from, crewto, &tocap, &pcto, 0); 124 if (fromcap == 0) 125 fromcap = from; 126 if (tocap == 0) 127 tocap = to; 128 if (key) { 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 } 140 fromstrength = menfrom * fromcap->specs->qual; 141 strengthto = mento * tocap->specs->qual; 142 for (count = 0; 143 (fromstrength < strengthto * 3 && strengthto < fromstrength * 3 144 || fromstrength == -1) && count < 4; 145 count++) { 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; 158 fromstrength = menfrom * fromcap->specs->qual; 159 strengthto = mento * tocap->specs->qual; 160 } 161 if (fromstrength >= strengthto * 3 || count == 4) { 162 unboard(to, from, 0); 163 subtract(from, totalfrom, crewfrom, fromcap, pcfrom); 164 subtract(to, totalto, crewto, tocap, pcto); 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); 169 if (key) 170 return 1; 171 } else if (strengthto >= fromstrength * 3) { 172 unboard(from, to, 0); 173 subtract(from, totalfrom, crewfrom, fromcap, pcfrom); 174 subtract(to, totalto, crewto, tocap, pcto); 175 if (key) { 176 if (fromcap != from) 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); 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 188 Write(W_CAPTURED, from, 0, to->file->index, 0, 0, 0); 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); 193 mento = crewto[0] ? crewto[0] : crewto[1]; 194 if (mento) { 195 subtract(to, mento, crewto, tocap, pcto); 196 subtract(from, - mento, crewfrom, to, 0); 197 } 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); 204 mento = 0; 205 return 0; 206 } 207 } 208 return 0; 209 } 210 211 resolve() 212 { 213 int thwart; 214 register struct ship *sp, *sq; 215 216 foreachship(sp) { 217 if (sp->file->dir == 0) 218 continue; 219 for (sq = sp + 1; sq < ls; sq++) 220 if (sq->file->dir && meleeing(sp, sq) && meleeing(sq, sp)) 221 (void) fightitout(sp, sq, 0); 222 thwart = 2; 223 foreachship(sq) { 224 if (sq->file->dir && meleeing(sq, sp)) 225 thwart = fightitout(sp, sq, 1); 226 if (!thwart) 227 break; 228 } 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) 237 unboard(sp, sp, 1); 238 } 239 } 240 241 compcombat() 242 { 243 register n; 244 register struct ship *sp; 245 struct ship *closest; 246 int crew[3], men = 0, target, temp; 247 int r, guns, ready, load, car; 248 int index, rakehim, sternrake; 249 int shootat, hit; 250 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; 283 } 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; 338 if (ready & R_INITIAL) { 339 if (!r) 340 sp->file->readyL &= ~R_INITIAL; 341 else 342 sp->file->readyR &= ~R_INITIAL; 343 if (index <= 3) 344 hit++; 345 else 346 hit += 2; 347 } 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()); 365 } 366 } 367 } 368 } 369 370 next() 371 { 372 if (++turn % 55 == 0) 373 if (alive) 374 alive = 0; 375 else 376 people = 0; 377 if (people <= 0 || windspeed == 7) { 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"; 394 if (islower(*p)) 395 *p = toupper(*p); 396 (void) strncpy(bestship->file->captain, p, 397 sizeof bestship->file->captain); 398 bestship->file->captain 399 [sizeof bestship->file->captain - 1] = 0; 400 log(bestship); 401 } 402 return -1; 403 } 404 Write(W_TURN, SHIP(0), 0, turn, 0, 0, 0); 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) 430 switch (die()) { 431 case 1: 432 case 2: 433 windspeed--; 434 break; 435 case 5: 436 case 6: 437 windspeed++; 438 break; 439 } 440 else 441 windspeed++; 442 Write(W_WIND, SHIP(0), 0, winddir, windspeed, 0, 0); 443 } 444 return 0; 445 } 446