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