1 /* 2 * Copyright (c) 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char copyright[] = 13 "@(#) Copyright (c) 1994\n\ 14 The Regents of the University of California. All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 05/03/95"; 19 #endif /* not lint */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <signal.h> 25 #include <curses.h> 26 #include <err.h> 27 28 #include "gomoku.h" 29 30 #define USER 0 /* get input from standard input */ 31 #define PROGRAM 1 /* get input from program */ 32 #define INPUTF 2 /* get input from a file */ 33 34 int interactive = 1; /* true if interactive */ 35 int debug; /* true if debugging */ 36 int test; /* both moves come from 1: input, 2: computer */ 37 char *prog; /* name of program */ 38 FILE *debugfp; /* file for debug output */ 39 FILE *inputfp; /* file for debug input */ 40 41 char pdir[4] = "-\\|/"; 42 char fmtbuf[128]; 43 44 struct spotstr board[BAREA]; /* info for board */ 45 struct combostr frames[FAREA]; /* storage for all frames */ 46 struct combostr *sortframes[2]; /* sorted list of non-empty frames */ 47 u_char overlap[FAREA * FAREA]; /* true if frame [a][b] overlap */ 48 short intersect[FAREA * FAREA]; /* frame [a][b] intersection */ 49 int movelog[BSZ * BSZ]; /* log of all the moves */ 50 int movenum; /* current move number */ 51 char *plyr[2]; /* who's who */ 52 53 extern void quit(); 54 #ifdef DEBUG 55 extern void whatsup(); 56 #endif 57 58 main(argc, argv) 59 int argc; 60 char **argv; 61 { 62 char buf[128]; 63 int color, curmove, i, ch; 64 int input[2]; 65 static char *fmt[2] = { 66 "%3d %-6s", 67 "%3d %-6s" 68 }; 69 70 prog = strrchr(argv[0], '/'); 71 if (prog) 72 prog++; 73 else 74 prog = argv[0]; 75 76 while ((ch = getopt(argc, argv, "bcdD:u")) != EOF) { 77 switch (ch) { 78 case 'b': /* background */ 79 interactive = 0; 80 break; 81 case 'd': /* debugging */ 82 debug++; 83 break; 84 case 'D': /* log debug output to file */ 85 if ((debugfp = fopen(optarg, "w")) == NULL) 86 err(1, "%s", optarg); 87 break; 88 case 'u': /* testing: user verses user */ 89 test = 1; 90 break; 91 case 'c': /* testing: computer verses computer */ 92 test = 2; 93 break; 94 } 95 } 96 argc -= optind; 97 argv += optind; 98 if (argc) { 99 if ((inputfp = fopen(*argv, "r")) == NULL) 100 err(1, "%s", *argv); 101 } 102 103 if (!debug) 104 #ifdef SVR4 105 srand(time(0)); 106 #else 107 srandom(time(0)); 108 #endif 109 if (interactive) 110 cursinit(); /* initialize curses */ 111 again: 112 bdinit(board); /* initialize board contents */ 113 114 if (interactive) { 115 plyr[BLACK] = plyr[WHITE] = "???"; 116 bdisp_init(); /* initialize display of board */ 117 #ifdef DEBUG 118 signal(SIGINT, whatsup); 119 #else 120 signal(SIGINT, quit); 121 #endif 122 123 if (inputfp == NULL && test == 0) { 124 for (;;) { 125 ask("black or white? "); 126 getline(buf, sizeof(buf)); 127 if (buf[0] == 'b' || buf[0] == 'B') { 128 color = BLACK; 129 break; 130 } 131 if (buf[0] == 'w' || buf[0] == 'W') { 132 color = WHITE; 133 break; 134 } 135 move(22, 0); 136 printw("Black moves first. Please enter `black' or `white'\n"); 137 } 138 move(22, 0); 139 clrtoeol(); 140 } 141 } else { 142 setbuf(stdout, 0); 143 getline(buf, sizeof(buf)); 144 if (strcmp(buf, "black") == 0) 145 color = BLACK; 146 else if (strcmp(buf, "white") == 0) 147 color = WHITE; 148 else { 149 sprintf(fmtbuf, 150 "Huh? Expected `black' or `white', got `%s'\n", 151 buf); 152 panic(fmtbuf); 153 } 154 } 155 156 if (inputfp) { 157 input[BLACK] = INPUTF; 158 input[WHITE] = INPUTF; 159 } else { 160 switch (test) { 161 case 0: /* user verses program */ 162 input[color] = USER; 163 input[!color] = PROGRAM; 164 break; 165 166 case 1: /* user verses user */ 167 input[BLACK] = USER; 168 input[WHITE] = USER; 169 break; 170 171 case 2: /* program verses program */ 172 input[BLACK] = PROGRAM; 173 input[WHITE] = PROGRAM; 174 break; 175 } 176 } 177 if (interactive) { 178 plyr[BLACK] = input[BLACK] == USER ? "you" : prog; 179 plyr[WHITE] = input[WHITE] == USER ? "you" : prog; 180 bdwho(1); 181 } 182 183 for (color = BLACK; ; color = !color) { 184 top: 185 switch (input[color]) { 186 case INPUTF: /* input comes from a file */ 187 curmove = readinput(inputfp); 188 if (curmove != ILLEGAL) 189 break; 190 switch (test) { 191 case 0: /* user verses program */ 192 input[color] = USER; 193 input[!color] = PROGRAM; 194 break; 195 196 case 1: /* user verses user */ 197 input[BLACK] = USER; 198 input[WHITE] = USER; 199 break; 200 201 case 2: /* program verses program */ 202 input[BLACK] = PROGRAM; 203 input[WHITE] = PROGRAM; 204 break; 205 } 206 plyr[BLACK] = input[BLACK] == USER ? "you" : prog; 207 plyr[WHITE] = input[WHITE] == USER ? "you" : prog; 208 bdwho(1); 209 goto top; 210 211 case USER: /* input comes from standard input */ 212 getinput: 213 if (interactive) 214 ask("move? "); 215 if (!getline(buf, sizeof(buf))) { 216 curmove = RESIGN; 217 break; 218 } 219 if (buf[0] == '\0') 220 goto getinput; 221 curmove = ctos(buf); 222 if (interactive) { 223 if (curmove == SAVE) { 224 FILE *fp; 225 226 ask("save file name? "); 227 (void)getline(buf, sizeof(buf)); 228 if ((fp = fopen(buf, "w")) == NULL) { 229 log("cannot create save file"); 230 goto getinput; 231 } 232 for (i = 0; i < movenum - 1; i++) 233 fprintf(fp, "%s\n", 234 stoc(movelog[i])); 235 fclose(fp); 236 goto getinput; 237 } 238 if (curmove != RESIGN && 239 board[curmove].s_occ != EMPTY) { 240 log("Illegal move"); 241 goto getinput; 242 } 243 } 244 break; 245 246 case PROGRAM: /* input comes from the program */ 247 curmove = pickmove(color); 248 break; 249 } 250 if (interactive) { 251 sprintf(fmtbuf, fmt[color], movenum, stoc(curmove)); 252 log(fmtbuf); 253 } 254 if ((i = makemove(color, curmove)) != MOVEOK) 255 break; 256 if (interactive) 257 bdisp(); 258 } 259 if (interactive) { 260 move(22, 0); 261 switch (i) { 262 case WIN: 263 if (input[color] == PROGRAM) 264 addstr("Ha ha, I won"); 265 else 266 addstr("Rats! you won"); 267 break; 268 case TIE: 269 addstr("Wow! its a tie"); 270 break; 271 case ILLEGAL: 272 addstr("Illegal move"); 273 break; 274 } 275 clrtoeol(); 276 bdisp(); 277 if (i != RESIGN) { 278 replay: 279 ask("replay? "); 280 if (getline(buf, sizeof(buf)) && 281 buf[0] == 'y' || buf[0] == 'Y') 282 goto again; 283 if (strcmp(buf, "save") == 0) { 284 FILE *fp; 285 286 ask("save file name? "); 287 (void)getline(buf, sizeof(buf)); 288 if ((fp = fopen(buf, "w")) == NULL) { 289 log("cannot create save file"); 290 goto replay; 291 } 292 for (i = 0; i < movenum - 1; i++) 293 fprintf(fp, "%s\n", 294 stoc(movelog[i])); 295 fclose(fp); 296 goto replay; 297 } 298 } 299 } 300 quit(); 301 } 302 303 readinput(fp) 304 FILE *fp; 305 { 306 char *cp; 307 int c; 308 309 cp = fmtbuf; 310 while ((c = getc(fp)) != EOF && c != '\n') 311 *cp++ = c; 312 *cp = '\0'; 313 return (ctos(fmtbuf)); 314 } 315 316 #ifdef DEBUG 317 /* 318 * Handle strange situations. 319 */ 320 void 321 whatsup(signum) 322 int signum; 323 { 324 int i, pnum, n, s1, s2, d1, d2; 325 struct spotstr *sp; 326 FILE *fp; 327 char *str; 328 struct elist *ep; 329 struct combostr *cbp; 330 331 if (!interactive) 332 quit(); 333 top: 334 ask("cmd? "); 335 if (!getline(fmtbuf, sizeof(fmtbuf))) 336 quit(); 337 switch (*fmtbuf) { 338 case '\0': 339 goto top; 340 case 'q': /* conservative quit */ 341 quit(); 342 case 'd': /* set debug level */ 343 debug = fmtbuf[1] - '0'; 344 sprintf(fmtbuf, "Debug set to %d", debug); 345 dlog(fmtbuf); 346 sleep(1); 347 case 'c': 348 break; 349 case 'b': /* back up a move */ 350 if (movenum > 1) { 351 movenum--; 352 board[movelog[movenum - 1]].s_occ = EMPTY; 353 bdisp(); 354 } 355 goto top; 356 case 's': /* suggest a move */ 357 i = fmtbuf[1] == 'b' ? BLACK : WHITE; 358 sprintf(fmtbuf, "suggest %c %s", i == BLACK ? 'B' : 'W', 359 stoc(pickmove(i))); 360 dlog(fmtbuf); 361 goto top; 362 case 'f': /* go forward a move */ 363 board[movelog[movenum - 1]].s_occ = movenum & 1 ? BLACK : WHITE; 364 movenum++; 365 bdisp(); 366 goto top; 367 case 'l': /* print move history */ 368 if (fmtbuf[1] == '\0') { 369 for (i = 0; i < movenum - 1; i++) 370 dlog(stoc(movelog[i])); 371 goto top; 372 } 373 if ((fp = fopen(fmtbuf + 1, "w")) == NULL) 374 goto top; 375 for (i = 0; i < movenum - 1; i++) { 376 fprintf(fp, "%s", stoc(movelog[i])); 377 if (++i < movenum - 1) 378 fprintf(fp, " %s\n", stoc(movelog[i])); 379 else 380 fputc('\n', fp); 381 } 382 bdump(fp); 383 fclose(fp); 384 goto top; 385 case 'o': 386 n = 0; 387 for (str = fmtbuf + 1; *str; str++) 388 if (*str == ',') { 389 for (d1 = 0; d1 < 4; d1++) 390 if (str[-1] == pdir[d1]) 391 break; 392 str[-1] = '\0'; 393 sp = &board[s1 = ctos(fmtbuf + 1)]; 394 n = (sp->s_frame[d1] - frames) * FAREA; 395 *str++ = '\0'; 396 break; 397 } 398 sp = &board[s2 = ctos(str)]; 399 while (*str) 400 str++; 401 for (d2 = 0; d2 < 4; d2++) 402 if (str[-1] == pdir[d2]) 403 break; 404 n += sp->s_frame[d2] - frames; 405 str = fmtbuf; 406 sprintf(str, "overlap %s%c,", stoc(s1), pdir[d1]); 407 str += strlen(str); 408 sprintf(str, "%s%c = %x", stoc(s2), pdir[d2], overlap[n]); 409 dlog(fmtbuf); 410 goto top; 411 case 'p': 412 sp = &board[i = ctos(fmtbuf + 1)]; 413 sprintf(fmtbuf, "V %s %x/%d %d %x/%d %d %d %x", stoc(i), 414 sp->s_combo[BLACK].s, sp->s_level[BLACK], 415 sp->s_nforce[BLACK], 416 sp->s_combo[WHITE].s, sp->s_level[WHITE], 417 sp->s_nforce[WHITE], sp->s_wval, sp->s_flg); 418 dlog(fmtbuf); 419 sprintf(fmtbuf, "FB %s %x %x %x %x", stoc(i), 420 sp->s_fval[BLACK][0].s, sp->s_fval[BLACK][1].s, 421 sp->s_fval[BLACK][2].s, sp->s_fval[BLACK][3].s); 422 dlog(fmtbuf); 423 sprintf(fmtbuf, "FW %s %x %x %x %x", stoc(i), 424 sp->s_fval[WHITE][0].s, sp->s_fval[WHITE][1].s, 425 sp->s_fval[WHITE][2].s, sp->s_fval[WHITE][3].s); 426 dlog(fmtbuf); 427 goto top; 428 case 'e': /* e {b|w} [0-9] spot */ 429 str = fmtbuf + 1; 430 if (*str >= '0' && *str <= '9') 431 n = *str++ - '0'; 432 else 433 n = 0; 434 sp = &board[i = ctos(str)]; 435 for (ep = sp->s_empty; ep; ep = ep->e_next) { 436 cbp = ep->e_combo; 437 if (n) { 438 if (cbp->c_nframes > n) 439 continue; 440 if (cbp->c_nframes != n) 441 break; 442 } 443 printcombo(cbp, fmtbuf); 444 dlog(fmtbuf); 445 } 446 goto top; 447 default: 448 syntax: 449 dlog("Options are:"); 450 dlog("q - quit"); 451 dlog("c - continue"); 452 dlog("d# - set debug level to #"); 453 dlog("p# - print values at #"); 454 goto top; 455 } 456 } 457 #endif /* DEBUG */ 458 459 /* 460 * Display debug info. 461 */ 462 dlog(str) 463 char *str; 464 { 465 466 if (debugfp) 467 fprintf(debugfp, "%s\n", str); 468 if (interactive) 469 dislog(str); 470 else 471 fprintf(stderr, "%s\n", str); 472 } 473 474 log(str) 475 char *str; 476 { 477 478 if (debugfp) 479 fprintf(debugfp, "%s\n", str); 480 if (interactive) 481 dislog(str); 482 else 483 printf("%s\n", str); 484 } 485 486 void 487 quit() 488 { 489 if (interactive) { 490 bdisp(); /* show final board */ 491 cursfini(); 492 } 493 exit(0); 494 } 495 496 /* 497 * Die gracefully. 498 */ 499 panic(str) 500 char *str; 501 { 502 fprintf(stderr, "%s: %s\n", prog, str); 503 fputs("resign\n", stdout); 504 quit(); 505 } 506