1 /*
2  * XGalaga-SDL - a SDL port of XGalaga, clone of the game Galaga
3  * Copyright (c) 1995-1998 Joe Rumsey (mrogre@mediaone.net)
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * 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., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA.
19  */
20 
21 #include <stdlib.h>
22 
23 #include "xgalaga.h"
24 
25 #define PR_SING 0
26 #define PR_DOUB 1
27 #define PR_TRIP 2
28 #define PR_SPEED 3
29 #define PR_SHIELD 4
30 #define PR_SMART 5
31 #define PR_LEMON 6
32 #define PR_EXTRABULLET 7
33 
34 #ifdef ENABLE_SPREAD_SHOT
35 #define PR_SPREAD 8
36 #endif
37 
38 #ifdef ENABLE_MACHINE_GUN
39 # ifdef ENABLE_SPREAD_SHOT
40 #  define PR_MACHINE 9
41 #  define NUMPRIZES 10
42 # else
43 #  define PR_MACHINE 8
44 #  define NUMPRIZES 9
45 # endif /* ENABLE_SPREAD_SHOT */
46 #else
47 # ifdef ENABLE_SPREAD_SHOT
48 #  define PR_SPREAD 8
49 #  define NUMPRIZES 9
50 # else
51 #  define NUMPRIZES 8
52 # endif /* ENABLE_SPREAD_SHOT */
53 #endif /* ENABLE_MACHINE_GUN */
54 
55 #define PRIZESPEED 3
56 
57 static struct {
58 	struct W_Image *image;
59 	const char *desc;
60 } prizes[NUMPRIZES];
61 
62 static struct prize {
63     struct prize *next, *prev;
64     int x, y, type, dying;
65 } *first_prize; /* 8-) */
66 
init_prizes(void)67 void init_prizes(void)
68 {
69     prizes[0].image = getImage(I_PR_SING);
70 	prizes[0].desc = "Shot single torpedo";
71 
72     prizes[1].image = getImage(I_PR_DOUB);
73 	prizes[1].desc = "Shot double torpedo";
74 
75     prizes[2].image = getImage(I_PR_TRIP);
76 	prizes[2].desc = "Shot triple torpedo";
77 
78     prizes[3].image = getImage(I_PR_SPEED);
79 	prizes[3].desc = "Increase ship speed";
80 
81     prizes[4].image = getImage(I_PR_SHIELD);
82 	prizes[4].desc = "Shield";
83 
84     prizes[5].image = getImage(I_PR_SMART);
85 	prizes[5].desc = "Smart";
86 
87     prizes[6].image = getImage(I_PR_LEMON);
88 	prizes[6].desc = "Increase chance to get a bonus";
89 
90     prizes[7].image = getImage(I_PR_EXTRABULLET);
91 	prizes[7].desc = "Add a torpedo";
92 
93 #ifdef ENABLE_SPREAD_SHOT
94     prizes[8].image = getImage(I_PR_SPREAD);
95 	prizes[8].desc = "Spread Shot";
96 #endif
97 
98 #ifdef ENABLE_MACHINE_GUN
99     prizes[NUMPRIZES - 1].image = getImage(I_PR_MACHINE);
100 	prizes[NUMPRIZES - 1].desc = "Machine Gun";
101 #endif
102 }
103 
new_prize(int x,int y)104 void new_prize(int x, int y)
105 {
106     struct prize *p;
107 
108     p = malloc(sizeof(struct prize));
109     p->next = first_prize;
110     p->prev = NULL;
111     if(first_prize)
112 		first_prize->prev = p;
113     first_prize = p;
114     p->x = x;
115     p->y = y;
116     p->type = random()%NUMPRIZES;
117     p->dying = 0;
118 }
119 
undo_prizes(void)120 void undo_prizes(void)
121 {
122     struct prize *p = first_prize, *nextp;
123 
124     while(p) {
125 		nextp = p->next;
126 
127 		if(p->dying) {
128 			if(p->next)
129 				p->next->prev = p->prev;
130 			if(p->prev)
131 				p->prev->next = p->next;
132 			if(p == first_prize)
133 				first_prize = p->next;
134 			free(p);
135 		}
136 		p = nextp;
137     }
138 }
139 
do_prizes(void)140 void do_prizes(void)
141 {
142     struct prize *p = first_prize;
143     int i,k, ne;
144     int oldPlaySounds;
145 
146     while(p) {
147 		if (gstate != PAUSED)
148 			p->y+=PRIZESPEED;
149 		S_DrawImage(p->x-prizes[p->type].image->width/2, p->y-prizes[p->type].image->width/2,
150 					0, prizes[p->type].image);
151 
152 		if(p->y > (winheight-20) && (ABS(p->x - plx) < 15)
153 #ifdef NO_PRIZE_WHILE_DEAD
154 		   && !pldead
155 #endif
156 			) {
157 			p->dying = 1;
158 			play_sound(SND_DDLOO);
159 			switch(p->type) {
160 			case PR_SING:
161 				if(weapon == SINGLESHOT)
162 					maxtorps++;
163 				else
164 					weapon = SINGLESHOT;
165 				break;
166 			case PR_DOUB:
167 				if(weapon == DOUBLESHOT)
168 					maxtorps++;
169 				else {
170 					weapon = DOUBLESHOT;
171 					if(maxtorps < 4)
172 						maxtorps = 4;
173 				}
174 				break;
175 			case PR_TRIP:
176 				if(weapon == TRIPLESHOT)
177 					maxtorps++;
178 				else {
179 					weapon = TRIPLESHOT;
180 					if(maxtorps < 6)
181 						maxtorps=6;
182 				}
183 				break;
184 			case PR_SPEED:
185 				if(movespeed < MAXSPEED)
186 					movespeed++;
187 				break;
188 #ifdef ENABLE_SPREAD_SHOT
189 			case PR_SPREAD:
190                 if (weapon == SPREADSHOT)
191                     maxtorps++;
192                 else {
193                     weapon = SPREADSHOT;
194                     if (maxtorps < 5)
195 						maxtorps = 5;
196 				}
197 				break;
198 #endif /* ENABLE_SPREAD_SHOT */
199 #ifdef ENABLE_MACHINE_GUN
200 			case PR_MACHINE:
201                 if (weapon == MACHINEGUN)
202 					maxtorps++;
203                 else {
204 					weapon = MACHINEGUN;
205 					if (maxtorps < 3)
206 						maxtorps = 3;
207                 }
208                 break;
209 #endif /* ENABLE_MACHINE_GUN */
210 			case PR_SHIELD:
211 #ifdef ACTIVATED_SHIELD
212 				if (shieldon)
213 					plshield += SHIELDTIME;
214 				else
215 					shieldsleft += SHIELDTIME;
216 				if (shieldsleft + plshield > MAXSHIELDS)
217 				{
218 					if (shieldon)
219 					{
220 						shieldsleft = 0;
221 						plshield = MAXSHIELDS;
222 					} else {
223 						shieldsleft = MAXSHIELDS;
224 						plshield = 0;
225 					}
226 				}
227 #else
228 				plshield = SHIELDTIME;
229 				play_sound(SND_SHIELD);
230 #endif /* ACTIVATED_SHIELD */
231 				break;
232 			case PR_SMART:
233 				play_sound(SND_SMART);
234 				oldPlaySounds = playSounds;
235 				playSounds = 0;
236 				for(i=0;i<MAXALIENS;i++) {
237 					if(aliens[i].alive && !aliens[i].dying) {
238 						aliens[i].dying = 1;
239 						if(i >= 10) {
240 							if(aliens[i].dir < 0)
241 								score += 50;
242 							else {
243 								score += (6-(i/10))*100;
244 								if(!(random()%(gotlemon ? 3 : PRIZECHANCE)))
245 									new_prize(aliens[i].x, aliens[i].y);
246 							}
247 							new_explosion(aliens[i].x, aliens[i].y, 0);
248 						} else {
249 							if(aliens[i].dir < 0)
250 								score += 200;
251 							else {
252 								ne=0; /* count how many escorts */
253 								for(k = i+9;k < i+12; k++) {
254 									if(aliens[k].escorting == i)
255 										ne++;
256 								}
257 								score_flagship(aliens[i].x, aliens[i].y, ne);
258 							}
259 							new_explosion(aliens[i].x, aliens[i].y, 1);
260 						}
261 					}
262 				}
263 				playSounds = oldPlaySounds;
264 				break;
265 			case PR_LEMON:
266 				gotlemon = 1;
267 				maxtorps = MINTORPS;
268 				weapon = 0;
269 				movespeed = MINSPEED;
270 				break;
271 			case PR_EXTRABULLET:
272 				if(maxtorps < MAXTORPS)
273 					maxtorps++;
274 				break;
275 			}
276 			if(maxtorps > MAXTORPS)
277 				maxtorps = MAXTORPS;
278 		} else if(p->y > winheight) {
279 			p->dying = 1;
280 		}
281 		p=p->next;
282     }
283 }
284 
show_bonuses(int top)285 void show_bonuses(int top)
286 {
287 	int i;
288 	int dy = SFont_TextHeight(fnt_reg_yellow);
289 	const char *label = "Bonuses";
290 	int length;
291 
292 	if (dy < 22)
293 		dy = 22;
294 
295 	SFont_WriteCenter(fnt_reg_yellow, top, label);
296 
297 	/* Draw a line. */
298 	length = SFont_TextWidth(fnt_reg_yellow, label);
299 	S_DrawRect((winwidth-length)/2, top + 1 + SFont_TextHeight(fnt_reg_yellow),
300 			   length, 1,
301 			   SDL_MapRGB(screen->format, 0xff, 0, 0));
302 
303 	top += dy;
304 
305     for (i=0; i<NUMPRIZES; i++) {
306 		S_DrawImage(100, top, 0, prizes[i].image);
307 
308 		SFont_Write(fnt_reg_yellow, 130, top, prizes[i].desc);
309 		top += dy;
310 	}
311 }
312 
313