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