home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_progs
/
libs
/
curses.lzh
/
CURSES
/
EXAMPLES
/
BATTLE
/
BATTLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-15
|
14KB
|
682 lines
/*
* battle.c - original author: Bruce Holloway
* mods by: Chuck A DeGaul
*/
#include <stdio.h>
#include <curses.h>
#include <signal.h>
/* #define BSD 1 /* Define BSD if compiling for BSD Unix */
#ifdef BSD
#define beep() write(1,"\007",1);
#define saveterm savetty
#define resetterm resetty
#endif
#define OTHER 1-turn
/* following #ifdef constants are now unnecessary, use the - options */
/*#define NOBLITZ 0 */ /* Defined if HITs don't mean you get to
continue wiping out your opponent. */
/*#define NOASK 0 */ /* Defined if the computer figures out whether
it hits without bothering yout about it. */
/*#define SEEMISS 0 */ /* Defined if the player sees the computer's
misses. */
char numbers[] = " 0 1 2 3 4 5 6 7 8 9";
char carrier[] = "Aircraft Carrier";
char battle[] = "Battleship";
char sub[] = "Submarine";
char destroy[] = "Destroyer";
char ptboat[] = "PT Boat";
char name[40];
char dftname[] = "Stranger";
struct _ships {
char *name;
char symbol;
char length;
char start; /* Coordinates - 0,0=0; 10,10=100. */
char dir; /* Direction - 0 = right; 1 = down. */
char hits; /* How many times has this ship been hit? (-1==sunk) */
};
struct _ships plyship[] = {
{ carrier,'A',5,0,0,0 },
{ battle,'B',4,0,0,0 },
{ destroy,'D',3,0,0,0 },
{ sub,'S',3,0,0,0 },
{ ptboat,'P',2,0,0,0 },
};
struct _ships cpuship[] = {
{ carrier,'A',5,0,0,0 },
{ battle,'B',4,0,0,0 },
{ destroy,'D',3,0,0,0 },
{ sub,'S',3,0,0,0 },
{ ptboat,'P',2,0,0,0 },
};
char hits[2][100], board[2][100]; /* "Hits" board, and main board. */
int srchstep;
int cpuhits;
int cstart, cdir;
int plywon=0, cpuwon=0; /* How many games has each won? */
int turn; /* 0=player, 1=computer */
int huntoffs; /* Offset on search strategy */
int salvo, blitz, ask, seemiss, do_options(); /* options */
main(argc, argv)
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();
}
#define PR addstr
intro(){
int uninitgame();
#ifndef AMIGA
extern char *getlogin();
#endif
char *tmpname;
srand(time(0L)); /* Kick the random number generator */
signal(SIGINT,uninitgame);
#ifndef AMIGA
if(signal(SIGQUIT,SIG_IGN) != SIG_IGN) signal(SIGQUIT,uninitgame);
#endif
#ifndef AMIGA
if(tmpname = getlogin())
strcpy(name,tmpname);
else
#endif
strcpy(name,dftname);
name[0] = toupper(name[0]);
initscr();
#ifndef AMIGA
saveterm();
#endif
nonl(); cbreak(); noecho();
clear();
mvaddstr(4,29,"Welcome to Battleship!");
move(8,0);
PR(" \\\n");
PR(" \\ \\ \\\n");
PR(" \\ \\ \\ \\ \\_____________\n");
PR(" \\ \\ \\_____________ \\ \\/ |\n");
PR(" \\ \\/ \\ \\/ |\n");
PR(" \\/ \\_____/ |__\n");
PR(" ________________/ |\n");
PR(" \\ S.S. Penguin |\n");
PR(" \\ /\n");
PR(" \\___________________________________________________/\n");
mvaddstr(20,27,"Hit any key to continue..."); refresh();
getch();
}
initgame(){
int i;
clear();
mvaddstr(0,35,"BATTLESHIP");
mvaddstr(4,12,"Main Board");
mvaddstr(6,0,numbers);
move(7,0);
for(i=0; i<10; ++i){
printw("%c . . . . . . . . . . %c\n",i+'A',i+'A');
}
mvaddstr(17,0,numbers);
mvaddstr(4,55,"Hit/Miss Board");
mvaddstr(6,45,numbers);
for(i=0; i<10; ++i){
mvprintw(7+i,45,"%c . . . . . . . . . . %c",i+'A',i+'A');
}
mvaddstr(17,45,numbers);
for(turn=0; turn<2; ++turn)
for(i=0; i<100; ++i){
hits[turn][i] = board[turn][i] = 0;
}
for(turn=0; turn<2; ++turn){
for(i=0; i<5; ++i)
if(!turn) plyplace(&plyship[i]);
else cpuplace(&cpuship[i]);
}
turn = rnd(2);
cstart = cdir = -1;
cpuhits = 0;
srchstep = 3;
huntoffs = rnd(srchstep);
}
rnd(n)
int n;
{
return(((rand() & 0x7FFF) % n));
}
plyplace(ss)
struct _ships *ss;
{
int c, d;
do{
prompt();
printw("Place your %s (ex.%c%d) ? ",ss->name,rnd(10)+'A',rnd(10));
c = getcoord();
d = getdir();
} while(!checkplace(ss,c,d));
placeship(ss,c,d);
}
getdir(){
int d;
prompt(); addstr("What direction (0=right, 1=down) ? ");
return(sgetc("01")-'0');
}
placeship(ss,c,d)
struct _ships *ss;
int c, d;
{
int x, y, l, i;
for(l=0; l<ss->length; ++l){
i = c + l * ((d) ? 10 : 1);
board[turn][i] = ss->symbol;
x = (i % 10) * 3 + 3;
y = (i / 10) + 7;
if(!turn) mvaddch(y,x,ss->symbol);
}
ss->start = c;
ss->dir = d;
ss->hits = 0;
}
checkplace(ss,c,d)
struct _ships *ss;
int c, d;
{
int x, y, l;
x = c%10; y = c/10;
if(((x+ss->length) > 10 && !d) || ((y+ss->length) > 10 && d==1)){
if(!turn)
switch(rnd(3)){
case 0:
error("Ship is hanging from the edge of the world");
break;
case 1:
error("Try fitting it on the board");
break;
case 2:
error("Figure I won't find it if you put it there?");
break;
}
return(0);
}
for(l=0; l<ss->length; ++l){
x = c + l * ((d) ? 10 : 1);
if(board[turn][x]){
if(!turn)
switch(rnd(3)){
case 0:
error("There's already a ship there");
break;
case 1:
error("Collision alert! Aaaaaagh!");
break;
case 2:
error("Er, Admiral, what about the other ship?");
break;
}
return(0);
}
}
return(1);
}
error(s)
char *s;
{
prompt(); beep();
printw("%s -- hit any key to continue --",s);
refresh();
getch();
}
prompt(){
move(22,0); clrtoeol();
}
toupper(ch)
int ch;
{
return((ch >= 'a' && ch <= 'z') ? ch-'a'+'A' : ch);
}
getcoord(){
int ch, x, y, oldx, oldy;
redo:
y = sgetc("ABCDEFGHIJ");
do{
ch = getch();
if(ch == 0x7F || ch == 8){
addstr("\b \b"); refresh();
goto redo;
}
} while(ch < '0' || ch > '9');
addch(x=ch); refresh();
return((y-'A')*10+x-'0');
}
cpuplace(ss)
struct _ships *ss;
{
int c, d;
do{
c = rnd(100); d = rnd(2);
} while(!checkplace(ss,c,d));
placeship(ss,c,d);
}
awinna(){
int i, j;
struct _ships *ss;
for(i=0; i<2; ++i){
ss = (i) ? cpuship : plyship;
for(j=0; j<5; ++j, ++ss)
if(ss->length != ss->hits)
break;
if(j == 5) return(OTHER);
}
return(-1);
}
plyturn(){
int c, res, i;
char *m;
prompt();
addstr("Where do you want to shoot? ");
c = getcoord();
if(!(res = hits[turn][c])){
hits[turn][c] = res = (board[OTHER][c]) ? 'H' : 'M';
mvaddch(7+c/10,48+3*(c%10),(res=='H') ? 'H' : 'o');
if(c = hitship(c)){
prompt();
switch(rnd(3)){
case 0:
m = "You sank my %s!";
break;
case 1:
m = "I have this sinking feeling about my %s....";
break;
case 2:
m = "Have some mercy for my %s!";
break;
}
move(23,0); clrtoeol(); beep();
printw(m,cpuship[c-1].name); refresh();
return(awinna() == -1);
}
}
prompt();
move(23,0); clrtoeol();
printw("You %s.",(res=='M')?"missed":"scored a hit"); refresh();
return(res == 'H');
}
hitship(c)
int c;
{
struct _ships *ss;
int sym, i, j;
ss = (turn) ? plyship : cpuship;
if(!(sym = board[OTHER][c])) return(0);
for(i=0; i<5; ++i, ++ss)
if(ss->symbol == sym){
j = ss->hits; ++j; ss->hits = j;
if(j == ss->length) return(i+1);
return(0);
}
}
cputurn(){
int c, res, x, y, i, d;
redo:
if(cstart == -1){
if(cpuhits){
for(i=0, c=rnd(100); i<100; ++i, c = (c+1) % 100)
if(hits[turn][c] == 'H')
break;
if(i != 100){
cstart = c;
cdir = -1;
goto fndir;
}
}
do{
i = 0;
do{
while(hits[turn][c=rnd(100)]);
x = c % 10; y = c / 10;
if(++i == 1000) break;
} while(((x+huntoffs) % srchstep) != (y % srchstep));
if(i == 1000) --srchstep;
} while(i == 1000);
}
else if(cdir == -1){
fndir: for(i=0, d=rnd(4); i++ < 4; d = (d+1) % 4){
x = cstart%10; y = cstart/10;
switch(d){
case 0: ++x; break;
case 1: ++y; break;
case 2: --x; break;
case 3: --y; break;
}
if(x<0 || x>9 || y<0 || y>9) continue;
if(hits[turn][c=y*10+x]) continue;
cdir = -2;
break;
}
if(i == 4){
cstart = -1;
goto redo;
}
}
else{
x = cstart%10; y = cstart/10;
switch(cdir){
case 0: ++x; break;
case 1: ++y; break;
case 2: --x; break;
case 3: --y; break;
}
if(x<0 || x>9 || y<0 || y>9 || hits[turn][y*10+x]){
cdir = (cdir+2) % 4;
for(;;){
switch(cdir){
case 0: ++x; break;
case 1: ++y; break;
case 2: --x; break;
case 3: --y; break;
}
if(x<0 || x>9 || y<0 || y>9){ cstart = -1; goto redo; }
if(!hits[turn][y*10+x]) break;
}
}
c = y*10 + x;
}
if (!ask) {
res = (board[OTHER][c]) ? 'H' : 'M';
move(21,0); clrtoeol();
printw("I shoot at %c%d. I %s!",c/10+'A',c%10,(res=='H')?"hit":"miss");
} else {
for(;;){
prompt();
printw("I shoot at %c%d. Do I (H)it or (M)iss? ",c/10+'A',c%10);
res = sgetc("HM");
if((res=='H' && !board[OTHER][c]) || (res=='M' && board[OTHER][c])){
error("You lie!");
continue;
}
break;
}
addch(res);
}
hits[turn][c] = res;
if(res == 'H') {
++cpuhits;
if(cstart == -1) cdir = -1;
cstart = c;
if(cdir == -2) cdir = d;
mvaddch(7+(c/10),3+3*(c%10),'*');
if (blitz && !ask) {
refresh();
sleep(1);
}
}
else {
if (seemiss) {
mvaddch(7+(c/10),3+3*(c%10),' ');
} else {
if(cdir == -2) cdir = -1;
}
}
if(c=hitship(c)){
cstart = -1;
cpuhits -= plyship[c-1].length;
x = plyship[c-1].start;
d = plyship[c-1].dir;
y = plyship[c-1].length;
for(i=0; i<y; ++i){
hits[turn][x] = '*';
x += (d) ? 10 : 1;
}
}
if (salvo && !ask) {
refresh();
sleep(1);
}
if(awinna() != -1) return(0);
return(res == 'H');
}
playagain(){
int i, x, y, dx, dy, j;
for(i=0; i<5; ++i){
x = cpuship[i].start; y = x/10+7; x = (x % 10) * 3 + 48;
dx = (cpuship[i].dir) ? 0 : 3;
dy = (cpuship[i].dir) ? 1 : 0;
for(j=0; j < cpuship[i].length; ++j){
mvaddch(y,x,cpuship[i].symbol);
x += dx; y += dy;
}
}
if(awinna()) ++cpuwon; else ++plywon;
i = 18 + strlen(name);
if(plywon >= 10) ++i;
if(cpuwon >= 10) ++i;
mvprintw(2,(80-i)/2,"%s: %d Computer: %d",name,plywon,cpuwon);
prompt();
printw((awinna()) ? "Want to be humiliated again, %s? "
: "Going to give me a chance for revenge, %s? ",name);
return(sgetc("YN") == 'Y');
}
uninitgame(){
refresh();
#ifndef AMIGA
resetterm();
#endif
echo();
endwin();
exit(0);
}
sgetc(s)
char *s;
{
char *s1;
int ch;
refresh();
for(;;){
ch = toupper(getch());
if(ch == 3) uninitgame();
for(s1=s; *s1 && ch != *s1; ++s1);
if(*s1){
addch(ch); refresh();
return(ch);
}
}
}
/*
* I should use getopts() from libc.a, but I'm leary that other UNIX
* systems might not have it, although I'd love to use it.
*/
int
do_options(c,op)
int c;
char *op[];
{
register int i;
if (c > 1) {
for (i=1; i<c; i++) {
switch(op[i][0]) {
default:
case '?':
fprintf(stderr, "Usage: battle [ -s | -b ] [ -a ] [ -m ]\n");
fprintf(stderr, "\tWhere the options are:\n");
fprintf(stderr, "\t-s : play a salvo game (mutex with -b)\n");
fprintf(stderr, "\t-b : play a blitz game (mutex with -s)\n");
fprintf(stderr, "\t-a : computer asks you for hit/miss\n");
fprintf(stderr, "\t-m : computer misses are displayed\n");
exit(1);
break;
case '-':
switch(op[i][1]) {
case 'b':
blitz = 1;
if (salvo == 1) {
fprintf(stderr,
"Bad Arg: -b and -s are mutually exclusive\n");
exit(1);
}
break;
case 's':
salvo = 1;
if (blitz == 1) {
fprintf(stderr,
"Bad Arg: -s and -b are mutually exclusive\n");
exit(1);
}
break;
case 'a':
ask = 1;
break;
case 'm':
seemiss = 1;
break;
default:
fprintf(stderr,
"Bad Arg: type \"%s ?\" for usage message\n", op[0]);
exit(1);
}
}
}
fprintf(stdout, "Playing optional game (");
if (salvo) {
fprintf(stdout, "salvo, noblitz, ");
} else if (blitz) {
fprintf(stdout, "blitz, nosalvo, ");
} else {
fprintf(stdout, "noblitz, nosalvo, ");
}
if (ask) {
fprintf(stdout, "ask, ");
} else {
fprintf(stdout, "noask, ");
}
if (seemiss) {
fprintf(stdout, "seemiss)\n");
} else {
fprintf(stdout, "noseemiss)\n");
}
} else {
fprintf(stdout,
"Playing standard game (noblitz, noslavo, noask, noseemiss)\n");
}
sleep(2);
return(0);
}
int
scount(who)
int who;
{
register int i, shots;
register struct _ships *sp;
if (who) {
/* count cpu shots */
sp = cpuship;
} else {
/* count player shots */
sp = plyship;
}
for (i=0, shots = 0; i<5; i++, sp++) {
/* extra test for machines with unsigned chars! */
if (sp->hits == (char) -1 || sp->hits >= sp->length) {
continue; /* dead ship */
} else {
shots++;
}
}
return(shots);
}
#ifdef AMIGA
sleep(n)
{
Delay(50 * n);
}
#endif