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