|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)phaser.c 5.1 (Berkeley) 1/29/86";
9: #endif not lint
10:
11: # include "trek.h"
12: # include "getpar.h"
13:
14: /* factors for phaser hits; see description below */
15:
16: # define ALPHA 3.0 /* spread */
17: # define BETA 3.0 /* franf() */
18: # define GAMMA 0.30 /* cos(angle) */
19: # define EPSILON 150.0 /* dist ** 2 */
20: # define OMEGA 10.596 /* overall scaling factor */
21:
22: /* OMEGA ~= 100 * (ALPHA + 1) * (BETA + 1) / (EPSILON + 1) */
23:
24: /*
25: ** Phaser Control
26: **
27: ** There are up to NBANKS phaser banks which may be fired
28: ** simultaneously. There are two modes, "manual" and
29: ** "automatic". In manual mode, you specify exactly which
30: ** direction you want each bank to be aimed, the number
31: ** of units to fire, and the spread angle. In automatic
32: ** mode, you give only the total number of units to fire.
33: **
34: ** The spread is specified as a number between zero and
35: ** one, with zero being minimum spread and one being maximum
36: ** spread. You will normally want zero spread, unless your
37: ** short range scanners are out, in which case you probably
38: ** don't know exactly where the Klingons are. In that case,
39: ** you really don't have any choice except to specify a
40: ** fairly large spread.
41: **
42: ** Phasers spread slightly, even if you specify zero spread.
43: **
44: ** Uses trace flag 30
45: */
46:
47: struct cvntab Matab[] =
48: {
49: "m", "anual", (int (*)())1, 0,
50: "a", "utomatic", 0, 0,
51: 0
52: };
53:
54: struct banks
55: {
56: int units;
57: double angle;
58: double spread;
59: };
60:
61:
62:
63: phaser()
64: {
65: register int i;
66: int j;
67: register struct kling *k;
68: double dx, dy;
69: double anglefactor, distfactor;
70: register struct banks *b;
71: int manual, flag, extra;
72: int hit;
73: double tot;
74: int n;
75: int hitreqd[NBANKS];
76: struct banks bank[NBANKS];
77: struct cvntab *ptr;
78:
79: if (Ship.cond == DOCKED)
80: return(printf("Phasers cannot fire through starbase shields\n"));
81: if (damaged(PHASER))
82: return (out(PHASER));
83: if (Ship.shldup)
84: return (printf("Sulu: Captain, we cannot fire through shields.\n"));
85: if (Ship.cloaked)
86: {
87: printf("Sulu: Captain, surely you must realize that we cannot fire\n");
88: printf(" phasers with the cloaking device up.\n");
89: return;
90: }
91:
92: /* decide if we want manual or automatic mode */
93: manual = 0;
94: if (testnl())
95: {
96: if (damaged(COMPUTER))
97: {
98: printf(Device[COMPUTER].name);
99: manual++;
100: }
101: else
102: if (damaged(SRSCAN))
103: {
104: printf(Device[SRSCAN].name);
105: manual++;
106: }
107: if (manual)
108: printf(" damaged, manual mode selected\n");
109: }
110:
111: if (!manual)
112: {
113: ptr = getcodpar("Manual or automatic", Matab);
114: manual = (int) ptr->value;
115: }
116: if (!manual && damaged(COMPUTER))
117: {
118: printf("Computer damaged, manual selected\n");
119: skiptonl(0);
120: manual++;
121: }
122:
123: /* initialize the bank[] array */
124: flag = 1;
125: for (i = 0; i < NBANKS; i++)
126: bank[i].units = 0;
127: if (manual)
128: {
129: /* collect manual mode statistics */
130: while (flag)
131: {
132: printf("%d units available\n", Ship.energy);
133: extra = 0;
134: flag = 0;
135: for (i = 0; i < NBANKS; i++)
136: {
137: b = &bank[i];
138: printf("\nBank %d:\n", i);
139: hit = getintpar("units");
140: if (hit < 0)
141: return;
142: if (hit == 0)
143: break;
144: extra += hit;
145: if (extra > Ship.energy)
146: {
147: printf("available energy exceeded. ");
148: skiptonl(0);
149: flag++;
150: break;
151: }
152: b->units = hit;
153: hit = getintpar("course");
154: if (hit < 0 || hit > 360)
155: return;
156: b->angle = hit * 0.0174532925;
157: b->spread = getfltpar("spread");
158: if (b->spread < 0 || b->spread > 1)
159: return;
160: }
161: Ship.energy -= extra;
162: }
163: extra = 0;
164: }
165: else
166: {
167: /* automatic distribution of power */
168: if (Etc.nkling <= 0)
169: return (printf("Sulu: But there are no Klingons in this quadrant\n"));
170: printf("Phasers locked on target. ");
171: while (flag)
172: {
173: printf("%d units available\n", Ship.energy);
174: hit = getintpar("Units to fire");
175: if (hit <= 0)
176: return;
177: if (hit > Ship.energy)
178: {
179: printf("available energy exceeded. ");
180: skiptonl(0);
181: continue;
182: }
183: flag = 0;
184: Ship.energy -= hit;
185: extra = hit;
186: n = Etc.nkling;
187: if (n > NBANKS)
188: n = NBANKS;
189: tot = n * (n + 1) / 2;
190: for (i = 0; i < n; i++)
191: {
192: k = &Etc.klingon[i];
193: b = &bank[i];
194: distfactor = k->dist;
195: anglefactor = ALPHA * BETA * OMEGA / (distfactor * distfactor + EPSILON);
196: anglefactor *= GAMMA;
197: distfactor = k->power;
198: distfactor /= anglefactor;
199: hitreqd[i] = distfactor + 0.5;
200: dx = Ship.sectx - k->x;
201: dy = k->y - Ship.secty;
202: b->angle = atan2(dy, dx);
203: b->spread = 0.0;
204: b->units = ((n - i) / tot) * extra;
205: # ifdef xTRACE
206: if (Trace)
207: {
208: printf("b%d hr%d u%d df%.2f af%.2f\n",
209: i, hitreqd[i], b->units,
210: distfactor, anglefactor);
211: }
212: # endif
213: extra -= b->units;
214: hit = b->units - hitreqd[i];
215: if (hit > 0)
216: {
217: extra += hit;
218: b->units -= hit;
219: }
220: }
221:
222: /* give out any extra energy we might have around */
223: if (extra > 0)
224: {
225: for (i = 0; i < n; i++)
226: {
227: b = &bank[i];
228: hit = hitreqd[i] - b->units;
229: if (hit <= 0)
230: continue;
231: if (hit >= extra)
232: {
233: b->units += extra;
234: extra = 0;
235: break;
236: }
237: b->units = hitreqd[i];
238: extra -= hit;
239: }
240: if (extra > 0)
241: printf("%d units overkill\n", extra);
242: }
243: }
244: }
245:
246: # ifdef xTRACE
247: if (Trace)
248: {
249: for (i = 0; i < NBANKS; i++)
250: {
251: b = &bank[i];
252: printf("b%d u%d", i, b->units);
253: if (b->units > 0)
254: printf(" a%.2f s%.2f\n", b->angle, b->spread);
255: else
256: printf("\n");
257: }
258: }
259: # endif
260:
261: /* actually fire the shots */
262: Move.free = 0;
263: for (i = 0; i < NBANKS; i++)
264: {
265: b = &bank[i];
266: if (b->units <= 0)
267: {
268: continue;
269: }
270: printf("\nPhaser bank %d fires:\n", i);
271: n = Etc.nkling;
272: k = Etc.klingon;
273: for (j = 0; j < n; j++)
274: {
275: if (b->units <= 0)
276: break;
277: /*
278: ** The formula for hit is as follows:
279: **
280: ** zap = OMEGA * [(sigma + ALPHA) * (rho + BETA)]
281: ** / (dist ** 2 + EPSILON)]
282: ** * [cos(delta * sigma) + GAMMA]
283: ** * hit
284: **
285: ** where sigma is the spread factor,
286: ** rho is a random number (0 -> 1),
287: ** GAMMA is a crud factor for angle (essentially
288: ** cruds up the spread factor),
289: ** delta is the difference in radians between the
290: ** angle you are shooting at and the actual
291: ** angle of the klingon,
292: ** ALPHA scales down the significance of sigma,
293: ** BETA scales down the significance of rho,
294: ** OMEGA is the magic number which makes everything
295: ** up to "* hit" between zero and one,
296: ** dist is the distance to the klingon
297: ** hit is the number of units in the bank, and
298: ** zap is the amount of the actual hit.
299: **
300: ** Everything up through dist squared should maximize
301: ** at 1.0, so that the distance factor is never
302: ** greater than one. Conveniently, cos() is
303: ** never greater than one, but the same restric-
304: ** tion applies.
305: */
306: distfactor = BETA + franf();
307: distfactor *= ALPHA + b->spread;
308: distfactor *= OMEGA;
309: anglefactor = k->dist;
310: distfactor /= anglefactor * anglefactor + EPSILON;
311: distfactor *= b->units;
312: dx = Ship.sectx - k->x;
313: dy = k->y - Ship.secty;
314: anglefactor = atan2(dy, dx) - b->angle;
315: anglefactor = cos((anglefactor * b->spread) + GAMMA);
316: if (anglefactor < 0.0)
317: {
318: k++;
319: continue;
320: }
321: hit = anglefactor * distfactor + 0.5;
322: k->power -= hit;
323: printf("%d unit hit on Klingon", hit);
324: if (!damaged(SRSCAN))
325: printf(" at %d,%d", k->x, k->y);
326: printf("\n");
327: b->units -= hit;
328: if (k->power <= 0)
329: {
330: killk(k->x, k->y);
331: continue;
332: }
333: k++;
334: }
335: }
336:
337: /* compute overkill */
338: for (i = 0; i < NBANKS; i++)
339: extra += bank[i].units;
340: if (extra > 0)
341: printf("\n%d units expended on empty space\n", extra);
342: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.