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++)
559 graphic = element_info[i].graphic[act];
560 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
561 element_info[i].graphic[act] = -1;
563 graphic = element_info[i].crumbled[act];
564 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
565 element_info[i].crumbled[act] = -1;
567 for (dir=0; dir<NUM_DIRECTIONS; dir++)
569 graphic = element_info[i].direction_graphic[act][dir];
570 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
571 element_info[i].direction_graphic[act][dir] = -1;
573 graphic = element_info[i].direction_crumbled[act][dir];
574 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
575 element_info[i].direction_crumbled[act][dir] = -1;
581 /* now set all '-1' values to element specific default values */
582 for (i=0; i<MAX_NUM_ELEMENTS; i++)
584 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
585 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
586 int default_direction_graphic[NUM_DIRECTIONS];
587 int default_direction_crumbled[NUM_DIRECTIONS];
589 if (default_graphic == -1)
590 default_graphic = IMG_CHAR_QUESTION;
591 if (default_crumbled == -1)
592 default_crumbled = IMG_EMPTY;
594 for (dir=0; dir<NUM_DIRECTIONS; dir++)
596 default_direction_graphic[dir] =
597 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
598 default_direction_crumbled[dir] =
599 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
601 if (default_direction_graphic[dir] == -1)
602 default_direction_graphic[dir] = default_graphic;
603 if (default_direction_crumbled[dir] == -1)
604 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));
613 /* generic default action graphic (defined by "[default]" directive) */
614 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
615 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
617 /* look for special default action graphic (classic game specific) */
618 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
619 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
620 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
621 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
622 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
623 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
625 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
626 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
627 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
628 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
629 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
630 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
632 if (default_action_graphic == -1)
633 default_action_graphic = default_graphic;
634 if (default_action_crumbled == -1)
635 default_action_crumbled = default_crumbled;
637 for (dir=0; dir<NUM_DIRECTIONS; dir++)
639 int default_action_direction_graphic = element_info[i].graphic[act];
640 int default_action_direction_crumbled = element_info[i].crumbled[act];
642 /* no graphic for current action -- use default direction graphic */
643 if (default_action_direction_graphic == -1)
644 default_action_direction_graphic =
645 (act_remove ? IMG_EMPTY : default_direction_graphic[dir]);
646 if (default_action_direction_crumbled == -1)
647 default_action_direction_crumbled =
648 (act_remove ? IMG_EMPTY : default_direction_crumbled[dir]);
650 if (element_info[i].direction_graphic[act][dir] == -1)
651 element_info[i].direction_graphic[act][dir] =
652 default_action_direction_graphic;
653 if (element_info[i].direction_crumbled[act][dir] == -1)
654 element_info[i].direction_crumbled[act][dir] =
655 default_action_direction_crumbled;
658 /* no graphic for this specific action -- use default action graphic */
659 if (element_info[i].graphic[act] == -1)
660 element_info[i].graphic[act] =
661 (act_remove ? IMG_EMPTY : default_action_graphic);
662 if (element_info[i].crumbled[act] == -1)
663 element_info[i].crumbled[act] =
664 (act_remove ? IMG_EMPTY : default_action_crumbled);
672 for (i=0; i<MAX_NUM_ELEMENTS; i++)
673 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
674 i != EL_CHAR_QUESTION)
675 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
676 element_info[i].token_name, i);
682 void InitElementSpecialGraphicInfo()
684 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
685 int num_property_mappings = getImageListPropertyMappingSize();
688 /* always start with reliable default values */
689 for (i=0; i < MAX_NUM_ELEMENTS; i++)
690 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
691 element_info[i].special_graphic[j] =
692 element_info[i].graphic[ACTION_DEFAULT];
694 /* initialize special element/graphic mapping from static configuration */
695 for (i=0; element_to_special_graphic[i].element > -1; i++)
697 int element = element_to_special_graphic[i].element;
698 int special = element_to_special_graphic[i].special;
699 int graphic = element_to_special_graphic[i].graphic;
700 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
701 boolean special_redefined = getImageListEntry(graphic)->redefined;
703 /* if the base graphic ("emerald", for example) has been redefined,
704 but not the special graphic ("emerald.EDITOR", for example), do not
705 use an existing (in this case considered obsolete) special graphic
706 anymore, but use the automatically created (down-scaled) graphic */
707 if (base_redefined && !special_redefined)
710 element_info[element].special_graphic[special] = graphic;
713 /* initialize special element/graphic mapping from dynamic configuration */
714 for (i=0; i < num_property_mappings; i++)
716 int element = property_mapping[i].base_index;
717 int special = property_mapping[i].ext3_index;
718 int graphic = property_mapping[i].artwork_index;
720 if (element >= MAX_NUM_ELEMENTS)
723 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
724 element_info[element].special_graphic[special] = graphic;
728 /* now set all undefined/invalid graphics to default */
729 for (i=0; i < MAX_NUM_ELEMENTS; i++)
730 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
731 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
732 element_info[i].special_graphic[j] =
733 element_info[i].graphic[ACTION_DEFAULT];
737 static int get_element_from_token(char *token)
741 for (i=0; i < MAX_NUM_ELEMENTS; i++)
742 if (strcmp(element_info[i].token_name, token) == 0)
748 static void set_graphic_parameters(int graphic, char **parameter_raw)
750 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
751 int parameter[NUM_GFX_ARGS];
752 int anim_frames_per_row = 1, anim_frames_per_col = 1;
753 int anim_frames_per_line = 1;
756 /* get integer values from string parameters */
757 for (i=0; i < NUM_GFX_ARGS; i++)
760 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
761 image_config_suffix[i].type);
763 if (image_config_suffix[i].type == TYPE_TOKEN)
764 parameter[i] = get_element_from_token(parameter_raw[i]);
767 graphic_info[graphic].bitmap = src_bitmap;
769 /* start with reliable default values */
770 graphic_info[graphic].src_x = 0;
771 graphic_info[graphic].src_y = 0;
772 graphic_info[graphic].width = TILEX;
773 graphic_info[graphic].height = TILEY;
774 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
775 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
776 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
777 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
778 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
780 /* optional x and y tile position of animation frame sequence */
781 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
782 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
783 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
784 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
786 /* optional x and y pixel position of animation frame sequence */
787 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
788 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
789 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
790 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
792 /* optional width and height of each animation frame */
793 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
794 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
795 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
796 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
800 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
801 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
804 /* correct x or y offset dependent of vertical or horizontal frame order */
805 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
807 graphic_info[graphic].offset_y =
808 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
809 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
810 anim_frames_per_line = anim_frames_per_col;
812 else /* frames are ordered horizontally */
814 graphic_info[graphic].offset_x =
815 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
816 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
817 anim_frames_per_line = anim_frames_per_row;
820 /* optionally, the x and y offset of frames can be specified directly */
821 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
822 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
823 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
824 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
826 /* automatically determine correct number of frames, if not defined */
827 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
828 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
829 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
830 graphic_info[graphic].anim_frames = anim_frames_per_row;
831 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
832 graphic_info[graphic].anim_frames = anim_frames_per_col;
834 graphic_info[graphic].anim_frames = 1;
836 graphic_info[graphic].anim_frames_per_line =
837 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
838 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
840 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
841 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
842 graphic_info[graphic].anim_delay = 1;
844 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
845 if (graphic_info[graphic].anim_frames == 1)
846 graphic_info[graphic].anim_mode = ANIM_NONE;
848 /* automatically determine correct start frame, if not defined */
849 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
850 graphic_info[graphic].anim_start_frame = 0;
851 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
852 graphic_info[graphic].anim_start_frame =
853 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
855 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
857 /* animation synchronized with global frame counter, not move position */
858 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
860 /* optional element for cloning crumble graphics */
861 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
862 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
864 /* optional element for cloning digging graphics */
865 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
866 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
868 /* optional border size for "crumbling" diggable graphics */
869 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
870 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
872 /* this is only used for toon animations */
873 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
874 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
876 /* this is only used for drawing font characters */
877 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
878 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
880 /* this is only used for drawing envelope graphics */
881 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
884 static void InitGraphicInfo()
886 int fallback_graphic = IMG_CHAR_EXCLAM;
887 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
888 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
889 int num_images = getImageListSize();
892 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
893 static boolean clipmasks_initialized = FALSE;
895 XGCValues clip_gc_values;
896 unsigned long clip_gc_valuemask;
897 GC copy_clipmask_gc = None;
900 if (graphic_info != NULL)
903 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
906 printf("::: graphic_info: %d entries\n", num_images);
909 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
910 if (clipmasks_initialized)
912 for (i=0; i<num_images; i++)
914 if (graphic_info[i].clip_mask)
915 XFreePixmap(display, graphic_info[i].clip_mask);
916 if (graphic_info[i].clip_gc)
917 XFreeGC(display, graphic_info[i].clip_gc);
919 graphic_info[i].clip_mask = None;
920 graphic_info[i].clip_gc = None;
925 for (i=0; i<num_images; i++)
927 struct FileInfo *image = getImageListEntry(i);
930 int first_frame, last_frame;
933 printf("::: image: '%s' [%d]\n", image->token, i);
937 printf("::: image # %d: '%s' ['%s']\n",
939 getTokenFromImageID(i));
942 set_graphic_parameters(i, image->parameter);
944 /* now check if no animation frames are outside of the loaded image */
946 if (graphic_info[i].bitmap == NULL)
947 continue; /* skip check for optional images that are undefined */
950 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
951 if (src_x < 0 || src_y < 0 ||
952 src_x + TILEX > src_bitmap->width ||
953 src_y + TILEY > src_bitmap->height)
955 Error(ERR_RETURN_LINE, "-");
956 Error(ERR_RETURN, "warning: error found in config file:");
957 Error(ERR_RETURN, "- config file: '%s'",
958 getImageConfigFilename());
959 Error(ERR_RETURN, "- config token: '%s'",
960 getTokenFromImageID(i));
961 Error(ERR_RETURN, "- image file: '%s'",
962 src_bitmap->source_filename);
964 "error: first animation frame out of bounds (%d, %d)",
966 Error(ERR_RETURN, "custom graphic rejected for this element/action");
968 if (i == fallback_graphic)
969 Error(ERR_EXIT, "fatal error: no fallback graphic available");
971 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
972 Error(ERR_RETURN_LINE, "-");
974 set_graphic_parameters(i, fallback_image->default_parameter);
975 graphic_info[i].bitmap = fallback_bitmap;
978 last_frame = graphic_info[i].anim_frames - 1;
979 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
980 if (src_x < 0 || src_y < 0 ||
981 src_x + TILEX > src_bitmap->width ||
982 src_y + TILEY > src_bitmap->height)
984 Error(ERR_RETURN_LINE, "-");
985 Error(ERR_RETURN, "warning: error found in config file:");
986 Error(ERR_RETURN, "- config file: '%s'",
987 getImageConfigFilename());
988 Error(ERR_RETURN, "- config token: '%s'",
989 getTokenFromImageID(i));
990 Error(ERR_RETURN, "- image file: '%s'",
991 src_bitmap->source_filename);
993 "error: last animation frame (%d) out of bounds (%d, %d)",
994 last_frame, src_x, src_y);
995 Error(ERR_RETURN, "custom graphic rejected for this element/action");
997 if (i == fallback_graphic)
998 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1000 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1001 Error(ERR_RETURN_LINE, "-");
1003 set_graphic_parameters(i, fallback_image->default_parameter);
1004 graphic_info[i].bitmap = fallback_bitmap;
1007 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1008 /* currently we need only a tile clip mask from the first frame */
1009 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1011 if (copy_clipmask_gc == None)
1013 clip_gc_values.graphics_exposures = False;
1014 clip_gc_valuemask = GCGraphicsExposures;
1015 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1016 clip_gc_valuemask, &clip_gc_values);
1019 graphic_info[i].clip_mask =
1020 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1022 src_pixmap = src_bitmap->clip_mask;
1023 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1024 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1026 clip_gc_values.graphics_exposures = False;
1027 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1028 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1030 graphic_info[i].clip_gc =
1031 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1035 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1036 if (copy_clipmask_gc)
1037 XFreeGC(display, copy_clipmask_gc);
1039 clipmasks_initialized = TRUE;
1043 static void InitElementSoundInfo()
1045 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1046 int num_property_mappings = getSoundListPropertyMappingSize();
1049 /* set values to -1 to identify later as "uninitialized" values */
1050 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1051 for (act=0; act < NUM_ACTIONS; act++)
1052 element_info[i].sound[act] = -1;
1054 /* initialize element/sound mapping from static configuration */
1055 for (i=0; element_to_sound[i].element > -1; i++)
1057 int element = element_to_sound[i].element;
1058 int action = element_to_sound[i].action;
1059 int sound = element_to_sound[i].sound;
1060 boolean is_class = element_to_sound[i].is_class;
1063 action = ACTION_DEFAULT;
1066 element_info[element].sound[action] = sound;
1068 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1069 if (strcmp(element_info[j].class_name,
1070 element_info[element].class_name) == 0)
1071 element_info[j].sound[action] = sound;
1074 /* initialize element class/sound mapping from dynamic configuration */
1075 for (i=0; i < num_property_mappings; i++)
1077 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1078 int action = property_mapping[i].ext1_index;
1079 int sound = property_mapping[i].artwork_index;
1081 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1085 action = ACTION_DEFAULT;
1087 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1088 if (strcmp(element_info[j].class_name,
1089 element_info[element_class].class_name) == 0)
1090 element_info[j].sound[action] = sound;
1093 /* initialize element/sound mapping from dynamic configuration */
1094 for (i=0; i < num_property_mappings; i++)
1096 int element = property_mapping[i].base_index;
1097 int action = property_mapping[i].ext1_index;
1098 int sound = property_mapping[i].artwork_index;
1100 if (element >= MAX_NUM_ELEMENTS)
1104 action = ACTION_DEFAULT;
1106 element_info[element].sound[action] = sound;
1109 /* now set all '-1' values to element specific default values */
1110 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1112 for (act=0; act < NUM_ACTIONS; act++)
1114 /* generic default action sound (defined by "[default]" directive) */
1115 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1117 /* look for special default action sound (classic game specific) */
1118 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1119 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1120 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1121 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1122 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1123 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1125 /* look for element specific default sound (independent from action) */
1126 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1127 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1129 /* no sound for this specific action -- use default action sound */
1130 if (element_info[i].sound[act] == -1)
1131 element_info[i].sound[act] = default_action_sound;
1136 static void set_sound_parameters(int sound, char **parameter_raw)
1138 int parameter[NUM_SND_ARGS];
1141 /* get integer values from string parameters */
1142 for (i=0; i < NUM_SND_ARGS; i++)
1144 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1145 sound_config_suffix[i].type);
1147 /* explicit loop mode setting in configuration overrides default value */
1148 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1149 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1152 static void InitSoundInfo()
1155 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1156 int num_property_mappings = getSoundListPropertyMappingSize();
1158 int *sound_effect_properties;
1159 int num_sounds = getSoundListSize();
1162 if (sound_info != NULL)
1165 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1166 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1168 /* initialize sound effect for all elements to "no sound" */
1169 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1170 for (j=0; j<NUM_ACTIONS; j++)
1171 element_info[i].sound[j] = SND_UNDEFINED;
1173 for (i=0; i<num_sounds; i++)
1175 struct FileInfo *sound = getSoundListEntry(i);
1176 int len_effect_text = strlen(sound->token);
1178 sound_effect_properties[i] = ACTION_OTHER;
1179 sound_info[i].loop = FALSE;
1182 printf("::: sound %d: '%s'\n", i, sound->token);
1185 /* determine all loop sounds and identify certain sound classes */
1187 for (j=0; element_action_info[j].suffix; j++)
1189 int len_action_text = strlen(element_action_info[j].suffix);
1191 if (len_action_text < len_effect_text &&
1192 strcmp(&sound->token[len_effect_text - len_action_text],
1193 element_action_info[j].suffix) == 0)
1195 sound_effect_properties[i] = element_action_info[j].value;
1196 sound_info[i].loop = element_action_info[j].is_loop_sound;
1203 if (strcmp(sound->token, "custom_42") == 0)
1204 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1207 /* associate elements and some selected sound actions */
1209 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1211 if (element_info[j].class_name)
1213 int len_class_text = strlen(element_info[j].class_name);
1215 if (len_class_text + 1 < len_effect_text &&
1216 strncmp(sound->token,
1217 element_info[j].class_name, len_class_text) == 0 &&
1218 sound->token[len_class_text] == '.')
1220 int sound_action_value = sound_effect_properties[i];
1222 element_info[j].sound[sound_action_value] = i;
1227 set_sound_parameters(i, sound->parameter);
1230 free(sound_effect_properties);
1233 /* !!! now handled in InitElementSoundInfo() !!! */
1234 /* initialize element/sound mapping from dynamic configuration */
1235 for (i=0; i < num_property_mappings; i++)
1237 int element = property_mapping[i].base_index;
1238 int action = property_mapping[i].ext1_index;
1239 int sound = property_mapping[i].artwork_index;
1242 action = ACTION_DEFAULT;
1244 printf("::: %d: %d, %d, %d ['%s']\n",
1245 i, element, action, sound, element_info[element].token_name);
1247 element_info[element].sound[action] = sound;
1254 int element = EL_CUSTOM_11;
1257 while (element_action_info[j].suffix)
1259 printf("element %d, sound action '%s' == %d\n",
1260 element, element_action_info[j].suffix,
1261 element_info[element].sound[j]);
1266 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1272 int element = EL_SAND;
1273 int sound_action = ACTION_DIGGING;
1276 while (element_action_info[j].suffix)
1278 if (element_action_info[j].value == sound_action)
1279 printf("element %d, sound action '%s' == %d\n",
1280 element, element_action_info[j].suffix,
1281 element_info[element].sound[sound_action]);
1288 static void ReinitializeGraphics()
1290 InitGraphicInfo(); /* graphic properties mapping */
1291 InitElementGraphicInfo(); /* element game graphic mapping */
1292 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1294 InitElementSmallImages(); /* create editor and preview images */
1295 InitFontGraphicInfo(); /* initialize text drawing functions */
1297 SetMainBackgroundImage(IMG_BACKGROUND);
1298 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1304 static void ReinitializeSounds()
1306 InitSoundInfo(); /* sound properties mapping */
1307 InitElementSoundInfo(); /* element game sound mapping */
1309 InitPlaySoundLevel(); /* internal game sound settings */
1312 static void ReinitializeMusic()
1314 /* currently nothing to do */
1317 void InitElementPropertiesStatic()
1319 static int ep_diggable[] =
1324 EL_SP_BUGGY_BASE_ACTIVATING,
1327 EL_INVISIBLE_SAND_ACTIVE,
1329 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1333 EL_SP_BUGGY_BASE_ACTIVE,
1338 static int ep_collectible_only[] =
1355 EL_DYNABOMB_INCREASE_NUMBER,
1356 EL_DYNABOMB_INCREASE_SIZE,
1357 EL_DYNABOMB_INCREASE_POWER,
1374 static int ep_dont_run_into[] =
1376 /* same elements as in 'ep_dont_touch' */
1382 /* same elements as in 'ep_dont_collide_with' */
1394 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1396 EL_SP_BUGGY_BASE_ACTIVE,
1403 static int ep_dont_collide_with[] =
1405 /* same elements as in 'ep_dont_touch' */
1421 static int ep_dont_touch[] =
1430 static int ep_indestructible[] =
1434 EL_ACID_POOL_TOPLEFT,
1435 EL_ACID_POOL_TOPRIGHT,
1436 EL_ACID_POOL_BOTTOMLEFT,
1437 EL_ACID_POOL_BOTTOM,
1438 EL_ACID_POOL_BOTTOMRIGHT,
1439 EL_SP_HARDWARE_GRAY,
1440 EL_SP_HARDWARE_GREEN,
1441 EL_SP_HARDWARE_BLUE,
1443 EL_SP_HARDWARE_YELLOW,
1444 EL_SP_HARDWARE_BASE_1,
1445 EL_SP_HARDWARE_BASE_2,
1446 EL_SP_HARDWARE_BASE_3,
1447 EL_SP_HARDWARE_BASE_4,
1448 EL_SP_HARDWARE_BASE_5,
1449 EL_SP_HARDWARE_BASE_6,
1450 EL_INVISIBLE_STEELWALL,
1451 EL_INVISIBLE_STEELWALL_ACTIVE,
1452 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1453 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1454 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1455 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1456 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1457 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1458 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1459 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1460 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1461 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1462 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1463 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1465 EL_LIGHT_SWITCH_ACTIVE,
1466 EL_SIGN_EXCLAMATION,
1467 EL_SIGN_RADIOACTIVITY,
1478 EL_STEELWALL_SLIPPERY,
1501 EL_SWITCHGATE_OPENING,
1502 EL_SWITCHGATE_CLOSED,
1503 EL_SWITCHGATE_CLOSING,
1505 EL_SWITCHGATE_SWITCH_UP,
1506 EL_SWITCHGATE_SWITCH_DOWN,
1509 EL_TIMEGATE_OPENING,
1511 EL_TIMEGATE_CLOSING,
1514 EL_TIMEGATE_SWITCH_ACTIVE,
1519 EL_TUBE_VERTICAL_LEFT,
1520 EL_TUBE_VERTICAL_RIGHT,
1521 EL_TUBE_HORIZONTAL_UP,
1522 EL_TUBE_HORIZONTAL_DOWN,
1530 static int ep_slippery[] =
1544 EL_ROBOT_WHEEL_ACTIVE,
1550 EL_ACID_POOL_TOPLEFT,
1551 EL_ACID_POOL_TOPRIGHT,
1561 EL_STEELWALL_SLIPPERY,
1567 static int ep_can_change[] =
1572 static int ep_can_move[] =
1594 static int ep_can_fall[] =
1609 EL_BD_MAGIC_WALL_FULL,
1622 static int ep_can_smash_player[] =
1647 static int ep_can_smash_enemies[] =
1655 static int ep_can_smash_everything[] =
1663 static int ep_can_explode_by_fire[] =
1665 /* same elements as in 'ep_can_explode_impact' */
1670 /* same elements as in 'ep_can_explode_smashed' */
1679 EL_DYNABOMB_PLAYER_1_ACTIVE,
1680 EL_DYNABOMB_PLAYER_2_ACTIVE,
1681 EL_DYNABOMB_PLAYER_3_ACTIVE,
1682 EL_DYNABOMB_PLAYER_4_ACTIVE,
1683 EL_DYNABOMB_INCREASE_NUMBER,
1684 EL_DYNABOMB_INCREASE_SIZE,
1685 EL_DYNABOMB_INCREASE_POWER,
1686 EL_SP_DISK_RED_ACTIVE,
1696 static int ep_can_explode_smashed[] =
1698 /* same elements as in 'ep_can_explode_impact' */
1711 static int ep_can_explode_impact[] =
1719 static int ep_walkable_over[] =
1723 EL_SOKOBAN_FIELD_EMPTY,
1740 static int ep_walkable_inside[] =
1745 EL_TUBE_VERTICAL_LEFT,
1746 EL_TUBE_VERTICAL_RIGHT,
1747 EL_TUBE_HORIZONTAL_UP,
1748 EL_TUBE_HORIZONTAL_DOWN,
1756 static int ep_walkable_under[] =
1761 static int ep_passable_over[] =
1776 static int ep_passable_inside[] =
1782 EL_SP_PORT_HORIZONTAL,
1783 EL_SP_PORT_VERTICAL,
1785 EL_SP_GRAVITY_PORT_LEFT,
1786 EL_SP_GRAVITY_PORT_RIGHT,
1787 EL_SP_GRAVITY_PORT_UP,
1788 EL_SP_GRAVITY_PORT_DOWN,
1792 static int ep_passable_under[] =
1797 static int ep_pushable[] =
1809 EL_SOKOBAN_FIELD_FULL,
1816 static int ep_can_be_crumbled[] =
1825 static int ep_player[] =
1835 static int ep_can_pass_magic_wall[] =
1848 static int ep_switchable[] =
1852 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1853 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1854 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1855 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1856 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1857 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1858 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1859 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1860 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1861 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1862 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1863 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1864 EL_SWITCHGATE_SWITCH_UP,
1865 EL_SWITCHGATE_SWITCH_DOWN,
1867 EL_LIGHT_SWITCH_ACTIVE,
1869 EL_BALLOON_SWITCH_LEFT,
1870 EL_BALLOON_SWITCH_RIGHT,
1871 EL_BALLOON_SWITCH_UP,
1872 EL_BALLOON_SWITCH_DOWN,
1873 EL_BALLOON_SWITCH_ANY,
1879 static int ep_bd_element[] =
1908 static int ep_sp_element[] =
1910 /* should always be valid */
1919 EL_SP_HARDWARE_GRAY,
1927 EL_SP_GRAVITY_PORT_RIGHT,
1928 EL_SP_GRAVITY_PORT_DOWN,
1929 EL_SP_GRAVITY_PORT_LEFT,
1930 EL_SP_GRAVITY_PORT_UP,
1935 EL_SP_PORT_VERTICAL,
1936 EL_SP_PORT_HORIZONTAL,
1942 EL_SP_HARDWARE_BASE_1,
1943 EL_SP_HARDWARE_GREEN,
1944 EL_SP_HARDWARE_BLUE,
1946 EL_SP_HARDWARE_YELLOW,
1947 EL_SP_HARDWARE_BASE_2,
1948 EL_SP_HARDWARE_BASE_3,
1949 EL_SP_HARDWARE_BASE_4,
1950 EL_SP_HARDWARE_BASE_5,
1951 EL_SP_HARDWARE_BASE_6,
1954 /* additional elements that appeared in newer Supaplex levels */
1956 /* more than one murphy in a level results in an inactive clone */
1958 /* runtime elements*/
1959 EL_SP_DISK_RED_ACTIVE,
1960 EL_SP_TERMINAL_ACTIVE,
1961 EL_SP_BUGGY_BASE_ACTIVATING,
1962 EL_SP_BUGGY_BASE_ACTIVE,
1966 static int ep_sb_element[] =
1971 EL_SOKOBAN_FIELD_EMPTY,
1972 EL_SOKOBAN_FIELD_FULL,
1974 EL_INVISIBLE_STEELWALL,
1978 static int ep_gem[] =
1989 static int ep_food_dark_yamyam[] =
2016 static int ep_food_penguin[] =
2029 static int ep_food_pig[] =
2040 static int ep_historic_wall[] =
2065 EL_EXPANDABLE_WALL_HORIZONTAL,
2066 EL_EXPANDABLE_WALL_VERTICAL,
2067 EL_EXPANDABLE_WALL_ANY,
2068 EL_EXPANDABLE_WALL_GROWING,
2075 EL_SP_HARDWARE_GRAY,
2076 EL_SP_HARDWARE_GREEN,
2077 EL_SP_HARDWARE_BLUE,
2079 EL_SP_HARDWARE_YELLOW,
2080 EL_SP_HARDWARE_BASE_1,
2081 EL_SP_HARDWARE_BASE_2,
2082 EL_SP_HARDWARE_BASE_3,
2083 EL_SP_HARDWARE_BASE_4,
2084 EL_SP_HARDWARE_BASE_5,
2085 EL_SP_HARDWARE_BASE_6,
2087 EL_SP_TERMINAL_ACTIVE,
2090 EL_INVISIBLE_STEELWALL,
2091 EL_INVISIBLE_STEELWALL_ACTIVE,
2093 EL_INVISIBLE_WALL_ACTIVE,
2094 EL_STEELWALL_SLIPPERY,
2110 static int ep_historic_solid[] =
2114 EL_EXPANDABLE_WALL_HORIZONTAL,
2115 EL_EXPANDABLE_WALL_VERTICAL,
2116 EL_EXPANDABLE_WALL_ANY,
2129 EL_QUICKSAND_FILLING,
2130 EL_QUICKSAND_EMPTYING,
2132 EL_MAGIC_WALL_ACTIVE,
2133 EL_MAGIC_WALL_EMPTYING,
2134 EL_MAGIC_WALL_FILLING,
2138 EL_BD_MAGIC_WALL_ACTIVE,
2139 EL_BD_MAGIC_WALL_EMPTYING,
2140 EL_BD_MAGIC_WALL_FULL,
2141 EL_BD_MAGIC_WALL_FILLING,
2142 EL_BD_MAGIC_WALL_DEAD,
2151 EL_SP_TERMINAL_ACTIVE,
2155 EL_INVISIBLE_WALL_ACTIVE,
2156 EL_SWITCHGATE_SWITCH_UP,
2157 EL_SWITCHGATE_SWITCH_DOWN,
2159 EL_TIMEGATE_SWITCH_ACTIVE,
2171 /* the following elements are a direct copy of "indestructible" elements,
2172 except "EL_ACID", which is "indestructible", but not "solid"! */
2177 EL_ACID_POOL_TOPLEFT,
2178 EL_ACID_POOL_TOPRIGHT,
2179 EL_ACID_POOL_BOTTOMLEFT,
2180 EL_ACID_POOL_BOTTOM,
2181 EL_ACID_POOL_BOTTOMRIGHT,
2182 EL_SP_HARDWARE_GRAY,
2183 EL_SP_HARDWARE_GREEN,
2184 EL_SP_HARDWARE_BLUE,
2186 EL_SP_HARDWARE_YELLOW,
2187 EL_SP_HARDWARE_BASE_1,
2188 EL_SP_HARDWARE_BASE_2,
2189 EL_SP_HARDWARE_BASE_3,
2190 EL_SP_HARDWARE_BASE_4,
2191 EL_SP_HARDWARE_BASE_5,
2192 EL_SP_HARDWARE_BASE_6,
2193 EL_INVISIBLE_STEELWALL,
2194 EL_INVISIBLE_STEELWALL_ACTIVE,
2195 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2196 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2197 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2198 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2199 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2200 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2201 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2202 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2203 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2204 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2205 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2206 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2208 EL_LIGHT_SWITCH_ACTIVE,
2209 EL_SIGN_EXCLAMATION,
2210 EL_SIGN_RADIOACTIVITY,
2221 EL_STEELWALL_SLIPPERY,
2244 EL_SWITCHGATE_OPENING,
2245 EL_SWITCHGATE_CLOSED,
2246 EL_SWITCHGATE_CLOSING,
2248 EL_TIMEGATE_OPENING,
2250 EL_TIMEGATE_CLOSING,
2254 EL_TUBE_VERTICAL_LEFT,
2255 EL_TUBE_VERTICAL_RIGHT,
2256 EL_TUBE_HORIZONTAL_UP,
2257 EL_TUBE_HORIZONTAL_DOWN,
2265 static int ep_classic_enemy[] =
2281 static int ep_belt[] =
2283 EL_CONVEYOR_BELT_1_LEFT,
2284 EL_CONVEYOR_BELT_1_MIDDLE,
2285 EL_CONVEYOR_BELT_1_RIGHT,
2286 EL_CONVEYOR_BELT_2_LEFT,
2287 EL_CONVEYOR_BELT_2_MIDDLE,
2288 EL_CONVEYOR_BELT_2_RIGHT,
2289 EL_CONVEYOR_BELT_3_LEFT,
2290 EL_CONVEYOR_BELT_3_MIDDLE,
2291 EL_CONVEYOR_BELT_3_RIGHT,
2292 EL_CONVEYOR_BELT_4_LEFT,
2293 EL_CONVEYOR_BELT_4_MIDDLE,
2294 EL_CONVEYOR_BELT_4_RIGHT,
2298 static int ep_belt_active[] =
2300 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2301 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2302 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2303 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2304 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2305 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2306 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2307 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2308 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2309 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2310 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2311 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2315 static int ep_belt_switch[] =
2317 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2318 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2319 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2320 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2321 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2322 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2323 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2324 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2325 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2326 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2327 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2328 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2332 static int ep_tube[] =
2339 EL_TUBE_HORIZONTAL_UP,
2340 EL_TUBE_HORIZONTAL_DOWN,
2342 EL_TUBE_VERTICAL_LEFT,
2343 EL_TUBE_VERTICAL_RIGHT,
2348 static int ep_keygate[] =
2369 static int ep_amoeboid[] =
2379 static int ep_amoebalive[] =
2388 static int ep_has_content[] =
2398 static int ep_active_bomb[] =
2401 EL_DYNABOMB_PLAYER_1_ACTIVE,
2402 EL_DYNABOMB_PLAYER_2_ACTIVE,
2403 EL_DYNABOMB_PLAYER_3_ACTIVE,
2404 EL_DYNABOMB_PLAYER_4_ACTIVE,
2405 EL_SP_DISK_RED_ACTIVE,
2409 static int ep_inactive[] =
2446 EL_INVISIBLE_STEELWALL,
2454 EL_WALL_EMERALD_YELLOW,
2455 EL_DYNABOMB_INCREASE_NUMBER,
2456 EL_DYNABOMB_INCREASE_SIZE,
2457 EL_DYNABOMB_INCREASE_POWER,
2461 EL_SOKOBAN_FIELD_EMPTY,
2462 EL_SOKOBAN_FIELD_FULL,
2463 EL_WALL_EMERALD_RED,
2464 EL_WALL_EMERALD_PURPLE,
2465 EL_ACID_POOL_TOPLEFT,
2466 EL_ACID_POOL_TOPRIGHT,
2467 EL_ACID_POOL_BOTTOMLEFT,
2468 EL_ACID_POOL_BOTTOM,
2469 EL_ACID_POOL_BOTTOMRIGHT,
2473 EL_BD_MAGIC_WALL_DEAD,
2474 EL_AMOEBA_TO_DIAMOND,
2482 EL_SP_GRAVITY_PORT_RIGHT,
2483 EL_SP_GRAVITY_PORT_DOWN,
2484 EL_SP_GRAVITY_PORT_LEFT,
2485 EL_SP_GRAVITY_PORT_UP,
2486 EL_SP_PORT_HORIZONTAL,
2487 EL_SP_PORT_VERTICAL,
2498 EL_SP_HARDWARE_GRAY,
2499 EL_SP_HARDWARE_GREEN,
2500 EL_SP_HARDWARE_BLUE,
2502 EL_SP_HARDWARE_YELLOW,
2503 EL_SP_HARDWARE_BASE_1,
2504 EL_SP_HARDWARE_BASE_2,
2505 EL_SP_HARDWARE_BASE_3,
2506 EL_SP_HARDWARE_BASE_4,
2507 EL_SP_HARDWARE_BASE_5,
2508 EL_SP_HARDWARE_BASE_6,
2509 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2510 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2511 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2512 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2513 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2514 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2515 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2516 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2517 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2518 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2519 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2520 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2521 EL_SIGN_EXCLAMATION,
2522 EL_SIGN_RADIOACTIVITY,
2533 EL_STEELWALL_SLIPPERY,
2553 } element_properties[] =
2555 { ep_diggable, EP_DIGGABLE },
2556 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2557 { ep_dont_run_into, EP_DONT_RUN_INTO },
2558 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2559 { ep_dont_touch, EP_DONT_TOUCH },
2560 { ep_indestructible, EP_INDESTRUCTIBLE },
2561 { ep_slippery, EP_SLIPPERY },
2562 { ep_can_change, EP_CAN_CHANGE },
2563 { ep_can_move, EP_CAN_MOVE },
2564 { ep_can_fall, EP_CAN_FALL },
2565 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2566 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2567 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2568 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2569 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2570 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2571 { ep_walkable_over, EP_WALKABLE_OVER },
2572 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2573 { ep_walkable_under, EP_WALKABLE_UNDER },
2574 { ep_passable_over, EP_PASSABLE_OVER },
2575 { ep_passable_inside, EP_PASSABLE_INSIDE },
2576 { ep_passable_under, EP_PASSABLE_UNDER },
2577 { ep_pushable, EP_PUSHABLE },
2579 { ep_can_be_crumbled, EP_CAN_BE_CRUMBLED },
2581 { ep_player, EP_PLAYER },
2582 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2583 { ep_switchable, EP_SWITCHABLE },
2584 { ep_bd_element, EP_BD_ELEMENT },
2585 { ep_sp_element, EP_SP_ELEMENT },
2586 { ep_sb_element, EP_SB_ELEMENT },
2588 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2589 { ep_food_penguin, EP_FOOD_PENGUIN },
2590 { ep_food_pig, EP_FOOD_PIG },
2591 { ep_historic_wall, EP_HISTORIC_WALL },
2592 { ep_historic_solid, EP_HISTORIC_SOLID },
2593 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2594 { ep_belt, EP_BELT },
2595 { ep_belt_active, EP_BELT_ACTIVE },
2596 { ep_belt_switch, EP_BELT_SWITCH },
2597 { ep_tube, EP_TUBE },
2598 { ep_keygate, EP_KEYGATE },
2599 { ep_amoeboid, EP_AMOEBOID },
2600 { ep_amoebalive, EP_AMOEBALIVE },
2601 { ep_has_content, EP_HAS_CONTENT },
2602 { ep_active_bomb, EP_ACTIVE_BOMB },
2603 { ep_inactive, EP_INACTIVE },
2608 static int copy_properties[][5] =
2612 EL_BUG_LEFT, EL_BUG_RIGHT,
2613 EL_BUG_UP, EL_BUG_DOWN
2617 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2618 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2622 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2623 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2627 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2628 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2632 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2633 EL_PACMAN_UP, EL_PACMAN_DOWN
2643 /* always start with reliable default values (element has no properties) */
2644 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2645 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2646 SET_PROPERTY(i, j, FALSE);
2648 /* set all base element properties from above array definitions */
2649 for (i=0; element_properties[i].elements != NULL; i++)
2650 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2651 SET_PROPERTY((element_properties[i].elements)[j],
2652 element_properties[i].property, TRUE);
2654 /* copy properties to some elements that are only stored in level file */
2655 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2656 for (j=0; copy_properties[j][0] != -1; j++)
2657 if (HAS_PROPERTY(copy_properties[j][0], i))
2658 for (k=1; k<=4; k++)
2659 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2662 void InitElementPropertiesEngine(int engine_version)
2665 static int active_properties[] =
2670 EP_DONT_COLLIDE_WITH,
2674 EP_CAN_PASS_MAGIC_WALL,
2679 EP_CAN_EXPLODE_BY_FIRE,
2692 EP_EM_SLIPPERY_WALL,
2697 static int no_wall_properties[] =
2700 EP_COLLECTIBLE_ONLY,
2702 EP_DONT_COLLIDE_WITH,
2705 EP_CAN_SMASH_PLAYER,
2706 EP_CAN_SMASH_ENEMIES,
2707 EP_CAN_SMASH_EVERYTHING,
2714 EP_FOOD_DARK_YAMYAM,
2730 InitElementPropertiesStatic();
2733 /* set all special, combined or engine dependent element properties */
2734 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2737 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2738 SET_PROPERTY(i, j, FALSE);
2741 /* ---------- INACTIVE ------------------------------------------------- */
2742 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2743 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2745 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2746 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2747 IS_WALKABLE_INSIDE(i) ||
2748 IS_WALKABLE_UNDER(i)));
2750 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2751 IS_PASSABLE_INSIDE(i) ||
2752 IS_PASSABLE_UNDER(i)));
2754 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2755 IS_PASSABLE_OVER(i)));
2757 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2758 IS_PASSABLE_INSIDE(i)));
2760 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2761 IS_PASSABLE_UNDER(i)));
2763 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2766 /* ---------- COLLECTIBLE ---------------------------------------------- */
2767 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2770 /* ---------- SNAPPABLE ------------------------------------------------ */
2771 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2772 IS_COLLECTIBLE(i) ||
2776 /* ---------- WALL ----------------------------------------------------- */
2777 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2779 for (j=0; no_wall_properties[j] != -1; j++)
2780 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2781 i >= EL_FIRST_RUNTIME_UNREAL)
2782 SET_PROPERTY(i, EP_WALL, FALSE);
2784 if (IS_HISTORIC_WALL(i))
2785 SET_PROPERTY(i, EP_WALL, TRUE);
2787 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2788 if (engine_version < VERSION_IDENT(2,2,0))
2789 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2791 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2793 !IS_COLLECTIBLE(i)));
2795 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2797 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2798 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2800 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2801 IS_INDESTRUCTIBLE(i)));
2803 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2805 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2806 else if (engine_version < VERSION_IDENT(2,2,0))
2807 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2809 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2810 !IS_WALKABLE_OVER(i) &&
2811 !IS_WALKABLE_UNDER(i)));
2813 if (IS_CUSTOM_ELEMENT(i))
2815 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2817 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2818 if (DONT_COLLIDE_WITH(i))
2819 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2821 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2822 if (CAN_SMASH_EVERYTHING(i))
2823 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2824 if (CAN_SMASH_ENEMIES(i))
2825 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2828 /* ---------- CAN_SMASH ------------------------------------------------ */
2829 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2830 CAN_SMASH_ENEMIES(i) ||
2831 CAN_SMASH_EVERYTHING(i)));
2833 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2834 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2835 CAN_EXPLODE_SMASHED(i) ||
2836 CAN_EXPLODE_IMPACT(i)));
2838 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2839 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2840 !CAN_EXPLODE_1X1(i)));
2842 /* ---------- CAN_BE_CRUMBLED ------------------------------------------ */
2843 SET_PROPERTY(i, EP_CAN_BE_CRUMBLED,
2844 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2847 if (CAN_BE_CRUMBLED(i))
2848 printf("::: '%s' can be crumbled [%d]\n",
2849 element_info[i].token_name,
2850 element_info[i].crumbled[ACTION_DEFAULT]);
2853 /* ---------- CAN_CHANGE ----------------------------------------------- */
2854 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
2855 for (j=0; j < element_info[i].num_change_pages; j++)
2856 if (element_info[i].change_page[j].can_change)
2857 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
2861 /* determine inactive elements (used for engine main loop optimization) */
2862 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2864 boolean active = FALSE;
2866 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2868 if (HAS_PROPERTY(i, j))
2874 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2879 /* dynamically adjust element properties according to game engine version */
2881 static int ep_em_slippery_wall[] =
2886 EL_EXPANDABLE_WALL_HORIZONTAL,
2887 EL_EXPANDABLE_WALL_VERTICAL,
2888 EL_EXPANDABLE_WALL_ANY,
2892 /* special EM style gems behaviour */
2893 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2894 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2895 level.em_slippery_gems);
2897 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2898 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2899 (level.em_slippery_gems &&
2900 engine_version > VERSION_IDENT(2,0,1)));
2904 /* dynamically adjust element properties according to game engine version */
2906 if (engine_version < RELEASE_IDENT(2,2,0,7))
2909 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2911 int element = EL_CUSTOM_START + i;
2913 element_info[element].push_delay_fixed = 2;
2914 element_info[element].push_delay_random = 8;
2920 static void InitGlobal()
2922 global.autoplay_leveldir = NULL;
2924 global.frames_per_second = 0;
2925 global.fps_slowdown = FALSE;
2926 global.fps_slowdown_factor = 1;
2929 void Execute_Command(char *command)
2931 if (strcmp(command, "print graphicsinfo.conf") == 0)
2935 printf("# You can configure additional/alternative image files here.\n");
2936 printf("# (The images below are default and therefore commented out.)\n");
2938 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2940 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2943 for (i=0; image_config[i].token != NULL; i++)
2945 getFormattedSetupEntry(image_config[i].token,
2946 image_config[i].value));
2950 else if (strcmp(command, "print soundsinfo.conf") == 0)
2954 printf("# You can configure additional/alternative sound files here.\n");
2955 printf("# (The sounds below are default and therefore commented out.)\n");
2957 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2959 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2962 for (i=0; sound_config[i].token != NULL; i++)
2964 getFormattedSetupEntry(sound_config[i].token,
2965 sound_config[i].value));
2969 else if (strcmp(command, "print musicinfo.conf") == 0)
2971 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2973 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2975 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2979 else if (strncmp(command, "dump level ", 11) == 0)
2981 char *filename = &command[11];
2983 if (access(filename, F_OK) != 0)
2984 Error(ERR_EXIT, "cannot open file '%s'", filename);
2986 LoadLevelFromFilename(&level, filename);
2991 else if (strncmp(command, "dump tape ", 10) == 0)
2993 char *filename = &command[10];
2995 if (access(filename, F_OK) != 0)
2996 Error(ERR_EXIT, "cannot open file '%s'", filename);
2998 LoadTapeFromFilename(filename);
3003 else if (strncmp(command, "autoplay ", 9) == 0)
3005 char *str_copy = getStringCopy(&command[9]);
3006 char *str_ptr = strchr(str_copy, ' ');
3008 global.autoplay_leveldir = str_copy;
3009 global.autoplay_level_nr = -1;
3011 if (str_ptr != NULL)
3013 *str_ptr++ = '\0'; /* terminate leveldir string */
3014 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3019 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3023 static void InitSetup()
3025 LoadSetup(); /* global setup info */
3027 /* set some options from setup file */
3029 if (setup.options.verbose)
3030 options.verbose = TRUE;
3033 static void InitPlayerInfo()
3037 /* choose default local player */
3038 local_player = &stored_player[0];
3040 for (i=0; i<MAX_PLAYERS; i++)
3041 stored_player[i].connected = FALSE;
3043 local_player->connected = TRUE;
3046 static void InitArtworkInfo()
3051 static char *get_string_in_brackets(char *string)
3053 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3055 sprintf(string_in_brackets, "[%s]", string);
3057 return string_in_brackets;
3061 static char *get_element_class_token(int element)
3063 char *element_class_name = element_info[element].class_name;
3064 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3066 sprintf(element_class_token, "[%s]", element_class_name);
3068 return element_class_token;
3071 static char *get_action_class_token(int action)
3073 char *action_class_name = &element_action_info[action].suffix[1];
3074 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3076 sprintf(action_class_token, "[%s]", action_class_name);
3078 return action_class_token;
3082 static void InitArtworkConfig()
3084 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3085 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3086 static char *action_id_suffix[NUM_ACTIONS + 1];
3087 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3088 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3089 static char *dummy[1] = { NULL };
3090 static char *ignore_generic_tokens[] =
3096 static char **ignore_image_tokens, **ignore_sound_tokens;
3097 int num_ignore_generic_tokens;
3098 int num_ignore_image_tokens, num_ignore_sound_tokens;
3101 /* dynamically determine list of generic tokens to be ignored */
3102 num_ignore_generic_tokens = 0;
3103 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3104 num_ignore_generic_tokens++;
3106 /* dynamically determine list of image tokens to be ignored */
3107 num_ignore_image_tokens = num_ignore_generic_tokens;
3108 for (i=0; image_config_vars[i].token != NULL; i++)
3109 num_ignore_image_tokens++;
3110 ignore_image_tokens =
3111 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3112 for (i=0; i < num_ignore_generic_tokens; i++)
3113 ignore_image_tokens[i] = ignore_generic_tokens[i];
3114 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3115 ignore_image_tokens[num_ignore_generic_tokens + i] =
3116 image_config_vars[i].token;
3117 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3119 /* dynamically determine list of sound tokens to be ignored */
3120 num_ignore_sound_tokens = num_ignore_generic_tokens;
3121 ignore_sound_tokens =
3122 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3123 for (i=0; i < num_ignore_generic_tokens; i++)
3124 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3125 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3127 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3128 image_id_prefix[i] = element_info[i].token_name;
3129 for (i=0; i<NUM_FONTS; i++)
3130 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3131 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3133 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3134 sound_id_prefix[i] = element_info[i].token_name;
3135 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3136 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3137 get_string_in_brackets(element_info[i].class_name);
3138 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3140 for (i=0; i<NUM_ACTIONS; i++)
3141 action_id_suffix[i] = element_action_info[i].suffix;
3142 action_id_suffix[NUM_ACTIONS] = NULL;
3144 for (i=0; i<NUM_DIRECTIONS; i++)
3145 direction_id_suffix[i] = element_direction_info[i].suffix;
3146 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3148 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3149 special_id_suffix[i] = special_suffix_info[i].suffix;
3150 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3152 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3153 image_id_prefix, action_id_suffix, direction_id_suffix,
3154 special_id_suffix, ignore_image_tokens);
3155 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3156 sound_id_prefix, action_id_suffix, dummy,
3157 special_id_suffix, ignore_sound_tokens);
3160 static void InitMixer()
3168 char *filename_font_initial = NULL;
3169 Bitmap *bitmap_font_initial = NULL;
3172 /* determine settings for initial font (for displaying startup messages) */
3173 for (i=0; image_config[i].token != NULL; i++)
3175 for (j=0; j < NUM_INITIAL_FONTS; j++)
3177 char font_token[128];
3180 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3181 len_font_token = strlen(font_token);
3183 if (strcmp(image_config[i].token, font_token) == 0)
3184 filename_font_initial = image_config[i].value;
3185 else if (strlen(image_config[i].token) > len_font_token &&
3186 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3188 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3189 font_initial[j].src_x = atoi(image_config[i].value);
3190 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3191 font_initial[j].src_y = atoi(image_config[i].value);
3192 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3193 font_initial[j].width = atoi(image_config[i].value);
3194 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3195 font_initial[j].height = atoi(image_config[i].value);
3200 for (j=0; j < NUM_INITIAL_FONTS; j++)
3202 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3203 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3206 if (filename_font_initial == NULL) /* should not happen */
3207 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3209 /* create additional image buffers for double-buffering */
3210 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3211 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3213 /* initialize screen properties */
3214 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3215 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3217 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3218 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3219 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3221 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3223 for (j=0; j < NUM_INITIAL_FONTS; j++)
3224 font_initial[j].bitmap = bitmap_font_initial;
3226 InitFontGraphicInfo();
3228 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3229 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3231 DrawInitText("Loading graphics:", 120, FC_GREEN);
3233 InitTileClipmasks();
3236 void InitGfxBackground()
3240 drawto = backbuffer;
3241 fieldbuffer = bitmap_db_field;
3242 SetDrawtoField(DRAW_BACKBUFFER);
3244 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3245 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3246 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3247 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3249 for (x=0; x<MAX_BUF_XSIZE; x++)
3250 for (y=0; y<MAX_BUF_YSIZE; y++)
3253 redraw_mask = REDRAW_ALL;
3256 static void InitLevelInfo()
3258 LoadLevelInfo(); /* global level info */
3259 LoadLevelSetup_LastSeries(); /* last played series info */
3260 LoadLevelSetup_SeriesInfo(); /* last played level info */
3263 void InitLevelArtworkInfo()
3265 LoadLevelArtworkInfo();
3268 static void InitImages()
3271 setLevelArtworkDir(artwork.gfx_first);
3275 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3276 leveldir_current->identifier,
3277 artwork.gfx_current_identifier,
3278 artwork.gfx_current->identifier,
3279 leveldir_current->graphics_set,
3280 leveldir_current->graphics_path);
3283 ReloadCustomImages();
3285 LoadCustomElementDescriptions();
3286 LoadSpecialMenuDesignSettings();
3288 ReinitializeGraphics();
3291 static void InitSound(char *identifier)
3293 if (identifier == NULL)
3294 identifier = artwork.snd_current->identifier;
3297 /* set artwork path to send it to the sound server process */
3298 setLevelArtworkDir(artwork.snd_first);
3301 InitReloadCustomSounds(identifier);
3302 ReinitializeSounds();
3305 static void InitMusic(char *identifier)
3307 if (identifier == NULL)
3308 identifier = artwork.mus_current->identifier;
3311 /* set artwork path to send it to the sound server process */
3312 setLevelArtworkDir(artwork.mus_first);
3315 InitReloadCustomMusic(identifier);
3316 ReinitializeMusic();
3319 void InitNetworkServer()
3321 #if defined(PLATFORM_UNIX)
3325 if (!options.network)
3328 #if defined(PLATFORM_UNIX)
3329 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3331 if (!ConnectToServer(options.server_host, options.server_port))
3332 Error(ERR_EXIT, "cannot connect to network game server");
3334 SendToServer_PlayerName(setup.player_name);
3335 SendToServer_ProtocolVersion();
3338 SendToServer_NrWanted(nr_wanted);
3342 static char *getNewArtworkIdentifier(int type)
3344 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3345 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3346 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3347 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3348 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3349 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3350 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3351 char *leveldir_identifier = leveldir_current->identifier;
3353 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3354 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3356 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3358 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3359 char *artwork_current_identifier;
3360 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3362 /* leveldir_current may be invalid (level group, parent link) */
3363 if (!validLevelSeries(leveldir_current))
3366 /* 1st step: determine artwork set to be activated in descending order:
3367 --------------------------------------------------------------------
3368 1. setup artwork (when configured to override everything else)
3369 2. artwork set configured in "levelinfo.conf" of current level set
3370 (artwork in level directory will have priority when loading later)
3371 3. artwork in level directory (stored in artwork sub-directory)
3372 4. setup artwork (currently configured in setup menu) */
3374 if (setup_override_artwork)
3375 artwork_current_identifier = setup_artwork_set;
3376 else if (leveldir_artwork_set != NULL)
3377 artwork_current_identifier = leveldir_artwork_set;
3378 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3379 artwork_current_identifier = leveldir_identifier;
3381 artwork_current_identifier = setup_artwork_set;
3384 /* 2nd step: check if it is really needed to reload artwork set
3385 ------------------------------------------------------------ */
3388 if (type == ARTWORK_TYPE_GRAPHICS)
3389 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3390 artwork_new_identifier,
3391 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3392 artwork_current_identifier,
3393 leveldir_current->graphics_set,
3394 leveldir_current->identifier);
3397 /* ---------- reload if level set and also artwork set has changed ------- */
3398 if (leveldir_current_identifier[type] != leveldir_identifier &&
3399 (last_has_level_artwork_set[type] || has_level_artwork_set))
3400 artwork_new_identifier = artwork_current_identifier;
3402 leveldir_current_identifier[type] = leveldir_identifier;
3403 last_has_level_artwork_set[type] = has_level_artwork_set;
3406 if (type == ARTWORK_TYPE_GRAPHICS)
3407 printf("::: 1: '%s'\n", artwork_new_identifier);
3410 /* ---------- reload if "override artwork" setting has changed ----------- */
3411 if (last_override_level_artwork[type] != setup_override_artwork)
3412 artwork_new_identifier = artwork_current_identifier;
3414 last_override_level_artwork[type] = setup_override_artwork;
3417 if (type == ARTWORK_TYPE_GRAPHICS)
3418 printf("::: 2: '%s'\n", artwork_new_identifier);
3421 /* ---------- reload if current artwork identifier has changed ----------- */
3422 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3423 artwork_current_identifier) != 0)
3424 artwork_new_identifier = artwork_current_identifier;
3426 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3429 if (type == ARTWORK_TYPE_GRAPHICS)
3430 printf("::: 3: '%s'\n", artwork_new_identifier);
3433 /* ---------- do not reload directly after starting ---------------------- */
3434 if (!initialized[type])
3435 artwork_new_identifier = NULL;
3437 initialized[type] = TRUE;
3440 if (type == ARTWORK_TYPE_GRAPHICS)
3441 printf("::: 4: '%s'\n", artwork_new_identifier);
3445 if (type == ARTWORK_TYPE_GRAPHICS)
3446 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3447 artwork.gfx_current_identifier, artwork_current_identifier,
3448 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3449 artwork_new_identifier);
3452 return artwork_new_identifier;
3455 void ReloadCustomArtwork()
3457 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3458 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3459 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3460 boolean redraw_screen = FALSE;
3462 if (gfx_new_identifier != NULL)
3465 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3466 artwork.gfx_current_identifier,
3468 artwork.gfx_current->identifier,
3469 leveldir_current->graphics_set);
3472 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3477 printf("... '%s'\n",
3478 leveldir_current->graphics_set);
3481 FreeTileClipmasks();
3482 InitTileClipmasks();
3484 redraw_screen = TRUE;
3487 if (snd_new_identifier != NULL)
3489 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3491 InitSound(snd_new_identifier);
3493 redraw_screen = TRUE;
3496 if (mus_new_identifier != NULL)
3498 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3500 InitMusic(mus_new_identifier);
3502 redraw_screen = TRUE;
3507 InitGfxBackground();
3509 /* force redraw of (open or closed) door graphics */
3510 SetDoorState(DOOR_OPEN_ALL);
3511 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3515 void KeyboardAutoRepeatOffUnlessAutoplay()
3517 if (global.autoplay_leveldir == NULL)
3518 KeyboardAutoRepeatOff();
3522 /* ========================================================================= */
3524 /* ========================================================================= */
3528 InitGlobal(); /* initialize some global variables */
3530 if (options.execute_command)
3531 Execute_Command(options.execute_command);
3533 if (options.serveronly)
3535 #if defined(PLATFORM_UNIX)
3536 NetworkServer(options.server_port, options.serveronly);
3538 Error(ERR_WARN, "networking only supported in Unix version");
3540 exit(0); /* never reached */
3546 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3547 InitArtworkConfig(); /* needed before forking sound child process */
3552 InitRND(NEW_RANDOMIZE);
3553 InitSimpleRND(NEW_RANDOMIZE);
3558 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3561 InitEventFilter(FilterMouseMotionEvents);
3563 InitElementPropertiesStatic();
3564 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3569 InitLevelArtworkInfo();
3571 InitImages(); /* needs to know current level directory */
3572 InitSound(NULL); /* needs to know current level directory */
3573 InitMusic(NULL); /* needs to know current level directory */
3575 InitGfxBackground();
3577 if (global.autoplay_leveldir)
3583 game_status = GAME_MODE_MAIN;
3587 InitNetworkServer();
3590 void CloseAllAndExit(int exit_value)
3595 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3598 FreeTileClipmasks();
3600 CloseVideoDisplay();
3601 ClosePlatformDependentStuff();