]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - trek/phaser.c
make dm setgid games, rather than setuid games.
[bsdgames-darwin.git] / trek / phaser.c
1 /* $NetBSD: phaser.c,v 1.5 1997/10/12 21:25:06 christos Exp $ */
2
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)phaser.c 8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: phaser.c,v 1.5 1997/10/12 21:25:06 christos Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <stdio.h>
46 #include <math.h>
47 #include "trek.h"
48 #include "getpar.h"
49
50 /* factors for phaser hits; see description below */
51
52 # define ALPHA 3.0 /* spread */
53 # define BETA 3.0 /* franf() */
54 # define GAMMA 0.30 /* cos(angle) */
55 # define EPSILON 150.0 /* dist ** 2 */
56 # define OMEGA 10.596 /* overall scaling factor */
57
58 /* OMEGA ~= 100 * (ALPHA + 1) * (BETA + 1) / (EPSILON + 1) */
59
60 /*
61 ** Phaser Control
62 **
63 ** There are up to NBANKS phaser banks which may be fired
64 ** simultaneously. There are two modes, "manual" and
65 ** "automatic". In manual mode, you specify exactly which
66 ** direction you want each bank to be aimed, the number
67 ** of units to fire, and the spread angle. In automatic
68 ** mode, you give only the total number of units to fire.
69 **
70 ** The spread is specified as a number between zero and
71 ** one, with zero being minimum spread and one being maximum
72 ** spread. You will normally want zero spread, unless your
73 ** short range scanners are out, in which case you probably
74 ** don't know exactly where the Klingons are. In that case,
75 ** you really don't have any choice except to specify a
76 ** fairly large spread.
77 **
78 ** Phasers spread slightly, even if you specify zero spread.
79 **
80 ** Uses trace flag 30
81 */
82
83 struct cvntab Matab[] =
84 {
85 { "m", "anual", (cmdfun) 1, 0 },
86 { "a", "utomatic", (cmdfun) 0, 0 },
87 { NULL, NULL, NULL, 0 }
88 };
89
90 struct banks
91 {
92 int units;
93 double angle;
94 double spread;
95 };
96
97
98
99 /*ARGSUSED*/
100 void
101 phaser(v)
102 int v;
103 {
104 int i;
105 int j;
106 struct kling *k;
107 double dx, dy;
108 double anglefactor, distfactor;
109 struct banks *b;
110 int manual, flag, extra = 0;
111 int hit;
112 double tot;
113 int n;
114 int hitreqd[NBANKS];
115 struct banks bank[NBANKS];
116 struct cvntab *ptr;
117
118 if (Ship.cond == DOCKED) {
119 printf("Phasers cannot fire through starbase shields\n");
120 return;
121 }
122 if (damaged(PHASER)) {
123 out(PHASER);
124 return;
125 }
126 if (Ship.shldup) {
127 printf("Sulu: Captain, we cannot fire through shields.\n");
128 return;
129 }
130 if (Ship.cloaked)
131 {
132 printf("Sulu: Captain, surely you must realize that we cannot fire\n");
133 printf(" phasers with the cloaking device up.\n");
134 return;
135 }
136
137 /* decide if we want manual or automatic mode */
138 manual = 0;
139 if (testnl())
140 {
141 if (damaged(COMPUTER))
142 {
143 printf(Device[COMPUTER].name);
144 manual++;
145 }
146 else
147 if (damaged(SRSCAN))
148 {
149 printf(Device[SRSCAN].name);
150 manual++;
151 }
152 if (manual)
153 printf(" damaged, manual mode selected\n");
154 }
155
156 if (!manual)
157 {
158 ptr = getcodpar("Manual or automatic", Matab);
159 manual = (long) ptr->value;
160 }
161 if (!manual && damaged(COMPUTER))
162 {
163 printf("Computer damaged, manual selected\n");
164 skiptonl(0);
165 manual++;
166 }
167
168 /* initialize the bank[] array */
169 flag = 1;
170 for (i = 0; i < NBANKS; i++)
171 bank[i].units = 0;
172 if (manual)
173 {
174 /* collect manual mode statistics */
175 while (flag)
176 {
177 printf("%d units available\n", Ship.energy);
178 extra = 0;
179 flag = 0;
180 for (i = 0; i < NBANKS; i++)
181 {
182 b = &bank[i];
183 printf("\nBank %d:\n", i);
184 hit = getintpar("units");
185 if (hit < 0)
186 return;
187 if (hit == 0)
188 break;
189 extra += hit;
190 if (extra > Ship.energy)
191 {
192 printf("available energy exceeded. ");
193 skiptonl(0);
194 flag++;
195 break;
196 }
197 b->units = hit;
198 hit = getintpar("course");
199 if (hit < 0 || hit > 360)
200 return;
201 b->angle = hit * 0.0174532925;
202 b->spread = getfltpar("spread");
203 if (b->spread < 0 || b->spread > 1)
204 return;
205 }
206 Ship.energy -= extra;
207 }
208 extra = 0;
209 }
210 else
211 {
212 /* automatic distribution of power */
213 if (Etc.nkling <= 0) {
214 printf("Sulu: But there are no Klingons in this quadrant\n");
215 return;
216 }
217 printf("Phasers locked on target. ");
218 while (flag)
219 {
220 printf("%d units available\n", Ship.energy);
221 hit = getintpar("Units to fire");
222 if (hit <= 0)
223 return;
224 if (hit > Ship.energy)
225 {
226 printf("available energy exceeded. ");
227 skiptonl(0);
228 continue;
229 }
230 flag = 0;
231 Ship.energy -= hit;
232 extra = hit;
233 n = Etc.nkling;
234 if (n > NBANKS)
235 n = NBANKS;
236 tot = n * (n + 1) / 2;
237 for (i = 0; i < n; i++)
238 {
239 k = &Etc.klingon[i];
240 b = &bank[i];
241 distfactor = k->dist;
242 anglefactor = ALPHA * BETA * OMEGA / (distfactor * distfactor + EPSILON);
243 anglefactor *= GAMMA;
244 distfactor = k->power;
245 distfactor /= anglefactor;
246 hitreqd[i] = distfactor + 0.5;
247 dx = Ship.sectx - k->x;
248 dy = k->y - Ship.secty;
249 b->angle = atan2(dy, dx);
250 b->spread = 0.0;
251 b->units = ((n - i) / tot) * extra;
252 # ifdef xTRACE
253 if (Trace)
254 {
255 printf("b%d hr%d u%d df%.2f af%.2f\n",
256 i, hitreqd[i], b->units,
257 distfactor, anglefactor);
258 }
259 # endif
260 extra -= b->units;
261 hit = b->units - hitreqd[i];
262 if (hit > 0)
263 {
264 extra += hit;
265 b->units -= hit;
266 }
267 }
268
269 /* give out any extra energy we might have around */
270 if (extra > 0)
271 {
272 for (i = 0; i < n; i++)
273 {
274 b = &bank[i];
275 hit = hitreqd[i] - b->units;
276 if (hit <= 0)
277 continue;
278 if (hit >= extra)
279 {
280 b->units += extra;
281 extra = 0;
282 break;
283 }
284 b->units = hitreqd[i];
285 extra -= hit;
286 }
287 if (extra > 0)
288 printf("%d units overkill\n", extra);
289 }
290 }
291 }
292
293 # ifdef xTRACE
294 if (Trace)
295 {
296 for (i = 0; i < NBANKS; i++)
297 {
298 b = &bank[i];
299 printf("b%d u%d", i, b->units);
300 if (b->units > 0)
301 printf(" a%.2f s%.2f\n", b->angle, b->spread);
302 else
303 printf("\n");
304 }
305 }
306 # endif
307
308 /* actually fire the shots */
309 Move.free = 0;
310 for (i = 0; i < NBANKS; i++)
311 {
312 b = &bank[i];
313 if (b->units <= 0)
314 {
315 continue;
316 }
317 printf("\nPhaser bank %d fires:\n", i);
318 n = Etc.nkling;
319 k = Etc.klingon;
320 for (j = 0; j < n; j++)
321 {
322 if (b->units <= 0)
323 break;
324 /*
325 ** The formula for hit is as follows:
326 **
327 ** zap = OMEGA * [(sigma + ALPHA) * (rho + BETA)]
328 ** / (dist ** 2 + EPSILON)]
329 ** * [cos(delta * sigma) + GAMMA]
330 ** * hit
331 **
332 ** where sigma is the spread factor,
333 ** rho is a random number (0 -> 1),
334 ** GAMMA is a crud factor for angle (essentially
335 ** cruds up the spread factor),
336 ** delta is the difference in radians between the
337 ** angle you are shooting at and the actual
338 ** angle of the klingon,
339 ** ALPHA scales down the significance of sigma,
340 ** BETA scales down the significance of rho,
341 ** OMEGA is the magic number which makes everything
342 ** up to "* hit" between zero and one,
343 ** dist is the distance to the klingon
344 ** hit is the number of units in the bank, and
345 ** zap is the amount of the actual hit.
346 **
347 ** Everything up through dist squared should maximize
348 ** at 1.0, so that the distance factor is never
349 ** greater than one. Conveniently, cos() is
350 ** never greater than one, but the same restric-
351 ** tion applies.
352 */
353 distfactor = BETA + franf();
354 distfactor *= ALPHA + b->spread;
355 distfactor *= OMEGA;
356 anglefactor = k->dist;
357 distfactor /= anglefactor * anglefactor + EPSILON;
358 distfactor *= b->units;
359 dx = Ship.sectx - k->x;
360 dy = k->y - Ship.secty;
361 anglefactor = atan2(dy, dx) - b->angle;
362 anglefactor = cos((anglefactor * b->spread) + GAMMA);
363 if (anglefactor < 0.0)
364 {
365 k++;
366 continue;
367 }
368 hit = anglefactor * distfactor + 0.5;
369 k->power -= hit;
370 printf("%d unit hit on Klingon", hit);
371 if (!damaged(SRSCAN))
372 printf(" at %d,%d", k->x, k->y);
373 printf("\n");
374 b->units -= hit;
375 if (k->power <= 0)
376 {
377 killk(k->x, k->y);
378 continue;
379 }
380 k++;
381 }
382 }
383
384 /* compute overkill */
385 for (i = 0; i < NBANKS; i++)
386 extra += bank[i].units;
387 if (extra > 0)
388 printf("\n%d units expended on empty space\n", extra);
389 }