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