1/*	$OpenBSD: torped.c,v 1.10 2016/01/07 14:37:51 mestre Exp $	*/
2/*	$NetBSD: torped.c,v 1.3 1995/04/22 10:59:34 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
40static int randcourse(int);
41
42/*
43**  PHOTON TORPEDO CONTROL
44**
45**	Either one or three photon torpedoes are fired.  If three
46**	are fired, it is called a "burst" and you also specify
47**	a spread angle.
48**
49**	Torpedoes are never 100% accurate.  There is always a random
50**	cludge factor in their course which is increased if you have
51**	your shields up.  Hence, you will find that they are more
52**	accurate at close range.  However, they have the advantage that
53**	at long range they don't lose any of their power as phasers
54**	do, i.e., a hit is a hit is a hit, by any other name.
55**
56**	When the course spreads too much, you get a misfire, and the
57**	course is randomized even more.  You also have the chance that
58**	the misfire damages your torpedo tubes.
59*/
60
61void
62torped(int v)
63{
64	int	ix, iy;
65	double	x, y, dx, dy;
66	double	angle;
67	int	course, course2;
68	int	k;
69	double	bigger;
70	double	sectsize;
71	int	burst, n;
72
73	if (Ship.cloaked)
74	{
75		printf("Federation regulations do not permit attack while cloaked.\n");
76		return;
77	}
78	if (check_out(TORPED))
79		return;
80	if (Ship.torped <= 0)
81	{
82		printf("All photon torpedos expended\n");
83		return;
84	}
85
86	/* get the course */
87	course = getintpar("Torpedo course");
88	if (course < 0 || course > 360)
89		return;
90	burst = -1;
91
92	/* need at least three torpedoes for a burst */
93	if (Ship.torped < 3)
94	{
95		printf("No-burst mode selected\n");
96		burst = 0;
97	}
98	else
99	{
100		/* see if the user wants one */
101		if (!testnl())
102		{
103			k = ungetc(getchar(), stdin);
104			if (k >= '0' && k <= '9')
105				burst = 1;
106		}
107	}
108	if (burst < 0)
109	{
110		burst = getynpar("Do you want a burst");
111	}
112	if (burst)
113	{
114		burst = getintpar("burst angle");
115		if (burst <= 0)
116			return;
117		if (burst > 15)
118		{
119			printf("Maximum burst angle is 15 degrees\n");
120			return;
121		}
122	}
123	sectsize = NSECTS;
124	n = -1;
125	if (burst)
126	{
127		n = 1;
128		course -= burst;
129	}
130	for (; n && n <= 3; n++)
131	{
132		/* select a nice random course */
133		course2 = course + randcourse(n);
134		angle = course2 * 0.0174532925;			/* convert to radians */
135		dx = -cos(angle);
136		dy =  sin(angle);
137		bigger = fabs(dx);
138		x = fabs(dy);
139		if (x > bigger)
140			bigger = x;
141		dx /= bigger;
142		dy /= bigger;
143		x = Ship.sectx + 0.5;
144		y = Ship.secty + 0.5;
145		if (Ship.cond != DOCKED)
146			Ship.torped -= 1;
147		printf("Torpedo track");
148		if (n > 0)
149			printf(", torpedo number %d", n);
150		printf(":\n%6.1f\t%4.1f\n", x, y);
151		while (1)
152		{
153			ix = x += dx;
154			iy = y += dy;
155			if (x < 0.0 || x >= sectsize || y < 0.0 || y >= sectsize)
156			{
157				printf("Torpedo missed\n");
158				break;
159			}
160			printf("%6.1f\t%4.1f\n", x, y);
161			switch (Sect[ix][iy])
162			{
163			  case EMPTY:
164				continue;
165
166			  case HOLE:
167				printf("Torpedo disappears into a black hole\n");
168				break;
169
170			  case KLINGON:
171				for (k = 0; k < Etc.nkling; k++)
172				{
173					if (Etc.klingon[k].x != ix || Etc.klingon[k].y != iy)
174						continue;
175					Etc.klingon[k].power -= 500 + ranf(501);
176					if (Etc.klingon[k].power > 0)
177					{
178						printf("*** Hit on Klingon at %d,%d: extensive damages\n",
179							ix, iy);
180						break;
181					}
182					killk(ix, iy);
183					break;
184				}
185				break;
186
187			  case STAR:
188				nova(ix, iy);
189				break;
190
191			  case INHABIT:
192				kills(ix, iy, -1);
193				break;
194
195			  case BASE:
196				killb(Ship.quadx, Ship.quady);
197				Game.killb += 1;
198				break;
199			  default:
200				printf("Unknown object %c at %d,%d destroyed\n",
201					Sect[ix][iy], ix, iy);
202				Sect[ix][iy] = EMPTY;
203				break;
204			}
205			break;
206		}
207		if (damaged(TORPED) || Quad[Ship.quadx][Ship.quady].stars < 0)
208			break;
209		course += burst;
210	}
211	Move.free = 0;
212}
213
214
215/*
216**  RANDOMIZE COURSE
217**
218**	This routine randomizes the course for torpedo number 'n'.
219**	Other things handled by this routine are misfires, damages
220**	to the tubes, etc.
221*/
222
223static int
224randcourse(int n)
225{
226	double	r;
227	int	d;
228
229	d = ((franf() + franf()) - 1.0) * 20;
230	if (abs(d) > 12)
231	{
232		printf("Photon tubes misfire");
233		if (n < 0)
234			printf("\n");
235		else
236			printf(" on torpedo %d\n", n);
237		if (ranf(2))
238		{
239			damage(TORPED, 0.2 * abs(d) * (franf() + 1.0));
240		}
241		d *= 1.0 + 2.0 * franf();
242	}
243	if (Ship.shldup || Ship.cond == DOCKED)
244	{
245		r = Ship.shield;
246		r = 1.0 + r / Param.shield;
247		if (Ship.cond == DOCKED)
248			r = 2.0;
249		d *= r;
250	}
251	return (d);
252}
253