xref: /netbsd-src/games/battlestar/fly.c (revision 1182a44c59cae4d586117d55eca24b4b8b173211)
1 /*	$NetBSD: fly.c,v 1.16 2021/05/02 12:50:43 rillig Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)fly.c	8.2 (Berkeley) 4/28/95";
36 #else
37 __RCSID("$NetBSD: fly.c,v 1.16 2021/05/02 12:50:43 rillig Exp $");
38 #endif
39 #endif				/* not lint */
40 
41 #include "extern.h"
42 #undef UP
43 #include <curses.h>
44 #include <assert.h>
45 
46 #define MIDR  (LINES/2 - 1)
47 #define MIDC  (COLS/2 - 1)
48 
49 static int     row, column;
50 static int     dr = 0, dc = 0;
51 static char    destroyed;
52 int     ourclock = 120;		/* time for all the flights in the game */
53 static char    cross = 0;
54 static sig_t   oldsig;
55 
56 static void blast(void);
57 static void endfly(void);
58 static void moveenemy(int);
59 static void notarget(void);
60 static void screen(void);
61 static void succumb(int);
62 static void target(void);
63 
64 static void
succumb(int dummy __unused)65 succumb(int dummy __unused)
66 {
67 	if (oldsig == SIG_DFL) {
68 		endfly();
69 		exit(1);
70 	}
71 	if (oldsig != SIG_IGN) {
72 		endfly();
73 		(*oldsig) (SIGINT);
74 	}
75 }
76 
77 int
visual(void)78 visual(void)
79 {
80 	destroyed = 0;
81 	if (initscr() == NULL) {
82 		puts("Whoops!  No more memory...");
83 		return (0);
84 	}
85 	oldsig = signal(SIGINT, succumb);
86 	cbreak();
87 	noecho();
88 	screen();
89 	row = rnd(LINES - 3) + 1;
90 	column = rnd(COLS - 2) + 1;
91 	moveenemy(0);
92 	for (;;) {
93 		switch (getchar()) {
94 
95 		case 'h':
96 		case 'r':
97 			dc = -1;
98 			fuel--;
99 			break;
100 
101 		case 'H':
102 		case 'R':
103 			dc = -5;
104 			fuel -= 10;
105 			break;
106 
107 		case 'l':
108 			dc = 1;
109 			fuel--;
110 			break;
111 
112 		case 'L':
113 			dc = 5;
114 			fuel -= 10;
115 			break;
116 
117 		case 'j':
118 		case 'u':
119 			dr = 1;
120 			fuel--;
121 			break;
122 
123 		case 'J':
124 		case 'U':
125 			dr = 5;
126 			fuel -= 10;
127 			break;
128 
129 		case 'k':
130 		case 'd':
131 			dr = -1;
132 			fuel--;
133 			break;
134 
135 		case 'K':
136 		case 'D':
137 			dr = -5;
138 			fuel -= 10;
139 			break;
140 
141 		case '+':
142 			if (cross) {
143 				cross = 0;
144 				notarget();
145 			} else
146 				cross = 1;
147 			break;
148 
149 		case ' ':
150 		case 'f':
151 			if (torps) {
152 				torps -= 2;
153 				blast();
154 				if (row == MIDR && column < MIDC + 2 &&
155 				    column > MIDC - 2) {
156 					destroyed = 1;
157 					alarm(0);
158 				}
159 			} else
160 				mvaddstr(0, 0, "*** Out of torpedoes. ***");
161 			break;
162 
163 		case 'q':
164 			endfly();
165 			return (0);
166 
167 		default:
168 			mvaddstr(0, 26, "Commands = r,R,l,L,u,U,d,D,f,+,q");
169 			continue;
170 
171 		case EOF:
172 			break;
173 		}
174 		if (destroyed) {
175 			endfly();
176 			return (1);
177 		}
178 		if (ourclock <= 0) {
179 			endfly();
180 			die();
181 		}
182 	}
183 }
184 
185 static void
screen(void)186 screen(void)
187 {
188 	int     r, c, n;
189 	int     i;
190 
191 	clear();
192 	i = rnd(100);
193 	for (n = 0; n < i; n++) {
194 		r = rnd(LINES - 3) + 1;
195 		c = rnd(COLS);
196 		mvaddch(r, c, '.');
197 	}
198 	mvaddstr(LINES - 1 - 1, 21, "TORPEDOES           FUEL           TIME");
199 	refresh();
200 }
201 
202 static void
target(void)203 target(void)
204 {
205 	int     n;
206 
207 	move(MIDR, MIDC - 10);
208 	addstr("-------   +   -------");
209 	for (n = MIDR - 4; n < MIDR - 1; n++) {
210 		mvaddch(n, MIDC, '|');
211 		mvaddch(n + 6, MIDC, '|');
212 	}
213 }
214 
215 static void
notarget(void)216 notarget(void)
217 {
218 	int     n;
219 
220 	move(MIDR, MIDC - 10);
221 	addstr("                     ");
222 	for (n = MIDR - 4; n < MIDR - 1; n++) {
223 		mvaddch(n, MIDC, ' ');
224 		mvaddch(n + 6, MIDC, ' ');
225 	}
226 }
227 
228 static void
blast(void)229 blast(void)
230 {
231 	int     n;
232 
233 	alarm(0);
234 	move(LINES - 1, 24);
235 	printw("%3d", torps);
236 	for (n = LINES - 1 - 2; n >= MIDR + 1; n--) {
237 		mvaddch(n, MIDC + MIDR - n, '/');
238 		mvaddch(n, MIDC - MIDR + n, '\\');
239 		refresh();
240 	}
241 	mvaddch(MIDR, MIDC, '*');
242 	for (n = LINES - 1 - 2; n >= MIDR + 1; n--) {
243 		mvaddch(n, MIDC + MIDR - n, ' ');
244 		mvaddch(n, MIDC - MIDR + n, ' ');
245 		refresh();
246 	}
247 	alarm(1);
248 }
249 
250 static void
moveenemy(int dummy __unused)251 moveenemy(int dummy __unused)
252 {
253 	double  d;
254 	int     oldr, oldc;
255 
256 	oldr = row;
257 	oldc = column;
258 	if (fuel > 0) {
259 		if (row + dr <= LINES - 3 && row + dr > 0)
260 			row += dr;
261 		if (column + dc < COLS - 1 && column + dc > 0)
262 			column += dc;
263 	} else
264 		if (fuel < 0) {
265 			fuel = 0;
266 			mvaddstr(0, 60, "*** Out of fuel ***");
267 		}
268 	d = (double) ((row - MIDR) * (row - MIDR) + (column - MIDC) *
269 	    (column - MIDC));
270 	if (d < 16) {
271 		row += (rnd(9) - 4) % (4 - abs(row - MIDR));
272 		column += (rnd(9) - 4) % (4 - abs(column - MIDC));
273 	}
274 	ourclock--;
275 	mvaddstr(oldr, oldc - 1, "   ");
276 	if (cross)
277 		target();
278 	mvaddstr(row, column - 1, "/-\\");
279 	move(LINES - 1, 24);
280 	printw("%3d", torps);
281 	move(LINES - 1, 42);
282 	printw("%3d", fuel);
283 	move(LINES - 1, 57);
284 	printw("%3d", ourclock);
285 	refresh();
286 	signal(SIGALRM, moveenemy);
287 	alarm(1);
288 }
289 
290 static void
endfly(void)291 endfly(void)
292 {
293 	alarm(0);
294 	signal(SIGALRM, SIG_DFL);
295 	mvcur(0, COLS - 1, LINES - 1, 0);
296 	endwin();
297 	signal(SIGTSTP, SIG_DFL);
298 	signal(SIGINT, oldsig);
299 }
300