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