1 /**
2  * nInvaders - a space invaders clone for ncurses
3  * Copyright (C) 2002-2003 Dettus
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  *
19  * homepage: http://ninvaders.sourceforge.net
20  * mailto: ninvaders-devel@lists.sourceforge.net
21  *
22  */
23 
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/time.h>
28 #include "nInvaders.h"
29 #include "player.h"
30 #include "aliens.h"
31 #include "ufo.h"
32 
33 #define FPS 50
34 
35 int lives;
36 long score;
37 int status; // status handled in timer
38 
39 #define GAME_LOOP 1
40 #define GAME_NEXTLEVEL 2
41 #define GAME_PAUSED 3
42 #define GAME_OVER 4
43 #define GAME_EXIT 5
44 #define GAME_HIGHSCORE 6
45 
46 
47 
48 
49 /**
50  * initialize level: reset attributes of most units
51  */
initLevel()52 static void initLevel()
53 {
54 	playerReset();
55 	aliensReset();
56 	ufoReset();
57 	bunkersReset();
58 	render();
59 	drawscore();
60 }
61 
62 
63 /**
64  * evaluate command line parameters
65  */
evaluateCommandLine(int argc,char ** argv)66 static void evaluateCommandLine(int argc, char **argv)
67 {
68 
69 	// -l : set skill level
70 	if (argc == 3 && strcmp(argv[1], "-l") == 0) {
71 		if (argv[2][0] >= '0' && argv[2][0] <= '9') {
72 			skill_level = argv[2][0] - 48;
73 		} else {
74 			argc = 2;
75 		}
76 	}
77 
78 	// -gpl : show GNU GPL
79 	if (argc == 2 && strcmp(argv[1], "-gpl") == 0) {
80 		showGpl();
81 	}
82 
83 	// wrong command line: show usage
84 	if (argc == 2 || (argc == 3 && strcmp(argv[1], "-l") != 0)) {
85 		showVersion();
86 		showUsage();
87 		exit(1);
88 	}
89 }
90 
91 
finish(int sig)92 static void finish(int sig)
93 {
94         endwin();
95 	showGplShort();
96 
97 	fprintf(stderr,"\n");
98 	fprintf(stderr,"\n");
99 	fprintf(stderr,"=========================================================================\n");
100 	fprintf(stderr,"\n");
101 
102 	fprintf(stderr,"Final score: %7.7ld, Final level: %2.2d\nFinal rating... ",score,level);
103 	if (lives>0)
104 		fprintf(stderr,"Quitter\n\n");
105 	else if(score<5000)
106 		fprintf(stderr,"Alien Fodder\n\n");
107 	else if(score<7500)
108 		fprintf(stderr,"Easy Target\n\n");
109 	else if(score<10000)
110 		fprintf(stderr,"Barely Mediocre\n\n");
111 	else if(score<12500)
112 		fprintf(stderr,"Shows Promise\n\n");
113 	else if(score<15000)
114 		fprintf(stderr,"Alien Blaster\n\n");
115 	else if(score<20000)
116 		fprintf(stderr,"Earth Defender\n\n");
117 	else if(score>19999)
118 		fprintf(stderr,"Supreme Protector\n\n");
119 
120 	showVersion();
121         exit(0);
122 }
123 
124 
drawscore()125 void drawscore()
126 {
127 	statusDisplay(level, score, lives);
128 }
129 
130 
131 /**
132  * reads input from keyboard and do action
133  */
readInput()134 void readInput()
135 {
136 	int ch;
137 	static int lastmove;
138 
139 	ch = getch();		// get key pressed
140 
141 	switch (status) {
142 
143 	case GAME_PAUSED:
144 
145 		if (ch == 'p') {
146 			status = GAME_LOOP;
147 		}
148 		break;
149 
150 	case GAME_HIGHSCORE:
151 
152 		if (ch == ' ') {
153 			titleScreenClear();
154 			level = 0;      // reset level
155 			score = 0;      // reset score
156 			lives = 3;      // restore lives
157 			status = GAME_NEXTLEVEL;
158 		} else if (ch == 'q') {	// quit game
159 			status = GAME_EXIT;
160 		}
161 		break;
162 
163 	case GAME_OVER:
164 		break; // don't do anything
165 
166 	default:
167 
168 		if (ch == 'l' || ch == KEY_RIGHT) {	// move player right
169 			if (lastmove == 'l') {
170 				playerTurboOn();	// enable Turbo
171 			} else {
172 				playerTurboOff();	// disable Turbo
173 			}
174 			playerMoveRight();		// move player
175 			lastmove = 'l';			// remember last move for turbo mode
176 		} else if (ch == 'h' || ch == KEY_LEFT) {	// move player left
177 			if (lastmove == 'h') {
178 				playerTurboOn();	// enable Turbo
179 			} else {
180 				playerTurboOff();	// disable Turbo
181 			}
182 			playerMoveLeft();		// move player
183 			lastmove = 'h';			// remember last move for turbo mode
184 		} else if (ch == 'k' || ch == ' ') {	// shoot missile
185 			playerLaunchMissile();
186 		} else if (ch == 'p') {			// pause game until 'p' pressed again
187 			// set status to game paused
188 			status = GAME_PAUSED;
189 		} else if (ch == 'W') {			// cheat: goto next level
190 			status = GAME_NEXTLEVEL;
191 		} else if (ch == 'L') {			// cheat: one more live
192 			lives++;
193 			drawscore();
194 		} else if (ch == 'q') {	// quit game
195 			status = GAME_EXIT;
196 		} else {		// disable turbo mode if key is not kept pressed
197 			lastmove = ' ';
198 		}
199 
200 	} // switch
201 
202 }
203 
204 
205 /**
206  * timer
207  * this method is executed every 1 / FPS seconds
208  */
handleTimer()209 void handleTimer()
210 {
211 	static int aliens_move_counter = 0;
212 	static int aliens_shot_counter = 0;
213 	static int player_shot_counter = 0;
214 	static int ufo_move_counter = 0;
215 	static int title_animation_counter = 0;
216 	static int game_over_counter = 0;
217 
218 	switch (status) {
219 
220 	case GAME_NEXTLEVEL:    // go to next level
221 
222 		level++;	// increase level
223 
224 		initLevel();	// initialize level
225 
226 		aliens_move_counter = 0;
227 		aliens_shot_counter = 0;
228 		player_shot_counter = 0;
229 		ufo_move_counter = 0;
230 
231 		weite = (shipnum+(skill_level*10)-(level*5)+5)/10;
232 
233 		if (weite < 0) {
234 			weite = 0;
235 		}
236 
237 		// change status and start game!
238 		status = GAME_LOOP;
239 
240 	case GAME_LOOP:   	 // do game handling
241 
242 		// move aliens
243 		if (aliens_move_counter == 0 && aliensMove() == 1) {
244 			// aliens reached player
245 			lives = 0;
246 			status = GAME_OVER;
247 		}
248 
249 		// move player missile
250 		if (player_shot_counter == 0 && playerMoveMissile() == 1) {
251 			// no aliens left
252 			status = GAME_NEXTLEVEL;
253 		}
254 
255 		// move aliens' missiles
256 		if (aliens_shot_counter == 0 && aliensMissileMove() == 1) {
257 			// player was hit
258 			lives--;			// player looses one life
259 			drawscore();	                // draw score
260 			playerExplode();		// display some explosion graphics
261 			if (lives == 0) {		// if no lives left ...
262 				status = GAME_OVER;		// ... exit game
263 			}
264 		}
265 
266 		// move ufo
267 		if (ufo_move_counter == 0 && ufoShowUfo() == 1) {
268 			ufoMoveLeft();			// move it one position to the left
269 		}
270 
271 
272 		if (aliens_shot_counter++ >= 5) {aliens_shot_counter=0;}     // speed of alien shot
273 		if (player_shot_counter++ >= 1) {player_shot_counter=0;}     // speed of player shot
274 		if (aliens_move_counter++ >= weite) {aliens_move_counter=0;} // speed of aliend
275 		if (ufo_move_counter++ >= 3) {ufo_move_counter=0;}           // speed of ufo
276 
277 		refreshScreen();
278 		break;
279 
280 	case GAME_PAUSED:    // game is paused
281 		break;
282 
283 	case GAME_OVER:      // game over
284 		if (game_over_counter == 100) {
285 			battleFieldClear();
286 			status = GAME_HIGHSCORE;
287 			game_over_counter = 0;
288 		} else {
289 			gameOverDisplay();
290 			game_over_counter++;
291 		}
292 		break;
293 
294 	case GAME_EXIT:      // exit game
295 		finish(0);
296 		break;
297 
298 	case GAME_HIGHSCORE: // display highscore
299 		if (title_animation_counter == 0) {
300 			titleScreenDisplay();
301 		}
302 
303 		if (title_animation_counter++ >= 6) {title_animation_counter = 0;} // speed of animation
304 		break;
305 
306 	}
307 }
308 
309 
310 /**
311  * set up timer
312  */
setUpTimer()313 void setUpTimer()
314 {
315 	struct itimerval myTimer;
316 	struct sigaction myAction;
317 	myTimer.it_value.tv_sec = 0;
318 	myTimer.it_value.tv_usec = 1000000 / FPS;
319 	myTimer.it_interval.tv_sec = 0;
320 	myTimer.it_interval.tv_usec = 1000000 / FPS;
321 	setitimer(ITIMER_REAL, &myTimer, NULL);
322 
323 	myAction.sa_handler = &handleTimer;
324 	myAction.sa_flags = SA_RESTART;
325 	sigaction(SIGALRM, &myAction, NULL);
326 }
327 
328 
main(int argc,char ** argv)329 int main(int argc, char **argv)
330 {
331  	weite = 0;
332 	score = 0;
333 	lives = 3;
334 	level = 0;
335 	skill_level = 1;
336 
337 	evaluateCommandLine(argc, argv);	// evaluate command line parameters
338 	graphicEngineInit();			// initialize graphic engine
339 
340 	// set up timer/ game handling
341 	setUpTimer();
342 	status = GAME_HIGHSCORE;
343 
344 	// read keyboard input
345 	do {
346 		// do movements and key-checking
347 		readInput();
348 	} while (0 == 0);
349 
350 	return 0;
351 }
352 
353 
doScoring(int alienType)354 void doScoring(int alienType)
355 {
356 	int points[4] = {500, 200, 150, 100};   	// 0: ufo, 1:red, 2:green, 3:blue
357 
358 	score += points[alienType];		// every alien type does different scoring points
359 
360 	// every 6000 pts player gets a new live
361 	if (score % 6000 == 0){
362 		lives++;
363 	}
364 
365 	drawscore();	// display score
366 }
367 
368