rnd-20000718-1-src
[rocksndiamonds.git] / src / main.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  main.c                                                  *
12 ***********************************************************/
13
14 #include "main.h"
15 #include "init.h"
16 #include "game.h"
17 #include "events.h"
18 #include "sound.h"
19 #include "joystick.h"
20 #include "misc.h"
21
22 #ifdef MSDOS
23 #include <fcntl.h>
24 #endif
25
26 Display        *display;
27 Visual         *visual;
28 int             screen;
29 Window          window;
30 GC              gc, clip_gc[NUM_PIXMAPS], tile_clip_gc;
31 Pixmap          pix[NUM_PIXMAPS];
32 Pixmap          clipmask[NUM_PIXMAPS], tile_clipmask[NUM_TILES];
33
34 #ifdef USE_XPM_LIBRARY
35 XpmAttributes   xpm_att[NUM_PICTURES];
36 #endif
37
38 Drawable        drawto, drawto_field, backbuffer, fieldbuffer;
39 Colormap        cmap;
40
41 #ifdef USE_SDL_LIBRARY
42 SDL_Surface    *sdl_window;
43 SDL_Surface    *sdl_drawto, *sdl_drawto_field;
44 SDL_Surface    *sdl_backbuffer, *sdl_fieldbuffer;
45 SDL_Surface    *sdl_pix[NUM_PIXMAPS];
46 SDL_Surface    *sdl_pix_masked[NUM_PIXMAPS], *sdl_tile_masked[NUM_TILES];
47 #endif
48
49 int             sound_pipe[2];
50 int             sound_device;
51 char           *sound_device_name = SOUND_DEVICE;
52 int             joystick_device = 0;
53 char           *joystick_device_name[MAX_PLAYERS] =
54 {
55   DEV_JOYSTICK_0,
56   DEV_JOYSTICK_1,
57   DEV_JOYSTICK_2,
58   DEV_JOYSTICK_3
59 };
60
61 char           *program_name = NULL;
62
63 int             game_status = MAINMENU;
64 boolean         level_editor_test_game = FALSE;
65 boolean         network_playing = FALSE;
66 int             button_status = MB_NOT_PRESSED;
67 boolean         motion_status = FALSE;
68 int             key_joystick_mapping = 0;
69 int             global_joystick_status = JOYSTICK_STATUS;
70 int             joystick_status = JOYSTICK_STATUS;
71 int             sound_status = SOUND_STATUS;
72 boolean         sound_loops_allowed = FALSE;
73
74 boolean         redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE];
75 int             redraw_x1 = 0, redraw_y1 = 0;
76 int             redraw_mask;
77 int             redraw_tiles;
78
79 short           Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
80 short           Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
81 short           MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
82 short           MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
83 short           MovDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
84 short           Store[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
85 short           Store2[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
86 short           StorePlayer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
87 short           Frame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
88 boolean         Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
89 short           JustStopped[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
90 short           AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
91 short           AmoebaCnt[MAX_NUM_AMOEBA], AmoebaCnt2[MAX_NUM_AMOEBA];
92 unsigned long   Elementeigenschaften1[MAX_ELEMENTS];
93 unsigned long   Elementeigenschaften2[MAX_ELEMENTS];
94
95 int             level_nr;
96 int             lev_fieldx,lev_fieldy, scroll_x,scroll_y;
97
98 int             FX = SX, FY = SY, ScrollStepSize;
99 int             ScreenMovDir = MV_NO_MOVING, ScreenMovPos = 0;
100 int             ScreenGfxPos = 0;
101 int             BorderElement = EL_BETON;
102 int             GameFrameDelay = GAME_FRAME_DELAY;
103 int             FfwdFrameDelay = FFWD_FRAME_DELAY;
104 int             BX1 = 0, BY1 = 0, BX2 = SCR_FIELDX-1, BY2 = SCR_FIELDY-1;
105 int             SBX_Left, SBX_Right;
106 int             SBY_Upper, SBY_Lower;
107 int             ZX,ZY, ExitX,ExitY;
108 int             AllPlayersGone;
109 int             FrameCounter, TimeFrames, TimePlayed, TimeLeft;
110
111 boolean         network_player_action_received = FALSE;
112
113 struct LevelDirInfo    *leveldir_first = NULL, *leveldir_current = NULL;
114 struct LevelInfo        level;
115 struct PlayerInfo       stored_player[MAX_PLAYERS], *local_player = NULL;
116 struct HiScore          highscore[MAX_SCORE_ENTRIES];
117 struct SoundInfo        Sound[NUM_SOUNDS];
118 struct TapeInfo         tape;
119 struct OptionInfo       options;
120 struct SetupInfo        setup;
121 struct GameInfo         game;
122 struct GlobalInfo       global;
123
124 /* data needed for playing sounds */
125 char *sound_name[NUM_SOUNDS] =
126 {
127   "alchemy",
128   "amoebe",
129   "antigrav",
130   "autsch",
131   "blurb",
132   "bong",
133   "buing",
134   "chase",
135   "czardasz",
136   "deng",
137   "fuel",
138   "gong",
139   "halloffame",
140   "holz",
141   "hui",
142   "kabumm",
143   "kink",
144   "klapper",
145   "kling",
146   "klopf",
147   "klumpf",
148   "knack",
149   "knurk",
150   "krach",
151   "lachen",
152   "laser",
153   "miep",
154   "network",
155   "njam",
156   "oeffnen",
157   "pling",
158   "pong",
159   "pusch",
160   "quiek",
161   "quirk",
162   "rhythmloop",
163   "roaaar",
164   "roehr",
165   "rumms",
166   "schlopp",
167   "schlurf",
168   "schrff",
169   "schwirr",
170   "sirr",
171   "slurp",
172   "sproing",
173   "twilight",
174   "tyger",
175   "voyager",
176   "warnton",
177   "whoosh",
178   "zisch",
179   "base",
180   "infotron",
181   "zonkdown",
182   "zonkpush",
183   "bug",
184   "boom",
185   "booom",
186   "exit",
187   "empty",
188   "gate"
189 };
190
191 /* background music */
192 int background_loop[] =
193 {
194   SND_ALCHEMY,
195   SND_CHASE,
196   SND_NETWORK,
197   SND_CZARDASZ,
198   SND_TYGER,
199   SND_VOYAGER,
200   SND_TWILIGHT
201 };
202 int num_bg_loops = sizeof(background_loop)/sizeof(int);
203
204 char *element_info[] =
205 {
206   "empty space",                                /* 0 */
207   "sand",
208   "normal wall",
209   "round wall",
210   "rock",
211   "key",
212   "emerald",
213   "closed exit",
214   "player",
215   "bug",
216   "spaceship",                                  /* 10 */
217   "yam yam",
218   "robot",
219   "steel wall",
220   "diamond",
221   "dead amoeba",
222   "empty quicksand",
223   "quicksand with rock",
224   "amoeba drop",
225   "bomb",
226   "magic wall",                                 /* 20 */
227   "speed ball",
228   "acid pool",
229   "dropping amoeba",
230   "normal amoeba",
231   "nut with emerald",
232   "life wall",
233   "biomaze",
234   "burning dynamite",
235   "unknown",
236   "magic wheel",                                /* 30 */
237   "running wire",
238   "red key",
239   "yellow key",
240   "green key",
241   "blue key",
242   "red door",
243   "yellow door",
244   "green door",
245   "blue door",
246   "gray door (opened by red key)",              /* 40 */
247   "gray door (opened by yellow key)",
248   "gray door (opened by green key)",
249   "gray door (opened by blue key)",
250   "dynamite",
251   "pac man",
252   "invisible normal wall",
253   "light bulb (dark)",
254   "ligh bulb (glowing)",
255   "wall with emerald",
256   "wall with diamond",                          /* 50 */
257   "amoeba with content",
258   "amoeba (BD style)",
259   "time orb (full)",
260   "time orb (empty)",
261   "growing wall",
262   "diamond (BD style)",
263   "yellow emerald",
264   "wall with BD style diamond",
265   "wall with yellow emerald",
266   "dark yam yam",                               /* 60 */
267   "magic wall (BD style)",
268   "invisible steel wall",
269   "-",
270   "increases number of bombs",
271   "increases explosion size",
272   "increases power of explosion",
273   "sokoban object",
274   "sokoban empty field",
275   "sokoban field with object",
276   "butterfly (starts moving right)",            /* 70 */
277   "butterfly (starts moving up)",
278   "butterfly (starts moving left)",
279   "butterfly (starts moving down)",
280   "firefly (starts moving right)",
281   "firefly (starts moving up)",
282   "firefly (starts moving left)",
283   "firefly (starts moving down)",
284   "butterfly",
285   "firefly",
286   "yellow player",                              /* 80 */
287   "red player",
288   "green player",
289   "blue player",
290   "bug (starts moving right)",
291   "bug (starts moving up)",
292   "bug (starts moving left)",
293   "bug (starts moving down)",
294   "spaceship (starts moving right)",
295   "spaceship (starts moving up)",
296   "spaceship (starts moving left)",             /* 90 */
297   "spaceship (starts moving down)",
298   "pac man (starts moving right)",
299   "pac man (starts moving up)",
300   "pac man (starts moving left)",
301   "pac man (starts moving down)",
302   "red emerald",
303   "violet emerald",
304   "wall with red emerald",
305   "wall with violet emerald",
306   "unknown",                                    /* 100 */
307   "unknown",
308   "unknown",
309   "unknown",
310   "unknown",
311   "normal wall (BD style)",
312   "rock (BD style)",
313   "open exit",
314   "unknown",
315   "amoeba",
316   "mole",                                       /* 110 */
317   "penguin",
318   "satellite",
319   "arrow left",
320   "arrow right",
321   "arrow up",
322   "arrow down",
323   "pig",
324   "fire breathing dragon",
325   "unknown",
326   "letter ' '",                                 /* 120 */
327   "letter '!'",
328   "letter '\"'",
329   "letter '#'",
330   "letter '$'",
331   "letter '%'",
332   "letter '&'",
333   "letter '''",
334   "letter '('",
335   "letter ')'",
336   "letter '*'",                                 /* 130 */
337   "letter '+'",
338   "letter ','",
339   "letter '-'",
340   "letter '.'",
341   "letter '/'",
342   "letter '0'",
343   "letter '1'",
344   "letter '2'",
345   "letter '3'",
346   "letter '4'",                                 /* 140 */
347   "letter '5'",
348   "letter '6'",
349   "letter '7'",
350   "letter '8'",
351   "letter '9'",
352   "letter ':'",
353   "letter ';'",
354   "letter '<'",
355   "letter '='",
356   "letter '>'",                                 /* 150 */
357   "letter '?'",
358   "letter '@'",
359   "letter 'A'",
360   "letter 'B'",
361   "letter 'C'",
362   "letter 'D'",
363   "letter 'E'",
364   "letter 'F'",
365   "letter 'G'",
366   "letter 'H'",                                 /* 160 */
367   "letter 'I'",
368   "letter 'J'",
369   "letter 'K'",
370   "letter 'L'",
371   "letter 'M'",
372   "letter 'N'",
373   "letter 'O'",
374   "letter 'P'",
375   "letter 'Q'",
376   "letter 'R'",                                 /* 170 */
377   "letter 'S'",
378   "letter 'T'",
379   "letter 'U'",
380   "letter 'V'",
381   "letter 'W'",
382   "letter 'X'",
383   "letter 'Y'",
384   "letter 'Z'",
385   "letter 'Ä'",
386   "letter 'Ö'",                                 /* 180 */
387   "letter 'Ü'",
388   "letter '^'",
389   "letter ''",
390   "letter ''",
391   "letter ''",
392   "letter ''",
393   "letter ''",
394   "letter ''",
395   "letter ''",
396   "letter ''",                                  /* 190 */
397   "letter ''",
398   "letter ''",
399   "letter ''",
400   "letter ''",
401   "letter ''",
402   "letter ''",
403   "letter ''",
404   "letter ''",
405   "letter ''",
406   "growing wall (horizontal)",                  /* 200 */
407   "growing wall (vertical)",
408   "growing wall (all directions)",
409   "unused",
410   "unused",
411   "unused",
412   "unused",
413   "unused",
414   "unused",
415   "unused",
416   "empty space",                                /* 210 */
417   "zonk",
418   "base",
419   "murphy",
420   "infotron",
421   "chip (single)",
422   "hardware",
423   "exit",
424   "orange disk",
425   "port (leading right)",
426   "port (leading down)",                        /* 220 */
427   "port (leading left)",
428   "port (leading up)",
429   "port (leading right)",
430   "port (leading down)",
431   "port (leading left)",
432   "port (leading up)",
433   "snik snak",
434   "yellow disk",
435   "terminal",
436   "red disk",                                   /* 230 */
437   "port (vertical)",
438   "port (horizontal)",
439   "port (all directions)",
440   "electron",
441   "buggy base",
442   "chip (left half)",
443   "chip (right half)",
444   "hardware",
445   "hardware",
446   "hardware",                                   /* 240 */
447   "hardware",
448   "hardware",
449   "hardware",
450   "hardware",
451   "hardware",
452   "hardware",
453   "hardware",
454   "chip (upper half)",
455   "chip (lower half)",
456   "unknown",                                    /* 250 */
457   "unknown",
458   "unknown",
459   "unknown",
460   "unknown",
461   "unknown",
462
463   /* 256 */
464
465   "pearl",                                      /* (256) */
466   "crystal",
467   "wall with pearl",
468   "wall with crystal",
469   "white door",                                 /* 260 */
470   "gray door (opened by white key)",
471   "white key",
472   "shield (passive)",
473   "extra time",
474   "switch gate (open)",
475   "switch gate (closed)",
476   "switch for switch gate",
477   "switch for switch gate",
478   "-",
479   "-",                                          /* 270 */
480   "red conveyor belt (left)",
481   "red conveyor belt (middle)",
482   "red conveyor belt (right)",
483   "switch for red conveyor belt (left)",
484   "switch for red conveyor belt (middle)",
485   "switch for red conveyor belt (right)",
486   "yellow conveyor belt (left)",
487   "yellow conveyor belt (middle)",
488   "yellow conveyor belt (right)",
489   "switch for yellow conveyor belt (left)",     /* 280 */
490   "switch for yellow conveyor belt (middle)",
491   "switch for yellow conveyor belt (right)",
492   "green conveyor belt (left)",
493   "green conveyor belt (middle)",
494   "green conveyor belt (right)",
495   "switch for green conveyor belt (left)",
496   "switch for green conveyor belt (middle)",
497   "switch for green conveyor belt (right)",
498   "blue conveyor belt (left)",
499   "blue conveyor belt (middle)",                /* 290 */
500   "blue conveyor belt (right)",
501   "switch for blue conveyor belt (left)",
502   "switch for blue conveyor belt (middle)",
503   "switch for blue conveyor belt (right)",
504   "land mine",
505   "mail envelope",
506   "light switch (off)",
507   "light switch (on)",
508   "sign (exclamation)",
509   "sign (radio activity)",                      /* 300 */
510   "sign (stop)",
511   "sign (wheel chair)",
512   "sign (parking)",
513   "sign (one way)",
514   "sign (heart)",
515   "sign (triangle)",
516   "sign (round)",
517   "sign (exit)",
518   "sign (yin yang)",
519   "sign (other)",                               /* 310 */
520   "mole (starts moving left)",
521   "mole (starts moving right)",
522   "mole (starts moving up)",
523   "mole (starts moving down)",
524   "steel wall (slanted)",
525   "invisible sand",
526   "dx unknown 15",
527   "dx unknown 42",
528   "-",
529   "-",                                          /* 320 */
530   "shield (active, kills enemies)",
531   "time gate (open)",
532   "time gate (closed)",
533   "switch for time gate",
534   "switch for time gate",
535   "balloon",
536   "send balloon to the left",
537   "send balloon to the right",
538   "send balloon up",
539   "send balloon down",                          /* 330 */
540   "send balloon in any direction",
541   "steel wall",
542   "steel wall",
543   "steel wall",
544   "steel wall",
545   "normal wall",
546   "normal wall",
547   "normal wall",
548   "normal wall",
549   "normal wall",                                /* 340 */
550   "normal wall",
551   "normal wall",
552   "normal wall",
553   "tube (all directions)",
554   "tube (vertical)",
555   "tube (horizontal)",
556   "tube (vertical & left)",
557   "tube (vertical & right)",
558   "tube (horizontal & up)",
559   "tube (horizontal & down)",                   /* 350 */
560   "tube (left & up)",
561   "tube (left & down)",
562   "tube (right & up)",
563   "tube (right & down)",
564   "spring",
565   "trap",
566   "stable bomb (DX style)",
567   "-"
568
569   /*
570   "-------------------------------",
571   */
572 };
573
574
575
576 /* +-----------------------------------------------------------------------+ */
577 /* | SDL TEST STUFF                                                        | */
578 /* +-----------------------------------------------------------------------+ */
579
580 #ifdef  USE_SDL_LIBRARY
581
582 SDL_Surface *sdl_screen, *sdl_image_tmp, *sdl_image, *sdl_image_masked;
583 SDL_Surface *sdl_image2_tmp, *sdl_image2, *sdl_image2_masked;
584
585 void TEST_SDL_BLIT_RECT(int x, int y)
586 {
587   SDL_Rect rect_src, rect_dst;
588
589   SDLCopyArea(sdl_pix_masked[PIX_HEROES], sdl_window,
590               8 * TILEX, 8 * TILEY, TILEX, TILEY, x, y);
591   return;
592
593   rect_src.x = 8 * TILEX;
594   rect_src.y = 8 * TILEY;
595   rect_src.w = TILEX;
596   rect_src.h = TILEY;
597
598   rect_dst.x = x;
599   rect_dst.y = y;
600   rect_dst.w = TILEX;
601   rect_dst.h = TILEY;
602
603   SDL_BlitSurface(sdl_image2_masked, &rect_src, sdl_screen, &rect_dst);
604   SDL_UpdateRect(sdl_screen, x, y, TILEX, TILEY);
605 }
606
607 void TEST_SDL_INIT_DISPLAY()
608 {
609   SDL_Rect rect_src, rect_dst;
610
611   if (SDL_Init(SDL_INIT_VIDEO) < 0)
612   {
613     fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
614     exit(1);
615   }
616
617   /* automatically cleanup SDL stuff after exit() */
618   atexit(SDL_Quit);
619
620   if ((sdl_screen = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, 16, SDL_HWSURFACE))
621       == NULL)
622   {
623     fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
624     exit(1);
625   }
626
627   SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
628
629   if ((sdl_image_tmp = IMG_Load("graphics/RocksScreen.pcx")) == NULL)
630   {
631     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
632     exit(1);
633   }
634
635   sdl_image = SDL_DisplayFormat(sdl_image_tmp);
636
637   SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
638                   SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
639   sdl_image_masked = SDL_DisplayFormat(sdl_image_tmp);
640
641   SDL_FreeSurface(sdl_image_tmp);
642
643   if ((sdl_image2_tmp = IMG_Load("graphics/RocksHeroes.pcx")) == NULL)
644   {
645     fprintf(stderr, "IMG_Load() failed: %s\n", SDL_GetError());
646     exit(1);
647   }
648
649   sdl_image2 = SDL_DisplayFormat(sdl_image2_tmp);
650   SDL_FreeSurface(sdl_image2_tmp);
651
652   sdl_image2_masked = SDL_DisplayFormat(sdl_image2);
653   SDL_SetColorKey(sdl_image2_masked, SDL_SRCCOLORKEY,
654                   SDL_MapRGB(sdl_image2_masked->format, 0x00, 0x00, 0x00));
655
656   rect_src.x = 0;
657   rect_src.y = 0;
658   rect_src.w = sdl_image->w;
659   rect_src.h = sdl_image->h;
660
661   rect_dst.x = 0;
662   rect_dst.y = 0;
663   rect_dst.w = sdl_image->w;
664   rect_dst.h = sdl_image->h;
665                                            
666   SDL_BlitSurface(sdl_image, &rect_src, sdl_screen, &rect_dst);
667
668   /*
669   SDL_UpdateRect(sdl_screen, 0, 0, WIN_XSIZE, WIN_YSIZE);
670   */
671   /*
672   SDL_UpdateRect(sdl_screen, 0, 0, 0, 0);
673   */
674   SDL_Flip(sdl_screen);
675
676   /*
677   SDL_Delay(5000);
678   */
679 }
680
681 void TEST_SDL_EVENT_LOOP()
682 {
683   SDL_Event event;
684   int quit_loop = 0;
685
686   SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
687
688   while (!quit_loop && SDL_WaitEvent(&event) >=0)
689   {
690     /* hier werden die Ereignisse behandelt */
691     switch(event.type)
692     {
693       case SDL_QUIT:
694       {
695         quit_loop = 1;
696         break;
697       }
698
699       case SDL_MOUSEBUTTONDOWN:
700       {
701         int x = event.button.x;
702         int y = event.button.y;
703
704         SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
705
706         TEST_SDL_BLIT_RECT(x, y);
707
708         printf("SDL_MOUSEBUTTONDOWN(%d, %d)\n", x, y);
709         break;
710       }
711
712       case SDL_MOUSEBUTTONUP:
713       {
714         int x = event.button.x;
715         int y = event.button.y;
716
717         SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
718
719         printf("SDL_MOUSEBUTTONUP(%d, %d)\n", x, y);
720         break;
721       }
722
723       case SDL_MOUSEMOTION:
724       {
725         int x = event.motion.x;
726         int y = event.motion.y;
727
728         TEST_SDL_BLIT_RECT(x, y);
729
730         printf("SDL_MOUSEMOTION(%d, %d)\n", x, y);
731         break;
732       }
733
734       default:
735         break;
736     }
737   }
738
739   SDL_FreeSurface(sdl_image);
740   SDL_Quit();
741 }
742
743 #endif  /* USE_SDL_LIBRARY */
744
745 /* +-----------------------------------------------------------------------+ */
746 /* | SDL TEST STUFF                                                        | */
747 /* +-----------------------------------------------------------------------+ */
748
749
750
751 int main(int argc, char *argv[])
752 {
753   program_name = (strrchr(argv[0],'/') ? strrchr(argv[0],'/') + 1 : argv[0]);
754
755 #ifdef MSDOS
756   _fmode = O_BINARY;
757 #endif
758
759   GetOptions(argv);
760   OpenAll(argc,argv);
761
762 #ifdef USE_SDL_LIBRARY
763   TEST_SDL_BLIT_RECT((WIN_XSIZE - TILEX)/2, (WIN_YSIZE - TILEY)/2);
764   TEST_SDL_EVENT_LOOP();
765   exit(0);
766 #endif
767
768   EventLoop();
769   CloseAllAndExit(0);
770   exit(0);      /* to keep compilers happy */
771 }