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