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