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