xref: /openbsd/games/atc/graphics.c (revision 79af1000)
1*79af1000Sguenther /*	$OpenBSD: graphics.c,v 1.12 2016/08/27 02:02:44 guenther Exp $	*/
2df930be7Sderaadt /*	$NetBSD: graphics.c,v 1.3 1995/03/21 15:04:04 cgd Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1990, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt  * Ed James.
10df930be7Sderaadt  *
11df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt  * modification, are permitted provided that the following conditions
13df930be7Sderaadt  * are met:
14df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
197a09557bSmillert  * 3. Neither the name of the University nor the names of its contributors
20df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
21df930be7Sderaadt  *    without specific prior written permission.
22df930be7Sderaadt  *
23df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt  * SUCH DAMAGE.
34df930be7Sderaadt  */
35df930be7Sderaadt 
36df930be7Sderaadt /*
37df930be7Sderaadt  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
38df930be7Sderaadt  *
39df930be7Sderaadt  * Copy permission is hereby granted provided that this notice is
40df930be7Sderaadt  * retained on all partial or complete copies.
41df930be7Sderaadt  *
42df930be7Sderaadt  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
43df930be7Sderaadt  */
44df930be7Sderaadt 
45*79af1000Sguenther #include <sys/time.h>
462317ec67Smestre #include <curses.h>
4731aab2a5Spjanzen #include <err.h>
482317ec67Smestre #include <stdlib.h>
492317ec67Smestre 
502317ec67Smestre #include "def.h"
512317ec67Smestre #include "extern.h"
52df930be7Sderaadt 
53df930be7Sderaadt #define C_TOPBOTTOM		'-'
54df930be7Sderaadt #define C_LEFTRIGHT		'|'
55df930be7Sderaadt #define C_AIRPORT		'='
56df930be7Sderaadt #define C_LINE			'+'
57df930be7Sderaadt #define C_BACKROUND		'.'
58df930be7Sderaadt #define C_BEACON		'*'
59df930be7Sderaadt #define C_CREDIT		'*'
60df930be7Sderaadt 
61df930be7Sderaadt WINDOW	*radar, *cleanradar, *credit, *input, *planes;
62df930be7Sderaadt 
6331aab2a5Spjanzen int
getAChar(void)643eb8c9edSjsg getAChar(void)
65df930be7Sderaadt {
66859369c2Spjanzen 	int c;
6754740ad2Stedu 
68859369c2Spjanzen 	if ((c = getchar()) == EOF && feof(stdin))
69859369c2Spjanzen 		quit(0);
70859369c2Spjanzen 	return (c);
71df930be7Sderaadt }
72df930be7Sderaadt 
7331aab2a5Spjanzen void
erase_all(void)743eb8c9edSjsg erase_all(void)
75df930be7Sderaadt {
76df930be7Sderaadt 	PLANE	*pp;
77df930be7Sderaadt 
78df930be7Sderaadt 	for (pp = air.head; pp != NULL; pp = pp->next) {
79df930be7Sderaadt 		wmove(cleanradar, pp->ypos, pp->xpos * 2);
80df930be7Sderaadt 		wmove(radar, pp->ypos, pp->xpos * 2);
81df930be7Sderaadt 		waddch(radar, winch(cleanradar));
82df930be7Sderaadt 		wmove(cleanradar, pp->ypos, pp->xpos * 2 + 1);
83df930be7Sderaadt 		wmove(radar, pp->ypos, pp->xpos * 2 + 1);
84df930be7Sderaadt 		waddch(radar, winch(cleanradar));
85df930be7Sderaadt 	}
86df930be7Sderaadt }
87df930be7Sderaadt 
8831aab2a5Spjanzen void
draw_all(void)893eb8c9edSjsg draw_all(void)
90df930be7Sderaadt {
91df930be7Sderaadt 	PLANE	*pp;
92df930be7Sderaadt 
93df930be7Sderaadt 	for (pp = air.head; pp != NULL; pp = pp->next) {
94df930be7Sderaadt 		if (pp->status == S_MARKED)
95df930be7Sderaadt 			wstandout(radar);
96df930be7Sderaadt 		wmove(radar, pp->ypos, pp->xpos * 2);
97df930be7Sderaadt 		waddch(radar, name(pp));
98df930be7Sderaadt 		waddch(radar, '0' + pp->altitude);
99df930be7Sderaadt 		if (pp->status == S_MARKED)
100df930be7Sderaadt 			wstandend(radar);
101df930be7Sderaadt 	}
102df930be7Sderaadt 	wrefresh(radar);
103df930be7Sderaadt 	planewin();
104df930be7Sderaadt 	wrefresh(input);		/* return cursor */
105df930be7Sderaadt 	fflush(stdout);
106df930be7Sderaadt }
107df930be7Sderaadt 
10831aab2a5Spjanzen void
setup_screen(const C_SCREEN * scp)1093eb8c9edSjsg setup_screen(const C_SCREEN *scp)
110df930be7Sderaadt {
111df930be7Sderaadt 	static char	buffer[BUFSIZ];
1125803e5dcSpjanzen 	int	i, j;
1135803e5dcSpjanzen 	char	str[3];
1145803e5dcSpjanzen 	const char *airstr;
115df930be7Sderaadt 
116df930be7Sderaadt 	initscr();
1175803e5dcSpjanzen 	/* size of screen depends on chosen game, but we need at least 80
1185803e5dcSpjanzen 	 * columns for "Information area" to work. */
1195803e5dcSpjanzen 	if (LINES < (INPUT_LINES + scp->height) ||
1205803e5dcSpjanzen 	    COLS < (PLANE_COLS + 2 * scp->width) ||
1215803e5dcSpjanzen 	    COLS < 80) {
12231aab2a5Spjanzen 		endwin();
12331aab2a5Spjanzen 		errx(1, "screen too small.");
12431aab2a5Spjanzen 	}
12533206277Stedu 	setvbuf(stdout, buffer, _IOFBF, sizeof buffer);
126df930be7Sderaadt 	input = newwin(INPUT_LINES, COLS - PLANE_COLS, LINES - INPUT_LINES, 0);
127df930be7Sderaadt 	credit = newwin(INPUT_LINES, PLANE_COLS, LINES - INPUT_LINES,
128df930be7Sderaadt 		COLS - PLANE_COLS);
129df930be7Sderaadt 	planes = newwin(LINES - INPUT_LINES, PLANE_COLS, 0, COLS - PLANE_COLS);
130df930be7Sderaadt 
131df930be7Sderaadt 	str[2] = '\0';
132df930be7Sderaadt 
133df930be7Sderaadt 	if (radar != NULL)
134df930be7Sderaadt 		delwin(radar);
135df930be7Sderaadt 	radar = newwin(scp->height, scp->width * 2, 0, 0);
136df930be7Sderaadt 
137df930be7Sderaadt 	if (cleanradar != NULL)
138df930be7Sderaadt 		delwin(cleanradar);
139df930be7Sderaadt 	cleanradar = newwin(scp->height, scp->width * 2, 0, 0);
140df930be7Sderaadt 
141df930be7Sderaadt 	/* minus one here to prevent a scroll */
142df930be7Sderaadt 	for (i = 0; i < PLANE_COLS - 1; i++) {
143df930be7Sderaadt 		wmove(credit, 0, i);
144df930be7Sderaadt 		waddch(credit, C_CREDIT);
145df930be7Sderaadt 		wmove(credit, INPUT_LINES - 1, i);
146df930be7Sderaadt 		waddch(credit, C_CREDIT);
147df930be7Sderaadt 	}
148df930be7Sderaadt 	wmove(credit, INPUT_LINES / 2, 1);
149df930be7Sderaadt 	waddstr(credit, AUTHOR_STR);
150df930be7Sderaadt 
151df930be7Sderaadt 	for (i = 1; i < scp->height - 1; i++) {
152df930be7Sderaadt 		for (j = 1; j < scp->width - 1; j++) {
153df930be7Sderaadt 			wmove(radar, i, j * 2);
154df930be7Sderaadt 			waddch(radar, C_BACKROUND);
155df930be7Sderaadt 		}
156df930be7Sderaadt 	}
157df930be7Sderaadt 
158df930be7Sderaadt 	/*
159df930be7Sderaadt 	 * Draw the lines first, since people like to draw lines
160df930be7Sderaadt 	 * through beacons and exit points.
161df930be7Sderaadt 	 */
162df930be7Sderaadt 	str[0] = C_LINE;
163df930be7Sderaadt 	for (i = 0; i < scp->num_lines; i++) {
164df930be7Sderaadt 		str[1] = ' ';
165df930be7Sderaadt 		draw_line(radar, scp->line[i].p1.x, scp->line[i].p1.y,
166df930be7Sderaadt 			scp->line[i].p2.x, scp->line[i].p2.y, str);
167df930be7Sderaadt 	}
168df930be7Sderaadt 
169df930be7Sderaadt 	str[0] = C_TOPBOTTOM;
170df930be7Sderaadt 	str[1] = C_TOPBOTTOM;
171df930be7Sderaadt 	wmove(radar, 0, 0);
172df930be7Sderaadt 	for (i = 0; i < scp->width - 1; i++)
173df930be7Sderaadt 		waddstr(radar, str);
174df930be7Sderaadt 	waddch(radar, C_TOPBOTTOM);
175df930be7Sderaadt 
176df930be7Sderaadt 	str[0] = C_TOPBOTTOM;
177df930be7Sderaadt 	str[1] = C_TOPBOTTOM;
178df930be7Sderaadt 	wmove(radar, scp->height - 1, 0);
179df930be7Sderaadt 	for (i = 0; i < scp->width - 1; i++)
180df930be7Sderaadt 		waddstr(radar, str);
181df930be7Sderaadt 	waddch(radar, C_TOPBOTTOM);
182df930be7Sderaadt 
183df930be7Sderaadt 	for (i = 1; i < scp->height - 1; i++) {
184df930be7Sderaadt 		wmove(radar, i, 0);
185df930be7Sderaadt 		waddch(radar, C_LEFTRIGHT);
186df930be7Sderaadt 		wmove(radar, i, (scp->width - 1) * 2);
187df930be7Sderaadt 		waddch(radar, C_LEFTRIGHT);
188df930be7Sderaadt 	}
189df930be7Sderaadt 
190df930be7Sderaadt 	str[0] = C_BEACON;
191df930be7Sderaadt 	for (i = 0; i < scp->num_beacons; i++) {
192df930be7Sderaadt 		str[1] = '0' + i;
193df930be7Sderaadt 		wmove(radar, scp->beacon[i].y, scp->beacon[i].x * 2);
194df930be7Sderaadt 		waddstr(radar, str);
195df930be7Sderaadt 	}
196df930be7Sderaadt 
197df930be7Sderaadt 	for (i = 0; i < scp->num_exits; i++) {
198df930be7Sderaadt 		wmove(radar, scp->exit[i].y, scp->exit[i].x * 2);
199df930be7Sderaadt 		waddch(radar, '0' + i);
200df930be7Sderaadt 	}
201df930be7Sderaadt 
202df930be7Sderaadt 	airstr = "^?>?v?<?";
203df930be7Sderaadt 	for (i = 0; i < scp->num_airports; i++) {
204df930be7Sderaadt 		str[0] = airstr[scp->airport[i].dir];
205df930be7Sderaadt 		str[1] = '0' + i;
206df930be7Sderaadt 		wmove(radar, scp->airport[i].y, scp->airport[i].x * 2);
207df930be7Sderaadt 		waddstr(radar, str);
208df930be7Sderaadt 	}
209df930be7Sderaadt 
210df930be7Sderaadt 	overwrite(radar, cleanradar);
211df930be7Sderaadt 	wrefresh(radar);
212df930be7Sderaadt 	wrefresh(credit);
213df930be7Sderaadt 	fflush(stdout);
214df930be7Sderaadt }
215df930be7Sderaadt 
21631aab2a5Spjanzen void
draw_line(WINDOW * w,int x,int y,int lx,int ly,const char * s)2173eb8c9edSjsg draw_line(WINDOW *w, int x, int y, int lx, int ly, const char *s)
218df930be7Sderaadt {
219df930be7Sderaadt 	int	dx, dy;
220df930be7Sderaadt 
221df930be7Sderaadt 	dx = SGN(lx - x);
222df930be7Sderaadt 	dy = SGN(ly - y);
223df930be7Sderaadt 	for (;;) {
224df930be7Sderaadt 		wmove(w, y, x * 2);
225df930be7Sderaadt 		waddstr(w, s);
226df930be7Sderaadt 		if (x == lx && y == ly)
227df930be7Sderaadt 			break;
228df930be7Sderaadt 		x += dx;
229df930be7Sderaadt 		y += dy;
230df930be7Sderaadt 	}
231df930be7Sderaadt }
232df930be7Sderaadt 
23331aab2a5Spjanzen void
ioclrtoeol(int pos)2343eb8c9edSjsg ioclrtoeol(int pos)
235df930be7Sderaadt {
236df930be7Sderaadt 	wmove(input, 0, pos);
237df930be7Sderaadt 	wclrtoeol(input);
238df930be7Sderaadt 	wrefresh(input);
239df930be7Sderaadt 	fflush(stdout);
240df930be7Sderaadt }
241df930be7Sderaadt 
24231aab2a5Spjanzen void
iomove(int pos)2433eb8c9edSjsg iomove(int pos)
244df930be7Sderaadt {
245df930be7Sderaadt 	wmove(input, 0, pos);
246df930be7Sderaadt 	wrefresh(input);
247df930be7Sderaadt 	fflush(stdout);
248df930be7Sderaadt }
249df930be7Sderaadt 
25031aab2a5Spjanzen void
ioaddstr(int pos,const char * str)2513eb8c9edSjsg ioaddstr(int pos, const char *str)
252df930be7Sderaadt {
253df930be7Sderaadt 	wmove(input, 0, pos);
254df930be7Sderaadt 	waddstr(input, str);
255df930be7Sderaadt 	wrefresh(input);
256df930be7Sderaadt 	fflush(stdout);
257df930be7Sderaadt }
258df930be7Sderaadt 
25931aab2a5Spjanzen void
ioclrtobot(void)2603eb8c9edSjsg ioclrtobot(void)
261df930be7Sderaadt {
262df930be7Sderaadt 	wclrtobot(input);
263df930be7Sderaadt 	wrefresh(input);
264df930be7Sderaadt 	fflush(stdout);
265df930be7Sderaadt }
266df930be7Sderaadt 
26731aab2a5Spjanzen void
ioerror(int pos,int len,const char * str)2683eb8c9edSjsg ioerror(int pos, int len, const char *str)
269df930be7Sderaadt {
270df930be7Sderaadt 	int	i;
271df930be7Sderaadt 
272df930be7Sderaadt 	wmove(input, 1, pos);
273df930be7Sderaadt 	for (i = 0; i < len; i++)
274df930be7Sderaadt 		waddch(input, '^');
275df930be7Sderaadt 	wmove(input, 2, 0);
276df930be7Sderaadt 	waddstr(input, str);
277df930be7Sderaadt 	wrefresh(input);
278df930be7Sderaadt 	fflush(stdout);
279df930be7Sderaadt }
280df930be7Sderaadt 
28131aab2a5Spjanzen void
quit(int dummy)2823eb8c9edSjsg quit(int dummy)
283df930be7Sderaadt {
284df930be7Sderaadt 	int			c, y, x;
285df930be7Sderaadt 	struct itimerval	itv;
286df930be7Sderaadt 
287df930be7Sderaadt 	getyx(input, y, x);
288df930be7Sderaadt 	wmove(input, 2, 0);
289df930be7Sderaadt 	waddstr(input, "Really quit? (y/n) ");
290df930be7Sderaadt 	wclrtobot(input);
291df930be7Sderaadt 	wrefresh(input);
292df930be7Sderaadt 	fflush(stdout);
293df930be7Sderaadt 
294df930be7Sderaadt 	c = getchar();
295df930be7Sderaadt 	if (c == EOF || c == 'y') {
296df930be7Sderaadt 		/* disable timer */
297df930be7Sderaadt 		itv.it_value.tv_sec = 0;
298df930be7Sderaadt 		itv.it_value.tv_usec = 0;
299df930be7Sderaadt 		setitimer(ITIMER_REAL, &itv, NULL);
300df930be7Sderaadt 		fflush(stdout);
301df930be7Sderaadt 		clear();
302df930be7Sderaadt 		refresh();
303df930be7Sderaadt 		endwin();
304df930be7Sderaadt 		log_score(0);
305df930be7Sderaadt 		exit(0);
306df930be7Sderaadt 	}
307df930be7Sderaadt 	wmove(input, 2, 0);
308df930be7Sderaadt 	wclrtobot(input);
309df930be7Sderaadt 	wmove(input, y, x);
310df930be7Sderaadt 	wrefresh(input);
311df930be7Sderaadt 	fflush(stdout);
312df930be7Sderaadt }
313df930be7Sderaadt 
31431aab2a5Spjanzen void
planewin(void)3153eb8c9edSjsg planewin(void)
316df930be7Sderaadt {
317df930be7Sderaadt 	PLANE	*pp;
318df930be7Sderaadt 	int	warning = 0;
319df930be7Sderaadt 
320df930be7Sderaadt 	wclear(planes);
321df930be7Sderaadt 
322df930be7Sderaadt 	wmove(planes, 0,0);
323df930be7Sderaadt 
324df930be7Sderaadt 	wprintw(planes, "Time: %-4d Safe: %d", clck, safe_planes);
325df930be7Sderaadt 	wmove(planes, 2, 0);
326df930be7Sderaadt 
327df930be7Sderaadt 	waddstr(planes, "pl dt  comm");
328df930be7Sderaadt 	for (pp = air.head; pp != NULL; pp = pp->next) {
329df930be7Sderaadt 		if (waddch(planes, '\n') == ERR) {
330df930be7Sderaadt 			warning++;
331df930be7Sderaadt 			break;
332df930be7Sderaadt 		}
333df930be7Sderaadt 		waddstr(planes, command(pp));
334df930be7Sderaadt 	}
335df930be7Sderaadt 	waddch(planes, '\n');
336df930be7Sderaadt 	for (pp = ground.head; pp != NULL; pp = pp->next) {
337df930be7Sderaadt 		if (waddch(planes, '\n') == ERR) {
338df930be7Sderaadt 			warning++;
339df930be7Sderaadt 			break;
340df930be7Sderaadt 		}
341df930be7Sderaadt 		waddstr(planes, command(pp));
342df930be7Sderaadt 	}
343df930be7Sderaadt 	if (warning) {
344df930be7Sderaadt 		wmove(planes, LINES - INPUT_LINES - 1, 0);
345df930be7Sderaadt 		waddstr(planes, "---- more ----");
346df930be7Sderaadt 		wclrtoeol(planes);
347df930be7Sderaadt 	}
348df930be7Sderaadt 	wrefresh(planes);
349df930be7Sderaadt 	fflush(stdout);
350df930be7Sderaadt }
351df930be7Sderaadt 
35231aab2a5Spjanzen void
loser(const PLANE * p,const char * s)3533eb8c9edSjsg loser(const PLANE *p, const char *s)
354df930be7Sderaadt {
355df930be7Sderaadt 	int			c;
356df930be7Sderaadt 	struct itimerval	itv;
357df930be7Sderaadt 
358df930be7Sderaadt 	/* disable timer */
359df930be7Sderaadt 	itv.it_value.tv_sec = 0;
360df930be7Sderaadt 	itv.it_value.tv_usec = 0;
361df930be7Sderaadt 	setitimer(ITIMER_REAL, &itv, NULL);
362df930be7Sderaadt 
363df930be7Sderaadt 	wmove(input, 0, 0);
364df930be7Sderaadt 	wclrtobot(input);
365d9559820Spjanzen 	if (p == NULL)
366d9559820Spjanzen 		wprintw(input, "%s\n\nHit space for top players list...", s);
367d9559820Spjanzen 	else
368df930be7Sderaadt 		wprintw(input, "Plane '%c' %s\n\nHit space for top players list...",
369df930be7Sderaadt 			name(p), s);
370df930be7Sderaadt 	wrefresh(input);
371df930be7Sderaadt 	fflush(stdout);
372df930be7Sderaadt 	while ((c = getchar()) != EOF && c != ' ')
373df930be7Sderaadt 		;
374df930be7Sderaadt 	clear();	/* move to top of screen */
375df930be7Sderaadt 	refresh();
376df930be7Sderaadt 	endwin();
377df930be7Sderaadt 	log_score(0);
378df930be7Sderaadt 	exit(0);
379df930be7Sderaadt }
380df930be7Sderaadt 
38131aab2a5Spjanzen void
redraw(void)3823eb8c9edSjsg redraw(void)
383df930be7Sderaadt {
384df930be7Sderaadt 	clear();
385df930be7Sderaadt 	refresh();
386df930be7Sderaadt 
387df930be7Sderaadt 	touchwin(radar);
388df930be7Sderaadt 	wrefresh(radar);
389df930be7Sderaadt 	touchwin(planes);
390df930be7Sderaadt 	wrefresh(planes);
391df930be7Sderaadt 	touchwin(credit);
392df930be7Sderaadt 	wrefresh(credit);
393df930be7Sderaadt 
394df930be7Sderaadt 	/* refresh input last to get cursor in right place */
395df930be7Sderaadt 	touchwin(input);
396df930be7Sderaadt 	wrefresh(input);
397df930be7Sderaadt 	fflush(stdout);
398df930be7Sderaadt }
399df930be7Sderaadt 
40031aab2a5Spjanzen void
done_screen(void)4013eb8c9edSjsg done_screen(void)
402df930be7Sderaadt {
403df930be7Sderaadt 	clear();
404df930be7Sderaadt 	refresh();
405df930be7Sderaadt 	endwin();	  /* clean up curses */
406df930be7Sderaadt }
407