1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
28 #include "conf_e2g.c" /* include auto-generated data structure definitions */
29 #include "conf_esg.c" /* include auto-generated data structure definitions */
30 #include "conf_e2s.c" /* include auto-generated data structure definitions */
31 #include "conf_fnt.c" /* include auto-generated data structure definitions */
34 #define CONFIG_TOKEN_FONT_INITIAL "font.initial"
37 struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
40 static void InitTileClipmasks()
43 #if defined(TARGET_X11)
44 XGCValues clip_gc_values;
45 unsigned long clip_gc_valuemask;
47 #if defined(TARGET_X11_NATIVE)
57 tile_needs_clipping[] =
59 { GFX_SPIELER1_UP, 4 },
60 { GFX_SPIELER1_DOWN, 4 },
61 { GFX_SPIELER1_LEFT, 4 },
62 { GFX_SPIELER1_RIGHT, 4 },
63 { GFX_SPIELER1_PUSH_LEFT, 4 },
64 { GFX_SPIELER1_PUSH_RIGHT, 4 },
65 { GFX_SPIELER2_UP, 4 },
66 { GFX_SPIELER2_DOWN, 4 },
67 { GFX_SPIELER2_LEFT, 4 },
68 { GFX_SPIELER2_RIGHT, 4 },
69 { GFX_SPIELER2_PUSH_LEFT, 4 },
70 { GFX_SPIELER2_PUSH_RIGHT, 4 },
71 { GFX_SPIELER3_UP, 4 },
72 { GFX_SPIELER3_DOWN, 4 },
73 { GFX_SPIELER3_LEFT, 4 },
74 { GFX_SPIELER3_RIGHT, 4 },
75 { GFX_SPIELER3_PUSH_LEFT, 4 },
76 { GFX_SPIELER3_PUSH_RIGHT, 4 },
77 { GFX_SPIELER4_UP, 4 },
78 { GFX_SPIELER4_DOWN, 4 },
79 { GFX_SPIELER4_LEFT, 4 },
80 { GFX_SPIELER4_RIGHT, 4 },
81 { GFX_SPIELER4_PUSH_LEFT, 4 },
82 { GFX_SPIELER4_PUSH_RIGHT, 4 },
84 { GFX_MURPHY_GO_LEFT, 3 },
85 { GFX_MURPHY_GO_RIGHT, 3 },
86 { GFX_MURPHY_SNAP_UP, 1 },
87 { GFX_MURPHY_SNAP_DOWN, 1 },
88 { GFX_MURPHY_SNAP_RIGHT, 1 },
89 { GFX_MURPHY_SNAP_LEFT, 1 },
90 { GFX_MURPHY_PUSH_RIGHT, 1 },
91 { GFX_MURPHY_PUSH_LEFT, 1 },
96 { GFX_SOKOBAN_OBJEKT, 1 },
97 { GFX_FUNKELN_BLAU, 3 },
98 { GFX_FUNKELN_WEISS, 3 },
99 { GFX2_SHIELD_PASSIVE, 3 },
100 { GFX2_SHIELD_ACTIVE, 3 },
105 #endif /* TARGET_X11_NATIVE */
106 #endif /* TARGET_X11 */
110 /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
111 for (i=0; i<NUM_TILES; i++)
112 tile_clipmask[i] = None;
114 #if defined(TARGET_X11)
115 /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
116 often very slow when preparing a masked XCopyArea() for big Pixmaps.
117 To prevent this, create small (tile-sized) mask Pixmaps which will then
118 be set much faster with XSetClipOrigin() and speed things up a lot. */
120 clip_gc_values.graphics_exposures = False;
121 clip_gc_valuemask = GCGraphicsExposures;
122 tile_clip_gc = XCreateGC(display, window->drawable,
123 clip_gc_valuemask, &clip_gc_values);
126 for (i=0; i<NUM_BITMAPS; i++)
128 if (pix[i]->clip_mask)
130 clip_gc_values.graphics_exposures = False;
131 clip_gc_values.clip_mask = pix[i]->clip_mask;
132 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
133 pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
134 clip_gc_valuemask, &clip_gc_values);
139 #if defined(TARGET_X11_NATIVE)
142 /* create graphic context structures needed for clipping */
143 clip_gc_values.graphics_exposures = False;
144 clip_gc_valuemask = GCGraphicsExposures;
145 copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
146 clip_gc_valuemask, &clip_gc_values);
148 /* create only those clipping Pixmaps we really need */
149 for (i=0; tile_needs_clipping[i].start>=0; i++)
153 for (j=0; j<tile_needs_clipping[i].count; j++)
155 int tile = tile_needs_clipping[i].start + j;
161 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
162 src_pixmap = src_bitmap->clip_mask;
164 tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
167 XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
168 src_x, src_y, TILEX, TILEY, 0, 0);
172 XFreeGC(display, copy_clipmask_gc);
175 #endif /* TARGET_X11_NATIVE */
176 #endif /* TARGET_X11 */
180 void FreeTileClipmasks()
183 #if defined(TARGET_X11)
186 for (i=0; i<NUM_TILES; i++)
188 if (tile_clipmask[i] != None)
190 XFreePixmap(display, tile_clipmask[i]);
191 tile_clipmask[i] = None;
196 XFreeGC(display, tile_clip_gc);
200 for (i=0; i<NUM_BITMAPS; i++)
202 if (pix[i] != NULL && pix[i]->stored_clip_gc)
204 XFreeGC(display, pix[i]->stored_clip_gc);
205 pix[i]->stored_clip_gc = None;
210 #endif /* TARGET_X11 */
216 FreeLevelEditorGadgets();
225 static boolean gadgets_initialized = FALSE;
227 if (gadgets_initialized)
230 CreateLevelEditorGadgets();
234 CreateScreenGadgets();
236 gadgets_initialized = TRUE;
239 void InitElementSmallImages()
241 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
242 int num_property_mappings = getImageListPropertyMappingSize();
245 /* initialize normal images from static configuration */
246 for (i=0; element_to_graphic[i].element > -1; i++)
247 CreateImageWithSmallImages(element_to_graphic[i].graphic);
249 /* initialize special images from static configuration */
250 for (i=0; element_to_special_graphic[i].element > -1; i++)
251 CreateImageWithSmallImages(element_to_special_graphic[i].graphic);
253 /* initialize images from dynamic configuration */
254 for (i=0; i < num_property_mappings; i++)
255 if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
256 CreateImageWithSmallImages(property_mapping[i].artwork_index);
259 static int getFontBitmapID(int font_nr)
263 if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
264 special = game_status;
265 else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
266 special = GFX_SPECIAL_ARG_MAIN;
267 else if (game_status == GAME_MODE_PLAYING)
268 special = GFX_SPECIAL_ARG_DOOR;
271 return font_info[font_nr].special_bitmap_id[special];
276 void InitFontGraphicInfo()
278 static struct FontBitmapInfo *font_bitmap_info = NULL;
279 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
280 int num_property_mappings = getImageListPropertyMappingSize();
281 int num_font_bitmaps = NUM_FONTS;
284 if (graphic_info == NULL) /* still at startup phase */
286 InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
291 /* ---------- initialize font graphic definitions ---------- */
293 /* always start with reliable default values (normal font graphics) */
294 for (i=0; i < NUM_FONTS; i++)
295 font_info[i].graphic = FONT_INITIAL_1;
297 /* initialize normal font/graphic mapping from static configuration */
298 for (i=0; font_to_graphic[i].font_nr > -1; i++)
300 int font_nr = font_to_graphic[i].font_nr;
301 int special = font_to_graphic[i].special;
302 int graphic = font_to_graphic[i].graphic;
307 font_info[font_nr].graphic = graphic;
310 /* always start with reliable default values (special font graphics) */
311 for (i=0; i < NUM_FONTS; i++)
313 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
315 font_info[i].special_graphic[j] = font_info[i].graphic;
316 font_info[i].special_bitmap_id[j] = i;
320 /* initialize special font/graphic mapping from static configuration */
321 for (i=0; font_to_graphic[i].font_nr > -1; i++)
323 int font_nr = font_to_graphic[i].font_nr;
324 int special = font_to_graphic[i].special;
325 int graphic = font_to_graphic[i].graphic;
327 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
329 font_info[font_nr].special_graphic[special] = graphic;
330 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
335 /* initialize special element/graphic mapping from dynamic configuration */
336 for (i=0; i < num_property_mappings; i++)
338 int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
339 int special = property_mapping[i].ext3_index;
340 int graphic = property_mapping[i].artwork_index;
345 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
347 font_info[font_nr].special_graphic[special] = graphic;
348 font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
353 /* ---------- initialize font bitmap array ---------- */
355 if (font_bitmap_info != NULL)
356 FreeFontInfo(font_bitmap_info);
359 checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
361 /* ---------- initialize font bitmap definitions ---------- */
363 for (i=0; i < NUM_FONTS; i++)
365 if (i < NUM_INITIAL_FONTS)
367 font_bitmap_info[i] = font_initial[i];
371 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
373 int font_bitmap_id = font_info[i].special_bitmap_id[j];
374 int graphic = font_info[i].special_graphic[j];
376 /* set 'graphic_info' for font entries, if uninitialized (guessed) */
377 if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
379 graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
380 graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
383 /* copy font relevant information from graphics information */
384 font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
385 font_bitmap_info[font_bitmap_id].src_x = graphic_info[graphic].src_x;
386 font_bitmap_info[font_bitmap_id].src_y = graphic_info[graphic].src_y;
387 font_bitmap_info[font_bitmap_id].width = graphic_info[graphic].width;
388 font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
389 font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
390 font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
392 font_bitmap_info[font_bitmap_id].num_chars =
393 graphic_info[graphic].anim_frames;
394 font_bitmap_info[font_bitmap_id].num_chars_per_line =
395 graphic_info[graphic].anim_frames_per_line;
399 InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
402 void InitElementGraphicInfo()
404 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
405 int num_property_mappings = getImageListPropertyMappingSize();
408 /* set values to -1 to identify later as "uninitialized" values */
409 for (i=0; i<MAX_NUM_ELEMENTS; i++)
411 for (act=0; act<NUM_ACTIONS; act++)
413 element_info[i].graphic[act] = -1;
414 element_info[i].crumbled[act] = -1;
416 for (dir=0; dir<NUM_DIRECTIONS; dir++)
418 element_info[i].direction_graphic[act][dir] = -1;
419 element_info[i].direction_crumbled[act][dir] = -1;
424 /* initialize normal element/graphic mapping from static configuration */
425 for (i=0; element_to_graphic[i].element > -1; i++)
427 int element = element_to_graphic[i].element;
428 int action = element_to_graphic[i].action;
429 int direction = element_to_graphic[i].direction;
430 boolean crumbled = element_to_graphic[i].crumbled;
431 int graphic = element_to_graphic[i].graphic;
433 if (graphic_info[graphic].bitmap == NULL)
436 if ((action > -1 || direction > -1 || crumbled == TRUE) &&
437 el2img(element) != -1)
439 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
440 boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
442 /* if the base graphic ("emerald", for example) has been redefined,
443 but not the action graphic ("emerald.falling", for example), do not
444 use an existing (in this case considered obsolete) action graphic
445 anymore, but use the automatically determined default graphic */
446 if (base_redefined && !act_dir_redefined)
451 action = ACTION_DEFAULT;
456 element_info[element].direction_crumbled[action][direction] = graphic;
458 element_info[element].crumbled[action] = graphic;
463 element_info[element].direction_graphic[action][direction] = graphic;
465 element_info[element].graphic[action] = graphic;
469 /* initialize normal element/graphic mapping from dynamic configuration */
470 for (i=0; i < num_property_mappings; i++)
472 int element = property_mapping[i].base_index;
473 int action = property_mapping[i].ext1_index;
474 int direction = property_mapping[i].ext2_index;
475 int special = property_mapping[i].ext3_index;
476 int graphic = property_mapping[i].artwork_index;
477 boolean crumbled = FALSE;
479 if (special == GFX_SPECIAL_ARG_CRUMBLED)
485 if (graphic_info[graphic].bitmap == NULL)
488 if (element >= MAX_NUM_ELEMENTS || special != -1)
492 action = ACTION_DEFAULT;
497 for (dir=0; dir<NUM_DIRECTIONS; dir++)
498 element_info[element].direction_crumbled[action][dir] = -1;
501 element_info[element].direction_crumbled[action][direction] = graphic;
503 element_info[element].crumbled[action] = graphic;
508 for (dir=0; dir<NUM_DIRECTIONS; dir++)
509 element_info[element].direction_graphic[action][dir] = -1;
512 element_info[element].direction_graphic[action][direction] = graphic;
514 element_info[element].graphic[action] = graphic;
518 /* now copy all graphics that are defined to be cloned from other graphics */
519 for (i=0; i<MAX_NUM_ELEMENTS; i++)
521 int graphic = element_info[i].graphic[ACTION_DEFAULT];
522 int crumbled_like, diggable_like;
527 crumbled_like = graphic_info[graphic].crumbled_like;
528 diggable_like = graphic_info[graphic].diggable_like;
530 if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
532 for (act=0; act<NUM_ACTIONS; act++)
533 element_info[i].crumbled[act] =
534 element_info[crumbled_like].crumbled[act];
535 for (act=0; act<NUM_ACTIONS; act++)
536 for (dir=0; dir<NUM_DIRECTIONS; dir++)
537 element_info[i].direction_crumbled[act][dir] =
538 element_info[crumbled_like].direction_crumbled[act][dir];
541 if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
543 element_info[i].graphic[ACTION_DIGGING] =
544 element_info[diggable_like].graphic[ACTION_DIGGING];
545 for (dir=0; dir<NUM_DIRECTIONS; dir++)
546 element_info[i].direction_graphic[ACTION_DIGGING][dir] =
547 element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
552 /* now set all undefined/invalid graphics to -1 to set to default after it */
553 for (i=0; i<MAX_NUM_ELEMENTS; i++)
555 for (act=0; act<NUM_ACTIONS; act++)
559 graphic = element_info[i].graphic[act];
560 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
561 element_info[i].graphic[act] = -1;
563 graphic = element_info[i].crumbled[act];
564 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
565 element_info[i].crumbled[act] = -1;
567 for (dir=0; dir<NUM_DIRECTIONS; dir++)
569 graphic = element_info[i].direction_graphic[act][dir];
570 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
571 element_info[i].direction_graphic[act][dir] = -1;
573 graphic = element_info[i].direction_crumbled[act][dir];
574 if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
575 element_info[i].direction_crumbled[act][dir] = -1;
581 /* now set all '-1' values to element specific default values */
582 for (i=0; i<MAX_NUM_ELEMENTS; i++)
584 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
585 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
586 int default_direction_graphic[NUM_DIRECTIONS];
587 int default_direction_crumbled[NUM_DIRECTIONS];
589 if (default_graphic == -1)
590 default_graphic = IMG_CHAR_QUESTION;
591 if (default_crumbled == -1)
592 default_crumbled = IMG_EMPTY;
594 for (dir=0; dir<NUM_DIRECTIONS; dir++)
596 default_direction_graphic[dir] =
597 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
598 default_direction_crumbled[dir] =
599 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
601 if (default_direction_graphic[dir] == -1)
602 default_direction_graphic[dir] = default_graphic;
603 if (default_direction_crumbled[dir] == -1)
604 default_direction_crumbled[dir] = default_crumbled;
607 for (act=0; act<NUM_ACTIONS; act++)
609 boolean act_remove = ((IS_DIGGABLE(i) && act == ACTION_DIGGING) ||
610 (IS_SNAPPABLE(i) && act == ACTION_SNAPPING) ||
611 (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
613 /* generic default action graphic (defined by "[default]" directive) */
614 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
615 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
617 /* look for special default action graphic (classic game specific) */
618 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
619 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
620 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
621 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
622 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
623 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
625 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
626 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
627 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
628 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
629 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
630 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
632 if (default_action_graphic == -1)
633 default_action_graphic = default_graphic;
634 if (default_action_crumbled == -1)
635 default_action_crumbled = default_crumbled;
637 for (dir=0; dir<NUM_DIRECTIONS; dir++)
639 int default_action_direction_graphic = element_info[i].graphic[act];
640 int default_action_direction_crumbled = element_info[i].crumbled[act];
642 /* no graphic for current action -- use default direction graphic */
643 if (default_action_direction_graphic == -1)
644 default_action_direction_graphic =
645 (act_remove ? IMG_EMPTY : default_direction_graphic[dir]);
646 if (default_action_direction_crumbled == -1)
647 default_action_direction_crumbled =
648 (act_remove ? IMG_EMPTY : default_direction_crumbled[dir]);
650 if (element_info[i].direction_graphic[act][dir] == -1)
651 element_info[i].direction_graphic[act][dir] =
652 default_action_direction_graphic;
653 if (element_info[i].direction_crumbled[act][dir] == -1)
654 element_info[i].direction_crumbled[act][dir] =
655 default_action_direction_crumbled;
658 /* no graphic for this specific action -- use default action graphic */
659 if (element_info[i].graphic[act] == -1)
660 element_info[i].graphic[act] =
661 (act_remove ? IMG_EMPTY : default_action_graphic);
662 if (element_info[i].crumbled[act] == -1)
663 element_info[i].crumbled[act] =
664 (act_remove ? IMG_EMPTY : default_action_crumbled);
672 for (i=0; i<MAX_NUM_ELEMENTS; i++)
673 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
674 i != EL_CHAR_QUESTION)
675 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
676 element_info[i].token_name, i);
682 void InitElementSpecialGraphicInfo()
684 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
685 int num_property_mappings = getImageListPropertyMappingSize();
688 /* always start with reliable default values */
689 for (i=0; i < MAX_NUM_ELEMENTS; i++)
690 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
691 element_info[i].special_graphic[j] =
692 element_info[i].graphic[ACTION_DEFAULT];
694 /* initialize special element/graphic mapping from static configuration */
695 for (i=0; element_to_special_graphic[i].element > -1; i++)
697 int element = element_to_special_graphic[i].element;
698 int special = element_to_special_graphic[i].special;
699 int graphic = element_to_special_graphic[i].graphic;
700 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
701 boolean special_redefined = getImageListEntry(graphic)->redefined;
703 /* if the base graphic ("emerald", for example) has been redefined,
704 but not the special graphic ("emerald.EDITOR", for example), do not
705 use an existing (in this case considered obsolete) special graphic
706 anymore, but use the automatically created (down-scaled) graphic */
707 if (base_redefined && !special_redefined)
710 element_info[element].special_graphic[special] = graphic;
713 /* initialize special element/graphic mapping from dynamic configuration */
714 for (i=0; i < num_property_mappings; i++)
716 int element = property_mapping[i].base_index;
717 int special = property_mapping[i].ext3_index;
718 int graphic = property_mapping[i].artwork_index;
720 if (element >= MAX_NUM_ELEMENTS)
723 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
724 element_info[element].special_graphic[special] = graphic;
728 /* now set all undefined/invalid graphics to default */
729 for (i=0; i < MAX_NUM_ELEMENTS; i++)
730 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
731 if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
732 element_info[i].special_graphic[j] =
733 element_info[i].graphic[ACTION_DEFAULT];
737 static int get_element_from_token(char *token)
741 for (i=0; i < MAX_NUM_ELEMENTS; i++)
742 if (strcmp(element_info[i].token_name, token) == 0)
748 static void set_graphic_parameters(int graphic, char **parameter_raw)
750 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
751 int parameter[NUM_GFX_ARGS];
752 int anim_frames_per_row = 1, anim_frames_per_col = 1;
753 int anim_frames_per_line = 1;
756 /* get integer values from string parameters */
757 for (i=0; i < NUM_GFX_ARGS; i++)
760 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
761 image_config_suffix[i].type);
763 if (image_config_suffix[i].type == TYPE_TOKEN)
764 parameter[i] = get_element_from_token(parameter_raw[i]);
767 graphic_info[graphic].bitmap = src_bitmap;
769 /* start with reliable default values */
770 graphic_info[graphic].src_x = 0;
771 graphic_info[graphic].src_y = 0;
772 graphic_info[graphic].width = TILEX;
773 graphic_info[graphic].height = TILEY;
774 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
775 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
776 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
777 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
778 graphic_info[graphic].border_size = TILEX / 8; /* "CRUMBLED" border size */
780 /* optional x and y tile position of animation frame sequence */
781 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
782 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
783 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
784 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
786 /* optional x and y pixel position of animation frame sequence */
787 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
788 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
789 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
790 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
792 /* optional width and height of each animation frame */
793 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
794 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
795 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
796 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
800 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
801 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
804 /* correct x or y offset dependent of vertical or horizontal frame order */
805 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
807 graphic_info[graphic].offset_y =
808 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
809 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
810 anim_frames_per_line = anim_frames_per_col;
812 else /* frames are ordered horizontally */
814 graphic_info[graphic].offset_x =
815 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
816 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
817 anim_frames_per_line = anim_frames_per_row;
820 /* optionally, the x and y offset of frames can be specified directly */
821 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
822 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
823 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
824 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
826 /* automatically determine correct number of frames, if not defined */
827 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
828 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
829 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
830 graphic_info[graphic].anim_frames = anim_frames_per_row;
831 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
832 graphic_info[graphic].anim_frames = anim_frames_per_col;
834 graphic_info[graphic].anim_frames = 1;
836 graphic_info[graphic].anim_frames_per_line =
837 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
838 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
840 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
841 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
842 graphic_info[graphic].anim_delay = 1;
844 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
845 if (graphic_info[graphic].anim_frames == 1)
846 graphic_info[graphic].anim_mode = ANIM_NONE;
848 /* automatically determine correct start frame, if not defined */
849 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
850 graphic_info[graphic].anim_start_frame = 0;
851 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
852 graphic_info[graphic].anim_start_frame =
853 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
855 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
857 /* animation synchronized with global frame counter, not move position */
858 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
860 /* optional element for cloning crumble graphics */
861 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
862 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
864 /* optional element for cloning digging graphics */
865 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
866 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
868 /* optional border size for "crumbling" diggable graphics */
869 if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
870 graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
872 /* this is only used for toon animations */
873 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
874 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
876 /* this is only used for drawing font characters */
877 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
878 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
880 /* this is only used for drawing envelope graphics */
881 graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
884 static void InitGraphicInfo()
886 int fallback_graphic = IMG_CHAR_EXCLAM;
887 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
888 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
889 int num_images = getImageListSize();
892 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
893 static boolean clipmasks_initialized = FALSE;
895 XGCValues clip_gc_values;
896 unsigned long clip_gc_valuemask;
897 GC copy_clipmask_gc = None;
900 if (graphic_info != NULL)
903 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
906 printf("::: graphic_info: %d entries\n", num_images);
909 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
910 if (clipmasks_initialized)
912 for (i=0; i<num_images; i++)
914 if (graphic_info[i].clip_mask)
915 XFreePixmap(display, graphic_info[i].clip_mask);
916 if (graphic_info[i].clip_gc)
917 XFreeGC(display, graphic_info[i].clip_gc);
919 graphic_info[i].clip_mask = None;
920 graphic_info[i].clip_gc = None;
925 for (i=0; i<num_images; i++)
927 struct FileInfo *image = getImageListEntry(i);
930 int first_frame, last_frame;
933 printf("::: image: '%s' [%d]\n", image->token, i);
937 printf("::: image # %d: '%s' ['%s']\n",
939 getTokenFromImageID(i));
942 set_graphic_parameters(i, image->parameter);
944 /* now check if no animation frames are outside of the loaded image */
946 if (graphic_info[i].bitmap == NULL)
947 continue; /* skip check for optional images that are undefined */
950 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
951 if (src_x < 0 || src_y < 0 ||
952 src_x + TILEX > src_bitmap->width ||
953 src_y + TILEY > src_bitmap->height)
955 Error(ERR_RETURN_LINE, "-");
956 Error(ERR_RETURN, "warning: error found in config file:");
957 Error(ERR_RETURN, "- config file: '%s'",
958 getImageConfigFilename());
959 Error(ERR_RETURN, "- config token: '%s'",
960 getTokenFromImageID(i));
961 Error(ERR_RETURN, "- image file: '%s'",
962 src_bitmap->source_filename);
964 "error: first animation frame out of bounds (%d, %d)",
966 Error(ERR_RETURN, "custom graphic rejected for this element/action");
968 if (i == fallback_graphic)
969 Error(ERR_EXIT, "fatal error: no fallback graphic available");
971 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
972 Error(ERR_RETURN_LINE, "-");
974 set_graphic_parameters(i, fallback_image->default_parameter);
975 graphic_info[i].bitmap = fallback_bitmap;
978 last_frame = graphic_info[i].anim_frames - 1;
979 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
980 if (src_x < 0 || src_y < 0 ||
981 src_x + TILEX > src_bitmap->width ||
982 src_y + TILEY > src_bitmap->height)
984 Error(ERR_RETURN_LINE, "-");
985 Error(ERR_RETURN, "warning: error found in config file:");
986 Error(ERR_RETURN, "- config file: '%s'",
987 getImageConfigFilename());
988 Error(ERR_RETURN, "- config token: '%s'",
989 getTokenFromImageID(i));
990 Error(ERR_RETURN, "- image file: '%s'",
991 src_bitmap->source_filename);
993 "error: last animation frame (%d) out of bounds (%d, %d)",
994 last_frame, src_x, src_y);
995 Error(ERR_RETURN, "custom graphic rejected for this element/action");
997 if (i == fallback_graphic)
998 Error(ERR_EXIT, "fatal error: no fallback graphic available");
1000 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1001 Error(ERR_RETURN_LINE, "-");
1003 set_graphic_parameters(i, fallback_image->default_parameter);
1004 graphic_info[i].bitmap = fallback_bitmap;
1007 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1008 /* currently we need only a tile clip mask from the first frame */
1009 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1011 if (copy_clipmask_gc == None)
1013 clip_gc_values.graphics_exposures = False;
1014 clip_gc_valuemask = GCGraphicsExposures;
1015 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1016 clip_gc_valuemask, &clip_gc_values);
1019 graphic_info[i].clip_mask =
1020 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1022 src_pixmap = src_bitmap->clip_mask;
1023 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1024 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1026 clip_gc_values.graphics_exposures = False;
1027 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1028 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1030 graphic_info[i].clip_gc =
1031 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1035 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1036 if (copy_clipmask_gc)
1037 XFreeGC(display, copy_clipmask_gc);
1039 clipmasks_initialized = TRUE;
1043 static void InitElementSoundInfo()
1045 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1046 int num_property_mappings = getSoundListPropertyMappingSize();
1049 /* set values to -1 to identify later as "uninitialized" values */
1050 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1051 for (act=0; act < NUM_ACTIONS; act++)
1052 element_info[i].sound[act] = -1;
1054 /* initialize element/sound mapping from static configuration */
1055 for (i=0; element_to_sound[i].element > -1; i++)
1057 int element = element_to_sound[i].element;
1058 int action = element_to_sound[i].action;
1059 int sound = element_to_sound[i].sound;
1060 boolean is_class = element_to_sound[i].is_class;
1063 action = ACTION_DEFAULT;
1066 element_info[element].sound[action] = sound;
1068 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1069 if (strcmp(element_info[j].class_name,
1070 element_info[element].class_name) == 0)
1071 element_info[j].sound[action] = sound;
1074 /* initialize element class/sound mapping from dynamic configuration */
1075 for (i=0; i < num_property_mappings; i++)
1077 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1078 int action = property_mapping[i].ext1_index;
1079 int sound = property_mapping[i].artwork_index;
1081 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1085 action = ACTION_DEFAULT;
1087 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1088 if (strcmp(element_info[j].class_name,
1089 element_info[element_class].class_name) == 0)
1090 element_info[j].sound[action] = sound;
1093 /* initialize element/sound mapping from dynamic configuration */
1094 for (i=0; i < num_property_mappings; i++)
1096 int element = property_mapping[i].base_index;
1097 int action = property_mapping[i].ext1_index;
1098 int sound = property_mapping[i].artwork_index;
1100 if (element >= MAX_NUM_ELEMENTS)
1104 action = ACTION_DEFAULT;
1106 element_info[element].sound[action] = sound;
1109 /* now set all '-1' values to element specific default values */
1110 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1112 for (act=0; act < NUM_ACTIONS; act++)
1114 /* generic default action sound (defined by "[default]" directive) */
1115 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1117 /* look for special default action sound (classic game specific) */
1118 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1119 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1120 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1121 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1122 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1123 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1125 /* look for element specific default sound (independent from action) */
1126 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1127 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1129 /* no sound for this specific action -- use default action sound */
1130 if (element_info[i].sound[act] == -1)
1131 element_info[i].sound[act] = default_action_sound;
1136 static void set_sound_parameters(int sound, char **parameter_raw)
1138 int parameter[NUM_SND_ARGS];
1141 /* get integer values from string parameters */
1142 for (i=0; i < NUM_SND_ARGS; i++)
1144 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1145 sound_config_suffix[i].type);
1147 /* explicit loop mode setting in configuration overrides default value */
1148 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1149 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1152 static void InitSoundInfo()
1155 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1156 int num_property_mappings = getSoundListPropertyMappingSize();
1158 int *sound_effect_properties;
1159 int num_sounds = getSoundListSize();
1162 if (sound_info != NULL)
1165 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1166 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1168 /* initialize sound effect for all elements to "no sound" */
1169 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1170 for (j=0; j<NUM_ACTIONS; j++)
1171 element_info[i].sound[j] = SND_UNDEFINED;
1173 for (i=0; i<num_sounds; i++)
1175 struct FileInfo *sound = getSoundListEntry(i);
1176 int len_effect_text = strlen(sound->token);
1178 sound_effect_properties[i] = ACTION_OTHER;
1179 sound_info[i].loop = FALSE;
1182 printf("::: sound %d: '%s'\n", i, sound->token);
1185 /* determine all loop sounds and identify certain sound classes */
1187 for (j=0; element_action_info[j].suffix; j++)
1189 int len_action_text = strlen(element_action_info[j].suffix);
1191 if (len_action_text < len_effect_text &&
1192 strcmp(&sound->token[len_effect_text - len_action_text],
1193 element_action_info[j].suffix) == 0)
1195 sound_effect_properties[i] = element_action_info[j].value;
1196 sound_info[i].loop = element_action_info[j].is_loop_sound;
1203 if (strcmp(sound->token, "custom_42") == 0)
1204 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1207 /* associate elements and some selected sound actions */
1209 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1211 if (element_info[j].class_name)
1213 int len_class_text = strlen(element_info[j].class_name);
1215 if (len_class_text + 1 < len_effect_text &&
1216 strncmp(sound->token,
1217 element_info[j].class_name, len_class_text) == 0 &&
1218 sound->token[len_class_text] == '.')
1220 int sound_action_value = sound_effect_properties[i];
1222 element_info[j].sound[sound_action_value] = i;
1227 set_sound_parameters(i, sound->parameter);
1230 free(sound_effect_properties);
1233 /* !!! now handled in InitElementSoundInfo() !!! */
1234 /* initialize element/sound mapping from dynamic configuration */
1235 for (i=0; i < num_property_mappings; i++)
1237 int element = property_mapping[i].base_index;
1238 int action = property_mapping[i].ext1_index;
1239 int sound = property_mapping[i].artwork_index;
1242 action = ACTION_DEFAULT;
1244 printf("::: %d: %d, %d, %d ['%s']\n",
1245 i, element, action, sound, element_info[element].token_name);
1247 element_info[element].sound[action] = sound;
1254 int element = EL_CUSTOM_11;
1257 while (element_action_info[j].suffix)
1259 printf("element %d, sound action '%s' == %d\n",
1260 element, element_action_info[j].suffix,
1261 element_info[element].sound[j]);
1266 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1272 int element = EL_SAND;
1273 int sound_action = ACTION_DIGGING;
1276 while (element_action_info[j].suffix)
1278 if (element_action_info[j].value == sound_action)
1279 printf("element %d, sound action '%s' == %d\n",
1280 element, element_action_info[j].suffix,
1281 element_info[element].sound[sound_action]);
1288 static void ReinitializeGraphics()
1290 InitGraphicInfo(); /* graphic properties mapping */
1291 InitElementGraphicInfo(); /* element game graphic mapping */
1292 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1294 InitElementSmallImages(); /* create editor and preview images */
1295 InitFontGraphicInfo(); /* initialize text drawing functions */
1297 SetMainBackgroundImage(IMG_BACKGROUND);
1298 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1304 static void ReinitializeSounds()
1306 InitSoundInfo(); /* sound properties mapping */
1307 InitElementSoundInfo(); /* element game sound mapping */
1309 InitPlaySoundLevel(); /* internal game sound settings */
1312 static void ReinitializeMusic()
1314 /* currently nothing to do */
1317 void InitElementPropertiesStatic()
1319 static int ep_diggable[] =
1324 EL_SP_BUGGY_BASE_ACTIVATING,
1327 EL_INVISIBLE_SAND_ACTIVE,
1329 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1333 EL_SP_BUGGY_BASE_ACTIVE,
1338 static int ep_collectible_only[] =
1355 EL_DYNABOMB_INCREASE_NUMBER,
1356 EL_DYNABOMB_INCREASE_SIZE,
1357 EL_DYNABOMB_INCREASE_POWER,
1371 static int ep_dont_run_into[] =
1373 /* same elements as in 'ep_dont_touch' */
1379 /* same elements as in 'ep_dont_collide_with' */
1391 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1393 EL_SP_BUGGY_BASE_ACTIVE,
1400 static int ep_dont_collide_with[] =
1402 /* same elements as in 'ep_dont_touch' */
1418 static int ep_dont_touch[] =
1427 static int ep_indestructible[] =
1431 EL_ACID_POOL_TOPLEFT,
1432 EL_ACID_POOL_TOPRIGHT,
1433 EL_ACID_POOL_BOTTOMLEFT,
1434 EL_ACID_POOL_BOTTOM,
1435 EL_ACID_POOL_BOTTOMRIGHT,
1436 EL_SP_HARDWARE_GRAY,
1437 EL_SP_HARDWARE_GREEN,
1438 EL_SP_HARDWARE_BLUE,
1440 EL_SP_HARDWARE_YELLOW,
1441 EL_SP_HARDWARE_BASE_1,
1442 EL_SP_HARDWARE_BASE_2,
1443 EL_SP_HARDWARE_BASE_3,
1444 EL_SP_HARDWARE_BASE_4,
1445 EL_SP_HARDWARE_BASE_5,
1446 EL_SP_HARDWARE_BASE_6,
1447 EL_INVISIBLE_STEELWALL,
1448 EL_INVISIBLE_STEELWALL_ACTIVE,
1449 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1450 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1451 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1452 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1453 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1454 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1455 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1456 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1457 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1458 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1459 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1460 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1462 EL_LIGHT_SWITCH_ACTIVE,
1463 EL_SIGN_EXCLAMATION,
1464 EL_SIGN_RADIOACTIVITY,
1475 EL_STEELWALL_SLIPPERY,
1498 EL_SWITCHGATE_OPENING,
1499 EL_SWITCHGATE_CLOSED,
1500 EL_SWITCHGATE_CLOSING,
1502 EL_SWITCHGATE_SWITCH_UP,
1503 EL_SWITCHGATE_SWITCH_DOWN,
1506 EL_TIMEGATE_OPENING,
1508 EL_TIMEGATE_CLOSING,
1511 EL_TIMEGATE_SWITCH_ACTIVE,
1516 EL_TUBE_VERTICAL_LEFT,
1517 EL_TUBE_VERTICAL_RIGHT,
1518 EL_TUBE_HORIZONTAL_UP,
1519 EL_TUBE_HORIZONTAL_DOWN,
1527 static int ep_slippery[] =
1541 EL_ROBOT_WHEEL_ACTIVE,
1547 EL_ACID_POOL_TOPLEFT,
1548 EL_ACID_POOL_TOPRIGHT,
1558 EL_STEELWALL_SLIPPERY,
1564 static int ep_can_change[] =
1569 static int ep_can_move[] =
1591 static int ep_can_fall[] =
1606 EL_BD_MAGIC_WALL_FULL,
1619 static int ep_can_smash_player[] =
1644 static int ep_can_smash_enemies[] =
1652 static int ep_can_smash_everything[] =
1660 static int ep_can_explode_by_fire[] =
1662 /* same elements as in 'ep_can_explode_impact' */
1667 /* same elements as in 'ep_can_explode_smashed' */
1676 EL_DYNABOMB_PLAYER_1_ACTIVE,
1677 EL_DYNABOMB_PLAYER_2_ACTIVE,
1678 EL_DYNABOMB_PLAYER_3_ACTIVE,
1679 EL_DYNABOMB_PLAYER_4_ACTIVE,
1680 EL_DYNABOMB_INCREASE_NUMBER,
1681 EL_DYNABOMB_INCREASE_SIZE,
1682 EL_DYNABOMB_INCREASE_POWER,
1683 EL_SP_DISK_RED_ACTIVE,
1693 static int ep_can_explode_smashed[] =
1695 /* same elements as in 'ep_can_explode_impact' */
1708 static int ep_can_explode_impact[] =
1716 static int ep_walkable_over[] =
1720 EL_SOKOBAN_FIELD_EMPTY,
1737 static int ep_walkable_inside[] =
1742 EL_TUBE_VERTICAL_LEFT,
1743 EL_TUBE_VERTICAL_RIGHT,
1744 EL_TUBE_HORIZONTAL_UP,
1745 EL_TUBE_HORIZONTAL_DOWN,
1753 static int ep_walkable_under[] =
1758 static int ep_passable_over[] =
1773 static int ep_passable_inside[] =
1779 EL_SP_PORT_HORIZONTAL,
1780 EL_SP_PORT_VERTICAL,
1782 EL_SP_GRAVITY_PORT_LEFT,
1783 EL_SP_GRAVITY_PORT_RIGHT,
1784 EL_SP_GRAVITY_PORT_UP,
1785 EL_SP_GRAVITY_PORT_DOWN,
1789 static int ep_passable_under[] =
1794 static int ep_pushable[] =
1806 EL_SOKOBAN_FIELD_FULL,
1813 static int ep_can_be_crumbled[] =
1822 static int ep_player[] =
1832 static int ep_can_pass_magic_wall[] =
1845 static int ep_switchable[] =
1849 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1850 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1851 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1852 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1853 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1854 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1855 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1856 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1857 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1858 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1859 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1860 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1861 EL_SWITCHGATE_SWITCH_UP,
1862 EL_SWITCHGATE_SWITCH_DOWN,
1864 EL_LIGHT_SWITCH_ACTIVE,
1866 EL_BALLOON_SWITCH_LEFT,
1867 EL_BALLOON_SWITCH_RIGHT,
1868 EL_BALLOON_SWITCH_UP,
1869 EL_BALLOON_SWITCH_DOWN,
1870 EL_BALLOON_SWITCH_ANY,
1876 static int ep_bd_element[] =
1905 static int ep_sp_element[] =
1913 EL_SP_HARDWARE_GRAY,
1921 EL_SP_GRAVITY_PORT_RIGHT,
1922 EL_SP_GRAVITY_PORT_DOWN,
1923 EL_SP_GRAVITY_PORT_LEFT,
1924 EL_SP_GRAVITY_PORT_UP,
1929 EL_SP_PORT_VERTICAL,
1930 EL_SP_PORT_HORIZONTAL,
1936 EL_SP_HARDWARE_BASE_1,
1937 EL_SP_HARDWARE_GREEN,
1938 EL_SP_HARDWARE_BLUE,
1940 EL_SP_HARDWARE_YELLOW,
1941 EL_SP_HARDWARE_BASE_2,
1942 EL_SP_HARDWARE_BASE_3,
1943 EL_SP_HARDWARE_BASE_4,
1944 EL_SP_HARDWARE_BASE_5,
1945 EL_SP_HARDWARE_BASE_6,
1948 /* additional elements that appeared in newer Supaplex levels */
1950 /* more than one murphy in a level results in an inactive clone */
1952 /* runtime elements*/
1953 EL_SP_DISK_RED_ACTIVE,
1954 EL_SP_TERMINAL_ACTIVE,
1955 EL_SP_BUGGY_BASE_ACTIVATING,
1956 EL_SP_BUGGY_BASE_ACTIVE,
1960 static int ep_sb_element[] =
1965 EL_SOKOBAN_FIELD_EMPTY,
1966 EL_SOKOBAN_FIELD_FULL,
1968 EL_INVISIBLE_STEELWALL,
1972 static int ep_gem[] =
1983 static int ep_food_dark_yamyam[] =
2010 static int ep_food_penguin[] =
2023 static int ep_food_pig[] =
2034 static int ep_historic_wall[] =
2059 EL_EXPANDABLE_WALL_HORIZONTAL,
2060 EL_EXPANDABLE_WALL_VERTICAL,
2061 EL_EXPANDABLE_WALL_ANY,
2062 EL_EXPANDABLE_WALL_GROWING,
2069 EL_SP_HARDWARE_GRAY,
2070 EL_SP_HARDWARE_GREEN,
2071 EL_SP_HARDWARE_BLUE,
2073 EL_SP_HARDWARE_YELLOW,
2074 EL_SP_HARDWARE_BASE_1,
2075 EL_SP_HARDWARE_BASE_2,
2076 EL_SP_HARDWARE_BASE_3,
2077 EL_SP_HARDWARE_BASE_4,
2078 EL_SP_HARDWARE_BASE_5,
2079 EL_SP_HARDWARE_BASE_6,
2081 EL_SP_TERMINAL_ACTIVE,
2084 EL_INVISIBLE_STEELWALL,
2085 EL_INVISIBLE_STEELWALL_ACTIVE,
2087 EL_INVISIBLE_WALL_ACTIVE,
2088 EL_STEELWALL_SLIPPERY,
2104 static int ep_historic_solid[] =
2108 EL_EXPANDABLE_WALL_HORIZONTAL,
2109 EL_EXPANDABLE_WALL_VERTICAL,
2110 EL_EXPANDABLE_WALL_ANY,
2123 EL_QUICKSAND_FILLING,
2124 EL_QUICKSAND_EMPTYING,
2126 EL_MAGIC_WALL_ACTIVE,
2127 EL_MAGIC_WALL_EMPTYING,
2128 EL_MAGIC_WALL_FILLING,
2132 EL_BD_MAGIC_WALL_ACTIVE,
2133 EL_BD_MAGIC_WALL_EMPTYING,
2134 EL_BD_MAGIC_WALL_FULL,
2135 EL_BD_MAGIC_WALL_FILLING,
2136 EL_BD_MAGIC_WALL_DEAD,
2145 EL_SP_TERMINAL_ACTIVE,
2149 EL_INVISIBLE_WALL_ACTIVE,
2150 EL_SWITCHGATE_SWITCH_UP,
2151 EL_SWITCHGATE_SWITCH_DOWN,
2153 EL_TIMEGATE_SWITCH_ACTIVE,
2165 /* the following elements are a direct copy of "indestructible" elements,
2166 except "EL_ACID", which is "indestructible", but not "solid"! */
2171 EL_ACID_POOL_TOPLEFT,
2172 EL_ACID_POOL_TOPRIGHT,
2173 EL_ACID_POOL_BOTTOMLEFT,
2174 EL_ACID_POOL_BOTTOM,
2175 EL_ACID_POOL_BOTTOMRIGHT,
2176 EL_SP_HARDWARE_GRAY,
2177 EL_SP_HARDWARE_GREEN,
2178 EL_SP_HARDWARE_BLUE,
2180 EL_SP_HARDWARE_YELLOW,
2181 EL_SP_HARDWARE_BASE_1,
2182 EL_SP_HARDWARE_BASE_2,
2183 EL_SP_HARDWARE_BASE_3,
2184 EL_SP_HARDWARE_BASE_4,
2185 EL_SP_HARDWARE_BASE_5,
2186 EL_SP_HARDWARE_BASE_6,
2187 EL_INVISIBLE_STEELWALL,
2188 EL_INVISIBLE_STEELWALL_ACTIVE,
2189 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2190 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2191 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2192 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2193 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2194 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2195 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2196 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2197 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2198 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2199 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2200 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2202 EL_LIGHT_SWITCH_ACTIVE,
2203 EL_SIGN_EXCLAMATION,
2204 EL_SIGN_RADIOACTIVITY,
2215 EL_STEELWALL_SLIPPERY,
2238 EL_SWITCHGATE_OPENING,
2239 EL_SWITCHGATE_CLOSED,
2240 EL_SWITCHGATE_CLOSING,
2242 EL_TIMEGATE_OPENING,
2244 EL_TIMEGATE_CLOSING,
2248 EL_TUBE_VERTICAL_LEFT,
2249 EL_TUBE_VERTICAL_RIGHT,
2250 EL_TUBE_HORIZONTAL_UP,
2251 EL_TUBE_HORIZONTAL_DOWN,
2259 static int ep_classic_enemy[] =
2275 static int ep_belt[] =
2277 EL_CONVEYOR_BELT_1_LEFT,
2278 EL_CONVEYOR_BELT_1_MIDDLE,
2279 EL_CONVEYOR_BELT_1_RIGHT,
2280 EL_CONVEYOR_BELT_2_LEFT,
2281 EL_CONVEYOR_BELT_2_MIDDLE,
2282 EL_CONVEYOR_BELT_2_RIGHT,
2283 EL_CONVEYOR_BELT_3_LEFT,
2284 EL_CONVEYOR_BELT_3_MIDDLE,
2285 EL_CONVEYOR_BELT_3_RIGHT,
2286 EL_CONVEYOR_BELT_4_LEFT,
2287 EL_CONVEYOR_BELT_4_MIDDLE,
2288 EL_CONVEYOR_BELT_4_RIGHT,
2292 static int ep_belt_active[] =
2294 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2295 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2296 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2297 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2298 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2299 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2300 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2301 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2302 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2303 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2304 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2305 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2309 static int ep_belt_switch[] =
2311 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2312 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2313 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2314 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2315 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2316 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2317 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2318 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2319 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2320 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2321 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2322 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2326 static int ep_tube[] =
2333 EL_TUBE_HORIZONTAL_UP,
2334 EL_TUBE_HORIZONTAL_DOWN,
2336 EL_TUBE_VERTICAL_LEFT,
2337 EL_TUBE_VERTICAL_RIGHT,
2342 static int ep_keygate[] =
2363 static int ep_amoeboid[] =
2373 static int ep_amoebalive[] =
2382 static int ep_has_content[] =
2392 static int ep_active_bomb[] =
2395 EL_DYNABOMB_PLAYER_1_ACTIVE,
2396 EL_DYNABOMB_PLAYER_2_ACTIVE,
2397 EL_DYNABOMB_PLAYER_3_ACTIVE,
2398 EL_DYNABOMB_PLAYER_4_ACTIVE,
2399 EL_SP_DISK_RED_ACTIVE,
2403 static int ep_inactive[] =
2440 EL_INVISIBLE_STEELWALL,
2448 EL_WALL_EMERALD_YELLOW,
2449 EL_DYNABOMB_INCREASE_NUMBER,
2450 EL_DYNABOMB_INCREASE_SIZE,
2451 EL_DYNABOMB_INCREASE_POWER,
2455 EL_SOKOBAN_FIELD_EMPTY,
2456 EL_SOKOBAN_FIELD_FULL,
2457 EL_WALL_EMERALD_RED,
2458 EL_WALL_EMERALD_PURPLE,
2459 EL_ACID_POOL_TOPLEFT,
2460 EL_ACID_POOL_TOPRIGHT,
2461 EL_ACID_POOL_BOTTOMLEFT,
2462 EL_ACID_POOL_BOTTOM,
2463 EL_ACID_POOL_BOTTOMRIGHT,
2467 EL_BD_MAGIC_WALL_DEAD,
2468 EL_AMOEBA_TO_DIAMOND,
2476 EL_SP_GRAVITY_PORT_RIGHT,
2477 EL_SP_GRAVITY_PORT_DOWN,
2478 EL_SP_GRAVITY_PORT_LEFT,
2479 EL_SP_GRAVITY_PORT_UP,
2480 EL_SP_PORT_HORIZONTAL,
2481 EL_SP_PORT_VERTICAL,
2492 EL_SP_HARDWARE_GRAY,
2493 EL_SP_HARDWARE_GREEN,
2494 EL_SP_HARDWARE_BLUE,
2496 EL_SP_HARDWARE_YELLOW,
2497 EL_SP_HARDWARE_BASE_1,
2498 EL_SP_HARDWARE_BASE_2,
2499 EL_SP_HARDWARE_BASE_3,
2500 EL_SP_HARDWARE_BASE_4,
2501 EL_SP_HARDWARE_BASE_5,
2502 EL_SP_HARDWARE_BASE_6,
2503 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2504 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2505 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2506 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2507 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2508 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2509 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2510 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2511 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2512 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2513 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2514 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2515 EL_SIGN_EXCLAMATION,
2516 EL_SIGN_RADIOACTIVITY,
2527 EL_STEELWALL_SLIPPERY,
2547 } element_properties[] =
2549 { ep_diggable, EP_DIGGABLE },
2550 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2551 { ep_dont_run_into, EP_DONT_RUN_INTO },
2552 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2553 { ep_dont_touch, EP_DONT_TOUCH },
2554 { ep_indestructible, EP_INDESTRUCTIBLE },
2555 { ep_slippery, EP_SLIPPERY },
2556 { ep_can_change, EP_CAN_CHANGE },
2557 { ep_can_move, EP_CAN_MOVE },
2558 { ep_can_fall, EP_CAN_FALL },
2559 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2560 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2561 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2562 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2563 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2564 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2565 { ep_walkable_over, EP_WALKABLE_OVER },
2566 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2567 { ep_walkable_under, EP_WALKABLE_UNDER },
2568 { ep_passable_over, EP_PASSABLE_OVER },
2569 { ep_passable_inside, EP_PASSABLE_INSIDE },
2570 { ep_passable_under, EP_PASSABLE_UNDER },
2571 { ep_pushable, EP_PUSHABLE },
2573 { ep_can_be_crumbled, EP_CAN_BE_CRUMBLED },
2575 { ep_player, EP_PLAYER },
2576 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2577 { ep_switchable, EP_SWITCHABLE },
2578 { ep_bd_element, EP_BD_ELEMENT },
2579 { ep_sp_element, EP_SP_ELEMENT },
2580 { ep_sb_element, EP_SB_ELEMENT },
2582 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2583 { ep_food_penguin, EP_FOOD_PENGUIN },
2584 { ep_food_pig, EP_FOOD_PIG },
2585 { ep_historic_wall, EP_HISTORIC_WALL },
2586 { ep_historic_solid, EP_HISTORIC_SOLID },
2587 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2588 { ep_belt, EP_BELT },
2589 { ep_belt_active, EP_BELT_ACTIVE },
2590 { ep_belt_switch, EP_BELT_SWITCH },
2591 { ep_tube, EP_TUBE },
2592 { ep_keygate, EP_KEYGATE },
2593 { ep_amoeboid, EP_AMOEBOID },
2594 { ep_amoebalive, EP_AMOEBALIVE },
2595 { ep_has_content, EP_HAS_CONTENT },
2596 { ep_active_bomb, EP_ACTIVE_BOMB },
2597 { ep_inactive, EP_INACTIVE },
2602 static int copy_properties[][5] =
2606 EL_BUG_LEFT, EL_BUG_RIGHT,
2607 EL_BUG_UP, EL_BUG_DOWN
2611 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2612 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2616 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2617 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2621 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2622 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2626 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2627 EL_PACMAN_UP, EL_PACMAN_DOWN
2637 /* always start with reliable default values (element has no properties) */
2638 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2639 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2640 SET_PROPERTY(i, j, FALSE);
2642 /* set all base element properties from above array definitions */
2643 for (i=0; element_properties[i].elements != NULL; i++)
2644 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2645 SET_PROPERTY((element_properties[i].elements)[j],
2646 element_properties[i].property, TRUE);
2648 /* copy properties to some elements that are only stored in level file */
2649 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2650 for (j=0; copy_properties[j][0] != -1; j++)
2651 if (HAS_PROPERTY(copy_properties[j][0], i))
2652 for (k=1; k<=4; k++)
2653 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2656 void InitElementPropertiesEngine(int engine_version)
2659 static int active_properties[] =
2664 EP_DONT_COLLIDE_WITH,
2668 EP_CAN_PASS_MAGIC_WALL,
2673 EP_CAN_EXPLODE_BY_FIRE,
2686 EP_EM_SLIPPERY_WALL,
2691 static int no_wall_properties[] =
2694 EP_COLLECTIBLE_ONLY,
2696 EP_DONT_COLLIDE_WITH,
2699 EP_CAN_SMASH_PLAYER,
2700 EP_CAN_SMASH_ENEMIES,
2701 EP_CAN_SMASH_EVERYTHING,
2708 EP_FOOD_DARK_YAMYAM,
2724 InitElementPropertiesStatic();
2727 /* set all special, combined or engine dependent element properties */
2728 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2731 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2732 SET_PROPERTY(i, j, FALSE);
2735 /* ---------- INACTIVE ------------------------------------------------- */
2736 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2737 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2739 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2740 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2741 IS_WALKABLE_INSIDE(i) ||
2742 IS_WALKABLE_UNDER(i)));
2744 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2745 IS_PASSABLE_INSIDE(i) ||
2746 IS_PASSABLE_UNDER(i)));
2748 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2749 IS_PASSABLE_OVER(i)));
2751 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2752 IS_PASSABLE_INSIDE(i)));
2754 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2755 IS_PASSABLE_UNDER(i)));
2757 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2760 /* ---------- COLLECTIBLE ---------------------------------------------- */
2761 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2764 /* ---------- SNAPPABLE ------------------------------------------------ */
2765 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2766 IS_COLLECTIBLE(i) ||
2770 /* ---------- WALL ----------------------------------------------------- */
2771 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2773 for (j=0; no_wall_properties[j] != -1; j++)
2774 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2775 i >= EL_FIRST_RUNTIME_UNREAL)
2776 SET_PROPERTY(i, EP_WALL, FALSE);
2778 if (IS_HISTORIC_WALL(i))
2779 SET_PROPERTY(i, EP_WALL, TRUE);
2781 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2782 if (engine_version < VERSION_IDENT(2,2,0))
2783 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2785 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2787 !IS_COLLECTIBLE(i)));
2789 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2791 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2792 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2794 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2795 IS_INDESTRUCTIBLE(i)));
2797 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2799 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2800 else if (engine_version < VERSION_IDENT(2,2,0))
2801 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2803 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2804 !IS_WALKABLE_OVER(i) &&
2805 !IS_WALKABLE_UNDER(i)));
2807 if (IS_CUSTOM_ELEMENT(i))
2809 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2811 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2812 if (DONT_COLLIDE_WITH(i))
2813 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2815 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2816 if (CAN_SMASH_EVERYTHING(i))
2817 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2818 if (CAN_SMASH_ENEMIES(i))
2819 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2822 /* ---------- CAN_SMASH ------------------------------------------------ */
2823 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2824 CAN_SMASH_ENEMIES(i) ||
2825 CAN_SMASH_EVERYTHING(i)));
2827 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2828 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2829 CAN_EXPLODE_SMASHED(i) ||
2830 CAN_EXPLODE_IMPACT(i)));
2832 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2833 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2834 !CAN_EXPLODE_1X1(i)));
2836 /* ---------- CAN_BE_CRUMBLED ------------------------------------------ */
2837 SET_PROPERTY(i, EP_CAN_BE_CRUMBLED,
2838 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2841 if (CAN_BE_CRUMBLED(i))
2842 printf("::: '%s' can be crumbled [%d]\n",
2843 element_info[i].token_name,
2844 element_info[i].crumbled[ACTION_DEFAULT]);
2847 /* ---------- CAN_CHANGE ----------------------------------------------- */
2848 SET_PROPERTY(i, EP_CAN_CHANGE, FALSE); /* default: cannot change */
2849 for (j=0; j < element_info[i].num_change_pages; j++)
2850 if (element_info[i].change_page[j].can_change)
2851 SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
2855 /* determine inactive elements (used for engine main loop optimization) */
2856 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2858 boolean active = FALSE;
2860 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2862 if (HAS_PROPERTY(i, j))
2868 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2873 /* dynamically adjust element properties according to game engine version */
2875 static int ep_em_slippery_wall[] =
2880 EL_EXPANDABLE_WALL_HORIZONTAL,
2881 EL_EXPANDABLE_WALL_VERTICAL,
2882 EL_EXPANDABLE_WALL_ANY,
2886 /* special EM style gems behaviour */
2887 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2888 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2889 level.em_slippery_gems);
2891 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2892 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2893 (level.em_slippery_gems &&
2894 engine_version > VERSION_IDENT(2,0,1)));
2898 /* dynamically adjust element properties according to game engine version */
2900 if (engine_version < RELEASE_IDENT(2,2,0,7))
2903 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2905 int element = EL_CUSTOM_START + i;
2907 element_info[element].push_delay_fixed = 2;
2908 element_info[element].push_delay_random = 8;
2914 static void InitGlobal()
2916 global.autoplay_leveldir = NULL;
2918 global.frames_per_second = 0;
2919 global.fps_slowdown = FALSE;
2920 global.fps_slowdown_factor = 1;
2923 void Execute_Command(char *command)
2925 if (strcmp(command, "print graphicsinfo.conf") == 0)
2929 printf("# You can configure additional/alternative image files here.\n");
2930 printf("# (The images below are default and therefore commented out.)\n");
2932 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2934 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2937 for (i=0; image_config[i].token != NULL; i++)
2939 getFormattedSetupEntry(image_config[i].token,
2940 image_config[i].value));
2944 else if (strcmp(command, "print soundsinfo.conf") == 0)
2948 printf("# You can configure additional/alternative sound files here.\n");
2949 printf("# (The sounds below are default and therefore commented out.)\n");
2951 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2953 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2956 for (i=0; sound_config[i].token != NULL; i++)
2958 getFormattedSetupEntry(sound_config[i].token,
2959 sound_config[i].value));
2963 else if (strcmp(command, "print musicinfo.conf") == 0)
2965 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2967 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2969 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2973 else if (strncmp(command, "dump level ", 11) == 0)
2975 char *filename = &command[11];
2977 if (access(filename, F_OK) != 0)
2978 Error(ERR_EXIT, "cannot open file '%s'", filename);
2980 LoadLevelFromFilename(&level, filename);
2985 else if (strncmp(command, "dump tape ", 10) == 0)
2987 char *filename = &command[10];
2989 if (access(filename, F_OK) != 0)
2990 Error(ERR_EXIT, "cannot open file '%s'", filename);
2992 LoadTapeFromFilename(filename);
2997 else if (strncmp(command, "autoplay ", 9) == 0)
2999 char *str_copy = getStringCopy(&command[9]);
3000 char *str_ptr = strchr(str_copy, ' ');
3002 global.autoplay_leveldir = str_copy;
3003 global.autoplay_level_nr = -1;
3005 if (str_ptr != NULL)
3007 *str_ptr++ = '\0'; /* terminate leveldir string */
3008 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3013 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3017 static void InitSetup()
3019 LoadSetup(); /* global setup info */
3021 /* set some options from setup file */
3023 if (setup.options.verbose)
3024 options.verbose = TRUE;
3027 static void InitPlayerInfo()
3031 /* choose default local player */
3032 local_player = &stored_player[0];
3034 for (i=0; i<MAX_PLAYERS; i++)
3035 stored_player[i].connected = FALSE;
3037 local_player->connected = TRUE;
3040 static void InitArtworkInfo()
3045 static char *get_string_in_brackets(char *string)
3047 char *string_in_brackets = checked_malloc(strlen(string) + 3);
3049 sprintf(string_in_brackets, "[%s]", string);
3051 return string_in_brackets;
3055 static char *get_element_class_token(int element)
3057 char *element_class_name = element_info[element].class_name;
3058 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3060 sprintf(element_class_token, "[%s]", element_class_name);
3062 return element_class_token;
3065 static char *get_action_class_token(int action)
3067 char *action_class_name = &element_action_info[action].suffix[1];
3068 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3070 sprintf(action_class_token, "[%s]", action_class_name);
3072 return action_class_token;
3076 static void InitArtworkConfig()
3078 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3079 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3080 static char *action_id_suffix[NUM_ACTIONS + 1];
3081 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3082 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3083 static char *dummy[1] = { NULL };
3084 static char *ignore_generic_tokens[] =
3090 static char **ignore_image_tokens, **ignore_sound_tokens;
3091 int num_ignore_generic_tokens;
3092 int num_ignore_image_tokens, num_ignore_sound_tokens;
3095 /* dynamically determine list of generic tokens to be ignored */
3096 num_ignore_generic_tokens = 0;
3097 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3098 num_ignore_generic_tokens++;
3100 /* dynamically determine list of image tokens to be ignored */
3101 num_ignore_image_tokens = num_ignore_generic_tokens;
3102 for (i=0; image_config_vars[i].token != NULL; i++)
3103 num_ignore_image_tokens++;
3104 ignore_image_tokens =
3105 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3106 for (i=0; i < num_ignore_generic_tokens; i++)
3107 ignore_image_tokens[i] = ignore_generic_tokens[i];
3108 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3109 ignore_image_tokens[num_ignore_generic_tokens + i] =
3110 image_config_vars[i].token;
3111 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3113 /* dynamically determine list of sound tokens to be ignored */
3114 num_ignore_sound_tokens = num_ignore_generic_tokens;
3115 ignore_sound_tokens =
3116 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3117 for (i=0; i < num_ignore_generic_tokens; i++)
3118 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3119 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3121 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3122 image_id_prefix[i] = element_info[i].token_name;
3123 for (i=0; i<NUM_FONTS; i++)
3124 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3125 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3127 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3128 sound_id_prefix[i] = element_info[i].token_name;
3129 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3130 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3131 get_string_in_brackets(element_info[i].class_name);
3132 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3134 for (i=0; i<NUM_ACTIONS; i++)
3135 action_id_suffix[i] = element_action_info[i].suffix;
3136 action_id_suffix[NUM_ACTIONS] = NULL;
3138 for (i=0; i<NUM_DIRECTIONS; i++)
3139 direction_id_suffix[i] = element_direction_info[i].suffix;
3140 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3142 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3143 special_id_suffix[i] = special_suffix_info[i].suffix;
3144 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3146 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3147 image_id_prefix, action_id_suffix, direction_id_suffix,
3148 special_id_suffix, ignore_image_tokens);
3149 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3150 sound_id_prefix, action_id_suffix, dummy,
3151 special_id_suffix, ignore_sound_tokens);
3154 static void InitMixer()
3162 char *filename_font_initial = NULL;
3163 Bitmap *bitmap_font_initial = NULL;
3166 /* determine settings for initial font (for displaying startup messages) */
3167 for (i=0; image_config[i].token != NULL; i++)
3169 for (j=0; j < NUM_INITIAL_FONTS; j++)
3171 char font_token[128];
3174 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3175 len_font_token = strlen(font_token);
3177 if (strcmp(image_config[i].token, font_token) == 0)
3178 filename_font_initial = image_config[i].value;
3179 else if (strlen(image_config[i].token) > len_font_token &&
3180 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3182 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3183 font_initial[j].src_x = atoi(image_config[i].value);
3184 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3185 font_initial[j].src_y = atoi(image_config[i].value);
3186 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3187 font_initial[j].width = atoi(image_config[i].value);
3188 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3189 font_initial[j].height = atoi(image_config[i].value);
3194 for (j=0; j < NUM_INITIAL_FONTS; j++)
3196 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3197 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3200 if (filename_font_initial == NULL) /* should not happen */
3201 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3203 /* create additional image buffers for double-buffering */
3204 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3205 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3207 /* initialize screen properties */
3208 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3209 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3211 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3212 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3213 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3215 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3217 for (j=0; j < NUM_INITIAL_FONTS; j++)
3218 font_initial[j].bitmap = bitmap_font_initial;
3220 InitFontGraphicInfo();
3222 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3223 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3225 DrawInitText("Loading graphics:", 120, FC_GREEN);
3227 InitTileClipmasks();
3230 void InitGfxBackground()
3234 drawto = backbuffer;
3235 fieldbuffer = bitmap_db_field;
3236 SetDrawtoField(DRAW_BACKBUFFER);
3238 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3239 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3240 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3241 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3243 for (x=0; x<MAX_BUF_XSIZE; x++)
3244 for (y=0; y<MAX_BUF_YSIZE; y++)
3247 redraw_mask = REDRAW_ALL;
3250 static void InitLevelInfo()
3252 LoadLevelInfo(); /* global level info */
3253 LoadLevelSetup_LastSeries(); /* last played series info */
3254 LoadLevelSetup_SeriesInfo(); /* last played level info */
3257 void InitLevelArtworkInfo()
3259 LoadLevelArtworkInfo();
3262 static void InitImages()
3265 setLevelArtworkDir(artwork.gfx_first);
3269 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3270 leveldir_current->identifier,
3271 artwork.gfx_current_identifier,
3272 artwork.gfx_current->identifier,
3273 leveldir_current->graphics_set,
3274 leveldir_current->graphics_path);
3277 ReloadCustomImages();
3279 LoadCustomElementDescriptions();
3280 LoadSpecialMenuDesignSettings();
3282 ReinitializeGraphics();
3285 static void InitSound(char *identifier)
3287 if (identifier == NULL)
3288 identifier = artwork.snd_current->identifier;
3291 /* set artwork path to send it to the sound server process */
3292 setLevelArtworkDir(artwork.snd_first);
3295 InitReloadCustomSounds(identifier);
3296 ReinitializeSounds();
3299 static void InitMusic(char *identifier)
3301 if (identifier == NULL)
3302 identifier = artwork.mus_current->identifier;
3305 /* set artwork path to send it to the sound server process */
3306 setLevelArtworkDir(artwork.mus_first);
3309 InitReloadCustomMusic(identifier);
3310 ReinitializeMusic();
3313 void InitNetworkServer()
3315 #if defined(PLATFORM_UNIX)
3319 if (!options.network)
3322 #if defined(PLATFORM_UNIX)
3323 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3325 if (!ConnectToServer(options.server_host, options.server_port))
3326 Error(ERR_EXIT, "cannot connect to network game server");
3328 SendToServer_PlayerName(setup.player_name);
3329 SendToServer_ProtocolVersion();
3332 SendToServer_NrWanted(nr_wanted);
3336 static char *getNewArtworkIdentifier(int type)
3338 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3339 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3340 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3341 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3342 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3343 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3344 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3345 char *leveldir_identifier = leveldir_current->identifier;
3347 /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3348 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3350 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3352 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3353 char *artwork_current_identifier;
3354 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3356 /* leveldir_current may be invalid (level group, parent link) */
3357 if (!validLevelSeries(leveldir_current))
3360 /* 1st step: determine artwork set to be activated in descending order:
3361 --------------------------------------------------------------------
3362 1. setup artwork (when configured to override everything else)
3363 2. artwork set configured in "levelinfo.conf" of current level set
3364 (artwork in level directory will have priority when loading later)
3365 3. artwork in level directory (stored in artwork sub-directory)
3366 4. setup artwork (currently configured in setup menu) */
3368 if (setup_override_artwork)
3369 artwork_current_identifier = setup_artwork_set;
3370 else if (leveldir_artwork_set != NULL)
3371 artwork_current_identifier = leveldir_artwork_set;
3372 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3373 artwork_current_identifier = leveldir_identifier;
3375 artwork_current_identifier = setup_artwork_set;
3378 /* 2nd step: check if it is really needed to reload artwork set
3379 ------------------------------------------------------------ */
3382 if (type == ARTWORK_TYPE_GRAPHICS)
3383 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3384 artwork_new_identifier,
3385 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3386 artwork_current_identifier,
3387 leveldir_current->graphics_set,
3388 leveldir_current->identifier);
3391 /* ---------- reload if level set and also artwork set has changed ------- */
3392 if (leveldir_current_identifier[type] != leveldir_identifier &&
3393 (last_has_level_artwork_set[type] || has_level_artwork_set))
3394 artwork_new_identifier = artwork_current_identifier;
3396 leveldir_current_identifier[type] = leveldir_identifier;
3397 last_has_level_artwork_set[type] = has_level_artwork_set;
3400 if (type == ARTWORK_TYPE_GRAPHICS)
3401 printf("::: 1: '%s'\n", artwork_new_identifier);
3404 /* ---------- reload if "override artwork" setting has changed ----------- */
3405 if (last_override_level_artwork[type] != setup_override_artwork)
3406 artwork_new_identifier = artwork_current_identifier;
3408 last_override_level_artwork[type] = setup_override_artwork;
3411 if (type == ARTWORK_TYPE_GRAPHICS)
3412 printf("::: 2: '%s'\n", artwork_new_identifier);
3415 /* ---------- reload if current artwork identifier has changed ----------- */
3416 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3417 artwork_current_identifier) != 0)
3418 artwork_new_identifier = artwork_current_identifier;
3420 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3423 if (type == ARTWORK_TYPE_GRAPHICS)
3424 printf("::: 3: '%s'\n", artwork_new_identifier);
3427 /* ---------- do not reload directly after starting ---------------------- */
3428 if (!initialized[type])
3429 artwork_new_identifier = NULL;
3431 initialized[type] = TRUE;
3434 if (type == ARTWORK_TYPE_GRAPHICS)
3435 printf("::: 4: '%s'\n", artwork_new_identifier);
3439 if (type == ARTWORK_TYPE_GRAPHICS)
3440 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3441 artwork.gfx_current_identifier, artwork_current_identifier,
3442 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3443 artwork_new_identifier);
3446 return artwork_new_identifier;
3449 void ReloadCustomArtwork()
3451 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3452 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3453 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3454 boolean redraw_screen = FALSE;
3456 if (gfx_new_identifier != NULL)
3459 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3460 artwork.gfx_current_identifier,
3462 artwork.gfx_current->identifier,
3463 leveldir_current->graphics_set);
3466 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3471 printf("... '%s'\n",
3472 leveldir_current->graphics_set);
3475 FreeTileClipmasks();
3476 InitTileClipmasks();
3478 redraw_screen = TRUE;
3481 if (snd_new_identifier != NULL)
3483 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3485 InitSound(snd_new_identifier);
3487 redraw_screen = TRUE;
3490 if (mus_new_identifier != NULL)
3492 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3494 InitMusic(mus_new_identifier);
3496 redraw_screen = TRUE;
3501 InitGfxBackground();
3503 /* force redraw of (open or closed) door graphics */
3504 SetDoorState(DOOR_OPEN_ALL);
3505 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3509 void KeyboardAutoRepeatOffUnlessAutoplay()
3511 if (global.autoplay_leveldir == NULL)
3512 KeyboardAutoRepeatOff();
3516 /* ========================================================================= */
3518 /* ========================================================================= */
3522 InitGlobal(); /* initialize some global variables */
3524 if (options.execute_command)
3525 Execute_Command(options.execute_command);
3527 if (options.serveronly)
3529 #if defined(PLATFORM_UNIX)
3530 NetworkServer(options.server_port, options.serveronly);
3532 Error(ERR_WARN, "networking only supported in Unix version");
3534 exit(0); /* never reached */
3540 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3541 InitArtworkConfig(); /* needed before forking sound child process */
3546 InitRND(NEW_RANDOMIZE);
3547 InitSimpleRND(NEW_RANDOMIZE);
3552 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3555 InitEventFilter(FilterMouseMotionEvents);
3557 InitElementPropertiesStatic();
3558 InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3563 InitLevelArtworkInfo();
3565 InitImages(); /* needs to know current level directory */
3566 InitSound(NULL); /* needs to know current level directory */
3567 InitMusic(NULL); /* needs to know current level directory */
3569 InitGfxBackground();
3571 if (global.autoplay_leveldir)
3577 game_status = GAME_MODE_MAIN;
3581 InitNetworkServer();
3584 void CloseAllAndExit(int exit_value)
3589 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3592 FreeTileClipmasks();
3594 CloseVideoDisplay();
3595 ClosePlatformDependentStuff();