1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
29 #include "conf_e2g.c" /* include auto-generated data structure definitions */
30 #include "conf_esg.c" /* include auto-generated data structure definitions */
31 #include "conf_e2s.c" /* include auto-generated data structure definitions */
32 #include "conf_fnt.c" /* include auto-generated data structure definitions */
33 #include "conf_g2s.c" /* include auto-generated data structure definitions */
34 #include "conf_g2m.c" /* include auto-generated data structure definitions */
37 #define CONFIG_TOKEN_FONT_INITIAL "font.initial"
40 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
42 static int copy_properties[][5] =
46 EL_BUG_LEFT, EL_BUG_RIGHT,
47 EL_BUG_UP, EL_BUG_DOWN
51 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
52 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
56 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
57 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
61 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
62 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
66 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
67 EL_PACMAN_UP, EL_PACMAN_DOWN
71 EL_YAMYAM_LEFT, EL_YAMYAM_RIGHT,
72 EL_YAMYAM_UP, EL_YAMYAM_DOWN
76 EL_MOLE_LEFT, EL_MOLE_RIGHT,
77 EL_MOLE_UP, EL_MOLE_DOWN
87 FreeLevelEditorGadgets();
96 static boolean gadgets_initialized = FALSE;
98 if (gadgets_initialized)
101 CreateLevelEditorGadgets();
105 CreateScreenGadgets();
107 gadgets_initialized = TRUE;
110 inline void InitElementSmallImagesScaledUp(int graphic)
112 CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
115 void InitElementSmallImages()
117 static int special_graphics[] =
119 IMG_EDITOR_ELEMENT_BORDER,
120 IMG_EDITOR_ELEMENT_BORDER_INPUT,
121 IMG_EDITOR_CASCADE_LIST,
122 IMG_EDITOR_CASCADE_LIST_ACTIVE,
125 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
126 int num_property_mappings = getImageListPropertyMappingSize();
129 /* initialize normal images from static configuration */
130 for (i = 0; element_to_graphic[i].element > -1; i++)
131 InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
133 /* initialize special images from static configuration */
134 for (i = 0; element_to_special_graphic[i].element > -1; i++)
135 InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
137 /* initialize images from dynamic configuration (may be elements or other) */
138 for (i = 0; i < num_property_mappings; i++)
139 InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
141 /* initialize special images from above list (non-element images) */
142 for (i = 0; special_graphics[i] > -1; i++)
143 InitElementSmallImagesScaledUp(special_graphics[i]);
147 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
148 void SetBitmaps_EM(Bitmap **em_bitmap)
150 em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
151 em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
155 static int getFontBitmapID(int font_nr)
159 if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
160 special = game_status;
161 else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
162 special = GFX_SPECIAL_ARG_MAIN;
163 else if (game_status == GAME_MODE_PLAYING)
164 special = GFX_SPECIAL_ARG_DOOR;
167 return font_info[font_nr].special_bitmap_id[special];
172 void InitFontGraphicInfo()
174 static struct FontBitmapInfo *font_bitmap_info = NULL;
175 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
176 int num_property_mappings = getImageListPropertyMappingSize();
177 int num_font_bitmaps = NUM_FONTS;
180 if (graphic_info == NULL) /* still at startup phase */
182 InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
187 /* ---------- initialize font graphic definitions ---------- */
189 /* always start with reliable default values (normal font graphics) */
190 for (i = 0; i < NUM_FONTS; i++)
191 font_info[i].graphic = IMG_FONT_INITIAL_1;
193 /* initialize normal font/graphic mapping from static configuration */
194 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
196 int font_nr = font_to_graphic[i].font_nr;
197 int special = font_to_graphic[i].special;
198 int graphic = font_to_graphic[i].graphic;
203 font_info[font_nr].graphic = graphic;
206 /* always start with reliable default values (special font graphics) */
207 for (i = 0; i < NUM_FONTS; i++)
209 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
211 font_info[i].special_graphic[j] = font_info[i].graphic;
212 font_info[i].special_bitmap_id[j] = i;
216 /* initialize special font/graphic mapping from static configuration */
217 for (i = 0; font_to_graphic[i].font_nr > -1; i++)
219 int font_nr = font_to_graphic[i].font_nr;
220 int special = font_to_graphic[i].special;
221 int graphic = font_to_graphic[i].graphic;
222 int base_graphic = font2baseimg(font_nr);
224 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
226 boolean base_redefined =
227 getImageListEntryFromImageID(base_graphic)->redefined;
228 boolean special_redefined =
229 getImageListEntryFromImageID(graphic)->redefined;
231 /* if the base font ("font.title_1", for example) has been redefined,
232 but not the special font ("font.title_1.LEVELS", for example), do not
233 use an existing (in this case considered obsolete) special font
234 anymore, but use the automatically determined default font */
235 if (base_redefined && !special_redefined)
238 font_info[font_nr].special_graphic[special] = graphic;
239 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
244 /* initialize special element/graphic mapping from dynamic configuration */
245 for (i = 0; i < num_property_mappings; i++)
247 int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
248 int special = property_mapping[i].ext3_index;
249 int graphic = property_mapping[i].artwork_index;
254 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
256 font_info[font_nr].special_graphic[special] = graphic;
257 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
262 /* ---------- initialize font bitmap array ---------- */
264 if (font_bitmap_info != NULL)
265 FreeFontInfo(font_bitmap_info);
268 checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
270 /* ---------- initialize font bitmap definitions ---------- */
272 for (i = 0; i < NUM_FONTS; i++)
274 if (i < NUM_INITIAL_FONTS)
276 font_bitmap_info[i] = font_initial[i];
280 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
282 int font_bitmap_id = font_info[i].special_bitmap_id[j];
283 int graphic = font_info[i].special_graphic[j];
285 /* set 'graphic_info' for font entries, if uninitialized (guessed) */
286 if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
288 graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
289 graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
292 /* copy font relevant information from graphics information */
293 font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
294 font_bitmap_info[font_bitmap_id].src_x = graphic_info[graphic].src_x;
295 font_bitmap_info[font_bitmap_id].src_y = graphic_info[graphic].src_y;
296 font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
297 font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
298 font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
299 font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
301 font_bitmap_info[font_bitmap_id].num_chars =
302 graphic_info[graphic].anim_frames;
303 font_bitmap_info[font_bitmap_id].num_chars_per_line =
304 graphic_info[graphic].anim_frames_per_line;
308 InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
311 void InitElementGraphicInfo()
313 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
314 int num_property_mappings = getImageListPropertyMappingSize();
317 if (graphic_info == NULL) /* still at startup phase */
320 /* set values to -1 to identify later as "uninitialized" values */
321 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
323 for (act = 0; act < NUM_ACTIONS; act++)
325 element_info[i].graphic[act] = -1;
326 element_info[i].crumbled[act] = -1;
328 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
330 element_info[i].direction_graphic[act][dir] = -1;
331 element_info[i].direction_crumbled[act][dir] = -1;
336 /* initialize normal element/graphic mapping from static configuration */
337 for (i = 0; element_to_graphic[i].element > -1; i++)
339 int element = element_to_graphic[i].element;
340 int action = element_to_graphic[i].action;
341 int direction = element_to_graphic[i].direction;
342 boolean crumbled = element_to_graphic[i].crumbled;
343 int graphic = element_to_graphic[i].graphic;
344 int base_graphic = el2baseimg(element);
346 if (graphic_info[graphic].bitmap == NULL)
349 if ((action > -1 || direction > -1 || crumbled == TRUE) &&
352 boolean base_redefined =
353 getImageListEntryFromImageID(base_graphic)->redefined;
354 boolean act_dir_redefined =
355 getImageListEntryFromImageID(graphic)->redefined;
357 /* if the base graphic ("emerald", for example) has been redefined,
358 but not the action graphic ("emerald.falling", for example), do not
359 use an existing (in this case considered obsolete) action graphic
360 anymore, but use the automatically determined default graphic */
361 if (base_redefined && !act_dir_redefined)
366 action = ACTION_DEFAULT;
371 element_info[element].direction_crumbled[action][direction] = graphic;
373 element_info[element].crumbled[action] = graphic;
378 element_info[element].direction_graphic[action][direction] = graphic;
380 element_info[element].graphic[action] = graphic;
384 /* initialize normal element/graphic mapping from dynamic configuration */
385 for (i = 0; i < num_property_mappings; i++)
387 int element = property_mapping[i].base_index;
388 int action = property_mapping[i].ext1_index;
389 int direction = property_mapping[i].ext2_index;
390 int special = property_mapping[i].ext3_index;
391 int graphic = property_mapping[i].artwork_index;
392 boolean crumbled = FALSE;
394 if (special == GFX_SPECIAL_ARG_CRUMBLED)
400 if (graphic_info[graphic].bitmap == NULL)
403 if (element >= MAX_NUM_ELEMENTS || special != -1)
407 action = ACTION_DEFAULT;
412 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
413 element_info[element].direction_crumbled[action][dir] = -1;
416 element_info[element].direction_crumbled[action][direction] = graphic;
418 element_info[element].crumbled[action] = graphic;
423 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
424 element_info[element].direction_graphic[action][dir] = -1;
427 element_info[element].direction_graphic[action][direction] = graphic;
429 element_info[element].graphic[action] = graphic;
433 /* now copy all graphics that are defined to be cloned from other graphics */
434 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
436 int graphic = element_info[i].graphic[ACTION_DEFAULT];
437 int crumbled_like, diggable_like;
442 crumbled_like = graphic_info[graphic].crumbled_like;
443 diggable_like = graphic_info[graphic].diggable_like;
445 if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
447 for (act = 0; act < NUM_ACTIONS; act++)
448 element_info[i].crumbled[act] =
449 element_info[crumbled_like].crumbled[act];
450 for (act = 0; act < NUM_ACTIONS; act++)
451 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
452 element_info[i].direction_crumbled[act][dir] =
453 element_info[crumbled_like].direction_crumbled[act][dir];
456 if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
458 element_info[i].graphic[ACTION_DIGGING] =
459 element_info[diggable_like].graphic[ACTION_DIGGING];
460 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
461 element_info[i].direction_graphic[ACTION_DIGGING][dir] =
462 element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
467 /* set hardcoded definitions for some runtime elements without graphic */
468 element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
472 /* set hardcoded definitions for some internal elements without graphic */
473 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
475 if (IS_EDITOR_CASCADE_INACTIVE(i))
476 element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST;
477 else if (IS_EDITOR_CASCADE_ACTIVE(i))
478 element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
482 /* now set all undefined/invalid graphics to -1 to set to default after it */
483 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
485 for (act = 0; act < NUM_ACTIONS; act++)
489 graphic = element_info[i].graphic[act];
490 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
491 element_info[i].graphic[act] = -1;
493 graphic = element_info[i].crumbled[act];
494 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
495 element_info[i].crumbled[act] = -1;
497 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
499 graphic = element_info[i].direction_graphic[act][dir];
500 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
501 element_info[i].direction_graphic[act][dir] = -1;
503 graphic = element_info[i].direction_crumbled[act][dir];
504 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
505 element_info[i].direction_crumbled[act][dir] = -1;
510 /* adjust graphics with 2nd tile for movement according to direction
511 (do this before correcting '-1' values to minimize calculations) */
512 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
514 for (act = 0; act < NUM_ACTIONS; act++)
516 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
518 int graphic = element_info[i].direction_graphic[act][dir];
519 int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
521 if (act == ACTION_FALLING) /* special case */
522 graphic = element_info[i].graphic[act];
525 graphic_info[graphic].double_movement &&
526 graphic_info[graphic].swap_double_tiles != 0)
528 struct GraphicInfo *g = &graphic_info[graphic];
529 int src_x_front = g->src_x;
530 int src_y_front = g->src_y;
531 int src_x_back = g->src_x + g->offset2_x;
532 int src_y_back = g->src_y + g->offset2_y;
533 boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
535 boolean front_is_left_or_upper = (src_x_front < src_x_back ||
536 src_y_front < src_y_back);
537 boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
538 boolean swap_movement_tiles_autodetected =
539 (!frames_are_ordered_diagonally &&
540 ((move_dir == MV_BIT_LEFT && !front_is_left_or_upper) ||
541 (move_dir == MV_BIT_UP && !front_is_left_or_upper) ||
542 (move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
543 (move_dir == MV_BIT_DOWN && front_is_left_or_upper)));
546 /* swap frontside and backside graphic tile coordinates, if needed */
547 if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
549 /* get current (wrong) backside tile coordinates */
550 getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
553 /* set frontside tile coordinates to backside tile coordinates */
554 g->src_x = src_x_back;
555 g->src_y = src_y_back;
557 /* invert tile offset to point to new backside tile coordinates */
561 /* do not swap front and backside tiles again after correction */
562 g->swap_double_tiles = 0;
569 /* now set all '-1' values to element specific default values */
570 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
572 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
573 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
574 int default_direction_graphic[NUM_DIRECTIONS_FULL];
575 int default_direction_crumbled[NUM_DIRECTIONS_FULL];
577 if (default_graphic == -1)
578 default_graphic = IMG_UNKNOWN;
580 if (default_crumbled == -1)
581 default_crumbled = default_graphic;
583 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
584 if (default_crumbled == -1)
585 default_crumbled = IMG_EMPTY;
588 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
590 default_direction_graphic[dir] =
591 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
592 default_direction_crumbled[dir] =
593 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
595 if (default_direction_graphic[dir] == -1)
596 default_direction_graphic[dir] = default_graphic;
598 if (default_direction_crumbled[dir] == -1)
599 default_direction_crumbled[dir] = default_direction_graphic[dir];
601 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
602 if (default_direction_crumbled[dir] == -1)
603 default_direction_crumbled[dir] = default_crumbled;
607 for (act = 0; act < NUM_ACTIONS; act++)
609 boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
610 (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
611 (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
612 boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
613 act == ACTION_TURNING_FROM_RIGHT ||
614 act == ACTION_TURNING_FROM_UP ||
615 act == ACTION_TURNING_FROM_DOWN);
617 /* generic default action graphic (defined by "[default]" directive) */
618 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
619 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
620 int default_remove_graphic = IMG_EMPTY;
622 if (act_remove && default_action_graphic != -1)
623 default_remove_graphic = default_action_graphic;
625 /* look for special default action graphic (classic game specific) */
626 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
627 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
628 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
629 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
630 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
631 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
633 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
634 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
635 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
636 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
637 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
638 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
641 /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
642 /* !!! make this better !!! */
643 if (i == EL_EMPTY_SPACE)
645 default_action_graphic = element_info[EL_DEFAULT].graphic[act];
646 default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
650 if (default_action_graphic == -1)
651 default_action_graphic = default_graphic;
653 if (default_action_crumbled == -1)
654 default_action_crumbled = default_action_graphic;
656 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
657 if (default_action_crumbled == -1)
658 default_action_crumbled = default_crumbled;
661 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
663 /* use action graphic as the default direction graphic, if undefined */
664 int default_action_direction_graphic = element_info[i].graphic[act];
665 int default_action_direction_crumbled = element_info[i].crumbled[act];
667 /* no graphic for current action -- use default direction graphic */
668 if (default_action_direction_graphic == -1)
669 default_action_direction_graphic =
670 (act_remove ? default_remove_graphic :
672 element_info[i].direction_graphic[ACTION_TURNING][dir] :
673 default_action_graphic != default_graphic ?
674 default_action_graphic :
675 default_direction_graphic[dir]);
677 if (element_info[i].direction_graphic[act][dir] == -1)
678 element_info[i].direction_graphic[act][dir] =
679 default_action_direction_graphic;
682 if (default_action_direction_crumbled == -1)
683 default_action_direction_crumbled =
684 element_info[i].direction_graphic[act][dir];
686 if (default_action_direction_crumbled == -1)
687 default_action_direction_crumbled =
688 (act_remove ? default_remove_graphic :
690 element_info[i].direction_crumbled[ACTION_TURNING][dir] :
691 default_action_crumbled != default_crumbled ?
692 default_action_crumbled :
693 default_direction_crumbled[dir]);
696 if (element_info[i].direction_crumbled[act][dir] == -1)
697 element_info[i].direction_crumbled[act][dir] =
698 default_action_direction_crumbled;
701 /* no graphic for this specific action -- use default action graphic */
702 if (element_info[i].graphic[act] == -1)
703 element_info[i].graphic[act] =
704 (act_remove ? default_remove_graphic :
705 act_turning ? element_info[i].graphic[ACTION_TURNING] :
706 default_action_graphic);
708 if (element_info[i].crumbled[act] == -1)
709 element_info[i].crumbled[act] = element_info[i].graphic[act];
711 if (element_info[i].crumbled[act] == -1)
712 element_info[i].crumbled[act] =
713 (act_remove ? default_remove_graphic :
714 act_turning ? element_info[i].crumbled[ACTION_TURNING] :
715 default_action_crumbled);
721 /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */
722 /* set animation mode to "none" for each graphic with only 1 frame */
723 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
725 for (act = 0; act < NUM_ACTIONS; act++)
727 int graphic = element_info[i].graphic[act];
728 int crumbled = element_info[i].crumbled[act];
730 if (graphic_info[graphic].anim_frames == 1)
731 graphic_info[graphic].anim_mode = ANIM_NONE;
732 if (graphic_info[crumbled].anim_frames == 1)
733 graphic_info[crumbled].anim_mode = ANIM_NONE;
735 for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
737 graphic = element_info[i].direction_graphic[act][dir];
738 crumbled = element_info[i].direction_crumbled[act][dir];
740 if (graphic_info[graphic].anim_frames == 1)
741 graphic_info[graphic].anim_mode = ANIM_NONE;
742 if (graphic_info[crumbled].anim_frames == 1)
743 graphic_info[crumbled].anim_mode = ANIM_NONE;
753 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
754 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
756 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
757 element_info[i].token_name, i);
763 void InitElementSpecialGraphicInfo()
765 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
766 int num_property_mappings = getImageListPropertyMappingSize();
769 /* always start with reliable default values */
770 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
771 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
772 element_info[i].special_graphic[j] =
773 element_info[i].graphic[ACTION_DEFAULT];
775 /* initialize special element/graphic mapping from static configuration */
776 for (i = 0; element_to_special_graphic[i].element > -1; i++)
778 int element = element_to_special_graphic[i].element;
779 int special = element_to_special_graphic[i].special;
780 int graphic = element_to_special_graphic[i].graphic;
781 int base_graphic = el2baseimg(element);
782 boolean base_redefined =
783 getImageListEntryFromImageID(base_graphic)->redefined;
784 boolean special_redefined =
785 getImageListEntryFromImageID(graphic)->redefined;
787 /* if the base graphic ("emerald", for example) has been redefined,
788 but not the special graphic ("emerald.EDITOR", for example), do not
789 use an existing (in this case considered obsolete) special graphic
790 anymore, but use the automatically created (down-scaled) graphic */
791 if (base_redefined && !special_redefined)
794 element_info[element].special_graphic[special] = graphic;
797 /* initialize special element/graphic mapping from dynamic configuration */
798 for (i = 0; i < num_property_mappings; i++)
800 int element = property_mapping[i].base_index;
801 int special = property_mapping[i].ext3_index;
802 int graphic = property_mapping[i].artwork_index;
804 if (element >= MAX_NUM_ELEMENTS)
807 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
808 element_info[element].special_graphic[special] = graphic;
811 /* now set all undefined/invalid graphics to default */
812 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
813 for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
814 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
815 element_info[i].special_graphic[j] =
816 element_info[i].graphic[ACTION_DEFAULT];
819 static int get_graphic_parameter_value(char *value_raw, char *suffix, int type)
824 if (type != TYPE_TOKEN)
825 return get_parameter_value(value_raw, suffix, type);
827 if (strcmp(value_raw, ARG_UNDEFINED) == 0)
828 return ARG_UNDEFINED_VALUE;
830 /* !!! OPTIMIZE THIS BY USING HASH !!! */
831 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
832 if (strcmp(element_info[i].token_name, value_raw) == 0)
835 /* !!! OPTIMIZE THIS BY USING HASH !!! */
836 for (i = 0; image_config[i].token != NULL; i++)
838 int len_config_value = strlen(image_config[i].value);
840 if (strcmp(&image_config[i].value[len_config_value - 4], ".pcx") != 0 &&
841 strcmp(&image_config[i].value[len_config_value - 4], ".wav") != 0 &&
842 strcmp(image_config[i].value, UNDEFINED_FILENAME) != 0)
845 if (strcmp(image_config[i].token, value_raw) == 0)
854 static int get_scaled_graphic_width(int graphic)
856 int original_width = getOriginalImageWidthFromImageID(graphic);
857 int scale_up_factor = graphic_info[graphic].scale_up_factor;
859 return original_width * scale_up_factor;
862 static int get_scaled_graphic_height(int graphic)
864 int original_height = getOriginalImageHeightFromImageID(graphic);
865 int scale_up_factor = graphic_info[graphic].scale_up_factor;
867 return original_height * scale_up_factor;
870 static void set_graphic_parameters(int graphic)
872 struct FileInfo *image = getImageListEntryFromImageID(graphic);
873 char **parameter_raw = image->parameter;
874 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
875 int parameter[NUM_GFX_ARGS];
876 int anim_frames_per_row = 1, anim_frames_per_col = 1;
877 int anim_frames_per_line = 1;
880 /* if fallback to default artwork is done, also use the default parameters */
881 if (image->fallback_to_default)
882 parameter_raw = image->default_parameter;
884 /* get integer values from string parameters */
885 for (i = 0; i < NUM_GFX_ARGS; i++)
886 parameter[i] = get_graphic_parameter_value(parameter_raw[i],
887 image_config_suffix[i].token,
888 image_config_suffix[i].type);
890 graphic_info[graphic].bitmap = src_bitmap;
892 /* start with reliable default values */
893 graphic_info[graphic].src_image_width = 0;
894 graphic_info[graphic].src_image_height = 0;
895 graphic_info[graphic].src_x = 0;
896 graphic_info[graphic].src_y = 0;
897 graphic_info[graphic].width = TILEX;
898 graphic_info[graphic].height = TILEY;
899 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
900 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
901 graphic_info[graphic].offset2_x = 0; /* one or both of these values ... */
902 graphic_info[graphic].offset2_y = 0; /* ... will be corrected later */
903 graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */
904 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
905 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
906 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
907 graphic_info[graphic].scale_up_factor = 1; /* default: no scaling up */
908 graphic_info[graphic].clone_from = -1; /* do not use clone graphic */
909 graphic_info[graphic].anim_delay_fixed = 0;
910 graphic_info[graphic].anim_delay_random = 0;
911 graphic_info[graphic].post_delay_fixed = 0;
912 graphic_info[graphic].post_delay_random = 0;
914 /* optional x and y tile position of animation frame sequence */
915 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
916 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
917 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
918 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
920 /* optional x and y pixel position of animation frame sequence */
921 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
922 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
923 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
924 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
926 /* optional width and height of each animation frame */
927 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
928 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
929 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
930 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
932 /* optional zoom factor for scaling up the image to a larger size */
933 if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
934 graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
935 if (graphic_info[graphic].scale_up_factor < 1)
936 graphic_info[graphic].scale_up_factor = 1; /* no scaling */
940 /* get final bitmap size (with scaling, but without small images) */
941 int src_image_width = get_scaled_graphic_width(graphic);
942 int src_image_height = get_scaled_graphic_height(graphic);
944 anim_frames_per_row = src_image_width / graphic_info[graphic].width;
945 anim_frames_per_col = src_image_height / graphic_info[graphic].height;
947 graphic_info[graphic].src_image_width = src_image_width;
948 graphic_info[graphic].src_image_height = src_image_height;
951 /* correct x or y offset dependent of vertical or horizontal frame order */
952 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
954 graphic_info[graphic].offset_y =
955 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
956 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
957 anim_frames_per_line = anim_frames_per_col;
959 else /* frames are ordered horizontally */
961 graphic_info[graphic].offset_x =
962 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
963 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
964 anim_frames_per_line = anim_frames_per_row;
967 /* optionally, the x and y offset of frames can be specified directly */
968 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
969 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
970 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
971 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
973 /* optionally, moving animations may have separate start and end graphics */
974 graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
976 if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
977 parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
979 /* correct x or y offset2 dependent of vertical or horizontal frame order */
980 if (parameter[GFX_ARG_2ND_VERTICAL]) /* frames are ordered vertically */
981 graphic_info[graphic].offset2_y =
982 (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
983 parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
984 else /* frames are ordered horizontally */
985 graphic_info[graphic].offset2_x =
986 (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
987 parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
989 /* optionally, the x and y offset of 2nd graphic can be specified directly */
990 if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
991 graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
992 if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
993 graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
995 /* optionally, the second movement tile can be specified as start tile */
996 if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
997 graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
999 /* automatically determine correct number of frames, if not defined */
1000 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1001 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
1002 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1003 graphic_info[graphic].anim_frames = anim_frames_per_row;
1004 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1005 graphic_info[graphic].anim_frames = anim_frames_per_col;
1007 graphic_info[graphic].anim_frames = 1;
1009 graphic_info[graphic].anim_frames_per_line =
1010 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1011 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1013 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
1014 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
1015 graphic_info[graphic].anim_delay = 1;
1017 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
1019 if (graphic_info[graphic].anim_frames == 1)
1020 graphic_info[graphic].anim_mode = ANIM_NONE;
1023 /* automatically determine correct start frame, if not defined */
1024 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1025 graphic_info[graphic].anim_start_frame = 0;
1026 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
1027 graphic_info[graphic].anim_start_frame =
1028 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1030 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
1032 /* animation synchronized with global frame counter, not move position */
1033 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1035 /* optional element for cloning crumble graphics */
1036 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1037 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1039 /* optional element for cloning digging graphics */
1040 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1041 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1043 /* optional border size for "crumbling" diggable graphics */
1044 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1045 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
1047 /* this is only used for player "boring" and "sleeping" actions */
1048 if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1049 graphic_info[graphic].anim_delay_fixed =
1050 parameter[GFX_ARG_ANIM_DELAY_FIXED];
1051 if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1052 graphic_info[graphic].anim_delay_random =
1053 parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1054 if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1055 graphic_info[graphic].post_delay_fixed =
1056 parameter[GFX_ARG_POST_DELAY_FIXED];
1057 if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1058 graphic_info[graphic].post_delay_random =
1059 parameter[GFX_ARG_POST_DELAY_RANDOM];
1061 /* this is only used for toon animations */
1062 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
1063 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
1065 /* this is only used for drawing font characters */
1066 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
1067 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
1069 /* this is only used for drawing envelope graphics */
1070 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1072 /* optional graphic for cloning all graphics settings */
1073 if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
1074 graphic_info[graphic].clone_from = parameter[GFX_ARG_CLONE_FROM];
1077 static void set_cloned_graphic_parameters(int graphic)
1079 int fallback_graphic = IMG_CHAR_EXCLAM;
1080 int max_num_images = getImageListSize();
1081 int clone_graphic = graphic_info[graphic].clone_from;
1082 int num_references_followed = 1;
1084 while (graphic_info[clone_graphic].clone_from != -1 &&
1085 num_references_followed < max_num_images)
1087 clone_graphic = graphic_info[clone_graphic].clone_from;
1089 num_references_followed++;
1092 if (num_references_followed >= max_num_images)
1094 Error(ERR_RETURN_LINE, "-");
1095 Error(ERR_RETURN, "warning: error found in config file:");
1096 Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
1097 Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(graphic));
1098 Error(ERR_RETURN, "error: loop discovered when resolving cloned graphics");
1099 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1101 if (graphic == fallback_graphic)
1102 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1104 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1105 Error(ERR_RETURN_LINE, "-");
1107 graphic_info[graphic] = graphic_info[fallback_graphic];
1111 graphic_info[graphic] = graphic_info[clone_graphic];
1112 graphic_info[graphic].clone_from = clone_graphic;
1116 static void InitGraphicInfo()
1118 int fallback_graphic = IMG_CHAR_EXCLAM;
1119 int num_images = getImageListSize();
1122 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1123 static boolean clipmasks_initialized = FALSE;
1125 XGCValues clip_gc_values;
1126 unsigned long clip_gc_valuemask;
1127 GC copy_clipmask_gc = None;
1130 checked_free(graphic_info);
1132 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1134 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1135 if (clipmasks_initialized)
1137 for (i = 0; i < num_images; i++)
1139 if (graphic_info[i].clip_mask)
1140 XFreePixmap(display, graphic_info[i].clip_mask);
1141 if (graphic_info[i].clip_gc)
1142 XFreeGC(display, graphic_info[i].clip_gc);
1144 graphic_info[i].clip_mask = None;
1145 graphic_info[i].clip_gc = None;
1150 /* first set all graphic paramaters ... */
1151 for (i = 0; i < num_images; i++)
1152 set_graphic_parameters(i);
1154 /* ... then copy these parameters for cloned graphics */
1155 for (i = 0; i < num_images; i++)
1156 if (graphic_info[i].clone_from != -1)
1157 set_cloned_graphic_parameters(i);
1159 for (i = 0; i < num_images; i++)
1163 int first_frame, last_frame;
1164 int src_bitmap_width, src_bitmap_height;
1166 /* now check if no animation frames are outside of the loaded image */
1168 if (graphic_info[i].bitmap == NULL)
1169 continue; /* skip check for optional images that are undefined */
1171 /* get final bitmap size (with scaling, but without small images) */
1172 src_bitmap_width = graphic_info[i].src_image_width;
1173 src_bitmap_height = graphic_info[i].src_image_height;
1175 /* check if first animation frame is inside specified bitmap */
1178 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1180 if (src_x < 0 || src_y < 0 ||
1181 src_x + TILEX > src_bitmap_width ||
1182 src_y + TILEY > src_bitmap_height)
1184 Error(ERR_RETURN_LINE, "-");
1185 Error(ERR_RETURN, "warning: error found in config file:");
1186 Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
1187 Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i));
1188 Error(ERR_RETURN, "- image file: '%s'", src_bitmap->source_filename);
1190 "error: first animation frame out of bounds (%d, %d) [%d, %d]",
1191 src_x, src_y, src_bitmap_width, src_bitmap_height);
1192 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1194 if (i == fallback_graphic)
1195 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1197 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1198 Error(ERR_RETURN_LINE, "-");
1200 graphic_info[i] = graphic_info[fallback_graphic];
1203 /* check if last animation frame is inside specified bitmap */
1205 last_frame = graphic_info[i].anim_frames - 1;
1206 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1208 if (src_x < 0 || src_y < 0 ||
1209 src_x + TILEX > src_bitmap_width ||
1210 src_y + TILEY > src_bitmap_height)
1212 Error(ERR_RETURN_LINE, "-");
1213 Error(ERR_RETURN, "warning: error found in config file:");
1214 Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
1215 Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i));
1216 Error(ERR_RETURN, "- image file: '%s'", src_bitmap->source_filename);
1218 "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
1219 last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
1220 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1222 if (i == fallback_graphic)
1223 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1225 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1226 Error(ERR_RETURN_LINE, "-");
1228 graphic_info[i] = graphic_info[fallback_graphic];
1231 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1232 /* currently we only need a tile clip mask from the first frame */
1233 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1235 if (copy_clipmask_gc == None)
1237 clip_gc_values.graphics_exposures = False;
1238 clip_gc_valuemask = GCGraphicsExposures;
1239 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1240 clip_gc_valuemask, &clip_gc_values);
1243 graphic_info[i].clip_mask =
1244 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1246 src_pixmap = src_bitmap->clip_mask;
1247 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1248 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1250 clip_gc_values.graphics_exposures = False;
1251 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1252 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1254 graphic_info[i].clip_gc =
1255 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1259 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1260 if (copy_clipmask_gc)
1261 XFreeGC(display, copy_clipmask_gc);
1263 clipmasks_initialized = TRUE;
1267 static void InitElementSoundInfo()
1269 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1270 int num_property_mappings = getSoundListPropertyMappingSize();
1273 /* set values to -1 to identify later as "uninitialized" values */
1274 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1275 for (act = 0; act < NUM_ACTIONS; act++)
1276 element_info[i].sound[act] = -1;
1278 /* initialize element/sound mapping from static configuration */
1279 for (i = 0; element_to_sound[i].element > -1; i++)
1281 int element = element_to_sound[i].element;
1282 int action = element_to_sound[i].action;
1283 int sound = element_to_sound[i].sound;
1284 boolean is_class = element_to_sound[i].is_class;
1287 action = ACTION_DEFAULT;
1290 element_info[element].sound[action] = sound;
1292 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1293 if (strcmp(element_info[j].class_name,
1294 element_info[element].class_name) == 0)
1295 element_info[j].sound[action] = sound;
1298 /* initialize element class/sound mapping from dynamic configuration */
1299 for (i = 0; i < num_property_mappings; i++)
1301 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1302 int action = property_mapping[i].ext1_index;
1303 int sound = property_mapping[i].artwork_index;
1305 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1309 action = ACTION_DEFAULT;
1311 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1312 if (strcmp(element_info[j].class_name,
1313 element_info[element_class].class_name) == 0)
1314 element_info[j].sound[action] = sound;
1317 /* initialize element/sound mapping from dynamic configuration */
1318 for (i = 0; i < num_property_mappings; i++)
1320 int element = property_mapping[i].base_index;
1321 int action = property_mapping[i].ext1_index;
1322 int sound = property_mapping[i].artwork_index;
1324 if (element >= MAX_NUM_ELEMENTS)
1328 action = ACTION_DEFAULT;
1330 element_info[element].sound[action] = sound;
1333 /* now set all '-1' values to element specific default values */
1334 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1336 for (act = 0; act < NUM_ACTIONS; act++)
1338 /* generic default action sound (defined by "[default]" directive) */
1339 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1341 /* look for special default action sound (classic game specific) */
1342 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1343 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1344 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1345 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1346 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1347 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1349 /* !!! there's no such thing as a "default action sound" !!! */
1351 /* look for element specific default sound (independent from action) */
1352 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1353 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1357 /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
1358 /* !!! make this better !!! */
1359 if (i == EL_EMPTY_SPACE)
1360 default_action_sound = element_info[EL_DEFAULT].sound[act];
1363 /* no sound for this specific action -- use default action sound */
1364 if (element_info[i].sound[act] == -1)
1365 element_info[i].sound[act] = default_action_sound;
1369 /* copy sound settings to some elements that are only stored in level file
1370 in native R'n'D levels, but are used by game engine in native EM levels */
1371 for (i = 0; copy_properties[i][0] != -1; i++)
1372 for (j = 1; j <= 4; j++)
1373 for (act = 0; act < NUM_ACTIONS; act++)
1374 element_info[copy_properties[i][j]].sound[act] =
1375 element_info[copy_properties[i][0]].sound[act];
1378 static void InitGameModeSoundInfo()
1382 /* set values to -1 to identify later as "uninitialized" values */
1383 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1386 /* initialize gamemode/sound mapping from static configuration */
1387 for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1389 int gamemode = gamemode_to_sound[i].gamemode;
1390 int sound = gamemode_to_sound[i].sound;
1393 gamemode = GAME_MODE_DEFAULT;
1395 menu.sound[gamemode] = sound;
1398 /* now set all '-1' values to levelset specific default values */
1399 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1400 if (menu.sound[i] == -1)
1401 menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1404 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1405 if (menu.sound[i] != -1)
1406 printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1410 static void set_sound_parameters(int sound, char **parameter_raw)
1412 int parameter[NUM_SND_ARGS];
1415 /* get integer values from string parameters */
1416 for (i = 0; i < NUM_SND_ARGS; i++)
1418 get_parameter_value(parameter_raw[i],
1419 sound_config_suffix[i].token,
1420 sound_config_suffix[i].type);
1422 /* explicit loop mode setting in configuration overrides default value */
1423 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1424 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1426 /* sound volume to change the original volume when loading the sound file */
1427 sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1429 /* sound priority to give certain sounds a higher or lower priority */
1430 sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1433 static void InitSoundInfo()
1435 int *sound_effect_properties;
1436 int num_sounds = getSoundListSize();
1439 checked_free(sound_info);
1441 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1442 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1444 /* initialize sound effect for all elements to "no sound" */
1445 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1446 for (j = 0; j < NUM_ACTIONS; j++)
1447 element_info[i].sound[j] = SND_UNDEFINED;
1449 for (i = 0; i < num_sounds; i++)
1451 struct FileInfo *sound = getSoundListEntry(i);
1452 int len_effect_text = strlen(sound->token);
1454 sound_effect_properties[i] = ACTION_OTHER;
1455 sound_info[i].loop = FALSE; /* default: play sound only once */
1458 printf("::: sound %d: '%s'\n", i, sound->token);
1461 /* determine all loop sounds and identify certain sound classes */
1463 for (j = 0; element_action_info[j].suffix; j++)
1465 int len_action_text = strlen(element_action_info[j].suffix);
1467 if (len_action_text < len_effect_text &&
1468 strcmp(&sound->token[len_effect_text - len_action_text],
1469 element_action_info[j].suffix) == 0)
1471 sound_effect_properties[i] = element_action_info[j].value;
1472 sound_info[i].loop = element_action_info[j].is_loop_sound;
1478 /* associate elements and some selected sound actions */
1480 for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1482 if (element_info[j].class_name)
1484 int len_class_text = strlen(element_info[j].class_name);
1486 if (len_class_text + 1 < len_effect_text &&
1487 strncmp(sound->token,
1488 element_info[j].class_name, len_class_text) == 0 &&
1489 sound->token[len_class_text] == '.')
1491 int sound_action_value = sound_effect_properties[i];
1493 element_info[j].sound[sound_action_value] = i;
1498 set_sound_parameters(i, sound->parameter);
1501 free(sound_effect_properties);
1504 static void InitGameModeMusicInfo()
1506 struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1507 int num_property_mappings = getMusicListPropertyMappingSize();
1508 int default_levelset_music = -1;
1511 /* set values to -1 to identify later as "uninitialized" values */
1512 for (i = 0; i < MAX_LEVELS; i++)
1513 levelset.music[i] = -1;
1514 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1517 /* initialize gamemode/music mapping from static configuration */
1518 for (i = 0; gamemode_to_music[i].music > -1; i++)
1520 int gamemode = gamemode_to_music[i].gamemode;
1521 int music = gamemode_to_music[i].music;
1524 printf("::: gamemode == %d, music == %d\n", gamemode, music);
1528 gamemode = GAME_MODE_DEFAULT;
1530 menu.music[gamemode] = music;
1533 /* initialize gamemode/music mapping from dynamic configuration */
1534 for (i = 0; i < num_property_mappings; i++)
1536 int prefix = property_mapping[i].base_index;
1537 int gamemode = property_mapping[i].ext1_index;
1538 int level = property_mapping[i].ext2_index;
1539 int music = property_mapping[i].artwork_index;
1542 printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1543 prefix, gamemode, level, music);
1546 if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1550 gamemode = GAME_MODE_DEFAULT;
1552 /* level specific music only allowed for in-game music */
1553 if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1554 gamemode = GAME_MODE_PLAYING;
1559 default_levelset_music = music;
1562 if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1563 levelset.music[level] = music;
1564 if (gamemode != GAME_MODE_PLAYING)
1565 menu.music[gamemode] = music;
1568 /* now set all '-1' values to menu specific default values */
1569 /* (undefined values of "levelset.music[]" might stay at "-1" to
1570 allow dynamic selection of music files from music directory!) */
1571 for (i = 0; i < MAX_LEVELS; i++)
1572 if (levelset.music[i] == -1)
1573 levelset.music[i] = default_levelset_music;
1574 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1575 if (menu.music[i] == -1)
1576 menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1579 for (i = 0; i < MAX_LEVELS; i++)
1580 if (levelset.music[i] != -1)
1581 printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1582 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1583 if (menu.music[i] != -1)
1584 printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1588 static void set_music_parameters(int music, char **parameter_raw)
1590 int parameter[NUM_MUS_ARGS];
1593 /* get integer values from string parameters */
1594 for (i = 0; i < NUM_MUS_ARGS; i++)
1596 get_parameter_value(parameter_raw[i],
1597 music_config_suffix[i].token,
1598 music_config_suffix[i].type);
1600 /* explicit loop mode setting in configuration overrides default value */
1601 if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1602 music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
1605 static void InitMusicInfo()
1607 int num_music = getMusicListSize();
1610 checked_free(music_info);
1612 music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
1614 for (i = 0; i < num_music; i++)
1616 struct FileInfo *music = getMusicListEntry(i);
1617 int len_music_text = strlen(music->token);
1619 music_info[i].loop = TRUE; /* default: play music in loop mode */
1621 /* determine all loop music */
1623 for (j = 0; music_prefix_info[j].prefix; j++)
1625 int len_prefix_text = strlen(music_prefix_info[j].prefix);
1627 if (len_prefix_text < len_music_text &&
1628 strncmp(music->token,
1629 music_prefix_info[j].prefix, len_prefix_text) == 0)
1631 music_info[i].loop = music_prefix_info[j].is_loop_music;
1637 set_music_parameters(i, music->parameter);
1641 static void ReinitializeGraphics()
1643 InitGraphicInfo(); /* graphic properties mapping */
1644 InitElementGraphicInfo(); /* element game graphic mapping */
1645 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1647 InitElementSmallImages(); /* scale images to all needed sizes */
1648 InitFontGraphicInfo(); /* initialize text drawing functions */
1650 InitGraphicInfo_EM(); /* graphic mapping for EM engine */
1652 SetMainBackgroundImage(IMG_BACKGROUND);
1653 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1659 static void ReinitializeSounds()
1661 InitSoundInfo(); /* sound properties mapping */
1662 InitElementSoundInfo(); /* element game sound mapping */
1663 InitGameModeSoundInfo(); /* game mode sound mapping */
1665 InitPlayLevelSound(); /* internal game sound settings */
1668 static void ReinitializeMusic()
1670 InitMusicInfo(); /* music properties mapping */
1671 InitGameModeMusicInfo(); /* game mode music mapping */
1674 static int get_special_property_bit(int element, int property_bit_nr)
1676 struct PropertyBitInfo
1682 static struct PropertyBitInfo pb_can_move_into_acid[] =
1684 /* the player may be able fall into acid when gravity is activated */
1689 { EL_SP_MURPHY, 0 },
1690 { EL_SOKOBAN_FIELD_PLAYER, 0 },
1692 /* all elements that can move may be able to also move into acid */
1695 { EL_BUG_RIGHT, 1 },
1698 { EL_SPACESHIP, 2 },
1699 { EL_SPACESHIP_LEFT, 2 },
1700 { EL_SPACESHIP_RIGHT, 2 },
1701 { EL_SPACESHIP_UP, 2 },
1702 { EL_SPACESHIP_DOWN, 2 },
1703 { EL_BD_BUTTERFLY, 3 },
1704 { EL_BD_BUTTERFLY_LEFT, 3 },
1705 { EL_BD_BUTTERFLY_RIGHT, 3 },
1706 { EL_BD_BUTTERFLY_UP, 3 },
1707 { EL_BD_BUTTERFLY_DOWN, 3 },
1708 { EL_BD_FIREFLY, 4 },
1709 { EL_BD_FIREFLY_LEFT, 4 },
1710 { EL_BD_FIREFLY_RIGHT, 4 },
1711 { EL_BD_FIREFLY_UP, 4 },
1712 { EL_BD_FIREFLY_DOWN, 4 },
1714 { EL_YAMYAM_LEFT, 5 },
1715 { EL_YAMYAM_RIGHT, 5 },
1716 { EL_YAMYAM_UP, 5 },
1717 { EL_YAMYAM_DOWN, 5 },
1718 { EL_DARK_YAMYAM, 6 },
1721 { EL_PACMAN_LEFT, 8 },
1722 { EL_PACMAN_RIGHT, 8 },
1723 { EL_PACMAN_UP, 8 },
1724 { EL_PACMAN_DOWN, 8 },
1726 { EL_MOLE_LEFT, 9 },
1727 { EL_MOLE_RIGHT, 9 },
1729 { EL_MOLE_DOWN, 9 },
1733 { EL_SATELLITE, 13 },
1734 { EL_SP_SNIKSNAK, 14 },
1735 { EL_SP_ELECTRON, 15 },
1738 { EL_EMC_ANDROID, 18 },
1743 static struct PropertyBitInfo pb_dont_collide_with[] =
1745 { EL_SP_SNIKSNAK, 0 },
1746 { EL_SP_ELECTRON, 1 },
1754 struct PropertyBitInfo *pb_info;
1757 { EP_CAN_MOVE_INTO_ACID, pb_can_move_into_acid },
1758 { EP_DONT_COLLIDE_WITH, pb_dont_collide_with },
1763 struct PropertyBitInfo *pb_info = NULL;
1766 for (i = 0; pb_definition[i].bit_nr != -1; i++)
1767 if (pb_definition[i].bit_nr == property_bit_nr)
1768 pb_info = pb_definition[i].pb_info;
1770 if (pb_info == NULL)
1773 for (i = 0; pb_info[i].element != -1; i++)
1774 if (pb_info[i].element == element)
1775 return pb_info[i].bit_nr;
1780 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
1781 boolean property_value)
1783 int bit_nr = get_special_property_bit(element, property_bit_nr);
1788 *bitfield |= (1 << bit_nr);
1790 *bitfield &= ~(1 << bit_nr);
1794 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
1796 int bit_nr = get_special_property_bit(element, property_bit_nr);
1799 return ((*bitfield & (1 << bit_nr)) != 0);
1805 static void resolve_group_element(int group_element, int recursion_depth)
1807 static int group_nr;
1808 static struct ElementGroupInfo *group;
1809 struct ElementGroupInfo *actual_group = element_info[group_element].group;
1812 if (actual_group == NULL) /* not yet initialized */
1815 if (recursion_depth > NUM_GROUP_ELEMENTS) /* recursion too deep */
1817 Error(ERR_WARN, "recursion too deep when resolving group element %d",
1818 group_element - EL_GROUP_START + 1);
1820 /* replace element which caused too deep recursion by question mark */
1821 group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
1826 if (recursion_depth == 0) /* initialization */
1828 group = actual_group;
1829 group_nr = group_element - EL_GROUP_START;
1831 group->num_elements_resolved = 0;
1832 group->choice_pos = 0;
1835 for (i = 0; i < actual_group->num_elements; i++)
1837 int element = actual_group->element[i];
1839 if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
1842 if (IS_GROUP_ELEMENT(element))
1843 resolve_group_element(element, recursion_depth + 1);
1846 group->element_resolved[group->num_elements_resolved++] = element;
1847 element_info[element].in_group[group_nr] = TRUE;
1853 void InitElementPropertiesStatic()
1855 static int ep_diggable[] =
1860 EL_SP_BUGGY_BASE_ACTIVATING,
1863 EL_INVISIBLE_SAND_ACTIVE,
1866 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1867 /* (if amoeba can grow into anything diggable, maybe keep these out) */
1871 EL_SP_BUGGY_BASE_ACTIVE,
1878 static int ep_collectible_only[] =
1900 EL_DYNABOMB_INCREASE_NUMBER,
1901 EL_DYNABOMB_INCREASE_SIZE,
1902 EL_DYNABOMB_INCREASE_POWER,
1922 static int ep_dont_run_into[] =
1924 /* same elements as in 'ep_dont_touch' */
1930 /* same elements as in 'ep_dont_collide_with' */
1942 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1946 EL_SP_BUGGY_BASE_ACTIVE,
1953 static int ep_dont_collide_with[] =
1955 /* same elements as in 'ep_dont_touch' */
1972 static int ep_dont_touch[] =
1982 static int ep_indestructible[] =
1986 EL_ACID_POOL_TOPLEFT,
1987 EL_ACID_POOL_TOPRIGHT,
1988 EL_ACID_POOL_BOTTOMLEFT,
1989 EL_ACID_POOL_BOTTOM,
1990 EL_ACID_POOL_BOTTOMRIGHT,
1991 EL_SP_HARDWARE_GRAY,
1992 EL_SP_HARDWARE_GREEN,
1993 EL_SP_HARDWARE_BLUE,
1995 EL_SP_HARDWARE_YELLOW,
1996 EL_SP_HARDWARE_BASE_1,
1997 EL_SP_HARDWARE_BASE_2,
1998 EL_SP_HARDWARE_BASE_3,
1999 EL_SP_HARDWARE_BASE_4,
2000 EL_SP_HARDWARE_BASE_5,
2001 EL_SP_HARDWARE_BASE_6,
2002 EL_INVISIBLE_STEELWALL,
2003 EL_INVISIBLE_STEELWALL_ACTIVE,
2004 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2005 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2006 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2007 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2008 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2009 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2010 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2011 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2012 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2013 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2014 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2015 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2017 EL_LIGHT_SWITCH_ACTIVE,
2018 EL_SIGN_EXCLAMATION,
2019 EL_SIGN_RADIOACTIVITY,
2030 EL_STEELWALL_SLIPPERY,
2044 EL_GATE_1_GRAY_ACTIVE,
2045 EL_GATE_2_GRAY_ACTIVE,
2046 EL_GATE_3_GRAY_ACTIVE,
2047 EL_GATE_4_GRAY_ACTIVE,
2056 EL_EM_GATE_1_GRAY_ACTIVE,
2057 EL_EM_GATE_2_GRAY_ACTIVE,
2058 EL_EM_GATE_3_GRAY_ACTIVE,
2059 EL_EM_GATE_4_GRAY_ACTIVE,
2068 EL_EMC_GATE_5_GRAY_ACTIVE,
2069 EL_EMC_GATE_6_GRAY_ACTIVE,
2070 EL_EMC_GATE_7_GRAY_ACTIVE,
2071 EL_EMC_GATE_8_GRAY_ACTIVE,
2073 EL_SWITCHGATE_OPENING,
2074 EL_SWITCHGATE_CLOSED,
2075 EL_SWITCHGATE_CLOSING,
2077 EL_SWITCHGATE_SWITCH_UP,
2078 EL_SWITCHGATE_SWITCH_DOWN,
2081 EL_TIMEGATE_OPENING,
2083 EL_TIMEGATE_CLOSING,
2086 EL_TIMEGATE_SWITCH_ACTIVE,
2091 EL_TUBE_VERTICAL_LEFT,
2092 EL_TUBE_VERTICAL_RIGHT,
2093 EL_TUBE_HORIZONTAL_UP,
2094 EL_TUBE_HORIZONTAL_DOWN,
2103 static int ep_slippery[] =
2117 EL_ROBOT_WHEEL_ACTIVE,
2123 EL_ACID_POOL_TOPLEFT,
2124 EL_ACID_POOL_TOPRIGHT,
2134 EL_STEELWALL_SLIPPERY,
2137 EL_EMC_WALL_SLIPPERY_1,
2138 EL_EMC_WALL_SLIPPERY_2,
2139 EL_EMC_WALL_SLIPPERY_3,
2140 EL_EMC_WALL_SLIPPERY_4,
2142 EL_EMC_MAGIC_BALL_ACTIVE,
2147 static int ep_can_change[] =
2152 static int ep_can_move[] =
2154 /* same elements as in 'pb_can_move_into_acid' */
2177 static int ep_can_fall[] =
2192 EL_BD_MAGIC_WALL_FULL,
2206 static int ep_can_smash_player[] =
2232 static int ep_can_smash_enemies[] =
2241 static int ep_can_smash_everything[] =
2250 static int ep_explodes_by_fire[] =
2252 /* same elements as in 'ep_explodes_impact' */
2257 /* same elements as in 'ep_explodes_smashed' */
2267 EL_EM_DYNAMITE_ACTIVE,
2268 EL_DYNABOMB_PLAYER_1_ACTIVE,
2269 EL_DYNABOMB_PLAYER_2_ACTIVE,
2270 EL_DYNABOMB_PLAYER_3_ACTIVE,
2271 EL_DYNABOMB_PLAYER_4_ACTIVE,
2272 EL_DYNABOMB_INCREASE_NUMBER,
2273 EL_DYNABOMB_INCREASE_SIZE,
2274 EL_DYNABOMB_INCREASE_POWER,
2275 EL_SP_DISK_RED_ACTIVE,
2289 static int ep_explodes_smashed[] =
2291 /* same elements as in 'ep_explodes_impact' */
2305 static int ep_explodes_impact[] =
2314 static int ep_walkable_over[] =
2318 EL_SOKOBAN_FIELD_EMPTY,
2330 EL_GATE_1_GRAY_ACTIVE,
2331 EL_GATE_2_GRAY_ACTIVE,
2332 EL_GATE_3_GRAY_ACTIVE,
2333 EL_GATE_4_GRAY_ACTIVE,
2341 static int ep_walkable_inside[] =
2346 EL_TUBE_VERTICAL_LEFT,
2347 EL_TUBE_VERTICAL_RIGHT,
2348 EL_TUBE_HORIZONTAL_UP,
2349 EL_TUBE_HORIZONTAL_DOWN,
2358 static int ep_walkable_under[] =
2363 static int ep_passable_over[] =
2373 EL_EM_GATE_1_GRAY_ACTIVE,
2374 EL_EM_GATE_2_GRAY_ACTIVE,
2375 EL_EM_GATE_3_GRAY_ACTIVE,
2376 EL_EM_GATE_4_GRAY_ACTIVE,
2385 EL_EMC_GATE_5_GRAY_ACTIVE,
2386 EL_EMC_GATE_6_GRAY_ACTIVE,
2387 EL_EMC_GATE_7_GRAY_ACTIVE,
2388 EL_EMC_GATE_8_GRAY_ACTIVE,
2395 static int ep_passable_inside[] =
2401 EL_SP_PORT_HORIZONTAL,
2402 EL_SP_PORT_VERTICAL,
2404 EL_SP_GRAVITY_PORT_LEFT,
2405 EL_SP_GRAVITY_PORT_RIGHT,
2406 EL_SP_GRAVITY_PORT_UP,
2407 EL_SP_GRAVITY_PORT_DOWN,
2408 EL_SP_GRAVITY_ON_PORT_LEFT,
2409 EL_SP_GRAVITY_ON_PORT_RIGHT,
2410 EL_SP_GRAVITY_ON_PORT_UP,
2411 EL_SP_GRAVITY_ON_PORT_DOWN,
2412 EL_SP_GRAVITY_OFF_PORT_LEFT,
2413 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2414 EL_SP_GRAVITY_OFF_PORT_UP,
2415 EL_SP_GRAVITY_OFF_PORT_DOWN,
2420 static int ep_passable_under[] =
2425 static int ep_droppable[] =
2430 static int ep_explodes_1x1_old[] =
2435 static int ep_pushable[] =
2447 EL_SOKOBAN_FIELD_FULL,
2456 static int ep_explodes_cross_old[] =
2461 static int ep_protected[] =
2463 /* same elements as in 'ep_walkable_inside' */
2467 EL_TUBE_VERTICAL_LEFT,
2468 EL_TUBE_VERTICAL_RIGHT,
2469 EL_TUBE_HORIZONTAL_UP,
2470 EL_TUBE_HORIZONTAL_DOWN,
2476 /* same elements as in 'ep_passable_over' */
2485 EL_EM_GATE_1_GRAY_ACTIVE,
2486 EL_EM_GATE_2_GRAY_ACTIVE,
2487 EL_EM_GATE_3_GRAY_ACTIVE,
2488 EL_EM_GATE_4_GRAY_ACTIVE,
2497 EL_EMC_GATE_5_GRAY_ACTIVE,
2498 EL_EMC_GATE_6_GRAY_ACTIVE,
2499 EL_EMC_GATE_7_GRAY_ACTIVE,
2500 EL_EMC_GATE_8_GRAY_ACTIVE,
2504 /* same elements as in 'ep_passable_inside' */
2509 EL_SP_PORT_HORIZONTAL,
2510 EL_SP_PORT_VERTICAL,
2512 EL_SP_GRAVITY_PORT_LEFT,
2513 EL_SP_GRAVITY_PORT_RIGHT,
2514 EL_SP_GRAVITY_PORT_UP,
2515 EL_SP_GRAVITY_PORT_DOWN,
2516 EL_SP_GRAVITY_ON_PORT_LEFT,
2517 EL_SP_GRAVITY_ON_PORT_RIGHT,
2518 EL_SP_GRAVITY_ON_PORT_UP,
2519 EL_SP_GRAVITY_ON_PORT_DOWN,
2520 EL_SP_GRAVITY_OFF_PORT_LEFT,
2521 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2522 EL_SP_GRAVITY_OFF_PORT_UP,
2523 EL_SP_GRAVITY_OFF_PORT_DOWN,
2528 static int ep_throwable[] =
2533 static int ep_can_explode[] =
2535 /* same elements as in 'ep_explodes_impact' */
2540 /* same elements as in 'ep_explodes_smashed' */
2546 /* elements that can explode by explosion or by dragonfire */
2550 EL_EM_DYNAMITE_ACTIVE,
2551 EL_DYNABOMB_PLAYER_1_ACTIVE,
2552 EL_DYNABOMB_PLAYER_2_ACTIVE,
2553 EL_DYNABOMB_PLAYER_3_ACTIVE,
2554 EL_DYNABOMB_PLAYER_4_ACTIVE,
2555 EL_DYNABOMB_INCREASE_NUMBER,
2556 EL_DYNABOMB_INCREASE_SIZE,
2557 EL_DYNABOMB_INCREASE_POWER,
2558 EL_SP_DISK_RED_ACTIVE,
2566 /* elements that can explode only by explosion */
2572 static int ep_gravity_reachable[] =
2578 EL_INVISIBLE_SAND_ACTIVE,
2583 EL_SP_PORT_HORIZONTAL,
2584 EL_SP_PORT_VERTICAL,
2586 EL_SP_GRAVITY_PORT_LEFT,
2587 EL_SP_GRAVITY_PORT_RIGHT,
2588 EL_SP_GRAVITY_PORT_UP,
2589 EL_SP_GRAVITY_PORT_DOWN,
2590 EL_SP_GRAVITY_ON_PORT_LEFT,
2591 EL_SP_GRAVITY_ON_PORT_RIGHT,
2592 EL_SP_GRAVITY_ON_PORT_UP,
2593 EL_SP_GRAVITY_ON_PORT_DOWN,
2594 EL_SP_GRAVITY_OFF_PORT_LEFT,
2595 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2596 EL_SP_GRAVITY_OFF_PORT_UP,
2597 EL_SP_GRAVITY_OFF_PORT_DOWN,
2603 static int ep_player[] =
2610 EL_SOKOBAN_FIELD_PLAYER,
2616 static int ep_can_pass_magic_wall[] =
2630 static int ep_switchable[] =
2634 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2635 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2636 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2637 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2638 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2639 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2640 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2641 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2642 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2643 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2644 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2645 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2646 EL_SWITCHGATE_SWITCH_UP,
2647 EL_SWITCHGATE_SWITCH_DOWN,
2649 EL_LIGHT_SWITCH_ACTIVE,
2651 EL_BALLOON_SWITCH_LEFT,
2652 EL_BALLOON_SWITCH_RIGHT,
2653 EL_BALLOON_SWITCH_UP,
2654 EL_BALLOON_SWITCH_DOWN,
2655 EL_BALLOON_SWITCH_ANY,
2656 EL_BALLOON_SWITCH_NONE,
2659 EL_EMC_MAGIC_BALL_SWITCH,
2660 EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
2665 static int ep_bd_element[] =
2699 static int ep_sp_element[] =
2701 /* should always be valid */
2704 /* standard classic Supaplex elements */
2711 EL_SP_HARDWARE_GRAY,
2719 EL_SP_GRAVITY_PORT_RIGHT,
2720 EL_SP_GRAVITY_PORT_DOWN,
2721 EL_SP_GRAVITY_PORT_LEFT,
2722 EL_SP_GRAVITY_PORT_UP,
2727 EL_SP_PORT_VERTICAL,
2728 EL_SP_PORT_HORIZONTAL,
2734 EL_SP_HARDWARE_BASE_1,
2735 EL_SP_HARDWARE_GREEN,
2736 EL_SP_HARDWARE_BLUE,
2738 EL_SP_HARDWARE_YELLOW,
2739 EL_SP_HARDWARE_BASE_2,
2740 EL_SP_HARDWARE_BASE_3,
2741 EL_SP_HARDWARE_BASE_4,
2742 EL_SP_HARDWARE_BASE_5,
2743 EL_SP_HARDWARE_BASE_6,
2747 /* additional elements that appeared in newer Supaplex levels */
2750 /* additional gravity port elements (not switching, but setting gravity) */
2751 EL_SP_GRAVITY_ON_PORT_LEFT,
2752 EL_SP_GRAVITY_ON_PORT_RIGHT,
2753 EL_SP_GRAVITY_ON_PORT_UP,
2754 EL_SP_GRAVITY_ON_PORT_DOWN,
2755 EL_SP_GRAVITY_OFF_PORT_LEFT,
2756 EL_SP_GRAVITY_OFF_PORT_RIGHT,
2757 EL_SP_GRAVITY_OFF_PORT_UP,
2758 EL_SP_GRAVITY_OFF_PORT_DOWN,
2760 /* more than one Murphy in a level results in an inactive clone */
2763 /* runtime Supaplex elements */
2764 EL_SP_DISK_RED_ACTIVE,
2765 EL_SP_TERMINAL_ACTIVE,
2766 EL_SP_BUGGY_BASE_ACTIVATING,
2767 EL_SP_BUGGY_BASE_ACTIVE,
2774 static int ep_sb_element[] =
2779 EL_SOKOBAN_FIELD_EMPTY,
2780 EL_SOKOBAN_FIELD_FULL,
2781 EL_SOKOBAN_FIELD_PLAYER,
2786 EL_INVISIBLE_STEELWALL,
2791 static int ep_gem[] =
2803 static int ep_food_dark_yamyam[] =
2831 static int ep_food_penguin[] =
2845 static int ep_food_pig[] =
2857 static int ep_historic_wall[] =
2868 EL_GATE_1_GRAY_ACTIVE,
2869 EL_GATE_2_GRAY_ACTIVE,
2870 EL_GATE_3_GRAY_ACTIVE,
2871 EL_GATE_4_GRAY_ACTIVE,
2880 EL_EM_GATE_1_GRAY_ACTIVE,
2881 EL_EM_GATE_2_GRAY_ACTIVE,
2882 EL_EM_GATE_3_GRAY_ACTIVE,
2883 EL_EM_GATE_4_GRAY_ACTIVE,
2890 EL_EXPANDABLE_WALL_HORIZONTAL,
2891 EL_EXPANDABLE_WALL_VERTICAL,
2892 EL_EXPANDABLE_WALL_ANY,
2893 EL_EXPANDABLE_WALL_GROWING,
2900 EL_SP_HARDWARE_GRAY,
2901 EL_SP_HARDWARE_GREEN,
2902 EL_SP_HARDWARE_BLUE,
2904 EL_SP_HARDWARE_YELLOW,
2905 EL_SP_HARDWARE_BASE_1,
2906 EL_SP_HARDWARE_BASE_2,
2907 EL_SP_HARDWARE_BASE_3,
2908 EL_SP_HARDWARE_BASE_4,
2909 EL_SP_HARDWARE_BASE_5,
2910 EL_SP_HARDWARE_BASE_6,
2912 EL_SP_TERMINAL_ACTIVE,
2915 EL_INVISIBLE_STEELWALL,
2916 EL_INVISIBLE_STEELWALL_ACTIVE,
2918 EL_INVISIBLE_WALL_ACTIVE,
2919 EL_STEELWALL_SLIPPERY,
2936 static int ep_historic_solid[] =
2940 EL_EXPANDABLE_WALL_HORIZONTAL,
2941 EL_EXPANDABLE_WALL_VERTICAL,
2942 EL_EXPANDABLE_WALL_ANY,
2955 EL_QUICKSAND_FILLING,
2956 EL_QUICKSAND_EMPTYING,
2958 EL_MAGIC_WALL_ACTIVE,
2959 EL_MAGIC_WALL_EMPTYING,
2960 EL_MAGIC_WALL_FILLING,
2964 EL_BD_MAGIC_WALL_ACTIVE,
2965 EL_BD_MAGIC_WALL_EMPTYING,
2966 EL_BD_MAGIC_WALL_FULL,
2967 EL_BD_MAGIC_WALL_FILLING,
2968 EL_BD_MAGIC_WALL_DEAD,
2977 EL_SP_TERMINAL_ACTIVE,
2981 EL_INVISIBLE_WALL_ACTIVE,
2982 EL_SWITCHGATE_SWITCH_UP,
2983 EL_SWITCHGATE_SWITCH_DOWN,
2985 EL_TIMEGATE_SWITCH_ACTIVE,
2997 /* the following elements are a direct copy of "indestructible" elements,
2998 except "EL_ACID", which is "indestructible", but not "solid"! */
3003 EL_ACID_POOL_TOPLEFT,
3004 EL_ACID_POOL_TOPRIGHT,
3005 EL_ACID_POOL_BOTTOMLEFT,
3006 EL_ACID_POOL_BOTTOM,
3007 EL_ACID_POOL_BOTTOMRIGHT,
3008 EL_SP_HARDWARE_GRAY,
3009 EL_SP_HARDWARE_GREEN,
3010 EL_SP_HARDWARE_BLUE,
3012 EL_SP_HARDWARE_YELLOW,
3013 EL_SP_HARDWARE_BASE_1,
3014 EL_SP_HARDWARE_BASE_2,
3015 EL_SP_HARDWARE_BASE_3,
3016 EL_SP_HARDWARE_BASE_4,
3017 EL_SP_HARDWARE_BASE_5,
3018 EL_SP_HARDWARE_BASE_6,
3019 EL_INVISIBLE_STEELWALL,
3020 EL_INVISIBLE_STEELWALL_ACTIVE,
3021 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3022 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3023 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3024 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3025 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3026 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3027 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3028 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3029 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3030 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3031 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3032 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3034 EL_LIGHT_SWITCH_ACTIVE,
3035 EL_SIGN_EXCLAMATION,
3036 EL_SIGN_RADIOACTIVITY,
3047 EL_STEELWALL_SLIPPERY,
3061 EL_GATE_1_GRAY_ACTIVE,
3062 EL_GATE_2_GRAY_ACTIVE,
3063 EL_GATE_3_GRAY_ACTIVE,
3064 EL_GATE_4_GRAY_ACTIVE,
3073 EL_EM_GATE_1_GRAY_ACTIVE,
3074 EL_EM_GATE_2_GRAY_ACTIVE,
3075 EL_EM_GATE_3_GRAY_ACTIVE,
3076 EL_EM_GATE_4_GRAY_ACTIVE,
3078 EL_SWITCHGATE_OPENING,
3079 EL_SWITCHGATE_CLOSED,
3080 EL_SWITCHGATE_CLOSING,
3082 EL_TIMEGATE_OPENING,
3084 EL_TIMEGATE_CLOSING,
3088 EL_TUBE_VERTICAL_LEFT,
3089 EL_TUBE_VERTICAL_RIGHT,
3090 EL_TUBE_HORIZONTAL_UP,
3091 EL_TUBE_HORIZONTAL_DOWN,
3100 static int ep_classic_enemy[] =
3117 static int ep_belt[] =
3119 EL_CONVEYOR_BELT_1_LEFT,
3120 EL_CONVEYOR_BELT_1_MIDDLE,
3121 EL_CONVEYOR_BELT_1_RIGHT,
3122 EL_CONVEYOR_BELT_2_LEFT,
3123 EL_CONVEYOR_BELT_2_MIDDLE,
3124 EL_CONVEYOR_BELT_2_RIGHT,
3125 EL_CONVEYOR_BELT_3_LEFT,
3126 EL_CONVEYOR_BELT_3_MIDDLE,
3127 EL_CONVEYOR_BELT_3_RIGHT,
3128 EL_CONVEYOR_BELT_4_LEFT,
3129 EL_CONVEYOR_BELT_4_MIDDLE,
3130 EL_CONVEYOR_BELT_4_RIGHT,
3135 static int ep_belt_active[] =
3137 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3138 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3139 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3140 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3141 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3142 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3143 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3144 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3145 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3146 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3147 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3148 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3153 static int ep_belt_switch[] =
3155 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3156 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3157 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3158 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3159 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3160 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3161 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3162 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3163 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3164 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3165 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3166 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3171 static int ep_tube[] =
3178 EL_TUBE_HORIZONTAL_UP,
3179 EL_TUBE_HORIZONTAL_DOWN,
3181 EL_TUBE_VERTICAL_LEFT,
3182 EL_TUBE_VERTICAL_RIGHT,
3188 static int ep_keygate[] =
3198 EL_GATE_1_GRAY_ACTIVE,
3199 EL_GATE_2_GRAY_ACTIVE,
3200 EL_GATE_3_GRAY_ACTIVE,
3201 EL_GATE_4_GRAY_ACTIVE,
3210 EL_EM_GATE_1_GRAY_ACTIVE,
3211 EL_EM_GATE_2_GRAY_ACTIVE,
3212 EL_EM_GATE_3_GRAY_ACTIVE,
3213 EL_EM_GATE_4_GRAY_ACTIVE,
3222 EL_EMC_GATE_5_GRAY_ACTIVE,
3223 EL_EMC_GATE_6_GRAY_ACTIVE,
3224 EL_EMC_GATE_7_GRAY_ACTIVE,
3225 EL_EMC_GATE_8_GRAY_ACTIVE,
3230 static int ep_amoeboid[] =
3242 static int ep_amoebalive[] =
3253 static int ep_has_editor_content[] =
3275 static int ep_can_turn_each_move[] =
3277 /* !!! do something with this one !!! */
3281 static int ep_can_grow[] =
3295 static int ep_active_bomb[] =
3298 EL_EM_DYNAMITE_ACTIVE,
3299 EL_DYNABOMB_PLAYER_1_ACTIVE,
3300 EL_DYNABOMB_PLAYER_2_ACTIVE,
3301 EL_DYNABOMB_PLAYER_3_ACTIVE,
3302 EL_DYNABOMB_PLAYER_4_ACTIVE,
3303 EL_SP_DISK_RED_ACTIVE,
3308 static int ep_inactive[] =
3340 EL_GATE_1_GRAY_ACTIVE,
3341 EL_GATE_2_GRAY_ACTIVE,
3342 EL_GATE_3_GRAY_ACTIVE,
3343 EL_GATE_4_GRAY_ACTIVE,
3352 EL_EM_GATE_1_GRAY_ACTIVE,
3353 EL_EM_GATE_2_GRAY_ACTIVE,
3354 EL_EM_GATE_3_GRAY_ACTIVE,
3355 EL_EM_GATE_4_GRAY_ACTIVE,
3364 EL_EMC_GATE_5_GRAY_ACTIVE,
3365 EL_EMC_GATE_6_GRAY_ACTIVE,
3366 EL_EMC_GATE_7_GRAY_ACTIVE,
3367 EL_EMC_GATE_8_GRAY_ACTIVE,
3370 EL_INVISIBLE_STEELWALL,
3378 EL_WALL_EMERALD_YELLOW,
3379 EL_DYNABOMB_INCREASE_NUMBER,
3380 EL_DYNABOMB_INCREASE_SIZE,
3381 EL_DYNABOMB_INCREASE_POWER,
3385 EL_SOKOBAN_FIELD_EMPTY,
3386 EL_SOKOBAN_FIELD_FULL,
3387 EL_WALL_EMERALD_RED,
3388 EL_WALL_EMERALD_PURPLE,
3389 EL_ACID_POOL_TOPLEFT,
3390 EL_ACID_POOL_TOPRIGHT,
3391 EL_ACID_POOL_BOTTOMLEFT,
3392 EL_ACID_POOL_BOTTOM,
3393 EL_ACID_POOL_BOTTOMRIGHT,
3397 EL_BD_MAGIC_WALL_DEAD,
3398 EL_AMOEBA_TO_DIAMOND,
3406 EL_SP_GRAVITY_PORT_RIGHT,
3407 EL_SP_GRAVITY_PORT_DOWN,
3408 EL_SP_GRAVITY_PORT_LEFT,
3409 EL_SP_GRAVITY_PORT_UP,
3410 EL_SP_PORT_HORIZONTAL,
3411 EL_SP_PORT_VERTICAL,
3422 EL_SP_HARDWARE_GRAY,
3423 EL_SP_HARDWARE_GREEN,
3424 EL_SP_HARDWARE_BLUE,
3426 EL_SP_HARDWARE_YELLOW,
3427 EL_SP_HARDWARE_BASE_1,
3428 EL_SP_HARDWARE_BASE_2,
3429 EL_SP_HARDWARE_BASE_3,
3430 EL_SP_HARDWARE_BASE_4,
3431 EL_SP_HARDWARE_BASE_5,
3432 EL_SP_HARDWARE_BASE_6,
3433 EL_SP_GRAVITY_ON_PORT_LEFT,
3434 EL_SP_GRAVITY_ON_PORT_RIGHT,
3435 EL_SP_GRAVITY_ON_PORT_UP,
3436 EL_SP_GRAVITY_ON_PORT_DOWN,
3437 EL_SP_GRAVITY_OFF_PORT_LEFT,
3438 EL_SP_GRAVITY_OFF_PORT_RIGHT,
3439 EL_SP_GRAVITY_OFF_PORT_UP,
3440 EL_SP_GRAVITY_OFF_PORT_DOWN,
3441 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3442 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3443 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3444 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3445 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3446 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3447 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3448 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3449 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3450 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3451 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3452 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3453 EL_SIGN_EXCLAMATION,
3454 EL_SIGN_RADIOACTIVITY,
3465 EL_STEELWALL_SLIPPERY,
3470 EL_EMC_WALL_SLIPPERY_1,
3471 EL_EMC_WALL_SLIPPERY_2,
3472 EL_EMC_WALL_SLIPPERY_3,
3473 EL_EMC_WALL_SLIPPERY_4,
3494 static int ep_em_slippery_wall[] =
3499 static int ep_gfx_crumbled[] =
3509 static int ep_editor_cascade_active[] =
3511 EL_INTERNAL_CASCADE_BD_ACTIVE,
3512 EL_INTERNAL_CASCADE_EM_ACTIVE,
3513 EL_INTERNAL_CASCADE_EMC_ACTIVE,
3514 EL_INTERNAL_CASCADE_RND_ACTIVE,
3515 EL_INTERNAL_CASCADE_SB_ACTIVE,
3516 EL_INTERNAL_CASCADE_SP_ACTIVE,
3517 EL_INTERNAL_CASCADE_DC_ACTIVE,
3518 EL_INTERNAL_CASCADE_DX_ACTIVE,
3519 EL_INTERNAL_CASCADE_CHARS_ACTIVE,
3520 EL_INTERNAL_CASCADE_CE_ACTIVE,
3521 EL_INTERNAL_CASCADE_GE_ACTIVE,
3522 EL_INTERNAL_CASCADE_USER_ACTIVE,
3523 EL_INTERNAL_CASCADE_GENERIC_ACTIVE,
3524 EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
3529 static int ep_editor_cascade_inactive[] =
3531 EL_INTERNAL_CASCADE_BD,
3532 EL_INTERNAL_CASCADE_EM,
3533 EL_INTERNAL_CASCADE_EMC,
3534 EL_INTERNAL_CASCADE_RND,
3535 EL_INTERNAL_CASCADE_SB,
3536 EL_INTERNAL_CASCADE_SP,
3537 EL_INTERNAL_CASCADE_DC,
3538 EL_INTERNAL_CASCADE_DX,
3539 EL_INTERNAL_CASCADE_CHARS,
3540 EL_INTERNAL_CASCADE_CE,
3541 EL_INTERNAL_CASCADE_GE,
3542 EL_INTERNAL_CASCADE_USER,
3543 EL_INTERNAL_CASCADE_GENERIC,
3544 EL_INTERNAL_CASCADE_DYNAMIC,
3553 } element_properties[] =
3555 { ep_diggable, EP_DIGGABLE },
3556 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
3557 { ep_dont_run_into, EP_DONT_RUN_INTO },
3558 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
3559 { ep_dont_touch, EP_DONT_TOUCH },
3560 { ep_indestructible, EP_INDESTRUCTIBLE },
3561 { ep_slippery, EP_SLIPPERY },
3562 { ep_can_change, EP_CAN_CHANGE },
3563 { ep_can_move, EP_CAN_MOVE },
3564 { ep_can_fall, EP_CAN_FALL },
3565 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
3566 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
3567 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
3568 { ep_explodes_by_fire, EP_EXPLODES_BY_FIRE },
3569 { ep_explodes_smashed, EP_EXPLODES_SMASHED },
3570 { ep_explodes_impact, EP_EXPLODES_IMPACT },
3571 { ep_walkable_over, EP_WALKABLE_OVER },
3572 { ep_walkable_inside, EP_WALKABLE_INSIDE },
3573 { ep_walkable_under, EP_WALKABLE_UNDER },
3574 { ep_passable_over, EP_PASSABLE_OVER },
3575 { ep_passable_inside, EP_PASSABLE_INSIDE },
3576 { ep_passable_under, EP_PASSABLE_UNDER },
3577 { ep_droppable, EP_DROPPABLE },
3578 { ep_explodes_1x1_old, EP_EXPLODES_1X1_OLD },
3579 { ep_pushable, EP_PUSHABLE },
3580 { ep_explodes_cross_old, EP_EXPLODES_CROSS_OLD },
3581 { ep_protected, EP_PROTECTED },
3582 { ep_throwable, EP_THROWABLE },
3583 { ep_can_explode, EP_CAN_EXPLODE },
3584 { ep_gravity_reachable, EP_GRAVITY_REACHABLE },
3586 { ep_player, EP_PLAYER },
3587 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
3588 { ep_switchable, EP_SWITCHABLE },
3589 { ep_bd_element, EP_BD_ELEMENT },
3590 { ep_sp_element, EP_SP_ELEMENT },
3591 { ep_sb_element, EP_SB_ELEMENT },
3593 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
3594 { ep_food_penguin, EP_FOOD_PENGUIN },
3595 { ep_food_pig, EP_FOOD_PIG },
3596 { ep_historic_wall, EP_HISTORIC_WALL },
3597 { ep_historic_solid, EP_HISTORIC_SOLID },
3598 { ep_classic_enemy, EP_CLASSIC_ENEMY },
3599 { ep_belt, EP_BELT },
3600 { ep_belt_active, EP_BELT_ACTIVE },
3601 { ep_belt_switch, EP_BELT_SWITCH },
3602 { ep_tube, EP_TUBE },
3603 { ep_keygate, EP_KEYGATE },
3604 { ep_amoeboid, EP_AMOEBOID },
3605 { ep_amoebalive, EP_AMOEBALIVE },
3606 { ep_has_editor_content, EP_HAS_EDITOR_CONTENT },
3607 { ep_can_turn_each_move, EP_CAN_TURN_EACH_MOVE },
3608 { ep_can_grow, EP_CAN_GROW },
3609 { ep_active_bomb, EP_ACTIVE_BOMB },
3610 { ep_inactive, EP_INACTIVE },
3612 { ep_em_slippery_wall, EP_EM_SLIPPERY_WALL },
3614 { ep_gfx_crumbled, EP_GFX_CRUMBLED },
3616 { ep_editor_cascade_active, EP_EDITOR_CASCADE_ACTIVE },
3617 { ep_editor_cascade_inactive, EP_EDITOR_CASCADE_INACTIVE },
3624 /* always start with reliable default values (element has no properties) */
3625 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3626 for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3627 SET_PROPERTY(i, j, FALSE);
3629 /* set all base element properties from above array definitions */
3630 for (i = 0; element_properties[i].elements != NULL; i++)
3631 for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3632 SET_PROPERTY((element_properties[i].elements)[j],
3633 element_properties[i].property, TRUE);
3635 /* copy properties to some elements that are only stored in level file */
3636 for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3637 for (j = 0; copy_properties[j][0] != -1; j++)
3638 if (HAS_PROPERTY(copy_properties[j][0], i))
3639 for (k = 1; k <= 4; k++)
3640 SET_PROPERTY(copy_properties[j][k], i, TRUE);
3643 void InitElementPropertiesEngine(int engine_version)
3645 static int no_wall_properties[] =
3648 EP_COLLECTIBLE_ONLY,
3650 EP_DONT_COLLIDE_WITH,
3653 EP_CAN_SMASH_PLAYER,
3654 EP_CAN_SMASH_ENEMIES,
3655 EP_CAN_SMASH_EVERYTHING,
3660 EP_FOOD_DARK_YAMYAM,
3676 /* important: after initialization in InitElementPropertiesStatic(), the
3677 elements are not again initialized to a default value; therefore all
3678 changes have to make sure that they leave the element with a defined
3679 property (which means that conditional property changes must be set to
3680 a reliable default value before) */
3683 /* ---------- recursively resolve group elements ------------------------- */
3685 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3686 for (j = 0; j < NUM_GROUP_ELEMENTS; j++)
3687 element_info[i].in_group[j] = FALSE;
3689 for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
3690 resolve_group_element(EL_GROUP_START + i, 0);
3693 /* set all special, combined or engine dependent element properties */
3694 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3696 /* ---------- INACTIVE ------------------------------------------------- */
3697 SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
3699 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
3700 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
3701 IS_WALKABLE_INSIDE(i) ||
3702 IS_WALKABLE_UNDER(i)));
3704 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
3705 IS_PASSABLE_INSIDE(i) ||
3706 IS_PASSABLE_UNDER(i)));
3708 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
3709 IS_PASSABLE_OVER(i)));
3711 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
3712 IS_PASSABLE_INSIDE(i)));
3714 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
3715 IS_PASSABLE_UNDER(i)));
3717 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
3720 /* ---------- COLLECTIBLE ---------------------------------------------- */
3721 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
3725 /* ---------- SNAPPABLE ------------------------------------------------ */
3726 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
3727 IS_COLLECTIBLE(i) ||
3731 /* ---------- WALL ----------------------------------------------------- */
3732 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
3734 for (j = 0; no_wall_properties[j] != -1; j++)
3735 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
3736 i >= EL_FIRST_RUNTIME_UNREAL)
3737 SET_PROPERTY(i, EP_WALL, FALSE);
3739 if (IS_HISTORIC_WALL(i))
3740 SET_PROPERTY(i, EP_WALL, TRUE);
3742 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
3743 if (engine_version < VERSION_IDENT(2,2,0,0))
3744 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
3746 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
3748 !IS_COLLECTIBLE(i)));
3750 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
3752 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
3753 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
3755 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
3756 IS_INDESTRUCTIBLE(i)));
3758 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
3760 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
3761 else if (engine_version < VERSION_IDENT(2,2,0,0))
3762 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
3764 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3768 if (IS_CUSTOM_ELEMENT(i))
3770 /* these are additional properties which are initially false when set */
3772 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
3774 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
3775 if (DONT_COLLIDE_WITH(i))
3776 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
3778 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
3779 if (CAN_SMASH_EVERYTHING(i))
3780 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
3781 if (CAN_SMASH_ENEMIES(i))
3782 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
3785 /* ---------- CAN_SMASH ------------------------------------------------ */
3786 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
3787 CAN_SMASH_ENEMIES(i) ||
3788 CAN_SMASH_EVERYTHING(i)));
3790 /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
3791 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
3792 EXPLODES_BY_FIRE(i)));
3794 /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
3795 SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
3796 EXPLODES_SMASHED(i)));
3798 /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
3799 SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
3800 EXPLODES_IMPACT(i)));
3802 /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
3803 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
3805 /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
3806 SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
3807 i == EL_BLACK_ORB));
3809 /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
3810 SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
3812 IS_CUSTOM_ELEMENT(i)));
3814 /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
3815 SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
3816 i == EL_SP_ELECTRON));
3818 /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
3819 if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
3820 SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
3821 getMoveIntoAcidProperty(&level, i));
3823 /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
3824 if (MAYBE_DONT_COLLIDE_WITH(i))
3825 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
3826 getDontCollideWithProperty(&level, i));
3828 /* ---------- SP_PORT -------------------------------------------------- */
3829 SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
3830 IS_PASSABLE_INSIDE(i)));
3832 /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
3833 for (j = 0; j < level.num_android_clone_elements; j++)
3834 SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
3836 IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
3838 /* ---------- CAN_CHANGE ----------------------------------------------- */
3839 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
3840 for (j = 0; j < element_info[i].num_change_pages; j++)
3841 if (element_info[i].change_page[j].can_change)
3842 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
3844 /* ---------- HAS_ACTION ----------------------------------------------- */
3845 SET_PROPERTY(i, EP_HAS_ACTION, FALSE); /* default: has no action */
3846 for (j = 0; j < element_info[i].num_change_pages; j++)
3847 if (element_info[i].change_page[j].has_action)
3848 SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
3850 /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
3851 SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
3854 /* ---------- GFX_CRUMBLED --------------------------------------------- */
3856 SET_PROPERTY(i, EP_GFX_CRUMBLED,
3857 element_info[i].crumbled[ACTION_DEFAULT] !=
3858 element_info[i].graphic[ACTION_DEFAULT]);
3860 /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
3861 SET_PROPERTY(i, EP_GFX_CRUMBLED,
3862 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
3865 /* ---------- EDITOR_CASCADE ------------------------------------------- */
3866 SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
3867 IS_EDITOR_CASCADE_INACTIVE(i)));
3870 /* dynamically adjust element properties according to game engine version */
3872 static int ep_em_slippery_wall[] =
3877 EL_EXPANDABLE_WALL_HORIZONTAL,
3878 EL_EXPANDABLE_WALL_VERTICAL,
3879 EL_EXPANDABLE_WALL_ANY,
3883 /* special EM style gems behaviour */
3884 for (i = 0; ep_em_slippery_wall[i] != -1; i++)
3885 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
3886 level.em_slippery_gems);
3888 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
3889 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
3890 (level.em_slippery_gems &&
3891 engine_version > VERSION_IDENT(2,0,1,0)));
3894 /* set default push delay values (corrected since version 3.0.7-1) */
3895 if (engine_version < VERSION_IDENT(3,0,7,1))
3897 game.default_push_delay_fixed = 2;
3898 game.default_push_delay_random = 8;
3902 game.default_push_delay_fixed = 8;
3903 game.default_push_delay_random = 8;
3906 /* set uninitialized push delay values of custom elements in older levels */
3907 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3909 int element = EL_CUSTOM_START + i;
3911 if (element_info[element].push_delay_fixed == -1)
3912 element_info[element].push_delay_fixed = game.default_push_delay_fixed;
3913 if (element_info[element].push_delay_random == -1)
3914 element_info[element].push_delay_random = game.default_push_delay_random;
3917 /* set some other uninitialized values of custom elements in older levels */
3918 if (engine_version < VERSION_IDENT(3,1,0,0))
3920 for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3922 int element = EL_CUSTOM_START + i;
3924 element_info[element].access_direction = MV_ALL_DIRECTIONS;
3926 element_info[element].explosion_delay = 17;
3927 element_info[element].ignition_delay = 8;
3932 /* set element properties that were handled incorrectly in older levels */
3933 if (engine_version < VERSION_IDENT(3,1,0,0))
3935 SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
3936 SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
3940 /* this is needed because some graphics depend on element properties */
3941 if (game_status == GAME_MODE_PLAYING)
3942 InitElementGraphicInfo();
3945 static void InitGlobal()
3949 for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
3951 /* check if element_name_info entry defined for each element in "main.h" */
3952 if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
3953 Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
3955 element_info[i].token_name = element_name_info[i].token_name;
3956 element_info[i].class_name = element_name_info[i].class_name;
3957 element_info[i].editor_description=element_name_info[i].editor_description;
3960 global.autoplay_leveldir = NULL;
3961 global.convert_leveldir = NULL;
3963 global.frames_per_second = 0;
3964 global.fps_slowdown = FALSE;
3965 global.fps_slowdown_factor = 1;
3968 void Execute_Command(char *command)
3972 if (strcmp(command, "print graphicsinfo.conf") == 0)
3974 printf("# You can configure additional/alternative image files here.\n");
3975 printf("# (The entries below are default and therefore commented out.)\n");
3977 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
3979 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3982 for (i = 0; image_config[i].token != NULL; i++)
3983 printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
3984 image_config[i].value));
3988 else if (strcmp(command, "print soundsinfo.conf") == 0)
3990 printf("# You can configure additional/alternative sound files here.\n");
3991 printf("# (The entries below are default and therefore commented out.)\n");
3993 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
3995 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3998 for (i = 0; sound_config[i].token != NULL; i++)
3999 printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4000 sound_config[i].value));
4004 else if (strcmp(command, "print musicinfo.conf") == 0)
4006 printf("# You can configure additional/alternative music files here.\n");
4007 printf("# (The entries below are default and therefore commented out.)\n");
4009 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4011 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4014 for (i = 0; music_config[i].token != NULL; i++)
4015 printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4016 music_config[i].value));
4020 else if (strcmp(command, "print editorsetup.conf") == 0)
4022 printf("# You can configure your personal editor element list here.\n");
4023 printf("# (The entries below are default and therefore commented out.)\n");
4026 /* this is needed to be able to check element list for cascade elements */
4027 InitElementPropertiesStatic();
4028 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4030 PrintEditorElementList();
4034 else if (strcmp(command, "print helpanim.conf") == 0)
4036 printf("# You can configure different element help animations here.\n");
4037 printf("# (The entries below are default and therefore commented out.)\n");
4040 for (i = 0; helpanim_config[i].token != NULL; i++)
4042 printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4043 helpanim_config[i].value));
4045 if (strcmp(helpanim_config[i].token, "end") == 0)
4051 else if (strcmp(command, "print helptext.conf") == 0)
4053 printf("# You can configure different element help text here.\n");
4054 printf("# (The entries below are default and therefore commented out.)\n");
4057 for (i = 0; helptext_config[i].token != NULL; i++)
4058 printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4059 helptext_config[i].value));
4063 else if (strncmp(command, "dump level ", 11) == 0)
4065 char *filename = &command[11];
4067 if (!fileExists(filename))
4068 Error(ERR_EXIT, "cannot open file '%s'", filename);
4070 LoadLevelFromFilename(&level, filename);
4075 else if (strncmp(command, "dump tape ", 10) == 0)
4077 char *filename = &command[10];
4079 if (!fileExists(filename))
4080 Error(ERR_EXIT, "cannot open file '%s'", filename);
4082 LoadTapeFromFilename(filename);
4087 else if (strncmp(command, "autoplay ", 9) == 0)
4089 char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
4091 while (*str_ptr != '\0') /* continue parsing string */
4093 /* cut leading whitespace from string, replace it by string terminator */
4094 while (*str_ptr == ' ' || *str_ptr == '\t')
4097 if (*str_ptr == '\0') /* end of string reached */
4100 if (global.autoplay_leveldir == NULL) /* read level set string */
4102 global.autoplay_leveldir = str_ptr;
4103 global.autoplay_all = TRUE; /* default: play all tapes */
4105 for (i = 0; i < MAX_TAPES_PER_SET; i++)
4106 global.autoplay_level[i] = FALSE;
4108 else /* read level number string */
4110 int level_nr = atoi(str_ptr); /* get level_nr value */
4112 if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
4113 global.autoplay_level[level_nr] = TRUE;
4115 global.autoplay_all = FALSE;
4118 /* advance string pointer to the next whitespace (or end of string) */
4119 while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
4123 else if (strncmp(command, "convert ", 8) == 0)
4125 char *str_copy = getStringCopy(&command[8]);
4126 char *str_ptr = strchr(str_copy, ' ');
4128 global.convert_leveldir = str_copy;
4129 global.convert_level_nr = -1;
4131 if (str_ptr != NULL) /* level number follows */
4133 *str_ptr++ = '\0'; /* terminate leveldir string */
4134 global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
4139 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4143 static void InitSetup()
4145 LoadSetup(); /* global setup info */
4147 /* set some options from setup file */
4149 if (setup.options.verbose)
4150 options.verbose = TRUE;
4153 static void InitGameInfo()
4155 game.restart_level = FALSE;
4158 static void InitPlayerInfo()
4162 /* choose default local player */
4163 local_player = &stored_player[0];
4165 for (i = 0; i < MAX_PLAYERS; i++)
4166 stored_player[i].connected = FALSE;
4168 local_player->connected = TRUE;
4171 static void InitArtworkInfo()
4176 static char *get_string_in_brackets(char *string)
4178 char *string_in_brackets = checked_malloc(strlen(string) + 3);
4180 sprintf(string_in_brackets, "[%s]", string);
4182 return string_in_brackets;
4185 static char *get_level_id_suffix(int id_nr)
4187 char *id_suffix = checked_malloc(1 + 3 + 1);
4189 if (id_nr < 0 || id_nr > 999)
4192 sprintf(id_suffix, ".%03d", id_nr);
4198 static char *get_element_class_token(int element)
4200 char *element_class_name = element_info[element].class_name;
4201 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4203 sprintf(element_class_token, "[%s]", element_class_name);
4205 return element_class_token;
4208 static char *get_action_class_token(int action)
4210 char *action_class_name = &element_action_info[action].suffix[1];
4211 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4213 sprintf(action_class_token, "[%s]", action_class_name);
4215 return action_class_token;
4219 static void InitArtworkConfig()
4221 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4222 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4223 static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4224 static char *action_id_suffix[NUM_ACTIONS + 1];
4225 static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
4226 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4227 static char *level_id_suffix[MAX_LEVELS + 1];
4228 static char *dummy[1] = { NULL };
4229 static char *ignore_generic_tokens[] =
4235 static char **ignore_image_tokens;
4236 static char **ignore_sound_tokens;
4237 static char **ignore_music_tokens;
4238 int num_ignore_generic_tokens;
4239 int num_ignore_image_tokens;
4240 int num_ignore_sound_tokens;
4241 int num_ignore_music_tokens;
4244 /* dynamically determine list of generic tokens to be ignored */
4245 num_ignore_generic_tokens = 0;
4246 for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4247 num_ignore_generic_tokens++;
4249 /* dynamically determine list of image tokens to be ignored */
4250 num_ignore_image_tokens = num_ignore_generic_tokens;
4251 for (i = 0; image_config_vars[i].token != NULL; i++)
4252 num_ignore_image_tokens++;
4253 ignore_image_tokens =
4254 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4255 for (i = 0; i < num_ignore_generic_tokens; i++)
4256 ignore_image_tokens[i] = ignore_generic_tokens[i];
4257 for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4258 ignore_image_tokens[num_ignore_generic_tokens + i] =
4259 image_config_vars[i].token;
4260 ignore_image_tokens[num_ignore_image_tokens] = NULL;
4262 /* dynamically determine list of sound tokens to be ignored */
4263 num_ignore_sound_tokens = num_ignore_generic_tokens;
4264 ignore_sound_tokens =
4265 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4266 for (i = 0; i < num_ignore_generic_tokens; i++)
4267 ignore_sound_tokens[i] = ignore_generic_tokens[i];
4268 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4270 /* dynamically determine list of music tokens to be ignored */
4271 num_ignore_music_tokens = num_ignore_generic_tokens;
4272 ignore_music_tokens =
4273 checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4274 for (i = 0; i < num_ignore_generic_tokens; i++)
4275 ignore_music_tokens[i] = ignore_generic_tokens[i];
4276 ignore_music_tokens[num_ignore_music_tokens] = NULL;
4278 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4279 image_id_prefix[i] = element_info[i].token_name;
4280 for (i = 0; i < NUM_FONTS; i++)
4281 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4282 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4284 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4285 sound_id_prefix[i] = element_info[i].token_name;
4286 for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4287 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4288 get_string_in_brackets(element_info[i].class_name);
4289 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4291 for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4292 music_id_prefix[i] = music_prefix_info[i].prefix;
4293 music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
4295 for (i = 0; i < NUM_ACTIONS; i++)
4296 action_id_suffix[i] = element_action_info[i].suffix;
4297 action_id_suffix[NUM_ACTIONS] = NULL;
4299 for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
4300 direction_id_suffix[i] = element_direction_info[i].suffix;
4301 direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
4303 for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4304 special_id_suffix[i] = special_suffix_info[i].suffix;
4305 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4307 for (i = 0; i < MAX_LEVELS; i++)
4308 level_id_suffix[i] = get_level_id_suffix(i);
4309 level_id_suffix[MAX_LEVELS] = NULL;
4311 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4312 image_id_prefix, action_id_suffix, direction_id_suffix,
4313 special_id_suffix, ignore_image_tokens);
4314 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4315 sound_id_prefix, action_id_suffix, dummy,
4316 special_id_suffix, ignore_sound_tokens);
4317 InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4318 music_id_prefix, special_id_suffix, level_id_suffix,
4319 dummy, ignore_music_tokens);
4322 static void InitMixer()
4330 char *filename_font_initial = NULL;
4331 Bitmap *bitmap_font_initial = NULL;
4334 /* determine settings for initial font (for displaying startup messages) */
4335 for (i = 0; image_config[i].token != NULL; i++)
4337 for (j = 0; j < NUM_INITIAL_FONTS; j++)
4339 char font_token[128];
4342 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
4343 len_font_token = strlen(font_token);
4345 if (strcmp(image_config[i].token, font_token) == 0)
4346 filename_font_initial = image_config[i].value;
4347 else if (strlen(image_config[i].token) > len_font_token &&
4348 strncmp(image_config[i].token, font_token, len_font_token) == 0)
4350 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
4351 font_initial[j].src_x = atoi(image_config[i].value);
4352 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
4353 font_initial[j].src_y = atoi(image_config[i].value);
4354 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
4355 font_initial[j].width = atoi(image_config[i].value);
4356 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
4357 font_initial[j].height = atoi(image_config[i].value);
4362 for (j = 0; j < NUM_INITIAL_FONTS; j++)
4364 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
4365 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
4368 if (filename_font_initial == NULL) /* should not happen */
4369 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
4371 /* create additional image buffers for double-buffering */
4372 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
4373 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
4375 /* initialize screen properties */
4376 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
4377 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
4379 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
4380 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
4381 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
4383 bitmap_font_initial = LoadCustomImage(filename_font_initial);
4385 for (j = 0; j < NUM_INITIAL_FONTS; j++)
4386 font_initial[j].bitmap = bitmap_font_initial;
4388 InitFontGraphicInfo();
4390 DrawInitText(getProgramInitString(), 20, FC_YELLOW);
4391 DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
4393 DrawInitText("Loading graphics:", 120, FC_GREEN);
4396 void InitGfxBackground()
4400 drawto = backbuffer;
4401 fieldbuffer = bitmap_db_field;
4402 SetDrawtoField(DRAW_BACKBUFFER);
4404 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
4405 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
4406 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
4407 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
4409 for (x = 0; x < MAX_BUF_XSIZE; x++)
4410 for (y = 0; y < MAX_BUF_YSIZE; y++)
4413 redraw_mask = REDRAW_ALL;
4416 static void InitLevelInfo()
4418 LoadLevelInfo(); /* global level info */
4419 LoadLevelSetup_LastSeries(); /* last played series info */
4420 LoadLevelSetup_SeriesInfo(); /* last played level info */
4423 void InitLevelArtworkInfo()
4425 LoadLevelArtworkInfo();
4428 static void InitImages()
4430 setLevelArtworkDir(artwork.gfx_first);
4433 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
4434 leveldir_current->identifier,
4435 artwork.gfx_current_identifier,
4436 artwork.gfx_current->identifier,
4437 leveldir_current->graphics_set,
4438 leveldir_current->graphics_path);
4441 ReloadCustomImages();
4443 LoadCustomElementDescriptions();
4444 LoadSpecialMenuDesignSettings();
4446 ReinitializeGraphics();
4449 static void InitSound(char *identifier)
4451 if (identifier == NULL)
4452 identifier = artwork.snd_current->identifier;
4454 /* set artwork path to send it to the sound server process */
4455 setLevelArtworkDir(artwork.snd_first);
4457 InitReloadCustomSounds(identifier);
4458 ReinitializeSounds();
4461 static void InitMusic(char *identifier)
4463 if (identifier == NULL)
4464 identifier = artwork.mus_current->identifier;
4466 /* set artwork path to send it to the sound server process */
4467 setLevelArtworkDir(artwork.mus_first);
4469 InitReloadCustomMusic(identifier);
4470 ReinitializeMusic();
4473 void InitNetworkServer()
4475 #if defined(NETWORK_AVALIABLE)
4479 if (!options.network)
4482 #if defined(NETWORK_AVALIABLE)
4483 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
4485 if (!ConnectToServer(options.server_host, options.server_port))
4486 Error(ERR_EXIT, "cannot connect to network game server");
4488 SendToServer_PlayerName(setup.player_name);
4489 SendToServer_ProtocolVersion();
4492 SendToServer_NrWanted(nr_wanted);
4496 static char *getNewArtworkIdentifier(int type)
4498 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4499 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4500 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4501 static boolean initialized[3] = { FALSE, FALSE, FALSE };
4502 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4503 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4504 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4505 char *leveldir_identifier = leveldir_current->identifier;
4507 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4508 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4510 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4512 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4513 char *artwork_current_identifier;
4514 char *artwork_new_identifier = NULL; /* default: nothing has changed */
4516 /* leveldir_current may be invalid (level group, parent link) */
4517 if (!validLevelSeries(leveldir_current))
4520 /* 1st step: determine artwork set to be activated in descending order:
4521 --------------------------------------------------------------------
4522 1. setup artwork (when configured to override everything else)
4523 2. artwork set configured in "levelinfo.conf" of current level set
4524 (artwork in level directory will have priority when loading later)
4525 3. artwork in level directory (stored in artwork sub-directory)
4526 4. setup artwork (currently configured in setup menu) */
4528 if (setup_override_artwork)
4529 artwork_current_identifier = setup_artwork_set;
4530 else if (leveldir_artwork_set != NULL)
4531 artwork_current_identifier = leveldir_artwork_set;
4532 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4533 artwork_current_identifier = leveldir_identifier;
4535 artwork_current_identifier = setup_artwork_set;
4538 /* 2nd step: check if it is really needed to reload artwork set
4539 ------------------------------------------------------------ */
4542 if (type == ARTWORK_TYPE_GRAPHICS)
4543 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4544 artwork_new_identifier,
4545 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4546 artwork_current_identifier,
4547 leveldir_current->graphics_set,
4548 leveldir_current->identifier);
4551 /* ---------- reload if level set and also artwork set has changed ------- */
4552 if (leveldir_current_identifier[type] != leveldir_identifier &&
4553 (last_has_level_artwork_set[type] || has_level_artwork_set))
4554 artwork_new_identifier = artwork_current_identifier;
4556 leveldir_current_identifier[type] = leveldir_identifier;
4557 last_has_level_artwork_set[type] = has_level_artwork_set;
4560 if (type == ARTWORK_TYPE_GRAPHICS)
4561 printf("::: 1: '%s'\n", artwork_new_identifier);
4564 /* ---------- reload if "override artwork" setting has changed ----------- */
4565 if (last_override_level_artwork[type] != setup_override_artwork)
4566 artwork_new_identifier = artwork_current_identifier;
4568 last_override_level_artwork[type] = setup_override_artwork;
4571 if (type == ARTWORK_TYPE_GRAPHICS)
4572 printf("::: 2: '%s'\n", artwork_new_identifier);
4575 /* ---------- reload if current artwork identifier has changed ----------- */
4576 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4577 artwork_current_identifier) != 0)
4578 artwork_new_identifier = artwork_current_identifier;
4580 *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
4583 if (type == ARTWORK_TYPE_GRAPHICS)
4584 printf("::: 3: '%s'\n", artwork_new_identifier);
4587 /* ---------- do not reload directly after starting ---------------------- */
4588 if (!initialized[type])
4589 artwork_new_identifier = NULL;
4591 initialized[type] = TRUE;
4594 if (type == ARTWORK_TYPE_GRAPHICS)
4595 printf("::: 4: '%s'\n", artwork_new_identifier);
4599 if (type == ARTWORK_TYPE_GRAPHICS)
4600 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4601 artwork.gfx_current_identifier, artwork_current_identifier,
4602 artwork.gfx_current->identifier, leveldir_current->graphics_set,
4603 artwork_new_identifier);
4606 return artwork_new_identifier;
4609 void ReloadCustomArtwork(int force_reload)
4611 char *gfx_new_identifier;
4612 char *snd_new_identifier;
4613 char *mus_new_identifier;
4614 boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4615 boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4616 boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4617 boolean redraw_screen = FALSE;
4619 force_reload_gfx |= AdjustGraphicsForEMC();
4621 gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
4622 snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
4623 mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
4625 if (gfx_new_identifier != NULL || force_reload_gfx)
4628 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
4629 artwork.gfx_current_identifier,
4631 artwork.gfx_current->identifier,
4632 leveldir_current->graphics_set);
4635 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4639 redraw_screen = TRUE;
4642 if (snd_new_identifier != NULL || force_reload_snd)
4644 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4646 InitSound(snd_new_identifier);
4648 redraw_screen = TRUE;
4651 if (mus_new_identifier != NULL || force_reload_mus)
4653 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4655 InitMusic(mus_new_identifier);
4657 redraw_screen = TRUE;
4662 InitGfxBackground();
4664 /* force redraw of (open or closed) door graphics */
4665 SetDoorState(DOOR_OPEN_ALL);
4666 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
4670 void KeyboardAutoRepeatOffUnlessAutoplay()
4672 if (global.autoplay_leveldir == NULL)
4673 KeyboardAutoRepeatOff();
4677 /* ========================================================================= */
4679 /* ========================================================================= */
4683 InitGlobal(); /* initialize some global variables */
4685 if (options.execute_command)
4686 Execute_Command(options.execute_command);
4688 if (options.serveronly)
4690 #if defined(PLATFORM_UNIX)
4691 NetworkServer(options.server_port, options.serveronly);
4693 Error(ERR_WARN, "networking only supported in Unix version");
4696 exit(0); /* never reached, server loops forever */
4703 InitArtworkInfo(); /* needed before loading gfx, sound & music */
4704 InitArtworkConfig(); /* needed before forking sound child process */
4709 InitRND(NEW_RANDOMIZE);
4710 InitSimpleRND(NEW_RANDOMIZE);
4715 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
4718 InitEventFilter(FilterMouseMotionEvents);
4720 InitElementPropertiesStatic();
4721 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4726 InitLevelArtworkInfo();
4728 InitImages(); /* needs to know current level directory */
4729 InitSound(NULL); /* needs to know current level directory */
4730 InitMusic(NULL); /* needs to know current level directory */
4732 InitGfxBackground();
4734 if (global.autoplay_leveldir)
4739 else if (global.convert_leveldir)
4745 game_status = GAME_MODE_MAIN;
4753 InitNetworkServer();
4756 void CloseAllAndExit(int exit_value)
4761 CloseAudio(); /* called after freeing sounds (needed for SDL) */
4769 #if defined(TARGET_SDL)
4770 if (network_server) /* terminate network server */
4771 SDL_KillThread(server_thread);
4774 CloseVideoDisplay();
4775 ClosePlatformDependentStuff();