1 /*- 2 * Copyright (c) 1980, 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 * @(#)torped.c 8.1 (Berkeley) 5/31/93 30 * $FreeBSD: src/games/trek/torped.c,v 1.5 1999/11/30 03:49:55 billf Exp $ 31 * $DragonFly: src/games/trek/torped.c,v 1.3 2006/09/07 21:19:44 pavalos Exp $ 32 */ 33 34 #include "trek.h" 35 #include "getpar.h" 36 37 static int randcourse(int); 38 39 /* 40 ** PHOTON TORPEDO CONTROL 41 ** 42 ** Either one or three photon torpedoes are fired. If three 43 ** are fired, it is called a "burst" and you also specify 44 ** a spread angle. 45 ** 46 ** Torpedoes are never 100% accurate. There is always a random 47 ** cludge factor in their course which is increased if you have 48 ** your shields up. Hence, you will find that they are more 49 ** accurate at close range. However, they have the advantage that 50 ** at long range they don't lose any of their power as phasers 51 ** do, i.e., a hit is a hit is a hit, by any other name. 52 ** 53 ** When the course spreads too much, you get a misfire, and the 54 ** course is randomized even more. You also have the chance that 55 ** the misfire damages your torpedo tubes. 56 */ 57 58 void 59 torped(int v __unused) 60 { 61 int ix, iy; 62 double x, y, dx, dy; 63 double angle; 64 int course, course2; 65 int k; 66 double bigger; 67 double sectsize; 68 int burst; 69 int n; 70 71 if (Ship.cloaked) { 72 printf("Federation regulations do not permit attack while cloaked.\n"); 73 return; 74 } 75 if (check_out(TORPED)) 76 return; 77 if (Ship.torped <= 0) { 78 printf("All photon torpedos expended\n"); 79 return; 80 } 81 82 /* get the course */ 83 course = getintpar("Torpedo course"); 84 if (course < 0 || course > 360) 85 return; 86 burst = -1; 87 88 /* need at least three torpedoes for a burst */ 89 if (Ship.torped < 3) { 90 printf("No-burst mode selected\n"); 91 burst = 0; 92 } else { 93 /* see if the user wants one */ 94 if (!testnl()) { 95 k = ungetc(cgetc(0), stdin); 96 if (k >= '0' && k <= '9') 97 burst = 1; 98 } 99 } 100 if (burst < 0) { 101 burst = getynpar("Do you want a burst"); 102 } 103 if (burst) { 104 burst = getintpar("burst angle"); 105 if (burst <= 0) 106 return; 107 if (burst > 15) { 108 printf("Maximum burst angle is 15 degrees\n"); 109 return; 110 } 111 } 112 sectsize = NSECTS; 113 n = -1; 114 if (burst) { 115 n = 1; 116 course -= burst; 117 } 118 for (; n && n <= 3; n++) { 119 /* select a nice random course */ 120 course2 = course + randcourse(n); 121 angle = course2 * 0.0174532925; /* convert to radians */ 122 dx = -cos(angle); 123 dy = sin(angle); 124 bigger = fabs(dx); 125 x = fabs(dy); 126 if (x > bigger) 127 bigger = x; 128 dx /= bigger; 129 dy /= bigger; 130 x = Ship.sectx + 0.5; 131 y = Ship.secty + 0.5; 132 if (Ship.cond != DOCKED) 133 Ship.torped -= 1; 134 printf("Torpedo track"); 135 if (n > 0) 136 printf(", torpedo number %d", n); 137 printf(":\n%6.1f\t%4.1f\n", x, y); 138 while (1) { 139 ix = x += dx; 140 iy = y += dy; 141 if (x < 0.0 || x >= sectsize || 142 y < 0.0 || y >= sectsize) { 143 printf("Torpedo missed\n"); 144 break; 145 } 146 printf("%6.1f\t%4.1f\n", x, y); 147 switch (Sect[ix][iy]) { 148 case EMPTY: 149 continue; 150 151 case HOLE: 152 printf("Torpedo disappears into a black hole\n"); 153 break; 154 155 case KLINGON: 156 for (k = 0; k < Etc.nkling; k++) { 157 if (Etc.klingon[k].x != ix || Etc.klingon[k].y != iy) 158 continue; 159 Etc.klingon[k].power -= 500 + ranf(501); 160 if (Etc.klingon[k].power > 0) { 161 printf("*** Hit on Klingon at %d,%d: extensive damages\n", 162 ix, iy); 163 break; 164 } 165 killk(ix, iy); 166 break; 167 } 168 break; 169 170 case STAR: 171 nova(ix, iy); 172 break; 173 174 case INHABIT: 175 kills(ix, iy, -1); 176 break; 177 178 case BASE: 179 killb(Ship.quadx, Ship.quady); 180 Game.killb += 1; 181 break; 182 default: 183 printf("Unknown object %c at %d,%d destroyed\n", 184 Sect[ix][iy], ix, iy); 185 Sect[ix][iy] = EMPTY; 186 break; 187 } 188 break; 189 } 190 if (damaged(TORPED) || Quad[Ship.quadx][Ship.quady].stars < 0) 191 break; 192 course += burst; 193 } 194 Move.free = 0; 195 } 196 197 198 /* 199 ** RANDOMIZE COURSE 200 ** 201 ** This routine randomizes the course for torpedo number 'n'. 202 ** Other things handled by this routine are misfires, damages 203 ** to the tubes, etc. 204 */ 205 206 static int 207 randcourse(int n) 208 { 209 double r; 210 int d; 211 212 d = ((franf() + franf()) - 1.0) * 20; 213 if (abs(d) > 12) { 214 printf("Photon tubes misfire"); 215 if (n < 0) 216 printf("\n"); 217 else 218 printf(" on torpedo %d\n", n); 219 if (ranf(2)) { 220 damage(TORPED, 0.2 * abs(d) * (franf() + 1.0)); 221 } 222 d *= 1.0 + 2.0 * franf(); 223 } 224 if (Ship.shldup || Ship.cond == DOCKED) { 225 r = Ship.shield; 226 r = 1.0 + r / Param.shield; 227 if (Ship.cond == DOCKED) 228 r = 2.0; 229 d *= r; 230 } 231 return (d); 232 } 233