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