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];
846 /* automatically determine correct start frame, if not defined */
847 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
848 graphic_info[graphic].anim_start_frame = 0;
849 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
850 graphic_info[graphic].anim_start_frame =
851 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
853 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
855 /* animation synchronized with global frame counter, not move position */
856 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
858 /* optional element for cloning crumble graphics */
859 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
860 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
862 /* optional element for cloning digging graphics */
863 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
864 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
866 /* optional border size for "crumbling" diggable graphics */
867 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
868 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
870 /* this is only used for toon animations */
871 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
872 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
874 /* this is only used for drawing font characters */
875 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
876 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
878 /* this is only used for drawing envelope graphics */
879 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
882 static void InitGraphicInfo()
884 int fallback_graphic = IMG_CHAR_EXCLAM;
885 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
886 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
887 int num_images = getImageListSize();
890 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
891 static boolean clipmasks_initialized = FALSE;
893 XGCValues clip_gc_values;
894 unsigned long clip_gc_valuemask;
895 GC copy_clipmask_gc = None;
898 if (graphic_info != NULL)
901 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
904 printf("::: graphic_info: %d entries\n", num_images);
907 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
908 if (clipmasks_initialized)
910 for (i=0; i<num_images; i++)
912 if (graphic_info[i].clip_mask)
913 XFreePixmap(display, graphic_info[i].clip_mask);
914 if (graphic_info[i].clip_gc)
915 XFreeGC(display, graphic_info[i].clip_gc);
917 graphic_info[i].clip_mask = None;
918 graphic_info[i].clip_gc = None;
923 for (i=0; i<num_images; i++)
925 struct FileInfo *image = getImageListEntry(i);
928 int first_frame, last_frame;
931 printf("::: image: '%s' [%d]\n", image->token, i);
935 printf("::: image # %d: '%s' ['%s']\n",
937 getTokenFromImageID(i));
940 set_graphic_parameters(i, image->parameter);
942 /* now check if no animation frames are outside of the loaded image */
944 if (graphic_info[i].bitmap == NULL)
945 continue; /* skip check for optional images that are undefined */
948 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
949 if (src_x < 0 || src_y < 0 ||
950 src_x + TILEX > src_bitmap->width ||
951 src_y + TILEY > src_bitmap->height)
953 Error(ERR_RETURN_LINE, "-");
954 Error(ERR_RETURN, "warning: error found in config file:");
955 Error(ERR_RETURN, "- config file: '%s'",
956 getImageConfigFilename());
957 Error(ERR_RETURN, "- config token: '%s'",
958 getTokenFromImageID(i));
959 Error(ERR_RETURN, "- image file: '%s'",
960 src_bitmap->source_filename);
962 "error: first animation frame out of bounds (%d, %d)",
964 Error(ERR_RETURN, "custom graphic rejected for this element/action");
966 if (i == fallback_graphic)
967 Error(ERR_EXIT, "fatal error: no fallback graphic available");
969 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
970 Error(ERR_RETURN_LINE, "-");
972 set_graphic_parameters(i, fallback_image->default_parameter);
973 graphic_info[i].bitmap = fallback_bitmap;
976 last_frame = graphic_info[i].anim_frames - 1;
977 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
978 if (src_x < 0 || src_y < 0 ||
979 src_x + TILEX > src_bitmap->width ||
980 src_y + TILEY > src_bitmap->height)
982 Error(ERR_RETURN_LINE, "-");
983 Error(ERR_RETURN, "warning: error found in config file:");
984 Error(ERR_RETURN, "- config file: '%s'",
985 getImageConfigFilename());
986 Error(ERR_RETURN, "- config token: '%s'",
987 getTokenFromImageID(i));
988 Error(ERR_RETURN, "- image file: '%s'",
989 src_bitmap->source_filename);
991 "error: last animation frame (%d) out of bounds (%d, %d)",
992 last_frame, src_x, src_y);
993 Error(ERR_RETURN, "custom graphic rejected for this element/action");
995 if (i == fallback_graphic)
996 Error(ERR_EXIT, "fatal error: no fallback graphic available");
998 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
999 Error(ERR_RETURN_LINE, "-");
1001 set_graphic_parameters(i, fallback_image->default_parameter);
1002 graphic_info[i].bitmap = fallback_bitmap;
1005 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1006 /* currently we need only a tile clip mask from the first frame */
1007 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1009 if (copy_clipmask_gc == None)
1011 clip_gc_values.graphics_exposures = False;
1012 clip_gc_valuemask = GCGraphicsExposures;
1013 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1014 clip_gc_valuemask, &clip_gc_values);
1017 graphic_info[i].clip_mask =
1018 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1020 src_pixmap = src_bitmap->clip_mask;
1021 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1022 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1024 clip_gc_values.graphics_exposures = False;
1025 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1026 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1028 graphic_info[i].clip_gc =
1029 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1033 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1034 if (copy_clipmask_gc)
1035 XFreeGC(display, copy_clipmask_gc);
1037 clipmasks_initialized = TRUE;
1041 static void InitElementSoundInfo()
1043 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1044 int num_property_mappings = getSoundListPropertyMappingSize();
1047 /* set values to -1 to identify later as "uninitialized" values */
1048 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1049 for (act=0; act < NUM_ACTIONS; act++)
1050 element_info[i].sound[act] = -1;
1052 /* initialize element/sound mapping from static configuration */
1053 for (i=0; element_to_sound[i].element > -1; i++)
1055 int element = element_to_sound[i].element;
1056 int action = element_to_sound[i].action;
1057 int sound = element_to_sound[i].sound;
1058 boolean is_class = element_to_sound[i].is_class;
1061 action = ACTION_DEFAULT;
1064 element_info[element].sound[action] = sound;
1066 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1067 if (strcmp(element_info[j].class_name,
1068 element_info[element].class_name) == 0)
1069 element_info[j].sound[action] = sound;
1072 /* initialize element class/sound mapping from dynamic configuration */
1073 for (i=0; i < num_property_mappings; i++)
1075 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1076 int action = property_mapping[i].ext1_index;
1077 int sound = property_mapping[i].artwork_index;
1079 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1083 action = ACTION_DEFAULT;
1085 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1086 if (strcmp(element_info[j].class_name,
1087 element_info[element_class].class_name) == 0)
1088 element_info[j].sound[action] = sound;
1091 /* initialize element/sound mapping from dynamic configuration */
1092 for (i=0; i < num_property_mappings; i++)
1094 int element = property_mapping[i].base_index;
1095 int action = property_mapping[i].ext1_index;
1096 int sound = property_mapping[i].artwork_index;
1098 if (element >= MAX_NUM_ELEMENTS)
1102 action = ACTION_DEFAULT;
1104 element_info[element].sound[action] = sound;
1107 /* now set all '-1' values to element specific default values */
1108 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1110 for (act=0; act < NUM_ACTIONS; act++)
1112 /* generic default action sound (defined by "[default]" directive) */
1113 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1115 /* look for special default action sound (classic game specific) */
1116 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1117 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1118 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1119 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1120 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1121 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1123 /* look for element specific default sound (independent from action) */
1124 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1125 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1127 /* no sound for this specific action -- use default action sound */
1128 if (element_info[i].sound[act] == -1)
1129 element_info[i].sound[act] = default_action_sound;
1134 static void set_sound_parameters(int sound, char **parameter_raw)
1136 int parameter[NUM_SND_ARGS];
1139 /* get integer values from string parameters */
1140 for (i=0; i < NUM_SND_ARGS; i++)
1142 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1143 sound_config_suffix[i].type);
1145 /* explicit loop mode setting in configuration overrides default value */
1146 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1147 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1150 static void InitSoundInfo()
1153 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1154 int num_property_mappings = getSoundListPropertyMappingSize();
1156 int *sound_effect_properties;
1157 int num_sounds = getSoundListSize();
1160 if (sound_info != NULL)
1163 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1164 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1166 /* initialize sound effect for all elements to "no sound" */
1167 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1168 for (j=0; j<NUM_ACTIONS; j++)
1169 element_info[i].sound[j] = SND_UNDEFINED;
1171 for (i=0; i<num_sounds; i++)
1173 struct FileInfo *sound = getSoundListEntry(i);
1174 int len_effect_text = strlen(sound->token);
1176 sound_effect_properties[i] = ACTION_OTHER;
1177 sound_info[i].loop = FALSE;
1180 printf("::: sound %d: '%s'\n", i, sound->token);
1183 /* determine all loop sounds and identify certain sound classes */
1185 for (j=0; element_action_info[j].suffix; j++)
1187 int len_action_text = strlen(element_action_info[j].suffix);
1189 if (len_action_text < len_effect_text &&
1190 strcmp(&sound->token[len_effect_text - len_action_text],
1191 element_action_info[j].suffix) == 0)
1193 sound_effect_properties[i] = element_action_info[j].value;
1194 sound_info[i].loop = element_action_info[j].is_loop_sound;
1201 if (strcmp(sound->token, "custom_42") == 0)
1202 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1205 /* associate elements and some selected sound actions */
1207 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1209 if (element_info[j].class_name)
1211 int len_class_text = strlen(element_info[j].class_name);
1213 if (len_class_text + 1 < len_effect_text &&
1214 strncmp(sound->token,
1215 element_info[j].class_name, len_class_text) == 0 &&
1216 sound->token[len_class_text] == '.')
1218 int sound_action_value = sound_effect_properties[i];
1220 element_info[j].sound[sound_action_value] = i;
1225 set_sound_parameters(i, sound->parameter);
1228 free(sound_effect_properties);
1231 /* !!! now handled in InitElementSoundInfo() !!! */
1232 /* initialize element/sound mapping from dynamic configuration */
1233 for (i=0; i < num_property_mappings; i++)
1235 int element = property_mapping[i].base_index;
1236 int action = property_mapping[i].ext1_index;
1237 int sound = property_mapping[i].artwork_index;
1240 action = ACTION_DEFAULT;
1242 printf("::: %d: %d, %d, %d ['%s']\n",
1243 i, element, action, sound, element_info[element].token_name);
1245 element_info[element].sound[action] = sound;
1252 int element = EL_CUSTOM_11;
1255 while (element_action_info[j].suffix)
1257 printf("element %d, sound action '%s' == %d\n",
1258 element, element_action_info[j].suffix,
1259 element_info[element].sound[j]);
1264 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1270 int element = EL_SAND;
1271 int sound_action = ACTION_DIGGING;
1274 while (element_action_info[j].suffix)
1276 if (element_action_info[j].value == sound_action)
1277 printf("element %d, sound action '%s' == %d\n",
1278 element, element_action_info[j].suffix,
1279 element_info[element].sound[sound_action]);
1286 static void ReinitializeGraphics()
1288 InitGraphicInfo(); /* graphic properties mapping */
1289 InitElementGraphicInfo(); /* element game graphic mapping */
1290 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1292 InitElementSmallImages(); /* create editor and preview images */
1293 InitFontGraphicInfo(); /* initialize text drawing functions */
1295 SetMainBackgroundImage(IMG_BACKGROUND);
1296 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1302 static void ReinitializeSounds()
1304 InitSoundInfo(); /* sound properties mapping */
1305 InitElementSoundInfo(); /* element game sound mapping */
1307 InitPlaySoundLevel(); /* internal game sound settings */
1310 static void ReinitializeMusic()
1312 /* currently nothing to do */
1315 void InitElementPropertiesStatic()
1317 static int ep_diggable[] =
1322 EL_SP_BUGGY_BASE_ACTIVATING,
1325 EL_INVISIBLE_SAND_ACTIVE,
1327 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1331 EL_SP_BUGGY_BASE_ACTIVE,
1336 static int ep_collectible_only[] =
1353 EL_DYNABOMB_INCREASE_NUMBER,
1354 EL_DYNABOMB_INCREASE_SIZE,
1355 EL_DYNABOMB_INCREASE_POWER,
1372 static int ep_dont_run_into[] =
1374 /* same elements as in 'ep_dont_touch' */
1380 /* same elements as in 'ep_dont_collide_with' */
1392 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1396 EL_SP_BUGGY_BASE_ACTIVE,
1401 static int ep_dont_collide_with[] =
1403 /* same elements as in 'ep_dont_touch' */
1419 static int ep_dont_touch[] =
1428 static int ep_indestructible[] =
1432 EL_ACID_POOL_TOPLEFT,
1433 EL_ACID_POOL_TOPRIGHT,
1434 EL_ACID_POOL_BOTTOMLEFT,
1435 EL_ACID_POOL_BOTTOM,
1436 EL_ACID_POOL_BOTTOMRIGHT,
1437 EL_SP_HARDWARE_GRAY,
1438 EL_SP_HARDWARE_GREEN,
1439 EL_SP_HARDWARE_BLUE,
1441 EL_SP_HARDWARE_YELLOW,
1442 EL_SP_HARDWARE_BASE_1,
1443 EL_SP_HARDWARE_BASE_2,
1444 EL_SP_HARDWARE_BASE_3,
1445 EL_SP_HARDWARE_BASE_4,
1446 EL_SP_HARDWARE_BASE_5,
1447 EL_SP_HARDWARE_BASE_6,
1448 EL_INVISIBLE_STEELWALL,
1449 EL_INVISIBLE_STEELWALL_ACTIVE,
1450 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1451 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1452 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1453 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1454 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1455 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1456 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1457 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1458 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1459 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1460 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1461 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1463 EL_LIGHT_SWITCH_ACTIVE,
1464 EL_SIGN_EXCLAMATION,
1465 EL_SIGN_RADIOACTIVITY,
1476 EL_STEELWALL_SLIPPERY,
1499 EL_SWITCHGATE_OPENING,
1500 EL_SWITCHGATE_CLOSED,
1501 EL_SWITCHGATE_CLOSING,
1503 EL_SWITCHGATE_SWITCH_UP,
1504 EL_SWITCHGATE_SWITCH_DOWN,
1507 EL_TIMEGATE_OPENING,
1509 EL_TIMEGATE_CLOSING,
1512 EL_TIMEGATE_SWITCH_ACTIVE,
1517 EL_TUBE_VERTICAL_LEFT,
1518 EL_TUBE_VERTICAL_RIGHT,
1519 EL_TUBE_HORIZONTAL_UP,
1520 EL_TUBE_HORIZONTAL_DOWN,
1528 static int ep_slippery[] =
1542 EL_ROBOT_WHEEL_ACTIVE,
1548 EL_ACID_POOL_TOPLEFT,
1549 EL_ACID_POOL_TOPRIGHT,
1559 EL_STEELWALL_SLIPPERY,
1565 static int ep_can_change[] =
1570 static int ep_can_move[] =
1592 static int ep_can_fall[] =
1607 EL_BD_MAGIC_WALL_FULL,
1620 static int ep_can_smash_player[] =
1645 static int ep_can_smash_enemies[] =
1653 static int ep_can_smash_everything[] =
1661 static int ep_can_explode_by_fire[] =
1663 /* same elements as in 'ep_can_explode_impact' */
1668 /* same elements as in 'ep_can_explode_smashed' */
1677 EL_DYNABOMB_PLAYER_1_ACTIVE,
1678 EL_DYNABOMB_PLAYER_2_ACTIVE,
1679 EL_DYNABOMB_PLAYER_3_ACTIVE,
1680 EL_DYNABOMB_PLAYER_4_ACTIVE,
1681 EL_DYNABOMB_INCREASE_NUMBER,
1682 EL_DYNABOMB_INCREASE_SIZE,
1683 EL_DYNABOMB_INCREASE_POWER,
1684 EL_SP_DISK_RED_ACTIVE,
1694 static int ep_can_explode_smashed[] =
1696 /* same elements as in 'ep_can_explode_impact' */
1709 static int ep_can_explode_impact[] =
1717 static int ep_walkable_over[] =
1721 EL_SOKOBAN_FIELD_EMPTY,
1738 static int ep_walkable_inside[] =
1743 EL_TUBE_VERTICAL_LEFT,
1744 EL_TUBE_VERTICAL_RIGHT,
1745 EL_TUBE_HORIZONTAL_UP,
1746 EL_TUBE_HORIZONTAL_DOWN,
1754 static int ep_walkable_under[] =
1759 static int ep_passable_over[] =
1774 static int ep_passable_inside[] =
1780 EL_SP_PORT_HORIZONTAL,
1781 EL_SP_PORT_VERTICAL,
1783 EL_SP_GRAVITY_PORT_LEFT,
1784 EL_SP_GRAVITY_PORT_RIGHT,
1785 EL_SP_GRAVITY_PORT_UP,
1786 EL_SP_GRAVITY_PORT_DOWN,
1790 static int ep_passable_under[] =
1795 static int ep_droppable[] =
1800 static int ep_can_explode_1x1[] =
1805 static int ep_pushable[] =
1817 EL_SOKOBAN_FIELD_FULL,
1824 static int ep_player[] =
1834 static int ep_can_pass_magic_wall[] =
1847 static int ep_switchable[] =
1851 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1852 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1853 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1854 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1855 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1856 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1857 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1858 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1859 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1860 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1861 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1862 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1863 EL_SWITCHGATE_SWITCH_UP,
1864 EL_SWITCHGATE_SWITCH_DOWN,
1866 EL_LIGHT_SWITCH_ACTIVE,
1868 EL_BALLOON_SWITCH_LEFT,
1869 EL_BALLOON_SWITCH_RIGHT,
1870 EL_BALLOON_SWITCH_UP,
1871 EL_BALLOON_SWITCH_DOWN,
1872 EL_BALLOON_SWITCH_ANY,
1878 static int ep_bd_element[] =
1907 static int ep_sp_element[] =
1909 /* should always be valid */
1918 EL_SP_HARDWARE_GRAY,
1926 EL_SP_GRAVITY_PORT_RIGHT,
1927 EL_SP_GRAVITY_PORT_DOWN,
1928 EL_SP_GRAVITY_PORT_LEFT,
1929 EL_SP_GRAVITY_PORT_UP,
1934 EL_SP_PORT_VERTICAL,
1935 EL_SP_PORT_HORIZONTAL,
1941 EL_SP_HARDWARE_BASE_1,
1942 EL_SP_HARDWARE_GREEN,
1943 EL_SP_HARDWARE_BLUE,
1945 EL_SP_HARDWARE_YELLOW,
1946 EL_SP_HARDWARE_BASE_2,
1947 EL_SP_HARDWARE_BASE_3,
1948 EL_SP_HARDWARE_BASE_4,
1949 EL_SP_HARDWARE_BASE_5,
1950 EL_SP_HARDWARE_BASE_6,
1953 /* additional elements that appeared in newer Supaplex levels */
1955 /* more than one murphy in a level results in an inactive clone */
1957 /* runtime elements*/
1958 EL_SP_DISK_RED_ACTIVE,
1959 EL_SP_TERMINAL_ACTIVE,
1960 EL_SP_BUGGY_BASE_ACTIVATING,
1961 EL_SP_BUGGY_BASE_ACTIVE,
1965 static int ep_sb_element[] =
1970 EL_SOKOBAN_FIELD_EMPTY,
1971 EL_SOKOBAN_FIELD_FULL,
1973 EL_INVISIBLE_STEELWALL,
1977 static int ep_gem[] =
1988 static int ep_food_dark_yamyam[] =
2015 static int ep_food_penguin[] =
2028 static int ep_food_pig[] =
2039 static int ep_historic_wall[] =
2064 EL_EXPANDABLE_WALL_HORIZONTAL,
2065 EL_EXPANDABLE_WALL_VERTICAL,
2066 EL_EXPANDABLE_WALL_ANY,
2067 EL_EXPANDABLE_WALL_GROWING,
2074 EL_SP_HARDWARE_GRAY,
2075 EL_SP_HARDWARE_GREEN,
2076 EL_SP_HARDWARE_BLUE,
2078 EL_SP_HARDWARE_YELLOW,
2079 EL_SP_HARDWARE_BASE_1,
2080 EL_SP_HARDWARE_BASE_2,
2081 EL_SP_HARDWARE_BASE_3,
2082 EL_SP_HARDWARE_BASE_4,
2083 EL_SP_HARDWARE_BASE_5,
2084 EL_SP_HARDWARE_BASE_6,
2086 EL_SP_TERMINAL_ACTIVE,
2089 EL_INVISIBLE_STEELWALL,
2090 EL_INVISIBLE_STEELWALL_ACTIVE,
2092 EL_INVISIBLE_WALL_ACTIVE,
2093 EL_STEELWALL_SLIPPERY,
2109 static int ep_historic_solid[] =
2113 EL_EXPANDABLE_WALL_HORIZONTAL,
2114 EL_EXPANDABLE_WALL_VERTICAL,
2115 EL_EXPANDABLE_WALL_ANY,
2128 EL_QUICKSAND_FILLING,
2129 EL_QUICKSAND_EMPTYING,
2131 EL_MAGIC_WALL_ACTIVE,
2132 EL_MAGIC_WALL_EMPTYING,
2133 EL_MAGIC_WALL_FILLING,
2137 EL_BD_MAGIC_WALL_ACTIVE,
2138 EL_BD_MAGIC_WALL_EMPTYING,
2139 EL_BD_MAGIC_WALL_FULL,
2140 EL_BD_MAGIC_WALL_FILLING,
2141 EL_BD_MAGIC_WALL_DEAD,
2150 EL_SP_TERMINAL_ACTIVE,
2154 EL_INVISIBLE_WALL_ACTIVE,
2155 EL_SWITCHGATE_SWITCH_UP,
2156 EL_SWITCHGATE_SWITCH_DOWN,
2158 EL_TIMEGATE_SWITCH_ACTIVE,
2170 /* the following elements are a direct copy of "indestructible" elements,
2171 except "EL_ACID", which is "indestructible", but not "solid"! */
2176 EL_ACID_POOL_TOPLEFT,
2177 EL_ACID_POOL_TOPRIGHT,
2178 EL_ACID_POOL_BOTTOMLEFT,
2179 EL_ACID_POOL_BOTTOM,
2180 EL_ACID_POOL_BOTTOMRIGHT,
2181 EL_SP_HARDWARE_GRAY,
2182 EL_SP_HARDWARE_GREEN,
2183 EL_SP_HARDWARE_BLUE,
2185 EL_SP_HARDWARE_YELLOW,
2186 EL_SP_HARDWARE_BASE_1,
2187 EL_SP_HARDWARE_BASE_2,
2188 EL_SP_HARDWARE_BASE_3,
2189 EL_SP_HARDWARE_BASE_4,
2190 EL_SP_HARDWARE_BASE_5,
2191 EL_SP_HARDWARE_BASE_6,
2192 EL_INVISIBLE_STEELWALL,
2193 EL_INVISIBLE_STEELWALL_ACTIVE,
2194 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2195 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2196 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2197 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2198 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2199 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2200 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2201 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2202 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2203 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2204 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2205 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2207 EL_LIGHT_SWITCH_ACTIVE,
2208 EL_SIGN_EXCLAMATION,
2209 EL_SIGN_RADIOACTIVITY,
2220 EL_STEELWALL_SLIPPERY,
2243 EL_SWITCHGATE_OPENING,
2244 EL_SWITCHGATE_CLOSED,
2245 EL_SWITCHGATE_CLOSING,
2247 EL_TIMEGATE_OPENING,
2249 EL_TIMEGATE_CLOSING,
2253 EL_TUBE_VERTICAL_LEFT,
2254 EL_TUBE_VERTICAL_RIGHT,
2255 EL_TUBE_HORIZONTAL_UP,
2256 EL_TUBE_HORIZONTAL_DOWN,
2264 static int ep_classic_enemy[] =
2280 static int ep_belt[] =
2282 EL_CONVEYOR_BELT_1_LEFT,
2283 EL_CONVEYOR_BELT_1_MIDDLE,
2284 EL_CONVEYOR_BELT_1_RIGHT,
2285 EL_CONVEYOR_BELT_2_LEFT,
2286 EL_CONVEYOR_BELT_2_MIDDLE,
2287 EL_CONVEYOR_BELT_2_RIGHT,
2288 EL_CONVEYOR_BELT_3_LEFT,
2289 EL_CONVEYOR_BELT_3_MIDDLE,
2290 EL_CONVEYOR_BELT_3_RIGHT,
2291 EL_CONVEYOR_BELT_4_LEFT,
2292 EL_CONVEYOR_BELT_4_MIDDLE,
2293 EL_CONVEYOR_BELT_4_RIGHT,
2297 static int ep_belt_active[] =
2299 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2300 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2301 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2302 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2303 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2304 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2305 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2306 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2307 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2308 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2309 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2310 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2314 static int ep_belt_switch[] =
2316 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2317 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2318 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2319 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2320 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2321 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2322 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2323 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2324 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2325 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2326 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2327 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2331 static int ep_tube[] =
2338 EL_TUBE_HORIZONTAL_UP,
2339 EL_TUBE_HORIZONTAL_DOWN,
2341 EL_TUBE_VERTICAL_LEFT,
2342 EL_TUBE_VERTICAL_RIGHT,
2347 static int ep_keygate[] =
2368 static int ep_amoeboid[] =
2378 static int ep_amoebalive[] =
2387 static int ep_has_content[] =
2397 static int ep_active_bomb[] =
2400 EL_DYNABOMB_PLAYER_1_ACTIVE,
2401 EL_DYNABOMB_PLAYER_2_ACTIVE,
2402 EL_DYNABOMB_PLAYER_3_ACTIVE,
2403 EL_DYNABOMB_PLAYER_4_ACTIVE,
2404 EL_SP_DISK_RED_ACTIVE,
2408 static int ep_inactive[] =
2445 EL_INVISIBLE_STEELWALL,
2453 EL_WALL_EMERALD_YELLOW,
2454 EL_DYNABOMB_INCREASE_NUMBER,
2455 EL_DYNABOMB_INCREASE_SIZE,
2456 EL_DYNABOMB_INCREASE_POWER,
2460 EL_SOKOBAN_FIELD_EMPTY,
2461 EL_SOKOBAN_FIELD_FULL,
2462 EL_WALL_EMERALD_RED,
2463 EL_WALL_EMERALD_PURPLE,
2464 EL_ACID_POOL_TOPLEFT,
2465 EL_ACID_POOL_TOPRIGHT,
2466 EL_ACID_POOL_BOTTOMLEFT,
2467 EL_ACID_POOL_BOTTOM,
2468 EL_ACID_POOL_BOTTOMRIGHT,
2472 EL_BD_MAGIC_WALL_DEAD,
2473 EL_AMOEBA_TO_DIAMOND,
2481 EL_SP_GRAVITY_PORT_RIGHT,
2482 EL_SP_GRAVITY_PORT_DOWN,
2483 EL_SP_GRAVITY_PORT_LEFT,
2484 EL_SP_GRAVITY_PORT_UP,
2485 EL_SP_PORT_HORIZONTAL,
2486 EL_SP_PORT_VERTICAL,
2497 EL_SP_HARDWARE_GRAY,
2498 EL_SP_HARDWARE_GREEN,
2499 EL_SP_HARDWARE_BLUE,
2501 EL_SP_HARDWARE_YELLOW,
2502 EL_SP_HARDWARE_BASE_1,
2503 EL_SP_HARDWARE_BASE_2,
2504 EL_SP_HARDWARE_BASE_3,
2505 EL_SP_HARDWARE_BASE_4,
2506 EL_SP_HARDWARE_BASE_5,
2507 EL_SP_HARDWARE_BASE_6,
2508 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2509 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2510 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2511 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2512 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2513 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2514 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2515 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2516 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2517 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2518 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2519 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2520 EL_SIGN_EXCLAMATION,
2521 EL_SIGN_RADIOACTIVITY,
2532 EL_STEELWALL_SLIPPERY,
2548 static int ep_em_slippery_wall[] =
2553 static int ep_gfx_crumbled[] =
2566 } element_properties[] =
2568 { ep_diggable, EP_DIGGABLE },
2569 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2570 { ep_dont_run_into, EP_DONT_RUN_INTO },
2571 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2572 { ep_dont_touch, EP_DONT_TOUCH },
2573 { ep_indestructible, EP_INDESTRUCTIBLE },
2574 { ep_slippery, EP_SLIPPERY },
2575 { ep_can_change, EP_CAN_CHANGE },
2576 { ep_can_move, EP_CAN_MOVE },
2577 { ep_can_fall, EP_CAN_FALL },
2578 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2579 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2580 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2581 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2582 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2583 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2584 { ep_walkable_over, EP_WALKABLE_OVER },
2585 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2586 { ep_walkable_under, EP_WALKABLE_UNDER },
2587 { ep_passable_over, EP_PASSABLE_OVER },
2588 { ep_passable_inside, EP_PASSABLE_INSIDE },
2589 { ep_passable_under, EP_PASSABLE_UNDER },
2590 { ep_droppable, EP_DROPPABLE },
2591 { ep_can_explode_1x1, EP_CAN_EXPLODE_1X1 },
2592 { ep_pushable, EP_PUSHABLE },
2594 { ep_player, EP_PLAYER },
2595 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2596 { ep_switchable, EP_SWITCHABLE },
2597 { ep_bd_element, EP_BD_ELEMENT },
2598 { ep_sp_element, EP_SP_ELEMENT },
2599 { ep_sb_element, EP_SB_ELEMENT },
2601 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2602 { ep_food_penguin, EP_FOOD_PENGUIN },
2603 { ep_food_pig, EP_FOOD_PIG },
2604 { ep_historic_wall, EP_HISTORIC_WALL },
2605 { ep_historic_solid, EP_HISTORIC_SOLID },
2606 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2607 { ep_belt, EP_BELT },
2608 { ep_belt_active, EP_BELT_ACTIVE },
2609 { ep_belt_switch, EP_BELT_SWITCH },
2610 { ep_tube, EP_TUBE },
2611 { ep_keygate, EP_KEYGATE },
2612 { ep_amoeboid, EP_AMOEBOID },
2613 { ep_amoebalive, EP_AMOEBALIVE },
2614 { ep_has_content, EP_HAS_CONTENT },
2615 { ep_active_bomb, EP_ACTIVE_BOMB },
2616 { ep_inactive, EP_INACTIVE },
2618 { ep_em_slippery_wall, EP_EM_SLIPPERY_WALL },
2620 { ep_gfx_crumbled, EP_GFX_CRUMBLED },
2625 static int copy_properties[][5] =
2629 EL_BUG_LEFT, EL_BUG_RIGHT,
2630 EL_BUG_UP, EL_BUG_DOWN
2634 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2635 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2639 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2640 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2644 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2645 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2649 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2650 EL_PACMAN_UP, EL_PACMAN_DOWN
2660 /* always start with reliable default values (element has no properties) */
2661 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2662 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2663 SET_PROPERTY(i, j, FALSE);
2665 /* set all base element properties from above array definitions */
2666 for (i=0; element_properties[i].elements != NULL; i++)
2667 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2668 SET_PROPERTY((element_properties[i].elements)[j],
2669 element_properties[i].property, TRUE);
2671 /* copy properties to some elements that are only stored in level file */
2672 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2673 for (j=0; copy_properties[j][0] != -1; j++)
2674 if (HAS_PROPERTY(copy_properties[j][0], i))
2675 for (k=1; k<=4; k++)
2676 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2679 void InitElementPropertiesEngine(int engine_version)
2682 static int active_properties[] =
2687 EP_DONT_COLLIDE_WITH,
2691 EP_CAN_PASS_MAGIC_WALL,
2696 EP_CAN_EXPLODE_BY_FIRE,
2709 EP_EM_SLIPPERY_WALL,
2713 static int no_wall_properties[] =
2716 EP_COLLECTIBLE_ONLY,
2718 EP_DONT_COLLIDE_WITH,
2721 EP_CAN_SMASH_PLAYER,
2722 EP_CAN_SMASH_ENEMIES,
2723 EP_CAN_SMASH_EVERYTHING,
2728 EP_FOOD_DARK_YAMYAM,
2744 InitElementPropertiesStatic();
2747 /* set all special, combined or engine dependent element properties */
2748 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2751 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2752 SET_PROPERTY(i, j, FALSE);
2755 /* ---------- INACTIVE ------------------------------------------------- */
2756 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2757 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2759 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2760 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2761 IS_WALKABLE_INSIDE(i) ||
2762 IS_WALKABLE_UNDER(i)));
2764 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2765 IS_PASSABLE_INSIDE(i) ||
2766 IS_PASSABLE_UNDER(i)));
2768 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2769 IS_PASSABLE_OVER(i)));
2771 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2772 IS_PASSABLE_INSIDE(i)));
2774 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2775 IS_PASSABLE_UNDER(i)));
2777 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2780 /* ---------- COLLECTIBLE ---------------------------------------------- */
2781 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2784 /* ---------- SNAPPABLE ------------------------------------------------ */
2785 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2786 IS_COLLECTIBLE(i) ||
2790 /* ---------- WALL ----------------------------------------------------- */
2791 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2793 for (j=0; no_wall_properties[j] != -1; j++)
2794 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2795 i >= EL_FIRST_RUNTIME_UNREAL)
2796 SET_PROPERTY(i, EP_WALL, FALSE);
2798 if (IS_HISTORIC_WALL(i))
2799 SET_PROPERTY(i, EP_WALL, TRUE);
2801 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2802 if (engine_version < VERSION_IDENT(2,2,0))
2803 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2805 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2807 !IS_COLLECTIBLE(i)));
2809 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2811 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2812 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2814 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2815 IS_INDESTRUCTIBLE(i)));
2817 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2819 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2820 else if (engine_version < VERSION_IDENT(2,2,0))
2821 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2823 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2824 !IS_WALKABLE_OVER(i) &&
2825 !IS_WALKABLE_UNDER(i)));
2827 if (IS_CUSTOM_ELEMENT(i))
2829 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2831 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2832 if (DONT_COLLIDE_WITH(i))
2833 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2835 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2836 if (CAN_SMASH_EVERYTHING(i))
2837 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2838 if (CAN_SMASH_ENEMIES(i))
2839 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2842 /* ---------- CAN_SMASH ------------------------------------------------ */
2843 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2844 CAN_SMASH_ENEMIES(i) ||
2845 CAN_SMASH_EVERYTHING(i)));
2847 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2848 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2849 CAN_EXPLODE_SMASHED(i) ||
2850 CAN_EXPLODE_IMPACT(i)));
2852 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2853 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2854 !CAN_EXPLODE_1X1(i)));
2856 /* ---------- CAN_CHANGE ----------------------------------------------- */
2857 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
2858 for (j=0; j < element_info[i].num_change_pages; j++)
2859 if (element_info[i].change_page[j].can_change)
2860 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
2862 /* ---------- GFX_CRUMBLED --------------------------------------------- */
2863 SET_PROPERTY(i, EP_GFX_CRUMBLED,
2864 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2868 /* determine inactive elements (used for engine main loop optimization) */
2869 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2871 boolean active = FALSE;
2873 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2875 if (HAS_PROPERTY(i, j))
2881 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2886 /* dynamically adjust element properties according to game engine version */
2888 static int ep_em_slippery_wall[] =
2893 EL_EXPANDABLE_WALL_HORIZONTAL,
2894 EL_EXPANDABLE_WALL_VERTICAL,
2895 EL_EXPANDABLE_WALL_ANY,
2899 /* special EM style gems behaviour */
2900 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2901 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2902 level.em_slippery_gems);
2904 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2905 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2906 (level.em_slippery_gems &&
2907 engine_version > VERSION_IDENT(2,0,1)));
2911 /* dynamically adjust element properties according to game engine version */
2913 if (engine_version < RELEASE_IDENT(2,2,0,7))
2916 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2918 int element = EL_CUSTOM_START + i;
2920 element_info[element].push_delay_fixed = 2;
2921 element_info[element].push_delay_random = 8;
2927 static void InitGlobal()
2929 global.autoplay_leveldir = NULL;
2931 global.frames_per_second = 0;
2932 global.fps_slowdown = FALSE;
2933 global.fps_slowdown_factor = 1;
2936 void Execute_Command(char *command)
2938 if (strcmp(command, "print graphicsinfo.conf") == 0)
2942 printf("# You can configure additional/alternative image files here.\n");
2943 printf("# (The images below are default and therefore commented out.)\n");
2945 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2947 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2950 for (i=0; image_config[i].token != NULL; i++)
2952 getFormattedSetupEntry(image_config[i].token,
2953 image_config[i].value));
2957 else if (strcmp(command, "print soundsinfo.conf") == 0)
2961 printf("# You can configure additional/alternative sound files here.\n");
2962 printf("# (The sounds below are default and therefore commented out.)\n");
2964 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2966 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2969 for (i=0; sound_config[i].token != NULL; i++)
2971 getFormattedSetupEntry(sound_config[i].token,
2972 sound_config[i].value));
2976 else if (strcmp(command, "print musicinfo.conf") == 0)
2978 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2980 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2982 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2986 else if (strncmp(command, "dump level ", 11) == 0)
2988 char *filename = &command[11];
2990 if (access(filename, F_OK) != 0)
2991 Error(ERR_EXIT, "cannot open file '%s'", filename);
2993 LoadLevelFromFilename(&level, filename);
2998 else if (strncmp(command, "dump tape ", 10) == 0)
3000 char *filename = &command[10];
3002 if (access(filename, F_OK) != 0)
3003 Error(ERR_EXIT, "cannot open file '%s'", filename);
3005 LoadTapeFromFilename(filename);
3010 else if (strncmp(command, "autoplay ", 9) == 0)
3012 char *str_copy = getStringCopy(&command[9]);
3013 char *str_ptr = strchr(str_copy, ' ');
3015 global.autoplay_leveldir = str_copy;
3016 global.autoplay_level_nr = -1;
3018 if (str_ptr != NULL)
3020 *str_ptr++ = '\0'; /* terminate leveldir string */
3021 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3026 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3030 static void InitSetup()
3032 LoadSetup(); /* global setup info */
3034 /* set some options from setup file */
3036 if (setup.options.verbose)
3037 options.verbose = TRUE;
3040 static void InitPlayerInfo()
3044 /* choose default local player */
3045 local_player = &stored_player[0];
3047 for (i=0; i<MAX_PLAYERS; i++)
3048 stored_player[i].connected = FALSE;
3050 local_player->connected = TRUE;
3053 static void InitArtworkInfo()
3058 static char *get_string_in_brackets(char *string)
3060 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3062 sprintf(string_in_brackets, "[%s]", string);
3064 return string_in_brackets;
3068 static char *get_element_class_token(int element)
3070 char *element_class_name = element_info[element].class_name;
3071 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3073 sprintf(element_class_token, "[%s]", element_class_name);
3075 return element_class_token;
3078 static char *get_action_class_token(int action)
3080 char *action_class_name = &element_action_info[action].suffix[1];
3081 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3083 sprintf(action_class_token, "[%s]", action_class_name);
3085 return action_class_token;
3089 static void InitArtworkConfig()
3091 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3092 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3093 static char *action_id_suffix[NUM_ACTIONS + 1];
3094 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3095 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3096 static char *dummy[1] = { NULL };
3097 static char *ignore_generic_tokens[] =
3103 static char **ignore_image_tokens, **ignore_sound_tokens;
3104 int num_ignore_generic_tokens;
3105 int num_ignore_image_tokens, num_ignore_sound_tokens;
3108 /* dynamically determine list of generic tokens to be ignored */
3109 num_ignore_generic_tokens = 0;
3110 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3111 num_ignore_generic_tokens++;
3113 /* dynamically determine list of image tokens to be ignored */
3114 num_ignore_image_tokens = num_ignore_generic_tokens;
3115 for (i=0; image_config_vars[i].token != NULL; i++)
3116 num_ignore_image_tokens++;
3117 ignore_image_tokens =
3118 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3119 for (i=0; i < num_ignore_generic_tokens; i++)
3120 ignore_image_tokens[i] = ignore_generic_tokens[i];
3121 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3122 ignore_image_tokens[num_ignore_generic_tokens + i] =
3123 image_config_vars[i].token;
3124 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3126 /* dynamically determine list of sound tokens to be ignored */
3127 num_ignore_sound_tokens = num_ignore_generic_tokens;
3128 ignore_sound_tokens =
3129 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3130 for (i=0; i < num_ignore_generic_tokens; i++)
3131 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3132 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3134 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3135 image_id_prefix[i] = element_info[i].token_name;
3136 for (i=0; i<NUM_FONTS; i++)
3137 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3138 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3140 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3141 sound_id_prefix[i] = element_info[i].token_name;
3142 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3143 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3144 get_string_in_brackets(element_info[i].class_name);
3145 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3147 for (i=0; i<NUM_ACTIONS; i++)
3148 action_id_suffix[i] = element_action_info[i].suffix;
3149 action_id_suffix[NUM_ACTIONS] = NULL;
3151 for (i=0; i<NUM_DIRECTIONS; i++)
3152 direction_id_suffix[i] = element_direction_info[i].suffix;
3153 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3155 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3156 special_id_suffix[i] = special_suffix_info[i].suffix;
3157 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3159 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3160 image_id_prefix, action_id_suffix, direction_id_suffix,
3161 special_id_suffix, ignore_image_tokens);
3162 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3163 sound_id_prefix, action_id_suffix, dummy,
3164 special_id_suffix, ignore_sound_tokens);
3167 static void InitMixer()
3175 char *filename_font_initial = NULL;
3176 Bitmap *bitmap_font_initial = NULL;
3179 /* determine settings for initial font (for displaying startup messages) */
3180 for (i=0; image_config[i].token != NULL; i++)
3182 for (j=0; j < NUM_INITIAL_FONTS; j++)
3184 char font_token[128];
3187 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3188 len_font_token = strlen(font_token);
3190 if (strcmp(image_config[i].token, font_token) == 0)
3191 filename_font_initial = image_config[i].value;
3192 else if (strlen(image_config[i].token) > len_font_token &&
3193 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3195 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3196 font_initial[j].src_x = atoi(image_config[i].value);
3197 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3198 font_initial[j].src_y = atoi(image_config[i].value);
3199 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3200 font_initial[j].width = atoi(image_config[i].value);
3201 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3202 font_initial[j].height = atoi(image_config[i].value);
3207 for (j=0; j < NUM_INITIAL_FONTS; j++)
3209 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3210 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3213 if (filename_font_initial == NULL) /* should not happen */
3214 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3216 /* create additional image buffers for double-buffering */
3217 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3218 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3220 /* initialize screen properties */
3221 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3222 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3224 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3225 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3226 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3228 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3230 for (j=0; j < NUM_INITIAL_FONTS; j++)
3231 font_initial[j].bitmap = bitmap_font_initial;
3233 InitFontGraphicInfo();
3235 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3236 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3238 DrawInitText("Loading graphics:", 120, FC_GREEN);
3240 InitTileClipmasks();
3243 void InitGfxBackground()
3247 drawto = backbuffer;
3248 fieldbuffer = bitmap_db_field;
3249 SetDrawtoField(DRAW_BACKBUFFER);
3251 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3252 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3253 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3254 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3256 for (x=0; x<MAX_BUF_XSIZE; x++)
3257 for (y=0; y<MAX_BUF_YSIZE; y++)
3260 redraw_mask = REDRAW_ALL;
3263 static void InitLevelInfo()
3265 LoadLevelInfo(); /* global level info */
3266 LoadLevelSetup_LastSeries(); /* last played series info */
3267 LoadLevelSetup_SeriesInfo(); /* last played level info */
3270 void InitLevelArtworkInfo()
3272 LoadLevelArtworkInfo();
3275 static void InitImages()
3278 setLevelArtworkDir(artwork.gfx_first);
3282 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3283 leveldir_current->identifier,
3284 artwork.gfx_current_identifier,
3285 artwork.gfx_current->identifier,
3286 leveldir_current->graphics_set,
3287 leveldir_current->graphics_path);
3290 ReloadCustomImages();
3292 LoadCustomElementDescriptions();
3293 LoadSpecialMenuDesignSettings();
3295 ReinitializeGraphics();
3298 static void InitSound(char *identifier)
3300 if (identifier == NULL)
3301 identifier = artwork.snd_current->identifier;
3304 /* set artwork path to send it to the sound server process */
3305 setLevelArtworkDir(artwork.snd_first);
3308 InitReloadCustomSounds(identifier);
3309 ReinitializeSounds();
3312 static void InitMusic(char *identifier)
3314 if (identifier == NULL)
3315 identifier = artwork.mus_current->identifier;
3318 /* set artwork path to send it to the sound server process */
3319 setLevelArtworkDir(artwork.mus_first);
3322 InitReloadCustomMusic(identifier);
3323 ReinitializeMusic();
3326 void InitNetworkServer()
3328 #if defined(PLATFORM_UNIX)
3332 if (!options.network)
3335 #if defined(PLATFORM_UNIX)
3336 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3338 if (!ConnectToServer(options.server_host, options.server_port))
3339 Error(ERR_EXIT, "cannot connect to network game server");
3341 SendToServer_PlayerName(setup.player_name);
3342 SendToServer_ProtocolVersion();
3345 SendToServer_NrWanted(nr_wanted);
3349 static char *getNewArtworkIdentifier(int type)
3351 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3352 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3353 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3354 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3355 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3356 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3357 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3358 char *leveldir_identifier = leveldir_current->identifier;
3360 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3361 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3363 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3365 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3366 char *artwork_current_identifier;
3367 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3369 /* leveldir_current may be invalid (level group, parent link) */
3370 if (!validLevelSeries(leveldir_current))
3373 /* 1st step: determine artwork set to be activated in descending order:
3374 --------------------------------------------------------------------
3375 1. setup artwork (when configured to override everything else)
3376 2. artwork set configured in "levelinfo.conf" of current level set
3377 (artwork in level directory will have priority when loading later)
3378 3. artwork in level directory (stored in artwork sub-directory)
3379 4. setup artwork (currently configured in setup menu) */
3381 if (setup_override_artwork)
3382 artwork_current_identifier = setup_artwork_set;
3383 else if (leveldir_artwork_set != NULL)
3384 artwork_current_identifier = leveldir_artwork_set;
3385 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3386 artwork_current_identifier = leveldir_identifier;
3388 artwork_current_identifier = setup_artwork_set;
3391 /* 2nd step: check if it is really needed to reload artwork set
3392 ------------------------------------------------------------ */
3395 if (type == ARTWORK_TYPE_GRAPHICS)
3396 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3397 artwork_new_identifier,
3398 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3399 artwork_current_identifier,
3400 leveldir_current->graphics_set,
3401 leveldir_current->identifier);
3404 /* ---------- reload if level set and also artwork set has changed ------- */
3405 if (leveldir_current_identifier[type] != leveldir_identifier &&
3406 (last_has_level_artwork_set[type] || has_level_artwork_set))
3407 artwork_new_identifier = artwork_current_identifier;
3409 leveldir_current_identifier[type] = leveldir_identifier;
3410 last_has_level_artwork_set[type] = has_level_artwork_set;
3413 if (type == ARTWORK_TYPE_GRAPHICS)
3414 printf("::: 1: '%s'\n", artwork_new_identifier);
3417 /* ---------- reload if "override artwork" setting has changed ----------- */
3418 if (last_override_level_artwork[type] != setup_override_artwork)
3419 artwork_new_identifier = artwork_current_identifier;
3421 last_override_level_artwork[type] = setup_override_artwork;
3424 if (type == ARTWORK_TYPE_GRAPHICS)
3425 printf("::: 2: '%s'\n", artwork_new_identifier);
3428 /* ---------- reload if current artwork identifier has changed ----------- */
3429 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3430 artwork_current_identifier) != 0)
3431 artwork_new_identifier = artwork_current_identifier;
3433 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3436 if (type == ARTWORK_TYPE_GRAPHICS)
3437 printf("::: 3: '%s'\n", artwork_new_identifier);
3440 /* ---------- do not reload directly after starting ---------------------- */
3441 if (!initialized[type])
3442 artwork_new_identifier = NULL;
3444 initialized[type] = TRUE;
3447 if (type == ARTWORK_TYPE_GRAPHICS)
3448 printf("::: 4: '%s'\n", artwork_new_identifier);
3452 if (type == ARTWORK_TYPE_GRAPHICS)
3453 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3454 artwork.gfx_current_identifier, artwork_current_identifier,
3455 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3456 artwork_new_identifier);
3459 return artwork_new_identifier;
3462 void ReloadCustomArtwork()
3464 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3465 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3466 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3467 boolean redraw_screen = FALSE;
3469 if (gfx_new_identifier != NULL)
3472 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3473 artwork.gfx_current_identifier,
3475 artwork.gfx_current->identifier,
3476 leveldir_current->graphics_set);
3479 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3484 printf("... '%s'\n",
3485 leveldir_current->graphics_set);
3488 FreeTileClipmasks();
3489 InitTileClipmasks();
3491 redraw_screen = TRUE;
3494 if (snd_new_identifier != NULL)
3496 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3498 InitSound(snd_new_identifier);
3500 redraw_screen = TRUE;
3503 if (mus_new_identifier != NULL)
3505 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3507 InitMusic(mus_new_identifier);
3509 redraw_screen = TRUE;
3514 InitGfxBackground();
3516 /* force redraw of (open or closed) door graphics */
3517 SetDoorState(DOOR_OPEN_ALL);
3518 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3522 void KeyboardAutoRepeatOffUnlessAutoplay()
3524 if (global.autoplay_leveldir == NULL)
3525 KeyboardAutoRepeatOff();
3529 /* ========================================================================= */
3531 /* ========================================================================= */
3535 InitGlobal(); /* initialize some global variables */
3537 if (options.execute_command)
3538 Execute_Command(options.execute_command);
3540 if (options.serveronly)
3542 #if defined(PLATFORM_UNIX)
3543 NetworkServer(options.server_port, options.serveronly);
3545 Error(ERR_WARN, "networking only supported in Unix version");
3547 exit(0); /* never reached */
3553 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3554 InitArtworkConfig(); /* needed before forking sound child process */
3559 InitRND(NEW_RANDOMIZE);
3560 InitSimpleRND(NEW_RANDOMIZE);
3565 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3568 InitEventFilter(FilterMouseMotionEvents);
3570 InitElementPropertiesStatic();
3571 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3576 InitLevelArtworkInfo();
3578 InitImages(); /* needs to know current level directory */
3579 InitSound(NULL); /* needs to know current level directory */
3580 InitMusic(NULL); /* needs to know current level directory */
3582 InitGfxBackground();
3584 if (global.autoplay_leveldir)
3590 game_status = GAME_MODE_MAIN;
3594 InitNetworkServer();
3597 void CloseAllAndExit(int exit_value)
3602 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3605 FreeTileClipmasks();
3607 CloseVideoDisplay();
3608 ClosePlatformDependentStuff();