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