1*11da2480Smestre /* $OpenBSD: computer.c,v 1.12 2016/01/07 14:37:51 mestre Exp $ */
2df930be7Sderaadt /* $NetBSD: computer.c,v 1.4 1995/04/24 12:25:51 cgd Exp $ */
3df930be7Sderaadt
4df930be7Sderaadt /*
5df930be7Sderaadt * Copyright (c) 1980, 1993
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt * modification, are permitted provided that the following conditions
10df930be7Sderaadt * are met:
11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt * documentation and/or other materials provided with the distribution.
167a09557bSmillert * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt * may be used to endorse or promote products derived from this software
18df930be7Sderaadt * without specific prior written permission.
19df930be7Sderaadt *
20df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt * SUCH DAMAGE.
31df930be7Sderaadt */
32df930be7Sderaadt
3348b4d137Smestre #include <math.h>
341ed0e75dSpjanzen #include <stdio.h>
3570ef01f6Sdavid #include <stdlib.h>
3648b4d137Smestre
37df930be7Sderaadt #include "getpar.h"
3848b4d137Smestre #include "trek.h"
391ed0e75dSpjanzen
40df930be7Sderaadt /*
41df930be7Sderaadt ** On-Board Computer
42df930be7Sderaadt **
43df930be7Sderaadt ** A computer request is fetched from the captain. The requests
44df930be7Sderaadt ** are:
45df930be7Sderaadt **
46df930be7Sderaadt ** chart -- print a star chart of the known galaxy. This includes
47df930be7Sderaadt ** every quadrant that has ever had a long range or
48df930be7Sderaadt ** a short range scan done of it, plus the location of
49df930be7Sderaadt ** all starbases. This is of course updated by any sub-
50df930be7Sderaadt ** space radio broadcasts (unless the radio is out).
51df930be7Sderaadt ** The format is the same as that of a long range scan
52df930be7Sderaadt ** except that ".1." indicates that a starbase exists
53df930be7Sderaadt ** but we know nothing else.
54df930be7Sderaadt **
55df930be7Sderaadt ** trajectory -- gives the course and distance to every know
56df930be7Sderaadt ** Klingon in the quadrant. Obviously this fails if the
57df930be7Sderaadt ** short range scanners are out.
58df930be7Sderaadt **
59df930be7Sderaadt ** course -- gives a course computation from whereever you are
60df930be7Sderaadt ** to any specified location. If the course begins
61df930be7Sderaadt ** with a slash, the current quadrant is taken.
62df930be7Sderaadt ** Otherwise the input is quadrant and sector coordi-
63df930be7Sderaadt ** nates of the target sector.
64df930be7Sderaadt **
65df930be7Sderaadt ** move -- identical to course, except that the move is performed.
66df930be7Sderaadt **
67df930be7Sderaadt ** score -- prints out the current score.
68df930be7Sderaadt **
69df930be7Sderaadt ** pheff -- "PHaser EFFectiveness" at a given distance. Tells
70df930be7Sderaadt ** you how much stuff you need to make it work.
71df930be7Sderaadt **
72df930be7Sderaadt ** warpcost -- Gives you the cost in time and units to move for
73df930be7Sderaadt ** a given distance under a given warp speed.
74df930be7Sderaadt **
75df930be7Sderaadt ** impcost -- Same for the impulse engines.
76df930be7Sderaadt **
77df930be7Sderaadt ** distresslist -- Gives a list of the currently known starsystems
78df930be7Sderaadt ** or starbases which are distressed, together with their
79df930be7Sderaadt ** quadrant coordinates.
80df930be7Sderaadt **
81df930be7Sderaadt ** If a command is terminated with a semicolon, you remain in
82df930be7Sderaadt ** the computer; otherwise, you escape immediately to the main
83df930be7Sderaadt ** command processor.
84df930be7Sderaadt */
85df930be7Sderaadt
86df930be7Sderaadt struct cvntab Cputab[] =
87df930be7Sderaadt {
881ed0e75dSpjanzen { "ch", "art", (cmdfun)1, 0 },
891ed0e75dSpjanzen { "t", "rajectory", (cmdfun)2, 0 },
901ed0e75dSpjanzen { "c", "ourse", (cmdfun)3, 0 },
911ed0e75dSpjanzen { "m", "ove", (cmdfun)3, 1 },
921ed0e75dSpjanzen { "s", "core", (cmdfun)4, 0 },
931ed0e75dSpjanzen { "p", "heff", (cmdfun)5, 0 },
941ed0e75dSpjanzen { "w", "arpcost", (cmdfun)6, 0 },
951ed0e75dSpjanzen { "i", "mpcost", (cmdfun)7, 0 },
961ed0e75dSpjanzen { "d", "istresslist", (cmdfun)8, 0 },
971ed0e75dSpjanzen { NULL, NULL, NULL, 0 }
98df930be7Sderaadt };
99df930be7Sderaadt
100c72b5b24Smillert static int kalc(int, int, int, int, double *);
101c72b5b24Smillert static void prkalc(int, double);
1021ed0e75dSpjanzen
1031ed0e75dSpjanzen void
computer(int v)104*11da2480Smestre computer(int v)
105df930be7Sderaadt {
106df930be7Sderaadt int ix, iy;
10797419aa0Spjanzen int i, j;
108df930be7Sderaadt int tqx, tqy;
1094c24da34Spjanzen const struct cvntab *r;
110df930be7Sderaadt int cost;
111df930be7Sderaadt int course;
112df930be7Sderaadt double dist, time;
113df930be7Sderaadt double warpfact;
114df930be7Sderaadt struct quad *q;
11597419aa0Spjanzen struct event *e;
116df930be7Sderaadt
117df930be7Sderaadt if (check_out(COMPUTER))
118df930be7Sderaadt return;
119df930be7Sderaadt while (1)
120df930be7Sderaadt {
121df930be7Sderaadt r = getcodpar("\nRequest", Cputab);
122df930be7Sderaadt switch ((long)r->value)
123df930be7Sderaadt {
124df930be7Sderaadt
125df930be7Sderaadt case 1: /* star chart */
126df930be7Sderaadt printf("Computer record of galaxy for all long range sensor scans\n\n");
127df930be7Sderaadt printf(" ");
128df930be7Sderaadt /* print top header */
129df930be7Sderaadt for (i = 0; i < NQUADS; i++)
130df930be7Sderaadt printf("-%d- ", i);
131df930be7Sderaadt printf("\n");
132df930be7Sderaadt for (i = 0; i < NQUADS; i++)
133df930be7Sderaadt {
134df930be7Sderaadt printf("%d ", i);
135df930be7Sderaadt for (j = 0; j < NQUADS; j++)
136df930be7Sderaadt {
137df930be7Sderaadt if (i == Ship.quadx && j == Ship.quady)
138df930be7Sderaadt {
139df930be7Sderaadt printf("$$$ ");
140df930be7Sderaadt continue;
141df930be7Sderaadt }
142df930be7Sderaadt q = &Quad[i][j];
143df930be7Sderaadt /* 1000 or 1001 is special case */
144df930be7Sderaadt if (q->scanned >= 1000)
1451ed0e75dSpjanzen {
146df930be7Sderaadt if (q->scanned > 1000)
147df930be7Sderaadt printf(".1. ");
148df930be7Sderaadt else
149df930be7Sderaadt printf("/// ");
1501ed0e75dSpjanzen }
151df930be7Sderaadt else
152df930be7Sderaadt if (q->scanned < 0)
153df930be7Sderaadt printf("... ");
154df930be7Sderaadt else
155df930be7Sderaadt printf("%3d ", q->scanned);
156df930be7Sderaadt }
157df930be7Sderaadt printf("%d\n", i);
158df930be7Sderaadt }
159df930be7Sderaadt printf(" ");
160df930be7Sderaadt /* print bottom footer */
161df930be7Sderaadt for (i = 0; i < NQUADS; i++)
162df930be7Sderaadt printf("-%d- ", i);
163df930be7Sderaadt printf("\n");
164df930be7Sderaadt break;
165df930be7Sderaadt
166df930be7Sderaadt case 2: /* trajectory */
167df930be7Sderaadt if (check_out(SRSCAN))
168df930be7Sderaadt {
169df930be7Sderaadt break;
170df930be7Sderaadt }
171df930be7Sderaadt if (Etc.nkling <= 0)
172df930be7Sderaadt {
173df930be7Sderaadt printf("No Klingons in this quadrant\n");
174df930be7Sderaadt break;
175df930be7Sderaadt }
176df930be7Sderaadt /* for each Klingon, give the course & distance */
177df930be7Sderaadt for (i = 0; i < Etc.nkling; i++)
178df930be7Sderaadt {
179df930be7Sderaadt printf("Klingon at %d,%d", Etc.klingon[i].x, Etc.klingon[i].y);
180df930be7Sderaadt course = kalc(Ship.quadx, Ship.quady, Etc.klingon[i].x, Etc.klingon[i].y, &dist);
181df930be7Sderaadt prkalc(course, dist);
182df930be7Sderaadt }
183df930be7Sderaadt break;
184df930be7Sderaadt
185df930be7Sderaadt case 3: /* course calculation */
186df930be7Sderaadt if (readdelim('/'))
187df930be7Sderaadt {
188df930be7Sderaadt tqx = Ship.quadx;
189df930be7Sderaadt tqy = Ship.quady;
190df930be7Sderaadt }
191df930be7Sderaadt else
192df930be7Sderaadt {
193df930be7Sderaadt ix = getintpar("Quadrant");
194df930be7Sderaadt if (ix < 0 || ix >= NSECTS)
195df930be7Sderaadt break;
196df930be7Sderaadt iy = getintpar("q-y");
197df930be7Sderaadt if (iy < 0 || iy >= NSECTS)
198df930be7Sderaadt break;
199df930be7Sderaadt tqx = ix;
200df930be7Sderaadt tqy = iy;
201df930be7Sderaadt }
202df930be7Sderaadt ix = getintpar("Sector");
203df930be7Sderaadt if (ix < 0 || ix >= NSECTS)
204df930be7Sderaadt break;
205df930be7Sderaadt iy = getintpar("s-y");
206df930be7Sderaadt if (iy < 0 || iy >= NSECTS)
207df930be7Sderaadt break;
208df930be7Sderaadt course = kalc(tqx, tqy, ix, iy, &dist);
209df930be7Sderaadt if (r->value2)
210df930be7Sderaadt {
211df930be7Sderaadt warp(-1, course, dist);
212df930be7Sderaadt break;
213df930be7Sderaadt }
214df930be7Sderaadt printf("%d,%d/%d,%d to %d,%d/%d,%d",
215df930be7Sderaadt Ship.quadx, Ship.quady, Ship.sectx, Ship.secty, tqx, tqy, ix, iy);
216df930be7Sderaadt prkalc(course, dist);
217df930be7Sderaadt break;
218df930be7Sderaadt
219df930be7Sderaadt case 4: /* score */
220df930be7Sderaadt score();
221df930be7Sderaadt break;
222df930be7Sderaadt
223df930be7Sderaadt case 5: /* phaser effectiveness */
224df930be7Sderaadt dist = getfltpar("range");
225df930be7Sderaadt if (dist < 0.0)
226df930be7Sderaadt break;
227df930be7Sderaadt dist *= 10.0;
228df930be7Sderaadt cost = pow(0.90, dist) * 98.0 + 0.5;
229df930be7Sderaadt printf("Phasers are %d%% effective at that range\n", cost);
230df930be7Sderaadt break;
231df930be7Sderaadt
232df930be7Sderaadt case 6: /* warp cost (time/energy) */
233df930be7Sderaadt dist = getfltpar("distance");
234df930be7Sderaadt if (dist < 0.0)
235df930be7Sderaadt break;
236df930be7Sderaadt warpfact = getfltpar("warp factor");
237df930be7Sderaadt if (warpfact <= 0.0)
238df930be7Sderaadt warpfact = Ship.warp;
239df930be7Sderaadt cost = (dist + 0.05) * warpfact * warpfact * warpfact;
240df930be7Sderaadt time = Param.warptime * dist / (warpfact * warpfact);
241d5873fd2Sschwarze printf("Warp %.2f distance %.2f stardates %.2f cost %d (%d w/ shlds up) units\n",
242df930be7Sderaadt warpfact, dist, time, cost, cost + cost);
243df930be7Sderaadt break;
244df930be7Sderaadt
245df930be7Sderaadt case 7: /* impulse cost */
246df930be7Sderaadt dist = getfltpar("distance");
247df930be7Sderaadt if (dist < 0.0)
248df930be7Sderaadt break;
249df930be7Sderaadt cost = 20 + 100 * dist;
250df930be7Sderaadt time = dist / 0.095;
251df930be7Sderaadt printf("Distance %.2f cost %.2f stardates %d units\n",
252df930be7Sderaadt dist, time, cost);
253df930be7Sderaadt break;
254df930be7Sderaadt
255df930be7Sderaadt case 8: /* distresslist */
256df930be7Sderaadt j = 1;
257df930be7Sderaadt printf("\n");
258df930be7Sderaadt /* scan the event list */
259df930be7Sderaadt for (i = 0; i < MAXEVENTS; i++)
260df930be7Sderaadt {
261df930be7Sderaadt e = &Event[i];
262df930be7Sderaadt /* ignore hidden entries */
263df930be7Sderaadt if (e->evcode & E_HIDDEN)
264df930be7Sderaadt continue;
265df930be7Sderaadt switch (e->evcode & E_EVENT)
266df930be7Sderaadt {
267df930be7Sderaadt
268df930be7Sderaadt case E_KDESB:
269df930be7Sderaadt printf("Klingon is attacking starbase in quadrant %d,%d\n",
270df930be7Sderaadt e->x, e->y);
271df930be7Sderaadt j = 0;
272df930be7Sderaadt break;
273df930be7Sderaadt
274df930be7Sderaadt case E_ENSLV:
275df930be7Sderaadt case E_REPRO:
276df930be7Sderaadt printf("Starsystem %s in quadrant %d,%d is distressed\n",
277df930be7Sderaadt Systemname[e->systemname], e->x, e->y);
278df930be7Sderaadt j = 0;
279df930be7Sderaadt break;
280df930be7Sderaadt }
281df930be7Sderaadt }
282df930be7Sderaadt if (j)
283df930be7Sderaadt printf("No known distress calls are active\n");
284df930be7Sderaadt break;
285df930be7Sderaadt
286df930be7Sderaadt }
287df930be7Sderaadt
288df930be7Sderaadt /* skip to next semicolon or newline. Semicolon
289df930be7Sderaadt * means get new computer request; newline means
290df930be7Sderaadt * exit computer mode. */
2915c4c4ba9Spjanzen while ((i = getchar()) != ';')
292df930be7Sderaadt {
293df930be7Sderaadt if (i == '\0')
294df930be7Sderaadt exit(1);
295df930be7Sderaadt if (i == '\n')
296df930be7Sderaadt {
297df930be7Sderaadt ungetc(i, stdin);
298df930be7Sderaadt return;
299df930be7Sderaadt }
300df930be7Sderaadt }
301df930be7Sderaadt }
302df930be7Sderaadt }
303df930be7Sderaadt
304df930be7Sderaadt
305df930be7Sderaadt /*
306df930be7Sderaadt ** Course Calculation
307df930be7Sderaadt **
308df930be7Sderaadt ** Computes and outputs the course and distance from position
309df930be7Sderaadt ** sqx,sqy/ssx,ssy to tqx,tqy/tsx,tsy.
310df930be7Sderaadt */
311df930be7Sderaadt
3121ed0e75dSpjanzen static int
kalc(int tqx,int tqy,int tsx,int tsy,double * dist)313*11da2480Smestre kalc(int tqx, int tqy, int tsx, int tsy, double *dist)
314df930be7Sderaadt {
315df930be7Sderaadt double dx, dy;
316df930be7Sderaadt double quadsize;
317df930be7Sderaadt double angle;
31897419aa0Spjanzen int course;
319df930be7Sderaadt
320df930be7Sderaadt /* normalize to quadrant distances */
321df930be7Sderaadt quadsize = NSECTS;
322df930be7Sderaadt dx = (Ship.quadx + Ship.sectx / quadsize) - (tqx + tsx / quadsize);
323df930be7Sderaadt dy = (tqy + tsy / quadsize) - (Ship.quady + Ship.secty / quadsize);
324df930be7Sderaadt
325df930be7Sderaadt /* get the angle */
326df930be7Sderaadt angle = atan2(dy, dx);
327df930be7Sderaadt /* make it 0 -> 2 pi */
328df930be7Sderaadt if (angle < 0.0)
329df930be7Sderaadt angle += 6.283185307;
330df930be7Sderaadt /* convert from radians to degrees */
331df930be7Sderaadt course = angle * 57.29577951 + 0.5;
332df930be7Sderaadt dx = dx * dx + dy * dy;
333df930be7Sderaadt *dist = sqrt(dx);
334df930be7Sderaadt return (course);
335df930be7Sderaadt }
336df930be7Sderaadt
3371ed0e75dSpjanzen static void
prkalc(int course,double dist)338*11da2480Smestre prkalc(int course, double dist)
339df930be7Sderaadt {
340df930be7Sderaadt printf(": course %d dist %.3f\n", course, dist);
341df930be7Sderaadt }
342