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