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