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