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