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