diff options
Diffstat (limited to 'lib/libncurses/TESTS/battle.c')
-rw-r--r-- | lib/libncurses/TESTS/battle.c | 705 |
1 files changed, 705 insertions, 0 deletions
diff --git a/lib/libncurses/TESTS/battle.c b/lib/libncurses/TESTS/battle.c new file mode 100644 index 0000000..e7785fc --- /dev/null +++ b/lib/libncurses/TESTS/battle.c @@ -0,0 +1,705 @@ +/* + * battle.c - original author: Bruce Holloway + * mods by: Chuck A DeGaul + */ + +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <time.h> +#include <signal.h> +#include <ncurses.h> + +#define OTHER 1-turn + +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; /* options */ + +void intro(void); +void initgame(void); +int rnd(int); +void plyplace(struct _ships *); +int getdir(void); +void placeship(struct _ships *, int, int); +int checkplace(struct _ships *, int, int); +void error(char *); +void prompt(void); +char getcoord(void); +void cpuplace(struct _ships *); +int awinna(void); +int plyturn(void); +int hitship(int); +int cputurn(void); +int playagain(void); +void uninitgame(); +int sgetc(char *); +int do_options(int, char *[]); +int scount(int); + +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); +} + +#define PR addstr + +void +intro() +{ +char *tmpname; + + srand(time(0L)); /* Kick the random number generator */ + + signal(SIGINT,uninitgame); + if(signal(SIGQUIT,SIG_IGN) != SIG_IGN) signal(SIGQUIT,uninitgame); +#if 1 + /* for some bizzare reason, getlogin or cuserid cause havoc with the terminal */ + if ((tmpname = getlogin()) != NULL) { + strcpy(name, tmpname); + } else +#endif + strcpy(name,dftname); + name[0] = toupper(name[0]); + + initscr(); + savetty(); + 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(); +} + +void +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); +} + +int +rnd(int n) +{ + return(((rand() & 0x7FFF) % n)); +} + +void +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); +} + +int +getdir() +{ + + prompt(); + addstr("What direction (0=right, 1=down) ? "); + return(sgetc("01")-'0'); +} + +void +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; +} + +int +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); +} + +void +error(s) +char *s; +{ + prompt(); + beep(); + printw("%s -- hit any key to continue --",s); + refresh(); + getch(); +} + +void +prompt(){ + move(22,0); + clrtoeol(); +} + +char +getcoord() +{ +int ch, x, y; + +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'); +} + +void +cpuplace(ss) +struct _ships *ss; +{ +int c, d; + + do{ + c = rnd(100); + d = rnd(2); + } while(!checkplace(ss,c,d)); + placeship(ss,c,d); +} + +int +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); +} + +int +plyturn() +{ +int c, res; +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'); +} + +int +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); + } +} + +int +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'); +} + +int +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'); +} + +void +uninitgame(int sig) +{ + refresh(); + endwin(); + exit(0); +} + +int +sgetc(s) +char *s; +{ +char *s1; +int ch; + + refresh(); + for (;;) { + ch = toupper(getch()); + 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 (no blitz, no slavo, no ask, no seemiss)\n"); + sleep(2); + return(0); +} + +int +scount(who) +int who; +{ +int i, shots; +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); +} + |