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 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
42 static int copy_properties[][5] =
46 EL_BUG_LEFT, EL_BUG_RIGHT,
47 EL_BUG_UP, EL_BUG_DOWN
51 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
52 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
56 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
57 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
61 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
62 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
66 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
67 EL_PACMAN_UP, EL_PACMAN_DOWN
71 EL_MOLE_LEFT, EL_MOLE_RIGHT,
72 EL_MOLE_UP, EL_MOLE_DOWN
80 static void InitTileClipmasks()
83 #if defined(TARGET_X11)
84 XGCValues clip_gc_values;
85 unsigned long clip_gc_valuemask;
87 #if defined(TARGET_X11_NATIVE)
97 tile_needs_clipping[] =
99 { GFX_SPIELER1_UP, 4 },
100 { GFX_SPIELER1_DOWN, 4 },
101 { GFX_SPIELER1_LEFT, 4 },
102 { GFX_SPIELER1_RIGHT, 4 },
103 { GFX_SPIELER1_PUSH_LEFT, 4 },
104 { GFX_SPIELER1_PUSH_RIGHT, 4 },
105 { GFX_SPIELER2_UP, 4 },
106 { GFX_SPIELER2_DOWN, 4 },
107 { GFX_SPIELER2_LEFT, 4 },
108 { GFX_SPIELER2_RIGHT, 4 },
109 { GFX_SPIELER2_PUSH_LEFT, 4 },
110 { GFX_SPIELER2_PUSH_RIGHT, 4 },
111 { GFX_SPIELER3_UP, 4 },
112 { GFX_SPIELER3_DOWN, 4 },
113 { GFX_SPIELER3_LEFT, 4 },
114 { GFX_SPIELER3_RIGHT, 4 },
115 { GFX_SPIELER3_PUSH_LEFT, 4 },
116 { GFX_SPIELER3_PUSH_RIGHT, 4 },
117 { GFX_SPIELER4_UP, 4 },
118 { GFX_SPIELER4_DOWN, 4 },
119 { GFX_SPIELER4_LEFT, 4 },
120 { GFX_SPIELER4_RIGHT, 4 },
121 { GFX_SPIELER4_PUSH_LEFT, 4 },
122 { GFX_SPIELER4_PUSH_RIGHT, 4 },
123 { GFX_SP_MURPHY, 1 },
124 { GFX_MURPHY_GO_LEFT, 3 },
125 { GFX_MURPHY_GO_RIGHT, 3 },
126 { GFX_MURPHY_SNAP_UP, 1 },
127 { GFX_MURPHY_SNAP_DOWN, 1 },
128 { GFX_MURPHY_SNAP_RIGHT, 1 },
129 { GFX_MURPHY_SNAP_LEFT, 1 },
130 { GFX_MURPHY_PUSH_RIGHT, 1 },
131 { GFX_MURPHY_PUSH_LEFT, 1 },
132 { GFX_GEBLUBBER, 4 },
135 { GFX_EXPLOSION, 8 },
136 { GFX_SOKOBAN_OBJEKT, 1 },
137 { GFX_FUNKELN_BLAU, 3 },
138 { GFX_FUNKELN_WEISS, 3 },
139 { GFX2_SHIELD_PASSIVE, 3 },
140 { GFX2_SHIELD_ACTIVE, 3 },
145 #endif /* TARGET_X11_NATIVE */
146 #endif /* TARGET_X11 */
150 /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
151 for (i = 0; i < NUM_TILES; i++)
152 tile_clipmask[i] = None;
154 #if defined(TARGET_X11)
155 /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
156 often very slow when preparing a masked XCopyArea() for big Pixmaps.
157 To prevent this, create small (tile-sized) mask Pixmaps which will then
158 be set much faster with XSetClipOrigin() and speed things up a lot. */
160 clip_gc_values.graphics_exposures = False;
161 clip_gc_valuemask = GCGraphicsExposures;
162 tile_clip_gc = XCreateGC(display, window->drawable,
163 clip_gc_valuemask, &clip_gc_values);
166 for (i = 0; i < NUM_BITMAPS; i++)
168 if (pix[i]->clip_mask)
170 clip_gc_values.graphics_exposures = False;
171 clip_gc_values.clip_mask = pix[i]->clip_mask;
172 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
173 pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
174 clip_gc_valuemask, &clip_gc_values);
179 #if defined(TARGET_X11_NATIVE)
182 /* create graphic context structures needed for clipping */
183 clip_gc_values.graphics_exposures = False;
184 clip_gc_valuemask = GCGraphicsExposures;
185 copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
186 clip_gc_valuemask, &clip_gc_values);
188 /* create only those clipping Pixmaps we really need */
189 for (i = 0; tile_needs_clipping[i].start >= 0; i++)
193 for (j = 0; j < tile_needs_clipping[i].count; j++)
195 int tile = tile_needs_clipping[i].start + j;
201 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
202 src_pixmap = src_bitmap->clip_mask;
204 tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
207 XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
208 src_x, src_y, TILEX, TILEY, 0, 0);
212 XFreeGC(display, copy_clipmask_gc);
215 #endif /* TARGET_X11_NATIVE */
216 #endif /* TARGET_X11 */
220 void FreeTileClipmasks()
223 #if defined(TARGET_X11)
226 for (i = 0; i < NUM_TILES; i++)
228 if (tile_clipmask[i] != None)
230 XFreePixmap(display, tile_clipmask[i]);
231 tile_clipmask[i] = None;
236 XFreeGC(display, tile_clip_gc);
240 for (i = 0; i < NUM_BITMAPS; i++)
242 if (pix[i] != NULL && pix[i]->stored_clip_gc)
244 XFreeGC(display, pix[i]->stored_clip_gc);
245 pix[i]->stored_clip_gc = None;
250 #endif /* TARGET_X11 */
256 FreeLevelEditorGadgets();
265 static boolean gadgets_initialized = FALSE;
267 if (gadgets_initialized)
270 CreateLevelEditorGadgets();
274 CreateScreenGadgets();
276 gadgets_initialized = TRUE;
279 inline void InitElementSmallImagesScaledUp(int graphic)
281 CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
284 void InitElementSmallImages()
286 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
287 int num_property_mappings = getImageListPropertyMappingSize();
290 /* initialize normal images from static configuration */
291 for (i = 0; element_to_graphic[i].element > -1; i++)
292 InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
294 /* initialize special images from static configuration */
295 for (i = 0; element_to_special_graphic[i].element > -1; i++)
296 InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
298 /* initialize images from dynamic configuration (may be elements or other) */
300 for (i = 0; i < num_property_mappings; i++)
301 InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
303 /* !!! THIS DOES NOT WORK -- "artwork_index" is graphic, not element !!! */
304 /* !!! ALSO, non-element graphics might need scaling-up !!! */
305 for (i = 0; i < num_property_mappings; i++)
306 if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
307 InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
311 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
312 for (i = IMG_EMC_OBJECT; i <= IMG_EMC_SPRITE; i++)
313 InitElementSmallImagesScaledUp(i);
318 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
319 void SetBitmaps_EM(Bitmap **em_bitmap)
321 em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
322 em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
326 static int getFontBitmapID(int font_nr)
330 if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
331 special = game_status;
332 else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
333 special = GFX_SPECIAL_ARG_MAIN;
334 else if (game_status == GAME_MODE_PLAYING)
335 special = GFX_SPECIAL_ARG_DOOR;
338 return font_info[font_nr].special_bitmap_id[special];
343 void InitFontGraphicInfo()
345 static struct FontBitmapInfo *font_bitmap_info = NULL;
346 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
347 int num_property_mappings = getImageListPropertyMappingSize();
348 int num_font_bitmaps = NUM_FONTS;
351 if (graphic_info == NULL) /* still at startup phase */
353 InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
358 /* ---------- initialize font graphic definitions ---------- */
360 /* always start with reliable default values (normal font graphics) */
362 for (i = 0; i < NUM_FONTS; i++)
363 font_info[i].graphic = IMG_FONT_INITIAL_1;
365 for (i = 0; i < NUM_FONTS; i++)
366 font_info[i].graphic = FONT_INITIAL_1;
369 /* initialize normal font/graphic mapping from static configuration */
370 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
372 int font_nr = font_to_graphic[i].font_nr;
373 int special = font_to_graphic[i].special;
374 int graphic = font_to_graphic[i].graphic;
379 font_info[font_nr].graphic = graphic;
382 /* always start with reliable default values (special font graphics) */
383 for (i = 0; i < NUM_FONTS; i++)
385 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
387 font_info[i].special_graphic[j] = font_info[i].graphic;
388 font_info[i].special_bitmap_id[j] = i;
392 /* initialize special font/graphic mapping from static configuration */
393 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
395 int font_nr = font_to_graphic[i].font_nr;
396 int special = font_to_graphic[i].special;
397 int graphic = font_to_graphic[i].graphic;
399 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
401 font_info[font_nr].special_graphic[special] = graphic;
402 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
407 /* initialize special element/graphic mapping from dynamic configuration */
408 for (i = 0; i < num_property_mappings; i++)
410 int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
411 int special = property_mapping[i].ext3_index;
412 int graphic = property_mapping[i].artwork_index;
417 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
419 font_info[font_nr].special_graphic[special] = graphic;
420 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
425 /* ---------- initialize font bitmap array ---------- */
427 if (font_bitmap_info != NULL)
428 FreeFontInfo(font_bitmap_info);
431 checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
433 /* ---------- initialize font bitmap definitions ---------- */
435 for (i = 0; i < NUM_FONTS; i++)
437 if (i < NUM_INITIAL_FONTS)
439 font_bitmap_info[i] = font_initial[i];
443 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
445 int font_bitmap_id = font_info[i].special_bitmap_id[j];
446 int graphic = font_info[i].special_graphic[j];
448 /* set 'graphic_info' for font entries, if uninitialized (guessed) */
449 if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
451 graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
452 graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
455 /* copy font relevant information from graphics information */
456 font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
457 font_bitmap_info[font_bitmap_id].src_x = graphic_info[graphic].src_x;
458 font_bitmap_info[font_bitmap_id].src_y = graphic_info[graphic].src_y;
459 font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
460 font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
461 font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
462 font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
464 font_bitmap_info[font_bitmap_id].num_chars =
465 graphic_info[graphic].anim_frames;
466 font_bitmap_info[font_bitmap_id].num_chars_per_line =
467 graphic_info[graphic].anim_frames_per_line;
471 InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
474 void InitElementGraphicInfo()
476 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
477 int num_property_mappings = getImageListPropertyMappingSize();
480 if (graphic_info == NULL) /* still at startup phase */
483 /* set values to -1 to identify later as "uninitialized" values */
484 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
486 for (act = 0; act < NUM_ACTIONS; act++)
488 element_info[i].graphic[act] = -1;
489 element_info[i].crumbled[act] = -1;
491 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
493 element_info[i].direction_graphic[act][dir] = -1;
494 element_info[i].direction_crumbled[act][dir] = -1;
499 /* initialize normal element/graphic mapping from static configuration */
500 for (i = 0; element_to_graphic[i].element > -1; i++)
502 int element = element_to_graphic[i].element;
503 int action = element_to_graphic[i].action;
504 int direction = element_to_graphic[i].direction;
505 boolean crumbled = element_to_graphic[i].crumbled;
506 int graphic = element_to_graphic[i].graphic;
507 int base_graphic = el2baseimg(element);
509 if (graphic_info[graphic].bitmap == NULL)
512 if ((action > -1 || direction > -1 || crumbled == TRUE) &&
515 boolean base_redefined =
516 getImageListEntryFromImageID(base_graphic)->redefined;
517 boolean act_dir_redefined =
518 getImageListEntryFromImageID(graphic)->redefined;
520 /* if the base graphic ("emerald", for example) has been redefined,
521 but not the action graphic ("emerald.falling", for example), do not
522 use an existing (in this case considered obsolete) action graphic
523 anymore, but use the automatically determined default graphic */
524 if (base_redefined && !act_dir_redefined)
529 action = ACTION_DEFAULT;
534 element_info[element].direction_crumbled[action][direction] = graphic;
536 element_info[element].crumbled[action] = graphic;
541 element_info[element].direction_graphic[action][direction] = graphic;
543 element_info[element].graphic[action] = graphic;
547 /* initialize normal element/graphic mapping from dynamic configuration */
548 for (i = 0; i < num_property_mappings; i++)
550 int element = property_mapping[i].base_index;
551 int action = property_mapping[i].ext1_index;
552 int direction = property_mapping[i].ext2_index;
553 int special = property_mapping[i].ext3_index;
554 int graphic = property_mapping[i].artwork_index;
555 boolean crumbled = FALSE;
557 if (special == GFX_SPECIAL_ARG_CRUMBLED)
563 if (graphic_info[graphic].bitmap == NULL)
566 if (element >= MAX_NUM_ELEMENTS || special != -1)
570 action = ACTION_DEFAULT;
575 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
576 element_info[element].direction_crumbled[action][dir] = -1;
579 element_info[element].direction_crumbled[action][direction] = graphic;
581 element_info[element].crumbled[action] = graphic;
586 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
587 element_info[element].direction_graphic[action][dir] = -1;
590 element_info[element].direction_graphic[action][direction] = graphic;
592 element_info[element].graphic[action] = graphic;
596 /* now copy all graphics that are defined to be cloned from other graphics */
597 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
599 int graphic = element_info[i].graphic[ACTION_DEFAULT];
600 int crumbled_like, diggable_like;
605 crumbled_like = graphic_info[graphic].crumbled_like;
606 diggable_like = graphic_info[graphic].diggable_like;
608 if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
610 for (act = 0; act < NUM_ACTIONS; act++)
611 element_info[i].crumbled[act] =
612 element_info[crumbled_like].crumbled[act];
613 for (act = 0; act < NUM_ACTIONS; act++)
614 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
615 element_info[i].direction_crumbled[act][dir] =
616 element_info[crumbled_like].direction_crumbled[act][dir];
619 if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
621 element_info[i].graphic[ACTION_DIGGING] =
622 element_info[diggable_like].graphic[ACTION_DIGGING];
623 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
624 element_info[i].direction_graphic[ACTION_DIGGING][dir] =
625 element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
630 /* set hardcoded definitions for some runtime elements without graphic */
631 element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
635 /* now set all undefined/invalid graphics to -1 to set to default after it */
636 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
638 for (act = 0; act < NUM_ACTIONS; act++)
642 graphic = element_info[i].graphic[act];
643 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
644 element_info[i].graphic[act] = -1;
646 graphic = element_info[i].crumbled[act];
647 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
648 element_info[i].crumbled[act] = -1;
650 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
652 graphic = element_info[i].direction_graphic[act][dir];
653 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
654 element_info[i].direction_graphic[act][dir] = -1;
656 graphic = element_info[i].direction_crumbled[act][dir];
657 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
658 element_info[i].direction_crumbled[act][dir] = -1;
665 /* adjust graphics with 2nd tile for movement according to direction
666 (do this before correcting '-1' values to minimize calculations) */
667 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
669 for (act = 0; act < NUM_ACTIONS; act++)
671 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
673 int graphic = element_info[i].direction_graphic[act][dir];
674 int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
676 if (act == ACTION_FALLING) /* special case */
677 graphic = element_info[i].graphic[act];
680 graphic_info[graphic].double_movement &&
681 graphic_info[graphic].swap_double_tiles != 0)
683 struct GraphicInfo *g = &graphic_info[graphic];
684 int src_x_front = g->src_x;
685 int src_y_front = g->src_y;
686 int src_x_back = g->src_x + g->offset2_x;
687 int src_y_back = g->src_y + g->offset2_y;
688 boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
690 boolean front_is_left_or_upper = (src_x_front < src_x_back ||
691 src_y_front < src_y_back);
693 boolean second_tile_is_back =
694 ((move_dir == MV_BIT_LEFT && front_is_left_or_upper) ||
695 (move_dir == MV_BIT_UP && front_is_left_or_upper));
696 boolean second_tile_is_front =
697 ((move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
698 (move_dir == MV_BIT_DOWN && front_is_left_or_upper));
699 boolean second_tile_should_be_front =
700 (g->second_tile_is_start == 0);
701 boolean second_tile_should_be_back =
702 (g->second_tile_is_start == 1);
704 boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
705 boolean swap_movement_tiles_autodetected =
706 (!frames_are_ordered_diagonally &&
707 ((move_dir == MV_BIT_LEFT && !front_is_left_or_upper) ||
708 (move_dir == MV_BIT_UP && !front_is_left_or_upper) ||
709 (move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
710 (move_dir == MV_BIT_DOWN && front_is_left_or_upper)));
714 printf("::: CHECKING element %d ('%s'), '%s', dir %d [(%d -> %d, %d), %d => %d]\n",
715 i, element_info[i].token_name,
716 element_action_info[act].suffix, move_dir,
717 g->swap_double_tiles,
718 swap_movement_tiles_never,
719 swap_movement_tiles_always,
720 swap_movement_tiles_autodetected,
721 swap_movement_tiles);
724 /* swap frontside and backside graphic tile coordinates, if needed */
725 if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
727 /* get current (wrong) backside tile coordinates */
728 getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
731 /* set frontside tile coordinates to backside tile coordinates */
732 g->src_x = src_x_back;
733 g->src_y = src_y_back;
735 /* invert tile offset to point to new backside tile coordinates */
739 /* do not swap front and backside tiles again after correction */
740 g->swap_double_tiles = 0;
743 printf(" CORRECTED\n");
752 /* now set all '-1' values to element specific default values */
753 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
755 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
756 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
757 int default_direction_graphic[NUM_DIRECTIONS];
758 int default_direction_crumbled[NUM_DIRECTIONS];
760 if (default_graphic == -1)
761 default_graphic = IMG_UNKNOWN;
763 if (default_crumbled == -1)
764 default_crumbled = default_graphic;
766 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
767 if (default_crumbled == -1)
768 default_crumbled = IMG_EMPTY;
771 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
773 default_direction_graphic[dir] =
774 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
775 default_direction_crumbled[dir] =
776 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
778 if (default_direction_graphic[dir] == -1)
779 default_direction_graphic[dir] = default_graphic;
781 if (default_direction_crumbled[dir] == -1)
782 default_direction_crumbled[dir] = default_direction_graphic[dir];
784 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
785 if (default_direction_crumbled[dir] == -1)
786 default_direction_crumbled[dir] = default_crumbled;
790 for (act = 0; act < NUM_ACTIONS; act++)
792 boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
793 (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
794 (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
795 boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
796 act == ACTION_TURNING_FROM_RIGHT ||
797 act == ACTION_TURNING_FROM_UP ||
798 act == ACTION_TURNING_FROM_DOWN);
800 /* generic default action graphic (defined by "[default]" directive) */
801 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
802 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
803 int default_remove_graphic = IMG_EMPTY;
805 if (act_remove && default_action_graphic != -1)
806 default_remove_graphic = default_action_graphic;
808 /* look for special default action graphic (classic game specific) */
809 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
810 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
811 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
812 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
813 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
814 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
816 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
817 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
818 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
819 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
820 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
821 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
824 /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
825 /* !!! make this better !!! */
826 if (i == EL_EMPTY_SPACE)
828 default_action_graphic = element_info[EL_DEFAULT].graphic[act];
829 default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
833 if (default_action_graphic == -1)
834 default_action_graphic = default_graphic;
836 if (default_action_crumbled == -1)
837 default_action_crumbled = default_action_graphic;
839 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
840 if (default_action_crumbled == -1)
841 default_action_crumbled = default_crumbled;
844 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
846 /* use action graphic as the default direction graphic, if undefined */
847 int default_action_direction_graphic = element_info[i].graphic[act];
848 int default_action_direction_crumbled = element_info[i].crumbled[act];
850 /* no graphic for current action -- use default direction graphic */
851 if (default_action_direction_graphic == -1)
852 default_action_direction_graphic =
853 (act_remove ? default_remove_graphic :
855 element_info[i].direction_graphic[ACTION_TURNING][dir] :
856 default_action_graphic != default_graphic ?
857 default_action_graphic :
858 default_direction_graphic[dir]);
860 if (element_info[i].direction_graphic[act][dir] == -1)
861 element_info[i].direction_graphic[act][dir] =
862 default_action_direction_graphic;
865 if (default_action_direction_crumbled == -1)
866 default_action_direction_crumbled =
867 element_info[i].direction_graphic[act][dir];
869 if (default_action_direction_crumbled == -1)
870 default_action_direction_crumbled =
871 (act_remove ? default_remove_graphic :
873 element_info[i].direction_crumbled[ACTION_TURNING][dir] :
874 default_action_crumbled != default_crumbled ?
875 default_action_crumbled :
876 default_direction_crumbled[dir]);
879 if (element_info[i].direction_crumbled[act][dir] == -1)
880 element_info[i].direction_crumbled[act][dir] =
881 default_action_direction_crumbled;
884 if (i == EL_EMC_GRASS &&
885 act == ACTION_DIGGING &&
887 printf("::: direction_crumbled == %d, %d, %d\n",
888 element_info[i].direction_crumbled[act][dir],
889 default_action_direction_crumbled,
890 element_info[i].crumbled[act]);
894 /* no graphic for this specific action -- use default action graphic */
895 if (element_info[i].graphic[act] == -1)
896 element_info[i].graphic[act] =
897 (act_remove ? default_remove_graphic :
898 act_turning ? element_info[i].graphic[ACTION_TURNING] :
899 default_action_graphic);
901 if (element_info[i].crumbled[act] == -1)
902 element_info[i].crumbled[act] = element_info[i].graphic[act];
904 if (element_info[i].crumbled[act] == -1)
905 element_info[i].crumbled[act] =
906 (act_remove ? default_remove_graphic :
907 act_turning ? element_info[i].crumbled[ACTION_TURNING] :
908 default_action_crumbled);
914 /* set animation mode to "none" for each graphic with only 1 frame */
915 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
917 for (act = 0; act < NUM_ACTIONS; act++)
919 int graphic = element_info[i].graphic[act];
920 int crumbled = element_info[i].crumbled[act];
922 if (graphic_info[graphic].anim_frames == 1)
923 graphic_info[graphic].anim_mode = ANIM_NONE;
924 if (graphic_info[crumbled].anim_frames == 1)
925 graphic_info[crumbled].anim_mode = ANIM_NONE;
927 for (dir = 0; dir < NUM_DIRECTIONS; dir++)
929 graphic = element_info[i].direction_graphic[act][dir];
930 crumbled = element_info[i].direction_crumbled[act][dir];
932 if (graphic_info[graphic].anim_frames == 1)
933 graphic_info[graphic].anim_mode = ANIM_NONE;
934 if (graphic_info[crumbled].anim_frames == 1)
935 graphic_info[crumbled].anim_mode = ANIM_NONE;
945 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
946 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
948 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
949 element_info[i].token_name, i);
955 void InitElementSpecialGraphicInfo()
957 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
958 int num_property_mappings = getImageListPropertyMappingSize();
961 /* always start with reliable default values */
962 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
963 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
964 element_info[i].special_graphic[j] =
965 element_info[i].graphic[ACTION_DEFAULT];
967 /* initialize special element/graphic mapping from static configuration */
968 for (i = 0; element_to_special_graphic[i].element > -1; i++)
970 int element = element_to_special_graphic[i].element;
971 int special = element_to_special_graphic[i].special;
972 int graphic = element_to_special_graphic[i].graphic;
973 int base_graphic = el2baseimg(element);
974 boolean base_redefined =
975 getImageListEntryFromImageID(base_graphic)->redefined;
976 boolean special_redefined =
977 getImageListEntryFromImageID(graphic)->redefined;
979 /* if the base graphic ("emerald", for example) has been redefined,
980 but not the special graphic ("emerald.EDITOR", for example), do not
981 use an existing (in this case considered obsolete) special graphic
982 anymore, but use the automatically created (down-scaled) graphic */
983 if (base_redefined && !special_redefined)
986 element_info[element].special_graphic[special] = graphic;
989 /* initialize special element/graphic mapping from dynamic configuration */
990 for (i = 0; i < num_property_mappings; i++)
992 int element = property_mapping[i].base_index;
993 int special = property_mapping[i].ext3_index;
994 int graphic = property_mapping[i].artwork_index;
996 if (element >= MAX_NUM_ELEMENTS)
999 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
1000 element_info[element].special_graphic[special] = graphic;
1004 /* now set all undefined/invalid graphics to default */
1005 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1006 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
1007 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
1008 element_info[i].special_graphic[j] =
1009 element_info[i].graphic[ACTION_DEFAULT];
1013 static int get_element_from_token(char *token)
1017 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1018 if (strcmp(element_info[i].token_name, token) == 0)
1024 static int get_scaled_graphic_width(int graphic)
1026 int original_width = getOriginalImageWidthFromImageID(graphic);
1027 int scale_up_factor = graphic_info[graphic].scale_up_factor;
1029 return original_width * scale_up_factor;
1032 static int get_scaled_graphic_height(int graphic)
1034 int original_height = getOriginalImageHeightFromImageID(graphic);
1035 int scale_up_factor = graphic_info[graphic].scale_up_factor;
1037 return original_height * scale_up_factor;
1040 static void set_graphic_parameters(int graphic, int graphic_copy_from)
1042 struct FileInfo *image = getImageListEntryFromImageID(graphic_copy_from);
1043 char **parameter_raw = image->parameter;
1044 Bitmap *src_bitmap = getBitmapFromImageID(graphic_copy_from);
1045 int parameter[NUM_GFX_ARGS];
1046 int anim_frames_per_row = 1, anim_frames_per_col = 1;
1047 int anim_frames_per_line = 1;
1053 /* !!! NEW ARTWORK FALLBACK CODE !!! NEARLY UNTESTED !!! */
1054 /* if fallback to default artwork is done, also use the default parameters */
1055 if (image->fallback_to_default)
1058 printf("::: FALLBACK for %d\n", graphic_copy_from);
1061 parameter_raw = image->default_parameter;
1066 /* !!! ARTWORK FALLBACK CODE !!! NEARLY UNTESTED !!! */
1067 /* (better try to set a "fallback -> use default parameters" flag) */
1070 int len_source_filename = strlen(src_bitmap->source_filename);
1071 int len_default_filename = strlen(image->default_filename);
1072 int pos_basename = len_source_filename - len_default_filename;
1073 char *source_basename = &src_bitmap->source_filename[pos_basename];
1076 printf("::: src_bitmap->source_filename -> '%s'\n",
1077 src_bitmap->source_filename);
1078 printf("::: image->default_filename -> '%s'\n",
1079 image->default_filename);
1080 printf("::: image->filename -> '%s'\n",
1084 /* check if there was a fallback to the default artwork file */
1085 if (strcmp(image->filename, image->default_filename) != 0 &&
1086 pos_basename >= 0 &&
1087 strcmp(source_basename, image->default_filename) == 0)
1088 parameter_raw = image->default_parameter;
1093 /* get integer values from string parameters */
1094 for (i = 0; i < NUM_GFX_ARGS; i++)
1097 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
1098 image_config_suffix[i].type);
1100 if (image_config_suffix[i].type == TYPE_TOKEN)
1101 parameter[i] = get_element_from_token(parameter_raw[i]);
1104 graphic_info[graphic].bitmap = src_bitmap;
1106 /* start with reliable default values */
1107 graphic_info[graphic].src_x = 0;
1108 graphic_info[graphic].src_y = 0;
1109 graphic_info[graphic].width = TILEX;
1110 graphic_info[graphic].height = TILEY;
1111 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
1112 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
1113 graphic_info[graphic].offset2_x = 0; /* one or both of these values ... */
1114 graphic_info[graphic].offset2_y = 0; /* ... will be corrected later */
1115 graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */
1116 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
1117 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
1118 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
1119 graphic_info[graphic].scale_up_factor = 1; /* default: no scaling up */
1120 graphic_info[graphic].anim_delay_fixed = 0;
1121 graphic_info[graphic].anim_delay_random = 0;
1122 graphic_info[graphic].post_delay_fixed = 0;
1123 graphic_info[graphic].post_delay_random = 0;
1125 /* optional x and y tile position of animation frame sequence */
1126 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
1127 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
1128 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
1129 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
1131 /* optional x and y pixel position of animation frame sequence */
1132 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
1133 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
1134 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
1135 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
1137 /* optional width and height of each animation frame */
1138 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
1139 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
1140 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
1141 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
1143 /* optional zoom factor for scaling up the image to a larger size */
1144 if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1145 graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1146 if (graphic_info[graphic].scale_up_factor < 1)
1147 graphic_info[graphic].scale_up_factor = 1; /* no scaling */
1151 /* get final bitmap size (with scaling, but without small images) */
1152 int src_bitmap_width = get_scaled_graphic_width(graphic);
1153 int src_bitmap_height = get_scaled_graphic_height(graphic);
1155 anim_frames_per_row = src_bitmap_width / graphic_info[graphic].width;
1156 anim_frames_per_col = src_bitmap_height / graphic_info[graphic].height;
1159 /* correct x or y offset dependent of vertical or horizontal frame order */
1160 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
1162 graphic_info[graphic].offset_y =
1163 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1164 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
1165 anim_frames_per_line = anim_frames_per_col;
1167 else /* frames are ordered horizontally */
1169 graphic_info[graphic].offset_x =
1170 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1171 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
1172 anim_frames_per_line = anim_frames_per_row;
1175 /* optionally, the x and y offset of frames can be specified directly */
1176 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
1177 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
1178 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
1179 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
1181 /* optionally, moving animations may have separate start and end graphics */
1182 graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
1184 if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
1185 parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
1187 /* correct x or y offset2 dependent of vertical or horizontal frame order */
1188 if (parameter[GFX_ARG_2ND_VERTICAL]) /* frames are ordered vertically */
1189 graphic_info[graphic].offset2_y =
1190 (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1191 parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
1192 else /* frames are ordered horizontally */
1193 graphic_info[graphic].offset2_x =
1194 (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1195 parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
1197 /* optionally, the x and y offset of 2nd graphic can be specified directly */
1198 if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
1199 graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
1200 if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
1201 graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
1203 /* optionally, the second movement tile can be specified as start tile */
1204 if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
1205 graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
1207 /* automatically determine correct number of frames, if not defined */
1208 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1209 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
1210 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1211 graphic_info[graphic].anim_frames = anim_frames_per_row;
1212 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1213 graphic_info[graphic].anim_frames = anim_frames_per_col;
1215 graphic_info[graphic].anim_frames = 1;
1217 graphic_info[graphic].anim_frames_per_line =
1218 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1219 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1221 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
1222 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
1223 graphic_info[graphic].anim_delay = 1;
1225 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
1227 if (graphic_info[graphic].anim_frames == 1)
1228 graphic_info[graphic].anim_mode = ANIM_NONE;
1231 /* automatically determine correct start frame, if not defined */
1232 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1233 graphic_info[graphic].anim_start_frame = 0;
1234 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
1235 graphic_info[graphic].anim_start_frame =
1236 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1238 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
1240 /* animation synchronized with global frame counter, not move position */
1241 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1243 /* optional element for cloning crumble graphics */
1244 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1245 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1247 /* optional element for cloning digging graphics */
1248 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1249 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1251 /* optional border size for "crumbling" diggable graphics */
1252 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1253 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
1255 /* this is only used for player "boring" and "sleeping" actions */
1256 if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1257 graphic_info[graphic].anim_delay_fixed =
1258 parameter[GFX_ARG_ANIM_DELAY_FIXED];
1259 if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1260 graphic_info[graphic].anim_delay_random =
1261 parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1262 if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1263 graphic_info[graphic].post_delay_fixed =
1264 parameter[GFX_ARG_POST_DELAY_FIXED];
1265 if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1266 graphic_info[graphic].post_delay_random =
1267 parameter[GFX_ARG_POST_DELAY_RANDOM];
1269 /* this is only used for toon animations */
1270 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
1271 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
1273 /* this is only used for drawing font characters */
1274 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
1275 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
1277 /* this is only used for drawing envelope graphics */
1278 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1281 static void InitGraphicInfo()
1283 int fallback_graphic = IMG_CHAR_EXCLAM;
1284 int num_images = getImageListSize();
1287 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1288 static boolean clipmasks_initialized = FALSE;
1290 XGCValues clip_gc_values;
1291 unsigned long clip_gc_valuemask;
1292 GC copy_clipmask_gc = None;
1295 checked_free(graphic_info);
1297 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1300 printf("::: graphic_info: %d entries\n", num_images);
1303 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1304 if (clipmasks_initialized)
1306 for (i = 0; i < num_images; i++)
1308 if (graphic_info[i].clip_mask)
1309 XFreePixmap(display, graphic_info[i].clip_mask);
1310 if (graphic_info[i].clip_gc)
1311 XFreeGC(display, graphic_info[i].clip_gc);
1313 graphic_info[i].clip_mask = None;
1314 graphic_info[i].clip_gc = None;
1319 for (i = 0; i < num_images; i++)
1323 int first_frame, last_frame;
1324 int src_bitmap_width, src_bitmap_height;
1327 printf("::: image: '%s' [%d]\n", image->token, i);
1331 printf("::: image # %d: '%s' ['%s']\n",
1333 getTokenFromImageID(i));
1336 set_graphic_parameters(i, i);
1338 /* now check if no animation frames are outside of the loaded image */
1340 if (graphic_info[i].bitmap == NULL)
1341 continue; /* skip check for optional images that are undefined */
1343 /* get final bitmap size (with scaling, but without small images) */
1344 src_bitmap_width = get_scaled_graphic_width(i);
1345 src_bitmap_height = get_scaled_graphic_height(i);
1348 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1349 if (src_x < 0 || src_y < 0 ||
1350 src_x + TILEX > src_bitmap_width ||
1351 src_y + TILEY > src_bitmap_height)
1353 Error(ERR_RETURN_LINE, "-");
1354 Error(ERR_RETURN, "warning: error found in config file:");
1355 Error(ERR_RETURN, "- config file: '%s'",
1356 getImageConfigFilename());
1357 Error(ERR_RETURN, "- config token: '%s'",
1358 getTokenFromImageID(i));
1359 Error(ERR_RETURN, "- image file: '%s'",
1360 src_bitmap->source_filename);
1362 "error: first animation frame out of bounds (%d, %d)",
1364 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1367 Error(ERR_RETURN, "scale_up_factor == %d", scale_up_factor);
1370 if (i == fallback_graphic)
1371 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1373 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1374 Error(ERR_RETURN_LINE, "-");
1376 set_graphic_parameters(i, fallback_graphic);
1379 last_frame = graphic_info[i].anim_frames - 1;
1380 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1381 if (src_x < 0 || src_y < 0 ||
1382 src_x + TILEX > src_bitmap_width ||
1383 src_y + TILEY > src_bitmap_height)
1385 Error(ERR_RETURN_LINE, "-");
1386 Error(ERR_RETURN, "warning: error found in config file:");
1387 Error(ERR_RETURN, "- config file: '%s'",
1388 getImageConfigFilename());
1389 Error(ERR_RETURN, "- config token: '%s'",
1390 getTokenFromImageID(i));
1391 Error(ERR_RETURN, "- image file: '%s'",
1392 src_bitmap->source_filename);
1394 "error: last animation frame (%d) out of bounds (%d, %d)",
1395 last_frame, src_x, src_y);
1396 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1398 if (i == fallback_graphic)
1399 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1401 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1402 Error(ERR_RETURN_LINE, "-");
1404 set_graphic_parameters(i, fallback_graphic);
1407 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1408 /* currently we only need a tile clip mask from the first frame */
1409 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1411 if (copy_clipmask_gc == None)
1413 clip_gc_values.graphics_exposures = False;
1414 clip_gc_valuemask = GCGraphicsExposures;
1415 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1416 clip_gc_valuemask, &clip_gc_values);
1419 graphic_info[i].clip_mask =
1420 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1422 src_pixmap = src_bitmap->clip_mask;
1423 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1424 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1426 clip_gc_values.graphics_exposures = False;
1427 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1428 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1430 graphic_info[i].clip_gc =
1431 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1435 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1436 if (copy_clipmask_gc)
1437 XFreeGC(display, copy_clipmask_gc);
1439 clipmasks_initialized = TRUE;
1443 static void InitElementSoundInfo()
1445 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1446 int num_property_mappings = getSoundListPropertyMappingSize();
1449 /* set values to -1 to identify later as "uninitialized" values */
1450 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1451 for (act = 0; act < NUM_ACTIONS; act++)
1452 element_info[i].sound[act] = -1;
1454 /* initialize element/sound mapping from static configuration */
1455 for (i = 0; element_to_sound[i].element > -1; i++)
1457 int element = element_to_sound[i].element;
1458 int action = element_to_sound[i].action;
1459 int sound = element_to_sound[i].sound;
1460 boolean is_class = element_to_sound[i].is_class;
1463 action = ACTION_DEFAULT;
1466 element_info[element].sound[action] = sound;
1468 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1469 if (strcmp(element_info[j].class_name,
1470 element_info[element].class_name) == 0)
1471 element_info[j].sound[action] = sound;
1474 /* initialize element class/sound mapping from dynamic configuration */
1475 for (i = 0; i < num_property_mappings; i++)
1477 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1478 int action = property_mapping[i].ext1_index;
1479 int sound = property_mapping[i].artwork_index;
1481 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1485 action = ACTION_DEFAULT;
1487 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1488 if (strcmp(element_info[j].class_name,
1489 element_info[element_class].class_name) == 0)
1490 element_info[j].sound[action] = sound;
1493 /* initialize element/sound mapping from dynamic configuration */
1494 for (i = 0; i < num_property_mappings; i++)
1496 int element = property_mapping[i].base_index;
1497 int action = property_mapping[i].ext1_index;
1498 int sound = property_mapping[i].artwork_index;
1500 if (element >= MAX_NUM_ELEMENTS)
1504 action = ACTION_DEFAULT;
1506 element_info[element].sound[action] = sound;
1509 /* now set all '-1' values to element specific default values */
1510 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1512 for (act = 0; act < NUM_ACTIONS; act++)
1514 /* generic default action sound (defined by "[default]" directive) */
1515 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1517 /* look for special default action sound (classic game specific) */
1518 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1519 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1520 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1521 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1522 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1523 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1525 /* !!! there's no such thing as a "default action sound" !!! */
1527 /* look for element specific default sound (independent from action) */
1528 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1529 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1533 /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
1534 /* !!! make this better !!! */
1535 if (i == EL_EMPTY_SPACE)
1536 default_action_sound = element_info[EL_DEFAULT].sound[act];
1539 /* no sound for this specific action -- use default action sound */
1540 if (element_info[i].sound[act] == -1)
1541 element_info[i].sound[act] = default_action_sound;
1546 /* copy sound settings to some elements that are only stored in level file
1547 in native R'n'D levels, but are used by game engine in native EM levels */
1548 for (i = 0; copy_properties[i][0] != -1; i++)
1549 for (j = 1; j <= 4; j++)
1550 for (act = 0; act < NUM_ACTIONS; act++)
1551 element_info[copy_properties[i][j]].sound[act] =
1552 element_info[copy_properties[i][0]].sound[act];
1556 static void InitGameModeSoundInfo()
1560 /* set values to -1 to identify later as "uninitialized" values */
1561 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1564 /* initialize gamemode/sound mapping from static configuration */
1565 for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1567 int gamemode = gamemode_to_sound[i].gamemode;
1568 int sound = gamemode_to_sound[i].sound;
1571 gamemode = GAME_MODE_DEFAULT;
1573 menu.sound[gamemode] = sound;
1576 /* now set all '-1' values to levelset specific default values */
1577 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1578 if (menu.sound[i] == -1)
1579 menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1583 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1584 if (menu.sound[i] != -1)
1585 printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1589 static void set_sound_parameters(int sound, char **parameter_raw)
1591 int parameter[NUM_SND_ARGS];
1594 /* get integer values from string parameters */
1595 for (i = 0; i < NUM_SND_ARGS; i++)
1597 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1598 sound_config_suffix[i].type);
1600 /* explicit loop mode setting in configuration overrides default value */
1601 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1602 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1604 /* sound volume to change the original volume when loading the sound file */
1605 sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1607 /* sound priority to give certain sounds a higher or lower priority */
1608 sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1611 static void InitSoundInfo()
1614 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1615 int num_property_mappings = getSoundListPropertyMappingSize();
1617 int *sound_effect_properties;
1618 int num_sounds = getSoundListSize();
1621 checked_free(sound_info);
1623 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1624 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1626 /* initialize sound effect for all elements to "no sound" */
1627 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1628 for (j = 0; j < NUM_ACTIONS; j++)
1629 element_info[i].sound[j] = SND_UNDEFINED;
1631 for (i = 0; i < num_sounds; i++)
1633 struct FileInfo *sound = getSoundListEntry(i);
1634 int len_effect_text = strlen(sound->token);
1636 sound_effect_properties[i] = ACTION_OTHER;
1637 sound_info[i].loop = FALSE; /* default: play sound only once */
1640 printf("::: sound %d: '%s'\n", i, sound->token);
1643 /* determine all loop sounds and identify certain sound classes */
1645 for (j = 0; element_action_info[j].suffix; j++)
1647 int len_action_text = strlen(element_action_info[j].suffix);
1649 if (len_action_text < len_effect_text &&
1650 strcmp(&sound->token[len_effect_text - len_action_text],
1651 element_action_info[j].suffix) == 0)
1653 sound_effect_properties[i] = element_action_info[j].value;
1654 sound_info[i].loop = element_action_info[j].is_loop_sound;
1661 if (strcmp(sound->token, "custom_42") == 0)
1662 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1665 /* associate elements and some selected sound actions */
1667 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1669 if (element_info[j].class_name)
1671 int len_class_text = strlen(element_info[j].class_name);
1673 if (len_class_text + 1 < len_effect_text &&
1674 strncmp(sound->token,
1675 element_info[j].class_name, len_class_text) == 0 &&
1676 sound->token[len_class_text] == '.')
1678 int sound_action_value = sound_effect_properties[i];
1680 element_info[j].sound[sound_action_value] = i;
1685 set_sound_parameters(i, sound->parameter);
1688 free(sound_effect_properties);
1691 /* !!! MOVED TO "InitElementSoundInfo()" !!! */
1692 /* !!! everything defined here gets overwritten there !!! */
1694 /* copy sound settings to some elements that are only stored in level file
1695 in native R'n'D levels, but are used by game engine in native EM levels */
1696 for (i = 0; i < NUM_ACTIONS; i++)
1697 for (j = 0; copy_properties[j][0] != -1; j++)
1698 for (k = 1; k <= 4; k++)
1699 element_info[copy_properties[j][k]].sound[i] =
1700 element_info[copy_properties[j][0]].sound[i];
1702 printf("::: bug -> %d\n", element_info[EL_BUG].sound[ACTION_MOVING]);
1703 printf("::: bug_r -> %d\n", element_info[EL_BUG_RIGHT].sound[ACTION_MOVING]);
1707 /* !!! now handled in InitElementSoundInfo() !!! */
1708 /* initialize element/sound mapping from dynamic configuration */
1709 for (i = 0; i < num_property_mappings; i++)
1711 int element = property_mapping[i].base_index;
1712 int action = property_mapping[i].ext1_index;
1713 int sound = property_mapping[i].artwork_index;
1716 action = ACTION_DEFAULT;
1718 printf("::: %d: %d, %d, %d ['%s']\n",
1719 i, element, action, sound, element_info[element].token_name);
1721 element_info[element].sound[action] = sound;
1728 int element = EL_CUSTOM_11;
1731 while (element_action_info[j].suffix)
1733 printf("element %d, sound action '%s' == %d\n",
1734 element, element_action_info[j].suffix,
1735 element_info[element].sound[j]);
1740 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1746 int element = EL_SAND;
1747 int sound_action = ACTION_DIGGING;
1750 while (element_action_info[j].suffix)
1752 if (element_action_info[j].value == sound_action)
1753 printf("element %d, sound action '%s' == %d\n",
1754 element, element_action_info[j].suffix,
1755 element_info[element].sound[sound_action]);
1762 static void InitGameModeMusicInfo()
1764 struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1765 int num_property_mappings = getMusicListPropertyMappingSize();
1766 int default_levelset_music = -1;
1769 /* set values to -1 to identify later as "uninitialized" values */
1770 for (i = 0; i < MAX_LEVELS; i++)
1771 levelset.music[i] = -1;
1772 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1775 /* initialize gamemode/music mapping from static configuration */
1776 for (i = 0; gamemode_to_music[i].music > -1; i++)
1778 int gamemode = gamemode_to_music[i].gamemode;
1779 int music = gamemode_to_music[i].music;
1782 printf("::: gamemode == %d, music == %d\n", gamemode, music);
1786 gamemode = GAME_MODE_DEFAULT;
1788 menu.music[gamemode] = music;
1791 /* initialize gamemode/music mapping from dynamic configuration */
1792 for (i = 0; i < num_property_mappings; i++)
1794 int prefix = property_mapping[i].base_index;
1795 int gamemode = property_mapping[i].ext1_index;
1796 int level = property_mapping[i].ext2_index;
1797 int music = property_mapping[i].artwork_index;
1800 printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1801 prefix, gamemode, level, music);
1804 if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1808 gamemode = GAME_MODE_DEFAULT;
1810 /* level specific music only allowed for in-game music */
1811 if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1812 gamemode = GAME_MODE_PLAYING;
1817 default_levelset_music = music;
1820 if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1821 levelset.music[level] = music;
1822 if (gamemode != GAME_MODE_PLAYING)
1823 menu.music[gamemode] = music;
1826 /* now set all '-1' values to menu specific default values */
1827 /* (undefined values of "levelset.music[]" might stay at "-1" to
1828 allow dynamic selection of music files from music directory!) */
1829 for (i = 0; i < MAX_LEVELS; i++)
1830 if (levelset.music[i] == -1)
1831 levelset.music[i] = default_levelset_music;
1832 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1833 if (menu.music[i] == -1)
1834 menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1838 for (i = 0; i < MAX_LEVELS; i++)
1839 if (levelset.music[i] != -1)
1840 printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1841 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1842 if (menu.music[i] != -1)
1843 printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1847 static void set_music_parameters(int music, char **parameter_raw)
1849 int parameter[NUM_MUS_ARGS];
1852 /* get integer values from string parameters */
1853 for (i = 0; i < NUM_MUS_ARGS; i++)
1855 get_parameter_value(music_config_suffix[i].token, parameter_raw[i],
1856 music_config_suffix[i].type);
1858 /* explicit loop mode setting in configuration overrides default value */
1859 if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1860 music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
1863 static void InitMusicInfo()
1865 int num_music = getMusicListSize();
1868 checked_free(music_info);
1870 music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
1872 for (i = 0; i < num_music; i++)
1874 struct FileInfo *music = getMusicListEntry(i);
1875 int len_music_text = strlen(music->token);
1877 music_info[i].loop = TRUE; /* default: play music in loop mode */
1879 /* determine all loop music */
1881 for (j = 0; music_prefix_info[j].prefix; j++)
1883 int len_prefix_text = strlen(music_prefix_info[j].prefix);
1885 if (len_prefix_text < len_music_text &&
1886 strncmp(music->token,
1887 music_prefix_info[j].prefix, len_prefix_text) == 0)
1889 music_info[i].loop = music_prefix_info[j].is_loop_music;
1895 set_music_parameters(i, music->parameter);
1899 static void ReinitializeGraphics()
1901 InitGraphicInfo(); /* graphic properties mapping */
1902 InitElementGraphicInfo(); /* element game graphic mapping */
1903 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1905 InitElementSmallImages(); /* scale images to all needed sizes */
1906 InitFontGraphicInfo(); /* initialize text drawing functions */
1908 InitGraphicInfo_EM(); /* graphic mapping for EM engine */
1910 SetMainBackgroundImage(IMG_BACKGROUND);
1911 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1917 static void ReinitializeSounds()
1919 InitSoundInfo(); /* sound properties mapping */
1920 InitElementSoundInfo(); /* element game sound mapping */
1921 InitGameModeSoundInfo(); /* game mode sound mapping */
1923 InitPlayLevelSound(); /* internal game sound settings */
1926 static void ReinitializeMusic()
1928 InitMusicInfo(); /* music properties mapping */
1929 InitGameModeMusicInfo(); /* game mode music mapping */
1932 static int get_special_property_bit(int element, int property_bit_nr)
1934 struct PropertyBitInfo
1940 static struct PropertyBitInfo pb_can_move_into_acid[] =
1942 /* the player may be able fall into acid when gravity is activated */
1947 { EL_SP_MURPHY, 0 },
1948 { EL_SOKOBAN_FIELD_PLAYER, 0 },
1950 /* all element that can move may be able to also move into acid */
1953 { EL_BUG_RIGHT, 1 },
1956 { EL_SPACESHIP, 2 },
1957 { EL_SPACESHIP_LEFT, 2 },
1958 { EL_SPACESHIP_RIGHT, 2 },
1959 { EL_SPACESHIP_UP, 2 },
1960 { EL_SPACESHIP_DOWN, 2 },
1961 { EL_BD_BUTTERFLY, 3 },
1962 { EL_BD_BUTTERFLY_LEFT, 3 },
1963 { EL_BD_BUTTERFLY_RIGHT, 3 },
1964 { EL_BD_BUTTERFLY_UP, 3 },
1965 { EL_BD_BUTTERFLY_DOWN, 3 },
1966 { EL_BD_FIREFLY, 4 },
1967 { EL_BD_FIREFLY_LEFT, 4 },
1968 { EL_BD_FIREFLY_RIGHT, 4 },
1969 { EL_BD_FIREFLY_UP, 4 },
1970 { EL_BD_FIREFLY_DOWN, 4 },
1972 { EL_DARK_YAMYAM, 6 },
1975 { EL_PACMAN_LEFT, 8 },
1976 { EL_PACMAN_RIGHT, 8 },
1977 { EL_PACMAN_UP, 8 },
1978 { EL_PACMAN_DOWN, 8 },
1980 { EL_MOLE_LEFT, 9 },
1981 { EL_MOLE_RIGHT, 9 },
1983 { EL_MOLE_DOWN, 9 },
1987 { EL_SATELLITE, 13 },
1988 { EL_SP_SNIKSNAK, 14 },
1989 { EL_SP_ELECTRON, 15 },
1996 static struct PropertyBitInfo pb_dont_collide_with[] =
1998 { EL_SP_SNIKSNAK, 0 },
1999 { EL_SP_ELECTRON, 1 },
2007 struct PropertyBitInfo *pb_info;
2010 { EP_CAN_MOVE_INTO_ACID, pb_can_move_into_acid },
2011 { EP_DONT_COLLIDE_WITH, pb_dont_collide_with },
2016 struct PropertyBitInfo *pb_info = NULL;
2019 for (i = 0; pb_definition[i].bit_nr != -1; i++)
2020 if (pb_definition[i].bit_nr == property_bit_nr)
2021 pb_info = pb_definition[i].pb_info;
2023 if (pb_info == NULL)
2026 for (i = 0; pb_info[i].element != -1; i++)
2027 if (pb_info[i].element == element)
2028 return pb_info[i].bit_nr;
2034 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
2035 boolean property_value)
2037 int bit_nr = get_special_property_bit(element, property_bit_nr);
2042 *bitfield |= (1 << bit_nr);
2044 *bitfield &= ~(1 << bit_nr);
2048 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
2050 int bit_nr = get_special_property_bit(element, property_bit_nr);
2053 return ((*bitfield & (1 << bit_nr)) != 0);
2060 void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set)
2062 int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
2066 level->can_move_into_acid_bits &= ~(1 << bit_nr);
2069 level->can_move_into_acid_bits |= (1 << bit_nr);
2073 boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
2075 int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
2078 return ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0);
2084 void InitElementPropertiesStatic()
2086 static int ep_diggable[] =
2091 EL_SP_BUGGY_BASE_ACTIVATING,
2094 EL_INVISIBLE_SAND_ACTIVE,
2097 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
2098 /* (if amoeba can grow into anything diggable, maybe keep these out) */
2102 EL_SP_BUGGY_BASE_ACTIVE,
2108 static int ep_collectible_only[] =
2129 EL_DYNABOMB_INCREASE_NUMBER,
2130 EL_DYNABOMB_INCREASE_SIZE,
2131 EL_DYNABOMB_INCREASE_POWER,
2150 static int ep_dont_run_into[] =
2152 /* same elements as in 'ep_dont_touch' */
2158 /* same elements as in 'ep_dont_collide_with' */
2170 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
2174 EL_SP_BUGGY_BASE_ACTIVE,
2180 static int ep_dont_collide_with[] =
2182 /* same elements as in 'ep_dont_touch' */
2198 static int ep_dont_touch[] =
2207 static int ep_indestructible[] =
2211 EL_ACID_POOL_TOPLEFT,
2212 EL_ACID_POOL_TOPRIGHT,
2213 EL_ACID_POOL_BOTTOMLEFT,
2214 EL_ACID_POOL_BOTTOM,
2215 EL_ACID_POOL_BOTTOMRIGHT,
2216 EL_SP_HARDWARE_GRAY,
2217 EL_SP_HARDWARE_GREEN,
2218 EL_SP_HARDWARE_BLUE,
2220 EL_SP_HARDWARE_YELLOW,
2221 EL_SP_HARDWARE_BASE_1,
2222 EL_SP_HARDWARE_BASE_2,
2223 EL_SP_HARDWARE_BASE_3,
2224 EL_SP_HARDWARE_BASE_4,
2225 EL_SP_HARDWARE_BASE_5,
2226 EL_SP_HARDWARE_BASE_6,
2227 EL_INVISIBLE_STEELWALL,
2228 EL_INVISIBLE_STEELWALL_ACTIVE,
2229 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2230 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2231 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2232 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2233 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2234 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2235 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2236 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2237 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2238 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2239 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2240 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2242 EL_LIGHT_SWITCH_ACTIVE,
2243 EL_SIGN_EXCLAMATION,
2244 EL_SIGN_RADIOACTIVITY,
2255 EL_STEELWALL_SLIPPERY,
2286 EL_SWITCHGATE_OPENING,
2287 EL_SWITCHGATE_CLOSED,
2288 EL_SWITCHGATE_CLOSING,
2290 EL_SWITCHGATE_SWITCH_UP,
2291 EL_SWITCHGATE_SWITCH_DOWN,
2294 EL_TIMEGATE_OPENING,
2296 EL_TIMEGATE_CLOSING,
2299 EL_TIMEGATE_SWITCH_ACTIVE,
2304 EL_TUBE_VERTICAL_LEFT,
2305 EL_TUBE_VERTICAL_RIGHT,
2306 EL_TUBE_HORIZONTAL_UP,
2307 EL_TUBE_HORIZONTAL_DOWN,
2315 static int ep_slippery[] =
2329 EL_ROBOT_WHEEL_ACTIVE,
2335 EL_ACID_POOL_TOPLEFT,
2336 EL_ACID_POOL_TOPRIGHT,
2346 EL_STEELWALL_SLIPPERY,
2349 EL_EMC_WALL_SLIPPERY_1,
2350 EL_EMC_WALL_SLIPPERY_2,
2351 EL_EMC_WALL_SLIPPERY_3,
2352 EL_EMC_WALL_SLIPPERY_4,
2356 static int ep_can_change[] =
2361 static int ep_can_move[] =
2363 /* same elements as in 'pb_can_move_into_acid' */
2385 static int ep_can_fall[] =
2400 EL_BD_MAGIC_WALL_FULL,
2413 static int ep_can_smash_player[] =
2438 static int ep_can_smash_enemies[] =
2446 static int ep_can_smash_everything[] =
2454 static int ep_explodes_by_fire[] =
2456 /* same elements as in 'ep_explodes_impact' */
2461 /* same elements as in 'ep_explodes_smashed' */
2470 EL_DYNABOMB_PLAYER_1_ACTIVE,
2471 EL_DYNABOMB_PLAYER_2_ACTIVE,
2472 EL_DYNABOMB_PLAYER_3_ACTIVE,
2473 EL_DYNABOMB_PLAYER_4_ACTIVE,
2474 EL_DYNABOMB_INCREASE_NUMBER,
2475 EL_DYNABOMB_INCREASE_SIZE,
2476 EL_DYNABOMB_INCREASE_POWER,
2477 EL_SP_DISK_RED_ACTIVE,
2490 static int ep_explodes_smashed[] =
2492 /* same elements as in 'ep_explodes_impact' */
2505 static int ep_explodes_impact[] =
2513 static int ep_walkable_over[] =
2517 EL_SOKOBAN_FIELD_EMPTY,
2533 #if 0 /* USE_GRAVITY_BUGFIX_OLD */
2534 EL_PLAYER_IS_LEAVING, /* needed for gravity + "block last field" */
2540 static int ep_walkable_inside[] =
2545 EL_TUBE_VERTICAL_LEFT,
2546 EL_TUBE_VERTICAL_RIGHT,
2547 EL_TUBE_HORIZONTAL_UP,
2548 EL_TUBE_HORIZONTAL_DOWN,
2556 static int ep_walkable_under[] =
2561 static int ep_passable_over[] =
2584 static int ep_passable_inside[] =
2590 EL_SP_PORT_HORIZONTAL,
2591 EL_SP_PORT_VERTICAL,
2593 EL_SP_GRAVITY_PORT_LEFT,
2594 EL_SP_GRAVITY_PORT_RIGHT,
2595 EL_SP_GRAVITY_PORT_UP,
2596 EL_SP_GRAVITY_PORT_DOWN,
2597 EL_SP_GRAVITY_ON_PORT_LEFT,
2598 EL_SP_GRAVITY_ON_PORT_RIGHT,
2599 EL_SP_GRAVITY_ON_PORT_UP,
2600 EL_SP_GRAVITY_ON_PORT_DOWN,
2601 EL_SP_GRAVITY_OFF_PORT_LEFT,
2602 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2603 EL_SP_GRAVITY_OFF_PORT_UP,
2604 EL_SP_GRAVITY_OFF_PORT_DOWN,
2608 static int ep_passable_under[] =
2613 static int ep_droppable[] =
2618 static int ep_explodes_1x1_old[] =
2623 static int ep_pushable[] =
2635 EL_SOKOBAN_FIELD_FULL,
2643 static int ep_explodes_cross_old[] =
2648 static int ep_protected[] =
2650 /* same elements as in 'ep_walkable_inside' */
2654 EL_TUBE_VERTICAL_LEFT,
2655 EL_TUBE_VERTICAL_RIGHT,
2656 EL_TUBE_HORIZONTAL_UP,
2657 EL_TUBE_HORIZONTAL_DOWN,
2663 /* same elements as in 'ep_passable_over' */
2683 /* same elements as in 'ep_passable_inside' */
2688 EL_SP_PORT_HORIZONTAL,
2689 EL_SP_PORT_VERTICAL,
2691 EL_SP_GRAVITY_PORT_LEFT,
2692 EL_SP_GRAVITY_PORT_RIGHT,
2693 EL_SP_GRAVITY_PORT_UP,
2694 EL_SP_GRAVITY_PORT_DOWN,
2695 EL_SP_GRAVITY_ON_PORT_LEFT,
2696 EL_SP_GRAVITY_ON_PORT_RIGHT,
2697 EL_SP_GRAVITY_ON_PORT_UP,
2698 EL_SP_GRAVITY_ON_PORT_DOWN,
2699 EL_SP_GRAVITY_OFF_PORT_LEFT,
2700 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2701 EL_SP_GRAVITY_OFF_PORT_UP,
2702 EL_SP_GRAVITY_OFF_PORT_DOWN,
2706 static int ep_throwable[] =
2711 static int ep_can_explode[] =
2713 /* same elements as in 'ep_explodes_impact' */
2718 /* same elements as in 'ep_explodes_smashed' */
2724 /* elements that can explode by explosion or by dragonfire */
2727 EL_DYNABOMB_PLAYER_1_ACTIVE,
2728 EL_DYNABOMB_PLAYER_2_ACTIVE,
2729 EL_DYNABOMB_PLAYER_3_ACTIVE,
2730 EL_DYNABOMB_PLAYER_4_ACTIVE,
2731 EL_DYNABOMB_INCREASE_NUMBER,
2732 EL_DYNABOMB_INCREASE_SIZE,
2733 EL_DYNABOMB_INCREASE_POWER,
2734 EL_SP_DISK_RED_ACTIVE,
2742 /* elements that can explode only by explosion */
2747 static int ep_gravity_reachable[] =
2753 EL_INVISIBLE_SAND_ACTIVE,
2758 EL_SP_PORT_HORIZONTAL,
2759 EL_SP_PORT_VERTICAL,
2761 EL_SP_GRAVITY_PORT_LEFT,
2762 EL_SP_GRAVITY_PORT_RIGHT,
2763 EL_SP_GRAVITY_PORT_UP,
2764 EL_SP_GRAVITY_PORT_DOWN,
2765 EL_SP_GRAVITY_ON_PORT_LEFT,
2766 EL_SP_GRAVITY_ON_PORT_RIGHT,
2767 EL_SP_GRAVITY_ON_PORT_UP,
2768 EL_SP_GRAVITY_ON_PORT_DOWN,
2769 EL_SP_GRAVITY_OFF_PORT_LEFT,
2770 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2771 EL_SP_GRAVITY_OFF_PORT_UP,
2772 EL_SP_GRAVITY_OFF_PORT_DOWN,
2777 static int ep_player[] =
2784 EL_SOKOBAN_FIELD_PLAYER,
2789 static int ep_can_pass_magic_wall[] =
2802 static int ep_switchable[] =
2806 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2807 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2808 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2809 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2810 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2811 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2812 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2813 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2814 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2815 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2816 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2817 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2818 EL_SWITCHGATE_SWITCH_UP,
2819 EL_SWITCHGATE_SWITCH_DOWN,
2821 EL_LIGHT_SWITCH_ACTIVE,
2823 EL_BALLOON_SWITCH_LEFT,
2824 EL_BALLOON_SWITCH_RIGHT,
2825 EL_BALLOON_SWITCH_UP,
2826 EL_BALLOON_SWITCH_DOWN,
2827 EL_BALLOON_SWITCH_ANY,
2830 EL_EMC_MAGIC_BALL_SWITCH,
2834 static int ep_bd_element[] =
2867 static int ep_sp_element[] =
2869 /* should always be valid */
2872 /* standard classic Supaplex elements */
2879 EL_SP_HARDWARE_GRAY,
2887 EL_SP_GRAVITY_PORT_RIGHT,
2888 EL_SP_GRAVITY_PORT_DOWN,
2889 EL_SP_GRAVITY_PORT_LEFT,
2890 EL_SP_GRAVITY_PORT_UP,
2895 EL_SP_PORT_VERTICAL,
2896 EL_SP_PORT_HORIZONTAL,
2902 EL_SP_HARDWARE_BASE_1,
2903 EL_SP_HARDWARE_GREEN,
2904 EL_SP_HARDWARE_BLUE,
2906 EL_SP_HARDWARE_YELLOW,
2907 EL_SP_HARDWARE_BASE_2,
2908 EL_SP_HARDWARE_BASE_3,
2909 EL_SP_HARDWARE_BASE_4,
2910 EL_SP_HARDWARE_BASE_5,
2911 EL_SP_HARDWARE_BASE_6,
2915 /* additional elements that appeared in newer Supaplex levels */
2918 /* additional gravity port elements (not switching, but setting gravity) */
2919 EL_SP_GRAVITY_ON_PORT_LEFT,
2920 EL_SP_GRAVITY_ON_PORT_RIGHT,
2921 EL_SP_GRAVITY_ON_PORT_UP,
2922 EL_SP_GRAVITY_ON_PORT_DOWN,
2923 EL_SP_GRAVITY_OFF_PORT_LEFT,
2924 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2925 EL_SP_GRAVITY_OFF_PORT_UP,
2926 EL_SP_GRAVITY_OFF_PORT_DOWN,
2928 /* more than one Murphy in a level results in an inactive clone */
2931 /* runtime Supaplex elements */
2932 EL_SP_DISK_RED_ACTIVE,
2933 EL_SP_TERMINAL_ACTIVE,
2934 EL_SP_BUGGY_BASE_ACTIVATING,
2935 EL_SP_BUGGY_BASE_ACTIVE,
2941 static int ep_sb_element[] =
2946 EL_SOKOBAN_FIELD_EMPTY,
2947 EL_SOKOBAN_FIELD_FULL,
2948 EL_SOKOBAN_FIELD_PLAYER,
2953 EL_INVISIBLE_STEELWALL,
2957 static int ep_gem[] =
2968 static int ep_food_dark_yamyam[] =
2995 static int ep_food_penguin[] =
3008 static int ep_food_pig[] =
3019 static int ep_historic_wall[] =
3044 EL_EXPANDABLE_WALL_HORIZONTAL,
3045 EL_EXPANDABLE_WALL_VERTICAL,
3046 EL_EXPANDABLE_WALL_ANY,
3047 EL_EXPANDABLE_WALL_GROWING,
3054 EL_SP_HARDWARE_GRAY,
3055 EL_SP_HARDWARE_GREEN,
3056 EL_SP_HARDWARE_BLUE,
3058 EL_SP_HARDWARE_YELLOW,
3059 EL_SP_HARDWARE_BASE_1,
3060 EL_SP_HARDWARE_BASE_2,
3061 EL_SP_HARDWARE_BASE_3,
3062 EL_SP_HARDWARE_BASE_4,
3063 EL_SP_HARDWARE_BASE_5,
3064 EL_SP_HARDWARE_BASE_6,
3066 EL_SP_TERMINAL_ACTIVE,
3069 EL_INVISIBLE_STEELWALL,
3070 EL_INVISIBLE_STEELWALL_ACTIVE,
3072 EL_INVISIBLE_WALL_ACTIVE,
3073 EL_STEELWALL_SLIPPERY,
3089 static int ep_historic_solid[] =
3093 EL_EXPANDABLE_WALL_HORIZONTAL,
3094 EL_EXPANDABLE_WALL_VERTICAL,
3095 EL_EXPANDABLE_WALL_ANY,
3108 EL_QUICKSAND_FILLING,
3109 EL_QUICKSAND_EMPTYING,
3111 EL_MAGIC_WALL_ACTIVE,
3112 EL_MAGIC_WALL_EMPTYING,
3113 EL_MAGIC_WALL_FILLING,
3117 EL_BD_MAGIC_WALL_ACTIVE,
3118 EL_BD_MAGIC_WALL_EMPTYING,
3119 EL_BD_MAGIC_WALL_FULL,
3120 EL_BD_MAGIC_WALL_FILLING,
3121 EL_BD_MAGIC_WALL_DEAD,
3130 EL_SP_TERMINAL_ACTIVE,
3134 EL_INVISIBLE_WALL_ACTIVE,
3135 EL_SWITCHGATE_SWITCH_UP,
3136 EL_SWITCHGATE_SWITCH_DOWN,
3138 EL_TIMEGATE_SWITCH_ACTIVE,
3150 /* the following elements are a direct copy of "indestructible" elements,
3151 except "EL_ACID", which is "indestructible", but not "solid"! */
3156 EL_ACID_POOL_TOPLEFT,
3157 EL_ACID_POOL_TOPRIGHT,
3158 EL_ACID_POOL_BOTTOMLEFT,
3159 EL_ACID_POOL_BOTTOM,
3160 EL_ACID_POOL_BOTTOMRIGHT,
3161 EL_SP_HARDWARE_GRAY,
3162 EL_SP_HARDWARE_GREEN,
3163 EL_SP_HARDWARE_BLUE,
3165 EL_SP_HARDWARE_YELLOW,
3166 EL_SP_HARDWARE_BASE_1,
3167 EL_SP_HARDWARE_BASE_2,
3168 EL_SP_HARDWARE_BASE_3,
3169 EL_SP_HARDWARE_BASE_4,
3170 EL_SP_HARDWARE_BASE_5,
3171 EL_SP_HARDWARE_BASE_6,
3172 EL_INVISIBLE_STEELWALL,
3173 EL_INVISIBLE_STEELWALL_ACTIVE,
3174 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3175 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3176 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3177 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3178 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3179 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3180 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3181 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3182 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3183 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3184 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3185 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3187 EL_LIGHT_SWITCH_ACTIVE,
3188 EL_SIGN_EXCLAMATION,
3189 EL_SIGN_RADIOACTIVITY,
3200 EL_STEELWALL_SLIPPERY,
3223 EL_SWITCHGATE_OPENING,
3224 EL_SWITCHGATE_CLOSED,
3225 EL_SWITCHGATE_CLOSING,
3227 EL_TIMEGATE_OPENING,
3229 EL_TIMEGATE_CLOSING,
3233 EL_TUBE_VERTICAL_LEFT,
3234 EL_TUBE_VERTICAL_RIGHT,
3235 EL_TUBE_HORIZONTAL_UP,
3236 EL_TUBE_HORIZONTAL_DOWN,
3244 static int ep_classic_enemy[] =
3260 static int ep_belt[] =
3262 EL_CONVEYOR_BELT_1_LEFT,
3263 EL_CONVEYOR_BELT_1_MIDDLE,
3264 EL_CONVEYOR_BELT_1_RIGHT,
3265 EL_CONVEYOR_BELT_2_LEFT,
3266 EL_CONVEYOR_BELT_2_MIDDLE,
3267 EL_CONVEYOR_BELT_2_RIGHT,
3268 EL_CONVEYOR_BELT_3_LEFT,
3269 EL_CONVEYOR_BELT_3_MIDDLE,
3270 EL_CONVEYOR_BELT_3_RIGHT,
3271 EL_CONVEYOR_BELT_4_LEFT,
3272 EL_CONVEYOR_BELT_4_MIDDLE,
3273 EL_CONVEYOR_BELT_4_RIGHT,
3277 static int ep_belt_active[] =
3279 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3280 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3281 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3282 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3283 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3284 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3285 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3286 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3287 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3288 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3289 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3290 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3294 static int ep_belt_switch[] =
3296 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3297 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3298 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3299 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3300 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3301 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3302 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3303 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3304 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3305 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3306 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3307 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3311 static int ep_tube[] =
3318 EL_TUBE_HORIZONTAL_UP,
3319 EL_TUBE_HORIZONTAL_DOWN,
3321 EL_TUBE_VERTICAL_LEFT,
3322 EL_TUBE_VERTICAL_RIGHT,
3327 static int ep_keygate[] =
3356 static int ep_amoeboid[] =
3366 static int ep_amoebalive[] =
3375 static int ep_has_content[] =
3385 static int ep_can_turn_each_move[] =
3387 /* !!! do something with this one !!! */
3391 static int ep_can_grow[] =
3403 static int ep_active_bomb[] =
3406 EL_DYNABOMB_PLAYER_1_ACTIVE,
3407 EL_DYNABOMB_PLAYER_2_ACTIVE,
3408 EL_DYNABOMB_PLAYER_3_ACTIVE,
3409 EL_DYNABOMB_PLAYER_4_ACTIVE,
3410 EL_SP_DISK_RED_ACTIVE,
3414 static int ep_inactive[] =
3463 EL_INVISIBLE_STEELWALL,
3471 EL_WALL_EMERALD_YELLOW,
3472 EL_DYNABOMB_INCREASE_NUMBER,
3473 EL_DYNABOMB_INCREASE_SIZE,
3474 EL_DYNABOMB_INCREASE_POWER,
3478 EL_SOKOBAN_FIELD_EMPTY,
3479 EL_SOKOBAN_FIELD_FULL,
3480 EL_WALL_EMERALD_RED,
3481 EL_WALL_EMERALD_PURPLE,
3482 EL_ACID_POOL_TOPLEFT,
3483 EL_ACID_POOL_TOPRIGHT,
3484 EL_ACID_POOL_BOTTOMLEFT,
3485 EL_ACID_POOL_BOTTOM,
3486 EL_ACID_POOL_BOTTOMRIGHT,
3490 EL_BD_MAGIC_WALL_DEAD,
3491 EL_AMOEBA_TO_DIAMOND,
3499 EL_SP_GRAVITY_PORT_RIGHT,
3500 EL_SP_GRAVITY_PORT_DOWN,
3501 EL_SP_GRAVITY_PORT_LEFT,
3502 EL_SP_GRAVITY_PORT_UP,
3503 EL_SP_PORT_HORIZONTAL,
3504 EL_SP_PORT_VERTICAL,
3515 EL_SP_HARDWARE_GRAY,
3516 EL_SP_HARDWARE_GREEN,
3517 EL_SP_HARDWARE_BLUE,
3519 EL_SP_HARDWARE_YELLOW,
3520 EL_SP_HARDWARE_BASE_1,
3521 EL_SP_HARDWARE_BASE_2,
3522 EL_SP_HARDWARE_BASE_3,
3523 EL_SP_HARDWARE_BASE_4,
3524 EL_SP_HARDWARE_BASE_5,
3525 EL_SP_HARDWARE_BASE_6,
3526 EL_SP_GRAVITY_ON_PORT_LEFT,
3527 EL_SP_GRAVITY_ON_PORT_RIGHT,
3528 EL_SP_GRAVITY_ON_PORT_UP,
3529 EL_SP_GRAVITY_ON_PORT_DOWN,
3530 EL_SP_GRAVITY_OFF_PORT_LEFT,
3531 EL_SP_GRAVITY_OFF_PORT_RIGHT,
3532 EL_SP_GRAVITY_OFF_PORT_UP,
3533 EL_SP_GRAVITY_OFF_PORT_DOWN,
3534 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3535 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3536 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3537 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3538 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3539 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3540 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3541 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3542 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3543 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3544 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3545 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3546 EL_SIGN_EXCLAMATION,
3547 EL_SIGN_RADIOACTIVITY,
3558 EL_STEELWALL_SLIPPERY,
3563 EL_EMC_WALL_SLIPPERY_1,
3564 EL_EMC_WALL_SLIPPERY_2,
3565 EL_EMC_WALL_SLIPPERY_3,
3566 EL_EMC_WALL_SLIPPERY_4,
3586 static int ep_em_slippery_wall[] =
3591 static int ep_gfx_crumbled[] =
3604 } element_properties[] =
3606 { ep_diggable, EP_DIGGABLE },
3607 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
3608 { ep_dont_run_into, EP_DONT_RUN_INTO },
3609 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
3610 { ep_dont_touch, EP_DONT_TOUCH },
3611 { ep_indestructible, EP_INDESTRUCTIBLE },
3612 { ep_slippery, EP_SLIPPERY },
3613 { ep_can_change, EP_CAN_CHANGE },
3614 { ep_can_move, EP_CAN_MOVE },
3615 { ep_can_fall, EP_CAN_FALL },
3616 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
3617 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
3618 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
3619 { ep_explodes_by_fire, EP_EXPLODES_BY_FIRE },
3620 { ep_explodes_smashed, EP_EXPLODES_SMASHED },
3621 { ep_explodes_impact, EP_EXPLODES_IMPACT },
3622 { ep_walkable_over, EP_WALKABLE_OVER },
3623 { ep_walkable_inside, EP_WALKABLE_INSIDE },
3624 { ep_walkable_under, EP_WALKABLE_UNDER },
3625 { ep_passable_over, EP_PASSABLE_OVER },
3626 { ep_passable_inside, EP_PASSABLE_INSIDE },
3627 { ep_passable_under, EP_PASSABLE_UNDER },
3628 { ep_droppable, EP_DROPPABLE },
3629 { ep_explodes_1x1_old, EP_EXPLODES_1X1_OLD },
3630 { ep_pushable, EP_PUSHABLE },
3631 { ep_explodes_cross_old, EP_EXPLODES_CROSS_OLD },
3632 { ep_protected, EP_PROTECTED },
3633 { ep_throwable, EP_THROWABLE },
3634 { ep_can_explode, EP_CAN_EXPLODE },
3635 { ep_gravity_reachable, EP_GRAVITY_REACHABLE },
3637 { ep_player, EP_PLAYER },
3638 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
3639 { ep_switchable, EP_SWITCHABLE },
3640 { ep_bd_element, EP_BD_ELEMENT },
3641 { ep_sp_element, EP_SP_ELEMENT },
3642 { ep_sb_element, EP_SB_ELEMENT },
3644 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
3645 { ep_food_penguin, EP_FOOD_PENGUIN },
3646 { ep_food_pig, EP_FOOD_PIG },
3647 { ep_historic_wall, EP_HISTORIC_WALL },
3648 { ep_historic_solid, EP_HISTORIC_SOLID },
3649 { ep_classic_enemy, EP_CLASSIC_ENEMY },
3650 { ep_belt, EP_BELT },
3651 { ep_belt_active, EP_BELT_ACTIVE },
3652 { ep_belt_switch, EP_BELT_SWITCH },
3653 { ep_tube, EP_TUBE },
3654 { ep_keygate, EP_KEYGATE },
3655 { ep_amoeboid, EP_AMOEBOID },
3656 { ep_amoebalive, EP_AMOEBALIVE },
3657 { ep_has_content, EP_HAS_CONTENT },
3658 { ep_can_turn_each_move, EP_CAN_TURN_EACH_MOVE },
3659 { ep_can_grow, EP_CAN_GROW },
3660 { ep_active_bomb, EP_ACTIVE_BOMB },
3661 { ep_inactive, EP_INACTIVE },
3663 { ep_em_slippery_wall, EP_EM_SLIPPERY_WALL },
3665 { ep_gfx_crumbled, EP_GFX_CRUMBLED },
3672 /* always start with reliable default values (element has no properties) */
3673 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3674 for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3675 SET_PROPERTY(i, j, FALSE);
3677 /* set all base element properties from above array definitions */
3678 for (i = 0; element_properties[i].elements != NULL; i++)
3679 for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3680 SET_PROPERTY((element_properties[i].elements)[j],
3681 element_properties[i].property, TRUE);
3683 /* copy properties to some elements that are only stored in level file */
3684 for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3685 for (j = 0; copy_properties[j][0] != -1; j++)
3686 if (HAS_PROPERTY(copy_properties[j][0], i))
3687 for (k = 1; k <= 4; k++)
3688 SET_PROPERTY(copy_properties[j][k], i, TRUE);
3691 void InitElementPropertiesEngine(int engine_version)
3694 static int active_properties[] =
3699 EP_DONT_COLLIDE_WITH,
3703 EP_CAN_PASS_MAGIC_WALL,
3708 EP_EXPLODES_BY_FIRE,
3721 EP_EM_SLIPPERY_WALL,
3725 static int no_wall_properties[] =
3728 EP_COLLECTIBLE_ONLY,
3730 EP_DONT_COLLIDE_WITH,
3733 EP_CAN_SMASH_PLAYER,
3734 EP_CAN_SMASH_ENEMIES,
3735 EP_CAN_SMASH_EVERYTHING,
3740 EP_FOOD_DARK_YAMYAM,
3757 InitElementPropertiesStatic();
3760 /* important: after initialization in InitElementPropertiesStatic(), the
3761 elements are not again initialized to a default value; therefore all
3762 changes have to make sure that they leave the element with a defined
3763 property (which means that conditional property changes must be set to
3764 a reliable default value before) */
3766 /* set all special, combined or engine dependent element properties */
3767 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3770 for (j = EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
3771 SET_PROPERTY(i, j, FALSE);
3774 /* ---------- INACTIVE ------------------------------------------------- */
3775 SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
3777 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
3778 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
3779 IS_WALKABLE_INSIDE(i) ||
3780 IS_WALKABLE_UNDER(i)));
3782 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
3783 IS_PASSABLE_INSIDE(i) ||
3784 IS_PASSABLE_UNDER(i)));
3786 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
3787 IS_PASSABLE_OVER(i)));
3789 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
3790 IS_PASSABLE_INSIDE(i)));
3792 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
3793 IS_PASSABLE_UNDER(i)));
3795 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
3798 /* ---------- COLLECTIBLE ---------------------------------------------- */
3799 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
3803 /* ---------- SNAPPABLE ------------------------------------------------ */
3804 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
3805 IS_COLLECTIBLE(i) ||
3809 /* ---------- WALL ----------------------------------------------------- */
3810 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
3812 for (j = 0; no_wall_properties[j] != -1; j++)
3813 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
3814 i >= EL_FIRST_RUNTIME_UNREAL)
3815 SET_PROPERTY(i, EP_WALL, FALSE);
3817 if (IS_HISTORIC_WALL(i))
3818 SET_PROPERTY(i, EP_WALL, TRUE);
3820 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
3821 if (engine_version < VERSION_IDENT(2,2,0,0))
3822 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
3824 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
3826 !IS_COLLECTIBLE(i)));
3829 /* ---------- PROTECTED ------------------------------------------------ */
3830 if (IS_ACCESSIBLE_INSIDE(i))
3831 SET_PROPERTY(i, EP_PROTECTED, TRUE);
3834 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
3836 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
3837 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
3839 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
3840 IS_INDESTRUCTIBLE(i)));
3842 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
3844 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
3845 else if (engine_version < VERSION_IDENT(2,2,0,0))
3846 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
3849 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3854 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3855 !IS_WALKABLE_OVER(i) &&
3856 !IS_WALKABLE_UNDER(i)));
3858 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3863 if (IS_CUSTOM_ELEMENT(i))
3865 /* these are additional properties which are initially false when set */
3867 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
3869 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
3870 if (DONT_COLLIDE_WITH(i))
3871 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
3873 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
3874 if (CAN_SMASH_EVERYTHING(i))
3875 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
3876 if (CAN_SMASH_ENEMIES(i))
3877 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
3880 /* ---------- CAN_SMASH ------------------------------------------------ */
3881 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
3882 CAN_SMASH_ENEMIES(i) ||
3883 CAN_SMASH_EVERYTHING(i)));
3886 /* ---------- CAN_EXPLODE ---------------------------------------------- */
3887 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
3888 CAN_EXPLODE_SMASHED(i) ||
3889 CAN_EXPLODE_IMPACT(i)));
3893 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
3895 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (!CAN_EXPLODE_1X1(i) &&
3896 !CAN_EXPLODE_CROSS(i)));
3898 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
3899 !CAN_EXPLODE_1X1(i) &&
3900 !CAN_EXPLODE_CROSS(i)));
3904 /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
3905 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
3906 EXPLODES_BY_FIRE(i)));
3908 /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
3909 SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
3910 EXPLODES_SMASHED(i)));
3912 /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
3913 SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
3914 EXPLODES_IMPACT(i)));
3916 /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
3917 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
3919 /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
3920 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
3921 i == EL_BLACK_ORB));
3923 /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
3924 SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
3926 IS_CUSTOM_ELEMENT(i)));
3928 /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
3929 SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
3930 i == EL_SP_ELECTRON));
3932 /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
3933 if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
3934 SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
3935 getMoveIntoAcidProperty(&level, i));
3937 /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
3938 if (MAYBE_DONT_COLLIDE_WITH(i))
3939 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
3940 getDontCollideWithProperty(&level, i));
3942 /* ---------- SP_PORT -------------------------------------------------- */
3943 SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
3944 IS_PASSABLE_INSIDE(i)));
3946 /* ---------- CAN_CHANGE ----------------------------------------------- */
3947 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
3948 for (j = 0; j < element_info[i].num_change_pages; j++)
3949 if (element_info[i].change_page[j].can_change)
3950 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
3952 /* ---------- HAS_ACTION ----------------------------------------------- */
3953 SET_PROPERTY(i, EP_HAS_ACTION, FALSE); /* default: has no action */
3954 for (j = 0; j < element_info[i].num_change_pages; j++)
3955 if (element_info[i].change_page[j].has_action)
3956 SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
3958 /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
3959 SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
3962 /* ---------- GFX_CRUMBLED --------------------------------------------- */
3964 SET_PROPERTY(i, EP_GFX_CRUMBLED,
3965 element_info[i].crumbled[ACTION_DEFAULT] !=
3966 element_info[i].graphic[ACTION_DEFAULT]);
3968 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
3969 SET_PROPERTY(i, EP_GFX_CRUMBLED,
3970 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
3975 /* determine inactive elements (used for engine main loop optimization) */
3976 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3978 boolean active = FALSE;
3980 for (j = 0; i < NUM_ELEMENT_PROPERTIES; j++)
3982 if (HAS_PROPERTY(i, j))
3988 SET_PROPERTY(i, EP_INACTIVE, TRUE);
3993 /* dynamically adjust element properties according to game engine version */
3995 static int ep_em_slippery_wall[] =
4000 EL_EXPANDABLE_WALL_HORIZONTAL,
4001 EL_EXPANDABLE_WALL_VERTICAL,
4002 EL_EXPANDABLE_WALL_ANY,
4006 /* special EM style gems behaviour */
4007 for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4008 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4009 level.em_slippery_gems);
4011 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4012 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4013 (level.em_slippery_gems &&
4014 engine_version > VERSION_IDENT(2,0,1,0)));
4018 /* set default push delay values (corrected since version 3.0.7-1) */
4019 if (engine_version < VERSION_IDENT(3,0,7,1))
4021 game.default_push_delay_fixed = 2;
4022 game.default_push_delay_random = 8;
4026 game.default_push_delay_fixed = 8;
4027 game.default_push_delay_random = 8;
4030 /* set uninitialized push delay values of custom elements in older levels */
4031 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4033 int element = EL_CUSTOM_START + i;
4035 if (element_info[element].push_delay_fixed == -1)
4036 element_info[element].push_delay_fixed = game.default_push_delay_fixed;
4037 if (element_info[element].push_delay_random == -1)
4038 element_info[element].push_delay_random = game.default_push_delay_random;
4041 /* set some other uninitialized values of custom elements in older levels */
4042 if (engine_version < VERSION_IDENT(3,1,0,0))
4044 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4046 int element = EL_CUSTOM_START + i;
4048 element_info[element].access_direction = MV_ALL_DIRECTIONS;
4050 element_info[element].explosion_delay = 17;
4051 element_info[element].ignition_delay = 8;
4056 /* set element properties that were handled incorrectly in older levels */
4057 if (engine_version < VERSION_IDENT(3,1,0,0))
4059 SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
4060 SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
4066 /* this is needed because some graphics depend on element properties */
4067 if (game_status == GAME_MODE_PLAYING)
4068 InitElementGraphicInfo();
4071 static void InitGlobal()
4075 for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
4077 /* check if element_name_info entry defined for each element in "main.h" */
4078 if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
4079 Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
4081 element_info[i].token_name = element_name_info[i].token_name;
4082 element_info[i].class_name = element_name_info[i].class_name;
4083 element_info[i].editor_description=element_name_info[i].editor_description;
4086 global.autoplay_leveldir = NULL;
4087 global.convert_leveldir = NULL;
4089 global.frames_per_second = 0;
4090 global.fps_slowdown = FALSE;
4091 global.fps_slowdown_factor = 1;
4094 void Execute_Command(char *command)
4098 if (strcmp(command, "print graphicsinfo.conf") == 0)
4100 printf("# You can configure additional/alternative image files here.\n");
4101 printf("# (The entries below are default and therefore commented out.)\n");
4103 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
4105 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4108 for (i = 0; image_config[i].token != NULL; i++)
4109 printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
4110 image_config[i].value));
4114 else if (strcmp(command, "print soundsinfo.conf") == 0)
4116 printf("# You can configure additional/alternative sound files here.\n");
4117 printf("# (The entries below are default and therefore commented out.)\n");
4119 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
4121 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4124 for (i = 0; sound_config[i].token != NULL; i++)
4125 printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4126 sound_config[i].value));
4130 else if (strcmp(command, "print musicinfo.conf") == 0)
4132 printf("# You can configure additional/alternative music files here.\n");
4133 printf("# (The entries below are default and therefore commented out.)\n");
4135 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4137 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4140 for (i = 0; music_config[i].token != NULL; i++)
4141 printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4142 music_config[i].value));
4146 else if (strcmp(command, "print editorsetup.conf") == 0)
4148 printf("# You can configure your personal editor element list here.\n");
4149 printf("# (The entries below are default and therefore commented out.)\n");
4152 PrintEditorElementList();
4156 else if (strcmp(command, "print helpanim.conf") == 0)
4158 printf("# You can configure different element help animations here.\n");
4159 printf("# (The entries below are default and therefore commented out.)\n");
4162 for (i = 0; helpanim_config[i].token != NULL; i++)
4164 printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4165 helpanim_config[i].value));
4167 if (strcmp(helpanim_config[i].token, "end") == 0)
4173 else if (strcmp(command, "print helptext.conf") == 0)
4175 printf("# You can configure different element help text here.\n");
4176 printf("# (The entries below are default and therefore commented out.)\n");
4179 for (i = 0; helptext_config[i].token != NULL; i++)
4180 printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4181 helptext_config[i].value));
4185 else if (strncmp(command, "dump level ", 11) == 0)
4187 char *filename = &command[11];
4189 if (!fileExists(filename))
4190 Error(ERR_EXIT, "cannot open file '%s'", filename);
4192 LoadLevelFromFilename(&level, filename);
4197 else if (strncmp(command, "dump tape ", 10) == 0)
4199 char *filename = &command[10];
4201 if (!fileExists(filename))
4202 Error(ERR_EXIT, "cannot open file '%s'", filename);
4204 LoadTapeFromFilename(filename);
4209 else if (strncmp(command, "autoplay ", 9) == 0)
4211 char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
4213 while (*str_ptr != '\0') /* continue parsing string */
4215 /* cut leading whitespace from string, replace it by string terminator */
4216 while (*str_ptr == ' ' || *str_ptr == '\t')
4219 if (*str_ptr == '\0') /* end of string reached */
4222 if (global.autoplay_leveldir == NULL) /* read level set string */
4224 global.autoplay_leveldir = str_ptr;
4225 global.autoplay_all = TRUE; /* default: play all tapes */
4227 for (i = 0; i < MAX_TAPES_PER_SET; i++)
4228 global.autoplay_level[i] = FALSE;
4230 else /* read level number string */
4232 int level_nr = atoi(str_ptr); /* get level_nr value */
4234 if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
4235 global.autoplay_level[level_nr] = TRUE;
4237 global.autoplay_all = FALSE;
4240 /* advance string pointer to the next whitespace (or end of string) */
4241 while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
4246 printf("level set == '%s'\n", global.autoplay_leveldir);
4248 if (global.autoplay_all)
4249 printf("play all levels\n");
4252 printf("play the following levels:");
4254 for (i = 0; i < MAX_TAPES_PER_SET; i++)
4255 if (global.autoplay_level[i])
4263 else if (strncmp(command, "convert ", 8) == 0)
4265 char *str_copy = getStringCopy(&command[8]);
4266 char *str_ptr = strchr(str_copy, ' ');
4268 global.convert_leveldir = str_copy;
4269 global.convert_level_nr = -1;
4271 if (str_ptr != NULL) /* level number follows */
4273 *str_ptr++ = '\0'; /* terminate leveldir string */
4274 global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
4279 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4283 static void InitSetup()
4285 LoadSetup(); /* global setup info */
4287 /* set some options from setup file */
4289 if (setup.options.verbose)
4290 options.verbose = TRUE;
4293 static void InitGameInfo()
4295 game.restart_level = FALSE;
4298 static void InitPlayerInfo()
4302 /* choose default local player */
4303 local_player = &stored_player[0];
4305 for (i = 0; i < MAX_PLAYERS; i++)
4306 stored_player[i].connected = FALSE;
4308 local_player->connected = TRUE;
4311 static void InitArtworkInfo()
4316 static char *get_string_in_brackets(char *string)
4318 char *string_in_brackets = checked_malloc(strlen(string) + 3);
4320 sprintf(string_in_brackets, "[%s]", string);
4322 return string_in_brackets;
4325 static char *get_level_id_suffix(int id_nr)
4327 char *id_suffix = checked_malloc(1 + 3 + 1);
4329 if (id_nr < 0 || id_nr > 999)
4332 sprintf(id_suffix, ".%03d", id_nr);
4338 static char *get_element_class_token(int element)
4340 char *element_class_name = element_info[element].class_name;
4341 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4343 sprintf(element_class_token, "[%s]", element_class_name);
4345 return element_class_token;
4348 static char *get_action_class_token(int action)
4350 char *action_class_name = &element_action_info[action].suffix[1];
4351 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4353 sprintf(action_class_token, "[%s]", action_class_name);
4355 return action_class_token;
4359 static void InitArtworkConfig()
4361 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4362 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4363 static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4364 static char *action_id_suffix[NUM_ACTIONS + 1];
4365 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
4366 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4367 static char *level_id_suffix[MAX_LEVELS + 1];
4368 static char *dummy[1] = { NULL };
4369 static char *ignore_generic_tokens[] =
4375 static char **ignore_image_tokens;
4376 static char **ignore_sound_tokens;
4377 static char **ignore_music_tokens;
4378 int num_ignore_generic_tokens;
4379 int num_ignore_image_tokens;
4380 int num_ignore_sound_tokens;
4381 int num_ignore_music_tokens;
4384 /* dynamically determine list of generic tokens to be ignored */
4385 num_ignore_generic_tokens = 0;
4386 for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4387 num_ignore_generic_tokens++;
4389 /* dynamically determine list of image tokens to be ignored */
4390 num_ignore_image_tokens = num_ignore_generic_tokens;
4391 for (i = 0; image_config_vars[i].token != NULL; i++)
4392 num_ignore_image_tokens++;
4393 ignore_image_tokens =
4394 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4395 for (i = 0; i < num_ignore_generic_tokens; i++)
4396 ignore_image_tokens[i] = ignore_generic_tokens[i];
4397 for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4398 ignore_image_tokens[num_ignore_generic_tokens + i] =
4399 image_config_vars[i].token;
4400 ignore_image_tokens[num_ignore_image_tokens] = NULL;
4402 /* dynamically determine list of sound tokens to be ignored */
4403 num_ignore_sound_tokens = num_ignore_generic_tokens;
4404 ignore_sound_tokens =
4405 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4406 for (i = 0; i < num_ignore_generic_tokens; i++)
4407 ignore_sound_tokens[i] = ignore_generic_tokens[i];
4408 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4410 /* dynamically determine list of music tokens to be ignored */
4411 num_ignore_music_tokens = num_ignore_generic_tokens;
4412 ignore_music_tokens =
4413 checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4414 for (i = 0; i < num_ignore_generic_tokens; i++)
4415 ignore_music_tokens[i] = ignore_generic_tokens[i];
4416 ignore_music_tokens[num_ignore_music_tokens] = NULL;
4418 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4419 image_id_prefix[i] = element_info[i].token_name;
4420 for (i = 0; i < NUM_FONTS; i++)
4421 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4422 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4424 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4425 sound_id_prefix[i] = element_info[i].token_name;
4426 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4427 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4428 get_string_in_brackets(element_info[i].class_name);
4429 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4431 for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4432 music_id_prefix[i] = music_prefix_info[i].prefix;
4433 music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
4435 for (i = 0; i < NUM_ACTIONS; i++)
4436 action_id_suffix[i] = element_action_info[i].suffix;
4437 action_id_suffix[NUM_ACTIONS] = NULL;
4439 for (i = 0; i < NUM_DIRECTIONS; i++)
4440 direction_id_suffix[i] = element_direction_info[i].suffix;
4441 direction_id_suffix[NUM_DIRECTIONS] = NULL;
4443 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4444 special_id_suffix[i] = special_suffix_info[i].suffix;
4445 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4447 for (i = 0; i < MAX_LEVELS; i++)
4448 level_id_suffix[i] = get_level_id_suffix(i);
4449 level_id_suffix[MAX_LEVELS] = NULL;
4451 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4452 image_id_prefix, action_id_suffix, direction_id_suffix,
4453 special_id_suffix, ignore_image_tokens);
4454 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4455 sound_id_prefix, action_id_suffix, dummy,
4456 special_id_suffix, ignore_sound_tokens);
4457 InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4458 music_id_prefix, special_id_suffix, level_id_suffix,
4459 dummy, ignore_music_tokens);
4462 static void InitMixer()
4470 char *filename_font_initial = NULL;
4471 Bitmap *bitmap_font_initial = NULL;
4474 /* determine settings for initial font (for displaying startup messages) */
4475 for (i = 0; image_config[i].token != NULL; i++)
4477 for (j = 0; j < NUM_INITIAL_FONTS; j++)
4479 char font_token[128];
4482 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
4483 len_font_token = strlen(font_token);
4485 if (strcmp(image_config[i].token, font_token) == 0)
4486 filename_font_initial = image_config[i].value;
4487 else if (strlen(image_config[i].token) > len_font_token &&
4488 strncmp(image_config[i].token, font_token, len_font_token) == 0)
4490 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
4491 font_initial[j].src_x = atoi(image_config[i].value);
4492 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
4493 font_initial[j].src_y = atoi(image_config[i].value);
4494 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
4495 font_initial[j].width = atoi(image_config[i].value);
4496 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
4497 font_initial[j].height = atoi(image_config[i].value);
4502 for (j = 0; j < NUM_INITIAL_FONTS; j++)
4504 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
4505 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
4508 if (filename_font_initial == NULL) /* should not happen */
4509 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
4511 /* create additional image buffers for double-buffering */
4512 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
4513 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
4515 /* initialize screen properties */
4516 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
4517 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
4519 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
4520 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
4521 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
4523 bitmap_font_initial = LoadCustomImage(filename_font_initial);
4525 for (j = 0; j < NUM_INITIAL_FONTS; j++)
4526 font_initial[j].bitmap = bitmap_font_initial;
4528 InitFontGraphicInfo();
4530 DrawInitText(getProgramInitString(), 20, FC_YELLOW);
4531 DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
4533 DrawInitText("Loading graphics:", 120, FC_GREEN);
4535 InitTileClipmasks();
4538 void InitGfxBackground()
4542 drawto = backbuffer;
4543 fieldbuffer = bitmap_db_field;
4544 SetDrawtoField(DRAW_BACKBUFFER);
4546 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
4547 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
4548 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
4549 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
4551 for (x = 0; x < MAX_BUF_XSIZE; x++)
4552 for (y = 0; y < MAX_BUF_YSIZE; y++)
4555 redraw_mask = REDRAW_ALL;
4558 static void InitLevelInfo()
4560 LoadLevelInfo(); /* global level info */
4561 LoadLevelSetup_LastSeries(); /* last played series info */
4562 LoadLevelSetup_SeriesInfo(); /* last played level info */
4565 void InitLevelArtworkInfo()
4567 LoadLevelArtworkInfo();
4570 static void InitImages()
4573 setLevelArtworkDir(artwork.gfx_first);
4577 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
4578 leveldir_current->identifier,
4579 artwork.gfx_current_identifier,
4580 artwork.gfx_current->identifier,
4581 leveldir_current->graphics_set,
4582 leveldir_current->graphics_path);
4585 ReloadCustomImages();
4587 LoadCustomElementDescriptions();
4588 LoadSpecialMenuDesignSettings();
4590 ReinitializeGraphics();
4593 static void InitSound(char *identifier)
4595 if (identifier == NULL)
4596 identifier = artwork.snd_current->identifier;
4599 /* set artwork path to send it to the sound server process */
4600 setLevelArtworkDir(artwork.snd_first);
4603 InitReloadCustomSounds(identifier);
4604 ReinitializeSounds();
4607 static void InitMusic(char *identifier)
4609 if (identifier == NULL)
4610 identifier = artwork.mus_current->identifier;
4613 /* set artwork path to send it to the sound server process */
4614 setLevelArtworkDir(artwork.mus_first);
4617 InitReloadCustomMusic(identifier);
4618 ReinitializeMusic();
4621 void InitNetworkServer()
4623 #if defined(NETWORK_AVALIABLE)
4627 if (!options.network)
4630 #if defined(NETWORK_AVALIABLE)
4631 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
4633 if (!ConnectToServer(options.server_host, options.server_port))
4634 Error(ERR_EXIT, "cannot connect to network game server");
4636 SendToServer_PlayerName(setup.player_name);
4637 SendToServer_ProtocolVersion();
4640 SendToServer_NrWanted(nr_wanted);
4644 static char *getNewArtworkIdentifier(int type)
4646 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4647 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4648 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4649 static boolean initialized[3] = { FALSE, FALSE, FALSE };
4650 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4651 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4652 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4653 char *leveldir_identifier = leveldir_current->identifier;
4655 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4656 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4658 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4660 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4661 char *artwork_current_identifier;
4662 char *artwork_new_identifier = NULL; /* default: nothing has changed */
4664 /* leveldir_current may be invalid (level group, parent link) */
4665 if (!validLevelSeries(leveldir_current))
4668 /* 1st step: determine artwork set to be activated in descending order:
4669 --------------------------------------------------------------------
4670 1. setup artwork (when configured to override everything else)
4671 2. artwork set configured in "levelinfo.conf" of current level set
4672 (artwork in level directory will have priority when loading later)
4673 3. artwork in level directory (stored in artwork sub-directory)
4674 4. setup artwork (currently configured in setup menu) */
4676 if (setup_override_artwork)
4677 artwork_current_identifier = setup_artwork_set;
4678 else if (leveldir_artwork_set != NULL)
4679 artwork_current_identifier = leveldir_artwork_set;
4680 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4681 artwork_current_identifier = leveldir_identifier;
4683 artwork_current_identifier = setup_artwork_set;
4686 /* 2nd step: check if it is really needed to reload artwork set
4687 ------------------------------------------------------------ */
4690 if (type == ARTWORK_TYPE_GRAPHICS)
4691 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4692 artwork_new_identifier,
4693 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4694 artwork_current_identifier,
4695 leveldir_current->graphics_set,
4696 leveldir_current->identifier);
4699 /* ---------- reload if level set and also artwork set has changed ------- */
4700 if (leveldir_current_identifier[type] != leveldir_identifier &&
4701 (last_has_level_artwork_set[type] || has_level_artwork_set))
4702 artwork_new_identifier = artwork_current_identifier;
4704 leveldir_current_identifier[type] = leveldir_identifier;
4705 last_has_level_artwork_set[type] = has_level_artwork_set;
4708 if (type == ARTWORK_TYPE_GRAPHICS)
4709 printf("::: 1: '%s'\n", artwork_new_identifier);
4712 /* ---------- reload if "override artwork" setting has changed ----------- */
4713 if (last_override_level_artwork[type] != setup_override_artwork)
4714 artwork_new_identifier = artwork_current_identifier;
4716 last_override_level_artwork[type] = setup_override_artwork;
4719 if (type == ARTWORK_TYPE_GRAPHICS)
4720 printf("::: 2: '%s'\n", artwork_new_identifier);
4723 /* ---------- reload if current artwork identifier has changed ----------- */
4724 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4725 artwork_current_identifier) != 0)
4726 artwork_new_identifier = artwork_current_identifier;
4729 *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
4731 /* newer versions of gcc do not like this anymore :-/ */
4732 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
4736 if (type == ARTWORK_TYPE_GRAPHICS)
4737 printf("::: 3: '%s'\n", artwork_new_identifier);
4740 /* ---------- do not reload directly after starting ---------------------- */
4741 if (!initialized[type])
4742 artwork_new_identifier = NULL;
4744 initialized[type] = TRUE;
4747 if (type == ARTWORK_TYPE_GRAPHICS)
4748 printf("::: 4: '%s'\n", artwork_new_identifier);
4752 if (type == ARTWORK_TYPE_GRAPHICS)
4753 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4754 artwork.gfx_current_identifier, artwork_current_identifier,
4755 artwork.gfx_current->identifier, leveldir_current->graphics_set,
4756 artwork_new_identifier);
4759 return artwork_new_identifier;
4762 void ReloadCustomArtwork(int force_reload)
4764 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
4765 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
4766 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
4767 boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4768 boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4769 boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4770 boolean redraw_screen = FALSE;
4772 if (gfx_new_identifier != NULL || force_reload_gfx)
4775 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
4776 artwork.gfx_current_identifier,
4778 artwork.gfx_current->identifier,
4779 leveldir_current->graphics_set);
4782 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4787 printf("... '%s'\n",
4788 leveldir_current->graphics_set);
4791 FreeTileClipmasks();
4792 InitTileClipmasks();
4794 redraw_screen = TRUE;
4797 if (snd_new_identifier != NULL || force_reload_snd)
4799 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4801 InitSound(snd_new_identifier);
4803 redraw_screen = TRUE;
4806 if (mus_new_identifier != NULL || force_reload_mus)
4808 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4810 InitMusic(mus_new_identifier);
4812 redraw_screen = TRUE;
4817 InitGfxBackground();
4819 /* force redraw of (open or closed) door graphics */
4820 SetDoorState(DOOR_OPEN_ALL);
4821 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
4825 void KeyboardAutoRepeatOffUnlessAutoplay()
4827 if (global.autoplay_leveldir == NULL)
4828 KeyboardAutoRepeatOff();
4832 /* ========================================================================= */
4834 /* ========================================================================= */
4838 InitGlobal(); /* initialize some global variables */
4840 if (options.execute_command)
4841 Execute_Command(options.execute_command);
4843 if (options.serveronly)
4845 #if defined(PLATFORM_UNIX)
4846 NetworkServer(options.server_port, options.serveronly);
4848 Error(ERR_WARN, "networking only supported in Unix version");
4851 exit(0); /* never reached, server loops forever */
4858 InitArtworkInfo(); /* needed before loading gfx, sound & music */
4859 InitArtworkConfig(); /* needed before forking sound child process */
4864 InitRND(NEW_RANDOMIZE);
4865 InitSimpleRND(NEW_RANDOMIZE);
4870 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
4873 InitEventFilter(FilterMouseMotionEvents);
4875 InitElementPropertiesStatic();
4876 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4881 InitLevelArtworkInfo();
4883 InitImages(); /* needs to know current level directory */
4884 InitSound(NULL); /* needs to know current level directory */
4885 InitMusic(NULL); /* needs to know current level directory */
4887 InitGfxBackground();
4889 if (global.autoplay_leveldir)
4894 else if (global.convert_leveldir)
4900 game_status = GAME_MODE_MAIN;
4908 InitNetworkServer();
4911 void CloseAllAndExit(int exit_value)
4916 CloseAudio(); /* called after freeing sounds (needed for SDL) */
4923 FreeTileClipmasks();
4925 #if defined(TARGET_SDL)
4926 if (network_server) /* terminate network server */
4927 SDL_KillThread(server_thread);
4930 CloseVideoDisplay();
4931 ClosePlatformDependentStuff();