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