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 61 WINDOW *radar, *cleanradar, *credit, *input, *planes; 62 63 int 64 getAChar(void) 65 { 66 int c; 67 68 if ((c = getchar()) == EOF && feof(stdin)) 69 quit(0); 70 return (c); 71 } 72 73 void 74 erase_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 88 void 89 draw_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 108 void 109 setup_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 216 void 217 draw_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 233 void 234 ioclrtoeol(int pos) 235 { 236 wmove(input, 0, pos); 237 wclrtoeol(input); 238 wrefresh(input); 239 fflush(stdout); 240 } 241 242 void 243 iomove(int pos) 244 { 245 wmove(input, 0, pos); 246 wrefresh(input); 247 fflush(stdout); 248 } 249 250 void 251 ioaddstr(int pos, const char *str) 252 { 253 wmove(input, 0, pos); 254 waddstr(input, str); 255 wrefresh(input); 256 fflush(stdout); 257 } 258 259 void 260 ioclrtobot(void) 261 { 262 wclrtobot(input); 263 wrefresh(input); 264 fflush(stdout); 265 } 266 267 void 268 ioerror(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 281 void 282 quit(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 314 void 315 planewin(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 352 void 353 loser(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 381 void 382 redraw(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 400 void 401 done_screen(void) 402 { 403 clear(); 404 refresh(); 405 endwin(); /* clean up curses */ 406 } 407