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