1 /* $NetBSD: dr_1.c,v 1.27 2009/03/14 22:52:52 dholland Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 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.27 2009/03/14 22:52:52 dholland Exp $"); 38 #endif 39 #endif /* not lint */ 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 /* OBP */ 103 sendbp(sp, sq, crew[0]*100, 0); 104 crew[0] = 0; 105 } else if (crew[1]) { 106 /* OBP */ 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 /* OBP */ 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 /* OBP */ 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 /* OBP */ 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 indx, 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 == NULL) 152 fromcap = from; 153 if (tocap == NULL) 154 tocap = to; 155 if (key) { 156 if (!menfrom) { /* if crew surprised */ 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; /* DBP's fight at an advantage */ 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 indx = fromstrength/10; 174 if (indx > 8) 175 indx = 8; 176 toinjured = MT[indx][2 - dieroll() / 3]; 177 totalto += toinjured; 178 indx = strengthto/10; 179 if (indx > 8) 180 indx = 8; 181 frominjured = MT[indx][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 snprintf(message, sizeof(message), 194 "killed in melee: %d. %s: %d", 195 totalto, from->shipname, totalfrom); 196 send_signal(to, message); 197 if (key) 198 return 1; 199 } else if (strengthto >= fromstrength * 3) { 200 unboard(from, to, 0); 201 subtract(from, fromcap, totalfrom, crewfrom, pcfrom); 202 subtract(to, tocap, totalto, crewto, pcto); 203 if (key) { 204 if (fromcap != from) 205 send_points(fromcap, 206 fromcap->file->points - 207 from->file->struck 208 ? from->specs->pts 209 : 2 * from->specs->pts); 210 211 send_captured(from, to->file->index); 212 topoints = 2 * from->specs->pts + to->file->points; 213 if (from->file->struck) 214 topoints -= from->specs->pts; 215 send_points(to, topoints); 216 mento = crewto[0] ? crewto[0] : crewto[1]; 217 if (mento) { 218 subtract(to, tocap, mento, crewto, pcto); 219 subtract(from, to, - mento, crewfrom, 0); 220 } 221 snprintf(message, sizeof(message), 222 "captured by the %s!", to->shipname); 223 send_signal(from, message); 224 snprintf(message, sizeof(message), 225 "killed in melee: %d. %s: %d", 226 totalto, from->shipname, totalfrom); 227 send_signal(to, message); 228 mento = 0; 229 return 0; 230 } 231 } 232 return 0; 233 } 234 235 void 236 resolve(void) 237 { 238 int thwart; 239 struct ship *sp, *sq; 240 241 foreachship(sp) { 242 if (sp->file->dir == 0) 243 continue; 244 for (sq = sp + 1; sq < ls; sq++) 245 if (sq->file->dir && meleeing(sp, sq) && 246 meleeing(sq, sp)) 247 fightitout(sp, sq, 0); 248 thwart = 2; 249 foreachship(sq) { 250 if (sq->file->dir && meleeing(sq, sp)) 251 thwart = fightitout(sp, sq, 1); 252 if (!thwart) 253 break; 254 } 255 if (!thwart) { 256 foreachship(sq) { 257 if (sq->file->dir && meleeing(sq, sp)) 258 unboard(sq, sp, 0); 259 unboard(sp, sq, 0); 260 } 261 unboard(sp, sp, 1); 262 } else if (thwart == 2) 263 unboard(sp, sp, 1); 264 } 265 } 266 267 void 268 compcombat(void) 269 { 270 int n; 271 struct ship *sp; 272 struct ship *closest; 273 int crew[3], men = 0, target, temp; 274 int r, guns, ready, load, car; 275 int indx, rakehim, sternrake; 276 int shootat, hit; 277 278 foreachship(sp) { 279 if (sp->file->captain[0] || sp->file->dir == 0) 280 continue; 281 crew[0] = sp->specs->crew1; 282 crew[1] = sp->specs->crew2; 283 crew[2] = sp->specs->crew3; 284 for (n = 0; n < 3; n++) { 285 if (sp->file->OBP[n].turnsent) 286 men += sp->file->OBP[n].mensent; 287 } 288 for (n = 0; n < 3; n++) { 289 if (sp->file->DBP[n].turnsent) 290 men += sp->file->DBP[n].mensent; 291 } 292 if (men) { 293 crew[0] = men/100 ? 0 : crew[0] != 0; 294 crew[1] = (men%100)/10 ? 0 : crew[1] != 0; 295 crew[2] = men%10 ? 0 : crew[2] != 0; 296 } 297 for (r = 0; r < 2; r++) { 298 if (!crew[2]) 299 continue; 300 if (sp->file->struck) 301 continue; 302 if (r) { 303 ready = sp->file->readyR; 304 guns = sp->specs->gunR; 305 car = sp->specs->carR; 306 } else { 307 ready = sp->file->readyL; 308 guns = sp->specs->gunL; 309 car = sp->specs->carL; 310 } 311 if (!guns && !car) 312 continue; 313 if ((ready & R_LOADED) == 0) 314 continue; 315 closest = closestenemy(sp, r ? 'r' : 'l', 0); 316 if (closest == NULL) 317 continue; 318 if (range(closest, sp) > 319 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 indx = guns; 349 if (target < 3) 350 indx += car; 351 indx = (indx - 1) / 3; 352 indx = indx > 8 ? 8 : indx; 353 if (!rakehim) 354 hit = HDT[indx][target-1]; 355 else 356 hit = HDTrake[indx][target-1]; 357 if (rakehim && sternrake) 358 hit++; 359 hit += QUAL[indx][capship(sp)->specs->qual - 1]; 360 for (n = 0; n < 3 && sp->file->captured == 0; n++) { 361 if (!crew[n]) { 362 if (indx <= 5) 363 hit--; 364 else 365 hit -= 2; 366 } 367 } 368 if (ready & R_INITIAL) { 369 if (!r) 370 sp->file->readyL &= ~R_INITIAL; 371 else 372 sp->file->readyR &= ~R_INITIAL; 373 if (indx <= 3) 374 hit++; 375 else 376 hit += 2; 377 } 378 if (sp->file->captured != 0) { 379 if (indx <= 1) 380 hit--; 381 else 382 hit -= 2; 383 } 384 hit += AMMO[indx][load - 1]; 385 temp = sp->specs->class; 386 if ((temp >= 5 || temp == 1) && windspeed == 5) 387 hit--; 388 if (windspeed == 6 && temp == 4) 389 hit -= 2; 390 if (windspeed == 6 && temp <= 3) 391 hit--; 392 if (hit >= 0) { 393 if (load != L_GRAPE) 394 hit = hit > 10 ? 10 : hit; 395 table(sp, closest, shootat, load, hit, 396 dieroll()); 397 } 398 } 399 } 400 } 401 402 int 403 next(void) 404 { 405 if (++turn % 55 == 0) { 406 if (alive) 407 alive = 0; 408 else 409 people = 0; 410 } 411 if (people <= 0 || windspeed == 7) { 412 struct ship *s; 413 struct ship *bestship = NULL; 414 float net, best = 0.0; 415 foreachship(s) { 416 if (*s->file->captain) 417 continue; 418 net = (float)s->file->points / s->specs->pts; 419 if (net > best) { 420 best = net; 421 bestship = s; 422 } 423 } 424 if (best > 0.0 && bestship) { 425 char *tp = getenv("WOTD"); 426 const char *p; 427 if (tp == NULL) 428 p = "Driver"; 429 else { 430 *tp = toupper((unsigned char)*tp); 431 p = tp; 432 } 433 strlcpy(bestship->file->captain, p, 434 sizeof bestship->file->captain); 435 logger(bestship); 436 } 437 return -1; 438 } 439 send_turn(turn); 440 if (turn % 7 == 0 && (dieroll() >= cc->windchange || !windspeed)) { 441 switch (dieroll()) { 442 case 1: 443 winddir = 1; 444 break; 445 case 2: 446 break; 447 case 3: 448 winddir++; 449 break; 450 case 4: 451 winddir--; 452 break; 453 case 5: 454 winddir += 2; 455 break; 456 case 6: 457 winddir -= 2; 458 break; 459 } 460 if (winddir > 8) 461 winddir -= 8; 462 if (winddir < 1) 463 winddir += 8; 464 if (windspeed) 465 switch (dieroll()) { 466 case 1: 467 case 2: 468 windspeed--; 469 break; 470 case 5: 471 case 6: 472 windspeed++; 473 break; 474 } 475 else 476 windspeed++; 477 send_wind( winddir, windspeed); 478 } 479 return 0; 480 } 481