1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 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 */
35 #include "conf_act.c" /* include auto-generated data structure definitions */
38 #define CONFIG_TOKEN_FONT_INITIAL "font.initial"
39 #define CONFIG_TOKEN_GLOBAL_BUSY "global.busy"
41 #define DEBUG_PRINT_INIT_TIMESTAMPS TRUE
42 #define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH 5
45 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
46 static struct GraphicInfo anim_initial;
48 static int copy_properties[][5] =
52 EL_BUG_LEFT, EL_BUG_RIGHT,
53 EL_BUG_UP, EL_BUG_DOWN
57 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
58 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
62 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
63 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
67 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
68 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
72 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
73 EL_PACMAN_UP, EL_PACMAN_DOWN
77 EL_YAMYAM_LEFT, EL_YAMYAM_RIGHT,
78 EL_YAMYAM_UP, EL_YAMYAM_DOWN
82 EL_MOLE_LEFT, EL_MOLE_RIGHT,
83 EL_MOLE_UP, EL_MOLE_DOWN
92 static void print_init_timestamp(char *message)
95 #if DEBUG_PRINT_INIT_TIMESTAMPS
96 static char *last_message = NULL;
97 static int counter_nr = 0;
98 int max_depth = DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH;
100 if (strEqualPrefix(message, "INIT"))
102 if (counter_nr + 1 < max_depth)
104 debug_print_timestamp(counter_nr, NULL);
105 debug_print_timestamp(counter_nr, message);
110 debug_print_timestamp(counter_nr, NULL);
112 else if (strEqualPrefix(message, "DONE"))
116 if (counter_nr + 1 < max_depth)
118 last_message = &message[4];
120 debug_print_timestamp(counter_nr, message);
123 else if (!strEqualPrefix(message, "TIME") ||
124 !strEqualSuffix(message, last_message))
126 if (counter_nr < max_depth)
127 debug_print_timestamp(counter_nr, message);
135 struct GraphicInfo *graphic_info_last = graphic_info;
137 static unsigned long action_delay = 0;
138 unsigned long action_delay_value = GameFrameDelay;
139 int sync_frame = FrameCounter;
142 if (anim_initial.bitmap == NULL || window == NULL)
145 if (!DelayReached(&action_delay, action_delay_value))
150 static unsigned long last_counter = -1;
151 unsigned long current_counter = Counter();
152 unsigned long delay = current_counter - last_counter;
154 if (last_counter != -1 && delay > action_delay_value + 5)
155 printf("::: DrawInitAnim: DELAY TOO LONG: %ld\n", delay);
157 last_counter = current_counter;
161 anim_initial.anim_mode = ANIM_LOOP;
162 anim_initial.anim_start_frame = 0;
163 anim_initial.offset_x = anim_initial.width;
164 anim_initial.offset_y = 0;
166 x = WIN_XSIZE / 2 - TILESIZE / 2;
167 y = WIN_YSIZE / 2 - TILESIZE / 2;
169 graphic_info = &anim_initial;
171 if (sync_frame % anim_initial.anim_delay == 0)
172 DrawGraphicAnimationExt(window, x, y, graphic, sync_frame, NO_MASKING);
174 graphic_info = graphic_info_last;
181 FreeLevelEditorGadgets();
190 static boolean gadgets_initialized = FALSE;
192 if (gadgets_initialized)
195 CreateLevelEditorGadgets();
199 CreateScreenGadgets();
201 InitGadgetsSoundCallback(PlaySoundActivating, PlaySoundSelecting);
203 gadgets_initialized = TRUE;
206 inline void InitElementSmallImagesScaledUp(int graphic)
209 struct FileInfo *fi = getImageListEntryFromImageID(graphic);
211 printf("::: '%s' -> '%s'\n", fi->token, fi->filename);
214 CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
217 void InitElementSmallImages()
219 static int special_graphics[] =
221 IMG_EDITOR_ELEMENT_BORDER,
222 IMG_EDITOR_ELEMENT_BORDER_INPUT,
223 IMG_EDITOR_CASCADE_LIST,
224 IMG_EDITOR_CASCADE_LIST_ACTIVE,
227 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
228 int num_property_mappings = getImageListPropertyMappingSize();
231 /* initialize normal images from static configuration */
232 for (i = 0; element_to_graphic[i].element > -1; i++)
233 InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
235 /* initialize special images from static configuration */
236 for (i = 0; element_to_special_graphic[i].element > -1; i++)
237 InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
239 /* initialize images from dynamic configuration (may be elements or other) */
240 for (i = 0; i < num_property_mappings; i++)
241 InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
243 /* initialize special images from above list (non-element images) */
244 for (i = 0; special_graphics[i] > -1; i++)
245 InitElementSmallImagesScaledUp(special_graphics[i]);
248 void InitScaledImages()
252 /* scale normal images from static configuration, if not already scaled */
253 for (i = 0; i < NUM_IMAGE_FILES; i++)
254 ScaleImage(i, graphic_info[i].scale_up_factor);
258 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
259 void SetBitmaps_EM(Bitmap **em_bitmap)
261 em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
262 em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
266 static int getFontBitmapID(int font_nr)
270 if (game_status >= GAME_MODE_TITLE_INITIAL &&
271 game_status <= GAME_MODE_PSEUDO_PREVIEW)
272 special = game_status;
273 else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
274 special = GFX_SPECIAL_ARG_MAIN;
276 else if (game_status == GAME_MODE_PLAYING)
277 special = GFX_SPECIAL_ARG_DOOR;
281 return font_info[font_nr].special_bitmap_id[special];
286 static int getFontFromToken(char *token)
290 /* !!! OPTIMIZE THIS BY USING HASH !!! */
291 for (i = 0; i < NUM_FONTS; i++)
292 if (strEqual(token, font_info[i].token_name))
295 /* if font not found, use reliable default value */
296 return FONT_INITIAL_1;
299 void InitFontGraphicInfo()
301 static struct FontBitmapInfo *font_bitmap_info = NULL;
302 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
303 int num_property_mappings = getImageListPropertyMappingSize();
304 int num_font_bitmaps = NUM_FONTS;
307 if (graphic_info == NULL) /* still at startup phase */
309 InitFontInfo(font_initial, NUM_INITIAL_FONTS,
310 getFontBitmapID, getFontFromToken);
315 /* ---------- initialize font graphic definitions ---------- */
317 /* always start with reliable default values (normal font graphics) */
318 for (i = 0; i < NUM_FONTS; i++)
319 font_info[i].graphic = IMG_FONT_INITIAL_1;
321 /* initialize normal font/graphic mapping from static configuration */
322 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
324 int font_nr = font_to_graphic[i].font_nr;
325 int special = font_to_graphic[i].special;
326 int graphic = font_to_graphic[i].graphic;
331 font_info[font_nr].graphic = graphic;
334 /* always start with reliable default values (special font graphics) */
335 for (i = 0; i < NUM_FONTS; i++)
337 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
339 font_info[i].special_graphic[j] = font_info[i].graphic;
340 font_info[i].special_bitmap_id[j] = i;
344 /* initialize special font/graphic mapping from static configuration */
345 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
347 int font_nr = font_to_graphic[i].font_nr;
348 int special = font_to_graphic[i].special;
349 int graphic = font_to_graphic[i].graphic;
350 int base_graphic = font2baseimg(font_nr);
352 if (IS_SPECIAL_GFX_ARG(special))
354 boolean base_redefined =
355 getImageListEntryFromImageID(base_graphic)->redefined;
356 boolean special_redefined =
357 getImageListEntryFromImageID(graphic)->redefined;
358 boolean special_cloned = (graphic_info[graphic].clone_from != -1);
360 /* if the base font ("font.title_1", for example) has been redefined,
361 but not the special font ("font.title_1.LEVELS", for example), do not
362 use an existing (in this case considered obsolete) special font
363 anymore, but use the automatically determined default font */
364 /* special case: cloned special fonts must be explicitly redefined,
365 but are not automatically redefined by redefining base font */
366 if (base_redefined && !special_redefined && !special_cloned)
369 font_info[font_nr].special_graphic[special] = graphic;
370 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
375 /* initialize special font/graphic mapping from dynamic configuration */
376 for (i = 0; i < num_property_mappings; i++)
378 int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
379 int special = property_mapping[i].ext3_index;
380 int graphic = property_mapping[i].artwork_index;
385 if (IS_SPECIAL_GFX_ARG(special))
387 font_info[font_nr].special_graphic[special] = graphic;
388 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
393 /* correct special font/graphic mapping for cloned fonts for downwards
394 compatibility of PREVIEW fonts -- this is only needed for implicit
395 redefinition of special font by redefined base font, and only if other
396 fonts are cloned from this special font (like in the "Zelda" level set) */
397 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
399 int font_nr = font_to_graphic[i].font_nr;
400 int special = font_to_graphic[i].special;
401 int graphic = font_to_graphic[i].graphic;
403 if (IS_SPECIAL_GFX_ARG(special))
405 boolean special_redefined =
406 getImageListEntryFromImageID(graphic)->redefined;
407 boolean special_cloned = (graphic_info[graphic].clone_from != -1);
409 if (special_cloned && !special_redefined)
413 for (j = 0; font_to_graphic[j].font_nr > -1; j++)
415 int font_nr2 = font_to_graphic[j].font_nr;
416 int special2 = font_to_graphic[j].special;
417 int graphic2 = font_to_graphic[j].graphic;
419 if (IS_SPECIAL_GFX_ARG(special2) &&
420 graphic2 == graphic_info[graphic].clone_from)
422 font_info[font_nr].special_graphic[special] =
423 font_info[font_nr2].special_graphic[special2];
424 font_info[font_nr].special_bitmap_id[special] =
425 font_info[font_nr2].special_bitmap_id[special2];
432 /* reset non-redefined ".active" font graphics if normal font is redefined */
433 /* (this different treatment is needed because normal and active fonts are
434 independently defined ("active" is not a property of font definitions!) */
435 for (i = 0; i < NUM_FONTS; i++)
437 int font_nr_base = i;
438 int font_nr_active = FONT_ACTIVE(font_nr_base);
440 /* check only those fonts with exist as normal and ".active" variant */
441 if (font_nr_base != font_nr_active)
443 int base_graphic = font_info[font_nr_base].graphic;
444 int active_graphic = font_info[font_nr_active].graphic;
445 boolean base_redefined =
446 getImageListEntryFromImageID(base_graphic)->redefined;
447 boolean active_redefined =
448 getImageListEntryFromImageID(active_graphic)->redefined;
450 /* if the base font ("font.menu_1", for example) has been redefined,
451 but not the active font ("font.menu_1.active", for example), do not
452 use an existing (in this case considered obsolete) active font
453 anymore, but use the automatically determined default font */
454 if (base_redefined && !active_redefined)
455 font_info[font_nr_active].graphic = base_graphic;
457 /* now also check each "special" font (which may be the same as above) */
458 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
460 int base_graphic = font_info[font_nr_base].special_graphic[j];
461 int active_graphic = font_info[font_nr_active].special_graphic[j];
462 boolean base_redefined =
463 getImageListEntryFromImageID(base_graphic)->redefined;
464 boolean active_redefined =
465 getImageListEntryFromImageID(active_graphic)->redefined;
467 /* same as above, but check special graphic definitions, for example:
468 redefined "font.menu_1.MAIN" invalidates "font.menu_1.active.MAIN" */
469 if (base_redefined && !active_redefined)
471 font_info[font_nr_active].special_graphic[j] =
472 font_info[font_nr_base].special_graphic[j];
473 font_info[font_nr_active].special_bitmap_id[j] =
474 font_info[font_nr_base].special_bitmap_id[j];
480 /* ---------- initialize font bitmap array ---------- */
482 if (font_bitmap_info != NULL)
483 FreeFontInfo(font_bitmap_info);
486 checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
488 /* ---------- initialize font bitmap definitions ---------- */
490 for (i = 0; i < NUM_FONTS; i++)
492 if (i < NUM_INITIAL_FONTS)
494 font_bitmap_info[i] = font_initial[i];
498 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
500 int font_bitmap_id = font_info[i].special_bitmap_id[j];
501 int graphic = font_info[i].special_graphic[j];
503 /* set 'graphic_info' for font entries, if uninitialized (guessed) */
504 if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
506 graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
507 graphic_info[graphic].anim_frames_per_line = DEFAULT_NUM_CHARS_PER_LINE;
510 /* copy font relevant information from graphics information */
511 font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
512 font_bitmap_info[font_bitmap_id].src_x = graphic_info[graphic].src_x;
513 font_bitmap_info[font_bitmap_id].src_y = graphic_info[graphic].src_y;
514 font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
515 font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
517 font_bitmap_info[font_bitmap_id].draw_xoffset =
518 graphic_info[graphic].draw_xoffset;
519 font_bitmap_info[font_bitmap_id].draw_yoffset =
520 graphic_info[graphic].draw_yoffset;
522 font_bitmap_info[font_bitmap_id].num_chars =
523 graphic_info[graphic].anim_frames;
524 font_bitmap_info[font_bitmap_id].num_chars_per_line =
525 graphic_info[graphic].anim_frames_per_line;
529 InitFontInfo(font_bitmap_info, num_font_bitmaps,
530 getFontBitmapID, getFontFromToken);
533 void InitElementGraphicInfo()
535 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
536 int num_property_mappings = getImageListPropertyMappingSize();
539 if (graphic_info == NULL) /* still at startup phase */
542 /* set values to -1 to identify later as "uninitialized" values */
543 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
545 for (act = 0; act < NUM_ACTIONS; act++)
547 element_info[i].graphic[act] = -1;
548 element_info[i].crumbled[act] = -1;
550 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
552 element_info[i].direction_graphic[act][dir] = -1;
553 element_info[i].direction_crumbled[act][dir] = -1;
560 /* initialize normal element/graphic mapping from static configuration */
561 for (i = 0; element_to_graphic[i].element > -1; i++)
563 int element = element_to_graphic[i].element;
564 int action = element_to_graphic[i].action;
565 int direction = element_to_graphic[i].direction;
566 boolean crumbled = element_to_graphic[i].crumbled;
567 int graphic = element_to_graphic[i].graphic;
568 int base_graphic = el2baseimg(element);
570 if (graphic_info[graphic].bitmap == NULL)
573 if ((action > -1 || direction > -1 || crumbled == TRUE) &&
576 boolean base_redefined =
577 getImageListEntryFromImageID(base_graphic)->redefined;
578 boolean act_dir_redefined =
579 getImageListEntryFromImageID(graphic)->redefined;
581 /* if the base graphic ("emerald", for example) has been redefined,
582 but not the action graphic ("emerald.falling", for example), do not
583 use an existing (in this case considered obsolete) action graphic
584 anymore, but use the automatically determined default graphic */
585 if (base_redefined && !act_dir_redefined)
590 action = ACTION_DEFAULT;
595 element_info[element].direction_crumbled[action][direction] = graphic;
597 element_info[element].crumbled[action] = graphic;
602 element_info[element].direction_graphic[action][direction] = graphic;
604 element_info[element].graphic[action] = graphic;
608 /* initialize normal element/graphic mapping from dynamic configuration */
609 for (i = 0; i < num_property_mappings; i++)
611 int element = property_mapping[i].base_index;
612 int action = property_mapping[i].ext1_index;
613 int direction = property_mapping[i].ext2_index;
614 int special = property_mapping[i].ext3_index;
615 int graphic = property_mapping[i].artwork_index;
616 boolean crumbled = FALSE;
619 if ((element == EL_EM_DYNAMITE ||
620 element == EL_EM_DYNAMITE_ACTIVE) &&
621 action == ACTION_ACTIVE &&
622 (special == GFX_SPECIAL_ARG_EDITOR ||
623 special == GFX_SPECIAL_ARG_PANEL))
624 printf("::: DYNAMIC: %d, %d, %d -> %d\n",
625 element, action, special, graphic);
628 if (special == GFX_SPECIAL_ARG_CRUMBLED)
634 if (graphic_info[graphic].bitmap == NULL)
637 if (element >= MAX_NUM_ELEMENTS || special != -1)
641 action = ACTION_DEFAULT;
646 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
647 element_info[element].direction_crumbled[action][dir] = -1;
650 element_info[element].direction_crumbled[action][direction] = graphic;
652 element_info[element].crumbled[action] = graphic;
657 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
658 element_info[element].direction_graphic[action][dir] = -1;
661 element_info[element].direction_graphic[action][direction] = graphic;
663 element_info[element].graphic[action] = graphic;
667 /* now copy all graphics that are defined to be cloned from other graphics */
668 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
670 int graphic = element_info[i].graphic[ACTION_DEFAULT];
671 int crumbled_like, diggable_like;
676 crumbled_like = graphic_info[graphic].crumbled_like;
677 diggable_like = graphic_info[graphic].diggable_like;
679 if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
681 for (act = 0; act < NUM_ACTIONS; act++)
682 element_info[i].crumbled[act] =
683 element_info[crumbled_like].crumbled[act];
684 for (act = 0; act < NUM_ACTIONS; act++)
685 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
686 element_info[i].direction_crumbled[act][dir] =
687 element_info[crumbled_like].direction_crumbled[act][dir];
690 if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
692 element_info[i].graphic[ACTION_DIGGING] =
693 element_info[diggable_like].graphic[ACTION_DIGGING];
694 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
695 element_info[i].direction_graphic[ACTION_DIGGING][dir] =
696 element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
701 /* set hardcoded definitions for some runtime elements without graphic */
702 element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
706 /* set hardcoded definitions for some internal elements without graphic */
707 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
709 if (IS_EDITOR_CASCADE_INACTIVE(i))
710 element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST;
711 else if (IS_EDITOR_CASCADE_ACTIVE(i))
712 element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
716 /* now set all undefined/invalid graphics to -1 to set to default after it */
717 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
719 for (act = 0; act < NUM_ACTIONS; act++)
723 graphic = element_info[i].graphic[act];
724 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
725 element_info[i].graphic[act] = -1;
727 graphic = element_info[i].crumbled[act];
728 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
729 element_info[i].crumbled[act] = -1;
731 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
733 graphic = element_info[i].direction_graphic[act][dir];
734 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
735 element_info[i].direction_graphic[act][dir] = -1;
737 graphic = element_info[i].direction_crumbled[act][dir];
738 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
739 element_info[i].direction_crumbled[act][dir] = -1;
746 /* adjust graphics with 2nd tile for movement according to direction
747 (do this before correcting '-1' values to minimize calculations) */
748 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
750 for (act = 0; act < NUM_ACTIONS; act++)
752 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
754 int graphic = element_info[i].direction_graphic[act][dir];
755 int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
757 if (act == ACTION_FALLING) /* special case */
758 graphic = element_info[i].graphic[act];
761 graphic_info[graphic].double_movement &&
762 graphic_info[graphic].swap_double_tiles != 0)
764 struct GraphicInfo *g = &graphic_info[graphic];
765 int src_x_front = g->src_x;
766 int src_y_front = g->src_y;
767 int src_x_back = g->src_x + g->offset2_x;
768 int src_y_back = g->src_y + g->offset2_y;
769 boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
771 boolean front_is_left_or_upper = (src_x_front < src_x_back ||
772 src_y_front < src_y_back);
773 boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
774 boolean swap_movement_tiles_autodetected =
775 (!frames_are_ordered_diagonally &&
776 ((move_dir == MV_BIT_LEFT && !front_is_left_or_upper) ||
777 (move_dir == MV_BIT_UP && !front_is_left_or_upper) ||
778 (move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
779 (move_dir == MV_BIT_DOWN && front_is_left_or_upper)));
782 /* swap frontside and backside graphic tile coordinates, if needed */
783 if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
785 /* get current (wrong) backside tile coordinates */
786 getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
789 /* set frontside tile coordinates to backside tile coordinates */
790 g->src_x = src_x_back;
791 g->src_y = src_y_back;
793 /* invert tile offset to point to new backside tile coordinates */
797 /* do not swap front and backside tiles again after correction */
798 g->swap_double_tiles = 0;
807 /* now set all '-1' values to element specific default values */
808 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
810 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
811 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
812 int default_direction_graphic[NUM_DIRECTIONS_FULL];
813 int default_direction_crumbled[NUM_DIRECTIONS_FULL];
815 if (default_graphic == -1)
816 default_graphic = IMG_UNKNOWN;
818 if (default_crumbled == -1)
819 default_crumbled = default_graphic;
821 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
822 if (default_crumbled == -1)
823 default_crumbled = IMG_EMPTY;
826 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
828 default_direction_graphic[dir] =
829 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
830 default_direction_crumbled[dir] =
831 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
833 if (default_direction_graphic[dir] == -1)
834 default_direction_graphic[dir] = default_graphic;
836 if (default_direction_crumbled[dir] == -1)
837 default_direction_crumbled[dir] = default_direction_graphic[dir];
839 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
840 if (default_direction_crumbled[dir] == -1)
841 default_direction_crumbled[dir] = default_crumbled;
845 for (act = 0; act < NUM_ACTIONS; act++)
847 boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
848 (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
849 (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
850 boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
851 act == ACTION_TURNING_FROM_RIGHT ||
852 act == ACTION_TURNING_FROM_UP ||
853 act == ACTION_TURNING_FROM_DOWN);
855 /* generic default action graphic (defined by "[default]" directive) */
856 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
857 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
858 int default_remove_graphic = IMG_EMPTY;
860 if (act_remove && default_action_graphic != -1)
861 default_remove_graphic = default_action_graphic;
863 /* look for special default action graphic (classic game specific) */
864 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
865 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
866 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
867 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
868 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
869 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
871 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
872 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
873 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
874 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
875 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
876 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
879 /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
880 /* !!! make this better !!! */
881 if (i == EL_EMPTY_SPACE)
883 default_action_graphic = element_info[EL_DEFAULT].graphic[act];
884 default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
888 if (default_action_graphic == -1)
889 default_action_graphic = default_graphic;
891 if (default_action_crumbled == -1)
892 default_action_crumbled = default_action_graphic;
894 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
895 if (default_action_crumbled == -1)
896 default_action_crumbled = default_crumbled;
899 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
901 /* use action graphic as the default direction graphic, if undefined */
902 int default_action_direction_graphic = element_info[i].graphic[act];
903 int default_action_direction_crumbled = element_info[i].crumbled[act];
905 /* no graphic for current action -- use default direction graphic */
906 if (default_action_direction_graphic == -1)
907 default_action_direction_graphic =
908 (act_remove ? default_remove_graphic :
910 element_info[i].direction_graphic[ACTION_TURNING][dir] :
911 default_action_graphic != default_graphic ?
912 default_action_graphic :
913 default_direction_graphic[dir]);
915 if (element_info[i].direction_graphic[act][dir] == -1)
916 element_info[i].direction_graphic[act][dir] =
917 default_action_direction_graphic;
920 if (default_action_direction_crumbled == -1)
921 default_action_direction_crumbled =
922 element_info[i].direction_graphic[act][dir];
924 if (default_action_direction_crumbled == -1)
925 default_action_direction_crumbled =
926 (act_remove ? default_remove_graphic :
928 element_info[i].direction_crumbled[ACTION_TURNING][dir] :
929 default_action_crumbled != default_crumbled ?
930 default_action_crumbled :
931 default_direction_crumbled[dir]);
934 if (element_info[i].direction_crumbled[act][dir] == -1)
935 element_info[i].direction_crumbled[act][dir] =
936 default_action_direction_crumbled;
939 /* no graphic for this specific action -- use default action graphic */
940 if (element_info[i].graphic[act] == -1)
941 element_info[i].graphic[act] =
942 (act_remove ? default_remove_graphic :
943 act_turning ? element_info[i].graphic[ACTION_TURNING] :
944 default_action_graphic);
946 if (element_info[i].crumbled[act] == -1)
947 element_info[i].crumbled[act] = element_info[i].graphic[act];
949 if (element_info[i].crumbled[act] == -1)
950 element_info[i].crumbled[act] =
951 (act_remove ? default_remove_graphic :
952 act_turning ? element_info[i].crumbled[ACTION_TURNING] :
953 default_action_crumbled);
961 /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */
962 /* set animation mode to "none" for each graphic with only 1 frame */
963 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
965 for (act = 0; act < NUM_ACTIONS; act++)
967 int graphic = element_info[i].graphic[act];
968 int crumbled = element_info[i].crumbled[act];
970 if (graphic_info[graphic].anim_frames == 1)
971 graphic_info[graphic].anim_mode = ANIM_NONE;
972 if (graphic_info[crumbled].anim_frames == 1)
973 graphic_info[crumbled].anim_mode = ANIM_NONE;
975 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
977 graphic = element_info[i].direction_graphic[act][dir];
978 crumbled = element_info[i].direction_crumbled[act][dir];
980 if (graphic_info[graphic].anim_frames == 1)
981 graphic_info[graphic].anim_mode = ANIM_NONE;
982 if (graphic_info[crumbled].anim_frames == 1)
983 graphic_info[crumbled].anim_mode = ANIM_NONE;
993 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
994 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
996 Error(ERR_INFO, "warning: no graphic for element '%s' (%d)",
997 element_info[i].token_name, i);
1003 void InitElementSpecialGraphicInfo()
1005 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
1006 int num_property_mappings = getImageListPropertyMappingSize();
1009 /* always start with reliable default values */
1010 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1011 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
1012 element_info[i].special_graphic[j] =
1013 element_info[i].graphic[ACTION_DEFAULT];
1015 /* initialize special element/graphic mapping from static configuration */
1016 for (i = 0; element_to_special_graphic[i].element > -1; i++)
1018 int element = element_to_special_graphic[i].element;
1019 int special = element_to_special_graphic[i].special;
1020 int graphic = element_to_special_graphic[i].graphic;
1021 int base_graphic = el2baseimg(element);
1022 boolean base_redefined =
1023 getImageListEntryFromImageID(base_graphic)->redefined;
1024 boolean special_redefined =
1025 getImageListEntryFromImageID(graphic)->redefined;
1028 if ((element == EL_EM_DYNAMITE ||
1029 element == EL_EM_DYNAMITE_ACTIVE) &&
1030 (special == GFX_SPECIAL_ARG_EDITOR ||
1031 special == GFX_SPECIAL_ARG_PANEL))
1032 printf("::: SPECIAL STATIC: %d, %d -> %d\n",
1033 element, special, graphic);
1036 /* if the base graphic ("emerald", for example) has been redefined,
1037 but not the special graphic ("emerald.EDITOR", for example), do not
1038 use an existing (in this case considered obsolete) special graphic
1039 anymore, but use the automatically created (down-scaled) graphic */
1040 if (base_redefined && !special_redefined)
1043 element_info[element].special_graphic[special] = graphic;
1046 /* initialize special element/graphic mapping from dynamic configuration */
1047 for (i = 0; i < num_property_mappings; i++)
1049 int element = property_mapping[i].base_index;
1050 int action = property_mapping[i].ext1_index;
1051 int direction = property_mapping[i].ext2_index;
1052 int special = property_mapping[i].ext3_index;
1053 int graphic = property_mapping[i].artwork_index;
1056 if ((element == EL_EM_DYNAMITE ||
1057 element == EL_EM_DYNAMITE_ACTIVE ||
1058 element == EL_CONVEYOR_BELT_1_MIDDLE ||
1059 element == EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE) &&
1060 (special == GFX_SPECIAL_ARG_EDITOR ||
1061 special == GFX_SPECIAL_ARG_PANEL))
1062 printf("::: SPECIAL DYNAMIC: %d, %d -> %d [%d]\n",
1063 element, special, graphic, property_mapping[i].ext1_index);
1067 if (element == EL_CONVEYOR_BELT_1_MIDDLE &&
1068 action == ACTION_ACTIVE)
1070 element = EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE;
1076 if (element == EL_MAGIC_WALL &&
1077 action == ACTION_ACTIVE)
1079 element = EL_MAGIC_WALL_ACTIVE;
1085 /* for action ".active", replace element with active element, if exists */
1086 if (action == ACTION_ACTIVE && element != ELEMENT_ACTIVE(element))
1088 element = ELEMENT_ACTIVE(element);
1093 if (element >= MAX_NUM_ELEMENTS)
1096 /* do not change special graphic if action or direction was specified */
1097 if (action != -1 || direction != -1)
1100 if (IS_SPECIAL_GFX_ARG(special))
1101 element_info[element].special_graphic[special] = graphic;
1104 /* now set all undefined/invalid graphics to default */
1105 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1106 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
1107 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
1108 element_info[i].special_graphic[j] =
1109 element_info[i].graphic[ACTION_DEFAULT];
1112 static int get_graphic_parameter_value(char *value_raw, char *suffix, int type)
1117 if (type != TYPE_TOKEN)
1118 return get_parameter_value(value_raw, suffix, type);
1120 if (strEqual(value_raw, ARG_UNDEFINED))
1121 return ARG_UNDEFINED_VALUE;
1123 /* !!! OPTIMIZE THIS BY USING HASH !!! */
1124 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1125 if (strEqual(element_info[i].token_name, value_raw))
1128 /* !!! OPTIMIZE THIS BY USING HASH !!! */
1129 for (i = 0; image_config[i].token != NULL; i++)
1131 int len_config_value = strlen(image_config[i].value);
1133 if (!strEqual(&image_config[i].value[len_config_value - 4], ".pcx") &&
1134 !strEqual(&image_config[i].value[len_config_value - 4], ".wav") &&
1135 !strEqual(image_config[i].value, UNDEFINED_FILENAME))
1138 if (strEqual(image_config[i].token, value_raw))
1147 static int get_scaled_graphic_width(int graphic)
1149 int original_width = getOriginalImageWidthFromImageID(graphic);
1150 int scale_up_factor = graphic_info[graphic].scale_up_factor;
1152 return original_width * scale_up_factor;
1155 static int get_scaled_graphic_height(int graphic)
1157 int original_height = getOriginalImageHeightFromImageID(graphic);
1158 int scale_up_factor = graphic_info[graphic].scale_up_factor;
1160 return original_height * scale_up_factor;
1163 static void set_graphic_parameters(int graphic)
1165 struct FileInfo *image = getImageListEntryFromImageID(graphic);
1166 char **parameter_raw = image->parameter;
1167 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
1168 int parameter[NUM_GFX_ARGS];
1169 int anim_frames_per_row = 1, anim_frames_per_col = 1;
1170 int anim_frames_per_line = 1;
1173 /* if fallback to default artwork is done, also use the default parameters */
1174 if (image->fallback_to_default)
1175 parameter_raw = image->default_parameter;
1177 /* get integer values from string parameters */
1178 for (i = 0; i < NUM_GFX_ARGS; i++)
1179 parameter[i] = get_graphic_parameter_value(parameter_raw[i],
1180 image_config_suffix[i].token,
1181 image_config_suffix[i].type);
1183 graphic_info[graphic].bitmap = src_bitmap;
1185 /* always start with reliable default values */
1186 graphic_info[graphic].src_image_width = 0;
1187 graphic_info[graphic].src_image_height = 0;
1188 graphic_info[graphic].src_x = 0;
1189 graphic_info[graphic].src_y = 0;
1190 graphic_info[graphic].width = TILEX; /* default for element graphics */
1191 graphic_info[graphic].height = TILEY; /* default for element graphics */
1192 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
1193 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
1194 graphic_info[graphic].offset2_x = 0; /* one or both of these values ... */
1195 graphic_info[graphic].offset2_y = 0; /* ... will be corrected later */
1196 graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */
1197 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
1198 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
1199 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
1200 graphic_info[graphic].scale_up_factor = 1; /* default: no scaling up */
1201 graphic_info[graphic].clone_from = -1; /* do not use clone graphic */
1202 graphic_info[graphic].anim_delay_fixed = 0;
1203 graphic_info[graphic].anim_delay_random = 0;
1204 graphic_info[graphic].post_delay_fixed = 0;
1205 graphic_info[graphic].post_delay_random = 0;
1206 graphic_info[graphic].fade_mode = FADE_MODE_DEFAULT;
1207 graphic_info[graphic].fade_delay = -1;
1208 graphic_info[graphic].post_delay = -1;
1209 graphic_info[graphic].auto_delay = -1;
1210 graphic_info[graphic].align = ALIGN_CENTER; /* default for title screens */
1211 graphic_info[graphic].valign = VALIGN_MIDDLE; /* default for title screens */
1212 graphic_info[graphic].sort_priority = 0; /* default for title screens */
1215 /* optional zoom factor for scaling up the image to a larger size */
1216 if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1217 graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1218 if (graphic_info[graphic].scale_up_factor < 1)
1219 graphic_info[graphic].scale_up_factor = 1; /* no scaling */
1223 if (graphic_info[graphic].use_image_size)
1225 /* set new default bitmap size (with scaling, but without small images) */
1226 graphic_info[graphic].width = get_scaled_graphic_width(graphic);
1227 graphic_info[graphic].height = get_scaled_graphic_height(graphic);
1231 /* optional x and y tile position of animation frame sequence */
1232 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
1233 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
1234 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
1235 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
1237 /* optional x and y pixel position of animation frame sequence */
1238 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
1239 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
1240 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
1241 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
1243 /* optional width and height of each animation frame */
1244 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
1245 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
1246 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
1247 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
1250 /* optional zoom factor for scaling up the image to a larger size */
1251 if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1252 graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1253 if (graphic_info[graphic].scale_up_factor < 1)
1254 graphic_info[graphic].scale_up_factor = 1; /* no scaling */
1259 /* get final bitmap size (with scaling, but without small images) */
1260 int src_image_width = get_scaled_graphic_width(graphic);
1261 int src_image_height = get_scaled_graphic_height(graphic);
1263 anim_frames_per_row = src_image_width / graphic_info[graphic].width;
1264 anim_frames_per_col = src_image_height / graphic_info[graphic].height;
1266 graphic_info[graphic].src_image_width = src_image_width;
1267 graphic_info[graphic].src_image_height = src_image_height;
1270 /* correct x or y offset dependent of vertical or horizontal frame order */
1271 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
1273 graphic_info[graphic].offset_y =
1274 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1275 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
1276 anim_frames_per_line = anim_frames_per_col;
1278 else /* frames are ordered horizontally */
1280 graphic_info[graphic].offset_x =
1281 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1282 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
1283 anim_frames_per_line = anim_frames_per_row;
1286 /* optionally, the x and y offset of frames can be specified directly */
1287 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
1288 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
1289 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
1290 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
1292 /* optionally, moving animations may have separate start and end graphics */
1293 graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
1295 if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
1296 parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
1298 /* correct x or y offset2 dependent of vertical or horizontal frame order */
1299 if (parameter[GFX_ARG_2ND_VERTICAL]) /* frames are ordered vertically */
1300 graphic_info[graphic].offset2_y =
1301 (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1302 parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
1303 else /* frames are ordered horizontally */
1304 graphic_info[graphic].offset2_x =
1305 (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1306 parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
1308 /* optionally, the x and y offset of 2nd graphic can be specified directly */
1309 if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
1310 graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
1311 if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
1312 graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
1314 /* optionally, the second movement tile can be specified as start tile */
1315 if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
1316 graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
1318 /* automatically determine correct number of frames, if not defined */
1319 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1320 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
1321 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1322 graphic_info[graphic].anim_frames = anim_frames_per_row;
1323 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1324 graphic_info[graphic].anim_frames = anim_frames_per_col;
1326 graphic_info[graphic].anim_frames = 1;
1328 if (graphic_info[graphic].anim_frames == 0) /* frames must be at least 1 */
1329 graphic_info[graphic].anim_frames = 1;
1331 graphic_info[graphic].anim_frames_per_line =
1332 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1333 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1335 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
1336 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
1337 graphic_info[graphic].anim_delay = 1;
1339 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
1341 if (graphic_info[graphic].anim_frames == 1)
1342 graphic_info[graphic].anim_mode = ANIM_NONE;
1345 /* automatically determine correct start frame, if not defined */
1346 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1347 graphic_info[graphic].anim_start_frame = 0;
1348 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
1349 graphic_info[graphic].anim_start_frame =
1350 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1352 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
1354 /* animation synchronized with global frame counter, not move position */
1355 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1357 /* optional element for cloning crumble graphics */
1358 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1359 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1361 /* optional element for cloning digging graphics */
1362 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1363 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1365 /* optional border size for "crumbling" diggable graphics */
1366 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1367 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
1369 /* this is only used for player "boring" and "sleeping" actions */
1370 if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1371 graphic_info[graphic].anim_delay_fixed =
1372 parameter[GFX_ARG_ANIM_DELAY_FIXED];
1373 if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1374 graphic_info[graphic].anim_delay_random =
1375 parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1376 if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1377 graphic_info[graphic].post_delay_fixed =
1378 parameter[GFX_ARG_POST_DELAY_FIXED];
1379 if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1380 graphic_info[graphic].post_delay_random =
1381 parameter[GFX_ARG_POST_DELAY_RANDOM];
1383 /* this is only used for toon animations */
1384 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
1385 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
1387 /* this is only used for drawing font characters */
1388 graphic_info[graphic].draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
1389 graphic_info[graphic].draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
1391 /* this is only used for drawing envelope graphics */
1392 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1394 /* optional graphic for cloning all graphics settings */
1395 if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
1396 graphic_info[graphic].clone_from = parameter[GFX_ARG_CLONE_FROM];
1398 /* optional settings for drawing title screens and title messages */
1399 if (parameter[GFX_ARG_FADE_MODE] != ARG_UNDEFINED_VALUE)
1400 graphic_info[graphic].fade_mode = parameter[GFX_ARG_FADE_MODE];
1401 if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE)
1402 graphic_info[graphic].fade_delay = parameter[GFX_ARG_FADE_DELAY];
1403 if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE)
1404 graphic_info[graphic].post_delay = parameter[GFX_ARG_POST_DELAY];
1405 if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE)
1406 graphic_info[graphic].auto_delay = parameter[GFX_ARG_AUTO_DELAY];
1407 if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE)
1408 graphic_info[graphic].align = parameter[GFX_ARG_ALIGN];
1409 if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE)
1410 graphic_info[graphic].valign = parameter[GFX_ARG_VALIGN];
1411 if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
1412 graphic_info[graphic].sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
1414 UPDATE_BUSY_STATE();
1417 static void set_cloned_graphic_parameters(int graphic)
1419 int fallback_graphic = IMG_CHAR_EXCLAM;
1420 int max_num_images = getImageListSize();
1421 int clone_graphic = graphic_info[graphic].clone_from;
1422 int num_references_followed = 1;
1424 while (graphic_info[clone_graphic].clone_from != -1 &&
1425 num_references_followed < max_num_images)
1427 clone_graphic = graphic_info[clone_graphic].clone_from;
1429 num_references_followed++;
1432 if (num_references_followed >= max_num_images)
1434 Error(ERR_INFO_LINE, "-");
1435 Error(ERR_INFO, "warning: error found in config file:");
1436 Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1437 Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(graphic));
1438 Error(ERR_INFO, "error: loop discovered when resolving cloned graphics");
1439 Error(ERR_INFO, "custom graphic rejected for this element/action");
1441 if (graphic == fallback_graphic)
1442 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1444 Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1445 Error(ERR_INFO_LINE, "-");
1447 graphic_info[graphic] = graphic_info[fallback_graphic];
1451 graphic_info[graphic] = graphic_info[clone_graphic];
1452 graphic_info[graphic].clone_from = clone_graphic;
1456 static void InitGraphicInfo()
1458 int fallback_graphic = IMG_CHAR_EXCLAM;
1459 int num_images = getImageListSize();
1462 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1463 static boolean clipmasks_initialized = FALSE;
1465 XGCValues clip_gc_values;
1466 unsigned long clip_gc_valuemask;
1467 GC copy_clipmask_gc = None;
1470 /* use image size as default values for width and height for these images */
1471 static int full_size_graphics[] =
1476 IMG_BACKGROUND_ENVELOPE_1,
1477 IMG_BACKGROUND_ENVELOPE_2,
1478 IMG_BACKGROUND_ENVELOPE_3,
1479 IMG_BACKGROUND_ENVELOPE_4,
1482 IMG_BACKGROUND_TITLE_INITIAL,
1483 IMG_BACKGROUND_TITLE,
1484 IMG_BACKGROUND_MAIN,
1485 IMG_BACKGROUND_LEVELS,
1486 IMG_BACKGROUND_SCORES,
1487 IMG_BACKGROUND_EDITOR,
1488 IMG_BACKGROUND_INFO,
1489 IMG_BACKGROUND_INFO_ELEMENTS,
1490 IMG_BACKGROUND_INFO_MUSIC,
1491 IMG_BACKGROUND_INFO_CREDITS,
1492 IMG_BACKGROUND_INFO_PROGRAM,
1493 IMG_BACKGROUND_INFO_LEVELSET,
1494 IMG_BACKGROUND_SETUP,
1495 IMG_BACKGROUND_DOOR,
1497 IMG_TITLESCREEN_INITIAL_1,
1498 IMG_TITLESCREEN_INITIAL_2,
1499 IMG_TITLESCREEN_INITIAL_3,
1500 IMG_TITLESCREEN_INITIAL_4,
1501 IMG_TITLESCREEN_INITIAL_5,
1511 checked_free(graphic_info);
1513 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1516 /* initialize "use_image_size" flag with default value */
1517 for (i = 0; i < num_images; i++)
1518 graphic_info[i].use_image_size = FALSE;
1520 /* initialize "use_image_size" flag from static configuration above */
1521 for (i = 0; full_size_graphics[i] != -1; i++)
1522 graphic_info[full_size_graphics[i]].use_image_size = TRUE;
1525 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1526 if (clipmasks_initialized)
1528 for (i = 0; i < num_images; i++)
1530 if (graphic_info[i].clip_mask)
1531 XFreePixmap(display, graphic_info[i].clip_mask);
1532 if (graphic_info[i].clip_gc)
1533 XFreeGC(display, graphic_info[i].clip_gc);
1535 graphic_info[i].clip_mask = None;
1536 graphic_info[i].clip_gc = None;
1541 /* first set all graphic paramaters ... */
1542 for (i = 0; i < num_images; i++)
1543 set_graphic_parameters(i);
1545 /* ... then copy these parameters for cloned graphics */
1546 for (i = 0; i < num_images; i++)
1547 if (graphic_info[i].clone_from != -1)
1548 set_cloned_graphic_parameters(i);
1550 for (i = 0; i < num_images; i++)
1555 int first_frame, last_frame;
1556 int src_bitmap_width, src_bitmap_height;
1558 /* now check if no animation frames are outside of the loaded image */
1560 if (graphic_info[i].bitmap == NULL)
1561 continue; /* skip check for optional images that are undefined */
1563 /* get image size (this can differ from the standard element tile size!) */
1564 width = graphic_info[i].width;
1565 height = graphic_info[i].height;
1567 /* get final bitmap size (with scaling, but without small images) */
1568 src_bitmap_width = graphic_info[i].src_image_width;
1569 src_bitmap_height = graphic_info[i].src_image_height;
1571 /* check if first animation frame is inside specified bitmap */
1574 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1577 /* this avoids calculating wrong start position for out-of-bounds frame */
1578 src_x = graphic_info[i].src_x;
1579 src_y = graphic_info[i].src_y;
1582 if (src_x < 0 || src_y < 0 ||
1583 src_x + width > src_bitmap_width ||
1584 src_y + height > src_bitmap_height)
1586 Error(ERR_INFO_LINE, "-");
1587 Error(ERR_INFO, "warning: error found in config file:");
1588 Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1589 Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1590 Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1592 "error: first animation frame out of bounds (%d, %d) [%d, %d]",
1593 src_x, src_y, src_bitmap_width, src_bitmap_height);
1594 Error(ERR_INFO, "custom graphic rejected for this element/action");
1596 if (i == fallback_graphic)
1597 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1599 Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1600 Error(ERR_INFO_LINE, "-");
1602 graphic_info[i] = graphic_info[fallback_graphic];
1605 /* check if last animation frame is inside specified bitmap */
1607 last_frame = graphic_info[i].anim_frames - 1;
1608 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1610 if (src_x < 0 || src_y < 0 ||
1611 src_x + width > src_bitmap_width ||
1612 src_y + height > src_bitmap_height)
1614 Error(ERR_INFO_LINE, "-");
1615 Error(ERR_INFO, "warning: error found in config file:");
1616 Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1617 Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1618 Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1620 "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
1621 last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
1622 Error(ERR_INFO, "custom graphic rejected for this element/action");
1624 if (i == fallback_graphic)
1625 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1627 Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1628 Error(ERR_INFO_LINE, "-");
1630 graphic_info[i] = graphic_info[fallback_graphic];
1633 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1634 /* currently we only need a tile clip mask from the first frame */
1635 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1637 if (copy_clipmask_gc == None)
1639 clip_gc_values.graphics_exposures = False;
1640 clip_gc_valuemask = GCGraphicsExposures;
1641 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1642 clip_gc_valuemask, &clip_gc_values);
1645 graphic_info[i].clip_mask =
1646 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1648 src_pixmap = src_bitmap->clip_mask;
1649 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1650 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1652 clip_gc_values.graphics_exposures = False;
1653 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1654 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1656 graphic_info[i].clip_gc =
1657 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1661 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1662 if (copy_clipmask_gc)
1663 XFreeGC(display, copy_clipmask_gc);
1665 clipmasks_initialized = TRUE;
1669 static void InitElementSoundInfo()
1671 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1672 int num_property_mappings = getSoundListPropertyMappingSize();
1675 /* set values to -1 to identify later as "uninitialized" values */
1676 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1677 for (act = 0; act < NUM_ACTIONS; act++)
1678 element_info[i].sound[act] = -1;
1680 /* initialize element/sound mapping from static configuration */
1681 for (i = 0; element_to_sound[i].element > -1; i++)
1683 int element = element_to_sound[i].element;
1684 int action = element_to_sound[i].action;
1685 int sound = element_to_sound[i].sound;
1686 boolean is_class = element_to_sound[i].is_class;
1689 action = ACTION_DEFAULT;
1692 element_info[element].sound[action] = sound;
1694 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1695 if (strEqual(element_info[j].class_name,
1696 element_info[element].class_name))
1697 element_info[j].sound[action] = sound;
1700 /* initialize element class/sound mapping from dynamic configuration */
1701 for (i = 0; i < num_property_mappings; i++)
1703 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1704 int action = property_mapping[i].ext1_index;
1705 int sound = property_mapping[i].artwork_index;
1707 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1711 action = ACTION_DEFAULT;
1713 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1714 if (strEqual(element_info[j].class_name,
1715 element_info[element_class].class_name))
1716 element_info[j].sound[action] = sound;
1719 /* initialize element/sound mapping from dynamic configuration */
1720 for (i = 0; i < num_property_mappings; i++)
1722 int element = property_mapping[i].base_index;
1723 int action = property_mapping[i].ext1_index;
1724 int sound = property_mapping[i].artwork_index;
1726 if (element >= MAX_NUM_ELEMENTS)
1730 action = ACTION_DEFAULT;
1732 element_info[element].sound[action] = sound;
1735 /* now set all '-1' values to element specific default values */
1736 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1738 for (act = 0; act < NUM_ACTIONS; act++)
1740 /* generic default action sound (defined by "[default]" directive) */
1741 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1743 /* look for special default action sound (classic game specific) */
1744 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1745 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1746 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1747 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1748 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1749 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1751 /* !!! there's no such thing as a "default action sound" !!! */
1753 /* look for element specific default sound (independent from action) */
1754 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1755 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1759 /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
1760 /* !!! make this better !!! */
1761 if (i == EL_EMPTY_SPACE)
1762 default_action_sound = element_info[EL_DEFAULT].sound[act];
1765 /* no sound for this specific action -- use default action sound */
1766 if (element_info[i].sound[act] == -1)
1767 element_info[i].sound[act] = default_action_sound;
1771 /* copy sound settings to some elements that are only stored in level file
1772 in native R'n'D levels, but are used by game engine in native EM levels */
1773 for (i = 0; copy_properties[i][0] != -1; i++)
1774 for (j = 1; j <= 4; j++)
1775 for (act = 0; act < NUM_ACTIONS; act++)
1776 element_info[copy_properties[i][j]].sound[act] =
1777 element_info[copy_properties[i][0]].sound[act];
1780 static void InitGameModeSoundInfo()
1784 /* set values to -1 to identify later as "uninitialized" values */
1785 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1788 /* initialize gamemode/sound mapping from static configuration */
1789 for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1791 int gamemode = gamemode_to_sound[i].gamemode;
1792 int sound = gamemode_to_sound[i].sound;
1795 gamemode = GAME_MODE_DEFAULT;
1797 menu.sound[gamemode] = sound;
1800 /* now set all '-1' values to levelset specific default values */
1801 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1802 if (menu.sound[i] == -1)
1803 menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1806 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1807 if (menu.sound[i] != -1)
1808 printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1812 static void set_sound_parameters(int sound, char **parameter_raw)
1814 int parameter[NUM_SND_ARGS];
1817 /* get integer values from string parameters */
1818 for (i = 0; i < NUM_SND_ARGS; i++)
1820 get_parameter_value(parameter_raw[i],
1821 sound_config_suffix[i].token,
1822 sound_config_suffix[i].type);
1824 /* explicit loop mode setting in configuration overrides default value */
1825 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1826 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1828 /* sound volume to change the original volume when loading the sound file */
1829 sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1831 /* sound priority to give certain sounds a higher or lower priority */
1832 sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
1835 static void InitSoundInfo()
1837 int *sound_effect_properties;
1838 int num_sounds = getSoundListSize();
1841 checked_free(sound_info);
1843 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1844 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1846 /* initialize sound effect for all elements to "no sound" */
1847 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1848 for (j = 0; j < NUM_ACTIONS; j++)
1849 element_info[i].sound[j] = SND_UNDEFINED;
1851 for (i = 0; i < num_sounds; i++)
1853 struct FileInfo *sound = getSoundListEntry(i);
1854 int len_effect_text = strlen(sound->token);
1856 sound_effect_properties[i] = ACTION_OTHER;
1857 sound_info[i].loop = FALSE; /* default: play sound only once */
1860 printf("::: sound %d: '%s'\n", i, sound->token);
1863 /* determine all loop sounds and identify certain sound classes */
1865 for (j = 0; element_action_info[j].suffix; j++)
1867 int len_action_text = strlen(element_action_info[j].suffix);
1869 if (len_action_text < len_effect_text &&
1870 strEqual(&sound->token[len_effect_text - len_action_text],
1871 element_action_info[j].suffix))
1873 sound_effect_properties[i] = element_action_info[j].value;
1874 sound_info[i].loop = element_action_info[j].is_loop_sound;
1880 /* associate elements and some selected sound actions */
1882 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1884 if (element_info[j].class_name)
1886 int len_class_text = strlen(element_info[j].class_name);
1888 if (len_class_text + 1 < len_effect_text &&
1889 strncmp(sound->token,
1890 element_info[j].class_name, len_class_text) == 0 &&
1891 sound->token[len_class_text] == '.')
1893 int sound_action_value = sound_effect_properties[i];
1895 element_info[j].sound[sound_action_value] = i;
1900 set_sound_parameters(i, sound->parameter);
1903 free(sound_effect_properties);
1906 static void InitGameModeMusicInfo()
1908 struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1909 int num_property_mappings = getMusicListPropertyMappingSize();
1910 int default_levelset_music = -1;
1913 /* set values to -1 to identify later as "uninitialized" values */
1914 for (i = 0; i < MAX_LEVELS; i++)
1915 levelset.music[i] = -1;
1916 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1919 /* initialize gamemode/music mapping from static configuration */
1920 for (i = 0; gamemode_to_music[i].music > -1; i++)
1922 int gamemode = gamemode_to_music[i].gamemode;
1923 int music = gamemode_to_music[i].music;
1926 printf("::: gamemode == %d, music == %d\n", gamemode, music);
1930 gamemode = GAME_MODE_DEFAULT;
1932 menu.music[gamemode] = music;
1935 /* initialize gamemode/music mapping from dynamic configuration */
1936 for (i = 0; i < num_property_mappings; i++)
1938 int prefix = property_mapping[i].base_index;
1939 int gamemode = property_mapping[i].ext1_index;
1940 int level = property_mapping[i].ext2_index;
1941 int music = property_mapping[i].artwork_index;
1944 printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1945 prefix, gamemode, level, music);
1948 if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1952 gamemode = GAME_MODE_DEFAULT;
1954 /* level specific music only allowed for in-game music */
1955 if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1956 gamemode = GAME_MODE_PLAYING;
1961 default_levelset_music = music;
1964 if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1965 levelset.music[level] = music;
1966 if (gamemode != GAME_MODE_PLAYING)
1967 menu.music[gamemode] = music;
1970 /* now set all '-1' values to menu specific default values */
1971 /* (undefined values of "levelset.music[]" might stay at "-1" to
1972 allow dynamic selection of music files from music directory!) */
1973 for (i = 0; i < MAX_LEVELS; i++)
1974 if (levelset.music[i] == -1)
1975 levelset.music[i] = default_levelset_music;
1976 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1977 if (menu.music[i] == -1)
1978 menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1981 for (i = 0; i < MAX_LEVELS; i++)
1982 if (levelset.music[i] != -1)
1983 printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1984 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1985 if (menu.music[i] != -1)
1986 printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1990 static void set_music_parameters(int music, char **parameter_raw)
1992 int parameter[NUM_MUS_ARGS];
1995 /* get integer values from string parameters */
1996 for (i = 0; i < NUM_MUS_ARGS; i++)
1998 get_parameter_value(parameter_raw[i],
1999 music_config_suffix[i].token,
2000 music_config_suffix[i].type);
2002 /* explicit loop mode setting in configuration overrides default value */
2003 if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2004 music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
2007 static void InitMusicInfo()
2009 int num_music = getMusicListSize();
2012 checked_free(music_info);
2014 music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
2016 for (i = 0; i < num_music; i++)
2018 struct FileInfo *music = getMusicListEntry(i);
2019 int len_music_text = strlen(music->token);
2021 music_info[i].loop = TRUE; /* default: play music in loop mode */
2023 /* determine all loop music */
2025 for (j = 0; music_prefix_info[j].prefix; j++)
2027 int len_prefix_text = strlen(music_prefix_info[j].prefix);
2029 if (len_prefix_text < len_music_text &&
2030 strncmp(music->token,
2031 music_prefix_info[j].prefix, len_prefix_text) == 0)
2033 music_info[i].loop = music_prefix_info[j].is_loop_music;
2039 set_music_parameters(i, music->parameter);
2043 static void ReinitializeGraphics()
2045 print_init_timestamp("INIT ReinitializeGraphics");
2047 InitGraphicInfo(); /* graphic properties mapping */
2048 print_init_timestamp("TIME InitGraphicInfo");
2049 InitElementGraphicInfo(); /* element game graphic mapping */
2050 print_init_timestamp("TIME InitElementGraphicInfo");
2051 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
2052 print_init_timestamp("TIME InitElementSpecialGraphicInfo");
2054 InitElementSmallImages(); /* scale elements to all needed sizes */
2055 print_init_timestamp("TIME InitElementSmallImages");
2056 InitScaledImages(); /* scale all other images, if needed */
2057 print_init_timestamp("TIME InitScaledImages");
2058 InitFontGraphicInfo(); /* initialize text drawing functions */
2059 print_init_timestamp("TIME InitFontGraphicInfo");
2061 InitGraphicInfo_EM(); /* graphic mapping for EM engine */
2062 print_init_timestamp("TIME InitGraphicInfo_EM");
2064 SetMainBackgroundImage(IMG_BACKGROUND);
2065 print_init_timestamp("TIME SetMainBackgroundImage");
2066 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
2067 print_init_timestamp("TIME SetDoorBackgroundImage");
2070 print_init_timestamp("TIME InitGadgets");
2072 print_init_timestamp("TIME InitToons");
2074 print_init_timestamp("DONE ReinitializeGraphics");
2077 static void ReinitializeSounds()
2079 InitSoundInfo(); /* sound properties mapping */
2080 InitElementSoundInfo(); /* element game sound mapping */
2081 InitGameModeSoundInfo(); /* game mode sound mapping */
2083 InitPlayLevelSound(); /* internal game sound settings */
2086 static void ReinitializeMusic()
2088 InitMusicInfo(); /* music properties mapping */
2089 InitGameModeMusicInfo(); /* game mode music mapping */
2092 static int get_special_property_bit(int element, int property_bit_nr)
2094 struct PropertyBitInfo
2100 static struct PropertyBitInfo pb_can_move_into_acid[] =
2102 /* the player may be able fall into acid when gravity is activated */
2107 { EL_SP_MURPHY, 0 },
2108 { EL_SOKOBAN_FIELD_PLAYER, 0 },
2110 /* all elements that can move may be able to also move into acid */
2113 { EL_BUG_RIGHT, 1 },
2116 { EL_SPACESHIP, 2 },
2117 { EL_SPACESHIP_LEFT, 2 },
2118 { EL_SPACESHIP_RIGHT, 2 },
2119 { EL_SPACESHIP_UP, 2 },
2120 { EL_SPACESHIP_DOWN, 2 },
2121 { EL_BD_BUTTERFLY, 3 },
2122 { EL_BD_BUTTERFLY_LEFT, 3 },
2123 { EL_BD_BUTTERFLY_RIGHT, 3 },
2124 { EL_BD_BUTTERFLY_UP, 3 },
2125 { EL_BD_BUTTERFLY_DOWN, 3 },
2126 { EL_BD_FIREFLY, 4 },
2127 { EL_BD_FIREFLY_LEFT, 4 },
2128 { EL_BD_FIREFLY_RIGHT, 4 },
2129 { EL_BD_FIREFLY_UP, 4 },
2130 { EL_BD_FIREFLY_DOWN, 4 },
2132 { EL_YAMYAM_LEFT, 5 },
2133 { EL_YAMYAM_RIGHT, 5 },
2134 { EL_YAMYAM_UP, 5 },
2135 { EL_YAMYAM_DOWN, 5 },
2136 { EL_DARK_YAMYAM, 6 },
2139 { EL_PACMAN_LEFT, 8 },
2140 { EL_PACMAN_RIGHT, 8 },
2141 { EL_PACMAN_UP, 8 },
2142 { EL_PACMAN_DOWN, 8 },
2144 { EL_MOLE_LEFT, 9 },
2145 { EL_MOLE_RIGHT, 9 },
2147 { EL_MOLE_DOWN, 9 },
2151 { EL_SATELLITE, 13 },
2152 { EL_SP_SNIKSNAK, 14 },
2153 { EL_SP_ELECTRON, 15 },
2156 { EL_EMC_ANDROID, 18 },
2161 static struct PropertyBitInfo pb_dont_collide_with[] =
2163 { EL_SP_SNIKSNAK, 0 },
2164 { EL_SP_ELECTRON, 1 },
2172 struct PropertyBitInfo *pb_info;
2175 { EP_CAN_MOVE_INTO_ACID, pb_can_move_into_acid },
2176 { EP_DONT_COLLIDE_WITH, pb_dont_collide_with },
2181 struct PropertyBitInfo *pb_info = NULL;
2184 for (i = 0; pb_definition[i].bit_nr != -1; i++)
2185 if (pb_definition[i].bit_nr == property_bit_nr)
2186 pb_info = pb_definition[i].pb_info;
2188 if (pb_info == NULL)
2191 for (i = 0; pb_info[i].element != -1; i++)
2192 if (pb_info[i].element == element)
2193 return pb_info[i].bit_nr;
2198 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
2199 boolean property_value)
2201 int bit_nr = get_special_property_bit(element, property_bit_nr);
2206 *bitfield |= (1 << bit_nr);
2208 *bitfield &= ~(1 << bit_nr);
2212 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
2214 int bit_nr = get_special_property_bit(element, property_bit_nr);
2217 return ((*bitfield & (1 << bit_nr)) != 0);
2222 static void ResolveGroupElementExt(int group_element, int recursion_depth)
2224 static int group_nr;
2225 static struct ElementGroupInfo *group;
2226 struct ElementGroupInfo *actual_group = element_info[group_element].group;
2229 if (actual_group == NULL) /* not yet initialized */
2232 if (recursion_depth > NUM_GROUP_ELEMENTS) /* recursion too deep */
2234 Error(ERR_WARN, "recursion too deep when resolving group element %d",
2235 group_element - EL_GROUP_START + 1);
2237 /* replace element which caused too deep recursion by question mark */
2238 group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
2243 if (recursion_depth == 0) /* initialization */
2245 group = actual_group;
2246 group_nr = GROUP_NR(group_element);
2248 group->num_elements_resolved = 0;
2249 group->choice_pos = 0;
2251 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2252 element_info[i].in_group[group_nr] = FALSE;
2255 for (i = 0; i < actual_group->num_elements; i++)
2257 int element = actual_group->element[i];
2259 if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
2262 if (IS_GROUP_ELEMENT(element))
2263 ResolveGroupElementExt(element, recursion_depth + 1);
2266 group->element_resolved[group->num_elements_resolved++] = element;
2267 element_info[element].in_group[group_nr] = TRUE;
2272 void ResolveGroupElement(int group_element)
2274 ResolveGroupElementExt(group_element, 0);
2277 void InitElementPropertiesStatic()
2279 static int ep_diggable[] =
2284 EL_SP_BUGGY_BASE_ACTIVATING,
2287 EL_INVISIBLE_SAND_ACTIVE,
2290 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
2291 /* (if amoeba can grow into anything diggable, maybe keep these out) */
2296 EL_SP_BUGGY_BASE_ACTIVE,
2303 static int ep_collectible_only[] =
2325 EL_DYNABOMB_INCREASE_NUMBER,
2326 EL_DYNABOMB_INCREASE_SIZE,
2327 EL_DYNABOMB_INCREASE_POWER,
2345 /* !!! handle separately !!! */
2346 EL_DC_LANDMINE, /* deadly when running into, but can be snapped */
2352 static int ep_dont_run_into[] =
2354 /* same elements as in 'ep_dont_touch' */
2360 /* same elements as in 'ep_dont_collide_with' */
2372 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
2377 EL_SP_BUGGY_BASE_ACTIVE,
2384 static int ep_dont_collide_with[] =
2386 /* same elements as in 'ep_dont_touch' */
2403 static int ep_dont_touch[] =
2413 static int ep_indestructible[] =
2417 EL_ACID_POOL_TOPLEFT,
2418 EL_ACID_POOL_TOPRIGHT,
2419 EL_ACID_POOL_BOTTOMLEFT,
2420 EL_ACID_POOL_BOTTOM,
2421 EL_ACID_POOL_BOTTOMRIGHT,
2422 EL_SP_HARDWARE_GRAY,
2423 EL_SP_HARDWARE_GREEN,
2424 EL_SP_HARDWARE_BLUE,
2426 EL_SP_HARDWARE_YELLOW,
2427 EL_SP_HARDWARE_BASE_1,
2428 EL_SP_HARDWARE_BASE_2,
2429 EL_SP_HARDWARE_BASE_3,
2430 EL_SP_HARDWARE_BASE_4,
2431 EL_SP_HARDWARE_BASE_5,
2432 EL_SP_HARDWARE_BASE_6,
2433 EL_INVISIBLE_STEELWALL,
2434 EL_INVISIBLE_STEELWALL_ACTIVE,
2435 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2436 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2437 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2438 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2439 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2440 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2441 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2442 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2443 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2444 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2445 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2446 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2448 EL_LIGHT_SWITCH_ACTIVE,
2449 EL_SIGN_EXCLAMATION,
2450 EL_SIGN_RADIOACTIVITY,
2457 EL_SIGN_ENTRY_FORBIDDEN,
2458 EL_SIGN_EMERGENCY_EXIT,
2466 EL_STEEL_EXIT_CLOSED,
2468 EL_EM_STEEL_EXIT_CLOSED,
2469 EL_EM_STEEL_EXIT_OPEN,
2470 EL_DC_STEELWALL_1_LEFT,
2471 EL_DC_STEELWALL_1_RIGHT,
2472 EL_DC_STEELWALL_1_TOP,
2473 EL_DC_STEELWALL_1_BOTTOM,
2474 EL_DC_STEELWALL_1_HORIZONTAL,
2475 EL_DC_STEELWALL_1_VERTICAL,
2476 EL_DC_STEELWALL_1_TOPLEFT,
2477 EL_DC_STEELWALL_1_TOPRIGHT,
2478 EL_DC_STEELWALL_1_BOTTOMLEFT,
2479 EL_DC_STEELWALL_1_BOTTOMRIGHT,
2480 EL_DC_STEELWALL_1_TOPLEFT_2,
2481 EL_DC_STEELWALL_1_TOPRIGHT_2,
2482 EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2483 EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2484 EL_DC_STEELWALL_2_LEFT,
2485 EL_DC_STEELWALL_2_RIGHT,
2486 EL_DC_STEELWALL_2_TOP,
2487 EL_DC_STEELWALL_2_BOTTOM,
2488 EL_DC_STEELWALL_2_HORIZONTAL,
2489 EL_DC_STEELWALL_2_VERTICAL,
2490 EL_DC_STEELWALL_2_MIDDLE,
2491 EL_DC_STEELWALL_2_SINGLE,
2492 EL_STEELWALL_SLIPPERY,
2506 EL_GATE_1_GRAY_ACTIVE,
2507 EL_GATE_2_GRAY_ACTIVE,
2508 EL_GATE_3_GRAY_ACTIVE,
2509 EL_GATE_4_GRAY_ACTIVE,
2518 EL_EM_GATE_1_GRAY_ACTIVE,
2519 EL_EM_GATE_2_GRAY_ACTIVE,
2520 EL_EM_GATE_3_GRAY_ACTIVE,
2521 EL_EM_GATE_4_GRAY_ACTIVE,
2530 EL_EMC_GATE_5_GRAY_ACTIVE,
2531 EL_EMC_GATE_6_GRAY_ACTIVE,
2532 EL_EMC_GATE_7_GRAY_ACTIVE,
2533 EL_EMC_GATE_8_GRAY_ACTIVE,
2535 EL_DC_GATE_WHITE_GRAY,
2536 EL_DC_GATE_WHITE_GRAY_ACTIVE,
2537 EL_DC_GATE_FAKE_GRAY,
2539 EL_SWITCHGATE_OPENING,
2540 EL_SWITCHGATE_CLOSED,
2541 EL_SWITCHGATE_CLOSING,
2543 EL_DC_SWITCHGATE_SWITCH_UP,
2544 EL_DC_SWITCHGATE_SWITCH_DOWN,
2547 EL_TIMEGATE_OPENING,
2549 EL_TIMEGATE_CLOSING,
2551 EL_DC_TIMEGATE_SWITCH,
2552 EL_DC_TIMEGATE_SWITCH_ACTIVE,
2557 EL_TUBE_VERTICAL_LEFT,
2558 EL_TUBE_VERTICAL_RIGHT,
2559 EL_TUBE_HORIZONTAL_UP,
2560 EL_TUBE_HORIZONTAL_DOWN,
2565 EL_EXPANDABLE_STEELWALL_HORIZONTAL,
2566 EL_EXPANDABLE_STEELWALL_VERTICAL,
2567 EL_EXPANDABLE_STEELWALL_ANY,
2572 static int ep_slippery[] =
2586 EL_ROBOT_WHEEL_ACTIVE,
2592 EL_ACID_POOL_TOPLEFT,
2593 EL_ACID_POOL_TOPRIGHT,
2603 EL_STEELWALL_SLIPPERY,
2606 EL_EMC_WALL_SLIPPERY_1,
2607 EL_EMC_WALL_SLIPPERY_2,
2608 EL_EMC_WALL_SLIPPERY_3,
2609 EL_EMC_WALL_SLIPPERY_4,
2611 EL_EMC_MAGIC_BALL_ACTIVE,
2616 static int ep_can_change[] =
2621 static int ep_can_move[] =
2623 /* same elements as in 'pb_can_move_into_acid' */
2646 static int ep_can_fall[] =
2660 EL_QUICKSAND_FAST_FULL,
2662 EL_BD_MAGIC_WALL_FULL,
2663 EL_DC_MAGIC_WALL_FULL,
2677 static int ep_can_smash_player[] =
2703 static int ep_can_smash_enemies[] =
2712 static int ep_can_smash_everything[] =
2721 static int ep_explodes_by_fire[] =
2723 /* same elements as in 'ep_explodes_impact' */
2728 /* same elements as in 'ep_explodes_smashed' */
2738 EL_EM_DYNAMITE_ACTIVE,
2739 EL_DYNABOMB_PLAYER_1_ACTIVE,
2740 EL_DYNABOMB_PLAYER_2_ACTIVE,
2741 EL_DYNABOMB_PLAYER_3_ACTIVE,
2742 EL_DYNABOMB_PLAYER_4_ACTIVE,
2743 EL_DYNABOMB_INCREASE_NUMBER,
2744 EL_DYNABOMB_INCREASE_SIZE,
2745 EL_DYNABOMB_INCREASE_POWER,
2746 EL_SP_DISK_RED_ACTIVE,
2760 static int ep_explodes_smashed[] =
2762 /* same elements as in 'ep_explodes_impact' */
2776 static int ep_explodes_impact[] =
2785 static int ep_walkable_over[] =
2789 EL_SOKOBAN_FIELD_EMPTY,
2795 EL_EM_STEEL_EXIT_OPEN,
2804 EL_GATE_1_GRAY_ACTIVE,
2805 EL_GATE_2_GRAY_ACTIVE,
2806 EL_GATE_3_GRAY_ACTIVE,
2807 EL_GATE_4_GRAY_ACTIVE,
2815 static int ep_walkable_inside[] =
2820 EL_TUBE_VERTICAL_LEFT,
2821 EL_TUBE_VERTICAL_RIGHT,
2822 EL_TUBE_HORIZONTAL_UP,
2823 EL_TUBE_HORIZONTAL_DOWN,
2832 static int ep_walkable_under[] =
2837 static int ep_passable_over[] =
2847 EL_EM_GATE_1_GRAY_ACTIVE,
2848 EL_EM_GATE_2_GRAY_ACTIVE,
2849 EL_EM_GATE_3_GRAY_ACTIVE,
2850 EL_EM_GATE_4_GRAY_ACTIVE,
2859 EL_EMC_GATE_5_GRAY_ACTIVE,
2860 EL_EMC_GATE_6_GRAY_ACTIVE,
2861 EL_EMC_GATE_7_GRAY_ACTIVE,
2862 EL_EMC_GATE_8_GRAY_ACTIVE,
2864 EL_DC_GATE_WHITE_GRAY,
2865 EL_DC_GATE_WHITE_GRAY_ACTIVE,
2872 static int ep_passable_inside[] =
2878 EL_SP_PORT_HORIZONTAL,
2879 EL_SP_PORT_VERTICAL,
2881 EL_SP_GRAVITY_PORT_LEFT,
2882 EL_SP_GRAVITY_PORT_RIGHT,
2883 EL_SP_GRAVITY_PORT_UP,
2884 EL_SP_GRAVITY_PORT_DOWN,
2885 EL_SP_GRAVITY_ON_PORT_LEFT,
2886 EL_SP_GRAVITY_ON_PORT_RIGHT,
2887 EL_SP_GRAVITY_ON_PORT_UP,
2888 EL_SP_GRAVITY_ON_PORT_DOWN,
2889 EL_SP_GRAVITY_OFF_PORT_LEFT,
2890 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2891 EL_SP_GRAVITY_OFF_PORT_UP,
2892 EL_SP_GRAVITY_OFF_PORT_DOWN,
2897 static int ep_passable_under[] =
2902 static int ep_droppable[] =
2907 static int ep_explodes_1x1_old[] =
2912 static int ep_pushable[] =
2924 EL_SOKOBAN_FIELD_FULL,
2933 static int ep_explodes_cross_old[] =
2938 static int ep_protected[] =
2940 /* same elements as in 'ep_walkable_inside' */
2944 EL_TUBE_VERTICAL_LEFT,
2945 EL_TUBE_VERTICAL_RIGHT,
2946 EL_TUBE_HORIZONTAL_UP,
2947 EL_TUBE_HORIZONTAL_DOWN,
2953 /* same elements as in 'ep_passable_over' */
2962 EL_EM_GATE_1_GRAY_ACTIVE,
2963 EL_EM_GATE_2_GRAY_ACTIVE,
2964 EL_EM_GATE_3_GRAY_ACTIVE,
2965 EL_EM_GATE_4_GRAY_ACTIVE,
2974 EL_EMC_GATE_5_GRAY_ACTIVE,
2975 EL_EMC_GATE_6_GRAY_ACTIVE,
2976 EL_EMC_GATE_7_GRAY_ACTIVE,
2977 EL_EMC_GATE_8_GRAY_ACTIVE,
2979 EL_DC_GATE_WHITE_GRAY,
2980 EL_DC_GATE_WHITE_GRAY_ACTIVE,
2984 /* same elements as in 'ep_passable_inside' */
2989 EL_SP_PORT_HORIZONTAL,
2990 EL_SP_PORT_VERTICAL,
2992 EL_SP_GRAVITY_PORT_LEFT,
2993 EL_SP_GRAVITY_PORT_RIGHT,
2994 EL_SP_GRAVITY_PORT_UP,
2995 EL_SP_GRAVITY_PORT_DOWN,
2996 EL_SP_GRAVITY_ON_PORT_LEFT,
2997 EL_SP_GRAVITY_ON_PORT_RIGHT,
2998 EL_SP_GRAVITY_ON_PORT_UP,
2999 EL_SP_GRAVITY_ON_PORT_DOWN,
3000 EL_SP_GRAVITY_OFF_PORT_LEFT,
3001 EL_SP_GRAVITY_OFF_PORT_RIGHT,
3002 EL_SP_GRAVITY_OFF_PORT_UP,
3003 EL_SP_GRAVITY_OFF_PORT_DOWN,
3008 static int ep_throwable[] =
3013 static int ep_can_explode[] =
3015 /* same elements as in 'ep_explodes_impact' */
3020 /* same elements as in 'ep_explodes_smashed' */
3026 /* elements that can explode by explosion or by dragonfire */
3030 EL_EM_DYNAMITE_ACTIVE,
3031 EL_DYNABOMB_PLAYER_1_ACTIVE,
3032 EL_DYNABOMB_PLAYER_2_ACTIVE,
3033 EL_DYNABOMB_PLAYER_3_ACTIVE,
3034 EL_DYNABOMB_PLAYER_4_ACTIVE,
3035 EL_DYNABOMB_INCREASE_NUMBER,
3036 EL_DYNABOMB_INCREASE_SIZE,
3037 EL_DYNABOMB_INCREASE_POWER,
3038 EL_SP_DISK_RED_ACTIVE,
3046 /* elements that can explode only by explosion */
3052 static int ep_gravity_reachable[] =
3058 EL_INVISIBLE_SAND_ACTIVE,
3063 EL_SP_PORT_HORIZONTAL,
3064 EL_SP_PORT_VERTICAL,
3066 EL_SP_GRAVITY_PORT_LEFT,
3067 EL_SP_GRAVITY_PORT_RIGHT,
3068 EL_SP_GRAVITY_PORT_UP,
3069 EL_SP_GRAVITY_PORT_DOWN,
3070 EL_SP_GRAVITY_ON_PORT_LEFT,
3071 EL_SP_GRAVITY_ON_PORT_RIGHT,
3072 EL_SP_GRAVITY_ON_PORT_UP,
3073 EL_SP_GRAVITY_ON_PORT_DOWN,
3074 EL_SP_GRAVITY_OFF_PORT_LEFT,
3075 EL_SP_GRAVITY_OFF_PORT_RIGHT,
3076 EL_SP_GRAVITY_OFF_PORT_UP,
3077 EL_SP_GRAVITY_OFF_PORT_DOWN,
3083 static int ep_player[] =
3090 EL_SOKOBAN_FIELD_PLAYER,
3096 static int ep_can_pass_magic_wall[] =
3110 static int ep_can_pass_dc_magic_wall[] =
3126 static int ep_switchable[] =
3130 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3131 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3132 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3133 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3134 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3135 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3136 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3137 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3138 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3139 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3140 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3141 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3142 EL_SWITCHGATE_SWITCH_UP,
3143 EL_SWITCHGATE_SWITCH_DOWN,
3144 EL_DC_SWITCHGATE_SWITCH_UP,
3145 EL_DC_SWITCHGATE_SWITCH_DOWN,
3147 EL_LIGHT_SWITCH_ACTIVE,
3149 EL_DC_TIMEGATE_SWITCH,
3150 EL_BALLOON_SWITCH_LEFT,
3151 EL_BALLOON_SWITCH_RIGHT,
3152 EL_BALLOON_SWITCH_UP,
3153 EL_BALLOON_SWITCH_DOWN,
3154 EL_BALLOON_SWITCH_ANY,
3155 EL_BALLOON_SWITCH_NONE,
3158 EL_EMC_MAGIC_BALL_SWITCH,
3159 EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
3164 static int ep_bd_element[] =
3198 static int ep_sp_element[] =
3200 /* should always be valid */
3203 /* standard classic Supaplex elements */
3210 EL_SP_HARDWARE_GRAY,
3218 EL_SP_GRAVITY_PORT_RIGHT,
3219 EL_SP_GRAVITY_PORT_DOWN,
3220 EL_SP_GRAVITY_PORT_LEFT,
3221 EL_SP_GRAVITY_PORT_UP,
3226 EL_SP_PORT_VERTICAL,
3227 EL_SP_PORT_HORIZONTAL,
3233 EL_SP_HARDWARE_BASE_1,
3234 EL_SP_HARDWARE_GREEN,
3235 EL_SP_HARDWARE_BLUE,
3237 EL_SP_HARDWARE_YELLOW,
3238 EL_SP_HARDWARE_BASE_2,
3239 EL_SP_HARDWARE_BASE_3,
3240 EL_SP_HARDWARE_BASE_4,
3241 EL_SP_HARDWARE_BASE_5,
3242 EL_SP_HARDWARE_BASE_6,
3246 /* additional elements that appeared in newer Supaplex levels */
3249 /* additional gravity port elements (not switching, but setting gravity) */
3250 EL_SP_GRAVITY_ON_PORT_LEFT,
3251 EL_SP_GRAVITY_ON_PORT_RIGHT,
3252 EL_SP_GRAVITY_ON_PORT_UP,
3253 EL_SP_GRAVITY_ON_PORT_DOWN,
3254 EL_SP_GRAVITY_OFF_PORT_LEFT,
3255 EL_SP_GRAVITY_OFF_PORT_RIGHT,
3256 EL_SP_GRAVITY_OFF_PORT_UP,
3257 EL_SP_GRAVITY_OFF_PORT_DOWN,
3259 /* more than one Murphy in a level results in an inactive clone */
3262 /* runtime Supaplex elements */
3263 EL_SP_DISK_RED_ACTIVE,
3264 EL_SP_TERMINAL_ACTIVE,
3265 EL_SP_BUGGY_BASE_ACTIVATING,
3266 EL_SP_BUGGY_BASE_ACTIVE,
3273 static int ep_sb_element[] =
3278 EL_SOKOBAN_FIELD_EMPTY,
3279 EL_SOKOBAN_FIELD_FULL,
3280 EL_SOKOBAN_FIELD_PLAYER,
3285 EL_INVISIBLE_STEELWALL,
3290 static int ep_gem[] =
3302 static int ep_food_dark_yamyam[] =
3330 static int ep_food_penguin[] =
3344 static int ep_food_pig[] =
3356 static int ep_historic_wall[] =
3367 EL_GATE_1_GRAY_ACTIVE,
3368 EL_GATE_2_GRAY_ACTIVE,
3369 EL_GATE_3_GRAY_ACTIVE,
3370 EL_GATE_4_GRAY_ACTIVE,
3379 EL_EM_GATE_1_GRAY_ACTIVE,
3380 EL_EM_GATE_2_GRAY_ACTIVE,
3381 EL_EM_GATE_3_GRAY_ACTIVE,
3382 EL_EM_GATE_4_GRAY_ACTIVE,
3389 EL_EXPANDABLE_WALL_HORIZONTAL,
3390 EL_EXPANDABLE_WALL_VERTICAL,
3391 EL_EXPANDABLE_WALL_ANY,
3392 EL_EXPANDABLE_WALL_GROWING,
3393 EL_BD_EXPANDABLE_WALL,
3400 EL_SP_HARDWARE_GRAY,
3401 EL_SP_HARDWARE_GREEN,
3402 EL_SP_HARDWARE_BLUE,
3404 EL_SP_HARDWARE_YELLOW,
3405 EL_SP_HARDWARE_BASE_1,
3406 EL_SP_HARDWARE_BASE_2,
3407 EL_SP_HARDWARE_BASE_3,
3408 EL_SP_HARDWARE_BASE_4,
3409 EL_SP_HARDWARE_BASE_5,
3410 EL_SP_HARDWARE_BASE_6,
3412 EL_SP_TERMINAL_ACTIVE,
3415 EL_INVISIBLE_STEELWALL,
3416 EL_INVISIBLE_STEELWALL_ACTIVE,
3418 EL_INVISIBLE_WALL_ACTIVE,
3419 EL_STEELWALL_SLIPPERY,
3436 static int ep_historic_solid[] =
3440 EL_EXPANDABLE_WALL_HORIZONTAL,
3441 EL_EXPANDABLE_WALL_VERTICAL,
3442 EL_EXPANDABLE_WALL_ANY,
3443 EL_BD_EXPANDABLE_WALL,
3456 EL_QUICKSAND_FILLING,
3457 EL_QUICKSAND_EMPTYING,
3459 EL_MAGIC_WALL_ACTIVE,
3460 EL_MAGIC_WALL_EMPTYING,
3461 EL_MAGIC_WALL_FILLING,
3465 EL_BD_MAGIC_WALL_ACTIVE,
3466 EL_BD_MAGIC_WALL_EMPTYING,
3467 EL_BD_MAGIC_WALL_FULL,
3468 EL_BD_MAGIC_WALL_FILLING,
3469 EL_BD_MAGIC_WALL_DEAD,
3478 EL_SP_TERMINAL_ACTIVE,
3482 EL_INVISIBLE_WALL_ACTIVE,
3483 EL_SWITCHGATE_SWITCH_UP,
3484 EL_SWITCHGATE_SWITCH_DOWN,
3485 EL_DC_SWITCHGATE_SWITCH_UP,
3486 EL_DC_SWITCHGATE_SWITCH_DOWN,
3488 EL_TIMEGATE_SWITCH_ACTIVE,
3489 EL_DC_TIMEGATE_SWITCH,
3490 EL_DC_TIMEGATE_SWITCH_ACTIVE,
3502 /* the following elements are a direct copy of "indestructible" elements,
3503 except "EL_ACID", which is "indestructible", but not "solid"! */
3508 EL_ACID_POOL_TOPLEFT,
3509 EL_ACID_POOL_TOPRIGHT,
3510 EL_ACID_POOL_BOTTOMLEFT,
3511 EL_ACID_POOL_BOTTOM,
3512 EL_ACID_POOL_BOTTOMRIGHT,
3513 EL_SP_HARDWARE_GRAY,
3514 EL_SP_HARDWARE_GREEN,
3515 EL_SP_HARDWARE_BLUE,
3517 EL_SP_HARDWARE_YELLOW,
3518 EL_SP_HARDWARE_BASE_1,
3519 EL_SP_HARDWARE_BASE_2,
3520 EL_SP_HARDWARE_BASE_3,
3521 EL_SP_HARDWARE_BASE_4,
3522 EL_SP_HARDWARE_BASE_5,
3523 EL_SP_HARDWARE_BASE_6,
3524 EL_INVISIBLE_STEELWALL,
3525 EL_INVISIBLE_STEELWALL_ACTIVE,
3526 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3527 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3528 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3529 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3530 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3531 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3532 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3533 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3534 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3535 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3536 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3537 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3539 EL_LIGHT_SWITCH_ACTIVE,
3540 EL_SIGN_EXCLAMATION,
3541 EL_SIGN_RADIOACTIVITY,
3548 EL_SIGN_ENTRY_FORBIDDEN,
3549 EL_SIGN_EMERGENCY_EXIT,
3557 EL_STEEL_EXIT_CLOSED,
3559 EL_DC_STEELWALL_1_LEFT,
3560 EL_DC_STEELWALL_1_RIGHT,
3561 EL_DC_STEELWALL_1_TOP,
3562 EL_DC_STEELWALL_1_BOTTOM,
3563 EL_DC_STEELWALL_1_HORIZONTAL,
3564 EL_DC_STEELWALL_1_VERTICAL,
3565 EL_DC_STEELWALL_1_TOPLEFT,
3566 EL_DC_STEELWALL_1_TOPRIGHT,
3567 EL_DC_STEELWALL_1_BOTTOMLEFT,
3568 EL_DC_STEELWALL_1_BOTTOMRIGHT,
3569 EL_DC_STEELWALL_1_TOPLEFT_2,
3570 EL_DC_STEELWALL_1_TOPRIGHT_2,
3571 EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3572 EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3573 EL_DC_STEELWALL_2_LEFT,
3574 EL_DC_STEELWALL_2_RIGHT,
3575 EL_DC_STEELWALL_2_TOP,
3576 EL_DC_STEELWALL_2_BOTTOM,
3577 EL_DC_STEELWALL_2_HORIZONTAL,
3578 EL_DC_STEELWALL_2_VERTICAL,
3579 EL_DC_STEELWALL_2_MIDDLE,
3580 EL_DC_STEELWALL_2_SINGLE,
3581 EL_STEELWALL_SLIPPERY,
3595 EL_GATE_1_GRAY_ACTIVE,
3596 EL_GATE_2_GRAY_ACTIVE,
3597 EL_GATE_3_GRAY_ACTIVE,
3598 EL_GATE_4_GRAY_ACTIVE,
3607 EL_EM_GATE_1_GRAY_ACTIVE,
3608 EL_EM_GATE_2_GRAY_ACTIVE,
3609 EL_EM_GATE_3_GRAY_ACTIVE,
3610 EL_EM_GATE_4_GRAY_ACTIVE,
3612 EL_SWITCHGATE_OPENING,
3613 EL_SWITCHGATE_CLOSED,
3614 EL_SWITCHGATE_CLOSING,
3616 EL_TIMEGATE_OPENING,
3618 EL_TIMEGATE_CLOSING,
3622 EL_TUBE_VERTICAL_LEFT,
3623 EL_TUBE_VERTICAL_RIGHT,
3624 EL_TUBE_HORIZONTAL_UP,
3625 EL_TUBE_HORIZONTAL_DOWN,
3634 static int ep_classic_enemy[] =
3651 static int ep_belt[] =
3653 EL_CONVEYOR_BELT_1_LEFT,
3654 EL_CONVEYOR_BELT_1_MIDDLE,
3655 EL_CONVEYOR_BELT_1_RIGHT,
3656 EL_CONVEYOR_BELT_2_LEFT,
3657 EL_CONVEYOR_BELT_2_MIDDLE,
3658 EL_CONVEYOR_BELT_2_RIGHT,
3659 EL_CONVEYOR_BELT_3_LEFT,
3660 EL_CONVEYOR_BELT_3_MIDDLE,
3661 EL_CONVEYOR_BELT_3_RIGHT,
3662 EL_CONVEYOR_BELT_4_LEFT,
3663 EL_CONVEYOR_BELT_4_MIDDLE,
3664 EL_CONVEYOR_BELT_4_RIGHT,
3669 static int ep_belt_active[] =
3671 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3672 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3673 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3674 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3675 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3676 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3677 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3678 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3679 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3680 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3681 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3682 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3687 static int ep_belt_switch[] =
3689 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3690 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3691 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3692 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3693 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3694 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3695 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3696 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3697 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3698 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3699 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3700 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3705 static int ep_tube[] =
3712 EL_TUBE_HORIZONTAL_UP,
3713 EL_TUBE_HORIZONTAL_DOWN,
3715 EL_TUBE_VERTICAL_LEFT,
3716 EL_TUBE_VERTICAL_RIGHT,
3722 static int ep_acid_pool[] =
3724 EL_ACID_POOL_TOPLEFT,
3725 EL_ACID_POOL_TOPRIGHT,
3726 EL_ACID_POOL_BOTTOMLEFT,
3727 EL_ACID_POOL_BOTTOM,
3728 EL_ACID_POOL_BOTTOMRIGHT,
3733 static int ep_keygate[] =
3743 EL_GATE_1_GRAY_ACTIVE,
3744 EL_GATE_2_GRAY_ACTIVE,
3745 EL_GATE_3_GRAY_ACTIVE,
3746 EL_GATE_4_GRAY_ACTIVE,
3755 EL_EM_GATE_1_GRAY_ACTIVE,
3756 EL_EM_GATE_2_GRAY_ACTIVE,
3757 EL_EM_GATE_3_GRAY_ACTIVE,
3758 EL_EM_GATE_4_GRAY_ACTIVE,
3767 EL_EMC_GATE_5_GRAY_ACTIVE,
3768 EL_EMC_GATE_6_GRAY_ACTIVE,
3769 EL_EMC_GATE_7_GRAY_ACTIVE,
3770 EL_EMC_GATE_8_GRAY_ACTIVE,
3772 EL_DC_GATE_WHITE_GRAY,
3773 EL_DC_GATE_WHITE_GRAY_ACTIVE,
3778 static int ep_amoeboid[] =
3790 static int ep_amoebalive[] =
3801 static int ep_has_editor_content[] =
3823 static int ep_can_turn_each_move[] =
3825 /* !!! do something with this one !!! */
3829 static int ep_can_grow[] =
3843 static int ep_active_bomb[] =
3846 EL_EM_DYNAMITE_ACTIVE,
3847 EL_DYNABOMB_PLAYER_1_ACTIVE,
3848 EL_DYNABOMB_PLAYER_2_ACTIVE,
3849 EL_DYNABOMB_PLAYER_3_ACTIVE,
3850 EL_DYNABOMB_PLAYER_4_ACTIVE,
3851 EL_SP_DISK_RED_ACTIVE,
3856 static int ep_inactive[] =
3866 EL_QUICKSAND_FAST_EMPTY,
3889 EL_GATE_1_GRAY_ACTIVE,
3890 EL_GATE_2_GRAY_ACTIVE,
3891 EL_GATE_3_GRAY_ACTIVE,
3892 EL_GATE_4_GRAY_ACTIVE,
3901 EL_EM_GATE_1_GRAY_ACTIVE,
3902 EL_EM_GATE_2_GRAY_ACTIVE,
3903 EL_EM_GATE_3_GRAY_ACTIVE,
3904 EL_EM_GATE_4_GRAY_ACTIVE,
3913 EL_EMC_GATE_5_GRAY_ACTIVE,
3914 EL_EMC_GATE_6_GRAY_ACTIVE,
3915 EL_EMC_GATE_7_GRAY_ACTIVE,
3916 EL_EMC_GATE_8_GRAY_ACTIVE,
3918 EL_DC_GATE_WHITE_GRAY,
3919 EL_DC_GATE_WHITE_GRAY_ACTIVE,
3920 EL_DC_GATE_FAKE_GRAY,
3923 EL_INVISIBLE_STEELWALL,
3931 EL_WALL_EMERALD_YELLOW,
3932 EL_DYNABOMB_INCREASE_NUMBER,
3933 EL_DYNABOMB_INCREASE_SIZE,
3934 EL_DYNABOMB_INCREASE_POWER,
3938 EL_SOKOBAN_FIELD_EMPTY,
3939 EL_SOKOBAN_FIELD_FULL,
3940 EL_WALL_EMERALD_RED,
3941 EL_WALL_EMERALD_PURPLE,
3942 EL_ACID_POOL_TOPLEFT,
3943 EL_ACID_POOL_TOPRIGHT,
3944 EL_ACID_POOL_BOTTOMLEFT,
3945 EL_ACID_POOL_BOTTOM,
3946 EL_ACID_POOL_BOTTOMRIGHT,
3950 EL_BD_MAGIC_WALL_DEAD,
3952 EL_DC_MAGIC_WALL_DEAD,
3953 EL_AMOEBA_TO_DIAMOND,
3961 EL_SP_GRAVITY_PORT_RIGHT,
3962 EL_SP_GRAVITY_PORT_DOWN,
3963 EL_SP_GRAVITY_PORT_LEFT,
3964 EL_SP_GRAVITY_PORT_UP,
3965 EL_SP_PORT_HORIZONTAL,
3966 EL_SP_PORT_VERTICAL,
3977 EL_SP_HARDWARE_GRAY,
3978 EL_SP_HARDWARE_GREEN,
3979 EL_SP_HARDWARE_BLUE,
3981 EL_SP_HARDWARE_YELLOW,
3982 EL_SP_HARDWARE_BASE_1,
3983 EL_SP_HARDWARE_BASE_2,
3984 EL_SP_HARDWARE_BASE_3,
3985 EL_SP_HARDWARE_BASE_4,
3986 EL_SP_HARDWARE_BASE_5,
3987 EL_SP_HARDWARE_BASE_6,
3988 EL_SP_GRAVITY_ON_PORT_LEFT,
3989 EL_SP_GRAVITY_ON_PORT_RIGHT,
3990 EL_SP_GRAVITY_ON_PORT_UP,
3991 EL_SP_GRAVITY_ON_PORT_DOWN,
3992 EL_SP_GRAVITY_OFF_PORT_LEFT,
3993 EL_SP_GRAVITY_OFF_PORT_RIGHT,
3994 EL_SP_GRAVITY_OFF_PORT_UP,
3995 EL_SP_GRAVITY_OFF_PORT_DOWN,
3996 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3997 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3998 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3999 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
4000 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
4001 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
4002 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
4003 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
4004 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
4005 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
4006 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
4007 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
4008 EL_SIGN_EXCLAMATION,
4009 EL_SIGN_RADIOACTIVITY,
4016 EL_SIGN_ENTRY_FORBIDDEN,
4017 EL_SIGN_EMERGENCY_EXIT,
4025 EL_DC_STEELWALL_1_LEFT,
4026 EL_DC_STEELWALL_1_RIGHT,
4027 EL_DC_STEELWALL_1_TOP,
4028 EL_DC_STEELWALL_1_BOTTOM,
4029 EL_DC_STEELWALL_1_HORIZONTAL,
4030 EL_DC_STEELWALL_1_VERTICAL,
4031 EL_DC_STEELWALL_1_TOPLEFT,
4032 EL_DC_STEELWALL_1_TOPRIGHT,
4033 EL_DC_STEELWALL_1_BOTTOMLEFT,
4034 EL_DC_STEELWALL_1_BOTTOMRIGHT,
4035 EL_DC_STEELWALL_1_TOPLEFT_2,
4036 EL_DC_STEELWALL_1_TOPRIGHT_2,
4037 EL_DC_STEELWALL_1_BOTTOMLEFT_2,
4038 EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
4039 EL_DC_STEELWALL_2_LEFT,
4040 EL_DC_STEELWALL_2_RIGHT,
4041 EL_DC_STEELWALL_2_TOP,
4042 EL_DC_STEELWALL_2_BOTTOM,
4043 EL_DC_STEELWALL_2_HORIZONTAL,
4044 EL_DC_STEELWALL_2_VERTICAL,
4045 EL_DC_STEELWALL_2_MIDDLE,
4046 EL_DC_STEELWALL_2_SINGLE,
4047 EL_STEELWALL_SLIPPERY,
4052 EL_EMC_WALL_SLIPPERY_1,
4053 EL_EMC_WALL_SLIPPERY_2,
4054 EL_EMC_WALL_SLIPPERY_3,
4055 EL_EMC_WALL_SLIPPERY_4,
4076 static int ep_em_slippery_wall[] =
4081 static int ep_gfx_crumbled[] =
4092 static int ep_editor_cascade_active[] =
4094 EL_INTERNAL_CASCADE_BD_ACTIVE,
4095 EL_INTERNAL_CASCADE_EM_ACTIVE,
4096 EL_INTERNAL_CASCADE_EMC_ACTIVE,
4097 EL_INTERNAL_CASCADE_RND_ACTIVE,
4098 EL_INTERNAL_CASCADE_SB_ACTIVE,
4099 EL_INTERNAL_CASCADE_SP_ACTIVE,
4100 EL_INTERNAL_CASCADE_DC_ACTIVE,
4101 EL_INTERNAL_CASCADE_DX_ACTIVE,
4102 EL_INTERNAL_CASCADE_CHARS_ACTIVE,
4103 EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
4104 EL_INTERNAL_CASCADE_CE_ACTIVE,
4105 EL_INTERNAL_CASCADE_GE_ACTIVE,
4106 EL_INTERNAL_CASCADE_REF_ACTIVE,
4107 EL_INTERNAL_CASCADE_USER_ACTIVE,
4108 EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
4113 static int ep_editor_cascade_inactive[] =
4115 EL_INTERNAL_CASCADE_BD,
4116 EL_INTERNAL_CASCADE_EM,
4117 EL_INTERNAL_CASCADE_EMC,
4118 EL_INTERNAL_CASCADE_RND,
4119 EL_INTERNAL_CASCADE_SB,
4120 EL_INTERNAL_CASCADE_SP,
4121 EL_INTERNAL_CASCADE_DC,
4122 EL_INTERNAL_CASCADE_DX,
4123 EL_INTERNAL_CASCADE_CHARS,
4124 EL_INTERNAL_CASCADE_STEEL_CHARS,
4125 EL_INTERNAL_CASCADE_CE,
4126 EL_INTERNAL_CASCADE_GE,
4127 EL_INTERNAL_CASCADE_REF,
4128 EL_INTERNAL_CASCADE_USER,
4129 EL_INTERNAL_CASCADE_DYNAMIC,
4134 static int ep_obsolete[] =
4138 EL_EM_KEY_1_FILE_OBSOLETE,
4139 EL_EM_KEY_2_FILE_OBSOLETE,
4140 EL_EM_KEY_3_FILE_OBSOLETE,
4141 EL_EM_KEY_4_FILE_OBSOLETE,
4142 EL_ENVELOPE_OBSOLETE,
4151 } element_properties[] =
4153 { ep_diggable, EP_DIGGABLE },
4154 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
4155 { ep_dont_run_into, EP_DONT_RUN_INTO },
4156 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
4157 { ep_dont_touch, EP_DONT_TOUCH },
4158 { ep_indestructible, EP_INDESTRUCTIBLE },
4159 { ep_slippery, EP_SLIPPERY },
4160 { ep_can_change, EP_CAN_CHANGE },
4161 { ep_can_move, EP_CAN_MOVE },
4162 { ep_can_fall, EP_CAN_FALL },
4163 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
4164 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
4165 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
4166 { ep_explodes_by_fire, EP_EXPLODES_BY_FIRE },
4167 { ep_explodes_smashed, EP_EXPLODES_SMASHED },
4168 { ep_explodes_impact, EP_EXPLODES_IMPACT },
4169 { ep_walkable_over, EP_WALKABLE_OVER },
4170 { ep_walkable_inside, EP_WALKABLE_INSIDE },
4171 { ep_walkable_under, EP_WALKABLE_UNDER },
4172 { ep_passable_over, EP_PASSABLE_OVER },
4173 { ep_passable_inside, EP_PASSABLE_INSIDE },
4174 { ep_passable_under, EP_PASSABLE_UNDER },
4175 { ep_droppable, EP_DROPPABLE },
4176 { ep_explodes_1x1_old, EP_EXPLODES_1X1_OLD },
4177 { ep_pushable, EP_PUSHABLE },
4178 { ep_explodes_cross_old, EP_EXPLODES_CROSS_OLD },
4179 { ep_protected, EP_PROTECTED },
4180 { ep_throwable, EP_THROWABLE },
4181 { ep_can_explode, EP_CAN_EXPLODE },
4182 { ep_gravity_reachable, EP_GRAVITY_REACHABLE },
4184 { ep_player, EP_PLAYER },
4185 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
4186 { ep_can_pass_dc_magic_wall, EP_CAN_PASS_DC_MAGIC_WALL },
4187 { ep_switchable, EP_SWITCHABLE },
4188 { ep_bd_element, EP_BD_ELEMENT },
4189 { ep_sp_element, EP_SP_ELEMENT },
4190 { ep_sb_element, EP_SB_ELEMENT },
4192 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
4193 { ep_food_penguin, EP_FOOD_PENGUIN },
4194 { ep_food_pig, EP_FOOD_PIG },
4195 { ep_historic_wall, EP_HISTORIC_WALL },
4196 { ep_historic_solid, EP_HISTORIC_SOLID },
4197 { ep_classic_enemy, EP_CLASSIC_ENEMY },
4198 { ep_belt, EP_BELT },
4199 { ep_belt_active, EP_BELT_ACTIVE },
4200 { ep_belt_switch, EP_BELT_SWITCH },
4201 { ep_tube, EP_TUBE },
4202 { ep_acid_pool, EP_ACID_POOL },
4203 { ep_keygate, EP_KEYGATE },
4204 { ep_amoeboid, EP_AMOEBOID },
4205 { ep_amoebalive, EP_AMOEBALIVE },
4206 { ep_has_editor_content, EP_HAS_EDITOR_CONTENT },
4207 { ep_can_turn_each_move, EP_CAN_TURN_EACH_MOVE },
4208 { ep_can_grow, EP_CAN_GROW },
4209 { ep_active_bomb, EP_ACTIVE_BOMB },
4210 { ep_inactive, EP_INACTIVE },
4212 { ep_em_slippery_wall, EP_EM_SLIPPERY_WALL },
4214 { ep_gfx_crumbled, EP_GFX_CRUMBLED },
4216 { ep_editor_cascade_active, EP_EDITOR_CASCADE_ACTIVE },
4217 { ep_editor_cascade_inactive, EP_EDITOR_CASCADE_INACTIVE },
4219 { ep_obsolete, EP_OBSOLETE },
4226 /* always start with reliable default values (element has no properties) */
4227 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4228 for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
4229 SET_PROPERTY(i, j, FALSE);
4231 /* set all base element properties from above array definitions */
4232 for (i = 0; element_properties[i].elements != NULL; i++)
4233 for (j = 0; (element_properties[i].elements)[j] != -1; j++)
4234 SET_PROPERTY((element_properties[i].elements)[j],
4235 element_properties[i].property, TRUE);
4237 /* copy properties to some elements that are only stored in level file */
4238 for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
4239 for (j = 0; copy_properties[j][0] != -1; j++)
4240 if (HAS_PROPERTY(copy_properties[j][0], i))
4241 for (k = 1; k <= 4; k++)
4242 SET_PROPERTY(copy_properties[j][k], i, TRUE);
4244 /* set static element properties that are not listed in array definitions */
4245 for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++)
4246 SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE);
4249 void InitElementPropertiesEngine(int engine_version)
4251 static int no_wall_properties[] =
4254 EP_COLLECTIBLE_ONLY,
4256 EP_DONT_COLLIDE_WITH,
4259 EP_CAN_SMASH_PLAYER,
4260 EP_CAN_SMASH_ENEMIES,
4261 EP_CAN_SMASH_EVERYTHING,
4266 EP_FOOD_DARK_YAMYAM,
4282 /* important: after initialization in InitElementPropertiesStatic(), the
4283 elements are not again initialized to a default value; therefore all
4284 changes have to make sure that they leave the element with a defined
4285 property (which means that conditional property changes must be set to
4286 a reliable default value before) */
4288 /* resolve group elements */
4289 for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
4290 ResolveGroupElement(EL_GROUP_START + i);
4292 /* set all special, combined or engine dependent element properties */
4293 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4295 /* ---------- INACTIVE ------------------------------------------------- */
4296 SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START &&
4297 i <= EL_CHAR_END) ||
4298 (i >= EL_STEEL_CHAR_START &&
4299 i <= EL_STEEL_CHAR_END)));
4301 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
4302 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
4303 IS_WALKABLE_INSIDE(i) ||
4304 IS_WALKABLE_UNDER(i)));
4306 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
4307 IS_PASSABLE_INSIDE(i) ||
4308 IS_PASSABLE_UNDER(i)));
4310 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
4311 IS_PASSABLE_OVER(i)));
4313 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
4314 IS_PASSABLE_INSIDE(i)));
4316 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
4317 IS_PASSABLE_UNDER(i)));
4319 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
4322 /* ---------- COLLECTIBLE ---------------------------------------------- */
4323 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
4327 /* ---------- SNAPPABLE ------------------------------------------------ */
4328 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
4329 IS_COLLECTIBLE(i) ||
4333 /* ---------- WALL ----------------------------------------------------- */
4334 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
4336 for (j = 0; no_wall_properties[j] != -1; j++)
4337 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
4338 i >= EL_FIRST_RUNTIME_UNREAL)
4339 SET_PROPERTY(i, EP_WALL, FALSE);
4341 if (IS_HISTORIC_WALL(i))
4342 SET_PROPERTY(i, EP_WALL, TRUE);
4344 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
4345 if (engine_version < VERSION_IDENT(2,2,0,0))
4346 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
4348 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
4350 !IS_COLLECTIBLE(i)));
4352 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
4353 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
4354 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
4356 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
4357 IS_INDESTRUCTIBLE(i)));
4359 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
4361 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
4362 else if (engine_version < VERSION_IDENT(2,2,0,0))
4363 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
4365 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
4369 if (IS_CUSTOM_ELEMENT(i))
4371 /* these are additional properties which are initially false when set */
4373 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
4375 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
4376 if (DONT_COLLIDE_WITH(i))
4377 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
4379 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
4380 if (CAN_SMASH_EVERYTHING(i))
4381 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
4382 if (CAN_SMASH_ENEMIES(i))
4383 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
4386 /* ---------- CAN_SMASH ------------------------------------------------ */
4387 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
4388 CAN_SMASH_ENEMIES(i) ||
4389 CAN_SMASH_EVERYTHING(i)));
4391 /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
4392 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
4393 EXPLODES_BY_FIRE(i)));
4395 /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
4396 SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
4397 EXPLODES_SMASHED(i)));
4399 /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
4400 SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
4401 EXPLODES_IMPACT(i)));
4403 /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
4404 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
4406 /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
4407 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
4408 i == EL_BLACK_ORB));
4410 /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
4411 SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
4413 IS_CUSTOM_ELEMENT(i)));
4415 /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
4416 SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
4417 i == EL_SP_ELECTRON));
4419 /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
4420 if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
4421 SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
4422 getMoveIntoAcidProperty(&level, i));
4424 /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
4425 if (MAYBE_DONT_COLLIDE_WITH(i))
4426 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
4427 getDontCollideWithProperty(&level, i));
4429 /* ---------- SP_PORT -------------------------------------------------- */
4430 SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
4431 IS_PASSABLE_INSIDE(i)));
4433 /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
4434 for (j = 0; j < level.num_android_clone_elements; j++)
4435 SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
4437 IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
4439 /* ---------- CAN_CHANGE ----------------------------------------------- */
4440 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
4441 for (j = 0; j < element_info[i].num_change_pages; j++)
4442 if (element_info[i].change_page[j].can_change)
4443 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
4445 /* ---------- HAS_ACTION ----------------------------------------------- */
4446 SET_PROPERTY(i, EP_HAS_ACTION, FALSE); /* default: has no action */
4447 for (j = 0; j < element_info[i].num_change_pages; j++)
4448 if (element_info[i].change_page[j].has_action)
4449 SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
4451 /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
4452 SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
4455 /* ---------- GFX_CRUMBLED --------------------------------------------- */
4457 SET_PROPERTY(i, EP_GFX_CRUMBLED,
4458 element_info[i].crumbled[ACTION_DEFAULT] !=
4459 element_info[i].graphic[ACTION_DEFAULT]);
4461 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
4462 SET_PROPERTY(i, EP_GFX_CRUMBLED,
4463 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
4466 /* ---------- EDITOR_CASCADE ------------------------------------------- */
4467 SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
4468 IS_EDITOR_CASCADE_INACTIVE(i)));
4471 /* dynamically adjust element properties according to game engine version */
4473 static int ep_em_slippery_wall[] =
4478 EL_EXPANDABLE_WALL_HORIZONTAL,
4479 EL_EXPANDABLE_WALL_VERTICAL,
4480 EL_EXPANDABLE_WALL_ANY,
4481 EL_EXPANDABLE_STEELWALL_HORIZONTAL,
4482 EL_EXPANDABLE_STEELWALL_VERTICAL,
4483 EL_EXPANDABLE_STEELWALL_ANY,
4484 EL_EXPANDABLE_STEELWALL_GROWING,
4488 /* special EM style gems behaviour */
4489 for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4490 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4491 level.em_slippery_gems);
4493 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4494 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4495 (level.em_slippery_gems &&
4496 engine_version > VERSION_IDENT(2,0,1,0)));
4499 /* this is needed because some graphics depend on element properties */
4500 if (game_status == GAME_MODE_PLAYING)
4501 InitElementGraphicInfo();
4504 void InitElementPropertiesAfterLoading(int engine_version)
4508 /* set some other uninitialized values of custom elements in older levels */
4509 if (engine_version < VERSION_IDENT(3,1,0,0))
4511 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4513 int element = EL_CUSTOM_START + i;
4515 element_info[element].access_direction = MV_ALL_DIRECTIONS;
4517 element_info[element].explosion_delay = 17;
4518 element_info[element].ignition_delay = 8;
4523 static void InitGlobal()
4527 for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
4529 /* check if element_name_info entry defined for each element in "main.h" */
4530 if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
4531 Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
4533 element_info[i].token_name = element_name_info[i].token_name;
4534 element_info[i].class_name = element_name_info[i].class_name;
4535 element_info[i].editor_description= element_name_info[i].editor_description;
4538 printf("%04d: %s\n", i, element_name_info[i].token_name);
4542 /* always start with reliable default values (all elements) */
4543 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4544 ActiveElement[i] = i;
4546 /* now add all entries that have an active state (active elements) */
4547 for (i = 0; element_with_active_state[i].element != -1; i++)
4549 int element = element_with_active_state[i].element;
4550 int element_active = element_with_active_state[i].element_active;
4552 ActiveElement[element] = element_active;
4555 /* always start with reliable default values (all buttons) */
4556 for (i = 0; i < NUM_IMAGE_FILES; i++)
4557 ActiveButton[i] = i;
4559 /* now add all entries that have an active state (active buttons) */
4560 for (i = 0; button_with_active_state[i].button != -1; i++)
4562 int button = button_with_active_state[i].button;
4563 int button_active = button_with_active_state[i].button_active;
4565 ActiveButton[button] = button_active;
4568 /* always start with reliable default values (all fonts) */
4569 for (i = 0; i < NUM_FONTS; i++)
4572 /* now add all entries that have an active state (active fonts) */
4573 for (i = 0; font_with_active_state[i].font_nr != -1; i++)
4575 int font = font_with_active_state[i].font_nr;
4576 int font_active = font_with_active_state[i].font_nr_active;
4578 ActiveFont[font] = font_active;
4581 global.autoplay_leveldir = NULL;
4582 global.convert_leveldir = NULL;
4584 global.frames_per_second = 0;
4585 global.fps_slowdown = FALSE;
4586 global.fps_slowdown_factor = 1;
4588 global.border_status = GAME_MODE_MAIN;
4590 global.fading_status = GAME_MODE_MAIN;
4591 global.fading_type = TYPE_ENTER_MENU;
4595 void Execute_Command(char *command)
4599 if (strEqual(command, "print graphicsinfo.conf"))
4601 printf("# You can configure additional/alternative image files here.\n");
4602 printf("# (The entries below are default and therefore commented out.)\n");
4604 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
4606 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4609 for (i = 0; image_config[i].token != NULL; i++)
4610 printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
4611 image_config[i].value));
4615 else if (strEqual(command, "print soundsinfo.conf"))
4617 printf("# You can configure additional/alternative sound files here.\n");
4618 printf("# (The entries below are default and therefore commented out.)\n");
4620 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
4622 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4625 for (i = 0; sound_config[i].token != NULL; i++)
4626 printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4627 sound_config[i].value));
4631 else if (strEqual(command, "print musicinfo.conf"))
4633 printf("# You can configure additional/alternative music files here.\n");
4634 printf("# (The entries below are default and therefore commented out.)\n");
4636 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4638 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4641 for (i = 0; music_config[i].token != NULL; i++)
4642 printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4643 music_config[i].value));
4647 else if (strEqual(command, "print editorsetup.conf"))
4649 printf("# You can configure your personal editor element list here.\n");
4650 printf("# (The entries below are default and therefore commented out.)\n");
4653 /* this is needed to be able to check element list for cascade elements */
4654 InitElementPropertiesStatic();
4655 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4657 PrintEditorElementList();
4661 else if (strEqual(command, "print helpanim.conf"))
4663 printf("# You can configure different element help animations here.\n");
4664 printf("# (The entries below are default and therefore commented out.)\n");
4667 for (i = 0; helpanim_config[i].token != NULL; i++)
4669 printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4670 helpanim_config[i].value));
4672 if (strEqual(helpanim_config[i].token, "end"))
4678 else if (strEqual(command, "print helptext.conf"))
4680 printf("# You can configure different element help text here.\n");
4681 printf("# (The entries below are default and therefore commented out.)\n");
4684 for (i = 0; helptext_config[i].token != NULL; i++)
4685 printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4686 helptext_config[i].value));
4690 else if (strncmp(command, "dump level ", 11) == 0)
4692 char *filename = &command[11];
4694 if (!fileExists(filename))
4695 Error(ERR_EXIT, "cannot open file '%s'", filename);
4697 LoadLevelFromFilename(&level, filename);
4702 else if (strncmp(command, "dump tape ", 10) == 0)
4704 char *filename = &command[10];
4706 if (!fileExists(filename))
4707 Error(ERR_EXIT, "cannot open file '%s'", filename);
4709 LoadTapeFromFilename(filename);
4714 else if (strncmp(command, "autoplay ", 9) == 0)
4716 char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
4718 while (*str_ptr != '\0') /* continue parsing string */
4720 /* cut leading whitespace from string, replace it by string terminator */
4721 while (*str_ptr == ' ' || *str_ptr == '\t')
4724 if (*str_ptr == '\0') /* end of string reached */
4727 if (global.autoplay_leveldir == NULL) /* read level set string */
4729 global.autoplay_leveldir = str_ptr;
4730 global.autoplay_all = TRUE; /* default: play all tapes */
4732 for (i = 0; i < MAX_TAPES_PER_SET; i++)
4733 global.autoplay_level[i] = FALSE;
4735 else /* read level number string */
4737 int level_nr = atoi(str_ptr); /* get level_nr value */
4739 if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
4740 global.autoplay_level[level_nr] = TRUE;
4742 global.autoplay_all = FALSE;
4745 /* advance string pointer to the next whitespace (or end of string) */
4746 while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
4750 else if (strncmp(command, "convert ", 8) == 0)
4752 char *str_copy = getStringCopy(&command[8]);
4753 char *str_ptr = strchr(str_copy, ' ');
4755 global.convert_leveldir = str_copy;
4756 global.convert_level_nr = -1;
4758 if (str_ptr != NULL) /* level number follows */
4760 *str_ptr++ = '\0'; /* terminate leveldir string */
4761 global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
4766 #if defined(TARGET_SDL)
4767 else if (strEqual(command, "SDL_ListModes"))
4772 SDL_Init(SDL_INIT_VIDEO);
4774 /* get available fullscreen/hardware modes */
4775 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
4777 /* check if there are any modes available */
4780 printf("No modes available!\n");
4785 /* check if our resolution is restricted */
4786 if (modes == (SDL_Rect **)-1)
4788 printf("All resolutions available.\n");
4792 printf("Available Modes:\n");
4794 for(i = 0; modes[i]; i++)
4795 printf(" %d x %d\n", modes[i]->w, modes[i]->h);
4805 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4809 static void InitSetup()
4811 LoadSetup(); /* global setup info */
4813 /* set some options from setup file */
4815 if (setup.options.verbose)
4816 options.verbose = TRUE;
4819 static void InitGameInfo()
4821 game.restart_level = FALSE;
4824 static void InitPlayerInfo()
4828 /* choose default local player */
4829 local_player = &stored_player[0];
4831 for (i = 0; i < MAX_PLAYERS; i++)
4832 stored_player[i].connected = FALSE;
4834 local_player->connected = TRUE;
4837 static void InitArtworkInfo()
4842 static char *get_string_in_brackets(char *string)
4844 char *string_in_brackets = checked_malloc(strlen(string) + 3);
4846 sprintf(string_in_brackets, "[%s]", string);
4848 return string_in_brackets;
4851 static char *get_level_id_suffix(int id_nr)
4853 char *id_suffix = checked_malloc(1 + 3 + 1);
4855 if (id_nr < 0 || id_nr > 999)
4858 sprintf(id_suffix, ".%03d", id_nr);
4864 static char *get_element_class_token(int element)
4866 char *element_class_name = element_info[element].class_name;
4867 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4869 sprintf(element_class_token, "[%s]", element_class_name);
4871 return element_class_token;
4874 static char *get_action_class_token(int action)
4876 char *action_class_name = &element_action_info[action].suffix[1];
4877 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4879 sprintf(action_class_token, "[%s]", action_class_name);
4881 return action_class_token;
4885 static void InitArtworkConfig()
4887 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4888 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4889 static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4890 static char *action_id_suffix[NUM_ACTIONS + 1];
4891 static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
4892 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4893 static char *level_id_suffix[MAX_LEVELS + 1];
4894 static char *dummy[1] = { NULL };
4895 static char *ignore_generic_tokens[] =
4901 static char **ignore_image_tokens;
4902 static char **ignore_sound_tokens;
4903 static char **ignore_music_tokens;
4904 int num_ignore_generic_tokens;
4905 int num_ignore_image_tokens;
4906 int num_ignore_sound_tokens;
4907 int num_ignore_music_tokens;
4910 /* dynamically determine list of generic tokens to be ignored */
4911 num_ignore_generic_tokens = 0;
4912 for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4913 num_ignore_generic_tokens++;
4915 /* dynamically determine list of image tokens to be ignored */
4916 num_ignore_image_tokens = num_ignore_generic_tokens;
4917 for (i = 0; image_config_vars[i].token != NULL; i++)
4918 num_ignore_image_tokens++;
4919 ignore_image_tokens =
4920 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4921 for (i = 0; i < num_ignore_generic_tokens; i++)
4922 ignore_image_tokens[i] = ignore_generic_tokens[i];
4923 for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4924 ignore_image_tokens[num_ignore_generic_tokens + i] =
4925 image_config_vars[i].token;
4926 ignore_image_tokens[num_ignore_image_tokens] = NULL;
4928 /* dynamically determine list of sound tokens to be ignored */
4929 num_ignore_sound_tokens = num_ignore_generic_tokens;
4930 ignore_sound_tokens =
4931 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4932 for (i = 0; i < num_ignore_generic_tokens; i++)
4933 ignore_sound_tokens[i] = ignore_generic_tokens[i];
4934 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4936 /* dynamically determine list of music tokens to be ignored */
4937 num_ignore_music_tokens = num_ignore_generic_tokens;
4938 ignore_music_tokens =
4939 checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4940 for (i = 0; i < num_ignore_generic_tokens; i++)
4941 ignore_music_tokens[i] = ignore_generic_tokens[i];
4942 ignore_music_tokens[num_ignore_music_tokens] = NULL;
4944 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4945 image_id_prefix[i] = element_info[i].token_name;
4946 for (i = 0; i < NUM_FONTS; i++)
4947 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4948 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4950 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4951 sound_id_prefix[i] = element_info[i].token_name;
4952 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4953 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4954 get_string_in_brackets(element_info[i].class_name);
4955 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4957 for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4958 music_id_prefix[i] = music_prefix_info[i].prefix;
4959 music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
4961 for (i = 0; i < NUM_ACTIONS; i++)
4962 action_id_suffix[i] = element_action_info[i].suffix;
4963 action_id_suffix[NUM_ACTIONS] = NULL;
4965 for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
4966 direction_id_suffix[i] = element_direction_info[i].suffix;
4967 direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
4969 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4970 special_id_suffix[i] = special_suffix_info[i].suffix;
4971 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4973 for (i = 0; i < MAX_LEVELS; i++)
4974 level_id_suffix[i] = get_level_id_suffix(i);
4975 level_id_suffix[MAX_LEVELS] = NULL;
4977 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4978 image_id_prefix, action_id_suffix, direction_id_suffix,
4979 special_id_suffix, ignore_image_tokens);
4980 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4981 sound_id_prefix, action_id_suffix, dummy,
4982 special_id_suffix, ignore_sound_tokens);
4983 InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4984 music_id_prefix, special_id_suffix, level_id_suffix,
4985 dummy, ignore_music_tokens);
4988 static void InitMixer()
4996 char *filename_font_initial = NULL;
4997 char *filename_anim_initial = NULL;
4998 Bitmap *bitmap_font_initial = NULL;
5002 /* determine settings for initial font (for displaying startup messages) */
5003 for (i = 0; image_config[i].token != NULL; i++)
5005 for (j = 0; j < NUM_INITIAL_FONTS; j++)
5007 char font_token[128];
5010 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
5011 len_font_token = strlen(font_token);
5013 if (strEqual(image_config[i].token, font_token))
5014 filename_font_initial = image_config[i].value;
5015 else if (strlen(image_config[i].token) > len_font_token &&
5016 strncmp(image_config[i].token, font_token, len_font_token) == 0)
5018 if (strEqual(&image_config[i].token[len_font_token], ".x"))
5019 font_initial[j].src_x = atoi(image_config[i].value);
5020 else if (strEqual(&image_config[i].token[len_font_token], ".y"))
5021 font_initial[j].src_y = atoi(image_config[i].value);
5022 else if (strEqual(&image_config[i].token[len_font_token], ".width"))
5023 font_initial[j].width = atoi(image_config[i].value);
5024 else if (strEqual(&image_config[i].token[len_font_token], ".height"))
5025 font_initial[j].height = atoi(image_config[i].value);
5030 for (j = 0; j < NUM_INITIAL_FONTS; j++)
5032 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
5033 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
5036 if (filename_font_initial == NULL) /* should not happen */
5037 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
5039 /* create additional image buffers for double-buffering and cross-fading */
5040 bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5041 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
5042 bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
5043 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
5045 /* initialize screen properties */
5046 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
5047 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
5049 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
5050 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
5051 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
5053 bitmap_font_initial = LoadCustomImage(filename_font_initial);
5055 for (j = 0; j < NUM_INITIAL_FONTS; j++)
5056 font_initial[j].bitmap = bitmap_font_initial;
5058 InitFontGraphicInfo();
5060 font_height = getFontHeight(FC_RED);
5063 DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
5065 DrawInitText(getProgramInitString(), 20, FC_YELLOW);
5067 DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
5068 DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
5070 DrawInitText("Loading graphics", 120, FC_GREEN);
5073 /* determine settings for busy animation (when displaying startup messages) */
5074 for (i = 0; image_config[i].token != NULL; i++)
5076 char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
5077 int len_anim_token = strlen(anim_token);
5079 if (strEqual(image_config[i].token, anim_token))
5080 filename_anim_initial = image_config[i].value;
5081 else if (strlen(image_config[i].token) > len_anim_token &&
5082 strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
5084 if (strEqual(&image_config[i].token[len_anim_token], ".x"))
5085 anim_initial.src_x = atoi(image_config[i].value);
5086 else if (strEqual(&image_config[i].token[len_anim_token], ".y"))
5087 anim_initial.src_y = atoi(image_config[i].value);
5088 else if (strEqual(&image_config[i].token[len_anim_token], ".width"))
5089 anim_initial.width = atoi(image_config[i].value);
5090 else if (strEqual(&image_config[i].token[len_anim_token], ".height"))
5091 anim_initial.height = atoi(image_config[i].value);
5092 else if (strEqual(&image_config[i].token[len_anim_token], ".frames"))
5093 anim_initial.anim_frames = atoi(image_config[i].value);
5094 else if (strEqual(&image_config[i].token[len_anim_token],
5095 ".frames_per_line"))
5096 anim_initial.anim_frames_per_line = atoi(image_config[i].value);
5097 else if (strEqual(&image_config[i].token[len_anim_token], ".delay"))
5098 anim_initial.anim_delay = atoi(image_config[i].value);
5102 if (filename_anim_initial == NULL) /* should not happen */
5103 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
5105 anim_initial.bitmap = LoadCustomImage(filename_anim_initial);
5107 InitGfxDrawBusyAnimFunction(DrawInitAnim);
5111 void RedrawBackground()
5113 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
5114 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
5116 redraw_mask = REDRAW_ALL;
5119 void InitGfxBackground()
5123 fieldbuffer = bitmap_db_field;
5124 SetDrawtoField(DRAW_BACKBUFFER);
5127 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
5131 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
5132 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
5135 for (x = 0; x < MAX_BUF_XSIZE; x++)
5136 for (y = 0; y < MAX_BUF_YSIZE; y++)
5139 redraw_mask = REDRAW_ALL;
5142 static void InitLevelInfo()
5144 LoadLevelInfo(); /* global level info */
5145 LoadLevelSetup_LastSeries(); /* last played series info */
5146 LoadLevelSetup_SeriesInfo(); /* last played level info */
5149 void InitLevelArtworkInfo()
5151 LoadLevelArtworkInfo();
5154 static void InitImages()
5156 print_init_timestamp("INIT InitImages");
5158 setLevelArtworkDir(artwork.gfx_first);
5161 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
5162 leveldir_current->identifier,
5163 artwork.gfx_current_identifier,
5164 artwork.gfx_current->identifier,
5165 leveldir_current->graphics_set,
5166 leveldir_current->graphics_path);
5169 UPDATE_BUSY_STATE();
5171 ReloadCustomImages();
5172 print_init_timestamp("TIME ReloadCustomImages");
5174 UPDATE_BUSY_STATE();
5176 LoadCustomElementDescriptions();
5177 print_init_timestamp("TIME LoadCustomElementDescriptions");
5179 UPDATE_BUSY_STATE();
5181 LoadMenuDesignSettings();
5182 print_init_timestamp("TIME LoadMenuDesignSettings");
5184 UPDATE_BUSY_STATE();
5186 ReinitializeGraphics();
5187 print_init_timestamp("TIME ReinitializeGraphics");
5189 UPDATE_BUSY_STATE();
5191 print_init_timestamp("DONE InitImages");
5194 static void InitSound(char *identifier)
5196 print_init_timestamp("INIT InitSound");
5198 if (identifier == NULL)
5199 identifier = artwork.snd_current->identifier;
5201 /* set artwork path to send it to the sound server process */
5202 setLevelArtworkDir(artwork.snd_first);
5204 InitReloadCustomSounds(identifier);
5205 print_init_timestamp("TIME InitReloadCustomSounds");
5207 ReinitializeSounds();
5208 print_init_timestamp("TIME ReinitializeSounds");
5210 print_init_timestamp("DONE InitSound");
5213 static void InitMusic(char *identifier)
5215 print_init_timestamp("INIT InitMusic");
5217 if (identifier == NULL)
5218 identifier = artwork.mus_current->identifier;
5220 /* set artwork path to send it to the sound server process */
5221 setLevelArtworkDir(artwork.mus_first);
5223 InitReloadCustomMusic(identifier);
5224 print_init_timestamp("TIME InitReloadCustomMusic");
5226 ReinitializeMusic();
5227 print_init_timestamp("TIME ReinitializeMusic");
5229 print_init_timestamp("DONE InitMusic");
5232 void InitNetworkServer()
5234 #if defined(NETWORK_AVALIABLE)
5238 if (!options.network)
5241 #if defined(NETWORK_AVALIABLE)
5242 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
5244 if (!ConnectToServer(options.server_host, options.server_port))
5245 Error(ERR_EXIT, "cannot connect to network game server");
5247 SendToServer_PlayerName(setup.player_name);
5248 SendToServer_ProtocolVersion();
5251 SendToServer_NrWanted(nr_wanted);
5255 static char *getNewArtworkIdentifier(int type)
5257 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
5258 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
5259 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
5260 static boolean initialized[3] = { FALSE, FALSE, FALSE };
5261 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
5262 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
5263 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
5264 char *leveldir_identifier = leveldir_current->identifier;
5266 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
5267 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
5269 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
5271 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
5272 char *artwork_current_identifier;
5273 char *artwork_new_identifier = NULL; /* default: nothing has changed */
5275 /* leveldir_current may be invalid (level group, parent link) */
5276 if (!validLevelSeries(leveldir_current))
5279 /* 1st step: determine artwork set to be activated in descending order:
5280 --------------------------------------------------------------------
5281 1. setup artwork (when configured to override everything else)
5282 2. artwork set configured in "levelinfo.conf" of current level set
5283 (artwork in level directory will have priority when loading later)
5284 3. artwork in level directory (stored in artwork sub-directory)
5285 4. setup artwork (currently configured in setup menu) */
5287 if (setup_override_artwork)
5288 artwork_current_identifier = setup_artwork_set;
5289 else if (leveldir_artwork_set != NULL)
5290 artwork_current_identifier = leveldir_artwork_set;
5291 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
5292 artwork_current_identifier = leveldir_identifier;
5294 artwork_current_identifier = setup_artwork_set;
5297 /* 2nd step: check if it is really needed to reload artwork set
5298 ------------------------------------------------------------ */
5301 if (type == ARTWORK_TYPE_GRAPHICS)
5302 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
5303 artwork_new_identifier,
5304 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
5305 artwork_current_identifier,
5306 leveldir_current->graphics_set,
5307 leveldir_current->identifier);
5310 /* ---------- reload if level set and also artwork set has changed ------- */
5311 if (leveldir_current_identifier[type] != leveldir_identifier &&
5312 (last_has_level_artwork_set[type] || has_level_artwork_set))
5313 artwork_new_identifier = artwork_current_identifier;
5315 leveldir_current_identifier[type] = leveldir_identifier;
5316 last_has_level_artwork_set[type] = has_level_artwork_set;
5319 if (type == ARTWORK_TYPE_GRAPHICS)
5320 printf("::: 1: '%s'\n", artwork_new_identifier);
5323 /* ---------- reload if "override artwork" setting has changed ----------- */
5324 if (last_override_level_artwork[type] != setup_override_artwork)
5325 artwork_new_identifier = artwork_current_identifier;
5327 last_override_level_artwork[type] = setup_override_artwork;
5330 if (type == ARTWORK_TYPE_GRAPHICS)
5331 printf("::: 2: '%s'\n", artwork_new_identifier);
5334 /* ---------- reload if current artwork identifier has changed ----------- */
5335 if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
5336 artwork_current_identifier))
5337 artwork_new_identifier = artwork_current_identifier;
5339 *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
5342 if (type == ARTWORK_TYPE_GRAPHICS)
5343 printf("::: 3: '%s'\n", artwork_new_identifier);
5346 /* ---------- do not reload directly after starting ---------------------- */
5347 if (!initialized[type])
5348 artwork_new_identifier = NULL;
5350 initialized[type] = TRUE;
5353 if (type == ARTWORK_TYPE_GRAPHICS)
5354 printf("::: 4: '%s'\n", artwork_new_identifier);
5358 if (type == ARTWORK_TYPE_GRAPHICS)
5359 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
5360 artwork.gfx_current_identifier, artwork_current_identifier,
5361 artwork.gfx_current->identifier, leveldir_current->graphics_set,
5362 artwork_new_identifier);
5365 return artwork_new_identifier;
5368 void ReloadCustomArtwork(int force_reload)
5370 char *gfx_new_identifier;
5371 char *snd_new_identifier;
5372 char *mus_new_identifier;
5373 boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
5374 boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
5375 boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
5376 boolean reload_needed;
5378 force_reload_gfx |= AdjustGraphicsForEMC();
5380 gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
5381 snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
5382 mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
5384 reload_needed = (gfx_new_identifier != NULL || force_reload_gfx ||
5385 snd_new_identifier != NULL || force_reload_snd ||
5386 mus_new_identifier != NULL || force_reload_mus);
5391 print_init_timestamp("INIT ReloadCustomArtwork");
5393 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5394 print_init_timestamp("TIME ClearRectangle");
5396 if (gfx_new_identifier != NULL || force_reload_gfx)
5399 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
5400 artwork.gfx_current_identifier,
5402 artwork.gfx_current->identifier,
5403 leveldir_current->graphics_set);
5407 print_init_timestamp("TIME InitImages");
5410 if (snd_new_identifier != NULL || force_reload_snd)
5412 InitSound(snd_new_identifier);
5413 print_init_timestamp("TIME InitSound");
5416 if (mus_new_identifier != NULL || force_reload_mus)
5418 InitMusic(mus_new_identifier);
5419 print_init_timestamp("TIME InitMusic");
5424 /* force redraw of (open or closed) door graphics */
5425 SetDoorState(DOOR_OPEN_ALL);
5426 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
5430 FadeSetEnterScreen();
5431 // FadeSkipNextFadeOut();
5432 // FadeSetDisabled();
5437 fading = fading_none;
5440 print_init_timestamp("DONE ReloadCustomArtwork");
5443 void KeyboardAutoRepeatOffUnlessAutoplay()
5445 if (global.autoplay_leveldir == NULL)
5446 KeyboardAutoRepeatOff();
5450 /* ========================================================================= */
5452 /* ========================================================================= */
5456 print_init_timestamp("INIT OpenAll");
5458 InitGlobal(); /* initialize some global variables */
5460 if (options.execute_command)
5461 Execute_Command(options.execute_command);
5463 if (options.serveronly)
5465 #if defined(PLATFORM_UNIX)
5466 NetworkServer(options.server_port, options.serveronly);
5468 Error(ERR_WARN, "networking only supported in Unix version");
5471 exit(0); /* never reached, server loops forever */
5478 InitArtworkInfo(); /* needed before loading gfx, sound & music */
5479 InitArtworkConfig(); /* needed before forking sound child process */
5484 InitRND(NEW_RANDOMIZE);
5485 InitSimpleRandom(NEW_RANDOMIZE);
5489 print_init_timestamp("TIME [pre-video]");
5492 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
5494 InitEventFilter(FilterMouseMotionEvents);
5496 InitElementPropertiesStatic();
5497 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5499 print_init_timestamp("TIME [post-video]");
5503 print_init_timestamp("TIME InitGfx");
5506 print_init_timestamp("TIME InitLevelInfo");
5508 InitLevelArtworkInfo();
5509 print_init_timestamp("TIME InitLevelArtworkInfo");
5511 InitImages(); /* needs to know current level directory */
5512 print_init_timestamp("TIME InitImages");
5514 InitSound(NULL); /* needs to know current level directory */
5515 print_init_timestamp("TIME InitSound");
5517 InitMusic(NULL); /* needs to know current level directory */
5518 print_init_timestamp("TIME InitMusic");
5520 InitGfxBackground();
5526 if (global.autoplay_leveldir)
5531 else if (global.convert_leveldir)
5537 game_status = GAME_MODE_MAIN;
5540 FadeSetEnterScreen();
5541 if (!(fading.fade_mode & FADE_TYPE_TRANSFORM))
5542 FadeSkipNextFadeOut();
5543 // FadeSetDisabled();
5545 fading = fading_none;
5548 print_init_timestamp("TIME [post-artwork]");
5550 print_init_timestamp("DONE OpenAll");
5554 InitNetworkServer();
5557 void CloseAllAndExit(int exit_value)
5562 CloseAudio(); /* called after freeing sounds (needed for SDL) */
5570 #if defined(TARGET_SDL)
5571 if (network_server) /* terminate network server */
5572 SDL_KillThread(server_thread);
5575 CloseVideoDisplay();
5576 ClosePlatformDependentStuff();
5578 if (exit_value != 0)
5579 NotifyUserAboutErrorFile();