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