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