Merge branch 'vendor/GDB' into gdb7
[games.git] / games / atc / graphics.c
1 /*-
2  * Copyright (c) 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ed James.
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. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)graphics.c       8.1 (Berkeley) 5/31/93
37  * $FreeBSD: src/games/atc/graphics.c,v 1.7 1999/11/30 03:48:19 billf Exp $
38  * $DragonFly: src/games/atc/graphics.c,v 1.3 2006/08/08 15:03:02 pavalos Exp $
39  */
40
41 /*
42  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
43  *
44  * Copy permission is hereby granted provided that this notice is
45  * retained on all partial or complete copies.
46  *
47  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
48  */
49
50 #include <stdlib.h>
51 #include "include.h"
52 #include <errno.h>
53
54 #define C_TOPBOTTOM             '-'
55 #define C_LEFTRIGHT             '|'
56 #define C_AIRPORT               '='
57 #define C_LINE                  '+'
58 #define C_BACKROUND             '.'
59 #define C_BEACON                '*'
60 #define C_CREDIT                '*'
61
62 WINDOW  *radar, *cleanradar, *credit, *input, *planes;
63
64 static void     draw_line(WINDOW *, int, int, int, int, const char *);
65
66
67 int
68 getAChar(void)
69 {
70         int c;
71
72         errno = 0;
73         while ((c = getchar()) == -1 && errno == EINTR) {
74                 errno = 0;
75                 clearerr(stdin);
76         }
77         return(c);
78 }
79
80 void
81 erase_all(void)
82 {
83         PLANE   *pp;
84
85         for (pp = air.head; pp != NULL; pp = pp->next) {
86                 wmove(cleanradar, pp->ypos, pp->xpos * 2);
87                 wmove(radar, pp->ypos, pp->xpos * 2);
88                 waddch(radar, winch(cleanradar));
89                 wmove(cleanradar, pp->ypos, pp->xpos * 2 + 1);
90                 wmove(radar, pp->ypos, pp->xpos * 2 + 1);
91                 waddch(radar, winch(cleanradar));
92         }
93 }
94
95 void
96 draw_all(void)
97 {
98         PLANE   *pp;
99
100         for (pp = air.head; pp != NULL; pp = pp->next) {
101                 if (pp->status == S_MARKED)
102                         wstandout(radar);
103                 wmove(radar, pp->ypos, pp->xpos * 2);
104                 waddch(radar, name(pp));
105                 waddch(radar, '0' + pp->altitude);
106                 if (pp->status == S_MARKED)
107                         wstandend(radar);
108         }
109         wrefresh(radar);
110         planewin();
111         wrefresh(input);                /* return cursor */
112         fflush(stdout);
113 }
114
115 void
116 init_gr(void)
117 {
118         static char     buffer[BUFSIZ];
119
120         initscr();
121         setbuf(stdout, buffer);
122         input = newwin(INPUT_LINES, COLS - PLANE_COLS, LINES - INPUT_LINES, 0);
123         credit = newwin(INPUT_LINES, PLANE_COLS, LINES - INPUT_LINES,
124                 COLS - PLANE_COLS);
125         planes = newwin(LINES - INPUT_LINES, PLANE_COLS, 0, COLS - PLANE_COLS);
126 }
127
128 void
129 setup_screen(const C_SCREEN *scp)
130 {
131         int             i, j;
132         char            str[3];
133         const char      *airstr;
134
135         str[2] = '\0';
136
137         if (radar != NULL)
138                 delwin(radar);
139         radar = newwin(scp->height, scp->width * 2, 0, 0);
140
141         if (cleanradar != NULL)
142                 delwin(cleanradar);
143         cleanradar = newwin(scp->height, scp->width * 2, 0, 0);
144
145         /* minus one here to prevent a scroll */
146         for (i = 0; i < PLANE_COLS - 1; i++) {
147                 wmove(credit, 0, i);
148                 waddch(credit, C_CREDIT);
149                 wmove(credit, INPUT_LINES - 1, i);
150                 waddch(credit, C_CREDIT);
151         }
152         wmove(credit, INPUT_LINES / 2, 1);
153         waddstr(credit, AUTHOR_STR);
154
155         for (i = 1; i < scp->height - 1; i++) {
156                 for (j = 1; j < scp->width - 1; j++) {
157                         wmove(radar, i, j * 2);
158                         waddch(radar, C_BACKROUND);
159                 }
160         }
161
162         /*
163          * Draw the lines first, since people like to draw lines
164          * through beacons and exit points.
165          */
166         str[0] = C_LINE;
167         for (i = 0; i < scp->num_lines; i++) {
168                 str[1] = ' ';
169                 draw_line(radar, scp->line[i].p1.x, scp->line[i].p1.y,
170                         scp->line[i].p2.x, scp->line[i].p2.y, str);
171         }
172
173         str[0] = C_TOPBOTTOM;
174         str[1] = C_TOPBOTTOM;
175         wmove(radar, 0, 0);
176         for (i = 0; i < scp->width - 1; i++)
177                 waddstr(radar, str);
178         waddch(radar, C_TOPBOTTOM);
179
180         str[0] = C_TOPBOTTOM;
181         str[1] = C_TOPBOTTOM;
182         wmove(radar, scp->height - 1, 0);
183         for (i = 0; i < scp->width - 1; i++)
184                 waddstr(radar, str);
185         waddch(radar, C_TOPBOTTOM);
186
187         for (i = 1; i < scp->height - 1; i++) {
188                 wmove(radar, i, 0);
189                 waddch(radar, C_LEFTRIGHT);
190                 wmove(radar, i, (scp->width - 1) * 2);
191                 waddch(radar, C_LEFTRIGHT);
192         }
193
194         str[0] = C_BEACON;
195         for (i = 0; i < scp->num_beacons; i++) {
196                 str[1] = '0' + i;
197                 wmove(radar, scp->beacon[i].y, scp->beacon[i].x * 2);
198                 waddstr(radar, str);
199         }
200
201         for (i = 0; i < scp->num_exits; i++) {
202                 wmove(radar, scp->exit[i].y, scp->exit[i].x * 2);
203                 waddch(radar, '0' + i);
204         }
205
206         airstr = "^?>?v?<?";
207         for (i = 0; i < scp->num_airports; i++) {
208                 str[0] = airstr[scp->airport[i].dir];
209                 str[1] = '0' + i;
210                 wmove(radar, scp->airport[i].y, scp->airport[i].x * 2);
211                 waddstr(radar, str);
212         }
213
214         overwrite(radar, cleanradar);
215         wrefresh(radar);
216         wrefresh(credit);
217         fflush(stdout);
218 }
219
220 static void
221 draw_line(WINDOW *w, int x, int y, int lx, int ly, const char *s)
222 {
223         int     dx, dy;
224
225         dx = SGN(lx - x);
226         dy = SGN(ly - y);
227         for (;;) {
228                 wmove(w, y, x * 2);
229                 waddstr(w, s);
230                 if (x == lx && y == ly)
231                         break;
232                 x += dx;
233                 y += dy;
234         }
235 }
236
237 void
238 ioclrtoeol(int pos)
239 {
240         wmove(input, 0, pos);
241         wclrtoeol(input);
242         wrefresh(input);
243         fflush(stdout);
244 }
245
246 void
247 iomove(int pos)
248 {
249         wmove(input, 0, pos);
250         wrefresh(input);
251         fflush(stdout);
252 }
253
254 void
255 ioaddstr(int pos, const char *str)
256 {
257         wmove(input, 0, pos);
258         waddstr(input, str);
259         wrefresh(input);
260         fflush(stdout);
261 }
262
263 void
264 ioclrtobot(void)
265 {
266         wclrtobot(input);
267         wrefresh(input);
268         fflush(stdout);
269 }
270
271 void
272 ioerror(int pos, int len, const char *str)
273 {
274         int     i;
275
276         wmove(input, 1, pos);
277         for (i = 0; i < len; i++)
278                 waddch(input, '^');
279         wmove(input, 2, 0);
280         waddstr(input, str);
281         wrefresh(input);
282         fflush(stdout);
283 }
284
285 void
286 quit(void)
287 {
288         int                     c, y, x;
289         struct itimerval        itv;
290
291         getyx(input, y, x);
292         wmove(input, 2, 0);
293         waddstr(input, "Really quit? (y/n) ");
294         wclrtobot(input);
295         wrefresh(input);
296         fflush(stdout);
297
298         c = getchar();
299         if (c == EOF || c == 'y') {
300                 /* disable timer */
301                 itv.it_value.tv_sec = 0;
302                 itv.it_value.tv_usec = 0;
303                 setitimer(ITIMER_REAL, &itv, NULL);
304                 fflush(stdout);
305                 clear();
306                 refresh();
307                 endwin();
308                 log_score(0);
309                 exit(0);
310         }
311         wmove(input, 2, 0);
312         wclrtobot(input);
313         wmove(input, y, x);
314         wrefresh(input);
315         fflush(stdout);
316         return;
317 }
318
319 void
320 planewin(void)
321 {
322         PLANE   *pp;
323         int     warning = 0;
324
325         wclear(planes);
326         wmove(planes, 0,0);
327         wprintw(planes, "Time: %-4d Safe: %d", clck, safe_planes);
328         wmove(planes, 2, 0);
329         waddstr(planes, "pl dt  comm");
330         for (pp = air.head; pp != NULL; pp = pp->next) {
331                 if (waddch(planes, '\n') == ERR) {
332                         warning++;
333                         break;
334                 }
335                 waddstr(planes, command(pp));
336         }
337         waddch(planes, '\n');
338         for (pp = ground.head; pp != NULL; pp = pp->next) {
339                 if (waddch(planes, '\n') == ERR) {
340                         warning++;
341                         break;
342                 }
343                 waddstr(planes, command(pp));
344         }
345         if (warning) {
346                 wmove(planes, LINES - INPUT_LINES - 1, 0);
347                 waddstr(planes, "---- more ----");
348                 wclrtoeol(planes);
349         }
350         wrefresh(planes);
351         fflush(stdout);
352 }
353
354 void
355 loser(const PLANE *p, const char *s)
356 {
357         int                     c;
358         struct itimerval        itv;
359
360         /* disable timer */
361         itv.it_value.tv_sec = 0;
362         itv.it_value.tv_usec = 0;
363         setitimer(ITIMER_REAL, &itv, NULL);
364
365         wmove(input, 0, 0);
366         wclrtobot(input);
367         wprintw(input, "Plane '%c' %s\n\nHit space for top players list...",
368                 name(p), s);
369         wrefresh(input);
370         fflush(stdout);
371         while ((c = getchar()) != EOF && c != ' ')
372                 ;
373         clear();        /* move to top of screen */
374         refresh();
375         endwin();
376         log_score(0);
377         exit(0);
378 }
379
380 void
381 redraw(void)
382 {
383         clear();
384         refresh();
385
386         touchwin(radar);
387         wrefresh(radar);
388         touchwin(planes);
389         wrefresh(planes);
390         touchwin(credit);
391         wrefresh(credit);
392
393         /* refresh input last to get cursor in right place */
394         touchwin(input);
395         wrefresh(input);
396         fflush(stdout);
397 }
398
399 void
400 done_screen(void)
401 {
402         clear();
403         refresh();
404         endwin();         /* clean up curses */
405 }