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