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 * $DragonFly: src/games/sail/pl_3.c,v 1.3 2006/09/03 17:33:13 pavalos Exp $ 32 */ 33 34 #include "player.h" 35 36 void 37 acceptcombat(void) 38 { 39 int men = 0; 40 int target, temp; 41 int n, r; 42 int idx, rakehim, sternrake; 43 int hhits = 0, ghits = 0, rhits = 0, chits = 0; 44 int crew[3]; 45 int load; 46 int guns, car, ready, shootat, hit; 47 int roll; 48 struct ship *closest; 49 50 crew[0] = mc->crew1; 51 crew[1] = mc->crew2; 52 crew[2] = mc->crew3; 53 for (n = 0; n < 3; n++) { 54 if (mf->OBP[n].turnsent) 55 men += mf->OBP[n].mensent; 56 } 57 for (n = 0; n < 3; n++) { 58 if (mf->DBP[n].turnsent) 59 men += mf->DBP[n].mensent; 60 } 61 if (men) { 62 crew[0] = men/100 ? 0 : crew[0] != 0; 63 crew[1] = (men%100)/10 ? 0 : crew[1] != 0; 64 crew[2] = men%10 ? 0 : crew[2] != 0; 65 } 66 for (r = 0; r < 2; r++) { 67 if (r) { 68 ready = mf->readyR; 69 load = mf->loadR; 70 guns = mc->gunR; 71 car = mc->carR; 72 } else { 73 ready = mf->readyL; 74 load = mf->loadL; 75 guns = mc->gunL; 76 car = mc->carL; 77 } 78 if ((!guns && !car) || load == L_EMPTY || 79 (ready & R_LOADED) == 0) 80 goto cant; 81 if (mf->struck || !crew[2]) 82 goto cant; 83 closest = closestenemy(ms, (r ? 'r' : 'l'), 1); 84 if (closest == 0) 85 goto cant; 86 if (closest->file->struck) 87 goto cant; 88 target = range(ms, closest); 89 if (target > rangeofshot[load] || (!guns && target >= 3)) 90 goto cant; 91 Signal("%s (%c%c) within range of %s broadside.", 92 closest, r ? "right" : "left"); 93 if (load > L_CHAIN && target < 6) { 94 switch (sgetch("Aim for hull or rigging? ", 95 NULL, 1)) { 96 case 'r': 97 shootat = RIGGING; 98 break; 99 case 'h': 100 shootat = HULL; 101 break; 102 default: 103 shootat = -1; 104 Signal("'Avast there! Hold your fire.'", 105 NULL); 106 } 107 } else { 108 if (sgetch("Fire? ", NULL, 1) == 'n') { 109 shootat = -1; 110 Signal("Belay that! Hold your fire.", 111 NULL); 112 } else 113 shootat = RIGGING; 114 } 115 if (shootat == -1) 116 continue; 117 fired = 1; 118 rakehim = gunsbear(ms, closest) && !gunsbear(closest, ms); 119 temp = portside(closest, ms, 1) - closest->file->dir + 1; 120 if (temp < 1) 121 temp += 8; 122 else if (temp > 8) 123 temp -= 8; 124 sternrake = temp > 4 && temp < 6; 125 if (rakehim) { 126 if (!sternrake) 127 Signal("Raking the %s!", closest); 128 else 129 Signal("Stern Rake! %s splintering!", closest); 130 } 131 idx = guns; 132 if (target < 3) 133 idx += car; 134 idx = (idx - 1)/3; 135 idx = idx > 8 ? 8 : idx; 136 if (!rakehim) 137 hit = HDT[idx][target-1]; 138 else 139 hit = HDTrake[idx][target-1]; 140 if (rakehim && sternrake) 141 hit++; 142 hit += QUAL[idx][mc->qual-1]; 143 for (n = 0; n < 3 && mf->captured == 0; n++) 144 if (!crew[n]) { 145 if (idx <= 5) 146 hit--; 147 else 148 hit -= 2; 149 } 150 if (ready & R_INITIAL) { 151 if (idx <= 3) 152 hit++; 153 else 154 hit += 2; 155 } 156 if (mf->captured != 0) { 157 if (idx <= 1) 158 hit--; 159 else 160 hit -= 2; 161 } 162 hit += AMMO[idx][load - 1]; 163 if (((temp = mc->class) >= 5 || temp == 1) && windspeed == 5) 164 hit--; 165 if (windspeed == 6 && temp == 4) 166 hit -= 2; 167 if (windspeed == 6 && temp <= 3) 168 hit--; 169 if (hit >= 0) { 170 roll = die(); 171 if (load == L_GRAPE) 172 chits = hit; 173 else { 174 struct Tables *t; 175 if (hit > 10) 176 hit = 10; 177 t = &(shootat == RIGGING ? RigTable : HullTable) 178 [hit][roll-1]; 179 chits = t->C; 180 rhits = t->R; 181 hhits = t->H; 182 ghits = t->G; 183 if (closest->file->FS) 184 rhits *= 2; 185 if (load == L_CHAIN) { 186 ghits = 0; 187 hhits = 0; 188 } 189 } 190 table(shootat, load, hit, closest, ms, roll); 191 } 192 Signal("Damage inflicted on the %s:", 193 NULL, closest->shipname); 194 Signal("\t%d HULL, %d GUNS, %d CREW, %d RIGGING", 195 NULL, hhits, ghits, chits, rhits); 196 if (!r) { 197 mf->loadL = L_EMPTY; 198 mf->readyL = R_EMPTY; 199 } else { 200 mf->loadR = L_EMPTY; 201 mf->readyR = R_EMPTY; 202 } 203 continue; 204 cant: 205 Signal("Unable to fire %s broadside", 206 NULL, r ? "right" : "left"); 207 } 208 blockalarm(); 209 draw_stat(); 210 unblockalarm(); 211 } 212 213 void 214 grapungrap(void) 215 { 216 struct ship *sp; 217 int i; 218 219 foreachship(sp) { 220 if (sp == ms || sp->file->dir == 0) 221 continue; 222 if (range(ms, sp) > 1 && !grappled2(ms, sp)) 223 continue; 224 switch (sgetch("Attempt to grapple or ungrapple %s (%c%c): ", 225 sp, 1)) { 226 case 'g': 227 if (die() < 3 228 || ms->nationality == capship(sp)->nationality) { 229 Write(W_GRAP, ms, sp->file->index, 0, 0, 0); 230 Write(W_GRAP, sp, player, 0, 0, 0); 231 Signal("Attempt succeeds!", NULL); 232 makesignal(ms, "grappled with %s (%c%c)", sp); 233 } else 234 Signal("Attempt fails.", NULL); 235 break; 236 case 'u': 237 for (i = grappled2(ms, sp); --i >= 0;) { 238 if (ms->nationality 239 == capship(sp)->nationality 240 || die() < 3) { 241 cleangrapple(ms, sp, 0); 242 Signal("Attempt succeeds!", 243 NULL); 244 makesignal(ms, 245 "ungrappling with %s (%c%c)", 246 sp); 247 } else 248 Signal("Attempt fails.", 249 NULL); 250 } 251 break; 252 } 253 } 254 } 255 256 void 257 unfoulplayer(void) 258 { 259 struct ship *to; 260 int i; 261 262 foreachship(to) { 263 if (fouled2(ms, to) == 0) 264 continue; 265 if (sgetch("Attempt to unfoul with the %s (%c%c)? ", to, 1) != 'y') 266 continue; 267 for (i = fouled2(ms, to); --i >= 0;) { 268 if (die() <= 2) { 269 cleanfoul(ms, to, 0); 270 Signal("Attempt succeeds!", NULL); 271 makesignal(ms, "Unfouling %s (%c%c)", to); 272 } else 273 Signal("Attempt fails.", NULL); 274 } 275 } 276 } 277