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