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.1 (Berkeley) 07/24/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 srandom(time(0)); 104 #else 105 srand(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 != 3) { 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 ask("replay? "); 260 if (getline(buf, sizeof buf) && 261 buf[0] == 'y' || buf[0] == 'Y') 262 goto again; 263 } 264 } 265 quit(); 266 } 267 268 readinput(fp) 269 FILE *fp; 270 { 271 char *cp; 272 int c; 273 274 cp = fmtbuf; 275 while ((c = getc(fp)) != EOF && c != '\n') 276 *cp++ = c; 277 *cp = '\0'; 278 return (ctos(fmtbuf)); 279 } 280 281 #ifdef DEBUG 282 /* 283 * Handle strange situations. 284 */ 285 void 286 whatsup(signum) 287 int signum; 288 { 289 int i, pnum, n; 290 struct spotstr *sp; 291 FILE *fp; 292 char *str; 293 struct elist *ep; 294 struct combostr *cbp; 295 296 if (!interactive) 297 quit(); 298 top: 299 ask("cmd? "); 300 if (!getline(fmtbuf, 128)) 301 quit(); 302 switch (*fmtbuf) { 303 case 'q': /* conservative quit */ 304 quit(); 305 case 'd': /* set debug level */ 306 debug = fmtbuf[1] - '0'; 307 sprintf(fmtbuf, "Debug set to %d", debug); 308 dlog(fmtbuf); 309 sleep(1); 310 case 'c': 311 break; 312 case 'b': /* back up a move */ 313 if (movenum > 1) { 314 movenum--; 315 board[movelog[movenum - 1]].s_occ = EMPTY; 316 bdisp(); 317 } 318 goto top; 319 case 'f': /* go forward a move */ 320 board[movelog[movenum - 1]].s_occ = movenum & 1 ? BLACK : WHITE; 321 movenum++; 322 bdisp(); 323 goto top; 324 case 'l': /* print move history */ 325 if (fmtbuf[1] == '\0') { 326 for (i = 0; i < movenum - 1; i++) 327 dlog(stoc(movelog[i])); 328 goto top; 329 } 330 if ((fp = fopen(fmtbuf + 1, "w")) == NULL) 331 goto top; 332 for (i = 0; i < movenum - 1; i++) { 333 fprintf(fp, "%s", stoc(movelog[i])); 334 if (++i < movenum - 1) 335 fprintf(fp, " %s\n", stoc(movelog[i])); 336 else 337 fputc('\n', fp); 338 } 339 bdump(fp); 340 fclose(fp); 341 goto top; 342 case 'p': 343 sp = &board[i = ctos(fmtbuf + 1)]; 344 sprintf(fmtbuf, "V %s %x/%d %d %x/%d %d %d %x", stoc(i), 345 sp->s_combo[BLACK].s, sp->s_level[BLACK], 346 sp->s_nforce[BLACK], 347 sp->s_combo[WHITE].s, sp->s_level[WHITE], 348 sp->s_nforce[WHITE], sp->s_wval, sp->s_flg); 349 dlog(fmtbuf); 350 sprintf(fmtbuf, "FB %s %x %x %x %x", stoc(i), 351 sp->s_fval[BLACK][0].s, sp->s_fval[BLACK][1].s, 352 sp->s_fval[BLACK][2].s, sp->s_fval[BLACK][3].s); 353 dlog(fmtbuf); 354 sprintf(fmtbuf, "FW %s %x %x %x %x", stoc(i), 355 sp->s_fval[WHITE][0].s, sp->s_fval[WHITE][1].s, 356 sp->s_fval[WHITE][2].s, sp->s_fval[WHITE][3].s); 357 dlog(fmtbuf); 358 goto top; 359 case 'P': 360 sp = &board[i = ctos(fmtbuf + 1)]; 361 for (pnum = BLACK; pnum <= WHITE; pnum++) { 362 for (ep = sp->s_empty[pnum]; ep; ep = ep->e_next) { 363 cbp = ep->e_combo; 364 str = fmtbuf; 365 sprintf(str, "C%c %s", "BW"[pnum], stoc(i)); 366 str += strlen(str); 367 if (cbp->c_nframes == 2) { 368 sprintf(str, " %s%c", 369 stoc(cbp->c_link[0]->c_vertex), 370 pdir[cbp->c_link[0]->c_dir]); 371 str += strlen(str); 372 sprintf(str, " %s%c %x/%d", 373 stoc(cbp->c_link[1]->c_vertex), 374 pdir[cbp->c_link[1]->c_dir], 375 cbp->c_combo.s, cbp->c_nframes); 376 } else { 377 sprintf(str, " %s%c %x/%d", 378 stoc(cbp->c_vertex), 379 pdir[ep->e_frame->c_dir], 380 cbp->c_combo.s, cbp->c_nframes); 381 } 382 dlog(fmtbuf); 383 } 384 } 385 goto top; 386 default: 387 syntax: 388 dlog("Options are:"); 389 dlog("q - quit"); 390 dlog("c - continue"); 391 dlog("d# - set debug level to #"); 392 dlog("p# - print values at #"); 393 goto top; 394 } 395 } 396 #endif /* DEBUG */ 397 398 /* 399 * Display debug info. 400 */ 401 dlog(str) 402 char *str; 403 { 404 405 if (debugfp) 406 fprintf(debugfp, "%s\n", str); 407 else if (interactive) 408 dislog(str); 409 else 410 fprintf(stderr, "%s\n", str); 411 } 412 413 log(str) 414 char *str; 415 { 416 417 if (debugfp) 418 fprintf(debugfp, "%s\n", str); 419 if (interactive) 420 dislog(str); 421 else 422 printf("%s\n", str); 423 } 424 425 void 426 quit() 427 { 428 if (interactive) { 429 bdisp(); /* show final board */ 430 cursfini(); 431 } 432 exit(0); 433 } 434 435 /* 436 * Die gracefully. 437 */ 438 panic(str) 439 char *str; 440 { 441 fprintf(stderr, "%s: %s\n", prog, str); 442 fputs("resign\n", stdout); 443 quit(); 444 } 445