Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84 / QGSI 2.0; site qubix.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!mtuxo!mtunh! mtung!mtunf!ariel!vax135!petsd!pesnta!hplabs!intelca!t12tst!qubix!lab From: l...@qubix.UUCP (Larry Bickford) Newsgroups: net.games Subject: Battleship (version 1) update Message-ID: <1626@qubix.UUCP> Date: Thu, 4-Jul-85 18:08:10 EDT Article-I.D.: qubix.1626 Posted: Thu Jul 4 18:08:10 1985 Date-Received: Sun, 7-Jul-85 05:57:12 EDT Distribution: net Organization: Quadratix ... Quartix Lines: 725 /* battleships by Judah S. Kaminetsky */ /* Vax 4.2bsd improvements by Tom Truscott (rti-sel!trt) */ /* Improvements on Version 1 by Larry Bickford (qubix!lab): /* register efficiency * horizontal expansion (more readable) * catching SIGINT gracefully * exit(0) rather than exit(1) * 4.2bsd correction in flash() * other various fixes * Known bug: when battleship exits, your cursor is left at some * screwball place on the screen. Un-nice. * Note: Judah has introduced Version 2, which could still use some of * the above changes, even on SysV. Someone should blend the two. */ /* qubix!lab: next line is for 4.2 compilation */ /* cc -O -o bs bs.c -lcurses -ltermcap */ #define MAX_X 12 #define MAX_Y 12 #define NO 1 #define YES 0 #include <curses.h> /* rti-sel!trt: hack to support old-fashioned curses */ #ifndef A_REVERSE #define wattron(w, foo) wstandout(w) #define wattroff(w, foo) wstandend(w) #endif long r;/* for random number generator*/ int myscore = 0; int hisscore = 0; int hismoves = 1; int mymoves = 1; int nextx, nexty;/* next square to attack if adjacent to previous hit*/ int lastx, lasty; /* last move made */ /* qubix!lab: SIGINT catcher */ getout() { endwin(); exit(0); } main() { register WINDOW *mywin, /*player's screen*/ *myscrwin, /*players's score window*/ *hisscrwin, /*computers's score window*/ *hidwin, /* computers hidden screen */ *showwin, /*computer's displayed screen*/ *recwin; /*computers record of my screen */ register int t; time(&r);/*Seed the random number generator*/ srand((int)(r&0177777L)); initscr(); nonl(); noecho(); cbreak(); signal(2, getout); err("Battleships System Test - comments to hounx!juda"); mywin = newwin(MAX_Y, MAX_X << 1, 5, 15); recwin = newwin(MAX_Y, MAX_X, 5, 0); werase(mywin); werase(recwin); wattron(mywin,A_REVERSE); label_x(mywin); wrefresh(mywin); label_y(mywin); wrefresh(mywin); wattroff(mywin,A_REVERSE); /* qubix!lab: deemed unnecessary; need for labels later removed wattron(recwin,A_REVERSE); label_x(recwin); label_y(recwin); wattroff(recwin,A_REVERSE); */ set(mywin,'A',5); wrefresh(mywin); set(mywin,'B',4); wrefresh(mywin); set(mywin,'S',3); wrefresh(mywin); set(mywin,'D',3); wrefresh(mywin); set(mywin,'P',2); wrefresh(mywin); clrtop(); hidwin = newwin(MAX_Y, MAX_X, 5, 40); showwin = newwin(MAX_Y, MAX_X << 1, 5, 55); myscrwin = newwin(4, MAX_X+13, 17, 55); hisscrwin = newwin(4, MAX_X+13, 17, 15); werase(hidwin); werase(showwin); /** qubix!lab: deemed unnecessary; need for labels later removed ** wattron(hidwin,A_REVERSE); label_x(hidwin); wrefresh(hidwin); label_y(hidwin); wrefresh(hidwin); wattroff(hidwin,A_REVERSE); /**/ wattron(showwin,A_REVERSE); label_x(showwin); label_y(showwin); wrefresh(showwin); wattroff(showwin,A_REVERSE); setup(hidwin,'A',5); setup(hidwin,'B',4); setup(hidwin,'S',3); setup(hidwin,'D',3); setup(hidwin,'P',2); clrtop(); for(t = (MAX_X-2)*(MAX_Y-2); --t >= 0; ) { myttack(hidwin,showwin); myrecord(myscrwin); if(myscore>16) { msg("YOU WIN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); wrefresh(hidwin); wrefresh(recwin); endwin(); exit(0); } hisattack(mywin,recwin); hisrecord(hisscrwin); if(hisscore>16) { msg("YOU LOSE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); wrefresh(hidwin); wrefresh(recwin); endwin(); exit(0); } } endwin(); } /*************************************************************/ /* Draw x axis labels */ label_x(win) register WINDOW *win; { register int x,y; register int ch; for(y=0;y<MAX_Y;y+=MAX_Y-1) { for(x=1,ch=0;x<MAX_X-1;x++,ch++) { /* qubix!lab: horiz. expand */ wmove(win,y,x << 1); waddch(win,ch+'0'); } } touchwin(win); } /*****************************************************************/ /* Draw y axis labels */ label_y(win) register WINDOW *win; { register int x,y; /* in columns 1 and MAX_X */ for(x=0;x<MAX_X;x+=MAX_X-1) { for(y=0;y<MAX_Y;y++) { /* qubix!lab: horiz. expand */ wmove(win,y,x << 1); waddch(win,y+'/');/*start with char 0*/ } } touchwin(win); } /************************************************************************/ /* Place ship of length len, represented by character ch at coordinates * y, x */ /* direction up, down, right, left from start */ place(win,len,ch,init_y,init_x,dir) register WINDOW *win; register int len; /*length*/ char ch; register int init_y,init_x; register int dir; /*direction*/ { register int i; char c; register int dir_y, dir_x; register int x, y; dir_x=xdir(dir); dir_y=ydir(dir); /* avoid collisions with existing characters*/ for(i=0, x=init_x, y=init_y; i<len; i++, x=x+dir_x, y=y+dir_y) { if(x < 1 || y < 1 || y >= MAX_Y-1) return(1); if(dir > 0) if(x >= MAX_X - 1) return(1); /* qubix!lab: horiz expand */ else if(x >= (MAX_X-1)<<1) return(1); wmove(win,y,x); c=winch(win); if(c!=' ') { return(1); } } /* place characters if no collision */ for(i=0, x=init_x, y=init_y; i<len; i++, x=x+dir_x, y=y+dir_y) { wmove(win,y,x); waddch(win,ch); } return(0); } /*********************************************************************/ /* Determine x direction increment or decrement */ /* neg values are input by user => expand to 2X */ xdir(dir) register int dir; { register int xdir; switch(dir){ case 0 :/*up*/ xdir=0; break; case 1 :/*down*/ case -1 :/*down*/ xdir=0; break; case 2 :/*right*/ xdir=1; break; case -2 :/*right*/ xdir=2; break; case 3 :/*left*/ xdir=(-1); break; case -3 :/*left*/ xdir=(-2); break; default: xdir=1; break; } return(xdir); } /*********************************************************************/ /* Determine y direction increment or decrement */ ydir(dir) register int dir; { register int ydir; switch(dir){ case 0 :/*up*/ ydir=(-1); break; case -1: case 1 :/*down*/ ydir=1; break; case -2: case 2 :/*right*/ ydir=0; break; case -3: case 3 :/*left*/ ydir=0; break; default: ydir=0; break; } return(ydir); } /***********************************************************************/ /* generate random number between 0 and high (arg1), retrun random number */ random(high) register int high; { /* qubix!lab: without right-shift, and high = 10, was returning * values ending alternately 00 or 10 (binary). Un-random. */ return( ((rand() >> 2) % high) +1); } /********************************************************************/ /* place ship for computer*/ setup(win,ship,length) register WINDOW *win; char ship; register int length; { register int y , x; register int dir; for(;;) { msg("The computer is now placing its ships in a random manner"); x=random(MAX_X-2); y=random(MAX_X-2); dir=random(3); if(place(win,length,ship,y,x,dir)!=1) { return(0); } } } /********************************************************************/ /* get x coordinate from user*/ get_x() { register WINDOW *xwin; register int i, c; char ch; xwin = newwin(1, COLS, 1, 0);/*line 1*/ werase(xwin); wprintw(xwin,"Enter x (horizontal) coordinate [0-9] (q to exit):\t"); touchwin(stdscr); wrefresh(xwin); c=getch(); out(c); waddch(xwin,c); touchwin(stdscr); wrefresh(xwin); return(c-'0'+1); } /********************************************************************/ /* get y coordinate from user*/ get_y() { register WINDOW *ywin; register int i, c; char ch; ywin = newwin(1, COLS, 2, 0);/*line 2*/ werase(ywin); wprintw(ywin,"Enter y (vertical) coordinate [0-9] (q to exit):\t"); touchwin(stdscr); wrefresh(ywin); c=getch(); out(c); waddch(ywin,c); touchwin(stdscr); wrefresh(ywin); return(c-'0'+1); } /*********************************************************************/ /* get dir from user*/ get_dir() { register WINDOW *dirwin; register int i, c; char ch; dirwin = newwin(1, COLS, 3, 0);/*line 3*/ werase(dirwin); wprintw(dirwin, "Enter Direction, 0 is up, 1 is down, 2 is right, 3 is left: (q to exit)"); touchwin(stdscr); wrefresh(dirwin); c=getch(); out(c); waddch(dirwin,c); touchwin(stdscr); wrefresh(dirwin); /* get the NEGATIVE value */ return(c-'0'); } /*********************************************************************/ /* place ship for player*/ set(win,ship,length) register WINDOW *win; char ship; register int length; { register int y , x; register int dir; char msg_str[80]; for(;;) { sprintf(msg_str, "PLACE SHIP %c, length %d avoiding collisions",ship,length); msg(msg_str); if(verify(x = get_x(), 0, MAX_X-2)==1) { continue; } if(verify(y = get_y(), 0, MAX_Y-2)==1) { continue; } if(verify( dir = get_dir(), 0, 3) == 1) { continue; } /* qubix!lab: horiz expand; also note negative */ if(place(win, length, ship, y, x<<1, -dir) != 1) { touchwin(win); return(0); } } } /***********************************************************************/ msg(str) register char *str; { register WINDOW *msgwin; msgwin = newwin(1, COLS, 0,0); werase(msgwin); wattron(msgwin, A_REVERSE); wprintw(msgwin, "%s", str); touchwin(stdscr); wrefresh(msgwin); return(0); } /***********************************************************************/ verify(c,low,high) register int c; register int low; register int high; { char msgstr[80]; if(c < low || c > high) { sprintf(msgstr,"%c is out of legal range %c to %c",c,low,high); return(1); } else { return(0); } } /*********************************************************************/ /*player attack computer - goes to attack coordinates on hidwin*/ /*and copies ch (+attributes?) to showwin - touchwin and refresh showwin*/ /* allows duplicate moves but does not score duplicaate hits*/ myttack(hidwin,showwin) register WINDOW *hidwin, *showwin; { register int y , x; register int hit; char c; char d; char msg_str[80]; msg("ATTACK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); while(verify(x=get_x(),0,MAX_X-2)==1) { } while(verify(y=get_y(),0,MAX_Y-2)==1) { } wmove(hidwin,y,x); c=winch(hidwin); if(c!=' ' && c != '.') { hit=YES; } wmove(showwin,y,x << 1); d=winch(showwin); if(hit == YES && (d==' ' || d=='.')) /* first hit - not repeat */ { flash(); myscore++; } wattron(showwin,A_REVERSE); /* qubix!lab: record where I've been */ if(c == ' ') c = '.'; waddch(showwin,c); touchwin(showwin); wrefresh(showwin); lastx = x; lasty = y; } /***************************************************************************/ /* clear top of screen */ clrtop() { register WINDOW *topwin; register int i, c; char ch; topwin = newwin(5, COLS, 0, 0);/*top 5 lines*/ werase(topwin); touchwin(topwin); wrefresh(topwin); } /*********************************************************************/ /*computer attack player - goes to attack coordinates on recwin*/ /* checks recwin - blank means haven't attacked here yet */ /* if so go to coord on mywin - attack & record result on recwin */ hisattack(mywin,recwin) register WINDOW *mywin; register WINDOW *recwin; { register int y , x; char c; char mark='+'; clrtop(); for(;;) { if(nextshot(recwin)==YES) { x=nextx; y=nexty; } else /* if(nextshot(recwin)==NO) */ { x=random(MAX_X-2); y=random(MAX_Y-2); } lastx = x; lasty = y; wmove(recwin,y,x);/*check for repeat move*/ c=winch(recwin); if(c!=' ')/*repeat move */ { continue; } else { /* qubix!lab: horiz expand */ wmove(mywin,y,x << 1); c=winch(mywin); if(c!=' ')/*hit*/ { flash(); mark=c;/*mark recwin with ship character*/ hisscore++; } else c = '.'; wattron(mywin,A_REVERSE); waddch(mywin,c); touchwin(mywin); wrefresh(mywin); waddch(recwin,mark); /*mark square as tried already and result + for blank or char for ship */ touchwin(recwin); return(YES); } } return(NO); } /***********************************************************************/ err(str) register char *str; { register WINDOW *errwin; /* rti-sel!trt: fix for window manager */ errwin=newwin(1,COLS,LINES-1,0); if (errwin == NULL) { fprintf(stderr, "cannot create error window\n"); return; } werase(errwin); wattron(errwin,A_REVERSE); wprintw(errwin,"%s",str); touchwin(stdscr); wrefresh(errwin); return(0); } /***********************************************************************/ out(c) char c; { if(c=='q') { endwin(); exit(1); } } /*********************************************************************/ myrecord(win) register WINDOW *win; { werase(win); wprintw(win, "Try %d,%d: ",lastx-1,lasty-1); wprintw(win,"hit %d ",myscore); wprintw(win,"move %d\n",mymoves++); touchwin(win); wrefresh(win); } /*********************************************************************/ hisrecord(win) register WINDOW *win; { werase(win); wprintw(win, "Try %d,%d: ",lastx-1,lasty-1); wprintw(win,"hit %d ",hisscore); wprintw(win,"move %d\n",hismoves++); touchwin(win); wrefresh(win); } /************************************************************************/ /* check win for previous hit and choose next guess at adjacent square */ nextshot(win) register WINDOW *win; { register int y; register int x; register int ax; register int by; char c; for(by = 1; by < MAX_Y-1; by++) { for(ax = 1;ax < MAX_X-1; ax++) { wmove(win,by,ax); c=winch(win); if(c!=' '&&c!='+') /* space was hit previously */ { /* eliminate need for hidden labels */ y=by; /*right*/ if((x=ax+1) < MAX_X-1 && check(win,y,x)==YES ) { return(YES); } /*left*/ if((x=ax-1) > 0 && check(win,y,x)==YES ) { return(YES); } x=ax; /*1 square down */ if((y=by+1) < MAX_Y - 1 && check(win,y,x)==YES ) { return(YES); } x=ax; /*up*/ if((y=by-1) > 0 && check(win,y,x)==YES ) { return(YES); } } } } return(NO);/* no untried squares adjacent to hits */ } /*******************************************************************/ /* check y,x on win, return YES if blank - not shot at yet return NO if not blank */ check(win,y,x) register WINDOW *win; register int y; register int x; { char c; wmove(win,y,x); c=winch(win); if(c==' ') /* adjacent to previous hit & blank */ { nextx=x; nexty=y; return(YES); } else { return(NO); } } #ifndef A_REVERSE /* need to define some other routines */ cbreak() { crmode(); } flash() { extern int _putchar(); /* qubix!lab: no ';' because of ways curses.h defines it! */ if (VB) _puts(VB) else putchar('\07'); } #endif -- The Ice Floe of Larry Bickford {amd,decwrl,sun,idi,ittvax}!qubix!lab You can't settle the issue until you've settled how to settle the issue.