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"
28 #include "conf_e2g.c" /* include auto-generated data structure definitions */
29 #include "conf_esg.c" /* include auto-generated data structure definitions */
30 #include "conf_e2s.c" /* include auto-generated data structure definitions */
31 #include "conf_fnt.c" /* include auto-generated data structure definitions */
34 #define CONFIG_TOKEN_FONT_INITIAL "font.initial"
37 struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
40 static void InitTileClipmasks()
43 #if defined(TARGET_X11)
44 XGCValues clip_gc_values;
45 unsigned long clip_gc_valuemask;
47 #if defined(TARGET_X11_NATIVE)
57 tile_needs_clipping[] =
59 { GFX_SPIELER1_UP, 4 },
60 { GFX_SPIELER1_DOWN, 4 },
61 { GFX_SPIELER1_LEFT, 4 },
62 { GFX_SPIELER1_RIGHT, 4 },
63 { GFX_SPIELER1_PUSH_LEFT, 4 },
64 { GFX_SPIELER1_PUSH_RIGHT, 4 },
65 { GFX_SPIELER2_UP, 4 },
66 { GFX_SPIELER2_DOWN, 4 },
67 { GFX_SPIELER2_LEFT, 4 },
68 { GFX_SPIELER2_RIGHT, 4 },
69 { GFX_SPIELER2_PUSH_LEFT, 4 },
70 { GFX_SPIELER2_PUSH_RIGHT, 4 },
71 { GFX_SPIELER3_UP, 4 },
72 { GFX_SPIELER3_DOWN, 4 },
73 { GFX_SPIELER3_LEFT, 4 },
74 { GFX_SPIELER3_RIGHT, 4 },
75 { GFX_SPIELER3_PUSH_LEFT, 4 },
76 { GFX_SPIELER3_PUSH_RIGHT, 4 },
77 { GFX_SPIELER4_UP, 4 },
78 { GFX_SPIELER4_DOWN, 4 },
79 { GFX_SPIELER4_LEFT, 4 },
80 { GFX_SPIELER4_RIGHT, 4 },
81 { GFX_SPIELER4_PUSH_LEFT, 4 },
82 { GFX_SPIELER4_PUSH_RIGHT, 4 },
84 { GFX_MURPHY_GO_LEFT, 3 },
85 { GFX_MURPHY_GO_RIGHT, 3 },
86 { GFX_MURPHY_SNAP_UP, 1 },
87 { GFX_MURPHY_SNAP_DOWN, 1 },
88 { GFX_MURPHY_SNAP_RIGHT, 1 },
89 { GFX_MURPHY_SNAP_LEFT, 1 },
90 { GFX_MURPHY_PUSH_RIGHT, 1 },
91 { GFX_MURPHY_PUSH_LEFT, 1 },
96 { GFX_SOKOBAN_OBJEKT, 1 },
97 { GFX_FUNKELN_BLAU, 3 },
98 { GFX_FUNKELN_WEISS, 3 },
99 { GFX2_SHIELD_PASSIVE, 3 },
100 { GFX2_SHIELD_ACTIVE, 3 },
105 #endif /* TARGET_X11_NATIVE */
106 #endif /* TARGET_X11 */
110 /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
111 for (i=0; i<NUM_TILES; i++)
112 tile_clipmask[i] = None;
114 #if defined(TARGET_X11)
115 /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
116 often very slow when preparing a masked XCopyArea() for big Pixmaps.
117 To prevent this, create small (tile-sized) mask Pixmaps which will then
118 be set much faster with XSetClipOrigin() and speed things up a lot. */
120 clip_gc_values.graphics_exposures = False;
121 clip_gc_valuemask = GCGraphicsExposures;
122 tile_clip_gc = XCreateGC(display, window->drawable,
123 clip_gc_valuemask, &clip_gc_values);
126 for (i=0; i<NUM_BITMAPS; i++)
128 if (pix[i]->clip_mask)
130 clip_gc_values.graphics_exposures = False;
131 clip_gc_values.clip_mask = pix[i]->clip_mask;
132 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
133 pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
134 clip_gc_valuemask, &clip_gc_values);
139 #if defined(TARGET_X11_NATIVE)
142 /* create graphic context structures needed for clipping */
143 clip_gc_values.graphics_exposures = False;
144 clip_gc_valuemask = GCGraphicsExposures;
145 copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
146 clip_gc_valuemask, &clip_gc_values);
148 /* create only those clipping Pixmaps we really need */
149 for (i=0; tile_needs_clipping[i].start>=0; i++)
153 for (j=0; j<tile_needs_clipping[i].count; j++)
155 int tile = tile_needs_clipping[i].start + j;
161 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
162 src_pixmap = src_bitmap->clip_mask;
164 tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
167 XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
168 src_x, src_y, TILEX, TILEY, 0, 0);
172 XFreeGC(display, copy_clipmask_gc);
175 #endif /* TARGET_X11_NATIVE */
176 #endif /* TARGET_X11 */
180 void FreeTileClipmasks()
183 #if defined(TARGET_X11)
186 for (i=0; i<NUM_TILES; i++)
188 if (tile_clipmask[i] != None)
190 XFreePixmap(display, tile_clipmask[i]);
191 tile_clipmask[i] = None;
196 XFreeGC(display, tile_clip_gc);
200 for (i=0; i<NUM_BITMAPS; i++)
202 if (pix[i] != NULL && pix[i]->stored_clip_gc)
204 XFreeGC(display, pix[i]->stored_clip_gc);
205 pix[i]->stored_clip_gc = None;
210 #endif /* TARGET_X11 */
216 FreeLevelEditorGadgets();
225 static boolean gadgets_initialized = FALSE;
227 if (gadgets_initialized)
230 CreateLevelEditorGadgets();
234 CreateScreenGadgets();
236 gadgets_initialized = TRUE;
239 void InitElementSmallImages()
241 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
242 int num_property_mappings = getImageListPropertyMappingSize();
245 /* initialize normal images from static configuration */
246 for (i=0; element_to_graphic[i].element > -1; i++)
247 CreateImageWithSmallImages(element_to_graphic[i].graphic);
249 /* initialize special images from static configuration */
250 for (i=0; element_to_special_graphic[i].element > -1; i++)
251 CreateImageWithSmallImages(element_to_special_graphic[i].graphic);
253 /* initialize images from dynamic configuration */
254 for (i=0; i < num_property_mappings; i++)
255 if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
256 CreateImageWithSmallImages(property_mapping[i].artwork_index);
259 static int getFontBitmapID(int font_nr)
263 if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
264 special = game_status;
265 else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
266 special = GFX_SPECIAL_ARG_MAIN;
267 else if (game_status == GAME_MODE_PLAYING)
268 special = GFX_SPECIAL_ARG_DOOR;
271 return font_info[font_nr].special_bitmap_id[special];
276 void InitFontGraphicInfo()
278 static struct FontBitmapInfo *font_bitmap_info = NULL;
279 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
280 int num_property_mappings = getImageListPropertyMappingSize();
281 int num_font_bitmaps = NUM_FONTS;
284 if (graphic_info == NULL) /* still at startup phase */
286 InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
291 /* ---------- initialize font graphic definitions ---------- */
293 /* always start with reliable default values (normal font graphics) */
294 for (i=0; i < NUM_FONTS; i++)
295 font_info[i].graphic = FONT_INITIAL_1;
297 /* initialize normal font/graphic mapping from static configuration */
298 for (i=0; font_to_graphic[i].font_nr > -1; i++)
300 int font_nr = font_to_graphic[i].font_nr;
301 int special = font_to_graphic[i].special;
302 int graphic = font_to_graphic[i].graphic;
307 font_info[font_nr].graphic = graphic;
310 /* always start with reliable default values (special font graphics) */
311 for (i=0; i < NUM_FONTS; i++)
313 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
315 font_info[i].special_graphic[j] = font_info[i].graphic;
316 font_info[i].special_bitmap_id[j] = i;
320 /* initialize special font/graphic mapping from static configuration */
321 for (i=0; font_to_graphic[i].font_nr > -1; i++)
323 int font_nr = font_to_graphic[i].font_nr;
324 int special = font_to_graphic[i].special;
325 int graphic = font_to_graphic[i].graphic;
327 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
329 font_info[font_nr].special_graphic[special] = graphic;
330 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
335 /* initialize special element/graphic mapping from dynamic configuration */
336 for (i=0; i < num_property_mappings; i++)
338 int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
339 int special = property_mapping[i].ext3_index;
340 int graphic = property_mapping[i].artwork_index;
345 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
347 font_info[font_nr].special_graphic[special] = graphic;
348 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
353 /* ---------- initialize font bitmap array ---------- */
355 if (font_bitmap_info != NULL)
356 FreeFontInfo(font_bitmap_info);
359 checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
361 /* ---------- initialize font bitmap definitions ---------- */
363 for (i=0; i < NUM_FONTS; i++)
365 if (i < NUM_INITIAL_FONTS)
367 font_bitmap_info[i] = font_initial[i];
371 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
373 int font_bitmap_id = font_info[i].special_bitmap_id[j];
374 int graphic = font_info[i].special_graphic[j];
376 /* set 'graphic_info' for font entries, if uninitialized (guessed) */
377 if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
379 graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
380 graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
383 /* copy font relevant information from graphics information */
384 font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
385 font_bitmap_info[font_bitmap_id].src_x = graphic_info[graphic].src_x;
386 font_bitmap_info[font_bitmap_id].src_y = graphic_info[graphic].src_y;
387 font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
388 font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
389 font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
390 font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
392 font_bitmap_info[font_bitmap_id].num_chars =
393 graphic_info[graphic].anim_frames;
394 font_bitmap_info[font_bitmap_id].num_chars_per_line =
395 graphic_info[graphic].anim_frames_per_line;
399 InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
402 void InitElementGraphicInfo()
404 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
405 int num_property_mappings = getImageListPropertyMappingSize();
408 /* set values to -1 to identify later as "uninitialized" values */
409 for (i=0; i<MAX_NUM_ELEMENTS; i++)
411 for (act=0; act<NUM_ACTIONS; act++)
413 element_info[i].graphic[act] = -1;
414 element_info[i].crumbled[act] = -1;
416 for (dir=0; dir<NUM_DIRECTIONS; dir++)
418 element_info[i].direction_graphic[act][dir] = -1;
419 element_info[i].direction_crumbled[act][dir] = -1;
424 /* initialize normal element/graphic mapping from static configuration */
425 for (i=0; element_to_graphic[i].element > -1; i++)
427 int element = element_to_graphic[i].element;
428 int action = element_to_graphic[i].action;
429 int direction = element_to_graphic[i].direction;
430 boolean crumbled = element_to_graphic[i].crumbled;
431 int graphic = element_to_graphic[i].graphic;
433 if (graphic_info[graphic].bitmap == NULL)
436 if ((action > -1 || direction > -1 || crumbled == TRUE) &&
437 el2img(element) != -1)
439 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
440 boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
442 /* if the base graphic ("emerald", for example) has been redefined,
443 but not the action graphic ("emerald.falling", for example), do not
444 use an existing (in this case considered obsolete) action graphic
445 anymore, but use the automatically determined default graphic */
446 if (base_redefined && !act_dir_redefined)
451 action = ACTION_DEFAULT;
456 element_info[element].direction_crumbled[action][direction] = graphic;
458 element_info[element].crumbled[action] = graphic;
463 element_info[element].direction_graphic[action][direction] = graphic;
465 element_info[element].graphic[action] = graphic;
469 /* initialize normal element/graphic mapping from dynamic configuration */
470 for (i=0; i < num_property_mappings; i++)
472 int element = property_mapping[i].base_index;
473 int action = property_mapping[i].ext1_index;
474 int direction = property_mapping[i].ext2_index;
475 int special = property_mapping[i].ext3_index;
476 int graphic = property_mapping[i].artwork_index;
477 boolean crumbled = FALSE;
479 if (special == GFX_SPECIAL_ARG_CRUMBLED)
485 if (graphic_info[graphic].bitmap == NULL)
488 if (element >= MAX_NUM_ELEMENTS || special != -1)
492 action = ACTION_DEFAULT;
497 for (dir=0; dir<NUM_DIRECTIONS; dir++)
498 element_info[element].direction_crumbled[action][dir] = -1;
501 element_info[element].direction_crumbled[action][direction] = graphic;
503 element_info[element].crumbled[action] = graphic;
508 for (dir=0; dir<NUM_DIRECTIONS; dir++)
509 element_info[element].direction_graphic[action][dir] = -1;
512 element_info[element].direction_graphic[action][direction] = graphic;
514 element_info[element].graphic[action] = graphic;
518 /* now copy all graphics that are defined to be cloned from other graphics */
519 for (i=0; i<MAX_NUM_ELEMENTS; i++)
521 int graphic = element_info[i].graphic[ACTION_DEFAULT];
522 int crumbled_like, diggable_like;
527 crumbled_like = graphic_info[graphic].crumbled_like;
528 diggable_like = graphic_info[graphic].diggable_like;
530 if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
532 for (act=0; act<NUM_ACTIONS; act++)
533 element_info[i].crumbled[act] =
534 element_info[crumbled_like].crumbled[act];
535 for (act=0; act<NUM_ACTIONS; act++)
536 for (dir=0; dir<NUM_DIRECTIONS; dir++)
537 element_info[i].direction_crumbled[act][dir] =
538 element_info[crumbled_like].direction_crumbled[act][dir];
541 if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
543 element_info[i].graphic[ACTION_DIGGING] =
544 element_info[diggable_like].graphic[ACTION_DIGGING];
545 for (dir=0; dir<NUM_DIRECTIONS; dir++)
546 element_info[i].direction_graphic[ACTION_DIGGING][dir] =
547 element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
552 /* now set all undefined/invalid graphics to -1 to set to default after it */
553 for (i=0; i<MAX_NUM_ELEMENTS; i++)
555 for (act=0; act<NUM_ACTIONS; act++)
557 if (graphic_info[element_info[i].graphic[act]].bitmap == NULL)
558 element_info[i].graphic[act] = -1;
560 if (graphic_info[element_info[i].crumbled[act]].bitmap == NULL)
561 element_info[i].crumbled[act] = -1;
563 for (dir=0; dir<NUM_DIRECTIONS; dir++)
567 graphic = element_info[i].direction_graphic[act][dir];
568 if (graphic_info[graphic].bitmap == NULL)
569 element_info[i].direction_graphic[act][dir] = -1;
571 graphic = element_info[i].direction_crumbled[act][dir];
572 if (graphic_info[graphic].bitmap == NULL)
573 element_info[i].direction_crumbled[act][dir] = -1;
579 /* now set all '-1' values to element specific default values */
580 for (i=0; i<MAX_NUM_ELEMENTS; i++)
582 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
583 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
584 int default_direction_graphic[NUM_DIRECTIONS];
585 int default_direction_crumbled[NUM_DIRECTIONS];
587 if (default_graphic == -1)
588 default_graphic = IMG_CHAR_QUESTION;
589 if (default_crumbled == -1)
590 default_crumbled = IMG_EMPTY;
592 for (dir=0; dir<NUM_DIRECTIONS; dir++)
594 default_direction_graphic[dir] =
595 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
596 default_direction_crumbled[dir] =
597 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
599 if (default_direction_graphic[dir] == -1)
600 default_direction_graphic[dir] = default_graphic;
601 if (default_direction_crumbled[dir] == -1)
602 default_direction_crumbled[dir] = default_crumbled;
605 for (act=0; act<NUM_ACTIONS; act++)
607 boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
608 (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
609 (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
611 /* generic default action graphic (defined by "[default]" directive) */
612 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
613 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
615 /* look for special default action graphic (classic game specific) */
616 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
617 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
618 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
619 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
620 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
621 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
623 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
624 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
625 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
626 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
627 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
628 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
630 if (default_action_graphic == -1)
631 default_action_graphic = default_graphic;
632 if (default_action_crumbled == -1)
633 default_action_crumbled = default_crumbled;
635 for (dir=0; dir<NUM_DIRECTIONS; dir++)
637 int default_action_direction_graphic = element_info[i].graphic[act];
638 int default_action_direction_crumbled = element_info[i].crumbled[act];
640 /* no graphic for current action -- use default direction graphic */
641 if (default_action_direction_graphic == -1)
642 default_action_direction_graphic =
643 (act_remove ? IMG_EMPTY : default_direction_graphic[dir]);
644 if (default_action_direction_crumbled == -1)
645 default_action_direction_crumbled =
646 (act_remove ? IMG_EMPTY : default_direction_crumbled[dir]);
648 if (element_info[i].direction_graphic[act][dir] == -1)
649 element_info[i].direction_graphic[act][dir] =
650 default_action_direction_graphic;
651 if (element_info[i].direction_crumbled[act][dir] == -1)
652 element_info[i].direction_crumbled[act][dir] =
653 default_action_direction_crumbled;
656 /* no graphic for this specific action -- use default action graphic */
657 if (element_info[i].graphic[act] == -1)
658 element_info[i].graphic[act] =
659 (act_remove ? IMG_EMPTY : default_action_graphic);
660 if (element_info[i].crumbled[act] == -1)
661 element_info[i].crumbled[act] =
662 (act_remove ? IMG_EMPTY : default_action_crumbled);
670 for (i=0; i<MAX_NUM_ELEMENTS; i++)
671 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
672 i != EL_CHAR_QUESTION)
673 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
674 element_info[i].token_name, i);
680 void InitElementSpecialGraphicInfo()
682 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
683 int num_property_mappings = getImageListPropertyMappingSize();
686 /* always start with reliable default values */
687 for (i=0; i < MAX_NUM_ELEMENTS; i++)
688 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
689 element_info[i].special_graphic[j] =
690 element_info[i].graphic[ACTION_DEFAULT];
692 /* initialize special element/graphic mapping from static configuration */
693 for (i=0; element_to_special_graphic[i].element > -1; i++)
695 int element = element_to_special_graphic[i].element;
696 int special = element_to_special_graphic[i].special;
697 int graphic = element_to_special_graphic[i].graphic;
698 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
699 boolean special_redefined = getImageListEntry(graphic)->redefined;
701 /* if the base graphic ("emerald", for example) has been redefined,
702 but not the special graphic ("emerald.EDITOR", for example), do not
703 use an existing (in this case considered obsolete) special graphic
704 anymore, but use the automatically created (down-scaled) graphic */
705 if (base_redefined && !special_redefined)
708 element_info[element].special_graphic[special] = graphic;
711 /* initialize special element/graphic mapping from dynamic configuration */
712 for (i=0; i < num_property_mappings; i++)
714 int element = property_mapping[i].base_index;
715 int special = property_mapping[i].ext3_index;
716 int graphic = property_mapping[i].artwork_index;
718 if (element >= MAX_NUM_ELEMENTS)
721 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
722 element_info[element].special_graphic[special] = graphic;
726 /* now set all undefined/invalid graphics to default */
727 for (i=0; i < MAX_NUM_ELEMENTS; i++)
728 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
729 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
730 element_info[i].special_graphic[j] =
731 element_info[i].graphic[ACTION_DEFAULT];
735 static int get_element_from_token(char *token)
739 for (i=0; i < MAX_NUM_ELEMENTS; i++)
740 if (strcmp(element_info[i].token_name, token) == 0)
746 static void set_graphic_parameters(int graphic, char **parameter_raw)
748 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
749 int parameter[NUM_GFX_ARGS];
750 int anim_frames_per_row = 1, anim_frames_per_col = 1;
751 int anim_frames_per_line = 1;
754 /* get integer values from string parameters */
755 for (i=0; i < NUM_GFX_ARGS; i++)
758 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
759 image_config_suffix[i].type);
761 if (image_config_suffix[i].type == TYPE_TOKEN)
762 parameter[i] = get_element_from_token(parameter_raw[i]);
765 graphic_info[graphic].bitmap = src_bitmap;
767 /* start with reliable default values */
768 graphic_info[graphic].src_x = 0;
769 graphic_info[graphic].src_y = 0;
770 graphic_info[graphic].width = TILEX;
771 graphic_info[graphic].height = TILEY;
772 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
773 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
774 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
775 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
777 /* optional x and y tile position of animation frame sequence */
778 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
779 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
780 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
781 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
783 /* optional x and y pixel position of animation frame sequence */
784 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
785 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
786 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
787 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
789 /* optional width and height of each animation frame */
790 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
791 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
792 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
793 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
797 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
798 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
801 /* correct x or y offset dependent of vertical or horizontal frame order */
802 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
804 graphic_info[graphic].offset_y =
805 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
806 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
807 anim_frames_per_line = anim_frames_per_col;
809 else /* frames are ordered horizontally */
811 graphic_info[graphic].offset_x =
812 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
813 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
814 anim_frames_per_line = anim_frames_per_row;
817 /* optionally, the x and y offset of frames can be specified directly */
818 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
819 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
820 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
821 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
823 /* automatically determine correct number of frames, if not defined */
824 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
825 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
826 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
827 graphic_info[graphic].anim_frames = anim_frames_per_row;
828 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
829 graphic_info[graphic].anim_frames = anim_frames_per_col;
831 graphic_info[graphic].anim_frames = 1;
833 graphic_info[graphic].anim_frames_per_line =
834 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
835 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
837 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
838 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
839 graphic_info[graphic].anim_delay = 1;
841 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
842 if (graphic_info[graphic].anim_frames == 1)
843 graphic_info[graphic].anim_mode = ANIM_NONE;
845 /* automatically determine correct start frame, if not defined */
846 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
847 graphic_info[graphic].anim_start_frame = 0;
848 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
849 graphic_info[graphic].anim_start_frame =
850 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
852 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
854 /* animation synchronized with global frame counter, not move position */
855 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
857 /* optional element for cloning crumble graphics */
858 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
859 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
861 /* optional element for cloning digging graphics */
862 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
863 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
865 /* this is only used for toon animations */
866 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
867 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
869 /* this is only used for drawing font characters */
870 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
871 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
874 static void InitGraphicInfo()
876 int fallback_graphic = IMG_CHAR_EXCLAM;
877 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
878 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
879 int num_images = getImageListSize();
882 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
883 static boolean clipmasks_initialized = FALSE;
885 XGCValues clip_gc_values;
886 unsigned long clip_gc_valuemask;
887 GC copy_clipmask_gc = None;
890 if (graphic_info != NULL)
893 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
895 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
896 if (clipmasks_initialized)
898 for (i=0; i<num_images; i++)
900 if (graphic_info[i].clip_mask)
901 XFreePixmap(display, graphic_info[i].clip_mask);
902 if (graphic_info[i].clip_gc)
903 XFreeGC(display, graphic_info[i].clip_gc);
905 graphic_info[i].clip_mask = None;
906 graphic_info[i].clip_gc = None;
911 for (i=0; i<num_images; i++)
913 struct FileInfo *image = getImageListEntry(i);
916 int first_frame, last_frame;
919 printf("::: image: '%s' [%d]\n", image->token, i);
923 printf("::: image # %d: '%s' ['%s']\n",
925 getTokenFromImageID(i));
928 set_graphic_parameters(i, image->parameter);
930 /* now check if no animation frames are outside of the loaded image */
932 if (graphic_info[i].bitmap == NULL)
933 continue; /* skip check for optional images that are undefined */
936 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
937 if (src_x < 0 || src_y < 0 ||
938 src_x + TILEX > src_bitmap->width ||
939 src_y + TILEY > src_bitmap->height)
941 Error(ERR_RETURN_LINE, "-");
942 Error(ERR_RETURN, "warning: error found in config file:");
943 Error(ERR_RETURN, "- config file: '%s'",
944 getImageConfigFilename());
945 Error(ERR_RETURN, "- config token: '%s'",
946 getTokenFromImageID(i));
947 Error(ERR_RETURN, "- image file: '%s'",
948 src_bitmap->source_filename);
950 "error: first animation frame out of bounds (%d, %d)",
952 Error(ERR_RETURN, "custom graphic rejected for this element/action");
954 if (i == fallback_graphic)
955 Error(ERR_EXIT, "fatal error: no fallback graphic available");
957 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
958 Error(ERR_RETURN_LINE, "-");
960 set_graphic_parameters(i, fallback_image->default_parameter);
961 graphic_info[i].bitmap = fallback_bitmap;
964 last_frame = graphic_info[i].anim_frames - 1;
965 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
966 if (src_x < 0 || src_y < 0 ||
967 src_x + TILEX > src_bitmap->width ||
968 src_y + TILEY > src_bitmap->height)
970 Error(ERR_RETURN_LINE, "-");
971 Error(ERR_RETURN, "warning: error found in config file:");
972 Error(ERR_RETURN, "- config file: '%s'",
973 getImageConfigFilename());
974 Error(ERR_RETURN, "- config token: '%s'",
975 getTokenFromImageID(i));
976 Error(ERR_RETURN, "- image file: '%s'",
977 src_bitmap->source_filename);
979 "error: last animation frame (%d) out of bounds (%d, %d)",
980 last_frame, src_x, src_y);
981 Error(ERR_RETURN, "custom graphic rejected for this element/action");
983 if (i == fallback_graphic)
984 Error(ERR_EXIT, "fatal error: no fallback graphic available");
986 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
987 Error(ERR_RETURN_LINE, "-");
989 set_graphic_parameters(i, fallback_image->default_parameter);
990 graphic_info[i].bitmap = fallback_bitmap;
993 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
994 /* currently we need only a tile clip mask from the first frame */
995 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
997 if (copy_clipmask_gc == None)
999 clip_gc_values.graphics_exposures = False;
1000 clip_gc_valuemask = GCGraphicsExposures;
1001 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1002 clip_gc_valuemask, &clip_gc_values);
1005 graphic_info[i].clip_mask =
1006 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1008 src_pixmap = src_bitmap->clip_mask;
1009 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1010 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1012 clip_gc_values.graphics_exposures = False;
1013 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1014 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1016 graphic_info[i].clip_gc =
1017 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1021 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1022 if (copy_clipmask_gc)
1023 XFreeGC(display, copy_clipmask_gc);
1025 clipmasks_initialized = TRUE;
1029 static void InitElementSoundInfo()
1031 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1032 int num_property_mappings = getSoundListPropertyMappingSize();
1035 /* set values to -1 to identify later as "uninitialized" values */
1036 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1037 for (act=0; act < NUM_ACTIONS; act++)
1038 element_info[i].sound[act] = -1;
1040 /* initialize element/sound mapping from static configuration */
1041 for (i=0; element_to_sound[i].element > -1; i++)
1043 int element = element_to_sound[i].element;
1044 int action = element_to_sound[i].action;
1045 int sound = element_to_sound[i].sound;
1046 boolean is_class = element_to_sound[i].is_class;
1049 action = ACTION_DEFAULT;
1052 element_info[element].sound[action] = sound;
1054 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1055 if (strcmp(element_info[j].class_name,
1056 element_info[element].class_name) == 0)
1057 element_info[j].sound[action] = sound;
1060 /* initialize element class/sound mapping from dynamic configuration */
1061 for (i=0; i < num_property_mappings; i++)
1063 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1064 int action = property_mapping[i].ext1_index;
1065 int sound = property_mapping[i].artwork_index;
1067 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1071 action = ACTION_DEFAULT;
1073 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1074 if (strcmp(element_info[j].class_name,
1075 element_info[element_class].class_name) == 0)
1076 element_info[j].sound[action] = sound;
1079 /* initialize element/sound mapping from dynamic configuration */
1080 for (i=0; i < num_property_mappings; i++)
1082 int element = property_mapping[i].base_index;
1083 int action = property_mapping[i].ext1_index;
1084 int sound = property_mapping[i].artwork_index;
1086 if (element >= MAX_NUM_ELEMENTS)
1090 action = ACTION_DEFAULT;
1092 element_info[element].sound[action] = sound;
1095 /* now set all '-1' values to element specific default values */
1096 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1098 for (act=0; act < NUM_ACTIONS; act++)
1100 /* generic default action sound (defined by "[default]" directive) */
1101 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1103 /* look for special default action sound (classic game specific) */
1104 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1105 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1106 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1107 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1108 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1109 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1111 /* look for element specific default sound (independent from action) */
1112 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1113 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1115 /* no sound for this specific action -- use default action sound */
1116 if (element_info[i].sound[act] == -1)
1117 element_info[i].sound[act] = default_action_sound;
1122 static void set_sound_parameters(int sound, char **parameter_raw)
1124 int parameter[NUM_SND_ARGS];
1127 /* get integer values from string parameters */
1128 for (i=0; i < NUM_SND_ARGS; i++)
1130 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1131 sound_config_suffix[i].type);
1133 /* explicit loop mode setting in configuration overrides default value */
1134 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1135 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1138 static void InitSoundInfo()
1141 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1142 int num_property_mappings = getSoundListPropertyMappingSize();
1144 int *sound_effect_properties;
1145 int num_sounds = getSoundListSize();
1148 if (sound_info != NULL)
1151 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1152 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1154 /* initialize sound effect for all elements to "no sound" */
1155 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1156 for (j=0; j<NUM_ACTIONS; j++)
1157 element_info[i].sound[j] = SND_UNDEFINED;
1159 for (i=0; i<num_sounds; i++)
1161 struct FileInfo *sound = getSoundListEntry(i);
1162 int len_effect_text = strlen(sound->token);
1164 sound_effect_properties[i] = ACTION_OTHER;
1165 sound_info[i].loop = FALSE;
1168 printf("::: sound %d: '%s'\n", i, sound->token);
1171 /* determine all loop sounds and identify certain sound classes */
1173 for (j=0; element_action_info[j].suffix; j++)
1175 int len_action_text = strlen(element_action_info[j].suffix);
1177 if (len_action_text < len_effect_text &&
1178 strcmp(&sound->token[len_effect_text - len_action_text],
1179 element_action_info[j].suffix) == 0)
1181 sound_effect_properties[i] = element_action_info[j].value;
1182 sound_info[i].loop = element_action_info[j].is_loop_sound;
1189 if (strcmp(sound->token, "custom_42") == 0)
1190 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1193 /* associate elements and some selected sound actions */
1195 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1197 if (element_info[j].class_name)
1199 int len_class_text = strlen(element_info[j].class_name);
1201 if (len_class_text + 1 < len_effect_text &&
1202 strncmp(sound->token,
1203 element_info[j].class_name, len_class_text) == 0 &&
1204 sound->token[len_class_text] == '.')
1206 int sound_action_value = sound_effect_properties[i];
1208 element_info[j].sound[sound_action_value] = i;
1213 set_sound_parameters(i, sound->parameter);
1216 free(sound_effect_properties);
1219 /* !!! now handled in InitElementSoundInfo() !!! */
1220 /* initialize element/sound mapping from dynamic configuration */
1221 for (i=0; i < num_property_mappings; i++)
1223 int element = property_mapping[i].base_index;
1224 int action = property_mapping[i].ext1_index;
1225 int sound = property_mapping[i].artwork_index;
1228 action = ACTION_DEFAULT;
1230 printf("::: %d: %d, %d, %d ['%s']\n",
1231 i, element, action, sound, element_info[element].token_name);
1233 element_info[element].sound[action] = sound;
1240 int element = EL_CUSTOM_11;
1243 while (element_action_info[j].suffix)
1245 printf("element %d, sound action '%s' == %d\n",
1246 element, element_action_info[j].suffix,
1247 element_info[element].sound[j]);
1252 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1258 int element = EL_SAND;
1259 int sound_action = ACTION_DIGGING;
1262 while (element_action_info[j].suffix)
1264 if (element_action_info[j].value == sound_action)
1265 printf("element %d, sound action '%s' == %d\n",
1266 element, element_action_info[j].suffix,
1267 element_info[element].sound[sound_action]);
1274 static void ReinitializeGraphics()
1276 InitGraphicInfo(); /* graphic properties mapping */
1277 InitElementGraphicInfo(); /* element game graphic mapping */
1278 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1280 InitElementSmallImages(); /* create editor and preview images */
1281 InitFontGraphicInfo(); /* initialize text drawing functions */
1283 SetMainBackgroundImage(IMG_BACKGROUND);
1284 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1290 static void ReinitializeSounds()
1292 InitSoundInfo(); /* sound properties mapping */
1293 InitElementSoundInfo(); /* element game sound mapping */
1295 InitPlaySoundLevel(); /* internal game sound settings */
1298 static void ReinitializeMusic()
1300 /* currently nothing to do */
1303 void InitElementPropertiesStatic()
1305 static int ep_diggable[] =
1310 EL_SP_BUGGY_BASE_ACTIVATING,
1313 EL_INVISIBLE_SAND_ACTIVE,
1315 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1319 EL_SP_BUGGY_BASE_ACTIVE,
1324 static int ep_collectible_only[] =
1341 EL_DYNABOMB_INCREASE_NUMBER,
1342 EL_DYNABOMB_INCREASE_SIZE,
1343 EL_DYNABOMB_INCREASE_POWER,
1357 static int ep_dont_run_into[] =
1359 /* same elements as in 'ep_dont_touch' */
1365 /* same elements as in 'ep_dont_collide_with' */
1377 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1379 EL_SP_BUGGY_BASE_ACTIVE,
1386 static int ep_dont_collide_with[] =
1388 /* same elements as in 'ep_dont_touch' */
1404 static int ep_dont_touch[] =
1413 static int ep_indestructible[] =
1417 EL_ACID_POOL_TOPLEFT,
1418 EL_ACID_POOL_TOPRIGHT,
1419 EL_ACID_POOL_BOTTOMLEFT,
1420 EL_ACID_POOL_BOTTOM,
1421 EL_ACID_POOL_BOTTOMRIGHT,
1422 EL_SP_HARDWARE_GRAY,
1423 EL_SP_HARDWARE_GREEN,
1424 EL_SP_HARDWARE_BLUE,
1426 EL_SP_HARDWARE_YELLOW,
1427 EL_SP_HARDWARE_BASE_1,
1428 EL_SP_HARDWARE_BASE_2,
1429 EL_SP_HARDWARE_BASE_3,
1430 EL_SP_HARDWARE_BASE_4,
1431 EL_SP_HARDWARE_BASE_5,
1432 EL_SP_HARDWARE_BASE_6,
1433 EL_INVISIBLE_STEELWALL,
1434 EL_INVISIBLE_STEELWALL_ACTIVE,
1435 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1436 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1437 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1438 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1439 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1440 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1441 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1442 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1443 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1444 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1445 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1446 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1448 EL_LIGHT_SWITCH_ACTIVE,
1449 EL_SIGN_EXCLAMATION,
1450 EL_SIGN_RADIOACTIVITY,
1461 EL_STEELWALL_SLIPPERY,
1484 EL_SWITCHGATE_OPENING,
1485 EL_SWITCHGATE_CLOSED,
1486 EL_SWITCHGATE_CLOSING,
1488 EL_SWITCHGATE_SWITCH_UP,
1489 EL_SWITCHGATE_SWITCH_DOWN,
1492 EL_TIMEGATE_OPENING,
1494 EL_TIMEGATE_CLOSING,
1497 EL_TIMEGATE_SWITCH_ACTIVE,
1502 EL_TUBE_VERTICAL_LEFT,
1503 EL_TUBE_VERTICAL_RIGHT,
1504 EL_TUBE_HORIZONTAL_UP,
1505 EL_TUBE_HORIZONTAL_DOWN,
1513 static int ep_slippery[] =
1527 EL_ROBOT_WHEEL_ACTIVE,
1533 EL_ACID_POOL_TOPLEFT,
1534 EL_ACID_POOL_TOPRIGHT,
1544 EL_STEELWALL_SLIPPERY,
1550 static int ep_can_change[] =
1555 static int ep_can_move[] =
1577 static int ep_can_fall[] =
1592 EL_BD_MAGIC_WALL_FULL,
1605 static int ep_can_smash_player[] =
1630 static int ep_can_smash_enemies[] =
1638 static int ep_can_smash_everything[] =
1646 static int ep_can_explode_by_fire[] =
1648 /* same elements as in 'ep_can_explode_impact' */
1653 /* same elements as in 'ep_can_explode_smashed' */
1662 EL_DYNABOMB_PLAYER_1_ACTIVE,
1663 EL_DYNABOMB_PLAYER_2_ACTIVE,
1664 EL_DYNABOMB_PLAYER_3_ACTIVE,
1665 EL_DYNABOMB_PLAYER_4_ACTIVE,
1666 EL_DYNABOMB_INCREASE_NUMBER,
1667 EL_DYNABOMB_INCREASE_SIZE,
1668 EL_DYNABOMB_INCREASE_POWER,
1669 EL_SP_DISK_RED_ACTIVE,
1679 static int ep_can_explode_smashed[] =
1681 /* same elements as in 'ep_can_explode_impact' */
1694 static int ep_can_explode_impact[] =
1702 static int ep_walkable_over[] =
1706 EL_SOKOBAN_FIELD_EMPTY,
1723 static int ep_walkable_inside[] =
1728 EL_TUBE_VERTICAL_LEFT,
1729 EL_TUBE_VERTICAL_RIGHT,
1730 EL_TUBE_HORIZONTAL_UP,
1731 EL_TUBE_HORIZONTAL_DOWN,
1739 static int ep_walkable_under[] =
1744 static int ep_passable_over[] =
1759 static int ep_passable_inside[] =
1765 EL_SP_PORT_HORIZONTAL,
1766 EL_SP_PORT_VERTICAL,
1768 EL_SP_GRAVITY_PORT_LEFT,
1769 EL_SP_GRAVITY_PORT_RIGHT,
1770 EL_SP_GRAVITY_PORT_UP,
1771 EL_SP_GRAVITY_PORT_DOWN,
1775 static int ep_passable_under[] =
1780 static int ep_pushable[] =
1792 EL_SOKOBAN_FIELD_FULL,
1799 static int ep_can_be_crumbled[] =
1808 static int ep_player[] =
1818 static int ep_can_pass_magic_wall[] =
1831 static int ep_switchable[] =
1835 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1836 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1837 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1838 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1839 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1840 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1841 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1842 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1843 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1844 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1845 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1846 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1847 EL_SWITCHGATE_SWITCH_UP,
1848 EL_SWITCHGATE_SWITCH_DOWN,
1850 EL_LIGHT_SWITCH_ACTIVE,
1852 EL_BALLOON_SWITCH_LEFT,
1853 EL_BALLOON_SWITCH_RIGHT,
1854 EL_BALLOON_SWITCH_UP,
1855 EL_BALLOON_SWITCH_DOWN,
1856 EL_BALLOON_SWITCH_ANY,
1862 static int ep_bd_element[] =
1891 static int ep_sp_element[] =
1899 EL_SP_HARDWARE_GRAY,
1907 EL_SP_GRAVITY_PORT_RIGHT,
1908 EL_SP_GRAVITY_PORT_DOWN,
1909 EL_SP_GRAVITY_PORT_LEFT,
1910 EL_SP_GRAVITY_PORT_UP,
1915 EL_SP_PORT_VERTICAL,
1916 EL_SP_PORT_HORIZONTAL,
1922 EL_SP_HARDWARE_BASE_1,
1923 EL_SP_HARDWARE_GREEN,
1924 EL_SP_HARDWARE_BLUE,
1926 EL_SP_HARDWARE_YELLOW,
1927 EL_SP_HARDWARE_BASE_2,
1928 EL_SP_HARDWARE_BASE_3,
1929 EL_SP_HARDWARE_BASE_4,
1930 EL_SP_HARDWARE_BASE_5,
1931 EL_SP_HARDWARE_BASE_6,
1934 /* additional elements that appeared in newer Supaplex levels */
1936 /* more than one murphy in a level results in an inactive clone */
1938 /* runtime elements*/
1939 EL_SP_DISK_RED_ACTIVE,
1940 EL_SP_TERMINAL_ACTIVE,
1941 EL_SP_BUGGY_BASE_ACTIVATING,
1942 EL_SP_BUGGY_BASE_ACTIVE,
1946 static int ep_sb_element[] =
1951 EL_SOKOBAN_FIELD_EMPTY,
1952 EL_SOKOBAN_FIELD_FULL,
1954 EL_INVISIBLE_STEELWALL,
1958 static int ep_gem[] =
1969 static int ep_food_dark_yamyam[] =
1996 static int ep_food_penguin[] =
2009 static int ep_food_pig[] =
2020 static int ep_historic_wall[] =
2045 EL_EXPANDABLE_WALL_HORIZONTAL,
2046 EL_EXPANDABLE_WALL_VERTICAL,
2047 EL_EXPANDABLE_WALL_ANY,
2048 EL_EXPANDABLE_WALL_GROWING,
2055 EL_SP_HARDWARE_GRAY,
2056 EL_SP_HARDWARE_GREEN,
2057 EL_SP_HARDWARE_BLUE,
2059 EL_SP_HARDWARE_YELLOW,
2060 EL_SP_HARDWARE_BASE_1,
2061 EL_SP_HARDWARE_BASE_2,
2062 EL_SP_HARDWARE_BASE_3,
2063 EL_SP_HARDWARE_BASE_4,
2064 EL_SP_HARDWARE_BASE_5,
2065 EL_SP_HARDWARE_BASE_6,
2067 EL_SP_TERMINAL_ACTIVE,
2070 EL_INVISIBLE_STEELWALL,
2071 EL_INVISIBLE_STEELWALL_ACTIVE,
2073 EL_INVISIBLE_WALL_ACTIVE,
2074 EL_STEELWALL_SLIPPERY,
2090 static int ep_historic_solid[] =
2094 EL_EXPANDABLE_WALL_HORIZONTAL,
2095 EL_EXPANDABLE_WALL_VERTICAL,
2096 EL_EXPANDABLE_WALL_ANY,
2109 EL_QUICKSAND_FILLING,
2110 EL_QUICKSAND_EMPTYING,
2112 EL_MAGIC_WALL_ACTIVE,
2113 EL_MAGIC_WALL_EMPTYING,
2114 EL_MAGIC_WALL_FILLING,
2118 EL_BD_MAGIC_WALL_ACTIVE,
2119 EL_BD_MAGIC_WALL_EMPTYING,
2120 EL_BD_MAGIC_WALL_FULL,
2121 EL_BD_MAGIC_WALL_FILLING,
2122 EL_BD_MAGIC_WALL_DEAD,
2131 EL_SP_TERMINAL_ACTIVE,
2135 EL_INVISIBLE_WALL_ACTIVE,
2136 EL_SWITCHGATE_SWITCH_UP,
2137 EL_SWITCHGATE_SWITCH_DOWN,
2139 EL_TIMEGATE_SWITCH_ACTIVE,
2151 /* the following elements are a direct copy of "indestructible" elements,
2152 except "EL_ACID", which is "indestructible", but not "solid"! */
2157 EL_ACID_POOL_TOPLEFT,
2158 EL_ACID_POOL_TOPRIGHT,
2159 EL_ACID_POOL_BOTTOMLEFT,
2160 EL_ACID_POOL_BOTTOM,
2161 EL_ACID_POOL_BOTTOMRIGHT,
2162 EL_SP_HARDWARE_GRAY,
2163 EL_SP_HARDWARE_GREEN,
2164 EL_SP_HARDWARE_BLUE,
2166 EL_SP_HARDWARE_YELLOW,
2167 EL_SP_HARDWARE_BASE_1,
2168 EL_SP_HARDWARE_BASE_2,
2169 EL_SP_HARDWARE_BASE_3,
2170 EL_SP_HARDWARE_BASE_4,
2171 EL_SP_HARDWARE_BASE_5,
2172 EL_SP_HARDWARE_BASE_6,
2173 EL_INVISIBLE_STEELWALL,
2174 EL_INVISIBLE_STEELWALL_ACTIVE,
2175 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2176 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2177 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2178 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2179 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2180 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2181 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2182 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2183 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2184 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2185 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2186 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2188 EL_LIGHT_SWITCH_ACTIVE,
2189 EL_SIGN_EXCLAMATION,
2190 EL_SIGN_RADIOACTIVITY,
2201 EL_STEELWALL_SLIPPERY,
2224 EL_SWITCHGATE_OPENING,
2225 EL_SWITCHGATE_CLOSED,
2226 EL_SWITCHGATE_CLOSING,
2228 EL_TIMEGATE_OPENING,
2230 EL_TIMEGATE_CLOSING,
2234 EL_TUBE_VERTICAL_LEFT,
2235 EL_TUBE_VERTICAL_RIGHT,
2236 EL_TUBE_HORIZONTAL_UP,
2237 EL_TUBE_HORIZONTAL_DOWN,
2245 static int ep_classic_enemy[] =
2261 static int ep_belt[] =
2263 EL_CONVEYOR_BELT_1_LEFT,
2264 EL_CONVEYOR_BELT_1_MIDDLE,
2265 EL_CONVEYOR_BELT_1_RIGHT,
2266 EL_CONVEYOR_BELT_2_LEFT,
2267 EL_CONVEYOR_BELT_2_MIDDLE,
2268 EL_CONVEYOR_BELT_2_RIGHT,
2269 EL_CONVEYOR_BELT_3_LEFT,
2270 EL_CONVEYOR_BELT_3_MIDDLE,
2271 EL_CONVEYOR_BELT_3_RIGHT,
2272 EL_CONVEYOR_BELT_4_LEFT,
2273 EL_CONVEYOR_BELT_4_MIDDLE,
2274 EL_CONVEYOR_BELT_4_RIGHT,
2278 static int ep_belt_active[] =
2280 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2281 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2282 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2283 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2284 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2285 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2286 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2287 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2288 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2289 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2290 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2291 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2295 static int ep_belt_switch[] =
2297 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2298 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2299 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2300 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2301 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2302 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2303 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2304 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2305 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2306 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2307 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2308 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2312 static int ep_tube[] =
2319 EL_TUBE_HORIZONTAL_UP,
2320 EL_TUBE_HORIZONTAL_DOWN,
2322 EL_TUBE_VERTICAL_LEFT,
2323 EL_TUBE_VERTICAL_RIGHT,
2328 static int ep_keygate[] =
2349 static int ep_amoeboid[] =
2359 static int ep_amoebalive[] =
2368 static int ep_has_content[] =
2378 static int ep_active_bomb[] =
2381 EL_DYNABOMB_PLAYER_1_ACTIVE,
2382 EL_DYNABOMB_PLAYER_2_ACTIVE,
2383 EL_DYNABOMB_PLAYER_3_ACTIVE,
2384 EL_DYNABOMB_PLAYER_4_ACTIVE,
2385 EL_SP_DISK_RED_ACTIVE,
2389 static int ep_inactive[] =
2426 EL_INVISIBLE_STEELWALL,
2434 EL_WALL_EMERALD_YELLOW,
2435 EL_DYNABOMB_INCREASE_NUMBER,
2436 EL_DYNABOMB_INCREASE_SIZE,
2437 EL_DYNABOMB_INCREASE_POWER,
2441 EL_SOKOBAN_FIELD_EMPTY,
2442 EL_SOKOBAN_FIELD_FULL,
2443 EL_WALL_EMERALD_RED,
2444 EL_WALL_EMERALD_PURPLE,
2445 EL_ACID_POOL_TOPLEFT,
2446 EL_ACID_POOL_TOPRIGHT,
2447 EL_ACID_POOL_BOTTOMLEFT,
2448 EL_ACID_POOL_BOTTOM,
2449 EL_ACID_POOL_BOTTOMRIGHT,
2453 EL_BD_MAGIC_WALL_DEAD,
2454 EL_AMOEBA_TO_DIAMOND,
2462 EL_SP_GRAVITY_PORT_RIGHT,
2463 EL_SP_GRAVITY_PORT_DOWN,
2464 EL_SP_GRAVITY_PORT_LEFT,
2465 EL_SP_GRAVITY_PORT_UP,
2466 EL_SP_PORT_HORIZONTAL,
2467 EL_SP_PORT_VERTICAL,
2478 EL_SP_HARDWARE_GRAY,
2479 EL_SP_HARDWARE_GREEN,
2480 EL_SP_HARDWARE_BLUE,
2482 EL_SP_HARDWARE_YELLOW,
2483 EL_SP_HARDWARE_BASE_1,
2484 EL_SP_HARDWARE_BASE_2,
2485 EL_SP_HARDWARE_BASE_3,
2486 EL_SP_HARDWARE_BASE_4,
2487 EL_SP_HARDWARE_BASE_5,
2488 EL_SP_HARDWARE_BASE_6,
2489 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2490 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2491 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2492 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2493 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2494 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2495 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2496 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2497 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2498 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2499 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2500 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2501 EL_SIGN_EXCLAMATION,
2502 EL_SIGN_RADIOACTIVITY,
2513 EL_STEELWALL_SLIPPERY,
2533 } element_properties[] =
2535 { ep_diggable, EP_DIGGABLE },
2536 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2537 { ep_dont_run_into, EP_DONT_RUN_INTO },
2538 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2539 { ep_dont_touch, EP_DONT_TOUCH },
2540 { ep_indestructible, EP_INDESTRUCTIBLE },
2541 { ep_slippery, EP_SLIPPERY },
2542 { ep_can_change, EP_CAN_CHANGE },
2543 { ep_can_move, EP_CAN_MOVE },
2544 { ep_can_fall, EP_CAN_FALL },
2545 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2546 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2547 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2548 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2549 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2550 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2551 { ep_walkable_over, EP_WALKABLE_OVER },
2552 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2553 { ep_walkable_under, EP_WALKABLE_UNDER },
2554 { ep_passable_over, EP_PASSABLE_OVER },
2555 { ep_passable_inside, EP_PASSABLE_INSIDE },
2556 { ep_passable_under, EP_PASSABLE_UNDER },
2557 { ep_pushable, EP_PUSHABLE },
2559 { ep_can_be_crumbled, EP_CAN_BE_CRUMBLED },
2561 { ep_player, EP_PLAYER },
2562 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2563 { ep_switchable, EP_SWITCHABLE },
2564 { ep_bd_element, EP_BD_ELEMENT },
2565 { ep_sp_element, EP_SP_ELEMENT },
2566 { ep_sb_element, EP_SB_ELEMENT },
2568 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2569 { ep_food_penguin, EP_FOOD_PENGUIN },
2570 { ep_food_pig, EP_FOOD_PIG },
2571 { ep_historic_wall, EP_HISTORIC_WALL },
2572 { ep_historic_solid, EP_HISTORIC_SOLID },
2573 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2574 { ep_belt, EP_BELT },
2575 { ep_belt_active, EP_BELT_ACTIVE },
2576 { ep_belt_switch, EP_BELT_SWITCH },
2577 { ep_tube, EP_TUBE },
2578 { ep_keygate, EP_KEYGATE },
2579 { ep_amoeboid, EP_AMOEBOID },
2580 { ep_amoebalive, EP_AMOEBALIVE },
2581 { ep_has_content, EP_HAS_CONTENT },
2582 { ep_active_bomb, EP_ACTIVE_BOMB },
2583 { ep_inactive, EP_INACTIVE },
2588 static int copy_properties[][5] =
2592 EL_BUG_LEFT, EL_BUG_RIGHT,
2593 EL_BUG_UP, EL_BUG_DOWN
2597 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2598 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2602 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2603 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2607 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2608 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2612 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2613 EL_PACMAN_UP, EL_PACMAN_DOWN
2623 /* always start with reliable default values (element has no properties) */
2624 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2625 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2626 SET_PROPERTY(i, j, FALSE);
2628 /* set all base element properties from above array definitions */
2629 for (i=0; element_properties[i].elements != NULL; i++)
2630 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2631 SET_PROPERTY((element_properties[i].elements)[j],
2632 element_properties[i].property, TRUE);
2634 /* copy properties to some elements that are only stored in level file */
2635 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2636 for (j=0; copy_properties[j][0] != -1; j++)
2637 if (HAS_PROPERTY(copy_properties[j][0], i))
2638 for (k=1; k<=4; k++)
2639 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2642 void InitElementPropertiesEngine(int engine_version)
2645 static int active_properties[] =
2650 EP_DONT_COLLIDE_WITH,
2654 EP_CAN_PASS_MAGIC_WALL,
2659 EP_CAN_EXPLODE_BY_FIRE,
2672 EP_EM_SLIPPERY_WALL,
2677 static int no_wall_properties[] =
2680 EP_COLLECTIBLE_ONLY,
2682 EP_DONT_COLLIDE_WITH,
2685 EP_CAN_SMASH_PLAYER,
2686 EP_CAN_SMASH_ENEMIES,
2687 EP_CAN_SMASH_EVERYTHING,
2694 EP_FOOD_DARK_YAMYAM,
2710 InitElementPropertiesStatic();
2713 /* set all special, combined or engine dependent element properties */
2714 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2717 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2718 SET_PROPERTY(i, j, FALSE);
2721 /* ---------- INACTIVE ------------------------------------------------- */
2722 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2723 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2725 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2726 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2727 IS_WALKABLE_INSIDE(i) ||
2728 IS_WALKABLE_UNDER(i)));
2730 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2731 IS_PASSABLE_INSIDE(i) ||
2732 IS_PASSABLE_UNDER(i)));
2734 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2735 IS_PASSABLE_OVER(i)));
2737 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2738 IS_PASSABLE_INSIDE(i)));
2740 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2741 IS_PASSABLE_UNDER(i)));
2743 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2746 /* ---------- COLLECTIBLE ---------------------------------------------- */
2747 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2750 /* ---------- SNAPPABLE ------------------------------------------------ */
2751 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2752 IS_COLLECTIBLE(i) ||
2756 /* ---------- WALL ----------------------------------------------------- */
2757 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2759 for (j=0; no_wall_properties[j] != -1; j++)
2760 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2761 i >= EL_FIRST_RUNTIME_UNREAL)
2762 SET_PROPERTY(i, EP_WALL, FALSE);
2764 if (IS_HISTORIC_WALL(i))
2765 SET_PROPERTY(i, EP_WALL, TRUE);
2767 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2768 if (engine_version < VERSION_IDENT(2,2,0))
2769 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2771 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2773 !IS_COLLECTIBLE(i)));
2775 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2777 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2778 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2780 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2781 IS_INDESTRUCTIBLE(i)));
2783 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2785 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2786 else if (engine_version < VERSION_IDENT(2,2,0))
2787 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2789 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2790 !IS_WALKABLE_OVER(i) &&
2791 !IS_WALKABLE_UNDER(i)));
2793 if (IS_CUSTOM_ELEMENT(i))
2795 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2797 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2798 if (DONT_COLLIDE_WITH(i))
2799 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2801 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2802 if (CAN_SMASH_EVERYTHING(i))
2803 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2804 if (CAN_SMASH_ENEMIES(i))
2805 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2808 /* ---------- CAN_SMASH ------------------------------------------------ */
2809 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2810 CAN_SMASH_ENEMIES(i) ||
2811 CAN_SMASH_EVERYTHING(i)));
2813 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2814 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2815 CAN_EXPLODE_SMASHED(i) ||
2816 CAN_EXPLODE_IMPACT(i)));
2818 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2819 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2820 !CAN_EXPLODE_1X1(i)));
2822 /* ---------- CAN_BE_CRUMBLED ------------------------------------------ */
2823 SET_PROPERTY(i, EP_CAN_BE_CRUMBLED,
2824 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2827 if (CAN_BE_CRUMBLED(i))
2828 printf("::: '%s' can be crumbled [%d]\n",
2829 element_info[i].token_name,
2830 element_info[i].crumbled[ACTION_DEFAULT]);
2835 /* determine inactive elements (used for engine main loop optimization) */
2836 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2838 boolean active = FALSE;
2840 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2842 if (HAS_PROPERTY(i, j))
2848 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2853 /* dynamically adjust element properties according to game engine version */
2855 static int ep_em_slippery_wall[] =
2860 EL_EXPANDABLE_WALL_HORIZONTAL,
2861 EL_EXPANDABLE_WALL_VERTICAL,
2862 EL_EXPANDABLE_WALL_ANY,
2866 /* special EM style gems behaviour */
2867 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2868 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2869 level.em_slippery_gems);
2871 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2872 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2873 (level.em_slippery_gems &&
2874 engine_version > VERSION_IDENT(2,0,1)));
2878 /* dynamically adjust element properties according to game engine version */
2880 if (engine_version < RELEASE_IDENT(2,2,0,7))
2883 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2885 int element = EL_CUSTOM_START + i;
2887 element_info[element].push_delay_fixed = 2;
2888 element_info[element].push_delay_random = 8;
2894 static void InitGlobal()
2896 global.autoplay_leveldir = NULL;
2898 global.frames_per_second = 0;
2899 global.fps_slowdown = FALSE;
2900 global.fps_slowdown_factor = 1;
2903 void Execute_Command(char *command)
2905 if (strcmp(command, "print graphicsinfo.conf") == 0)
2909 printf("# You can configure additional/alternative image files here.\n");
2910 printf("# (The images below are default and therefore commented out.)\n");
2912 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2914 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2917 for (i=0; image_config[i].token != NULL; i++)
2919 getFormattedSetupEntry(image_config[i].token,
2920 image_config[i].value));
2924 else if (strcmp(command, "print soundsinfo.conf") == 0)
2928 printf("# You can configure additional/alternative sound files here.\n");
2929 printf("# (The sounds below are default and therefore commented out.)\n");
2931 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2933 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2936 for (i=0; sound_config[i].token != NULL; i++)
2938 getFormattedSetupEntry(sound_config[i].token,
2939 sound_config[i].value));
2943 else if (strcmp(command, "print musicinfo.conf") == 0)
2945 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2947 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2949 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2953 else if (strncmp(command, "dump level ", 11) == 0)
2955 char *filename = &command[11];
2957 if (access(filename, F_OK) != 0)
2958 Error(ERR_EXIT, "cannot open file '%s'", filename);
2960 LoadLevelFromFilename(&level, filename);
2965 else if (strncmp(command, "dump tape ", 10) == 0)
2967 char *filename = &command[10];
2969 if (access(filename, F_OK) != 0)
2970 Error(ERR_EXIT, "cannot open file '%s'", filename);
2972 LoadTapeFromFilename(filename);
2977 else if (strncmp(command, "autoplay ", 9) == 0)
2979 char *str_copy = getStringCopy(&command[9]);
2980 char *str_ptr = strchr(str_copy, ' ');
2982 global.autoplay_leveldir = str_copy;
2983 global.autoplay_level_nr = -1;
2985 if (str_ptr != NULL)
2987 *str_ptr++ = '\0'; /* terminate leveldir string */
2988 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
2993 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
2997 static void InitSetup()
2999 LoadSetup(); /* global setup info */
3001 /* set some options from setup file */
3003 if (setup.options.verbose)
3004 options.verbose = TRUE;
3007 static void InitPlayerInfo()
3011 /* choose default local player */
3012 local_player = &stored_player[0];
3014 for (i=0; i<MAX_PLAYERS; i++)
3015 stored_player[i].connected = FALSE;
3017 local_player->connected = TRUE;
3020 static void InitArtworkInfo()
3025 static char *get_string_in_brackets(char *string)
3027 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3029 sprintf(string_in_brackets, "[%s]", string);
3031 return string_in_brackets;
3035 static char *get_element_class_token(int element)
3037 char *element_class_name = element_info[element].class_name;
3038 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3040 sprintf(element_class_token, "[%s]", element_class_name);
3042 return element_class_token;
3045 static char *get_action_class_token(int action)
3047 char *action_class_name = &element_action_info[action].suffix[1];
3048 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3050 sprintf(action_class_token, "[%s]", action_class_name);
3052 return action_class_token;
3056 static void InitArtworkConfig()
3058 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3059 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3060 static char *action_id_suffix[NUM_ACTIONS + 1];
3061 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3062 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3063 static char *dummy[1] = { NULL };
3064 static char *ignore_generic_tokens[] =
3070 static char **ignore_image_tokens, **ignore_sound_tokens;
3071 int num_ignore_generic_tokens;
3072 int num_ignore_image_tokens, num_ignore_sound_tokens;
3075 /* dynamically determine list of generic tokens to be ignored */
3076 num_ignore_generic_tokens = 0;
3077 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3078 num_ignore_generic_tokens++;
3080 /* dynamically determine list of image tokens to be ignored */
3081 num_ignore_image_tokens = num_ignore_generic_tokens;
3082 for (i=0; image_config_vars[i].token != NULL; i++)
3083 num_ignore_image_tokens++;
3084 ignore_image_tokens =
3085 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3086 for (i=0; i < num_ignore_generic_tokens; i++)
3087 ignore_image_tokens[i] = ignore_generic_tokens[i];
3088 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3089 ignore_image_tokens[num_ignore_generic_tokens + i] =
3090 image_config_vars[i].token;
3091 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3093 /* dynamically determine list of sound tokens to be ignored */
3094 num_ignore_sound_tokens = num_ignore_generic_tokens;
3095 ignore_sound_tokens =
3096 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3097 for (i=0; i < num_ignore_generic_tokens; i++)
3098 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3099 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3101 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3102 image_id_prefix[i] = element_info[i].token_name;
3103 for (i=0; i<NUM_FONTS; i++)
3104 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3105 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3107 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3108 sound_id_prefix[i] = element_info[i].token_name;
3109 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3110 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3111 get_string_in_brackets(element_info[i].class_name);
3112 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3114 for (i=0; i<NUM_ACTIONS; i++)
3115 action_id_suffix[i] = element_action_info[i].suffix;
3116 action_id_suffix[NUM_ACTIONS] = NULL;
3118 for (i=0; i<NUM_DIRECTIONS; i++)
3119 direction_id_suffix[i] = element_direction_info[i].suffix;
3120 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3122 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3123 special_id_suffix[i] = special_suffix_info[i].suffix;
3124 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3126 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3127 image_id_prefix, action_id_suffix, direction_id_suffix,
3128 special_id_suffix, ignore_image_tokens);
3129 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3130 sound_id_prefix, action_id_suffix, dummy,
3131 special_id_suffix, ignore_sound_tokens);
3134 static void InitMixer()
3142 char *filename_font_initial = NULL;
3143 Bitmap *bitmap_font_initial = NULL;
3146 /* determine settings for initial font (for displaying startup messages) */
3147 for (i=0; image_config[i].token != NULL; i++)
3149 for (j=0; j < NUM_INITIAL_FONTS; j++)
3151 char font_token[128];
3154 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3155 len_font_token = strlen(font_token);
3157 if (strcmp(image_config[i].token, font_token) == 0)
3158 filename_font_initial = image_config[i].value;
3159 else if (strlen(image_config[i].token) > len_font_token &&
3160 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3162 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3163 font_initial[j].src_x = atoi(image_config[i].value);
3164 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3165 font_initial[j].src_y = atoi(image_config[i].value);
3166 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3167 font_initial[j].width = atoi(image_config[i].value);
3168 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3169 font_initial[j].height = atoi(image_config[i].value);
3174 for (j=0; j < NUM_INITIAL_FONTS; j++)
3176 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3177 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3180 if (filename_font_initial == NULL) /* should not happen */
3181 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3183 /* create additional image buffers for double-buffering */
3184 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3185 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3187 /* initialize screen properties */
3188 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3189 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3191 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3192 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3193 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3195 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3197 for (j=0; j < NUM_INITIAL_FONTS; j++)
3198 font_initial[j].bitmap = bitmap_font_initial;
3200 InitFontGraphicInfo();
3202 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3203 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3205 DrawInitText("Loading graphics:", 120, FC_GREEN);
3207 InitTileClipmasks();
3210 void InitGfxBackground()
3214 drawto = backbuffer;
3215 fieldbuffer = bitmap_db_field;
3216 SetDrawtoField(DRAW_BACKBUFFER);
3218 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3219 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3220 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3221 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3223 for (x=0; x<MAX_BUF_XSIZE; x++)
3224 for (y=0; y<MAX_BUF_YSIZE; y++)
3227 redraw_mask = REDRAW_ALL;
3230 static void InitLevelInfo()
3232 LoadLevelInfo(); /* global level info */
3233 LoadLevelSetup_LastSeries(); /* last played series info */
3234 LoadLevelSetup_SeriesInfo(); /* last played level info */
3237 void InitLevelArtworkInfo()
3239 LoadLevelArtworkInfo();
3242 static void InitImages()
3245 setLevelArtworkDir(artwork.gfx_first);
3249 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3250 leveldir_current->identifier,
3251 artwork.gfx_current_identifier,
3252 artwork.gfx_current->identifier,
3253 leveldir_current->graphics_set,
3254 leveldir_current->graphics_path);
3257 ReloadCustomImages();
3259 LoadCustomElementDescriptions();
3260 LoadSpecialMenuDesignSettings();
3262 ReinitializeGraphics();
3265 static void InitSound(char *identifier)
3267 if (identifier == NULL)
3268 identifier = artwork.snd_current->identifier;
3271 /* set artwork path to send it to the sound server process */
3272 setLevelArtworkDir(artwork.snd_first);
3275 InitReloadCustomSounds(identifier);
3276 ReinitializeSounds();
3279 static void InitMusic(char *identifier)
3281 if (identifier == NULL)
3282 identifier = artwork.mus_current->identifier;
3285 /* set artwork path to send it to the sound server process */
3286 setLevelArtworkDir(artwork.mus_first);
3289 InitReloadCustomMusic(identifier);
3290 ReinitializeMusic();
3293 void InitNetworkServer()
3295 #if defined(PLATFORM_UNIX)
3299 if (!options.network)
3302 #if defined(PLATFORM_UNIX)
3303 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3305 if (!ConnectToServer(options.server_host, options.server_port))
3306 Error(ERR_EXIT, "cannot connect to network game server");
3308 SendToServer_PlayerName(setup.player_name);
3309 SendToServer_ProtocolVersion();
3312 SendToServer_NrWanted(nr_wanted);
3316 static char *getNewArtworkIdentifier(int type)
3318 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3319 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3320 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3321 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3322 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3323 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3324 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3325 char *leveldir_identifier = leveldir_current->identifier;
3327 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3328 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3330 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3332 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3333 char *artwork_current_identifier;
3334 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3336 /* leveldir_current may be invalid (level group, parent link) */
3337 if (!validLevelSeries(leveldir_current))
3340 /* 1st step: determine artwork set to be activated in descending order:
3341 --------------------------------------------------------------------
3342 1. setup artwork (when configured to override everything else)
3343 2. artwork set configured in "levelinfo.conf" of current level set
3344 (artwork in level directory will have priority when loading later)
3345 3. artwork in level directory (stored in artwork sub-directory)
3346 4. setup artwork (currently configured in setup menu) */
3348 if (setup_override_artwork)
3349 artwork_current_identifier = setup_artwork_set;
3350 else if (leveldir_artwork_set != NULL)
3351 artwork_current_identifier = leveldir_artwork_set;
3352 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3353 artwork_current_identifier = leveldir_identifier;
3355 artwork_current_identifier = setup_artwork_set;
3358 /* 2nd step: check if it is really needed to reload artwork set
3359 ------------------------------------------------------------ */
3362 if (type == ARTWORK_TYPE_GRAPHICS)
3363 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3364 artwork_new_identifier,
3365 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3366 artwork_current_identifier,
3367 leveldir_current->graphics_set,
3368 leveldir_current->identifier);
3371 /* ---------- reload if level set and also artwork set has changed ------- */
3372 if (leveldir_current_identifier[type] != leveldir_identifier &&
3373 (last_has_level_artwork_set[type] || has_level_artwork_set))
3374 artwork_new_identifier = artwork_current_identifier;
3376 leveldir_current_identifier[type] = leveldir_identifier;
3377 last_has_level_artwork_set[type] = has_level_artwork_set;
3380 if (type == ARTWORK_TYPE_GRAPHICS)
3381 printf("::: 1: '%s'\n", artwork_new_identifier);
3384 /* ---------- reload if "override artwork" setting has changed ----------- */
3385 if (last_override_level_artwork[type] != setup_override_artwork)
3386 artwork_new_identifier = artwork_current_identifier;
3388 last_override_level_artwork[type] = setup_override_artwork;
3391 if (type == ARTWORK_TYPE_GRAPHICS)
3392 printf("::: 2: '%s'\n", artwork_new_identifier);
3395 /* ---------- reload if current artwork identifier has changed ----------- */
3396 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3397 artwork_current_identifier) != 0)
3398 artwork_new_identifier = artwork_current_identifier;
3400 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3403 if (type == ARTWORK_TYPE_GRAPHICS)
3404 printf("::: 3: '%s'\n", artwork_new_identifier);
3407 /* ---------- do not reload directly after starting ---------------------- */
3408 if (!initialized[type])
3409 artwork_new_identifier = NULL;
3411 initialized[type] = TRUE;
3414 if (type == ARTWORK_TYPE_GRAPHICS)
3415 printf("::: 4: '%s'\n", artwork_new_identifier);
3419 if (type == ARTWORK_TYPE_GRAPHICS)
3420 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3421 artwork.gfx_current_identifier, artwork_current_identifier,
3422 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3423 artwork_new_identifier);
3426 return artwork_new_identifier;
3429 void ReloadCustomArtwork()
3431 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3432 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3433 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3434 boolean redraw_screen = FALSE;
3436 if (gfx_new_identifier != NULL)
3439 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3440 artwork.gfx_current_identifier,
3442 artwork.gfx_current->identifier,
3443 leveldir_current->graphics_set);
3446 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3451 printf("... '%s'\n",
3452 leveldir_current->graphics_set);
3455 FreeTileClipmasks();
3456 InitTileClipmasks();
3458 redraw_screen = TRUE;
3461 if (snd_new_identifier != NULL)
3463 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3465 InitSound(snd_new_identifier);
3467 redraw_screen = TRUE;
3470 if (mus_new_identifier != NULL)
3472 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3474 InitMusic(mus_new_identifier);
3476 redraw_screen = TRUE;
3481 InitGfxBackground();
3483 /* force redraw of (open or closed) door graphics */
3484 SetDoorState(DOOR_OPEN_ALL);
3485 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3489 void KeyboardAutoRepeatOffUnlessAutoplay()
3491 if (global.autoplay_leveldir == NULL)
3492 KeyboardAutoRepeatOff();
3496 /* ========================================================================= */
3498 /* ========================================================================= */
3502 InitGlobal(); /* initialize some global variables */
3504 if (options.execute_command)
3505 Execute_Command(options.execute_command);
3507 if (options.serveronly)
3509 #if defined(PLATFORM_UNIX)
3510 NetworkServer(options.server_port, options.serveronly);
3512 Error(ERR_WARN, "networking only supported in Unix version");
3514 exit(0); /* never reached */
3520 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3521 InitArtworkConfig(); /* needed before forking sound child process */
3526 InitRND(NEW_RANDOMIZE);
3527 InitSimpleRND(NEW_RANDOMIZE);
3532 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3535 InitEventFilter(FilterMouseMotionEvents);
3537 InitElementPropertiesStatic();
3538 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3543 InitLevelArtworkInfo();
3545 InitImages(); /* needs to know current level directory */
3546 InitSound(NULL); /* needs to know current level directory */
3547 InitMusic(NULL); /* needs to know current level directory */
3549 InitGfxBackground();
3551 if (global.autoplay_leveldir)
3557 game_status = GAME_MODE_MAIN;
3561 InitNetworkServer();
3564 void CloseAllAndExit(int exit_value)
3569 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3572 FreeTileClipmasks();
3574 CloseVideoDisplay();
3575 ClosePlatformDependentStuff();