1 /* $OpenBSD: graphics.c,v 1.7 2004/11/29 08:52:28 jsg 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 #ifndef lint 46 #if 0 47 static char sccsid[] = "@(#)graphics.c 8.1 (Berkeley) 5/31/93"; 48 #else 49 static char rcsid[] = "$OpenBSD: graphics.c,v 1.7 2004/11/29 08:52:28 jsg Exp $"; 50 #endif 51 #endif /* not lint */ 52 53 #include <err.h> 54 #include "include.h" 55 56 #define C_TOPBOTTOM '-' 57 #define C_LEFTRIGHT '|' 58 #define C_AIRPORT '=' 59 #define C_LINE '+' 60 #define C_BACKROUND '.' 61 #define C_BEACON '*' 62 #define C_CREDIT '*' 63 64 WINDOW *radar, *cleanradar, *credit, *input, *planes; 65 66 int 67 getAChar(void) 68 { 69 int c; 70 #ifdef BSD 71 if ((c = getchar()) == EOF && feof(stdin)) 72 quit(0); 73 return (c); 74 #endif 75 #ifdef SYSV 76 while ((c = getchar()) == -1 && errno == EINTR) ; 77 return(c); 78 #endif 79 } 80 81 void 82 erase_all(void) 83 { 84 PLANE *pp; 85 86 for (pp = air.head; pp != NULL; pp = pp->next) { 87 wmove(cleanradar, pp->ypos, pp->xpos * 2); 88 wmove(radar, pp->ypos, pp->xpos * 2); 89 waddch(radar, winch(cleanradar)); 90 wmove(cleanradar, pp->ypos, pp->xpos * 2 + 1); 91 wmove(radar, pp->ypos, pp->xpos * 2 + 1); 92 waddch(radar, winch(cleanradar)); 93 } 94 } 95 96 void 97 draw_all(void) 98 { 99 PLANE *pp; 100 101 for (pp = air.head; pp != NULL; pp = pp->next) { 102 if (pp->status == S_MARKED) 103 wstandout(radar); 104 wmove(radar, pp->ypos, pp->xpos * 2); 105 waddch(radar, name(pp)); 106 waddch(radar, '0' + pp->altitude); 107 if (pp->status == S_MARKED) 108 wstandend(radar); 109 } 110 wrefresh(radar); 111 planewin(); 112 wrefresh(input); /* return cursor */ 113 fflush(stdout); 114 } 115 116 void 117 setup_screen(const C_SCREEN *scp) 118 { 119 static char buffer[BUFSIZ]; 120 int i, j; 121 char str[3]; 122 const char *airstr; 123 124 initscr(); 125 /* size of screen depends on chosen game, but we need at least 80 126 * columns for "Information area" to work. */ 127 if (LINES < (INPUT_LINES + scp->height) || 128 COLS < (PLANE_COLS + 2 * scp->width) || 129 COLS < 80) { 130 endwin(); 131 errx(1, "screen too small."); 132 } 133 setbuf(stdout, buffer); 134 input = newwin(INPUT_LINES, COLS - PLANE_COLS, LINES - INPUT_LINES, 0); 135 credit = newwin(INPUT_LINES, PLANE_COLS, LINES - INPUT_LINES, 136 COLS - PLANE_COLS); 137 planes = newwin(LINES - INPUT_LINES, PLANE_COLS, 0, COLS - PLANE_COLS); 138 139 str[2] = '\0'; 140 141 if (radar != NULL) 142 delwin(radar); 143 radar = newwin(scp->height, scp->width * 2, 0, 0); 144 145 if (cleanradar != NULL) 146 delwin(cleanradar); 147 cleanradar = newwin(scp->height, scp->width * 2, 0, 0); 148 149 /* minus one here to prevent a scroll */ 150 for (i = 0; i < PLANE_COLS - 1; i++) { 151 wmove(credit, 0, i); 152 waddch(credit, C_CREDIT); 153 wmove(credit, INPUT_LINES - 1, i); 154 waddch(credit, C_CREDIT); 155 } 156 wmove(credit, INPUT_LINES / 2, 1); 157 waddstr(credit, AUTHOR_STR); 158 159 for (i = 1; i < scp->height - 1; i++) { 160 for (j = 1; j < scp->width - 1; j++) { 161 wmove(radar, i, j * 2); 162 waddch(radar, C_BACKROUND); 163 } 164 } 165 166 /* 167 * Draw the lines first, since people like to draw lines 168 * through beacons and exit points. 169 */ 170 str[0] = C_LINE; 171 for (i = 0; i < scp->num_lines; i++) { 172 str[1] = ' '; 173 draw_line(radar, scp->line[i].p1.x, scp->line[i].p1.y, 174 scp->line[i].p2.x, scp->line[i].p2.y, str); 175 } 176 177 str[0] = C_TOPBOTTOM; 178 str[1] = C_TOPBOTTOM; 179 wmove(radar, 0, 0); 180 for (i = 0; i < scp->width - 1; i++) 181 waddstr(radar, str); 182 waddch(radar, C_TOPBOTTOM); 183 184 str[0] = C_TOPBOTTOM; 185 str[1] = C_TOPBOTTOM; 186 wmove(radar, scp->height - 1, 0); 187 for (i = 0; i < scp->width - 1; i++) 188 waddstr(radar, str); 189 waddch(radar, C_TOPBOTTOM); 190 191 for (i = 1; i < scp->height - 1; i++) { 192 wmove(radar, i, 0); 193 waddch(radar, C_LEFTRIGHT); 194 wmove(radar, i, (scp->width - 1) * 2); 195 waddch(radar, C_LEFTRIGHT); 196 } 197 198 str[0] = C_BEACON; 199 for (i = 0; i < scp->num_beacons; i++) { 200 str[1] = '0' + i; 201 wmove(radar, scp->beacon[i].y, scp->beacon[i].x * 2); 202 waddstr(radar, str); 203 } 204 205 for (i = 0; i < scp->num_exits; i++) { 206 wmove(radar, scp->exit[i].y, scp->exit[i].x * 2); 207 waddch(radar, '0' + i); 208 } 209 210 airstr = "^?>?v?<?"; 211 for (i = 0; i < scp->num_airports; i++) { 212 str[0] = airstr[scp->airport[i].dir]; 213 str[1] = '0' + i; 214 wmove(radar, scp->airport[i].y, scp->airport[i].x * 2); 215 waddstr(radar, str); 216 } 217 218 overwrite(radar, cleanradar); 219 wrefresh(radar); 220 wrefresh(credit); 221 fflush(stdout); 222 } 223 224 void 225 draw_line(WINDOW *w, int x, int y, int lx, int ly, const char *s) 226 { 227 int dx, dy; 228 229 dx = SGN(lx - x); 230 dy = SGN(ly - y); 231 for (;;) { 232 wmove(w, y, x * 2); 233 waddstr(w, s); 234 if (x == lx && y == ly) 235 break; 236 x += dx; 237 y += dy; 238 } 239 } 240 241 void 242 ioclrtoeol(int pos) 243 { 244 wmove(input, 0, pos); 245 wclrtoeol(input); 246 wrefresh(input); 247 fflush(stdout); 248 } 249 250 void 251 iomove(int pos) 252 { 253 wmove(input, 0, pos); 254 wrefresh(input); 255 fflush(stdout); 256 } 257 258 void 259 ioaddstr(int pos, const char *str) 260 { 261 wmove(input, 0, pos); 262 waddstr(input, str); 263 wrefresh(input); 264 fflush(stdout); 265 } 266 267 void 268 ioclrtobot(void) 269 { 270 wclrtobot(input); 271 wrefresh(input); 272 fflush(stdout); 273 } 274 275 void 276 ioerror(int pos, int len, const char *str) 277 { 278 int i; 279 280 wmove(input, 1, pos); 281 for (i = 0; i < len; i++) 282 waddch(input, '^'); 283 wmove(input, 2, 0); 284 waddstr(input, str); 285 wrefresh(input); 286 fflush(stdout); 287 } 288 289 void 290 quit(int dummy) 291 { 292 int c, y, x; 293 #ifdef BSD 294 struct itimerval itv; 295 #endif 296 297 getyx(input, y, x); 298 wmove(input, 2, 0); 299 waddstr(input, "Really quit? (y/n) "); 300 wclrtobot(input); 301 wrefresh(input); 302 fflush(stdout); 303 304 c = getchar(); 305 if (c == EOF || c == 'y') { 306 /* disable timer */ 307 #ifdef BSD 308 itv.it_value.tv_sec = 0; 309 itv.it_value.tv_usec = 0; 310 setitimer(ITIMER_REAL, &itv, NULL); 311 #endif 312 #ifdef SYSV 313 alarm(0); 314 #endif 315 fflush(stdout); 316 clear(); 317 refresh(); 318 endwin(); 319 log_score(0); 320 exit(0); 321 } 322 wmove(input, 2, 0); 323 wclrtobot(input); 324 wmove(input, y, x); 325 wrefresh(input); 326 fflush(stdout); 327 } 328 329 void 330 planewin(void) 331 { 332 PLANE *pp; 333 int warning = 0; 334 335 #ifdef BSD 336 wclear(planes); 337 #endif 338 339 wmove(planes, 0,0); 340 341 #ifdef SYSV 342 wclrtobot(planes); 343 #endif 344 wprintw(planes, "Time: %-4d Safe: %d", clck, safe_planes); 345 wmove(planes, 2, 0); 346 347 waddstr(planes, "pl dt comm"); 348 for (pp = air.head; pp != NULL; pp = pp->next) { 349 if (waddch(planes, '\n') == ERR) { 350 warning++; 351 break; 352 } 353 waddstr(planes, command(pp)); 354 } 355 waddch(planes, '\n'); 356 for (pp = ground.head; pp != NULL; pp = pp->next) { 357 if (waddch(planes, '\n') == ERR) { 358 warning++; 359 break; 360 } 361 waddstr(planes, command(pp)); 362 } 363 if (warning) { 364 wmove(planes, LINES - INPUT_LINES - 1, 0); 365 waddstr(planes, "---- more ----"); 366 wclrtoeol(planes); 367 } 368 wrefresh(planes); 369 fflush(stdout); 370 } 371 372 void 373 loser(const PLANE *p, const char *s) 374 { 375 int c; 376 #ifdef BSD 377 struct itimerval itv; 378 #endif 379 380 /* disable timer */ 381 #ifdef BSD 382 itv.it_value.tv_sec = 0; 383 itv.it_value.tv_usec = 0; 384 setitimer(ITIMER_REAL, &itv, NULL); 385 #endif 386 #ifdef SYSV 387 alarm(0); 388 #endif 389 390 wmove(input, 0, 0); 391 wclrtobot(input); 392 if (p == NULL) 393 wprintw(input, "%s\n\nHit space for top players list...", s); 394 else 395 wprintw(input, "Plane '%c' %s\n\nHit space for top players list...", 396 name(p), s); 397 wrefresh(input); 398 fflush(stdout); 399 while ((c = getchar()) != EOF && c != ' ') 400 ; 401 clear(); /* move to top of screen */ 402 refresh(); 403 endwin(); 404 log_score(0); 405 exit(0); 406 } 407 408 void 409 redraw(void) 410 { 411 clear(); 412 refresh(); 413 414 touchwin(radar); 415 wrefresh(radar); 416 touchwin(planes); 417 wrefresh(planes); 418 touchwin(credit); 419 wrefresh(credit); 420 421 /* refresh input last to get cursor in right place */ 422 touchwin(input); 423 wrefresh(input); 424 fflush(stdout); 425 } 426 427 void 428 done_screen(void) 429 { 430 clear(); 431 refresh(); 432 endwin(); /* clean up curses */ 433 } 434