6718c13480704d3494385437bb8d4e4e6f2f69cd
[supertux.git] / src / gameloop.cpp
1 /*
2   gameloop.c
3   
4   Super Tux - Game Loop!
5   
6   by Bill Kendrick & Tobias Glaesser
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - March 15, 2004
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <math.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <unistd.h>
19 #include <math.h>
20 #include <time.h>
21 #include <SDL.h>
22
23 #ifndef WIN32
24 #include <sys/types.h>
25 #include <ctype.h>
26 #endif
27
28 #include "defines.h"
29 #include "globals.h"
30 #include "gameloop.h"
31 #include "screen.h"
32 #include "setup.h"
33 #include "high_scores.h"
34 #include "menu.h"
35 #include "badguy.h"
36 #include "world.h"
37 #include "special.h"
38 #include "player.h"
39 #include "level.h"
40 #include "scene.h"
41 #include "collision.h"
42 #include "tile.h"
43 #include "particlesystem.h"
44
45 /* extern variables */
46
47 st_level current_level;
48 int game_started = false;
49
50 /* Local variables: */
51
52 static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
53 static texture_type img_cloud[2][4];
54 static SDL_Event event;
55 static SDLKey key;
56 static char level_subset[100];
57 static float fps_fps;
58 static int st_gl_mode;
59 static unsigned int last_update_time;
60 static unsigned int update_time;
61 static int pause_menu_frame;
62 static int debug_fps;
63
64 /* Local function prototypes: */
65
66 void levelintro(void);
67 void loadshared(void);
68 void unloadshared(void);
69 void drawstatus(void);
70 void drawendscreen(void);
71 void drawresultscreen(void);
72
73 void levelintro(void)
74 {
75   char str[60];
76   /* Level Intro: */
77   clearscreen(0, 0, 0);
78
79   sprintf(str, "LEVEL %d", level);
80   text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1);
81
82   sprintf(str, "%s", current_level.name.c_str());
83   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
84
85   sprintf(str, "TUX x %d", tux.lives);
86   text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
87
88   flipscreen();
89
90   SDL_Event event;
91   wait_for_event(event,1000,3000,true);
92 }
93
94 /* Reset Timers */
95 void start_timers(void)
96 {
97   timer_start(&time_left,current_level.time_left*1000);
98   st_pause_ticks_init();
99   update_time = st_get_ticks();
100 }
101
102 void activate_bad_guys(st_level* plevel)
103 {
104   for (std::vector<BadGuyData>::iterator i = plevel->badguy_data.begin();
105        i != plevel->badguy_data.end();
106        ++i)
107     {
108       add_bad_guy(i->x, i->y, i->kind);
109     }
110 }
111
112 void activate_particle_systems(void)
113 {
114   if(current_level.particle_system == "clouds")
115     {
116       particle_systems.push_back(new CloudParticleSystem);
117     }
118   else if(current_level.particle_system == "snow")
119     {
120       particle_systems.push_back(new SnowParticleSystem);
121     }
122   else if(current_level.particle_system != "")
123     {
124       st_abort("unknown particle system specified in level", "");
125     }
126 }
127
128 /* --- GAME EVENT! --- */
129
130 void game_event(void)
131 {
132   while (SDL_PollEvent(&event))
133     {
134           /* Check for menu-events, if the menu is shown */
135           if(show_menu)
136             menu_event(event);
137       switch(event.type)
138         {
139         case SDL_QUIT:        /* Quit event - quit: */
140           quit = 1;
141           break;
142         case SDL_KEYDOWN:     /* A keypress! */
143           key = event.key.keysym.sym;
144
145           if(tux.key_event(key,DOWN))
146             break;
147
148           switch(key)
149             {
150             case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
151               if(!game_pause)
152                 {
153                   if(st_gl_mode == ST_GL_TEST)
154                     quit = 1;
155                   else if(show_menu)
156                     {
157                       Menu::set_current(game_menu);
158                       show_menu = 0;
159                       st_pause_ticks_stop();
160                     }
161                   else
162                     {
163                       Menu::set_current(game_menu);
164                       show_menu = 1;
165                       st_pause_ticks_start();
166                     }
167                 }
168               break;
169             default:
170               break;
171             }
172           break;
173         case SDL_KEYUP:      /* A keyrelease! */
174           key = event.key.keysym.sym;
175
176           if(tux.key_event(key, UP))
177             break;
178
179           switch(key)
180             {
181             case SDLK_p:
182               if(!show_menu)
183                 {
184                   if(game_pause)
185                     {
186                       game_pause = 0;
187                       st_pause_ticks_stop();
188                     }
189                   else
190                     {
191                       game_pause = 1;
192                       st_pause_ticks_start();
193                     }
194                 }
195               break;
196             case SDLK_TAB:
197               if(debug_mode)
198                 {
199                   tux.size = !tux.size;
200                   if(tux.size == BIG)
201                     {
202                       tux.base.height = 64;
203                     }
204                   else
205                     tux.base.height = 32;
206                 }
207               break;
208             case SDLK_END:
209               if(debug_mode)
210                 distros += 50;
211               break;
212             case SDLK_SPACE:
213               if(debug_mode)
214                 next_level = 1;
215               break;
216             case SDLK_DELETE:
217               if(debug_mode)
218                 tux.got_coffee = 1;
219               break;
220             case SDLK_INSERT:
221               if(debug_mode)
222                 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
223               break;
224             case SDLK_l:
225               if(debug_mode)
226                 --tux.lives;
227               break;
228             case SDLK_s:
229               if(debug_mode)
230                 score += 1000;
231             case SDLK_f:
232               if(debug_fps)
233                 debug_fps = false;
234               else
235                 debug_fps = true;
236               break;
237             default:
238               break;
239             }
240           break;
241
242         case SDL_JOYAXISMOTION:
243           switch(event.jaxis.axis)
244             {
245             case JOY_X:
246               if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
247                 {
248                   tux.input.left  = DOWN;
249                   tux.input.right = UP;
250                 }
251               else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
252                 {
253                   tux.input.left  = UP;
254                   tux.input.right = DOWN;
255                 }
256               else
257                 {
258                   tux.input.left  = DOWN;
259                   tux.input.right = DOWN;
260                 }
261               break;
262             case JOY_Y:
263               if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
264                 tux.input.down = DOWN;
265               else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
266                 tux.input.down = UP;
267               else
268                 tux.input.down = UP;
269               
270               break;
271             default:
272               break;
273             }
274           break;
275         case SDL_JOYBUTTONDOWN:
276           if (event.jbutton.button == JOY_A)
277             tux.input.up = DOWN;
278           else if (event.jbutton.button == JOY_B)
279             tux.input.fire = DOWN;
280           break;
281         case SDL_JOYBUTTONUP:
282           if (event.jbutton.button == JOY_A)
283             tux.input.up = UP;
284           else if (event.jbutton.button == JOY_B)
285             tux.input.fire = UP;
286             
287           break;
288
289         default:
290           break;
291
292         }  /* switch */
293
294     } /* while */
295 }
296
297 /* --- GAME ACTION! --- */
298
299 int game_action(void)
300 {
301   unsigned int i;
302
303   /* (tux.is_dead() || next_level) */
304   if (tux.is_dead() || next_level)
305     {
306       /* Tux either died, or reached the end of a level! */
307
308       halt_music();
309
310
311       if (next_level)
312         {
313           /* End of a level! */
314           level++;
315           next_level = 0;
316           if(st_gl_mode != ST_GL_TEST)
317             {
318               drawresultscreen();
319             }
320           else
321             {
322               level_free_gfx();
323               level_free(&current_level);
324               level_free_song();
325               unloadshared();
326               arrays_free();
327               return(0);
328             }
329           tux.level_begin();
330         }
331       else
332         {
333           tux.is_dying();
334
335           /* No more lives!? */
336
337           if (tux.lives < 0)
338             {
339               if(st_gl_mode != ST_GL_TEST)
340                 drawendscreen();
341
342               if(st_gl_mode != ST_GL_TEST)
343                 {
344                   if (score > hs_score)
345                     save_hs(score);
346                 }
347               level_free_gfx();
348               level_free(&current_level);
349               level_free_song();
350               unloadshared();
351               arrays_free();
352               return(0);
353             } /* if (lives < 0) */
354         }
355
356       /* Either way, (re-)load the (next) level... */
357
358       tux.level_begin();
359       set_defaults();
360       level_free(&current_level);
361
362       if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
363         {
364           if(level_load(&current_level, level_subset) != 0)
365             return 0;
366         }
367       else
368         {
369           if(level_load(&current_level,level_subset,level) != 0)
370             return 0;
371         }
372
373       arrays_free();
374       activate_bad_guys(&current_level);
375       activate_particle_systems();
376       level_free_gfx();
377       level_load_gfx(&current_level);
378       level_free_song();
379       level_load_song(&current_level);
380       if(st_gl_mode != ST_GL_TEST)
381         levelintro();
382       start_timers();
383       /* Play music: */
384       play_current_music();
385     }
386
387   tux.action();
388
389   /* Handle bouncy distros: */
390   for (i = 0; i < bouncy_distros.size(); i++)
391     {
392       bouncy_distro_action(&bouncy_distros[i]);
393     }
394
395
396   /* Handle broken bricks: */
397   for (i = 0; i < broken_bricks.size(); i++)
398     {
399       broken_brick_action(&broken_bricks[i]);
400     }
401
402
403   /* Handle distro counting: */
404
405   if (counting_distros)
406     {
407       distro_counter--;
408
409       if (distro_counter <= 0)
410         counting_distros = -1;
411     }
412
413
414   /* Handle bouncy bricks: */
415
416   for (i = 0; i < bouncy_bricks.size(); i++)
417     {
418       bouncy_brick_action(&bouncy_bricks[i]);
419     }
420
421
422   /* Handle floating scores: */
423
424   for (i = 0; i < floating_scores.size(); i++)
425     {
426       floating_score_action(&floating_scores[i]);
427     }
428
429
430   /* Handle bullets: */
431
432   for (i = 0; i < bullets.size(); ++i)
433     {
434       bullet_action(&bullets[i]);
435     }
436
437   /* Handle upgrades: */
438
439   for (i = 0; i < upgrades.size(); i++)
440     {
441       upgrade_action(&upgrades[i]);
442     }
443
444
445   /* Handle bad guys: */
446
447   for (i = 0; i < bad_guys.size(); i++)
448     {
449       bad_guys[i].action();
450     }
451
452   /* update particle systems */
453   std::vector<ParticleSystem*>::iterator p;
454   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
455     {
456       (*p)->simulate(frame_ratio);
457     }
458
459   /* Handle all possible collisions. */
460   collision_handler();
461
462   return -1;
463 }
464
465 /* --- GAME DRAW! --- */
466
467 void game_draw(void)
468 {
469   int y,x;
470
471   /* Draw screen: */
472   if(timer_check(&super_bkgd_timer))
473     texture_draw(&img_super_bkgd, 0, 0);
474   else
475     {
476       /* Draw the real background */
477       if(current_level.bkgd_image[0] != '\0')
478         {
479           int s = (int)scroll_x / 30;
480           texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h);
481           texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h);
482         }
483       else
484         {
485           clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
486         }
487     }
488
489   /* Draw particle systems (background) */
490   std::vector<ParticleSystem*>::iterator p;
491   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
492     {
493       (*p)->draw(scroll_x, 0, 0);
494     }
495
496   /* Draw background: */
497
498   for (y = 0; y < 15; ++y)
499     {
500       for (x = 0; x < 21; ++x)
501         {
502           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
503                     current_level.bg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
504         }
505     }
506
507   /* Draw interactive tiles: */
508   for (y = 0; y < 15; ++y)
509     {
510       for (x = 0; x < 21; ++x)
511         {
512           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
513                     current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
514         }
515     }
516
517   /* (Bouncy bricks): */
518   for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
519     bouncy_brick_draw(&bouncy_bricks[i]);
520
521   for (unsigned int i = 0; i < bad_guys.size(); ++i)
522     bad_guys[i].draw();
523
524   tux.draw();
525
526   for (unsigned int i = 0; i < bullets.size(); ++i)
527     bullet_draw(&bullets[i]);
528
529   for (unsigned int i = 0; i < floating_scores.size(); ++i)
530     floating_score_draw(&floating_scores[i]);
531
532   for (unsigned int i = 0; i < upgrades.size(); ++i)
533     upgrade_draw(&upgrades[i]);
534
535   for (unsigned int i = 0; i < bouncy_distros.size(); ++i)
536     bouncy_distro_draw(&bouncy_distros[i]);
537
538   for (unsigned int i = 0; i < broken_bricks.size(); ++i)
539     broken_brick_draw(&broken_bricks[i]);
540
541   /* Draw foreground: */
542   for (y = 0; y < 15; ++y)
543     {
544       for (x = 0; x < 21; ++x)
545         {
546           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
547                     current_level.fg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
548         }
549     }
550
551   /* Draw particle systems (foreground) */
552   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
553     {
554       (*p)->draw(scroll_x, 0, 1);
555     }
556
557   drawstatus();
558
559   if(game_pause)
560     {
561       int x = screen->h / 20;
562       for(int i = 0; i < x; ++i)
563         {
564           fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1);
565         }
566       fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
567       text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1);
568     }
569
570   if(show_menu)
571   {
572     menu_process_current();
573     mouse_cursor->draw();
574   }
575
576   /* (Update it all!) */
577   updatescreen();
578 }
579
580 /* --- GAME LOOP! --- */
581
582 int gameloop(const char * subset, int levelnb, int mode)
583 {
584   int fps_cnt, jump, done;
585   timer_type fps_timer, frame_timer;
586   timer_init(&fps_timer, true);
587   timer_init(&frame_timer, true);
588
589   game_started = true;
590
591   st_gl_mode = mode;
592   level = levelnb;
593
594   /* Init the game: */
595   arrays_free();
596   set_defaults();
597
598   strcpy(level_subset,subset);
599
600   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
601     {
602       if (level_load(&current_level, level_subset))
603         exit(1);
604     }
605   else
606     {
607       if(level_load(&current_level, level_subset, level) != 0)
608         exit(1);
609     }
610
611   level_load_gfx(&current_level);
612   loadshared();
613   activate_bad_guys(&current_level);
614   activate_particle_systems();
615   level_load_song(&current_level);
616
617   tux.init();
618
619   if(st_gl_mode != ST_GL_TEST)
620     load_hs();
621
622   if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
623     levelintro();
624
625   timer_init(&time_left,true);
626   start_timers();
627
628   if(st_gl_mode == ST_GL_LOAD_GAME)
629     loadgame(levelnb);
630
631   /* --- MAIN GAME LOOP!!! --- */
632
633   jump = false;
634   done = 0;
635   quit = 0;
636   global_frame_counter = 0;
637   game_pause = 0;
638   timer_init(&fps_timer,true);
639   timer_init(&frame_timer,true);
640   last_update_time = st_get_ticks();
641   fps_cnt = 0;
642
643   /* Clear screen: */
644
645   clearscreen(0, 0, 0);
646   updatescreen();
647
648   /* Play music: */
649   play_current_music();
650
651
652   while (SDL_PollEvent(&event))
653   {}
654
655   game_draw();
656   do
657     {
658       jump = false;
659
660       /* Calculate the movement-factor */
661       frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
662       if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
663         frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
664
665       if(!timer_check(&frame_timer))
666         {
667           timer_start(&frame_timer,25);
668           ++global_frame_counter;
669         }
670
671       /* Handle events: */
672
673       tux.input.old_fire = tux.input.fire;
674
675       game_event();
676
677       if(show_menu)
678         {
679           if(current_menu == game_menu)
680             {
681               switch (game_menu->check())
682                 {
683                 case 2:
684                   st_pause_ticks_stop();
685                   break;
686                 case 3:
687                   update_load_save_game_menu(save_game_menu, false);
688                   break;
689                 case 4:
690                   update_load_save_game_menu(load_game_menu, true);
691                   break;
692                 case 7:
693                   st_pause_ticks_stop();
694                   done = 1;
695                   break;
696                 }
697             }
698           else if(current_menu == options_menu)
699             {
700               process_options_menu();
701             }
702           else if(current_menu == save_game_menu )
703             {
704               process_save_load_game_menu(true);
705             }
706           else if(current_menu == load_game_menu )
707             {
708               process_save_load_game_menu(false);
709             }
710         }
711
712
713       /* Handle actions: */
714
715       if(!game_pause && !show_menu)
716         {
717           /*float z = frame_ratio;
718             frame_ratio = 1;
719             while(z >= 1)
720             {*/
721           if (game_action() == 0)
722             {
723               /* == 0: no more lives */
724               /* == -1: continues */
725               return 0;
726             }
727           /*  --z;
728                      }*/
729         }
730       else
731         {
732           ++pause_menu_frame;
733           SDL_Delay(50);
734         }
735
736       if(debug_mode && debug_fps)
737         SDL_Delay(60);
738
739       /*Draw the current scene to the screen */
740       /*If the machine running the game is too slow
741         skip the drawing of the frame (so the calculations are more precise and
742         the FPS aren't affected).*/
743       /*if( ! fps_fps < 50.0 )
744         game_draw();
745         else
746         jump = true;*/ /*FIXME: Implement this tweak right.*/
747       game_draw();
748
749       /* Time stops in pause mode */
750       if(game_pause || show_menu )
751         {
752           continue;
753         }
754
755       /* Set the time of the last update and the time of the current update */
756       last_update_time = update_time;
757       update_time = st_get_ticks();
758
759       /* Pause till next frame, if the machine running the game is too fast: */
760       /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
761          the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
762       if(last_update_time >= update_time - 12 && !jump) {
763         SDL_Delay(10);
764         update_time = st_get_ticks();
765       }
766       /*if((update_time - last_update_time) < 10)
767         SDL_Delay((11 - (update_time - last_update_time))/2);*/
768
769
770
771       /* Handle time: */
772
773       if (timer_check(&time_left))
774         {
775           /* are we low on time ? */
776           if ((timer_get_left(&time_left) < TIME_WARNING)
777               && (get_current_music() != HURRYUP_MUSIC))     /* play the fast music */
778             {
779               set_current_music(HURRYUP_MUSIC);
780               play_current_music();
781             }
782
783         }
784       else
785         tux.kill(KILL);
786
787
788       /* Calculate frames per second */
789       if(show_fps)
790         {
791           ++fps_cnt;
792           fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
793
794           if(!timer_check(&fps_timer))
795             {
796               timer_start(&fps_timer,1000);
797               fps_cnt = 0;
798             }
799         }
800
801     }
802   while (!done && !quit);
803
804   halt_music();
805
806   level_free_gfx();
807   level_free(&current_level);
808   level_free_song();
809   unloadshared();
810   arrays_free();
811
812   game_started = false;
813
814   return(quit);
815 }
816
817
818 /* Load graphics/sounds shared between all levels: */
819
820 void loadshared(void)
821 {
822   int i;
823
824   /* Tuxes: */
825   texture_load(&tux_right[0], datadir + "/images/shared/tux-right-0.png", USE_ALPHA);
826   texture_load(&tux_right[1], datadir + "/images/shared/tux-right-1.png", USE_ALPHA);
827   texture_load(&tux_right[2], datadir + "/images/shared/tux-right-2.png", USE_ALPHA);
828
829   texture_load(&tux_left[0], datadir + "/images/shared/tux-left-0.png", USE_ALPHA);
830   texture_load(&tux_left[1], datadir + "/images/shared/tux-left-1.png", USE_ALPHA);
831   texture_load(&tux_left[2], datadir + "/images/shared/tux-left-2.png", USE_ALPHA);
832
833   texture_load(&firetux_right[0], datadir + "/images/shared/firetux-right-0.png", USE_ALPHA);
834   texture_load(&firetux_right[1], datadir + "/images/shared/firetux-right-1.png", USE_ALPHA);
835   texture_load(&firetux_right[2], datadir + "/images/shared/firetux-right-2.png", USE_ALPHA);
836
837   texture_load(&firetux_left[0], datadir + "/images/shared/firetux-left-0.png", USE_ALPHA);
838   texture_load(&firetux_left[1], datadir + "/images/shared/firetux-left-1.png", USE_ALPHA);
839   texture_load(&firetux_left[2], datadir + "/images/shared/firetux-left-2.png", USE_ALPHA);
840
841
842   texture_load(&cape_right[0], datadir + "/images/shared/cape-right-0.png",
843                USE_ALPHA);
844
845   texture_load(&cape_right[1], datadir + "/images/shared/cape-right-1.png",
846                USE_ALPHA);
847
848   texture_load(&cape_left[0], datadir + "/images/shared/cape-left-0.png",
849                USE_ALPHA);
850
851   texture_load(&cape_left[1], datadir + "/images/shared/cape-left-1.png",
852                USE_ALPHA);
853
854   texture_load(&bigtux_right[0], datadir + "/images/shared/bigtux-right-0.png",
855                USE_ALPHA);
856
857   texture_load(&bigtux_right[1], datadir + "/images/shared/bigtux-right-1.png",
858                USE_ALPHA);
859
860   texture_load(&bigtux_right[2], datadir + "/images/shared/bigtux-right-2.png",
861                USE_ALPHA);
862
863   texture_load(&bigtux_right_jump, datadir + "/images/shared/bigtux-right-jump.png", USE_ALPHA);
864
865   texture_load(&bigtux_left[0], datadir + "/images/shared/bigtux-left-0.png",
866                USE_ALPHA);
867
868   texture_load(&bigtux_left[1], datadir + "/images/shared/bigtux-left-1.png",
869                USE_ALPHA);
870
871   texture_load(&bigtux_left[2], datadir + "/images/shared/bigtux-left-2.png",
872                USE_ALPHA);
873
874   texture_load(&bigtux_left_jump, datadir + "/images/shared/bigtux-left-jump.png", USE_ALPHA);
875
876   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
877                USE_ALPHA);
878
879   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
880                USE_ALPHA);
881
882   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
883                USE_ALPHA);
884
885   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
886                USE_ALPHA);
887
888   texture_load(&bigfiretux_right[0], datadir + "/images/shared/bigfiretux-right-0.png",
889                USE_ALPHA);
890
891   texture_load(&bigfiretux_right[1], datadir + "/images/shared/bigfiretux-right-1.png",
892                USE_ALPHA);
893
894   texture_load(&bigfiretux_right[2], datadir + "/images/shared/bigfiretux-right-2.png",
895                USE_ALPHA);
896
897   texture_load(&bigfiretux_right_jump, datadir + "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
898
899   texture_load(&bigfiretux_left[0], datadir + "/images/shared/bigfiretux-left-0.png",
900                USE_ALPHA);
901
902   texture_load(&bigfiretux_left[1], datadir + "/images/shared/bigfiretux-left-1.png",
903                USE_ALPHA);
904
905   texture_load(&bigfiretux_left[2], datadir + "/images/shared/bigfiretux-left-2.png",
906                USE_ALPHA);
907
908   texture_load(&bigfiretux_left_jump, datadir + "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
909
910   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
911                USE_ALPHA);
912
913   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
914                USE_ALPHA);
915
916   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
917                USE_ALPHA);
918
919   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
920                USE_ALPHA);
921
922
923   texture_load(&ducktux_right, datadir +
924                "/images/shared/ducktux-right.png",
925                USE_ALPHA);
926
927   texture_load(&ducktux_left, datadir +
928                "/images/shared/ducktux-left.png",
929                USE_ALPHA);
930
931   texture_load(&skidtux_right, datadir +
932                "/images/shared/skidtux-right.png",
933                USE_ALPHA);
934
935   texture_load(&skidtux_left, datadir +
936                "/images/shared/skidtux-left.png",
937                USE_ALPHA);
938
939   texture_load(&duckfiretux_right, datadir +
940                "/images/shared/duckfiretux-right.png",
941                USE_ALPHA);
942
943   texture_load(&duckfiretux_left, datadir +
944                "/images/shared/duckfiretux-left.png",
945                USE_ALPHA);
946
947   texture_load(&skidfiretux_right, datadir +
948                "/images/shared/skidfiretux-right.png",
949                USE_ALPHA);
950
951   texture_load(&skidfiretux_left, datadir +
952                "/images/shared/skidfiretux-left.png",
953                USE_ALPHA);
954
955
956   /* Boxes: */
957
958   texture_load(&img_box_full, datadir + "/images/shared/box-full.png",
959                IGNORE_ALPHA);
960   texture_load(&img_box_empty, datadir + "/images/shared/box-empty.png",
961                IGNORE_ALPHA);
962
963
964   /* Water: */
965
966
967   texture_load(&img_water, datadir + "/images/shared/water.png", IGNORE_ALPHA);
968
969   texture_load(&img_waves[0], datadir + "/images/shared/waves-0.png",
970                USE_ALPHA);
971
972   texture_load(&img_waves[1], datadir + "/images/shared/waves-1.png",
973                USE_ALPHA);
974
975   texture_load(&img_waves[2], datadir + "/images/shared/waves-2.png",
976                USE_ALPHA);
977
978
979   /* Pole: */
980
981   texture_load(&img_pole, datadir + "/images/shared/pole.png", USE_ALPHA);
982   texture_load(&img_poletop, datadir + "/images/shared/poletop.png",
983                USE_ALPHA);
984
985
986   /* Flag: */
987
988   texture_load(&img_flag[0], datadir + "/images/shared/flag-0.png",
989                USE_ALPHA);
990   texture_load(&img_flag[1], datadir + "/images/shared/flag-1.png",
991                USE_ALPHA);
992
993
994   /* Cloud: */
995
996   texture_load(&img_cloud[0][0], datadir + "/images/shared/cloud-00.png",
997                USE_ALPHA);
998
999   texture_load(&img_cloud[0][1], datadir + "/images/shared/cloud-01.png",
1000                USE_ALPHA);
1001
1002   texture_load(&img_cloud[0][2], datadir + "/images/shared/cloud-02.png",
1003                USE_ALPHA);
1004
1005   texture_load(&img_cloud[0][3], datadir + "/images/shared/cloud-03.png",
1006                USE_ALPHA);
1007
1008
1009   texture_load(&img_cloud[1][0], datadir + "/images/shared/cloud-10.png",
1010                USE_ALPHA);
1011
1012   texture_load(&img_cloud[1][1], datadir + "/images/shared/cloud-11.png",
1013                USE_ALPHA);
1014
1015   texture_load(&img_cloud[1][2], datadir + "/images/shared/cloud-12.png",
1016                USE_ALPHA);
1017
1018   texture_load(&img_cloud[1][3], datadir + "/images/shared/cloud-13.png",
1019                USE_ALPHA);
1020
1021
1022   /* Bad guys: */
1023   load_badguy_gfx();
1024
1025   /* Upgrades: */
1026
1027   texture_load(&img_mints, datadir + "/images/shared/mints.png", USE_ALPHA);
1028   texture_load(&img_coffee, datadir + "/images/shared/coffee.png", USE_ALPHA);
1029
1030
1031   /* Weapons: */
1032
1033   texture_load(&img_bullet, datadir + "/images/shared/bullet.png", USE_ALPHA);
1034
1035   texture_load(&img_red_glow, datadir + "/images/shared/red-glow.png",
1036                USE_ALPHA);
1037
1038
1039
1040   /* Distros: */
1041
1042   texture_load(&img_distro[0], datadir + "/images/shared/distro-0.png",
1043                USE_ALPHA);
1044
1045   texture_load(&img_distro[1], datadir + "/images/shared/distro-1.png",
1046                USE_ALPHA);
1047
1048   texture_load(&img_distro[2], datadir + "/images/shared/distro-2.png",
1049                USE_ALPHA);
1050
1051   texture_load(&img_distro[3], datadir + "/images/shared/distro-3.png",
1052                USE_ALPHA);
1053
1054
1055   /* Tux life: */
1056
1057   texture_load(&tux_life, datadir + "/images/shared/tux-life.png",
1058                USE_ALPHA);
1059
1060   /* Herring: */
1061
1062   texture_load(&img_golden_herring, datadir + "/images/shared/golden-herring.png",
1063                USE_ALPHA);
1064
1065
1066   /* Super background: */
1067
1068   texture_load(&img_super_bkgd, datadir + "/images/shared/super-bkgd.png",
1069                IGNORE_ALPHA);
1070
1071
1072   /* Sound effects: */
1073
1074   /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1075                     // initialize sounds[i] with the correct pointer's value:
1076                     // NULL or something else. And it will be dangerous to
1077                     // play with not-initialized pointers.
1078                     // This is also true with if (use_music)
1079                     Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1080   */
1081   for (i = 0; i < NUM_SOUNDS; i++)
1082     sounds[i] = load_sound(datadir + soundfilenames[i]);
1083
1084   /* Herring song */
1085   herring_song = load_song(datadir + "/music/SALCON.MOD");
1086 }
1087
1088
1089 /* Free shared data: */
1090
1091 void unloadshared(void)
1092 {
1093   int i;
1094
1095   for (i = 0; i < 3; i++)
1096     {
1097       texture_free(&tux_right[i]);
1098       texture_free(&tux_left[i]);
1099       texture_free(&bigtux_right[i]);
1100       texture_free(&bigtux_left[i]);
1101     }
1102
1103   texture_free(&bigtux_right_jump);
1104   texture_free(&bigtux_left_jump);
1105
1106   for (i = 0; i < 2; i++)
1107     {
1108       texture_free(&cape_right[i]);
1109       texture_free(&cape_left[i]);
1110       texture_free(&bigcape_right[i]);
1111       texture_free(&bigcape_left[i]);
1112     }
1113
1114   texture_free(&ducktux_left);
1115   texture_free(&ducktux_right);
1116
1117   texture_free(&skidtux_left);
1118   texture_free(&skidtux_right);
1119
1120   free_badguy_gfx();
1121
1122   texture_free(&img_box_full);
1123   texture_free(&img_box_empty);
1124
1125   texture_free(&img_water);
1126   for (i = 0; i < 3; i++)
1127     texture_free(&img_waves[i]);
1128
1129   texture_free(&img_pole);
1130   texture_free(&img_poletop);
1131
1132   for (i = 0; i < 2; i++)
1133     texture_free(&img_flag[i]);
1134
1135   texture_free(&img_mints);
1136   texture_free(&img_coffee);
1137
1138   for (i = 0; i < 4; i++)
1139     {
1140       texture_free(&img_distro[i]);
1141       texture_free(&img_cloud[0][i]);
1142       texture_free(&img_cloud[1][i]);
1143     }
1144
1145   texture_free(&img_golden_herring);
1146
1147   for (i = 0; i < NUM_SOUNDS; i++)
1148     free_chunk(sounds[i]);
1149
1150   /* free the herring song */
1151   free_music( herring_song );
1152 }
1153
1154
1155 /* Draw a tile on the screen: */
1156
1157 void drawshape(float x, float y, unsigned int c, Uint8 alpha)
1158 {
1159   if (c != 0)
1160     {
1161       Tile* ptile = TileManager::instance()->get(c);
1162       if(ptile)
1163         {
1164           if(ptile->images.size() > 1)
1165             {
1166               texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y, alpha);
1167             }
1168           else if (ptile->images.size() == 1)
1169             {
1170               texture_draw(&ptile->images[0],x,y, alpha);
1171             }
1172           else
1173             {
1174               //printf("Tile not dravable %u\n", c);
1175             }
1176         }
1177     }
1178 }
1179
1180
1181 /* What shape is at some position? */
1182 unsigned int shape(float x, float y)
1183 {
1184
1185   int xx, yy;
1186   unsigned int c;
1187
1188   yy = ((int)y / 32);
1189   xx = ((int)x / 32);
1190
1191   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1192     {
1193       c = current_level.ia_tiles[yy][xx];
1194     }
1195   else
1196     c = 0;
1197
1198   return(c);
1199 }
1200
1201 Tile* gettile(float x, float y)
1202 {
1203   return TileManager::instance()->get(shape(x, y));
1204 }
1205
1206 bool issolid(float x, float y)
1207 {
1208   Tile* tile = TileManager::instance()->get
1209                (shape(x,y));
1210   if(tile)
1211     {
1212       if(tile->solid == true)
1213         return true;
1214       else
1215         return false;
1216     }
1217   else
1218     {
1219       return false;
1220     }
1221 }
1222
1223 /* Is it a brick? */
1224
1225 bool isbrick(float x, float y)
1226 {
1227   Tile* tile = TileManager::instance()->get
1228                (shape(x,y));
1229   if(tile)
1230     {
1231       if(tile->brick == true)
1232         return true;
1233       else
1234         return false;
1235     }
1236   else
1237     {
1238       return false;
1239     }
1240 }
1241
1242
1243 /* Is it ice? */
1244
1245 bool isice(float x, float y)
1246 {
1247   Tile* tile = TileManager::instance()->get
1248                (shape(x,y));
1249   if(tile)
1250     {
1251       if(tile->ice == true)
1252         return true;
1253       else
1254         return false;
1255     }
1256   else
1257     {
1258       return false;
1259     }
1260 }
1261
1262 /* Is it a full box? */
1263
1264 bool isfullbox(float x, float y)
1265 {
1266   Tile* tile = TileManager::instance()->get
1267                (shape(x,y));
1268   if(tile)
1269     {
1270       if(tile->fullbox == true)
1271         return true;
1272       else
1273         return false;
1274     }
1275   else
1276     {
1277       return false;
1278     }
1279 }
1280
1281 bool isdistro(float x, float y)
1282 {
1283   Tile* tile = TileManager::instance()->get(shape(x,y));
1284   return tile && tile->distro;
1285 }
1286
1287 /* Break a brick: */
1288 void trybreakbrick(float x, float y, bool small)
1289 {
1290   Tile* tile = gettile(x, y);
1291   if (tile->brick)
1292     {
1293       if (tile->data > 0)
1294         {
1295           /* Get a distro from it: */
1296           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1297                             (int)(y / 32) * 32);
1298
1299           if (!counting_distros)
1300             {
1301               counting_distros = true;
1302               distro_counter = 50;
1303             }
1304
1305           if (distro_counter <= 0)
1306             level_change(&current_level,x, y, TM_IA, tile->next_tile);
1307
1308           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1309           score = score + SCORE_DISTRO;
1310           distros++;
1311         }
1312       else if (!small)
1313         {
1314           /* Get rid of it: */
1315           level_change(&current_level,x, y, TM_IA, tile->next_tile);
1316           
1317           /* Replace it with broken bits: */
1318           add_broken_brick(((int)(x + 1) / 32) * 32,
1319                            (int)(y / 32) * 32);
1320           
1321           /* Get some score: */
1322           play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1323           score = score + SCORE_BRICK;
1324         }
1325     }
1326 }
1327
1328
1329 /* Bounce a brick: */
1330
1331 void bumpbrick(float x, float y)
1332 {
1333   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1334                    (int)(y / 32) * 32);
1335
1336   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1337
1338 }
1339
1340
1341 /* Empty a box: */
1342 void tryemptybox(float x, float y, int col_side)
1343 {
1344   Tile* tile = gettile(x,y);
1345   if (!tile->fullbox)
1346     return;
1347
1348   // according to the collision side, set the upgrade direction
1349   if(col_side == LEFT)
1350     col_side = RIGHT;
1351   else
1352     col_side = LEFT;
1353
1354   switch(tile->data)
1355     {
1356     case 1: //'A':      /* Box with a distro! */
1357       add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1358       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1359       score = score + SCORE_DISTRO;
1360       distros++;
1361       break;
1362
1363     case 2: // 'B':      /* Add an upgrade! */
1364       if (tux.size == SMALL)     /* Tux is small, add mints! */
1365         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1366       else     /* Tux is big, add coffee: */
1367         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1368       play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1369       break;
1370
1371     case 3:// '!':     /* Add a golden herring */
1372       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1373       break;
1374     default:
1375       break;
1376     }
1377
1378   /* Empty the box: */
1379   level_change(&current_level,x, y, TM_IA, tile->next_tile);
1380 }
1381
1382 /* Try to grab a distro: */
1383 void trygrabdistro(float x, float y, int bounciness)
1384 {
1385   Tile* tile = gettile(x, y);
1386   if (tile && tile->distro)
1387     {
1388       level_change(&current_level,x, y, TM_IA, tile->next_tile);
1389       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1390
1391       if (bounciness == BOUNCE)
1392         {
1393           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1394                             (int)(y / 32) * 32);
1395         }
1396
1397       score = score + SCORE_DISTRO;
1398       distros++;
1399     }
1400 }
1401
1402 /* Try to bump a bad guy from below: */
1403 void trybumpbadguy(float x, float y)
1404 {
1405   /* Bad guys: */
1406   for (unsigned int i = 0; i < bad_guys.size(); i++)
1407     {
1408       if (bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1409           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1410         {
1411           bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_BUMP);
1412         }
1413     }
1414
1415
1416   /* Upgrades: */
1417   for (unsigned int i = 0; i < upgrades.size(); i++)
1418     {
1419       if (upgrades[i].base.height == 32 &&
1420           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1421           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1422         {
1423           upgrades[i].base.xm = -upgrades[i].base.xm;
1424           upgrades[i].base.ym = -8;
1425           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1426         }
1427     }
1428 }
1429
1430 /* (Status): */
1431 void drawstatus(void)
1432 {
1433   char str[60];
1434
1435   sprintf(str, "%d", score);
1436   text_draw(&white_text, "SCORE", 0, 0, 1);
1437   text_draw(&gold_text, str, 96, 0, 1);
1438
1439   if(st_gl_mode != ST_GL_TEST)
1440     {
1441       sprintf(str, "%d", hs_score);
1442       text_draw(&white_text, "HIGH", 0, 20, 1);
1443       text_draw(&gold_text, str, 96, 20, 1);
1444     }
1445   else
1446     {
1447       text_draw(&white_text,"Press ESC To Return",0,20,1);
1448     }
1449
1450   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1451     {
1452       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1453       text_draw(&white_text, "TIME", 224, 0, 1);
1454       text_draw(&gold_text, str, 304, 0, 1);
1455     }
1456
1457   sprintf(str, "%d", distros);
1458   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1459   text_draw(&gold_text, str, 608, 0, 1);
1460
1461   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1462
1463   if(show_fps)
1464     {
1465       sprintf(str, "%2.1f", fps_fps);
1466       text_draw(&white_text, "FPS", screen->h, 40, 1);
1467       text_draw(&gold_text, str, screen->h + 60, 40, 1);
1468     }
1469
1470   for(int i=0; i < tux.lives; ++i)
1471     {
1472       texture_draw(&tux_life,565+(18*i),20);
1473     }
1474 }
1475
1476
1477 void drawendscreen(void)
1478 {
1479   char str[80];
1480
1481   clearscreen(0, 0, 0);
1482
1483   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1484
1485   sprintf(str, "SCORE: %d", score);
1486   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1487
1488   sprintf(str, "DISTROS: %d", distros);
1489   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1490
1491   flipscreen();
1492   
1493   SDL_Event event;
1494   wait_for_event(event,2000,5000,true);
1495 }
1496
1497 void drawresultscreen(void)
1498 {
1499   char str[80];
1500
1501   clearscreen(0, 0, 0);
1502
1503   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1504
1505   sprintf(str, "SCORE: %d", score);
1506   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1507
1508   sprintf(str, "DISTROS: %d", distros);
1509   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1510
1511   flipscreen();
1512   
1513   SDL_Event event;
1514   wait_for_event(event,2000,5000,true);
1515 }
1516
1517 void savegame(int slot)
1518 {
1519   char savefile[1024];
1520   FILE* fi;
1521   unsigned int ui;
1522
1523   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1524
1525   fi = fopen(savefile, "wb");
1526
1527   if (fi == NULL)
1528     {
1529       fprintf(stderr, "Warning: I could not open the slot file ");
1530     }
1531   else
1532     {
1533       fputs(level_subset, fi);
1534       fputs("\n", fi);
1535       fwrite(&level,sizeof(int),1,fi);
1536       fwrite(&score,sizeof(int),1,fi);
1537       fwrite(&distros,sizeof(int),1,fi);
1538       fwrite(&scroll_x,sizeof(float),1,fi);
1539       fwrite(&tux,sizeof(Player),1,fi);
1540       timer_fwrite(&tux.invincible_timer,fi);
1541       timer_fwrite(&tux.skidding_timer,fi);
1542       timer_fwrite(&tux.safe_timer,fi);
1543       timer_fwrite(&tux.frame_timer,fi);
1544       timer_fwrite(&time_left,fi);
1545       ui = st_get_ticks();
1546       fwrite(&ui,sizeof(int),1,fi);
1547     }
1548   fclose(fi);
1549
1550 }
1551
1552 void loadgame(int slot)
1553 {
1554   char savefile[1024];
1555   char str[100];
1556   FILE* fi;
1557   unsigned int ui;
1558
1559   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1560
1561   fi = fopen(savefile, "rb");
1562
1563   if (fi == NULL)
1564     {
1565       fprintf(stderr, "Warning: I could not open the slot file ");
1566
1567     }
1568   else
1569     {
1570       fgets(str, 100, fi);
1571       strcpy(level_subset, str);
1572       level_subset[strlen(level_subset)-1] = '\0';
1573       fread(&level,sizeof(int),1,fi);
1574
1575       set_defaults();
1576       level_free(&current_level);
1577       if(level_load(&current_level,level_subset,level) != 0)
1578         exit(1);
1579       arrays_free();
1580       activate_bad_guys(&current_level);
1581       activate_particle_systems();
1582       level_free_gfx();
1583       level_load_gfx(&current_level);
1584       level_free_song();
1585       level_load_song(&current_level);
1586       levelintro();
1587       update_time = st_get_ticks();
1588
1589       fread(&score,sizeof(int),1,fi);
1590       fread(&distros,sizeof(int),1,fi);
1591       fread(&scroll_x,sizeof(float),1,fi);
1592       fread(&tux, sizeof(Player), 1, fi);
1593       timer_fread(&tux.invincible_timer,fi);
1594       timer_fread(&tux.skidding_timer,fi);
1595       timer_fread(&tux.safe_timer,fi);
1596       timer_fread(&tux.frame_timer,fi);
1597       timer_fread(&time_left,fi);
1598       fread(&ui,sizeof(int),1,fi);
1599       fclose(fi);
1600     }
1601
1602 }
1603
1604 void slotinfo(char **pinfo, int slot)
1605 {
1606   FILE* fi;
1607   char slotfile[1024];
1608   char tmp[200];
1609   char str[5];
1610   int slot_level;
1611   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1612
1613   fi = fopen(slotfile, "rb");
1614
1615   sprintf(tmp,"Slot %d - ",slot);
1616
1617   if (fi == NULL)
1618     {
1619       strcat(tmp,"Free");
1620     }
1621   else
1622     {
1623       fgets(str, 100, fi);
1624       str[strlen(str)-1] = '\0';
1625       strcat(tmp, str);
1626       strcat(tmp, " / Level:");
1627       fread(&slot_level,sizeof(int),1,fi);
1628       sprintf(str,"%d",slot_level);
1629       strcat(tmp,str);
1630       fclose(fi);
1631     }
1632
1633   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1634   strcpy(*pinfo,tmp);
1635 }
1636