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];
551 /* now set all '-1' values to element specific default values */
552 for (i=0; i<MAX_NUM_ELEMENTS; i++)
554 int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
555 int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
556 int default_direction_graphic[NUM_DIRECTIONS];
557 int default_direction_crumbled[NUM_DIRECTIONS];
559 if (default_graphic == -1)
560 default_graphic = IMG_CHAR_QUESTION;
561 if (default_crumbled == -1)
562 default_crumbled = IMG_EMPTY;
564 for (dir=0; dir<NUM_DIRECTIONS; dir++)
566 default_direction_graphic[dir] =
567 element_info[i].direction_graphic[ACTION_DEFAULT][dir];
568 default_direction_crumbled[dir] =
569 element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
571 if (default_direction_graphic[dir] == -1)
572 default_direction_graphic[dir] = default_graphic;
573 if (default_direction_crumbled[dir] == -1)
574 default_direction_crumbled[dir] = default_crumbled;
577 for (act=0; act<NUM_ACTIONS; act++)
579 boolean act_remove = (act == ACTION_DIGGING ||
580 act == ACTION_SNAPPING ||
581 act == ACTION_COLLECTING);
583 /* generic default action graphic (defined by "[default]" directive) */
584 int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
585 int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
587 /* look for special default action graphic (classic game specific) */
588 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
589 default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
590 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
591 default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
592 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
593 default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
595 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
596 default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
597 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
598 default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
599 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
600 default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
602 if (default_action_graphic == -1)
603 default_action_graphic = default_graphic;
604 if (default_action_crumbled == -1)
605 default_action_crumbled = default_crumbled;
607 for (dir=0; dir<NUM_DIRECTIONS; dir++)
609 int default_action_direction_graphic = element_info[i].graphic[act];
610 int default_action_direction_crumbled = element_info[i].crumbled[act];
612 /* no graphic for current action -- use default direction graphic */
613 if (default_action_direction_graphic == -1)
614 default_action_direction_graphic =
615 (act_remove ? IMG_EMPTY : default_direction_graphic[dir]);
616 if (default_action_direction_crumbled == -1)
617 default_action_direction_crumbled =
618 (act_remove ? IMG_EMPTY : default_direction_crumbled[dir]);
620 if (element_info[i].direction_graphic[act][dir] == -1)
621 element_info[i].direction_graphic[act][dir] =
622 default_action_direction_graphic;
623 if (element_info[i].direction_crumbled[act][dir] == -1)
624 element_info[i].direction_crumbled[act][dir] =
625 default_action_direction_crumbled;
628 /* no graphic for this specific action -- use default action graphic */
629 if (element_info[i].graphic[act] == -1)
630 element_info[i].graphic[act] =
631 (act_remove ? IMG_EMPTY : default_action_graphic);
632 if (element_info[i].crumbled[act] == -1)
633 element_info[i].crumbled[act] =
634 (act_remove ? IMG_EMPTY : default_action_crumbled);
642 for (i=0; i<MAX_NUM_ELEMENTS; i++)
643 if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
644 i != EL_CHAR_QUESTION)
645 Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
646 element_info[i].token_name, i);
652 void InitElementSpecialGraphicInfo()
654 struct PropertyMapping *property_mapping = getImageListPropertyMapping();
655 int num_property_mappings = getImageListPropertyMappingSize();
658 /* always start with reliable default values */
659 for (i=0; i < MAX_NUM_ELEMENTS; i++)
660 for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
661 element_info[i].special_graphic[j] =
662 element_info[i].graphic[ACTION_DEFAULT];
664 /* initialize special element/graphic mapping from static configuration */
665 for (i=0; element_to_special_graphic[i].element > -1; i++)
667 int element = element_to_special_graphic[i].element;
668 int special = element_to_special_graphic[i].special;
669 int graphic = element_to_special_graphic[i].graphic;
670 boolean base_redefined = getImageListEntry(el2img(element))->redefined;
671 boolean special_redefined = getImageListEntry(graphic)->redefined;
673 /* if the base graphic ("emerald", for example) has been redefined,
674 but not the special graphic ("emerald.EDITOR", for example), do not
675 use an existing (in this case considered obsolete) special graphic
676 anymore, but use the automatically created (down-scaled) graphic */
677 if (base_redefined && !special_redefined)
680 element_info[element].special_graphic[special] = graphic;
683 /* initialize special element/graphic mapping from dynamic configuration */
684 for (i=0; i < num_property_mappings; i++)
686 int element = property_mapping[i].base_index;
687 int special = property_mapping[i].ext3_index;
688 int graphic = property_mapping[i].artwork_index;
690 if (element >= MAX_NUM_ELEMENTS)
693 if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
694 element_info[element].special_graphic[special] = graphic;
698 static int get_element_from_token(char *token)
702 for (i=0; i < MAX_NUM_ELEMENTS; i++)
703 if (strcmp(element_info[i].token_name, token) == 0)
709 static void set_graphic_parameters(int graphic, char **parameter_raw)
711 Bitmap *src_bitmap = getBitmapFromImageID(graphic);
712 int parameter[NUM_GFX_ARGS];
713 int anim_frames_per_row = 1, anim_frames_per_col = 1;
714 int anim_frames_per_line = 1;
717 /* get integer values from string parameters */
718 for (i=0; i < NUM_GFX_ARGS; i++)
721 get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
722 image_config_suffix[i].type);
724 if (image_config_suffix[i].type == TYPE_TOKEN)
725 parameter[i] = get_element_from_token(parameter_raw[i]);
728 graphic_info[graphic].bitmap = src_bitmap;
730 /* start with reliable default values */
731 graphic_info[graphic].src_x = 0;
732 graphic_info[graphic].src_y = 0;
733 graphic_info[graphic].width = TILEX;
734 graphic_info[graphic].height = TILEY;
735 graphic_info[graphic].offset_x = 0; /* one or both of these values ... */
736 graphic_info[graphic].offset_y = 0; /* ... will be corrected later */
737 graphic_info[graphic].crumbled_like = -1; /* do not use clone element */
738 graphic_info[graphic].diggable_like = -1; /* do not use clone element */
740 /* optional x and y tile position of animation frame sequence */
741 if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
742 graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
743 if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
744 graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
746 /* optional x and y pixel position of animation frame sequence */
747 if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
748 graphic_info[graphic].src_x = parameter[GFX_ARG_X];
749 if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
750 graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
752 /* optional width and height of each animation frame */
753 if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
754 graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
755 if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
756 graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
760 anim_frames_per_row = src_bitmap->width / graphic_info[graphic].width;
761 anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
764 /* correct x or y offset dependent of vertical or horizontal frame order */
765 if (parameter[GFX_ARG_VERTICAL]) /* frames are ordered vertically */
767 graphic_info[graphic].offset_y =
768 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
769 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
770 anim_frames_per_line = anim_frames_per_col;
772 else /* frames are ordered horizontally */
774 graphic_info[graphic].offset_x =
775 (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
776 parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
777 anim_frames_per_line = anim_frames_per_row;
780 /* optionally, the x and y offset of frames can be specified directly */
781 if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
782 graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
783 if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
784 graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
786 /* automatically determine correct number of frames, if not defined */
787 if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
788 graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
789 else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
790 graphic_info[graphic].anim_frames = anim_frames_per_row;
791 else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
792 graphic_info[graphic].anim_frames = anim_frames_per_col;
794 graphic_info[graphic].anim_frames = 1;
796 graphic_info[graphic].anim_frames_per_line =
797 (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
798 parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
800 graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
801 if (graphic_info[graphic].anim_delay == 0) /* delay must be at least 1 */
802 graphic_info[graphic].anim_delay = 1;
804 graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
805 if (graphic_info[graphic].anim_frames == 1)
806 graphic_info[graphic].anim_mode = ANIM_NONE;
808 /* automatically determine correct start frame, if not defined */
809 if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
810 graphic_info[graphic].anim_start_frame = 0;
811 else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
812 graphic_info[graphic].anim_start_frame =
813 graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
815 graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
817 /* animation synchronized with global frame counter, not move position */
818 graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
820 /* optional element for cloning crumble graphics */
821 if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
822 graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
824 /* optional element for cloning digging graphics */
825 if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
826 graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
828 /* this is only used for toon animations */
829 graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
830 graphic_info[graphic].step_delay = parameter[GFX_ARG_STEP_DELAY];
832 /* this is only used for drawing font characters */
833 graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
834 graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
837 static void InitGraphicInfo()
839 int fallback_graphic = IMG_CHAR_EXCLAM;
840 struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
841 Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
842 int num_images = getImageListSize();
845 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
846 static boolean clipmasks_initialized = FALSE;
848 XGCValues clip_gc_values;
849 unsigned long clip_gc_valuemask;
850 GC copy_clipmask_gc = None;
853 if (graphic_info != NULL)
856 graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
858 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
859 if (clipmasks_initialized)
861 for (i=0; i<num_images; i++)
863 if (graphic_info[i].clip_mask)
864 XFreePixmap(display, graphic_info[i].clip_mask);
865 if (graphic_info[i].clip_gc)
866 XFreeGC(display, graphic_info[i].clip_gc);
868 graphic_info[i].clip_mask = None;
869 graphic_info[i].clip_gc = None;
874 for (i=0; i<num_images; i++)
876 struct FileInfo *image = getImageListEntry(i);
879 int first_frame, last_frame;
882 printf("::: image: '%s'\n", image->token);
886 printf("::: image # %d: '%s' ['%s']\n",
888 getTokenFromImageID(i));
891 set_graphic_parameters(i, image->parameter);
893 /* now check if no animation frames are outside of the loaded image */
895 if (graphic_info[i].bitmap == NULL)
896 continue; /* skip check for optional images that are undefined */
899 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
900 if (src_x < 0 || src_y < 0 ||
901 src_x + TILEX > src_bitmap->width ||
902 src_y + TILEY > src_bitmap->height)
904 Error(ERR_RETURN_LINE, "-");
905 Error(ERR_RETURN, "warning: error found in config file:");
906 Error(ERR_RETURN, "- config file: '%s'",
907 getImageConfigFilename());
908 Error(ERR_RETURN, "- config token: '%s'",
909 getTokenFromImageID(i));
910 Error(ERR_RETURN, "- image file: '%s'",
911 src_bitmap->source_filename);
913 "error: first animation frame out of bounds (%d, %d)",
915 Error(ERR_RETURN, "custom graphic rejected for this element/action");
917 if (i == fallback_graphic)
918 Error(ERR_EXIT, "fatal error: no fallback graphic available");
920 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
921 Error(ERR_RETURN_LINE, "-");
923 set_graphic_parameters(i, fallback_image->default_parameter);
924 graphic_info[i].bitmap = fallback_bitmap;
927 last_frame = graphic_info[i].anim_frames - 1;
928 getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
929 if (src_x < 0 || src_y < 0 ||
930 src_x + TILEX > src_bitmap->width ||
931 src_y + TILEY > src_bitmap->height)
933 Error(ERR_RETURN_LINE, "-");
934 Error(ERR_RETURN, "warning: error found in config file:");
935 Error(ERR_RETURN, "- config file: '%s'",
936 getImageConfigFilename());
937 Error(ERR_RETURN, "- config token: '%s'",
938 getTokenFromImageID(i));
939 Error(ERR_RETURN, "- image file: '%s'",
940 src_bitmap->source_filename);
942 "error: last animation frame (%d) out of bounds (%d, %d)",
943 last_frame, src_x, src_y);
944 Error(ERR_RETURN, "custom graphic rejected for this element/action");
946 if (i == fallback_graphic)
947 Error(ERR_EXIT, "fatal error: no fallback graphic available");
949 Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
950 Error(ERR_RETURN_LINE, "-");
952 set_graphic_parameters(i, fallback_image->default_parameter);
953 graphic_info[i].bitmap = fallback_bitmap;
956 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
957 /* currently we need only a tile clip mask from the first frame */
958 getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
960 if (copy_clipmask_gc == None)
962 clip_gc_values.graphics_exposures = False;
963 clip_gc_valuemask = GCGraphicsExposures;
964 copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
965 clip_gc_valuemask, &clip_gc_values);
968 graphic_info[i].clip_mask =
969 XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
971 src_pixmap = src_bitmap->clip_mask;
972 XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
973 copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
975 clip_gc_values.graphics_exposures = False;
976 clip_gc_values.clip_mask = graphic_info[i].clip_mask;
977 clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
979 graphic_info[i].clip_gc =
980 XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
984 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
985 if (copy_clipmask_gc)
986 XFreeGC(display, copy_clipmask_gc);
988 clipmasks_initialized = TRUE;
992 static void InitElementSoundInfo()
994 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
995 int num_property_mappings = getSoundListPropertyMappingSize();
998 /* set values to -1 to identify later as "uninitialized" values */
999 for (i=0; i < MAX_NUM_ELEMENTS; i++)
1000 for (act=0; act < NUM_ACTIONS; act++)
1001 element_info[i].sound[act] = -1;
1003 /* initialize element/sound mapping from static configuration */
1004 for (i=0; element_to_sound[i].element > -1; i++)
1006 int element = element_to_sound[i].element;
1007 int action = element_to_sound[i].action;
1008 int sound = element_to_sound[i].sound;
1009 boolean is_class = element_to_sound[i].is_class;
1012 action = ACTION_DEFAULT;
1015 element_info[element].sound[action] = sound;
1017 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1018 if (strcmp(element_info[j].class_name,
1019 element_info[element].class_name) == 0)
1020 element_info[j].sound[action] = sound;
1023 /* initialize element class/sound mapping from dynamic configuration */
1024 for (i=0; i < num_property_mappings; i++)
1026 int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1027 int action = property_mapping[i].ext1_index;
1028 int sound = property_mapping[i].artwork_index;
1030 if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1034 action = ACTION_DEFAULT;
1036 for (j=0; j < MAX_NUM_ELEMENTS; j++)
1037 if (strcmp(element_info[j].class_name,
1038 element_info[element_class].class_name) == 0)
1039 element_info[j].sound[action] = sound;
1042 /* initialize element/sound mapping from dynamic configuration */
1043 for (i=0; i < num_property_mappings; i++)
1045 int element = property_mapping[i].base_index;
1046 int action = property_mapping[i].ext1_index;
1047 int sound = property_mapping[i].artwork_index;
1049 if (element >= MAX_NUM_ELEMENTS)
1053 action = ACTION_DEFAULT;
1055 element_info[element].sound[action] = sound;
1058 /* now set all '-1' values to element specific default values */
1059 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1061 for (act=0; act < NUM_ACTIONS; act++)
1063 /* generic default action sound (defined by "[default]" directive) */
1064 int default_action_sound = element_info[EL_DEFAULT].sound[act];
1066 /* look for special default action sound (classic game specific) */
1067 if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1068 default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1069 if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1070 default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1071 if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1072 default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1074 /* look for element specific default sound (independent from action) */
1075 if (element_info[i].sound[ACTION_DEFAULT] != -1)
1076 default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1078 /* no sound for this specific action -- use default action sound */
1079 if (element_info[i].sound[act] == -1)
1080 element_info[i].sound[act] = default_action_sound;
1085 static void set_sound_parameters(int sound, char **parameter_raw)
1087 int parameter[NUM_SND_ARGS];
1090 /* get integer values from string parameters */
1091 for (i=0; i < NUM_SND_ARGS; i++)
1093 get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1094 sound_config_suffix[i].type);
1096 /* explicit loop mode setting in configuration overrides default value */
1097 if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1098 sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1101 static void InitSoundInfo()
1104 struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1105 int num_property_mappings = getSoundListPropertyMappingSize();
1107 int *sound_effect_properties;
1108 int num_sounds = getSoundListSize();
1111 if (sound_info != NULL)
1114 sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1115 sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1117 /* initialize sound effect for all elements to "no sound" */
1118 for (i=0; i<MAX_NUM_ELEMENTS; i++)
1119 for (j=0; j<NUM_ACTIONS; j++)
1120 element_info[i].sound[j] = SND_UNDEFINED;
1122 for (i=0; i<num_sounds; i++)
1124 struct FileInfo *sound = getSoundListEntry(i);
1125 int len_effect_text = strlen(sound->token);
1127 sound_effect_properties[i] = ACTION_OTHER;
1128 sound_info[i].loop = FALSE;
1131 printf("::: sound %d: '%s'\n", i, sound->token);
1134 /* determine all loop sounds and identify certain sound classes */
1136 for (j=0; element_action_info[j].suffix; j++)
1138 int len_action_text = strlen(element_action_info[j].suffix);
1140 if (len_action_text < len_effect_text &&
1141 strcmp(&sound->token[len_effect_text - len_action_text],
1142 element_action_info[j].suffix) == 0)
1144 sound_effect_properties[i] = element_action_info[j].value;
1145 sound_info[i].loop = element_action_info[j].is_loop_sound;
1152 if (strcmp(sound->token, "custom_42") == 0)
1153 printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1156 /* associate elements and some selected sound actions */
1158 for (j=0; j<MAX_NUM_ELEMENTS; j++)
1160 if (element_info[j].class_name)
1162 int len_class_text = strlen(element_info[j].class_name);
1164 if (len_class_text + 1 < len_effect_text &&
1165 strncmp(sound->token,
1166 element_info[j].class_name, len_class_text) == 0 &&
1167 sound->token[len_class_text] == '.')
1169 int sound_action_value = sound_effect_properties[i];
1171 element_info[j].sound[sound_action_value] = i;
1176 set_sound_parameters(i, sound->parameter);
1179 free(sound_effect_properties);
1182 /* !!! now handled in InitElementSoundInfo() !!! */
1183 /* initialize element/sound mapping from dynamic configuration */
1184 for (i=0; i < num_property_mappings; i++)
1186 int element = property_mapping[i].base_index;
1187 int action = property_mapping[i].ext1_index;
1188 int sound = property_mapping[i].artwork_index;
1191 action = ACTION_DEFAULT;
1193 printf("::: %d: %d, %d, %d ['%s']\n",
1194 i, element, action, sound, element_info[element].token_name);
1196 element_info[element].sound[action] = sound;
1203 int element = EL_CUSTOM_11;
1206 while (element_action_info[j].suffix)
1208 printf("element %d, sound action '%s' == %d\n",
1209 element, element_action_info[j].suffix,
1210 element_info[element].sound[j]);
1215 PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1221 int element = EL_SAND;
1222 int sound_action = ACTION_DIGGING;
1225 while (element_action_info[j].suffix)
1227 if (element_action_info[j].value == sound_action)
1228 printf("element %d, sound action '%s' == %d\n",
1229 element, element_action_info[j].suffix,
1230 element_info[element].sound[sound_action]);
1237 static void ReinitializeGraphics()
1239 InitGraphicInfo(); /* graphic properties mapping */
1240 InitElementGraphicInfo(); /* element game graphic mapping */
1241 InitElementSpecialGraphicInfo(); /* element special graphic mapping */
1243 InitElementSmallImages(); /* create editor and preview images */
1244 InitFontGraphicInfo(); /* initialize text drawing functions */
1246 SetMainBackgroundImage(IMG_BACKGROUND);
1247 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1253 static void ReinitializeSounds()
1255 InitSoundInfo(); /* sound properties mapping */
1256 InitElementSoundInfo(); /* element game sound mapping */
1258 InitPlaySoundLevel(); /* internal game sound settings */
1261 static void ReinitializeMusic()
1263 /* currently nothing to do */
1266 void InitElementPropertiesStatic()
1268 static int ep_diggable[] =
1273 EL_SP_BUGGY_BASE_ACTIVATING,
1276 EL_INVISIBLE_SAND_ACTIVE,
1278 /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1282 EL_SP_BUGGY_BASE_ACTIVE,
1287 static int ep_collectible_only[] =
1304 EL_DYNABOMB_INCREASE_NUMBER,
1305 EL_DYNABOMB_INCREASE_SIZE,
1306 EL_DYNABOMB_INCREASE_POWER,
1320 static int ep_dont_run_into[] =
1322 /* same elements as in 'ep_dont_touch' */
1328 /* same elements as in 'ep_dont_collide_with' */
1340 /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1342 EL_SP_BUGGY_BASE_ACTIVE,
1349 static int ep_dont_collide_with[] =
1351 /* same elements as in 'ep_dont_touch' */
1367 static int ep_dont_touch[] =
1376 static int ep_indestructible[] =
1380 EL_ACID_POOL_TOPLEFT,
1381 EL_ACID_POOL_TOPRIGHT,
1382 EL_ACID_POOL_BOTTOMLEFT,
1383 EL_ACID_POOL_BOTTOM,
1384 EL_ACID_POOL_BOTTOMRIGHT,
1385 EL_SP_HARDWARE_GRAY,
1386 EL_SP_HARDWARE_GREEN,
1387 EL_SP_HARDWARE_BLUE,
1389 EL_SP_HARDWARE_YELLOW,
1390 EL_SP_HARDWARE_BASE_1,
1391 EL_SP_HARDWARE_BASE_2,
1392 EL_SP_HARDWARE_BASE_3,
1393 EL_SP_HARDWARE_BASE_4,
1394 EL_SP_HARDWARE_BASE_5,
1395 EL_SP_HARDWARE_BASE_6,
1396 EL_INVISIBLE_STEELWALL,
1397 EL_INVISIBLE_STEELWALL_ACTIVE,
1398 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1399 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1400 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1401 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1402 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1403 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1404 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1405 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1406 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1407 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1408 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1409 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1411 EL_LIGHT_SWITCH_ACTIVE,
1412 EL_SIGN_EXCLAMATION,
1413 EL_SIGN_RADIOACTIVITY,
1424 EL_STEELWALL_SLIPPERY,
1447 EL_SWITCHGATE_OPENING,
1448 EL_SWITCHGATE_CLOSED,
1449 EL_SWITCHGATE_CLOSING,
1451 EL_SWITCHGATE_SWITCH_UP,
1452 EL_SWITCHGATE_SWITCH_DOWN,
1455 EL_TIMEGATE_OPENING,
1457 EL_TIMEGATE_CLOSING,
1460 EL_TIMEGATE_SWITCH_ACTIVE,
1465 EL_TUBE_VERTICAL_LEFT,
1466 EL_TUBE_VERTICAL_RIGHT,
1467 EL_TUBE_HORIZONTAL_UP,
1468 EL_TUBE_HORIZONTAL_DOWN,
1476 static int ep_slippery[] =
1490 EL_ROBOT_WHEEL_ACTIVE,
1496 EL_ACID_POOL_TOPLEFT,
1497 EL_ACID_POOL_TOPRIGHT,
1507 EL_STEELWALL_SLIPPERY,
1513 static int ep_can_change[] =
1518 static int ep_can_move[] =
1540 static int ep_can_fall[] =
1555 EL_BD_MAGIC_WALL_FULL,
1568 static int ep_can_smash_player[] =
1593 static int ep_can_smash_enemies[] =
1601 static int ep_can_smash_everything[] =
1609 static int ep_can_explode_by_fire[] =
1611 /* same elements as in 'ep_can_explode_impact' */
1616 /* same elements as in 'ep_can_explode_smashed' */
1625 EL_DYNABOMB_PLAYER_1_ACTIVE,
1626 EL_DYNABOMB_PLAYER_2_ACTIVE,
1627 EL_DYNABOMB_PLAYER_3_ACTIVE,
1628 EL_DYNABOMB_PLAYER_4_ACTIVE,
1629 EL_DYNABOMB_INCREASE_NUMBER,
1630 EL_DYNABOMB_INCREASE_SIZE,
1631 EL_DYNABOMB_INCREASE_POWER,
1632 EL_SP_DISK_RED_ACTIVE,
1642 static int ep_can_explode_smashed[] =
1644 /* same elements as in 'ep_can_explode_impact' */
1657 static int ep_can_explode_impact[] =
1665 static int ep_walkable_over[] =
1669 EL_SOKOBAN_FIELD_EMPTY,
1686 static int ep_walkable_inside[] =
1691 EL_TUBE_VERTICAL_LEFT,
1692 EL_TUBE_VERTICAL_RIGHT,
1693 EL_TUBE_HORIZONTAL_UP,
1694 EL_TUBE_HORIZONTAL_DOWN,
1702 static int ep_walkable_under[] =
1707 static int ep_passable_over[] =
1722 static int ep_passable_inside[] =
1728 EL_SP_PORT_HORIZONTAL,
1729 EL_SP_PORT_VERTICAL,
1731 EL_SP_GRAVITY_PORT_LEFT,
1732 EL_SP_GRAVITY_PORT_RIGHT,
1733 EL_SP_GRAVITY_PORT_UP,
1734 EL_SP_GRAVITY_PORT_DOWN,
1738 static int ep_passable_under[] =
1743 static int ep_pushable[] =
1755 EL_SOKOBAN_FIELD_FULL,
1762 static int ep_can_be_crumbled[] =
1771 static int ep_player[] =
1780 static int ep_can_pass_magic_wall[] =
1793 static int ep_switchable[] =
1797 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1798 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1799 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1800 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1801 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1802 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1803 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1804 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1805 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1806 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1807 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1808 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1809 EL_SWITCHGATE_SWITCH_UP,
1810 EL_SWITCHGATE_SWITCH_DOWN,
1812 EL_LIGHT_SWITCH_ACTIVE,
1814 EL_BALLOON_SWITCH_LEFT,
1815 EL_BALLOON_SWITCH_RIGHT,
1816 EL_BALLOON_SWITCH_UP,
1817 EL_BALLOON_SWITCH_DOWN,
1818 EL_BALLOON_SWITCH_ANY,
1824 static int ep_bd_element[] =
1853 static int ep_sp_element[] =
1861 EL_SP_HARDWARE_GRAY,
1869 EL_SP_GRAVITY_PORT_RIGHT,
1870 EL_SP_GRAVITY_PORT_DOWN,
1871 EL_SP_GRAVITY_PORT_LEFT,
1872 EL_SP_GRAVITY_PORT_UP,
1877 EL_SP_PORT_VERTICAL,
1878 EL_SP_PORT_HORIZONTAL,
1884 EL_SP_HARDWARE_BASE_1,
1885 EL_SP_HARDWARE_GREEN,
1886 EL_SP_HARDWARE_BLUE,
1888 EL_SP_HARDWARE_YELLOW,
1889 EL_SP_HARDWARE_BASE_2,
1890 EL_SP_HARDWARE_BASE_3,
1891 EL_SP_HARDWARE_BASE_4,
1892 EL_SP_HARDWARE_BASE_5,
1893 EL_SP_HARDWARE_BASE_6,
1896 /* additional elements that appeared in newer Supaplex levels */
1898 /* more than one murphy in a level results in an inactive clone */
1900 /* runtime elements*/
1901 EL_SP_DISK_RED_ACTIVE,
1902 EL_SP_TERMINAL_ACTIVE,
1903 EL_SP_BUGGY_BASE_ACTIVATING,
1904 EL_SP_BUGGY_BASE_ACTIVE,
1908 static int ep_sb_element[] =
1913 EL_SOKOBAN_FIELD_EMPTY,
1914 EL_SOKOBAN_FIELD_FULL,
1916 EL_INVISIBLE_STEELWALL,
1920 static int ep_gem[] =
1931 static int ep_food_dark_yamyam[] =
1958 static int ep_food_penguin[] =
1971 static int ep_food_pig[] =
1982 static int ep_historic_wall[] =
2007 EL_EXPANDABLE_WALL_HORIZONTAL,
2008 EL_EXPANDABLE_WALL_VERTICAL,
2009 EL_EXPANDABLE_WALL_ANY,
2010 EL_EXPANDABLE_WALL_GROWING,
2017 EL_SP_HARDWARE_GRAY,
2018 EL_SP_HARDWARE_GREEN,
2019 EL_SP_HARDWARE_BLUE,
2021 EL_SP_HARDWARE_YELLOW,
2022 EL_SP_HARDWARE_BASE_1,
2023 EL_SP_HARDWARE_BASE_2,
2024 EL_SP_HARDWARE_BASE_3,
2025 EL_SP_HARDWARE_BASE_4,
2026 EL_SP_HARDWARE_BASE_5,
2027 EL_SP_HARDWARE_BASE_6,
2029 EL_SP_TERMINAL_ACTIVE,
2032 EL_INVISIBLE_STEELWALL,
2033 EL_INVISIBLE_STEELWALL_ACTIVE,
2035 EL_INVISIBLE_WALL_ACTIVE,
2036 EL_STEELWALL_SLIPPERY,
2052 static int ep_historic_solid[] =
2056 EL_EXPANDABLE_WALL_HORIZONTAL,
2057 EL_EXPANDABLE_WALL_VERTICAL,
2058 EL_EXPANDABLE_WALL_ANY,
2071 EL_QUICKSAND_FILLING,
2072 EL_QUICKSAND_EMPTYING,
2074 EL_MAGIC_WALL_ACTIVE,
2075 EL_MAGIC_WALL_EMPTYING,
2076 EL_MAGIC_WALL_FILLING,
2080 EL_BD_MAGIC_WALL_ACTIVE,
2081 EL_BD_MAGIC_WALL_EMPTYING,
2082 EL_BD_MAGIC_WALL_FULL,
2083 EL_BD_MAGIC_WALL_FILLING,
2084 EL_BD_MAGIC_WALL_DEAD,
2093 EL_SP_TERMINAL_ACTIVE,
2097 EL_INVISIBLE_WALL_ACTIVE,
2098 EL_SWITCHGATE_SWITCH_UP,
2099 EL_SWITCHGATE_SWITCH_DOWN,
2101 EL_TIMEGATE_SWITCH_ACTIVE,
2113 /* the following elements are a direct copy of "indestructible" elements,
2114 except "EL_ACID", which is "indestructible", but not "solid"! */
2119 EL_ACID_POOL_TOPLEFT,
2120 EL_ACID_POOL_TOPRIGHT,
2121 EL_ACID_POOL_BOTTOMLEFT,
2122 EL_ACID_POOL_BOTTOM,
2123 EL_ACID_POOL_BOTTOMRIGHT,
2124 EL_SP_HARDWARE_GRAY,
2125 EL_SP_HARDWARE_GREEN,
2126 EL_SP_HARDWARE_BLUE,
2128 EL_SP_HARDWARE_YELLOW,
2129 EL_SP_HARDWARE_BASE_1,
2130 EL_SP_HARDWARE_BASE_2,
2131 EL_SP_HARDWARE_BASE_3,
2132 EL_SP_HARDWARE_BASE_4,
2133 EL_SP_HARDWARE_BASE_5,
2134 EL_SP_HARDWARE_BASE_6,
2135 EL_INVISIBLE_STEELWALL,
2136 EL_INVISIBLE_STEELWALL_ACTIVE,
2137 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2138 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2139 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2140 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2141 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2142 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2143 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2144 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2145 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2146 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2147 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2148 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2150 EL_LIGHT_SWITCH_ACTIVE,
2151 EL_SIGN_EXCLAMATION,
2152 EL_SIGN_RADIOACTIVITY,
2163 EL_STEELWALL_SLIPPERY,
2186 EL_SWITCHGATE_OPENING,
2187 EL_SWITCHGATE_CLOSED,
2188 EL_SWITCHGATE_CLOSING,
2190 EL_TIMEGATE_OPENING,
2192 EL_TIMEGATE_CLOSING,
2196 EL_TUBE_VERTICAL_LEFT,
2197 EL_TUBE_VERTICAL_RIGHT,
2198 EL_TUBE_HORIZONTAL_UP,
2199 EL_TUBE_HORIZONTAL_DOWN,
2207 static int ep_classic_enemy[] =
2223 static int ep_belt[] =
2225 EL_CONVEYOR_BELT_1_LEFT,
2226 EL_CONVEYOR_BELT_1_MIDDLE,
2227 EL_CONVEYOR_BELT_1_RIGHT,
2228 EL_CONVEYOR_BELT_2_LEFT,
2229 EL_CONVEYOR_BELT_2_MIDDLE,
2230 EL_CONVEYOR_BELT_2_RIGHT,
2231 EL_CONVEYOR_BELT_3_LEFT,
2232 EL_CONVEYOR_BELT_3_MIDDLE,
2233 EL_CONVEYOR_BELT_3_RIGHT,
2234 EL_CONVEYOR_BELT_4_LEFT,
2235 EL_CONVEYOR_BELT_4_MIDDLE,
2236 EL_CONVEYOR_BELT_4_RIGHT,
2240 static int ep_belt_active[] =
2242 EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2243 EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2244 EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2245 EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2246 EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2247 EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2248 EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2249 EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2250 EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2251 EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2252 EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2253 EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2257 static int ep_belt_switch[] =
2259 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2260 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2261 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2262 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2263 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2264 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2265 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2266 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2267 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2268 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2269 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2270 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2274 static int ep_tube[] =
2281 EL_TUBE_HORIZONTAL_UP,
2282 EL_TUBE_HORIZONTAL_DOWN,
2284 EL_TUBE_VERTICAL_LEFT,
2285 EL_TUBE_VERTICAL_RIGHT,
2290 static int ep_keygate[] =
2311 static int ep_amoeboid[] =
2321 static int ep_amoebalive[] =
2330 static int ep_has_content[] =
2340 static int ep_active_bomb[] =
2343 EL_DYNABOMB_PLAYER_1_ACTIVE,
2344 EL_DYNABOMB_PLAYER_2_ACTIVE,
2345 EL_DYNABOMB_PLAYER_3_ACTIVE,
2346 EL_DYNABOMB_PLAYER_4_ACTIVE,
2347 EL_SP_DISK_RED_ACTIVE,
2351 static int ep_inactive[] =
2388 EL_INVISIBLE_STEELWALL,
2396 EL_WALL_EMERALD_YELLOW,
2397 EL_DYNABOMB_INCREASE_NUMBER,
2398 EL_DYNABOMB_INCREASE_SIZE,
2399 EL_DYNABOMB_INCREASE_POWER,
2403 EL_SOKOBAN_FIELD_EMPTY,
2404 EL_SOKOBAN_FIELD_FULL,
2405 EL_WALL_EMERALD_RED,
2406 EL_WALL_EMERALD_PURPLE,
2407 EL_ACID_POOL_TOPLEFT,
2408 EL_ACID_POOL_TOPRIGHT,
2409 EL_ACID_POOL_BOTTOMLEFT,
2410 EL_ACID_POOL_BOTTOM,
2411 EL_ACID_POOL_BOTTOMRIGHT,
2415 EL_BD_MAGIC_WALL_DEAD,
2416 EL_AMOEBA_TO_DIAMOND,
2424 EL_SP_GRAVITY_PORT_RIGHT,
2425 EL_SP_GRAVITY_PORT_DOWN,
2426 EL_SP_GRAVITY_PORT_LEFT,
2427 EL_SP_GRAVITY_PORT_UP,
2428 EL_SP_PORT_HORIZONTAL,
2429 EL_SP_PORT_VERTICAL,
2440 EL_SP_HARDWARE_GRAY,
2441 EL_SP_HARDWARE_GREEN,
2442 EL_SP_HARDWARE_BLUE,
2444 EL_SP_HARDWARE_YELLOW,
2445 EL_SP_HARDWARE_BASE_1,
2446 EL_SP_HARDWARE_BASE_2,
2447 EL_SP_HARDWARE_BASE_3,
2448 EL_SP_HARDWARE_BASE_4,
2449 EL_SP_HARDWARE_BASE_5,
2450 EL_SP_HARDWARE_BASE_6,
2451 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2452 EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2453 EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2454 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2455 EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2456 EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2457 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2458 EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2459 EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2460 EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2461 EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2462 EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2463 EL_SIGN_EXCLAMATION,
2464 EL_SIGN_RADIOACTIVITY,
2475 EL_STEELWALL_SLIPPERY,
2495 } element_properties[] =
2497 { ep_diggable, EP_DIGGABLE },
2498 { ep_collectible_only, EP_COLLECTIBLE_ONLY },
2499 { ep_dont_run_into, EP_DONT_RUN_INTO },
2500 { ep_dont_collide_with, EP_DONT_COLLIDE_WITH },
2501 { ep_dont_touch, EP_DONT_TOUCH },
2502 { ep_indestructible, EP_INDESTRUCTIBLE },
2503 { ep_slippery, EP_SLIPPERY },
2504 { ep_can_change, EP_CAN_CHANGE },
2505 { ep_can_move, EP_CAN_MOVE },
2506 { ep_can_fall, EP_CAN_FALL },
2507 { ep_can_smash_player, EP_CAN_SMASH_PLAYER },
2508 { ep_can_smash_enemies, EP_CAN_SMASH_ENEMIES },
2509 { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
2510 { ep_can_explode_by_fire, EP_CAN_EXPLODE_BY_FIRE },
2511 { ep_can_explode_smashed, EP_CAN_EXPLODE_SMASHED },
2512 { ep_can_explode_impact, EP_CAN_EXPLODE_IMPACT },
2513 { ep_walkable_over, EP_WALKABLE_OVER },
2514 { ep_walkable_inside, EP_WALKABLE_INSIDE },
2515 { ep_walkable_under, EP_WALKABLE_UNDER },
2516 { ep_passable_over, EP_PASSABLE_OVER },
2517 { ep_passable_inside, EP_PASSABLE_INSIDE },
2518 { ep_passable_under, EP_PASSABLE_UNDER },
2519 { ep_pushable, EP_PUSHABLE },
2521 { ep_can_be_crumbled, EP_CAN_BE_CRUMBLED },
2523 { ep_player, EP_PLAYER },
2524 { ep_can_pass_magic_wall, EP_CAN_PASS_MAGIC_WALL },
2525 { ep_switchable, EP_SWITCHABLE },
2526 { ep_bd_element, EP_BD_ELEMENT },
2527 { ep_sp_element, EP_SP_ELEMENT },
2528 { ep_sb_element, EP_SB_ELEMENT },
2530 { ep_food_dark_yamyam, EP_FOOD_DARK_YAMYAM },
2531 { ep_food_penguin, EP_FOOD_PENGUIN },
2532 { ep_food_pig, EP_FOOD_PIG },
2533 { ep_historic_wall, EP_HISTORIC_WALL },
2534 { ep_historic_solid, EP_HISTORIC_SOLID },
2535 { ep_classic_enemy, EP_CLASSIC_ENEMY },
2536 { ep_belt, EP_BELT },
2537 { ep_belt_active, EP_BELT_ACTIVE },
2538 { ep_belt_switch, EP_BELT_SWITCH },
2539 { ep_tube, EP_TUBE },
2540 { ep_keygate, EP_KEYGATE },
2541 { ep_amoeboid, EP_AMOEBOID },
2542 { ep_amoebalive, EP_AMOEBALIVE },
2543 { ep_has_content, EP_HAS_CONTENT },
2544 { ep_active_bomb, EP_ACTIVE_BOMB },
2545 { ep_inactive, EP_INACTIVE },
2550 static int copy_properties[][5] =
2554 EL_BUG_LEFT, EL_BUG_RIGHT,
2555 EL_BUG_UP, EL_BUG_DOWN
2559 EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT,
2560 EL_SPACESHIP_UP, EL_SPACESHIP_DOWN
2564 EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT,
2565 EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN
2569 EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT,
2570 EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN
2574 EL_PACMAN_LEFT, EL_PACMAN_RIGHT,
2575 EL_PACMAN_UP, EL_PACMAN_DOWN
2585 /* always start with reliable default values (element has no properties) */
2586 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2587 for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2588 SET_PROPERTY(i, j, FALSE);
2590 /* set all base element properties from above array definitions */
2591 for (i=0; element_properties[i].elements != NULL; i++)
2592 for (j=0; (element_properties[i].elements)[j] != -1; j++)
2593 SET_PROPERTY((element_properties[i].elements)[j],
2594 element_properties[i].property, TRUE);
2596 /* copy properties to some elements that are only stored in level file */
2597 for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2598 for (j=0; copy_properties[j][0] != -1; j++)
2599 if (HAS_PROPERTY(copy_properties[j][0], i))
2600 for (k=1; k<=4; k++)
2601 SET_PROPERTY(copy_properties[j][k], i, TRUE);
2604 void InitElementPropertiesEngine(int engine_version)
2607 static int active_properties[] =
2612 EP_DONT_COLLIDE_WITH,
2616 EP_CAN_PASS_MAGIC_WALL,
2621 EP_CAN_EXPLODE_BY_FIRE,
2634 EP_EM_SLIPPERY_WALL,
2639 static int no_wall_properties[] =
2642 EP_COLLECTIBLE_ONLY,
2644 EP_DONT_COLLIDE_WITH,
2647 EP_CAN_SMASH_PLAYER,
2648 EP_CAN_SMASH_ENEMIES,
2649 EP_CAN_SMASH_EVERYTHING,
2656 EP_FOOD_DARK_YAMYAM,
2672 InitElementPropertiesStatic();
2675 /* set all special, combined or engine dependent element properties */
2676 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2679 for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2680 SET_PROPERTY(i, j, FALSE);
2683 /* ---------- INACTIVE ------------------------------------------------- */
2684 if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2685 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2687 /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2688 SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2689 IS_WALKABLE_INSIDE(i) ||
2690 IS_WALKABLE_UNDER(i)));
2692 SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2693 IS_PASSABLE_INSIDE(i) ||
2694 IS_PASSABLE_UNDER(i)));
2696 SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2697 IS_PASSABLE_OVER(i)));
2699 SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2700 IS_PASSABLE_INSIDE(i)));
2702 SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2703 IS_PASSABLE_UNDER(i)));
2705 SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2708 /* ---------- COLLECTIBLE ---------------------------------------------- */
2709 SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2712 /* ---------- SNAPPABLE ------------------------------------------------ */
2713 SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2714 IS_COLLECTIBLE(i) ||
2718 /* ---------- WALL ----------------------------------------------------- */
2719 SET_PROPERTY(i, EP_WALL, TRUE); /* default: element is wall */
2721 for (j=0; no_wall_properties[j] != -1; j++)
2722 if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2723 i >= EL_FIRST_RUNTIME_UNREAL)
2724 SET_PROPERTY(i, EP_WALL, FALSE);
2726 if (IS_HISTORIC_WALL(i))
2727 SET_PROPERTY(i, EP_WALL, TRUE);
2729 /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2730 if (engine_version < VERSION_IDENT(2,2,0))
2731 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2733 SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2735 !IS_COLLECTIBLE(i)));
2737 /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2739 if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2740 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2742 SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2743 IS_INDESTRUCTIBLE(i)));
2745 /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2747 SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2748 else if (engine_version < VERSION_IDENT(2,2,0))
2749 SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2751 SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2752 !IS_WALKABLE_OVER(i) &&
2753 !IS_WALKABLE_UNDER(i)));
2755 if (IS_CUSTOM_ELEMENT(i))
2757 /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2759 SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2760 if (DONT_COLLIDE_WITH(i))
2761 SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2763 /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2764 if (CAN_SMASH_EVERYTHING(i))
2765 SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2766 if (CAN_SMASH_ENEMIES(i))
2767 SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2770 /* ---------- CAN_SMASH ------------------------------------------------ */
2771 SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2772 CAN_SMASH_ENEMIES(i) ||
2773 CAN_SMASH_EVERYTHING(i)));
2775 /* ---------- CAN_EXPLODE ---------------------------------------------- */
2776 SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2777 CAN_EXPLODE_SMASHED(i) ||
2778 CAN_EXPLODE_IMPACT(i)));
2780 /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2781 SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2782 !CAN_EXPLODE_1X1(i)));
2784 /* ---------- CAN_BE_CRUMBLED ------------------------------------------ */
2785 SET_PROPERTY(i, EP_CAN_BE_CRUMBLED,
2786 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2789 if (CAN_BE_CRUMBLED(i))
2790 printf("::: '%s' can be crumbled [%d]\n",
2791 element_info[i].token_name,
2792 element_info[i].crumbled[ACTION_DEFAULT]);
2797 /* determine inactive elements (used for engine main loop optimization) */
2798 for (i=0; i < MAX_NUM_ELEMENTS; i++)
2800 boolean active = FALSE;
2802 for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2804 if (HAS_PROPERTY(i, j))
2810 SET_PROPERTY(i, EP_INACTIVE, TRUE);
2815 /* dynamically adjust element properties according to game engine version */
2817 static int ep_em_slippery_wall[] =
2822 EL_EXPANDABLE_WALL_HORIZONTAL,
2823 EL_EXPANDABLE_WALL_VERTICAL,
2824 EL_EXPANDABLE_WALL_ANY,
2828 /* special EM style gems behaviour */
2829 for (i=0; ep_em_slippery_wall[i] != -1; i++)
2830 SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2831 level.em_slippery_gems);
2833 /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2834 SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2835 (level.em_slippery_gems &&
2836 engine_version > VERSION_IDENT(2,0,1)));
2840 /* dynamically adjust element properties according to game engine version */
2842 if (engine_version < RELEASE_IDENT(2,2,0,7))
2845 for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2847 int element = EL_CUSTOM_START + i;
2849 element_info[element].push_delay_fixed = 2;
2850 element_info[element].push_delay_random = 8;
2856 static void InitGlobal()
2858 global.autoplay_leveldir = NULL;
2860 global.frames_per_second = 0;
2861 global.fps_slowdown = FALSE;
2862 global.fps_slowdown_factor = 1;
2865 void Execute_Command(char *command)
2867 if (strcmp(command, "print graphicsinfo.conf") == 0)
2871 printf("# You can configure additional/alternative image files here.\n");
2872 printf("# (The images below are default and therefore commented out.)\n");
2874 printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2876 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2879 for (i=0; image_config[i].token != NULL; i++)
2881 getFormattedSetupEntry(image_config[i].token,
2882 image_config[i].value));
2886 else if (strcmp(command, "print soundsinfo.conf") == 0)
2890 printf("# You can configure additional/alternative sound files here.\n");
2891 printf("# (The sounds below are default and therefore commented out.)\n");
2893 printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2895 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2898 for (i=0; sound_config[i].token != NULL; i++)
2900 getFormattedSetupEntry(sound_config[i].token,
2901 sound_config[i].value));
2905 else if (strcmp(command, "print musicinfo.conf") == 0)
2907 printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2909 printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2911 printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2915 else if (strncmp(command, "dump level ", 11) == 0)
2917 char *filename = &command[11];
2919 if (access(filename, F_OK) != 0)
2920 Error(ERR_EXIT, "cannot open file '%s'", filename);
2922 LoadLevelFromFilename(&level, filename);
2927 else if (strncmp(command, "dump tape ", 10) == 0)
2929 char *filename = &command[10];
2931 if (access(filename, F_OK) != 0)
2932 Error(ERR_EXIT, "cannot open file '%s'", filename);
2934 LoadTapeFromFilename(filename);
2939 else if (strncmp(command, "autoplay ", 9) == 0)
2941 char *str_copy = getStringCopy(&command[9]);
2942 char *str_ptr = strchr(str_copy, ' ');
2944 global.autoplay_leveldir = str_copy;
2945 global.autoplay_level_nr = -1;
2947 if (str_ptr != NULL)
2949 *str_ptr++ = '\0'; /* terminate leveldir string */
2950 global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
2955 Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
2959 static void InitSetup()
2961 LoadSetup(); /* global setup info */
2963 /* set some options from setup file */
2965 if (setup.options.verbose)
2966 options.verbose = TRUE;
2969 static void InitPlayerInfo()
2973 /* choose default local player */
2974 local_player = &stored_player[0];
2976 for (i=0; i<MAX_PLAYERS; i++)
2977 stored_player[i].connected = FALSE;
2979 local_player->connected = TRUE;
2982 static void InitArtworkInfo()
2987 static char *get_string_in_brackets(char *string)
2989 char *string_in_brackets = checked_malloc(strlen(string) + 3);
2991 sprintf(string_in_brackets, "[%s]", string);
2993 return string_in_brackets;
2997 static char *get_element_class_token(int element)
2999 char *element_class_name = element_info[element].class_name;
3000 char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3002 sprintf(element_class_token, "[%s]", element_class_name);
3004 return element_class_token;
3007 static char *get_action_class_token(int action)
3009 char *action_class_name = &element_action_info[action].suffix[1];
3010 char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3012 sprintf(action_class_token, "[%s]", action_class_name);
3014 return action_class_token;
3018 static void InitArtworkConfig()
3020 static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3021 static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3022 static char *action_id_suffix[NUM_ACTIONS + 1];
3023 static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3024 static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3025 static char *dummy[1] = { NULL };
3026 static char *ignore_generic_tokens[] =
3032 static char **ignore_image_tokens, **ignore_sound_tokens;
3033 int num_ignore_generic_tokens;
3034 int num_ignore_image_tokens, num_ignore_sound_tokens;
3037 /* dynamically determine list of generic tokens to be ignored */
3038 num_ignore_generic_tokens = 0;
3039 for (i=0; ignore_generic_tokens[i] != NULL; i++)
3040 num_ignore_generic_tokens++;
3042 /* dynamically determine list of image tokens to be ignored */
3043 num_ignore_image_tokens = num_ignore_generic_tokens;
3044 for (i=0; image_config_vars[i].token != NULL; i++)
3045 num_ignore_image_tokens++;
3046 ignore_image_tokens =
3047 checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3048 for (i=0; i < num_ignore_generic_tokens; i++)
3049 ignore_image_tokens[i] = ignore_generic_tokens[i];
3050 for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3051 ignore_image_tokens[num_ignore_generic_tokens + i] =
3052 image_config_vars[i].token;
3053 ignore_image_tokens[num_ignore_image_tokens] = NULL;
3055 /* dynamically determine list of sound tokens to be ignored */
3056 num_ignore_sound_tokens = num_ignore_generic_tokens;
3057 ignore_sound_tokens =
3058 checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3059 for (i=0; i < num_ignore_generic_tokens; i++)
3060 ignore_sound_tokens[i] = ignore_generic_tokens[i];
3061 ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3063 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3064 image_id_prefix[i] = element_info[i].token_name;
3065 for (i=0; i<NUM_FONTS; i++)
3066 image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3067 image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3069 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3070 sound_id_prefix[i] = element_info[i].token_name;
3071 for (i=0; i<MAX_NUM_ELEMENTS; i++)
3072 sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3073 get_string_in_brackets(element_info[i].class_name);
3074 sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3076 for (i=0; i<NUM_ACTIONS; i++)
3077 action_id_suffix[i] = element_action_info[i].suffix;
3078 action_id_suffix[NUM_ACTIONS] = NULL;
3080 for (i=0; i<NUM_DIRECTIONS; i++)
3081 direction_id_suffix[i] = element_direction_info[i].suffix;
3082 direction_id_suffix[NUM_DIRECTIONS] = NULL;
3084 for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3085 special_id_suffix[i] = special_suffix_info[i].suffix;
3086 special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3088 InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3089 image_id_prefix, action_id_suffix, direction_id_suffix,
3090 special_id_suffix, ignore_image_tokens);
3091 InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3092 sound_id_prefix, action_id_suffix, dummy,
3093 special_id_suffix, ignore_sound_tokens);
3096 static void InitMixer()
3104 char *filename_font_initial = NULL;
3105 Bitmap *bitmap_font_initial = NULL;
3108 /* determine settings for initial font (for displaying startup messages) */
3109 for (i=0; image_config[i].token != NULL; i++)
3111 for (j=0; j < NUM_INITIAL_FONTS; j++)
3113 char font_token[128];
3116 sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3117 len_font_token = strlen(font_token);
3119 if (strcmp(image_config[i].token, font_token) == 0)
3120 filename_font_initial = image_config[i].value;
3121 else if (strlen(image_config[i].token) > len_font_token &&
3122 strncmp(image_config[i].token, font_token, len_font_token) == 0)
3124 if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3125 font_initial[j].src_x = atoi(image_config[i].value);
3126 else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3127 font_initial[j].src_y = atoi(image_config[i].value);
3128 else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3129 font_initial[j].width = atoi(image_config[i].value);
3130 else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3131 font_initial[j].height = atoi(image_config[i].value);
3136 for (j=0; j < NUM_INITIAL_FONTS; j++)
3138 font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3139 font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3142 if (filename_font_initial == NULL) /* should not happen */
3143 Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3145 /* create additional image buffers for double-buffering */
3146 bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3147 bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3149 /* initialize screen properties */
3150 InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3151 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3153 InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3154 InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3155 InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3157 bitmap_font_initial = LoadCustomImage(filename_font_initial);
3159 for (j=0; j < NUM_INITIAL_FONTS; j++)
3160 font_initial[j].bitmap = bitmap_font_initial;
3162 InitFontGraphicInfo();
3164 DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3165 DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3167 DrawInitText("Loading graphics:", 120, FC_GREEN);
3169 InitTileClipmasks();
3172 void InitGfxBackground()
3176 drawto = backbuffer;
3177 fieldbuffer = bitmap_db_field;
3178 SetDrawtoField(DRAW_BACKBUFFER);
3180 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3181 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3182 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3183 ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3185 for (x=0; x<MAX_BUF_XSIZE; x++)
3186 for (y=0; y<MAX_BUF_YSIZE; y++)
3189 redraw_mask = REDRAW_ALL;
3192 static void InitLevelInfo()
3194 LoadLevelInfo(); /* global level info */
3195 LoadLevelSetup_LastSeries(); /* last played series info */
3196 LoadLevelSetup_SeriesInfo(); /* last played level info */
3199 void InitLevelArtworkInfo()
3201 LoadLevelArtworkInfo();
3204 static void InitImages()
3207 setLevelArtworkDir(artwork.gfx_first);
3211 printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3212 leveldir_current->identifier,
3213 artwork.gfx_current_identifier,
3214 artwork.gfx_current->identifier,
3215 leveldir_current->graphics_set,
3216 leveldir_current->graphics_path);
3219 ReloadCustomImages();
3221 LoadCustomElementDescriptions();
3222 LoadSpecialMenuDesignSettings();
3224 ReinitializeGraphics();
3227 static void InitSound(char *identifier)
3229 if (identifier == NULL)
3230 identifier = artwork.snd_current->identifier;
3233 /* set artwork path to send it to the sound server process */
3234 setLevelArtworkDir(artwork.snd_first);
3237 InitReloadCustomSounds(identifier);
3238 ReinitializeSounds();
3241 static void InitMusic(char *identifier)
3243 if (identifier == NULL)
3244 identifier = artwork.mus_current->identifier;
3247 /* set artwork path to send it to the sound server process */
3248 setLevelArtworkDir(artwork.mus_first);
3251 InitReloadCustomMusic(identifier);
3252 ReinitializeMusic();
3255 void InitNetworkServer()
3257 #if defined(PLATFORM_UNIX)
3261 if (!options.network)
3264 #if defined(PLATFORM_UNIX)
3265 nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3267 if (!ConnectToServer(options.server_host, options.server_port))
3268 Error(ERR_EXIT, "cannot connect to network game server");
3270 SendToServer_PlayerName(setup.player_name);
3271 SendToServer_ProtocolVersion();
3274 SendToServer_NrWanted(nr_wanted);
3278 static char *getNewArtworkIdentifier(int type)
3280 static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3281 static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3282 static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3283 static boolean initialized[3] = { FALSE, FALSE, FALSE };
3284 TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3285 boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3286 char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3287 char *leveldir_identifier = leveldir_current->identifier;
3289 char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3291 char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3293 boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3294 char *artwork_current_identifier;
3295 char *artwork_new_identifier = NULL; /* default: nothing has changed */
3297 /* leveldir_current may be invalid (level group, parent link) */
3298 if (!validLevelSeries(leveldir_current))
3301 /* 1st step: determine artwork set to be activated in descending order:
3302 --------------------------------------------------------------------
3303 1. setup artwork (when configured to override everything else)
3304 2. artwork set configured in "levelinfo.conf" of current level set
3305 (artwork in level directory will have priority when loading later)
3306 3. artwork in level directory (stored in artwork sub-directory)
3307 4. setup artwork (currently configured in setup menu) */
3309 if (setup_override_artwork)
3310 artwork_current_identifier = setup_artwork_set;
3311 else if (leveldir_artwork_set != NULL)
3312 artwork_current_identifier = leveldir_artwork_set;
3313 else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3314 artwork_current_identifier = leveldir_identifier;
3316 artwork_current_identifier = setup_artwork_set;
3319 /* 2nd step: check if it is really needed to reload artwork set
3320 ------------------------------------------------------------ */
3323 if (type == ARTWORK_TYPE_GRAPHICS)
3324 printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3325 artwork_new_identifier,
3326 ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3327 artwork_current_identifier,
3328 leveldir_current->graphics_set,
3329 leveldir_current->identifier);
3332 /* ---------- reload if level set and also artwork set has changed ------- */
3333 if (leveldir_current_identifier[type] != leveldir_identifier &&
3334 (last_has_level_artwork_set[type] || has_level_artwork_set))
3335 artwork_new_identifier = artwork_current_identifier;
3337 leveldir_current_identifier[type] = leveldir_identifier;
3338 last_has_level_artwork_set[type] = has_level_artwork_set;
3341 if (type == ARTWORK_TYPE_GRAPHICS)
3342 printf("::: 1: '%s'\n", artwork_new_identifier);
3345 /* ---------- reload if "override artwork" setting has changed ----------- */
3346 if (last_override_level_artwork[type] != setup_override_artwork)
3347 artwork_new_identifier = artwork_current_identifier;
3349 last_override_level_artwork[type] = setup_override_artwork;
3352 if (type == ARTWORK_TYPE_GRAPHICS)
3353 printf("::: 2: '%s'\n", artwork_new_identifier);
3356 /* ---------- reload if current artwork identifier has changed ----------- */
3357 if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3358 artwork_current_identifier) != 0)
3359 artwork_new_identifier = artwork_current_identifier;
3361 *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3364 if (type == ARTWORK_TYPE_GRAPHICS)
3365 printf("::: 3: '%s'\n", artwork_new_identifier);
3368 /* ---------- do not reload directly after starting ---------------------- */
3369 if (!initialized[type])
3370 artwork_new_identifier = NULL;
3372 initialized[type] = TRUE;
3375 if (type == ARTWORK_TYPE_GRAPHICS)
3376 printf("::: 4: '%s'\n", artwork_new_identifier);
3380 if (type == ARTWORK_TYPE_GRAPHICS)
3381 printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3382 artwork.gfx_current_identifier, artwork_current_identifier,
3383 artwork.gfx_current->identifier, leveldir_current->graphics_set,
3384 artwork_new_identifier);
3387 return artwork_new_identifier;
3390 void ReloadCustomArtwork()
3392 char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3393 char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3394 char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3395 boolean redraw_screen = FALSE;
3397 if (gfx_new_identifier != NULL)
3400 printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3401 artwork.gfx_current_identifier,
3403 artwork.gfx_current->identifier,
3404 leveldir_current->graphics_set);
3407 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3412 printf("... '%s'\n",
3413 leveldir_current->graphics_set);
3416 FreeTileClipmasks();
3417 InitTileClipmasks();
3419 redraw_screen = TRUE;
3422 if (snd_new_identifier != NULL)
3424 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3426 InitSound(snd_new_identifier);
3428 redraw_screen = TRUE;
3431 if (mus_new_identifier != NULL)
3433 ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3435 InitMusic(mus_new_identifier);
3437 redraw_screen = TRUE;
3442 InitGfxBackground();
3444 /* force redraw of (open or closed) door graphics */
3445 SetDoorState(DOOR_OPEN_ALL);
3446 CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3450 void KeyboardAutoRepeatOffUnlessAutoplay()
3452 if (global.autoplay_leveldir == NULL)
3453 KeyboardAutoRepeatOff();
3457 /* ========================================================================= */
3459 /* ========================================================================= */
3463 InitGlobal(); /* initialize some global variables */
3465 if (options.execute_command)
3466 Execute_Command(options.execute_command);
3468 if (options.serveronly)
3470 #if defined(PLATFORM_UNIX)
3471 NetworkServer(options.server_port, options.serveronly);
3473 Error(ERR_WARN, "networking only supported in Unix version");
3475 exit(0); /* never reached */
3481 InitArtworkInfo(); /* needed before loading gfx, sound & music */
3482 InitArtworkConfig(); /* needed before forking sound child process */
3487 InitRND(NEW_RANDOMIZE);
3488 InitSimpleRND(NEW_RANDOMIZE);
3493 InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3496 InitEventFilter(FilterMouseMotionEvents);
3498 InitElementPropertiesStatic();
3503 InitLevelArtworkInfo();
3505 InitImages(); /* needs to know current level directory */
3506 InitSound(NULL); /* needs to know current level directory */
3507 InitMusic(NULL); /* needs to know current level directory */
3509 InitGfxBackground();
3511 if (global.autoplay_leveldir)
3517 game_status = GAME_MODE_MAIN;
3521 InitNetworkServer();
3524 void CloseAllAndExit(int exit_value)
3529 CloseAudio(); /* called after freeing sounds (needed for SDL) */
3532 FreeTileClipmasks();
3534 CloseVideoDisplay();
3535 ClosePlatformDependentStuff();