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