1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
29 #include "conf_e2g.c" /* include auto-generated data structure definitions */
30 #include "conf_esg.c" /* include auto-generated data structure definitions */
31 #include "conf_e2s.c" /* include auto-generated data structure definitions */
32 #include "conf_fnt.c" /* include auto-generated data structure definitions */
33 #include "conf_g2s.c" /* include auto-generated data structure definitions */
34 #include "conf_g2m.c" /* include auto-generated data structure definitions */
37 #define CONFIG_TOKEN_FONT_INITIAL "font.initial"
40 struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
43 static void InitTileClipmasks()
46 #if defined(TARGET_X11)
47 XGCValues clip_gc_values;
48 unsigned long clip_gc_valuemask;
50 #if defined(TARGET_X11_NATIVE)
60 tile_needs_clipping[] =
62 { GFX_SPIELER1_UP, 4 },
63 { GFX_SPIELER1_DOWN, 4 },
64 { GFX_SPIELER1_LEFT, 4 },
65 { GFX_SPIELER1_RIGHT, 4 },
66 { GFX_SPIELER1_PUSH_LEFT, 4 },
67 { GFX_SPIELER1_PUSH_RIGHT, 4 },
68 { GFX_SPIELER2_UP, 4 },
69 { GFX_SPIELER2_DOWN, 4 },
70 { GFX_SPIELER2_LEFT, 4 },
71 { GFX_SPIELER2_RIGHT, 4 },
72 { GFX_SPIELER2_PUSH_LEFT, 4 },
73 { GFX_SPIELER2_PUSH_RIGHT, 4 },
74 { GFX_SPIELER3_UP, 4 },
75 { GFX_SPIELER3_DOWN, 4 },
76 { GFX_SPIELER3_LEFT, 4 },
77 { GFX_SPIELER3_RIGHT, 4 },
78 { GFX_SPIELER3_PUSH_LEFT, 4 },
79 { GFX_SPIELER3_PUSH_RIGHT, 4 },
80 { GFX_SPIELER4_UP, 4 },
81 { GFX_SPIELER4_DOWN, 4 },
82 { GFX_SPIELER4_LEFT, 4 },
83 { GFX_SPIELER4_RIGHT, 4 },
84 { GFX_SPIELER4_PUSH_LEFT, 4 },
85 { GFX_SPIELER4_PUSH_RIGHT, 4 },
87 { GFX_MURPHY_GO_LEFT, 3 },
88 { GFX_MURPHY_GO_RIGHT, 3 },
89 { GFX_MURPHY_SNAP_UP, 1 },
90 { GFX_MURPHY_SNAP_DOWN, 1 },
91 { GFX_MURPHY_SNAP_RIGHT, 1 },
92 { GFX_MURPHY_SNAP_LEFT, 1 },
93 { GFX_MURPHY_PUSH_RIGHT, 1 },
94 { GFX_MURPHY_PUSH_LEFT, 1 },
99 { GFX_SOKOBAN_OBJEKT, 1 },
100 { GFX_FUNKELN_BLAU, 3 },
101 { GFX_FUNKELN_WEISS, 3 },
102 { GFX2_SHIELD_PASSIVE, 3 },
103 { GFX2_SHIELD_ACTIVE, 3 },
108 #endif /* TARGET_X11_NATIVE */
109 #endif /* TARGET_X11 */
113 /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
114 for (i = 0; i < NUM_TILES; i++)
115 tile_clipmask[i] = None;
117 #if defined(TARGET_X11)
118 /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
119 often very slow when preparing a masked XCopyArea() for big Pixmaps.
120 To prevent this, create small (tile-sized) mask Pixmaps which will then
121 be set much faster with XSetClipOrigin() and speed things up a lot. */
123 clip_gc_values.graphics_exposures = False;
124 clip_gc_valuemask = GCGraphicsExposures;
125 tile_clip_gc = XCreateGC(display, window->drawable,
126 clip_gc_valuemask, &clip_gc_values);
129 for (i = 0; i < NUM_BITMAPS; i++)
131 if (pix[i]->clip_mask)
133 clip_gc_values.graphics_exposures = False;
134 clip_gc_values.clip_mask = pix[i]->clip_mask;
135 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
136 pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
137 clip_gc_valuemask, &clip_gc_values);
142 #if defined(TARGET_X11_NATIVE)
145 /* create graphic context structures needed for clipping */
146 clip_gc_values.graphics_exposures = False;
147 clip_gc_valuemask = GCGraphicsExposures;
148 copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
149 clip_gc_valuemask, &clip_gc_values);
151 /* create only those clipping Pixmaps we really need */
152 for (i = 0; tile_needs_clipping[i].start >= 0; i++)
156 for (j = 0; j < tile_needs_clipping[i].count; j++)
158 int tile = tile_needs_clipping[i].start + j;
164 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
165 src_pixmap = src_bitmap->clip_mask;
167 tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
170 XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
171 src_x, src_y, TILEX, TILEY, 0, 0);
175 XFreeGC(display, copy_clipmask_gc);
178 #endif /* TARGET_X11_NATIVE */
179 #endif /* TARGET_X11 */
183 void FreeTileClipmasks()
186 #if defined(TARGET_X11)
189 for (i = 0; i < NUM_TILES; i++)
191 if (tile_clipmask[i] != None)
193 XFreePixmap(display, tile_clipmask[i]);
194 tile_clipmask[i] = None;
199 XFreeGC(display, tile_clip_gc);
203 for (i = 0; i < NUM_BITMAPS; i++)
205 if (pix[i] != NULL && pix[i]->stored_clip_gc)
207 XFreeGC(display, pix[i]->stored_clip_gc);
208 pix[i]->stored_clip_gc = None;
213 #endif /* TARGET_X11 */
219 FreeLevelEditorGadgets();
228 static boolean gadgets_initialized = FALSE;
230 if (gadgets_initialized)
233 CreateLevelEditorGadgets();
237 CreateScreenGadgets();
239 gadgets_initialized = TRUE;
242 void InitElementSmallImages()
244 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
245 int num_property_mappings = getImageListPropertyMappingSize();
248 /* initialize normal images from static configuration */
249 for (i = 0; element_to_graphic[i].element > -1; i++)
250 CreateImageWithSmallImages(element_to_graphic[i].graphic);
252 /* initialize special images from static configuration */
253 for (i = 0; element_to_special_graphic[i].element > -1; i++)
254 CreateImageWithSmallImages(element_to_special_graphic[i].graphic);
256 /* initialize images from dynamic configuration */
257 for (i = 0; i < num_property_mappings; i++)
258 if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
259 CreateImageWithSmallImages(property_mapping[i].artwork_index);
262 static int getFontBitmapID(int font_nr)
266 if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
267 special = game_status;
268 else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
269 special = GFX_SPECIAL_ARG_MAIN;
270 else if (game_status == GAME_MODE_PLAYING)
271 special = GFX_SPECIAL_ARG_DOOR;
274 return font_info[font_nr].special_bitmap_id[special];
279 void InitFontGraphicInfo()
281 static struct FontBitmapInfo *font_bitmap_info = NULL;
282 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
283 int num_property_mappings = getImageListPropertyMappingSize();
284 int num_font_bitmaps = NUM_FONTS;
287 if (graphic_info == NULL) /* still at startup phase */
289 InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
294 /* ---------- initialize font graphic definitions ---------- */
296 /* always start with reliable default values (normal font graphics) */
298 for (i = 0; i < NUM_FONTS; i++)
299 font_info[i].graphic = IMG_FONT_INITIAL_1;
301 for (i = 0; i < NUM_FONTS; i++)
302 font_info[i].graphic = FONT_INITIAL_1;
305 /* initialize normal font/graphic mapping from static configuration */
306 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
308 int font_nr = font_to_graphic[i].font_nr;
309 int special = font_to_graphic[i].special;
310 int graphic = font_to_graphic[i].graphic;
315 font_info[font_nr].graphic = graphic;
318 /* always start with reliable default values (special font graphics) */
319 for (i = 0; i < NUM_FONTS; i++)
321 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
323 font_info[i].special_graphic[j] = font_info[i].graphic;
324 font_info[i].special_bitmap_id[j] = i;
328 /* initialize special font/graphic mapping from static configuration */
329 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
331 int font_nr = font_to_graphic[i].font_nr;
332 int special = font_to_graphic[i].special;
333 int graphic = font_to_graphic[i].graphic;
335 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
337 font_info[font_nr].special_graphic[special] = graphic;
338 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
343 /* initialize special element/graphic mapping from dynamic configuration */
344 for (i = 0; i < num_property_mappings; i++)
346 int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
347 int special = property_mapping[i].ext3_index;
348 int graphic = property_mapping[i].artwork_index;
353 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
355 font_info[font_nr].special_graphic[special] = graphic;
356 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
361 /* ---------- initialize font bitmap array ---------- */
363 if (font_bitmap_info != NULL)
364 FreeFontInfo(font_bitmap_info);
367 checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
369 /* ---------- initialize font bitmap definitions ---------- */
371 for (i = 0; i < NUM_FONTS; i++)
373 if (i < NUM_INITIAL_FONTS)
375 font_bitmap_info[i] = font_initial[i];
379 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
381 int font_bitmap_id = font_info[i].special_bitmap_id[j];
382 int graphic = font_info[i].special_graphic[j];
384 /* set 'graphic_info' for font entries, if uninitialized (guessed) */
385 if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
387 graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
388 graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
391 /* copy font relevant information from graphics information */
392 font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
393 font_bitmap_info[font_bitmap_id].src_x = graphic_info[graphic].src_x;
394 font_bitmap_info[font_bitmap_id].src_y = graphic_info[graphic].src_y;
395 font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
396 font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
397 font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
398 font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
400 font_bitmap_info[font_bitmap_id].num_chars =
401 graphic_info[graphic].anim_frames;
402 font_bitmap_info[font_bitmap_id].num_chars_per_line =
403 graphic_info[graphic].anim_frames_per_line;
407 InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
410 void InitElementGraphicInfo()
412 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
413 int num_property_mappings = getImageListPropertyMappingSize();
416 if (graphic_info == NULL) /* still at startup phase */
419 /* set values to -1 to identify later as "uninitialized" values */
420 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
422 for (act = 0; act < NUM_ACTIONS; act++)
424 element_info[i].graphic[act] = -1;
425 element_info[i].crumbled[act] = -1;
427 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
429 element_info[i].direction_graphic[act][dir] = -1;
430 element_info[i].direction_crumbled[act][dir] = -1;
435 /* initialize normal element/graphic mapping from static configuration */
436 for (i = 0; element_to_graphic[i].element > -1; i++)
438 int element = element_to_graphic[i].element;
439 int action = element_to_graphic[i].action;
440 int direction = element_to_graphic[i].direction;
441 boolean crumbled = element_to_graphic[i].crumbled;
442 int graphic = element_to_graphic[i].graphic;
444 if (graphic_info[graphic].bitmap == NULL)
447 if ((action > -1 || direction > -1 || crumbled == TRUE) &&
448 el2img(element) != -1)
450 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
451 boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
453 /* if the base graphic ("emerald", for example) has been redefined,
454 but not the action graphic ("emerald.falling", for example), do not
455 use an existing (in this case considered obsolete) action graphic
456 anymore, but use the automatically determined default graphic */
457 if (base_redefined && !act_dir_redefined)
462 action = ACTION_DEFAULT;
467 element_info[element].direction_crumbled[action][direction] = graphic;
469 element_info[element].crumbled[action] = graphic;
474 element_info[element].direction_graphic[action][direction] = graphic;
476 element_info[element].graphic[action] = graphic;
480 /* initialize normal element/graphic mapping from dynamic configuration */
481 for (i = 0; i < num_property_mappings; i++)
483 int element = property_mapping[i].base_index;
484 int action = property_mapping[i].ext1_index;
485 int direction = property_mapping[i].ext2_index;
486 int special = property_mapping[i].ext3_index;
487 int graphic = property_mapping[i].artwork_index;
488 boolean crumbled = FALSE;
490 if (special == GFX_SPECIAL_ARG_CRUMBLED)
496 if (graphic_info[graphic].bitmap == NULL)
499 if (element >= MAX_NUM_ELEMENTS || special != -1)
503 action = ACTION_DEFAULT;
508 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
509 element_info[element].direction_crumbled[action][dir] = -1;
512 element_info[element].direction_crumbled[action][direction] = graphic;
514 element_info[element].crumbled[action] = graphic;
519 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
520 element_info[element].direction_graphic[action][dir] = -1;
523 element_info[element].direction_graphic[action][direction] = graphic;
525 element_info[element].graphic[action] = graphic;
529 /* now copy all graphics that are defined to be cloned from other graphics */
530 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
532 int graphic = element_info[i].graphic[ACTION_DEFAULT];
533 int crumbled_like, diggable_like;
538 crumbled_like = graphic_info[graphic].crumbled_like;
539 diggable_like = graphic_info[graphic].diggable_like;
541 if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
543 for (act = 0; act < NUM_ACTIONS; act++)
544 element_info[i].crumbled[act] =
545 element_info[crumbled_like].crumbled[act];
546 for (act = 0; act < NUM_ACTIONS; act++)
547 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
548 element_info[i].direction_crumbled[act][dir] =
549 element_info[crumbled_like].direction_crumbled[act][dir];
552 if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
554 element_info[i].graphic[ACTION_DIGGING] =
555 element_info[diggable_like].graphic[ACTION_DIGGING];
556 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
557 element_info[i].direction_graphic[ACTION_DIGGING][dir] =
558 element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
563 /* now set all undefined/invalid graphics to -1 to set to default after it */
564 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
566 for (act = 0; act < NUM_ACTIONS; act++)
570 graphic = element_info[i].graphic[act];
571 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
572 element_info[i].graphic[act] = -1;
574 graphic = element_info[i].crumbled[act];
575 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
576 element_info[i].crumbled[act] = -1;
578 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
580 graphic = element_info[i].direction_graphic[act][dir];
581 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
582 element_info[i].direction_graphic[act][dir] = -1;
584 graphic = element_info[i].direction_crumbled[act][dir];
585 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
586 element_info[i].direction_crumbled[act][dir] = -1;
592 /* now set all '-1' values to element specific default values */
593 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
595 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
596 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
597 int default_direction_graphic[NUM_DIRECTIONS];
598 int default_direction_crumbled[NUM_DIRECTIONS];
600 if (default_graphic == -1)
601 default_graphic = IMG_UNKNOWN;
602 if (default_crumbled == -1)
603 default_crumbled = IMG_EMPTY;
605 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
607 default_direction_graphic[dir] =
608 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
609 default_direction_crumbled[dir] =
610 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
612 if (default_direction_graphic[dir] == -1)
613 default_direction_graphic[dir] = default_graphic;
614 if (default_direction_crumbled[dir] == -1)
615 default_direction_crumbled[dir] = default_crumbled;
618 for (act = 0; act < NUM_ACTIONS; act++)
620 boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
621 (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
622 (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
623 boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
624 act == ACTION_TURNING_FROM_RIGHT ||
625 act == ACTION_TURNING_FROM_UP ||
626 act == ACTION_TURNING_FROM_DOWN);
628 /* generic default action graphic (defined by "[default]" directive) */
629 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
630 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
632 /* look for special default action graphic (classic game specific) */
633 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
634 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
635 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
636 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
637 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
638 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
640 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
641 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
642 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
643 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
644 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
645 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
648 /* !!! make this better !!! */
649 if (i == EL_EMPTY_SPACE)
651 default_action_graphic = element_info[EL_DEFAULT].graphic[act];
652 default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
656 if (default_action_graphic == -1)
657 default_action_graphic = default_graphic;
658 if (default_action_crumbled == -1)
659 default_action_crumbled = default_crumbled;
661 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
663 int default_action_direction_graphic = element_info[i].graphic[act];
664 int default_action_direction_crumbled = element_info[i].crumbled[act];
666 /* no graphic for current action -- use default direction graphic */
667 if (default_action_direction_graphic == -1)
668 default_action_direction_graphic =
669 (act_remove ? IMG_EMPTY :
671 element_info[i].direction_graphic[ACTION_TURNING][dir] :
672 default_direction_graphic[dir]);
673 if (default_action_direction_crumbled == -1)
674 default_action_direction_crumbled =
675 (act_remove ? IMG_EMPTY :
677 element_info[i].direction_crumbled[ACTION_TURNING][dir] :
678 default_direction_crumbled[dir]);
680 if (element_info[i].direction_graphic[act][dir] == -1)
681 element_info[i].direction_graphic[act][dir] =
682 default_action_direction_graphic;
683 if (element_info[i].direction_crumbled[act][dir] == -1)
684 element_info[i].direction_crumbled[act][dir] =
685 default_action_direction_crumbled;
688 /* no graphic for this specific action -- use default action graphic */
689 if (element_info[i].graphic[act] == -1)
690 element_info[i].graphic[act] =
691 (act_remove ? IMG_EMPTY :
692 act_turning ? element_info[i].graphic[ACTION_TURNING] :
693 default_action_graphic);
694 if (element_info[i].crumbled[act] == -1)
695 element_info[i].crumbled[act] =
696 (act_remove ? IMG_EMPTY :
697 act_turning ? element_info[i].crumbled[ACTION_TURNING] :
698 default_action_crumbled);
703 /* set animation mode to "none" for each graphic with only 1 frame */
704 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
706 for (act = 0; act < NUM_ACTIONS; act++)
708 int graphic = element_info[i].graphic[act];
709 int crumbled = element_info[i].crumbled[act];
711 if (graphic_info[graphic].anim_frames == 1)
712 graphic_info[graphic].anim_mode = ANIM_NONE;
713 if (graphic_info[crumbled].anim_frames == 1)
714 graphic_info[crumbled].anim_mode = ANIM_NONE;
716 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
718 graphic = element_info[i].direction_graphic[act][dir];
719 crumbled = element_info[i].direction_crumbled[act][dir];
721 if (graphic_info[graphic].anim_frames == 1)
722 graphic_info[graphic].anim_mode = ANIM_NONE;
723 if (graphic_info[crumbled].anim_frames == 1)
724 graphic_info[crumbled].anim_mode = ANIM_NONE;
734 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
735 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
737 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
738 element_info[i].token_name, i);
744 void InitElementSpecialGraphicInfo()
746 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
747 int num_property_mappings = getImageListPropertyMappingSize();
750 /* always start with reliable default values */
751 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
752 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
753 element_info[i].special_graphic[j] =
754 element_info[i].graphic[ACTION_DEFAULT];
756 /* initialize special element/graphic mapping from static configuration */
757 for (i = 0; element_to_special_graphic[i].element > -1; i++)
759 int element = element_to_special_graphic[i].element;
760 int special = element_to_special_graphic[i].special;
761 int graphic = element_to_special_graphic[i].graphic;
762 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
763 boolean special_redefined = getImageListEntry(graphic)->redefined;
765 /* if the base graphic ("emerald", for example) has been redefined,
766 but not the special graphic ("emerald.EDITOR", for example), do not
767 use an existing (in this case considered obsolete) special graphic
768 anymore, but use the automatically created (down-scaled) graphic */
769 if (base_redefined && !special_redefined)
772 element_info[element].special_graphic[special] = graphic;
775 /* initialize special element/graphic mapping from dynamic configuration */
776 for (i = 0; i < num_property_mappings; i++)
778 int element = property_mapping[i].base_index;
779 int special = property_mapping[i].ext3_index;
780 int graphic = property_mapping[i].artwork_index;
782 if (element >= MAX_NUM_ELEMENTS)
785 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
786 element_info[element].special_graphic[special] = graphic;
790 /* now set all undefined/invalid graphics to default */
791 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
792 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
793 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
794 element_info[i].special_graphic[j] =
795 element_info[i].graphic[ACTION_DEFAULT];
799 static int get_element_from_token(char *token)
803 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
804 if (strcmp(element_info[i].token_name, token) == 0)
810 static void set_graphic_parameters(int graphic, char **parameter_raw)
812 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
813 int parameter[NUM_GFX_ARGS];
814 int anim_frames_per_row = 1, anim_frames_per_col = 1;
815 int anim_frames_per_line = 1;
818 /* get integer values from string parameters */
819 for (i = 0; i < NUM_GFX_ARGS; i++)
822 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
823 image_config_suffix[i].type);
825 if (image_config_suffix[i].type == TYPE_TOKEN)
826 parameter[i] = get_element_from_token(parameter_raw[i]);
829 graphic_info[graphic].bitmap = src_bitmap;
831 /* start with reliable default values */
832 graphic_info[graphic].src_x = 0;
833 graphic_info[graphic].src_y = 0;
834 graphic_info[graphic].width = TILEX;
835 graphic_info[graphic].height = TILEY;
836 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
837 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
838 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
839 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
840 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
841 graphic_info[graphic].anim_delay_fixed = 0;
842 graphic_info[graphic].anim_delay_random = 0;
843 graphic_info[graphic].post_delay_fixed = 0;
844 graphic_info[graphic].post_delay_random = 0;
846 /* optional x and y tile position of animation frame sequence */
847 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
848 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
849 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
850 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
852 /* optional x and y pixel position of animation frame sequence */
853 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
854 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
855 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
856 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
858 /* optional width and height of each animation frame */
859 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
860 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
861 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
862 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
866 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
867 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
870 /* correct x or y offset dependent of vertical or horizontal frame order */
871 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
873 graphic_info[graphic].offset_y =
874 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
875 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
876 anim_frames_per_line = anim_frames_per_col;
878 else /* frames are ordered horizontally */
880 graphic_info[graphic].offset_x =
881 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
882 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
883 anim_frames_per_line = anim_frames_per_row;
886 /* optionally, the x and y offset of frames can be specified directly */
887 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
888 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
889 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
890 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
892 /* automatically determine correct number of frames, if not defined */
893 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
894 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
895 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
896 graphic_info[graphic].anim_frames = anim_frames_per_row;
897 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
898 graphic_info[graphic].anim_frames = anim_frames_per_col;
900 graphic_info[graphic].anim_frames = 1;
902 graphic_info[graphic].anim_frames_per_line =
903 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
904 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
906 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
907 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
908 graphic_info[graphic].anim_delay = 1;
910 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
912 if (graphic_info[graphic].anim_frames == 1)
913 graphic_info[graphic].anim_mode = ANIM_NONE;
916 /* automatically determine correct start frame, if not defined */
917 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
918 graphic_info[graphic].anim_start_frame = 0;
919 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
920 graphic_info[graphic].anim_start_frame =
921 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
923 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
925 /* animation synchronized with global frame counter, not move position */
926 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
928 /* optional element for cloning crumble graphics */
929 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
930 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
932 /* optional element for cloning digging graphics */
933 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
934 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
936 /* optional border size for "crumbling" diggable graphics */
937 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
938 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
940 /* this is only used for player "boring" and "sleeping" actions */
941 if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
942 graphic_info[graphic].anim_delay_fixed =
943 parameter[GFX_ARG_ANIM_DELAY_FIXED];
944 if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
945 graphic_info[graphic].anim_delay_random =
946 parameter[GFX_ARG_ANIM_DELAY_RANDOM];
947 if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
948 graphic_info[graphic].post_delay_fixed =
949 parameter[GFX_ARG_POST_DELAY_FIXED];
950 if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
951 graphic_info[graphic].post_delay_random =
952 parameter[GFX_ARG_POST_DELAY_RANDOM];
954 /* this is only used for toon animations */
955 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
956 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
958 /* this is only used for drawing font characters */
959 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
960 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
962 /* this is only used for drawing envelope graphics */
963 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
966 static void InitGraphicInfo()
968 int fallback_graphic = IMG_CHAR_EXCLAM;
969 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
970 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
971 int num_images = getImageListSize();
974 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
975 static boolean clipmasks_initialized = FALSE;
977 XGCValues clip_gc_values;
978 unsigned long clip_gc_valuemask;
979 GC copy_clipmask_gc = None;
982 checked_free(graphic_info);
984 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
987 printf("::: graphic_info: %d entries\n", num_images);
990 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
991 if (clipmasks_initialized)
993 for (i = 0; i < num_images; i++)
995 if (graphic_info[i].clip_mask)
996 XFreePixmap(display, graphic_info[i].clip_mask);
997 if (graphic_info[i].clip_gc)
998 XFreeGC(display, graphic_info[i].clip_gc);
1000 graphic_info[i].clip_mask = None;
1001 graphic_info[i].clip_gc = None;
1006 for (i = 0; i < num_images; i++)
1008 struct FileInfo *image = getImageListEntry(i);
1011 int first_frame, last_frame;
1014 printf("::: image: '%s' [%d]\n", image->token, i);
1018 printf("::: image # %d: '%s' ['%s']\n",
1020 getTokenFromImageID(i));
1023 set_graphic_parameters(i, image->parameter);
1025 /* now check if no animation frames are outside of the loaded image */
1027 if (graphic_info[i].bitmap == NULL)
1028 continue; /* skip check for optional images that are undefined */
1031 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1032 if (src_x < 0 || src_y < 0 ||
1033 src_x + TILEX > src_bitmap->width ||
1034 src_y + TILEY > src_bitmap->height)
1036 Error(ERR_RETURN_LINE, "-");
1037 Error(ERR_RETURN, "warning: error found in config file:");
1038 Error(ERR_RETURN, "- config file: '%s'",
1039 getImageConfigFilename());
1040 Error(ERR_RETURN, "- config token: '%s'",
1041 getTokenFromImageID(i));
1042 Error(ERR_RETURN, "- image file: '%s'",
1043 src_bitmap->source_filename);
1045 "error: first animation frame out of bounds (%d, %d)",
1047 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1049 if (i == fallback_graphic)
1050 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1052 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1053 Error(ERR_RETURN_LINE, "-");
1055 set_graphic_parameters(i, fallback_image->default_parameter);
1056 graphic_info[i].bitmap = fallback_bitmap;
1059 last_frame = graphic_info[i].anim_frames - 1;
1060 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1061 if (src_x < 0 || src_y < 0 ||
1062 src_x + TILEX > src_bitmap->width ||
1063 src_y + TILEY > src_bitmap->height)
1065 Error(ERR_RETURN_LINE, "-");
1066 Error(ERR_RETURN, "warning: error found in config file:");
1067 Error(ERR_RETURN, "- config file: '%s'",
1068 getImageConfigFilename());
1069 Error(ERR_RETURN, "- config token: '%s'",
1070 getTokenFromImageID(i));
1071 Error(ERR_RETURN, "- image file: '%s'",
1072 src_bitmap->source_filename);
1074 "error: last animation frame (%d) out of bounds (%d, %d)",
1075 last_frame, src_x, src_y);
1076 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1078 if (i == fallback_graphic)
1079 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1081 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1082 Error(ERR_RETURN_LINE, "-");
1084 set_graphic_parameters(i, fallback_image->default_parameter);
1085 graphic_info[i].bitmap = fallback_bitmap;
1088 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1089 /* currently we need only a tile clip mask from the first frame */
1090 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1092 if (copy_clipmask_gc == None)
1094 clip_gc_values.graphics_exposures = False;
1095 clip_gc_valuemask = GCGraphicsExposures;
1096 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1097 clip_gc_valuemask, &clip_gc_values);
1100 graphic_info[i].clip_mask =
1101 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1103 src_pixmap = src_bitmap->clip_mask;
1104 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1105 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1107 clip_gc_values.graphics_exposures = False;
1108 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1109 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1111 graphic_info[i].clip_gc =
1112 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1116 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1117 if (copy_clipmask_gc)
1118 XFreeGC(display, copy_clipmask_gc);
1120 clipmasks_initialized = TRUE;
1124 static void InitElementSoundInfo()
1126 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1127 int num_property_mappings = getSoundListPropertyMappingSize();
1130 /* set values to -1 to identify later as "uninitialized" values */
1131 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1132 for (act = 0; act < NUM_ACTIONS; act++)
1133 element_info[i].sound[act] = -1;
1135 /* initialize element/sound mapping from static configuration */
1136 for (i = 0; element_to_sound[i].element > -1; i++)
1138 int element = element_to_sound[i].element;
1139 int action = element_to_sound[i].action;
1140 int sound = element_to_sound[i].sound;
1141 boolean is_class = element_to_sound[i].is_class;
1144 action = ACTION_DEFAULT;
1147 element_info[element].sound[action] = sound;
1149 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1150 if (strcmp(element_info[j].class_name,
1151 element_info[element].class_name) == 0)
1152 element_info[j].sound[action] = sound;
1155 /* initialize element class/sound mapping from dynamic configuration */
1156 for (i = 0; i < num_property_mappings; i++)
1158 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1159 int action = property_mapping[i].ext1_index;
1160 int sound = property_mapping[i].artwork_index;
1162 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1166 action = ACTION_DEFAULT;
1168 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1169 if (strcmp(element_info[j].class_name,
1170 element_info[element_class].class_name) == 0)
1171 element_info[j].sound[action] = sound;
1174 /* initialize element/sound mapping from dynamic configuration */
1175 for (i = 0; i < num_property_mappings; i++)
1177 int element = property_mapping[i].base_index;
1178 int action = property_mapping[i].ext1_index;
1179 int sound = property_mapping[i].artwork_index;
1181 if (element >= MAX_NUM_ELEMENTS)
1185 action = ACTION_DEFAULT;
1187 element_info[element].sound[action] = sound;
1190 /* now set all '-1' values to element specific default values */
1191 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1193 for (act = 0; act < NUM_ACTIONS; act++)
1195 /* generic default action sound (defined by "[default]" directive) */
1196 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1198 /* look for special default action sound (classic game specific) */
1199 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1200 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1201 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1202 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1203 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1204 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1206 /* !!! there's no such thing as a "default action sound" !!! */
1208 /* look for element specific default sound (independent from action) */
1209 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1210 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1213 /* no sound for this specific action -- use default action sound */
1214 if (element_info[i].sound[act] == -1)
1215 element_info[i].sound[act] = default_action_sound;
1220 static void InitGameModeSoundInfo()
1224 /* set values to -1 to identify later as "uninitialized" values */
1225 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1228 /* initialize gamemode/sound mapping from static configuration */
1229 for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1231 int gamemode = gamemode_to_sound[i].gamemode;
1232 int sound = gamemode_to_sound[i].sound;
1235 gamemode = GAME_MODE_DEFAULT;
1237 menu.sound[gamemode] = sound;
1240 /* now set all '-1' values to levelset specific default values */
1241 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1242 if (menu.sound[i] == -1)
1243 menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1247 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1248 if (menu.sound[i] != -1)
1249 printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1253 static void set_sound_parameters(int sound, char **parameter_raw)
1255 int parameter[NUM_SND_ARGS];
1258 /* get integer values from string parameters */
1259 for (i = 0; i < NUM_SND_ARGS; i++)
1261 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1262 sound_config_suffix[i].type);
1264 /* explicit loop mode setting in configuration overrides default value */
1265 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1266 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1269 static void InitSoundInfo()
1272 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1273 int num_property_mappings = getSoundListPropertyMappingSize();
1275 int *sound_effect_properties;
1276 int num_sounds = getSoundListSize();
1279 checked_free(sound_info);
1281 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1282 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1284 /* initialize sound effect for all elements to "no sound" */
1285 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1286 for (j = 0; j < NUM_ACTIONS; j++)
1287 element_info[i].sound[j] = SND_UNDEFINED;
1289 for (i = 0; i < num_sounds; i++)
1291 struct FileInfo *sound = getSoundListEntry(i);
1292 int len_effect_text = strlen(sound->token);
1294 sound_effect_properties[i] = ACTION_OTHER;
1295 sound_info[i].loop = FALSE; /* default: play sound only once */
1298 printf("::: sound %d: '%s'\n", i, sound->token);
1301 /* determine all loop sounds and identify certain sound classes */
1303 for (j = 0; element_action_info[j].suffix; j++)
1305 int len_action_text = strlen(element_action_info[j].suffix);
1307 if (len_action_text < len_effect_text &&
1308 strcmp(&sound->token[len_effect_text - len_action_text],
1309 element_action_info[j].suffix) == 0)
1311 sound_effect_properties[i] = element_action_info[j].value;
1312 sound_info[i].loop = element_action_info[j].is_loop_sound;
1319 if (strcmp(sound->token, "custom_42") == 0)
1320 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1323 /* associate elements and some selected sound actions */
1325 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1327 if (element_info[j].class_name)
1329 int len_class_text = strlen(element_info[j].class_name);
1331 if (len_class_text + 1 < len_effect_text &&
1332 strncmp(sound->token,
1333 element_info[j].class_name, len_class_text) == 0 &&
1334 sound->token[len_class_text] == '.')
1336 int sound_action_value = sound_effect_properties[i];
1338 element_info[j].sound[sound_action_value] = i;
1343 set_sound_parameters(i, sound->parameter);
1346 free(sound_effect_properties);
1349 /* !!! now handled in InitElementSoundInfo() !!! */
1350 /* initialize element/sound mapping from dynamic configuration */
1351 for (i = 0; i < num_property_mappings; i++)
1353 int element = property_mapping[i].base_index;
1354 int action = property_mapping[i].ext1_index;
1355 int sound = property_mapping[i].artwork_index;
1358 action = ACTION_DEFAULT;
1360 printf("::: %d: %d, %d, %d ['%s']\n",
1361 i, element, action, sound, element_info[element].token_name);
1363 element_info[element].sound[action] = sound;
1370 int element = EL_CUSTOM_11;
1373 while (element_action_info[j].suffix)
1375 printf("element %d, sound action '%s' == %d\n",
1376 element, element_action_info[j].suffix,
1377 element_info[element].sound[j]);
1382 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1388 int element = EL_SAND;
1389 int sound_action = ACTION_DIGGING;
1392 while (element_action_info[j].suffix)
1394 if (element_action_info[j].value == sound_action)
1395 printf("element %d, sound action '%s' == %d\n",
1396 element, element_action_info[j].suffix,
1397 element_info[element].sound[sound_action]);
1404 static void InitGameModeMusicInfo()
1406 struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1407 int num_property_mappings = getMusicListPropertyMappingSize();
1408 int default_levelset_music = -1;
1411 /* set values to -1 to identify later as "uninitialized" values */
1412 for (i = 0; i < MAX_LEVELS; i++)
1413 levelset.music[i] = -1;
1414 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1417 /* initialize gamemode/music mapping from static configuration */
1418 for (i = 0; gamemode_to_music[i].music > -1; i++)
1420 int gamemode = gamemode_to_music[i].gamemode;
1421 int music = gamemode_to_music[i].music;
1424 printf("::: gamemode == %d, music == %d\n", gamemode, music);
1428 gamemode = GAME_MODE_DEFAULT;
1430 menu.music[gamemode] = music;
1433 /* initialize gamemode/music mapping from dynamic configuration */
1434 for (i = 0; i < num_property_mappings; i++)
1436 int prefix = property_mapping[i].base_index;
1437 int gamemode = property_mapping[i].ext1_index;
1438 int level = property_mapping[i].ext2_index;
1439 int music = property_mapping[i].artwork_index;
1442 printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1443 prefix, gamemode, level, music);
1446 if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1450 gamemode = GAME_MODE_DEFAULT;
1452 /* level specific music only allowed for in-game music */
1453 if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1454 gamemode = GAME_MODE_PLAYING;
1459 default_levelset_music = music;
1462 if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1463 levelset.music[level] = music;
1464 if (gamemode != GAME_MODE_PLAYING)
1465 menu.music[gamemode] = music;
1468 /* now set all '-1' values to menu specific default values */
1469 /* (undefined values of "levelset.music[]" might stay at "-1" to
1470 allow dynamic selection of music files from music directory!) */
1471 for (i = 0; i < MAX_LEVELS; i++)
1472 if (levelset.music[i] == -1)
1473 levelset.music[i] = default_levelset_music;
1474 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1475 if (menu.music[i] == -1)
1476 menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1480 for (i = 0; i < MAX_LEVELS; i++)
1481 if (levelset.music[i] != -1)
1482 printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1483 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1484 if (menu.music[i] != -1)
1485 printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1489 static void set_music_parameters(int music, char **parameter_raw)
1491 int parameter[NUM_MUS_ARGS];
1494 /* get integer values from string parameters */
1495 for (i = 0; i < NUM_MUS_ARGS; i++)
1497 get_parameter_value(music_config_suffix[i].token, parameter_raw[i],
1498 music_config_suffix[i].type);
1500 /* explicit loop mode setting in configuration overrides default value */
1501 if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1502 music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
1505 static void InitMusicInfo()
1507 int num_music = getMusicListSize();
1510 checked_free(music_info);
1512 music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
1514 for (i = 0; i < num_music; i++)
1516 struct FileInfo *music = getMusicListEntry(i);
1517 int len_music_text = strlen(music->token);
1519 music_info[i].loop = TRUE; /* default: play music in loop mode */
1521 /* determine all loop music */
1523 for (j = 0; music_prefix_info[j].prefix; j++)
1525 int len_prefix_text = strlen(music_prefix_info[j].prefix);
1527 if (len_prefix_text < len_music_text &&
1528 strncmp(music->token,
1529 music_prefix_info[j].prefix, len_prefix_text) == 0)
1531 music_info[i].loop = music_prefix_info[j].is_loop_music;
1537 set_music_parameters(i, music->parameter);
1541 static void ReinitializeGraphics()
1543 InitGraphicInfo(); /* graphic properties mapping */
1544 InitElementGraphicInfo(); /* element game graphic mapping */
1545 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1547 InitElementSmallImages(); /* create editor and preview images */
1548 InitFontGraphicInfo(); /* initialize text drawing functions */
1550 SetMainBackgroundImage(IMG_BACKGROUND);
1551 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1557 static void ReinitializeSounds()
1559 InitSoundInfo(); /* sound properties mapping */
1560 InitElementSoundInfo(); /* element game sound mapping */
1561 InitGameModeSoundInfo(); /* game mode sound mapping */
1563 InitPlayLevelSound(); /* internal game sound settings */
1566 static void ReinitializeMusic()
1568 InitMusicInfo(); /* music properties mapping */
1569 InitGameModeMusicInfo(); /* game mode music mapping */
1572 static int get_special_property_bit(int element, int property_bit_nr)
1574 struct PropertyBitInfo
1580 static struct PropertyBitInfo pb_can_move_into_acid[] =
1582 /* the player may be able fall into acid when gravity is activated */
1587 { EL_SP_MURPHY, 0 },
1588 { EL_SOKOBAN_FIELD_PLAYER, 0 },
1590 /* all element that can move may be able to also move into acid */
1593 { EL_BUG_RIGHT, 1 },
1596 { EL_SPACESHIP, 2 },
1597 { EL_SPACESHIP_LEFT, 2 },
1598 { EL_SPACESHIP_RIGHT, 2 },
1599 { EL_SPACESHIP_UP, 2 },
1600 { EL_SPACESHIP_DOWN, 2 },
1601 { EL_BD_BUTTERFLY, 3 },
1602 { EL_BD_BUTTERFLY_LEFT, 3 },
1603 { EL_BD_BUTTERFLY_RIGHT, 3 },
1604 { EL_BD_BUTTERFLY_UP, 3 },
1605 { EL_BD_BUTTERFLY_DOWN, 3 },
1606 { EL_BD_FIREFLY, 4 },
1607 { EL_BD_FIREFLY_LEFT, 4 },
1608 { EL_BD_FIREFLY_RIGHT, 4 },
1609 { EL_BD_FIREFLY_UP, 4 },
1610 { EL_BD_FIREFLY_DOWN, 4 },
1612 { EL_DARK_YAMYAM, 6 },
1615 { EL_PACMAN_LEFT, 8 },
1616 { EL_PACMAN_RIGHT, 8 },
1617 { EL_PACMAN_UP, 8 },
1618 { EL_PACMAN_DOWN, 8 },
1620 { EL_MOLE_LEFT, 9 },
1621 { EL_MOLE_RIGHT, 9 },
1623 { EL_MOLE_DOWN, 9 },
1627 { EL_SATELLITE, 13 },
1628 { EL_SP_SNIKSNAK, 14 },
1629 { EL_SP_ELECTRON, 15 },
1636 static struct PropertyBitInfo pb_dont_collide_with[] =
1638 { EL_SP_SNIKSNAK, 0 },
1639 { EL_SP_ELECTRON, 1 },
1647 struct PropertyBitInfo *pb_info;
1650 { EP_CAN_MOVE_INTO_ACID, pb_can_move_into_acid },
1651 { EP_DONT_COLLIDE_WITH, pb_dont_collide_with },
1656 struct PropertyBitInfo *pb_info = NULL;
1659 for (i = 0; pb_definition[i].bit_nr != -1; i++)
1660 if (pb_definition[i].bit_nr == property_bit_nr)
1661 pb_info = pb_definition[i].pb_info;
1663 if (pb_info == NULL)
1666 for (i = 0; pb_info[i].element != -1; i++)
1667 if (pb_info[i].element == element)
1668 return pb_info[i].bit_nr;
1674 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
1675 boolean property_value)
1677 int bit_nr = get_special_property_bit(element, property_bit_nr);
1682 *bitfield |= (1 << bit_nr);
1684 *bitfield &= ~(1 << bit_nr);
1688 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
1690 int bit_nr = get_special_property_bit(element, property_bit_nr);
1693 return ((*bitfield & (1 << bit_nr)) != 0);
1700 void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set)
1702 int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
1706 level->can_move_into_acid_bits &= ~(1 << bit_nr);
1709 level->can_move_into_acid_bits |= (1 << bit_nr);
1713 boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
1715 int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
1718 return ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0);
1724 void InitElementPropertiesStatic()
1726 static int ep_diggable[] =
1731 EL_SP_BUGGY_BASE_ACTIVATING,
1734 EL_INVISIBLE_SAND_ACTIVE,
1736 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1737 /* (if amoeba can grow into anything diggable, maybe keep these out) */
1741 EL_SP_BUGGY_BASE_ACTIVE,
1746 static int ep_collectible_only[] =
1763 EL_DYNABOMB_INCREASE_NUMBER,
1764 EL_DYNABOMB_INCREASE_SIZE,
1765 EL_DYNABOMB_INCREASE_POWER,
1782 static int ep_dont_run_into[] =
1784 /* same elements as in 'ep_dont_touch' */
1790 /* same elements as in 'ep_dont_collide_with' */
1802 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1806 EL_SP_BUGGY_BASE_ACTIVE,
1811 static int ep_dont_collide_with[] =
1813 /* same elements as in 'ep_dont_touch' */
1829 static int ep_dont_touch[] =
1838 static int ep_indestructible[] =
1842 EL_ACID_POOL_TOPLEFT,
1843 EL_ACID_POOL_TOPRIGHT,
1844 EL_ACID_POOL_BOTTOMLEFT,
1845 EL_ACID_POOL_BOTTOM,
1846 EL_ACID_POOL_BOTTOMRIGHT,
1847 EL_SP_HARDWARE_GRAY,
1848 EL_SP_HARDWARE_GREEN,
1849 EL_SP_HARDWARE_BLUE,
1851 EL_SP_HARDWARE_YELLOW,
1852 EL_SP_HARDWARE_BASE_1,
1853 EL_SP_HARDWARE_BASE_2,
1854 EL_SP_HARDWARE_BASE_3,
1855 EL_SP_HARDWARE_BASE_4,
1856 EL_SP_HARDWARE_BASE_5,
1857 EL_SP_HARDWARE_BASE_6,
1858 EL_INVISIBLE_STEELWALL,
1859 EL_INVISIBLE_STEELWALL_ACTIVE,
1860 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1861 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1862 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1863 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1864 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1865 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1866 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1867 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1868 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1869 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1870 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1871 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1873 EL_LIGHT_SWITCH_ACTIVE,
1874 EL_SIGN_EXCLAMATION,
1875 EL_SIGN_RADIOACTIVITY,
1886 EL_STEELWALL_SLIPPERY,
1909 EL_SWITCHGATE_OPENING,
1910 EL_SWITCHGATE_CLOSED,
1911 EL_SWITCHGATE_CLOSING,
1913 EL_SWITCHGATE_SWITCH_UP,
1914 EL_SWITCHGATE_SWITCH_DOWN,
1917 EL_TIMEGATE_OPENING,
1919 EL_TIMEGATE_CLOSING,
1922 EL_TIMEGATE_SWITCH_ACTIVE,
1927 EL_TUBE_VERTICAL_LEFT,
1928 EL_TUBE_VERTICAL_RIGHT,
1929 EL_TUBE_HORIZONTAL_UP,
1930 EL_TUBE_HORIZONTAL_DOWN,
1938 static int ep_slippery[] =
1952 EL_ROBOT_WHEEL_ACTIVE,
1958 EL_ACID_POOL_TOPLEFT,
1959 EL_ACID_POOL_TOPRIGHT,
1969 EL_STEELWALL_SLIPPERY,
1975 static int ep_can_change[] =
1980 static int ep_can_move[] =
1982 /* same elements as in 'pb_can_move_into_acid' */
2003 static int ep_can_fall[] =
2018 EL_BD_MAGIC_WALL_FULL,
2031 static int ep_can_smash_player[] =
2056 static int ep_can_smash_enemies[] =
2064 static int ep_can_smash_everything[] =
2072 static int ep_can_explode_by_fire[] =
2074 /* same elements as in 'ep_can_explode_impact' */
2079 /* same elements as in 'ep_can_explode_smashed' */
2088 EL_DYNABOMB_PLAYER_1_ACTIVE,
2089 EL_DYNABOMB_PLAYER_2_ACTIVE,
2090 EL_DYNABOMB_PLAYER_3_ACTIVE,
2091 EL_DYNABOMB_PLAYER_4_ACTIVE,
2092 EL_DYNABOMB_INCREASE_NUMBER,
2093 EL_DYNABOMB_INCREASE_SIZE,
2094 EL_DYNABOMB_INCREASE_POWER,
2095 EL_SP_DISK_RED_ACTIVE,
2108 static int ep_can_explode_smashed[] =
2110 /* same elements as in 'ep_can_explode_impact' */
2123 static int ep_can_explode_impact[] =
2131 static int ep_walkable_over[] =
2135 EL_SOKOBAN_FIELD_EMPTY,
2153 static int ep_walkable_inside[] =
2158 EL_TUBE_VERTICAL_LEFT,
2159 EL_TUBE_VERTICAL_RIGHT,
2160 EL_TUBE_HORIZONTAL_UP,
2161 EL_TUBE_HORIZONTAL_DOWN,
2169 static int ep_walkable_under[] =
2174 static int ep_passable_over[] =
2189 static int ep_passable_inside[] =
2195 EL_SP_PORT_HORIZONTAL,
2196 EL_SP_PORT_VERTICAL,
2198 EL_SP_GRAVITY_PORT_LEFT,
2199 EL_SP_GRAVITY_PORT_RIGHT,
2200 EL_SP_GRAVITY_PORT_UP,
2201 EL_SP_GRAVITY_PORT_DOWN,
2205 static int ep_passable_under[] =
2210 static int ep_droppable[] =
2215 static int ep_can_explode_1x1[] =
2220 static int ep_pushable[] =
2232 EL_SOKOBAN_FIELD_FULL,
2239 static int ep_can_explode_cross[] =
2244 static int ep_protected[] =
2259 static int ep_player[] =
2266 EL_SOKOBAN_FIELD_PLAYER,
2270 static int ep_can_pass_magic_wall[] =
2283 static int ep_switchable[] =
2287 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2288 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2289 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2290 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2291 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2292 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2293 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2294 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2295 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2296 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2297 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2298 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2299 EL_SWITCHGATE_SWITCH_UP,
2300 EL_SWITCHGATE_SWITCH_DOWN,
2302 EL_LIGHT_SWITCH_ACTIVE,
2304 EL_BALLOON_SWITCH_LEFT,
2305 EL_BALLOON_SWITCH_RIGHT,
2306 EL_BALLOON_SWITCH_UP,
2307 EL_BALLOON_SWITCH_DOWN,
2308 EL_BALLOON_SWITCH_ANY,
2314 static int ep_bd_element[] =
2347 static int ep_sp_element[] =
2349 /* should always be valid */
2358 EL_SP_HARDWARE_GRAY,
2366 EL_SP_GRAVITY_PORT_RIGHT,
2367 EL_SP_GRAVITY_PORT_DOWN,
2368 EL_SP_GRAVITY_PORT_LEFT,
2369 EL_SP_GRAVITY_PORT_UP,
2374 EL_SP_PORT_VERTICAL,
2375 EL_SP_PORT_HORIZONTAL,
2381 EL_SP_HARDWARE_BASE_1,
2382 EL_SP_HARDWARE_GREEN,
2383 EL_SP_HARDWARE_BLUE,
2385 EL_SP_HARDWARE_YELLOW,
2386 EL_SP_HARDWARE_BASE_2,
2387 EL_SP_HARDWARE_BASE_3,
2388 EL_SP_HARDWARE_BASE_4,
2389 EL_SP_HARDWARE_BASE_5,
2390 EL_SP_HARDWARE_BASE_6,
2393 /* additional elements that appeared in newer Supaplex levels */
2395 /* more than one murphy in a level results in an inactive clone */
2397 /* runtime elements*/
2398 EL_SP_DISK_RED_ACTIVE,
2399 EL_SP_TERMINAL_ACTIVE,
2400 EL_SP_BUGGY_BASE_ACTIVATING,
2401 EL_SP_BUGGY_BASE_ACTIVE,
2407 static int ep_sb_element[] =
2412 EL_SOKOBAN_FIELD_EMPTY,
2413 EL_SOKOBAN_FIELD_FULL,
2414 EL_SOKOBAN_FIELD_PLAYER,
2419 EL_INVISIBLE_STEELWALL,
2423 static int ep_gem[] =
2434 static int ep_food_dark_yamyam[] =
2461 static int ep_food_penguin[] =
2474 static int ep_food_pig[] =
2485 static int ep_historic_wall[] =
2510 EL_EXPANDABLE_WALL_HORIZONTAL,
2511 EL_EXPANDABLE_WALL_VERTICAL,
2512 EL_EXPANDABLE_WALL_ANY,
2513 EL_EXPANDABLE_WALL_GROWING,
2520 EL_SP_HARDWARE_GRAY,
2521 EL_SP_HARDWARE_GREEN,
2522 EL_SP_HARDWARE_BLUE,
2524 EL_SP_HARDWARE_YELLOW,
2525 EL_SP_HARDWARE_BASE_1,
2526 EL_SP_HARDWARE_BASE_2,
2527 EL_SP_HARDWARE_BASE_3,
2528 EL_SP_HARDWARE_BASE_4,
2529 EL_SP_HARDWARE_BASE_5,
2530 EL_SP_HARDWARE_BASE_6,
2532 EL_SP_TERMINAL_ACTIVE,
2535 EL_INVISIBLE_STEELWALL,
2536 EL_INVISIBLE_STEELWALL_ACTIVE,
2538 EL_INVISIBLE_WALL_ACTIVE,
2539 EL_STEELWALL_SLIPPERY,
2555 static int ep_historic_solid[] =
2559 EL_EXPANDABLE_WALL_HORIZONTAL,
2560 EL_EXPANDABLE_WALL_VERTICAL,
2561 EL_EXPANDABLE_WALL_ANY,
2574 EL_QUICKSAND_FILLING,
2575 EL_QUICKSAND_EMPTYING,
2577 EL_MAGIC_WALL_ACTIVE,
2578 EL_MAGIC_WALL_EMPTYING,
2579 EL_MAGIC_WALL_FILLING,
2583 EL_BD_MAGIC_WALL_ACTIVE,
2584 EL_BD_MAGIC_WALL_EMPTYING,
2585 EL_BD_MAGIC_WALL_FULL,
2586 EL_BD_MAGIC_WALL_FILLING,
2587 EL_BD_MAGIC_WALL_DEAD,
2596 EL_SP_TERMINAL_ACTIVE,
2600 EL_INVISIBLE_WALL_ACTIVE,
2601 EL_SWITCHGATE_SWITCH_UP,
2602 EL_SWITCHGATE_SWITCH_DOWN,
2604 EL_TIMEGATE_SWITCH_ACTIVE,
2616 /* the following elements are a direct copy of "indestructible" elements,
2617 except "EL_ACID", which is "indestructible", but not "solid"! */
2622 EL_ACID_POOL_TOPLEFT,
2623 EL_ACID_POOL_TOPRIGHT,
2624 EL_ACID_POOL_BOTTOMLEFT,
2625 EL_ACID_POOL_BOTTOM,
2626 EL_ACID_POOL_BOTTOMRIGHT,
2627 EL_SP_HARDWARE_GRAY,
2628 EL_SP_HARDWARE_GREEN,
2629 EL_SP_HARDWARE_BLUE,
2631 EL_SP_HARDWARE_YELLOW,
2632 EL_SP_HARDWARE_BASE_1,
2633 EL_SP_HARDWARE_BASE_2,
2634 EL_SP_HARDWARE_BASE_3,
2635 EL_SP_HARDWARE_BASE_4,
2636 EL_SP_HARDWARE_BASE_5,
2637 EL_SP_HARDWARE_BASE_6,
2638 EL_INVISIBLE_STEELWALL,
2639 EL_INVISIBLE_STEELWALL_ACTIVE,
2640 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2641 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2642 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2643 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2644 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2645 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2646 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2647 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2648 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2649 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2650 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2651 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2653 EL_LIGHT_SWITCH_ACTIVE,
2654 EL_SIGN_EXCLAMATION,
2655 EL_SIGN_RADIOACTIVITY,
2666 EL_STEELWALL_SLIPPERY,
2689 EL_SWITCHGATE_OPENING,
2690 EL_SWITCHGATE_CLOSED,
2691 EL_SWITCHGATE_CLOSING,
2693 EL_TIMEGATE_OPENING,
2695 EL_TIMEGATE_CLOSING,
2699 EL_TUBE_VERTICAL_LEFT,
2700 EL_TUBE_VERTICAL_RIGHT,
2701 EL_TUBE_HORIZONTAL_UP,
2702 EL_TUBE_HORIZONTAL_DOWN,
2710 static int ep_classic_enemy[] =
2726 static int ep_belt[] =
2728 EL_CONVEYOR_BELT_1_LEFT,
2729 EL_CONVEYOR_BELT_1_MIDDLE,
2730 EL_CONVEYOR_BELT_1_RIGHT,
2731 EL_CONVEYOR_BELT_2_LEFT,
2732 EL_CONVEYOR_BELT_2_MIDDLE,
2733 EL_CONVEYOR_BELT_2_RIGHT,
2734 EL_CONVEYOR_BELT_3_LEFT,
2735 EL_CONVEYOR_BELT_3_MIDDLE,
2736 EL_CONVEYOR_BELT_3_RIGHT,
2737 EL_CONVEYOR_BELT_4_LEFT,
2738 EL_CONVEYOR_BELT_4_MIDDLE,
2739 EL_CONVEYOR_BELT_4_RIGHT,
2743 static int ep_belt_active[] =
2745 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2746 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2747 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2748 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2749 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2750 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2751 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2752 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2753 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2754 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2755 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2756 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2760 static int ep_belt_switch[] =
2762 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2763 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2764 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2765 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2766 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2767 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2768 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2769 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2770 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2771 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2772 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2773 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2777 static int ep_tube[] =
2784 EL_TUBE_HORIZONTAL_UP,
2785 EL_TUBE_HORIZONTAL_DOWN,
2787 EL_TUBE_VERTICAL_LEFT,
2788 EL_TUBE_VERTICAL_RIGHT,
2793 static int ep_keygate[] =
2814 static int ep_amoeboid[] =
2824 static int ep_amoebalive[] =
2833 static int ep_has_content[] =
2843 static int ep_can_turn_each_move[] =
2845 /* !!! do something with this one !!! */
2849 static int ep_can_grow[] =
2861 static int ep_active_bomb[] =
2864 EL_DYNABOMB_PLAYER_1_ACTIVE,
2865 EL_DYNABOMB_PLAYER_2_ACTIVE,
2866 EL_DYNABOMB_PLAYER_3_ACTIVE,
2867 EL_DYNABOMB_PLAYER_4_ACTIVE,
2868 EL_SP_DISK_RED_ACTIVE,
2872 static int ep_inactive[] =
2909 EL_INVISIBLE_STEELWALL,
2917 EL_WALL_EMERALD_YELLOW,
2918 EL_DYNABOMB_INCREASE_NUMBER,
2919 EL_DYNABOMB_INCREASE_SIZE,
2920 EL_DYNABOMB_INCREASE_POWER,
2924 EL_SOKOBAN_FIELD_EMPTY,
2925 EL_SOKOBAN_FIELD_FULL,
2926 EL_WALL_EMERALD_RED,
2927 EL_WALL_EMERALD_PURPLE,
2928 EL_ACID_POOL_TOPLEFT,
2929 EL_ACID_POOL_TOPRIGHT,
2930 EL_ACID_POOL_BOTTOMLEFT,
2931 EL_ACID_POOL_BOTTOM,
2932 EL_ACID_POOL_BOTTOMRIGHT,
2936 EL_BD_MAGIC_WALL_DEAD,
2937 EL_AMOEBA_TO_DIAMOND,
2945 EL_SP_GRAVITY_PORT_RIGHT,
2946 EL_SP_GRAVITY_PORT_DOWN,
2947 EL_SP_GRAVITY_PORT_LEFT,
2948 EL_SP_GRAVITY_PORT_UP,
2949 EL_SP_PORT_HORIZONTAL,
2950 EL_SP_PORT_VERTICAL,
2961 EL_SP_HARDWARE_GRAY,
2962 EL_SP_HARDWARE_GREEN,
2963 EL_SP_HARDWARE_BLUE,
2965 EL_SP_HARDWARE_YELLOW,
2966 EL_SP_HARDWARE_BASE_1,
2967 EL_SP_HARDWARE_BASE_2,
2968 EL_SP_HARDWARE_BASE_3,
2969 EL_SP_HARDWARE_BASE_4,
2970 EL_SP_HARDWARE_BASE_5,
2971 EL_SP_HARDWARE_BASE_6,
2972 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2973 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2974 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2975 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2976 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2977 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2978 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2979 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2980 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2981 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2982 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2983 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2984 EL_SIGN_EXCLAMATION,
2985 EL_SIGN_RADIOACTIVITY,
2996 EL_STEELWALL_SLIPPERY,
3012 static int ep_em_slippery_wall[] =
3017 static int ep_gfx_crumbled[] =
3030 } element_properties[] =
3032 { ep_diggable, EP_DIGGABLE },
3033 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
3034 { ep_dont_run_into, EP_DONT_RUN_INTO },
3035 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
3036 { ep_dont_touch, EP_DONT_TOUCH },
3037 { ep_indestructible, EP_INDESTRUCTIBLE },
3038 { ep_slippery, EP_SLIPPERY },
3039 { ep_can_change, EP_CAN_CHANGE },
3040 { ep_can_move, EP_CAN_MOVE },
3041 { ep_can_fall, EP_CAN_FALL },
3042 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
3043 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
3044 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
3045 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
3046 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
3047 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
3048 { ep_walkable_over, EP_WALKABLE_OVER },
3049 { ep_walkable_inside, EP_WALKABLE_INSIDE },
3050 { ep_walkable_under, EP_WALKABLE_UNDER },
3051 { ep_passable_over, EP_PASSABLE_OVER },
3052 { ep_passable_inside, EP_PASSABLE_INSIDE },
3053 { ep_passable_under, EP_PASSABLE_UNDER },
3054 { ep_droppable, EP_DROPPABLE },
3055 { ep_can_explode_1x1, EP_CAN_EXPLODE_1X1 },
3056 { ep_pushable, EP_PUSHABLE },
3057 { ep_can_explode_cross, EP_CAN_EXPLODE_CROSS },
3058 { ep_protected, EP_PROTECTED },
3060 { ep_player, EP_PLAYER },
3061 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
3062 { ep_switchable, EP_SWITCHABLE },
3063 { ep_bd_element, EP_BD_ELEMENT },
3064 { ep_sp_element, EP_SP_ELEMENT },
3065 { ep_sb_element, EP_SB_ELEMENT },
3067 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
3068 { ep_food_penguin, EP_FOOD_PENGUIN },
3069 { ep_food_pig, EP_FOOD_PIG },
3070 { ep_historic_wall, EP_HISTORIC_WALL },
3071 { ep_historic_solid, EP_HISTORIC_SOLID },
3072 { ep_classic_enemy, EP_CLASSIC_ENEMY },
3073 { ep_belt, EP_BELT },
3074 { ep_belt_active, EP_BELT_ACTIVE },
3075 { ep_belt_switch, EP_BELT_SWITCH },
3076 { ep_tube, EP_TUBE },
3077 { ep_keygate, EP_KEYGATE },
3078 { ep_amoeboid, EP_AMOEBOID },
3079 { ep_amoebalive, EP_AMOEBALIVE },
3080 { ep_has_content, EP_HAS_CONTENT },
3081 { ep_can_turn_each_move, EP_CAN_TURN_EACH_MOVE },
3082 { ep_can_grow, EP_CAN_GROW },
3083 { ep_active_bomb, EP_ACTIVE_BOMB },
3084 { ep_inactive, EP_INACTIVE },
3086 { ep_em_slippery_wall, EP_EM_SLIPPERY_WALL },
3088 { ep_gfx_crumbled, EP_GFX_CRUMBLED },
3093 static int copy_properties[][5] =
3097 EL_BUG_LEFT, EL_BUG_RIGHT,
3098 EL_BUG_UP, EL_BUG_DOWN
3102 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
3103 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
3107 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
3108 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
3112 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
3113 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
3117 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
3118 EL_PACMAN_UP, EL_PACMAN_DOWN
3122 EL_MOLE_LEFT, EL_MOLE_RIGHT,
3123 EL_MOLE_UP, EL_MOLE_DOWN
3133 /* always start with reliable default values (element has no properties) */
3134 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3135 for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3136 SET_PROPERTY(i, j, FALSE);
3138 /* set all base element properties from above array definitions */
3139 for (i = 0; element_properties[i].elements != NULL; i++)
3140 for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3141 SET_PROPERTY((element_properties[i].elements)[j],
3142 element_properties[i].property, TRUE);
3144 /* copy properties to some elements that are only stored in level file */
3145 for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3146 for (j = 0; copy_properties[j][0] != -1; j++)
3147 if (HAS_PROPERTY(copy_properties[j][0], i))
3148 for (k = 1; k <= 4; k++)
3149 SET_PROPERTY(copy_properties[j][k], i, TRUE);
3152 void InitElementPropertiesEngine(int engine_version)
3155 static int active_properties[] =
3160 EP_DONT_COLLIDE_WITH,
3164 EP_CAN_PASS_MAGIC_WALL,
3169 EP_CAN_EXPLODE_BY_FIRE,
3182 EP_EM_SLIPPERY_WALL,
3186 static int no_wall_properties[] =
3189 EP_COLLECTIBLE_ONLY,
3191 EP_DONT_COLLIDE_WITH,
3194 EP_CAN_SMASH_PLAYER,
3195 EP_CAN_SMASH_ENEMIES,
3196 EP_CAN_SMASH_EVERYTHING,
3201 EP_FOOD_DARK_YAMYAM,
3218 InitElementPropertiesStatic();
3221 /* important: after initialization in InitElementPropertiesStatic(), the
3222 elements are not again initialized to a default value; therefore all
3223 changes have to make sure that they leave the element with a defined
3224 property (which means that conditional property changes must be set to
3225 a reliable default value before) */
3227 /* set all special, combined or engine dependent element properties */
3228 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3231 for (j = EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
3232 SET_PROPERTY(i, j, FALSE);
3235 /* ---------- INACTIVE ------------------------------------------------- */
3236 SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
3238 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
3239 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
3240 IS_WALKABLE_INSIDE(i) ||
3241 IS_WALKABLE_UNDER(i)));
3243 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
3244 IS_PASSABLE_INSIDE(i) ||
3245 IS_PASSABLE_UNDER(i)));
3247 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
3248 IS_PASSABLE_OVER(i)));
3250 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
3251 IS_PASSABLE_INSIDE(i)));
3253 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
3254 IS_PASSABLE_UNDER(i)));
3256 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
3259 /* ---------- COLLECTIBLE ---------------------------------------------- */
3260 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
3263 /* ---------- SNAPPABLE ------------------------------------------------ */
3264 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
3265 IS_COLLECTIBLE(i) ||
3269 /* ---------- WALL ----------------------------------------------------- */
3270 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
3272 for (j = 0; no_wall_properties[j] != -1; j++)
3273 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
3274 i >= EL_FIRST_RUNTIME_UNREAL)
3275 SET_PROPERTY(i, EP_WALL, FALSE);
3277 if (IS_HISTORIC_WALL(i))
3278 SET_PROPERTY(i, EP_WALL, TRUE);
3280 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
3281 if (engine_version < VERSION_IDENT(2,2,0,0))
3282 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
3284 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
3286 !IS_COLLECTIBLE(i)));
3289 /* ---------- PROTECTED ------------------------------------------------ */
3290 if (IS_ACCESSIBLE_INSIDE(i))
3291 SET_PROPERTY(i, EP_PROTECTED, TRUE);
3294 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
3296 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
3297 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
3299 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
3300 IS_INDESTRUCTIBLE(i)));
3302 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
3304 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
3305 else if (engine_version < VERSION_IDENT(2,2,0,0))
3306 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
3309 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3314 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3315 !IS_WALKABLE_OVER(i) &&
3316 !IS_WALKABLE_UNDER(i)));
3318 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3323 if (IS_CUSTOM_ELEMENT(i))
3325 /* these are additional properties which are initially false when set */
3327 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
3329 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
3330 if (DONT_COLLIDE_WITH(i))
3331 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
3333 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
3334 if (CAN_SMASH_EVERYTHING(i))
3335 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
3336 if (CAN_SMASH_ENEMIES(i))
3337 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
3340 /* ---------- CAN_SMASH ------------------------------------------------ */
3341 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
3342 CAN_SMASH_ENEMIES(i) ||
3343 CAN_SMASH_EVERYTHING(i)));
3345 /* ---------- CAN_EXPLODE ---------------------------------------------- */
3346 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
3347 CAN_EXPLODE_SMASHED(i) ||
3348 CAN_EXPLODE_IMPACT(i)));
3350 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
3351 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
3352 !CAN_EXPLODE_1X1(i) &&
3353 !CAN_EXPLODE_CROSS(i)));
3355 /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
3356 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
3358 /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
3359 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
3360 i == EL_BLACK_ORB));
3362 /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
3363 SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
3365 IS_CUSTOM_ELEMENT(i)));
3367 /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
3368 SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
3369 i == EL_SP_ELECTRON));
3371 /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
3372 if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
3373 SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
3374 getMoveIntoAcidProperty(&level, i));
3376 /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
3377 if (MAYBE_DONT_COLLIDE_WITH(i))
3378 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
3379 getDontCollideWithProperty(&level, i));
3381 /* ---------- SP_PORT -------------------------------------------------- */
3382 SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
3383 IS_PASSABLE_INSIDE(i)));
3386 if (i == EL_CUSTOM_START + 253)
3387 printf("::: %d, %d, %d -> %d\n",
3390 CAN_EXPLODE_CROSS(i),
3394 /* ---------- CAN_CHANGE ----------------------------------------------- */
3395 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
3396 for (j = 0; j < element_info[i].num_change_pages; j++)
3397 if (element_info[i].change_page[j].can_change)
3398 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
3400 /* ---------- GFX_CRUMBLED --------------------------------------------- */
3401 SET_PROPERTY(i, EP_GFX_CRUMBLED,
3402 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
3406 /* determine inactive elements (used for engine main loop optimization) */
3407 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3409 boolean active = FALSE;
3411 for (j = 0; i < NUM_ELEMENT_PROPERTIES; j++)
3413 if (HAS_PROPERTY(i, j))
3419 SET_PROPERTY(i, EP_INACTIVE, TRUE);
3424 /* dynamically adjust element properties according to game engine version */
3426 static int ep_em_slippery_wall[] =
3431 EL_EXPANDABLE_WALL_HORIZONTAL,
3432 EL_EXPANDABLE_WALL_VERTICAL,
3433 EL_EXPANDABLE_WALL_ANY,
3437 /* special EM style gems behaviour */
3438 for (i = 0; ep_em_slippery_wall[i] != -1; i++)
3439 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
3440 level.em_slippery_gems);
3442 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
3443 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
3444 (level.em_slippery_gems &&
3445 engine_version > VERSION_IDENT(2,0,1,0)));
3449 /* set default push delay values (corrected since version 3.0.7-1) */
3450 if (engine_version < VERSION_IDENT(3,0,7,1))
3452 game.default_push_delay_fixed = 2;
3453 game.default_push_delay_random = 8;
3457 game.default_push_delay_fixed = 8;
3458 game.default_push_delay_random = 8;
3461 /* set uninitialized push delay values of custom elements in older levels */
3462 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3464 int element = EL_CUSTOM_START + i;
3466 if (element_info[element].push_delay_fixed == -1)
3467 element_info[element].push_delay_fixed = game.default_push_delay_fixed;
3468 if (element_info[element].push_delay_random == -1)
3469 element_info[element].push_delay_random = game.default_push_delay_random;
3472 /* set some other uninitialized values of custom elements in older levels */
3473 if (engine_version < VERSION_IDENT(3,1,0,0))
3475 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3477 int element = EL_CUSTOM_START + i;
3479 element_info[element].access_direction = MV_ALL_DIRECTIONS;
3481 element_info[element].explosion_delay = 17;
3482 element_info[element].ignition_delay = 8;
3487 /* set element properties that were handled incorrectly in older levels */
3488 if (engine_version < VERSION_IDENT(3,1,0,0))
3490 SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
3491 SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
3497 /* this is needed because some graphics depend on element properties */
3498 if (game_status == GAME_MODE_PLAYING)
3499 InitElementGraphicInfo();
3502 static void InitGlobal()
3504 global.autoplay_leveldir = NULL;
3506 global.frames_per_second = 0;
3507 global.fps_slowdown = FALSE;
3508 global.fps_slowdown_factor = 1;
3511 void Execute_Command(char *command)
3515 if (strcmp(command, "print graphicsinfo.conf") == 0)
3517 printf("# You can configure additional/alternative image files here.\n");
3518 printf("# (The entries below are default and therefore commented out.)\n");
3520 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
3522 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3525 for (i = 0; image_config[i].token != NULL; i++)
3526 printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
3527 image_config[i].value));
3531 else if (strcmp(command, "print soundsinfo.conf") == 0)
3533 printf("# You can configure additional/alternative sound files here.\n");
3534 printf("# (The entries below are default and therefore commented out.)\n");
3536 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
3538 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3541 for (i = 0; sound_config[i].token != NULL; i++)
3542 printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
3543 sound_config[i].value));
3547 else if (strcmp(command, "print musicinfo.conf") == 0)
3549 printf("# You can configure additional/alternative music files here.\n");
3550 printf("# (The entries below are default and therefore commented out.)\n");
3552 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
3554 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3557 for (i = 0; music_config[i].token != NULL; i++)
3558 printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
3559 music_config[i].value));
3563 else if (strcmp(command, "print editorsetup.conf") == 0)
3565 printf("# You can configure your personal editor element list here.\n");
3566 printf("# (The entries below are default and therefore commented out.)\n");
3569 PrintEditorElementList();
3573 else if (strcmp(command, "print helpanim.conf") == 0)
3575 printf("# You can configure different element help animations here.\n");
3576 printf("# (The entries below are default and therefore commented out.)\n");
3579 for (i = 0; helpanim_config[i].token != NULL; i++)
3581 printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
3582 helpanim_config[i].value));
3584 if (strcmp(helpanim_config[i].token, "end") == 0)
3590 else if (strcmp(command, "print helptext.conf") == 0)
3592 printf("# You can configure different element help text here.\n");
3593 printf("# (The entries below are default and therefore commented out.)\n");
3596 for (i = 0; helptext_config[i].token != NULL; i++)
3597 printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
3598 helptext_config[i].value));
3602 else if (strncmp(command, "dump level ", 11) == 0)
3604 char *filename = &command[11];
3606 if (access(filename, F_OK) != 0)
3607 Error(ERR_EXIT, "cannot open file '%s'", filename);
3609 LoadLevelFromFilename(&level, filename);
3614 else if (strncmp(command, "dump tape ", 10) == 0)
3616 char *filename = &command[10];
3618 if (access(filename, F_OK) != 0)
3619 Error(ERR_EXIT, "cannot open file '%s'", filename);
3621 LoadTapeFromFilename(filename);
3626 else if (strncmp(command, "autoplay ", 9) == 0)
3628 char *str_copy = getStringCopy(&command[9]);
3629 char *str_ptr = strchr(str_copy, ' ');
3631 global.autoplay_leveldir = str_copy;
3632 global.autoplay_level_nr = -1;
3634 if (str_ptr != NULL)
3636 *str_ptr++ = '\0'; /* terminate leveldir string */
3637 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3642 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3646 static void InitSetup()
3648 LoadSetup(); /* global setup info */
3650 /* set some options from setup file */
3652 if (setup.options.verbose)
3653 options.verbose = TRUE;
3656 static void InitPlayerInfo()
3660 /* choose default local player */
3661 local_player = &stored_player[0];
3663 for (i = 0; i < MAX_PLAYERS; i++)
3664 stored_player[i].connected = FALSE;
3666 local_player->connected = TRUE;
3669 static void InitArtworkInfo()
3674 static char *get_string_in_brackets(char *string)
3676 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3678 sprintf(string_in_brackets, "[%s]", string);
3680 return string_in_brackets;
3683 static char *get_level_id_suffix(int id_nr)
3685 char *id_suffix = checked_malloc(1 + 3 + 1);
3687 if (id_nr < 0 || id_nr > 999)
3690 sprintf(id_suffix, ".%03d", id_nr);
3696 static char *get_element_class_token(int element)
3698 char *element_class_name = element_info[element].class_name;
3699 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3701 sprintf(element_class_token, "[%s]", element_class_name);
3703 return element_class_token;
3706 static char *get_action_class_token(int action)
3708 char *action_class_name = &element_action_info[action].suffix[1];
3709 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3711 sprintf(action_class_token, "[%s]", action_class_name);
3713 return action_class_token;
3717 static void InitArtworkConfig()
3719 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3720 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3721 static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
3722 static char *action_id_suffix[NUM_ACTIONS + 1];
3723 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3724 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3725 static char *level_id_suffix[MAX_LEVELS + 1];
3726 static char *dummy[1] = { NULL };
3727 static char *ignore_generic_tokens[] =
3733 static char **ignore_image_tokens;
3734 static char **ignore_sound_tokens;
3735 static char **ignore_music_tokens;
3736 int num_ignore_generic_tokens;
3737 int num_ignore_image_tokens;
3738 int num_ignore_sound_tokens;
3739 int num_ignore_music_tokens;
3742 /* dynamically determine list of generic tokens to be ignored */
3743 num_ignore_generic_tokens = 0;
3744 for (i = 0; ignore_generic_tokens[i] != NULL; i++)
3745 num_ignore_generic_tokens++;
3747 /* dynamically determine list of image tokens to be ignored */
3748 num_ignore_image_tokens = num_ignore_generic_tokens;
3749 for (i = 0; image_config_vars[i].token != NULL; i++)
3750 num_ignore_image_tokens++;
3751 ignore_image_tokens =
3752 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3753 for (i = 0; i < num_ignore_generic_tokens; i++)
3754 ignore_image_tokens[i] = ignore_generic_tokens[i];
3755 for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3756 ignore_image_tokens[num_ignore_generic_tokens + i] =
3757 image_config_vars[i].token;
3758 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3760 /* dynamically determine list of sound tokens to be ignored */
3761 num_ignore_sound_tokens = num_ignore_generic_tokens;
3762 ignore_sound_tokens =
3763 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3764 for (i = 0; i < num_ignore_generic_tokens; i++)
3765 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3766 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3768 /* dynamically determine list of music tokens to be ignored */
3769 num_ignore_music_tokens = num_ignore_generic_tokens;
3770 ignore_music_tokens =
3771 checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
3772 for (i = 0; i < num_ignore_generic_tokens; i++)
3773 ignore_music_tokens[i] = ignore_generic_tokens[i];
3774 ignore_music_tokens[num_ignore_music_tokens] = NULL;
3776 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3777 image_id_prefix[i] = element_info[i].token_name;
3778 for (i = 0; i < NUM_FONTS; i++)
3779 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3780 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3782 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3783 sound_id_prefix[i] = element_info[i].token_name;
3784 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3785 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3786 get_string_in_brackets(element_info[i].class_name);
3787 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3789 for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
3790 music_id_prefix[i] = music_prefix_info[i].prefix;
3791 music_id_prefix[MAX_LEVELS] = NULL;
3793 for (i = 0; i < NUM_ACTIONS; i++)
3794 action_id_suffix[i] = element_action_info[i].suffix;
3795 action_id_suffix[NUM_ACTIONS] = NULL;
3797 for (i = 0; i < NUM_DIRECTIONS; i++)
3798 direction_id_suffix[i] = element_direction_info[i].suffix;
3799 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3801 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
3802 special_id_suffix[i] = special_suffix_info[i].suffix;
3803 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3805 for (i = 0; i < MAX_LEVELS; i++)
3806 level_id_suffix[i] = get_level_id_suffix(i);
3807 level_id_suffix[MAX_LEVELS] = NULL;
3809 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3810 image_id_prefix, action_id_suffix, direction_id_suffix,
3811 special_id_suffix, ignore_image_tokens);
3812 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3813 sound_id_prefix, action_id_suffix, dummy,
3814 special_id_suffix, ignore_sound_tokens);
3815 InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
3816 music_id_prefix, special_id_suffix, level_id_suffix,
3817 dummy, ignore_music_tokens);
3820 static void InitMixer()
3828 char *filename_font_initial = NULL;
3829 Bitmap *bitmap_font_initial = NULL;
3832 /* determine settings for initial font (for displaying startup messages) */
3833 for (i = 0; image_config[i].token != NULL; i++)
3835 for (j = 0; j < NUM_INITIAL_FONTS; j++)
3837 char font_token[128];
3840 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3841 len_font_token = strlen(font_token);
3843 if (strcmp(image_config[i].token, font_token) == 0)
3844 filename_font_initial = image_config[i].value;
3845 else if (strlen(image_config[i].token) > len_font_token &&
3846 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3848 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3849 font_initial[j].src_x = atoi(image_config[i].value);
3850 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3851 font_initial[j].src_y = atoi(image_config[i].value);
3852 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3853 font_initial[j].width = atoi(image_config[i].value);
3854 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3855 font_initial[j].height = atoi(image_config[i].value);
3860 for (j = 0; j < NUM_INITIAL_FONTS; j++)
3862 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3863 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3866 if (filename_font_initial == NULL) /* should not happen */
3867 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3869 /* create additional image buffers for double-buffering */
3870 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3871 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3873 /* initialize screen properties */
3874 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3875 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3877 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3878 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3879 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3881 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3883 for (j = 0; j < NUM_INITIAL_FONTS; j++)
3884 font_initial[j].bitmap = bitmap_font_initial;
3886 InitFontGraphicInfo();
3888 DrawInitText(getProgramInitString(), 20, FC_YELLOW);
3889 DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
3891 DrawInitText("Loading graphics:", 120, FC_GREEN);
3893 InitTileClipmasks();
3896 void InitGfxBackground()
3900 drawto = backbuffer;
3901 fieldbuffer = bitmap_db_field;
3902 SetDrawtoField(DRAW_BACKBUFFER);
3904 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3905 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3906 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3907 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3909 for (x = 0; x < MAX_BUF_XSIZE; x++)
3910 for (y = 0; y < MAX_BUF_YSIZE; y++)
3913 redraw_mask = REDRAW_ALL;
3916 static void InitLevelInfo()
3918 LoadLevelInfo(); /* global level info */
3919 LoadLevelSetup_LastSeries(); /* last played series info */
3920 LoadLevelSetup_SeriesInfo(); /* last played level info */
3923 void InitLevelArtworkInfo()
3925 LoadLevelArtworkInfo();
3928 static void InitImages()
3931 setLevelArtworkDir(artwork.gfx_first);
3935 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3936 leveldir_current->identifier,
3937 artwork.gfx_current_identifier,
3938 artwork.gfx_current->identifier,
3939 leveldir_current->graphics_set,
3940 leveldir_current->graphics_path);
3943 ReloadCustomImages();
3945 LoadCustomElementDescriptions();
3946 LoadSpecialMenuDesignSettings();
3948 ReinitializeGraphics();
3951 static void InitSound(char *identifier)
3953 if (identifier == NULL)
3954 identifier = artwork.snd_current->identifier;
3957 /* set artwork path to send it to the sound server process */
3958 setLevelArtworkDir(artwork.snd_first);
3961 InitReloadCustomSounds(identifier);
3962 ReinitializeSounds();
3965 static void InitMusic(char *identifier)
3967 if (identifier == NULL)
3968 identifier = artwork.mus_current->identifier;
3971 /* set artwork path to send it to the sound server process */
3972 setLevelArtworkDir(artwork.mus_first);
3975 InitReloadCustomMusic(identifier);
3976 ReinitializeMusic();
3979 void InitNetworkServer()
3981 #if defined(PLATFORM_UNIX)
3985 if (!options.network)
3988 #if defined(PLATFORM_UNIX)
3989 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3991 if (!ConnectToServer(options.server_host, options.server_port))
3992 Error(ERR_EXIT, "cannot connect to network game server");
3994 SendToServer_PlayerName(setup.player_name);
3995 SendToServer_ProtocolVersion();
3998 SendToServer_NrWanted(nr_wanted);
4002 static char *getNewArtworkIdentifier(int type)
4004 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4005 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4006 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4007 static boolean initialized[3] = { FALSE, FALSE, FALSE };
4008 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4009 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4010 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4011 char *leveldir_identifier = leveldir_current->identifier;
4013 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4014 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4016 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4018 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4019 char *artwork_current_identifier;
4020 char *artwork_new_identifier = NULL; /* default: nothing has changed */
4022 /* leveldir_current may be invalid (level group, parent link) */
4023 if (!validLevelSeries(leveldir_current))
4026 /* 1st step: determine artwork set to be activated in descending order:
4027 --------------------------------------------------------------------
4028 1. setup artwork (when configured to override everything else)
4029 2. artwork set configured in "levelinfo.conf" of current level set
4030 (artwork in level directory will have priority when loading later)
4031 3. artwork in level directory (stored in artwork sub-directory)
4032 4. setup artwork (currently configured in setup menu) */
4034 if (setup_override_artwork)
4035 artwork_current_identifier = setup_artwork_set;
4036 else if (leveldir_artwork_set != NULL)
4037 artwork_current_identifier = leveldir_artwork_set;
4038 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4039 artwork_current_identifier = leveldir_identifier;
4041 artwork_current_identifier = setup_artwork_set;
4044 /* 2nd step: check if it is really needed to reload artwork set
4045 ------------------------------------------------------------ */
4048 if (type == ARTWORK_TYPE_GRAPHICS)
4049 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4050 artwork_new_identifier,
4051 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4052 artwork_current_identifier,
4053 leveldir_current->graphics_set,
4054 leveldir_current->identifier);
4057 /* ---------- reload if level set and also artwork set has changed ------- */
4058 if (leveldir_current_identifier[type] != leveldir_identifier &&
4059 (last_has_level_artwork_set[type] || has_level_artwork_set))
4060 artwork_new_identifier = artwork_current_identifier;
4062 leveldir_current_identifier[type] = leveldir_identifier;
4063 last_has_level_artwork_set[type] = has_level_artwork_set;
4066 if (type == ARTWORK_TYPE_GRAPHICS)
4067 printf("::: 1: '%s'\n", artwork_new_identifier);
4070 /* ---------- reload if "override artwork" setting has changed ----------- */
4071 if (last_override_level_artwork[type] != setup_override_artwork)
4072 artwork_new_identifier = artwork_current_identifier;
4074 last_override_level_artwork[type] = setup_override_artwork;
4077 if (type == ARTWORK_TYPE_GRAPHICS)
4078 printf("::: 2: '%s'\n", artwork_new_identifier);
4081 /* ---------- reload if current artwork identifier has changed ----------- */
4082 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4083 artwork_current_identifier) != 0)
4084 artwork_new_identifier = artwork_current_identifier;
4086 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
4089 if (type == ARTWORK_TYPE_GRAPHICS)
4090 printf("::: 3: '%s'\n", artwork_new_identifier);
4093 /* ---------- do not reload directly after starting ---------------------- */
4094 if (!initialized[type])
4095 artwork_new_identifier = NULL;
4097 initialized[type] = TRUE;
4100 if (type == ARTWORK_TYPE_GRAPHICS)
4101 printf("::: 4: '%s'\n", artwork_new_identifier);
4105 if (type == ARTWORK_TYPE_GRAPHICS)
4106 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4107 artwork.gfx_current_identifier, artwork_current_identifier,
4108 artwork.gfx_current->identifier, leveldir_current->graphics_set,
4109 artwork_new_identifier);
4112 return artwork_new_identifier;
4115 void ReloadCustomArtwork(int force_reload)
4117 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
4118 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
4119 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
4120 boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4121 boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4122 boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4123 boolean redraw_screen = FALSE;
4125 if (gfx_new_identifier != NULL || force_reload_gfx)
4128 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
4129 artwork.gfx_current_identifier,
4131 artwork.gfx_current->identifier,
4132 leveldir_current->graphics_set);
4135 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4140 printf("... '%s'\n",
4141 leveldir_current->graphics_set);
4144 FreeTileClipmasks();
4145 InitTileClipmasks();
4147 redraw_screen = TRUE;
4150 if (snd_new_identifier != NULL || force_reload_snd)
4152 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4154 InitSound(snd_new_identifier);
4156 redraw_screen = TRUE;
4159 if (mus_new_identifier != NULL || force_reload_mus)
4161 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4163 InitMusic(mus_new_identifier);
4165 redraw_screen = TRUE;
4170 InitGfxBackground();
4172 /* force redraw of (open or closed) door graphics */
4173 SetDoorState(DOOR_OPEN_ALL);
4174 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
4178 void KeyboardAutoRepeatOffUnlessAutoplay()
4180 if (global.autoplay_leveldir == NULL)
4181 KeyboardAutoRepeatOff();
4185 /* ========================================================================= */
4187 /* ========================================================================= */
4191 InitGlobal(); /* initialize some global variables */
4193 if (options.execute_command)
4194 Execute_Command(options.execute_command);
4196 if (options.serveronly)
4198 #if defined(PLATFORM_UNIX)
4199 NetworkServer(options.server_port, options.serveronly);
4201 Error(ERR_WARN, "networking only supported in Unix version");
4203 exit(0); /* never reached */
4209 InitArtworkInfo(); /* needed before loading gfx, sound & music */
4210 InitArtworkConfig(); /* needed before forking sound child process */
4215 InitRND(NEW_RANDOMIZE);
4216 InitSimpleRND(NEW_RANDOMIZE);
4221 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
4224 InitEventFilter(FilterMouseMotionEvents);
4226 InitElementPropertiesStatic();
4227 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4232 InitLevelArtworkInfo();
4234 InitImages(); /* needs to know current level directory */
4235 InitSound(NULL); /* needs to know current level directory */
4236 InitMusic(NULL); /* needs to know current level directory */
4238 InitGfxBackground();
4240 if (global.autoplay_leveldir)
4246 game_status = GAME_MODE_MAIN;
4250 InitNetworkServer();
4253 void CloseAllAndExit(int exit_value)
4258 CloseAudio(); /* called after freeing sounds (needed for SDL) */
4261 FreeTileClipmasks();
4263 CloseVideoDisplay();
4264 ClosePlatformDependentStuff();