1 /* $OpenBSD: dr_1.c,v 1.4 2003/06/03 03:01:41 millert Exp $ */ 2 /* $NetBSD: dr_1.c,v 1.4 1995/04/24 12:25:10 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)dr_1.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 static char rcsid[] = "$OpenBSD: dr_1.c,v 1.4 2003/06/03 03:01:41 millert Exp $"; 38 #endif 39 #endif /* not lint */ 40 41 #include "driver.h" 42 #include <stdlib.h> 43 44 void 45 unfoul() 46 { 47 struct ship *sp; 48 struct ship *to; 49 int nat; 50 int i; 51 52 foreachship(sp) { 53 if (sp->file->captain[0]) 54 continue; 55 nat = capship(sp)->nationality; 56 foreachship(to) { 57 if (nat != capship(to)->nationality && 58 !is_toughmelee(sp, to, 0, 0)) 59 continue; 60 for (i = fouled2(sp, to); --i >= 0;) 61 if (die() <= 2) 62 cleanfoul(sp, to, 0); 63 } 64 } 65 } 66 67 void 68 boardcomp() 69 { 70 int crew[3]; 71 struct ship *sp, *sq; 72 73 foreachship(sp) { 74 if (*sp->file->captain) 75 continue; 76 if (sp->file->dir == 0) 77 continue; 78 if (sp->file->struck || sp->file->captured != 0) 79 continue; 80 if (!snagged(sp)) 81 continue; 82 crew[0] = sp->specs->crew1 != 0; 83 crew[1] = sp->specs->crew2 != 0; 84 crew[2] = sp->specs->crew3 != 0; 85 foreachship(sq) { 86 if (!Xsnagged2(sp, sq)) 87 continue; 88 if (meleeing(sp, sq)) 89 continue; 90 if (!sq->file->dir 91 || sp->nationality == capship(sq)->nationality) 92 continue; 93 switch (sp->specs->class - sq->specs->class) { 94 case -3: case -4: case -5: 95 if (crew[0]) { 96 /* OBP */ 97 sendbp(sp, sq, crew[0]*100, 0); 98 crew[0] = 0; 99 } else if (crew[1]){ 100 /* OBP */ 101 sendbp(sp, sq, crew[1]*10, 0); 102 crew[1] = 0; 103 } 104 break; 105 case -2: 106 if (crew[0] || crew[1]) { 107 /* OBP */ 108 sendbp(sp, sq, crew[0]*100+crew[1]*10, 109 0); 110 crew[0] = crew[1] = 0; 111 } 112 break; 113 case -1: case 0: case 1: 114 if (crew[0]) { 115 /* OBP */ 116 sendbp(sp, sq, crew[0]*100+crew[1]*10, 117 0); 118 crew[0] = crew[1] = 0; 119 } 120 break; 121 case 2: case 3: case 4: case 5: 122 /* OBP */ 123 sendbp(sp, sq, crew[0]*100+crew[1]*10+crew[2], 124 0); 125 crew[0] = crew[1] = crew[2] = 0; 126 break; 127 } 128 } 129 } 130 } 131 132 int 133 fightitout(from, to, key) 134 struct ship *from, *to; 135 int key; 136 { 137 struct ship *fromcap, *tocap; 138 int crewfrom[3], crewto[3], menfrom, mento; 139 int pcto, pcfrom, fromstrength, strengthto, frominjured, toinjured; 140 int topoints; 141 int index, totalfrom = 0, totalto = 0; 142 int count; 143 char message[60]; 144 145 menfrom = mensent(from, to, crewfrom, &fromcap, &pcfrom, key); 146 mento = mensent(to, from, crewto, &tocap, &pcto, 0); 147 if (fromcap == 0) 148 fromcap = from; 149 if (tocap == 0) 150 tocap = to; 151 if (key) { 152 if (!menfrom) { /* if crew surprised */ 153 if (fromcap == from) 154 menfrom = from->specs->crew1 155 + from->specs->crew2 156 + from->specs->crew3; 157 else 158 menfrom = from->file->pcrew; 159 } else { 160 menfrom *= 2; /* DBP's fight at an advantage */ 161 } 162 } 163 fromstrength = menfrom * fromcap->specs->qual; 164 strengthto = mento * tocap->specs->qual; 165 for (count = 0; 166 ((fromstrength < strengthto * 3 && strengthto < fromstrength * 3) 167 || fromstrength == -1) && count < 4; 168 count++) { 169 index = fromstrength/10; 170 if (index > 8) 171 index = 8; 172 toinjured = MT[index][2 - die() / 3]; 173 totalto += toinjured; 174 index = strengthto/10; 175 if (index > 8) 176 index = 8; 177 frominjured = MT[index][2 - die() / 3]; 178 totalfrom += frominjured; 179 menfrom -= frominjured; 180 mento -= toinjured; 181 fromstrength = menfrom * fromcap->specs->qual; 182 strengthto = mento * tocap->specs->qual; 183 } 184 if (fromstrength >= strengthto * 3 || count == 4) { 185 unboard(to, from, 0); 186 subtract(from, totalfrom, crewfrom, fromcap, pcfrom); 187 subtract(to, totalto, crewto, tocap, pcto); 188 makemsg(from, "boarders from %s repelled", to->shipname); 189 (void) snprintf(message, sizeof message, 190 "killed in melee: %d. %s: %d", 191 totalto, from->shipname, totalfrom); 192 Writestr(W_SIGNAL, to, message); 193 if (key) 194 return 1; 195 } else if (strengthto >= fromstrength * 3) { 196 unboard(from, to, 0); 197 subtract(from, totalfrom, crewfrom, fromcap, pcfrom); 198 subtract(to, totalto, crewto, tocap, pcto); 199 if (key) { 200 if (fromcap != from) 201 Write(W_POINTS, fromcap, 202 fromcap->file->points - 203 from->file->struck 204 ? from->specs->pts 205 : 2 * from->specs->pts, 206 0, 0, 0); 207 208 /* ptr1 points to the shipspec for the ship that was just unboarded. 209 I guess that what is going on here is that the pointer is multiplied 210 or something. */ 211 212 Write(W_CAPTURED, from, to->file->index, 0, 0, 0); 213 topoints = 2 * from->specs->pts + to->file->points; 214 if (from->file->struck) 215 topoints -= from->specs->pts; 216 Write(W_POINTS, to, topoints, 0, 0, 0); 217 mento = crewto[0] ? crewto[0] : crewto[1]; 218 if (mento) { 219 subtract(to, mento, crewto, tocap, pcto); 220 subtract(from, - mento, crewfrom, to, 0); 221 } 222 (void) snprintf(message, sizeof message, 223 "captured by the %s!", 224 to->shipname); 225 Writestr(W_SIGNAL, from, message); 226 (void) snprintf(message, sizeof message, 227 "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() 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 (void) 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() 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(shootat, load, hit, closest, sp, die()); 395 } 396 } 397 } 398 } 399 400 int 401 next() 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 if (islower(*tp)) 429 *tp = toupper(*tp); 430 p = tp; 431 } 432 (void) strncpy(bestship->file->captain, p, 433 sizeof bestship->file->captain); 434 bestship->file->captain 435 [sizeof bestship->file->captain - 1] = 0; 436 logger(bestship); 437 } 438 return -1; 439 } 440 Write(W_TURN, SHIP(0), turn, 0, 0, 0); 441 if (turn % 7 == 0 && (die() >= cc->windchange || !windspeed)) { 442 switch (die()) { 443 case 1: 444 winddir = 1; 445 break; 446 case 2: 447 break; 448 case 3: 449 winddir++; 450 break; 451 case 4: 452 winddir--; 453 break; 454 case 5: 455 winddir += 2; 456 break; 457 case 6: 458 winddir -= 2; 459 break; 460 } 461 if (winddir > 8) 462 winddir -= 8; 463 if (winddir < 1) 464 winddir += 8; 465 if (windspeed) 466 switch (die()) { 467 case 1: 468 case 2: 469 windspeed--; 470 break; 471 case 5: 472 case 6: 473 windspeed++; 474 break; 475 } 476 else 477 windspeed++; 478 Write(W_WIND, SHIP(0), winddir, windspeed, 0, 0); 479 } 480 return 0; 481 } 482