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 >
C/C++ Source or Header  |  1991-08-15  |  14KB  |  682 lines

  1. /* 
  2.  * battle.c - original author: Bruce Holloway
  3.  *        mods by: Chuck A DeGaul
  4.  */
  5. #include <stdio.h>
  6. #include <curses.h>
  7. #include <signal.h>
  8.  
  9. /* #define    BSD    1    /* Define BSD if compiling for BSD Unix */
  10.  
  11. #ifdef BSD
  12. #define    beep()    write(1,"\007",1);
  13. #define    saveterm savetty
  14. #define    resetterm resetty
  15. #endif
  16.  
  17. #define    OTHER    1-turn
  18.  
  19. /* following #ifdef constants are now unnecessary, use the - options */
  20. /*#define    NOBLITZ    0 */    /* Defined if HITs don't mean you get to 
  21.                    continue wiping out your opponent. */
  22. /*#define    NOASK    0 */    /* Defined if the computer figures out whether
  23.                    it hits without bothering yout about it. */
  24. /*#define    SEEMISS    0 */    /* Defined if the player sees the computer's
  25.                    misses. */
  26.  
  27. char numbers[] = "   0  1  2  3  4  5  6  7  8  9";
  28.  
  29. char carrier[] = "Aircraft Carrier";
  30. char battle[] = "Battleship";
  31. char sub[] = "Submarine";
  32. char destroy[] = "Destroyer";
  33. char ptboat[] = "PT Boat";
  34.  
  35. char name[40];
  36. char dftname[] = "Stranger";
  37.  
  38. struct _ships {
  39.     char *name;
  40.     char symbol;
  41.     char length;
  42.     char start;        /* Coordinates - 0,0=0; 10,10=100. */
  43.     char dir;        /* Direction - 0 = right; 1 = down. */
  44.     char hits;        /* How many times has this ship been hit? (-1==sunk) */
  45.     };
  46.  
  47. struct _ships plyship[] = {
  48.     { carrier,'A',5,0,0,0 },
  49.     { battle,'B',4,0,0,0 },
  50.     { destroy,'D',3,0,0,0 },
  51.     { sub,'S',3,0,0,0 },
  52.     { ptboat,'P',2,0,0,0 },
  53. };
  54.  
  55. struct _ships cpuship[] = {
  56.     { carrier,'A',5,0,0,0 },
  57.     { battle,'B',4,0,0,0 },
  58.     { destroy,'D',3,0,0,0 },
  59.     { sub,'S',3,0,0,0 },
  60.     { ptboat,'P',2,0,0,0 },
  61. };
  62.  
  63. char hits[2][100], board[2][100];    /* "Hits" board, and main board. */
  64.  
  65. int srchstep;
  66. int cpuhits;
  67. int cstart, cdir;
  68. int plywon=0, cpuwon=0;            /* How many games has each won? */
  69. int turn;                /* 0=player, 1=computer */
  70. int huntoffs;                /* Offset on search strategy */
  71.  
  72. int salvo, blitz, ask, seemiss, do_options();        /* options */
  73.  
  74. main(argc, argv)
  75.     int argc;
  76.     char *argv[];
  77. {
  78.     do_options(argc, argv);
  79.  
  80.     intro();
  81.     do {
  82.     initgame();
  83.     while(awinna() == -1) {
  84.         if (!blitz) {
  85.         if (!salvo) {
  86.                 if(turn) cputurn(); else plyturn();
  87.         } else {
  88.              register int i;
  89.  
  90.              i = scount(turn);
  91.              while (i--) {
  92.              if (turn) {
  93.                  if (cputurn()) {
  94.                  if (awinna() != -1) {
  95.                      i = 0;
  96.                  }
  97.                  }
  98.              } else {
  99.                  if(plyturn()) {
  100.                  if (awinna() != -1) {
  101.                      i = 0;
  102.                  }
  103.                  }
  104.              }
  105.              }
  106.          } 
  107.         } else {
  108.             while((turn) ? cputurn() : plyturn());
  109.         }
  110.         turn = OTHER;
  111.     }
  112.     } while(playagain());
  113.     uninitgame();
  114. }
  115.  
  116. #define    PR    addstr
  117.  
  118. intro(){
  119.     int uninitgame();
  120. #ifndef AMIGA
  121.     extern char *getlogin();
  122. #endif
  123.     char *tmpname;
  124.  
  125.     srand(time(0L));            /* Kick the random number generator */
  126.  
  127.     signal(SIGINT,uninitgame);
  128. #ifndef AMIGA
  129.     if(signal(SIGQUIT,SIG_IGN) != SIG_IGN) signal(SIGQUIT,uninitgame);
  130. #endif
  131.  
  132. #ifndef AMIGA
  133.     if(tmpname = getlogin())
  134.     strcpy(name,tmpname);
  135.     else
  136. #endif
  137.     strcpy(name,dftname);
  138.     name[0] = toupper(name[0]);
  139.  
  140.     initscr();
  141. #ifndef AMIGA
  142.     saveterm();
  143. #endif
  144.     nonl(); cbreak(); noecho();
  145.     clear();
  146.     mvaddstr(4,29,"Welcome to Battleship!");
  147.     move(8,0);
  148. PR("                                                  \\\n");
  149. PR("                           \\                     \\ \\\n");
  150. PR("                          \\ \\                   \\ \\ \\_____________\n");
  151. PR("                         \\ \\ \\_____________      \\ \\/            |\n");
  152. PR("                          \\ \\/             \\      \\/             |\n");
  153. PR("                           \\/               \\_____/              |__\n");
  154. PR("           ________________/                                       |\n");
  155. PR("           \\  S.S. Penguin                                         |\n");
  156. PR("            \\                                                     /\n");
  157. PR("             \\___________________________________________________/\n");
  158.     mvaddstr(20,27,"Hit any key to continue..."); refresh();
  159.     getch();
  160. }
  161.  
  162. initgame(){
  163.     int i;
  164.  
  165.     clear();
  166.     mvaddstr(0,35,"BATTLESHIP");
  167.     mvaddstr(4,12,"Main Board");
  168.     mvaddstr(6,0,numbers);
  169.     move(7,0);
  170.     for(i=0; i<10; ++i){
  171.     printw("%c  .  .  .  .  .  .  .  .  .  .  %c\n",i+'A',i+'A');
  172.     }
  173.     mvaddstr(17,0,numbers);
  174.     mvaddstr(4,55,"Hit/Miss Board");
  175.     mvaddstr(6,45,numbers);
  176.     for(i=0; i<10; ++i){
  177.     mvprintw(7+i,45,"%c  .  .  .  .  .  .  .  .  .  .  %c",i+'A',i+'A');
  178.     }
  179.     mvaddstr(17,45,numbers);
  180.     for(turn=0; turn<2; ++turn)
  181.     for(i=0; i<100; ++i){
  182.         hits[turn][i] = board[turn][i] = 0;
  183.         }
  184.     for(turn=0; turn<2; ++turn){
  185.     for(i=0; i<5; ++i)
  186.         if(!turn) plyplace(&plyship[i]);
  187.         else cpuplace(&cpuship[i]);
  188.     }
  189.     turn = rnd(2);
  190.     cstart = cdir = -1;
  191.     cpuhits = 0;
  192.     srchstep = 3;
  193.     huntoffs = rnd(srchstep);
  194. }
  195.  
  196. rnd(n)
  197. int n;
  198. {
  199.     return(((rand() & 0x7FFF) % n));
  200. }
  201.  
  202. plyplace(ss)
  203. struct _ships *ss;
  204. {
  205.     int c, d;
  206.  
  207.     do{
  208.     prompt();
  209.     printw("Place your %s (ex.%c%d) ? ",ss->name,rnd(10)+'A',rnd(10));
  210.     c = getcoord();
  211.     d = getdir();
  212.     } while(!checkplace(ss,c,d));
  213.     placeship(ss,c,d);
  214. }
  215.  
  216. getdir(){
  217.     int d;
  218.  
  219.     prompt(); addstr("What direction (0=right, 1=down) ? ");
  220.     return(sgetc("01")-'0');
  221. }
  222.  
  223. placeship(ss,c,d)
  224. struct _ships *ss;
  225. int c, d;
  226. {
  227.     int x, y, l, i;
  228.  
  229.     for(l=0; l<ss->length; ++l){
  230.     i = c + l * ((d) ? 10 : 1);
  231.     board[turn][i] = ss->symbol;
  232.     x = (i % 10) * 3 + 3;
  233.     y = (i / 10) + 7;
  234.     if(!turn) mvaddch(y,x,ss->symbol);
  235.     }
  236.     ss->start = c;
  237.     ss->dir = d;
  238.     ss->hits = 0;
  239. }
  240.  
  241. checkplace(ss,c,d)
  242. struct _ships *ss;
  243. int c, d;
  244. {
  245.     int x, y, l;
  246.  
  247.     x = c%10; y = c/10;
  248.     if(((x+ss->length) > 10 && !d) || ((y+ss->length) > 10 && d==1)){
  249.     if(!turn)
  250.         switch(rnd(3)){
  251.         case 0:
  252.             error("Ship is hanging from the edge of the world");
  253.             break;
  254.         case 1:
  255.             error("Try fitting it on the board");
  256.             break;
  257.         case 2:
  258.             error("Figure I won't find it if you put it there?");
  259.             break;
  260.         }
  261.     return(0);
  262.     }
  263.     for(l=0; l<ss->length; ++l){
  264.     x = c + l * ((d) ? 10 : 1);
  265.     if(board[turn][x]){
  266.         if(!turn)
  267.         switch(rnd(3)){
  268.             case 0:
  269.             error("There's already a ship there");
  270.             break;
  271.             case 1:
  272.             error("Collision alert! Aaaaaagh!");
  273.             break;
  274.             case 2:
  275.             error("Er, Admiral, what about the other ship?");
  276.             break;
  277.             }
  278.         return(0);
  279.         }
  280.     }
  281.     return(1);
  282. }
  283.  
  284. error(s)
  285. char *s;
  286. {
  287.     prompt(); beep();
  288.     printw("%s -- hit any key to continue --",s);
  289.     refresh();
  290.     getch();
  291. }
  292.  
  293. prompt(){
  294.     move(22,0); clrtoeol();
  295. }
  296.  
  297. toupper(ch)
  298. int ch;
  299. {
  300.     return((ch >= 'a' && ch <= 'z') ? ch-'a'+'A' : ch);
  301. }
  302.  
  303. getcoord(){
  304.     int ch, x, y, oldx, oldy;
  305.  
  306. redo:
  307.     y = sgetc("ABCDEFGHIJ");
  308.     do{
  309.     ch = getch();
  310.     if(ch == 0x7F || ch == 8){
  311.         addstr("\b \b"); refresh();
  312.         goto redo;
  313.         }
  314.     } while(ch < '0' || ch > '9');
  315.     addch(x=ch); refresh();
  316.     return((y-'A')*10+x-'0');
  317. }
  318.  
  319. cpuplace(ss)
  320. struct _ships *ss;
  321. {
  322.     int c, d;
  323.  
  324.     do{
  325.     c = rnd(100); d = rnd(2);
  326.     } while(!checkplace(ss,c,d));
  327.     placeship(ss,c,d);
  328. }
  329.  
  330. awinna(){
  331.     int i, j;
  332.     struct _ships *ss;
  333.  
  334.     for(i=0; i<2; ++i){
  335.     ss = (i) ? cpuship : plyship;
  336.     for(j=0; j<5; ++j, ++ss)
  337.         if(ss->length != ss->hits)
  338.         break;
  339.     if(j == 5) return(OTHER);
  340.     }
  341.     return(-1);
  342. }
  343.  
  344. plyturn(){
  345.     int c, res, i;
  346.     char *m;
  347.  
  348.     prompt();
  349.     addstr("Where do you want to shoot? ");
  350.     c = getcoord();
  351.     if(!(res = hits[turn][c])){
  352.     hits[turn][c] = res = (board[OTHER][c]) ? 'H' : 'M';
  353.     mvaddch(7+c/10,48+3*(c%10),(res=='H') ? 'H' : 'o');
  354.     if(c = hitship(c)){
  355.         prompt();
  356.         switch(rnd(3)){
  357.         case 0:
  358.             m = "You sank my %s!";
  359.             break;
  360.         case 1:
  361.             m = "I have this sinking feeling about my %s....";
  362.             break;
  363.         case 2:
  364.             m = "Have some mercy for my %s!";
  365.             break;
  366.         }
  367.         move(23,0); clrtoeol(); beep();
  368.         printw(m,cpuship[c-1].name); refresh();
  369.         return(awinna() == -1);
  370.         }
  371.     }
  372.     prompt();
  373.     move(23,0); clrtoeol();
  374.     printw("You %s.",(res=='M')?"missed":"scored a hit"); refresh();
  375.     return(res == 'H');
  376. }
  377.  
  378. hitship(c)
  379. int c;
  380. {
  381.     struct _ships *ss;
  382.     int sym, i, j;
  383.  
  384.     ss = (turn) ? plyship : cpuship;
  385.     if(!(sym = board[OTHER][c])) return(0);
  386.     for(i=0; i<5; ++i, ++ss)
  387.     if(ss->symbol == sym){
  388.         j = ss->hits; ++j; ss->hits = j;
  389.         if(j == ss->length) return(i+1);
  390.         return(0);
  391.         }
  392. }
  393.  
  394. cputurn(){
  395.     int c, res, x, y, i, d;
  396.  
  397. redo:
  398.     if(cstart == -1){
  399.     if(cpuhits){
  400.         for(i=0, c=rnd(100); i<100; ++i, c = (c+1) % 100)
  401.         if(hits[turn][c] == 'H')
  402.             break;
  403.         if(i != 100){
  404.         cstart = c;
  405.         cdir = -1;
  406.         goto fndir;
  407.         }
  408.         }
  409.     do{
  410.         i = 0;
  411.         do{
  412.         while(hits[turn][c=rnd(100)]);
  413.         x = c % 10; y = c / 10;
  414.         if(++i == 1000) break;
  415.         } while(((x+huntoffs) % srchstep) != (y % srchstep));
  416.         if(i == 1000) --srchstep;
  417.         } while(i == 1000);
  418.     }
  419.     else if(cdir == -1){
  420. fndir:    for(i=0, d=rnd(4); i++ < 4; d = (d+1) % 4){
  421.         x = cstart%10; y = cstart/10;
  422.         switch(d){
  423.         case 0: ++x; break;
  424.         case 1: ++y; break;
  425.         case 2: --x; break;
  426.         case 3: --y; break;
  427.         }
  428.         if(x<0 || x>9 || y<0 || y>9) continue;
  429.         if(hits[turn][c=y*10+x]) continue;
  430.         cdir = -2;
  431.         break;
  432.         }
  433.     if(i == 4){
  434.         cstart = -1;
  435.         goto redo;
  436.         }
  437.     }
  438.     else{
  439.     x = cstart%10; y = cstart/10;
  440.     switch(cdir){
  441.         case 0: ++x; break;
  442.         case 1: ++y; break;
  443.         case 2: --x; break;
  444.         case 3: --y; break;
  445.         }
  446.     if(x<0 || x>9 || y<0 || y>9 || hits[turn][y*10+x]){
  447.         cdir = (cdir+2) % 4;
  448.         for(;;){
  449.         switch(cdir){
  450.             case 0: ++x; break;
  451.             case 1: ++y; break;
  452.             case 2: --x; break;
  453.             case 3: --y; break;
  454.             }
  455.         if(x<0 || x>9 || y<0 || y>9){ cstart = -1; goto redo; }
  456.         if(!hits[turn][y*10+x]) break;
  457.         }
  458.         }
  459.     c = y*10 + x;
  460.     }
  461.  
  462.     if (!ask) {
  463.         res = (board[OTHER][c]) ? 'H' : 'M';
  464.         move(21,0); clrtoeol();
  465.         printw("I shoot at %c%d. I %s!",c/10+'A',c%10,(res=='H')?"hit":"miss");
  466.     } else {
  467.         for(;;){
  468.         prompt();
  469.         printw("I shoot at %c%d. Do I (H)it or (M)iss? ",c/10+'A',c%10);
  470.         res = sgetc("HM");
  471.         if((res=='H' && !board[OTHER][c]) || (res=='M' && board[OTHER][c])){
  472.             error("You lie!");
  473.             continue;
  474.             }
  475.         break;
  476.         }
  477.         addch(res);
  478.     }
  479.     hits[turn][c] = res;
  480.     if(res == 'H') {
  481.     ++cpuhits;
  482.     if(cstart == -1) cdir = -1;
  483.     cstart = c;
  484.     if(cdir == -2) cdir = d;
  485.     mvaddch(7+(c/10),3+3*(c%10),'*');
  486.     if (blitz && !ask) {
  487.         refresh();
  488.         sleep(1);
  489.     }
  490.     }
  491.     else { 
  492.     if (seemiss) {
  493.         mvaddch(7+(c/10),3+3*(c%10),' ');
  494.     } else {
  495.         if(cdir == -2) cdir = -1;
  496.     }
  497.     }
  498.     if(c=hitship(c)){
  499.     cstart = -1;
  500.     cpuhits -= plyship[c-1].length;
  501.     x = plyship[c-1].start;
  502.     d = plyship[c-1].dir;
  503.     y = plyship[c-1].length;
  504.     for(i=0; i<y; ++i){
  505.         hits[turn][x] = '*';
  506.         x += (d) ? 10 : 1;
  507.         }
  508.     }
  509.     if (salvo && !ask) {
  510.     refresh();
  511.     sleep(1);
  512.     }
  513.     if(awinna() != -1) return(0);
  514.     return(res == 'H');
  515. }
  516.  
  517. playagain(){
  518.     int i, x, y, dx, dy, j;
  519.  
  520.     for(i=0; i<5; ++i){
  521.     x = cpuship[i].start; y = x/10+7; x = (x % 10) * 3 + 48;
  522.     dx = (cpuship[i].dir) ? 0 : 3;
  523.     dy = (cpuship[i].dir) ? 1 : 0;
  524.     for(j=0; j < cpuship[i].length; ++j){
  525.         mvaddch(y,x,cpuship[i].symbol);
  526.         x += dx; y += dy;
  527.         }
  528.     }
  529.  
  530.     if(awinna()) ++cpuwon; else ++plywon;
  531.     i = 18 + strlen(name);
  532.     if(plywon >= 10) ++i;
  533.     if(cpuwon >= 10) ++i;
  534.     mvprintw(2,(80-i)/2,"%s: %d     Computer: %d",name,plywon,cpuwon);
  535.  
  536.     prompt();
  537.     printw((awinna()) ? "Want to be humiliated again, %s? "
  538.           : "Going to give me a chance for revenge, %s? ",name);
  539.     return(sgetc("YN") == 'Y');
  540. }
  541.  
  542. uninitgame(){
  543.     refresh();
  544. #ifndef AMIGA
  545.     resetterm();
  546. #endif
  547.     echo();
  548.     endwin();
  549.     exit(0);
  550. }
  551.  
  552. sgetc(s)
  553. char *s;
  554. {
  555.     char *s1;
  556.     int ch;
  557.  
  558.     refresh();
  559.     for(;;){
  560.     ch = toupper(getch());
  561.     if(ch == 3) uninitgame();
  562.     for(s1=s; *s1 && ch != *s1; ++s1);
  563.     if(*s1){
  564.         addch(ch); refresh();
  565.         return(ch);
  566.         }
  567.     }
  568. }
  569.  
  570. /* 
  571.  * I should use getopts() from libc.a, but I'm leary that other UNIX
  572.  * systems might not have it, although I'd love to use it.
  573.  */
  574. int
  575. do_options(c,op)
  576.     int c;
  577.     char *op[];
  578. {
  579.     register int i;
  580.  
  581.     if (c > 1) {
  582.     for (i=1; i<c; i++) {
  583.         switch(op[i][0]) {
  584.         default:
  585.         case '?':
  586.         fprintf(stderr, "Usage: battle [ -s | -b ] [ -a ] [ -m ]\n");
  587.         fprintf(stderr, "\tWhere the options are:\n");
  588.         fprintf(stderr, "\t-s : play a salvo game (mutex with -b)\n");
  589.         fprintf(stderr, "\t-b : play a blitz game (mutex with -s)\n");
  590.         fprintf(stderr, "\t-a : computer asks you for hit/miss\n");
  591.         fprintf(stderr, "\t-m : computer misses are displayed\n");
  592.         exit(1);
  593.         break;
  594.         case '-':
  595.         switch(op[i][1]) {
  596.         case 'b':
  597.             blitz = 1;
  598.             if (salvo == 1) {
  599.             fprintf(stderr,
  600.                 "Bad Arg: -b and -s are mutually exclusive\n");
  601.             exit(1);
  602.             }
  603.             break;
  604.         case 's':
  605.             salvo = 1;
  606.             if (blitz == 1) {
  607.             fprintf(stderr,
  608.                 "Bad Arg: -s and -b are mutually exclusive\n");
  609.             exit(1);
  610.             }
  611.             break;
  612.         case 'a':
  613.             ask = 1;
  614.             break;
  615.         case 'm':
  616.             seemiss = 1;
  617.             break;
  618.         default:
  619.             fprintf(stderr,
  620.             "Bad Arg: type \"%s ?\" for usage message\n", op[0]);
  621.             exit(1);
  622.         }
  623.         }
  624.     }
  625.     fprintf(stdout, "Playing optional game (");
  626.     if (salvo) {
  627.         fprintf(stdout, "salvo, noblitz, ");
  628.     } else if (blitz) {
  629.         fprintf(stdout, "blitz, nosalvo, ");
  630.     } else {
  631.         fprintf(stdout, "noblitz, nosalvo, ");
  632.     }
  633.     if (ask) {
  634.         fprintf(stdout, "ask, ");
  635.     } else {
  636.         fprintf(stdout, "noask, ");
  637.     }
  638.     if (seemiss) {
  639.         fprintf(stdout, "seemiss)\n");
  640.     } else {
  641.         fprintf(stdout, "noseemiss)\n");
  642.     }
  643.     } else {
  644.     fprintf(stdout,
  645.         "Playing standard game (noblitz, noslavo, noask, noseemiss)\n");
  646.     }
  647.     sleep(2);
  648.     return(0);
  649. }
  650.  
  651. int
  652. scount(who)
  653.     int who;
  654. {
  655.     register int i, shots;
  656.     register struct _ships *sp;
  657.  
  658.     if (who) {
  659.     /* count cpu shots */
  660.     sp = cpuship;
  661.     } else {
  662.     /* count player shots */
  663.     sp = plyship;
  664.     }
  665.     for (i=0, shots = 0; i<5; i++, sp++) {
  666.     /* extra test for machines with unsigned chars! */
  667.     if (sp->hits == (char) -1 || sp->hits >= sp->length) {
  668.         continue;    /* dead ship */
  669.     } else {
  670.         shots++;
  671.     }
  672.     }
  673.     return(shots);
  674. }
  675.  
  676. #ifdef AMIGA
  677. sleep(n)
  678. {
  679.     Delay(50 * n);
  680. }
  681. #endif
  682.