1 /* @(#)torped.c 8.1 (Berkeley) 5/31/93 */
2 /* $NetBSD: torped.c,v 1.14 2009/05/24 23:20:22 dholland Exp $ */
3
4 /*
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include "trek.h"
37 #include "getpar.h"
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 static int randcourse(int);
59
60 /*ARGSUSED*/
61 void
torped(int v __unused)62 torped(int v __unused)
63 {
64 int ix, iy;
65 double x, y, dx, dy;
66 double angle;
67 int course, course2;
68 int k;
69 double bigger;
70 double sectsize;
71 int burst;
72 int n;
73
74 if (Ship.cloaked) {
75 printf("Federation regulations do not permit attack while "
76 "cloaked.\n");
77 return;
78 }
79 if (check_out(TORPED))
80 return;
81 if (Ship.torped <= 0) {
82 printf("All photon torpedos expended\n");
83 return;
84 }
85
86 /* get the course */
87 course = getintpar("Torpedo course");
88 if (course < 0 || course > 360)
89 return;
90 burst = -1;
91
92 /* need at least three torpedoes for a burst */
93 if (Ship.torped < 3) {
94 printf("No-burst mode selected\n");
95 burst = 0;
96 } else {
97 /* see if the user wants one */
98 if (!testnl()) {
99 k = ungetc(getchar(), stdin);
100 if (k >= '0' && k <= '9')
101 burst = 1;
102 }
103 }
104 if (burst < 0) {
105 burst = getynpar("Do you want a burst");
106 }
107 if (burst) {
108 burst = getintpar("burst angle");
109 if (burst <= 0)
110 return;
111 if (burst > 15) {
112 printf("Maximum burst angle is 15 degrees\n");
113 return;
114 }
115 }
116 sectsize = NSECTS;
117 n = -1;
118 if (burst) {
119 n = 1;
120 course -= burst;
121 }
122 for (; n && n <= 3; n++) {
123 /* select a nice random course */
124 course2 = course + randcourse(n);
125 /* convert to radians */
126 angle = course2 * 0.0174532925;
127 dx = -cos(angle);
128 dy = sin(angle);
129 bigger = fabs(dx);
130 x = fabs(dy);
131 if (x > bigger)
132 bigger = x;
133 dx /= bigger;
134 dy /= bigger;
135 x = Ship.sectx + 0.5;
136 y = Ship.secty + 0.5;
137 if (Ship.cond != DOCKED)
138 Ship.torped -= 1;
139 printf("Torpedo track");
140 if (n > 0)
141 printf(", torpedo number %d", n);
142 printf(":\n%6.1f\t%4.1f\n", x, y);
143 while (1) {
144 ix = x += dx;
145 iy = y += dy;
146 if (x < 0.0 || x >= sectsize ||
147 y < 0.0 || y >= sectsize) {
148 printf("Torpedo missed\n");
149 break;
150 }
151 printf("%6.1f\t%4.1f\n", x, y);
152 switch (Sect[ix][iy]) {
153 case EMPTY:
154 continue;
155
156 case HOLE:
157 printf("Torpedo disappears into a black "
158 "hole\n");
159 break;
160
161 case KLINGON:
162 for (k = 0; k < Etc.nkling; k++) {
163 if (Etc.klingon[k].x != ix ||
164 Etc.klingon[k].y != iy)
165 continue;
166 Etc.klingon[k].power -= 500 + ranf(501);
167 if (Etc.klingon[k].power > 0) {
168 printf("*** Hit on Klingon at "
169 "%d,%d: extensive "
170 "damages\n",
171 ix, iy);
172 break;
173 }
174 killk(ix, iy);
175 break;
176 }
177 break;
178
179 case STAR:
180 nova(ix, iy);
181 break;
182
183 case INHABIT:
184 kills(ix, iy, -1);
185 break;
186
187 case BASE:
188 killb(Ship.quadx, Ship.quady);
189 Game.killb += 1;
190 break;
191
192 default:
193 printf("Unknown object %c at %d,%d destroyed\n",
194 Sect[ix][iy], ix, iy);
195 Sect[ix][iy] = EMPTY;
196 break;
197 }
198 break;
199 }
200 if (damaged(TORPED) || Quad[Ship.quadx][Ship.quady].stars < 0)
201 break;
202 course += burst;
203 }
204 Move.free = 0;
205 }
206
207
208 /*
209 ** RANDOMIZE COURSE
210 **
211 ** This routine randomizes the course for torpedo number 'n'.
212 ** Other things handled by this routine are misfires, damages
213 ** to the tubes, etc.
214 */
215
216 static int
randcourse(int n)217 randcourse(int n)
218 {
219 double r;
220 int d;
221
222 d = ((franf() + franf()) - 1.0) * 20;
223 if (abs(d) > 12) {
224 printf("Photon tubes misfire");
225 if (n < 0)
226 printf("\n");
227 else
228 printf(" on torpedo %d\n", n);
229 if (ranf(2)) {
230 damage(TORPED, 0.2 * abs(d) * (franf() + 1.0));
231 }
232 d *= 1.0 + 2.0 * franf();
233 }
234 if (Ship.shldup || Ship.cond == DOCKED) {
235 r = Ship.shield;
236 r = 1.0 + r / Param.shield;
237 if (Ship.cond == DOCKED)
238 r = 2.0;
239 d *= r;
240 }
241 return (d);
242 }
243