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 */
779 /* optional x and y tile position of animation frame sequence */
780 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
781 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
782 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
783 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
785 /* optional x and y pixel position of animation frame sequence */
786 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
787 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
788 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
789 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
791 /* optional width and height of each animation frame */
792 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
793 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
794 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
795 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
799 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
800 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
803 /* correct x or y offset dependent of vertical or horizontal frame order */
804 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
806 graphic_info[graphic].offset_y =
807 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
808 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
809 anim_frames_per_line = anim_frames_per_col;
811 else /* frames are ordered horizontally */
813 graphic_info[graphic].offset_x =
814 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
815 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
816 anim_frames_per_line = anim_frames_per_row;
819 /* optionally, the x and y offset of frames can be specified directly */
820 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
821 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
822 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
823 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
825 /* automatically determine correct number of frames, if not defined */
826 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
827 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
828 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
829 graphic_info[graphic].anim_frames = anim_frames_per_row;
830 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
831 graphic_info[graphic].anim_frames = anim_frames_per_col;
833 graphic_info[graphic].anim_frames = 1;
835 graphic_info[graphic].anim_frames_per_line =
836 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
837 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
839 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
840 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
841 graphic_info[graphic].anim_delay = 1;
843 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
844 if (graphic_info[graphic].anim_frames == 1)
845 graphic_info[graphic].anim_mode = ANIM_NONE;
847 /* automatically determine correct start frame, if not defined */
848 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
849 graphic_info[graphic].anim_start_frame = 0;
850 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
851 graphic_info[graphic].anim_start_frame =
852 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
854 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
856 /* animation synchronized with global frame counter, not move position */
857 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
859 /* optional element for cloning crumble graphics */
860 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
861 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
863 /* optional element for cloning digging graphics */
864 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
865 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
867 /* this is only used for toon animations */
868 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
869 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
871 /* this is only used for drawing font characters */
872 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
873 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
876 static void InitGraphicInfo()
878 int fallback_graphic = IMG_CHAR_EXCLAM;
879 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
880 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
881 int num_images = getImageListSize();
884 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
885 static boolean clipmasks_initialized = FALSE;
887 XGCValues clip_gc_values;
888 unsigned long clip_gc_valuemask;
889 GC copy_clipmask_gc = None;
892 if (graphic_info != NULL)
895 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
898 printf("::: graphic_info: %d entries\n", num_images);
901 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
902 if (clipmasks_initialized)
904 for (i=0; i<num_images; i++)
906 if (graphic_info[i].clip_mask)
907 XFreePixmap(display, graphic_info[i].clip_mask);
908 if (graphic_info[i].clip_gc)
909 XFreeGC(display, graphic_info[i].clip_gc);
911 graphic_info[i].clip_mask = None;
912 graphic_info[i].clip_gc = None;
917 for (i=0; i<num_images; i++)
919 struct FileInfo *image = getImageListEntry(i);
922 int first_frame, last_frame;
925 printf("::: image: '%s' [%d]\n", image->token, i);
929 printf("::: image # %d: '%s' ['%s']\n",
931 getTokenFromImageID(i));
934 set_graphic_parameters(i, image->parameter);
936 /* now check if no animation frames are outside of the loaded image */
938 if (graphic_info[i].bitmap == NULL)
939 continue; /* skip check for optional images that are undefined */
942 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
943 if (src_x < 0 || src_y < 0 ||
944 src_x + TILEX > src_bitmap->width ||
945 src_y + TILEY > src_bitmap->height)
947 Error(ERR_RETURN_LINE, "-");
948 Error(ERR_RETURN, "warning: error found in config file:");
949 Error(ERR_RETURN, "- config file: '%s'",
950 getImageConfigFilename());
951 Error(ERR_RETURN, "- config token: '%s'",
952 getTokenFromImageID(i));
953 Error(ERR_RETURN, "- image file: '%s'",
954 src_bitmap->source_filename);
956 "error: first animation frame out of bounds (%d, %d)",
958 Error(ERR_RETURN, "custom graphic rejected for this element/action");
960 if (i == fallback_graphic)
961 Error(ERR_EXIT, "fatal error: no fallback graphic available");
963 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
964 Error(ERR_RETURN_LINE, "-");
966 set_graphic_parameters(i, fallback_image->default_parameter);
967 graphic_info[i].bitmap = fallback_bitmap;
970 last_frame = graphic_info[i].anim_frames - 1;
971 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
972 if (src_x < 0 || src_y < 0 ||
973 src_x + TILEX > src_bitmap->width ||
974 src_y + TILEY > src_bitmap->height)
976 Error(ERR_RETURN_LINE, "-");
977 Error(ERR_RETURN, "warning: error found in config file:");
978 Error(ERR_RETURN, "- config file: '%s'",
979 getImageConfigFilename());
980 Error(ERR_RETURN, "- config token: '%s'",
981 getTokenFromImageID(i));
982 Error(ERR_RETURN, "- image file: '%s'",
983 src_bitmap->source_filename);
985 "error: last animation frame (%d) out of bounds (%d, %d)",
986 last_frame, src_x, src_y);
987 Error(ERR_RETURN, "custom graphic rejected for this element/action");
989 if (i == fallback_graphic)
990 Error(ERR_EXIT, "fatal error: no fallback graphic available");
992 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
993 Error(ERR_RETURN_LINE, "-");
995 set_graphic_parameters(i, fallback_image->default_parameter);
996 graphic_info[i].bitmap = fallback_bitmap;
999 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1000 /* currently we need only a tile clip mask from the first frame */
1001 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1003 if (copy_clipmask_gc == None)
1005 clip_gc_values.graphics_exposures = False;
1006 clip_gc_valuemask = GCGraphicsExposures;
1007 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1008 clip_gc_valuemask, &clip_gc_values);
1011 graphic_info[i].clip_mask =
1012 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1014 src_pixmap = src_bitmap->clip_mask;
1015 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1016 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1018 clip_gc_values.graphics_exposures = False;
1019 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1020 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1022 graphic_info[i].clip_gc =
1023 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1027 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1028 if (copy_clipmask_gc)
1029 XFreeGC(display, copy_clipmask_gc);
1031 clipmasks_initialized = TRUE;
1035 static void InitElementSoundInfo()
1037 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1038 int num_property_mappings = getSoundListPropertyMappingSize();
1041 /* set values to -1 to identify later as "uninitialized" values */
1042 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1043 for (act=0; act < NUM_ACTIONS; act++)
1044 element_info[i].sound[act] = -1;
1046 /* initialize element/sound mapping from static configuration */
1047 for (i=0; element_to_sound[i].element > -1; i++)
1049 int element = element_to_sound[i].element;
1050 int action = element_to_sound[i].action;
1051 int sound = element_to_sound[i].sound;
1052 boolean is_class = element_to_sound[i].is_class;
1055 action = ACTION_DEFAULT;
1058 element_info[element].sound[action] = sound;
1060 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1061 if (strcmp(element_info[j].class_name,
1062 element_info[element].class_name) == 0)
1063 element_info[j].sound[action] = sound;
1066 /* initialize element class/sound mapping from dynamic configuration */
1067 for (i=0; i < num_property_mappings; i++)
1069 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1070 int action = property_mapping[i].ext1_index;
1071 int sound = property_mapping[i].artwork_index;
1073 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1077 action = ACTION_DEFAULT;
1079 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1080 if (strcmp(element_info[j].class_name,
1081 element_info[element_class].class_name) == 0)
1082 element_info[j].sound[action] = sound;
1085 /* initialize element/sound mapping from dynamic configuration */
1086 for (i=0; i < num_property_mappings; i++)
1088 int element = property_mapping[i].base_index;
1089 int action = property_mapping[i].ext1_index;
1090 int sound = property_mapping[i].artwork_index;
1092 if (element >= MAX_NUM_ELEMENTS)
1096 action = ACTION_DEFAULT;
1098 element_info[element].sound[action] = sound;
1101 /* now set all '-1' values to element specific default values */
1102 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1104 for (act=0; act < NUM_ACTIONS; act++)
1106 /* generic default action sound (defined by "[default]" directive) */
1107 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1109 /* look for special default action sound (classic game specific) */
1110 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1111 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1112 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1113 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1114 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1115 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1117 /* look for element specific default sound (independent from action) */
1118 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1119 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1121 /* no sound for this specific action -- use default action sound */
1122 if (element_info[i].sound[act] == -1)
1123 element_info[i].sound[act] = default_action_sound;
1128 static void set_sound_parameters(int sound, char **parameter_raw)
1130 int parameter[NUM_SND_ARGS];
1133 /* get integer values from string parameters */
1134 for (i=0; i < NUM_SND_ARGS; i++)
1136 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1137 sound_config_suffix[i].type);
1139 /* explicit loop mode setting in configuration overrides default value */
1140 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1141 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1144 static void InitSoundInfo()
1147 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1148 int num_property_mappings = getSoundListPropertyMappingSize();
1150 int *sound_effect_properties;
1151 int num_sounds = getSoundListSize();
1154 if (sound_info != NULL)
1157 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1158 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1160 /* initialize sound effect for all elements to "no sound" */
1161 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1162 for (j=0; j<NUM_ACTIONS; j++)
1163 element_info[i].sound[j] = SND_UNDEFINED;
1165 for (i=0; i<num_sounds; i++)
1167 struct FileInfo *sound = getSoundListEntry(i);
1168 int len_effect_text = strlen(sound->token);
1170 sound_effect_properties[i] = ACTION_OTHER;
1171 sound_info[i].loop = FALSE;
1174 printf("::: sound %d: '%s'\n", i, sound->token);
1177 /* determine all loop sounds and identify certain sound classes */
1179 for (j=0; element_action_info[j].suffix; j++)
1181 int len_action_text = strlen(element_action_info[j].suffix);
1183 if (len_action_text < len_effect_text &&
1184 strcmp(&sound->token[len_effect_text - len_action_text],
1185 element_action_info[j].suffix) == 0)
1187 sound_effect_properties[i] = element_action_info[j].value;
1188 sound_info[i].loop = element_action_info[j].is_loop_sound;
1195 if (strcmp(sound->token, "custom_42") == 0)
1196 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1199 /* associate elements and some selected sound actions */
1201 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1203 if (element_info[j].class_name)
1205 int len_class_text = strlen(element_info[j].class_name);
1207 if (len_class_text + 1 < len_effect_text &&
1208 strncmp(sound->token,
1209 element_info[j].class_name, len_class_text) == 0 &&
1210 sound->token[len_class_text] == '.')
1212 int sound_action_value = sound_effect_properties[i];
1214 element_info[j].sound[sound_action_value] = i;
1219 set_sound_parameters(i, sound->parameter);
1222 free(sound_effect_properties);
1225 /* !!! now handled in InitElementSoundInfo() !!! */
1226 /* initialize element/sound mapping from dynamic configuration */
1227 for (i=0; i < num_property_mappings; i++)
1229 int element = property_mapping[i].base_index;
1230 int action = property_mapping[i].ext1_index;
1231 int sound = property_mapping[i].artwork_index;
1234 action = ACTION_DEFAULT;
1236 printf("::: %d: %d, %d, %d ['%s']\n",
1237 i, element, action, sound, element_info[element].token_name);
1239 element_info[element].sound[action] = sound;
1246 int element = EL_CUSTOM_11;
1249 while (element_action_info[j].suffix)
1251 printf("element %d, sound action '%s' == %d\n",
1252 element, element_action_info[j].suffix,
1253 element_info[element].sound[j]);
1258 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1264 int element = EL_SAND;
1265 int sound_action = ACTION_DIGGING;
1268 while (element_action_info[j].suffix)
1270 if (element_action_info[j].value == sound_action)
1271 printf("element %d, sound action '%s' == %d\n",
1272 element, element_action_info[j].suffix,
1273 element_info[element].sound[sound_action]);
1280 static void ReinitializeGraphics()
1282 InitGraphicInfo(); /* graphic properties mapping */
1283 InitElementGraphicInfo(); /* element game graphic mapping */
1284 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1286 InitElementSmallImages(); /* create editor and preview images */
1287 InitFontGraphicInfo(); /* initialize text drawing functions */
1289 SetMainBackgroundImage(IMG_BACKGROUND);
1290 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1296 static void ReinitializeSounds()
1298 InitSoundInfo(); /* sound properties mapping */
1299 InitElementSoundInfo(); /* element game sound mapping */
1301 InitPlaySoundLevel(); /* internal game sound settings */
1304 static void ReinitializeMusic()
1306 /* currently nothing to do */
1309 void InitElementPropertiesStatic()
1311 static int ep_diggable[] =
1316 EL_SP_BUGGY_BASE_ACTIVATING,
1319 EL_INVISIBLE_SAND_ACTIVE,
1321 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1325 EL_SP_BUGGY_BASE_ACTIVE,
1330 static int ep_collectible_only[] =
1347 EL_DYNABOMB_INCREASE_NUMBER,
1348 EL_DYNABOMB_INCREASE_SIZE,
1349 EL_DYNABOMB_INCREASE_POWER,
1363 static int ep_dont_run_into[] =
1365 /* same elements as in 'ep_dont_touch' */
1371 /* same elements as in 'ep_dont_collide_with' */
1383 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1385 EL_SP_BUGGY_BASE_ACTIVE,
1392 static int ep_dont_collide_with[] =
1394 /* same elements as in 'ep_dont_touch' */
1410 static int ep_dont_touch[] =
1419 static int ep_indestructible[] =
1423 EL_ACID_POOL_TOPLEFT,
1424 EL_ACID_POOL_TOPRIGHT,
1425 EL_ACID_POOL_BOTTOMLEFT,
1426 EL_ACID_POOL_BOTTOM,
1427 EL_ACID_POOL_BOTTOMRIGHT,
1428 EL_SP_HARDWARE_GRAY,
1429 EL_SP_HARDWARE_GREEN,
1430 EL_SP_HARDWARE_BLUE,
1432 EL_SP_HARDWARE_YELLOW,
1433 EL_SP_HARDWARE_BASE_1,
1434 EL_SP_HARDWARE_BASE_2,
1435 EL_SP_HARDWARE_BASE_3,
1436 EL_SP_HARDWARE_BASE_4,
1437 EL_SP_HARDWARE_BASE_5,
1438 EL_SP_HARDWARE_BASE_6,
1439 EL_INVISIBLE_STEELWALL,
1440 EL_INVISIBLE_STEELWALL_ACTIVE,
1441 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1442 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1443 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1444 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1445 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1446 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1447 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1448 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1449 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1450 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1451 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1452 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1454 EL_LIGHT_SWITCH_ACTIVE,
1455 EL_SIGN_EXCLAMATION,
1456 EL_SIGN_RADIOACTIVITY,
1467 EL_STEELWALL_SLIPPERY,
1490 EL_SWITCHGATE_OPENING,
1491 EL_SWITCHGATE_CLOSED,
1492 EL_SWITCHGATE_CLOSING,
1494 EL_SWITCHGATE_SWITCH_UP,
1495 EL_SWITCHGATE_SWITCH_DOWN,
1498 EL_TIMEGATE_OPENING,
1500 EL_TIMEGATE_CLOSING,
1503 EL_TIMEGATE_SWITCH_ACTIVE,
1508 EL_TUBE_VERTICAL_LEFT,
1509 EL_TUBE_VERTICAL_RIGHT,
1510 EL_TUBE_HORIZONTAL_UP,
1511 EL_TUBE_HORIZONTAL_DOWN,
1519 static int ep_slippery[] =
1533 EL_ROBOT_WHEEL_ACTIVE,
1539 EL_ACID_POOL_TOPLEFT,
1540 EL_ACID_POOL_TOPRIGHT,
1550 EL_STEELWALL_SLIPPERY,
1556 static int ep_can_change[] =
1561 static int ep_can_move[] =
1583 static int ep_can_fall[] =
1598 EL_BD_MAGIC_WALL_FULL,
1611 static int ep_can_smash_player[] =
1636 static int ep_can_smash_enemies[] =
1644 static int ep_can_smash_everything[] =
1652 static int ep_can_explode_by_fire[] =
1654 /* same elements as in 'ep_can_explode_impact' */
1659 /* same elements as in 'ep_can_explode_smashed' */
1668 EL_DYNABOMB_PLAYER_1_ACTIVE,
1669 EL_DYNABOMB_PLAYER_2_ACTIVE,
1670 EL_DYNABOMB_PLAYER_3_ACTIVE,
1671 EL_DYNABOMB_PLAYER_4_ACTIVE,
1672 EL_DYNABOMB_INCREASE_NUMBER,
1673 EL_DYNABOMB_INCREASE_SIZE,
1674 EL_DYNABOMB_INCREASE_POWER,
1675 EL_SP_DISK_RED_ACTIVE,
1685 static int ep_can_explode_smashed[] =
1687 /* same elements as in 'ep_can_explode_impact' */
1700 static int ep_can_explode_impact[] =
1708 static int ep_walkable_over[] =
1712 EL_SOKOBAN_FIELD_EMPTY,
1729 static int ep_walkable_inside[] =
1734 EL_TUBE_VERTICAL_LEFT,
1735 EL_TUBE_VERTICAL_RIGHT,
1736 EL_TUBE_HORIZONTAL_UP,
1737 EL_TUBE_HORIZONTAL_DOWN,
1745 static int ep_walkable_under[] =
1750 static int ep_passable_over[] =
1765 static int ep_passable_inside[] =
1771 EL_SP_PORT_HORIZONTAL,
1772 EL_SP_PORT_VERTICAL,
1774 EL_SP_GRAVITY_PORT_LEFT,
1775 EL_SP_GRAVITY_PORT_RIGHT,
1776 EL_SP_GRAVITY_PORT_UP,
1777 EL_SP_GRAVITY_PORT_DOWN,
1781 static int ep_passable_under[] =
1786 static int ep_pushable[] =
1798 EL_SOKOBAN_FIELD_FULL,
1805 static int ep_can_be_crumbled[] =
1814 static int ep_player[] =
1824 static int ep_can_pass_magic_wall[] =
1837 static int ep_switchable[] =
1841 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1842 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1843 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1844 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1845 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1846 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1847 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1848 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1849 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1850 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1851 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1852 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1853 EL_SWITCHGATE_SWITCH_UP,
1854 EL_SWITCHGATE_SWITCH_DOWN,
1856 EL_LIGHT_SWITCH_ACTIVE,
1858 EL_BALLOON_SWITCH_LEFT,
1859 EL_BALLOON_SWITCH_RIGHT,
1860 EL_BALLOON_SWITCH_UP,
1861 EL_BALLOON_SWITCH_DOWN,
1862 EL_BALLOON_SWITCH_ANY,
1868 static int ep_bd_element[] =
1897 static int ep_sp_element[] =
1905 EL_SP_HARDWARE_GRAY,
1913 EL_SP_GRAVITY_PORT_RIGHT,
1914 EL_SP_GRAVITY_PORT_DOWN,
1915 EL_SP_GRAVITY_PORT_LEFT,
1916 EL_SP_GRAVITY_PORT_UP,
1921 EL_SP_PORT_VERTICAL,
1922 EL_SP_PORT_HORIZONTAL,
1928 EL_SP_HARDWARE_BASE_1,
1929 EL_SP_HARDWARE_GREEN,
1930 EL_SP_HARDWARE_BLUE,
1932 EL_SP_HARDWARE_YELLOW,
1933 EL_SP_HARDWARE_BASE_2,
1934 EL_SP_HARDWARE_BASE_3,
1935 EL_SP_HARDWARE_BASE_4,
1936 EL_SP_HARDWARE_BASE_5,
1937 EL_SP_HARDWARE_BASE_6,
1940 /* additional elements that appeared in newer Supaplex levels */
1942 /* more than one murphy in a level results in an inactive clone */
1944 /* runtime elements*/
1945 EL_SP_DISK_RED_ACTIVE,
1946 EL_SP_TERMINAL_ACTIVE,
1947 EL_SP_BUGGY_BASE_ACTIVATING,
1948 EL_SP_BUGGY_BASE_ACTIVE,
1952 static int ep_sb_element[] =
1957 EL_SOKOBAN_FIELD_EMPTY,
1958 EL_SOKOBAN_FIELD_FULL,
1960 EL_INVISIBLE_STEELWALL,
1964 static int ep_gem[] =
1975 static int ep_food_dark_yamyam[] =
2002 static int ep_food_penguin[] =
2015 static int ep_food_pig[] =
2026 static int ep_historic_wall[] =
2051 EL_EXPANDABLE_WALL_HORIZONTAL,
2052 EL_EXPANDABLE_WALL_VERTICAL,
2053 EL_EXPANDABLE_WALL_ANY,
2054 EL_EXPANDABLE_WALL_GROWING,
2061 EL_SP_HARDWARE_GRAY,
2062 EL_SP_HARDWARE_GREEN,
2063 EL_SP_HARDWARE_BLUE,
2065 EL_SP_HARDWARE_YELLOW,
2066 EL_SP_HARDWARE_BASE_1,
2067 EL_SP_HARDWARE_BASE_2,
2068 EL_SP_HARDWARE_BASE_3,
2069 EL_SP_HARDWARE_BASE_4,
2070 EL_SP_HARDWARE_BASE_5,
2071 EL_SP_HARDWARE_BASE_6,
2073 EL_SP_TERMINAL_ACTIVE,
2076 EL_INVISIBLE_STEELWALL,
2077 EL_INVISIBLE_STEELWALL_ACTIVE,
2079 EL_INVISIBLE_WALL_ACTIVE,
2080 EL_STEELWALL_SLIPPERY,
2096 static int ep_historic_solid[] =
2100 EL_EXPANDABLE_WALL_HORIZONTAL,
2101 EL_EXPANDABLE_WALL_VERTICAL,
2102 EL_EXPANDABLE_WALL_ANY,
2115 EL_QUICKSAND_FILLING,
2116 EL_QUICKSAND_EMPTYING,
2118 EL_MAGIC_WALL_ACTIVE,
2119 EL_MAGIC_WALL_EMPTYING,
2120 EL_MAGIC_WALL_FILLING,
2124 EL_BD_MAGIC_WALL_ACTIVE,
2125 EL_BD_MAGIC_WALL_EMPTYING,
2126 EL_BD_MAGIC_WALL_FULL,
2127 EL_BD_MAGIC_WALL_FILLING,
2128 EL_BD_MAGIC_WALL_DEAD,
2137 EL_SP_TERMINAL_ACTIVE,
2141 EL_INVISIBLE_WALL_ACTIVE,
2142 EL_SWITCHGATE_SWITCH_UP,
2143 EL_SWITCHGATE_SWITCH_DOWN,
2145 EL_TIMEGATE_SWITCH_ACTIVE,
2157 /* the following elements are a direct copy of "indestructible" elements,
2158 except "EL_ACID", which is "indestructible", but not "solid"! */
2163 EL_ACID_POOL_TOPLEFT,
2164 EL_ACID_POOL_TOPRIGHT,
2165 EL_ACID_POOL_BOTTOMLEFT,
2166 EL_ACID_POOL_BOTTOM,
2167 EL_ACID_POOL_BOTTOMRIGHT,
2168 EL_SP_HARDWARE_GRAY,
2169 EL_SP_HARDWARE_GREEN,
2170 EL_SP_HARDWARE_BLUE,
2172 EL_SP_HARDWARE_YELLOW,
2173 EL_SP_HARDWARE_BASE_1,
2174 EL_SP_HARDWARE_BASE_2,
2175 EL_SP_HARDWARE_BASE_3,
2176 EL_SP_HARDWARE_BASE_4,
2177 EL_SP_HARDWARE_BASE_5,
2178 EL_SP_HARDWARE_BASE_6,
2179 EL_INVISIBLE_STEELWALL,
2180 EL_INVISIBLE_STEELWALL_ACTIVE,
2181 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2182 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2183 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2184 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2185 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2186 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2187 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2188 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2189 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2190 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2191 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2192 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2194 EL_LIGHT_SWITCH_ACTIVE,
2195 EL_SIGN_EXCLAMATION,
2196 EL_SIGN_RADIOACTIVITY,
2207 EL_STEELWALL_SLIPPERY,
2230 EL_SWITCHGATE_OPENING,
2231 EL_SWITCHGATE_CLOSED,
2232 EL_SWITCHGATE_CLOSING,
2234 EL_TIMEGATE_OPENING,
2236 EL_TIMEGATE_CLOSING,
2240 EL_TUBE_VERTICAL_LEFT,
2241 EL_TUBE_VERTICAL_RIGHT,
2242 EL_TUBE_HORIZONTAL_UP,
2243 EL_TUBE_HORIZONTAL_DOWN,
2251 static int ep_classic_enemy[] =
2267 static int ep_belt[] =
2269 EL_CONVEYOR_BELT_1_LEFT,
2270 EL_CONVEYOR_BELT_1_MIDDLE,
2271 EL_CONVEYOR_BELT_1_RIGHT,
2272 EL_CONVEYOR_BELT_2_LEFT,
2273 EL_CONVEYOR_BELT_2_MIDDLE,
2274 EL_CONVEYOR_BELT_2_RIGHT,
2275 EL_CONVEYOR_BELT_3_LEFT,
2276 EL_CONVEYOR_BELT_3_MIDDLE,
2277 EL_CONVEYOR_BELT_3_RIGHT,
2278 EL_CONVEYOR_BELT_4_LEFT,
2279 EL_CONVEYOR_BELT_4_MIDDLE,
2280 EL_CONVEYOR_BELT_4_RIGHT,
2284 static int ep_belt_active[] =
2286 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2287 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2288 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2289 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2290 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2291 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2292 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2293 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2294 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2295 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2296 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2297 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2301 static int ep_belt_switch[] =
2303 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2304 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2305 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2306 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2307 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2308 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2309 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2310 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2311 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2312 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2313 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2314 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2318 static int ep_tube[] =
2325 EL_TUBE_HORIZONTAL_UP,
2326 EL_TUBE_HORIZONTAL_DOWN,
2328 EL_TUBE_VERTICAL_LEFT,
2329 EL_TUBE_VERTICAL_RIGHT,
2334 static int ep_keygate[] =
2355 static int ep_amoeboid[] =
2365 static int ep_amoebalive[] =
2374 static int ep_has_content[] =
2384 static int ep_active_bomb[] =
2387 EL_DYNABOMB_PLAYER_1_ACTIVE,
2388 EL_DYNABOMB_PLAYER_2_ACTIVE,
2389 EL_DYNABOMB_PLAYER_3_ACTIVE,
2390 EL_DYNABOMB_PLAYER_4_ACTIVE,
2391 EL_SP_DISK_RED_ACTIVE,
2395 static int ep_inactive[] =
2432 EL_INVISIBLE_STEELWALL,
2440 EL_WALL_EMERALD_YELLOW,
2441 EL_DYNABOMB_INCREASE_NUMBER,
2442 EL_DYNABOMB_INCREASE_SIZE,
2443 EL_DYNABOMB_INCREASE_POWER,
2447 EL_SOKOBAN_FIELD_EMPTY,
2448 EL_SOKOBAN_FIELD_FULL,
2449 EL_WALL_EMERALD_RED,
2450 EL_WALL_EMERALD_PURPLE,
2451 EL_ACID_POOL_TOPLEFT,
2452 EL_ACID_POOL_TOPRIGHT,
2453 EL_ACID_POOL_BOTTOMLEFT,
2454 EL_ACID_POOL_BOTTOM,
2455 EL_ACID_POOL_BOTTOMRIGHT,
2459 EL_BD_MAGIC_WALL_DEAD,
2460 EL_AMOEBA_TO_DIAMOND,
2468 EL_SP_GRAVITY_PORT_RIGHT,
2469 EL_SP_GRAVITY_PORT_DOWN,
2470 EL_SP_GRAVITY_PORT_LEFT,
2471 EL_SP_GRAVITY_PORT_UP,
2472 EL_SP_PORT_HORIZONTAL,
2473 EL_SP_PORT_VERTICAL,
2484 EL_SP_HARDWARE_GRAY,
2485 EL_SP_HARDWARE_GREEN,
2486 EL_SP_HARDWARE_BLUE,
2488 EL_SP_HARDWARE_YELLOW,
2489 EL_SP_HARDWARE_BASE_1,
2490 EL_SP_HARDWARE_BASE_2,
2491 EL_SP_HARDWARE_BASE_3,
2492 EL_SP_HARDWARE_BASE_4,
2493 EL_SP_HARDWARE_BASE_5,
2494 EL_SP_HARDWARE_BASE_6,
2495 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2496 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2497 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2498 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2499 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2500 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2501 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2502 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2503 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2504 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2505 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2506 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2507 EL_SIGN_EXCLAMATION,
2508 EL_SIGN_RADIOACTIVITY,
2519 EL_STEELWALL_SLIPPERY,
2539 } element_properties[] =
2541 { ep_diggable, EP_DIGGABLE },
2542 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2543 { ep_dont_run_into, EP_DONT_RUN_INTO },
2544 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2545 { ep_dont_touch, EP_DONT_TOUCH },
2546 { ep_indestructible, EP_INDESTRUCTIBLE },
2547 { ep_slippery, EP_SLIPPERY },
2548 { ep_can_change, EP_CAN_CHANGE },
2549 { ep_can_move, EP_CAN_MOVE },
2550 { ep_can_fall, EP_CAN_FALL },
2551 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2552 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2553 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2554 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2555 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2556 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2557 { ep_walkable_over, EP_WALKABLE_OVER },
2558 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2559 { ep_walkable_under, EP_WALKABLE_UNDER },
2560 { ep_passable_over, EP_PASSABLE_OVER },
2561 { ep_passable_inside, EP_PASSABLE_INSIDE },
2562 { ep_passable_under, EP_PASSABLE_UNDER },
2563 { ep_pushable, EP_PUSHABLE },
2565 { ep_can_be_crumbled, EP_CAN_BE_CRUMBLED },
2567 { ep_player, EP_PLAYER },
2568 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2569 { ep_switchable, EP_SWITCHABLE },
2570 { ep_bd_element, EP_BD_ELEMENT },
2571 { ep_sp_element, EP_SP_ELEMENT },
2572 { ep_sb_element, EP_SB_ELEMENT },
2574 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2575 { ep_food_penguin, EP_FOOD_PENGUIN },
2576 { ep_food_pig, EP_FOOD_PIG },
2577 { ep_historic_wall, EP_HISTORIC_WALL },
2578 { ep_historic_solid, EP_HISTORIC_SOLID },
2579 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2580 { ep_belt, EP_BELT },
2581 { ep_belt_active, EP_BELT_ACTIVE },
2582 { ep_belt_switch, EP_BELT_SWITCH },
2583 { ep_tube, EP_TUBE },
2584 { ep_keygate, EP_KEYGATE },
2585 { ep_amoeboid, EP_AMOEBOID },
2586 { ep_amoebalive, EP_AMOEBALIVE },
2587 { ep_has_content, EP_HAS_CONTENT },
2588 { ep_active_bomb, EP_ACTIVE_BOMB },
2589 { ep_inactive, EP_INACTIVE },
2594 static int copy_properties[][5] =
2598 EL_BUG_LEFT, EL_BUG_RIGHT,
2599 EL_BUG_UP, EL_BUG_DOWN
2603 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2604 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2608 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2609 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2613 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2614 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2618 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2619 EL_PACMAN_UP, EL_PACMAN_DOWN
2629 /* always start with reliable default values (element has no properties) */
2630 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2631 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2632 SET_PROPERTY(i, j, FALSE);
2634 /* set all base element properties from above array definitions */
2635 for (i=0; element_properties[i].elements != NULL; i++)
2636 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2637 SET_PROPERTY((element_properties[i].elements)[j],
2638 element_properties[i].property, TRUE);
2640 /* copy properties to some elements that are only stored in level file */
2641 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2642 for (j=0; copy_properties[j][0] != -1; j++)
2643 if (HAS_PROPERTY(copy_properties[j][0], i))
2644 for (k=1; k<=4; k++)
2645 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2648 void InitElementPropertiesEngine(int engine_version)
2651 static int active_properties[] =
2656 EP_DONT_COLLIDE_WITH,
2660 EP_CAN_PASS_MAGIC_WALL,
2665 EP_CAN_EXPLODE_BY_FIRE,
2678 EP_EM_SLIPPERY_WALL,
2683 static int no_wall_properties[] =
2686 EP_COLLECTIBLE_ONLY,
2688 EP_DONT_COLLIDE_WITH,
2691 EP_CAN_SMASH_PLAYER,
2692 EP_CAN_SMASH_ENEMIES,
2693 EP_CAN_SMASH_EVERYTHING,
2700 EP_FOOD_DARK_YAMYAM,
2716 InitElementPropertiesStatic();
2719 /* set all special, combined or engine dependent element properties */
2720 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2723 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2724 SET_PROPERTY(i, j, FALSE);
2727 /* ---------- INACTIVE ------------------------------------------------- */
2728 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2729 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2731 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2732 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2733 IS_WALKABLE_INSIDE(i) ||
2734 IS_WALKABLE_UNDER(i)));
2736 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2737 IS_PASSABLE_INSIDE(i) ||
2738 IS_PASSABLE_UNDER(i)));
2740 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2741 IS_PASSABLE_OVER(i)));
2743 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2744 IS_PASSABLE_INSIDE(i)));
2746 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2747 IS_PASSABLE_UNDER(i)));
2749 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2752 /* ---------- COLLECTIBLE ---------------------------------------------- */
2753 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2756 /* ---------- SNAPPABLE ------------------------------------------------ */
2757 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2758 IS_COLLECTIBLE(i) ||
2762 /* ---------- WALL ----------------------------------------------------- */
2763 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2765 for (j=0; no_wall_properties[j] != -1; j++)
2766 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2767 i >= EL_FIRST_RUNTIME_UNREAL)
2768 SET_PROPERTY(i, EP_WALL, FALSE);
2770 if (IS_HISTORIC_WALL(i))
2771 SET_PROPERTY(i, EP_WALL, TRUE);
2773 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2774 if (engine_version < VERSION_IDENT(2,2,0))
2775 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2777 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2779 !IS_COLLECTIBLE(i)));
2781 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2783 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2784 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2786 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2787 IS_INDESTRUCTIBLE(i)));
2789 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2791 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2792 else if (engine_version < VERSION_IDENT(2,2,0))
2793 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2795 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2796 !IS_WALKABLE_OVER(i) &&
2797 !IS_WALKABLE_UNDER(i)));
2799 if (IS_CUSTOM_ELEMENT(i))
2801 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2803 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2804 if (DONT_COLLIDE_WITH(i))
2805 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2807 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2808 if (CAN_SMASH_EVERYTHING(i))
2809 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2810 if (CAN_SMASH_ENEMIES(i))
2811 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2814 /* ---------- CAN_SMASH ------------------------------------------------ */
2815 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2816 CAN_SMASH_ENEMIES(i) ||
2817 CAN_SMASH_EVERYTHING(i)));
2819 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2820 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2821 CAN_EXPLODE_SMASHED(i) ||
2822 CAN_EXPLODE_IMPACT(i)));
2824 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2825 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2826 !CAN_EXPLODE_1X1(i)));
2828 /* ---------- CAN_BE_CRUMBLED ------------------------------------------ */
2829 SET_PROPERTY(i, EP_CAN_BE_CRUMBLED,
2830 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2833 if (CAN_BE_CRUMBLED(i))
2834 printf("::: '%s' can be crumbled [%d]\n",
2835 element_info[i].token_name,
2836 element_info[i].crumbled[ACTION_DEFAULT]);
2839 /* ---------- CAN_CHANGE ----------------------------------------------- */
2840 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
2841 for (j=0; j < element_info[i].num_change_pages; j++)
2842 if (element_info[i].change_page[j].can_change)
2843 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
2847 /* determine inactive elements (used for engine main loop optimization) */
2848 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2850 boolean active = FALSE;
2852 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2854 if (HAS_PROPERTY(i, j))
2860 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2865 /* dynamically adjust element properties according to game engine version */
2867 static int ep_em_slippery_wall[] =
2872 EL_EXPANDABLE_WALL_HORIZONTAL,
2873 EL_EXPANDABLE_WALL_VERTICAL,
2874 EL_EXPANDABLE_WALL_ANY,
2878 /* special EM style gems behaviour */
2879 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2880 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2881 level.em_slippery_gems);
2883 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2884 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2885 (level.em_slippery_gems &&
2886 engine_version > VERSION_IDENT(2,0,1)));
2890 /* dynamically adjust element properties according to game engine version */
2892 if (engine_version < RELEASE_IDENT(2,2,0,7))
2895 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2897 int element = EL_CUSTOM_START + i;
2899 element_info[element].push_delay_fixed = 2;
2900 element_info[element].push_delay_random = 8;
2906 static void InitGlobal()
2908 global.autoplay_leveldir = NULL;
2910 global.frames_per_second = 0;
2911 global.fps_slowdown = FALSE;
2912 global.fps_slowdown_factor = 1;
2915 void Execute_Command(char *command)
2917 if (strcmp(command, "print graphicsinfo.conf") == 0)
2921 printf("# You can configure additional/alternative image files here.\n");
2922 printf("# (The images below are default and therefore commented out.)\n");
2924 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2926 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2929 for (i=0; image_config[i].token != NULL; i++)
2931 getFormattedSetupEntry(image_config[i].token,
2932 image_config[i].value));
2936 else if (strcmp(command, "print soundsinfo.conf") == 0)
2940 printf("# You can configure additional/alternative sound files here.\n");
2941 printf("# (The sounds below are default and therefore commented out.)\n");
2943 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2945 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2948 for (i=0; sound_config[i].token != NULL; i++)
2950 getFormattedSetupEntry(sound_config[i].token,
2951 sound_config[i].value));
2955 else if (strcmp(command, "print musicinfo.conf") == 0)
2957 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2959 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2961 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2965 else if (strncmp(command, "dump level ", 11) == 0)
2967 char *filename = &command[11];
2969 if (access(filename, F_OK) != 0)
2970 Error(ERR_EXIT, "cannot open file '%s'", filename);
2972 LoadLevelFromFilename(&level, filename);
2977 else if (strncmp(command, "dump tape ", 10) == 0)
2979 char *filename = &command[10];
2981 if (access(filename, F_OK) != 0)
2982 Error(ERR_EXIT, "cannot open file '%s'", filename);
2984 LoadTapeFromFilename(filename);
2989 else if (strncmp(command, "autoplay ", 9) == 0)
2991 char *str_copy = getStringCopy(&command[9]);
2992 char *str_ptr = strchr(str_copy, ' ');
2994 global.autoplay_leveldir = str_copy;
2995 global.autoplay_level_nr = -1;
2997 if (str_ptr != NULL)
2999 *str_ptr++ = '\0'; /* terminate leveldir string */
3000 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3005 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3009 static void InitSetup()
3011 LoadSetup(); /* global setup info */
3013 /* set some options from setup file */
3015 if (setup.options.verbose)
3016 options.verbose = TRUE;
3019 static void InitPlayerInfo()
3023 /* choose default local player */
3024 local_player = &stored_player[0];
3026 for (i=0; i<MAX_PLAYERS; i++)
3027 stored_player[i].connected = FALSE;
3029 local_player->connected = TRUE;
3032 static void InitArtworkInfo()
3037 static char *get_string_in_brackets(char *string)
3039 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3041 sprintf(string_in_brackets, "[%s]", string);
3043 return string_in_brackets;
3047 static char *get_element_class_token(int element)
3049 char *element_class_name = element_info[element].class_name;
3050 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3052 sprintf(element_class_token, "[%s]", element_class_name);
3054 return element_class_token;
3057 static char *get_action_class_token(int action)
3059 char *action_class_name = &element_action_info[action].suffix[1];
3060 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3062 sprintf(action_class_token, "[%s]", action_class_name);
3064 return action_class_token;
3068 static void InitArtworkConfig()
3070 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3071 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3072 static char *action_id_suffix[NUM_ACTIONS + 1];
3073 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3074 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3075 static char *dummy[1] = { NULL };
3076 static char *ignore_generic_tokens[] =
3082 static char **ignore_image_tokens, **ignore_sound_tokens;
3083 int num_ignore_generic_tokens;
3084 int num_ignore_image_tokens, num_ignore_sound_tokens;
3087 /* dynamically determine list of generic tokens to be ignored */
3088 num_ignore_generic_tokens = 0;
3089 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3090 num_ignore_generic_tokens++;
3092 /* dynamically determine list of image tokens to be ignored */
3093 num_ignore_image_tokens = num_ignore_generic_tokens;
3094 for (i=0; image_config_vars[i].token != NULL; i++)
3095 num_ignore_image_tokens++;
3096 ignore_image_tokens =
3097 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3098 for (i=0; i < num_ignore_generic_tokens; i++)
3099 ignore_image_tokens[i] = ignore_generic_tokens[i];
3100 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3101 ignore_image_tokens[num_ignore_generic_tokens + i] =
3102 image_config_vars[i].token;
3103 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3105 /* dynamically determine list of sound tokens to be ignored */
3106 num_ignore_sound_tokens = num_ignore_generic_tokens;
3107 ignore_sound_tokens =
3108 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3109 for (i=0; i < num_ignore_generic_tokens; i++)
3110 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3111 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3113 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3114 image_id_prefix[i] = element_info[i].token_name;
3115 for (i=0; i<NUM_FONTS; i++)
3116 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3117 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3119 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3120 sound_id_prefix[i] = element_info[i].token_name;
3121 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3122 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3123 get_string_in_brackets(element_info[i].class_name);
3124 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3126 for (i=0; i<NUM_ACTIONS; i++)
3127 action_id_suffix[i] = element_action_info[i].suffix;
3128 action_id_suffix[NUM_ACTIONS] = NULL;
3130 for (i=0; i<NUM_DIRECTIONS; i++)
3131 direction_id_suffix[i] = element_direction_info[i].suffix;
3132 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3134 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3135 special_id_suffix[i] = special_suffix_info[i].suffix;
3136 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3138 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3139 image_id_prefix, action_id_suffix, direction_id_suffix,
3140 special_id_suffix, ignore_image_tokens);
3141 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3142 sound_id_prefix, action_id_suffix, dummy,
3143 special_id_suffix, ignore_sound_tokens);
3146 static void InitMixer()
3154 char *filename_font_initial = NULL;
3155 Bitmap *bitmap_font_initial = NULL;
3158 /* determine settings for initial font (for displaying startup messages) */
3159 for (i=0; image_config[i].token != NULL; i++)
3161 for (j=0; j < NUM_INITIAL_FONTS; j++)
3163 char font_token[128];
3166 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3167 len_font_token = strlen(font_token);
3169 if (strcmp(image_config[i].token, font_token) == 0)
3170 filename_font_initial = image_config[i].value;
3171 else if (strlen(image_config[i].token) > len_font_token &&
3172 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3174 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3175 font_initial[j].src_x = atoi(image_config[i].value);
3176 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3177 font_initial[j].src_y = atoi(image_config[i].value);
3178 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3179 font_initial[j].width = atoi(image_config[i].value);
3180 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3181 font_initial[j].height = atoi(image_config[i].value);
3186 for (j=0; j < NUM_INITIAL_FONTS; j++)
3188 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3189 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3192 if (filename_font_initial == NULL) /* should not happen */
3193 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3195 /* create additional image buffers for double-buffering */
3196 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3197 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3199 /* initialize screen properties */
3200 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3201 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3203 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3204 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3205 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3207 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3209 for (j=0; j < NUM_INITIAL_FONTS; j++)
3210 font_initial[j].bitmap = bitmap_font_initial;
3212 InitFontGraphicInfo();
3214 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3215 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3217 DrawInitText("Loading graphics:", 120, FC_GREEN);
3219 InitTileClipmasks();
3222 void InitGfxBackground()
3226 drawto = backbuffer;
3227 fieldbuffer = bitmap_db_field;
3228 SetDrawtoField(DRAW_BACKBUFFER);
3230 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3231 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3232 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3233 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3235 for (x=0; x<MAX_BUF_XSIZE; x++)
3236 for (y=0; y<MAX_BUF_YSIZE; y++)
3239 redraw_mask = REDRAW_ALL;
3242 static void InitLevelInfo()
3244 LoadLevelInfo(); /* global level info */
3245 LoadLevelSetup_LastSeries(); /* last played series info */
3246 LoadLevelSetup_SeriesInfo(); /* last played level info */
3249 void InitLevelArtworkInfo()
3251 LoadLevelArtworkInfo();
3254 static void InitImages()
3257 setLevelArtworkDir(artwork.gfx_first);
3261 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3262 leveldir_current->identifier,
3263 artwork.gfx_current_identifier,
3264 artwork.gfx_current->identifier,
3265 leveldir_current->graphics_set,
3266 leveldir_current->graphics_path);
3269 ReloadCustomImages();
3271 LoadCustomElementDescriptions();
3272 LoadSpecialMenuDesignSettings();
3274 ReinitializeGraphics();
3277 static void InitSound(char *identifier)
3279 if (identifier == NULL)
3280 identifier = artwork.snd_current->identifier;
3283 /* set artwork path to send it to the sound server process */
3284 setLevelArtworkDir(artwork.snd_first);
3287 InitReloadCustomSounds(identifier);
3288 ReinitializeSounds();
3291 static void InitMusic(char *identifier)
3293 if (identifier == NULL)
3294 identifier = artwork.mus_current->identifier;
3297 /* set artwork path to send it to the sound server process */
3298 setLevelArtworkDir(artwork.mus_first);
3301 InitReloadCustomMusic(identifier);
3302 ReinitializeMusic();
3305 void InitNetworkServer()
3307 #if defined(PLATFORM_UNIX)
3311 if (!options.network)
3314 #if defined(PLATFORM_UNIX)
3315 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3317 if (!ConnectToServer(options.server_host, options.server_port))
3318 Error(ERR_EXIT, "cannot connect to network game server");
3320 SendToServer_PlayerName(setup.player_name);
3321 SendToServer_ProtocolVersion();
3324 SendToServer_NrWanted(nr_wanted);
3328 static char *getNewArtworkIdentifier(int type)
3330 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3331 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3332 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3333 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3334 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3335 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3336 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3337 char *leveldir_identifier = leveldir_current->identifier;
3339 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3340 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3342 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3344 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3345 char *artwork_current_identifier;
3346 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3348 /* leveldir_current may be invalid (level group, parent link) */
3349 if (!validLevelSeries(leveldir_current))
3352 /* 1st step: determine artwork set to be activated in descending order:
3353 --------------------------------------------------------------------
3354 1. setup artwork (when configured to override everything else)
3355 2. artwork set configured in "levelinfo.conf" of current level set
3356 (artwork in level directory will have priority when loading later)
3357 3. artwork in level directory (stored in artwork sub-directory)
3358 4. setup artwork (currently configured in setup menu) */
3360 if (setup_override_artwork)
3361 artwork_current_identifier = setup_artwork_set;
3362 else if (leveldir_artwork_set != NULL)
3363 artwork_current_identifier = leveldir_artwork_set;
3364 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3365 artwork_current_identifier = leveldir_identifier;
3367 artwork_current_identifier = setup_artwork_set;
3370 /* 2nd step: check if it is really needed to reload artwork set
3371 ------------------------------------------------------------ */
3374 if (type == ARTWORK_TYPE_GRAPHICS)
3375 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3376 artwork_new_identifier,
3377 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3378 artwork_current_identifier,
3379 leveldir_current->graphics_set,
3380 leveldir_current->identifier);
3383 /* ---------- reload if level set and also artwork set has changed ------- */
3384 if (leveldir_current_identifier[type] != leveldir_identifier &&
3385 (last_has_level_artwork_set[type] || has_level_artwork_set))
3386 artwork_new_identifier = artwork_current_identifier;
3388 leveldir_current_identifier[type] = leveldir_identifier;
3389 last_has_level_artwork_set[type] = has_level_artwork_set;
3392 if (type == ARTWORK_TYPE_GRAPHICS)
3393 printf("::: 1: '%s'\n", artwork_new_identifier);
3396 /* ---------- reload if "override artwork" setting has changed ----------- */
3397 if (last_override_level_artwork[type] != setup_override_artwork)
3398 artwork_new_identifier = artwork_current_identifier;
3400 last_override_level_artwork[type] = setup_override_artwork;
3403 if (type == ARTWORK_TYPE_GRAPHICS)
3404 printf("::: 2: '%s'\n", artwork_new_identifier);
3407 /* ---------- reload if current artwork identifier has changed ----------- */
3408 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3409 artwork_current_identifier) != 0)
3410 artwork_new_identifier = artwork_current_identifier;
3412 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3415 if (type == ARTWORK_TYPE_GRAPHICS)
3416 printf("::: 3: '%s'\n", artwork_new_identifier);
3419 /* ---------- do not reload directly after starting ---------------------- */
3420 if (!initialized[type])
3421 artwork_new_identifier = NULL;
3423 initialized[type] = TRUE;
3426 if (type == ARTWORK_TYPE_GRAPHICS)
3427 printf("::: 4: '%s'\n", artwork_new_identifier);
3431 if (type == ARTWORK_TYPE_GRAPHICS)
3432 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3433 artwork.gfx_current_identifier, artwork_current_identifier,
3434 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3435 artwork_new_identifier);
3438 return artwork_new_identifier;
3441 void ReloadCustomArtwork()
3443 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3444 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3445 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3446 boolean redraw_screen = FALSE;
3448 if (gfx_new_identifier != NULL)
3451 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3452 artwork.gfx_current_identifier,
3454 artwork.gfx_current->identifier,
3455 leveldir_current->graphics_set);
3458 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3463 printf("... '%s'\n",
3464 leveldir_current->graphics_set);
3467 FreeTileClipmasks();
3468 InitTileClipmasks();
3470 redraw_screen = TRUE;
3473 if (snd_new_identifier != NULL)
3475 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3477 InitSound(snd_new_identifier);
3479 redraw_screen = TRUE;
3482 if (mus_new_identifier != NULL)
3484 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3486 InitMusic(mus_new_identifier);
3488 redraw_screen = TRUE;
3493 InitGfxBackground();
3495 /* force redraw of (open or closed) door graphics */
3496 SetDoorState(DOOR_OPEN_ALL);
3497 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3501 void KeyboardAutoRepeatOffUnlessAutoplay()
3503 if (global.autoplay_leveldir == NULL)
3504 KeyboardAutoRepeatOff();
3508 /* ========================================================================= */
3510 /* ========================================================================= */
3514 InitGlobal(); /* initialize some global variables */
3516 if (options.execute_command)
3517 Execute_Command(options.execute_command);
3519 if (options.serveronly)
3521 #if defined(PLATFORM_UNIX)
3522 NetworkServer(options.server_port, options.serveronly);
3524 Error(ERR_WARN, "networking only supported in Unix version");
3526 exit(0); /* never reached */
3532 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3533 InitArtworkConfig(); /* needed before forking sound child process */
3538 InitRND(NEW_RANDOMIZE);
3539 InitSimpleRND(NEW_RANDOMIZE);
3544 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3547 InitEventFilter(FilterMouseMotionEvents);
3549 InitElementPropertiesStatic();
3550 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3555 InitLevelArtworkInfo();
3557 InitImages(); /* needs to know current level directory */
3558 InitSound(NULL); /* needs to know current level directory */
3559 InitMusic(NULL); /* needs to know current level directory */
3561 InitGfxBackground();
3563 if (global.autoplay_leveldir)
3569 game_status = GAME_MODE_MAIN;
3573 InitNetworkServer();
3576 void CloseAllAndExit(int exit_value)
3581 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3584 FreeTileClipmasks();
3586 CloseVideoDisplay();
3587 ClosePlatformDependentStuff();