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