xref: /openbsd-src/games/trek/computer.c (revision 11da2480c68e9717c510fd663096c44c53785231)
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