1 /* $NetBSD: bdisp.c,v 1.15 2010/03/29 04:28:47 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 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)bdisp.c 8.2 (Berkeley) 5/3/95"; 39 #else 40 __RCSID("$NetBSD: bdisp.c,v 1.15 2010/03/29 04:28:47 dholland Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <curses.h> 45 #include <string.h> 46 #include <stdlib.h> 47 #include <err.h> 48 #include "gomoku.h" 49 50 #define SCRNH 24 /* assume 24 lines for the moment */ 51 #define SCRNW 80 /* assume 80 chars for the moment */ 52 53 static int lastline; 54 static char pcolor[] = "*O.?"; 55 56 extern int interactive; 57 extern char *plyr[]; 58 59 /* 60 * Initialize screen display. 61 */ 62 void 63 cursinit(void) 64 { 65 66 if (!initscr()) { 67 errx(EXIT_FAILURE, "Couldn't initialize screen"); 68 } 69 if ((LINES < SCRNH) || (COLS < SCRNW)) { 70 errx(EXIT_FAILURE, "Screen too small (need %d%xd)", 71 SCRNW, SCRNH); 72 } 73 keypad(stdscr, TRUE); 74 nonl(); 75 noecho(); 76 cbreak(); 77 leaveok(stdscr, FALSE); 78 79 #if 0 /* no mouse support in netbsd curses yet */ 80 mousemask(BUTTON1_CLICKED, NULL); 81 #endif 82 } 83 84 /* 85 * Restore screen display. 86 */ 87 void 88 cursfini(void) 89 { 90 91 move(BSZ4, 0); 92 clrtoeol(); 93 refresh(); 94 echo(); 95 endwin(); 96 } 97 98 /* 99 * Initialize board display. 100 */ 101 void 102 bdisp_init(void) 103 { 104 int i, j; 105 106 /* top border */ 107 for (i = 1; i < BSZ1; i++) { 108 move(0, 2 * i + 1); 109 addch(letters[i]); 110 } 111 /* left and right edges */ 112 for (j = BSZ1; --j > 0; ) { 113 move(20 - j, 0); 114 printw("%2d ", j); 115 move(20 - j, 2 * BSZ1 + 1); 116 printw("%d ", j); 117 } 118 /* bottom border */ 119 for (i = 1; i < BSZ1; i++) { 120 move(20, 2 * i + 1); 121 addch(letters[i]); 122 } 123 bdwho(0); 124 move(0, 47); 125 addstr("# black white"); 126 lastline = 0; 127 bdisp(); 128 } 129 130 /* 131 * Update who is playing whom. 132 */ 133 void 134 bdwho(int update) 135 { 136 int i, j; 137 138 move(21, 0); 139 printw(" "); 140 i = strlen(plyr[BLACK]); 141 j = strlen(plyr[WHITE]); 142 if (i + j <= 20) { 143 move(21, 10 - (i+j)/2); 144 printw("BLACK/%s (*) vs. WHITE/%s (O)", 145 plyr[BLACK], plyr[WHITE]); 146 } else { 147 move(21, 0); 148 if (i <= 10) { 149 j = 20 - i; 150 } else if (j <= 10) { 151 i = 20 - j; 152 } else { 153 i = j = 10; 154 } 155 printw("BLACK/%.*s (*) vs. WHITE/%.*s (O)", 156 i, plyr[BLACK], j, plyr[WHITE]); 157 } 158 if (update) 159 refresh(); 160 } 161 162 /* 163 * Update the board display after a move. 164 */ 165 void 166 bdisp(void) 167 { 168 int i, j, c; 169 struct spotstr *sp; 170 171 for (j = BSZ1; --j > 0; ) { 172 for (i = 1; i < BSZ1; i++) { 173 move(BSZ1 - j, 2 * i + 1); 174 sp = &board[i + j * BSZ1]; 175 if (debug > 1 && sp->s_occ == EMPTY) { 176 if (sp->s_flags & IFLAGALL) 177 c = '+'; 178 else if (sp->s_flags & CFLAGALL) 179 c = '-'; 180 else 181 c = '.'; 182 } else 183 c = pcolor[sp->s_occ]; 184 addch(c); 185 } 186 } 187 refresh(); 188 } 189 190 #ifdef DEBUG 191 /* 192 * Dump board display to a file. 193 */ 194 void 195 bdump(FILE *fp) 196 { 197 int i, j, c; 198 struct spotstr *sp; 199 200 /* top border */ 201 fprintf(fp, " A B C D E F G H J K L M N O P Q R S T\n"); 202 203 for (j = BSZ1; --j > 0; ) { 204 /* left edge */ 205 fprintf(fp, "%2d ", j); 206 for (i = 1; i < BSZ1; i++) { 207 sp = &board[i + j * BSZ1]; 208 if (debug > 1 && sp->s_occ == EMPTY) { 209 if (sp->s_flags & IFLAGALL) 210 c = '+'; 211 else if (sp->s_flags & CFLAGALL) 212 c = '-'; 213 else 214 c = '.'; 215 } else 216 c = pcolor[sp->s_occ]; 217 putc(c, fp); 218 putc(' ', fp); 219 } 220 /* right edge */ 221 fprintf(fp, "%d\n", j); 222 } 223 224 /* bottom border */ 225 fprintf(fp, " A B C D E F G H J K L M N O P Q R S T\n"); 226 } 227 #endif /* DEBUG */ 228 229 /* 230 * Display a transcript entry 231 */ 232 void 233 dislog(const char *str) 234 { 235 236 if (++lastline >= SCRNH - 1) { 237 /* move 'em up */ 238 lastline = 1; 239 } 240 move(lastline, TRANSCRIPT_COL); 241 addnstr(str, SCRNW - TRANSCRIPT_COL - 1); 242 clrtoeol(); 243 move(lastline + 1, TRANSCRIPT_COL); 244 clrtoeol(); 245 } 246 247 /* 248 * Display a question. 249 */ 250 251 void 252 ask(const char *str) 253 { 254 int len = strlen(str); 255 256 move(BSZ4, 0); 257 addstr(str); 258 clrtoeol(); 259 move(BSZ4, len); 260 refresh(); 261 } 262 263 int 264 get_key(const char *allowed) 265 { 266 int ch; 267 268 while (1) { 269 ch = getch(); 270 if (allowed != NULL && 271 ch != '\0' && strchr(allowed, ch) == NULL) { 272 beep(); 273 refresh(); 274 continue; 275 } 276 break; 277 } 278 return ch; 279 } 280 281 int 282 get_line(char *buf, int size) 283 { 284 char *cp, *end; 285 int c; 286 287 c = 0; 288 cp = buf; 289 end = buf + size - 1; /* save room for the '\0' */ 290 while (cp < end && (c = getchar()) != EOF && c != '\n' && c != '\r') { 291 *cp++ = c; 292 if (interactive) { 293 switch (c) { 294 case 0x0c: /* ^L */ 295 wrefresh(curscr); 296 cp--; 297 continue; 298 case 0x15: /* ^U */ 299 case 0x18: /* ^X */ 300 while (cp > buf) { 301 cp--; 302 addch('\b'); 303 } 304 clrtoeol(); 305 break; 306 case '\b': 307 case 0x7f: /* DEL */ 308 if (cp == buf + 1) { 309 cp--; 310 continue; 311 } 312 cp -= 2; 313 addch('\b'); 314 c = ' '; 315 /* FALLTHROUGH */ 316 default: 317 addch(c); 318 } 319 refresh(); 320 } 321 } 322 *cp = '\0'; 323 return(c != EOF); 324 } 325 326 /* 327 * Decent (n)curses interface for the game, based on Eric S. Raymond's 328 * modifications to the battleship (bs) user interface. 329 */ 330 int 331 get_coord(void) 332 { 333 static int curx = BSZ / 2; 334 static int cury = BSZ / 2; 335 int ny, nx, ch; 336 337 BGOTO(cury, curx); 338 refresh(); 339 nx = curx; 340 ny = cury; 341 for (;;) { 342 mvprintw(BSZ3, (BSZ -6)/2, "(%c %d) ", 343 'A'+ ((curx > 7) ? (curx+1) : curx), cury + 1); 344 BGOTO(cury, curx); 345 346 ch = getch(); 347 switch (ch) { 348 case 'k': 349 case '8': 350 case KEY_UP: 351 nx = curx; 352 ny = cury + 1; 353 break; 354 case 'j': 355 case '2': 356 case KEY_DOWN: 357 nx = curx; 358 ny = BSZ + cury - 1; 359 break; 360 case 'h': 361 case '4': 362 case KEY_LEFT: 363 nx = BSZ + curx - 1; 364 ny = cury; 365 break; 366 case 'l': 367 case '6': 368 case KEY_RIGHT: 369 nx = curx + 1; 370 ny = cury; 371 break; 372 case 'y': 373 case '7': 374 case KEY_A1: 375 nx = BSZ + curx - 1; 376 ny = cury + 1; 377 break; 378 case 'b': 379 case '1': 380 case KEY_C1: 381 nx = BSZ + curx - 1; 382 ny = BSZ + cury - 1; 383 break; 384 case 'u': 385 case '9': 386 case KEY_A3: 387 nx = curx + 1; 388 ny = cury + 1; 389 break; 390 case 'n': 391 case '3': 392 case KEY_C3: 393 nx = curx + 1; 394 ny = BSZ + cury - 1; 395 break; 396 case 'K': 397 nx = curx; 398 ny = cury + 5; 399 break; 400 case 'J': 401 nx = curx; 402 ny = BSZ + cury - 5; 403 break; 404 case 'H': 405 nx = BSZ + curx - 5; 406 ny = cury; 407 break; 408 case 'L': 409 nx = curx + 5; 410 ny = cury; 411 break; 412 case 'Y': 413 nx = BSZ + curx - 5; 414 ny = cury + 5; 415 break; 416 case 'B': 417 nx = BSZ + curx - 5; 418 ny = BSZ + cury - 5; 419 break; 420 case 'U': 421 nx = curx + 5; 422 ny = cury + 5; 423 break; 424 case 'N': 425 nx = curx + 5; 426 ny = BSZ + cury - 5; 427 break; 428 case '\f': 429 nx = curx; 430 ny = cury; 431 (void)clearok(stdscr, TRUE); 432 (void)refresh(); 433 break; 434 #if 0 /* notyet */ 435 case KEY_MOUSE: 436 { 437 MEVENT myevent; 438 439 getmouse(&myevent); 440 if (myevent.y >= 1 && myevent.y <= BSZ1 && 441 myevent.x >= 3 && myevent.x <= (2 * BSZ + 1)) { 442 curx = (myevent.x - 3) / 2; 443 cury = BSZ - myevent.y; 444 return PT(curx,cury); 445 } else { 446 beep(); 447 } 448 } 449 break; 450 #endif /* 0 */ 451 case 'Q': 452 case 'q': 453 return RESIGN; 454 break; 455 case 'S': 456 case 's': 457 return SAVE; 458 break; 459 case ' ': 460 case '\r': 461 (void) mvaddstr(BSZ3, (BSZ -6)/2, " "); 462 return PT(curx+1,cury+1); 463 break; 464 } 465 466 curx = nx % BSZ; 467 cury = ny % BSZ; 468 } 469 } 470