/* $NetBSD: dr_1.c,v 1.27 2009/03/14 22:52:52 dholland Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #ifndef lint #if 0 static char sccsid[] = "@(#)dr_1.c 8.1 (Berkeley) 5/31/93"; #else __RCSID("$NetBSD: dr_1.c,v 1.27 2009/03/14 22:52:52 dholland Exp $"); #endif #endif /* not lint */ #include #include #include #include #include "extern.h" #include "driver.h" static int fightitout(struct ship *, struct ship *, int); void unfoul(void) { struct ship *sp; struct ship *to; int nat; int i; foreachship(sp) { if (sp->file->captain[0]) continue; nat = capship(sp)->nationality; foreachship(to) { if (nat != capship(to)->nationality && !is_toughmelee(sp, to, 0, 0)) continue; for (i = fouled2(sp, to); --i >= 0;) if (dieroll() <= 2) cleanfoul(sp, to, 0); } } } void boardcomp(void) { int crew[3]; struct ship *sp, *sq; foreachship(sp) { if (*sp->file->captain) continue; if (sp->file->dir == 0) continue; if (sp->file->struck || sp->file->captured != 0) continue; if (!snagged(sp)) continue; crew[0] = sp->specs->crew1 != 0; crew[1] = sp->specs->crew2 != 0; crew[2] = sp->specs->crew3 != 0; foreachship(sq) { if (!Xsnagged2(sp, sq)) continue; if (meleeing(sp, sq)) continue; if (!sq->file->dir || sp->nationality == capship(sq)->nationality) continue; switch (sp->specs->class - sq->specs->class) { case -3: case -4: case -5: if (crew[0]) { /* OBP */ sendbp(sp, sq, crew[0]*100, 0); crew[0] = 0; } else if (crew[1]) { /* OBP */ sendbp(sp, sq, crew[1]*10, 0); crew[1] = 0; } break; case -2: if (crew[0] || crew[1]) { /* OBP */ sendbp(sp, sq, crew[0]*100+crew[1]*10, 0); crew[0] = crew[1] = 0; } break; case -1: case 0: case 1: if (crew[0]) { /* OBP */ sendbp(sp, sq, crew[0]*100+crew[1]*10, 0); crew[0] = crew[1] = 0; } break; case 2: case 3: case 4: case 5: /* OBP */ sendbp(sp, sq, crew[0]*100+crew[1]*10+crew[2], 0); crew[0] = crew[1] = crew[2] = 0; break; } } } } static int fightitout(struct ship *from, struct ship *to, int key) { struct ship *fromcap, *tocap; int crewfrom[3], crewto[3], menfrom, mento; int pcto, pcfrom, fromstrength, strengthto, frominjured, toinjured; int topoints; int indx, totalfrom = 0, totalto = 0; int count; char message[60]; menfrom = mensent(from, to, crewfrom, &fromcap, &pcfrom, key); mento = mensent(to, from, crewto, &tocap, &pcto, 0); if (fromcap == NULL) fromcap = from; if (tocap == NULL) tocap = to; if (key) { if (!menfrom) { /* if crew surprised */ if (fromcap == from) menfrom = from->specs->crew1 + from->specs->crew2 + from->specs->crew3; else menfrom = from->file->pcrew; } else { menfrom *= 2; /* DBP's fight at an advantage */ } } fromstrength = menfrom * fromcap->specs->qual; strengthto = mento * tocap->specs->qual; for (count = 0; ((fromstrength < strengthto * 3 && strengthto < fromstrength * 3) || fromstrength == -1) && count < 4; count++) { indx = fromstrength/10; if (indx > 8) indx = 8; toinjured = MT[indx][2 - dieroll() / 3]; totalto += toinjured; indx = strengthto/10; if (indx > 8) indx = 8; frominjured = MT[indx][2 - dieroll() / 3]; totalfrom += frominjured; menfrom -= frominjured; mento -= toinjured; fromstrength = menfrom * fromcap->specs->qual; strengthto = mento * tocap->specs->qual; } if (fromstrength >= strengthto * 3 || count == 4) { unboard(to, from, 0); subtract(from, fromcap, totalfrom, crewfrom, pcfrom); subtract(to, tocap, totalto, crewto, pcto); makemsg(from, "boarders from %s repelled", to->shipname); snprintf(message, sizeof(message), "killed in melee: %d. %s: %d", totalto, from->shipname, totalfrom); send_signal(to, message); if (key) return 1; } else if (strengthto >= fromstrength * 3) { unboard(from, to, 0); subtract(from, fromcap, totalfrom, crewfrom, pcfrom); subtract(to, tocap, totalto, crewto, pcto); if (key) { if (fromcap != from) send_points(fromcap, fromcap->file->points - from->file->struck ? from->specs->pts : 2 * from->specs->pts); send_captured(from, to->file->index); topoints = 2 * from->specs->pts + to->file->points; if (from->file->struck) topoints -= from->specs->pts; send_points(to, topoints); mento = crewto[0] ? crewto[0] : crewto[1]; if (mento) { subtract(to, tocap, mento, crewto, pcto); subtract(from, to, - mento, crewfrom, 0); } snprintf(message, sizeof(message), "captured by the %s!", to->shipname); send_signal(from, message); snprintf(message, sizeof(message), "killed in melee: %d. %s: %d", totalto, from->shipname, totalfrom); send_signal(to, message); mento = 0; return 0; } } return 0; } void resolve(void) { int thwart; struct ship *sp, *sq; foreachship(sp) { if (sp->file->dir == 0) continue; for (sq = sp + 1; sq < ls; sq++) if (sq->file->dir && meleeing(sp, sq) && meleeing(sq, sp)) fightitout(sp, sq, 0); thwart = 2; foreachship(sq) { if (sq->file->dir && meleeing(sq, sp)) thwart = fightitout(sp, sq, 1); if (!thwart) break; } if (!thwart) { foreachship(sq) { if (sq->file->dir && meleeing(sq, sp)) unboard(sq, sp, 0); unboard(sp, sq, 0); } unboard(sp, sp, 1); } else if (thwart == 2) unboard(sp, sp, 1); } } void compcombat(void) { int n; struct ship *sp; struct ship *closest; int crew[3], men = 0, target, temp; int r, guns, ready, load, car; int indx, rakehim, sternrake; int shootat, hit; foreachship(sp) { if (sp->file->captain[0] || sp->file->dir == 0) continue; crew[0] = sp->specs->crew1; crew[1] = sp->specs->crew2; crew[2] = sp->specs->crew3; for (n = 0; n < 3; n++) { if (sp->file->OBP[n].turnsent) men += sp->file->OBP[n].mensent; } for (n = 0; n < 3; n++) { if (sp->file->DBP[n].turnsent) men += sp->file->DBP[n].mensent; } if (men) { crew[0] = men/100 ? 0 : crew[0] != 0; crew[1] = (men%100)/10 ? 0 : crew[1] != 0; crew[2] = men%10 ? 0 : crew[2] != 0; } for (r = 0; r < 2; r++) { if (!crew[2]) continue; if (sp->file->struck) continue; if (r) { ready = sp->file->readyR; guns = sp->specs->gunR; car = sp->specs->carR; } else { ready = sp->file->readyL; guns = sp->specs->gunL; car = sp->specs->carL; } if (!guns && !car) continue; if ((ready & R_LOADED) == 0) continue; closest = closestenemy(sp, r ? 'r' : 'l', 0); if (closest == NULL) continue; if (range(closest, sp) > range(sp, closestenemy(sp, r ? 'r' : 'l', 1))) continue; if (closest->file->struck) continue; target = range(sp, closest); if (target > 10) continue; if (!guns && target >= 3) continue; load = L_ROUND; if (target == 1 && sp->file->loadwith == L_GRAPE) load = L_GRAPE; if (target <= 3 && closest->file->FS) load = L_CHAIN; if (target == 1 && load != L_GRAPE) load = L_DOUBLE; if (load > L_CHAIN && target < 6) shootat = HULL; else shootat = RIGGING; rakehim = gunsbear(sp, closest) && !gunsbear(closest, sp); temp = portside(closest, sp, 1) - closest->file->dir + 1; if (temp < 1) temp += 8; if (temp > 8) temp -= 8; sternrake = temp > 4 && temp < 6; indx = guns; if (target < 3) indx += car; indx = (indx - 1) / 3; indx = indx > 8 ? 8 : indx; if (!rakehim) hit = HDT[indx][target-1]; else hit = HDTrake[indx][target-1]; if (rakehim && sternrake) hit++; hit += QUAL[indx][capship(sp)->specs->qual - 1]; for (n = 0; n < 3 && sp->file->captured == 0; n++) { if (!crew[n]) { if (indx <= 5) hit--; else hit -= 2; } } if (ready & R_INITIAL) { if (!r) sp->file->readyL &= ~R_INITIAL; else sp->file->readyR &= ~R_INITIAL; if (indx <= 3) hit++; else hit += 2; } if (sp->file->captured != 0) { if (indx <= 1) hit--; else hit -= 2; } hit += AMMO[indx][load - 1]; temp = sp->specs->class; if ((temp >= 5 || temp == 1) && windspeed == 5) hit--; if (windspeed == 6 && temp == 4) hit -= 2; if (windspeed == 6 && temp <= 3) hit--; if (hit >= 0) { if (load != L_GRAPE) hit = hit > 10 ? 10 : hit; table(sp, closest, shootat, load, hit, dieroll()); } } } } int next(void) { if (++turn % 55 == 0) { if (alive) alive = 0; else people = 0; } if (people <= 0 || windspeed == 7) { struct ship *s; struct ship *bestship = NULL; float net, best = 0.0; foreachship(s) { if (*s->file->captain) continue; net = (float)s->file->points / s->specs->pts; if (net > best) { best = net; bestship = s; } } if (best > 0.0 && bestship) { char *tp = getenv("WOTD"); const char *p; if (tp == NULL) p = "Driver"; else { *tp = toupper((unsigned char)*tp); p = tp; } strlcpy(bestship->file->captain, p, sizeof bestship->file->captain); logger(bestship); } return -1; } send_turn(turn); if (turn % 7 == 0 && (dieroll() >= cc->windchange || !windspeed)) { switch (dieroll()) { case 1: winddir = 1; break; case 2: break; case 3: winddir++; break; case 4: winddir--; break; case 5: winddir += 2; break; case 6: winddir -= 2; break; } if (winddir > 8) winddir -= 8; if (winddir < 1) winddir += 8; if (windspeed) switch (dieroll()) { case 1: case 2: windspeed--; break; case 5: case 6: windspeed++; break; } else windspeed++; send_wind( winddir, windspeed); } return 0; }