applied leveleditor and multiline-drawtext patches from Ricardo Cruz <rick2@aeiou...
[supertux.git] / src / gameloop.c
1 /*
2   gameloop.c
3   
4   Super Tux - Game Loop!
5   
6   by Bill Kendrick
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - December 29, 2003
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <time.h>
19 #include <SDL.h>
20
21 #ifdef LINUX
22 #include <pwd.h>
23 #include <sys/types.h>
24 #include <ctype.h>
25 #endif
26
27 #include "defines.h"
28 #include "globals.h"
29 #include "gameloop.h"
30 #include "screen.h"
31 #include "setup.h"
32 #include "high_scores.h"
33 #include "menu.h"
34 #include "badguy.h"
35 #include "world.h"
36 #include "player.h"
37 #include "level.h"
38
39 /* extern variables */
40
41 extern char* soundfilenames[NUM_SOUNDS];
42
43 /* Local variables: */
44
45 int score, highscore, distros, level, lives, scroll_x, next_level, game_pause,
46 done, quit, tux_dir, tux_size, tux_duck, tux_x, tux_xm, tux_y, tux_ym,
47 tux_dying, tux_safe, jumping, jump_counter, frame, score_multiplier,
48 tux_frame_main, tux_frame, tux_got_coffee, tux_skidding,
49 super_bkgd_time, tux_invincible_time, endpos,
50 counting_distros, distro_counter;
51 int left, right, up, down, fire, old_fire;
52 SDL_Surface * img_brick[2], * img_solid[4], * img_distro[4],
53 * img_waves[3], * img_water, * img_pole, * img_poletop, * img_flag[2];
54 SDL_Surface * img_bkgd[2][4];
55 SDL_Surface * img_golden_herring;
56 SDL_Surface * img_bsod_left[4], * img_bsod_right[4],
57 * img_laptop_left[3], * img_laptop_right[3],
58 * img_money_left[2], * img_money_right[2];
59 SDL_Surface * img_bsod_squished_left, * img_bsod_squished_right,
60 * img_bsod_falling_left, * img_bsod_falling_right,
61 * img_laptop_flat_left, * img_laptop_flat_right,
62 * img_laptop_falling_left, * img_laptop_falling_right;
63 SDL_Surface * img_box_full, * img_box_empty, * img_mints, * img_coffee,
64 * img_super_bkgd, * img_bullet, * img_red_glow;
65 SDL_Surface * img_cloud[2][4];
66 SDL_Surface * tux_life,
67 * tux_right[3], * tux_left[3],
68 * bigtux_right[3], * bigtux_left[3],
69 * bigtux_right_jump, * bigtux_left_jump,
70 * ducktux_right, * ducktux_left,
71 * skidtux_right, * skidtux_left,
72 * firetux_right[3], * firetux_left[3],
73 * bigfiretux_right[3], * bigfiretux_left[3],
74 * bigfiretux_right_jump, * bigfiretux_left_jump,
75 * duckfiretux_right, * duckfiretux_left,
76 * skidfiretux_right, * skidfiretux_left,
77 * cape_right[2], * cape_left[2],
78 * bigcape_right[2], * bigcape_left[2];
79 SDL_Event event;
80 SDL_Rect src, dest;
81 SDLKey key;
82 bouncy_distro_type bouncy_distros[NUM_BOUNCY_DISTROS];
83 broken_brick_type broken_bricks[NUM_BROKEN_BRICKS];
84 bouncy_brick_type bouncy_bricks[NUM_BOUNCY_BRICKS];
85 bad_guy_type bad_guys[NUM_BAD_GUYS];
86 floating_score_type floating_scores[NUM_FLOATING_SCORES];
87 upgrade_type upgrades[NUM_UPGRADES];
88 bullet_type bullets[NUM_BULLETS];
89 st_level current_level;
90 char level_subset[100];
91 char str[60];
92
93
94 /* Local function prototypes: */
95
96 void levelintro(void);
97 void set_default(void);
98 void initgame(void);
99 void loadlevelgfx(void);
100 void loadlevelsong(void);
101 void unloadlevelgfx(void);
102 void unloadlevelsong(void);
103 void loadshared(void);
104 void unloadshared(void);
105 void drawshape(int x, int y, unsigned char c);
106 unsigned char shape(int x, int y, int sx);
107 int issolid(int x, int y, int sx);
108 int isbrick(int x, int y, int sx);
109 int isice(int x, int y, int sx);
110 int isfullbox(int x, int y, int sx);
111 void change(int x, int y, int sx, unsigned char c);
112 void trybreakbrick(int x, int y, int sx);
113 void bumpbrick(int x, int y, int sx);
114 void tryemptybox(int x, int y, int sx);
115 void trygrabdistro(int x, int y, int sx, int bounciness);
116 void add_bouncy_distro(int x, int y);
117 void add_broken_brick(int x, int y);
118 void add_broken_brick_piece(int x, int y, int xm, int ym);
119 void add_bouncy_brick(int x, int y);
120 void add_bad_guy(int x, int y, int kind);
121 void add_score(int x, int y, int s);
122 void trybumpbadguy(int x, int y, int sx);
123 void add_upgrade(int x, int y, int kind);
124 void killtux(int mode);
125 void remove_powerups(void);
126 void add_bullet(int x, int y, int dir, int xm);
127 void drawendscreen(void);
128 void drawresultscreen(void);
129
130 void levelintro(void)
131 {
132   /* Level Intro: */
133
134   clearscreen(0, 0, 0);
135
136   sprintf(str, "LEVEL %d", level);
137   drawcenteredtext(str, 200, letters_red, NO_UPDATE, 1);
138
139   sprintf(str, "%s", current_level.name);
140   drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
141
142   sprintf(str, "TUX x %d", lives);
143   drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
144
145   SDL_Flip(screen);
146
147   SDL_Delay(1000);
148 }
149
150 void set_defaults(void)
151 {
152   int i;
153   
154   /* Reset arrays: */
155
156   for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
157     bouncy_distros[i].alive = NO;
158
159   for (i = 0; i < NUM_BROKEN_BRICKS; i++)
160     broken_bricks[i].alive = NO;
161
162   for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
163     bouncy_bricks[i].alive = NO;
164
165   for (i = 0; i < NUM_BAD_GUYS; i++)
166     bad_guys[i].alive = NO;
167
168   for (i = 0; i < NUM_FLOATING_SCORES; i++)
169     floating_scores[i].alive = NO;
170
171   for (i = 0; i < NUM_UPGRADES; i++)
172     upgrades[i].alive = NO;
173
174   for (i = 0; i < NUM_BULLETS; i++)
175     bullets[i].alive = NO;
176
177
178   /* Set defaults: */
179
180   tux_x = 0;
181   tux_xm = 0;
182   tux_y = 240;
183   tux_ym = 0;
184   tux_dir = RIGHT;
185   tux_invincible_time = 0;
186   tux_duck = NO;
187
188   tux_dying = NO;
189   tux_safe = TUX_SAFE_TIME;
190
191   jumping = NO;
192   jump_counter = 0;
193
194   tux_skidding = 0;
195
196   scroll_x = 0;
197
198   right = UP;
199   left = UP;
200   up = UP;
201   down = UP;
202   fire = UP;
203   old_fire = UP;
204
205   score_multiplier = 1;
206   super_bkgd_time = 0;
207
208   counting_distros = NO;
209   distro_counter = 0;
210
211   endpos = 0;
212
213   /* set current song/music */
214   current_music = LEVEL_MUSIC;
215 }
216
217 void activate_bad_guys(void)
218 {
219 int x,y;
220
221   /* Activate bad guys: */
222
223   for (y = 0; y < 15; y++)
224     {
225       for (x = 0; x < current_level.width; x++)
226         {
227           if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
228             {
229               add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
230               current_level.tiles[y][x] = '.';
231             }
232         }
233     }
234     
235 }
236
237 /* --- GAME EVENT! --- */
238
239 void game_event(void)
240 {
241
242   while (SDL_PollEvent(&event))
243     {
244
245       if (event.type == SDL_QUIT)
246         {
247           /* Quit event - quit: */
248
249           quit = 1;
250         }
251       else if (event.type == SDL_KEYDOWN)
252         {
253           /* A keypress! */
254
255           key = event.key.keysym.sym;
256
257           /* Check for menu-events, if the menu is shown */
258           if(show_menu)
259             menu_event(key);
260
261           if (key == SDLK_ESCAPE)
262             {
263               /* Escape: Open/Close the menu: */
264               if(!game_pause)
265                 {
266                   if(show_menu)
267                     show_menu = 0;
268                   else
269                     show_menu = 1;
270                 }
271             }
272           else if (key == SDLK_RIGHT)
273             {
274               right = DOWN;
275             }
276           else if (key == SDLK_LEFT)
277             {
278               left = DOWN;
279             }
280           else if (key == SDLK_UP)
281             {
282               up = DOWN;
283             }
284           else if (key == SDLK_DOWN)
285             {
286               down = DOWN;
287             }
288           else if (key == SDLK_LCTRL)
289             {
290               fire = DOWN;
291             }
292         }
293       else if (event.type == SDL_KEYUP)
294         {
295           /* A keyrelease! */
296
297           key = event.key.keysym.sym;
298
299           if (key == SDLK_RIGHT)
300             {
301               right = UP;
302             }
303           else if (key == SDLK_LEFT)
304             {
305               left = UP;
306             }
307           else if (key == SDLK_UP)
308             {
309               up = UP;
310             }
311           else if (key == SDLK_DOWN)
312             {
313               down = UP;
314             }
315           else if (key == SDLK_LCTRL)
316             {
317               fire = UP;
318             }
319           else if (key == SDLK_p)
320             {
321               if(!show_menu)
322                 {
323                   if(game_pause)
324                     game_pause = 0;
325                   else
326                     game_pause = 1;
327                 }
328             }
329           else if (key == SDLK_TAB && debug_mode == YES)
330             {
331               tux_size = !tux_size;
332             }
333           else if (key == SDLK_END && debug_mode == YES)
334             {
335               distros += 50;
336             }
337           else if (key == SDLK_SPACE && debug_mode == YES)
338             {
339               next_level = 1;
340             }
341         }
342 #ifdef JOY_YES
343       else if (event.type == SDL_JOYAXISMOTION)
344         {
345           if (event.jaxis.axis == JOY_X)
346             {
347               if (event.jaxis.value < -256)
348                 left = DOWN;
349               else
350                 left = UP;
351
352               if (event.jaxis.value > 256)
353                 right = DOWN;
354               else
355                 right = UP;
356             }
357           else if (event.jaxis.axis == JOY_Y)
358             {
359               if (event.jaxis.value > 256)
360                 down = DOWN;
361               else
362                 down = UP;
363
364               /* Handle joystick for the menu */
365               if(show_menu)
366                 {
367                   if(down == DOWN)
368                     menuaction = MN_DOWN;
369                   else
370                     menuaction = MN_UP;
371                 }
372             }
373         }
374       else if (event.type == SDL_JOYBUTTONDOWN)
375         {
376           if (event.jbutton.button == JOY_A)
377             up = DOWN;
378           else if (event.jbutton.button == JOY_B)
379             fire = DOWN;
380         }
381       else if (event.type == SDL_JOYBUTTONUP)
382         {
383           if (event.jbutton.button == JOY_A)
384             up = UP;
385           else if (event.jbutton.button == JOY_B)
386             fire = UP;
387
388           if(show_menu)
389             menuaction = MN_HIT;
390
391         }
392 #endif
393
394     }
395
396 }
397
398 /* --- GAME ACTION! --- */
399
400 int game_action(void)
401 {
402   int i,j;
403
404   /* --- HANDLE TUX! --- */
405
406   /* Handle key and joystick state: */
407
408   if (!(tux_dying || next_level))
409     {
410       if (right == DOWN && left == UP)
411         {
412           if (jumping == NO)
413             {
414               if (tux_xm < -SKID_XM && !tux_skidding &&
415                   tux_dir == LEFT)
416                 {
417                   tux_skidding = SKID_TIME;
418
419                   play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
420
421                 }
422               tux_dir = RIGHT;
423             }
424
425           if (tux_xm < 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
426               !tux_skidding)
427             {
428               tux_xm = 0;
429             }
430
431           if (!tux_duck)
432             {
433               if (tux_dir == RIGHT)
434                 {
435                   /* Facing the direction we're jumping?  Go full-speed: */
436
437                   if (fire == UP)
438                     {
439                       tux_xm = tux_xm + WALK_SPEED;
440
441                       if (tux_xm > MAX_WALK_XM)
442                         tux_xm = MAX_WALK_XM;
443                     }
444                   else if (fire == DOWN)
445                     {
446                       tux_xm = tux_xm + RUN_SPEED;
447
448                       if (tux_xm > MAX_RUN_XM)
449                         tux_xm = MAX_RUN_XM;
450                     }
451                 }
452               else
453                 {
454                   /* Not facing the direction we're jumping?
455                   Go half-speed: */
456
457                   tux_xm = tux_xm + WALK_SPEED / 2;
458
459                   if (tux_xm > MAX_WALK_XM / 2)
460                     tux_xm = MAX_WALK_XM / 2;
461                 }
462             }
463         }
464       else if (left == DOWN && right == UP)
465         {
466           if (jumping == NO)
467             {
468               if (tux_xm > SKID_XM && !tux_skidding &&
469                   tux_dir == RIGHT)
470                 {
471                   tux_skidding = SKID_TIME;
472                   play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER);
473                 }
474               tux_dir = LEFT;
475             }
476
477           if (tux_xm > 0 && !isice(tux_x, tux_y + 32, scroll_x) &&
478               !tux_skidding)
479             {
480               tux_xm = 0;
481             }
482
483           if (!tux_duck)
484             {
485               if (tux_dir == LEFT)
486                 {
487                   /* Facing the direction we're jumping?  Go full-speed: */
488
489                   if (fire == UP)
490                     {
491                       tux_xm = tux_xm - WALK_SPEED;
492
493                       if (tux_xm < -MAX_WALK_XM)
494                         tux_xm = -MAX_WALK_XM;
495                     }
496                   else if (fire == DOWN)
497                     {
498                       tux_xm = tux_xm - RUN_SPEED;
499
500                       if (tux_xm < -MAX_RUN_XM)
501                         tux_xm = -MAX_RUN_XM;
502                     }
503                 }
504               else
505                 {
506                   /* Not facing the direction we're jumping?
507                   Go half-speed: */
508
509                   tux_xm = tux_xm - WALK_SPEED / 2;
510
511                   if (tux_xm < -MAX_WALK_XM / 2)
512                     tux_xm = -MAX_WALK_XM / 2;
513                 }
514             }
515         }
516
517
518       /* End of level? */
519
520       if (tux_x >= endpos && endpos != 0)
521         {
522           next_level = 1;
523         }
524
525
526       /* Jump/jumping? */
527
528       if (up == DOWN)
529         {
530           if (jump_counter == 0)
531             {
532               /* Taking off? */
533
534               if (!issolid(tux_x, tux_y + 32, scroll_x) ||
535                   tux_ym != 0)
536                 {
537                   /* If they're not on the ground, or are currently moving
538                   vertically, don't jump! */
539
540                   jump_counter = MAX_JUMP_COUNT;
541                 }
542               else
543                 {
544                   /* Make sure we're not standing back up into a solid! */
545
546                   if (tux_size == SMALL || tux_duck == NO ||
547                       !issolid(tux_x, tux_y, scroll_x))
548                     {
549                       jumping = YES;
550
551                       if (tux_size == SMALL)
552                         play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER);
553                       else
554                         play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER);
555                     }
556                 }
557             }
558
559
560           /* Keep jumping for a while: */
561
562           if (jump_counter < MAX_JUMP_COUNT)
563             {
564               tux_ym = tux_ym - JUMP_SPEED;
565               jump_counter++;
566             }
567         }
568       else
569         jump_counter = 0;
570
571
572       /* Shoot! */
573
574       if (fire == DOWN && old_fire == UP && tux_got_coffee)
575         {
576           add_bullet(tux_x + scroll_x, tux_y, tux_dir, tux_xm);
577         }
578
579
580       /* Duck! */
581
582       if (down == DOWN)
583         {
584           if (tux_size == BIG)
585             tux_duck = YES;
586         }
587       else
588         {
589           if (tux_size == BIG && tux_duck == YES)
590             {
591               /* Make sure we're not standing back up into a solid! */
592
593               if (!issolid(tux_x, tux_y - 32, scroll_x))
594                 tux_duck = NO;
595             }
596           else
597             tux_duck = NO;
598         }
599     } /* (tux_dying || next_level) */
600   else
601     {
602       /* Tux either died, or reached the end of a level! */
603
604
605       if (playing_music())
606         halt_music();
607
608
609       if (next_level)
610         {
611           /* End of a level! */
612           level++;
613           next_level = 0;
614           drawresultscreen();
615         }
616       else
617         {
618
619           tux_ym = tux_ym + GRAVITY;
620
621
622
623           /* He died :^( */
624
625           --lives;
626           remove_powerups();
627
628           /* No more lives!? */
629
630           if (lives < 0)
631             {
632               drawendscreen();
633
634               if (score > highscore)
635                 save_hs(score);
636
637               unloadlevelgfx();
638               unloadlevelsong();
639               unloadshared();
640               return(0);
641             } /* if (lives < 0) */
642         }
643
644       /* Either way, (re-)load the (next) level... */
645
646       set_defaults();
647       loadlevel(&current_level,"default",level);
648       activate_bad_guys();
649       unloadlevelgfx();
650       loadlevelgfx();
651       unloadlevelsong();
652       loadlevelsong();
653       levelintro();
654     }
655
656   /* Move tux: */
657
658   tux_x = tux_x + tux_xm;
659   tux_y = tux_y + tux_ym;
660
661
662   /* Keep tux in bounds: */
663   if (tux_x < 0)
664     tux_x = 0;
665   else if (tux_x < 160 && scroll_x > 0 && debug_mode == YES)
666     {
667       scroll_x = scroll_x - ( 160 - tux_x);
668       tux_x = 160;
669
670       if(scroll_x < 0)
671         scroll_x = 0;
672
673     }
674   else if (tux_x > 320 && scroll_x < ((current_level.width * 32) - 640))
675     {
676       /* Scroll the screen in past center: */
677
678       scroll_x = scroll_x + (tux_x - 320);
679       tux_x = 320;
680
681       if (scroll_x > ((current_level.width * 32) - 640))
682         scroll_x = ((current_level.width * 32) - 640);
683     }
684   else if (tux_x > 608)
685     {
686       /* ... unless there's no more to scroll! */
687
688       tux_x = 608;
689     }
690
691
692   /* Land: */
693
694   if (!tux_dying)
695     {
696       if (issolid(tux_x, tux_y + 31, scroll_x) &&
697           !issolid(tux_x - tux_xm, tux_y + 31, scroll_x))
698         {
699           while (issolid(tux_x, tux_y + 31, scroll_x))
700             {
701               if (tux_xm < 0)
702                 tux_x++;
703               else if (tux_xm > 0)
704                 tux_x--;
705             }
706
707           tux_xm = 0;
708         }
709
710       if (issolid(tux_x, tux_y, scroll_x) &&
711           !issolid(tux_x - tux_xm, tux_y, scroll_x))
712         {
713           while (issolid(tux_x, tux_y, scroll_x))
714             {
715               if (tux_xm < 0)
716                 tux_x++;
717               else if (tux_xm > 0)
718                 tux_x--;
719             }
720
721           tux_xm = 0;
722         }
723
724       if (issolid(tux_x, tux_y + 31, scroll_x))
725         {
726           /* Set down properly: */
727
728           while (issolid(tux_x, tux_y + 31, scroll_x))
729             {
730               if (tux_ym < 0)
731                 tux_y++;
732               else if (tux_ym > 0)
733                 tux_y--;
734             }
735
736
737           /* Reset score multiplier (for mutli-hits): */
738
739           if (tux_ym > 0)
740             score_multiplier = 1;
741
742
743           /* Stop jumping! */
744
745           tux_ym = 0;
746           jumping = NO;
747         }
748
749
750       /* Bump into things: */
751
752       if (issolid(tux_x, tux_y, scroll_x) ||
753           (tux_size == BIG && !tux_duck &&
754            (issolid(tux_x, tux_y - 32, scroll_x))))
755         {
756           if (!issolid(tux_x - tux_xm, tux_y, scroll_x) &&
757               (tux_size == SMALL || tux_duck ||
758                !issolid(tux_x - tux_xm, tux_y - 32, scroll_x)))
759             {
760               tux_x = tux_x - tux_xm;
761               tux_xm = 0;
762             }
763           else if (!issolid(tux_x, tux_y - tux_ym, scroll_x) &&
764                    (tux_size == SMALL || tux_duck ||
765                     !issolid(tux_x, tux_y - 32 - tux_ym, scroll_x)))
766             {
767               if (tux_ym <= 0)
768                 {
769                   /* Jumping up? */
770
771                   if (tux_size == BIG)
772                     {
773                       /* Break bricks and empty boxes: */
774
775                       if (!tux_duck)
776                         {
777                           if (isbrick(tux_x, tux_y - 32, scroll_x) ||
778                               isfullbox(tux_x, tux_y - 32, scroll_x))
779                             {
780                               trygrabdistro(tux_x, tux_y - 64, scroll_x,
781                                             BOUNCE);
782                               trybumpbadguy(tux_x, tux_y - 96, scroll_x);
783
784                               if (isfullbox(tux_x, tux_y - 32,
785                                             scroll_x))
786                                 {
787                                   bumpbrick(tux_x, tux_y - 32,
788                                             scroll_x);
789                                 }
790
791                               trybreakbrick(tux_x, tux_y - 32, scroll_x);
792                               tryemptybox(tux_x, tux_y - 32, scroll_x);
793                             }
794
795                           if (isbrick(tux_x + 31, tux_y - 32, scroll_x) ||
796                               isfullbox(tux_x + 31, tux_y - 32, scroll_x))
797                             {
798                               trygrabdistro(tux_x + 31,
799                                             tux_y - 64,
800                                             scroll_x,
801                                             BOUNCE);
802                               trybumpbadguy(tux_x + 31,
803                                             tux_y - 96,
804                                             scroll_x);
805
806                               if (isfullbox(tux_x + 31, tux_y - 32,
807                                             scroll_x))
808                                 {
809                                   bumpbrick(tux_x + 31, tux_y - 32,
810                                             scroll_x);
811                                 }
812
813                               trybreakbrick(tux_x + 31,
814                                             tux_y - 32,
815                                             scroll_x);
816                               tryemptybox(tux_x + 31,
817                                           tux_y - 32,
818                                           scroll_x);
819                             }
820                         }
821                       else /* ducking */
822                         {
823                           if (isbrick(tux_x, tux_y, scroll_x) ||
824                               isfullbox(tux_x, tux_y, scroll_x))
825                             {
826                               trygrabdistro(tux_x, tux_y - 32, scroll_x,
827                                             BOUNCE);
828                               trybumpbadguy(tux_x, tux_y - 64, scroll_x);
829                               if (isfullbox(tux_x, tux_y, scroll_x))
830                                 bumpbrick(tux_x, tux_y, scroll_x);
831                               trybreakbrick(tux_x, tux_y, scroll_x);
832                               tryemptybox(tux_x, tux_y, scroll_x);
833                             }
834
835                           if (isbrick(tux_x + 31, tux_y, scroll_x) ||
836                               isfullbox(tux_x + 31, tux_y, scroll_x))
837                             {
838                               trygrabdistro(tux_x + 31,
839                                             tux_y - 32,
840                                             scroll_x,
841                                             BOUNCE);
842                               trybumpbadguy(tux_x + 31,
843                                             tux_y - 64,
844                                             scroll_x);
845                               if (isfullbox(tux_x + 31, tux_y, scroll_x))
846                                 bumpbrick(tux_x + 31, tux_y, scroll_x);
847                               trybreakbrick(tux_x + 31, tux_y, scroll_x);
848                               tryemptybox(tux_x + 31, tux_y, scroll_x);
849                             }
850                         }
851                     }
852                   else
853                     {
854                       /* It's a brick and we're small, make the brick
855                          bounce, and grab any distros above it: */
856
857                       if (isbrick(tux_x, tux_y, scroll_x) ||
858                           isfullbox(tux_x, tux_y, scroll_x))
859                         {
860                           trygrabdistro(tux_x, tux_y - 32, scroll_x,
861                                         BOUNCE);
862                           trybumpbadguy(tux_x, tux_y - 64, scroll_x);
863                           bumpbrick(tux_x, tux_y, scroll_x);
864                           tryemptybox(tux_x, tux_y, scroll_x);
865                         }
866
867                       if (isbrick(tux_x + 31, tux_y, scroll_x) ||
868                           isfullbox(tux_x + 31, tux_y, scroll_x))
869                         {
870                           trygrabdistro(tux_x + 31, tux_y - 32, scroll_x,
871                                         BOUNCE);
872                           trybumpbadguy(tux_x + 31, tux_y - 64, scroll_x);
873                           bumpbrick(tux_x + 31, tux_y, scroll_x);
874                           tryemptybox(tux_x + 31, tux_y, scroll_x);
875                         }
876
877
878                       /* Get a distro from a brick? */
879
880                       if (shape(tux_x, tux_y, scroll_x) == 'x' ||
881                           shape(tux_x, tux_y, scroll_x) == 'y')
882                         {
883                           add_bouncy_distro(((tux_x + scroll_x + 1)
884                                              / 32) * 32,
885                                             (tux_y / 32) * 32);
886
887                           if (counting_distros == NO)
888                             {
889                               counting_distros = YES;
890                               distro_counter = 100;
891                             }
892
893                           if (distro_counter <= 0)
894                             change(tux_x, tux_y, scroll_x, 'a');
895
896                           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
897                           score = score + SCORE_DISTRO;
898                           distros++;
899                         }
900                       else if (shape(tux_x + 31, tux_y, scroll_x) == 'x' ||
901                                shape(tux_x + 31, tux_y, scroll_x) == 'y')
902                         {
903                           add_bouncy_distro(((tux_x + scroll_x + 1 + 31)
904                                              / 32) * 32,
905                                             (tux_y / 32) * 32);
906
907                           if (counting_distros == NO)
908                             {
909                               counting_distros = YES;
910                               distro_counter = 100;
911                             }
912
913                           if (distro_counter <= 0)
914                             change(tux_x + 31, tux_y, scroll_x, 'a');
915
916                           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
917                           score = score + SCORE_DISTRO;
918                           distros++;
919                         }
920                     }
921
922
923                   /* Bump head: */
924
925                   tux_y = (tux_y / 32) * 32 + 30;
926                 }
927               else
928                 {
929                   /* Land on feet: */
930
931                   tux_y = (tux_y / 32) * 32 - 32;
932                 }
933
934               tux_ym = 0;
935               jumping = NO;
936               jump_counter = MAX_JUMP_COUNT;
937             }
938         }
939     }
940
941
942   /* Grab distros: */
943
944   if (!tux_dying)
945     {
946       trygrabdistro(tux_x, tux_y, scroll_x, NO_BOUNCE);
947       trygrabdistro(tux_x + 31, tux_y, scroll_x, NO_BOUNCE);
948
949       if (tux_size == BIG && !tux_duck)
950         {
951           trygrabdistro(tux_x, tux_y - 32, scroll_x, NO_BOUNCE);
952           trygrabdistro(tux_x + 31, tux_y - 32, scroll_x, NO_BOUNCE);
953         }
954     }
955
956
957   /* Enough distros for a One-up? */
958
959   if (distros >= DISTROS_LIFEUP)
960     {
961       distros = distros - DISTROS_LIFEUP;
962       if(lives < MAX_LIVES)
963         lives++;
964       /*We want to hear the sound even, if MAX_LIVES is reached*/
965       play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER);
966     }
967
968
969   /* Keep in-bounds, vertically: */
970
971   if (tux_y < 0)
972     tux_y = 0;
973   else if (tux_y > 480)
974     {
975       killtux(KILL);
976     }
977
978
979   /* Slow down horizontally: */
980
981   if (!tux_dying)
982     {
983       if (right == UP && left == UP)
984         {
985           if (isice(tux_x, tux_y + 32, scroll_x) ||
986               !issolid(tux_x, tux_y + 32, scroll_x))
987             {
988               /* Slowly on ice or in air: */
989
990               if (tux_xm > 0)
991                 tux_xm--;
992               else if (tux_xm < 0)
993                 tux_xm++;
994             }
995           else
996             {
997               /* Quickly, otherwise: */
998
999               tux_xm = tux_xm / 2;
1000             }
1001         }
1002
1003
1004       /* Drop vertically: */
1005
1006       if (!issolid(tux_x, tux_y + 32, scroll_x))
1007         {
1008           tux_ym = tux_ym + GRAVITY;
1009
1010           if (tux_ym > MAX_YM)
1011             tux_ym = MAX_YM;
1012         }
1013     }
1014
1015
1016   if (tux_safe > 0)
1017     tux_safe--;
1018
1019
1020   /* ---- DONE HANDLING TUX! --- */
1021
1022
1023   /* Handle bouncy distros: */
1024
1025   for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
1026     {
1027       if (bouncy_distros[i].alive)
1028         {
1029           bouncy_distros[i].y = bouncy_distros[i].y + bouncy_distros[i].ym;
1030
1031           bouncy_distros[i].ym++;
1032
1033           if (bouncy_distros[i].ym >= 0)
1034             bouncy_distros[i].alive = NO;
1035         }
1036     }
1037
1038
1039   /* Handle broken bricks: */
1040
1041   for (i = 0; i < NUM_BROKEN_BRICKS; i++)
1042     {
1043       if (broken_bricks[i].alive)
1044         {
1045           broken_bricks[i].x = broken_bricks[i].x + broken_bricks[i].xm;
1046           broken_bricks[i].y = broken_bricks[i].y + broken_bricks[i].ym;
1047
1048           broken_bricks[i].ym++;
1049
1050           if (broken_bricks[i].ym >= 0)
1051             broken_bricks[i].alive = NO;
1052         }
1053     }
1054
1055
1056   /* Handle distro counting: */
1057
1058   if (counting_distros == YES)
1059     {
1060       distro_counter--;
1061
1062       if (distro_counter <= 0)
1063         counting_distros = -1;
1064     }
1065
1066
1067   /* Handle bouncy bricks: */
1068
1069   for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1070     {
1071       if (bouncy_bricks[i].alive)
1072         {
1073           bouncy_bricks[i].offset = (bouncy_bricks[i].offset +
1074                                      bouncy_bricks[i].offset_m);
1075
1076           /* Go back down? */
1077
1078           if (bouncy_bricks[i].offset < -BOUNCY_BRICK_MAX_OFFSET)
1079             bouncy_bricks[i].offset_m = BOUNCY_BRICK_SPEED;
1080
1081
1082           /* Stop bouncing? */
1083
1084           if (bouncy_bricks[i].offset == 0)
1085             bouncy_bricks[i].alive = NO;
1086         }
1087     }
1088
1089
1090   /* Handle floating scores: */
1091
1092   for (i = 0; i < NUM_FLOATING_SCORES; i++)
1093     {
1094       if (floating_scores[i].alive)
1095         {
1096           floating_scores[i].y = floating_scores[i].y - 2;
1097           floating_scores[i].timer--;
1098
1099           if (floating_scores[i].timer <= 0)
1100             floating_scores[i].alive = NO;
1101         }
1102     }
1103
1104
1105   /* Handle bullets: */
1106
1107   for (i = 0; i < NUM_BULLETS; i++)
1108     {
1109       if (bullets[i].alive)
1110         {
1111           bullets[i].x = bullets[i].x + bullets[i].xm;
1112           bullets[i].y = bullets[i].y + bullets[i].ym;
1113
1114           if (issolid(bullets[i].x, bullets[i].y, 0))
1115             {
1116               if (issolid(bullets[i].x, bullets[i].y - bullets[i].ym, 0))
1117                 bullets[i].alive = NO;
1118               else
1119                 {
1120                   if (bullets[i].ym >= 0)
1121                     {
1122                       bullets[i].y = (bullets[i].y / 32) * 32 - 8;
1123                     }
1124                   bullets[i].ym = -bullets[i].ym;
1125                 }
1126             }
1127
1128           bullets[i].ym = bullets[i].ym + GRAVITY;
1129
1130           if (bullets[i].x < scroll_x ||
1131               bullets[i].x > scroll_x + 640)
1132             {
1133               bullets[i].alive = NO;
1134             }
1135         }
1136
1137
1138       if (bullets[i].alive)
1139         {
1140           for (j = 0; j < NUM_BAD_GUYS; j++)
1141             {
1142               if (bad_guys[j].alive && !bad_guys[j].dying)
1143                 {
1144                   if (bullets[i].x >= bad_guys[j].x - 4 &&
1145                       bullets[i].x <= bad_guys[j].x + 32 + 4 &&
1146                       bullets[i].y >= bad_guys[j].y - 4 &&
1147                       bullets[i].y <= bad_guys[j].y + 32 + 4)
1148                     {
1149                       /* Kill the bad guy! */
1150
1151                       bullets[i].alive = 0;
1152                       bad_guys[j].dying = FALLING;
1153                       bad_guys[j].ym = -8;
1154
1155
1156                       /* Gain some points: */
1157
1158                       if (bad_guys[j].kind == BAD_BSOD)
1159                         {
1160                           add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1161                                     50 * score_multiplier);
1162                         }
1163                       else if (bad_guys[j].kind == BAD_LAPTOP)
1164                         {
1165                           add_score(bad_guys[j].x - scroll_x, bad_guys[j].y,
1166                                     25 * score_multiplier);
1167                         }
1168
1169
1170                       /* Play death sound: */
1171                       play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1172                     }
1173                 }
1174             }
1175         }
1176     }
1177
1178
1179   /* Handle background timer: */
1180
1181   if (super_bkgd_time)
1182     super_bkgd_time--;
1183
1184
1185   /* Handle invincibility timer: */
1186
1187
1188   if (tux_invincible_time > 50)
1189     {
1190       tux_invincible_time--;
1191
1192
1193       if (!playing_music())
1194         play_music( herring_song, 1 );
1195     }
1196   else
1197     {
1198       if (current_music == HERRING_MUSIC)
1199         {
1200           /* stop the herring_song, now play the level_song ! */
1201           current_music = LEVEL_MUSIC;
1202           halt_music();
1203         }
1204
1205       if (!playing_music())
1206         {
1207           if (current_level.time_left <= TIME_WARNING)
1208             play_music( level_song_fast, 1 );
1209           else
1210             play_music( level_song, 1 );
1211         }
1212
1213       if (tux_invincible_time > 0)
1214         tux_invincible_time--;
1215     }
1216
1217
1218   /* Handle upgrades: */
1219
1220   for (i = 0; i < NUM_UPGRADES; i++)
1221     {
1222       if (upgrades[i].alive)
1223         {
1224           if (upgrades[i].height < 32)
1225             {
1226               /* Rise up! */
1227
1228               upgrades[i].height++;
1229             }
1230           else
1231             {
1232               /* Move around? */
1233
1234               if (upgrades[i].kind == UPGRADE_MINTS ||
1235                   upgrades[i].kind == UPGRADE_HERRING)
1236                 {
1237                   upgrades[i].x = upgrades[i].x + upgrades[i].xm;
1238                   upgrades[i].y = upgrades[i].y + upgrades[i].ym;
1239
1240                   if (issolid(upgrades[i].x, upgrades[i].y + 31, 0) ||
1241                       issolid(upgrades[i].x + 31, upgrades[i].y + 31, 0))
1242                     {
1243                       if (upgrades[i].ym > 0)
1244                         {
1245                           if (upgrades[i].kind == UPGRADE_MINTS)
1246                             {
1247                               upgrades[i].ym = 0;
1248                             }
1249                           else if (upgrades[i].kind == UPGRADE_HERRING)
1250                             {
1251                               upgrades[i].ym = -24;
1252                             }
1253
1254                           upgrades[i].y = (upgrades[i].y / 32) * 32;
1255                         }
1256                     }
1257                   else
1258                     upgrades[i].ym = upgrades[i].ym + GRAVITY;
1259
1260                   if (issolid(upgrades[i].x, upgrades[i].y, 0))
1261                     {
1262                       upgrades[i].xm = -upgrades[i].xm;
1263                     }
1264                 }
1265
1266
1267               /* Off the screen?  Kill it! */
1268
1269               if (upgrades[i].x < scroll_x)
1270                 upgrades[i].alive = NO;
1271
1272
1273               /* Did the player grab it? */
1274
1275               if (tux_x + scroll_x >= upgrades[i].x - 32 &&
1276                   tux_x + scroll_x <= upgrades[i].x + 32 &&
1277                   tux_y >= upgrades[i].y - 32 &&
1278                   tux_y <= upgrades[i].y + 32)
1279                 {
1280                   /* Remove the upgrade: */
1281
1282                   upgrades[i].alive = NO;
1283
1284
1285                   /* Affect the player: */
1286
1287                   if (upgrades[i].kind == UPGRADE_MINTS)
1288                     {
1289                       play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER);
1290                       tux_size = BIG;
1291                       super_bkgd_time = 8;
1292                     }
1293                   else if (upgrades[i].kind == UPGRADE_COFFEE)
1294                     {
1295                       play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER);
1296                       tux_got_coffee = YES;
1297                       super_bkgd_time = 4;
1298                     }
1299                   else if (upgrades[i].kind == UPGRADE_HERRING)
1300                     {
1301                       play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER);
1302                       tux_invincible_time = TUX_INVINCIBLE_TIME;
1303                       super_bkgd_time = 4;
1304                       /* play the herring song ^^ */
1305                       current_music = HERRING_MUSIC;
1306                       if (playing_music())
1307                         halt_music();
1308                       play_music( herring_song, 1 );
1309                     }
1310                 }
1311             }
1312         }
1313     }
1314
1315
1316   /* Handle bad guys: */
1317
1318   for (i = 0; i < NUM_BAD_GUYS; i++)
1319     {
1320       if (bad_guys[i].alive)
1321         {
1322           if (bad_guys[i].seen)
1323             {
1324               if (bad_guys[i].kind == BAD_BSOD)
1325                 {
1326                   /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1327
1328                   /* Move left/right: */
1329
1330                   if (bad_guys[i].dying == NO ||
1331                       bad_guys[i].dying == FALLING)
1332                     {
1333                       if (bad_guys[i].dir == RIGHT)
1334                         bad_guys[i].x = bad_guys[i].x + 4;
1335                       else if (bad_guys[i].dir == LEFT)
1336                         bad_guys[i].x = bad_guys[i].x - 4;
1337                     }
1338
1339
1340                   /* Move vertically: */
1341
1342                   bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1343
1344
1345                   /* Bump into things horizontally: */
1346
1347                   if (!bad_guys[i].dying)
1348                     {
1349                       if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1350                         bad_guys[i].dir = !bad_guys[i].dir;
1351                     }
1352
1353
1354                   /* Bump into other bad guys: */
1355
1356                   for (j = 0; j < NUM_BAD_GUYS; j++)
1357                     {
1358                       if (j != i && bad_guys[j].alive &&
1359                           !bad_guys[j].dying && !bad_guys[i].dying &&
1360                           bad_guys[i].x >= bad_guys[j].x - 32 &&
1361                           bad_guys[i].x <= bad_guys[j].x + 32 &&
1362                           bad_guys[i].y >= bad_guys[j].y - 32 &&
1363                           bad_guys[i].y <= bad_guys[j].y + 32)
1364                         {
1365                           bad_guys[i].dir = !bad_guys[i].dir;
1366                         }
1367                     }
1368
1369
1370                   /* Fall if we get off the ground: */
1371
1372                   if (bad_guys[i].dying != FALLING)
1373                     {
1374                       if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1375                           bad_guys[i].ym < MAX_YM)
1376                         {
1377                           bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1378                         }
1379                       else
1380                         {
1381                           /* Land: */
1382
1383                           if (bad_guys[i].ym > 0)
1384                             {
1385                               bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1386                               bad_guys[i].ym = 0;
1387                             }
1388                         }
1389                     }
1390                   else
1391                     bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1392
1393                   if (bad_guys[i].y > 480)
1394                     bad_guys[i].alive = NO;
1395                 }
1396               else if (bad_guys[i].kind == BAD_LAPTOP)
1397                 {
1398                   /* --- LAPTOP MONSTER: --- */
1399
1400                   /* Move left/right: */
1401
1402                   if (bad_guys[i].mode != FLAT && bad_guys[i].mode != KICK)
1403                     {
1404                       if (bad_guys[i].dying == NO ||
1405                           bad_guys[i].dying == FALLING)
1406                         {
1407                           if (bad_guys[i].dir == RIGHT)
1408                             bad_guys[i].x = bad_guys[i].x + 4;
1409                           else if (bad_guys[i].dir == LEFT)
1410                             bad_guys[i].x = bad_guys[i].x - 4;
1411                         }
1412                     }
1413                   else if (bad_guys[i].mode == KICK)
1414                     {
1415                       if (bad_guys[i].dir == RIGHT)
1416                         bad_guys[i].x = bad_guys[i].x + 16;
1417                       else if (bad_guys[i].dir == LEFT)
1418                         bad_guys[i].x = bad_guys[i].x - 16;
1419                     }
1420
1421
1422                   /* Move vertically: */
1423
1424                   bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1425
1426
1427                   /* Bump into things horizontally: */
1428
1429                   if (!bad_guys[i].dying)
1430                     {
1431                       if (issolid(bad_guys[i].x, bad_guys[i].y, 0))
1432                         {
1433                           bad_guys[i].dir = !bad_guys[i].dir;
1434
1435                           if (bad_guys[i].mode == KICK)
1436                             {
1437                               /* handle stereo sound */
1438                               if (tux_x + scroll_x > bad_guys[i].x)
1439                                 play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
1440                               else if (tux_x + scroll_x < bad_guys[i].x)
1441                                 play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
1442                               else
1443                                 play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
1444                             }
1445                         }
1446                     }
1447
1448
1449                   /* Bump into other bad guys: */
1450
1451                   for (j = 0; j < NUM_BAD_GUYS; j++)
1452                     {
1453                       if (j != i && bad_guys[j].alive &&
1454                           !bad_guys[j].dying && !bad_guys[i].dying &&
1455                           bad_guys[i].x >= bad_guys[j].x - 32 &&
1456                           bad_guys[i].x <= bad_guys[j].x + 32 &&
1457                           bad_guys[i].y >= bad_guys[j].y - 32 &&
1458                           bad_guys[i].y <= bad_guys[j].y + 32)
1459                         {
1460                           if (bad_guys[i].mode != KICK)
1461                             bad_guys[i].dir = !bad_guys[i].dir;
1462                           else
1463                             {
1464                               /* We're in kick mode, kill the other guy: */
1465
1466                               bad_guys[j].dying = FALLING;
1467                               bad_guys[j].ym = -8;
1468                               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1469
1470                               add_score(bad_guys[i].x - scroll_x,
1471                                         bad_guys[i].y, 100);
1472                             }
1473                         }
1474                     }
1475
1476
1477                   /* Fall if we get off the ground: */
1478
1479                   if (bad_guys[i].dying != FALLING)
1480                     {
1481                       if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0) &&
1482                           bad_guys[i].ym < MAX_YM)
1483                         {
1484                           bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1485                         }
1486                       else
1487                         {
1488                           /* Land: */
1489
1490                           if (bad_guys[i].ym > 0)
1491                             {
1492                               bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1493                               bad_guys[i].ym = 0;
1494                             }
1495                         }
1496                     }
1497                   else
1498                     bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1499
1500                   if (bad_guys[i].y > 480)
1501                     bad_guys[i].alive = NO;
1502                 }
1503               else if (bad_guys[i].kind == BAD_MONEY)
1504                 {
1505                   /* --- MONEY BAGS: --- */
1506
1507
1508                   /* Move vertically: */
1509
1510                   bad_guys[i].y = bad_guys[i].y + bad_guys[i].ym;
1511
1512
1513                   /* Fall if we get off the ground: */
1514
1515                   if (bad_guys[i].dying != FALLING)
1516                     {
1517                       if (!issolid(bad_guys[i].x, bad_guys[i].y + 32, 0))
1518                         {
1519                           if (bad_guys[i].ym < MAX_YM)
1520                             {
1521                               bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1522                             }
1523                         }
1524                       else
1525                         {
1526                           /* Land: */
1527
1528                           if (bad_guys[i].ym > 0)
1529                             {
1530                               bad_guys[i].y = (bad_guys[i].y / 32) * 32;
1531                               bad_guys[i].ym = -MAX_YM;
1532                             }
1533                         }
1534                     }
1535                   else
1536                     bad_guys[i].ym = bad_guys[i].ym + GRAVITY;
1537
1538                   if (bad_guys[i].y > 480)
1539                     bad_guys[i].alive = NO;
1540                 }
1541               else if (bad_guys[i].kind == -1)
1542               {}
1543
1544
1545               /* Kill it if the player jumped on it: */
1546
1547               if (!bad_guys[i].dying && !tux_dying && !tux_safe &&
1548                   tux_x + scroll_x >= bad_guys[i].x - 32 &&
1549                   tux_x + scroll_x <= bad_guys[i].x + 32 &&
1550                   tux_y >= bad_guys[i].y - 32 &&
1551                   tux_y <= bad_guys[i].y - 8
1552                   /* &&
1553                   tux_ym >= 0 */)
1554                 {
1555                   if (bad_guys[i].kind == BAD_BSOD)
1556                     {
1557                       bad_guys[i].dying = SQUISHED;
1558                       bad_guys[i].timer = 16;
1559                       tux_ym = -KILL_BOUNCE_YM;
1560
1561                       add_score(bad_guys[i].x - scroll_x, bad_guys[i].y,
1562                                 50 * score_multiplier);
1563
1564                       play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
1565                     }
1566                   else if (bad_guys[i].kind == BAD_LAPTOP)
1567                     {
1568                       if (bad_guys[i].mode != FLAT)
1569                         {
1570                           /* Flatten! */
1571
1572                           play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1573                           bad_guys[i].mode = FLAT;
1574
1575                           bad_guys[i].timer = 64;
1576
1577                           tux_y = tux_y - 32;
1578                         }
1579                       else
1580                         {
1581                           /* Kick! */
1582
1583                           bad_guys[i].mode = KICK;
1584                           play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1585
1586                           if (tux_x + scroll_x <= bad_guys[i].x)
1587                             bad_guys[i].dir = RIGHT;
1588                           else
1589                             bad_guys[i].dir = LEFT;
1590
1591                           bad_guys[i].timer = 8;
1592                         }
1593
1594                       tux_ym = -KILL_BOUNCE_YM;
1595
1596                       add_score(bad_guys[i].x - scroll_x,
1597                                 bad_guys[i].y,
1598                                 25 * score_multiplier);
1599
1600                       /* play_sound(sounds[SND_SQUISH]); */
1601                     }
1602                   else if (bad_guys[i].kind == -1)
1603                   {}
1604
1605                   score_multiplier++;
1606                 }
1607
1608
1609               /* Hurt the player if he just touched it: */
1610
1611               if (!bad_guys[i].dying && !tux_dying &&
1612                   !tux_safe &&
1613                   tux_x + scroll_x >= bad_guys[i].x - 32 &&
1614                   tux_x + scroll_x <= bad_guys[i].x + 32 &&
1615                   tux_y >= bad_guys[i].y - 32 &&
1616                   tux_y <= bad_guys[i].y + 32)
1617                 {
1618                   if (bad_guys[i].mode == FLAT)
1619                     {
1620                       /* Kick: */
1621
1622                       bad_guys[i].mode = KICK;
1623                       play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
1624
1625                       if (tux_x + scroll_x <= bad_guys[i].x)
1626                         {
1627                           bad_guys[i].dir = RIGHT;
1628                           bad_guys[i].x = bad_guys[i].x + 16;
1629                         }
1630                       else
1631                         {
1632                           bad_guys[i].dir = LEFT;
1633                           bad_guys[i].x = bad_guys[i].x - 16;
1634                         }
1635
1636                       bad_guys[i].timer = 8;
1637                     }
1638                   else if (bad_guys[i].mode == KICK)
1639                     {
1640                       if (tux_y < bad_guys[i].y - 16 &&
1641                           bad_guys[i].timer == 0)
1642                         {
1643                           /* Step on (stop being kicked) */
1644
1645                           bad_guys[i].mode = FLAT;
1646                           play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
1647                           bad_guys[i].timer = 64;
1648                         }
1649                       else
1650                         {
1651                           /* Hurt if you get hit by kicked laptop: */
1652
1653                           if (bad_guys[i].timer == 0)
1654                             {
1655                               if (tux_invincible_time == 0)
1656                                 {
1657                                   killtux(SHRINK);
1658                                 }
1659                               else
1660                                 {
1661                                   bad_guys[i].dying = FALLING;
1662                                   bad_guys[i].ym = -8;
1663                                   play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1664                                 }
1665                             }
1666                         }
1667                     }
1668                   else
1669                     {
1670                       if (tux_invincible_time == 0)
1671                         {
1672                           killtux(SHRINK);
1673                         }
1674                       else
1675                         {
1676                           bad_guys[i].dying = FALLING;
1677                           bad_guys[i].ym = -8;
1678                           play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1679                         }
1680                     }
1681                 }
1682
1683
1684               /* Handle mode timer: */
1685
1686               if (bad_guys[i].mode == FLAT)
1687                 {
1688                   bad_guys[i].timer--;
1689
1690                   if (bad_guys[i].timer <= 0)
1691                     bad_guys[i].mode = NORMAL;
1692                 }
1693               else if (bad_guys[i].mode == KICK)
1694                 {
1695                   if (bad_guys[i].timer > 0)
1696                     bad_guys[i].timer--;
1697                 }
1698
1699
1700               /* Handle dying timer: */
1701
1702               if (bad_guys[i].dying == SQUISHED)
1703                 {
1704                   bad_guys[i].timer--;
1705
1706
1707                   /* Remove it if time's up: */
1708
1709                   if (bad_guys[i].timer <= 0)
1710                     bad_guys[i].alive = NO;
1711                 }
1712
1713
1714               /* Remove if it's far off the screen: */
1715
1716               if (bad_guys[i].x < scroll_x - OFFSCREEN_DISTANCE)
1717                 bad_guys[i].alive = NO;
1718             }
1719           else /* !seen */
1720             {
1721               /* Once it's on screen, it's activated! */
1722
1723               if (bad_guys[i].x <= scroll_x + 640 + OFFSCREEN_DISTANCE)
1724                 bad_guys[i].seen = YES;
1725             }
1726         }
1727     }
1728
1729
1730   /* Handle skidding: */
1731
1732   if (tux_skidding > 0)
1733     {
1734       tux_skidding--;
1735     }
1736
1737   return -1;
1738 }
1739
1740 /* --- GAME DRAW! --- */
1741
1742 void game_draw()
1743 {
1744   int  x, y, i;
1745
1746   /* Draw screen: */
1747
1748   if (tux_dying && (frame % 4) == 0)
1749     clearscreen(255, 255, 255);
1750   else
1751     {
1752       if (super_bkgd_time == 0)
1753         clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
1754       else
1755         drawimage(img_super_bkgd, 0, 0, NO_UPDATE);
1756     }
1757
1758
1759   /* Draw background: */
1760
1761   for (y = 0; y < 15; y++)
1762     {
1763       for (x = 0; x < 21; x++)
1764         {
1765           drawshape(x * 32 - (scroll_x % 32), y * 32,
1766                     current_level.tiles[y][x + (scroll_x / 32)]);
1767         }
1768     }
1769
1770
1771   /* (Bouncy bricks): */
1772
1773   for (i = 0; i < NUM_BOUNCY_BRICKS; i++)
1774     {
1775       if (bouncy_bricks[i].alive)
1776         {
1777           if (bouncy_bricks[i].x >= scroll_x - 32 &&
1778               bouncy_bricks[i].x <= scroll_x + 640)
1779             {
1780               dest.x = bouncy_bricks[i].x - scroll_x;
1781               dest.y = bouncy_bricks[i].y;
1782               dest.w = 32;
1783               dest.h = 32;
1784
1785               SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format,
1786                                                      current_level.bkgd_red,
1787                                                      current_level.bkgd_green,
1788                                                      current_level.bkgd_blue));
1789
1790               drawshape(bouncy_bricks[i].x - scroll_x,
1791                         bouncy_bricks[i].y + bouncy_bricks[i].offset,
1792                         bouncy_bricks[i].shape);
1793             }
1794         }
1795     }
1796
1797
1798   /* (Bad guys): */
1799
1800   for (i = 0; i < NUM_BAD_GUYS; i++)
1801     {
1802       if (bad_guys[i].alive &&
1803           bad_guys[i].x > scroll_x - 32 &&
1804           bad_guys[i].x < scroll_x + 640)
1805         {
1806           if (bad_guys[i].kind == BAD_BSOD)
1807             {
1808               /* --- BLUE SCREEN OF DEATH MONSTER: --- */
1809
1810               if (bad_guys[i].dying == NO)
1811                 {
1812                   /* Alive: */
1813
1814                   if (bad_guys[i].dir == LEFT)
1815                     {
1816                       drawimage(img_bsod_left[(frame / 5) % 4],
1817                                 bad_guys[i].x - scroll_x,
1818                                 bad_guys[i].y,
1819                                 NO_UPDATE);
1820                     }
1821                   else
1822                     {
1823                       drawimage(img_bsod_right[(frame / 5) % 4],
1824                                 bad_guys[i].x - scroll_x,
1825                                 bad_guys[i].y,
1826                                 NO_UPDATE);
1827                     }
1828                 }
1829               else if (bad_guys[i].dying == FALLING)
1830                 {
1831                   /* Falling: */
1832
1833                   if (bad_guys[i].dir == LEFT)
1834                     {
1835                       drawimage(img_bsod_falling_left,
1836                                 bad_guys[i].x - scroll_x,
1837                                 bad_guys[i].y,
1838                                 NO_UPDATE);
1839                     }
1840                   else
1841                     {
1842                       drawimage(img_bsod_falling_right,
1843                                 bad_guys[i].x - scroll_x,
1844                                 bad_guys[i].y,
1845                                 NO_UPDATE);
1846                     }
1847                 }
1848               else if (bad_guys[i].dying == SQUISHED)
1849                 {
1850                   /* Dying - Squished: */
1851
1852                   if (bad_guys[i].dir == LEFT)
1853                     {
1854                       drawimage(img_bsod_squished_left,
1855                                 bad_guys[i].x - scroll_x,
1856                                 bad_guys[i].y + 24,
1857                                 NO_UPDATE);
1858                     }
1859                   else
1860                     {
1861                       drawimage(img_bsod_squished_right,
1862                                 bad_guys[i].x - scroll_x,
1863                                 bad_guys[i].y + 24,
1864                                 NO_UPDATE);
1865                     }
1866                 }
1867             }
1868           else if (bad_guys[i].kind == BAD_LAPTOP)
1869             {
1870               /* --- LAPTOP MONSTER: --- */
1871
1872               if (bad_guys[i].dying == NO)
1873                 {
1874                   /* Alive: */
1875
1876                   if (bad_guys[i].mode == NORMAL)
1877                     {
1878                       /* Not flat: */
1879
1880                       if (bad_guys[i].dir == LEFT)
1881                         {
1882                           drawimage(img_laptop_left[(frame / 5) % 3],
1883                                     bad_guys[i].x - scroll_x,
1884                                     bad_guys[i].y,
1885                                     NO_UPDATE);
1886                         }
1887                       else
1888                         {
1889                           drawimage(img_laptop_right[(frame / 5) % 3],
1890                                     bad_guys[i].x - scroll_x,
1891                                     bad_guys[i].y,
1892                                     NO_UPDATE);
1893                         }
1894                     }
1895                   else
1896                     {
1897                       /* Flat: */
1898
1899                       if (bad_guys[i].dir == LEFT)
1900                         {
1901                           drawimage(img_laptop_flat_left,
1902                                     bad_guys[i].x - scroll_x,
1903                                     bad_guys[i].y,
1904                                     NO_UPDATE);
1905                         }
1906                       else
1907                         {
1908                           drawimage(img_laptop_flat_right,
1909                                     bad_guys[i].x - scroll_x,
1910                                     bad_guys[i].y,
1911                                     NO_UPDATE);
1912                         }
1913                     }
1914                 }
1915               else if (bad_guys[i].dying == FALLING)
1916                 {
1917                   /* Falling: */
1918
1919                   if (bad_guys[i].dir == LEFT)
1920                     {
1921                       drawimage(img_laptop_falling_left,
1922                                 bad_guys[i].x - scroll_x,
1923                                 bad_guys[i].y,
1924                                 NO_UPDATE);
1925                     }
1926                   else
1927                     {
1928                       drawimage(img_laptop_falling_right,
1929                                 bad_guys[i].x - scroll_x,
1930                                 bad_guys[i].y,
1931                                 NO_UPDATE);
1932                     }
1933                 }
1934             }
1935           else if (bad_guys[i].kind == BAD_MONEY)
1936             {
1937               if (bad_guys[i].ym > -16)
1938                 {
1939                   if (bad_guys[i].dir == LEFT)
1940                     {
1941                       drawimage(img_money_left[0],
1942                                 bad_guys[i].x - scroll_x,
1943                                 bad_guys[i].y,
1944                                 NO_UPDATE);
1945                     }
1946                   else
1947                     {
1948                       drawimage(img_money_right[0],
1949                                 bad_guys[i].x - scroll_x,
1950                                 bad_guys[i].y,
1951                                 NO_UPDATE);
1952                     }
1953                 }
1954               else
1955                 {
1956                   if (bad_guys[i].dir == LEFT)
1957                     {
1958                       drawimage(img_money_left[1],
1959                                 bad_guys[i].x - scroll_x,
1960                                 bad_guys[i].y,
1961                                 NO_UPDATE);
1962                     }
1963                   else
1964                     {
1965                       drawimage(img_money_right[1],
1966                                 bad_guys[i].x - scroll_x,
1967                                 bad_guys[i].y,
1968                                 NO_UPDATE);
1969                     }
1970                 }
1971             }
1972           else if (bad_guys[i].kind == -1)
1973           {}
1974         }
1975     }
1976
1977
1978   /* (Tux): */
1979
1980   if (right == UP && left == UP)
1981     {
1982       tux_frame_main = 1;
1983       tux_frame = 1;
1984     }
1985   else
1986     {
1987       if ((fire == DOWN && (frame % 2) == 0) ||
1988           (frame % 4) == 0)
1989         tux_frame_main = (tux_frame_main + 1) % 4;
1990
1991       tux_frame = tux_frame_main;
1992
1993       if (tux_frame == 3)
1994         tux_frame = 1;
1995     }
1996
1997
1998   if (tux_safe == 0 || (frame % 2) == 0)
1999     {
2000       if (tux_size == SMALL)
2001         {
2002           if (tux_invincible_time)
2003             {
2004               /* Draw cape: */
2005
2006               if (tux_dir == RIGHT)
2007                 {
2008                   drawimage(cape_right[frame % 2],
2009                             tux_x, tux_y,
2010                             NO_UPDATE);
2011                 }
2012               else
2013                 {
2014                   drawimage(cape_left[frame % 2],
2015                             tux_x, tux_y,
2016                             NO_UPDATE);
2017                 }
2018             }
2019
2020
2021           if (!tux_got_coffee)
2022             {
2023               if (tux_dir == RIGHT)
2024                 {
2025                   drawimage(tux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
2026                 }
2027               else
2028                 {
2029                   drawimage(tux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
2030                 }
2031             }
2032           else
2033             {
2034               /* Tux got coffee! */
2035
2036               if (tux_dir == RIGHT)
2037                 {
2038                   drawimage(firetux_right[tux_frame], tux_x, tux_y, NO_UPDATE);
2039                 }
2040               else
2041                 {
2042                   drawimage(firetux_left[tux_frame], tux_x, tux_y, NO_UPDATE);
2043                 }
2044             }
2045         }
2046       else
2047         {
2048           if (tux_invincible_time)
2049             {
2050               /* Draw cape: */
2051
2052               if (tux_dir == RIGHT)
2053                 {
2054                   drawimage(bigcape_right[frame % 2],
2055                             tux_x - 8 - 16, tux_y - 32,
2056                             NO_UPDATE);
2057                 }
2058               else
2059                 {
2060                   drawimage(bigcape_left[frame % 2],
2061                             tux_x - 8, tux_y - 32,
2062                             NO_UPDATE);
2063                 }
2064             }
2065
2066           if (!tux_got_coffee)
2067             {
2068               if (!tux_duck)
2069                 {
2070                   if (!tux_skidding)
2071                     {
2072                       if (!jumping || tux_ym > 0)
2073                         {
2074                           if (tux_dir == RIGHT)
2075                             {
2076                               drawimage(bigtux_right[tux_frame],
2077                                         tux_x - 8, tux_y - 32,
2078                                         NO_UPDATE);
2079                             }
2080                           else
2081                             {
2082                               drawimage(bigtux_left[tux_frame],
2083                                         tux_x - 8, tux_y - 32,
2084                                         NO_UPDATE);
2085                             }
2086                         }
2087                       else
2088                         {
2089                           if (tux_dir == RIGHT)
2090                             {
2091                               drawimage(bigtux_right_jump,
2092                                         tux_x - 8, tux_y - 32,
2093                                         NO_UPDATE);
2094                             }
2095                           else
2096                             {
2097                               drawimage(bigtux_left_jump,
2098                                         tux_x - 8, tux_y - 32,
2099                                         NO_UPDATE);
2100                             }
2101                         }
2102                     }
2103                   else
2104                     {
2105                       if (tux_dir == RIGHT)
2106                         {
2107                           drawimage(skidtux_right,
2108                                     tux_x - 8, tux_y - 32,
2109                                     NO_UPDATE);
2110                         }
2111                       else
2112                         {
2113                           drawimage(skidtux_left,
2114                                     tux_x - 8, tux_y - 32,
2115                                     NO_UPDATE);
2116                         }
2117                     }
2118                 }
2119               else
2120                 {
2121                   if (tux_dir == RIGHT)
2122                     {
2123                       drawimage(ducktux_right, tux_x - 8, tux_y - 16,
2124                                 NO_UPDATE);
2125                     }
2126                   else
2127                     {
2128                       drawimage(ducktux_left, tux_x - 8, tux_y - 16,
2129                                 NO_UPDATE);
2130                     }
2131                 }
2132             }
2133           else
2134             {
2135               /* Tux has coffee! */
2136
2137               if (!tux_duck)
2138                 {
2139                   if (!tux_skidding)
2140                     {
2141                       if (!jumping || tux_ym > 0)
2142                         {
2143                           if (tux_dir == RIGHT)
2144                             {
2145                               drawimage(bigfiretux_right[tux_frame],
2146                                         tux_x - 8, tux_y - 32,
2147                                         NO_UPDATE);
2148                             }
2149                           else
2150                             {
2151                               drawimage(bigfiretux_left[tux_frame],
2152                                         tux_x - 8, tux_y - 32,
2153                                         NO_UPDATE);
2154                             }
2155                         }
2156                       else
2157                         {
2158                           if (tux_dir == RIGHT)
2159                             {
2160                               drawimage(bigfiretux_right_jump,
2161                                         tux_x - 8, tux_y - 32,
2162                                         NO_UPDATE);
2163                             }
2164                           else
2165                             {
2166                               drawimage(bigfiretux_left_jump,
2167                                         tux_x - 8, tux_y - 32,
2168                                         NO_UPDATE);
2169                             }
2170                         }
2171                     }
2172                   else
2173                     {
2174                       if (tux_dir == RIGHT)
2175                         {
2176                           drawimage(skidfiretux_right,
2177                                     tux_x - 8, tux_y - 32,
2178                                     NO_UPDATE);
2179                         }
2180                       else
2181                         {
2182                           drawimage(skidfiretux_left,
2183                                     tux_x - 8, tux_y - 32,
2184                                     NO_UPDATE);
2185                         }
2186                     }
2187                 }
2188               else
2189                 {
2190                   if (tux_dir == RIGHT)
2191                     {
2192                       drawimage(duckfiretux_right, tux_x - 8, tux_y - 16,
2193                                 NO_UPDATE);
2194                     }
2195                   else
2196                     {
2197                       drawimage(duckfiretux_left, tux_x - 8, tux_y - 16,
2198                                 NO_UPDATE);
2199                     }
2200                 }
2201             }
2202         }
2203     }
2204
2205
2206   /* (Bullets): */
2207
2208   for (i = 0; i < NUM_BULLETS; i++)
2209     {
2210       if (bullets[i].alive &&
2211           bullets[i].x >= scroll_x - 4 &&
2212           bullets[i].x <= scroll_x + 640)
2213         {
2214           drawimage(img_bullet, bullets[i].x - scroll_x, bullets[i].y,
2215                     NO_UPDATE);
2216         }
2217     }
2218
2219
2220   /* (Floating scores): */
2221
2222   for (i = 0; i < NUM_FLOATING_SCORES; i++)
2223     {
2224       if (floating_scores[i].alive)
2225         {
2226           sprintf(str, "%d", floating_scores[i].value);
2227           drawtext(str,
2228                    floating_scores[i].x + 16 - strlen(str) * 8,
2229                    floating_scores[i].y,
2230                    letters_gold, NO_UPDATE, 1);
2231         }
2232     }
2233
2234
2235   /* (Upgrades): */
2236
2237   for (i = 0; i < NUM_UPGRADES; i++)
2238     {
2239       if (upgrades[i].alive)
2240         {
2241           if (upgrades[i].height < 32)
2242             {
2243               /* Rising up... */
2244
2245               dest.x = upgrades[i].x - scroll_x;
2246               dest.y = upgrades[i].y + 32 - upgrades[i].height;
2247               dest.w = 32;
2248               dest.h = upgrades[i].height;
2249
2250               src.x = 0;
2251               src.y = 0;
2252               src.w = 32;
2253               src.h = upgrades[i].height;
2254
2255               if (upgrades[i].kind == UPGRADE_MINTS)
2256                 SDL_BlitSurface(img_mints, &src, screen, &dest);
2257               else if (upgrades[i].kind == UPGRADE_COFFEE)
2258                 SDL_BlitSurface(img_coffee, &src, screen, &dest);
2259               else if (upgrades[i].kind == UPGRADE_HERRING)
2260                 SDL_BlitSurface(img_golden_herring, &src, screen, &dest);
2261             }
2262           else
2263             {
2264               if (upgrades[i].kind == UPGRADE_MINTS)
2265                 {
2266                   drawimage(img_mints,
2267                             upgrades[i].x - scroll_x, upgrades[i].y,
2268                             NO_UPDATE);
2269                 }
2270               else if (upgrades[i].kind == UPGRADE_COFFEE)
2271                 {
2272                   drawimage(img_coffee,
2273                             upgrades[i].x - scroll_x, upgrades[i].y,
2274                             NO_UPDATE);
2275                 }
2276               else if (upgrades[i].kind == UPGRADE_HERRING)
2277                 {
2278                   drawimage(img_golden_herring,
2279                             upgrades[i].x - scroll_x, upgrades[i].y,
2280                             NO_UPDATE);
2281                 }
2282             }
2283         }
2284     }
2285
2286
2287   /* (Bouncy distros): */
2288
2289   for (i = 0; i < NUM_BOUNCY_DISTROS; i++)
2290     {
2291       if (bouncy_distros[i].alive)
2292         {
2293           drawimage(img_distro[0],
2294                     bouncy_distros[i].x - scroll_x,
2295                     bouncy_distros[i].y,
2296                     NO_UPDATE);
2297         }
2298     }
2299
2300
2301   /* (Broken bricks): */
2302
2303   for (i = 0; i < NUM_BROKEN_BRICKS; i++)
2304     {
2305       if (broken_bricks[i].alive)
2306         {
2307           src.x = rand() % 16;
2308           src.y = rand() % 16;
2309           src.w = 16;
2310           src.h = 16;
2311
2312           dest.x = broken_bricks[i].x - scroll_x;
2313           dest.y = broken_bricks[i].y;
2314           dest.w = 16;
2315           dest.h = 16;
2316
2317           SDL_BlitSurface(img_brick[0], &src, screen, &dest);
2318         }
2319     }
2320
2321
2322   /* (Status): */
2323
2324   sprintf(str, "%d", score);
2325   drawtext("SCORE", 0, 0, letters_blue, NO_UPDATE, 1);
2326   drawtext(str, 96, 0, letters_gold, NO_UPDATE, 1);
2327
2328   sprintf(str, "%d", highscore);
2329   drawtext("HIGH", 0, 20, letters_blue, NO_UPDATE, 1);
2330   drawtext(str, 96, 20, letters_gold, NO_UPDATE, 1);
2331
2332   if (current_level.time_left >= TIME_WARNING || (frame % 10) < 5)
2333     {
2334       sprintf(str, "%d", current_level.time_left);
2335       drawtext("TIME", 224, 0, letters_blue, NO_UPDATE, 1);
2336       drawtext(str, 304, 0, letters_gold, NO_UPDATE, 1);
2337     }
2338
2339   sprintf(str, "%d", distros);
2340   drawtext("DISTROS", 480, 0, letters_blue, NO_UPDATE, 1);
2341   drawtext(str, 608, 0, letters_gold, NO_UPDATE, 1);
2342
2343   drawtext("LIVES", 480, 20, letters_blue, NO_UPDATE, 1);
2344
2345   for(i=0; i < lives; ++i)
2346     {
2347       drawimage(tux_life,565+(18*i),20,NO_UPDATE);
2348     }
2349
2350   if(game_pause)
2351     drawcenteredtext("PAUSE",230,letters_red, NO_UPDATE, 1);
2352
2353   if(show_menu)
2354     done = drawmenu();
2355
2356   /* (Update it all!) */
2357
2358   updatescreen();
2359
2360
2361 }
2362
2363 /* --- GAME LOOP! --- */
2364
2365 int gameloop(void)
2366 {
2367
2368   Uint32 last_time, now_time;
2369
2370   /* Clear screen: */
2371
2372   clearscreen(0, 0, 0);
2373   updatescreen();
2374
2375
2376   /* Init the game: */
2377
2378   initmenu();
2379   menumenu = MENU_GAME;
2380   initgame();
2381   loadshared();
2382   
2383   tux_size = SMALL;
2384   tux_got_coffee = NO;
2385
2386   set_defaults();
2387   loadlevel(&current_level,"default",level);
2388   loadlevelgfx();
2389   activate_bad_guys();
2390   loadlevelsong();
2391   highscore = load_hs();
2392
2393   levelintro();
2394   
2395   /* --- MAIN GAME LOOP!!! --- */
2396
2397   done = 0;
2398   quit = 0;
2399   frame = 0;
2400   tux_frame_main = 0;
2401   tux_frame = 0;
2402   game_pause = 0;
2403
2404   game_draw();
2405   do
2406     {
2407       last_time = SDL_GetTicks();
2408       frame++;
2409
2410
2411       /* Handle events: */
2412
2413       old_fire = fire;
2414
2415       game_event();
2416
2417       /* Handle actions: */
2418
2419       if(!game_pause && !show_menu)
2420         {
2421           if (game_action() == 0)
2422             {
2423               /* == 0: no more lives */
2424               /* == -1: continues */
2425               return 0;
2426             }
2427         }
2428       else
2429         SDL_Delay(50);
2430
2431       /*Draw the current scene to the screen */
2432       game_draw();
2433
2434       /* Keep playing music: */
2435
2436
2437       if (!playing_music())
2438         {
2439           switch (current_music)
2440             {
2441             case LEVEL_MUSIC:
2442               if (current_level.time_left <= TIME_WARNING)
2443                 play_music(level_song_fast, 1);
2444               else
2445                 play_music(level_song, 1);
2446               break;
2447             case HERRING_MUSIC:
2448               play_music(herring_song, 1);
2449               break;
2450             case HURRYUP_MUSIC: // keep the compiler happy
2451             case NO_MUSIC:      // keep the compiler happy for the moment :-)
2452             {}
2453               /*default:*/
2454             }
2455         }
2456
2457       /* Time stops in pause mode */
2458       if(game_pause || show_menu )
2459         {
2460           continue;
2461         }
2462
2463       /* Pause til next frame: */
2464
2465       now_time = SDL_GetTicks();
2466       if (now_time < last_time + FPS)
2467         SDL_Delay(last_time + FPS - now_time);
2468
2469
2470       /* Handle time: */
2471
2472       if ((frame % 10) == 0 && current_level.time_left > 0)
2473         {
2474           current_level.time_left--;
2475
2476           /* Stop the music; it will start again, faster! */
2477           if (current_level.time_left == TIME_WARNING)
2478             halt_music();
2479
2480           if (current_level.time_left <= 0)
2481             killtux(KILL);
2482         }
2483     }
2484   while (!done && !quit);
2485
2486   if (playing_music())
2487     halt_music();
2488
2489   unloadlevelgfx();
2490   unloadlevelsong();
2491   unloadshared();
2492
2493   return(quit);
2494 }
2495
2496
2497 /* Initialize the game stuff: */
2498
2499 void initgame(void)
2500 {
2501   level = 1;
2502   score = 0;
2503   distros = 0;
2504   lives = 3;
2505 }
2506
2507 /* Load graphics: */
2508
2509 void loadlevelgfx(void)
2510 {
2511
2512   img_brick[0] = load_level_image(current_level.theme,"brick0.png", IGNORE_ALPHA);
2513   img_brick[1] = load_level_image(current_level.theme,"brick1.png", IGNORE_ALPHA);
2514
2515   img_solid[0] = load_level_image(current_level.theme,"solid0.png", USE_ALPHA);
2516   img_solid[1] = load_level_image(current_level.theme,"solid1.png", USE_ALPHA);
2517   img_solid[2] = load_level_image(current_level.theme,"solid2.png", USE_ALPHA);
2518   img_solid[3] = load_level_image(current_level.theme,"solid3.png", USE_ALPHA);
2519
2520   img_bkgd[0][0] = load_level_image(current_level.theme,"bkgd-00.png", USE_ALPHA);
2521   img_bkgd[0][1] = load_level_image(current_level.theme,"bkgd-01.png", USE_ALPHA);
2522   img_bkgd[0][2] = load_level_image(current_level.theme,"bkgd-02.png", USE_ALPHA);
2523   img_bkgd[0][3] = load_level_image(current_level.theme,"bkgd-03.png", USE_ALPHA);
2524
2525   img_bkgd[1][0] = load_level_image(current_level.theme,"bkgd-10.png", USE_ALPHA);
2526   img_bkgd[1][1] = load_level_image(current_level.theme,"bkgd-11.png", USE_ALPHA);
2527   img_bkgd[1][2] = load_level_image(current_level.theme,"bkgd-12.png", USE_ALPHA);
2528   img_bkgd[1][3] = load_level_image(current_level.theme,"bkgd-13.png", USE_ALPHA);
2529 }
2530
2531
2532 /* Load music: */
2533
2534 void loadlevelsong(void)
2535 {
2536
2537   char * song_path;
2538   char * song_subtitle;
2539
2540   song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2541                               strlen(current_level.song_title) + 8));
2542   sprintf(song_path, "%s/music/%s", DATA_PREFIX, current_level.song_title);
2543   level_song = load_song(song_path);
2544   free(song_path);
2545
2546
2547   song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
2548                               strlen(current_level.song_title) + 8 + 5));
2549   song_subtitle = strdup(current_level.song_title);
2550   strcpy(strstr(song_subtitle, "."), "\0");
2551   sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(current_level.song_title, "."));
2552   level_song_fast = load_song(song_path);
2553   free(song_subtitle);
2554   free(song_path);
2555 }
2556
2557
2558 /* Free graphics data for this level: */
2559
2560 void unloadlevelgfx(void)
2561 {
2562   int i;
2563
2564   for (i = 0; i < 2; i++)
2565     {
2566       SDL_FreeSurface(img_brick[i]);
2567     }
2568   for (i = 0; i < 4; i++)
2569     {
2570       SDL_FreeSurface(img_solid[i]);
2571       SDL_FreeSurface(img_bkgd[0][i]);
2572       SDL_FreeSurface(img_bkgd[1][i]);
2573     }
2574 }
2575
2576
2577 /* Free music data for this level: */
2578
2579 void unloadlevelsong(void)
2580 {
2581   free_music(level_song);
2582 }
2583
2584
2585 /* Load graphics/sounds shared between all levels: */
2586
2587 void loadshared(void)
2588 {
2589   int i;
2590   char * herring_song_path; /* for loading herring song*/
2591
2592   /* Tuxes: */
2593
2594   tux_right[0] = load_image(DATA_PREFIX "/images/shared/tux-right-0.png",
2595                             USE_ALPHA);
2596
2597   tux_right[1] = load_image(DATA_PREFIX "/images/shared/tux-right-1.png",
2598                             USE_ALPHA);
2599
2600   tux_right[2] = load_image(DATA_PREFIX "/images/shared/tux-right-2.png",
2601                             USE_ALPHA);
2602
2603   tux_left[0] = load_image(DATA_PREFIX "/images/shared/tux-left-0.png",
2604                            USE_ALPHA);
2605
2606   tux_left[1] = load_image(DATA_PREFIX "/images/shared/tux-left-1.png",
2607                            USE_ALPHA);
2608
2609   tux_left[2] = load_image(DATA_PREFIX "/images/shared/tux-left-2.png",
2610                            USE_ALPHA);
2611
2612   firetux_right[0] = load_image(DATA_PREFIX "/images/shared/firetux-right-0.png",
2613                                 USE_ALPHA);
2614
2615   firetux_right[1] = load_image(DATA_PREFIX "/images/shared/firetux-right-1.png",
2616                                 USE_ALPHA);
2617
2618   firetux_right[2] = load_image(DATA_PREFIX "/images/shared/firetux-right-2.png",
2619                                 USE_ALPHA);
2620
2621   firetux_left[0] = load_image(DATA_PREFIX "/images/shared/firetux-left-0.png",
2622                                USE_ALPHA);
2623
2624   firetux_left[1] = load_image(DATA_PREFIX "/images/shared/firetux-left-1.png",
2625                                USE_ALPHA);
2626
2627   firetux_left[2] = load_image(DATA_PREFIX "/images/shared/firetux-left-2.png",
2628                                USE_ALPHA);
2629
2630   cape_right[0] = load_image(DATA_PREFIX "/images/shared/cape-right-0.png",
2631                              USE_ALPHA);
2632
2633   cape_right[1] = load_image(DATA_PREFIX "/images/shared/cape-right-1.png",
2634                              USE_ALPHA);
2635
2636   cape_left[0] = load_image(DATA_PREFIX "/images/shared/cape-left-0.png",
2637                             USE_ALPHA);
2638
2639   cape_left[1] = load_image(DATA_PREFIX "/images/shared/cape-left-1.png",
2640                             USE_ALPHA);
2641
2642   bigtux_right[0] = load_image(DATA_PREFIX "/images/shared/bigtux-right-0.png",
2643                                USE_ALPHA);
2644
2645   bigtux_right[1] = load_image(DATA_PREFIX "/images/shared/bigtux-right-1.png",
2646                                USE_ALPHA);
2647
2648   bigtux_right[2] = load_image(DATA_PREFIX "/images/shared/bigtux-right-2.png",
2649                                USE_ALPHA);
2650
2651   bigtux_right_jump =
2652     load_image(DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA);
2653
2654   bigtux_left[0] = load_image(DATA_PREFIX "/images/shared/bigtux-left-0.png",
2655                               USE_ALPHA);
2656
2657   bigtux_left[1] = load_image(DATA_PREFIX "/images/shared/bigtux-left-1.png",
2658                               USE_ALPHA);
2659
2660   bigtux_left[2] = load_image(DATA_PREFIX "/images/shared/bigtux-left-2.png",
2661                               USE_ALPHA);
2662
2663   bigtux_left_jump =
2664     load_image(DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA);
2665
2666   bigcape_right[0] =
2667     load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2668                USE_ALPHA);
2669
2670   bigcape_right[1] =
2671     load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2672                USE_ALPHA);
2673
2674   bigcape_left[0] =
2675     load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2676                USE_ALPHA);
2677
2678   bigcape_left[1] =
2679     load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2680                USE_ALPHA);
2681
2682   bigfiretux_right[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-0.png",
2683                                    USE_ALPHA);
2684
2685   bigfiretux_right[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-1.png",
2686                                    USE_ALPHA);
2687
2688   bigfiretux_right[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-right-2.png",
2689                                    USE_ALPHA);
2690
2691   bigfiretux_right_jump =
2692     load_image(DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
2693
2694   bigfiretux_left[0] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-0.png",
2695                                   USE_ALPHA);
2696
2697   bigfiretux_left[1] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-1.png",
2698                                   USE_ALPHA);
2699
2700   bigfiretux_left[2] = load_image(DATA_PREFIX "/images/shared/bigfiretux-left-2.png",
2701                                   USE_ALPHA);
2702
2703   bigfiretux_left_jump =
2704     load_image(DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
2705
2706   bigcape_right[0] =
2707     load_image(DATA_PREFIX "/images/shared/bigcape-right-0.png",
2708                USE_ALPHA);
2709
2710   bigcape_right[1] =
2711     load_image(DATA_PREFIX "/images/shared/bigcape-right-1.png",
2712                USE_ALPHA);
2713
2714   bigcape_left[0] =
2715     load_image(DATA_PREFIX "/images/shared/bigcape-left-0.png",
2716                USE_ALPHA);
2717
2718   bigcape_left[1] =
2719     load_image(DATA_PREFIX "/images/shared/bigcape-left-1.png",
2720                USE_ALPHA);
2721
2722
2723   ducktux_right = load_image(DATA_PREFIX
2724                              "/images/shared/ducktux-right.png",
2725                              USE_ALPHA);
2726
2727   ducktux_left = load_image(DATA_PREFIX
2728                             "/images/shared/ducktux-left.png",
2729                             USE_ALPHA);
2730
2731   skidtux_right = load_image(DATA_PREFIX
2732                              "/images/shared/skidtux-right.png",
2733                              USE_ALPHA);
2734
2735   skidtux_left = load_image(DATA_PREFIX
2736                             "/images/shared/skidtux-left.png",
2737                             USE_ALPHA);
2738
2739   duckfiretux_right = load_image(DATA_PREFIX
2740                                  "/images/shared/duckfiretux-right.png",
2741                                  USE_ALPHA);
2742
2743   duckfiretux_left = load_image(DATA_PREFIX
2744                                 "/images/shared/duckfiretux-left.png",
2745                                 USE_ALPHA);
2746
2747   skidfiretux_right = load_image(DATA_PREFIX
2748                                  "/images/shared/skidfiretux-right.png",
2749                                  USE_ALPHA);
2750
2751   skidfiretux_left = load_image(DATA_PREFIX
2752                                 "/images/shared/skidfiretux-left.png",
2753                                 USE_ALPHA);
2754
2755
2756   /* Boxes: */
2757
2758   img_box_full = load_image(DATA_PREFIX "/images/shared/box-full.png",
2759                             IGNORE_ALPHA);
2760   img_box_empty = load_image(DATA_PREFIX "/images/shared/box-empty.png",
2761                              IGNORE_ALPHA);
2762
2763
2764   /* Water: */
2765
2766
2767   img_water = load_image(DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA);
2768
2769   img_waves[0] = load_image(DATA_PREFIX "/images/shared/waves-0.png",
2770                             USE_ALPHA);
2771
2772   img_waves[1] = load_image(DATA_PREFIX "/images/shared/waves-1.png",
2773                             USE_ALPHA);
2774
2775   img_waves[2] = load_image(DATA_PREFIX "/images/shared/waves-2.png",
2776                             USE_ALPHA);
2777
2778
2779   /* Pole: */
2780
2781   img_pole = load_image(DATA_PREFIX "/images/shared/pole.png", USE_ALPHA);
2782   img_poletop = load_image(DATA_PREFIX "/images/shared/poletop.png",
2783                            USE_ALPHA);
2784
2785
2786   /* Flag: */
2787
2788   img_flag[0] = load_image(DATA_PREFIX "/images/shared/flag-0.png",
2789                            USE_ALPHA);
2790   img_flag[1] = load_image(DATA_PREFIX "/images/shared/flag-1.png",
2791                            USE_ALPHA);
2792
2793
2794   /* Cloud: */
2795
2796   img_cloud[0][0] = load_image(DATA_PREFIX "/images/shared/cloud-00.png",
2797                                USE_ALPHA);
2798
2799   img_cloud[0][1] = load_image(DATA_PREFIX "/images/shared/cloud-01.png",
2800                                USE_ALPHA);
2801
2802   img_cloud[0][2] = load_image(DATA_PREFIX "/images/shared/cloud-02.png",
2803                                USE_ALPHA);
2804
2805   img_cloud[0][3] = load_image(DATA_PREFIX "/images/shared/cloud-03.png",
2806                                USE_ALPHA);
2807
2808
2809   img_cloud[1][0] = load_image(DATA_PREFIX "/images/shared/cloud-10.png",
2810                                USE_ALPHA);
2811
2812   img_cloud[1][1] = load_image(DATA_PREFIX "/images/shared/cloud-11.png",
2813                                USE_ALPHA);
2814
2815   img_cloud[1][2] = load_image(DATA_PREFIX "/images/shared/cloud-12.png",
2816                                USE_ALPHA);
2817
2818   img_cloud[1][3] = load_image(DATA_PREFIX "/images/shared/cloud-13.png",
2819                                USE_ALPHA);
2820
2821
2822   /* Bad guys: */
2823
2824   /* (BSOD) */
2825
2826   img_bsod_left[0] = load_image(DATA_PREFIX
2827                                 "/images/shared/bsod-left-0.png",
2828                                 USE_ALPHA);
2829
2830   img_bsod_left[1] = load_image(DATA_PREFIX
2831                                 "/images/shared/bsod-left-1.png",
2832                                 USE_ALPHA);
2833
2834   img_bsod_left[2] = load_image(DATA_PREFIX
2835                                 "/images/shared/bsod-left-2.png",
2836                                 USE_ALPHA);
2837
2838   img_bsod_left[3] = load_image(DATA_PREFIX
2839                                 "/images/shared/bsod-left-3.png",
2840                                 USE_ALPHA);
2841
2842   img_bsod_right[0] = load_image(DATA_PREFIX
2843                                  "/images/shared/bsod-right-0.png",
2844                                  USE_ALPHA);
2845
2846   img_bsod_right[1] = load_image(DATA_PREFIX
2847                                  "/images/shared/bsod-right-1.png",
2848                                  USE_ALPHA);
2849
2850   img_bsod_right[2] = load_image(DATA_PREFIX
2851                                  "/images/shared/bsod-right-2.png",
2852                                  USE_ALPHA);
2853
2854   img_bsod_right[3] = load_image(DATA_PREFIX
2855                                  "/images/shared/bsod-right-3.png",
2856                                  USE_ALPHA);
2857
2858   img_bsod_squished_left = load_image(DATA_PREFIX
2859                                       "/images/shared/bsod-squished-left.png",
2860                                       USE_ALPHA);
2861
2862   img_bsod_squished_right = load_image(DATA_PREFIX
2863                                        "/images/shared/bsod-squished-right.png",
2864                                        USE_ALPHA);
2865
2866   img_bsod_falling_left = load_image(DATA_PREFIX
2867                                      "/images/shared/bsod-falling-left.png",
2868                                      USE_ALPHA);
2869
2870   img_bsod_falling_right = load_image(DATA_PREFIX
2871                                       "/images/shared/bsod-falling-right.png",
2872                                       USE_ALPHA);
2873
2874
2875   /* (Laptop) */
2876
2877   img_laptop_left[0] = load_image(DATA_PREFIX
2878                                   "/images/shared/laptop-left-0.png",
2879                                   USE_ALPHA);
2880
2881   img_laptop_left[1] = load_image(DATA_PREFIX
2882                                   "/images/shared/laptop-left-1.png",
2883                                   USE_ALPHA);
2884
2885   img_laptop_left[2] = load_image(DATA_PREFIX
2886                                   "/images/shared/laptop-left-2.png",
2887                                   USE_ALPHA);
2888
2889   img_laptop_right[0] = load_image(DATA_PREFIX
2890                                    "/images/shared/laptop-right-0.png",
2891                                    USE_ALPHA);
2892
2893   img_laptop_right[1] = load_image(DATA_PREFIX
2894                                    "/images/shared/laptop-right-1.png",
2895                                    USE_ALPHA);
2896
2897   img_laptop_right[2] = load_image(DATA_PREFIX
2898                                    "/images/shared/laptop-right-2.png",
2899                                    USE_ALPHA);
2900
2901   img_laptop_flat_left = load_image(DATA_PREFIX
2902                                     "/images/shared/laptop-flat-left.png",
2903                                     USE_ALPHA);
2904
2905   img_laptop_flat_right = load_image(DATA_PREFIX
2906                                      "/images/shared/laptop-flat-right.png",
2907                                      USE_ALPHA);
2908
2909   img_laptop_falling_left =
2910     load_image(DATA_PREFIX
2911                "/images/shared/laptop-falling-left.png",
2912                USE_ALPHA);
2913
2914   img_laptop_falling_right =
2915     load_image(DATA_PREFIX
2916                "/images/shared/laptop-falling-right.png",
2917                USE_ALPHA);
2918
2919
2920   /* (Money) */
2921
2922   img_money_left[0] = load_image(DATA_PREFIX
2923                                  "/images/shared/bag-left-0.png",
2924                                  USE_ALPHA);
2925
2926   img_money_left[1] = load_image(DATA_PREFIX
2927                                  "/images/shared/bag-left-1.png",
2928                                  USE_ALPHA);
2929
2930   img_money_right[0] = load_image(DATA_PREFIX
2931                                   "/images/shared/bag-right-0.png",
2932                                   USE_ALPHA);
2933
2934   img_money_right[1] = load_image(DATA_PREFIX
2935                                   "/images/shared/bag-right-1.png",
2936                                   USE_ALPHA);
2937
2938
2939
2940   /* Upgrades: */
2941
2942   img_mints = load_image(DATA_PREFIX "/images/shared/mints.png", USE_ALPHA);
2943   img_coffee = load_image(DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA);
2944
2945
2946   /* Weapons: */
2947
2948   img_bullet = load_image(DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA);
2949
2950   img_red_glow = load_image(DATA_PREFIX "/images/shared/red-glow.png",
2951                             USE_ALPHA);
2952
2953
2954
2955   /* Distros: */
2956
2957   img_distro[0] = load_image(DATA_PREFIX "/images/shared/distro-0.png",
2958                              USE_ALPHA);
2959
2960   img_distro[1] = load_image(DATA_PREFIX "/images/shared/distro-1.png",
2961                              USE_ALPHA);
2962
2963   img_distro[2] = load_image(DATA_PREFIX "/images/shared/distro-2.png",
2964                              USE_ALPHA);
2965
2966   img_distro[3] = load_image(DATA_PREFIX "/images/shared/distro-3.png",
2967                              USE_ALPHA);
2968
2969
2970   /* Tux life: */
2971
2972   tux_life = load_image(DATA_PREFIX "/images/shared/tux-life.png",
2973                         USE_ALPHA);
2974
2975   /* Herring: */
2976
2977   img_golden_herring =
2978     load_image(DATA_PREFIX "/images/shared/golden-herring.png",
2979                USE_ALPHA);
2980
2981
2982   /* Super background: */
2983
2984   img_super_bkgd = load_image(DATA_PREFIX "/images/shared/super-bkgd.png",
2985                               IGNORE_ALPHA);
2986
2987
2988   /* Sound effects: */
2989
2990   /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
2991                     // initialize sounds[i] with the correct pointer's value:
2992                     // NULL or something else. And it will be dangerous to
2993                     // play with not-initialized pointers.
2994                     // This is also true with if (use_music)
2995      Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
2996   */
2997   for (i = 0; i < NUM_SOUNDS; i++)
2998     sounds[i] = load_sound(soundfilenames[i]);
2999
3000   /* Herring song */
3001   herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) +
3002                                       strlen("SALCON.MOD") + 8)); /* FIXME: We need a real herring_song! Thats a fake.:) */
3003
3004   sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD");
3005
3006   herring_song = load_song(herring_song_path);
3007
3008   free(herring_song_path);
3009
3010 }
3011
3012
3013 /* Free shared data: */
3014
3015 void unloadshared(void)
3016 {
3017   int i;
3018
3019   for (i = 0; i < 3; i++)
3020     {
3021       SDL_FreeSurface(tux_right[i]);
3022       SDL_FreeSurface(tux_left[i]);
3023       SDL_FreeSurface(bigtux_right[i]);
3024       SDL_FreeSurface(bigtux_left[i]);
3025     }
3026
3027   SDL_FreeSurface(bigtux_right_jump);
3028   SDL_FreeSurface(bigtux_left_jump);
3029
3030   for (i = 0; i < 2; i++)
3031     {
3032       SDL_FreeSurface(cape_right[i]);
3033       SDL_FreeSurface(cape_left[i]);
3034       SDL_FreeSurface(bigcape_right[i]);
3035       SDL_FreeSurface(bigcape_left[i]);
3036     }
3037
3038   SDL_FreeSurface(ducktux_left);
3039   SDL_FreeSurface(ducktux_right);
3040
3041   SDL_FreeSurface(skidtux_left);
3042   SDL_FreeSurface(skidtux_right);
3043
3044   for (i = 0; i < 4; i++)
3045     {
3046       SDL_FreeSurface(img_bsod_left[i]);
3047       SDL_FreeSurface(img_bsod_right[i]);
3048     }
3049
3050   SDL_FreeSurface(img_bsod_squished_left);
3051   SDL_FreeSurface(img_bsod_squished_right);
3052
3053   SDL_FreeSurface(img_bsod_falling_left);
3054   SDL_FreeSurface(img_bsod_falling_right);
3055
3056   for (i = 0; i < 3; i++)
3057     {
3058       SDL_FreeSurface(img_laptop_left[i]);
3059       SDL_FreeSurface(img_laptop_right[i]);
3060     }
3061
3062   SDL_FreeSurface(img_laptop_flat_left);
3063   SDL_FreeSurface(img_laptop_flat_right);
3064
3065   SDL_FreeSurface(img_laptop_falling_left);
3066   SDL_FreeSurface(img_laptop_falling_right);
3067
3068   for (i = 0; i < 2; i++)
3069     {
3070       SDL_FreeSurface(img_money_left[i]);
3071       SDL_FreeSurface(img_money_right[i]);
3072     }
3073
3074   SDL_FreeSurface(img_box_full);
3075   SDL_FreeSurface(img_box_empty);
3076
3077   SDL_FreeSurface(img_water);
3078   for (i = 0; i < 3; i++)
3079     SDL_FreeSurface(img_waves[i]);
3080
3081   SDL_FreeSurface(img_pole);
3082   SDL_FreeSurface(img_poletop);
3083
3084   for (i = 0; i < 2; i++)
3085     SDL_FreeSurface(img_flag[i]);
3086
3087   SDL_FreeSurface(img_mints);
3088   SDL_FreeSurface(img_coffee);
3089
3090   for (i = 0; i < 4; i++)
3091     {
3092       SDL_FreeSurface(img_distro[i]);
3093       SDL_FreeSurface(img_cloud[0][i]);
3094       SDL_FreeSurface(img_cloud[1][i]);
3095     }
3096
3097   SDL_FreeSurface(img_golden_herring);
3098
3099   for (i = 0; i < NUM_SOUNDS; i++)
3100     free_chunk(sounds[i]);
3101
3102   /* free the herring song */
3103   free_music( herring_song );
3104 }
3105
3106
3107 /* Draw a tile on the screen: */
3108
3109 void drawshape(int x, int y, unsigned char c)
3110 {
3111   int z;
3112
3113   if (c == 'X' || c == 'x')
3114     drawimage(img_brick[0], x, y, NO_UPDATE);
3115   else if (c == 'Y' || c == 'y')
3116     drawimage(img_brick[1], x, y, NO_UPDATE);
3117   else if (c == 'A' || c =='B' || c == '!')
3118     drawimage(img_box_full, x, y, NO_UPDATE);
3119   else if (c == 'a')
3120     drawimage(img_box_empty, x, y, NO_UPDATE);
3121   else if (c >= 'C' && c <= 'F')
3122     drawimage(img_cloud[0][c - 'C'], x, y, NO_UPDATE);
3123   else if (c >= 'c' && c <= 'f')
3124     drawimage(img_cloud[1][c - 'c'], x, y, NO_UPDATE);
3125   else if (c >= 'G' && c <= 'J')
3126     drawimage(img_bkgd[0][c - 'G'], x, y, NO_UPDATE);
3127   else if (c >= 'g' && c <= 'j')
3128     drawimage(img_bkgd[1][c - 'g'], x, y, NO_UPDATE);
3129   else if (c == '#')
3130     drawimage(img_solid[0], x, y, NO_UPDATE);
3131   else if (c == '[')
3132     drawimage(img_solid[1], x, y, NO_UPDATE);
3133   else if (c == '=')
3134     drawimage(img_solid[2], x, y, NO_UPDATE);
3135   else if (c == ']')
3136     drawimage(img_solid[3], x, y, NO_UPDATE);
3137   else if (c == '$')
3138     {
3139       z = (frame / 2) % 6;
3140
3141       if (z < 4)
3142         drawimage(img_distro[z], x, y, NO_UPDATE);
3143       else if (z == 4)
3144         drawimage(img_distro[2], x, y, NO_UPDATE);
3145       else if (z == 5)
3146         drawimage(img_distro[1], x, y, NO_UPDATE);
3147     }
3148   else if (c == '^')
3149     {
3150       z = (frame / 3) % 3;
3151
3152       drawimage(img_waves[z], x, y, NO_UPDATE);
3153     }
3154   else if (c == '*')
3155     drawimage(img_poletop, x, y, NO_UPDATE);
3156   else if (c == '|')
3157     {
3158       drawimage(img_pole, x, y, NO_UPDATE);
3159
3160       /* Mark this as the end position of the level! */
3161
3162       endpos = x;
3163     }
3164   else if (c == '\\')
3165     {
3166       z = (frame / 3) % 2;
3167
3168       drawimage(img_flag[z], x + 16, y, NO_UPDATE);
3169     }
3170   else if (c == '&')
3171     drawimage(img_water, x, y, NO_UPDATE);
3172 }
3173
3174
3175 /* What shape is at some position? */
3176
3177 unsigned char shape(int x, int y, int sx)
3178 {
3179
3180   int xx, yy;
3181   unsigned char c;
3182   
3183   yy = (y / 32);
3184   xx = ((x + sx) / 32);
3185  
3186
3187   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
3188     c = current_level.tiles[yy][xx];
3189   else
3190     c = '.';
3191     
3192   return(c);
3193 }
3194
3195
3196 /* Is is ground? */
3197
3198 int issolid(int x, int y, int sx)
3199 {
3200   int v;
3201
3202   v = 0;
3203
3204   if (isbrick(x, y, sx) ||
3205       isbrick(x + 31, y, sx) ||
3206       isice(x, y, sx) ||
3207       isice(x + 31, y, sx) ||
3208       (shape(x, y, sx) == '[' ||
3209        shape(x + 31, y, sx) == '[') ||
3210       (shape(x, y, sx) == '=' ||
3211        shape(x + 31, y, sx) == '=') ||
3212       (shape(x, y, sx) == ']' ||
3213        shape(x + 31, y, sx) == ']') ||
3214       (shape(x, y, sx) == 'A' ||
3215        shape(x + 31, y, sx) == 'A') ||
3216       (shape(x, y, sx) == 'B' ||
3217        shape(x + 31, y, sx) == 'B') ||
3218       (shape(x, y, sx) == '!' ||
3219        shape(x + 31, y, sx) == '!') ||
3220       (shape(x, y, sx) == 'a' ||
3221        shape(x + 31, y, sx) == 'a'))
3222     {
3223       v = 1;
3224     }
3225
3226   return(v);
3227 }
3228
3229
3230 /* Is it a brick? */
3231
3232 int isbrick(int x, int y, int sx)
3233 {
3234   int v;
3235
3236   v = 0;
3237
3238   if (shape(x, y, sx) == 'X' ||
3239       shape(x, y, sx) == 'x' ||
3240       shape(x, y, sx) == 'Y' ||
3241       shape(x, y, sx) == 'y')
3242     {
3243       v = 1;
3244     }
3245
3246   return(v);
3247 }
3248
3249
3250 /* Is it ice? */
3251
3252 int isice(int x, int y, int sx)
3253 {
3254   int v;
3255
3256   v = 0;
3257
3258   if (shape(x, y, sx) == '#')
3259     {
3260       v = 1;
3261     }
3262
3263   return(v);
3264 }
3265
3266
3267 /* Is it a full box? */
3268
3269 int isfullbox(int x, int y, int sx)
3270 {
3271   int v;
3272
3273   v = 0;
3274
3275   if (shape(x, y, sx) == 'A' ||
3276       shape(x, y, sx) == 'B' ||
3277       shape(x, y, sx) == '!')
3278     {
3279       v = 1;
3280     }
3281
3282   return(v);
3283 }
3284
3285
3286 /* Edit a piece of the map! */
3287
3288 void change(int x, int y, int sx, unsigned char c)
3289 {
3290   int xx, yy;
3291
3292   yy = (y / 32);
3293   xx = ((x + sx) / 32);
3294
3295   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
3296     current_level.tiles[yy][xx] = c;
3297 }
3298
3299
3300 /* Break a brick: */
3301
3302 void trybreakbrick(int x, int y, int sx)
3303 {
3304   if (isbrick(x, y, sx))
3305     {
3306       if (shape(x, y, sx) == 'x' || shape(x, y, sx) == 'y')
3307         {
3308           /* Get a distro from it: */
3309
3310           add_bouncy_distro(((x + sx + 1) / 32) * 32,
3311                             (y / 32) * 32);
3312
3313           if (counting_distros == NO)
3314             {
3315               counting_distros = YES;
3316               distro_counter = 50;
3317             }
3318
3319           if (distro_counter <= 0)
3320             change(x, y, sx, 'a');
3321
3322           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3323           score = score + SCORE_DISTRO;
3324           distros++;
3325         }
3326       else
3327         {
3328           /* Get rid of it: */
3329
3330           change(x, y, sx, '.');
3331         }
3332
3333
3334       /* Replace it with broken bits: */
3335
3336       add_broken_brick(((x + sx + 1) / 32) * 32,
3337                        (y / 32) * 32);
3338
3339
3340       /* Get some score: */
3341
3342       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
3343       score = score + SCORE_BRICK;
3344     }
3345 }
3346
3347
3348 /* Bounce a brick: */
3349
3350 void bumpbrick(int x, int y, int sx)
3351 {
3352   add_bouncy_brick(((x + sx + 1) / 32) * 32,
3353                    (y / 32) * 32);
3354
3355   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
3356 }
3357
3358
3359 /* Empty a box: */
3360
3361 void tryemptybox(int x, int y, int sx)
3362 {
3363   if (isfullbox(x, y, sx))
3364     {
3365       if (shape(x, y, sx) == 'A')
3366         {
3367           /* Box with a distro! */
3368
3369           add_bouncy_distro(((x + sx + 1) / 32) * 32,
3370                             (y / 32) * 32 - 32);
3371
3372           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3373           score = score + SCORE_DISTRO;
3374           distros++;
3375         }
3376       else if (shape(x, y, sx) == 'B')
3377         {
3378           /* Add an upgrade! */
3379
3380           if (tux_size == SMALL)
3381             {
3382               /* Tux is small, add mints! */
3383
3384               add_upgrade(((x + sx + 1) / 32) * 32,
3385                           (y / 32) * 32 - 32,
3386                           UPGRADE_MINTS);
3387             }
3388           else
3389             {
3390               /* Tux is big, add coffee: */
3391
3392               add_upgrade(((x + sx + 1) / 32) * 32,
3393                           (y / 32) * 32 - 32,
3394                           UPGRADE_COFFEE);
3395             }
3396
3397           play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
3398         }
3399       else if (shape(x, y, sx) == '!')
3400         {
3401           /* Add a golden herring */
3402
3403           add_upgrade(((x + sx + 1) / 32) * 32,
3404                       (y / 32) * 32 - 32,
3405                       UPGRADE_HERRING);
3406         }
3407
3408       /* Empty the box: */
3409
3410       change(x, y, sx, 'a');
3411     }
3412 }
3413
3414
3415 /* Try to grab a distro: */
3416
3417 void trygrabdistro(int x, int y, int sx, int bounciness)
3418 {
3419   if (shape(x, y, sx) == '$')
3420     {
3421       change(x, y, sx, '.');
3422       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
3423
3424       if (bounciness == BOUNCE)
3425         {
3426           add_bouncy_distro(((x + sx + 1) / 32) * 32,
3427                             (y / 32) * 32);
3428         }
3429
3430       score = score + SCORE_DISTRO;
3431       distros++;
3432     }
3433 }
3434
3435
3436 /* Add a bouncy distro: */
3437
3438 void add_bouncy_distro(int x, int y)
3439 {
3440   int i, found;
3441
3442   found = -1;
3443
3444   for (i = 0; i < NUM_BOUNCY_DISTROS && found == -1; i++)
3445     {
3446       if (!bouncy_distros[i].alive)
3447         found = i;
3448     }
3449
3450   if (found != -1)
3451     {
3452       bouncy_distros[found].alive = YES;
3453       bouncy_distros[found].x = x;
3454       bouncy_distros[found].y = y;
3455       bouncy_distros[found].ym = -6;
3456     }
3457 }
3458
3459
3460 /* Add broken brick pieces: */
3461
3462 void add_broken_brick(int x, int y)
3463 {
3464   add_broken_brick_piece(x, y, -4, -16);
3465   add_broken_brick_piece(x, y + 16, -6, -12);
3466
3467   add_broken_brick_piece(x + 16, y, 4, -16);
3468   add_broken_brick_piece(x + 16, y + 16, 6, -12);
3469 }
3470
3471
3472 /* Add a broken brick piece: */
3473
3474 void add_broken_brick_piece(int x, int y, int xm, int ym)
3475 {
3476   int i, found;
3477
3478   found = -1;
3479
3480   for (i = 0; i < NUM_BROKEN_BRICKS && found == -1; i++)
3481     {
3482       if (!broken_bricks[i].alive)
3483         found = i;
3484     }
3485
3486   if (found != -1)
3487     {
3488       broken_bricks[found].alive = YES;
3489       broken_bricks[found].x = x;
3490       broken_bricks[found].y = y;
3491       broken_bricks[found].xm = xm;
3492       broken_bricks[found].ym = ym;
3493     }
3494 }
3495
3496
3497 /* Add a bouncy brick piece: */
3498
3499 void add_bouncy_brick(int x, int y)
3500 {
3501   int i, found;
3502
3503   found = -1;
3504
3505   for (i = 0; i < NUM_BOUNCY_BRICKS && found == -1; i++)
3506     {
3507       if (!bouncy_bricks[i].alive)
3508         found = i;
3509     }
3510
3511   if (found != -1)
3512     {
3513       bouncy_bricks[found].alive = YES;
3514       bouncy_bricks[found].x = x;
3515       bouncy_bricks[found].y = y;
3516       bouncy_bricks[found].offset = 0;
3517       bouncy_bricks[found].offset_m = -BOUNCY_BRICK_SPEED;
3518       bouncy_bricks[found].shape = shape(x, y, 0);
3519     }
3520 }
3521
3522
3523 /* Add a bad guy: */
3524
3525 void add_bad_guy(int x, int y, int kind)
3526 {
3527   int i, found;
3528
3529   found = -1;
3530
3531   for (i = 0; i < NUM_BAD_GUYS && found == -1; i++)
3532     {
3533       if (!bad_guys[i].alive)
3534         found = i;
3535     }
3536
3537   if (found != -1)
3538     {
3539       bad_guys[found].alive = YES;
3540       bad_guys[found].mode = NORMAL;
3541       bad_guys[found].dying = NO;
3542       bad_guys[found].timer = 0;
3543       bad_guys[found].kind = kind;
3544       bad_guys[found].x = x;
3545       bad_guys[found].y = y;
3546       bad_guys[found].xm = 0;
3547       bad_guys[found].ym = 0;
3548       bad_guys[found].dir = LEFT;
3549       bad_guys[found].seen = NO;
3550     }
3551 }
3552
3553
3554 /* Add score: */
3555
3556 void add_score(int x, int y, int s)
3557 {
3558   int i, found;
3559
3560
3561   /* Add the score: */
3562
3563   score = score + s;
3564
3565
3566   /* Add a floating score thing to the game: */
3567
3568   found = -1;
3569
3570   for (i = 0; i < NUM_FLOATING_SCORES && found == -1; i++)
3571     {
3572       if (!floating_scores[i].alive)
3573         found = i;
3574     }
3575
3576
3577   if (found != -1)
3578     {
3579       floating_scores[found].alive = YES;
3580       floating_scores[found].x = x;
3581       floating_scores[found].y = y - 16;
3582       floating_scores[found].timer = 8;
3583       floating_scores[found].value = s;
3584     }
3585 }
3586
3587
3588 /* Try to bump a bad guy from below: */
3589
3590 void trybumpbadguy(int x, int y, int sx)
3591 {
3592   int i;
3593
3594
3595   /* Bad guys: */
3596
3597   for (i = 0; i < NUM_BAD_GUYS; i++)
3598     {
3599       if (bad_guys[i].alive &&
3600           bad_guys[i].x >= x + sx - 32 && bad_guys[i].x <= x + sx + 32 &&
3601           bad_guys[i].y >= y - 16 && bad_guys[i].y <= y + 16)
3602         {
3603           if (bad_guys[i].kind == BAD_BSOD ||
3604               bad_guys[i].kind == BAD_LAPTOP)
3605             {
3606               bad_guys[i].dying = FALLING;
3607               bad_guys[i].ym = -8;
3608               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
3609             }
3610         }
3611     }
3612
3613
3614   /* Upgrades: */
3615
3616   for (i = 0; i < NUM_UPGRADES; i++)
3617     {
3618       if (upgrades[i].alive && upgrades[i].height == 32 &&
3619           upgrades[i].x >= x + sx - 32 && upgrades[i].x <= x + sx + 32 &&
3620           upgrades[i].y >= y - 16 && upgrades[i].y <= y + 16)
3621         {
3622           upgrades[i].xm = -upgrades[i].xm;
3623           upgrades[i].ym = -8;
3624           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
3625         }
3626     }
3627 }
3628
3629
3630 /* Add an upgrade: */
3631
3632 void add_upgrade(int x, int y, int kind)
3633 {
3634   int i, found;
3635
3636   found = -1;
3637
3638   for (i = 0; i < NUM_UPGRADES && found == -1; i++)
3639     {
3640       if (!upgrades[i].alive)
3641         found = i;
3642     }
3643
3644   if (found != -1)
3645     {
3646       upgrades[found].alive = YES;
3647       upgrades[found].kind = kind;
3648       upgrades[found].x = x;
3649       upgrades[found].y = y;
3650       upgrades[found].xm = 4;
3651       upgrades[found].ym = -4;
3652       upgrades[found].height = 0;
3653     }
3654 }
3655
3656 /* Remove Tux's power ups */
3657 void remove_powerups(void)
3658 {
3659         tux_got_coffee = NO;
3660         tux_size = SMALL;
3661 }
3662
3663
3664 /* Kill tux! */
3665
3666 void killtux(int mode)
3667 {
3668   tux_ym = -16;
3669
3670   play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER);
3671
3672   if (tux_dir == RIGHT)
3673     tux_xm = -8;
3674   else if (tux_dir == LEFT)
3675     tux_xm = 8;
3676
3677   if (mode == SHRINK && tux_size == BIG)
3678     {
3679       if (tux_got_coffee)
3680         tux_got_coffee = NO;
3681
3682       tux_size = SMALL;
3683
3684       tux_safe = TUX_SAFE_TIME;
3685     }
3686   else
3687     {
3688       tux_dying = 1;
3689     }
3690 }
3691
3692
3693 /* Add a bullet: */
3694
3695 void add_bullet(int x, int y, int dir, int xm)
3696 {
3697   int i, found;
3698
3699   found = -1;
3700
3701   for (i = 0; i < NUM_BULLETS && found == -1; i++)
3702     {
3703       if (!bullets[i].alive)
3704         found = i;
3705     }
3706
3707   if (found != -1)
3708     {
3709       bullets[found].alive = YES;
3710
3711       if (dir == RIGHT)
3712         {
3713           bullets[found].x = x + 32;
3714           bullets[found].xm = BULLET_XM + xm;
3715         }
3716       else
3717         {
3718           bullets[found].x = x;
3719           bullets[found].xm = -BULLET_XM + xm;
3720         }
3721
3722       bullets[found].y = y;
3723       bullets[found].ym = BULLET_STARTING_YM;
3724
3725       play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER);
3726     }
3727 }
3728
3729
3730 void drawendscreen(void)
3731 {
3732   char str[80];
3733
3734   clearscreen(0, 0, 0);
3735
3736   drawcenteredtext("GAMEOVER", 200, letters_red, NO_UPDATE, 1);
3737
3738   sprintf(str, "SCORE: %d", score);
3739   drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
3740
3741   sprintf(str, "DISTROS: %d", distros);
3742   drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
3743
3744   SDL_Flip(screen);
3745   SDL_Delay(2000);
3746 }
3747
3748 void drawresultscreen(void)
3749 {
3750   char str[80];
3751
3752   clearscreen(0, 0, 0);
3753
3754   drawcenteredtext("Result:", 200, letters_red, NO_UPDATE, 1);
3755
3756   sprintf(str, "SCORE: %d", score);
3757   drawcenteredtext(str, 224, letters_gold, NO_UPDATE, 1);
3758
3759   sprintf(str, "DISTROS: %d", distros);
3760   drawcenteredtext(str, 256, letters_blue, NO_UPDATE, 1);
3761
3762   SDL_Flip(screen);
3763   SDL_Delay(2000);
3764 }
3765
3766 void savegame(void)
3767 {
3768   char savefile[300];
3769   time_t current_time = time(NULL);
3770   struct tm* time_struct;
3771   FILE* fi;
3772
3773   time_struct = localtime(&current_time);
3774   sprintf(savefile,"%s/%d-%d-%d-%d.save",st_save_dir,time_struct->tm_year+1900,time_struct->tm_mon,time_struct->tm_mday,time_struct->tm_hour);
3775   printf("%s",savefile);
3776
3777
3778   fi = fopen(savefile, "wb");
3779
3780   if (fi == NULL)
3781     {
3782       fprintf(stderr, "Warning: I could not open the high score file ");
3783
3784     }
3785   else
3786   {
3787    fwrite(&level,4,1,fi);
3788    fwrite(&score,4,1,fi);
3789    fwrite(&distros,4,1,fi);
3790    fwrite(&tux_x,4,1,fi);
3791    fwrite(&tux_y,4,1,fi);
3792    fwrite(&scroll_x,4,1,fi);
3793    fwrite(&current_level.time_left,4,1,fi);
3794   }
3795   fclose(fi);
3796
3797 }
3798
3799 void loadgame(char* filename)
3800 {
3801   char savefile[300];
3802   FILE* fi;
3803   time_t current_time = time(NULL);
3804   struct tm* time_struct;
3805   
3806   time_struct = localtime(&current_time);
3807   sprintf(savefile,"%s/%d-%d-%d-%d.save",st_save_dir,time_struct->tm_year+1900,time_struct->tm_mon,time_struct->tm_mday,time_struct->tm_hour);
3808   printf("%s",savefile);
3809
3810
3811   fi = fopen(savefile, "rb");
3812
3813   if (fi == NULL)
3814     {
3815       fprintf(stderr, "Warning: I could not open the high score file ");
3816
3817     }
3818   else
3819   { 
3820   set_defaults();
3821          loadlevel(&current_level,"default",level);
3822          activate_bad_guys();
3823       unloadlevelgfx();
3824       loadlevelgfx();
3825       unloadlevelsong();
3826       loadlevelsong();
3827       levelintro();
3828       
3829    fread(&level,4,1,fi);
3830    fread(&score,4,1,fi);
3831    fread(&distros,4,1,fi);
3832    fread(&tux_x,4,1,fi);
3833    fread(&tux_y,4,1,fi);
3834    fread(&scroll_x,4,1,fi);
3835    fread(&current_level.time_left,4,1,fi);
3836    fclose(fi);
3837   }
3838
3839 }