1 /* $OpenBSD: computer.c,v 1.12 2016/01/07 14:37:51 mestre Exp $ */
2 /* $NetBSD: computer.c,v 1.4 1995/04/24 12:25:51 cgd 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 <math.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 #include "getpar.h"
38 #include "trek.h"
39
40 /*
41 ** On-Board Computer
42 **
43 ** A computer request is fetched from the captain. The requests
44 ** are:
45 **
46 ** chart -- print a star chart of the known galaxy. This includes
47 ** every quadrant that has ever had a long range or
48 ** a short range scan done of it, plus the location of
49 ** all starbases. This is of course updated by any sub-
50 ** space radio broadcasts (unless the radio is out).
51 ** The format is the same as that of a long range scan
52 ** except that ".1." indicates that a starbase exists
53 ** but we know nothing else.
54 **
55 ** trajectory -- gives the course and distance to every know
56 ** Klingon in the quadrant. Obviously this fails if the
57 ** short range scanners are out.
58 **
59 ** course -- gives a course computation from whereever you are
60 ** to any specified location. If the course begins
61 ** with a slash, the current quadrant is taken.
62 ** Otherwise the input is quadrant and sector coordi-
63 ** nates of the target sector.
64 **
65 ** move -- identical to course, except that the move is performed.
66 **
67 ** score -- prints out the current score.
68 **
69 ** pheff -- "PHaser EFFectiveness" at a given distance. Tells
70 ** you how much stuff you need to make it work.
71 **
72 ** warpcost -- Gives you the cost in time and units to move for
73 ** a given distance under a given warp speed.
74 **
75 ** impcost -- Same for the impulse engines.
76 **
77 ** distresslist -- Gives a list of the currently known starsystems
78 ** or starbases which are distressed, together with their
79 ** quadrant coordinates.
80 **
81 ** If a command is terminated with a semicolon, you remain in
82 ** the computer; otherwise, you escape immediately to the main
83 ** command processor.
84 */
85
86 struct cvntab Cputab[] =
87 {
88 { "ch", "art", (cmdfun)1, 0 },
89 { "t", "rajectory", (cmdfun)2, 0 },
90 { "c", "ourse", (cmdfun)3, 0 },
91 { "m", "ove", (cmdfun)3, 1 },
92 { "s", "core", (cmdfun)4, 0 },
93 { "p", "heff", (cmdfun)5, 0 },
94 { "w", "arpcost", (cmdfun)6, 0 },
95 { "i", "mpcost", (cmdfun)7, 0 },
96 { "d", "istresslist", (cmdfun)8, 0 },
97 { NULL, NULL, NULL, 0 }
98 };
99
100 static int kalc(int, int, int, int, double *);
101 static void prkalc(int, double);
102
103 void
computer(int v)104 computer(int v)
105 {
106 int ix, iy;
107 int i, j;
108 int tqx, tqy;
109 const struct cvntab *r;
110 int cost;
111 int course;
112 double dist, time;
113 double warpfact;
114 struct quad *q;
115 struct event *e;
116
117 if (check_out(COMPUTER))
118 return;
119 while (1)
120 {
121 r = getcodpar("\nRequest", Cputab);
122 switch ((long)r->value)
123 {
124
125 case 1: /* star chart */
126 printf("Computer record of galaxy for all long range sensor scans\n\n");
127 printf(" ");
128 /* print top header */
129 for (i = 0; i < NQUADS; i++)
130 printf("-%d- ", i);
131 printf("\n");
132 for (i = 0; i < NQUADS; i++)
133 {
134 printf("%d ", i);
135 for (j = 0; j < NQUADS; j++)
136 {
137 if (i == Ship.quadx && j == Ship.quady)
138 {
139 printf("$$$ ");
140 continue;
141 }
142 q = &Quad[i][j];
143 /* 1000 or 1001 is special case */
144 if (q->scanned >= 1000)
145 {
146 if (q->scanned > 1000)
147 printf(".1. ");
148 else
149 printf("/// ");
150 }
151 else
152 if (q->scanned < 0)
153 printf("... ");
154 else
155 printf("%3d ", q->scanned);
156 }
157 printf("%d\n", i);
158 }
159 printf(" ");
160 /* print bottom footer */
161 for (i = 0; i < NQUADS; i++)
162 printf("-%d- ", i);
163 printf("\n");
164 break;
165
166 case 2: /* trajectory */
167 if (check_out(SRSCAN))
168 {
169 break;
170 }
171 if (Etc.nkling <= 0)
172 {
173 printf("No Klingons in this quadrant\n");
174 break;
175 }
176 /* for each Klingon, give the course & distance */
177 for (i = 0; i < Etc.nkling; i++)
178 {
179 printf("Klingon at %d,%d", Etc.klingon[i].x, Etc.klingon[i].y);
180 course = kalc(Ship.quadx, Ship.quady, Etc.klingon[i].x, Etc.klingon[i].y, &dist);
181 prkalc(course, dist);
182 }
183 break;
184
185 case 3: /* course calculation */
186 if (readdelim('/'))
187 {
188 tqx = Ship.quadx;
189 tqy = Ship.quady;
190 }
191 else
192 {
193 ix = getintpar("Quadrant");
194 if (ix < 0 || ix >= NSECTS)
195 break;
196 iy = getintpar("q-y");
197 if (iy < 0 || iy >= NSECTS)
198 break;
199 tqx = ix;
200 tqy = iy;
201 }
202 ix = getintpar("Sector");
203 if (ix < 0 || ix >= NSECTS)
204 break;
205 iy = getintpar("s-y");
206 if (iy < 0 || iy >= NSECTS)
207 break;
208 course = kalc(tqx, tqy, ix, iy, &dist);
209 if (r->value2)
210 {
211 warp(-1, course, dist);
212 break;
213 }
214 printf("%d,%d/%d,%d to %d,%d/%d,%d",
215 Ship.quadx, Ship.quady, Ship.sectx, Ship.secty, tqx, tqy, ix, iy);
216 prkalc(course, dist);
217 break;
218
219 case 4: /* score */
220 score();
221 break;
222
223 case 5: /* phaser effectiveness */
224 dist = getfltpar("range");
225 if (dist < 0.0)
226 break;
227 dist *= 10.0;
228 cost = pow(0.90, dist) * 98.0 + 0.5;
229 printf("Phasers are %d%% effective at that range\n", cost);
230 break;
231
232 case 6: /* warp cost (time/energy) */
233 dist = getfltpar("distance");
234 if (dist < 0.0)
235 break;
236 warpfact = getfltpar("warp factor");
237 if (warpfact <= 0.0)
238 warpfact = Ship.warp;
239 cost = (dist + 0.05) * warpfact * warpfact * warpfact;
240 time = Param.warptime * dist / (warpfact * warpfact);
241 printf("Warp %.2f distance %.2f stardates %.2f cost %d (%d w/ shlds up) units\n",
242 warpfact, dist, time, cost, cost + cost);
243 break;
244
245 case 7: /* impulse cost */
246 dist = getfltpar("distance");
247 if (dist < 0.0)
248 break;
249 cost = 20 + 100 * dist;
250 time = dist / 0.095;
251 printf("Distance %.2f cost %.2f stardates %d units\n",
252 dist, time, cost);
253 break;
254
255 case 8: /* distresslist */
256 j = 1;
257 printf("\n");
258 /* scan the event list */
259 for (i = 0; i < MAXEVENTS; i++)
260 {
261 e = &Event[i];
262 /* ignore hidden entries */
263 if (e->evcode & E_HIDDEN)
264 continue;
265 switch (e->evcode & E_EVENT)
266 {
267
268 case E_KDESB:
269 printf("Klingon is attacking starbase in quadrant %d,%d\n",
270 e->x, e->y);
271 j = 0;
272 break;
273
274 case E_ENSLV:
275 case E_REPRO:
276 printf("Starsystem %s in quadrant %d,%d is distressed\n",
277 Systemname[e->systemname], e->x, e->y);
278 j = 0;
279 break;
280 }
281 }
282 if (j)
283 printf("No known distress calls are active\n");
284 break;
285
286 }
287
288 /* skip to next semicolon or newline. Semicolon
289 * means get new computer request; newline means
290 * exit computer mode. */
291 while ((i = getchar()) != ';')
292 {
293 if (i == '\0')
294 exit(1);
295 if (i == '\n')
296 {
297 ungetc(i, stdin);
298 return;
299 }
300 }
301 }
302 }
303
304
305 /*
306 ** Course Calculation
307 **
308 ** Computes and outputs the course and distance from position
309 ** sqx,sqy/ssx,ssy to tqx,tqy/tsx,tsy.
310 */
311
312 static int
kalc(int tqx,int tqy,int tsx,int tsy,double * dist)313 kalc(int tqx, int tqy, int tsx, int tsy, double *dist)
314 {
315 double dx, dy;
316 double quadsize;
317 double angle;
318 int course;
319
320 /* normalize to quadrant distances */
321 quadsize = NSECTS;
322 dx = (Ship.quadx + Ship.sectx / quadsize) - (tqx + tsx / quadsize);
323 dy = (tqy + tsy / quadsize) - (Ship.quady + Ship.secty / quadsize);
324
325 /* get the angle */
326 angle = atan2(dy, dx);
327 /* make it 0 -> 2 pi */
328 if (angle < 0.0)
329 angle += 6.283185307;
330 /* convert from radians to degrees */
331 course = angle * 57.29577951 + 0.5;
332 dx = dx * dx + dy * dy;
333 *dist = sqrt(dx);
334 return (course);
335 }
336
337 static void
prkalc(int course,double dist)338 prkalc(int course, double dist)
339 {
340 printf(": course %d dist %.3f\n", course, dist);
341 }
342