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