1 /*
2 * IceBreaker
3 * Copyright (c) 2000-2002 Matthew Miller <mattdm@mattdm.org> and
4 *   Enrico Tassi <gareuselesinge@infinito.it>
5 *
6 * <http://www.mattdm.org/icebreaker/>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23 
24 /* special thanks to Enrico for the grid coloring stuff for themes */
25 /* and for the vastly improved circular scrolling code */
26 
27 
28 #include <SDL.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include "icebreaker.h"
32 #include "cursor.h"
33 #include "penguin.h"
34 #include "line.h"
35 #include "grid.h"
36 #include "sound.h"
37 #include "laundry.h"
38 #include "globals.h"
39 #include "level.h"
40 #include "status.h"
41 #include "text.h"
42 #include "hiscore.h"
43 #include "themes.h"
44 #include "event.h"
45 #include "fullscreen.h"
46 #include "options.h"
47 
48 #define LXPOS(x) (BORDERLEFT+(BLOCKWIDTH*(x)))
49 #define LYPOS(y) (BORDERTOP+(BLOCKHEIGHT*(y)))
50 
51 static void setupintro(void);
52 void circularblit(SDL_Surface* scoresurface,SDL_Rect* scrollrect,Uint16 hiscorescroll);
53 SDL_Surface* createscoresurface();
54 
setupintro()55 void setupintro()
56 {
57 	int x,y;
58 
59 	setcursor(CURSORARROW);
60 	SDL_FillRect(screen,NULL,color.background);
61 
62 
63 	for (x=0;x<WIDTH;x++)
64 		for (y=0;y<HEIGHT;y++)
65 		{
66 			if (x<BORDERLEFT || x>=BORDERRIGHT || y <BORDERTOP || y>=BORDERBOTTOM)
67 				grid[x][y]='X';
68 			else
69 				grid[x][y]='w';
70 		}
71 
72 	/// Here's the fun part where we set up the letters.
73 	// I
74 	markgrid(LXPOS(1),LYPOS(2),BLOCKWIDTH*3,BLOCKHEIGHT  ,' ');
75 	markgrid(LXPOS(1),LYPOS(7),BLOCKWIDTH*3,BLOCKHEIGHT  ,' ');
76 	markgrid(LXPOS(2),LYPOS(2),BLOCKWIDTH  ,BLOCKHEIGHT*6,' ');
77 
78 	//C
79 	markgrid(LXPOS(5),LYPOS(2),BLOCKWIDTH*4,BLOCKHEIGHT  ,' ');
80 	markgrid(LXPOS(5),LYPOS(3),BLOCKWIDTH  ,BLOCKHEIGHT*5,' ');
81 	markgrid(LXPOS(6),LYPOS(7),BLOCKWIDTH*3,BLOCKHEIGHT,  ' ');
82 
83 	//E
84 	markgrid(LXPOS(10),LYPOS(2),BLOCKWIDTH*4,BLOCKHEIGHT  ,' ');
85 	markgrid(LXPOS(10),LYPOS(3),BLOCKWIDTH  ,BLOCKHEIGHT*5,' ');
86 	markgrid(LXPOS(11),LYPOS(7),BLOCKWIDTH*3,BLOCKHEIGHT,  ' ');
87 	markgrid(LXPOS(11),LYPOS(4),BLOCKWIDTH*2,BLOCKHEIGHT  ,' ');
88 
89 	drawgridblocks();
90 
91 	updateall();
92 }
93 
94 
95 
intro(void)96 int intro(void)
97 {
98 	int penguincount=0;
99 	int frozen=true;
100 	int i;
101 	int x,y;
102 	int letterstep=0;
103 	int hiscorescroll=0;
104 	int hiscorestep=0;
105 	int linedone1=false; int linedone2=false;
106 
107 	SDL_Rect labelrect;
108 	SDL_Rect scrollrect;
109 	SDL_Rect bigrect;
110 	SDL_Rect rightmarginrect;
111 	SDL_Rect leftmarginrect;
112 #ifdef DEVELRELEASE
113 	SDL_Rect develdisclaimerrect;
114 #endif
115 
116 	int done = false;
117 
118 	Penguin flock[100];
119 	Penguin tux;
120 
121 	SDL_Event event;
122 
123 	SDL_Surface* scoresurface;
124 
125 	setupintro();
126 
127 #ifdef DEVELRELEASE
128 	develdisclaimerrect.x=BORDERLEFT-3;
129 	develdisclaimerrect.y=MARGINTOP+PLAYHEIGHT+CHARHEIGHT*2;
130 	develdisclaimerrect.h=CHARHEIGHT*3;
131 	develdisclaimerrect.w=WIDTH-develdisclaimerrect.x;
132 #endif
133 
134 	labelrect.x=BORDERLEFT;
135 	labelrect.y=BORDERTOP-(4*CHARHEIGHT);
136 	labelrect.h=CHARHEIGHT*2;
137 	labelrect.w=CHARWIDTH*21;
138 
139 	scrollrect.x=BORDERLEFT+CHARWIDTH*21;
140 	scrollrect.y=labelrect.y;
141 	scrollrect.w=BORDERRIGHT-(BORDERLEFT+CHARWIDTH*21);
142 	scrollrect.h=labelrect.h;
143 
144 	rightmarginrect.x=BORDERRIGHT;
145 	rightmarginrect.y=labelrect.y;
146 	rightmarginrect.w=MARGINRIGHT;
147 	rightmarginrect.h=labelrect.h;
148 
149 	leftmarginrect.x=0;
150 	leftmarginrect.y=labelrect.y;
151 	leftmarginrect.w=BORDERLEFT;
152 	leftmarginrect.h=labelrect.h;
153 
154 	bigrect.x=labelrect.x;
155 	bigrect.y=labelrect.y;
156 	bigrect.w=WIDTH-(BORDERLEFT);
157 	bigrect.h=labelrect.h;
158 
159 	hiscorescroll=0;
160 
161 	puttext(labelrect.x,labelrect.y,2,color.normaltext,"HIGH SCORES:");
162 	soil(labelrect);
163 
164 #ifdef DEVELRELEASE
165 	puttext(develdisclaimerrect.x,develdisclaimerrect.y,1,color.copyrighttext,"This is a development (beta) release meant for bug-testing only. Please check");
166 	puttext(develdisclaimerrect.x+3,develdisclaimerrect.y+CHARHEIGHT*1.5,1,color.copyrighttext,"<http://www.mattdm.org/icebreaker/> for the latest stable release. Thanks!");
167 	soil(develdisclaimerrect);
168 #endif
169 
170 	line1=createline(1);
171 	line2=createline(2);
172 
173 	tux = createpenguin();
174 
175 	// create highscore surface
176 	scoresurface = createscoresurface();
177 
178 	do
179 	{
180 		while (pollevent(&event))
181 		{
182 			if (event.type == SDL_QUIT)
183 			{
184 				return(true);
185 				// fix -- should delete penguins here
186 			}
187 			else if (event.type == SDL_MOUSEBUTTONUP)
188 			{
189 				done=true;
190 			}
191 			else if (event.type == SDL_KEYUP)
192 			{
193 				switch(translatekeyevent(&event))
194 				{
195 					case KEYCANCEL:
196 						if (gameflags.isfullscreen) makewindowed();
197 					break;
198 					case KEYSWITCHLINE: // falls through
199 					case KEYMENU:      // yep
200 					case KEYSTARTLINE: // start game
201 						if (letterstep>1) done=true; // kludge to keep from catching enter keystroke which launched app
202 					default:
203 					break;
204 				}
205 			}
206 		}
207 		if (letterstep < 10)
208 		{
209 			switch (letterstep)
210 			{
211 				// I
212 				case 0:
213 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(2),LYPOS(2));
214 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(2),LYPOS(2));
215 				break;
216 				case 1:
217 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(2),LYPOS(7));
218 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(2),LYPOS(7));
219 				break;
220 				case 2:
221 					if (!linedone1 && !line1.on) startline(&line1,UP,LXPOS(2),LYPOS(5));
222 					if (!linedone2 && !line2.on) startline(&line2,DOWN,LXPOS(2),LYPOS(5));
223 				break;
224 				// C
225 				case 3:
226 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(7),LYPOS(2));
227 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(7),LYPOS(2));
228 				break;
229 				case 4:
230 					if (!linedone1 && !line1.on) startline(&line1,UP,LXPOS(5),LYPOS(5));
231 					if (!linedone2 && !line2.on) startline(&line2,DOWN,LXPOS(5),LYPOS(5));
232 				break;
233 				case 5:
234 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(7),LYPOS(7));
235 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(7),LYPOS(7));
236 				break;
237 				// E
238 				case 6:
239 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(11),LYPOS(2));
240 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(11),LYPOS(2));
241 				break;
242 				case 7:
243 					if (!linedone1 && !line1.on) startline(&line1,UP,LXPOS(10),LYPOS(5));
244 					if (!linedone2 && !line2.on) startline(&line2,DOWN,LXPOS(10),LYPOS(5));
245 				break;
246 				case 8:
247 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(13),LYPOS(7));
248 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(13),LYPOS(7));
249 				break;
250 				case 9:
251 					if (!linedone1 && !line1.on) startline(&line1,LEFT,LXPOS(12),LYPOS(4));
252 					if (!linedone2 && !line2.on) startline(&line2,RIGHT,LXPOS(12),LYPOS(4));
253 				break;
254 			}
255 
256 		}
257 		else if (letterstep==10)
258 		{
259 			for (x=0;x<WIDTH;x++)
260 				for (y=0;y<HEIGHT;y++)
261 					if (grid[x][y]=='w')
262 					{
263 						grid[x][y]=' ';
264 					}
265 					// FIX: known bug -- if a line stops partway through a grid cell,
266 					// the space left over is not cleared properly later. this isn't
267 					// an issue in the game, as lines aways stop on cell boundaries, but
268 					// sometimes shows up in the intro. this is a kludge
269 					// which should fix it.
270 					else if (((x-BORDERLEFT) % BLOCKWIDTH)==0 && ((y-BORDERTOP) % BLOCKHEIGHT)==0)
271 					{
272 						if (grid[x+BLOCKWIDTH-1][y+BLOCKHEIGHT-1]==' ')
273 							grid[x][y]=' ';
274 					}
275 			letterstep++;
276 		}
277 		else if (letterstep==11)
278 		{
279 			//B
280 			flock[penguincount]=createpenguinxy(LXPOS(0),LYPOS(11)); penguincount++;
281 			flock[penguincount]=createpenguinxy(LXPOS(0),LYPOS(12)); penguincount++;
282 			flock[penguincount]=createpenguinxy(LXPOS(0),LYPOS(13)); penguincount++;
283 			flock[penguincount]=createpenguinxy(LXPOS(0),LYPOS(14)); penguincount++;
284 			flock[penguincount]=createpenguinxy(LXPOS(0),LYPOS(15)); penguincount++;
285 			flock[penguincount]=createpenguinxy(LXPOS(0),LYPOS(16)); penguincount++;
286 
287 			flock[penguincount]=createpenguinxy(LXPOS(1),LYPOS(11)); penguincount++;
288 			flock[penguincount]=createpenguinxy(LXPOS(2),LYPOS(11)); penguincount++;
289 
290 			flock[penguincount]=createpenguinxy(LXPOS(1),LYPOS(13)); penguincount++;
291 			flock[penguincount]=createpenguinxy(LXPOS(2),LYPOS(13)); penguincount++;
292 
293 			flock[penguincount]=createpenguinxy(LXPOS(1),LYPOS(16)); penguincount++;
294 			flock[penguincount]=createpenguinxy(LXPOS(2),LYPOS(16)); penguincount++;
295 
296 			flock[penguincount]=createpenguinxy(LXPOS(3),LYPOS(12)); penguincount++;
297 
298 			flock[penguincount]=createpenguinxy(LXPOS(3),LYPOS(14)); penguincount++;
299 			flock[penguincount]=createpenguinxy(LXPOS(3),LYPOS(15)); penguincount++;
300 
301 			//R
302 			flock[penguincount]=createpenguinxy(LXPOS(5),LYPOS(11)); penguincount++;
303 			flock[penguincount]=createpenguinxy(LXPOS(5),LYPOS(12)); penguincount++;
304 			flock[penguincount]=createpenguinxy(LXPOS(5),LYPOS(13)); penguincount++;
305 			flock[penguincount]=createpenguinxy(LXPOS(5),LYPOS(14)); penguincount++;
306 			flock[penguincount]=createpenguinxy(LXPOS(5),LYPOS(15)); penguincount++;
307 			flock[penguincount]=createpenguinxy(LXPOS(5),LYPOS(16)); penguincount++;
308 
309 			flock[penguincount]=createpenguinxy(LXPOS(6),LYPOS(11)); penguincount++;
310 			flock[penguincount]=createpenguinxy(LXPOS(7),LYPOS(11)); penguincount++;
311 
312 			flock[penguincount]=createpenguinxy(LXPOS(6),LYPOS(13)); penguincount++;
313 			flock[penguincount]=createpenguinxy(LXPOS(7),LYPOS(13)); penguincount++;
314 
315 			flock[penguincount]=createpenguinxy(LXPOS(8),LYPOS(12)); penguincount++;
316 
317 			flock[penguincount]=createpenguinxy(LXPOS(8),LYPOS(14)); penguincount++;
318  			flock[penguincount]=createpenguinxy(LXPOS(8),LYPOS(15)); penguincount++;
319 			flock[penguincount]=createpenguinxy(LXPOS(8),LYPOS(16)); penguincount++;
320 
321 			//E
322 			flock[penguincount]=createpenguinxy(LXPOS(10),LYPOS(11)); penguincount++;
323 			flock[penguincount]=createpenguinxy(LXPOS(10),LYPOS(12)); penguincount++;
324 			flock[penguincount]=createpenguinxy(LXPOS(10),LYPOS(13)); penguincount++;
325 			flock[penguincount]=createpenguinxy(LXPOS(10),LYPOS(14)); penguincount++;
326 			flock[penguincount]=createpenguinxy(LXPOS(10),LYPOS(15)); penguincount++;
327 			flock[penguincount]=createpenguinxy(LXPOS(10),LYPOS(16)); penguincount++;
328 
329 			flock[penguincount]=createpenguinxy(LXPOS(11),LYPOS(11)); penguincount++;
330 			flock[penguincount]=createpenguinxy(LXPOS(12),LYPOS(11)); penguincount++;
331 
332 			flock[penguincount]=createpenguinxy(LXPOS(11),LYPOS(13)); penguincount++;
333 			flock[penguincount]=createpenguinxy(LXPOS(12),LYPOS(13)); penguincount++;
334 
335 			flock[penguincount]=createpenguinxy(LXPOS(11),LYPOS(16)); penguincount++;
336 			flock[penguincount]=createpenguinxy(LXPOS(12),LYPOS(16)); penguincount++;
337 
338 			//A
339 			flock[penguincount]=createpenguinxy(LXPOS(14),LYPOS(12)); penguincount++;
340 			flock[penguincount]=createpenguinxy(LXPOS(14),LYPOS(13)); penguincount++;
341 			flock[penguincount]=createpenguinxy(LXPOS(14),LYPOS(14)); penguincount++;
342 			flock[penguincount]=createpenguinxy(LXPOS(14),LYPOS(15)); penguincount++;
343 			flock[penguincount]=createpenguinxy(LXPOS(14),LYPOS(16)); penguincount++;
344 
345 			flock[penguincount]=createpenguinxy(LXPOS(17),LYPOS(12)); penguincount++;
346 			flock[penguincount]=createpenguinxy(LXPOS(17),LYPOS(13)); penguincount++;
347 			flock[penguincount]=createpenguinxy(LXPOS(17),LYPOS(14)); penguincount++;
348 			flock[penguincount]=createpenguinxy(LXPOS(17),LYPOS(15)); penguincount++;
349 			flock[penguincount]=createpenguinxy(LXPOS(17),LYPOS(16)); penguincount++;
350 
351 			flock[penguincount]=createpenguinxy(LXPOS(15),LYPOS(11)); penguincount++;
352 			flock[penguincount]=createpenguinxy(LXPOS(16),LYPOS(11)); penguincount++;
353 
354 			flock[penguincount]=createpenguinxy(LXPOS(15),LYPOS(13)); penguincount++;
355 			flock[penguincount]=createpenguinxy(LXPOS(16),LYPOS(13)); penguincount++;
356 
357 			//K
358 			flock[penguincount]=createpenguinxy(LXPOS(19),LYPOS(11)); penguincount++;
359 			flock[penguincount]=createpenguinxy(LXPOS(19),LYPOS(12)); penguincount++;
360 			flock[penguincount]=createpenguinxy(LXPOS(19),LYPOS(13)); penguincount++;
361 			flock[penguincount]=createpenguinxy(LXPOS(19),LYPOS(14)); penguincount++;
362 			flock[penguincount]=createpenguinxy(LXPOS(19),LYPOS(15)); penguincount++;
363 			flock[penguincount]=createpenguinxy(LXPOS(19),LYPOS(16)); penguincount++;
364 
365 			flock[penguincount]=createpenguinxy(LXPOS(20),LYPOS(13)); penguincount++;
366 			flock[penguincount]=createpenguinxy(LXPOS(21),LYPOS(12)); penguincount++;
367 			flock[penguincount]=createpenguinxy(LXPOS(22),LYPOS(11)); penguincount++;
368 
369 			flock[penguincount]=createpenguinxy(LXPOS(21),LYPOS(14)); penguincount++;
370 			flock[penguincount]=createpenguinxy(LXPOS(22),LYPOS(15)); penguincount++;
371 			flock[penguincount]=createpenguinxy(LXPOS(22),LYPOS(16)); penguincount++;
372 
373 			//E
374 			flock[penguincount]=createpenguinxy(LXPOS(24),LYPOS(11)); penguincount++;
375 			flock[penguincount]=createpenguinxy(LXPOS(24),LYPOS(12)); penguincount++;
376 			flock[penguincount]=createpenguinxy(LXPOS(24),LYPOS(13)); penguincount++;
377 			flock[penguincount]=createpenguinxy(LXPOS(24),LYPOS(14)); penguincount++;
378 			flock[penguincount]=createpenguinxy(LXPOS(24),LYPOS(15)); penguincount++;
379 			flock[penguincount]=createpenguinxy(LXPOS(24),LYPOS(16)); penguincount++;
380 
381 			flock[penguincount]=createpenguinxy(LXPOS(25),LYPOS(11)); penguincount++;
382 			flock[penguincount]=createpenguinxy(LXPOS(26),LYPOS(11)); penguincount++;
383 
384 			flock[penguincount]=createpenguinxy(LXPOS(25),LYPOS(13)); penguincount++;
385 			flock[penguincount]=createpenguinxy(LXPOS(26),LYPOS(13)); penguincount++;
386 
387 			flock[penguincount]=createpenguinxy(LXPOS(25),LYPOS(16)); penguincount++;
388 			flock[penguincount]=createpenguinxy(LXPOS(26),LYPOS(16)); penguincount++;
389 
390 			//R
391 			flock[penguincount]=createpenguinxy(LXPOS(28),LYPOS(11)); penguincount++;
392 			flock[penguincount]=createpenguinxy(LXPOS(28),LYPOS(12)); penguincount++;
393 			flock[penguincount]=createpenguinxy(LXPOS(28),LYPOS(13)); penguincount++;
394 			flock[penguincount]=createpenguinxy(LXPOS(28),LYPOS(14)); penguincount++;
395 			flock[penguincount]=createpenguinxy(LXPOS(28),LYPOS(15)); penguincount++;
396 			flock[penguincount]=createpenguinxy(LXPOS(28),LYPOS(16)); penguincount++;
397 
398 			flock[penguincount]=createpenguinxy(LXPOS(29),LYPOS(11)); penguincount++;
399 			flock[penguincount]=createpenguinxy(LXPOS(30),LYPOS(11)); penguincount++;
400 
401 			flock[penguincount]=createpenguinxy(LXPOS(29),LYPOS(13)); penguincount++;
402 			flock[penguincount]=createpenguinxy(LXPOS(30),LYPOS(13)); penguincount++;
403 
404 			flock[penguincount]=createpenguinxy(LXPOS(31),LYPOS(12)); penguincount++;
405 
406 			flock[penguincount]=createpenguinxy(LXPOS(31),LYPOS(14)); penguincount++;
407  			flock[penguincount]=createpenguinxy(LXPOS(31),LYPOS(15)); penguincount++;
408 			flock[penguincount]=createpenguinxy(LXPOS(31),LYPOS(16)); penguincount++;
409 
410 			if (penguincount>=MAXPENGUINS) { fprintf(stderr,"Too many penguins!\n"); }
411 
412 			for (i=0;i<penguincount;i++)
413 			{
414 				savebehindpenguin(&flock[i]);
415 				markgrid(flock[i].geom.x,flock[i].geom.y,BLOCKWIDTH,BLOCKHEIGHT,'*');
416 				drawpenguin(&flock[i]);
417 				soil(flock[i].geom);
418 			}
419 
420 
421 			letterstep++;
422 		}
423 		else if (letterstep<300)
424 		{
425 			letterstep++;
426 		}
427 		else if (letterstep==300)
428 		{
429 			frozen=false;
430 			for (i=0;i<penguincount;i++)
431 			{
432 				markgrid(flock[i].geom.x,flock[i].geom.y,BLOCKWIDTH,BLOCKHEIGHT,' ');
433 				erasepenguin(&flock[i]);
434 				soil(flock[i].geom);
435 			}
436 			letterstep++;
437 			setcursor(CURSORCLICK);
438 		}
439 		else if (letterstep<400)
440 		{
441 			letterstep++;
442 		}
443 		else if (letterstep==400)
444 		{
445 			if (penguincount)
446 			{
447 				penguincount--;
448 				markgrid(flock[penguincount].geom.x,flock[penguincount].geom.y,BLOCKWIDTH,BLOCKHEIGHT,' ');
449 				erasepenguin(&flock[penguincount]);
450 				soil(flock[penguincount].geom);
451 				deletepenguin(&flock[penguincount]);
452 			}
453 			else
454 			{
455 				letterstep++;
456 			}
457 		}
458 		else if (letterstep<800)
459 		{
460 			if (!line1.on && !line2.on)
461 			{
462 				x=LXPOS(random() % 32);
463 				y=LYPOS(random() % 20);
464 				if (random()%2)
465 				{
466 					startline(&line1,UP,x,y);
467 					startline(&line2,DOWN,x,y);
468 				}
469 				else
470 				{
471 					startline(&line1,LEFT,x,y);
472 					startline(&line2,RIGHT,x,y);
473 				}
474 
475 			}
476 		}
477 		//else if (letterstep<2000)
478 		//{
479 		//	letterstep++;
480 		//}
481 		//else
482 		//{
483 		//	done=true;
484 		//}
485 
486 
487 		hiscorestep--;
488 		if (hiscorestep<0)
489 		{
490 			circularblit(scoresurface,&scrollrect,hiscorescroll);
491 			soil(scrollrect);
492 			hiscorescroll++;
493 			hiscorestep=2;
494 		}
495 		if (hiscorescroll >= scoresurface->w)
496 		{
497 			hiscorescroll=0;
498 		}
499 
500 		// move split-lines
501 		if (line1.on)
502 		{
503 			if (moveline(&line1))
504 			{
505 				linedone1=true;
506 			}
507 			if (line1.dead) // need a second check because moveline could change this
508 			{
509 				//no sound in intro?
510 				//playsound(SNDBREAK);
511 				killline(&line1);
512 				linedone1=false;
513 			}
514 		}
515 		if (line2.on)
516 		{
517 
518 			if (moveline(&line2))
519 			{
520 				linedone2=true;
521 
522 			}
523 			if (line2.dead)
524 			{
525 				// no sound in intro?
526 				//playsound(SNDBREAK);
527 				killline(&line2);
528 				linedone2=false;
529 			}
530 		}
531 		if (linedone1 && linedone2) { letterstep++; linedone1=false; linedone2=false; }
532 
533 
534 		// move (and get old background)
535 
536 		if (!frozen)
537 		{
538 			for (i=0;i<penguincount;i+=2)
539 			{
540 				soil(flock[i].geom); // mark the penguin's old position as dirty
541 				movepenguin(&flock[i]);
542 				soil(flock[i].geom); // mark the penguin's new position as dirty too (it will be soon...)
543 				savebehindpenguin(&flock[i]);
544 			}
545 		}
546 		soil(tux.geom); // mark the penguin's old position as dirty
547 		movepenguin(&tux);
548 		soil(tux.geom); // mark the penguin's new position as dirty too (it will be soon...)
549 		savebehindpenguin(&tux);
550 
551 		// actually draw
552 		if (!frozen)
553 		{
554 			for (i=0;i<penguincount;i+=2)
555 			{
556 				drawpenguin(&flock[i]);
557 			}
558 		}
559 		drawpenguin(&tux);
560 
561 		// update screen
562 		clean();
563 
564 		// clear for next update
565 		if (!frozen)
566 		{
567 			for (i=0;i<penguincount;i+=2)
568 			{
569 				erasepenguin(&flock[i]);
570 			}
571 		}
572 		erasepenguin(&tux);
573 
574 		SDL_Delay(10);
575 
576 	} while (!done);
577 
578 	clean();
579 
580 	while (penguincount)
581 	{
582 		penguincount--;
583 		deletepenguin(&flock[penguincount]);
584 	}
585 	deletepenguin(&tux);
586 
587 	// destroy highscore surface
588 	SDL_FreeSurface(scoresurface);
589 
590 	return(false);
591 }
592 
593 #define EXTRASCROLLSCORESPACE 30
594 // FIX -- the max username length is hardcoded at 50 in highscore.c, and as
595 // 12 in dialog.c. The 12 is so it fits in the dialog box nicely, and should
596 // be plenty long, but it's good to keep the buffer bigger. Anyway, the value
597 // in highscore.c should be a define, and this should be that-define + some
598 // reasonable value for the width of the score.
599 #define SCOREMAXLEN 70
600 
createscoresurface()601 SDL_Surface* createscoresurface()
602 {
603 	SDL_Surface* tmpsurface;
604 	char scoretext[SCOREMAXLEN];
605 	int i,len;
606 
607 	//caculate needed len
608 	len=0;
609 	for( i = 0 ; i < HISCORENUM ; i++)
610 	{
611 		snprintf(scoretext,SCOREMAXLEN,"#%d. %s: %ld",i+1,hiscorename[i],hiscoreval[i]);
612 		len += gettextwidth(2,scoretext);
613 	}
614 
615 	len += (HISCORENUM+1) * EXTRASCROLLSCORESPACE;
616 
617 	//alloc surface
618 	tmpsurface = SDL_CreateRGBSurface(SDL_SWSURFACE,len,CHARHEIGHT*2,VIDEODEPTH,0,0,0,0);
619 
620 	// fill surface
621 	SDL_FillRect(tmpsurface,NULL,color.background);
622 	len=0;
623 	for( i = 0 ; i < HISCORENUM ; i++)
624 	{
625 		snprintf(scoretext,SCOREMAXLEN,"#%d. %s: %ld",i+1,hiscorename[i],hiscoreval[i]);
626 		sputtext(tmpsurface,len,0,2,color.normaltext,scoretext);
627 		len += gettextwidth(2,scoretext) + EXTRASCROLLSCORESPACE;
628 	}
629 
630 	return tmpsurface;
631 }
632 
633 // this assumes that scoresurface->w > scrollrect->w
circularblit(SDL_Surface * scoresurface,SDL_Rect * scrollrect,Uint16 hiscorescroll)634 void circularblit(SDL_Surface* scoresurface,SDL_Rect* scrollrect,Uint16 hiscorescroll)
635 {
636 	SDL_Rect from,to;
637 	Sint32 len;
638 
639 	//calculate fiirst part w
640 	if( scoresurface->w - hiscorescroll < scrollrect->w)
641 		len = scoresurface->w - hiscorescroll;
642 	else
643 		len = scrollrect->w;
644 
645 	// draw first part to scoresurface
646 	from.x=hiscorescroll;
647 	from.y=0;
648 	from.w=len;
649 	from.h=scoresurface->h;
650 
651 	to.x=scrollrect->x;
652 	to.y=scrollrect->y;
653 	to.w=from.w;
654 	to.h=from.h;
655 
656 	SDL_BlitSurface(scoresurface,&from,screen,&to);
657 
658 	//if needed, draw second part to scoresurface
659 	if(len < scrollrect->w)
660 	{
661 	       	from.x=0;
662 	        from.y=0;
663 	        from.w=scrollrect->w - len;
664 	        from.h=scoresurface->h;
665 
666         	to.x=scrollrect->x + len;
667 	        to.y=scrollrect->y;
668 	        to.w=from.w;
669 	        to.h=from.h;
670 
671         	SDL_BlitSurface(scoresurface,&from,screen,&to);
672 	}
673 }
674