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