1 /* $NetBSD: bdisp.c,v 1.17 2014/03/22 18:58:57 dholland Exp $ */ 2 3 /* 4 * Copyright (c) 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Ralph Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)bdisp.c 8.2 (Berkeley) 5/3/95 35 */ 36 37 #include <curses.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include <err.h> 41 #include "gomoku.h" 42 43 #define SCRNH 24 /* assume 24 lines for the moment */ 44 #define SCRNW 80 /* assume 80 chars for the moment */ 45 46 static int lastline; 47 static char pcolor[] = "*O.?"; 48 49 /* 50 * Initialize screen display. 51 */ 52 void 53 cursinit(void) 54 { 55 56 if (!initscr()) { 57 errx(EXIT_FAILURE, "Couldn't initialize screen"); 58 } 59 if ((LINES < SCRNH) || (COLS < SCRNW)) { 60 errx(EXIT_FAILURE, "Screen too small (need %d%xd)", 61 SCRNW, SCRNH); 62 } 63 keypad(stdscr, TRUE); 64 nonl(); 65 noecho(); 66 cbreak(); 67 leaveok(stdscr, FALSE); 68 69 #if 0 /* no mouse support in netbsd curses yet */ 70 mousemask(BUTTON1_CLICKED, NULL); 71 #endif 72 } 73 74 /* 75 * Restore screen display. 76 */ 77 void 78 cursfini(void) 79 { 80 81 move(BSZ4, 0); 82 clrtoeol(); 83 refresh(); 84 echo(); 85 endwin(); 86 } 87 88 /* 89 * Initialize board display. 90 */ 91 void 92 bdisp_init(void) 93 { 94 int i, j; 95 96 /* top border */ 97 for (i = 1; i < BSZ1; i++) { 98 move(0, 2 * i + 1); 99 addch(letters[i]); 100 } 101 /* left and right edges */ 102 for (j = BSZ1; --j > 0; ) { 103 move(20 - j, 0); 104 printw("%2d ", j); 105 move(20 - j, 2 * BSZ1 + 1); 106 printw("%d ", j); 107 } 108 /* bottom border */ 109 for (i = 1; i < BSZ1; i++) { 110 move(20, 2 * i + 1); 111 addch(letters[i]); 112 } 113 bdwho(0); 114 move(0, 47); 115 addstr("# black white"); 116 lastline = 0; 117 bdisp(); 118 } 119 120 /* 121 * Update who is playing whom. 122 */ 123 void 124 bdwho(int update) 125 { 126 int i, j; 127 128 move(21, 0); 129 printw(" "); 130 i = strlen(plyr[BLACK]); 131 j = strlen(plyr[WHITE]); 132 if (i + j <= 20) { 133 move(21, 10 - (i+j)/2); 134 printw("BLACK/%s (*) vs. WHITE/%s (O)", 135 plyr[BLACK], plyr[WHITE]); 136 } else { 137 move(21, 0); 138 if (i <= 10) { 139 j = 20 - i; 140 } else if (j <= 10) { 141 i = 20 - j; 142 } else { 143 i = j = 10; 144 } 145 printw("BLACK/%.*s (*) vs. WHITE/%.*s (O)", 146 i, plyr[BLACK], j, plyr[WHITE]); 147 } 148 if (update) 149 refresh(); 150 } 151 152 /* 153 * Update the board display after a move. 154 */ 155 void 156 bdisp(void) 157 { 158 int i, j, c; 159 struct spotstr *sp; 160 161 for (j = BSZ1; --j > 0; ) { 162 for (i = 1; i < BSZ1; i++) { 163 move(BSZ1 - j, 2 * i + 1); 164 sp = &board[i + j * BSZ1]; 165 if (debug > 1 && sp->s_occ == EMPTY) { 166 if (sp->s_flags & IFLAGALL) 167 c = '+'; 168 else if (sp->s_flags & CFLAGALL) 169 c = '-'; 170 else 171 c = '.'; 172 } else 173 c = pcolor[sp->s_occ]; 174 addch(c); 175 } 176 } 177 refresh(); 178 } 179 180 #ifdef DEBUG 181 /* 182 * Dump board display to a file. 183 */ 184 void 185 bdump(FILE *fp) 186 { 187 int i, j, c; 188 struct spotstr *sp; 189 190 /* top border */ 191 fprintf(fp, " A B C D E F G H J K L M N O P Q R S T\n"); 192 193 for (j = BSZ1; --j > 0; ) { 194 /* left edge */ 195 fprintf(fp, "%2d ", j); 196 for (i = 1; i < BSZ1; i++) { 197 sp = &board[i + j * BSZ1]; 198 if (debug > 1 && sp->s_occ == EMPTY) { 199 if (sp->s_flags & IFLAGALL) 200 c = '+'; 201 else if (sp->s_flags & CFLAGALL) 202 c = '-'; 203 else 204 c = '.'; 205 } else 206 c = pcolor[sp->s_occ]; 207 putc(c, fp); 208 putc(' ', fp); 209 } 210 /* right edge */ 211 fprintf(fp, "%d\n", j); 212 } 213 214 /* bottom border */ 215 fprintf(fp, " A B C D E F G H J K L M N O P Q R S T\n"); 216 } 217 #endif /* DEBUG */ 218 219 /* 220 * Display a transcript entry 221 */ 222 void 223 dislog(const char *str) 224 { 225 226 if (++lastline >= SCRNH - 1) { 227 /* move 'em up */ 228 lastline = 1; 229 } 230 move(lastline, TRANSCRIPT_COL); 231 addnstr(str, SCRNW - TRANSCRIPT_COL - 1); 232 clrtoeol(); 233 move(lastline + 1, TRANSCRIPT_COL); 234 clrtoeol(); 235 } 236 237 /* 238 * Display a question. 239 */ 240 241 void 242 ask(const char *str) 243 { 244 int len = strlen(str); 245 246 move(BSZ4, 0); 247 addstr(str); 248 clrtoeol(); 249 move(BSZ4, len); 250 refresh(); 251 } 252 253 int 254 get_key(const char *allowed) 255 { 256 int ch; 257 258 while (1) { 259 ch = getch(); 260 if (allowed != NULL && 261 ch != '\0' && strchr(allowed, ch) == NULL) { 262 beep(); 263 refresh(); 264 continue; 265 } 266 break; 267 } 268 return ch; 269 } 270 271 int 272 get_line(char *buf, int size) 273 { 274 char *cp, *end; 275 int c; 276 277 c = 0; 278 cp = buf; 279 end = buf + size - 1; /* save room for the '\0' */ 280 while (cp < end && (c = getchar()) != EOF && c != '\n' && c != '\r') { 281 *cp++ = c; 282 if (interactive) { 283 switch (c) { 284 case 0x0c: /* ^L */ 285 wrefresh(curscr); 286 cp--; 287 continue; 288 case 0x15: /* ^U */ 289 case 0x18: /* ^X */ 290 while (cp > buf) { 291 cp--; 292 addch('\b'); 293 } 294 clrtoeol(); 295 break; 296 case '\b': 297 case 0x7f: /* DEL */ 298 if (cp == buf + 1) { 299 cp--; 300 continue; 301 } 302 cp -= 2; 303 addch('\b'); 304 c = ' '; 305 /* FALLTHROUGH */ 306 default: 307 addch(c); 308 } 309 refresh(); 310 } 311 } 312 *cp = '\0'; 313 return(c != EOF); 314 } 315 316 /* 317 * Decent (n)curses interface for the game, based on Eric S. Raymond's 318 * modifications to the battleship (bs) user interface. 319 */ 320 int 321 get_coord(void) 322 { 323 static int curx = BSZ / 2; 324 static int cury = BSZ / 2; 325 int ny, nx, ch; 326 327 BGOTO(cury, curx); 328 refresh(); 329 nx = curx; 330 ny = cury; 331 for (;;) { 332 mvprintw(BSZ3, (BSZ -6)/2, "(%c %d) ", 333 'A'+ ((curx > 7) ? (curx+1) : curx), cury + 1); 334 BGOTO(cury, curx); 335 336 ch = getch(); 337 switch (ch) { 338 case 'k': 339 case '8': 340 case KEY_UP: 341 nx = curx; 342 ny = cury + 1; 343 break; 344 case 'j': 345 case '2': 346 case KEY_DOWN: 347 nx = curx; 348 ny = BSZ + cury - 1; 349 break; 350 case 'h': 351 case '4': 352 case KEY_LEFT: 353 nx = BSZ + curx - 1; 354 ny = cury; 355 break; 356 case 'l': 357 case '6': 358 case KEY_RIGHT: 359 nx = curx + 1; 360 ny = cury; 361 break; 362 case 'y': 363 case '7': 364 case KEY_A1: 365 nx = BSZ + curx - 1; 366 ny = cury + 1; 367 break; 368 case 'b': 369 case '1': 370 case KEY_C1: 371 nx = BSZ + curx - 1; 372 ny = BSZ + cury - 1; 373 break; 374 case 'u': 375 case '9': 376 case KEY_A3: 377 nx = curx + 1; 378 ny = cury + 1; 379 break; 380 case 'n': 381 case '3': 382 case KEY_C3: 383 nx = curx + 1; 384 ny = BSZ + cury - 1; 385 break; 386 case 'K': 387 nx = curx; 388 ny = cury + 5; 389 break; 390 case 'J': 391 nx = curx; 392 ny = BSZ + cury - 5; 393 break; 394 case 'H': 395 nx = BSZ + curx - 5; 396 ny = cury; 397 break; 398 case 'L': 399 nx = curx + 5; 400 ny = cury; 401 break; 402 case 'Y': 403 nx = BSZ + curx - 5; 404 ny = cury + 5; 405 break; 406 case 'B': 407 nx = BSZ + curx - 5; 408 ny = BSZ + cury - 5; 409 break; 410 case 'U': 411 nx = curx + 5; 412 ny = cury + 5; 413 break; 414 case 'N': 415 nx = curx + 5; 416 ny = BSZ + cury - 5; 417 break; 418 case '\f': 419 nx = curx; 420 ny = cury; 421 (void)clearok(stdscr, TRUE); 422 (void)refresh(); 423 break; 424 #if 0 /* notyet */ 425 case KEY_MOUSE: 426 { 427 MEVENT myevent; 428 429 getmouse(&myevent); 430 if (myevent.y >= 1 && myevent.y <= BSZ1 && 431 myevent.x >= 3 && myevent.x <= (2 * BSZ + 1)) { 432 curx = (myevent.x - 3) / 2; 433 cury = BSZ - myevent.y; 434 return PT(curx,cury); 435 } else { 436 beep(); 437 } 438 } 439 break; 440 #endif /* 0 */ 441 case 'Q': 442 case 'q': 443 return RESIGN; 444 break; 445 case 'S': 446 case 's': 447 return SAVE; 448 break; 449 case ' ': 450 case '\r': 451 (void) mvaddstr(BSZ3, (BSZ -6)/2, " "); 452 return PT(curx+1,cury+1); 453 break; 454 } 455 456 curx = nx % BSZ; 457 cury = ny % BSZ; 458 } 459 } 460