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