int main(int argc, char *argv[]) { if (pledge("stdio rpath tty", NULL) == -1) err(1, "pledge"); do_options(argc, argv); intro(); do { initgame(); while(awinna() == -1) { if (!blitz) { if (!salvo) { if(turn) (void) cputurn(); else (void) plyturn(); } else /* salvo */ { int i; i = scount(turn); while (i--) { if (turn) { if (cputurn() && awinna() != -1) i = 0; } else { if (plyturn() && awinna() != -1) i = 0; } } } } else /* blitz */ while(turn ? cputurn() : plyturn()) { if (turn) /* Pause between successive computer shots */ { (void)refresh(); (void)sleep(1); } if (awinna() != -1) break; } turn = OTHER; } } while (playagain()); uninitgame(0); return 0; }
int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); do_options(argc, argv); intro(); do { initgame(); while (awinna() == -1) { if (!blitz) { if (!salvo) { if (turn) (void) cputurn(); else (void) plyturn(); } else { register int i; i = scount(turn); while (i--) { if (turn) { if (cputurn() && awinna() != -1) i = 0; } else { if (plyturn() && awinna() != -1) i = 0; } } } } else while ((turn ? cputurn() : plyturn()) && awinna() == -1) continue; turn = OTHER; } } while (playagain()); uninitgame(0); /*NOTREACHED */ }
int main(int argc, char **argv) { do_options(argc, argv); intro(); do { initgame(); while(awinna() == -1) { if (!blitz) { if (!salvo) { if (turn) cputurn(); else plyturn(); } else { register int i; i = scount(turn); while (i--) { if (turn) if (cputurn()) if (awinna() != -1) i = 0; else if(plyturn()) if (awinna() != -1) i = 0; } } } else { while((turn) ? cputurn() : plyturn()); } turn = OTHER; } } while(playagain()); uninitgame(); exit(0); }
int main(int argc, char **argv) { int ch; /* revoke */ setgid(getgid()); while ((ch = getopt(argc, argv, "bsc")) != -1) { switch (ch) { case 'b': blitz = 1; break; case 's': salvo = 1; break; case 'c': closepack = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (blitz && salvo) usage(); intro(); do { initgame(); while(awinna() == -1) { if (blitz) { while(turn ? cputurn() : plyturn()) continue; } else if (salvo) { int i; i = scount(turn); while (i--) { if (turn) { if (cputurn() && awinna() != -1) i = 0; } else { if (plyturn() && awinna() != -1) i = 0; } } } else { /* Normal game */ if(turn) cputurn(); else plyturn(); } turn = OTHER; } } while (playagain()); uninitgame(); exit(0); }
/* * This code implements a fairly irregular FSM, so please forgive the rampant * unstructuredness below. The five labels are states which need to be held * between computer turns. */ static int cputurn(void) { static bool used[4]; static ship_t ts; int navail, x, y, d, n, hit = S_MISS; bool closenoshot = FALSE; switch(next) { case RANDOM_FIRE: /* last shot was random and missed */ refire: randomfire(&x, &y); if (!(hit = cpufire(x, y))) next = RANDOM_FIRE; else { ts.x = x; ts.y = y; ts.hits = 1; next = (hit == S_SUNK) ? RANDOM_FIRE : RANDOM_HIT; } break; case RANDOM_HIT: /* last shot was random and hit */ used[E/2] = used[W/2] = (!(cpushipcanfit(ts.x,ts.y,cpushortest,E))); used[S/2] = used[N/2] = (!(cpushipcanfit(ts.x,ts.y,cpushortest,S))); /* FALLTHROUGH */ case HUNT_DIRECT: /* last shot hit, we're looking for ship's long axis */ for (d = navail = 0; d < 4; d++) { x = ts.x + xincr[d*2]; y = ts.y + yincr[d*2]; if (!used[d] && POSSIBLE(x, y)) navail++; else used[d] = TRUE; } if (navail == 0) /* no valid places for shots adjacent... */ goto refire; /* ...so we must random-fire */ else { for (d = 0, n = rnd(navail) + 1; n; n--,d++) while (used[d]) d++; d--; x = ts.x + xincr[d*2]; y = ts.y + yincr[d*2]; if (!(hit = cpufire(x, y))) next = HUNT_DIRECT; else { ts.x = x; ts.y = y; ts.dir = d*2; ts.hits++; next = (hit == S_SUNK) ? RANDOM_FIRE : FIRST_PASS; } } break; case FIRST_PASS: /* we have a start and a direction now */ x = ts.x + xincr[ts.dir]; y = ts.y + yincr[ts.dir]; if (POSSIBLE(x, y)) { if ((hit = cpufire(x, y))) { ts.x = x; ts.y = y; ts.hits++; next = (hit == S_SUNK) ? RANDOM_FIRE : FIRST_PASS; } else next = REVERSE_JUMP; break; } else next = REVERSE_JUMP; /* FALL THROUGH */ case REVERSE_JUMP: /* nail down the ship's other end */ ts.dir = (ts.dir + 4) % 8; ts.x += (ts.hits-1) * xincr[ts.dir]; ts.y += (ts.hits-1) * yincr[ts.dir]; /* FALL THROUGH */ case SECOND_PASS: /* kill squares not caught on first pass */ x = ts.x + xincr[ts.dir]; y = ts.y + yincr[ts.dir]; if (POSSIBLE(x, y)) { if ((hit = cpufire(x, y))) { ts.x = x; ts.y = y; ts.hits++; next = (hit == S_SUNK) ? RANDOM_FIRE : SECOND_PASS; } else { /* The only way to get here is if closepack is on; otherwise, * we _have_ sunk the ship. I set hit to S_SUNK just to get * the additional closepack logic at the end of the switch. */ /*assert closepack*/ if (!closepack) error("Assertion failed: not closepack 1"); hit = S_SUNK; next = RANDOM_FIRE; } } else { /*assert closepack*/ if (!closepack) error("Assertion failed: not closepack 2"); hit = S_SUNK; closenoshot = TRUE; /* Didn't shoot yet! */ next = RANDOM_FIRE; } break; } /* switch(next) */ if (hit == S_SUNK) { /* Update cpulongest and cpushortest. We could increase srchstep * if it's smaller than cpushortest but that makes strategic sense * only if we've been doing continuous diagonal stripes, and that's * less interesting to watch. */ ship_t *sp = plyship; cpushortest = cpulongest; cpulongest = 0; for (d=0 ; d < SHIPTYPES; d++, sp++) { if (sp->hits < sp->length) { cpushortest = (cpushortest < sp->length) ? cpushortest : sp->length; cpulongest = (cpulongest > sp->length) ? cpulongest : sp->length; } } /* Now, if we're in closepack mode, we may have knocked off part of * another ship, in which case we shouldn't do RANDOM_FIRE. A * more robust implementation would probably do this check regardless * of whether closepack was set or not. * Note that MARK_HIT is set only for ships that aren't sunk; * hitship() changes the marker to the ship's character when the * ship is sunk. */ if (closepack) { ts.hits = 0; for (x = 0; x < BWIDTH; x++) for (y = 0; y < BDEPTH; y++) { if (hits[COMPUTER][x][y] == MARK_HIT) { /* So we found part of another ship. It may have more * than one hit on it. Check to see if it does. If no * hit does, take the last MARK_HIT and be RANDOM_HIT. */ ts.x = x; ts.y = y; ts.hits = 1; for (d = 0; d < 8; d += 2) { while ((ONBOARD(ts.x, ts.y)) && (hits[COMPUTER][(int)ts.x][(int)ts.y] == MARK_HIT)) { ts.x += xincr[d]; ts.y += yincr[d]; ts.hits++; } if ((--ts.hits > 1) && (ONBOARD(ts.x, ts.y)) && (hits[COMPUTER][(int)ts.x][(int)ts.y] == 0)) { ts.dir = d; ts.x -= xincr[d]; ts.y -= yincr[d]; d = 100; /* use as a flag */ x = BWIDTH; y = BDEPTH; /* end the loop */ } else { ts.x = x; ts.y = y; ts.hits = 1; } } } if (ts.hits) { next = (d >= 100) ? FIRST_PASS : RANDOM_HIT; } else next = RANDOM_FIRE; } } if (closenoshot) { return(cputurn()); } } /* check for continuation and/or winner */ if (salvo) { (void)refresh(); (void)sleep(1); } return(hit); }