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