1 /*- 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)pl_3.c 8.1 (Berkeley) 5/31/93 30 * $FreeBSD: src/games/sail/pl_3.c,v 1.6 1999/11/30 03:49:37 billf Exp $ 31 */ 32 33 #include "player.h" 34 35 void 36 acceptcombat(void) 37 { 38 int men = 0; 39 int target, temp; 40 int n, r; 41 int idx, rakehim, sternrake; 42 int hhits = 0, ghits = 0, rhits = 0, chits = 0; 43 int crew[3]; 44 int load; 45 int guns, car, ready, shootat, hit; 46 int roll; 47 struct ship *closest; 48 49 crew[0] = mc->crew1; 50 crew[1] = mc->crew2; 51 crew[2] = mc->crew3; 52 for (n = 0; n < 3; n++) { 53 if (mf->OBP[n].turnsent) 54 men += mf->OBP[n].mensent; 55 } 56 for (n = 0; n < 3; n++) { 57 if (mf->DBP[n].turnsent) 58 men += mf->DBP[n].mensent; 59 } 60 if (men) { 61 crew[0] = men/100 ? 0 : crew[0] != 0; 62 crew[1] = (men%100)/10 ? 0 : crew[1] != 0; 63 crew[2] = men%10 ? 0 : crew[2] != 0; 64 } 65 for (r = 0; r < 2; r++) { 66 if (r) { 67 ready = mf->readyR; 68 load = mf->loadR; 69 guns = mc->gunR; 70 car = mc->carR; 71 } else { 72 ready = mf->readyL; 73 load = mf->loadL; 74 guns = mc->gunL; 75 car = mc->carL; 76 } 77 if ((!guns && !car) || load == L_EMPTY || 78 (ready & R_LOADED) == 0) 79 goto cant; 80 if (mf->struck || !crew[2]) 81 goto cant; 82 closest = closestenemy(ms, (r ? 'r' : 'l'), 1); 83 if (closest == NULL) 84 goto cant; 85 if (closest->file->struck) 86 goto cant; 87 target = range(ms, closest); 88 if (target > rangeofshot[load] || (!guns && target >= 3)) 89 goto cant; 90 Signal("%s (%c%c) within range of %s broadside.", 91 closest, r ? "right" : "left"); 92 if (load > L_CHAIN && target < 6) { 93 switch (sgetch("Aim for hull or rigging? ", 94 NULL, 1)) { 95 case 'r': 96 shootat = RIGGING; 97 break; 98 case 'h': 99 shootat = HULL; 100 break; 101 default: 102 shootat = -1; 103 Signal("'Avast there! Hold your fire.'", 104 NULL); 105 } 106 } else { 107 if (sgetch("Fire? ", NULL, 1) == 'n') { 108 shootat = -1; 109 Signal("Belay that! Hold your fire.", 110 NULL); 111 } else 112 shootat = RIGGING; 113 } 114 if (shootat == -1) 115 continue; 116 fired = 1; 117 rakehim = gunsbear(ms, closest) && !gunsbear(closest, ms); 118 temp = portside(closest, ms, 1) - closest->file->dir + 1; 119 if (temp < 1) 120 temp += 8; 121 else if (temp > 8) 122 temp -= 8; 123 sternrake = temp > 4 && temp < 6; 124 if (rakehim) { 125 if (!sternrake) 126 Signal("Raking the %s!", closest); 127 else 128 Signal("Stern Rake! %s splintering!", closest); 129 } 130 idx = guns; 131 if (target < 3) 132 idx += car; 133 idx = (idx - 1)/3; 134 idx = idx > 8 ? 8 : idx; 135 if (!rakehim) 136 hit = HDT[idx][target-1]; 137 else 138 hit = HDTrake[idx][target-1]; 139 if (rakehim && sternrake) 140 hit++; 141 hit += QUAL[idx][mc->qual-1]; 142 for (n = 0; n < 3 && mf->captured == 0; n++) 143 if (!crew[n]) { 144 if (idx <= 5) 145 hit--; 146 else 147 hit -= 2; 148 } 149 if (ready & R_INITIAL) { 150 if (idx <= 3) 151 hit++; 152 else 153 hit += 2; 154 } 155 if (mf->captured != 0) { 156 if (idx <= 1) 157 hit--; 158 else 159 hit -= 2; 160 } 161 hit += AMMO[idx][load - 1]; 162 if (((temp = mc->class) >= 5 || temp == 1) && windspeed == 5) 163 hit--; 164 if (windspeed == 6 && temp == 4) 165 hit -= 2; 166 if (windspeed == 6 && temp <= 3) 167 hit--; 168 if (hit >= 0) { 169 roll = die(); 170 if (load == L_GRAPE) 171 chits = hit; 172 else { 173 struct Tables *t; 174 if (hit > 10) 175 hit = 10; 176 t = &(shootat == RIGGING ? RigTable : HullTable) 177 [hit][roll-1]; 178 chits = t->C; 179 rhits = t->R; 180 hhits = t->H; 181 ghits = t->G; 182 if (closest->file->FS) 183 rhits *= 2; 184 if (load == L_CHAIN) { 185 ghits = 0; 186 hhits = 0; 187 } 188 } 189 table(shootat, load, hit, closest, ms, roll); 190 } 191 Signal("Damage inflicted on the %s:", 192 NULL, closest->shipname); 193 Signal("\t%d HULL, %d GUNS, %d CREW, %d RIGGING", 194 NULL, hhits, ghits, chits, rhits); 195 if (!r) { 196 mf->loadL = L_EMPTY; 197 mf->readyL = R_EMPTY; 198 } else { 199 mf->loadR = L_EMPTY; 200 mf->readyR = R_EMPTY; 201 } 202 continue; 203 cant: 204 Signal("Unable to fire %s broadside", 205 NULL, r ? "right" : "left"); 206 } 207 blockalarm(); 208 draw_stat(); 209 unblockalarm(); 210 } 211 212 void 213 grapungrap(void) 214 { 215 struct ship *sp; 216 int i; 217 218 foreachship(sp) { 219 if (sp == ms || sp->file->dir == 0) 220 continue; 221 if (range(ms, sp) > 1 && !grappled2(ms, sp)) 222 continue; 223 switch (sgetch("Attempt to grapple or ungrapple %s (%c%c): ", 224 sp, 1)) { 225 case 'g': 226 if (die() < 3 227 || ms->nationality == capship(sp)->nationality) { 228 Write(W_GRAP, ms, sp->file->index, 0, 0, 0); 229 Write(W_GRAP, sp, player, 0, 0, 0); 230 Signal("Attempt succeeds!", NULL); 231 makesignal(ms, "grappled with %s (%c%c)", sp); 232 } else 233 Signal("Attempt fails.", NULL); 234 break; 235 case 'u': 236 for (i = grappled2(ms, sp); --i >= 0;) { 237 if (ms->nationality 238 == capship(sp)->nationality 239 || die() < 3) { 240 cleangrapple(ms, sp, 0); 241 Signal("Attempt succeeds!", 242 NULL); 243 makesignal(ms, 244 "ungrappling with %s (%c%c)", 245 sp); 246 } else 247 Signal("Attempt fails.", 248 NULL); 249 } 250 break; 251 } 252 } 253 } 254 255 void 256 unfoulplayer(void) 257 { 258 struct ship *to; 259 int i; 260 261 foreachship(to) { 262 if (fouled2(ms, to) == 0) 263 continue; 264 if (sgetch("Attempt to unfoul with the %s (%c%c)? ", to, 1) != 'y') 265 continue; 266 for (i = fouled2(ms, to); --i >= 0;) { 267 if (die() <= 2) { 268 cleanfoul(ms, to, 0); 269 Signal("Attempt succeeds!", NULL); 270 makesignal(ms, "Unfouling %s (%c%c)", to); 271 } else 272 Signal("Attempt fails.", NULL); 273 } 274 } 275 } 276