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