1 /*************************************************************************
2 * binp.c --- The First Module of Vince Weaver's SEA BATTLE program *
3 * For ENEE114. Finished 15 April 1997 *
4 ************************************************************************/
5
6 #include <stdio.h>
7 #include <ncurses.h> /* Slang support is good for rxvt in linux */
8
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12
13 #include "batt.h" /* Include prototypes */
14
15 /* INIT CURSES -- inits curses */
16 /* library */
17
seabattle_init_curses(void)18 void seabattle_init_curses(void) {
19
20 initscr();
21 start_color();
22
23 /* Allocate the colors we'll use */
24 init_pair(1,COLOR_BLUE,COLOR_BLACK);
25 init_pair(2,COLOR_GREEN,COLOR_BLACK);
26 init_pair(3,COLOR_CYAN,COLOR_BLACK);
27 init_pair(4,COLOR_RED,COLOR_BLACK);
28 init_pair(6,COLOR_YELLOW,COLOR_BLACK);
29 init_pair(7,COLOR_WHITE,COLOR_BLACK);
30
31 init_pair(9,COLOR_BLACK,COLOR_BLUE);
32 init_pair(11,COLOR_BLACK,COLOR_CYAN);
33 init_pair(15,COLOR_BLACK,COLOR_WHITE);
34 init_pair(16,COLOR_WHITE,COLOR_CYAN);
35
36 /* Start key by key mode */
37 cbreak();
38
39 /* Don't echo */
40 noecho();
41
42 /* Um I forget, view the manpage */
43 nonl();
44 #ifndef USE_SLANG
45 intrflush(stdscr,FALSE); /* Slang doesn't like this */
46 #endif
47 /* Enable arrow keys */
48 keypad(stdscr,TRUE);
49 }
50
51
52 /* Function to set colors */
set_color(int color,int bold)53 void set_color(int color,int bold) {
54 if (bold) attrset(COLOR_PAIR(color)|A_BOLD);
55 else attrset(COLOR_PAIR(color)|A_NORMAL);
56 }
57
58
59 /* Simple function that saves */
60 /* repetitive move() printw() */
61 /* sequences */
printxy(int x,int y,char * tempst)62 void printxy(int x,int y,char *tempst) {
63 move(y,x);
64 printw(tempst);
65 }
66
67
68 /* Shutdown curses nicely so the */
69 /* terminal works properly */
seabattle_exit_curses(void)70 void seabattle_exit_curses(void) {
71 clear();
72 refresh();
73 nocbreak();
74 echo();
75 endwin();
76 }
77
draw_title(void)78 void draw_title(void) {
79
80 set_color(C_BLUE,C_BOLD);
81 printxy(4,0,".|'''| '||'''|, || || '||`");
82 printxy(4,1,"|| || || || || ||");
83 printxy(4,2,"`|'''|, .|''|, '''|. ||;;;; '''|. ''||'' ''||'' || .|''|,");
84 printxy(4,3," . || ||..|| .|''|| || || .|''|| || || || ||..||");
85 printxy(4,4," |...|' `|... `|..||. .||...|' `|..||. `|..' `|..' .||. `|...");
86 set_color(C_WHITE,C_NORMAL);
87
88 }
89
90 #if 0
91 static void draw_oldship(void) {
92 int i;
93
94 printxy(0,6," )_");
95 printxy(0,7," _____|_|_____+__");
96 printxy(0,8," | x x x |");
97 printxy(0,9," \\----|------------------------------------------/");
98 printxy(0,10," \\ /");
99 move(11,0);
100 set_color(C_CYAN,C_NORMAL);
101 for(i=0;i<39;i++) printw("/\\");
102 }
103 #endif
104
draw_newship(void)105 static void draw_newship(void) {
106 int i,j;
107
108 set_color(C_BGCYAN,C_NORMAL);
109
110 /* draw sky */
111 for(i=0;i<7;i++) {
112 move(6+i,0);
113 for(j=0;j<79;j++) {
114 printw(" ");
115 }
116 }
117
118 set_color(C_BGBLUE,C_NORMAL);
119
120 /* draw water */
121 for(i=0;i<5;i++) {
122 move(13+i,0);
123 for(j=0;j<79;j++) {
124 printw(" ");
125 }
126 }
127
128 set_color(C_BGWHITE,C_NORMAL);
129 /* draw ship */
130 move(7,37); printw(" ");
131 move(8,37); printw(" "); move(8,43); printw(" ");
132 move(9,32); printw(" "); move(9,43); printw(" ");
133 move(10,32); printw(" ");
134 move(11,13); for(j=0;j<53;j++) { printw(" "); }
135 move(12,14); for(j=0;j<51;j++) { printw(" "); }
136
137 move(10,22); printw(" ");
138 move(10,28); printw(" ");
139 move(10,50); printw(" ");
140
141 set_color(C_WHITECYAN,C_NORMAL);
142 move(9,20); printw("__");
143 move(9,26); printw("__");
144 move(9,52); printw("__");
145 move(7,44); printw("|");
146 move(7,40); printw("+");
147 move(8,40); printw("|");
148
149
150 }
151
152
153
154
155 /* Draw opening screen */
draw_opening(void)156 void draw_opening(void) {
157
158 char ch;
159
160 draw_title();
161
162 //draw_oldship();
163 draw_newship();
164
165 set_color(C_RED,C_BOLD);
166 printxy(13,18,"A Game By Vince Weaver - Who cannot draw ASCII ships");
167 set_color(C_YELLOW,C_BOLD);
168 printxy(16,19,"vince@deater.net http://www.deater.net/weave");
169 set_color(C_GREEN,C_BOLD);
170 printxy(21,20,"Another Amazing Project for ENEE114");
171 set_color(C_WHITE,C_BOLD);
172 if (!has_colors()) {
173 printxy(0,22,"COLOR NOT AVAILABLE ON THIS TERMINAL. Using Black and White.");
174 }
175 refresh();
176 set_color(C_WHITE,C_NORMAL);
177 move(22,0);
178
179 /***********************/
180 /* detect sound setup */
181 /*********************/
182
183 /* first see if /usr/bin/aplay exists */
184 if (!access("/usr/bin/aplay",X_OK)) {
185 sound_device=SOUND_DEVICE_APLAY;
186 }
187 /* Sees if /dev/audio is available */
188 else if (!access("/dev/audio",W_OK)) {
189 sound_device=SOUND_DEVICE_DEV_AUDIO;
190 }
191 else {
192 sound_device=SOUND_DEVICE_SPEAKER;
193 }
194
195 if (sound_device==SOUND_DEVICE_SPEAKER) {
196 printw("No digital sound available. "
197 "Press any key to continue.");
198 ch=mvgetch(22,55);
199 }
200 else {
201 printw("Do you want nifty digital sound effects (y/n) ?");
202 ch=mvgetch(22,49);
203 if ( (ch!='y') && (ch!='Y') ) {
204 sound_device=SOUND_DEVICE_SPEAKER;
205 }
206 }
207 }
208
209
210 /* This made code slightly less */
211 /* Cluttered */
put_dumb_instructions(void)212 static void put_dumb_instructions(void) {
213 set_color(C_GREEN,C_BOLD);
214 printxy(5,7,"Choose a ship:");
215 printxy(5,8,"1. Submarine");
216 printxy(5,9,"2. Battleship");
217 printxy(5,10,"3. Aircraft Carrier");
218 printxy(5,11,"Q. Continues with game");
219 printxy(5,12,"X. Quits game entirely");
220 printxy(5,13,"--->");
221 }
222
223
224 /* Clears an 8x8 grid */
clear_grid(int grid[8][8])225 static void clear_grid(int grid[8][8]) {
226
227 int i,j;
228
229 for(i=0;i<8;i++) {
230 for(j=0;j<8;j++) {
231 grid[i][j]=0;
232 }
233 }
234 }
235
236 /* Play appropriate sound */
237 /* through appropriate device */
238 /* 0=error 1=hit 2=miss 3=sunkit */
239 /* Incomplete as of yet */
240
play_sound(char * soundfile)241 void play_sound(char *soundfile) {
242
243 char command[256];
244
245 if (sound_device==SOUND_DEVICE_APLAY) {
246 snprintf(command,256,"/usr/bin/aplay -q %s/%s",
247 DATADIR,soundfile);
248 system(command);
249 }
250 else if (sound_device==SOUND_DEVICE_DEV_AUDIO) {
251 snprintf(command,256,"cat %s/%s > /dev/audio",
252 DATADIR,soundfile);
253 system(command);
254 }
255 else {
256 beep();
257 }
258 }
259
do_sound(int which_one)260 void do_sound(int which_one) {
261
262 if (!sound_on) return;
263
264 switch(which_one) {
265 case SOUND_ERROR:
266 beep();
267 break;
268 case SOUND_HIT:
269 if (rand()%2) play_sound("hit1.au");
270 else play_sound("hit2.au");
271 break;
272 case SOUND_MISS:
273 if (rand()%2) play_sound("miss1.au");
274 else play_sound("miss2.au");
275 break;
276 case SOUND_SUNKIT:
277 play_sound("sunkit.au");
278 break;
279 }
280 }
281
282 #define INVALID_LEAVES_BOARD 0
283 #define INVALID_OVERLAPS 1
284
285 /* Prints some simple messages */
invalid_message(int message)286 static void invalid_message(int message) {
287
288 clear_status_lines();
289 set_color(C_BLUE,C_BOLD);
290 do_sound(SOUND_ERROR);
291 if (message==0) {
292 printxy(10,20,"Invalid! Leaves Board! Try Again.");
293 }
294 if (message==1) {
295 printxy(10,20,"Invalid! Overlaps another ship! Try Again.");
296 }
297 }
298
299 /* Remove all of a value from */
300 /* a grid */
purge_grid(int grid[8][8],int type)301 static void purge_grid(int grid[8][8], int type) {
302
303 int i,j;
304 for(i=0;i<8;i++) {
305 for(j=0;j<8;j++) {
306 if (grid[i][j]==(type+3)) grid[i][j]=0;
307 }
308 }
309 }
310
311
312 /* Main function to allow user */
313 /* to place ships */
get_users_grid(int grid[8][8])314 int get_users_grid(int grid[8][8]) {
315
316 int i,ch,shiptype=0,x,y,ch2,ch3,ch4;
317 char shipname[3][19]={"Submarine","Battleship","Aircraft Carrier"};
318 int ship_placed[3];
319 char text[250];
320 int exit_now=0;
321
322 /* Clear placement memory */
323 for(i=0;i<3;i++) ship_placed[i]=0;
324
325 set_color(C_RED,C_BOLD);
326 printxy(32,1,"Place Your Ships");
327 set_color(C_WHITE,C_NORMAL);
328 printxy(1,2,"Pick the number corresponding to the type"
329 " of ship you want to place. ");
330 printxy(1,3,"Then you may either type the coordinate "
331 "[e.g. A1] or use the arrow keys to pick");
332 printxy(1,4,"the starting block of the ship. "
333 "Then Press Spacebar. Then pick the direction");
334 printxy(1,5,"to put the ship [using NESW or the arrows]. "
335 "Then type 'Q' to continue.");
336 put_dumb_instructions();
337
338 /* Draw Compas points */
339 set_color(C_CYAN,C_BOLD);
340 printxy(60,7," N");
341 printxy(60,8," |");
342 printxy(60,9,"W<-+->E");
343 printxy(60,10," | ");
344 printxy(60,11," S");
345
346 /* Clear the grid */
347 clear_grid(grid);
348 place_grid(grid,30,7,1);
349
350 /* The big loop */
351 do {
352 ch=mvgetch(13,9);
353 if ( (ch>'0') && (ch<'z') ) {
354 if ( (ch>'0') && (ch<'4') )shiptype=ch-'1';
355 if ( (ch=='1') || (ch=='2') || (ch=='3') ) {
356 if (ship_placed[shiptype]) {
357 clear_status_lines();
358 sprintf(text,
359 "You have already placed the %s!",
360 shipname[shiptype]);
361 printxy(5,20,text);
362 do_sound(SOUND_ERROR);
363 printxy(5,21,"Replace it? (y/n)");
364 ch4=mvgetch(21,24);
365 if (toupper(ch4)=='Y') {
366 ship_placed[shiptype]=0;
367 purge_grid(grid,shiptype);
368 place_grid(grid,30,7,1);
369 }
370 clear_status_lines();
371 }
372 if (!ship_placed[shiptype]){
373 x=0; y=0;
374 clear_side();
375 printxy(5,7,"Now Placing: ");
376 printxy(6,8,shipname[shiptype]);
377 printxy(5,9,"Press Space when done");
378 do {
379 ch2=mvgetch(8+y,31+x);
380 if((ch2==KEY_UP)&&(y>0)) y--;
381 if((ch2==KEY_DOWN)&&(y<7)) y++;
382 if((ch2==KEY_RIGHT)&&(x<14)) x+=2;
383 if((ch2==KEY_LEFT)&&(x>0)) x-=2;
384 ch3=toupper(ch2);
385 if((ch3>='A')&&(ch3<'I')) y=ch3-'A';
386 if((ch3>='1')&&(ch3<'9')) x=2*(ch3-'1');
387 place_grid(grid,30,7,1);
388 set_color(C_RED,C_BOLD);
389 move(8+y,31+x);
390 printw("&&");
391 refresh();
392 } while (ch2!=' ');
393 clear_side();
394 printxy(5,7,"Now Pick N,S,E, or W");
395 printxy(5,8,"Or press an arrow key");
396 ch2=mvgetch(7,5);
397 x=x/2;
398 switch (ch2) {
399 case 'N': case 'n': case KEY_UP :
400 if (y<shiptype+2) {
401 invalid_message(INVALID_LEAVES_BOARD); break;
402 }
403 else if (test_overlap(grid,x,y,0,-1,shiptype+3) ){
404 invalid_message(INVALID_OVERLAPS); break;
405 }
406 else {
407 put_ship(grid,x,y,0,-1,shiptype+3);
408 ship_placed[shiptype]=1;
409 }
410 break;
411 case 'S': case 's': case KEY_DOWN:
412 if (y>8-(shiptype+3)) {
413 invalid_message(INVALID_LEAVES_BOARD); break;
414 }
415 else if (test_overlap(grid,x,y,0,1,shiptype+3) ){
416 invalid_message(INVALID_OVERLAPS); break;
417 }
418 else {
419 put_ship(grid,x,y,0,1,shiptype+3);
420 ship_placed[shiptype]=1;
421 }
422 break;
423 case 'E': case 'e': case KEY_RIGHT:
424 if (x>8-(shiptype+3)) {
425 invalid_message(INVALID_LEAVES_BOARD);
426 }
427 else if (test_overlap(grid,x,y,1,0,shiptype+3) ){
428 invalid_message(INVALID_OVERLAPS);
429 }
430 else {
431 put_ship(grid,x,y,1,0,shiptype+3);
432 ship_placed[shiptype]=1;
433 }
434 break;
435 case 'W': case 'w': case KEY_LEFT:
436 if (x<(shiptype+2)) {
437 invalid_message(INVALID_LEAVES_BOARD); break;
438 }
439 else if (test_overlap(grid,x,y,-1,0,shiptype+3)){
440 invalid_message(INVALID_OVERLAPS); break;
441 }
442 else {
443 put_ship(grid,x,y,-1,0,shiptype+3);
444 ship_placed[shiptype]=1;
445 }
446 break;
447 default: /*printw("Invalid Entry")*/;
448 }
449 clear_side();
450 place_grid(grid,30,7,1);
451 put_dumb_instructions();
452 refresh();
453 }
454 }
455
456 if (toupper(ch)=='Q') {
457 if ((ship_placed[0]==1)&&
458 (ship_placed[1]==1)&&
459 (ship_placed[2]==1) ) {
460 exit_now=1;
461 }
462 else {
463 set_color(C_RED,C_BOLD);
464 printxy(5,20,"You need to place one of "
465 "each kind of ship before you "
466 "continue!");
467 do_sound(SOUND_ERROR);
468 }
469 }
470 if (toupper(ch)=='X') quit();
471 }
472 } while(!exit_now);
473 return 0;
474 }
475
476
477
478 /* Clear the bottom lines */
clear_status_lines(void)479 void clear_status_lines(void) {
480 move(20,1); clrtoeol();
481 move(21,1); clrtoeol();
482 }
483
484 /* Clear the side area */
clear_side(void)485 void clear_side(void) {
486 printxy(5,7," ");
487 printxy(5,8," ");
488 printxy(5,9," ");
489 printxy(5,10," ");
490 printxy(5,11," ");
491 printxy(5,12," ");
492 printxy(5,13," ");
493 refresh();
494 }
495
496 /* Create a Quit Pop-UP */
quit(void)497 void quit(void) {
498 char ch;
499 WINDOW *quit_window; /* It's a sub-window */
500
501 quit_window=newwin(5,30,10,20);
502 wattrset(quit_window,COLOR_PAIR(C_YELLOW)|A_BOLD);
503 mvwprintw(quit_window,0,0,"*****************************");
504 mvwprintw(quit_window,1,0,"* This will Quit COMPLETELY *");
505 mvwprintw(quit_window,2,0,"* Are you sure you want to *");
506 mvwprintw(quit_window,3,0,"* Do this? (y/n) *");
507 mvwprintw(quit_window,4,0,"*****************************");
508
509 wrefresh(quit_window);
510 ch=mvgetch(13,37);
511 wclear(quit_window);
512 wrefresh(quit_window);
513 delwin(quit_window);
514
515 if ((ch=='Y') || (ch=='y')) {
516 seabattle_exit_curses();
517 exit(0);
518 }
519 #ifndef BROKEN_CURSES
520 redrawwin(stdscr);
521 #endif
522 }
523
524 /* Place computers ships */
get_computers_grid(int grid[8][8])525 void get_computers_grid(int grid[8][8]) {
526
527 clear_grid(grid);
528 while(place_ship(grid,3));
529 while(place_ship(grid,4));
530 while(place_ship(grid,5));
531 }
532
533 /* Make sure ships don't overlap */
test_overlap(int grid[8][8],int x,int y,int xdir,int ydir,int size)534 int test_overlap(int grid[8][8],int x,int y,int xdir,int ydir,int size) {
535 int i,j;
536 j=0;
537 for(i=0;i<size;i++) {
538 if (grid[x+(i*xdir)][y+(i*ydir)]!=0) j++;
539 }
540 return j;
541 }
542
543 /* Put ship in a grid */
put_ship(int grid[8][8],int x,int y,int xdir,int ydir,int size)544 void put_ship(int grid[8][8],int x,int y,int xdir,int ydir,int size) {
545
546 int i;
547
548 for(i=0;i<size;i++) {
549 grid[x+(i*xdir)][y+(i*ydir)]=size;
550 }
551 }
552
553 /* Place the computer's ships */
554 /* in random locations, but no */
555 /* overlaps or out of bounds */
place_ship(int grid[8][8],int size)556 int place_ship(int grid[8][8],int size) {
557
558 int x,y,direction;
559
560 if ((grid[x=rand()%8][y=rand()%8])==0) {
561 direction=rand()%4;
562 switch(direction) {
563 case 0: /*north*/
564 if ((y>=size)&&
565 (test_overlap(grid,x,y,0,-1,size)==0)) {
566 put_ship(grid,x,y,0,-1,size);
567 }
568 else return -1;
569 break;
570 case 1: /*east*/
571 if ((x<(8-size))&&
572 (test_overlap(grid,x,y,1,0,size)==0)) {
573 put_ship(grid,x,y,1,0,size);
574 }
575 else return -1;
576 break;
577 case 2: /*south*/
578 if ((y<(8-size))&&
579 (test_overlap(grid,x,y,0,1,size)==0)) {
580 put_ship(grid,x,y,0,1,size);
581 }
582 else return -1;
583 break;
584 case 3: /*west*/
585 if ((x>=size)&&
586 (test_overlap(grid,x,y,-1,0,size)==0)) {
587 put_ship(grid,x,y,-1,0,size);
588 }
589 else return -1;
590 break;
591 }
592 return 0;
593 }
594
595 return -1;
596 }
597
598 /* Display a grid on the screen */
place_grid(int grid[8][8],int x,int y,int show_ships)599 void place_grid(int grid[8][8],int x,int y,int show_ships) {
600
601 int i,j;
602
603 move(y,x);
604 set_color(C_WHITE,C_BOLD);
605 printw(" 1 2 3 4 5 6 7 8");
606 for(i=0;i<8;i++) {
607 move(y+1+i,x);
608 set_color(C_WHITE,C_BOLD);
609 printw("%c",65+i);
610
611 for (j=0;j<8;j++) {
612 switch(grid[j][i]) {
613 case 0: printw(" ");
614 break;
615 case 3: set_color(C_WHITE,C_NORMAL);
616 if (show_ships) printw("SS");
617 else printw(" ");
618 break;
619 case 4: set_color(C_WHITE,C_NORMAL);
620 if (show_ships) printw("BB");
621 else printw(" ");
622 break;
623 case 5: set_color(C_WHITE,C_NORMAL);
624 if (show_ships) printw("AA");
625 else printw(" ");
626 break;
627 case 1: set_color(C_RED,C_BOLD);
628 printw("**");
629 break;
630 case 2: set_color(C_CYAN,C_NORMAL);
631 printw("',");
632 break;
633 }
634 }
635 }
636 }
637
638 /* ************************END binp.c ******************************** */
639