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