xref: /dragonfly/games/trek/torped.c (revision 4318c66eac379e15105fe145d406dfef81b795f6)
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