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