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