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 boolean special_envelope_graphic;
752 int parameter[NUM_GFX_ARGS];
753 int anim_frames_per_row = 1, anim_frames_per_col = 1;
754 int anim_frames_per_line = 1;
757 special_envelope_graphic = (graphic == IMG_GAME_ENVELOPE_BACKGROUND ||
758 (graphic >= IMG_GAME_ENVELOPE_1_BACKGROUND &&
759 graphic <= IMG_GAME_ENVELOPE_4_BACKGROUND));
761 /* get integer values from string parameters */
762 for (i=0; i < NUM_GFX_ARGS; i++)
765 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
766 image_config_suffix[i].type);
768 if (image_config_suffix[i].type == TYPE_TOKEN)
769 parameter[i] = get_element_from_token(parameter_raw[i]);
772 graphic_info[graphic].bitmap = src_bitmap;
774 /* start with reliable default values */
775 graphic_info[graphic].src_x = 0;
776 graphic_info[graphic].src_y = 0;
777 graphic_info[graphic].width = TILEX;
778 graphic_info[graphic].height = TILEY;
779 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
780 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
781 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
782 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
783 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
785 /* optional x and y tile position of animation frame sequence */
786 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
787 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
788 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
789 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
791 /* optional x and y pixel position of animation frame sequence */
792 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
793 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
794 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
795 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
797 /* optional width and height of each animation frame */
798 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
799 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
800 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
801 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
805 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
806 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
809 /* correct x or y offset dependent of vertical or horizontal frame order */
810 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
812 graphic_info[graphic].offset_y =
813 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
814 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
815 anim_frames_per_line = anim_frames_per_col;
817 else /* frames are ordered horizontally */
819 graphic_info[graphic].offset_x =
820 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
821 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
822 anim_frames_per_line = anim_frames_per_row;
825 /* optionally, the x and y offset of frames can be specified directly */
826 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
827 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
828 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
829 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
831 /* automatically determine correct number of frames, if not defined */
832 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
833 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
834 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
835 graphic_info[graphic].anim_frames = anim_frames_per_row;
836 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
837 graphic_info[graphic].anim_frames = anim_frames_per_col;
839 graphic_info[graphic].anim_frames = 1;
841 graphic_info[graphic].anim_frames_per_line =
842 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
843 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
845 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
846 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
847 graphic_info[graphic].anim_delay = 1;
849 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
850 if (graphic_info[graphic].anim_frames == 1 && !special_envelope_graphic)
851 graphic_info[graphic].anim_mode = ANIM_NONE;
853 /* automatically determine correct start frame, if not defined */
854 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
855 graphic_info[graphic].anim_start_frame = 0;
856 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
857 graphic_info[graphic].anim_start_frame =
858 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
860 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
862 /* animation synchronized with global frame counter, not move position */
863 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
865 /* optional element for cloning crumble graphics */
866 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
867 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
869 /* optional element for cloning digging graphics */
870 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
871 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
873 /* optional border size for "crumbling" diggable graphics */
874 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
875 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
877 /* this is only used for toon animations */
878 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
879 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
881 /* this is only used for drawing font characters */
882 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
883 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
885 /* this is only used for drawing envelope graphics */
886 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
888 /* global envelope settings override specific settings, if undefined */
889 if (special_envelope_graphic && graphic_info[graphic].bitmap == NULL)
890 graphic_info[graphic] = graphic_info[IMG_GAME_ENVELOPE_BACKGROUND];
893 static void InitGraphicInfo()
895 int fallback_graphic = IMG_CHAR_EXCLAM;
896 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
897 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
898 int num_images = getImageListSize();
901 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
902 static boolean clipmasks_initialized = FALSE;
904 XGCValues clip_gc_values;
905 unsigned long clip_gc_valuemask;
906 GC copy_clipmask_gc = None;
909 if (graphic_info != NULL)
912 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
915 printf("::: graphic_info: %d entries\n", num_images);
918 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
919 if (clipmasks_initialized)
921 for (i=0; i<num_images; i++)
923 if (graphic_info[i].clip_mask)
924 XFreePixmap(display, graphic_info[i].clip_mask);
925 if (graphic_info[i].clip_gc)
926 XFreeGC(display, graphic_info[i].clip_gc);
928 graphic_info[i].clip_mask = None;
929 graphic_info[i].clip_gc = None;
934 for (i=0; i<num_images; i++)
936 struct FileInfo *image = getImageListEntry(i);
939 int first_frame, last_frame;
942 printf("::: image: '%s' [%d]\n", image->token, i);
946 printf("::: image # %d: '%s' ['%s']\n",
948 getTokenFromImageID(i));
951 set_graphic_parameters(i, image->parameter);
953 /* now check if no animation frames are outside of the loaded image */
955 if (graphic_info[i].bitmap == NULL)
956 continue; /* skip check for optional images that are undefined */
959 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
960 if (src_x < 0 || src_y < 0 ||
961 src_x + TILEX > src_bitmap->width ||
962 src_y + TILEY > src_bitmap->height)
964 Error(ERR_RETURN_LINE, "-");
965 Error(ERR_RETURN, "warning: error found in config file:");
966 Error(ERR_RETURN, "- config file: '%s'",
967 getImageConfigFilename());
968 Error(ERR_RETURN, "- config token: '%s'",
969 getTokenFromImageID(i));
970 Error(ERR_RETURN, "- image file: '%s'",
971 src_bitmap->source_filename);
973 "error: first animation frame out of bounds (%d, %d)",
975 Error(ERR_RETURN, "custom graphic rejected for this element/action");
977 if (i == fallback_graphic)
978 Error(ERR_EXIT, "fatal error: no fallback graphic available");
980 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
981 Error(ERR_RETURN_LINE, "-");
983 set_graphic_parameters(i, fallback_image->default_parameter);
984 graphic_info[i].bitmap = fallback_bitmap;
987 last_frame = graphic_info[i].anim_frames - 1;
988 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
989 if (src_x < 0 || src_y < 0 ||
990 src_x + TILEX > src_bitmap->width ||
991 src_y + TILEY > src_bitmap->height)
993 Error(ERR_RETURN_LINE, "-");
994 Error(ERR_RETURN, "warning: error found in config file:");
995 Error(ERR_RETURN, "- config file: '%s'",
996 getImageConfigFilename());
997 Error(ERR_RETURN, "- config token: '%s'",
998 getTokenFromImageID(i));
999 Error(ERR_RETURN, "- image file: '%s'",
1000 src_bitmap->source_filename);
1002 "error: last animation frame (%d) out of bounds (%d, %d)",
1003 last_frame, src_x, src_y);
1004 Error(ERR_RETURN, "custom graphic rejected for this element/action");
1006 if (i == fallback_graphic)
1007 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1009 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1010 Error(ERR_RETURN_LINE, "-");
1012 set_graphic_parameters(i, fallback_image->default_parameter);
1013 graphic_info[i].bitmap = fallback_bitmap;
1016 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1017 /* currently we need only a tile clip mask from the first frame */
1018 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1020 if (copy_clipmask_gc == None)
1022 clip_gc_values.graphics_exposures = False;
1023 clip_gc_valuemask = GCGraphicsExposures;
1024 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1025 clip_gc_valuemask, &clip_gc_values);
1028 graphic_info[i].clip_mask =
1029 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1031 src_pixmap = src_bitmap->clip_mask;
1032 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1033 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1035 clip_gc_values.graphics_exposures = False;
1036 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1037 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1039 graphic_info[i].clip_gc =
1040 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1044 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1045 if (copy_clipmask_gc)
1046 XFreeGC(display, copy_clipmask_gc);
1048 clipmasks_initialized = TRUE;
1052 static void InitElementSoundInfo()
1054 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1055 int num_property_mappings = getSoundListPropertyMappingSize();
1058 /* set values to -1 to identify later as "uninitialized" values */
1059 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1060 for (act=0; act < NUM_ACTIONS; act++)
1061 element_info[i].sound[act] = -1;
1063 /* initialize element/sound mapping from static configuration */
1064 for (i=0; element_to_sound[i].element > -1; i++)
1066 int element = element_to_sound[i].element;
1067 int action = element_to_sound[i].action;
1068 int sound = element_to_sound[i].sound;
1069 boolean is_class = element_to_sound[i].is_class;
1072 action = ACTION_DEFAULT;
1075 element_info[element].sound[action] = sound;
1077 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1078 if (strcmp(element_info[j].class_name,
1079 element_info[element].class_name) == 0)
1080 element_info[j].sound[action] = sound;
1083 /* initialize element class/sound mapping from dynamic configuration */
1084 for (i=0; i < num_property_mappings; i++)
1086 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1087 int action = property_mapping[i].ext1_index;
1088 int sound = property_mapping[i].artwork_index;
1090 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1094 action = ACTION_DEFAULT;
1096 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1097 if (strcmp(element_info[j].class_name,
1098 element_info[element_class].class_name) == 0)
1099 element_info[j].sound[action] = sound;
1102 /* initialize element/sound mapping from dynamic configuration */
1103 for (i=0; i < num_property_mappings; i++)
1105 int element = property_mapping[i].base_index;
1106 int action = property_mapping[i].ext1_index;
1107 int sound = property_mapping[i].artwork_index;
1109 if (element >= MAX_NUM_ELEMENTS)
1113 action = ACTION_DEFAULT;
1115 element_info[element].sound[action] = sound;
1118 /* now set all '-1' values to element specific default values */
1119 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1121 for (act=0; act < NUM_ACTIONS; act++)
1123 /* generic default action sound (defined by "[default]" directive) */
1124 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1126 /* look for special default action sound (classic game specific) */
1127 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1128 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1129 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1130 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1131 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1132 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1134 /* look for element specific default sound (independent from action) */
1135 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1136 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1138 /* no sound for this specific action -- use default action sound */
1139 if (element_info[i].sound[act] == -1)
1140 element_info[i].sound[act] = default_action_sound;
1145 static void set_sound_parameters(int sound, char **parameter_raw)
1147 int parameter[NUM_SND_ARGS];
1150 /* get integer values from string parameters */
1151 for (i=0; i < NUM_SND_ARGS; i++)
1153 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1154 sound_config_suffix[i].type);
1156 /* explicit loop mode setting in configuration overrides default value */
1157 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1158 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1161 static void InitSoundInfo()
1164 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1165 int num_property_mappings = getSoundListPropertyMappingSize();
1167 int *sound_effect_properties;
1168 int num_sounds = getSoundListSize();
1171 if (sound_info != NULL)
1174 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1175 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1177 /* initialize sound effect for all elements to "no sound" */
1178 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1179 for (j=0; j<NUM_ACTIONS; j++)
1180 element_info[i].sound[j] = SND_UNDEFINED;
1182 for (i=0; i<num_sounds; i++)
1184 struct FileInfo *sound = getSoundListEntry(i);
1185 int len_effect_text = strlen(sound->token);
1187 sound_effect_properties[i] = ACTION_OTHER;
1188 sound_info[i].loop = FALSE;
1191 printf("::: sound %d: '%s'\n", i, sound->token);
1194 /* determine all loop sounds and identify certain sound classes */
1196 for (j=0; element_action_info[j].suffix; j++)
1198 int len_action_text = strlen(element_action_info[j].suffix);
1200 if (len_action_text < len_effect_text &&
1201 strcmp(&sound->token[len_effect_text - len_action_text],
1202 element_action_info[j].suffix) == 0)
1204 sound_effect_properties[i] = element_action_info[j].value;
1205 sound_info[i].loop = element_action_info[j].is_loop_sound;
1212 if (strcmp(sound->token, "custom_42") == 0)
1213 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1216 /* associate elements and some selected sound actions */
1218 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1220 if (element_info[j].class_name)
1222 int len_class_text = strlen(element_info[j].class_name);
1224 if (len_class_text + 1 < len_effect_text &&
1225 strncmp(sound->token,
1226 element_info[j].class_name, len_class_text) == 0 &&
1227 sound->token[len_class_text] == '.')
1229 int sound_action_value = sound_effect_properties[i];
1231 element_info[j].sound[sound_action_value] = i;
1236 set_sound_parameters(i, sound->parameter);
1239 free(sound_effect_properties);
1242 /* !!! now handled in InitElementSoundInfo() !!! */
1243 /* initialize element/sound mapping from dynamic configuration */
1244 for (i=0; i < num_property_mappings; i++)
1246 int element = property_mapping[i].base_index;
1247 int action = property_mapping[i].ext1_index;
1248 int sound = property_mapping[i].artwork_index;
1251 action = ACTION_DEFAULT;
1253 printf("::: %d: %d, %d, %d ['%s']\n",
1254 i, element, action, sound, element_info[element].token_name);
1256 element_info[element].sound[action] = sound;
1263 int element = EL_CUSTOM_11;
1266 while (element_action_info[j].suffix)
1268 printf("element %d, sound action '%s' == %d\n",
1269 element, element_action_info[j].suffix,
1270 element_info[element].sound[j]);
1275 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1281 int element = EL_SAND;
1282 int sound_action = ACTION_DIGGING;
1285 while (element_action_info[j].suffix)
1287 if (element_action_info[j].value == sound_action)
1288 printf("element %d, sound action '%s' == %d\n",
1289 element, element_action_info[j].suffix,
1290 element_info[element].sound[sound_action]);
1297 static void ReinitializeGraphics()
1299 InitGraphicInfo(); /* graphic properties mapping */
1300 InitElementGraphicInfo(); /* element game graphic mapping */
1301 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1303 InitElementSmallImages(); /* create editor and preview images */
1304 InitFontGraphicInfo(); /* initialize text drawing functions */
1306 SetMainBackgroundImage(IMG_BACKGROUND);
1307 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1313 static void ReinitializeSounds()
1315 InitSoundInfo(); /* sound properties mapping */
1316 InitElementSoundInfo(); /* element game sound mapping */
1318 InitPlaySoundLevel(); /* internal game sound settings */
1321 static void ReinitializeMusic()
1323 /* currently nothing to do */
1326 void InitElementPropertiesStatic()
1328 static int ep_diggable[] =
1333 EL_SP_BUGGY_BASE_ACTIVATING,
1336 EL_INVISIBLE_SAND_ACTIVE,
1338 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1342 EL_SP_BUGGY_BASE_ACTIVE,
1347 static int ep_collectible_only[] =
1364 EL_DYNABOMB_INCREASE_NUMBER,
1365 EL_DYNABOMB_INCREASE_SIZE,
1366 EL_DYNABOMB_INCREASE_POWER,
1383 static int ep_dont_run_into[] =
1385 /* same elements as in 'ep_dont_touch' */
1391 /* same elements as in 'ep_dont_collide_with' */
1403 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1407 EL_SP_BUGGY_BASE_ACTIVE,
1412 static int ep_dont_collide_with[] =
1414 /* same elements as in 'ep_dont_touch' */
1430 static int ep_dont_touch[] =
1439 static int ep_indestructible[] =
1443 EL_ACID_POOL_TOPLEFT,
1444 EL_ACID_POOL_TOPRIGHT,
1445 EL_ACID_POOL_BOTTOMLEFT,
1446 EL_ACID_POOL_BOTTOM,
1447 EL_ACID_POOL_BOTTOMRIGHT,
1448 EL_SP_HARDWARE_GRAY,
1449 EL_SP_HARDWARE_GREEN,
1450 EL_SP_HARDWARE_BLUE,
1452 EL_SP_HARDWARE_YELLOW,
1453 EL_SP_HARDWARE_BASE_1,
1454 EL_SP_HARDWARE_BASE_2,
1455 EL_SP_HARDWARE_BASE_3,
1456 EL_SP_HARDWARE_BASE_4,
1457 EL_SP_HARDWARE_BASE_5,
1458 EL_SP_HARDWARE_BASE_6,
1459 EL_INVISIBLE_STEELWALL,
1460 EL_INVISIBLE_STEELWALL_ACTIVE,
1461 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1462 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1463 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1464 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1465 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1466 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1467 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1468 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1469 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1470 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1471 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1472 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1474 EL_LIGHT_SWITCH_ACTIVE,
1475 EL_SIGN_EXCLAMATION,
1476 EL_SIGN_RADIOACTIVITY,
1487 EL_STEELWALL_SLIPPERY,
1510 EL_SWITCHGATE_OPENING,
1511 EL_SWITCHGATE_CLOSED,
1512 EL_SWITCHGATE_CLOSING,
1514 EL_SWITCHGATE_SWITCH_UP,
1515 EL_SWITCHGATE_SWITCH_DOWN,
1518 EL_TIMEGATE_OPENING,
1520 EL_TIMEGATE_CLOSING,
1523 EL_TIMEGATE_SWITCH_ACTIVE,
1528 EL_TUBE_VERTICAL_LEFT,
1529 EL_TUBE_VERTICAL_RIGHT,
1530 EL_TUBE_HORIZONTAL_UP,
1531 EL_TUBE_HORIZONTAL_DOWN,
1539 static int ep_slippery[] =
1553 EL_ROBOT_WHEEL_ACTIVE,
1559 EL_ACID_POOL_TOPLEFT,
1560 EL_ACID_POOL_TOPRIGHT,
1570 EL_STEELWALL_SLIPPERY,
1576 static int ep_can_change[] =
1581 static int ep_can_move[] =
1603 static int ep_can_fall[] =
1618 EL_BD_MAGIC_WALL_FULL,
1631 static int ep_can_smash_player[] =
1656 static int ep_can_smash_enemies[] =
1664 static int ep_can_smash_everything[] =
1672 static int ep_can_explode_by_fire[] =
1674 /* same elements as in 'ep_can_explode_impact' */
1679 /* same elements as in 'ep_can_explode_smashed' */
1688 EL_DYNABOMB_PLAYER_1_ACTIVE,
1689 EL_DYNABOMB_PLAYER_2_ACTIVE,
1690 EL_DYNABOMB_PLAYER_3_ACTIVE,
1691 EL_DYNABOMB_PLAYER_4_ACTIVE,
1692 EL_DYNABOMB_INCREASE_NUMBER,
1693 EL_DYNABOMB_INCREASE_SIZE,
1694 EL_DYNABOMB_INCREASE_POWER,
1695 EL_SP_DISK_RED_ACTIVE,
1705 static int ep_can_explode_smashed[] =
1707 /* same elements as in 'ep_can_explode_impact' */
1720 static int ep_can_explode_impact[] =
1728 static int ep_walkable_over[] =
1732 EL_SOKOBAN_FIELD_EMPTY,
1749 static int ep_walkable_inside[] =
1754 EL_TUBE_VERTICAL_LEFT,
1755 EL_TUBE_VERTICAL_RIGHT,
1756 EL_TUBE_HORIZONTAL_UP,
1757 EL_TUBE_HORIZONTAL_DOWN,
1765 static int ep_walkable_under[] =
1770 static int ep_passable_over[] =
1785 static int ep_passable_inside[] =
1791 EL_SP_PORT_HORIZONTAL,
1792 EL_SP_PORT_VERTICAL,
1794 EL_SP_GRAVITY_PORT_LEFT,
1795 EL_SP_GRAVITY_PORT_RIGHT,
1796 EL_SP_GRAVITY_PORT_UP,
1797 EL_SP_GRAVITY_PORT_DOWN,
1801 static int ep_passable_under[] =
1806 static int ep_droppable[] =
1811 static int ep_can_explode_1x1[] =
1816 static int ep_pushable[] =
1828 EL_SOKOBAN_FIELD_FULL,
1835 static int ep_player[] =
1845 static int ep_can_pass_magic_wall[] =
1858 static int ep_switchable[] =
1862 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1863 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1864 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1865 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1866 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1867 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1868 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1869 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1870 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1871 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1872 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1873 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1874 EL_SWITCHGATE_SWITCH_UP,
1875 EL_SWITCHGATE_SWITCH_DOWN,
1877 EL_LIGHT_SWITCH_ACTIVE,
1879 EL_BALLOON_SWITCH_LEFT,
1880 EL_BALLOON_SWITCH_RIGHT,
1881 EL_BALLOON_SWITCH_UP,
1882 EL_BALLOON_SWITCH_DOWN,
1883 EL_BALLOON_SWITCH_ANY,
1889 static int ep_bd_element[] =
1918 static int ep_sp_element[] =
1920 /* should always be valid */
1929 EL_SP_HARDWARE_GRAY,
1937 EL_SP_GRAVITY_PORT_RIGHT,
1938 EL_SP_GRAVITY_PORT_DOWN,
1939 EL_SP_GRAVITY_PORT_LEFT,
1940 EL_SP_GRAVITY_PORT_UP,
1945 EL_SP_PORT_VERTICAL,
1946 EL_SP_PORT_HORIZONTAL,
1952 EL_SP_HARDWARE_BASE_1,
1953 EL_SP_HARDWARE_GREEN,
1954 EL_SP_HARDWARE_BLUE,
1956 EL_SP_HARDWARE_YELLOW,
1957 EL_SP_HARDWARE_BASE_2,
1958 EL_SP_HARDWARE_BASE_3,
1959 EL_SP_HARDWARE_BASE_4,
1960 EL_SP_HARDWARE_BASE_5,
1961 EL_SP_HARDWARE_BASE_6,
1964 /* additional elements that appeared in newer Supaplex levels */
1966 /* more than one murphy in a level results in an inactive clone */
1968 /* runtime elements*/
1969 EL_SP_DISK_RED_ACTIVE,
1970 EL_SP_TERMINAL_ACTIVE,
1971 EL_SP_BUGGY_BASE_ACTIVATING,
1972 EL_SP_BUGGY_BASE_ACTIVE,
1976 static int ep_sb_element[] =
1981 EL_SOKOBAN_FIELD_EMPTY,
1982 EL_SOKOBAN_FIELD_FULL,
1984 EL_INVISIBLE_STEELWALL,
1988 static int ep_gem[] =
1999 static int ep_food_dark_yamyam[] =
2026 static int ep_food_penguin[] =
2039 static int ep_food_pig[] =
2050 static int ep_historic_wall[] =
2075 EL_EXPANDABLE_WALL_HORIZONTAL,
2076 EL_EXPANDABLE_WALL_VERTICAL,
2077 EL_EXPANDABLE_WALL_ANY,
2078 EL_EXPANDABLE_WALL_GROWING,
2085 EL_SP_HARDWARE_GRAY,
2086 EL_SP_HARDWARE_GREEN,
2087 EL_SP_HARDWARE_BLUE,
2089 EL_SP_HARDWARE_YELLOW,
2090 EL_SP_HARDWARE_BASE_1,
2091 EL_SP_HARDWARE_BASE_2,
2092 EL_SP_HARDWARE_BASE_3,
2093 EL_SP_HARDWARE_BASE_4,
2094 EL_SP_HARDWARE_BASE_5,
2095 EL_SP_HARDWARE_BASE_6,
2097 EL_SP_TERMINAL_ACTIVE,
2100 EL_INVISIBLE_STEELWALL,
2101 EL_INVISIBLE_STEELWALL_ACTIVE,
2103 EL_INVISIBLE_WALL_ACTIVE,
2104 EL_STEELWALL_SLIPPERY,
2120 static int ep_historic_solid[] =
2124 EL_EXPANDABLE_WALL_HORIZONTAL,
2125 EL_EXPANDABLE_WALL_VERTICAL,
2126 EL_EXPANDABLE_WALL_ANY,
2139 EL_QUICKSAND_FILLING,
2140 EL_QUICKSAND_EMPTYING,
2142 EL_MAGIC_WALL_ACTIVE,
2143 EL_MAGIC_WALL_EMPTYING,
2144 EL_MAGIC_WALL_FILLING,
2148 EL_BD_MAGIC_WALL_ACTIVE,
2149 EL_BD_MAGIC_WALL_EMPTYING,
2150 EL_BD_MAGIC_WALL_FULL,
2151 EL_BD_MAGIC_WALL_FILLING,
2152 EL_BD_MAGIC_WALL_DEAD,
2161 EL_SP_TERMINAL_ACTIVE,
2165 EL_INVISIBLE_WALL_ACTIVE,
2166 EL_SWITCHGATE_SWITCH_UP,
2167 EL_SWITCHGATE_SWITCH_DOWN,
2169 EL_TIMEGATE_SWITCH_ACTIVE,
2181 /* the following elements are a direct copy of "indestructible" elements,
2182 except "EL_ACID", which is "indestructible", but not "solid"! */
2187 EL_ACID_POOL_TOPLEFT,
2188 EL_ACID_POOL_TOPRIGHT,
2189 EL_ACID_POOL_BOTTOMLEFT,
2190 EL_ACID_POOL_BOTTOM,
2191 EL_ACID_POOL_BOTTOMRIGHT,
2192 EL_SP_HARDWARE_GRAY,
2193 EL_SP_HARDWARE_GREEN,
2194 EL_SP_HARDWARE_BLUE,
2196 EL_SP_HARDWARE_YELLOW,
2197 EL_SP_HARDWARE_BASE_1,
2198 EL_SP_HARDWARE_BASE_2,
2199 EL_SP_HARDWARE_BASE_3,
2200 EL_SP_HARDWARE_BASE_4,
2201 EL_SP_HARDWARE_BASE_5,
2202 EL_SP_HARDWARE_BASE_6,
2203 EL_INVISIBLE_STEELWALL,
2204 EL_INVISIBLE_STEELWALL_ACTIVE,
2205 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2206 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2207 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2208 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2209 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2210 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2211 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2212 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2213 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2214 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2215 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2216 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2218 EL_LIGHT_SWITCH_ACTIVE,
2219 EL_SIGN_EXCLAMATION,
2220 EL_SIGN_RADIOACTIVITY,
2231 EL_STEELWALL_SLIPPERY,
2254 EL_SWITCHGATE_OPENING,
2255 EL_SWITCHGATE_CLOSED,
2256 EL_SWITCHGATE_CLOSING,
2258 EL_TIMEGATE_OPENING,
2260 EL_TIMEGATE_CLOSING,
2264 EL_TUBE_VERTICAL_LEFT,
2265 EL_TUBE_VERTICAL_RIGHT,
2266 EL_TUBE_HORIZONTAL_UP,
2267 EL_TUBE_HORIZONTAL_DOWN,
2275 static int ep_classic_enemy[] =
2291 static int ep_belt[] =
2293 EL_CONVEYOR_BELT_1_LEFT,
2294 EL_CONVEYOR_BELT_1_MIDDLE,
2295 EL_CONVEYOR_BELT_1_RIGHT,
2296 EL_CONVEYOR_BELT_2_LEFT,
2297 EL_CONVEYOR_BELT_2_MIDDLE,
2298 EL_CONVEYOR_BELT_2_RIGHT,
2299 EL_CONVEYOR_BELT_3_LEFT,
2300 EL_CONVEYOR_BELT_3_MIDDLE,
2301 EL_CONVEYOR_BELT_3_RIGHT,
2302 EL_CONVEYOR_BELT_4_LEFT,
2303 EL_CONVEYOR_BELT_4_MIDDLE,
2304 EL_CONVEYOR_BELT_4_RIGHT,
2308 static int ep_belt_active[] =
2310 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2311 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2312 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2313 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2314 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2315 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2316 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2317 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2318 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2319 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2320 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2321 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2325 static int ep_belt_switch[] =
2327 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2328 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2329 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2330 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2331 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2332 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2333 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2334 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2335 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2336 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2337 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2338 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2342 static int ep_tube[] =
2349 EL_TUBE_HORIZONTAL_UP,
2350 EL_TUBE_HORIZONTAL_DOWN,
2352 EL_TUBE_VERTICAL_LEFT,
2353 EL_TUBE_VERTICAL_RIGHT,
2358 static int ep_keygate[] =
2379 static int ep_amoeboid[] =
2389 static int ep_amoebalive[] =
2398 static int ep_has_content[] =
2408 static int ep_active_bomb[] =
2411 EL_DYNABOMB_PLAYER_1_ACTIVE,
2412 EL_DYNABOMB_PLAYER_2_ACTIVE,
2413 EL_DYNABOMB_PLAYER_3_ACTIVE,
2414 EL_DYNABOMB_PLAYER_4_ACTIVE,
2415 EL_SP_DISK_RED_ACTIVE,
2419 static int ep_inactive[] =
2456 EL_INVISIBLE_STEELWALL,
2464 EL_WALL_EMERALD_YELLOW,
2465 EL_DYNABOMB_INCREASE_NUMBER,
2466 EL_DYNABOMB_INCREASE_SIZE,
2467 EL_DYNABOMB_INCREASE_POWER,
2471 EL_SOKOBAN_FIELD_EMPTY,
2472 EL_SOKOBAN_FIELD_FULL,
2473 EL_WALL_EMERALD_RED,
2474 EL_WALL_EMERALD_PURPLE,
2475 EL_ACID_POOL_TOPLEFT,
2476 EL_ACID_POOL_TOPRIGHT,
2477 EL_ACID_POOL_BOTTOMLEFT,
2478 EL_ACID_POOL_BOTTOM,
2479 EL_ACID_POOL_BOTTOMRIGHT,
2483 EL_BD_MAGIC_WALL_DEAD,
2484 EL_AMOEBA_TO_DIAMOND,
2492 EL_SP_GRAVITY_PORT_RIGHT,
2493 EL_SP_GRAVITY_PORT_DOWN,
2494 EL_SP_GRAVITY_PORT_LEFT,
2495 EL_SP_GRAVITY_PORT_UP,
2496 EL_SP_PORT_HORIZONTAL,
2497 EL_SP_PORT_VERTICAL,
2508 EL_SP_HARDWARE_GRAY,
2509 EL_SP_HARDWARE_GREEN,
2510 EL_SP_HARDWARE_BLUE,
2512 EL_SP_HARDWARE_YELLOW,
2513 EL_SP_HARDWARE_BASE_1,
2514 EL_SP_HARDWARE_BASE_2,
2515 EL_SP_HARDWARE_BASE_3,
2516 EL_SP_HARDWARE_BASE_4,
2517 EL_SP_HARDWARE_BASE_5,
2518 EL_SP_HARDWARE_BASE_6,
2519 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2520 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2521 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2522 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2523 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2524 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2525 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2526 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2527 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2528 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2529 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2530 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2531 EL_SIGN_EXCLAMATION,
2532 EL_SIGN_RADIOACTIVITY,
2543 EL_STEELWALL_SLIPPERY,
2559 static int ep_em_slippery_wall[] =
2564 static int ep_gfx_crumbled[] =
2577 } element_properties[] =
2579 { ep_diggable, EP_DIGGABLE },
2580 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2581 { ep_dont_run_into, EP_DONT_RUN_INTO },
2582 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2583 { ep_dont_touch, EP_DONT_TOUCH },
2584 { ep_indestructible, EP_INDESTRUCTIBLE },
2585 { ep_slippery, EP_SLIPPERY },
2586 { ep_can_change, EP_CAN_CHANGE },
2587 { ep_can_move, EP_CAN_MOVE },
2588 { ep_can_fall, EP_CAN_FALL },
2589 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2590 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2591 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2592 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2593 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2594 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2595 { ep_walkable_over, EP_WALKABLE_OVER },
2596 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2597 { ep_walkable_under, EP_WALKABLE_UNDER },
2598 { ep_passable_over, EP_PASSABLE_OVER },
2599 { ep_passable_inside, EP_PASSABLE_INSIDE },
2600 { ep_passable_under, EP_PASSABLE_UNDER },
2601 { ep_droppable, EP_DROPPABLE },
2602 { ep_can_explode_1x1, EP_CAN_EXPLODE_1X1 },
2603 { ep_pushable, EP_PUSHABLE },
2605 { ep_player, EP_PLAYER },
2606 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2607 { ep_switchable, EP_SWITCHABLE },
2608 { ep_bd_element, EP_BD_ELEMENT },
2609 { ep_sp_element, EP_SP_ELEMENT },
2610 { ep_sb_element, EP_SB_ELEMENT },
2612 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2613 { ep_food_penguin, EP_FOOD_PENGUIN },
2614 { ep_food_pig, EP_FOOD_PIG },
2615 { ep_historic_wall, EP_HISTORIC_WALL },
2616 { ep_historic_solid, EP_HISTORIC_SOLID },
2617 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2618 { ep_belt, EP_BELT },
2619 { ep_belt_active, EP_BELT_ACTIVE },
2620 { ep_belt_switch, EP_BELT_SWITCH },
2621 { ep_tube, EP_TUBE },
2622 { ep_keygate, EP_KEYGATE },
2623 { ep_amoeboid, EP_AMOEBOID },
2624 { ep_amoebalive, EP_AMOEBALIVE },
2625 { ep_has_content, EP_HAS_CONTENT },
2626 { ep_active_bomb, EP_ACTIVE_BOMB },
2627 { ep_inactive, EP_INACTIVE },
2629 { ep_em_slippery_wall, EP_EM_SLIPPERY_WALL },
2631 { ep_gfx_crumbled, EP_GFX_CRUMBLED },
2636 static int copy_properties[][5] =
2640 EL_BUG_LEFT, EL_BUG_RIGHT,
2641 EL_BUG_UP, EL_BUG_DOWN
2645 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2646 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2650 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2651 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2655 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2656 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2660 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2661 EL_PACMAN_UP, EL_PACMAN_DOWN
2671 /* always start with reliable default values (element has no properties) */
2672 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2673 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2674 SET_PROPERTY(i, j, FALSE);
2676 /* set all base element properties from above array definitions */
2677 for (i=0; element_properties[i].elements != NULL; i++)
2678 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2679 SET_PROPERTY((element_properties[i].elements)[j],
2680 element_properties[i].property, TRUE);
2682 /* copy properties to some elements that are only stored in level file */
2683 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2684 for (j=0; copy_properties[j][0] != -1; j++)
2685 if (HAS_PROPERTY(copy_properties[j][0], i))
2686 for (k=1; k<=4; k++)
2687 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2690 void InitElementPropertiesEngine(int engine_version)
2693 static int active_properties[] =
2698 EP_DONT_COLLIDE_WITH,
2702 EP_CAN_PASS_MAGIC_WALL,
2707 EP_CAN_EXPLODE_BY_FIRE,
2720 EP_EM_SLIPPERY_WALL,
2724 static int no_wall_properties[] =
2727 EP_COLLECTIBLE_ONLY,
2729 EP_DONT_COLLIDE_WITH,
2732 EP_CAN_SMASH_PLAYER,
2733 EP_CAN_SMASH_ENEMIES,
2734 EP_CAN_SMASH_EVERYTHING,
2739 EP_FOOD_DARK_YAMYAM,
2755 InitElementPropertiesStatic();
2758 /* set all special, combined or engine dependent element properties */
2759 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2762 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2763 SET_PROPERTY(i, j, FALSE);
2766 /* ---------- INACTIVE ------------------------------------------------- */
2767 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2768 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2770 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2771 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2772 IS_WALKABLE_INSIDE(i) ||
2773 IS_WALKABLE_UNDER(i)));
2775 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2776 IS_PASSABLE_INSIDE(i) ||
2777 IS_PASSABLE_UNDER(i)));
2779 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2780 IS_PASSABLE_OVER(i)));
2782 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2783 IS_PASSABLE_INSIDE(i)));
2785 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2786 IS_PASSABLE_UNDER(i)));
2788 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2791 /* ---------- COLLECTIBLE ---------------------------------------------- */
2792 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2795 /* ---------- SNAPPABLE ------------------------------------------------ */
2796 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2797 IS_COLLECTIBLE(i) ||
2801 /* ---------- WALL ----------------------------------------------------- */
2802 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2804 for (j=0; no_wall_properties[j] != -1; j++)
2805 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2806 i >= EL_FIRST_RUNTIME_UNREAL)
2807 SET_PROPERTY(i, EP_WALL, FALSE);
2809 if (IS_HISTORIC_WALL(i))
2810 SET_PROPERTY(i, EP_WALL, TRUE);
2812 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2813 if (engine_version < VERSION_IDENT(2,2,0))
2814 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2816 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2818 !IS_COLLECTIBLE(i)));
2820 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2822 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2823 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2825 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2826 IS_INDESTRUCTIBLE(i)));
2828 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2830 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2831 else if (engine_version < VERSION_IDENT(2,2,0))
2832 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2834 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2835 !IS_WALKABLE_OVER(i) &&
2836 !IS_WALKABLE_UNDER(i)));
2838 if (IS_CUSTOM_ELEMENT(i))
2840 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2842 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2843 if (DONT_COLLIDE_WITH(i))
2844 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2846 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2847 if (CAN_SMASH_EVERYTHING(i))
2848 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2849 if (CAN_SMASH_ENEMIES(i))
2850 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2853 /* ---------- CAN_SMASH ------------------------------------------------ */
2854 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2855 CAN_SMASH_ENEMIES(i) ||
2856 CAN_SMASH_EVERYTHING(i)));
2858 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2859 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2860 CAN_EXPLODE_SMASHED(i) ||
2861 CAN_EXPLODE_IMPACT(i)));
2863 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2864 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2865 !CAN_EXPLODE_1X1(i)));
2867 /* ---------- CAN_CHANGE ----------------------------------------------- */
2868 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
2869 for (j=0; j < element_info[i].num_change_pages; j++)
2870 if (element_info[i].change_page[j].can_change)
2871 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
2873 /* ---------- GFX_CRUMBLED --------------------------------------------- */
2874 SET_PROPERTY(i, EP_GFX_CRUMBLED,
2875 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2879 /* determine inactive elements (used for engine main loop optimization) */
2880 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2882 boolean active = FALSE;
2884 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2886 if (HAS_PROPERTY(i, j))
2892 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2897 /* dynamically adjust element properties according to game engine version */
2899 static int ep_em_slippery_wall[] =
2904 EL_EXPANDABLE_WALL_HORIZONTAL,
2905 EL_EXPANDABLE_WALL_VERTICAL,
2906 EL_EXPANDABLE_WALL_ANY,
2910 /* special EM style gems behaviour */
2911 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2912 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2913 level.em_slippery_gems);
2915 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2916 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2917 (level.em_slippery_gems &&
2918 engine_version > VERSION_IDENT(2,0,1)));
2922 /* dynamically adjust element properties according to game engine version */
2924 if (engine_version < RELEASE_IDENT(2,2,0,7))
2927 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2929 int element = EL_CUSTOM_START + i;
2931 element_info[element].push_delay_fixed = 2;
2932 element_info[element].push_delay_random = 8;
2938 static void InitGlobal()
2940 global.autoplay_leveldir = NULL;
2942 global.frames_per_second = 0;
2943 global.fps_slowdown = FALSE;
2944 global.fps_slowdown_factor = 1;
2947 void Execute_Command(char *command)
2949 if (strcmp(command, "print graphicsinfo.conf") == 0)
2953 printf("# You can configure additional/alternative image files here.\n");
2954 printf("# (The images below are default and therefore commented out.)\n");
2956 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2958 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2961 for (i=0; image_config[i].token != NULL; i++)
2963 getFormattedSetupEntry(image_config[i].token,
2964 image_config[i].value));
2968 else if (strcmp(command, "print soundsinfo.conf") == 0)
2972 printf("# You can configure additional/alternative sound files here.\n");
2973 printf("# (The sounds below are default and therefore commented out.)\n");
2975 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2977 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2980 for (i=0; sound_config[i].token != NULL; i++)
2982 getFormattedSetupEntry(sound_config[i].token,
2983 sound_config[i].value));
2987 else if (strcmp(command, "print musicinfo.conf") == 0)
2989 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2991 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2993 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2997 else if (strncmp(command, "dump level ", 11) == 0)
2999 char *filename = &command[11];
3001 if (access(filename, F_OK) != 0)
3002 Error(ERR_EXIT, "cannot open file '%s'", filename);
3004 LoadLevelFromFilename(&level, filename);
3009 else if (strncmp(command, "dump tape ", 10) == 0)
3011 char *filename = &command[10];
3013 if (access(filename, F_OK) != 0)
3014 Error(ERR_EXIT, "cannot open file '%s'", filename);
3016 LoadTapeFromFilename(filename);
3021 else if (strncmp(command, "autoplay ", 9) == 0)
3023 char *str_copy = getStringCopy(&command[9]);
3024 char *str_ptr = strchr(str_copy, ' ');
3026 global.autoplay_leveldir = str_copy;
3027 global.autoplay_level_nr = -1;
3029 if (str_ptr != NULL)
3031 *str_ptr++ = '\0'; /* terminate leveldir string */
3032 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3037 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3041 static void InitSetup()
3043 LoadSetup(); /* global setup info */
3045 /* set some options from setup file */
3047 if (setup.options.verbose)
3048 options.verbose = TRUE;
3051 static void InitPlayerInfo()
3055 /* choose default local player */
3056 local_player = &stored_player[0];
3058 for (i=0; i<MAX_PLAYERS; i++)
3059 stored_player[i].connected = FALSE;
3061 local_player->connected = TRUE;
3064 static void InitArtworkInfo()
3069 static char *get_string_in_brackets(char *string)
3071 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3073 sprintf(string_in_brackets, "[%s]", string);
3075 return string_in_brackets;
3079 static char *get_element_class_token(int element)
3081 char *element_class_name = element_info[element].class_name;
3082 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3084 sprintf(element_class_token, "[%s]", element_class_name);
3086 return element_class_token;
3089 static char *get_action_class_token(int action)
3091 char *action_class_name = &element_action_info[action].suffix[1];
3092 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3094 sprintf(action_class_token, "[%s]", action_class_name);
3096 return action_class_token;
3100 static void InitArtworkConfig()
3102 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3103 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3104 static char *action_id_suffix[NUM_ACTIONS + 1];
3105 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3106 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3107 static char *dummy[1] = { NULL };
3108 static char *ignore_generic_tokens[] =
3114 static char **ignore_image_tokens, **ignore_sound_tokens;
3115 int num_ignore_generic_tokens;
3116 int num_ignore_image_tokens, num_ignore_sound_tokens;
3119 /* dynamically determine list of generic tokens to be ignored */
3120 num_ignore_generic_tokens = 0;
3121 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3122 num_ignore_generic_tokens++;
3124 /* dynamically determine list of image tokens to be ignored */
3125 num_ignore_image_tokens = num_ignore_generic_tokens;
3126 for (i=0; image_config_vars[i].token != NULL; i++)
3127 num_ignore_image_tokens++;
3128 ignore_image_tokens =
3129 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3130 for (i=0; i < num_ignore_generic_tokens; i++)
3131 ignore_image_tokens[i] = ignore_generic_tokens[i];
3132 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3133 ignore_image_tokens[num_ignore_generic_tokens + i] =
3134 image_config_vars[i].token;
3135 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3137 /* dynamically determine list of sound tokens to be ignored */
3138 num_ignore_sound_tokens = num_ignore_generic_tokens;
3139 ignore_sound_tokens =
3140 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3141 for (i=0; i < num_ignore_generic_tokens; i++)
3142 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3143 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3145 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3146 image_id_prefix[i] = element_info[i].token_name;
3147 for (i=0; i<NUM_FONTS; i++)
3148 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3149 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3151 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3152 sound_id_prefix[i] = element_info[i].token_name;
3153 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3154 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3155 get_string_in_brackets(element_info[i].class_name);
3156 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3158 for (i=0; i<NUM_ACTIONS; i++)
3159 action_id_suffix[i] = element_action_info[i].suffix;
3160 action_id_suffix[NUM_ACTIONS] = NULL;
3162 for (i=0; i<NUM_DIRECTIONS; i++)
3163 direction_id_suffix[i] = element_direction_info[i].suffix;
3164 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3166 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3167 special_id_suffix[i] = special_suffix_info[i].suffix;
3168 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3170 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3171 image_id_prefix, action_id_suffix, direction_id_suffix,
3172 special_id_suffix, ignore_image_tokens);
3173 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3174 sound_id_prefix, action_id_suffix, dummy,
3175 special_id_suffix, ignore_sound_tokens);
3178 static void InitMixer()
3186 char *filename_font_initial = NULL;
3187 Bitmap *bitmap_font_initial = NULL;
3190 /* determine settings for initial font (for displaying startup messages) */
3191 for (i=0; image_config[i].token != NULL; i++)
3193 for (j=0; j < NUM_INITIAL_FONTS; j++)
3195 char font_token[128];
3198 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3199 len_font_token = strlen(font_token);
3201 if (strcmp(image_config[i].token, font_token) == 0)
3202 filename_font_initial = image_config[i].value;
3203 else if (strlen(image_config[i].token) > len_font_token &&
3204 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3206 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3207 font_initial[j].src_x = atoi(image_config[i].value);
3208 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3209 font_initial[j].src_y = atoi(image_config[i].value);
3210 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3211 font_initial[j].width = atoi(image_config[i].value);
3212 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3213 font_initial[j].height = atoi(image_config[i].value);
3218 for (j=0; j < NUM_INITIAL_FONTS; j++)
3220 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3221 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3224 if (filename_font_initial == NULL) /* should not happen */
3225 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3227 /* create additional image buffers for double-buffering */
3228 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3229 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3231 /* initialize screen properties */
3232 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3233 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3235 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3236 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3237 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3239 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3241 for (j=0; j < NUM_INITIAL_FONTS; j++)
3242 font_initial[j].bitmap = bitmap_font_initial;
3244 InitFontGraphicInfo();
3246 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3247 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3249 DrawInitText("Loading graphics:", 120, FC_GREEN);
3251 InitTileClipmasks();
3254 void InitGfxBackground()
3258 drawto = backbuffer;
3259 fieldbuffer = bitmap_db_field;
3260 SetDrawtoField(DRAW_BACKBUFFER);
3262 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3263 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3264 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3265 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3267 for (x=0; x<MAX_BUF_XSIZE; x++)
3268 for (y=0; y<MAX_BUF_YSIZE; y++)
3271 redraw_mask = REDRAW_ALL;
3274 static void InitLevelInfo()
3276 LoadLevelInfo(); /* global level info */
3277 LoadLevelSetup_LastSeries(); /* last played series info */
3278 LoadLevelSetup_SeriesInfo(); /* last played level info */
3281 void InitLevelArtworkInfo()
3283 LoadLevelArtworkInfo();
3286 static void InitImages()
3289 setLevelArtworkDir(artwork.gfx_first);
3293 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3294 leveldir_current->identifier,
3295 artwork.gfx_current_identifier,
3296 artwork.gfx_current->identifier,
3297 leveldir_current->graphics_set,
3298 leveldir_current->graphics_path);
3301 ReloadCustomImages();
3303 LoadCustomElementDescriptions();
3304 LoadSpecialMenuDesignSettings();
3306 ReinitializeGraphics();
3309 static void InitSound(char *identifier)
3311 if (identifier == NULL)
3312 identifier = artwork.snd_current->identifier;
3315 /* set artwork path to send it to the sound server process */
3316 setLevelArtworkDir(artwork.snd_first);
3319 InitReloadCustomSounds(identifier);
3320 ReinitializeSounds();
3323 static void InitMusic(char *identifier)
3325 if (identifier == NULL)
3326 identifier = artwork.mus_current->identifier;
3329 /* set artwork path to send it to the sound server process */
3330 setLevelArtworkDir(artwork.mus_first);
3333 InitReloadCustomMusic(identifier);
3334 ReinitializeMusic();
3337 void InitNetworkServer()
3339 #if defined(PLATFORM_UNIX)
3343 if (!options.network)
3346 #if defined(PLATFORM_UNIX)
3347 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3349 if (!ConnectToServer(options.server_host, options.server_port))
3350 Error(ERR_EXIT, "cannot connect to network game server");
3352 SendToServer_PlayerName(setup.player_name);
3353 SendToServer_ProtocolVersion();
3356 SendToServer_NrWanted(nr_wanted);
3360 static char *getNewArtworkIdentifier(int type)
3362 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3363 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3364 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3365 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3366 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3367 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3368 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3369 char *leveldir_identifier = leveldir_current->identifier;
3371 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3372 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3374 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3376 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3377 char *artwork_current_identifier;
3378 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3380 /* leveldir_current may be invalid (level group, parent link) */
3381 if (!validLevelSeries(leveldir_current))
3384 /* 1st step: determine artwork set to be activated in descending order:
3385 --------------------------------------------------------------------
3386 1. setup artwork (when configured to override everything else)
3387 2. artwork set configured in "levelinfo.conf" of current level set
3388 (artwork in level directory will have priority when loading later)
3389 3. artwork in level directory (stored in artwork sub-directory)
3390 4. setup artwork (currently configured in setup menu) */
3392 if (setup_override_artwork)
3393 artwork_current_identifier = setup_artwork_set;
3394 else if (leveldir_artwork_set != NULL)
3395 artwork_current_identifier = leveldir_artwork_set;
3396 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3397 artwork_current_identifier = leveldir_identifier;
3399 artwork_current_identifier = setup_artwork_set;
3402 /* 2nd step: check if it is really needed to reload artwork set
3403 ------------------------------------------------------------ */
3406 if (type == ARTWORK_TYPE_GRAPHICS)
3407 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3408 artwork_new_identifier,
3409 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3410 artwork_current_identifier,
3411 leveldir_current->graphics_set,
3412 leveldir_current->identifier);
3415 /* ---------- reload if level set and also artwork set has changed ------- */
3416 if (leveldir_current_identifier[type] != leveldir_identifier &&
3417 (last_has_level_artwork_set[type] || has_level_artwork_set))
3418 artwork_new_identifier = artwork_current_identifier;
3420 leveldir_current_identifier[type] = leveldir_identifier;
3421 last_has_level_artwork_set[type] = has_level_artwork_set;
3424 if (type == ARTWORK_TYPE_GRAPHICS)
3425 printf("::: 1: '%s'\n", artwork_new_identifier);
3428 /* ---------- reload if "override artwork" setting has changed ----------- */
3429 if (last_override_level_artwork[type] != setup_override_artwork)
3430 artwork_new_identifier = artwork_current_identifier;
3432 last_override_level_artwork[type] = setup_override_artwork;
3435 if (type == ARTWORK_TYPE_GRAPHICS)
3436 printf("::: 2: '%s'\n", artwork_new_identifier);
3439 /* ---------- reload if current artwork identifier has changed ----------- */
3440 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3441 artwork_current_identifier) != 0)
3442 artwork_new_identifier = artwork_current_identifier;
3444 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3447 if (type == ARTWORK_TYPE_GRAPHICS)
3448 printf("::: 3: '%s'\n", artwork_new_identifier);
3451 /* ---------- do not reload directly after starting ---------------------- */
3452 if (!initialized[type])
3453 artwork_new_identifier = NULL;
3455 initialized[type] = TRUE;
3458 if (type == ARTWORK_TYPE_GRAPHICS)
3459 printf("::: 4: '%s'\n", artwork_new_identifier);
3463 if (type == ARTWORK_TYPE_GRAPHICS)
3464 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3465 artwork.gfx_current_identifier, artwork_current_identifier,
3466 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3467 artwork_new_identifier);
3470 return artwork_new_identifier;
3473 void ReloadCustomArtwork()
3475 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3476 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3477 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3478 boolean redraw_screen = FALSE;
3480 if (gfx_new_identifier != NULL)
3483 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3484 artwork.gfx_current_identifier,
3486 artwork.gfx_current->identifier,
3487 leveldir_current->graphics_set);
3490 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3495 printf("... '%s'\n",
3496 leveldir_current->graphics_set);
3499 FreeTileClipmasks();
3500 InitTileClipmasks();
3502 redraw_screen = TRUE;
3505 if (snd_new_identifier != NULL)
3507 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3509 InitSound(snd_new_identifier);
3511 redraw_screen = TRUE;
3514 if (mus_new_identifier != NULL)
3516 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3518 InitMusic(mus_new_identifier);
3520 redraw_screen = TRUE;
3525 InitGfxBackground();
3527 /* force redraw of (open or closed) door graphics */
3528 SetDoorState(DOOR_OPEN_ALL);
3529 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3533 void KeyboardAutoRepeatOffUnlessAutoplay()
3535 if (global.autoplay_leveldir == NULL)
3536 KeyboardAutoRepeatOff();
3540 /* ========================================================================= */
3542 /* ========================================================================= */
3546 InitGlobal(); /* initialize some global variables */
3548 if (options.execute_command)
3549 Execute_Command(options.execute_command);
3551 if (options.serveronly)
3553 #if defined(PLATFORM_UNIX)
3554 NetworkServer(options.server_port, options.serveronly);
3556 Error(ERR_WARN, "networking only supported in Unix version");
3558 exit(0); /* never reached */
3564 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3565 InitArtworkConfig(); /* needed before forking sound child process */
3570 InitRND(NEW_RANDOMIZE);
3571 InitSimpleRND(NEW_RANDOMIZE);
3576 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3579 InitEventFilter(FilterMouseMotionEvents);
3581 InitElementPropertiesStatic();
3582 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3587 InitLevelArtworkInfo();
3589 InitImages(); /* needs to know current level directory */
3590 InitSound(NULL); /* needs to know current level directory */
3591 InitMusic(NULL); /* needs to know current level directory */
3593 InitGfxBackground();
3595 if (global.autoplay_leveldir)
3601 game_status = GAME_MODE_MAIN;
3605 InitNetworkServer();
3608 void CloseAllAndExit(int exit_value)
3613 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3616 FreeTileClipmasks();
3618 CloseVideoDisplay();
3619 ClosePlatformDependentStuff();