Merge branch 'master' into releases 3.1.1
authorHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:49:18 +0000 (10:49 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:49:18 +0000 (10:49 +0200)
71 files changed:
CHANGES
ChangeLog
Makefile
src/Makefile
src/cartoons.c
src/conf_chr.c
src/conf_chr.h
src/conf_e2g.c
src/conf_e2s.c
src/conf_esg.c
src/conf_gfx.c
src/conf_gfx.h
src/conf_hlp.c
src/conf_mus.c
src/conf_snd.c
src/conf_snd.h
src/conftime.h
src/editor.c
src/editor.h
src/engines.h [new file with mode: 0644]
src/events.c
src/files.c
src/files.h
src/game.c
src/game.h
src/game_em/Makefile [new file with mode: 0644]
src/game_em/cave.c [new file with mode: 0644]
src/game_em/convert.c [new file with mode: 0644]
src/game_em/display.h [new file with mode: 0644]
src/game_em/game_em.h [new file with mode: 0644]
src/game_em/global.h [new file with mode: 0644]
src/game_em/graphics.c [new file with mode: 0644]
src/game_em/init.c [new file with mode: 0644]
src/game_em/input.c [new file with mode: 0644]
src/game_em/level.h [new file with mode: 0644]
src/game_em/main.c [new file with mode: 0644]
src/game_em/main_em.h [new file with mode: 0644]
src/game_em/sample.h [new file with mode: 0644]
src/game_em/sound.c [new file with mode: 0644]
src/game_em/synchro_1.c [new file with mode: 0644]
src/game_em/synchro_2.c [new file with mode: 0644]
src/game_em/synchro_3.c [new file with mode: 0644]
src/game_em/tab_generate.c [new file with mode: 0644]
src/game_em/tile.h [new file with mode: 0644]
src/game_em/ulaw_generate.c [new file with mode: 0644]
src/init.c
src/init.h
src/libgame/Makefile
src/libgame/gadgets.c
src/libgame/gadgets.h
src/libgame/image.c
src/libgame/image.h
src/libgame/joystick.c
src/libgame/misc.c
src/libgame/misc.h
src/libgame/platform.h
src/libgame/sdl.c
src/libgame/setup.c
src/libgame/setup.h
src/libgame/sound.c
src/libgame/sound.h
src/libgame/system.c
src/libgame/system.h
src/libgame/types.h
src/libgame/x11.c
src/main.c
src/main.h
src/screens.c
src/tape.c
src/tools.c
src/tools.h

diff --git a/CHANGES b/CHANGES
index 05c4210e16823f000b6e789a30f6e22a8aff7614..e7218e4287be6be9f24660be4a1ea646378f78e7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+Release Version 3.1.1 [16 AUG 2005]
+-----------------------------------
+       - added tutorial level set created by Aaron Davidson
+       - added editor element descriptions written by Aaron Davidson
+       - added native game engine for Emerald Mine (Club) levels
+       - added level skipping functionality to main menu
+       - added support for dumping small-sized level sketches from editor
+       - added use of "editorsetup.conf" for different level sets
+       - lots of bugfixes and internal engine changes (see ChangeLog)
+
 Release Version 3.1.0 [07 JUN 2004]
 -----------------------------------
        - fixed obvious bug with wrong "Murphy" graphics (when digging etc.)
index 0e836744113dec691e73ac725ccbfaa61175d04f..b3ae71e4f88d8d2bd5af778a814b326264e720e4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,225 @@
+2005-08-15
+       * fixed bug on Mac OS X (use of reserved name "Random") in EM engine
+
+2005-08-07
+       * version number temporarily set to 3.1.1 (intermediate bugfix release)
+       * version 3.1.1 released
+
+2005-08-07
+       * changed some va_arg() arguments from 'long' to 'int', fixing problems
+         on 64-bit architecture systems with LP64 data model
+
+2005-08-06
+       * fixed bug with bombs not exploding when hitting the last level line
+         (introduced after the release of 3.1.0)
+
+2005-08-06
+       * added support for dumping small-sized level sketches from editor
+
+2005-07-24
+       * added recognition of "trigger element" for "change digged element to"
+         (this is not really what the "trigger element" was made for, but its
+         use may seem obvious for leaving back digged elements unchanged)
+
+2005-07-23
+       * fixed multiple warnings about failed joystick device initialization
+
+2005-06-27
+       * fixed bug with dynamite dropped on top of just dropped custom element
+         (collect dynamite, collect CE, drop CE => dynamite was also dropped);
+         dynamite can still be dropped, but drop key must be released before
+
+2005-06-27
+       * fixed bug with wrong start directory when started from file browser
+         (due to this bug, R'n'D could not be started from KDE's Konqueror)
+
+2005-06-26
+       * fixed bug causing "change when impact" on player not working
+       * fixed wrong priority of "hitting something" over "hitting <element>"
+       * fixed wrong priority of "hit by something" over "hit by <element>"
+
+2005-06-14
+       * fixed graphical bug which caused the player (being Murphy) to show
+         collecting animations although the element was collected by penguin
+
+2005-06-08
+       * fixed two bugs causing wrong door background graphics in system.c
+         (in functions "SetBackgroundBitmap()" and "DrawingOnBackground()")
+
+2005-06-06
+       * fixed graphic bug with exploding bomb and R'n'D graphics in EM engine
+       * added "no direction" to "walkable/passable from" selectbox options
+
+2005-06-05
+       * enhanced tape autoplay to accept "autoplay <set> [<nr> ...]" format
+       * in tape autoplay, not only report broken, but also missing tapes
+
+2005-05-31
+       * uploaded pre-release (test) version 3.2.0-2 binary and source code
+
+2005-05-27
+       * fixed small bug with "linear" animation not working for active lamp
+
+2005-05-24
+       * fixed bug with moving up despite gravity due to "block last field"
+       * fixed small bug with wrong draw offset when typing name in main menu
+       * when reading user names from "passwd", ignore data after first comma
+       * when creating new "levelinfo.conf", only write some selected entries
+
+2005-04-28
+       * fixed displaying "imported from/by" on preview with empty string
+       * fixed ignoring draw offset for fonts used for level preview texts
+
+2005-04-24
+       * fixed a delay problem with SDL and too many mouse motion events
+       * added setup option "skip levels" and level skipping functionality
+
+2005-03-19
+       * added move speed "not moving" for non-moving CEs, but with direction
+
+2005-03-06
+       * fixed mapping of obsolete element token names in "editorsetup.conf"
+       * fixed bug with sound "acid.splashing" treated as a loop sound
+       * fixed some little sound bugs in native EM engine
+
+2005-02-20
+       * fixed small bug when dragging scrollbars to end positions
+
+2005-02-14
+       * added editor element descriptions written by Aaron Davidson
+
+2005-02-02
+       * improved fallback handling when configured artwork is not available
+         (now using default artwork instead of exiting when files not found)
+
+2005-02-01
+       * fixed bug on level selection screen when dragging scrollbar
+
+2005-01-19
+       * fixed bug which caused broken tapes when appending to EM engine tapes
+
+2005-01-17
+       * uploaded pre-release (test) version 3.2.0-1 binary and source code
+
+2005-01-17
+       * added code to replace changed artwork config tokens with other tokens
+         (needed for backwards compatibility, so that older tokens still work)
+
+2005-01-16
+       * added native R'n'D graphics for some new EMC elements in EM engine
+
+2005-01-15
+       * fixed some bugs in the EM engine integration code
+       * changed EM engine code to allow diagonal movement
+       * changed EM engine code to allow use of separate snap and drop keys
+
+2005-01-03
+       * fixed some redraw bugs when using EM engine
+
+2005-01-02
+       * fixed bug with not converting RND levels which are set to use native
+         engine to native level structure when loading
+
+2005-01-01
+       * uploaded pre-release (test) version 3.2.0-0 binary and source code
+
+2005-01-01
+       * version number set to 3.2.0
+
+2004-12-30
+       * level data now reset to defaults after attempt to load invalid file
+
+2004-11-13
+       * added use of "editorsetup.conf" for different level sets
+
+2004-10-26
+       * added auto-detection for various types of Emerald Mine level files
+
+2004-10-17
+       * fixed bug with scrollbars getting too small when list is very large
+
+2004-10-09
+       * fixed bug with 3+3 (cross) sized explosion not making explosion sound
+
+2004-10-04
+       * added most level editor configuration gadgets for new EMC elements
+
+2004-10-01
+       * added more element and graphic definitions for new EMC elements
+
+2004-09-27
+       * modified native EM engine to use integrated R'n'D sound system
+
+2004-09-21
+       * added SDL support to graphics functions in native EM engine
+         (by always using generic libgame interface functions)
+
+2004-09-20
+       * fixed bug in frame synchronization in native EM engine
+
+2004-09-18
+       * added code to convert levels between R'n'D and native EM engine
+
+2004-08-23
+       * new Emerald Mine engine can now play levels selected in main menu
+
+2004-08-16
+       * fixed big memory leak in function "CreateBitmapWithSmallBitmaps()"
+         (which creates scaled down graphics for level editor and preview);
+         there's still a memory leak somewhere in the artwork handling code
+       * added "scale image up" functionality to X11 version of zoom function
+
+2004-08-14
+       * first attempts to integrate new, native Emerald Mine Club engine
+
+2004-08-07
+       * fixed bug in gadget code which caused reset of CEs in level editor
+         (example: pressing 'b' [grab brush] on CE config page erased values)
+         (solution: check if gadgets in ClickOnGadget() are really mapped)
+       * improved level change detection in editor (settings now also checked)
+       * fixed bug with "can move into acid" and "don't collide with" state
+
+2004-07-29
+       * fixed maze runner style CEs to use the configured move delay value
+
+2004-06-27
+       * added Aaron Davidson's tutorial level set to the "Tutorials" section
+
+2004-06-20
+       * fixed engine change that broke 3.0.8 levels like "Walpurgis Gardens"
+       * fixed the above fix because it broke level set "machine" (*sigh*)
+       * fixed random element placement in level editor to work as expected
+       * fixed undefined graphic of runtime element "EL_AMOEBA_TO_DIAMOND"
+
+2004-06-15
+       * re-recorded tape for BD2K3, level 010 (broken due to bugfix)
+
+2004-06-13
+       * fixed bug (missing array boundary check) which caused broken tapes
+       * fixed bug (when loading level template) which caused broken levels
+       * fixed bug with new block last field code when using non-yellow player
+
+2004-06-12
+       * fixed bug when pressing "stop, pause, stop, play" on tape recorder
+       * internal change of how the player blocks the last field when moving
+       * fixed blocking delay of last field for EM and SP style block delay
+       * fixed bug where the player had to wait for the usual move delay after
+         unsuccessfully trying to move, when he directly could move after that
+       * the last two changes should make original Supaplex level 93 solvable
+       * improved use of random number generator to make it less predictable
+       * fixed behaviour of slippery SP elements to let slip left, then right
+
+2004-06-11
+       * fixed bug with wrong door state after trying to quickload empty tape
+       * fixed waste of static memory usage of the binary, making it smaller
+       * fixed very little graphical bug in Supaplex explosion
+
+2004-06-07
+       * version number set to 3.1.1
+
+2004-06-07
+       * version 3.1.0 released
+
 2004-06-07
        * fixed bug with crash when writing user levelinfo.conf the first time
 
index 9f1e23217da1495a982230cd6eeef1709feea2a5..bf09646daa34bb1b8136ea31f0cf5ecced63cba3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 # =============================================================================
 # Rocks'n'Diamonds Makefile
 # -----------------------------------------------------------------------------
-# (c) 1995-2003 Holger Schemel <info@artsoft.org>
+# (c) 1995-2005 Holger Schemel <info@artsoft.org>
 # =============================================================================
 
 # -----------------------------------------------------------------------------
@@ -76,6 +76,9 @@ solaris-sdl:
 mac:
        @$(MAKE_CMD) PLATFORM=macosx
 
+mac-static:
+       @$(MAKE_CMD) PLATFORM=macosx TARGET=sdl-static
+
 msdos:
        @$(MAKE_CMD) PLATFORM=msdos
 
@@ -103,7 +106,7 @@ run: all
        @./rocksndiamonds --verbose
 
 gdb: all
-       @gdb ./rocksndiamonds
+       @gdb -batch -x GDB_COMMANDS ./rocksndiamonds
 
 valgrind: all
        @valgrind -v --leak-check=yes ./rocksndiamonds 2> valgrind.out
@@ -169,11 +172,16 @@ dist-build-all:
        $(MAKE) clean
        $(MAKE) dist-build-unix         ; $(MAKE) dist-clean
        $(MAKE) dist-build-win32        ; $(MAKE) dist-clean
-       $(MAKE) dist-build-msdos        ; $(MAKE) dist-clean
+#      $(MAKE) dist-build-msdos        ; $(MAKE) dist-clean
+
+# dist-all: dist-build-all dist-unix dist-msdos dist-win32 dist-macosx
+dist-all: dist-build-all dist-unix dist-win32 dist-macosx
 
-dist-all: dist-build-all dist-unix dist-msdos dist-win32 dist-macosx
+# upload-all: upload-unix upload-msdos upload-win32 upload-macosx
+upload-all: upload-unix upload-win32 upload-macosx
 
-upload-all: upload-unix upload-msdos upload-win32 upload-macosx
+tags:
+       $(MAKE_CMD) tags
 
 depend dep:
        $(MAKE_CMD) depend
index 53bf400347a1dfdcc27386b3194c2074be27344a..973fdeadd74f539c7f5525d0a08a5585da101790 100644 (file)
@@ -1,7 +1,7 @@
 # =============================================================================
 # Rocks'n'Diamonds Makefile (src)
 # -----------------------------------------------------------------------------
-# (c) 1995-2003 Holger Schemel <info@artsoft.org>
+# (c) 1995-2005 Holger Schemel <info@artsoft.org>
 # =============================================================================
 
 # -----------------------------------------------------------------------------
@@ -27,6 +27,7 @@ endif
 
 AR = ar
 RANLIB = ranlib
+ETAGS = etags
 
 BMP2ICO = bmp2ico
 WINDRES = windres
@@ -94,6 +95,12 @@ SDL_LIBS = -lSDL_image -lSDL_mixer -lSDL_net -lsmpeg
 SYS_LDFLAGS = $(SDL_LIBS) $(shell sdl-config --libs)
 endif
 
+ifeq ($(TARGET),sdl-static)
+SYS_CFLAGS  = -DTARGET_SDL $(shell sdl-config --cflags)
+SDL_LIBS = -lSDL_image -lSDL_mixer -lSDL_net -lsmpeg
+SYS_LDFLAGS = $(SDL_LIBS) $(shell sdl-config --static-libs)
+endif
+
 ifeq ($(TARGET),allegro)
 SYS_CFLAGS = -DTARGET_ALLEGRO -I$(CROSS_PATH_MSDOS)/include
 SYS_LDFLAGS = -lalleg
@@ -194,8 +201,13 @@ CNFS_CMD = ../Scripts/create_element_defs.pl
 
 TIMESTAMP_FILE = conftime.h
 
-LIBDIR = libgame
-LIBGAME = $(LIBDIR)/libgame.a
+LIBGAME_DIR = libgame
+LIBGAME = $(LIBGAME_DIR)/libgame.a
+
+GAME_EM_DIR = game_em
+GAME_EM = $(GAME_EM_DIR)/game_em.a
+
+RNDLIBS = $(LIBGAME) $(GAME_EM)
 
 ICONBASE = windows_icon
 ifeq ($(PLATFORM),cross-win32)
@@ -208,15 +220,20 @@ endif
 # build targets
 # -----------------------------------------------------------------------------
 
-all: libgame_dir $(PROGNAME)
+all: libgame_dir game_em_dir $(PROGNAME)
 
-$(PROGNAME): $(LIBGAME) $(TIMESTAMP_FILE) $(OBJS) $(ICON)
-       $(CC) $(PROFILING) $(OBJS) $(ICON) $(LIBGAME) $(LDFLAGS) -o $(PROGNAME)
+$(PROGNAME): $(RNDLIBS) $(TIMESTAMP_FILE) $(OBJS) $(ICON)
+       $(CC) $(PROFILING) $(OBJS) $(ICON) $(RNDLIBS) $(LDFLAGS) -o $(PROGNAME)
 
 libgame_dir:
-       @$(MAKE) -C $(LIBDIR)
+       @$(MAKE) -C $(LIBGAME_DIR)
 $(LIBGAME):
-       @$(MAKE) -C $(LIBDIR)
+       @$(MAKE) -C $(LIBGAME_DIR)
+
+game_em_dir:
+       @$(MAKE) -C $(GAME_EM_DIR)
+$(GAME_EM):
+       @$(MAKE) -C $(GAME_EM_DIR)
 
 auto-conf:
        @for i in $(CNFS); do                   \
@@ -233,7 +250,7 @@ conf_snd.h: conf_snd.c
 conf_mus.h: conf_mus.c
        @$(MAKE) auto-conf
 
-$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME)
+$(TIMESTAMP_FILE): $(SRCS) $(LIBGAME) $(GAME_EM)
        @date '+"[%Y-%m-%d %H:%M]"' \
        | sed -e 's/^/#define COMPILE_DATE_STRING /' \
        > $(TIMESTAMP_FILE)
@@ -246,9 +263,11 @@ $(ICON):
        $(CC) $(PROFILING) $(CFLAGS) -c $*.c
 
 clean-obj:
-       $(MAKE) -C $(LIBDIR) clean
+       $(MAKE) -C $(LIBGAME_DIR) clean
+       $(MAKE) -C $(GAME_EM_DIR) clean
        $(RM) $(OBJS)
        $(RM) $(LIBGAME)
+       $(RM) $(GAME_EM)
 
 clean-ico:
        $(RM) $(ICONBASE).ico
@@ -267,8 +286,12 @@ clean: clean-obj clean-ico clean-bin
 
 dist-clean: clean-obj
 
+tags:
+       $(ETAGS) *.[ch] $(LIBGAME_DIR)/*.[ch] $(GAME_EM_DIR)/*.[ch]
+
 depend:
-       $(MAKE) -C $(LIBDIR) depend
+       $(MAKE) -C $(LIBGAME_DIR) depend
+       $(MAKE) -C $(GAME_EM_DIR) depend
        for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
 
 ifeq (.depend,$(wildcard .depend))
index fd53e502a2e955124eaf9c656cb0b721cf83a11a..fc465fac037bc4dbb32c49b6d7d40a2a8422c749 100644 (file)
@@ -23,7 +23,15 @@ static struct ToonInfo toons[MAX_NUM_TOONS];
 
 static void PrepareBackbuffer()
 {
-  /* Fill empty backbuffer for animation functions */
+  if (game_status == GAME_MODE_PLAYING &&
+      level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    BlitScreenToBitmap_EM(backbuffer);
+
+    return;
+  }
+
+  /* fill empty backbuffer for animation functions */
   if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
   {
     int xx, yy;
@@ -74,7 +82,7 @@ void InitToons()
   for (i=0; i < num_toons; i++)
   {
     int graphic = IMG_TOON_1 + i;
-    struct FileInfo *image = getImageListEntry(graphic);
+    struct FileInfo *image = getImageListEntryFromImageID(graphic);
 
     toons[i].bitmap = graphic_info[graphic].bitmap;
 
index 506c8b27244a0ae6f904d26af269c59e5ecbe5e7..63aee714a82c871e112ea1c94bb5b7e51bbabc15 100644 (file)
   { "char_dollar.ypos",                                "0"                     },
   { "char_dollar.frames",                      "1"                     },
 
-  { "char_procent",                            "RocksFontEM.pcx"       },
-  { "char_procent.xpos",                       "5"                     },
-  { "char_procent.ypos",                       "0"                     },
-  { "char_procent.frames",                     "1"                     },
+  { "char_percent",                            "RocksFontEM.pcx"       },
+  { "char_percent.xpos",                       "5"                     },
+  { "char_percent.ypos",                       "0"                     },
+  { "char_percent.frames",                     "1"                     },
 
   { "char_ampersand",                          "RocksFontEM.pcx"       },
   { "char_ampersand.xpos",                     "6"                     },
index 8cee272485e9fccebc29661db0e8563857aafa2e..af90160a42fe0ed0b0328c20e0c2f1c4aafc0979 100644 (file)
@@ -23,7 +23,7 @@
 #define EL_CHAR_QUOTEDBL               (EL_CHAR_ASCII0 + 34)
 #define EL_CHAR_NUMBERSIGN             (EL_CHAR_ASCII0 + 35)
 #define EL_CHAR_DOLLAR                 (EL_CHAR_ASCII0 + 36)
-#define EL_CHAR_PROCENT                        (EL_CHAR_ASCII0 + 37)
+#define EL_CHAR_PERCENT                        (EL_CHAR_ASCII0 + 37)
 #define EL_CHAR_AMPERSAND              (EL_CHAR_ASCII0 + 38)
 #define EL_CHAR_APOSTROPHE             (EL_CHAR_ASCII0 + 39)
 #define EL_CHAR_PARENLEFT              (EL_CHAR_ASCII0 + 40)
index 48c4401760a9a65724611d7c5a1ea6410aaa5f97..491ed8f8018db703e91ae359bf8e041a6b4fc98d 100644 (file)
@@ -109,10 +109,74 @@ element_to_graphic[] =
     EL_BD_BUTTERFLY,                   -1, -1, FALSE,
     IMG_BD_BUTTERFLY
   },
+  {
+    EL_BD_BUTTERFLY_RIGHT,             -1, -1, FALSE,
+    IMG_BD_BUTTERFLY_RIGHT
+  },
+  {
+    EL_BD_BUTTERFLY,                   -1, MV_BIT_RIGHT, FALSE,
+    IMG_BD_BUTTERFLY_RIGHT
+  },
+  {
+    EL_BD_BUTTERFLY_UP,                        -1, -1, FALSE,
+    IMG_BD_BUTTERFLY_UP
+  },
+  {
+    EL_BD_BUTTERFLY,                   -1, MV_BIT_UP, FALSE,
+    IMG_BD_BUTTERFLY_UP
+  },
+  {
+    EL_BD_BUTTERFLY_LEFT,              -1, -1, FALSE,
+    IMG_BD_BUTTERFLY_LEFT
+  },
+  {
+    EL_BD_BUTTERFLY,                   -1, MV_BIT_LEFT, FALSE,
+    IMG_BD_BUTTERFLY_LEFT
+  },
+  {
+    EL_BD_BUTTERFLY_DOWN,              -1, -1, FALSE,
+    IMG_BD_BUTTERFLY_DOWN
+  },
+  {
+    EL_BD_BUTTERFLY,                   -1, MV_BIT_DOWN, FALSE,
+    IMG_BD_BUTTERFLY_DOWN
+  },
   {
     EL_BD_FIREFLY,                     -1, -1, FALSE,
     IMG_BD_FIREFLY
   },
+  {
+    EL_BD_FIREFLY_RIGHT,               -1, -1, FALSE,
+    IMG_BD_FIREFLY_RIGHT
+  },
+  {
+    EL_BD_FIREFLY,                     -1, MV_BIT_RIGHT, FALSE,
+    IMG_BD_FIREFLY_RIGHT
+  },
+  {
+    EL_BD_FIREFLY_UP,                  -1, -1, FALSE,
+    IMG_BD_FIREFLY_UP
+  },
+  {
+    EL_BD_FIREFLY,                     -1, MV_BIT_UP, FALSE,
+    IMG_BD_FIREFLY_UP
+  },
+  {
+    EL_BD_FIREFLY_LEFT,                        -1, -1, FALSE,
+    IMG_BD_FIREFLY_LEFT
+  },
+  {
+    EL_BD_FIREFLY,                     -1, MV_BIT_LEFT, FALSE,
+    IMG_BD_FIREFLY_LEFT
+  },
+  {
+    EL_BD_FIREFLY_DOWN,                        -1, -1, FALSE,
+    IMG_BD_FIREFLY_DOWN
+  },
+  {
+    EL_BD_FIREFLY,                     -1, MV_BIT_DOWN, FALSE,
+    IMG_BD_FIREFLY_DOWN
+  },
   {
     EL_SP_DEFAULT,                     ACTION_EXPLODING, -1, FALSE,
     IMG_SP_DEFAULT_EXPLODING
@@ -1053,6 +1117,10 @@ element_to_graphic[] =
     EL_BALLOON_SWITCH_ANY,             -1, -1, FALSE,
     IMG_BALLOON_SWITCH_ANY
   },
+  {
+    EL_BALLOON_SWITCH_NONE,            -1, -1, FALSE,
+    IMG_BALLOON_SWITCH_NONE
+  },
   {
     EL_SPRING,                         -1, -1, FALSE,
     IMG_SPRING
@@ -1141,6 +1209,46 @@ element_to_graphic[] =
     EL_INVISIBLE_SAND,                 ACTION_ACTIVE, -1, FALSE,
     IMG_INVISIBLE_SAND_ACTIVE
   },
+  {
+    EL_INVISIBLE_SAND,                 ACTION_ACTIVE, -1, TRUE,
+    IMG_INVISIBLE_SAND_ACTIVE_CRUMBLED
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          -1, -1, TRUE,
+    IMG_INVISIBLE_SAND_ACTIVE_CRUMBLED
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_LEFT, FALSE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_RIGHT, FALSE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_UP, FALSE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_DOWN, FALSE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_LEFT, TRUE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT_CRUMBLED
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_RIGHT, TRUE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT_CRUMBLED
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_UP, TRUE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP_CRUMBLED
+  },
+  {
+    EL_INVISIBLE_SAND_ACTIVE,          ACTION_DIGGING, MV_BIT_DOWN, TRUE,
+    IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN_CRUMBLED
+  },
   {
     EL_CONVEYOR_BELT_1_MIDDLE,         -1, -1, FALSE,
     IMG_CONVEYOR_BELT_1_MIDDLE
@@ -2565,6 +2673,222 @@ element_to_graphic[] =
     EL_TRIGGER_PLAYER,                 -1, -1, FALSE,
     IMG_TRIGGER_PLAYER
   },
+  {
+    EL_EMC_KEY_5,                      -1, -1, FALSE,
+    IMG_EMC_KEY_5
+  },
+  {
+    EL_EMC_KEY_6,                      -1, -1, FALSE,
+    IMG_EMC_KEY_6
+  },
+  {
+    EL_EMC_KEY_7,                      -1, -1, FALSE,
+    IMG_EMC_KEY_7
+  },
+  {
+    EL_EMC_KEY_8,                      -1, -1, FALSE,
+    IMG_EMC_KEY_8
+  },
+  {
+    EL_EMC_GATE_5,                     -1, -1, FALSE,
+    IMG_EMC_GATE_5
+  },
+  {
+    EL_EMC_GATE_5_GRAY,                        -1, -1, FALSE,
+    IMG_EMC_GATE_5_GRAY
+  },
+  {
+    EL_EMC_GATE_6,                     -1, -1, FALSE,
+    IMG_EMC_GATE_6
+  },
+  {
+    EL_EMC_GATE_6_GRAY,                        -1, -1, FALSE,
+    IMG_EMC_GATE_6_GRAY
+  },
+  {
+    EL_EMC_GATE_7,                     -1, -1, FALSE,
+    IMG_EMC_GATE_7
+  },
+  {
+    EL_EMC_GATE_7_GRAY,                        -1, -1, FALSE,
+    IMG_EMC_GATE_7_GRAY
+  },
+  {
+    EL_EMC_GATE_8,                     -1, -1, FALSE,
+    IMG_EMC_GATE_8
+  },
+  {
+    EL_EMC_GATE_8_GRAY,                        -1, -1, FALSE,
+    IMG_EMC_GATE_8_GRAY
+  },
+  {
+    EL_EMC_ANDROID,                    -1, -1, FALSE,
+    IMG_EMC_ANDROID
+  },
+  {
+    EL_EMC_GRASS,                      -1, -1, FALSE,
+    IMG_EMC_GRASS
+  },
+  {
+    EL_EMC_GRASS,                      -1, -1, TRUE,
+    IMG_EMC_GRASS_CRUMBLED
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_LEFT, FALSE,
+    IMG_EMC_GRASS_DIGGING_LEFT
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_RIGHT, FALSE,
+    IMG_EMC_GRASS_DIGGING_RIGHT
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_UP, FALSE,
+    IMG_EMC_GRASS_DIGGING_UP
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_DOWN, FALSE,
+    IMG_EMC_GRASS_DIGGING_DOWN
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_LEFT, TRUE,
+    IMG_EMC_GRASS_DIGGING_LEFT_CRUMBLED
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_RIGHT, TRUE,
+    IMG_EMC_GRASS_DIGGING_RIGHT_CRUMBLED
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_UP, TRUE,
+    IMG_EMC_GRASS_DIGGING_UP_CRUMBLED
+  },
+  {
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_DOWN, TRUE,
+    IMG_EMC_GRASS_DIGGING_DOWN_CRUMBLED
+  },
+  {
+    EL_EMC_MAGIC_BALL,                 -1, -1, FALSE,
+    IMG_EMC_MAGIC_BALL
+  },
+  {
+    EL_EMC_MAGIC_BALL_ACTIVE,          -1, -1, FALSE,
+    IMG_EMC_MAGIC_BALL_ACTIVE
+  },
+  {
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1, FALSE,
+    IMG_EMC_MAGIC_BALL_ACTIVE
+  },
+  {
+    EL_EMC_MAGIC_BALL_SWITCH,          -1, -1, FALSE,
+    IMG_EMC_MAGIC_BALL_SWITCH
+  },
+  {
+    EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,   -1, -1, FALSE,
+    IMG_EMC_MAGIC_BALL_SWITCH_ACTIVE
+  },
+  {
+    EL_EMC_MAGIC_BALL_SWITCH,          ACTION_ACTIVE, -1, FALSE,
+    IMG_EMC_MAGIC_BALL_SWITCH_ACTIVE
+  },
+  {
+    EL_EMC_SPRING_BUMPER,              -1, -1, FALSE,
+    IMG_EMC_SPRING_BUMPER
+  },
+  {
+    EL_EMC_SPRING_BUMPER,              ACTION_ACTIVE, -1, FALSE,
+    IMG_EMC_SPRING_BUMPER_ACTIVE
+  },
+  {
+    EL_EMC_PLANT,                      -1, -1, FALSE,
+    IMG_EMC_PLANT
+  },
+  {
+    EL_EMC_PLANT,                      -1, -1, TRUE,
+    IMG_EMC_PLANT_CRUMBLED
+  },
+  {
+    EL_EMC_LENSES,                     -1, -1, FALSE,
+    IMG_EMC_LENSES
+  },
+  {
+    EL_EMC_MAGNIFIER,                  -1, -1, FALSE,
+    IMG_EMC_MAGNIFIER
+  },
+  {
+    EL_EMC_WALL_9,                     -1, -1, FALSE,
+    IMG_EMC_WALL_9
+  },
+  {
+    EL_EMC_WALL_10,                    -1, -1, FALSE,
+    IMG_EMC_WALL_10
+  },
+  {
+    EL_EMC_WALL_11,                    -1, -1, FALSE,
+    IMG_EMC_WALL_11
+  },
+  {
+    EL_EMC_WALL_12,                    -1, -1, FALSE,
+    IMG_EMC_WALL_12
+  },
+  {
+    EL_EMC_WALL_13,                    -1, -1, FALSE,
+    IMG_EMC_WALL_13
+  },
+  {
+    EL_EMC_WALL_14,                    -1, -1, FALSE,
+    IMG_EMC_WALL_14
+  },
+  {
+    EL_EMC_WALL_15,                    -1, -1, FALSE,
+    IMG_EMC_WALL_15
+  },
+  {
+    EL_EMC_WALL_16,                    -1, -1, FALSE,
+    IMG_EMC_WALL_16
+  },
+  {
+    EL_EMC_WALL_SLIPPERY_1,            -1, -1, FALSE,
+    IMG_EMC_WALL_SLIPPERY_1
+  },
+  {
+    EL_EMC_WALL_SLIPPERY_2,            -1, -1, FALSE,
+    IMG_EMC_WALL_SLIPPERY_2
+  },
+  {
+    EL_EMC_WALL_SLIPPERY_3,            -1, -1, FALSE,
+    IMG_EMC_WALL_SLIPPERY_3
+  },
+  {
+    EL_EMC_WALL_SLIPPERY_4,            -1, -1, FALSE,
+    IMG_EMC_WALL_SLIPPERY_4
+  },
+  {
+    EL_EMC_FAKE_GRASS,                 -1, -1, FALSE,
+    IMG_EMC_FAKE_GRASS
+  },
+  {
+    EL_EMC_FAKE_GRASS,                 -1, -1, TRUE,
+    IMG_EMC_FAKE_GRASS_CRUMBLED
+  },
+  {
+    EL_EMC_FAKE_GRASS,                 ACTION_ACTIVE, -1, FALSE,
+    IMG_EMC_FAKE_GRASS_ACTIVE
+  },
+  {
+    EL_EMC_FAKE_GRASS,                 ACTION_ACTIVE, -1, TRUE,
+    IMG_EMC_FAKE_GRASS_ACTIVE_CRUMBLED
+  },
+  {
+    EL_EMC_FAKE_ACID,                  -1, -1, FALSE,
+    IMG_EMC_FAKE_ACID
+  },
+  {
+    EL_EMC_DRIPPER,                    -1, -1, FALSE,
+    IMG_EMC_DRIPPER
+  },
+  {
+    EL_EMC_DRIPPER,                    ACTION_ACTIVE, -1, FALSE,
+    IMG_EMC_DRIPPER_ACTIVE
+  },
   {
     EL_BD_BUTTERFLY_DOWN,              -1, -1, FALSE,
     IMG_BD_BUTTERFLY
@@ -2678,8 +3002,8 @@ element_to_graphic[] =
     IMG_CHAR_DOLLAR
   },
   {
-    EL_CHAR_PROCENT,                   -1, -1, FALSE,
-    IMG_CHAR_PROCENT
+    EL_CHAR_PERCENT,                   -1, -1, FALSE,
+    IMG_CHAR_PERCENT
   },
   {
     EL_CHAR_AMPERSAND,                 -1, -1, FALSE,
index 1ffbe755c9987bc675f620b9260d88717f1afc61..825dc7a687bd840b147cfbcb18fa1498e5ab749e 100644 (file)
@@ -388,6 +388,10 @@ element_to_sound[] =
     EL_AMOEBA_DEAD, TRUE,                      ACTION_DROPPING,
     SND_CLASS_AMOEBA_DROPPING
   },
+  {
+    EL_ACID, FALSE,                            ACTION_SPLASHING,
+    SND_ACID_SPLASHING
+  },
   {
     EL_QUICKSAND_EMPTY, TRUE,                  ACTION_FILLING,
     SND_CLASS_QUICKSAND_FILLING
@@ -444,6 +448,22 @@ element_to_sound[] =
     EL_WALL, TRUE,                             ACTION_GROWING,
     SND_CLASS_WALL_GROWING
   },
+  {
+    EL_EMC_ANDROID, FALSE,                     ACTION_PUSHING,
+    SND_EMC_ANDROID_PUSHING
+  },
+  {
+    EL_EMC_ANDROID, FALSE,                     ACTION_MOVING,
+    SND_EMC_ANDROID_MOVING
+  },
+  {
+    EL_EMC_ANDROID, FALSE,                     ACTION_DROPPING,
+    SND_EMC_ANDROID_DROPPING
+  },
+  {
+    EL_EMC_MAGIC_BALL, FALSE,                  ACTION_DROPPING,
+    SND_EMC_MAGIC_BALL_DROPPING
+  },
   {
     EL_PEARL, FALSE,                           ACTION_COLLECTING,
     SND_PEARL_COLLECTING
@@ -484,6 +504,10 @@ element_to_sound[] =
     EL_INVISIBLE_SAND, FALSE,                  ACTION_DIGGING,
     SND_INVISIBLE_SAND_DIGGING
   },
+  {
+    EL_INVISIBLE_SAND_ACTIVE, FALSE,           ACTION_DIGGING,
+    SND_INVISIBLE_SAND_ACTIVE_DIGGING
+  },
   {
     EL_SHIELD_NORMAL, FALSE,                   ACTION_COLLECTING,
     SND_SHIELD_NORMAL_COLLECTING
index 540fe48fd92111a8280663cf7357ade832812b73..7ddf0510a8298f60f40d368254228eaea68551c7 100644 (file)
@@ -311,6 +311,26 @@ element_to_special_graphic[] =
     EL_INVISIBLE_STEELWALL_VERTICAL,           GFX_SPECIAL_ARG_EDITOR,
     IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR
   },
+  {
+    EL_EMC_GATE_5_GRAY,                                GFX_SPECIAL_ARG_EDITOR,
+    IMG_EMC_GATE_5_GRAY_EDITOR
+  },
+  {
+    EL_EMC_GATE_6_GRAY,                                GFX_SPECIAL_ARG_EDITOR,
+    IMG_EMC_GATE_6_GRAY_EDITOR
+  },
+  {
+    EL_EMC_GATE_7_GRAY,                                GFX_SPECIAL_ARG_EDITOR,
+    IMG_EMC_GATE_7_GRAY_EDITOR
+  },
+  {
+    EL_EMC_GATE_8_GRAY,                                GFX_SPECIAL_ARG_EDITOR,
+    IMG_EMC_GATE_8_GRAY_EDITOR
+  },
+  {
+    EL_EMC_DRIPPER,                            GFX_SPECIAL_ARG_EDITOR,
+    IMG_EMC_DRIPPER_EDITOR
+  },
   {
     EL_CUSTOM_1,                               GFX_SPECIAL_ARG_EDITOR,
     IMG_CUSTOM_1_EDITOR
index ada412c6c52b19b6b7dc0028bf31427fb30fa4fa..9aa3e6bbe9abb401875199a0d7964572eef92175 100644 (file)
@@ -19,7 +19,7 @@
    reliable default values. If that value is GFX_ARG_UNDEFINED, it will
    be dynamically determined, using some of the other list values. */
 
-struct ConfigInfo image_config_suffix[] =
+struct ConfigTypeInfo image_config_suffix[] =
 {
   { ".x",                              ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".y",                              ARG_UNDEFINED,  TYPE_INTEGER    },
@@ -27,10 +27,16 @@ struct ConfigInfo image_config_suffix[] =
   { ".ypos",                           ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".width",                          ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".height",                         ARG_UNDEFINED,  TYPE_INTEGER    },
-  { ".offset",                         ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".vertical",                       "false",        TYPE_BOOLEAN    },
+  { ".offset",                         ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".xoffset",                                ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".yoffset",                                ARG_UNDEFINED,  TYPE_INTEGER    },
+  { ".2nd_movement_tile",              "false",        TYPE_BOOLEAN    },
+  { ".2nd_vertical",                   ARG_UNDEFINED,  TYPE_BOOLEAN    },
+  { ".2nd_offset",                     ARG_UNDEFINED,  TYPE_INTEGER    },
+  { ".2nd_xoffset",                    ARG_UNDEFINED,  TYPE_INTEGER    },
+  { ".2nd_yoffset",                    ARG_UNDEFINED,  TYPE_INTEGER    },
+  { ".2nd_swap_tiles",                 ARG_UNDEFINED,  TYPE_BOOLEAN    },
   { ".frames",                         ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".frames_per_line",                        ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".start_frame",                    ARG_UNDEFINED,  TYPE_INTEGER    },
@@ -52,6 +58,7 @@ struct ConfigInfo image_config_suffix[] =
   { ".post_delay_fixed",               ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".post_delay_random",              ARG_UNDEFINED,  TYPE_INTEGER    },
   { ".name",                           ARG_UNDEFINED,  TYPE_STRING     },
+  { ".scale_up_factor",                        ARG_UNDEFINED,  TYPE_INTEGER    },
 
   { NULL,                              NULL,           0               }
 };
@@ -171,15 +178,43 @@ struct ConfigInfo image_config[] =
   { "bd_butterfly.anim_mode",                  "pingpong"              },
   { "bd_butterfly.delay",                      "4"                     },
   { "bd_butterfly.global_sync",                        "true"                  },
+  { "bd_butterfly.right",                      "RocksElements.pcx"     },
+  { "bd_butterfly.right.xpos",                 "4"                     },
+  { "bd_butterfly.right.ypos",                 "12"                    },
+  { "bd_butterfly.right.frames",               "2"                     },
+  { "bd_butterfly.right.anim_mode",            "pingpong"              },
+  { "bd_butterfly.right.delay",                        "4"                     },
+  { "bd_butterfly.right.global_sync",          "true"                  },
   { "bd_butterfly.right.EDITOR",               "RocksElements.pcx"     },
   { "bd_butterfly.right.EDITOR.xpos",          "8"                     },
   { "bd_butterfly.right.EDITOR.ypos",          "12"                    },
+  { "bd_butterfly.up",                         "RocksElements.pcx"     },
+  { "bd_butterfly.up.xpos",                    "4"                     },
+  { "bd_butterfly.up.ypos",                    "12"                    },
+  { "bd_butterfly.up.frames",                  "2"                     },
+  { "bd_butterfly.up.anim_mode",               "pingpong"              },
+  { "bd_butterfly.up.delay",                   "4"                     },
+  { "bd_butterfly.up.global_sync",             "true"                  },
   { "bd_butterfly.up.EDITOR",                  "RocksElements.pcx"     },
   { "bd_butterfly.up.EDITOR.xpos",             "9"                     },
   { "bd_butterfly.up.EDITOR.ypos",             "12"                    },
+  { "bd_butterfly.left",                       "RocksElements.pcx"     },
+  { "bd_butterfly.left.xpos",                  "4"                     },
+  { "bd_butterfly.left.ypos",                  "12"                    },
+  { "bd_butterfly.left.frames",                        "2"                     },
+  { "bd_butterfly.left.anim_mode",             "pingpong"              },
+  { "bd_butterfly.left.delay",                 "4"                     },
+  { "bd_butterfly.left.global_sync",           "true"                  },
   { "bd_butterfly.left.EDITOR",                        "RocksElements.pcx"     },
   { "bd_butterfly.left.EDITOR.xpos",           "10"                    },
   { "bd_butterfly.left.EDITOR.ypos",           "12"                    },
+  { "bd_butterfly.down",                       "RocksElements.pcx"     },
+  { "bd_butterfly.down.xpos",                  "4"                     },
+  { "bd_butterfly.down.ypos",                  "12"                    },
+  { "bd_butterfly.down.frames",                        "2"                     },
+  { "bd_butterfly.down.anim_mode",             "pingpong"              },
+  { "bd_butterfly.down.delay",                 "4"                     },
+  { "bd_butterfly.down.global_sync",           "true"                  },
   { "bd_butterfly.down.EDITOR",                        "RocksElements.pcx"     },
   { "bd_butterfly.down.EDITOR.xpos",           "11"                    },
   { "bd_butterfly.down.EDITOR.ypos",           "12"                    },
@@ -191,15 +226,43 @@ struct ConfigInfo image_config[] =
   { "bd_firefly.anim_mode",                    "pingpong"              },
   { "bd_firefly.delay",                                "4"                     },
   { "bd_firefly.global_sync",                  "true"                  },
+  { "bd_firefly.right",                                "RocksElements.pcx"     },
+  { "bd_firefly.right.xpos",                   "6"                     },
+  { "bd_firefly.right.ypos",                   "12"                    },
+  { "bd_firefly.right.frames",                 "2"                     },
+  { "bd_firefly.right.anim_mode",              "pingpong"              },
+  { "bd_firefly.right.delay",                  "4"                     },
+  { "bd_firefly.right.global_sync",            "true"                  },
   { "bd_firefly.right.EDITOR",                 "RocksElements.pcx"     },
   { "bd_firefly.right.EDITOR.xpos",            "12"                    },
   { "bd_firefly.right.EDITOR.ypos",            "12"                    },
+  { "bd_firefly.up",                           "RocksElements.pcx"     },
+  { "bd_firefly.up.xpos",                      "6"                     },
+  { "bd_firefly.up.ypos",                      "12"                    },
+  { "bd_firefly.up.frames",                    "2"                     },
+  { "bd_firefly.up.anim_mode",                 "pingpong"              },
+  { "bd_firefly.up.delay",                     "4"                     },
+  { "bd_firefly.up.global_sync",               "true"                  },
   { "bd_firefly.up.EDITOR",                    "RocksElements.pcx"     },
   { "bd_firefly.up.EDITOR.xpos",               "13"                    },
   { "bd_firefly.up.EDITOR.ypos",               "12"                    },
+  { "bd_firefly.left",                         "RocksElements.pcx"     },
+  { "bd_firefly.left.xpos",                    "6"                     },
+  { "bd_firefly.left.ypos",                    "12"                    },
+  { "bd_firefly.left.frames",                  "2"                     },
+  { "bd_firefly.left.anim_mode",               "pingpong"              },
+  { "bd_firefly.left.delay",                   "4"                     },
+  { "bd_firefly.left.global_sync",             "true"                  },
   { "bd_firefly.left.EDITOR",                  "RocksElements.pcx"     },
   { "bd_firefly.left.EDITOR.xpos",             "14"                    },
   { "bd_firefly.left.EDITOR.ypos",             "12"                    },
+  { "bd_firefly.down",                         "RocksElements.pcx"     },
+  { "bd_firefly.down.xpos",                    "6"                     },
+  { "bd_firefly.down.ypos",                    "12"                    },
+  { "bd_firefly.down.frames",                  "2"                     },
+  { "bd_firefly.down.anim_mode",               "pingpong"              },
+  { "bd_firefly.down.delay",                   "4"                     },
+  { "bd_firefly.down.global_sync",             "true"                  },
   { "bd_firefly.down.EDITOR",                  "RocksElements.pcx"     },
   { "bd_firefly.down.EDITOR.xpos",             "15"                    },
   { "bd_firefly.down.EDITOR.ypos",             "12"                    },
@@ -1388,6 +1451,10 @@ struct ConfigInfo image_config[] =
   { "balloon_switch_any.xpos",                 "15"                    },
   { "balloon_switch_any.ypos",                 "0"                     },
   { "balloon_switch_any.frames",               "1"                     },
+  { "balloon_switch_none",                     "RocksDC.pcx"           },
+  { "balloon_switch_none.xpos",                        "13"                    },
+  { "balloon_switch_none.ypos",                        "5"                     },
+  { "balloon_switch_none.frames",              "1"                     },
 
   { "spring",                                  "RocksDC.pcx"           },
   { "spring.xpos",                             "8"                     },
@@ -1398,17 +1465,17 @@ struct ConfigInfo image_config[] =
   { "emc_steelwall_1.xpos",                    "14"                    },
   { "emc_steelwall_1.ypos",                    "0"                     },
   { "emc_steelwall_1.frames",                  "1"                     },
-  { "emc_steelwall_2",                         "RocksDC.pcx"           },
-  { "emc_steelwall_2.xpos",                    "14"                    },
-  { "emc_steelwall_2.ypos",                    "0"                     },
+  { "emc_steelwall_2",                         "RocksEMC.pcx"          },
+  { "emc_steelwall_2.xpos",                    "9"                     },
+  { "emc_steelwall_2.ypos",                    "8"                     },
   { "emc_steelwall_2.frames",                  "1"                     },
-  { "emc_steelwall_3",                         "RocksDC.pcx"           },
-  { "emc_steelwall_3.xpos",                    "14"                    },
-  { "emc_steelwall_3.ypos",                    "0"                     },
+  { "emc_steelwall_3",                         "RocksEMC.pcx"          },
+  { "emc_steelwall_3.xpos",                    "9"                     },
+  { "emc_steelwall_3.ypos",                    "9"                     },
   { "emc_steelwall_3.frames",                  "1"                     },
-  { "emc_steelwall_4",                         "RocksDC.pcx"           },
-  { "emc_steelwall_4.xpos",                    "14"                    },
-  { "emc_steelwall_4.ypos",                    "0"                     },
+  { "emc_steelwall_4",                         "RocksEMC.pcx"          },
+  { "emc_steelwall_4.xpos",                    "9"                     },
+  { "emc_steelwall_4.ypos",                    "10"                    },
   { "emc_steelwall_4.frames",                  "1"                     },
 
   { "emc_wall_1",                              "RocksDC.pcx"           },
@@ -1439,9 +1506,9 @@ struct ConfigInfo image_config[] =
   { "emc_wall_7.xpos",                         "15"                    },
   { "emc_wall_7.ypos",                         "2"                     },
   { "emc_wall_7.frames",                       "1"                     },
-  { "emc_wall_8",                              "RocksDC.pcx"           },
-  { "emc_wall_8.xpos",                         "14"                    },
-  { "emc_wall_8.ypos",                         "1"                     },
+  { "emc_wall_8",                              "RocksEMC.pcx"          },
+  { "emc_wall_8.xpos",                         "8"                     },
+  { "emc_wall_8.ypos",                         "7"                     },
   { "emc_wall_8.frames",                       "1"                     },
 
   /* images for Diamond Caves style elements and actions */
@@ -1471,16 +1538,68 @@ struct ConfigInfo image_config[] =
   { "invisible_wall.active.frames",            "1"                     },
 
   { "invisible_sand",                          "RocksSP.pcx"           },
-  { "invisible_sand.xpos",                     "6"                     },
-  { "invisible_sand.ypos",                     "5"                     },
+  { "invisible_sand.xpos",                     "0"                     },
+  { "invisible_sand.ypos",                     "0"                     },
   { "invisible_sand.frames",                   "1"                     },
-  { "invisible_sand.EDITOR",                   "RocksSP.pcx"           },
+  { "invisible_sand.EDITOR",                   "RocksEMC.pcx"          },
   { "invisible_sand.EDITOR.xpos",              "2"                     },
-  { "invisible_sand.EDITOR.ypos",              "5"                     },
-  { "invisible_sand.active",                   "RocksSP.pcx"           },
+  { "invisible_sand.EDITOR.ypos",              "4"                     },
+  { "invisible_sand.active",                   "RocksEMC.pcx"          },
   { "invisible_sand.active.xpos",              "2"                     },
-  { "invisible_sand.active.ypos",              "5"                     },
+  { "invisible_sand.active.ypos",              "4"                     },
   { "invisible_sand.active.frames",            "1"                     },
+  { "invisible_sand.active.CRUMBLED",          "RocksEMC.pcx"          },
+  { "invisible_sand.active.CRUMBLED.xpos",     "3"                     },
+  { "invisible_sand.active.CRUMBLED.ypos",     "4"                     },
+  { "invisible_sand.active.CRUMBLED.frames",   "1"                     },
+  { "invisible_sand.active.digging.left",      "RocksEMC.pcx"          },
+  { "invisible_sand.active.digging.left.xpos", "6"                     },
+  { "invisible_sand.active.digging.left.ypos", "2"                     },
+  { "invisible_sand.active.digging.left.frames","3"                    },
+  { "invisible_sand.active.digging.left.delay",        "2"                     },
+  { "invisible_sand.active.digging.left.anim_mode","linear"            },
+  { "invisible_sand.active.digging.right",     "RocksEMC.pcx"          },
+  { "invisible_sand.active.digging.right.xpos",        "9"                     },
+  { "invisible_sand.active.digging.right.ypos",        "2"                     },
+  { "invisible_sand.active.digging.right.frames","3"                   },
+  { "invisible_sand.active.digging.right.delay","2"                    },
+  { "invisible_sand.active.digging.right.anim_mode","linear"           },
+  { "invisible_sand.active.digging.up",                "RocksEMC.pcx"          },
+  { "invisible_sand.active.digging.up.xpos",   "0"                     },
+  { "invisible_sand.active.digging.up.ypos",   "2"                     },
+  { "invisible_sand.active.digging.up.frames", "3"                     },
+  { "invisible_sand.active.digging.up.delay",  "2"                     },
+  { "invisible_sand.active.digging.up.anim_mode","linear"              },
+  { "invisible_sand.active.digging.down",      "RocksEMC.pcx"          },
+  { "invisible_sand.active.digging.down.xpos", "3"                     },
+  { "invisible_sand.active.digging.down.ypos", "2"                     },
+  { "invisible_sand.active.digging.down.frames","3"                    },
+  { "invisible_sand.active.digging.down.delay",        "2"                     },
+  { "invisible_sand.active.digging.down.anim_mode","linear"            },
+  { "invisible_sand.active.digging.left.CRUMBLED",     "RocksEMC.pcx"  },
+  { "invisible_sand.active.digging.left.CRUMBLED.xpos",        "6"             },
+  { "invisible_sand.active.digging.left.CRUMBLED.ypos",        "3"             },
+  { "invisible_sand.active.digging.left.CRUMBLED.frames","3"           },
+  { "invisible_sand.active.digging.left.CRUMBLED.delay","2"            },
+  { "invisible_sand.active.digging.left.CRUMBLED.anim_mode","linear"   },
+  { "invisible_sand.active.digging.right.CRUMBLED",    "RocksEMC.pcx"  },
+  { "invisible_sand.active.digging.right.CRUMBLED.xpos","9"            },
+  { "invisible_sand.active.digging.right.CRUMBLED.ypos","3"            },
+  { "invisible_sand.active.digging.right.CRUMBLED.frames","3"          },
+  { "invisible_sand.active.digging.right.CRUMBLED.delay","2"           },
+  { "invisible_sand.active.digging.right.CRUMBLED.anim_mode","linear"  },
+  { "invisible_sand.active.digging.up.CRUMBLED",       "RocksEMC.pcx"  },
+  { "invisible_sand.active.digging.up.CRUMBLED.xpos",  "0"             },
+  { "invisible_sand.active.digging.up.CRUMBLED.ypos",  "3"             },
+  { "invisible_sand.active.digging.up.CRUMBLED.frames",        "3"             },
+  { "invisible_sand.active.digging.up.CRUMBLED.delay", "2"             },
+  { "invisible_sand.active.digging.up.CRUMBLED.anim_mode","linear"     },
+  { "invisible_sand.active.digging.down.CRUMBLED",     "RocksEMC.pcx"  },
+  { "invisible_sand.active.digging.down.CRUMBLED.xpos",        "3"             },
+  { "invisible_sand.active.digging.down.CRUMBLED.ypos",        "3"             },
+  { "invisible_sand.active.digging.down.CRUMBLED.frames","3"           },
+  { "invisible_sand.active.digging.down.CRUMBLED.delay","2"            },
+  { "invisible_sand.active.digging.down.CRUMBLED.anim_mode","linear"   },
 
   { "conveyor_belt_1_middle",                  "RocksDC.pcx"           },
   { "conveyor_belt_1_middle.xpos",             "0"                     },
@@ -3216,6 +3335,267 @@ struct ConfigInfo image_config[] =
   { "trigger_player.ypos",                     "13"                    },
   { "trigger_player.frames",                   "1"                     },
 
+  { "emc_key_5",                               "RocksEMC.pcx"          },
+  { "emc_key_5.xpos",                          "0"                     },
+  { "emc_key_5.ypos",                          "5"                     },
+  { "emc_key_5.frames",                                "1"                     },
+  { "emc_key_6",                               "RocksEMC.pcx"          },
+  { "emc_key_6.xpos",                          "1"                     },
+  { "emc_key_6.ypos",                          "5"                     },
+  { "emc_key_6.frames",                                "1"                     },
+  { "emc_key_7",                               "RocksEMC.pcx"          },
+  { "emc_key_7.xpos",                          "2"                     },
+  { "emc_key_7.ypos",                          "5"                     },
+  { "emc_key_7.frames",                                "1"                     },
+  { "emc_key_8",                               "RocksEMC.pcx"          },
+  { "emc_key_8.xpos",                          "3"                     },
+  { "emc_key_8.ypos",                          "5"                     },
+  { "emc_key_8.frames",                                "1"                     },
+
+  { "emc_gate_5",                              "RocksEMC.pcx"          },
+  { "emc_gate_5.xpos",                         "0"                     },
+  { "emc_gate_5.ypos",                         "6"                     },
+  { "emc_gate_5.frames",                       "1"                     },
+  { "emc_gate_5_gray",                         "RocksEMC.pcx"          },
+  { "emc_gate_5_gray.xpos",                    "4"                     },
+  { "emc_gate_5_gray.ypos",                    "7"                     },
+  { "emc_gate_5_gray.frames",                  "1"                     },
+  { "emc_gate_5_gray.EDITOR",                  "RocksEMC.pcx"          },
+  { "emc_gate_5_gray.EDITOR.xpos",             "0"                     },
+  { "emc_gate_5_gray.EDITOR.ypos",             "7"                     },
+  { "emc_gate_6",                              "RocksEMC.pcx"          },
+  { "emc_gate_6.xpos",                         "1"                     },
+  { "emc_gate_6.ypos",                         "6"                     },
+  { "emc_gate_6.frames",                       "1"                     },
+  { "emc_gate_6_gray",                         "RocksEMC.pcx"          },
+  { "emc_gate_6_gray.xpos",                    "4"                     },
+  { "emc_gate_6_gray.ypos",                    "7"                     },
+  { "emc_gate_6_gray.frames",                  "1"                     },
+  { "emc_gate_6_gray.EDITOR",                  "RocksEMC.pcx"          },
+  { "emc_gate_6_gray.EDITOR.xpos",             "1"                     },
+  { "emc_gate_6_gray.EDITOR.ypos",             "7"                     },
+  { "emc_gate_7",                              "RocksEMC.pcx"          },
+  { "emc_gate_7.xpos",                         "2"                     },
+  { "emc_gate_7.ypos",                         "6"                     },
+  { "emc_gate_7.frames",                       "1"                     },
+  { "emc_gate_7_gray",                         "RocksEMC.pcx"          },
+  { "emc_gate_7_gray.xpos",                    "4"                     },
+  { "emc_gate_7_gray.ypos",                    "7"                     },
+  { "emc_gate_7_gray.frames",                  "1"                     },
+  { "emc_gate_7_gray.EDITOR",                  "RocksEMC.pcx"          },
+  { "emc_gate_7_gray.EDITOR.xpos",             "2"                     },
+  { "emc_gate_7_gray.EDITOR.ypos",             "7"                     },
+  { "emc_gate_8",                              "RocksEMC.pcx"          },
+  { "emc_gate_8.xpos",                         "3"                     },
+  { "emc_gate_8.ypos",                         "6"                     },
+  { "emc_gate_8.frames",                       "1"                     },
+  { "emc_gate_8_gray",                         "RocksEMC.pcx"          },
+  { "emc_gate_8_gray.xpos",                    "4"                     },
+  { "emc_gate_8_gray.ypos",                    "7"                     },
+  { "emc_gate_8_gray.frames",                  "1"                     },
+  { "emc_gate_8_gray.EDITOR",                  "RocksEMC.pcx"          },
+  { "emc_gate_8_gray.EDITOR.xpos",             "3"                     },
+  { "emc_gate_8_gray.EDITOR.ypos",             "7"                     },
+
+  { "emc_android",                             "RocksEMC.pcx"          },
+  { "emc_android.xpos",                                "0"                     },
+  { "emc_android.ypos",                                "8"                     },
+  { "emc_android.frames",                      "8"                     },
+
+  { "emc_grass",                               "RocksEMC.pcx"          },
+  { "emc_grass.xpos",                          "0"                     },
+  { "emc_grass.ypos",                          "4"                     },
+  { "emc_grass.frames",                                "1"                     },
+  { "emc_grass.CRUMBLED",                      "RocksEMC.pcx"          },
+  { "emc_grass.CRUMBLED.xpos",                 "1"                     },
+  { "emc_grass.CRUMBLED.ypos",                 "4"                     },
+  { "emc_grass.CRUMBLED.frames",               "1"                     },
+  { "emc_grass.digging.left",                  "RocksEMC.pcx"          },
+  { "emc_grass.digging.left.xpos",             "6"                     },
+  { "emc_grass.digging.left.ypos",             "0"                     },
+  { "emc_grass.digging.left.frames",           "3"                     },
+  { "emc_grass.digging.left.delay",            "2"                     },
+  { "emc_grass.digging.left.anim_mode",                "linear"                },
+  { "emc_grass.digging.right",                 "RocksEMC.pcx"          },
+  { "emc_grass.digging.right.xpos",            "9"                     },
+  { "emc_grass.digging.right.ypos",            "0"                     },
+  { "emc_grass.digging.right.frames",          "3"                     },
+  { "emc_grass.digging.right.delay",           "2"                     },
+  { "emc_grass.digging.right.anim_mode",       "linear"                },
+  { "emc_grass.digging.up",                    "RocksEMC.pcx"          },
+  { "emc_grass.digging.up.xpos",               "0"                     },
+  { "emc_grass.digging.up.ypos",               "0"                     },
+  { "emc_grass.digging.up.frames",             "3"                     },
+  { "emc_grass.digging.up.delay",              "2"                     },
+  { "emc_grass.digging.up.anim_mode",          "linear"                },
+  { "emc_grass.digging.down",                  "RocksEMC.pcx"          },
+  { "emc_grass.digging.down.xpos",             "3"                     },
+  { "emc_grass.digging.down.ypos",             "0"                     },
+  { "emc_grass.digging.down.frames",           "3"                     },
+  { "emc_grass.digging.down.delay",            "2"                     },
+  { "emc_grass.digging.down.anim_mode",                "linear"                },
+  { "emc_grass.digging.left.CRUMBLED",         "RocksEMC.pcx"          },
+  { "emc_grass.digging.left.CRUMBLED.xpos",    "6"                     },
+  { "emc_grass.digging.left.CRUMBLED.ypos",    "1"                     },
+  { "emc_grass.digging.left.CRUMBLED.frames",  "3"                     },
+  { "emc_grass.digging.left.CRUMBLED.delay",   "2"                     },
+  { "emc_grass.digging.left.CRUMBLED.anim_mode","linear"               },
+  { "emc_grass.digging.right.CRUMBLED",                "RocksEMC.pcx"          },
+  { "emc_grass.digging.right.CRUMBLED.xpos",   "9"                     },
+  { "emc_grass.digging.right.CRUMBLED.ypos",   "1"                     },
+  { "emc_grass.digging.right.CRUMBLED.frames", "3"                     },
+  { "emc_grass.digging.right.CRUMBLED.delay",  "2"                     },
+  { "emc_grass.digging.right.CRUMBLED.anim_mode","linear"              },
+  { "emc_grass.digging.up.CRUMBLED",           "RocksEMC.pcx"          },
+  { "emc_grass.digging.up.CRUMBLED.xpos",      "0"                     },
+  { "emc_grass.digging.up.CRUMBLED.ypos",      "1"                     },
+  { "emc_grass.digging.up.CRUMBLED.frames",    "3"                     },
+  { "emc_grass.digging.up.CRUMBLED.delay",     "2"                     },
+  { "emc_grass.digging.up.CRUMBLED.anim_mode", "linear"                },
+  { "emc_grass.digging.down.CRUMBLED",         "RocksEMC.pcx"          },
+  { "emc_grass.digging.down.CRUMBLED.xpos",    "3"                     },
+  { "emc_grass.digging.down.CRUMBLED.ypos",    "1"                     },
+  { "emc_grass.digging.down.CRUMBLED.frames",  "3"                     },
+  { "emc_grass.digging.down.CRUMBLED.delay",   "2"                     },
+  { "emc_grass.digging.down.CRUMBLED.anim_mode","linear"               },
+
+  { "emc_magic_ball",                          "RocksEMC.pcx"          },
+  { "emc_magic_ball.xpos",                     "0"                     },
+  { "emc_magic_ball.ypos",                     "9"                     },
+  { "emc_magic_ball.frames",                   "1"                     },
+
+  { "emc_magic_ball.active",                   "RocksEMC.pcx"          },
+  { "emc_magic_ball.active.xpos",              "0"                     },
+  { "emc_magic_ball.active.ypos",              "9"                     },
+  { "emc_magic_ball.active.frames",            "16"                    },
+  { "emc_magic_ball.active.frames_per_line",   "8"                     },
+
+  { "emc_magic_ball_switch",                   "RocksEMC.pcx"          },
+  { "emc_magic_ball_switch.xpos",              "8"                     },
+  { "emc_magic_ball_switch.ypos",              "10"                    },
+  { "emc_magic_ball_switch.frames",            "1"                     },
+
+  { "emc_magic_ball_switch.active",            "RocksEMC.pcx"          },
+  { "emc_magic_ball_switch.active.xpos",       "8"                     },
+  { "emc_magic_ball_switch.active.ypos",       "9"                     },
+  { "emc_magic_ball_switch.active.frames",     "1"                     },
+
+  { "emc_spring_bumper",                       "RocksEMC.pcx"          },
+  { "emc_spring_bumper.xpos",                  "8"                     },
+  { "emc_spring_bumper.ypos",                  "4"                     },
+  { "emc_spring_bumper.frames",                        "1"                     },
+
+  { "emc_spring_bumper.active",                        "RocksEMC.pcx"          },
+  { "emc_spring_bumper.active.xpos",           "8"                     },
+  { "emc_spring_bumper.active.ypos",           "4"                     },
+  { "emc_spring_bumper.active.frames",         "4"                     },
+  { "emc_spring_bumper.active.anim_mode",      "pingpong2"             },
+
+  { "emc_plant",                               "RocksEMC.pcx"          },
+  { "emc_plant.xpos",                          "4"                     },
+  { "emc_plant.ypos",                          "4"                     },
+  { "emc_plant.frames",                                "1"                     },
+  { "emc_plant.CRUMBLED",                      "RocksEMC.pcx"          },
+  { "emc_plant.CRUMBLED.xpos",                 "5"                     },
+  { "emc_plant.CRUMBLED.ypos",                 "4"                     },
+  { "emc_plant.CRUMBLED.frames",               "1"                     },
+
+  { "emc_lenses",                              "RocksEMC.pcx"          },
+  { "emc_lenses.xpos",                         "6"                     },
+  { "emc_lenses.ypos",                         "4"                     },
+  { "emc_lenses.frames",                       "1"                     },
+
+  { "emc_magnifier",                           "RocksEMC.pcx"          },
+  { "emc_magnifier.xpos",                      "7"                     },
+  { "emc_magnifier.ypos",                      "4"                     },
+  { "emc_magnifier.frames",                    "1"                     },
+
+  { "emc_wall_9",                              "RocksEMC.pcx"          },
+  { "emc_wall_9.xpos",                         "10"                    },
+  { "emc_wall_9.ypos",                         "5"                     },
+  { "emc_wall_9.frames",                       "1"                     },
+  { "emc_wall_10",                             "RocksEMC.pcx"          },
+  { "emc_wall_10.xpos",                                "10"                    },
+  { "emc_wall_10.ypos",                                "6"                     },
+  { "emc_wall_10.frames",                      "1"                     },
+  { "emc_wall_11",                             "RocksEMC.pcx"          },
+  { "emc_wall_11.xpos",                                "11"                    },
+  { "emc_wall_11.ypos",                                "5"                     },
+  { "emc_wall_11.frames",                      "1"                     },
+  { "emc_wall_12",                             "RocksEMC.pcx"          },
+  { "emc_wall_12.xpos",                                "11"                    },
+  { "emc_wall_12.ypos",                                "6"                     },
+  { "emc_wall_12.frames",                      "1"                     },
+  { "emc_wall_13",                             "RocksEMC.pcx"          },
+  { "emc_wall_13.xpos",                                "10"                    },
+  { "emc_wall_13.ypos",                                "7"                     },
+  { "emc_wall_13.frames",                      "1"                     },
+  { "emc_wall_14",                             "RocksEMC.pcx"          },
+  { "emc_wall_14.xpos",                                "10"                    },
+  { "emc_wall_14.ypos",                                "8"                     },
+  { "emc_wall_14.frames",                      "1"                     },
+  { "emc_wall_15",                             "RocksEMC.pcx"          },
+  { "emc_wall_15.xpos",                                "10"                    },
+  { "emc_wall_15.ypos",                                "9"                     },
+  { "emc_wall_15.frames",                      "1"                     },
+  { "emc_wall_16",                             "RocksEMC.pcx"          },
+  { "emc_wall_16.xpos",                                "10"                    },
+  { "emc_wall_16.ypos",                                "10"                    },
+  { "emc_wall_16.frames",                      "1"                     },
+
+  { "emc_wall_slippery_1",                     "RocksEMC.pcx"          },
+  { "emc_wall_slippery_1.xpos",                        "11"                    },
+  { "emc_wall_slippery_1.ypos",                        "7"                     },
+  { "emc_wall_slippery_1.frames",              "1"                     },
+  { "emc_wall_slippery_2",                     "RocksEMC.pcx"          },
+  { "emc_wall_slippery_2.xpos",                        "11"                    },
+  { "emc_wall_slippery_2.ypos",                        "8"                     },
+  { "emc_wall_slippery_2.frames",              "1"                     },
+  { "emc_wall_slippery_3",                     "RocksEMC.pcx"          },
+  { "emc_wall_slippery_3.xpos",                        "11"                    },
+  { "emc_wall_slippery_3.ypos",                        "9"                     },
+  { "emc_wall_slippery_3.frames",              "1"                     },
+  { "emc_wall_slippery_4",                     "RocksEMC.pcx"          },
+  { "emc_wall_slippery_4.xpos",                        "11"                    },
+  { "emc_wall_slippery_4.ypos",                        "10"                    },
+  { "emc_wall_slippery_4.frames",              "1"                     },
+
+  { "emc_fake_grass",                          "RocksEMC.pcx"          },
+  { "emc_fake_grass.xpos",                     "0"                     },
+  { "emc_fake_grass.ypos",                     "4"                     },
+  { "emc_fake_grass.frames",                   "1"                     },
+  { "emc_fake_grass.CRUMBLED",                 "RocksEMC.pcx"          },
+  { "emc_fake_grass.CRUMBLED.xpos",            "1"                     },
+  { "emc_fake_grass.CRUMBLED.ypos",            "4"                     },
+  { "emc_fake_grass.CRUMBLED.frames",          "1"                     },
+  { "emc_fake_grass.active",                   "RocksEMC.pcx"          },
+  { "emc_fake_grass.active.xpos",              "2"                     },
+  { "emc_fake_grass.active.ypos",              "4"                     },
+  { "emc_fake_grass.active.frames",            "1"                     },
+  { "emc_fake_grass.active.CRUMBLED",          "RocksEMC.pcx"          },
+  { "emc_fake_grass.active.CRUMBLED.xpos",     "3"                     },
+  { "emc_fake_grass.active.CRUMBLED.ypos",     "4"                     },
+  { "emc_fake_grass.active.CRUMBLED.frames",   "1"                     },
+
+  { "emc_fake_acid",                           "RocksElements.pcx"     },
+  { "emc_fake_acid.xpos",                      "12"                    },
+  { "emc_fake_acid.ypos",                      "7"                     },
+  { "emc_fake_acid.frames",                    "4"                     },
+  { "emc_fake_acid.delay",                     "10"                    },
+  { "emc_fake_acid.global_sync",               "true"                  },
+
+  { "emc_dripper",                             "RocksSP.pcx"           },
+  { "emc_dripper.xpos",                                "0"                     },
+  { "emc_dripper.ypos",                                "0"                     },
+  { "emc_dripper.frames",                      "1"                     },
+  { "emc_dripper.EDITOR",                      "RocksEMC.pcx"          },
+  { "emc_dripper.EDITOR.xpos",                 "8"                     },
+  { "emc_dripper.EDITOR.ypos",                 "8"                     },
+  { "emc_dripper.active",                      "RocksEMC.pcx"          },
+  { "emc_dripper.active.xpos",                 "8"                     },
+  { "emc_dripper.active.ypos",                 "8"                     },
+  { "emc_dripper.active.frames",               "1"                     },
+
 #include "conf_chr.c"  /* include auto-generated data structure definitions */
 #include "conf_cus.c"  /* include auto-generated data structure definitions */
 #include "conf_grp.c"  /* include auto-generated data structure definitions */
@@ -3223,6 +3603,22 @@ struct ConfigInfo image_config[] =
   /* images not associated to game elements (used for menu screens etc.) */
   /* keyword to stop parser: "NO_MORE_ELEMENT_IMAGES" <-- do not change! */
 
+#if 1
+  /* !!! TEMPORARILY STORED HERE -- PROBABLY TO BE CHANGED !!! */
+
+  /* (for testing, change filename back to "emc_object dot pcx") */
+  { "emc_object",                              "RocksEMC.pcx"          },
+#if 0
+  { "emc_object.scale_up_factor",              "2"                     },
+#endif
+
+  /* (for testing, change filename back to "emc_sprite dot pcx") */
+  { "emc_sprite",                              "RocksEMC.pcx"          },
+#if 0
+  { "emc_sprite.scale_up_factor",              "2"                     },
+#endif
+#endif
+
   { "toon_1",                                  "RocksToons.pcx"        },
   { "toon_1.x",                                        "2"                     },
   { "toon_1.y",                                        "72"                    },
index 697d8fbea657ed93f5c7cb38c4cad7c953e3c084..2d2cc45f745440fbea994ff460ce5e467ae867e0 100644 (file)
 #define IMG_BD_AMOEBA                                  17
 #define IMG_BD_AMOEBA_EDITOR                           18
 #define IMG_BD_BUTTERFLY                               19
-#define IMG_BD_BUTTERFLY_RIGHT_EDITOR                  20
-#define IMG_BD_BUTTERFLY_UP_EDITOR                     21
-#define IMG_BD_BUTTERFLY_LEFT_EDITOR                   22
-#define IMG_BD_BUTTERFLY_DOWN_EDITOR                   23
-#define IMG_BD_FIREFLY                                 24
-#define IMG_BD_FIREFLY_RIGHT_EDITOR                    25
-#define IMG_BD_FIREFLY_UP_EDITOR                       26
-#define IMG_BD_FIREFLY_LEFT_EDITOR                     27
-#define IMG_BD_FIREFLY_DOWN_EDITOR                     28
-#define IMG_SP_DEFAULT_EXPLODING                       29
-#define IMG_SP_ZONK                                    30
-#define IMG_SP_ZONK_MOVING_LEFT                                31
-#define IMG_SP_ZONK_MOVING_RIGHT                       32
-#define IMG_SP_ZONK_PUSHING_LEFT                       33
-#define IMG_SP_ZONK_PUSHING_RIGHT                      34
-#define IMG_SP_BASE                                    35
-#define IMG_SP_MURPHY                                  36
-#define IMG_SP_MURPHY_MOVING_LEFT                      37
-#define IMG_SP_MURPHY_MOVING_RIGHT                     38
-#define IMG_SP_MURPHY_DIGGING_LEFT                     39
-#define IMG_SP_MURPHY_DIGGING_RIGHT                    40
-#define IMG_SP_MURPHY_COLLECTING_LEFT                  41
-#define IMG_SP_MURPHY_COLLECTING_RIGHT                 42
-#define IMG_SP_MURPHY_PUSHING_LEFT                     43
-#define IMG_SP_MURPHY_PUSHING_RIGHT                    44
-#define IMG_SP_MURPHY_SNAPPING_LEFT                    45
-#define IMG_SP_MURPHY_SNAPPING_RIGHT                   46
-#define IMG_SP_MURPHY_SNAPPING_UP                      47
-#define IMG_SP_MURPHY_SNAPPING_DOWN                    48
-#define IMG_SP_MURPHY_CLONE                            49
-#define IMG_SP_INFOTRON                                        50
-#define IMG_SP_INFOTRON_EDITOR                         51
-#define IMG_SP_CHIP_SINGLE                             52
-#define IMG_SP_CHIP_LEFT                               53
-#define IMG_SP_CHIP_RIGHT                              54
-#define IMG_SP_CHIP_TOP                                        55
-#define IMG_SP_CHIP_BOTTOM                             56
-#define IMG_SP_HARDWARE_GRAY                           57
-#define IMG_SP_HARDWARE_GREEN                          58
-#define IMG_SP_HARDWARE_BLUE                           59
-#define IMG_SP_HARDWARE_RED                            60
-#define IMG_SP_HARDWARE_YELLOW                         61
-#define IMG_SP_EXIT_CLOSED                             62
-#define IMG_SP_EXIT_OPENING                            63
-#define IMG_SP_EXIT_OPEN                               64
-#define IMG_SP_EXIT_CLOSING                            65
-#define IMG_SP_DISK_ORANGE                             66
-#define IMG_SP_DISK_YELLOW                             67
-#define IMG_SP_DISK_RED                                        68
-#define IMG_SP_DISK_RED_COLLECTING                     69
-#define IMG_SP_DISK_RED_ACTIVE                         70
-#define IMG_SP_PORT_RIGHT                              71
-#define IMG_SP_PORT_DOWN                               72
-#define IMG_SP_PORT_LEFT                               73
-#define IMG_SP_PORT_UP                                 74
-#define IMG_SP_PORT_HORIZONTAL                         75
-#define IMG_SP_PORT_VERTICAL                           76
-#define IMG_SP_PORT_ANY                                        77
-#define IMG_SP_GRAVITY_PORT_RIGHT                      78
-#define IMG_SP_GRAVITY_PORT_RIGHT_EDITOR               79
-#define IMG_SP_GRAVITY_PORT_DOWN                       80
-#define IMG_SP_GRAVITY_PORT_DOWN_EDITOR                        81
-#define IMG_SP_GRAVITY_PORT_LEFT                       82
-#define IMG_SP_GRAVITY_PORT_LEFT_EDITOR                        83
-#define IMG_SP_GRAVITY_PORT_UP                         84
-#define IMG_SP_GRAVITY_PORT_UP_EDITOR                  85
-#define IMG_SP_GRAVITY_ON_PORT_RIGHT                   86
-#define IMG_SP_GRAVITY_ON_PORT_RIGHT_EDITOR            87
-#define IMG_SP_GRAVITY_ON_PORT_DOWN                    88
-#define IMG_SP_GRAVITY_ON_PORT_DOWN_EDITOR             89
-#define IMG_SP_GRAVITY_ON_PORT_LEFT                    90
-#define IMG_SP_GRAVITY_ON_PORT_LEFT_EDITOR             91
-#define IMG_SP_GRAVITY_ON_PORT_UP                      92
-#define IMG_SP_GRAVITY_ON_PORT_UP_EDITOR               93
-#define IMG_SP_GRAVITY_OFF_PORT_RIGHT                  94
-#define IMG_SP_GRAVITY_OFF_PORT_RIGHT_EDITOR           95
-#define IMG_SP_GRAVITY_OFF_PORT_DOWN                   96
-#define IMG_SP_GRAVITY_OFF_PORT_DOWN_EDITOR            97
-#define IMG_SP_GRAVITY_OFF_PORT_LEFT                   98
-#define IMG_SP_GRAVITY_OFF_PORT_LEFT_EDITOR            99
-#define IMG_SP_GRAVITY_OFF_PORT_UP                     100
-#define IMG_SP_GRAVITY_OFF_PORT_UP_EDITOR              101
-#define IMG_SP_SNIKSNAK                                        102
-#define IMG_SP_SNIKSNAK_LEFT                           103
-#define IMG_SP_SNIKSNAK_RIGHT                          104
-#define IMG_SP_SNIKSNAK_UP                             105
-#define IMG_SP_SNIKSNAK_DOWN                           106
-#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP           107
-#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN         108
-#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP          109
-#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN                110
-#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT           111
-#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT          112
-#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT         113
-#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT                114
-#define IMG_SP_ELECTRON                                        115
-#define IMG_SP_ELECTRON_EDITOR                         116
-#define IMG_SP_ELECTRON_EXPLODING                      117
-#define IMG_SP_TERMINAL                                        118
-#define IMG_SP_TERMINAL_EDITOR                         119
-#define IMG_SP_TERMINAL_ACTIVE                         120
-#define IMG_SP_BUGGY_BASE                              121
-#define IMG_SP_BUGGY_BASE_EDITOR                       122
-#define IMG_SP_BUGGY_BASE_ACTIVATING                   123
-#define IMG_SP_BUGGY_BASE_ACTIVE                       124
-#define IMG_SP_HARDWARE_BASE_1                         125
-#define IMG_SP_HARDWARE_BASE_2                         126
-#define IMG_SP_HARDWARE_BASE_3                         127
-#define IMG_SP_HARDWARE_BASE_4                         128
-#define IMG_SP_HARDWARE_BASE_5                         129
-#define IMG_SP_HARDWARE_BASE_6                         130
-#define IMG_SOKOBAN_OBJECT                             131
-#define IMG_SOKOBAN_OBJECT_EDITOR                      132
-#define IMG_SOKOBAN_FIELD_EMPTY                                133
-#define IMG_SOKOBAN_FIELD_FULL                         134
-#define IMG_SOKOBAN_FIELD_PLAYER                       135
-#define IMG_SOKOBAN_FIELD_PLAYER_EDITOR                        136
-#define IMG_EMPTY_SPACE                                        137
-#define IMG_SAND                                       138
-#define IMG_SAND_CRUMBLED                              139
-#define IMG_SAND_DIGGING_LEFT                          140
-#define IMG_SAND_DIGGING_RIGHT                         141
-#define IMG_SAND_DIGGING_UP                            142
-#define IMG_SAND_DIGGING_DOWN                          143
-#define IMG_SAND_DIGGING_LEFT_CRUMBLED                 144
-#define IMG_SAND_DIGGING_RIGHT_CRUMBLED                        145
-#define IMG_SAND_DIGGING_UP_CRUMBLED                   146
-#define IMG_SAND_DIGGING_DOWN_CRUMBLED                 147
-#define IMG_WALL                                       148
-#define IMG_WALL_SLIPPERY                              149
-#define IMG_STEELWALL                                  150
-#define IMG_ROCK                                       151
-#define IMG_ROCK_MOVING_LEFT                           152
-#define IMG_ROCK_MOVING_RIGHT                          153
-#define IMG_ROCK_PUSHING_LEFT                          154
-#define IMG_ROCK_PUSHING_RIGHT                         155
-#define IMG_EMERALD                                    156
-#define IMG_EMERALD_MOVING                             157
-#define IMG_EMERALD_FALLING                            158
-#define IMG_EMERALD_COLLECTING                         159
-#define IMG_DIAMOND                                    160
-#define IMG_DIAMOND_MOVING                             161
-#define IMG_DIAMOND_FALLING                            162
-#define IMG_DIAMOND_COLLECTING                         163
-#define IMG_BOMB                                       164
-#define IMG_NUT                                                165
-#define IMG_NUT_BREAKING                               166
-#define IMG_DYNAMITE                                   167
-#define IMG_DYNAMITE_EDITOR                            168
-#define IMG_DYNAMITE_ACTIVE                            169
-#define IMG_DYNAMITE_ACTIVE_EDITOR                     170
-#define IMG_WALL_EMERALD                               171
-#define IMG_WALL_DIAMOND                               172
-#define IMG_BUG                                                173
-#define IMG_BUG_RIGHT                                  174
-#define IMG_BUG_UP                                     175
-#define IMG_BUG_LEFT                                   176
-#define IMG_BUG_DOWN                                   177
-#define IMG_BUG_MOVING_RIGHT                           178
-#define IMG_BUG_MOVING_UP                              179
-#define IMG_BUG_MOVING_LEFT                            180
-#define IMG_BUG_MOVING_DOWN                            181
-#define IMG_BUG_TURNING_FROM_RIGHT_UP                  182
-#define IMG_BUG_TURNING_FROM_UP_LEFT                   183
-#define IMG_BUG_TURNING_FROM_LEFT_DOWN                 184
-#define IMG_BUG_TURNING_FROM_DOWN_RIGHT                        185
-#define IMG_BUG_TURNING_FROM_RIGHT_DOWN                        186
-#define IMG_BUG_TURNING_FROM_UP_RIGHT                  187
-#define IMG_BUG_TURNING_FROM_LEFT_UP                   188
-#define IMG_BUG_TURNING_FROM_DOWN_LEFT                 189
-#define IMG_SPACESHIP                                  190
-#define IMG_SPACESHIP_RIGHT                            191
-#define IMG_SPACESHIP_UP                               192
-#define IMG_SPACESHIP_LEFT                             193
-#define IMG_SPACESHIP_DOWN                             194
-#define IMG_SPACESHIP_MOVING_RIGHT                     195
-#define IMG_SPACESHIP_MOVING_UP                                196
-#define IMG_SPACESHIP_MOVING_LEFT                      197
-#define IMG_SPACESHIP_MOVING_DOWN                      198
-#define IMG_SPACESHIP_TURNING_FROM_RIGHT_UP            199
-#define IMG_SPACESHIP_TURNING_FROM_UP_LEFT             200
-#define IMG_SPACESHIP_TURNING_FROM_LEFT_DOWN           201
-#define IMG_SPACESHIP_TURNING_FROM_DOWN_RIGHT          202
-#define IMG_SPACESHIP_TURNING_FROM_RIGHT_DOWN          203
-#define IMG_SPACESHIP_TURNING_FROM_UP_RIGHT            204
-#define IMG_SPACESHIP_TURNING_FROM_LEFT_UP             205
-#define IMG_SPACESHIP_TURNING_FROM_DOWN_LEFT           206
-#define IMG_YAMYAM                                     207
-#define IMG_YAMYAM_MOVING                              208
-#define IMG_ROBOT                                      209
-#define IMG_ROBOT_MOVING                               210
-#define IMG_ROBOT_WHEEL                                        211
-#define IMG_ROBOT_WHEEL_ACTIVE                         212
-#define IMG_MAGIC_WALL                                 213
-#define IMG_MAGIC_WALL_ACTIVE                          214
-#define IMG_MAGIC_WALL_FILLING                         215
-#define IMG_MAGIC_WALL_FULL                            216
-#define IMG_MAGIC_WALL_EMPTYING                                217
-#define IMG_MAGIC_WALL_DEAD                            218
-#define IMG_QUICKSAND_EMPTY                            219
-#define IMG_QUICKSAND_FILLING                          220
-#define IMG_QUICKSAND_FULL                             221
-#define IMG_QUICKSAND_FULL_EDITOR                      222
-#define IMG_QUICKSAND_EMPTYING                         223
-#define IMG_ACID_POOL_TOPLEFT                          224
-#define IMG_ACID_POOL_TOPRIGHT                         225
-#define IMG_ACID_POOL_BOTTOMLEFT                       226
-#define IMG_ACID_POOL_BOTTOM                           227
-#define IMG_ACID_POOL_BOTTOMRIGHT                      228
-#define IMG_ACID                                       229
-#define IMG_ACID_SPLASH_LEFT                           230
-#define IMG_ACID_SPLASH_RIGHT                          231
-#define IMG_AMOEBA_DROP                                        232
-#define IMG_AMOEBA_GROWING                             233
-#define IMG_AMOEBA_SHRINKING                           234
-#define IMG_AMOEBA_WET                                 235
-#define IMG_AMOEBA_WET_EDITOR                          236
-#define IMG_AMOEBA_DROPPING                            237
-#define IMG_AMOEBA_DRY                                 238
-#define IMG_AMOEBA_FULL                                        239
-#define IMG_AMOEBA_FULL_EDITOR                         240
-#define IMG_AMOEBA_DEAD                                        241
-#define IMG_AMOEBA_DEAD_EDITOR                         242
-#define IMG_EM_KEY_1                                   243
-#define IMG_EM_KEY_2                                   244
-#define IMG_EM_KEY_3                                   245
-#define IMG_EM_KEY_4                                   246
-#define IMG_EM_GATE_1                                  247
-#define IMG_EM_GATE_2                                  248
-#define IMG_EM_GATE_3                                  249
-#define IMG_EM_GATE_4                                  250
-#define IMG_EM_GATE_1_GRAY                             251
-#define IMG_EM_GATE_1_GRAY_EDITOR                      252
-#define IMG_EM_GATE_2_GRAY                             253
-#define IMG_EM_GATE_2_GRAY_EDITOR                      254
-#define IMG_EM_GATE_3_GRAY                             255
-#define IMG_EM_GATE_3_GRAY_EDITOR                      256
-#define IMG_EM_GATE_4_GRAY                             257
-#define IMG_EM_GATE_4_GRAY_EDITOR                      258
-#define IMG_EXIT_CLOSED                                        259
-#define IMG_EXIT_OPENING                               260
-#define IMG_EXIT_OPEN                                  261
-#define IMG_EXIT_CLOSING                               262
-#define IMG_BALLOON                                    263
-#define IMG_BALLOON_MOVING                             264
-#define IMG_BALLOON_PUSHING                            265
-#define IMG_BALLOON_SWITCH_LEFT                                266
-#define IMG_BALLOON_SWITCH_RIGHT                       267
-#define IMG_BALLOON_SWITCH_UP                          268
-#define IMG_BALLOON_SWITCH_DOWN                                269
-#define IMG_BALLOON_SWITCH_ANY                         270
-#define IMG_SPRING                                     271
-#define IMG_EMC_STEELWALL_1                            272
-#define IMG_EMC_STEELWALL_2                            273
-#define IMG_EMC_STEELWALL_3                            274
-#define IMG_EMC_STEELWALL_4                            275
-#define IMG_EMC_WALL_1                                 276
-#define IMG_EMC_WALL_2                                 277
-#define IMG_EMC_WALL_3                                 278
-#define IMG_EMC_WALL_4                                 279
-#define IMG_EMC_WALL_5                                 280
-#define IMG_EMC_WALL_6                                 281
-#define IMG_EMC_WALL_7                                 282
-#define IMG_EMC_WALL_8                                 283
-#define IMG_INVISIBLE_STEELWALL                                284
-#define IMG_INVISIBLE_STEELWALL_EDITOR                 285
-#define IMG_INVISIBLE_STEELWALL_ACTIVE                 286
-#define IMG_INVISIBLE_WALL                             287
-#define IMG_INVISIBLE_WALL_EDITOR                      288
-#define IMG_INVISIBLE_WALL_ACTIVE                      289
-#define IMG_INVISIBLE_SAND                             290
-#define IMG_INVISIBLE_SAND_EDITOR                      291
-#define IMG_INVISIBLE_SAND_ACTIVE                      292
-#define IMG_CONVEYOR_BELT_1_MIDDLE                     293
-#define IMG_CONVEYOR_BELT_1_MIDDLE_ACTIVE              294
-#define IMG_CONVEYOR_BELT_1_LEFT                       295
-#define IMG_CONVEYOR_BELT_1_LEFT_ACTIVE                        296
-#define IMG_CONVEYOR_BELT_1_RIGHT                      297
-#define IMG_CONVEYOR_BELT_1_RIGHT_ACTIVE               298
-#define IMG_CONVEYOR_BELT_1_SWITCH_LEFT                        299
-#define IMG_CONVEYOR_BELT_1_SWITCH_MIDDLE              300
-#define IMG_CONVEYOR_BELT_1_SWITCH_RIGHT               301
-#define IMG_CONVEYOR_BELT_2_MIDDLE                     302
-#define IMG_CONVEYOR_BELT_2_MIDDLE_ACTIVE              303
-#define IMG_CONVEYOR_BELT_2_LEFT                       304
-#define IMG_CONVEYOR_BELT_2_LEFT_ACTIVE                        305
-#define IMG_CONVEYOR_BELT_2_RIGHT                      306
-#define IMG_CONVEYOR_BELT_2_RIGHT_ACTIVE               307
-#define IMG_CONVEYOR_BELT_2_SWITCH_LEFT                        308
-#define IMG_CONVEYOR_BELT_2_SWITCH_MIDDLE              309
-#define IMG_CONVEYOR_BELT_2_SWITCH_RIGHT               310
-#define IMG_CONVEYOR_BELT_3_MIDDLE                     311
-#define IMG_CONVEYOR_BELT_3_MIDDLE_ACTIVE              312
-#define IMG_CONVEYOR_BELT_3_LEFT                       313
-#define IMG_CONVEYOR_BELT_3_LEFT_ACTIVE                        314
-#define IMG_CONVEYOR_BELT_3_RIGHT                      315
-#define IMG_CONVEYOR_BELT_3_RIGHT_ACTIVE               316
-#define IMG_CONVEYOR_BELT_3_SWITCH_LEFT                        317
-#define IMG_CONVEYOR_BELT_3_SWITCH_MIDDLE              318
-#define IMG_CONVEYOR_BELT_3_SWITCH_RIGHT               319
-#define IMG_CONVEYOR_BELT_4_MIDDLE                     320
-#define IMG_CONVEYOR_BELT_4_MIDDLE_ACTIVE              321
-#define IMG_CONVEYOR_BELT_4_LEFT                       322
-#define IMG_CONVEYOR_BELT_4_LEFT_ACTIVE                        323
-#define IMG_CONVEYOR_BELT_4_RIGHT                      324
-#define IMG_CONVEYOR_BELT_4_RIGHT_ACTIVE               325
-#define IMG_CONVEYOR_BELT_4_SWITCH_LEFT                        326
-#define IMG_CONVEYOR_BELT_4_SWITCH_MIDDLE              327
-#define IMG_CONVEYOR_BELT_4_SWITCH_RIGHT               328
-#define IMG_SWITCHGATE_SWITCH_UP                       329
-#define IMG_SWITCHGATE_SWITCH_DOWN                     330
-#define IMG_LIGHT_SWITCH                               331
-#define IMG_LIGHT_SWITCH_ACTIVE                                332
-#define IMG_TIMEGATE_SWITCH                            333
-#define IMG_TIMEGATE_SWITCH_ACTIVE                     334
-#define IMG_ENVELOPE_1                                 335
-#define IMG_ENVELOPE_1_COLLECTING                      336
-#define IMG_ENVELOPE_2                                 337
-#define IMG_ENVELOPE_2_COLLECTING                      338
-#define IMG_ENVELOPE_3                                 339
-#define IMG_ENVELOPE_3_COLLECTING                      340
-#define IMG_ENVELOPE_4                                 341
-#define IMG_ENVELOPE_4_COLLECTING                      342
-#define IMG_SIGN_EXCLAMATION                           343
-#define IMG_SIGN_STOP                                  344
-#define IMG_LANDMINE                                   345
-#define IMG_STEELWALL_SLIPPERY                         346
-#define IMG_EXTRA_TIME                                 347
-#define IMG_SHIELD_NORMAL                              348
-#define IMG_SHIELD_NORMAL_ACTIVE                       349
-#define IMG_SHIELD_DEADLY                              350
-#define IMG_SHIELD_DEADLY_ACTIVE                       351
-#define IMG_SWITCHGATE_CLOSED                          352
-#define IMG_SWITCHGATE_OPENING                         353
-#define IMG_SWITCHGATE_OPEN                            354
-#define IMG_SWITCHGATE_CLOSING                         355
-#define IMG_TIMEGATE_CLOSED                            356
-#define IMG_TIMEGATE_OPENING                           357
-#define IMG_TIMEGATE_OPEN                              358
-#define IMG_TIMEGATE_CLOSING                           359
-#define IMG_PEARL                                      360
-#define IMG_PEARL_BREAKING                             361
-#define IMG_CRYSTAL                                    362
-#define IMG_WALL_PEARL                                 363
-#define IMG_WALL_CRYSTAL                               364
-#define IMG_TUBE_RIGHT_DOWN                            365
-#define IMG_TUBE_HORIZONTAL_DOWN                       366
-#define IMG_TUBE_LEFT_DOWN                             367
-#define IMG_TUBE_HORIZONTAL                            368
-#define IMG_TUBE_VERTICAL_RIGHT                                369
-#define IMG_TUBE_ANY                                   370
-#define IMG_TUBE_VERTICAL_LEFT                         371
-#define IMG_TUBE_VERTICAL                              372
-#define IMG_TUBE_RIGHT_UP                              373
-#define IMG_TUBE_HORIZONTAL_UP                         374
-#define IMG_TUBE_LEFT_UP                               375
-#define IMG_TRAP                                       376
-#define IMG_TRAP_ACTIVE                                        377
-#define IMG_DX_SUPABOMB                                        378
-#define IMG_KEY_1                                      379
-#define IMG_KEY_1_EDITOR                               380
-#define IMG_KEY_2                                      381
-#define IMG_KEY_2_EDITOR                               382
-#define IMG_KEY_3                                      383
-#define IMG_KEY_3_EDITOR                               384
-#define IMG_KEY_4                                      385
-#define IMG_KEY_4_EDITOR                               386
-#define IMG_GATE_1                                     387
-#define IMG_GATE_2                                     388
-#define IMG_GATE_3                                     389
-#define IMG_GATE_4                                     390
-#define IMG_GATE_1_GRAY                                        391
-#define IMG_GATE_1_GRAY_EDITOR                         392
-#define IMG_GATE_2_GRAY                                        393
-#define IMG_GATE_2_GRAY_EDITOR                         394
-#define IMG_GATE_3_GRAY                                        395
-#define IMG_GATE_3_GRAY_EDITOR                         396
-#define IMG_GATE_4_GRAY                                        397
-#define IMG_GATE_4_GRAY_EDITOR                         398
-#define IMG_GAME_OF_LIFE                               399
-#define IMG_BIOMAZE                                    400
-#define IMG_PACMAN                                     401
-#define IMG_PACMAN_RIGHT                               402
-#define IMG_PACMAN_UP                                  403
-#define IMG_PACMAN_LEFT                                        404
-#define IMG_PACMAN_DOWN                                        405
-#define IMG_PACMAN_TURNING_FROM_RIGHT                  406
-#define IMG_PACMAN_TURNING_FROM_UP                     407
-#define IMG_PACMAN_TURNING_FROM_LEFT                   408
-#define IMG_PACMAN_TURNING_FROM_DOWN                   409
-#define IMG_LAMP                                       410
-#define IMG_LAMP_EDITOR                                        411
-#define IMG_LAMP_ACTIVE                                        412
-#define IMG_TIME_ORB_FULL                              413
-#define IMG_TIME_ORB_EMPTY                             414
-#define IMG_EMERALD_YELLOW                             415
-#define IMG_EMERALD_YELLOW_MOVING                      416
-#define IMG_EMERALD_YELLOW_FALLING                     417
-#define IMG_EMERALD_RED                                        418
-#define IMG_EMERALD_RED_MOVING                         419
-#define IMG_EMERALD_RED_FALLING                                420
-#define IMG_EMERALD_PURPLE                             421
-#define IMG_EMERALD_PURPLE_MOVING                      422
-#define IMG_EMERALD_PURPLE_FALLING                     423
-#define IMG_WALL_EMERALD_YELLOW                                424
-#define IMG_WALL_EMERALD_RED                           425
-#define IMG_WALL_EMERALD_PURPLE                                426
-#define IMG_WALL_BD_DIAMOND                            427
-#define IMG_EXPANDABLE_WALL                            428
-#define IMG_EXPANDABLE_WALL_HORIZONTAL                 429
-#define IMG_EXPANDABLE_WALL_HORIZONTAL_EDITOR          430
-#define IMG_EXPANDABLE_WALL_VERTICAL                   431
-#define IMG_EXPANDABLE_WALL_VERTICAL_EDITOR            432
-#define IMG_EXPANDABLE_WALL_ANY                                433
-#define IMG_EXPANDABLE_WALL_ANY_EDITOR                 434
-#define IMG_EXPANDABLE_WALL_GROWING_LEFT               435
-#define IMG_EXPANDABLE_WALL_GROWING_RIGHT              436
-#define IMG_EXPANDABLE_WALL_GROWING_UP                 437
-#define IMG_EXPANDABLE_WALL_GROWING_DOWN               438
-#define IMG_BLACK_ORB                                  439
-#define IMG_SPEED_PILL                                 440
-#define IMG_DARK_YAMYAM                                        441
-#define IMG_DYNABOMB                                   442
-#define IMG_DYNABOMB_ACTIVE                            443
-#define IMG_DYNABOMB_PLAYER_1                          444
-#define IMG_DYNABOMB_PLAYER_1_ACTIVE                   445
-#define IMG_DYNABOMB_PLAYER_2                          446
-#define IMG_DYNABOMB_PLAYER_2_ACTIVE                   447
-#define IMG_DYNABOMB_PLAYER_3                          448
-#define IMG_DYNABOMB_PLAYER_3_ACTIVE                   449
-#define IMG_DYNABOMB_PLAYER_4                          450
-#define IMG_DYNABOMB_PLAYER_4_ACTIVE                   451
-#define IMG_DYNABOMB_INCREASE_NUMBER                   452
-#define IMG_DYNABOMB_INCREASE_SIZE                     453
-#define IMG_DYNABOMB_INCREASE_POWER                    454
-#define IMG_PIG                                                455
-#define IMG_PIG_DOWN                                   456
-#define IMG_PIG_UP                                     457
-#define IMG_PIG_LEFT                                   458
-#define IMG_PIG_RIGHT                                  459
-#define IMG_PIG_MOVING_DOWN                            460
-#define IMG_PIG_MOVING_UP                              461
-#define IMG_PIG_MOVING_LEFT                            462
-#define IMG_PIG_MOVING_RIGHT                           463
-#define IMG_PIG_DIGGING_DOWN                           464
-#define IMG_PIG_DIGGING_UP                             465
-#define IMG_PIG_DIGGING_LEFT                           466
-#define IMG_PIG_DIGGING_RIGHT                          467
-#define IMG_DRAGON                                     468
-#define IMG_DRAGON_DOWN                                        469
-#define IMG_DRAGON_UP                                  470
-#define IMG_DRAGON_LEFT                                        471
-#define IMG_DRAGON_RIGHT                               472
-#define IMG_DRAGON_MOVING_DOWN                         473
-#define IMG_DRAGON_MOVING_UP                           474
-#define IMG_DRAGON_MOVING_LEFT                         475
-#define IMG_DRAGON_MOVING_RIGHT                                476
-#define IMG_DRAGON_ATTACKING_DOWN                      477
-#define IMG_DRAGON_ATTACKING_UP                                478
-#define IMG_DRAGON_ATTACKING_LEFT                      479
-#define IMG_DRAGON_ATTACKING_RIGHT                     480
-#define IMG_MOLE                                       481
-#define IMG_MOLE_DOWN                                  482
-#define IMG_MOLE_UP                                    483
-#define IMG_MOLE_LEFT                                  484
-#define IMG_MOLE_RIGHT                                 485
-#define IMG_MOLE_MOVING_DOWN                           486
-#define IMG_MOLE_MOVING_UP                             487
-#define IMG_MOLE_MOVING_LEFT                           488
-#define IMG_MOLE_MOVING_RIGHT                          489
-#define IMG_MOLE_DIGGING_DOWN                          490
-#define IMG_MOLE_DIGGING_UP                            491
-#define IMG_MOLE_DIGGING_LEFT                          492
-#define IMG_MOLE_DIGGING_RIGHT                         493
-#define IMG_PENGUIN                                    494
-#define IMG_PENGUIN_EDITOR                             495
-#define IMG_PENGUIN_DOWN                               496
-#define IMG_PENGUIN_UP                                 497
-#define IMG_PENGUIN_LEFT                               498
-#define IMG_PENGUIN_RIGHT                              499
-#define IMG_PENGUIN_MOVING_DOWN                                500
-#define IMG_PENGUIN_MOVING_UP                          501
-#define IMG_PENGUIN_MOVING_LEFT                                502
-#define IMG_PENGUIN_MOVING_RIGHT                       503
-#define IMG_SATELLITE                                  504
-#define IMG_FLAMES_1_LEFT                              505
-#define IMG_FLAMES_2_LEFT                              506
-#define IMG_FLAMES_3_LEFT                              507
-#define IMG_FLAMES_1_RIGHT                             508
-#define IMG_FLAMES_2_RIGHT                             509
-#define IMG_FLAMES_3_RIGHT                             510
-#define IMG_FLAMES_1_UP                                        511
-#define IMG_FLAMES_2_UP                                        512
-#define IMG_FLAMES_3_UP                                        513
-#define IMG_FLAMES_1_DOWN                              514
-#define IMG_FLAMES_2_DOWN                              515
-#define IMG_FLAMES_3_DOWN                              516
-#define IMG_STONEBLOCK                                 517
-#define IMG_PLAYER_1                                   518
-#define IMG_PLAYER_1_EDITOR                            519
-#define IMG_PLAYER_1_DOWN                              520
-#define IMG_PLAYER_1_UP                                        521
-#define IMG_PLAYER_1_LEFT                              522
-#define IMG_PLAYER_1_RIGHT                             523
-#define IMG_PLAYER_1_MOVING_DOWN                       524
-#define IMG_PLAYER_1_MOVING_UP                         525
-#define IMG_PLAYER_1_MOVING_LEFT                       526
-#define IMG_PLAYER_1_MOVING_RIGHT                      527
-#define IMG_PLAYER_1_DIGGING_DOWN                      528
-#define IMG_PLAYER_1_DIGGING_UP                                529
-#define IMG_PLAYER_1_DIGGING_LEFT                      530
-#define IMG_PLAYER_1_DIGGING_RIGHT                     531
-#define IMG_PLAYER_1_COLLECTING_DOWN                   532
-#define IMG_PLAYER_1_COLLECTING_UP                     533
-#define IMG_PLAYER_1_COLLECTING_LEFT                   534
-#define IMG_PLAYER_1_COLLECTING_RIGHT                  535
-#define IMG_PLAYER_1_PUSHING_DOWN                      536
-#define IMG_PLAYER_1_PUSHING_UP                                537
-#define IMG_PLAYER_1_PUSHING_LEFT                      538
-#define IMG_PLAYER_1_PUSHING_RIGHT                     539
-#define IMG_PLAYER_1_SNAPPING_DOWN                     540
-#define IMG_PLAYER_1_SNAPPING_UP                       541
-#define IMG_PLAYER_1_SNAPPING_LEFT                     542
-#define IMG_PLAYER_1_SNAPPING_RIGHT                    543
-#define IMG_PLAYER_2                                   544
-#define IMG_PLAYER_2_EDITOR                            545
-#define IMG_PLAYER_2_DOWN                              546
-#define IMG_PLAYER_2_UP                                        547
-#define IMG_PLAYER_2_LEFT                              548
-#define IMG_PLAYER_2_RIGHT                             549
-#define IMG_PLAYER_2_MOVING_DOWN                       550
-#define IMG_PLAYER_2_MOVING_UP                         551
-#define IMG_PLAYER_2_MOVING_LEFT                       552
-#define IMG_PLAYER_2_MOVING_RIGHT                      553
-#define IMG_PLAYER_2_DIGGING_DOWN                      554
-#define IMG_PLAYER_2_DIGGING_UP                                555
-#define IMG_PLAYER_2_DIGGING_LEFT                      556
-#define IMG_PLAYER_2_DIGGING_RIGHT                     557
-#define IMG_PLAYER_2_COLLECTING_DOWN                   558
-#define IMG_PLAYER_2_COLLECTING_UP                     559
-#define IMG_PLAYER_2_COLLECTING_LEFT                   560
-#define IMG_PLAYER_2_COLLECTING_RIGHT                  561
-#define IMG_PLAYER_2_PUSHING_DOWN                      562
-#define IMG_PLAYER_2_PUSHING_UP                                563
-#define IMG_PLAYER_2_PUSHING_LEFT                      564
-#define IMG_PLAYER_2_PUSHING_RIGHT                     565
-#define IMG_PLAYER_2_SNAPPING_DOWN                     566
-#define IMG_PLAYER_2_SNAPPING_UP                       567
-#define IMG_PLAYER_2_SNAPPING_LEFT                     568
-#define IMG_PLAYER_2_SNAPPING_RIGHT                    569
-#define IMG_PLAYER_3                                   570
-#define IMG_PLAYER_3_EDITOR                            571
-#define IMG_PLAYER_3_DOWN                              572
-#define IMG_PLAYER_3_UP                                        573
-#define IMG_PLAYER_3_LEFT                              574
-#define IMG_PLAYER_3_RIGHT                             575
-#define IMG_PLAYER_3_MOVING_DOWN                       576
-#define IMG_PLAYER_3_MOVING_UP                         577
-#define IMG_PLAYER_3_MOVING_LEFT                       578
-#define IMG_PLAYER_3_MOVING_RIGHT                      579
-#define IMG_PLAYER_3_DIGGING_DOWN                      580
-#define IMG_PLAYER_3_DIGGING_UP                                581
-#define IMG_PLAYER_3_DIGGING_LEFT                      582
-#define IMG_PLAYER_3_DIGGING_RIGHT                     583
-#define IMG_PLAYER_3_COLLECTING_DOWN                   584
-#define IMG_PLAYER_3_COLLECTING_UP                     585
-#define IMG_PLAYER_3_COLLECTING_LEFT                   586
-#define IMG_PLAYER_3_COLLECTING_RIGHT                  587
-#define IMG_PLAYER_3_PUSHING_DOWN                      588
-#define IMG_PLAYER_3_PUSHING_UP                                589
-#define IMG_PLAYER_3_PUSHING_LEFT                      590
-#define IMG_PLAYER_3_PUSHING_RIGHT                     591
-#define IMG_PLAYER_3_SNAPPING_DOWN                     592
-#define IMG_PLAYER_3_SNAPPING_UP                       593
-#define IMG_PLAYER_3_SNAPPING_LEFT                     594
-#define IMG_PLAYER_3_SNAPPING_RIGHT                    595
-#define IMG_PLAYER_4                                   596
-#define IMG_PLAYER_4_EDITOR                            597
-#define IMG_PLAYER_4_DOWN                              598
-#define IMG_PLAYER_4_UP                                        599
-#define IMG_PLAYER_4_LEFT                              600
-#define IMG_PLAYER_4_RIGHT                             601
-#define IMG_PLAYER_4_MOVING_DOWN                       602
-#define IMG_PLAYER_4_MOVING_UP                         603
-#define IMG_PLAYER_4_MOVING_LEFT                       604
-#define IMG_PLAYER_4_MOVING_RIGHT                      605
-#define IMG_PLAYER_4_DIGGING_DOWN                      606
-#define IMG_PLAYER_4_DIGGING_UP                                607
-#define IMG_PLAYER_4_DIGGING_LEFT                      608
-#define IMG_PLAYER_4_DIGGING_RIGHT                     609
-#define IMG_PLAYER_4_COLLECTING_DOWN                   610
-#define IMG_PLAYER_4_COLLECTING_UP                     611
-#define IMG_PLAYER_4_COLLECTING_LEFT                   612
-#define IMG_PLAYER_4_COLLECTING_RIGHT                  613
-#define IMG_PLAYER_4_PUSHING_DOWN                      614
-#define IMG_PLAYER_4_PUSHING_UP                                615
-#define IMG_PLAYER_4_PUSHING_LEFT                      616
-#define IMG_PLAYER_4_PUSHING_RIGHT                     617
-#define IMG_PLAYER_4_SNAPPING_DOWN                     618
-#define IMG_PLAYER_4_SNAPPING_UP                       619
-#define IMG_PLAYER_4_SNAPPING_LEFT                     620
-#define IMG_PLAYER_4_SNAPPING_RIGHT                    621
-#define IMG_DEFAULT_EXPLODING                          622
-#define IMG_TWINKLE_BLUE                               623
-#define IMG_TWINKLE_WHITE                              624
-#define IMG_STEELWALL_TOPLEFT                          625
-#define IMG_STEELWALL_TOPRIGHT                         626
-#define IMG_STEELWALL_BOTTOMLEFT                       627
-#define IMG_STEELWALL_BOTTOMRIGHT                      628
-#define IMG_STEELWALL_HORIZONTAL                       629
-#define IMG_STEELWALL_VERTICAL                         630
-#define IMG_STEELWALL_TOPLEFT_EDITOR                   631
-#define IMG_STEELWALL_TOPRIGHT_EDITOR                  632
-#define IMG_STEELWALL_BOTTOMLEFT_EDITOR                        633
-#define IMG_STEELWALL_BOTTOMRIGHT_EDITOR               634
-#define IMG_STEELWALL_HORIZONTAL_EDITOR                        635
-#define IMG_STEELWALL_VERTICAL_EDITOR                  636
-#define IMG_INVISIBLE_STEELWALL_TOPLEFT                        637
-#define IMG_INVISIBLE_STEELWALL_TOPRIGHT               638
-#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT             639
-#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT            640
-#define IMG_INVISIBLE_STEELWALL_HORIZONTAL             641
-#define IMG_INVISIBLE_STEELWALL_VERTICAL               642
-#define IMG_INVISIBLE_STEELWALL_TOPLEFT_EDITOR         643
-#define IMG_INVISIBLE_STEELWALL_TOPRIGHT_EDITOR                644
-#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT_EDITOR      645
-#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT_EDITOR     646
-#define IMG_INVISIBLE_STEELWALL_HORIZONTAL_EDITOR      647
-#define IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR                648
-#define IMG_ARROW_LEFT                                 649
-#define IMG_ARROW_RIGHT                                        650
-#define IMG_ARROW_UP                                   651
-#define IMG_ARROW_DOWN                                 652
-#define IMG_UNKNOWN                                    653
-#define IMG_TRIGGER_ELEMENT                            654
-#define IMG_TRIGGER_PLAYER                             655
-#define IMG_CHAR_SPACE                                 656
-#define IMG_CHAR_EXCLAM                                        657
-#define IMG_CHAR_QUOTEDBL                              658
-#define IMG_CHAR_NUMBERSIGN                            659
-#define IMG_CHAR_DOLLAR                                        660
-#define IMG_CHAR_PROCENT                               661
-#define IMG_CHAR_AMPERSAND                             662
-#define IMG_CHAR_APOSTROPHE                            663
-#define IMG_CHAR_PARENLEFT                             664
-#define IMG_CHAR_PARENRIGHT                            665
-#define IMG_CHAR_ASTERISK                              666
-#define IMG_CHAR_PLUS                                  667
-#define IMG_CHAR_COMMA                                 668
-#define IMG_CHAR_MINUS                                 669
-#define IMG_CHAR_PERIOD                                        670
-#define IMG_CHAR_SLASH                                 671
-#define IMG_CHAR_0                                     672
-#define IMG_CHAR_1                                     673
-#define IMG_CHAR_2                                     674
-#define IMG_CHAR_3                                     675
-#define IMG_CHAR_4                                     676
-#define IMG_CHAR_5                                     677
-#define IMG_CHAR_6                                     678
-#define IMG_CHAR_7                                     679
-#define IMG_CHAR_8                                     680
-#define IMG_CHAR_9                                     681
-#define IMG_CHAR_COLON                                 682
-#define IMG_CHAR_SEMICOLON                             683
-#define IMG_CHAR_LESS                                  684
-#define IMG_CHAR_EQUAL                                 685
-#define IMG_CHAR_GREATER                               686
-#define IMG_CHAR_QUESTION                              687
-#define IMG_CHAR_AT                                    688
-#define IMG_CHAR_A                                     689
-#define IMG_CHAR_B                                     690
-#define IMG_CHAR_C                                     691
-#define IMG_CHAR_D                                     692
-#define IMG_CHAR_E                                     693
-#define IMG_CHAR_F                                     694
-#define IMG_CHAR_G                                     695
-#define IMG_CHAR_H                                     696
-#define IMG_CHAR_I                                     697
-#define IMG_CHAR_J                                     698
-#define IMG_CHAR_K                                     699
-#define IMG_CHAR_L                                     700
-#define IMG_CHAR_M                                     701
-#define IMG_CHAR_N                                     702
-#define IMG_CHAR_O                                     703
-#define IMG_CHAR_P                                     704
-#define IMG_CHAR_Q                                     705
-#define IMG_CHAR_R                                     706
-#define IMG_CHAR_S                                     707
-#define IMG_CHAR_T                                     708
-#define IMG_CHAR_U                                     709
-#define IMG_CHAR_V                                     710
-#define IMG_CHAR_W                                     711
-#define IMG_CHAR_X                                     712
-#define IMG_CHAR_Y                                     713
-#define IMG_CHAR_Z                                     714
-#define IMG_CHAR_BRACKETLEFT                           715
-#define IMG_CHAR_BACKSLASH                             716
-#define IMG_CHAR_BRACKETRIGHT                          717
-#define IMG_CHAR_ASCIICIRCUM                           718
-#define IMG_CHAR_UNDERSCORE                            719
-#define IMG_CHAR_COPYRIGHT                             720
-#define IMG_CHAR_AUMLAUT                               721
-#define IMG_CHAR_OUMLAUT                               722
-#define IMG_CHAR_UUMLAUT                               723
-#define IMG_CHAR_DEGREE                                        724
-#define IMG_CHAR_TRADEMARK                             725
-#define IMG_CHAR_CURSOR                                        726
-#define IMG_CUSTOM_1                                   727
-#define IMG_CUSTOM_1_EDITOR                            728
-#define IMG_CUSTOM_2                                   729
-#define IMG_CUSTOM_2_EDITOR                            730
-#define IMG_CUSTOM_3                                   731
-#define IMG_CUSTOM_3_EDITOR                            732
-#define IMG_CUSTOM_4                                   733
-#define IMG_CUSTOM_4_EDITOR                            734
-#define IMG_CUSTOM_5                                   735
-#define IMG_CUSTOM_5_EDITOR                            736
-#define IMG_CUSTOM_6                                   737
-#define IMG_CUSTOM_6_EDITOR                            738
-#define IMG_CUSTOM_7                                   739
-#define IMG_CUSTOM_7_EDITOR                            740
-#define IMG_CUSTOM_8                                   741
-#define IMG_CUSTOM_8_EDITOR                            742
-#define IMG_CUSTOM_9                                   743
-#define IMG_CUSTOM_9_EDITOR                            744
-#define IMG_CUSTOM_10                                  745
-#define IMG_CUSTOM_10_EDITOR                           746
-#define IMG_CUSTOM_11                                  747
-#define IMG_CUSTOM_11_EDITOR                           748
-#define IMG_CUSTOM_12                                  749
-#define IMG_CUSTOM_12_EDITOR                           750
-#define IMG_CUSTOM_13                                  751
-#define IMG_CUSTOM_13_EDITOR                           752
-#define IMG_CUSTOM_14                                  753
-#define IMG_CUSTOM_14_EDITOR                           754
-#define IMG_CUSTOM_15                                  755
-#define IMG_CUSTOM_15_EDITOR                           756
-#define IMG_CUSTOM_16                                  757
-#define IMG_CUSTOM_16_EDITOR                           758
-#define IMG_CUSTOM_17                                  759
-#define IMG_CUSTOM_17_EDITOR                           760
-#define IMG_CUSTOM_18                                  761
-#define IMG_CUSTOM_18_EDITOR                           762
-#define IMG_CUSTOM_19                                  763
-#define IMG_CUSTOM_19_EDITOR                           764
-#define IMG_CUSTOM_20                                  765
-#define IMG_CUSTOM_20_EDITOR                           766
-#define IMG_CUSTOM_21                                  767
-#define IMG_CUSTOM_21_EDITOR                           768
-#define IMG_CUSTOM_22                                  769
-#define IMG_CUSTOM_22_EDITOR                           770
-#define IMG_CUSTOM_23                                  771
-#define IMG_CUSTOM_23_EDITOR                           772
-#define IMG_CUSTOM_24                                  773
-#define IMG_CUSTOM_24_EDITOR                           774
-#define IMG_CUSTOM_25                                  775
-#define IMG_CUSTOM_25_EDITOR                           776
-#define IMG_CUSTOM_26                                  777
-#define IMG_CUSTOM_26_EDITOR                           778
-#define IMG_CUSTOM_27                                  779
-#define IMG_CUSTOM_27_EDITOR                           780
-#define IMG_CUSTOM_28                                  781
-#define IMG_CUSTOM_28_EDITOR                           782
-#define IMG_CUSTOM_29                                  783
-#define IMG_CUSTOM_29_EDITOR                           784
-#define IMG_CUSTOM_30                                  785
-#define IMG_CUSTOM_30_EDITOR                           786
-#define IMG_CUSTOM_31                                  787
-#define IMG_CUSTOM_31_EDITOR                           788
-#define IMG_CUSTOM_32                                  789
-#define IMG_CUSTOM_32_EDITOR                           790
-#define IMG_CUSTOM_33                                  791
-#define IMG_CUSTOM_33_EDITOR                           792
-#define IMG_CUSTOM_34                                  793
-#define IMG_CUSTOM_34_EDITOR                           794
-#define IMG_CUSTOM_35                                  795
-#define IMG_CUSTOM_35_EDITOR                           796
-#define IMG_CUSTOM_36                                  797
-#define IMG_CUSTOM_36_EDITOR                           798
-#define IMG_CUSTOM_37                                  799
-#define IMG_CUSTOM_37_EDITOR                           800
-#define IMG_CUSTOM_38                                  801
-#define IMG_CUSTOM_38_EDITOR                           802
-#define IMG_CUSTOM_39                                  803
-#define IMG_CUSTOM_39_EDITOR                           804
-#define IMG_CUSTOM_40                                  805
-#define IMG_CUSTOM_40_EDITOR                           806
-#define IMG_CUSTOM_41                                  807
-#define IMG_CUSTOM_41_EDITOR                           808
-#define IMG_CUSTOM_42                                  809
-#define IMG_CUSTOM_42_EDITOR                           810
-#define IMG_CUSTOM_43                                  811
-#define IMG_CUSTOM_43_EDITOR                           812
-#define IMG_CUSTOM_44                                  813
-#define IMG_CUSTOM_44_EDITOR                           814
-#define IMG_CUSTOM_45                                  815
-#define IMG_CUSTOM_45_EDITOR                           816
-#define IMG_CUSTOM_46                                  817
-#define IMG_CUSTOM_46_EDITOR                           818
-#define IMG_CUSTOM_47                                  819
-#define IMG_CUSTOM_47_EDITOR                           820
-#define IMG_CUSTOM_48                                  821
-#define IMG_CUSTOM_48_EDITOR                           822
-#define IMG_CUSTOM_49                                  823
-#define IMG_CUSTOM_49_EDITOR                           824
-#define IMG_CUSTOM_50                                  825
-#define IMG_CUSTOM_50_EDITOR                           826
-#define IMG_CUSTOM_51                                  827
-#define IMG_CUSTOM_51_EDITOR                           828
-#define IMG_CUSTOM_52                                  829
-#define IMG_CUSTOM_52_EDITOR                           830
-#define IMG_CUSTOM_53                                  831
-#define IMG_CUSTOM_53_EDITOR                           832
-#define IMG_CUSTOM_54                                  833
-#define IMG_CUSTOM_54_EDITOR                           834
-#define IMG_CUSTOM_55                                  835
-#define IMG_CUSTOM_55_EDITOR                           836
-#define IMG_CUSTOM_56                                  837
-#define IMG_CUSTOM_56_EDITOR                           838
-#define IMG_CUSTOM_57                                  839
-#define IMG_CUSTOM_57_EDITOR                           840
-#define IMG_CUSTOM_58                                  841
-#define IMG_CUSTOM_58_EDITOR                           842
-#define IMG_CUSTOM_59                                  843
-#define IMG_CUSTOM_59_EDITOR                           844
-#define IMG_CUSTOM_60                                  845
-#define IMG_CUSTOM_60_EDITOR                           846
-#define IMG_CUSTOM_61                                  847
-#define IMG_CUSTOM_61_EDITOR                           848
-#define IMG_CUSTOM_62                                  849
-#define IMG_CUSTOM_62_EDITOR                           850
-#define IMG_CUSTOM_63                                  851
-#define IMG_CUSTOM_63_EDITOR                           852
-#define IMG_CUSTOM_64                                  853
-#define IMG_CUSTOM_64_EDITOR                           854
-#define IMG_CUSTOM_65                                  855
-#define IMG_CUSTOM_65_EDITOR                           856
-#define IMG_CUSTOM_66                                  857
-#define IMG_CUSTOM_66_EDITOR                           858
-#define IMG_CUSTOM_67                                  859
-#define IMG_CUSTOM_67_EDITOR                           860
-#define IMG_CUSTOM_68                                  861
-#define IMG_CUSTOM_68_EDITOR                           862
-#define IMG_CUSTOM_69                                  863
-#define IMG_CUSTOM_69_EDITOR                           864
-#define IMG_CUSTOM_70                                  865
-#define IMG_CUSTOM_70_EDITOR                           866
-#define IMG_CUSTOM_71                                  867
-#define IMG_CUSTOM_71_EDITOR                           868
-#define IMG_CUSTOM_72                                  869
-#define IMG_CUSTOM_72_EDITOR                           870
-#define IMG_CUSTOM_73                                  871
-#define IMG_CUSTOM_73_EDITOR                           872
-#define IMG_CUSTOM_74                                  873
-#define IMG_CUSTOM_74_EDITOR                           874
-#define IMG_CUSTOM_75                                  875
-#define IMG_CUSTOM_75_EDITOR                           876
-#define IMG_CUSTOM_76                                  877
-#define IMG_CUSTOM_76_EDITOR                           878
-#define IMG_CUSTOM_77                                  879
-#define IMG_CUSTOM_77_EDITOR                           880
-#define IMG_CUSTOM_78                                  881
-#define IMG_CUSTOM_78_EDITOR                           882
-#define IMG_CUSTOM_79                                  883
-#define IMG_CUSTOM_79_EDITOR                           884
-#define IMG_CUSTOM_80                                  885
-#define IMG_CUSTOM_80_EDITOR                           886
-#define IMG_CUSTOM_81                                  887
-#define IMG_CUSTOM_81_EDITOR                           888
-#define IMG_CUSTOM_82                                  889
-#define IMG_CUSTOM_82_EDITOR                           890
-#define IMG_CUSTOM_83                                  891
-#define IMG_CUSTOM_83_EDITOR                           892
-#define IMG_CUSTOM_84                                  893
-#define IMG_CUSTOM_84_EDITOR                           894
-#define IMG_CUSTOM_85                                  895
-#define IMG_CUSTOM_85_EDITOR                           896
-#define IMG_CUSTOM_86                                  897
-#define IMG_CUSTOM_86_EDITOR                           898
-#define IMG_CUSTOM_87                                  899
-#define IMG_CUSTOM_87_EDITOR                           900
-#define IMG_CUSTOM_88                                  901
-#define IMG_CUSTOM_88_EDITOR                           902
-#define IMG_CUSTOM_89                                  903
-#define IMG_CUSTOM_89_EDITOR                           904
-#define IMG_CUSTOM_90                                  905
-#define IMG_CUSTOM_90_EDITOR                           906
-#define IMG_CUSTOM_91                                  907
-#define IMG_CUSTOM_91_EDITOR                           908
-#define IMG_CUSTOM_92                                  909
-#define IMG_CUSTOM_92_EDITOR                           910
-#define IMG_CUSTOM_93                                  911
-#define IMG_CUSTOM_93_EDITOR                           912
-#define IMG_CUSTOM_94                                  913
-#define IMG_CUSTOM_94_EDITOR                           914
-#define IMG_CUSTOM_95                                  915
-#define IMG_CUSTOM_95_EDITOR                           916
-#define IMG_CUSTOM_96                                  917
-#define IMG_CUSTOM_96_EDITOR                           918
-#define IMG_CUSTOM_97                                  919
-#define IMG_CUSTOM_97_EDITOR                           920
-#define IMG_CUSTOM_98                                  921
-#define IMG_CUSTOM_98_EDITOR                           922
-#define IMG_CUSTOM_99                                  923
-#define IMG_CUSTOM_99_EDITOR                           924
-#define IMG_CUSTOM_100                                 925
-#define IMG_CUSTOM_100_EDITOR                          926
-#define IMG_CUSTOM_101                                 927
-#define IMG_CUSTOM_101_EDITOR                          928
-#define IMG_CUSTOM_102                                 929
-#define IMG_CUSTOM_102_EDITOR                          930
-#define IMG_CUSTOM_103                                 931
-#define IMG_CUSTOM_103_EDITOR                          932
-#define IMG_CUSTOM_104                                 933
-#define IMG_CUSTOM_104_EDITOR                          934
-#define IMG_CUSTOM_105                                 935
-#define IMG_CUSTOM_105_EDITOR                          936
-#define IMG_CUSTOM_106                                 937
-#define IMG_CUSTOM_106_EDITOR                          938
-#define IMG_CUSTOM_107                                 939
-#define IMG_CUSTOM_107_EDITOR                          940
-#define IMG_CUSTOM_108                                 941
-#define IMG_CUSTOM_108_EDITOR                          942
-#define IMG_CUSTOM_109                                 943
-#define IMG_CUSTOM_109_EDITOR                          944
-#define IMG_CUSTOM_110                                 945
-#define IMG_CUSTOM_110_EDITOR                          946
-#define IMG_CUSTOM_111                                 947
-#define IMG_CUSTOM_111_EDITOR                          948
-#define IMG_CUSTOM_112                                 949
-#define IMG_CUSTOM_112_EDITOR                          950
-#define IMG_CUSTOM_113                                 951
-#define IMG_CUSTOM_113_EDITOR                          952
-#define IMG_CUSTOM_114                                 953
-#define IMG_CUSTOM_114_EDITOR                          954
-#define IMG_CUSTOM_115                                 955
-#define IMG_CUSTOM_115_EDITOR                          956
-#define IMG_CUSTOM_116                                 957
-#define IMG_CUSTOM_116_EDITOR                          958
-#define IMG_CUSTOM_117                                 959
-#define IMG_CUSTOM_117_EDITOR                          960
-#define IMG_CUSTOM_118                                 961
-#define IMG_CUSTOM_118_EDITOR                          962
-#define IMG_CUSTOM_119                                 963
-#define IMG_CUSTOM_119_EDITOR                          964
-#define IMG_CUSTOM_120                                 965
-#define IMG_CUSTOM_120_EDITOR                          966
-#define IMG_CUSTOM_121                                 967
-#define IMG_CUSTOM_121_EDITOR                          968
-#define IMG_CUSTOM_122                                 969
-#define IMG_CUSTOM_122_EDITOR                          970
-#define IMG_CUSTOM_123                                 971
-#define IMG_CUSTOM_123_EDITOR                          972
-#define IMG_CUSTOM_124                                 973
-#define IMG_CUSTOM_124_EDITOR                          974
-#define IMG_CUSTOM_125                                 975
-#define IMG_CUSTOM_125_EDITOR                          976
-#define IMG_CUSTOM_126                                 977
-#define IMG_CUSTOM_126_EDITOR                          978
-#define IMG_CUSTOM_127                                 979
-#define IMG_CUSTOM_127_EDITOR                          980
-#define IMG_CUSTOM_128                                 981
-#define IMG_CUSTOM_128_EDITOR                          982
-#define IMG_CUSTOM_129                                 983
-#define IMG_CUSTOM_129_EDITOR                          984
-#define IMG_CUSTOM_130                                 985
-#define IMG_CUSTOM_130_EDITOR                          986
-#define IMG_CUSTOM_131                                 987
-#define IMG_CUSTOM_131_EDITOR                          988
-#define IMG_CUSTOM_132                                 989
-#define IMG_CUSTOM_132_EDITOR                          990
-#define IMG_CUSTOM_133                                 991
-#define IMG_CUSTOM_133_EDITOR                          992
-#define IMG_CUSTOM_134                                 993
-#define IMG_CUSTOM_134_EDITOR                          994
-#define IMG_CUSTOM_135                                 995
-#define IMG_CUSTOM_135_EDITOR                          996
-#define IMG_CUSTOM_136                                 997
-#define IMG_CUSTOM_136_EDITOR                          998
-#define IMG_CUSTOM_137                                 999
-#define IMG_CUSTOM_137_EDITOR                          1000
-#define IMG_CUSTOM_138                                 1001
-#define IMG_CUSTOM_138_EDITOR                          1002
-#define IMG_CUSTOM_139                                 1003
-#define IMG_CUSTOM_139_EDITOR                          1004
-#define IMG_CUSTOM_140                                 1005
-#define IMG_CUSTOM_140_EDITOR                          1006
-#define IMG_CUSTOM_141                                 1007
-#define IMG_CUSTOM_141_EDITOR                          1008
-#define IMG_CUSTOM_142                                 1009
-#define IMG_CUSTOM_142_EDITOR                          1010
-#define IMG_CUSTOM_143                                 1011
-#define IMG_CUSTOM_143_EDITOR                          1012
-#define IMG_CUSTOM_144                                 1013
-#define IMG_CUSTOM_144_EDITOR                          1014
-#define IMG_CUSTOM_145                                 1015
-#define IMG_CUSTOM_145_EDITOR                          1016
-#define IMG_CUSTOM_146                                 1017
-#define IMG_CUSTOM_146_EDITOR                          1018
-#define IMG_CUSTOM_147                                 1019
-#define IMG_CUSTOM_147_EDITOR                          1020
-#define IMG_CUSTOM_148                                 1021
-#define IMG_CUSTOM_148_EDITOR                          1022
-#define IMG_CUSTOM_149                                 1023
-#define IMG_CUSTOM_149_EDITOR                          1024
-#define IMG_CUSTOM_150                                 1025
-#define IMG_CUSTOM_150_EDITOR                          1026
-#define IMG_CUSTOM_151                                 1027
-#define IMG_CUSTOM_151_EDITOR                          1028
-#define IMG_CUSTOM_152                                 1029
-#define IMG_CUSTOM_152_EDITOR                          1030
-#define IMG_CUSTOM_153                                 1031
-#define IMG_CUSTOM_153_EDITOR                          1032
-#define IMG_CUSTOM_154                                 1033
-#define IMG_CUSTOM_154_EDITOR                          1034
-#define IMG_CUSTOM_155                                 1035
-#define IMG_CUSTOM_155_EDITOR                          1036
-#define IMG_CUSTOM_156                                 1037
-#define IMG_CUSTOM_156_EDITOR                          1038
-#define IMG_CUSTOM_157                                 1039
-#define IMG_CUSTOM_157_EDITOR                          1040
-#define IMG_CUSTOM_158                                 1041
-#define IMG_CUSTOM_158_EDITOR                          1042
-#define IMG_CUSTOM_159                                 1043
-#define IMG_CUSTOM_159_EDITOR                          1044
-#define IMG_CUSTOM_160                                 1045
-#define IMG_CUSTOM_160_EDITOR                          1046
-#define IMG_CUSTOM_161                                 1047
-#define IMG_CUSTOM_161_EDITOR                          1048
-#define IMG_CUSTOM_162                                 1049
-#define IMG_CUSTOM_162_EDITOR                          1050
-#define IMG_CUSTOM_163                                 1051
-#define IMG_CUSTOM_163_EDITOR                          1052
-#define IMG_CUSTOM_164                                 1053
-#define IMG_CUSTOM_164_EDITOR                          1054
-#define IMG_CUSTOM_165                                 1055
-#define IMG_CUSTOM_165_EDITOR                          1056
-#define IMG_CUSTOM_166                                 1057
-#define IMG_CUSTOM_166_EDITOR                          1058
-#define IMG_CUSTOM_167                                 1059
-#define IMG_CUSTOM_167_EDITOR                          1060
-#define IMG_CUSTOM_168                                 1061
-#define IMG_CUSTOM_168_EDITOR                          1062
-#define IMG_CUSTOM_169                                 1063
-#define IMG_CUSTOM_169_EDITOR                          1064
-#define IMG_CUSTOM_170                                 1065
-#define IMG_CUSTOM_170_EDITOR                          1066
-#define IMG_CUSTOM_171                                 1067
-#define IMG_CUSTOM_171_EDITOR                          1068
-#define IMG_CUSTOM_172                                 1069
-#define IMG_CUSTOM_172_EDITOR                          1070
-#define IMG_CUSTOM_173                                 1071
-#define IMG_CUSTOM_173_EDITOR                          1072
-#define IMG_CUSTOM_174                                 1073
-#define IMG_CUSTOM_174_EDITOR                          1074
-#define IMG_CUSTOM_175                                 1075
-#define IMG_CUSTOM_175_EDITOR                          1076
-#define IMG_CUSTOM_176                                 1077
-#define IMG_CUSTOM_176_EDITOR                          1078
-#define IMG_CUSTOM_177                                 1079
-#define IMG_CUSTOM_177_EDITOR                          1080
-#define IMG_CUSTOM_178                                 1081
-#define IMG_CUSTOM_178_EDITOR                          1082
-#define IMG_CUSTOM_179                                 1083
-#define IMG_CUSTOM_179_EDITOR                          1084
-#define IMG_CUSTOM_180                                 1085
-#define IMG_CUSTOM_180_EDITOR                          1086
-#define IMG_CUSTOM_181                                 1087
-#define IMG_CUSTOM_181_EDITOR                          1088
-#define IMG_CUSTOM_182                                 1089
-#define IMG_CUSTOM_182_EDITOR                          1090
-#define IMG_CUSTOM_183                                 1091
-#define IMG_CUSTOM_183_EDITOR                          1092
-#define IMG_CUSTOM_184                                 1093
-#define IMG_CUSTOM_184_EDITOR                          1094
-#define IMG_CUSTOM_185                                 1095
-#define IMG_CUSTOM_185_EDITOR                          1096
-#define IMG_CUSTOM_186                                 1097
-#define IMG_CUSTOM_186_EDITOR                          1098
-#define IMG_CUSTOM_187                                 1099
-#define IMG_CUSTOM_187_EDITOR                          1100
-#define IMG_CUSTOM_188                                 1101
-#define IMG_CUSTOM_188_EDITOR                          1102
-#define IMG_CUSTOM_189                                 1103
-#define IMG_CUSTOM_189_EDITOR                          1104
-#define IMG_CUSTOM_190                                 1105
-#define IMG_CUSTOM_190_EDITOR                          1106
-#define IMG_CUSTOM_191                                 1107
-#define IMG_CUSTOM_191_EDITOR                          1108
-#define IMG_CUSTOM_192                                 1109
-#define IMG_CUSTOM_192_EDITOR                          1110
-#define IMG_CUSTOM_193                                 1111
-#define IMG_CUSTOM_193_EDITOR                          1112
-#define IMG_CUSTOM_194                                 1113
-#define IMG_CUSTOM_194_EDITOR                          1114
-#define IMG_CUSTOM_195                                 1115
-#define IMG_CUSTOM_195_EDITOR                          1116
-#define IMG_CUSTOM_196                                 1117
-#define IMG_CUSTOM_196_EDITOR                          1118
-#define IMG_CUSTOM_197                                 1119
-#define IMG_CUSTOM_197_EDITOR                          1120
-#define IMG_CUSTOM_198                                 1121
-#define IMG_CUSTOM_198_EDITOR                          1122
-#define IMG_CUSTOM_199                                 1123
-#define IMG_CUSTOM_199_EDITOR                          1124
-#define IMG_CUSTOM_200                                 1125
-#define IMG_CUSTOM_200_EDITOR                          1126
-#define IMG_CUSTOM_201                                 1127
-#define IMG_CUSTOM_201_EDITOR                          1128
-#define IMG_CUSTOM_202                                 1129
-#define IMG_CUSTOM_202_EDITOR                          1130
-#define IMG_CUSTOM_203                                 1131
-#define IMG_CUSTOM_203_EDITOR                          1132
-#define IMG_CUSTOM_204                                 1133
-#define IMG_CUSTOM_204_EDITOR                          1134
-#define IMG_CUSTOM_205                                 1135
-#define IMG_CUSTOM_205_EDITOR                          1136
-#define IMG_CUSTOM_206                                 1137
-#define IMG_CUSTOM_206_EDITOR                          1138
-#define IMG_CUSTOM_207                                 1139
-#define IMG_CUSTOM_207_EDITOR                          1140
-#define IMG_CUSTOM_208                                 1141
-#define IMG_CUSTOM_208_EDITOR                          1142
-#define IMG_CUSTOM_209                                 1143
-#define IMG_CUSTOM_209_EDITOR                          1144
-#define IMG_CUSTOM_210                                 1145
-#define IMG_CUSTOM_210_EDITOR                          1146
-#define IMG_CUSTOM_211                                 1147
-#define IMG_CUSTOM_211_EDITOR                          1148
-#define IMG_CUSTOM_212                                 1149
-#define IMG_CUSTOM_212_EDITOR                          1150
-#define IMG_CUSTOM_213                                 1151
-#define IMG_CUSTOM_213_EDITOR                          1152
-#define IMG_CUSTOM_214                                 1153
-#define IMG_CUSTOM_214_EDITOR                          1154
-#define IMG_CUSTOM_215                                 1155
-#define IMG_CUSTOM_215_EDITOR                          1156
-#define IMG_CUSTOM_216                                 1157
-#define IMG_CUSTOM_216_EDITOR                          1158
-#define IMG_CUSTOM_217                                 1159
-#define IMG_CUSTOM_217_EDITOR                          1160
-#define IMG_CUSTOM_218                                 1161
-#define IMG_CUSTOM_218_EDITOR                          1162
-#define IMG_CUSTOM_219                                 1163
-#define IMG_CUSTOM_219_EDITOR                          1164
-#define IMG_CUSTOM_220                                 1165
-#define IMG_CUSTOM_220_EDITOR                          1166
-#define IMG_CUSTOM_221                                 1167
-#define IMG_CUSTOM_221_EDITOR                          1168
-#define IMG_CUSTOM_222                                 1169
-#define IMG_CUSTOM_222_EDITOR                          1170
-#define IMG_CUSTOM_223                                 1171
-#define IMG_CUSTOM_223_EDITOR                          1172
-#define IMG_CUSTOM_224                                 1173
-#define IMG_CUSTOM_224_EDITOR                          1174
-#define IMG_CUSTOM_225                                 1175
-#define IMG_CUSTOM_225_EDITOR                          1176
-#define IMG_CUSTOM_226                                 1177
-#define IMG_CUSTOM_226_EDITOR                          1178
-#define IMG_CUSTOM_227                                 1179
-#define IMG_CUSTOM_227_EDITOR                          1180
-#define IMG_CUSTOM_228                                 1181
-#define IMG_CUSTOM_228_EDITOR                          1182
-#define IMG_CUSTOM_229                                 1183
-#define IMG_CUSTOM_229_EDITOR                          1184
-#define IMG_CUSTOM_230                                 1185
-#define IMG_CUSTOM_230_EDITOR                          1186
-#define IMG_CUSTOM_231                                 1187
-#define IMG_CUSTOM_231_EDITOR                          1188
-#define IMG_CUSTOM_232                                 1189
-#define IMG_CUSTOM_232_EDITOR                          1190
-#define IMG_CUSTOM_233                                 1191
-#define IMG_CUSTOM_233_EDITOR                          1192
-#define IMG_CUSTOM_234                                 1193
-#define IMG_CUSTOM_234_EDITOR                          1194
-#define IMG_CUSTOM_235                                 1195
-#define IMG_CUSTOM_235_EDITOR                          1196
-#define IMG_CUSTOM_236                                 1197
-#define IMG_CUSTOM_236_EDITOR                          1198
-#define IMG_CUSTOM_237                                 1199
-#define IMG_CUSTOM_237_EDITOR                          1200
-#define IMG_CUSTOM_238                                 1201
-#define IMG_CUSTOM_238_EDITOR                          1202
-#define IMG_CUSTOM_239                                 1203
-#define IMG_CUSTOM_239_EDITOR                          1204
-#define IMG_CUSTOM_240                                 1205
-#define IMG_CUSTOM_240_EDITOR                          1206
-#define IMG_CUSTOM_241                                 1207
-#define IMG_CUSTOM_241_EDITOR                          1208
-#define IMG_CUSTOM_242                                 1209
-#define IMG_CUSTOM_242_EDITOR                          1210
-#define IMG_CUSTOM_243                                 1211
-#define IMG_CUSTOM_243_EDITOR                          1212
-#define IMG_CUSTOM_244                                 1213
-#define IMG_CUSTOM_244_EDITOR                          1214
-#define IMG_CUSTOM_245                                 1215
-#define IMG_CUSTOM_245_EDITOR                          1216
-#define IMG_CUSTOM_246                                 1217
-#define IMG_CUSTOM_246_EDITOR                          1218
-#define IMG_CUSTOM_247                                 1219
-#define IMG_CUSTOM_247_EDITOR                          1220
-#define IMG_CUSTOM_248                                 1221
-#define IMG_CUSTOM_248_EDITOR                          1222
-#define IMG_CUSTOM_249                                 1223
-#define IMG_CUSTOM_249_EDITOR                          1224
-#define IMG_CUSTOM_250                                 1225
-#define IMG_CUSTOM_250_EDITOR                          1226
-#define IMG_CUSTOM_251                                 1227
-#define IMG_CUSTOM_251_EDITOR                          1228
-#define IMG_CUSTOM_252                                 1229
-#define IMG_CUSTOM_252_EDITOR                          1230
-#define IMG_CUSTOM_253                                 1231
-#define IMG_CUSTOM_253_EDITOR                          1232
-#define IMG_CUSTOM_254                                 1233
-#define IMG_CUSTOM_254_EDITOR                          1234
-#define IMG_CUSTOM_255                                 1235
-#define IMG_CUSTOM_255_EDITOR                          1236
-#define IMG_CUSTOM_256                                 1237
-#define IMG_CUSTOM_256_EDITOR                          1238
-#define IMG_GROUP_1                                    1239
-#define IMG_GROUP_1_EDITOR                             1240
-#define IMG_GROUP_2                                    1241
-#define IMG_GROUP_2_EDITOR                             1242
-#define IMG_GROUP_3                                    1243
-#define IMG_GROUP_3_EDITOR                             1244
-#define IMG_GROUP_4                                    1245
-#define IMG_GROUP_4_EDITOR                             1246
-#define IMG_GROUP_5                                    1247
-#define IMG_GROUP_5_EDITOR                             1248
-#define IMG_GROUP_6                                    1249
-#define IMG_GROUP_6_EDITOR                             1250
-#define IMG_GROUP_7                                    1251
-#define IMG_GROUP_7_EDITOR                             1252
-#define IMG_GROUP_8                                    1253
-#define IMG_GROUP_8_EDITOR                             1254
-#define IMG_GROUP_9                                    1255
-#define IMG_GROUP_9_EDITOR                             1256
-#define IMG_GROUP_10                                   1257
-#define IMG_GROUP_10_EDITOR                            1258
-#define IMG_GROUP_11                                   1259
-#define IMG_GROUP_11_EDITOR                            1260
-#define IMG_GROUP_12                                   1261
-#define IMG_GROUP_12_EDITOR                            1262
-#define IMG_GROUP_13                                   1263
-#define IMG_GROUP_13_EDITOR                            1264
-#define IMG_GROUP_14                                   1265
-#define IMG_GROUP_14_EDITOR                            1266
-#define IMG_GROUP_15                                   1267
-#define IMG_GROUP_15_EDITOR                            1268
-#define IMG_GROUP_16                                   1269
-#define IMG_GROUP_16_EDITOR                            1270
-#define IMG_GROUP_17                                   1271
-#define IMG_GROUP_17_EDITOR                            1272
-#define IMG_GROUP_18                                   1273
-#define IMG_GROUP_18_EDITOR                            1274
-#define IMG_GROUP_19                                   1275
-#define IMG_GROUP_19_EDITOR                            1276
-#define IMG_GROUP_20                                   1277
-#define IMG_GROUP_20_EDITOR                            1278
-#define IMG_GROUP_21                                   1279
-#define IMG_GROUP_21_EDITOR                            1280
-#define IMG_GROUP_22                                   1281
-#define IMG_GROUP_22_EDITOR                            1282
-#define IMG_GROUP_23                                   1283
-#define IMG_GROUP_23_EDITOR                            1284
-#define IMG_GROUP_24                                   1285
-#define IMG_GROUP_24_EDITOR                            1286
-#define IMG_GROUP_25                                   1287
-#define IMG_GROUP_25_EDITOR                            1288
-#define IMG_GROUP_26                                   1289
-#define IMG_GROUP_26_EDITOR                            1290
-#define IMG_GROUP_27                                   1291
-#define IMG_GROUP_27_EDITOR                            1292
-#define IMG_GROUP_28                                   1293
-#define IMG_GROUP_28_EDITOR                            1294
-#define IMG_GROUP_29                                   1295
-#define IMG_GROUP_29_EDITOR                            1296
-#define IMG_GROUP_30                                   1297
-#define IMG_GROUP_30_EDITOR                            1298
-#define IMG_GROUP_31                                   1299
-#define IMG_GROUP_31_EDITOR                            1300
-#define IMG_GROUP_32                                   1301
-#define IMG_GROUP_32_EDITOR                            1302
-#define IMG_TOON_1                                     1303
-#define IMG_TOON_2                                     1304
-#define IMG_TOON_3                                     1305
-#define IMG_TOON_4                                     1306
-#define IMG_TOON_5                                     1307
-#define IMG_TOON_6                                     1308
-#define IMG_TOON_7                                     1309
-#define IMG_TOON_8                                     1310
-#define IMG_TOON_9                                     1311
-#define IMG_TOON_10                                    1312
-#define IMG_TOON_11                                    1313
-#define IMG_TOON_12                                    1314
-#define IMG_TOON_13                                    1315
-#define IMG_TOON_14                                    1316
-#define IMG_TOON_15                                    1317
-#define IMG_TOON_16                                    1318
-#define IMG_TOON_17                                    1319
-#define IMG_TOON_18                                    1320
-#define IMG_TOON_19                                    1321
-#define IMG_TOON_20                                    1322
-#define IMG_MENU_CALIBRATE_RED                         1323
-#define IMG_MENU_CALIBRATE_BLUE                                1324
-#define IMG_MENU_CALIBRATE_YELLOW                      1325
-#define IMG_MENU_BUTTON                                        1326
-#define IMG_MENU_BUTTON_ACTIVE                         1327
-#define IMG_MENU_BUTTON_LEFT                           1328
-#define IMG_MENU_BUTTON_RIGHT                          1329
-#define IMG_MENU_BUTTON_UP                             1330
-#define IMG_MENU_BUTTON_DOWN                           1331
-#define IMG_MENU_BUTTON_LEFT_ACTIVE                    1332
-#define IMG_MENU_BUTTON_RIGHT_ACTIVE                   1333
-#define IMG_MENU_BUTTON_UP_ACTIVE                      1334
-#define IMG_MENU_BUTTON_DOWN_ACTIVE                    1335
-#define IMG_MENU_SCROLLBAR                             1336
-#define IMG_MENU_SCROLLBAR_ACTIVE                      1337
-#define IMG_FONT_INITIAL_1                             1338
-#define IMG_FONT_INITIAL_2                             1339
-#define IMG_FONT_INITIAL_3                             1340
-#define IMG_FONT_INITIAL_4                             1341
-#define IMG_FONT_TITLE_1                               1342
-#define IMG_FONT_TITLE_1_LEVELS                                1343
-#define IMG_FONT_TITLE_2                               1344
-#define IMG_FONT_MENU_1                                        1345
-#define IMG_FONT_MENU_2                                        1346
-#define IMG_FONT_TEXT_1                                        1347
-#define IMG_FONT_TEXT_1_LEVELS                         1348
-#define IMG_FONT_TEXT_1_PREVIEW                                1349
-#define IMG_FONT_TEXT_1_SCORES                         1350
-#define IMG_FONT_TEXT_1_ACTIVE_SCORES                  1351
-#define IMG_FONT_TEXT_2                                        1352
-#define IMG_FONT_TEXT_2_LEVELS                         1353
-#define IMG_FONT_TEXT_2_PREVIEW                                1354
-#define IMG_FONT_TEXT_2_SCORES                         1355
-#define IMG_FONT_TEXT_2_ACTIVE_SCORES                  1356
-#define IMG_FONT_TEXT_3                                        1357
-#define IMG_FONT_TEXT_3_LEVELS                         1358
-#define IMG_FONT_TEXT_3_PREVIEW                                1359
-#define IMG_FONT_TEXT_3_SCORES                         1360
-#define IMG_FONT_TEXT_3_ACTIVE_SCORES                  1361
-#define IMG_FONT_TEXT_4                                        1362
-#define IMG_FONT_TEXT_4_LEVELS                         1363
-#define IMG_FONT_TEXT_4_SCORES                         1364
-#define IMG_FONT_TEXT_4_ACTIVE_SCORES                  1365
-#define IMG_FONT_ENVELOPE_1                            1366
-#define IMG_FONT_ENVELOPE_2                            1367
-#define IMG_FONT_ENVELOPE_3                            1368
-#define IMG_FONT_ENVELOPE_4                            1369
-#define IMG_FONT_INPUT_1                               1370
-#define IMG_FONT_INPUT_1_MAIN                          1371
-#define IMG_FONT_INPUT_1_ACTIVE                                1372
-#define IMG_FONT_INPUT_1_ACTIVE_MAIN                   1373
-#define IMG_FONT_INPUT_1_ACTIVE_SETUP                  1374
-#define IMG_FONT_INPUT_2                               1375
-#define IMG_FONT_INPUT_2_ACTIVE                                1376
-#define IMG_FONT_OPTION_OFF                            1377
-#define IMG_FONT_OPTION_ON                             1378
-#define IMG_FONT_VALUE_1                               1379
-#define IMG_FONT_VALUE_2                               1380
-#define IMG_FONT_VALUE_OLD                             1381
-#define IMG_FONT_LEVEL_NUMBER                          1382
-#define IMG_FONT_TAPE_RECORDER                         1383
-#define IMG_FONT_GAME_INFO                             1384
-#define IMG_GLOBAL_BORDER                              1385
-#define IMG_GLOBAL_DOOR                                        1386
-#define IMG_EDITOR_ELEMENT_BORDER                      1387
-#define IMG_EDITOR_ELEMENT_BORDER_INPUT                        1388
-#define IMG_BACKGROUND_ENVELOPE_1                      1389
-#define IMG_BACKGROUND_ENVELOPE_2                      1390
-#define IMG_BACKGROUND_ENVELOPE_3                      1391
-#define IMG_BACKGROUND_ENVELOPE_4                      1392
-#define IMG_BACKGROUND                                 1393
-#define IMG_BACKGROUND_MAIN                            1394
-#define IMG_BACKGROUND_LEVELS                          1395
-#define IMG_BACKGROUND_SCORES                          1396
-#define IMG_BACKGROUND_EDITOR                          1397
-#define IMG_BACKGROUND_INFO                            1398
-#define IMG_BACKGROUND_INFO_ELEMENTS                   1399
-#define IMG_BACKGROUND_SETUP                           1400
-#define IMG_BACKGROUND_DOOR                            1401
+#define IMG_BD_BUTTERFLY_RIGHT                         20
+#define IMG_BD_BUTTERFLY_RIGHT_EDITOR                  21
+#define IMG_BD_BUTTERFLY_UP                            22
+#define IMG_BD_BUTTERFLY_UP_EDITOR                     23
+#define IMG_BD_BUTTERFLY_LEFT                          24
+#define IMG_BD_BUTTERFLY_LEFT_EDITOR                   25
+#define IMG_BD_BUTTERFLY_DOWN                          26
+#define IMG_BD_BUTTERFLY_DOWN_EDITOR                   27
+#define IMG_BD_FIREFLY                                 28
+#define IMG_BD_FIREFLY_RIGHT                           29
+#define IMG_BD_FIREFLY_RIGHT_EDITOR                    30
+#define IMG_BD_FIREFLY_UP                              31
+#define IMG_BD_FIREFLY_UP_EDITOR                       32
+#define IMG_BD_FIREFLY_LEFT                            33
+#define IMG_BD_FIREFLY_LEFT_EDITOR                     34
+#define IMG_BD_FIREFLY_DOWN                            35
+#define IMG_BD_FIREFLY_DOWN_EDITOR                     36
+#define IMG_SP_DEFAULT_EXPLODING                       37
+#define IMG_SP_ZONK                                    38
+#define IMG_SP_ZONK_MOVING_LEFT                                39
+#define IMG_SP_ZONK_MOVING_RIGHT                       40
+#define IMG_SP_ZONK_PUSHING_LEFT                       41
+#define IMG_SP_ZONK_PUSHING_RIGHT                      42
+#define IMG_SP_BASE                                    43
+#define IMG_SP_MURPHY                                  44
+#define IMG_SP_MURPHY_MOVING_LEFT                      45
+#define IMG_SP_MURPHY_MOVING_RIGHT                     46
+#define IMG_SP_MURPHY_DIGGING_LEFT                     47
+#define IMG_SP_MURPHY_DIGGING_RIGHT                    48
+#define IMG_SP_MURPHY_COLLECTING_LEFT                  49
+#define IMG_SP_MURPHY_COLLECTING_RIGHT                 50
+#define IMG_SP_MURPHY_PUSHING_LEFT                     51
+#define IMG_SP_MURPHY_PUSHING_RIGHT                    52
+#define IMG_SP_MURPHY_SNAPPING_LEFT                    53
+#define IMG_SP_MURPHY_SNAPPING_RIGHT                   54
+#define IMG_SP_MURPHY_SNAPPING_UP                      55
+#define IMG_SP_MURPHY_SNAPPING_DOWN                    56
+#define IMG_SP_MURPHY_CLONE                            57
+#define IMG_SP_INFOTRON                                        58
+#define IMG_SP_INFOTRON_EDITOR                         59
+#define IMG_SP_CHIP_SINGLE                             60
+#define IMG_SP_CHIP_LEFT                               61
+#define IMG_SP_CHIP_RIGHT                              62
+#define IMG_SP_CHIP_TOP                                        63
+#define IMG_SP_CHIP_BOTTOM                             64
+#define IMG_SP_HARDWARE_GRAY                           65
+#define IMG_SP_HARDWARE_GREEN                          66
+#define IMG_SP_HARDWARE_BLUE                           67
+#define IMG_SP_HARDWARE_RED                            68
+#define IMG_SP_HARDWARE_YELLOW                         69
+#define IMG_SP_EXIT_CLOSED                             70
+#define IMG_SP_EXIT_OPENING                            71
+#define IMG_SP_EXIT_OPEN                               72
+#define IMG_SP_EXIT_CLOSING                            73
+#define IMG_SP_DISK_ORANGE                             74
+#define IMG_SP_DISK_YELLOW                             75
+#define IMG_SP_DISK_RED                                        76
+#define IMG_SP_DISK_RED_COLLECTING                     77
+#define IMG_SP_DISK_RED_ACTIVE                         78
+#define IMG_SP_PORT_RIGHT                              79
+#define IMG_SP_PORT_DOWN                               80
+#define IMG_SP_PORT_LEFT                               81
+#define IMG_SP_PORT_UP                                 82
+#define IMG_SP_PORT_HORIZONTAL                         83
+#define IMG_SP_PORT_VERTICAL                           84
+#define IMG_SP_PORT_ANY                                        85
+#define IMG_SP_GRAVITY_PORT_RIGHT                      86
+#define IMG_SP_GRAVITY_PORT_RIGHT_EDITOR               87
+#define IMG_SP_GRAVITY_PORT_DOWN                       88
+#define IMG_SP_GRAVITY_PORT_DOWN_EDITOR                        89
+#define IMG_SP_GRAVITY_PORT_LEFT                       90
+#define IMG_SP_GRAVITY_PORT_LEFT_EDITOR                        91
+#define IMG_SP_GRAVITY_PORT_UP                         92
+#define IMG_SP_GRAVITY_PORT_UP_EDITOR                  93
+#define IMG_SP_GRAVITY_ON_PORT_RIGHT                   94
+#define IMG_SP_GRAVITY_ON_PORT_RIGHT_EDITOR            95
+#define IMG_SP_GRAVITY_ON_PORT_DOWN                    96
+#define IMG_SP_GRAVITY_ON_PORT_DOWN_EDITOR             97
+#define IMG_SP_GRAVITY_ON_PORT_LEFT                    98
+#define IMG_SP_GRAVITY_ON_PORT_LEFT_EDITOR             99
+#define IMG_SP_GRAVITY_ON_PORT_UP                      100
+#define IMG_SP_GRAVITY_ON_PORT_UP_EDITOR               101
+#define IMG_SP_GRAVITY_OFF_PORT_RIGHT                  102
+#define IMG_SP_GRAVITY_OFF_PORT_RIGHT_EDITOR           103
+#define IMG_SP_GRAVITY_OFF_PORT_DOWN                   104
+#define IMG_SP_GRAVITY_OFF_PORT_DOWN_EDITOR            105
+#define IMG_SP_GRAVITY_OFF_PORT_LEFT                   106
+#define IMG_SP_GRAVITY_OFF_PORT_LEFT_EDITOR            107
+#define IMG_SP_GRAVITY_OFF_PORT_UP                     108
+#define IMG_SP_GRAVITY_OFF_PORT_UP_EDITOR              109
+#define IMG_SP_SNIKSNAK                                        110
+#define IMG_SP_SNIKSNAK_LEFT                           111
+#define IMG_SP_SNIKSNAK_RIGHT                          112
+#define IMG_SP_SNIKSNAK_UP                             113
+#define IMG_SP_SNIKSNAK_DOWN                           114
+#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_UP           115
+#define IMG_SP_SNIKSNAK_TURNING_FROM_LEFT_DOWN         116
+#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_UP          117
+#define IMG_SP_SNIKSNAK_TURNING_FROM_RIGHT_DOWN                118
+#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_LEFT           119
+#define IMG_SP_SNIKSNAK_TURNING_FROM_UP_RIGHT          120
+#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_LEFT         121
+#define IMG_SP_SNIKSNAK_TURNING_FROM_DOWN_RIGHT                122
+#define IMG_SP_ELECTRON                                        123
+#define IMG_SP_ELECTRON_EDITOR                         124
+#define IMG_SP_ELECTRON_EXPLODING                      125
+#define IMG_SP_TERMINAL                                        126
+#define IMG_SP_TERMINAL_EDITOR                         127
+#define IMG_SP_TERMINAL_ACTIVE                         128
+#define IMG_SP_BUGGY_BASE                              129
+#define IMG_SP_BUGGY_BASE_EDITOR                       130
+#define IMG_SP_BUGGY_BASE_ACTIVATING                   131
+#define IMG_SP_BUGGY_BASE_ACTIVE                       132
+#define IMG_SP_HARDWARE_BASE_1                         133
+#define IMG_SP_HARDWARE_BASE_2                         134
+#define IMG_SP_HARDWARE_BASE_3                         135
+#define IMG_SP_HARDWARE_BASE_4                         136
+#define IMG_SP_HARDWARE_BASE_5                         137
+#define IMG_SP_HARDWARE_BASE_6                         138
+#define IMG_SOKOBAN_OBJECT                             139
+#define IMG_SOKOBAN_OBJECT_EDITOR                      140
+#define IMG_SOKOBAN_FIELD_EMPTY                                141
+#define IMG_SOKOBAN_FIELD_FULL                         142
+#define IMG_SOKOBAN_FIELD_PLAYER                       143
+#define IMG_SOKOBAN_FIELD_PLAYER_EDITOR                        144
+#define IMG_EMPTY_SPACE                                        145
+#define IMG_SAND                                       146
+#define IMG_SAND_CRUMBLED                              147
+#define IMG_SAND_DIGGING_LEFT                          148
+#define IMG_SAND_DIGGING_RIGHT                         149
+#define IMG_SAND_DIGGING_UP                            150
+#define IMG_SAND_DIGGING_DOWN                          151
+#define IMG_SAND_DIGGING_LEFT_CRUMBLED                 152
+#define IMG_SAND_DIGGING_RIGHT_CRUMBLED                        153
+#define IMG_SAND_DIGGING_UP_CRUMBLED                   154
+#define IMG_SAND_DIGGING_DOWN_CRUMBLED                 155
+#define IMG_WALL                                       156
+#define IMG_WALL_SLIPPERY                              157
+#define IMG_STEELWALL                                  158
+#define IMG_ROCK                                       159
+#define IMG_ROCK_MOVING_LEFT                           160
+#define IMG_ROCK_MOVING_RIGHT                          161
+#define IMG_ROCK_PUSHING_LEFT                          162
+#define IMG_ROCK_PUSHING_RIGHT                         163
+#define IMG_EMERALD                                    164
+#define IMG_EMERALD_MOVING                             165
+#define IMG_EMERALD_FALLING                            166
+#define IMG_EMERALD_COLLECTING                         167
+#define IMG_DIAMOND                                    168
+#define IMG_DIAMOND_MOVING                             169
+#define IMG_DIAMOND_FALLING                            170
+#define IMG_DIAMOND_COLLECTING                         171
+#define IMG_BOMB                                       172
+#define IMG_NUT                                                173
+#define IMG_NUT_BREAKING                               174
+#define IMG_DYNAMITE                                   175
+#define IMG_DYNAMITE_EDITOR                            176
+#define IMG_DYNAMITE_ACTIVE                            177
+#define IMG_DYNAMITE_ACTIVE_EDITOR                     178
+#define IMG_WALL_EMERALD                               179
+#define IMG_WALL_DIAMOND                               180
+#define IMG_BUG                                                181
+#define IMG_BUG_RIGHT                                  182
+#define IMG_BUG_UP                                     183
+#define IMG_BUG_LEFT                                   184
+#define IMG_BUG_DOWN                                   185
+#define IMG_BUG_MOVING_RIGHT                           186
+#define IMG_BUG_MOVING_UP                              187
+#define IMG_BUG_MOVING_LEFT                            188
+#define IMG_BUG_MOVING_DOWN                            189
+#define IMG_BUG_TURNING_FROM_RIGHT_UP                  190
+#define IMG_BUG_TURNING_FROM_UP_LEFT                   191
+#define IMG_BUG_TURNING_FROM_LEFT_DOWN                 192
+#define IMG_BUG_TURNING_FROM_DOWN_RIGHT                        193
+#define IMG_BUG_TURNING_FROM_RIGHT_DOWN                        194
+#define IMG_BUG_TURNING_FROM_UP_RIGHT                  195
+#define IMG_BUG_TURNING_FROM_LEFT_UP                   196
+#define IMG_BUG_TURNING_FROM_DOWN_LEFT                 197
+#define IMG_SPACESHIP                                  198
+#define IMG_SPACESHIP_RIGHT                            199
+#define IMG_SPACESHIP_UP                               200
+#define IMG_SPACESHIP_LEFT                             201
+#define IMG_SPACESHIP_DOWN                             202
+#define IMG_SPACESHIP_MOVING_RIGHT                     203
+#define IMG_SPACESHIP_MOVING_UP                                204
+#define IMG_SPACESHIP_MOVING_LEFT                      205
+#define IMG_SPACESHIP_MOVING_DOWN                      206
+#define IMG_SPACESHIP_TURNING_FROM_RIGHT_UP            207
+#define IMG_SPACESHIP_TURNING_FROM_UP_LEFT             208
+#define IMG_SPACESHIP_TURNING_FROM_LEFT_DOWN           209
+#define IMG_SPACESHIP_TURNING_FROM_DOWN_RIGHT          210
+#define IMG_SPACESHIP_TURNING_FROM_RIGHT_DOWN          211
+#define IMG_SPACESHIP_TURNING_FROM_UP_RIGHT            212
+#define IMG_SPACESHIP_TURNING_FROM_LEFT_UP             213
+#define IMG_SPACESHIP_TURNING_FROM_DOWN_LEFT           214
+#define IMG_YAMYAM                                     215
+#define IMG_YAMYAM_MOVING                              216
+#define IMG_ROBOT                                      217
+#define IMG_ROBOT_MOVING                               218
+#define IMG_ROBOT_WHEEL                                        219
+#define IMG_ROBOT_WHEEL_ACTIVE                         220
+#define IMG_MAGIC_WALL                                 221
+#define IMG_MAGIC_WALL_ACTIVE                          222
+#define IMG_MAGIC_WALL_FILLING                         223
+#define IMG_MAGIC_WALL_FULL                            224
+#define IMG_MAGIC_WALL_EMPTYING                                225
+#define IMG_MAGIC_WALL_DEAD                            226
+#define IMG_QUICKSAND_EMPTY                            227
+#define IMG_QUICKSAND_FILLING                          228
+#define IMG_QUICKSAND_FULL                             229
+#define IMG_QUICKSAND_FULL_EDITOR                      230
+#define IMG_QUICKSAND_EMPTYING                         231
+#define IMG_ACID_POOL_TOPLEFT                          232
+#define IMG_ACID_POOL_TOPRIGHT                         233
+#define IMG_ACID_POOL_BOTTOMLEFT                       234
+#define IMG_ACID_POOL_BOTTOM                           235
+#define IMG_ACID_POOL_BOTTOMRIGHT                      236
+#define IMG_ACID                                       237
+#define IMG_ACID_SPLASH_LEFT                           238
+#define IMG_ACID_SPLASH_RIGHT                          239
+#define IMG_AMOEBA_DROP                                        240
+#define IMG_AMOEBA_GROWING                             241
+#define IMG_AMOEBA_SHRINKING                           242
+#define IMG_AMOEBA_WET                                 243
+#define IMG_AMOEBA_WET_EDITOR                          244
+#define IMG_AMOEBA_DROPPING                            245
+#define IMG_AMOEBA_DRY                                 246
+#define IMG_AMOEBA_FULL                                        247
+#define IMG_AMOEBA_FULL_EDITOR                         248
+#define IMG_AMOEBA_DEAD                                        249
+#define IMG_AMOEBA_DEAD_EDITOR                         250
+#define IMG_EM_KEY_1                                   251
+#define IMG_EM_KEY_2                                   252
+#define IMG_EM_KEY_3                                   253
+#define IMG_EM_KEY_4                                   254
+#define IMG_EM_GATE_1                                  255
+#define IMG_EM_GATE_2                                  256
+#define IMG_EM_GATE_3                                  257
+#define IMG_EM_GATE_4                                  258
+#define IMG_EM_GATE_1_GRAY                             259
+#define IMG_EM_GATE_1_GRAY_EDITOR                      260
+#define IMG_EM_GATE_2_GRAY                             261
+#define IMG_EM_GATE_2_GRAY_EDITOR                      262
+#define IMG_EM_GATE_3_GRAY                             263
+#define IMG_EM_GATE_3_GRAY_EDITOR                      264
+#define IMG_EM_GATE_4_GRAY                             265
+#define IMG_EM_GATE_4_GRAY_EDITOR                      266
+#define IMG_EXIT_CLOSED                                        267
+#define IMG_EXIT_OPENING                               268
+#define IMG_EXIT_OPEN                                  269
+#define IMG_EXIT_CLOSING                               270
+#define IMG_BALLOON                                    271
+#define IMG_BALLOON_MOVING                             272
+#define IMG_BALLOON_PUSHING                            273
+#define IMG_BALLOON_SWITCH_LEFT                                274
+#define IMG_BALLOON_SWITCH_RIGHT                       275
+#define IMG_BALLOON_SWITCH_UP                          276
+#define IMG_BALLOON_SWITCH_DOWN                                277
+#define IMG_BALLOON_SWITCH_ANY                         278
+#define IMG_BALLOON_SWITCH_NONE                                279
+#define IMG_SPRING                                     280
+#define IMG_EMC_STEELWALL_1                            281
+#define IMG_EMC_STEELWALL_2                            282
+#define IMG_EMC_STEELWALL_3                            283
+#define IMG_EMC_STEELWALL_4                            284
+#define IMG_EMC_WALL_1                                 285
+#define IMG_EMC_WALL_2                                 286
+#define IMG_EMC_WALL_3                                 287
+#define IMG_EMC_WALL_4                                 288
+#define IMG_EMC_WALL_5                                 289
+#define IMG_EMC_WALL_6                                 290
+#define IMG_EMC_WALL_7                                 291
+#define IMG_EMC_WALL_8                                 292
+#define IMG_INVISIBLE_STEELWALL                                293
+#define IMG_INVISIBLE_STEELWALL_EDITOR                 294
+#define IMG_INVISIBLE_STEELWALL_ACTIVE                 295
+#define IMG_INVISIBLE_WALL                             296
+#define IMG_INVISIBLE_WALL_EDITOR                      297
+#define IMG_INVISIBLE_WALL_ACTIVE                      298
+#define IMG_INVISIBLE_SAND                             299
+#define IMG_INVISIBLE_SAND_EDITOR                      300
+#define IMG_INVISIBLE_SAND_ACTIVE                      301
+#define IMG_INVISIBLE_SAND_ACTIVE_CRUMBLED             302
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT         303
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT                304
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP           305
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN         306
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_LEFT_CRUMBLED        307
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_RIGHT_CRUMBLED       308
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_UP_CRUMBLED  309
+#define IMG_INVISIBLE_SAND_ACTIVE_DIGGING_DOWN_CRUMBLED        310
+#define IMG_CONVEYOR_BELT_1_MIDDLE                     311
+#define IMG_CONVEYOR_BELT_1_MIDDLE_ACTIVE              312
+#define IMG_CONVEYOR_BELT_1_LEFT                       313
+#define IMG_CONVEYOR_BELT_1_LEFT_ACTIVE                        314
+#define IMG_CONVEYOR_BELT_1_RIGHT                      315
+#define IMG_CONVEYOR_BELT_1_RIGHT_ACTIVE               316
+#define IMG_CONVEYOR_BELT_1_SWITCH_LEFT                        317
+#define IMG_CONVEYOR_BELT_1_SWITCH_MIDDLE              318
+#define IMG_CONVEYOR_BELT_1_SWITCH_RIGHT               319
+#define IMG_CONVEYOR_BELT_2_MIDDLE                     320
+#define IMG_CONVEYOR_BELT_2_MIDDLE_ACTIVE              321
+#define IMG_CONVEYOR_BELT_2_LEFT                       322
+#define IMG_CONVEYOR_BELT_2_LEFT_ACTIVE                        323
+#define IMG_CONVEYOR_BELT_2_RIGHT                      324
+#define IMG_CONVEYOR_BELT_2_RIGHT_ACTIVE               325
+#define IMG_CONVEYOR_BELT_2_SWITCH_LEFT                        326
+#define IMG_CONVEYOR_BELT_2_SWITCH_MIDDLE              327
+#define IMG_CONVEYOR_BELT_2_SWITCH_RIGHT               328
+#define IMG_CONVEYOR_BELT_3_MIDDLE                     329
+#define IMG_CONVEYOR_BELT_3_MIDDLE_ACTIVE              330
+#define IMG_CONVEYOR_BELT_3_LEFT                       331
+#define IMG_CONVEYOR_BELT_3_LEFT_ACTIVE                        332
+#define IMG_CONVEYOR_BELT_3_RIGHT                      333
+#define IMG_CONVEYOR_BELT_3_RIGHT_ACTIVE               334
+#define IMG_CONVEYOR_BELT_3_SWITCH_LEFT                        335
+#define IMG_CONVEYOR_BELT_3_SWITCH_MIDDLE              336
+#define IMG_CONVEYOR_BELT_3_SWITCH_RIGHT               337
+#define IMG_CONVEYOR_BELT_4_MIDDLE                     338
+#define IMG_CONVEYOR_BELT_4_MIDDLE_ACTIVE              339
+#define IMG_CONVEYOR_BELT_4_LEFT                       340
+#define IMG_CONVEYOR_BELT_4_LEFT_ACTIVE                        341
+#define IMG_CONVEYOR_BELT_4_RIGHT                      342
+#define IMG_CONVEYOR_BELT_4_RIGHT_ACTIVE               343
+#define IMG_CONVEYOR_BELT_4_SWITCH_LEFT                        344
+#define IMG_CONVEYOR_BELT_4_SWITCH_MIDDLE              345
+#define IMG_CONVEYOR_BELT_4_SWITCH_RIGHT               346
+#define IMG_SWITCHGATE_SWITCH_UP                       347
+#define IMG_SWITCHGATE_SWITCH_DOWN                     348
+#define IMG_LIGHT_SWITCH                               349
+#define IMG_LIGHT_SWITCH_ACTIVE                                350
+#define IMG_TIMEGATE_SWITCH                            351
+#define IMG_TIMEGATE_SWITCH_ACTIVE                     352
+#define IMG_ENVELOPE_1                                 353
+#define IMG_ENVELOPE_1_COLLECTING                      354
+#define IMG_ENVELOPE_2                                 355
+#define IMG_ENVELOPE_2_COLLECTING                      356
+#define IMG_ENVELOPE_3                                 357
+#define IMG_ENVELOPE_3_COLLECTING                      358
+#define IMG_ENVELOPE_4                                 359
+#define IMG_ENVELOPE_4_COLLECTING                      360
+#define IMG_SIGN_EXCLAMATION                           361
+#define IMG_SIGN_STOP                                  362
+#define IMG_LANDMINE                                   363
+#define IMG_STEELWALL_SLIPPERY                         364
+#define IMG_EXTRA_TIME                                 365
+#define IMG_SHIELD_NORMAL                              366
+#define IMG_SHIELD_NORMAL_ACTIVE                       367
+#define IMG_SHIELD_DEADLY                              368
+#define IMG_SHIELD_DEADLY_ACTIVE                       369
+#define IMG_SWITCHGATE_CLOSED                          370
+#define IMG_SWITCHGATE_OPENING                         371
+#define IMG_SWITCHGATE_OPEN                            372
+#define IMG_SWITCHGATE_CLOSING                         373
+#define IMG_TIMEGATE_CLOSED                            374
+#define IMG_TIMEGATE_OPENING                           375
+#define IMG_TIMEGATE_OPEN                              376
+#define IMG_TIMEGATE_CLOSING                           377
+#define IMG_PEARL                                      378
+#define IMG_PEARL_BREAKING                             379
+#define IMG_CRYSTAL                                    380
+#define IMG_WALL_PEARL                                 381
+#define IMG_WALL_CRYSTAL                               382
+#define IMG_TUBE_RIGHT_DOWN                            383
+#define IMG_TUBE_HORIZONTAL_DOWN                       384
+#define IMG_TUBE_LEFT_DOWN                             385
+#define IMG_TUBE_HORIZONTAL                            386
+#define IMG_TUBE_VERTICAL_RIGHT                                387
+#define IMG_TUBE_ANY                                   388
+#define IMG_TUBE_VERTICAL_LEFT                         389
+#define IMG_TUBE_VERTICAL                              390
+#define IMG_TUBE_RIGHT_UP                              391
+#define IMG_TUBE_HORIZONTAL_UP                         392
+#define IMG_TUBE_LEFT_UP                               393
+#define IMG_TRAP                                       394
+#define IMG_TRAP_ACTIVE                                        395
+#define IMG_DX_SUPABOMB                                        396
+#define IMG_KEY_1                                      397
+#define IMG_KEY_1_EDITOR                               398
+#define IMG_KEY_2                                      399
+#define IMG_KEY_2_EDITOR                               400
+#define IMG_KEY_3                                      401
+#define IMG_KEY_3_EDITOR                               402
+#define IMG_KEY_4                                      403
+#define IMG_KEY_4_EDITOR                               404
+#define IMG_GATE_1                                     405
+#define IMG_GATE_2                                     406
+#define IMG_GATE_3                                     407
+#define IMG_GATE_4                                     408
+#define IMG_GATE_1_GRAY                                        409
+#define IMG_GATE_1_GRAY_EDITOR                         410
+#define IMG_GATE_2_GRAY                                        411
+#define IMG_GATE_2_GRAY_EDITOR                         412
+#define IMG_GATE_3_GRAY                                        413
+#define IMG_GATE_3_GRAY_EDITOR                         414
+#define IMG_GATE_4_GRAY                                        415
+#define IMG_GATE_4_GRAY_EDITOR                         416
+#define IMG_GAME_OF_LIFE                               417
+#define IMG_BIOMAZE                                    418
+#define IMG_PACMAN                                     419
+#define IMG_PACMAN_RIGHT                               420
+#define IMG_PACMAN_UP                                  421
+#define IMG_PACMAN_LEFT                                        422
+#define IMG_PACMAN_DOWN                                        423
+#define IMG_PACMAN_TURNING_FROM_RIGHT                  424
+#define IMG_PACMAN_TURNING_FROM_UP                     425
+#define IMG_PACMAN_TURNING_FROM_LEFT                   426
+#define IMG_PACMAN_TURNING_FROM_DOWN                   427
+#define IMG_LAMP                                       428
+#define IMG_LAMP_EDITOR                                        429
+#define IMG_LAMP_ACTIVE                                        430
+#define IMG_TIME_ORB_FULL                              431
+#define IMG_TIME_ORB_EMPTY                             432
+#define IMG_EMERALD_YELLOW                             433
+#define IMG_EMERALD_YELLOW_MOVING                      434
+#define IMG_EMERALD_YELLOW_FALLING                     435
+#define IMG_EMERALD_RED                                        436
+#define IMG_EMERALD_RED_MOVING                         437
+#define IMG_EMERALD_RED_FALLING                                438
+#define IMG_EMERALD_PURPLE                             439
+#define IMG_EMERALD_PURPLE_MOVING                      440
+#define IMG_EMERALD_PURPLE_FALLING                     441
+#define IMG_WALL_EMERALD_YELLOW                                442
+#define IMG_WALL_EMERALD_RED                           443
+#define IMG_WALL_EMERALD_PURPLE                                444
+#define IMG_WALL_BD_DIAMOND                            445
+#define IMG_EXPANDABLE_WALL                            446
+#define IMG_EXPANDABLE_WALL_HORIZONTAL                 447
+#define IMG_EXPANDABLE_WALL_HORIZONTAL_EDITOR          448
+#define IMG_EXPANDABLE_WALL_VERTICAL                   449
+#define IMG_EXPANDABLE_WALL_VERTICAL_EDITOR            450
+#define IMG_EXPANDABLE_WALL_ANY                                451
+#define IMG_EXPANDABLE_WALL_ANY_EDITOR                 452
+#define IMG_EXPANDABLE_WALL_GROWING_LEFT               453
+#define IMG_EXPANDABLE_WALL_GROWING_RIGHT              454
+#define IMG_EXPANDABLE_WALL_GROWING_UP                 455
+#define IMG_EXPANDABLE_WALL_GROWING_DOWN               456
+#define IMG_BLACK_ORB                                  457
+#define IMG_SPEED_PILL                                 458
+#define IMG_DARK_YAMYAM                                        459
+#define IMG_DYNABOMB                                   460
+#define IMG_DYNABOMB_ACTIVE                            461
+#define IMG_DYNABOMB_PLAYER_1                          462
+#define IMG_DYNABOMB_PLAYER_1_ACTIVE                   463
+#define IMG_DYNABOMB_PLAYER_2                          464
+#define IMG_DYNABOMB_PLAYER_2_ACTIVE                   465
+#define IMG_DYNABOMB_PLAYER_3                          466
+#define IMG_DYNABOMB_PLAYER_3_ACTIVE                   467
+#define IMG_DYNABOMB_PLAYER_4                          468
+#define IMG_DYNABOMB_PLAYER_4_ACTIVE                   469
+#define IMG_DYNABOMB_INCREASE_NUMBER                   470
+#define IMG_DYNABOMB_INCREASE_SIZE                     471
+#define IMG_DYNABOMB_INCREASE_POWER                    472
+#define IMG_PIG                                                473
+#define IMG_PIG_DOWN                                   474
+#define IMG_PIG_UP                                     475
+#define IMG_PIG_LEFT                                   476
+#define IMG_PIG_RIGHT                                  477
+#define IMG_PIG_MOVING_DOWN                            478
+#define IMG_PIG_MOVING_UP                              479
+#define IMG_PIG_MOVING_LEFT                            480
+#define IMG_PIG_MOVING_RIGHT                           481
+#define IMG_PIG_DIGGING_DOWN                           482
+#define IMG_PIG_DIGGING_UP                             483
+#define IMG_PIG_DIGGING_LEFT                           484
+#define IMG_PIG_DIGGING_RIGHT                          485
+#define IMG_DRAGON                                     486
+#define IMG_DRAGON_DOWN                                        487
+#define IMG_DRAGON_UP                                  488
+#define IMG_DRAGON_LEFT                                        489
+#define IMG_DRAGON_RIGHT                               490
+#define IMG_DRAGON_MOVING_DOWN                         491
+#define IMG_DRAGON_MOVING_UP                           492
+#define IMG_DRAGON_MOVING_LEFT                         493
+#define IMG_DRAGON_MOVING_RIGHT                                494
+#define IMG_DRAGON_ATTACKING_DOWN                      495
+#define IMG_DRAGON_ATTACKING_UP                                496
+#define IMG_DRAGON_ATTACKING_LEFT                      497
+#define IMG_DRAGON_ATTACKING_RIGHT                     498
+#define IMG_MOLE                                       499
+#define IMG_MOLE_DOWN                                  500
+#define IMG_MOLE_UP                                    501
+#define IMG_MOLE_LEFT                                  502
+#define IMG_MOLE_RIGHT                                 503
+#define IMG_MOLE_MOVING_DOWN                           504
+#define IMG_MOLE_MOVING_UP                             505
+#define IMG_MOLE_MOVING_LEFT                           506
+#define IMG_MOLE_MOVING_RIGHT                          507
+#define IMG_MOLE_DIGGING_DOWN                          508
+#define IMG_MOLE_DIGGING_UP                            509
+#define IMG_MOLE_DIGGING_LEFT                          510
+#define IMG_MOLE_DIGGING_RIGHT                         511
+#define IMG_PENGUIN                                    512
+#define IMG_PENGUIN_EDITOR                             513
+#define IMG_PENGUIN_DOWN                               514
+#define IMG_PENGUIN_UP                                 515
+#define IMG_PENGUIN_LEFT                               516
+#define IMG_PENGUIN_RIGHT                              517
+#define IMG_PENGUIN_MOVING_DOWN                                518
+#define IMG_PENGUIN_MOVING_UP                          519
+#define IMG_PENGUIN_MOVING_LEFT                                520
+#define IMG_PENGUIN_MOVING_RIGHT                       521
+#define IMG_SATELLITE                                  522
+#define IMG_FLAMES_1_LEFT                              523
+#define IMG_FLAMES_2_LEFT                              524
+#define IMG_FLAMES_3_LEFT                              525
+#define IMG_FLAMES_1_RIGHT                             526
+#define IMG_FLAMES_2_RIGHT                             527
+#define IMG_FLAMES_3_RIGHT                             528
+#define IMG_FLAMES_1_UP                                        529
+#define IMG_FLAMES_2_UP                                        530
+#define IMG_FLAMES_3_UP                                        531
+#define IMG_FLAMES_1_DOWN                              532
+#define IMG_FLAMES_2_DOWN                              533
+#define IMG_FLAMES_3_DOWN                              534
+#define IMG_STONEBLOCK                                 535
+#define IMG_PLAYER_1                                   536
+#define IMG_PLAYER_1_EDITOR                            537
+#define IMG_PLAYER_1_DOWN                              538
+#define IMG_PLAYER_1_UP                                        539
+#define IMG_PLAYER_1_LEFT                              540
+#define IMG_PLAYER_1_RIGHT                             541
+#define IMG_PLAYER_1_MOVING_DOWN                       542
+#define IMG_PLAYER_1_MOVING_UP                         543
+#define IMG_PLAYER_1_MOVING_LEFT                       544
+#define IMG_PLAYER_1_MOVING_RIGHT                      545
+#define IMG_PLAYER_1_DIGGING_DOWN                      546
+#define IMG_PLAYER_1_DIGGING_UP                                547
+#define IMG_PLAYER_1_DIGGING_LEFT                      548
+#define IMG_PLAYER_1_DIGGING_RIGHT                     549
+#define IMG_PLAYER_1_COLLECTING_DOWN                   550
+#define IMG_PLAYER_1_COLLECTING_UP                     551
+#define IMG_PLAYER_1_COLLECTING_LEFT                   552
+#define IMG_PLAYER_1_COLLECTING_RIGHT                  553
+#define IMG_PLAYER_1_PUSHING_DOWN                      554
+#define IMG_PLAYER_1_PUSHING_UP                                555
+#define IMG_PLAYER_1_PUSHING_LEFT                      556
+#define IMG_PLAYER_1_PUSHING_RIGHT                     557
+#define IMG_PLAYER_1_SNAPPING_DOWN                     558
+#define IMG_PLAYER_1_SNAPPING_UP                       559
+#define IMG_PLAYER_1_SNAPPING_LEFT                     560
+#define IMG_PLAYER_1_SNAPPING_RIGHT                    561
+#define IMG_PLAYER_2                                   562
+#define IMG_PLAYER_2_EDITOR                            563
+#define IMG_PLAYER_2_DOWN                              564
+#define IMG_PLAYER_2_UP                                        565
+#define IMG_PLAYER_2_LEFT                              566
+#define IMG_PLAYER_2_RIGHT                             567
+#define IMG_PLAYER_2_MOVING_DOWN                       568
+#define IMG_PLAYER_2_MOVING_UP                         569
+#define IMG_PLAYER_2_MOVING_LEFT                       570
+#define IMG_PLAYER_2_MOVING_RIGHT                      571
+#define IMG_PLAYER_2_DIGGING_DOWN                      572
+#define IMG_PLAYER_2_DIGGING_UP                                573
+#define IMG_PLAYER_2_DIGGING_LEFT                      574
+#define IMG_PLAYER_2_DIGGING_RIGHT                     575
+#define IMG_PLAYER_2_COLLECTING_DOWN                   576
+#define IMG_PLAYER_2_COLLECTING_UP                     577
+#define IMG_PLAYER_2_COLLECTING_LEFT                   578
+#define IMG_PLAYER_2_COLLECTING_RIGHT                  579
+#define IMG_PLAYER_2_PUSHING_DOWN                      580
+#define IMG_PLAYER_2_PUSHING_UP                                581
+#define IMG_PLAYER_2_PUSHING_LEFT                      582
+#define IMG_PLAYER_2_PUSHING_RIGHT                     583
+#define IMG_PLAYER_2_SNAPPING_DOWN                     584
+#define IMG_PLAYER_2_SNAPPING_UP                       585
+#define IMG_PLAYER_2_SNAPPING_LEFT                     586
+#define IMG_PLAYER_2_SNAPPING_RIGHT                    587
+#define IMG_PLAYER_3                                   588
+#define IMG_PLAYER_3_EDITOR                            589
+#define IMG_PLAYER_3_DOWN                              590
+#define IMG_PLAYER_3_UP                                        591
+#define IMG_PLAYER_3_LEFT                              592
+#define IMG_PLAYER_3_RIGHT                             593
+#define IMG_PLAYER_3_MOVING_DOWN                       594
+#define IMG_PLAYER_3_MOVING_UP                         595
+#define IMG_PLAYER_3_MOVING_LEFT                       596
+#define IMG_PLAYER_3_MOVING_RIGHT                      597
+#define IMG_PLAYER_3_DIGGING_DOWN                      598
+#define IMG_PLAYER_3_DIGGING_UP                                599
+#define IMG_PLAYER_3_DIGGING_LEFT                      600
+#define IMG_PLAYER_3_DIGGING_RIGHT                     601
+#define IMG_PLAYER_3_COLLECTING_DOWN                   602
+#define IMG_PLAYER_3_COLLECTING_UP                     603
+#define IMG_PLAYER_3_COLLECTING_LEFT                   604
+#define IMG_PLAYER_3_COLLECTING_RIGHT                  605
+#define IMG_PLAYER_3_PUSHING_DOWN                      606
+#define IMG_PLAYER_3_PUSHING_UP                                607
+#define IMG_PLAYER_3_PUSHING_LEFT                      608
+#define IMG_PLAYER_3_PUSHING_RIGHT                     609
+#define IMG_PLAYER_3_SNAPPING_DOWN                     610
+#define IMG_PLAYER_3_SNAPPING_UP                       611
+#define IMG_PLAYER_3_SNAPPING_LEFT                     612
+#define IMG_PLAYER_3_SNAPPING_RIGHT                    613
+#define IMG_PLAYER_4                                   614
+#define IMG_PLAYER_4_EDITOR                            615
+#define IMG_PLAYER_4_DOWN                              616
+#define IMG_PLAYER_4_UP                                        617
+#define IMG_PLAYER_4_LEFT                              618
+#define IMG_PLAYER_4_RIGHT                             619
+#define IMG_PLAYER_4_MOVING_DOWN                       620
+#define IMG_PLAYER_4_MOVING_UP                         621
+#define IMG_PLAYER_4_MOVING_LEFT                       622
+#define IMG_PLAYER_4_MOVING_RIGHT                      623
+#define IMG_PLAYER_4_DIGGING_DOWN                      624
+#define IMG_PLAYER_4_DIGGING_UP                                625
+#define IMG_PLAYER_4_DIGGING_LEFT                      626
+#define IMG_PLAYER_4_DIGGING_RIGHT                     627
+#define IMG_PLAYER_4_COLLECTING_DOWN                   628
+#define IMG_PLAYER_4_COLLECTING_UP                     629
+#define IMG_PLAYER_4_COLLECTING_LEFT                   630
+#define IMG_PLAYER_4_COLLECTING_RIGHT                  631
+#define IMG_PLAYER_4_PUSHING_DOWN                      632
+#define IMG_PLAYER_4_PUSHING_UP                                633
+#define IMG_PLAYER_4_PUSHING_LEFT                      634
+#define IMG_PLAYER_4_PUSHING_RIGHT                     635
+#define IMG_PLAYER_4_SNAPPING_DOWN                     636
+#define IMG_PLAYER_4_SNAPPING_UP                       637
+#define IMG_PLAYER_4_SNAPPING_LEFT                     638
+#define IMG_PLAYER_4_SNAPPING_RIGHT                    639
+#define IMG_DEFAULT_EXPLODING                          640
+#define IMG_TWINKLE_BLUE                               641
+#define IMG_TWINKLE_WHITE                              642
+#define IMG_STEELWALL_TOPLEFT                          643
+#define IMG_STEELWALL_TOPRIGHT                         644
+#define IMG_STEELWALL_BOTTOMLEFT                       645
+#define IMG_STEELWALL_BOTTOMRIGHT                      646
+#define IMG_STEELWALL_HORIZONTAL                       647
+#define IMG_STEELWALL_VERTICAL                         648
+#define IMG_STEELWALL_TOPLEFT_EDITOR                   649
+#define IMG_STEELWALL_TOPRIGHT_EDITOR                  650
+#define IMG_STEELWALL_BOTTOMLEFT_EDITOR                        651
+#define IMG_STEELWALL_BOTTOMRIGHT_EDITOR               652
+#define IMG_STEELWALL_HORIZONTAL_EDITOR                        653
+#define IMG_STEELWALL_VERTICAL_EDITOR                  654
+#define IMG_INVISIBLE_STEELWALL_TOPLEFT                        655
+#define IMG_INVISIBLE_STEELWALL_TOPRIGHT               656
+#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT             657
+#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT            658
+#define IMG_INVISIBLE_STEELWALL_HORIZONTAL             659
+#define IMG_INVISIBLE_STEELWALL_VERTICAL               660
+#define IMG_INVISIBLE_STEELWALL_TOPLEFT_EDITOR         661
+#define IMG_INVISIBLE_STEELWALL_TOPRIGHT_EDITOR                662
+#define IMG_INVISIBLE_STEELWALL_BOTTOMLEFT_EDITOR      663
+#define IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT_EDITOR     664
+#define IMG_INVISIBLE_STEELWALL_HORIZONTAL_EDITOR      665
+#define IMG_INVISIBLE_STEELWALL_VERTICAL_EDITOR                666
+#define IMG_ARROW_LEFT                                 667
+#define IMG_ARROW_RIGHT                                        668
+#define IMG_ARROW_UP                                   669
+#define IMG_ARROW_DOWN                                 670
+#define IMG_UNKNOWN                                    671
+#define IMG_TRIGGER_ELEMENT                            672
+#define IMG_TRIGGER_PLAYER                             673
+#define IMG_EMC_KEY_5                                  674
+#define IMG_EMC_KEY_6                                  675
+#define IMG_EMC_KEY_7                                  676
+#define IMG_EMC_KEY_8                                  677
+#define IMG_EMC_GATE_5                                 678
+#define IMG_EMC_GATE_5_GRAY                            679
+#define IMG_EMC_GATE_5_GRAY_EDITOR                     680
+#define IMG_EMC_GATE_6                                 681
+#define IMG_EMC_GATE_6_GRAY                            682
+#define IMG_EMC_GATE_6_GRAY_EDITOR                     683
+#define IMG_EMC_GATE_7                                 684
+#define IMG_EMC_GATE_7_GRAY                            685
+#define IMG_EMC_GATE_7_GRAY_EDITOR                     686
+#define IMG_EMC_GATE_8                                 687
+#define IMG_EMC_GATE_8_GRAY                            688
+#define IMG_EMC_GATE_8_GRAY_EDITOR                     689
+#define IMG_EMC_ANDROID                                        690
+#define IMG_EMC_GRASS                                  691
+#define IMG_EMC_GRASS_CRUMBLED                         692
+#define IMG_EMC_GRASS_DIGGING_LEFT                     693
+#define IMG_EMC_GRASS_DIGGING_RIGHT                    694
+#define IMG_EMC_GRASS_DIGGING_UP                       695
+#define IMG_EMC_GRASS_DIGGING_DOWN                     696
+#define IMG_EMC_GRASS_DIGGING_LEFT_CRUMBLED            697
+#define IMG_EMC_GRASS_DIGGING_RIGHT_CRUMBLED           698
+#define IMG_EMC_GRASS_DIGGING_UP_CRUMBLED              699
+#define IMG_EMC_GRASS_DIGGING_DOWN_CRUMBLED            700
+#define IMG_EMC_MAGIC_BALL                             701
+#define IMG_EMC_MAGIC_BALL_ACTIVE                      702
+#define IMG_EMC_MAGIC_BALL_SWITCH                      703
+#define IMG_EMC_MAGIC_BALL_SWITCH_ACTIVE               704
+#define IMG_EMC_SPRING_BUMPER                          705
+#define IMG_EMC_SPRING_BUMPER_ACTIVE                   706
+#define IMG_EMC_PLANT                                  707
+#define IMG_EMC_PLANT_CRUMBLED                         708
+#define IMG_EMC_LENSES                                 709
+#define IMG_EMC_MAGNIFIER                              710
+#define IMG_EMC_WALL_9                                 711
+#define IMG_EMC_WALL_10                                        712
+#define IMG_EMC_WALL_11                                        713
+#define IMG_EMC_WALL_12                                        714
+#define IMG_EMC_WALL_13                                        715
+#define IMG_EMC_WALL_14                                        716
+#define IMG_EMC_WALL_15                                        717
+#define IMG_EMC_WALL_16                                        718
+#define IMG_EMC_WALL_SLIPPERY_1                                719
+#define IMG_EMC_WALL_SLIPPERY_2                                720
+#define IMG_EMC_WALL_SLIPPERY_3                                721
+#define IMG_EMC_WALL_SLIPPERY_4                                722
+#define IMG_EMC_FAKE_GRASS                             723
+#define IMG_EMC_FAKE_GRASS_CRUMBLED                    724
+#define IMG_EMC_FAKE_GRASS_ACTIVE                      725
+#define IMG_EMC_FAKE_GRASS_ACTIVE_CRUMBLED             726
+#define IMG_EMC_FAKE_ACID                              727
+#define IMG_EMC_DRIPPER                                        728
+#define IMG_EMC_DRIPPER_EDITOR                         729
+#define IMG_EMC_DRIPPER_ACTIVE                         730
+#define IMG_CHAR_SPACE                                 731
+#define IMG_CHAR_EXCLAM                                        732
+#define IMG_CHAR_QUOTEDBL                              733
+#define IMG_CHAR_NUMBERSIGN                            734
+#define IMG_CHAR_DOLLAR                                        735
+#define IMG_CHAR_PERCENT                               736
+#define IMG_CHAR_AMPERSAND                             737
+#define IMG_CHAR_APOSTROPHE                            738
+#define IMG_CHAR_PARENLEFT                             739
+#define IMG_CHAR_PARENRIGHT                            740
+#define IMG_CHAR_ASTERISK                              741
+#define IMG_CHAR_PLUS                                  742
+#define IMG_CHAR_COMMA                                 743
+#define IMG_CHAR_MINUS                                 744
+#define IMG_CHAR_PERIOD                                        745
+#define IMG_CHAR_SLASH                                 746
+#define IMG_CHAR_0                                     747
+#define IMG_CHAR_1                                     748
+#define IMG_CHAR_2                                     749
+#define IMG_CHAR_3                                     750
+#define IMG_CHAR_4                                     751
+#define IMG_CHAR_5                                     752
+#define IMG_CHAR_6                                     753
+#define IMG_CHAR_7                                     754
+#define IMG_CHAR_8                                     755
+#define IMG_CHAR_9                                     756
+#define IMG_CHAR_COLON                                 757
+#define IMG_CHAR_SEMICOLON                             758
+#define IMG_CHAR_LESS                                  759
+#define IMG_CHAR_EQUAL                                 760
+#define IMG_CHAR_GREATER                               761
+#define IMG_CHAR_QUESTION                              762
+#define IMG_CHAR_AT                                    763
+#define IMG_CHAR_A                                     764
+#define IMG_CHAR_B                                     765
+#define IMG_CHAR_C                                     766
+#define IMG_CHAR_D                                     767
+#define IMG_CHAR_E                                     768
+#define IMG_CHAR_F                                     769
+#define IMG_CHAR_G                                     770
+#define IMG_CHAR_H                                     771
+#define IMG_CHAR_I                                     772
+#define IMG_CHAR_J                                     773
+#define IMG_CHAR_K                                     774
+#define IMG_CHAR_L                                     775
+#define IMG_CHAR_M                                     776
+#define IMG_CHAR_N                                     777
+#define IMG_CHAR_O                                     778
+#define IMG_CHAR_P                                     779
+#define IMG_CHAR_Q                                     780
+#define IMG_CHAR_R                                     781
+#define IMG_CHAR_S                                     782
+#define IMG_CHAR_T                                     783
+#define IMG_CHAR_U                                     784
+#define IMG_CHAR_V                                     785
+#define IMG_CHAR_W                                     786
+#define IMG_CHAR_X                                     787
+#define IMG_CHAR_Y                                     788
+#define IMG_CHAR_Z                                     789
+#define IMG_CHAR_BRACKETLEFT                           790
+#define IMG_CHAR_BACKSLASH                             791
+#define IMG_CHAR_BRACKETRIGHT                          792
+#define IMG_CHAR_ASCIICIRCUM                           793
+#define IMG_CHAR_UNDERSCORE                            794
+#define IMG_CHAR_COPYRIGHT                             795
+#define IMG_CHAR_AUMLAUT                               796
+#define IMG_CHAR_OUMLAUT                               797
+#define IMG_CHAR_UUMLAUT                               798
+#define IMG_CHAR_DEGREE                                        799
+#define IMG_CHAR_TRADEMARK                             800
+#define IMG_CHAR_CURSOR                                        801
+#define IMG_CUSTOM_1                                   802
+#define IMG_CUSTOM_1_EDITOR                            803
+#define IMG_CUSTOM_2                                   804
+#define IMG_CUSTOM_2_EDITOR                            805
+#define IMG_CUSTOM_3                                   806
+#define IMG_CUSTOM_3_EDITOR                            807
+#define IMG_CUSTOM_4                                   808
+#define IMG_CUSTOM_4_EDITOR                            809
+#define IMG_CUSTOM_5                                   810
+#define IMG_CUSTOM_5_EDITOR                            811
+#define IMG_CUSTOM_6                                   812
+#define IMG_CUSTOM_6_EDITOR                            813
+#define IMG_CUSTOM_7                                   814
+#define IMG_CUSTOM_7_EDITOR                            815
+#define IMG_CUSTOM_8                                   816
+#define IMG_CUSTOM_8_EDITOR                            817
+#define IMG_CUSTOM_9                                   818
+#define IMG_CUSTOM_9_EDITOR                            819
+#define IMG_CUSTOM_10                                  820
+#define IMG_CUSTOM_10_EDITOR                           821
+#define IMG_CUSTOM_11                                  822
+#define IMG_CUSTOM_11_EDITOR                           823
+#define IMG_CUSTOM_12                                  824
+#define IMG_CUSTOM_12_EDITOR                           825
+#define IMG_CUSTOM_13                                  826
+#define IMG_CUSTOM_13_EDITOR                           827
+#define IMG_CUSTOM_14                                  828
+#define IMG_CUSTOM_14_EDITOR                           829
+#define IMG_CUSTOM_15                                  830
+#define IMG_CUSTOM_15_EDITOR                           831
+#define IMG_CUSTOM_16                                  832
+#define IMG_CUSTOM_16_EDITOR                           833
+#define IMG_CUSTOM_17                                  834
+#define IMG_CUSTOM_17_EDITOR                           835
+#define IMG_CUSTOM_18                                  836
+#define IMG_CUSTOM_18_EDITOR                           837
+#define IMG_CUSTOM_19                                  838
+#define IMG_CUSTOM_19_EDITOR                           839
+#define IMG_CUSTOM_20                                  840
+#define IMG_CUSTOM_20_EDITOR                           841
+#define IMG_CUSTOM_21                                  842
+#define IMG_CUSTOM_21_EDITOR                           843
+#define IMG_CUSTOM_22                                  844
+#define IMG_CUSTOM_22_EDITOR                           845
+#define IMG_CUSTOM_23                                  846
+#define IMG_CUSTOM_23_EDITOR                           847
+#define IMG_CUSTOM_24                                  848
+#define IMG_CUSTOM_24_EDITOR                           849
+#define IMG_CUSTOM_25                                  850
+#define IMG_CUSTOM_25_EDITOR                           851
+#define IMG_CUSTOM_26                                  852
+#define IMG_CUSTOM_26_EDITOR                           853
+#define IMG_CUSTOM_27                                  854
+#define IMG_CUSTOM_27_EDITOR                           855
+#define IMG_CUSTOM_28                                  856
+#define IMG_CUSTOM_28_EDITOR                           857
+#define IMG_CUSTOM_29                                  858
+#define IMG_CUSTOM_29_EDITOR                           859
+#define IMG_CUSTOM_30                                  860
+#define IMG_CUSTOM_30_EDITOR                           861
+#define IMG_CUSTOM_31                                  862
+#define IMG_CUSTOM_31_EDITOR                           863
+#define IMG_CUSTOM_32                                  864
+#define IMG_CUSTOM_32_EDITOR                           865
+#define IMG_CUSTOM_33                                  866
+#define IMG_CUSTOM_33_EDITOR                           867
+#define IMG_CUSTOM_34                                  868
+#define IMG_CUSTOM_34_EDITOR                           869
+#define IMG_CUSTOM_35                                  870
+#define IMG_CUSTOM_35_EDITOR                           871
+#define IMG_CUSTOM_36                                  872
+#define IMG_CUSTOM_36_EDITOR                           873
+#define IMG_CUSTOM_37                                  874
+#define IMG_CUSTOM_37_EDITOR                           875
+#define IMG_CUSTOM_38                                  876
+#define IMG_CUSTOM_38_EDITOR                           877
+#define IMG_CUSTOM_39                                  878
+#define IMG_CUSTOM_39_EDITOR                           879
+#define IMG_CUSTOM_40                                  880
+#define IMG_CUSTOM_40_EDITOR                           881
+#define IMG_CUSTOM_41                                  882
+#define IMG_CUSTOM_41_EDITOR                           883
+#define IMG_CUSTOM_42                                  884
+#define IMG_CUSTOM_42_EDITOR                           885
+#define IMG_CUSTOM_43                                  886
+#define IMG_CUSTOM_43_EDITOR                           887
+#define IMG_CUSTOM_44                                  888
+#define IMG_CUSTOM_44_EDITOR                           889
+#define IMG_CUSTOM_45                                  890
+#define IMG_CUSTOM_45_EDITOR                           891
+#define IMG_CUSTOM_46                                  892
+#define IMG_CUSTOM_46_EDITOR                           893
+#define IMG_CUSTOM_47                                  894
+#define IMG_CUSTOM_47_EDITOR                           895
+#define IMG_CUSTOM_48                                  896
+#define IMG_CUSTOM_48_EDITOR                           897
+#define IMG_CUSTOM_49                                  898
+#define IMG_CUSTOM_49_EDITOR                           899
+#define IMG_CUSTOM_50                                  900
+#define IMG_CUSTOM_50_EDITOR                           901
+#define IMG_CUSTOM_51                                  902
+#define IMG_CUSTOM_51_EDITOR                           903
+#define IMG_CUSTOM_52                                  904
+#define IMG_CUSTOM_52_EDITOR                           905
+#define IMG_CUSTOM_53                                  906
+#define IMG_CUSTOM_53_EDITOR                           907
+#define IMG_CUSTOM_54                                  908
+#define IMG_CUSTOM_54_EDITOR                           909
+#define IMG_CUSTOM_55                                  910
+#define IMG_CUSTOM_55_EDITOR                           911
+#define IMG_CUSTOM_56                                  912
+#define IMG_CUSTOM_56_EDITOR                           913
+#define IMG_CUSTOM_57                                  914
+#define IMG_CUSTOM_57_EDITOR                           915
+#define IMG_CUSTOM_58                                  916
+#define IMG_CUSTOM_58_EDITOR                           917
+#define IMG_CUSTOM_59                                  918
+#define IMG_CUSTOM_59_EDITOR                           919
+#define IMG_CUSTOM_60                                  920
+#define IMG_CUSTOM_60_EDITOR                           921
+#define IMG_CUSTOM_61                                  922
+#define IMG_CUSTOM_61_EDITOR                           923
+#define IMG_CUSTOM_62                                  924
+#define IMG_CUSTOM_62_EDITOR                           925
+#define IMG_CUSTOM_63                                  926
+#define IMG_CUSTOM_63_EDITOR                           927
+#define IMG_CUSTOM_64                                  928
+#define IMG_CUSTOM_64_EDITOR                           929
+#define IMG_CUSTOM_65                                  930
+#define IMG_CUSTOM_65_EDITOR                           931
+#define IMG_CUSTOM_66                                  932
+#define IMG_CUSTOM_66_EDITOR                           933
+#define IMG_CUSTOM_67                                  934
+#define IMG_CUSTOM_67_EDITOR                           935
+#define IMG_CUSTOM_68                                  936
+#define IMG_CUSTOM_68_EDITOR                           937
+#define IMG_CUSTOM_69                                  938
+#define IMG_CUSTOM_69_EDITOR                           939
+#define IMG_CUSTOM_70                                  940
+#define IMG_CUSTOM_70_EDITOR                           941
+#define IMG_CUSTOM_71                                  942
+#define IMG_CUSTOM_71_EDITOR                           943
+#define IMG_CUSTOM_72                                  944
+#define IMG_CUSTOM_72_EDITOR                           945
+#define IMG_CUSTOM_73                                  946
+#define IMG_CUSTOM_73_EDITOR                           947
+#define IMG_CUSTOM_74                                  948
+#define IMG_CUSTOM_74_EDITOR                           949
+#define IMG_CUSTOM_75                                  950
+#define IMG_CUSTOM_75_EDITOR                           951
+#define IMG_CUSTOM_76                                  952
+#define IMG_CUSTOM_76_EDITOR                           953
+#define IMG_CUSTOM_77                                  954
+#define IMG_CUSTOM_77_EDITOR                           955
+#define IMG_CUSTOM_78                                  956
+#define IMG_CUSTOM_78_EDITOR                           957
+#define IMG_CUSTOM_79                                  958
+#define IMG_CUSTOM_79_EDITOR                           959
+#define IMG_CUSTOM_80                                  960
+#define IMG_CUSTOM_80_EDITOR                           961
+#define IMG_CUSTOM_81                                  962
+#define IMG_CUSTOM_81_EDITOR                           963
+#define IMG_CUSTOM_82                                  964
+#define IMG_CUSTOM_82_EDITOR                           965
+#define IMG_CUSTOM_83                                  966
+#define IMG_CUSTOM_83_EDITOR                           967
+#define IMG_CUSTOM_84                                  968
+#define IMG_CUSTOM_84_EDITOR                           969
+#define IMG_CUSTOM_85                                  970
+#define IMG_CUSTOM_85_EDITOR                           971
+#define IMG_CUSTOM_86                                  972
+#define IMG_CUSTOM_86_EDITOR                           973
+#define IMG_CUSTOM_87                                  974
+#define IMG_CUSTOM_87_EDITOR                           975
+#define IMG_CUSTOM_88                                  976
+#define IMG_CUSTOM_88_EDITOR                           977
+#define IMG_CUSTOM_89                                  978
+#define IMG_CUSTOM_89_EDITOR                           979
+#define IMG_CUSTOM_90                                  980
+#define IMG_CUSTOM_90_EDITOR                           981
+#define IMG_CUSTOM_91                                  982
+#define IMG_CUSTOM_91_EDITOR                           983
+#define IMG_CUSTOM_92                                  984
+#define IMG_CUSTOM_92_EDITOR                           985
+#define IMG_CUSTOM_93                                  986
+#define IMG_CUSTOM_93_EDITOR                           987
+#define IMG_CUSTOM_94                                  988
+#define IMG_CUSTOM_94_EDITOR                           989
+#define IMG_CUSTOM_95                                  990
+#define IMG_CUSTOM_95_EDITOR                           991
+#define IMG_CUSTOM_96                                  992
+#define IMG_CUSTOM_96_EDITOR                           993
+#define IMG_CUSTOM_97                                  994
+#define IMG_CUSTOM_97_EDITOR                           995
+#define IMG_CUSTOM_98                                  996
+#define IMG_CUSTOM_98_EDITOR                           997
+#define IMG_CUSTOM_99                                  998
+#define IMG_CUSTOM_99_EDITOR                           999
+#define IMG_CUSTOM_100                                 1000
+#define IMG_CUSTOM_100_EDITOR                          1001
+#define IMG_CUSTOM_101                                 1002
+#define IMG_CUSTOM_101_EDITOR                          1003
+#define IMG_CUSTOM_102                                 1004
+#define IMG_CUSTOM_102_EDITOR                          1005
+#define IMG_CUSTOM_103                                 1006
+#define IMG_CUSTOM_103_EDITOR                          1007
+#define IMG_CUSTOM_104                                 1008
+#define IMG_CUSTOM_104_EDITOR                          1009
+#define IMG_CUSTOM_105                                 1010
+#define IMG_CUSTOM_105_EDITOR                          1011
+#define IMG_CUSTOM_106                                 1012
+#define IMG_CUSTOM_106_EDITOR                          1013
+#define IMG_CUSTOM_107                                 1014
+#define IMG_CUSTOM_107_EDITOR                          1015
+#define IMG_CUSTOM_108                                 1016
+#define IMG_CUSTOM_108_EDITOR                          1017
+#define IMG_CUSTOM_109                                 1018
+#define IMG_CUSTOM_109_EDITOR                          1019
+#define IMG_CUSTOM_110                                 1020
+#define IMG_CUSTOM_110_EDITOR                          1021
+#define IMG_CUSTOM_111                                 1022
+#define IMG_CUSTOM_111_EDITOR                          1023
+#define IMG_CUSTOM_112                                 1024
+#define IMG_CUSTOM_112_EDITOR                          1025
+#define IMG_CUSTOM_113                                 1026
+#define IMG_CUSTOM_113_EDITOR                          1027
+#define IMG_CUSTOM_114                                 1028
+#define IMG_CUSTOM_114_EDITOR                          1029
+#define IMG_CUSTOM_115                                 1030
+#define IMG_CUSTOM_115_EDITOR                          1031
+#define IMG_CUSTOM_116                                 1032
+#define IMG_CUSTOM_116_EDITOR                          1033
+#define IMG_CUSTOM_117                                 1034
+#define IMG_CUSTOM_117_EDITOR                          1035
+#define IMG_CUSTOM_118                                 1036
+#define IMG_CUSTOM_118_EDITOR                          1037
+#define IMG_CUSTOM_119                                 1038
+#define IMG_CUSTOM_119_EDITOR                          1039
+#define IMG_CUSTOM_120                                 1040
+#define IMG_CUSTOM_120_EDITOR                          1041
+#define IMG_CUSTOM_121                                 1042
+#define IMG_CUSTOM_121_EDITOR                          1043
+#define IMG_CUSTOM_122                                 1044
+#define IMG_CUSTOM_122_EDITOR                          1045
+#define IMG_CUSTOM_123                                 1046
+#define IMG_CUSTOM_123_EDITOR                          1047
+#define IMG_CUSTOM_124                                 1048
+#define IMG_CUSTOM_124_EDITOR                          1049
+#define IMG_CUSTOM_125                                 1050
+#define IMG_CUSTOM_125_EDITOR                          1051
+#define IMG_CUSTOM_126                                 1052
+#define IMG_CUSTOM_126_EDITOR                          1053
+#define IMG_CUSTOM_127                                 1054
+#define IMG_CUSTOM_127_EDITOR                          1055
+#define IMG_CUSTOM_128                                 1056
+#define IMG_CUSTOM_128_EDITOR                          1057
+#define IMG_CUSTOM_129                                 1058
+#define IMG_CUSTOM_129_EDITOR                          1059
+#define IMG_CUSTOM_130                                 1060
+#define IMG_CUSTOM_130_EDITOR                          1061
+#define IMG_CUSTOM_131                                 1062
+#define IMG_CUSTOM_131_EDITOR                          1063
+#define IMG_CUSTOM_132                                 1064
+#define IMG_CUSTOM_132_EDITOR                          1065
+#define IMG_CUSTOM_133                                 1066
+#define IMG_CUSTOM_133_EDITOR                          1067
+#define IMG_CUSTOM_134                                 1068
+#define IMG_CUSTOM_134_EDITOR                          1069
+#define IMG_CUSTOM_135                                 1070
+#define IMG_CUSTOM_135_EDITOR                          1071
+#define IMG_CUSTOM_136                                 1072
+#define IMG_CUSTOM_136_EDITOR                          1073
+#define IMG_CUSTOM_137                                 1074
+#define IMG_CUSTOM_137_EDITOR                          1075
+#define IMG_CUSTOM_138                                 1076
+#define IMG_CUSTOM_138_EDITOR                          1077
+#define IMG_CUSTOM_139                                 1078
+#define IMG_CUSTOM_139_EDITOR                          1079
+#define IMG_CUSTOM_140                                 1080
+#define IMG_CUSTOM_140_EDITOR                          1081
+#define IMG_CUSTOM_141                                 1082
+#define IMG_CUSTOM_141_EDITOR                          1083
+#define IMG_CUSTOM_142                                 1084
+#define IMG_CUSTOM_142_EDITOR                          1085
+#define IMG_CUSTOM_143                                 1086
+#define IMG_CUSTOM_143_EDITOR                          1087
+#define IMG_CUSTOM_144                                 1088
+#define IMG_CUSTOM_144_EDITOR                          1089
+#define IMG_CUSTOM_145                                 1090
+#define IMG_CUSTOM_145_EDITOR                          1091
+#define IMG_CUSTOM_146                                 1092
+#define IMG_CUSTOM_146_EDITOR                          1093
+#define IMG_CUSTOM_147                                 1094
+#define IMG_CUSTOM_147_EDITOR                          1095
+#define IMG_CUSTOM_148                                 1096
+#define IMG_CUSTOM_148_EDITOR                          1097
+#define IMG_CUSTOM_149                                 1098
+#define IMG_CUSTOM_149_EDITOR                          1099
+#define IMG_CUSTOM_150                                 1100
+#define IMG_CUSTOM_150_EDITOR                          1101
+#define IMG_CUSTOM_151                                 1102
+#define IMG_CUSTOM_151_EDITOR                          1103
+#define IMG_CUSTOM_152                                 1104
+#define IMG_CUSTOM_152_EDITOR                          1105
+#define IMG_CUSTOM_153                                 1106
+#define IMG_CUSTOM_153_EDITOR                          1107
+#define IMG_CUSTOM_154                                 1108
+#define IMG_CUSTOM_154_EDITOR                          1109
+#define IMG_CUSTOM_155                                 1110
+#define IMG_CUSTOM_155_EDITOR                          1111
+#define IMG_CUSTOM_156                                 1112
+#define IMG_CUSTOM_156_EDITOR                          1113
+#define IMG_CUSTOM_157                                 1114
+#define IMG_CUSTOM_157_EDITOR                          1115
+#define IMG_CUSTOM_158                                 1116
+#define IMG_CUSTOM_158_EDITOR                          1117
+#define IMG_CUSTOM_159                                 1118
+#define IMG_CUSTOM_159_EDITOR                          1119
+#define IMG_CUSTOM_160                                 1120
+#define IMG_CUSTOM_160_EDITOR                          1121
+#define IMG_CUSTOM_161                                 1122
+#define IMG_CUSTOM_161_EDITOR                          1123
+#define IMG_CUSTOM_162                                 1124
+#define IMG_CUSTOM_162_EDITOR                          1125
+#define IMG_CUSTOM_163                                 1126
+#define IMG_CUSTOM_163_EDITOR                          1127
+#define IMG_CUSTOM_164                                 1128
+#define IMG_CUSTOM_164_EDITOR                          1129
+#define IMG_CUSTOM_165                                 1130
+#define IMG_CUSTOM_165_EDITOR                          1131
+#define IMG_CUSTOM_166                                 1132
+#define IMG_CUSTOM_166_EDITOR                          1133
+#define IMG_CUSTOM_167                                 1134
+#define IMG_CUSTOM_167_EDITOR                          1135
+#define IMG_CUSTOM_168                                 1136
+#define IMG_CUSTOM_168_EDITOR                          1137
+#define IMG_CUSTOM_169                                 1138
+#define IMG_CUSTOM_169_EDITOR                          1139
+#define IMG_CUSTOM_170                                 1140
+#define IMG_CUSTOM_170_EDITOR                          1141
+#define IMG_CUSTOM_171                                 1142
+#define IMG_CUSTOM_171_EDITOR                          1143
+#define IMG_CUSTOM_172                                 1144
+#define IMG_CUSTOM_172_EDITOR                          1145
+#define IMG_CUSTOM_173                                 1146
+#define IMG_CUSTOM_173_EDITOR                          1147
+#define IMG_CUSTOM_174                                 1148
+#define IMG_CUSTOM_174_EDITOR                          1149
+#define IMG_CUSTOM_175                                 1150
+#define IMG_CUSTOM_175_EDITOR                          1151
+#define IMG_CUSTOM_176                                 1152
+#define IMG_CUSTOM_176_EDITOR                          1153
+#define IMG_CUSTOM_177                                 1154
+#define IMG_CUSTOM_177_EDITOR                          1155
+#define IMG_CUSTOM_178                                 1156
+#define IMG_CUSTOM_178_EDITOR                          1157
+#define IMG_CUSTOM_179                                 1158
+#define IMG_CUSTOM_179_EDITOR                          1159
+#define IMG_CUSTOM_180                                 1160
+#define IMG_CUSTOM_180_EDITOR                          1161
+#define IMG_CUSTOM_181                                 1162
+#define IMG_CUSTOM_181_EDITOR                          1163
+#define IMG_CUSTOM_182                                 1164
+#define IMG_CUSTOM_182_EDITOR                          1165
+#define IMG_CUSTOM_183                                 1166
+#define IMG_CUSTOM_183_EDITOR                          1167
+#define IMG_CUSTOM_184                                 1168
+#define IMG_CUSTOM_184_EDITOR                          1169
+#define IMG_CUSTOM_185                                 1170
+#define IMG_CUSTOM_185_EDITOR                          1171
+#define IMG_CUSTOM_186                                 1172
+#define IMG_CUSTOM_186_EDITOR                          1173
+#define IMG_CUSTOM_187                                 1174
+#define IMG_CUSTOM_187_EDITOR                          1175
+#define IMG_CUSTOM_188                                 1176
+#define IMG_CUSTOM_188_EDITOR                          1177
+#define IMG_CUSTOM_189                                 1178
+#define IMG_CUSTOM_189_EDITOR                          1179
+#define IMG_CUSTOM_190                                 1180
+#define IMG_CUSTOM_190_EDITOR                          1181
+#define IMG_CUSTOM_191                                 1182
+#define IMG_CUSTOM_191_EDITOR                          1183
+#define IMG_CUSTOM_192                                 1184
+#define IMG_CUSTOM_192_EDITOR                          1185
+#define IMG_CUSTOM_193                                 1186
+#define IMG_CUSTOM_193_EDITOR                          1187
+#define IMG_CUSTOM_194                                 1188
+#define IMG_CUSTOM_194_EDITOR                          1189
+#define IMG_CUSTOM_195                                 1190
+#define IMG_CUSTOM_195_EDITOR                          1191
+#define IMG_CUSTOM_196                                 1192
+#define IMG_CUSTOM_196_EDITOR                          1193
+#define IMG_CUSTOM_197                                 1194
+#define IMG_CUSTOM_197_EDITOR                          1195
+#define IMG_CUSTOM_198                                 1196
+#define IMG_CUSTOM_198_EDITOR                          1197
+#define IMG_CUSTOM_199                                 1198
+#define IMG_CUSTOM_199_EDITOR                          1199
+#define IMG_CUSTOM_200                                 1200
+#define IMG_CUSTOM_200_EDITOR                          1201
+#define IMG_CUSTOM_201                                 1202
+#define IMG_CUSTOM_201_EDITOR                          1203
+#define IMG_CUSTOM_202                                 1204
+#define IMG_CUSTOM_202_EDITOR                          1205
+#define IMG_CUSTOM_203                                 1206
+#define IMG_CUSTOM_203_EDITOR                          1207
+#define IMG_CUSTOM_204                                 1208
+#define IMG_CUSTOM_204_EDITOR                          1209
+#define IMG_CUSTOM_205                                 1210
+#define IMG_CUSTOM_205_EDITOR                          1211
+#define IMG_CUSTOM_206                                 1212
+#define IMG_CUSTOM_206_EDITOR                          1213
+#define IMG_CUSTOM_207                                 1214
+#define IMG_CUSTOM_207_EDITOR                          1215
+#define IMG_CUSTOM_208                                 1216
+#define IMG_CUSTOM_208_EDITOR                          1217
+#define IMG_CUSTOM_209                                 1218
+#define IMG_CUSTOM_209_EDITOR                          1219
+#define IMG_CUSTOM_210                                 1220
+#define IMG_CUSTOM_210_EDITOR                          1221
+#define IMG_CUSTOM_211                                 1222
+#define IMG_CUSTOM_211_EDITOR                          1223
+#define IMG_CUSTOM_212                                 1224
+#define IMG_CUSTOM_212_EDITOR                          1225
+#define IMG_CUSTOM_213                                 1226
+#define IMG_CUSTOM_213_EDITOR                          1227
+#define IMG_CUSTOM_214                                 1228
+#define IMG_CUSTOM_214_EDITOR                          1229
+#define IMG_CUSTOM_215                                 1230
+#define IMG_CUSTOM_215_EDITOR                          1231
+#define IMG_CUSTOM_216                                 1232
+#define IMG_CUSTOM_216_EDITOR                          1233
+#define IMG_CUSTOM_217                                 1234
+#define IMG_CUSTOM_217_EDITOR                          1235
+#define IMG_CUSTOM_218                                 1236
+#define IMG_CUSTOM_218_EDITOR                          1237
+#define IMG_CUSTOM_219                                 1238
+#define IMG_CUSTOM_219_EDITOR                          1239
+#define IMG_CUSTOM_220                                 1240
+#define IMG_CUSTOM_220_EDITOR                          1241
+#define IMG_CUSTOM_221                                 1242
+#define IMG_CUSTOM_221_EDITOR                          1243
+#define IMG_CUSTOM_222                                 1244
+#define IMG_CUSTOM_222_EDITOR                          1245
+#define IMG_CUSTOM_223                                 1246
+#define IMG_CUSTOM_223_EDITOR                          1247
+#define IMG_CUSTOM_224                                 1248
+#define IMG_CUSTOM_224_EDITOR                          1249
+#define IMG_CUSTOM_225                                 1250
+#define IMG_CUSTOM_225_EDITOR                          1251
+#define IMG_CUSTOM_226                                 1252
+#define IMG_CUSTOM_226_EDITOR                          1253
+#define IMG_CUSTOM_227                                 1254
+#define IMG_CUSTOM_227_EDITOR                          1255
+#define IMG_CUSTOM_228                                 1256
+#define IMG_CUSTOM_228_EDITOR                          1257
+#define IMG_CUSTOM_229                                 1258
+#define IMG_CUSTOM_229_EDITOR                          1259
+#define IMG_CUSTOM_230                                 1260
+#define IMG_CUSTOM_230_EDITOR                          1261
+#define IMG_CUSTOM_231                                 1262
+#define IMG_CUSTOM_231_EDITOR                          1263
+#define IMG_CUSTOM_232                                 1264
+#define IMG_CUSTOM_232_EDITOR                          1265
+#define IMG_CUSTOM_233                                 1266
+#define IMG_CUSTOM_233_EDITOR                          1267
+#define IMG_CUSTOM_234                                 1268
+#define IMG_CUSTOM_234_EDITOR                          1269
+#define IMG_CUSTOM_235                                 1270
+#define IMG_CUSTOM_235_EDITOR                          1271
+#define IMG_CUSTOM_236                                 1272
+#define IMG_CUSTOM_236_EDITOR                          1273
+#define IMG_CUSTOM_237                                 1274
+#define IMG_CUSTOM_237_EDITOR                          1275
+#define IMG_CUSTOM_238                                 1276
+#define IMG_CUSTOM_238_EDITOR                          1277
+#define IMG_CUSTOM_239                                 1278
+#define IMG_CUSTOM_239_EDITOR                          1279
+#define IMG_CUSTOM_240                                 1280
+#define IMG_CUSTOM_240_EDITOR                          1281
+#define IMG_CUSTOM_241                                 1282
+#define IMG_CUSTOM_241_EDITOR                          1283
+#define IMG_CUSTOM_242                                 1284
+#define IMG_CUSTOM_242_EDITOR                          1285
+#define IMG_CUSTOM_243                                 1286
+#define IMG_CUSTOM_243_EDITOR                          1287
+#define IMG_CUSTOM_244                                 1288
+#define IMG_CUSTOM_244_EDITOR                          1289
+#define IMG_CUSTOM_245                                 1290
+#define IMG_CUSTOM_245_EDITOR                          1291
+#define IMG_CUSTOM_246                                 1292
+#define IMG_CUSTOM_246_EDITOR                          1293
+#define IMG_CUSTOM_247                                 1294
+#define IMG_CUSTOM_247_EDITOR                          1295
+#define IMG_CUSTOM_248                                 1296
+#define IMG_CUSTOM_248_EDITOR                          1297
+#define IMG_CUSTOM_249                                 1298
+#define IMG_CUSTOM_249_EDITOR                          1299
+#define IMG_CUSTOM_250                                 1300
+#define IMG_CUSTOM_250_EDITOR                          1301
+#define IMG_CUSTOM_251                                 1302
+#define IMG_CUSTOM_251_EDITOR                          1303
+#define IMG_CUSTOM_252                                 1304
+#define IMG_CUSTOM_252_EDITOR                          1305
+#define IMG_CUSTOM_253                                 1306
+#define IMG_CUSTOM_253_EDITOR                          1307
+#define IMG_CUSTOM_254                                 1308
+#define IMG_CUSTOM_254_EDITOR                          1309
+#define IMG_CUSTOM_255                                 1310
+#define IMG_CUSTOM_255_EDITOR                          1311
+#define IMG_CUSTOM_256                                 1312
+#define IMG_CUSTOM_256_EDITOR                          1313
+#define IMG_GROUP_1                                    1314
+#define IMG_GROUP_1_EDITOR                             1315
+#define IMG_GROUP_2                                    1316
+#define IMG_GROUP_2_EDITOR                             1317
+#define IMG_GROUP_3                                    1318
+#define IMG_GROUP_3_EDITOR                             1319
+#define IMG_GROUP_4                                    1320
+#define IMG_GROUP_4_EDITOR                             1321
+#define IMG_GROUP_5                                    1322
+#define IMG_GROUP_5_EDITOR                             1323
+#define IMG_GROUP_6                                    1324
+#define IMG_GROUP_6_EDITOR                             1325
+#define IMG_GROUP_7                                    1326
+#define IMG_GROUP_7_EDITOR                             1327
+#define IMG_GROUP_8                                    1328
+#define IMG_GROUP_8_EDITOR                             1329
+#define IMG_GROUP_9                                    1330
+#define IMG_GROUP_9_EDITOR                             1331
+#define IMG_GROUP_10                                   1332
+#define IMG_GROUP_10_EDITOR                            1333
+#define IMG_GROUP_11                                   1334
+#define IMG_GROUP_11_EDITOR                            1335
+#define IMG_GROUP_12                                   1336
+#define IMG_GROUP_12_EDITOR                            1337
+#define IMG_GROUP_13                                   1338
+#define IMG_GROUP_13_EDITOR                            1339
+#define IMG_GROUP_14                                   1340
+#define IMG_GROUP_14_EDITOR                            1341
+#define IMG_GROUP_15                                   1342
+#define IMG_GROUP_15_EDITOR                            1343
+#define IMG_GROUP_16                                   1344
+#define IMG_GROUP_16_EDITOR                            1345
+#define IMG_GROUP_17                                   1346
+#define IMG_GROUP_17_EDITOR                            1347
+#define IMG_GROUP_18                                   1348
+#define IMG_GROUP_18_EDITOR                            1349
+#define IMG_GROUP_19                                   1350
+#define IMG_GROUP_19_EDITOR                            1351
+#define IMG_GROUP_20                                   1352
+#define IMG_GROUP_20_EDITOR                            1353
+#define IMG_GROUP_21                                   1354
+#define IMG_GROUP_21_EDITOR                            1355
+#define IMG_GROUP_22                                   1356
+#define IMG_GROUP_22_EDITOR                            1357
+#define IMG_GROUP_23                                   1358
+#define IMG_GROUP_23_EDITOR                            1359
+#define IMG_GROUP_24                                   1360
+#define IMG_GROUP_24_EDITOR                            1361
+#define IMG_GROUP_25                                   1362
+#define IMG_GROUP_25_EDITOR                            1363
+#define IMG_GROUP_26                                   1364
+#define IMG_GROUP_26_EDITOR                            1365
+#define IMG_GROUP_27                                   1366
+#define IMG_GROUP_27_EDITOR                            1367
+#define IMG_GROUP_28                                   1368
+#define IMG_GROUP_28_EDITOR                            1369
+#define IMG_GROUP_29                                   1370
+#define IMG_GROUP_29_EDITOR                            1371
+#define IMG_GROUP_30                                   1372
+#define IMG_GROUP_30_EDITOR                            1373
+#define IMG_GROUP_31                                   1374
+#define IMG_GROUP_31_EDITOR                            1375
+#define IMG_GROUP_32                                   1376
+#define IMG_GROUP_32_EDITOR                            1377
+#define IMG_EMC_OBJECT                                 1378
+#define IMG_EMC_SPRITE                                 1379
+#define IMG_TOON_1                                     1380
+#define IMG_TOON_2                                     1381
+#define IMG_TOON_3                                     1382
+#define IMG_TOON_4                                     1383
+#define IMG_TOON_5                                     1384
+#define IMG_TOON_6                                     1385
+#define IMG_TOON_7                                     1386
+#define IMG_TOON_8                                     1387
+#define IMG_TOON_9                                     1388
+#define IMG_TOON_10                                    1389
+#define IMG_TOON_11                                    1390
+#define IMG_TOON_12                                    1391
+#define IMG_TOON_13                                    1392
+#define IMG_TOON_14                                    1393
+#define IMG_TOON_15                                    1394
+#define IMG_TOON_16                                    1395
+#define IMG_TOON_17                                    1396
+#define IMG_TOON_18                                    1397
+#define IMG_TOON_19                                    1398
+#define IMG_TOON_20                                    1399
+#define IMG_MENU_CALIBRATE_RED                         1400
+#define IMG_MENU_CALIBRATE_BLUE                                1401
+#define IMG_MENU_CALIBRATE_YELLOW                      1402
+#define IMG_MENU_BUTTON                                        1403
+#define IMG_MENU_BUTTON_ACTIVE                         1404
+#define IMG_MENU_BUTTON_LEFT                           1405
+#define IMG_MENU_BUTTON_RIGHT                          1406
+#define IMG_MENU_BUTTON_UP                             1407
+#define IMG_MENU_BUTTON_DOWN                           1408
+#define IMG_MENU_BUTTON_LEFT_ACTIVE                    1409
+#define IMG_MENU_BUTTON_RIGHT_ACTIVE                   1410
+#define IMG_MENU_BUTTON_UP_ACTIVE                      1411
+#define IMG_MENU_BUTTON_DOWN_ACTIVE                    1412
+#define IMG_MENU_SCROLLBAR                             1413
+#define IMG_MENU_SCROLLBAR_ACTIVE                      1414
+#define IMG_FONT_INITIAL_1                             1415
+#define IMG_FONT_INITIAL_2                             1416
+#define IMG_FONT_INITIAL_3                             1417
+#define IMG_FONT_INITIAL_4                             1418
+#define IMG_FONT_TITLE_1                               1419
+#define IMG_FONT_TITLE_1_LEVELS                                1420
+#define IMG_FONT_TITLE_2                               1421
+#define IMG_FONT_MENU_1                                        1422
+#define IMG_FONT_MENU_2                                        1423
+#define IMG_FONT_TEXT_1                                        1424
+#define IMG_FONT_TEXT_1_LEVELS                         1425
+#define IMG_FONT_TEXT_1_PREVIEW                                1426
+#define IMG_FONT_TEXT_1_SCORES                         1427
+#define IMG_FONT_TEXT_1_ACTIVE_SCORES                  1428
+#define IMG_FONT_TEXT_2                                        1429
+#define IMG_FONT_TEXT_2_LEVELS                         1430
+#define IMG_FONT_TEXT_2_PREVIEW                                1431
+#define IMG_FONT_TEXT_2_SCORES                         1432
+#define IMG_FONT_TEXT_2_ACTIVE_SCORES                  1433
+#define IMG_FONT_TEXT_3                                        1434
+#define IMG_FONT_TEXT_3_LEVELS                         1435
+#define IMG_FONT_TEXT_3_PREVIEW                                1436
+#define IMG_FONT_TEXT_3_SCORES                         1437
+#define IMG_FONT_TEXT_3_ACTIVE_SCORES                  1438
+#define IMG_FONT_TEXT_4                                        1439
+#define IMG_FONT_TEXT_4_LEVELS                         1440
+#define IMG_FONT_TEXT_4_SCORES                         1441
+#define IMG_FONT_TEXT_4_ACTIVE_SCORES                  1442
+#define IMG_FONT_ENVELOPE_1                            1443
+#define IMG_FONT_ENVELOPE_2                            1444
+#define IMG_FONT_ENVELOPE_3                            1445
+#define IMG_FONT_ENVELOPE_4                            1446
+#define IMG_FONT_INPUT_1                               1447
+#define IMG_FONT_INPUT_1_MAIN                          1448
+#define IMG_FONT_INPUT_1_ACTIVE                                1449
+#define IMG_FONT_INPUT_1_ACTIVE_MAIN                   1450
+#define IMG_FONT_INPUT_1_ACTIVE_SETUP                  1451
+#define IMG_FONT_INPUT_2                               1452
+#define IMG_FONT_INPUT_2_ACTIVE                                1453
+#define IMG_FONT_OPTION_OFF                            1454
+#define IMG_FONT_OPTION_ON                             1455
+#define IMG_FONT_VALUE_1                               1456
+#define IMG_FONT_VALUE_2                               1457
+#define IMG_FONT_VALUE_OLD                             1458
+#define IMG_FONT_LEVEL_NUMBER                          1459
+#define IMG_FONT_TAPE_RECORDER                         1460
+#define IMG_FONT_GAME_INFO                             1461
+#define IMG_GLOBAL_BORDER                              1462
+#define IMG_GLOBAL_DOOR                                        1463
+#define IMG_EDITOR_ELEMENT_BORDER                      1464
+#define IMG_EDITOR_ELEMENT_BORDER_INPUT                        1465
+#define IMG_BACKGROUND_ENVELOPE_1                      1466
+#define IMG_BACKGROUND_ENVELOPE_2                      1467
+#define IMG_BACKGROUND_ENVELOPE_3                      1468
+#define IMG_BACKGROUND_ENVELOPE_4                      1469
+#define IMG_BACKGROUND                                 1470
+#define IMG_BACKGROUND_MAIN                            1471
+#define IMG_BACKGROUND_LEVELS                          1472
+#define IMG_BACKGROUND_SCORES                          1473
+#define IMG_BACKGROUND_EDITOR                          1474
+#define IMG_BACKGROUND_INFO                            1475
+#define IMG_BACKGROUND_INFO_ELEMENTS                   1476
+#define IMG_BACKGROUND_SETUP                           1477
+#define IMG_BACKGROUND_DOOR                            1478
 
-#define NUM_IMAGE_FILES                                        1402
+#define NUM_IMAGE_FILES                                        1479
 
 #endif /* CONF_GFX_H */
index a7f7eb222856f4c3e079991d7c2f8676bf74182f..7f2b5bb6375b1fe8be306b81d0e79d1e147ab719 100644 (file)
@@ -77,7 +77,7 @@ struct ConfigInfo helpanim_config[] =
   { "char_quotedbl",                           "10"                    },
   { "char_numbersign",                         "10"                    },
   { "char_dollar",                             "10"                    },
-  { "char_procent",                            "10"                    },
+  { "char_percent",                            "10"                    },
   { "char_ampersand",                          "10"                    },
   { "char_apostrophe",                         "10"                    },
   { "char_parenleft",                          "10"                    },
index 1c29c617d7d4ed6ebd65acec197d9b55b36cac61..27ec9056f35678f6d3ebe16f29914b254e1ac3ae 100644 (file)
@@ -19,7 +19,7 @@
    reliable default values. If that value is MUS_ARG_UNDEFINED, it will
    be dynamically determined, using some of the other list values. */
 
-struct ConfigInfo music_config_suffix[] =
+struct ConfigTypeInfo music_config_suffix[] =
 {
   { ".mode_loop",                      ARG_UNDEFINED,  TYPE_BOOLEAN    },
 
index cd9869b081fa9fc32e6dca45cdcdfea7d0897d94..8cdd4d7b1f0f3740328b663fafdfa0f2aa302cdc 100644 (file)
    reliable default values. If that value is SND_ARG_UNDEFINED, it will
    be dynamically determined, using some of the other list values. */
 
-struct ConfigInfo sound_config_suffix[] =
+struct ConfigTypeInfo sound_config_suffix[] =
 {
   { ".mode_loop",                      ARG_UNDEFINED,  TYPE_BOOLEAN    },
+  { ".volume",                         "100",          TYPE_INTEGER    },
+  { ".priority",                       "0",            TYPE_INTEGER    },
 
   { NULL,                              NULL,           0               }
 };
@@ -110,7 +112,7 @@ struct ConfigInfo sound_config[] =
   { "spaceship.waiting",               "roehr.wav"                     },
   { "yamyam.moving",                   UNDEFINED_FILENAME              },
   { "yamyam.waiting",                  "njam.wav"                      },
-  { "yamyam.digging",                  UNDEFINED_FILENAME              },
+  { "yamyam.digging",                  "njam.wav"                      },
   { "robot.moving",                    "schlurf.wav"                   },
   { "robot.moving.mode_loop",          "false"                         },
   { "robot.waiting",                   UNDEFINED_FILENAME              },
@@ -139,6 +141,11 @@ struct ConfigInfo sound_config[] =
   { "spring.pushing",                  "pusch.wav"                     },
   { "spring.impact",                   "klopf.wav"                     },
   { "[wall].growing",                  UNDEFINED_FILENAME              },
+  { "emc_android.pushing",             "pusch.wav"                     },
+  { "emc_android.moving",              "roehr.wav"                     },
+  { "emc_android.moving.mode_loop",    "false"                         },
+  { "emc_android.dropping",            "deng.wav"                      },
+  { "emc_magic_ball.dropping",         "deng.wav"                      },
 
   /* sounds for Diamond Caves style elements and actions */
   { "pearl.collecting",                        "pong.wav"                      },
@@ -150,6 +157,7 @@ struct ConfigInfo sound_config[] =
   { "[envelope].opening",              UNDEFINED_FILENAME              },
   { "[envelope].closing",              UNDEFINED_FILENAME              },
   { "invisible_sand.digging",          "schlurf.wav"                   },
+  { "invisible_sand.active.digging",   "schlurf.wav"                   },
   { "shield_normal.collecting",                "pong.wav"                      },
   { "shield_normal.active",            UNDEFINED_FILENAME              },
   { "shield_deadly.collecting",                "pong.wav"                      },
index 280815531baa9238c241769878922d857588ed8a..91bb12919c557716bfdf656d6a011caed0f21f95 100644 (file)
 #define SND_SPRING_PUSHING                             95
 #define SND_SPRING_IMPACT                              96
 #define SND_CLASS_WALL_GROWING                         97
-#define SND_PEARL_COLLECTING                           98
-#define SND_PEARL_BREAKING                             99
-#define SND_PEARL_IMPACT                               100
-#define SND_CRYSTAL_COLLECTING                         101
-#define SND_CRYSTAL_IMPACT                             102
-#define SND_CLASS_ENVELOPE_COLLECTING                  103
-#define SND_CLASS_ENVELOPE_OPENING                     104
-#define SND_CLASS_ENVELOPE_CLOSING                     105
-#define SND_INVISIBLE_SAND_DIGGING                     106
-#define SND_SHIELD_NORMAL_COLLECTING                   107
-#define SND_SHIELD_NORMAL_ACTIVE                       108
-#define SND_SHIELD_DEADLY_COLLECTING                   109
-#define SND_SHIELD_DEADLY_ACTIVE                       110
-#define SND_EXTRA_TIME_COLLECTING                      111
-#define SND_MOLE_MOVING                                        112
-#define SND_MOLE_WAITING                               113
-#define SND_MOLE_DIGGING                               114
-#define SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING         115
-#define SND_CLASS_SWITCHGATE_OPENING                   116
-#define SND_CLASS_SWITCHGATE_CLOSING                   117
-#define SND_CLASS_SWITCHGATE_PASSING                   118
-#define SND_TIMEGATE_SWITCH_ACTIVATING                 119
-#define SND_TIMEGATE_SWITCH_ACTIVE                     120
-#define SND_TIMEGATE_SWITCH_DEACTIVATING               121
-#define SND_TIMEGATE_OPENING                           122
-#define SND_CLASS_TIMEGATE_CLOSING                     123
-#define SND_CLASS_TIMEGATE_PASSING                     124
-#define SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING      125
-#define SND_CLASS_CONVEYOR_BELT_ACTIVE                 126
-#define SND_CLASS_CONVEYOR_BELT_SWITCH_DEACTIVATING    127
-#define SND_LIGHT_SWITCH_ACTIVATING                    128
-#define SND_LIGHT_SWITCH_DEACTIVATING                  129
-#define SND_DX_SUPABOMB_PUSHING                                130
-#define SND_TRAP_DIGGING                               131
-#define SND_TRAP_ACTIVATING                            132
-#define SND_CLASS_TUBE_WALKING                         133
-#define SND_AMOEBA_TURNING_TO_GEM                      134
-#define SND_AMOEBA_TURNING_TO_ROCK                     135
-#define SND_SPEED_PILL_COLLECTING                      136
-#define SND_DYNABOMB_INCREASE_NUMBER_COLLECTING                137
-#define SND_DYNABOMB_INCREASE_SIZE_COLLECTING          138
-#define SND_DYNABOMB_INCREASE_POWER_COLLECTING         139
-#define SND_CLASS_DYNABOMB_DROPPING                    140
-#define SND_CLASS_DYNABOMB_ACTIVE                      141
-#define SND_SATELLITE_MOVING                           142
-#define SND_SATELLITE_WAITING                          143
-#define SND_SATELLITE_PUSHING                          144
-#define SND_LAMP_ACTIVATING                            145
-#define SND_LAMP_DEACTIVATING                          146
-#define SND_TIME_ORB_FULL_COLLECTING                   147
-#define SND_TIME_ORB_FULL_IMPACT                       148
-#define SND_TIME_ORB_EMPTY_PUSHING                     149
-#define SND_TIME_ORB_EMPTY_IMPACT                      150
-#define SND_GAME_OF_LIFE_WAITING                       151
-#define SND_GAME_OF_LIFE_GROWING                       152
-#define SND_BIOMAZE_WAITING                            153
-#define SND_BIOMAZE_GROWING                            154
-#define SND_PACMAN_MOVING                              155
-#define SND_PACMAN_WAITING                             156
-#define SND_PACMAN_DIGGING                             157
-#define SND_DARK_YAMYAM_MOVING                         158
-#define SND_DARK_YAMYAM_WAITING                                159
-#define SND_DARK_YAMYAM_DIGGING                                160
-#define SND_PENGUIN_MOVING                             161
-#define SND_PENGUIN_WAITING                            162
-#define SND_PIG_MOVING                                 163
-#define SND_PIG_WAITING                                        164
-#define SND_PIG_DIGGING                                        165
-#define SND_DRAGON_MOVING                              166
-#define SND_DRAGON_WAITING                             167
-#define SND_DRAGON_ATTACKING                           168
-#define SND_GAME_STARTING                              169
-#define SND_GAME_RUNNING_OUT_OF_TIME                   170
-#define SND_GAME_LEVELTIME_BONUS                       171
-#define SND_GAME_LOSING                                        172
-#define SND_GAME_WINNING                               173
-#define SND_GAME_SOKOBAN_SOLVING                       174
-#define SND_DOOR_OPENING                               175
-#define SND_DOOR_CLOSING                               176
-#define SND_BACKGROUND_MAIN                            177
-#define SND_BACKGROUND_LEVELS                          178
-#define SND_BACKGROUND_SCORES                          179
-#define SND_BACKGROUND_EDITOR                          180
-#define SND_BACKGROUND_INFO                            181
-#define SND_BACKGROUND_SETUP                           182
+#define SND_EMC_ANDROID_PUSHING                                98
+#define SND_EMC_ANDROID_MOVING                         99
+#define SND_EMC_ANDROID_DROPPING                       100
+#define SND_EMC_MAGIC_BALL_DROPPING                    101
+#define SND_PEARL_COLLECTING                           102
+#define SND_PEARL_BREAKING                             103
+#define SND_PEARL_IMPACT                               104
+#define SND_CRYSTAL_COLLECTING                         105
+#define SND_CRYSTAL_IMPACT                             106
+#define SND_CLASS_ENVELOPE_COLLECTING                  107
+#define SND_CLASS_ENVELOPE_OPENING                     108
+#define SND_CLASS_ENVELOPE_CLOSING                     109
+#define SND_INVISIBLE_SAND_DIGGING                     110
+#define SND_INVISIBLE_SAND_ACTIVE_DIGGING              111
+#define SND_SHIELD_NORMAL_COLLECTING                   112
+#define SND_SHIELD_NORMAL_ACTIVE                       113
+#define SND_SHIELD_DEADLY_COLLECTING                   114
+#define SND_SHIELD_DEADLY_ACTIVE                       115
+#define SND_EXTRA_TIME_COLLECTING                      116
+#define SND_MOLE_MOVING                                        117
+#define SND_MOLE_WAITING                               118
+#define SND_MOLE_DIGGING                               119
+#define SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING         120
+#define SND_CLASS_SWITCHGATE_OPENING                   121
+#define SND_CLASS_SWITCHGATE_CLOSING                   122
+#define SND_CLASS_SWITCHGATE_PASSING                   123
+#define SND_TIMEGATE_SWITCH_ACTIVATING                 124
+#define SND_TIMEGATE_SWITCH_ACTIVE                     125
+#define SND_TIMEGATE_SWITCH_DEACTIVATING               126
+#define SND_TIMEGATE_OPENING                           127
+#define SND_CLASS_TIMEGATE_CLOSING                     128
+#define SND_CLASS_TIMEGATE_PASSING                     129
+#define SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING      130
+#define SND_CLASS_CONVEYOR_BELT_ACTIVE                 131
+#define SND_CLASS_CONVEYOR_BELT_SWITCH_DEACTIVATING    132
+#define SND_LIGHT_SWITCH_ACTIVATING                    133
+#define SND_LIGHT_SWITCH_DEACTIVATING                  134
+#define SND_DX_SUPABOMB_PUSHING                                135
+#define SND_TRAP_DIGGING                               136
+#define SND_TRAP_ACTIVATING                            137
+#define SND_CLASS_TUBE_WALKING                         138
+#define SND_AMOEBA_TURNING_TO_GEM                      139
+#define SND_AMOEBA_TURNING_TO_ROCK                     140
+#define SND_SPEED_PILL_COLLECTING                      141
+#define SND_DYNABOMB_INCREASE_NUMBER_COLLECTING                142
+#define SND_DYNABOMB_INCREASE_SIZE_COLLECTING          143
+#define SND_DYNABOMB_INCREASE_POWER_COLLECTING         144
+#define SND_CLASS_DYNABOMB_DROPPING                    145
+#define SND_CLASS_DYNABOMB_ACTIVE                      146
+#define SND_SATELLITE_MOVING                           147
+#define SND_SATELLITE_WAITING                          148
+#define SND_SATELLITE_PUSHING                          149
+#define SND_LAMP_ACTIVATING                            150
+#define SND_LAMP_DEACTIVATING                          151
+#define SND_TIME_ORB_FULL_COLLECTING                   152
+#define SND_TIME_ORB_FULL_IMPACT                       153
+#define SND_TIME_ORB_EMPTY_PUSHING                     154
+#define SND_TIME_ORB_EMPTY_IMPACT                      155
+#define SND_GAME_OF_LIFE_WAITING                       156
+#define SND_GAME_OF_LIFE_GROWING                       157
+#define SND_BIOMAZE_WAITING                            158
+#define SND_BIOMAZE_GROWING                            159
+#define SND_PACMAN_MOVING                              160
+#define SND_PACMAN_WAITING                             161
+#define SND_PACMAN_DIGGING                             162
+#define SND_DARK_YAMYAM_MOVING                         163
+#define SND_DARK_YAMYAM_WAITING                                164
+#define SND_DARK_YAMYAM_DIGGING                                165
+#define SND_PENGUIN_MOVING                             166
+#define SND_PENGUIN_WAITING                            167
+#define SND_PIG_MOVING                                 168
+#define SND_PIG_WAITING                                        169
+#define SND_PIG_DIGGING                                        170
+#define SND_DRAGON_MOVING                              171
+#define SND_DRAGON_WAITING                             172
+#define SND_DRAGON_ATTACKING                           173
+#define SND_GAME_STARTING                              174
+#define SND_GAME_RUNNING_OUT_OF_TIME                   175
+#define SND_GAME_LEVELTIME_BONUS                       176
+#define SND_GAME_LOSING                                        177
+#define SND_GAME_WINNING                               178
+#define SND_GAME_SOKOBAN_SOLVING                       179
+#define SND_DOOR_OPENING                               180
+#define SND_DOOR_CLOSING                               181
+#define SND_BACKGROUND_MAIN                            182
+#define SND_BACKGROUND_LEVELS                          183
+#define SND_BACKGROUND_SCORES                          184
+#define SND_BACKGROUND_EDITOR                          185
+#define SND_BACKGROUND_INFO                            186
+#define SND_BACKGROUND_SETUP                           187
 
-#define NUM_SOUND_FILES                                        183
+#define NUM_SOUND_FILES                                        188
 
 #endif /* CONF_SND_H */
index 7e962cc66ae8d15e60db268447301c5881e7324c..d3021871bce22ecfbfefc29523fc0442d2a19976 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2004-06-07 01:56]"
+#define COMPILE_DATE_STRING "[2005-08-16 00:08]"
index 9236f0a910ae59ed43758a5845921672d10bb7c4..f4b017cc724e5385409ac8d2a990833d57e8518b 100644 (file)
                                         MINI_TILEX / 2)
 
 /* values for the settings windows */
-#define ED_SETTINGS_XSTART             (3 * MINI_TILEX / 2)
-#define ED_SETTINGS_YSTART             (MINI_TILEY * 10)
+#define ED_LEVEL_SETTINGS_XSTART       (3 * MINI_TILEX / 2)
+#define ED_LEVEL_SETTINGS_YSTART       (5 * MINI_TILEY)
+
+#define ED_ELEMENT_SETTINGS_XSTART     (3 * MINI_TILEX / 2)
+#define ED_ELEMENT_SETTINGS_YSTART     (10 * MINI_TILEY)
 
 #define ED_XOFFSET_CHECKBOX            (ED_CHECKBUTTON_XSIZE +         \
                                         2 * ED_GADGET_DISTANCE)
 #define ED_SETTINGS_XOFFSET            ED_XOFFSET_CHECKBOX
 #define ED_SETTINGS_YOFFSET            (3 * MINI_TILEY / 2)
 
-#define ED_SETTINGS_XPOS(n)            (ED_SETTINGS_XSTART +           \
+#define ED_LEVEL_SETTINGS_XPOS(n)      (ED_LEVEL_SETTINGS_XSTART +     \
                                         (n) * ED_SETTINGS_XOFFSET)
-#define ED_SETTINGS_YPOS(n)            (ED_SETTINGS_YSTART +           \
+#define ED_LEVEL_SETTINGS_YPOS(n)      (ED_LEVEL_SETTINGS_YSTART +     \
+                                        (n) * ED_SETTINGS_YOFFSET)
+
+#define ED_ELEMENT_SETTINGS_XPOS(n)    (ED_ELEMENT_SETTINGS_XSTART +   \
+                                        (n) * ED_SETTINGS_XOFFSET)
+#define ED_ELEMENT_SETTINGS_YPOS(n)    (ED_ELEMENT_SETTINGS_YSTART +   \
                                         (n) * ED_SETTINGS_YOFFSET)
 
 #define ED_SETTINGS1_YPOS              MINI_TILEY
                                         (n) * ED_COUNTER_YDISTANCE - 2)
 
 /* values for element content drawing areas */
-#define ED_AREA_1X1_SETTINGS_XPOS(n)   (ED_SETTINGS_XPOS(n))
-#define ED_AREA_1X1_SETTINGS_YPOS(n)   (ED_SETTINGS_YPOS(n) +          \
+#define ED_AREA_1X1_SETTINGS_XPOS(n)   (ED_ELEMENT_SETTINGS_XPOS(n))
+#define ED_AREA_1X1_SETTINGS_YPOS(n)   (ED_ELEMENT_SETTINGS_YPOS(n) +  \
                                         ED_GADGET_DISTANCE)
 
-#define ED_AREA_3X3_SETTINGS_XPOS(n)   (ED_SETTINGS_XPOS(n))
-#define ED_AREA_3X3_SETTINGS_YPOS(n)   (ED_SETTINGS_YPOS(n) +          \
+#define ED_AREA_3X3_SETTINGS_XPOS(n)   (ED_ELEMENT_SETTINGS_XPOS(n))
+#define ED_AREA_3X3_SETTINGS_YPOS(n)   (ED_ELEMENT_SETTINGS_YPOS(n) +  \
                                         ED_GADGET_DISTANCE - MINI_TILEY)
 
 /* yamyam content */
 #define ED_AREA_YAMYAM_CONTENT_YPOS(n) (17 * MINI_TILEY +              \
                                         6 * ((n) / 4) * MINI_TILEY)
 
+/* magic ball content */
+#define ED_AREA_MAGIC_BALL_CONTENT_XPOS(n) (2 * MINI_TILEX +           \
+                                           5 * ((n) % 4) * MINI_TILEX)
+#define ED_AREA_MAGIC_BALL_CONTENT_YPOS(n) (17 * MINI_TILEY +          \
+                                           6 * ((n) / 4) * MINI_TILEY)
+
 /* values for scrolling gadgets for drawing area */
 #define ED_SCROLLBUTTON_XPOS           24
 #define ED_SCROLLBUTTON_YPOS           0
 #define GADGET_ID_LEVEL_TIMESCORE_DOWN (GADGET_ID_COUNTER_FIRST + 18)
 #define GADGET_ID_LEVEL_TIMESCORE_TEXT (GADGET_ID_COUNTER_FIRST + 19)
 #define GADGET_ID_LEVEL_TIMESCORE_UP   (GADGET_ID_COUNTER_FIRST + 20)
-#define GADGET_ID_ELEMENT_SCORE_DOWN   (GADGET_ID_COUNTER_FIRST + 21)
-#define GADGET_ID_ELEMENT_SCORE_TEXT   (GADGET_ID_COUNTER_FIRST + 22)
-#define GADGET_ID_ELEMENT_SCORE_UP     (GADGET_ID_COUNTER_FIRST + 23)
-#define GADGET_ID_ELEMENT_CONTENT_DOWN (GADGET_ID_COUNTER_FIRST + 24)
-#define GADGET_ID_ELEMENT_CONTENT_TEXT (GADGET_ID_COUNTER_FIRST + 25)
-#define GADGET_ID_ELEMENT_CONTENT_UP   (GADGET_ID_COUNTER_FIRST + 26)
-#define GADGET_ID_ENVELOPE_XSIZE_DOWN  (GADGET_ID_COUNTER_FIRST + 27)
-#define GADGET_ID_ENVELOPE_XSIZE_TEXT  (GADGET_ID_COUNTER_FIRST + 28)
-#define GADGET_ID_ENVELOPE_XSIZE_UP    (GADGET_ID_COUNTER_FIRST + 29)
-#define GADGET_ID_ENVELOPE_YSIZE_DOWN  (GADGET_ID_COUNTER_FIRST + 30)
-#define GADGET_ID_ENVELOPE_YSIZE_TEXT  (GADGET_ID_COUNTER_FIRST + 31)
-#define GADGET_ID_ENVELOPE_YSIZE_UP    (GADGET_ID_COUNTER_FIRST + 32)
-#define GADGET_ID_CUSTOM_SCORE_DOWN    (GADGET_ID_COUNTER_FIRST + 33)
-#define GADGET_ID_CUSTOM_SCORE_TEXT    (GADGET_ID_COUNTER_FIRST + 34)
-#define GADGET_ID_CUSTOM_SCORE_UP      (GADGET_ID_COUNTER_FIRST + 35)
-#define GADGET_ID_CUSTOM_GEMCOUNT_DOWN (GADGET_ID_COUNTER_FIRST + 36)
-#define GADGET_ID_CUSTOM_GEMCOUNT_TEXT (GADGET_ID_COUNTER_FIRST + 37)
-#define GADGET_ID_CUSTOM_GEMCOUNT_UP   (GADGET_ID_COUNTER_FIRST + 38)
-#define GADGET_ID_PUSH_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 39)
-#define GADGET_ID_PUSH_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 40)
-#define GADGET_ID_PUSH_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 41)
-#define GADGET_ID_PUSH_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 42)
-#define GADGET_ID_PUSH_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 43)
-#define GADGET_ID_PUSH_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 44)
-#define GADGET_ID_DROP_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 45)
-#define GADGET_ID_DROP_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 46)
-#define GADGET_ID_DROP_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 47)
-#define GADGET_ID_DROP_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 48)
-#define GADGET_ID_DROP_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 49)
-#define GADGET_ID_DROP_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 50)
-#define GADGET_ID_MOVE_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 51)
-#define GADGET_ID_MOVE_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 52)
-#define GADGET_ID_MOVE_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 53)
-#define GADGET_ID_MOVE_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 54)
-#define GADGET_ID_MOVE_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 55)
-#define GADGET_ID_MOVE_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 56)
-#define GADGET_ID_EXPLOSION_DELAY_DOWN (GADGET_ID_COUNTER_FIRST + 57)
-#define GADGET_ID_EXPLOSION_DELAY_TEXT (GADGET_ID_COUNTER_FIRST + 58)
-#define GADGET_ID_EXPLOSION_DELAY_UP   (GADGET_ID_COUNTER_FIRST + 59)
-#define GADGET_ID_IGNITION_DELAY_DOWN  (GADGET_ID_COUNTER_FIRST + 60)
-#define GADGET_ID_IGNITION_DELAY_TEXT  (GADGET_ID_COUNTER_FIRST + 61)
-#define GADGET_ID_IGNITION_DELAY_UP    (GADGET_ID_COUNTER_FIRST + 62)
-#define GADGET_ID_CHANGE_DELAY_FIX_DOWN        (GADGET_ID_COUNTER_FIRST + 63)
-#define GADGET_ID_CHANGE_DELAY_FIX_TEXT        (GADGET_ID_COUNTER_FIRST + 64)
-#define GADGET_ID_CHANGE_DELAY_FIX_UP  (GADGET_ID_COUNTER_FIRST + 65)
-#define GADGET_ID_CHANGE_DELAY_RND_DOWN        (GADGET_ID_COUNTER_FIRST + 66)
-#define GADGET_ID_CHANGE_DELAY_RND_TEXT        (GADGET_ID_COUNTER_FIRST + 67)
-#define GADGET_ID_CHANGE_DELAY_RND_UP  (GADGET_ID_COUNTER_FIRST + 68)
-#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 69)
-#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 70)
-#define GADGET_ID_CHANGE_CONT_RND_UP   (GADGET_ID_COUNTER_FIRST + 71)
-#define GADGET_ID_GROUP_CONTENT_DOWN   (GADGET_ID_COUNTER_FIRST + 72)
-#define GADGET_ID_GROUP_CONTENT_TEXT   (GADGET_ID_COUNTER_FIRST + 73)
-#define GADGET_ID_GROUP_CONTENT_UP     (GADGET_ID_COUNTER_FIRST + 74)
+#define GADGET_ID_ELEMENT_VALUE1_DOWN  (GADGET_ID_COUNTER_FIRST + 21)
+#define GADGET_ID_ELEMENT_VALUE1_TEXT  (GADGET_ID_COUNTER_FIRST + 22)
+#define GADGET_ID_ELEMENT_VALUE1_UP    (GADGET_ID_COUNTER_FIRST + 23)
+#define GADGET_ID_ELEMENT_VALUE2_DOWN  (GADGET_ID_COUNTER_FIRST + 24)
+#define GADGET_ID_ELEMENT_VALUE2_TEXT  (GADGET_ID_COUNTER_FIRST + 25)
+#define GADGET_ID_ELEMENT_VALUE2_UP    (GADGET_ID_COUNTER_FIRST + 26)
+#define GADGET_ID_YAMYAM_CONTENT_DOWN  (GADGET_ID_COUNTER_FIRST + 27)
+#define GADGET_ID_YAMYAM_CONTENT_TEXT  (GADGET_ID_COUNTER_FIRST + 28)
+#define GADGET_ID_YAMYAM_CONTENT_UP    (GADGET_ID_COUNTER_FIRST + 29)
+#define GADGET_ID_ENVELOPE_XSIZE_DOWN  (GADGET_ID_COUNTER_FIRST + 30)
+#define GADGET_ID_ENVELOPE_XSIZE_TEXT  (GADGET_ID_COUNTER_FIRST + 31)
+#define GADGET_ID_ENVELOPE_XSIZE_UP    (GADGET_ID_COUNTER_FIRST + 32)
+#define GADGET_ID_ENVELOPE_YSIZE_DOWN  (GADGET_ID_COUNTER_FIRST + 33)
+#define GADGET_ID_ENVELOPE_YSIZE_TEXT  (GADGET_ID_COUNTER_FIRST + 34)
+#define GADGET_ID_ENVELOPE_YSIZE_UP    (GADGET_ID_COUNTER_FIRST + 35)
+#define GADGET_ID_CUSTOM_SCORE_DOWN    (GADGET_ID_COUNTER_FIRST + 36)
+#define GADGET_ID_CUSTOM_SCORE_TEXT    (GADGET_ID_COUNTER_FIRST + 37)
+#define GADGET_ID_CUSTOM_SCORE_UP      (GADGET_ID_COUNTER_FIRST + 38)
+#define GADGET_ID_CUSTOM_GEMCOUNT_DOWN (GADGET_ID_COUNTER_FIRST + 39)
+#define GADGET_ID_CUSTOM_GEMCOUNT_TEXT (GADGET_ID_COUNTER_FIRST + 40)
+#define GADGET_ID_CUSTOM_GEMCOUNT_UP   (GADGET_ID_COUNTER_FIRST + 41)
+#define GADGET_ID_PUSH_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 42)
+#define GADGET_ID_PUSH_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 43)
+#define GADGET_ID_PUSH_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 44)
+#define GADGET_ID_PUSH_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 45)
+#define GADGET_ID_PUSH_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 46)
+#define GADGET_ID_PUSH_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 47)
+#define GADGET_ID_DROP_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 48)
+#define GADGET_ID_DROP_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 49)
+#define GADGET_ID_DROP_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 50)
+#define GADGET_ID_DROP_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 51)
+#define GADGET_ID_DROP_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 52)
+#define GADGET_ID_DROP_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 53)
+#define GADGET_ID_MOVE_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 54)
+#define GADGET_ID_MOVE_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 55)
+#define GADGET_ID_MOVE_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 56)
+#define GADGET_ID_MOVE_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 57)
+#define GADGET_ID_MOVE_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 58)
+#define GADGET_ID_MOVE_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 59)
+#define GADGET_ID_EXPLOSION_DELAY_DOWN (GADGET_ID_COUNTER_FIRST + 60)
+#define GADGET_ID_EXPLOSION_DELAY_TEXT (GADGET_ID_COUNTER_FIRST + 61)
+#define GADGET_ID_EXPLOSION_DELAY_UP   (GADGET_ID_COUNTER_FIRST + 62)
+#define GADGET_ID_IGNITION_DELAY_DOWN  (GADGET_ID_COUNTER_FIRST + 63)
+#define GADGET_ID_IGNITION_DELAY_TEXT  (GADGET_ID_COUNTER_FIRST + 64)
+#define GADGET_ID_IGNITION_DELAY_UP    (GADGET_ID_COUNTER_FIRST + 65)
+#define GADGET_ID_CHANGE_DELAY_FIX_DOWN        (GADGET_ID_COUNTER_FIRST + 66)
+#define GADGET_ID_CHANGE_DELAY_FIX_TEXT        (GADGET_ID_COUNTER_FIRST + 67)
+#define GADGET_ID_CHANGE_DELAY_FIX_UP  (GADGET_ID_COUNTER_FIRST + 68)
+#define GADGET_ID_CHANGE_DELAY_RND_DOWN        (GADGET_ID_COUNTER_FIRST + 69)
+#define GADGET_ID_CHANGE_DELAY_RND_TEXT        (GADGET_ID_COUNTER_FIRST + 70)
+#define GADGET_ID_CHANGE_DELAY_RND_UP  (GADGET_ID_COUNTER_FIRST + 71)
+#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 72)
+#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 73)
+#define GADGET_ID_CHANGE_CONT_RND_UP   (GADGET_ID_COUNTER_FIRST + 74)
+#define GADGET_ID_GROUP_CONTENT_DOWN   (GADGET_ID_COUNTER_FIRST + 75)
+#define GADGET_ID_GROUP_CONTENT_TEXT   (GADGET_ID_COUNTER_FIRST + 76)
+#define GADGET_ID_GROUP_CONTENT_UP     (GADGET_ID_COUNTER_FIRST + 77)
 
 /* drawing area identifiers */
-#define GADGET_ID_DRAWING_AREA_FIRST   (GADGET_ID_COUNTER_FIRST + 75)
+#define GADGET_ID_DRAWING_AREA_FIRST   (GADGET_ID_COUNTER_FIRST + 78)
 
 #define GADGET_ID_DRAWING_LEVEL                (GADGET_ID_DRAWING_AREA_FIRST + 0)
-#define GADGET_ID_ELEMENT_CONTENT_0    (GADGET_ID_DRAWING_AREA_FIRST + 1)
-#define GADGET_ID_ELEMENT_CONTENT_1    (GADGET_ID_DRAWING_AREA_FIRST + 2)
-#define GADGET_ID_ELEMENT_CONTENT_2    (GADGET_ID_DRAWING_AREA_FIRST + 3)
-#define GADGET_ID_ELEMENT_CONTENT_3    (GADGET_ID_DRAWING_AREA_FIRST + 4)
-#define GADGET_ID_ELEMENT_CONTENT_4    (GADGET_ID_DRAWING_AREA_FIRST + 5)
-#define GADGET_ID_ELEMENT_CONTENT_5    (GADGET_ID_DRAWING_AREA_FIRST + 6)
-#define GADGET_ID_ELEMENT_CONTENT_6    (GADGET_ID_DRAWING_AREA_FIRST + 7)
-#define GADGET_ID_ELEMENT_CONTENT_7    (GADGET_ID_DRAWING_AREA_FIRST + 8)
-#define GADGET_ID_AMOEBA_CONTENT       (GADGET_ID_DRAWING_AREA_FIRST + 9)
-#define GADGET_ID_CUSTOM_GRAPHIC       (GADGET_ID_DRAWING_AREA_FIRST + 10)
-#define GADGET_ID_CUSTOM_CONTENT       (GADGET_ID_DRAWING_AREA_FIRST + 11)
-#define GADGET_ID_CUSTOM_MOVE_ENTER    (GADGET_ID_DRAWING_AREA_FIRST + 12)
-#define GADGET_ID_CUSTOM_MOVE_LEAVE    (GADGET_ID_DRAWING_AREA_FIRST + 13)
-#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 14)
-#define GADGET_ID_CUSTOM_CHANGE_CONTENT        (GADGET_ID_DRAWING_AREA_FIRST + 15)
-#define GADGET_ID_CUSTOM_CHANGE_TRIGGER        (GADGET_ID_DRAWING_AREA_FIRST + 16)
-#define GADGET_ID_GROUP_CONTENT                (GADGET_ID_DRAWING_AREA_FIRST + 17)
-#define GADGET_ID_RANDOM_BACKGROUND    (GADGET_ID_DRAWING_AREA_FIRST + 18)
+#define GADGET_ID_YAMYAM_CONTENT_0     (GADGET_ID_DRAWING_AREA_FIRST + 1)
+#define GADGET_ID_YAMYAM_CONTENT_1     (GADGET_ID_DRAWING_AREA_FIRST + 2)
+#define GADGET_ID_YAMYAM_CONTENT_2     (GADGET_ID_DRAWING_AREA_FIRST + 3)
+#define GADGET_ID_YAMYAM_CONTENT_3     (GADGET_ID_DRAWING_AREA_FIRST + 4)
+#define GADGET_ID_YAMYAM_CONTENT_4     (GADGET_ID_DRAWING_AREA_FIRST + 5)
+#define GADGET_ID_YAMYAM_CONTENT_5     (GADGET_ID_DRAWING_AREA_FIRST + 6)
+#define GADGET_ID_YAMYAM_CONTENT_6     (GADGET_ID_DRAWING_AREA_FIRST + 7)
+#define GADGET_ID_YAMYAM_CONTENT_7     (GADGET_ID_DRAWING_AREA_FIRST + 8)
+#define GADGET_ID_MAGIC_BALL_CONTENT_0 (GADGET_ID_DRAWING_AREA_FIRST + 9)
+#define GADGET_ID_MAGIC_BALL_CONTENT_1 (GADGET_ID_DRAWING_AREA_FIRST + 10)
+#define GADGET_ID_MAGIC_BALL_CONTENT_2 (GADGET_ID_DRAWING_AREA_FIRST + 11)
+#define GADGET_ID_MAGIC_BALL_CONTENT_3 (GADGET_ID_DRAWING_AREA_FIRST + 12)
+#define GADGET_ID_MAGIC_BALL_CONTENT_4 (GADGET_ID_DRAWING_AREA_FIRST + 13)
+#define GADGET_ID_MAGIC_BALL_CONTENT_5 (GADGET_ID_DRAWING_AREA_FIRST + 14)
+#define GADGET_ID_MAGIC_BALL_CONTENT_6 (GADGET_ID_DRAWING_AREA_FIRST + 15)
+#define GADGET_ID_MAGIC_BALL_CONTENT_7 (GADGET_ID_DRAWING_AREA_FIRST + 16)
+#define GADGET_ID_AMOEBA_CONTENT       (GADGET_ID_DRAWING_AREA_FIRST + 17)
+#define GADGET_ID_CUSTOM_GRAPHIC       (GADGET_ID_DRAWING_AREA_FIRST + 18)
+#define GADGET_ID_CUSTOM_CONTENT       (GADGET_ID_DRAWING_AREA_FIRST + 19)
+#define GADGET_ID_CUSTOM_MOVE_ENTER    (GADGET_ID_DRAWING_AREA_FIRST + 20)
+#define GADGET_ID_CUSTOM_MOVE_LEAVE    (GADGET_ID_DRAWING_AREA_FIRST + 21)
+#define GADGET_ID_CUSTOM_CHANGE_TARGET (GADGET_ID_DRAWING_AREA_FIRST + 22)
+#define GADGET_ID_CUSTOM_CHANGE_CONTENT        (GADGET_ID_DRAWING_AREA_FIRST + 23)
+#define GADGET_ID_CUSTOM_CHANGE_TRIGGER        (GADGET_ID_DRAWING_AREA_FIRST + 24)
+#define GADGET_ID_GROUP_CONTENT                (GADGET_ID_DRAWING_AREA_FIRST + 25)
+#define GADGET_ID_RANDOM_BACKGROUND    (GADGET_ID_DRAWING_AREA_FIRST + 26)
 
 /* text input identifiers */
-#define GADGET_ID_TEXT_INPUT_FIRST     (GADGET_ID_DRAWING_AREA_FIRST + 19)
+#define GADGET_ID_TEXT_INPUT_FIRST     (GADGET_ID_DRAWING_AREA_FIRST + 27)
 
 #define GADGET_ID_LEVEL_NAME           (GADGET_ID_TEXT_INPUT_FIRST + 0)
 #define GADGET_ID_LEVEL_AUTHOR         (GADGET_ID_TEXT_INPUT_FIRST + 1)
 #define GADGET_ID_SELECTBOX_FIRST      (GADGET_ID_TEXT_AREA_FIRST + 1)
 
 #define GADGET_ID_TIME_OR_STEPS                (GADGET_ID_SELECTBOX_FIRST + 0)
-#define GADGET_ID_CUSTOM_WALK_TO_ACTION        (GADGET_ID_SELECTBOX_FIRST + 1)
-#define GADGET_ID_CUSTOM_EXPLOSION_TYPE        (GADGET_ID_SELECTBOX_FIRST + 2)
-#define GADGET_ID_CUSTOM_DEADLINESS    (GADGET_ID_SELECTBOX_FIRST + 3)
-#define GADGET_ID_CUSTOM_MOVE_PATTERN  (GADGET_ID_SELECTBOX_FIRST + 4)
-#define GADGET_ID_CUSTOM_MOVE_DIRECTION        (GADGET_ID_SELECTBOX_FIRST + 5)
-#define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 6)
-#define GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE (GADGET_ID_SELECTBOX_FIRST + 7)
-#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 8)
-#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 9)
-#define GADGET_ID_CUSTOM_ACCESS_TYPE   (GADGET_ID_SELECTBOX_FIRST + 10)
-#define GADGET_ID_CUSTOM_ACCESS_LAYER  (GADGET_ID_SELECTBOX_FIRST + 11)
-#define GADGET_ID_CUSTOM_ACCESS_PROTECTED (GADGET_ID_SELECTBOX_FIRST + 12)
-#define GADGET_ID_CUSTOM_ACCESS_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 13)
-#define GADGET_ID_CHANGE_TIME_UNITS    (GADGET_ID_SELECTBOX_FIRST + 14)
-#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 15)
-#define GADGET_ID_CHANGE_OTHER_ACTION  (GADGET_ID_SELECTBOX_FIRST + 16)
-#define GADGET_ID_CHANGE_SIDE          (GADGET_ID_SELECTBOX_FIRST + 17)
-#define GADGET_ID_CHANGE_PLAYER                (GADGET_ID_SELECTBOX_FIRST + 18)
-#define GADGET_ID_CHANGE_PAGE          (GADGET_ID_SELECTBOX_FIRST + 19)
-#define GADGET_ID_CHANGE_REPLACE_WHEN  (GADGET_ID_SELECTBOX_FIRST + 20)
-#define GADGET_ID_SELECT_CHANGE_PAGE   (GADGET_ID_SELECTBOX_FIRST + 21)
-#define GADGET_ID_GROUP_CHOICE_MODE    (GADGET_ID_SELECTBOX_FIRST + 22)
+#define GADGET_ID_GAME_ENGINE_TYPE     (GADGET_ID_SELECTBOX_FIRST + 1)
+#define GADGET_ID_CUSTOM_WALK_TO_ACTION        (GADGET_ID_SELECTBOX_FIRST + 2)
+#define GADGET_ID_CUSTOM_EXPLOSION_TYPE        (GADGET_ID_SELECTBOX_FIRST + 3)
+#define GADGET_ID_CUSTOM_DEADLINESS    (GADGET_ID_SELECTBOX_FIRST + 4)
+#define GADGET_ID_CUSTOM_MOVE_PATTERN  (GADGET_ID_SELECTBOX_FIRST + 5)
+#define GADGET_ID_CUSTOM_MOVE_DIRECTION        (GADGET_ID_SELECTBOX_FIRST + 6)
+#define GADGET_ID_CUSTOM_MOVE_STEPSIZE (GADGET_ID_SELECTBOX_FIRST + 7)
+#define GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE (GADGET_ID_SELECTBOX_FIRST + 8)
+#define GADGET_ID_CUSTOM_SMASH_TARGETS (GADGET_ID_SELECTBOX_FIRST + 9)
+#define GADGET_ID_CUSTOM_SLIPPERY_TYPE (GADGET_ID_SELECTBOX_FIRST + 10)
+#define GADGET_ID_CUSTOM_ACCESS_TYPE   (GADGET_ID_SELECTBOX_FIRST + 11)
+#define GADGET_ID_CUSTOM_ACCESS_LAYER  (GADGET_ID_SELECTBOX_FIRST + 12)
+#define GADGET_ID_CUSTOM_ACCESS_PROTECTED (GADGET_ID_SELECTBOX_FIRST + 13)
+#define GADGET_ID_CUSTOM_ACCESS_DIRECTION (GADGET_ID_SELECTBOX_FIRST + 14)
+#define GADGET_ID_CHANGE_TIME_UNITS    (GADGET_ID_SELECTBOX_FIRST + 15)
+#define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_CHANGE_OTHER_ACTION  (GADGET_ID_SELECTBOX_FIRST + 17)
+#define GADGET_ID_CHANGE_SIDE          (GADGET_ID_SELECTBOX_FIRST + 18)
+#define GADGET_ID_CHANGE_PLAYER                (GADGET_ID_SELECTBOX_FIRST + 19)
+#define GADGET_ID_CHANGE_PAGE          (GADGET_ID_SELECTBOX_FIRST + 20)
+#define GADGET_ID_CHANGE_REPLACE_WHEN  (GADGET_ID_SELECTBOX_FIRST + 21)
+#define GADGET_ID_SELECT_CHANGE_PAGE   (GADGET_ID_SELECTBOX_FIRST + 22)
+#define GADGET_ID_GROUP_CHOICE_MODE    (GADGET_ID_SELECTBOX_FIRST + 23)
 
 /* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST     (GADGET_ID_SELECTBOX_FIRST + 23)
+#define GADGET_ID_TEXTBUTTON_FIRST     (GADGET_ID_SELECTBOX_FIRST + 24)
 
 #define GADGET_ID_PROPERTIES_INFO      (GADGET_ID_TEXTBUTTON_FIRST + 0)
 #define GADGET_ID_PROPERTIES_CONFIG    (GADGET_ID_TEXTBUTTON_FIRST + 1)
 #define GADGET_ID_RANDOM_PERCENTAGE    (GADGET_ID_CHECKBUTTON_FIRST + 0)
 #define GADGET_ID_RANDOM_QUANTITY      (GADGET_ID_CHECKBUTTON_FIRST + 1)
 #define GADGET_ID_RANDOM_RESTRICTED    (GADGET_ID_CHECKBUTTON_FIRST + 2)
-#define GADGET_ID_DOUBLE_SPEED         (GADGET_ID_CHECKBUTTON_FIRST + 3)
-#define GADGET_ID_GRAVITY              (GADGET_ID_CHECKBUTTON_FIRST + 4)
-#define GADGET_ID_STICK_ELEMENT                (GADGET_ID_CHECKBUTTON_FIRST + 5)
-#define GADGET_ID_EM_SLIPPERY_GEMS     (GADGET_ID_CHECKBUTTON_FIRST + 6)
-#define GADGET_ID_USE_SPRING_BUG       (GADGET_ID_CHECKBUTTON_FIRST + 7)
-#define GADGET_ID_GROW_INTO_DIGGABLE   (GADGET_ID_CHECKBUTTON_FIRST + 8)
+#define GADGET_ID_INITIAL_GRAVITY      (GADGET_ID_CHECKBUTTON_FIRST + 3)
+#define GADGET_ID_STICK_ELEMENT                (GADGET_ID_CHECKBUTTON_FIRST + 4)
+#define GADGET_ID_EM_SLIPPERY_GEMS     (GADGET_ID_CHECKBUTTON_FIRST + 5)
+#define GADGET_ID_USE_SPRING_BUG       (GADGET_ID_CHECKBUTTON_FIRST + 6)
+#define GADGET_ID_GROW_INTO_DIGGABLE   (GADGET_ID_CHECKBUTTON_FIRST + 7)
+#define GADGET_ID_DOUBLE_SPEED         (GADGET_ID_CHECKBUTTON_FIRST + 8)
 #define GADGET_ID_BLOCK_LAST_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 9)
 #define GADGET_ID_SP_BLOCK_LAST_FIELD  (GADGET_ID_CHECKBUTTON_FIRST + 10)
 #define GADGET_ID_INSTANT_RELOCATION   (GADGET_ID_CHECKBUTTON_FIRST + 11)
 #define ED_COUNTER_ID_LEVEL_TIMELIMIT  4
 #define ED_COUNTER_ID_LEVEL_TIMESCORE  5
 #define ED_COUNTER_ID_LEVEL_RANDOM     6
-#define ED_COUNTER_ID_ELEMENT_SCORE    7
-#define ED_COUNTER_ID_ELEMENT_CONTENT  8
-#define ED_COUNTER_ID_ENVELOPE_XSIZE   9
-#define ED_COUNTER_ID_ENVELOPE_YSIZE   10
-#define ED_COUNTER_ID_CUSTOM_SCORE     11
-#define ED_COUNTER_ID_CUSTOM_GEMCOUNT  12
-#define ED_COUNTER_ID_PUSH_DELAY_FIX   13
-#define ED_COUNTER_ID_PUSH_DELAY_RND   14
-#define ED_COUNTER_ID_DROP_DELAY_FIX   15
-#define ED_COUNTER_ID_DROP_DELAY_RND   16
-#define ED_COUNTER_ID_MOVE_DELAY_FIX   17
-#define ED_COUNTER_ID_MOVE_DELAY_RND   18
-#define ED_COUNTER_ID_EXPLOSION_DELAY  19
-#define ED_COUNTER_ID_IGNITION_DELAY   20
-#define ED_COUNTER_ID_GROUP_CONTENT    21
-#define ED_COUNTER_ID_CHANGE_DELAY_FIX 22
-#define ED_COUNTER_ID_CHANGE_DELAY_RND 23
-#define ED_COUNTER_ID_CHANGE_CONT_RND  24
-
-#define ED_NUM_COUNTERBUTTONS          25
+#define ED_COUNTER_ID_ELEMENT_VALUE1   7
+#define ED_COUNTER_ID_ELEMENT_VALUE2   8
+#define ED_COUNTER_ID_YAMYAM_CONTENT   9
+#define ED_COUNTER_ID_ENVELOPE_XSIZE   10
+#define ED_COUNTER_ID_ENVELOPE_YSIZE   11
+#define ED_COUNTER_ID_CUSTOM_SCORE     12
+#define ED_COUNTER_ID_CUSTOM_GEMCOUNT  13
+#define ED_COUNTER_ID_PUSH_DELAY_FIX   14
+#define ED_COUNTER_ID_PUSH_DELAY_RND   15
+#define ED_COUNTER_ID_DROP_DELAY_FIX   16
+#define ED_COUNTER_ID_DROP_DELAY_RND   17
+#define ED_COUNTER_ID_MOVE_DELAY_FIX   18
+#define ED_COUNTER_ID_MOVE_DELAY_RND   19
+#define ED_COUNTER_ID_EXPLOSION_DELAY  20
+#define ED_COUNTER_ID_IGNITION_DELAY   21
+#define ED_COUNTER_ID_GROUP_CONTENT    22
+#define ED_COUNTER_ID_CHANGE_DELAY_FIX 23
+#define ED_COUNTER_ID_CHANGE_DELAY_RND 24
+#define ED_COUNTER_ID_CHANGE_CONT_RND  25
+
+#define ED_NUM_COUNTERBUTTONS          26
 
 #define ED_COUNTER_ID_LEVEL_FIRST      ED_COUNTER_ID_LEVEL_XSIZE
 #define ED_COUNTER_ID_LEVEL_LAST       ED_COUNTER_ID_LEVEL_RANDOM
 
 /* values for selectbox gadgets */
 #define ED_SELECTBOX_ID_TIME_OR_STEPS          0
-#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE     1
-#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER    2
-#define ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED        3
-#define ED_SELECTBOX_ID_CUSTOM_ACCESS_DIRECTION        4
-#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION  5
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN    6
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION  7
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE   8
-#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 9
-#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS   10
-#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE   11
-#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS      12
-#define ED_SELECTBOX_ID_CUSTOM_EXPLOSION_TYPE  13
-#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS      14
-#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION   15
-#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION    16
-#define ED_SELECTBOX_ID_CHANGE_SIDE            17
-#define ED_SELECTBOX_ID_CHANGE_PLAYER          18
-#define ED_SELECTBOX_ID_CHANGE_PAGE            19
-#define ED_SELECTBOX_ID_CHANGE_REPLACE_WHEN    20
-#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE     21
-#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE      22
-
-#define ED_NUM_SELECTBOX                       23
+#define ED_SELECTBOX_ID_GAME_ENGINE_TYPE       1
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE     2
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER    3
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED        4
+#define ED_SELECTBOX_ID_CUSTOM_ACCESS_DIRECTION        5
+#define ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION  6
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_PATTERN    7
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_DIRECTION  8
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_STEPSIZE   9
+#define ED_SELECTBOX_ID_CUSTOM_MOVE_LEAVE_TYPE 10
+#define ED_SELECTBOX_ID_CUSTOM_SMASH_TARGETS   11
+#define ED_SELECTBOX_ID_CUSTOM_SLIPPERY_TYPE   12
+#define ED_SELECTBOX_ID_CUSTOM_DEADLINESS      13
+#define ED_SELECTBOX_ID_CUSTOM_EXPLOSION_TYPE  14
+#define ED_SELECTBOX_ID_CHANGE_TIME_UNITS      15
+#define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION   16
+#define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION    17
+#define ED_SELECTBOX_ID_CHANGE_SIDE            18
+#define ED_SELECTBOX_ID_CHANGE_PLAYER          19
+#define ED_SELECTBOX_ID_CHANGE_PAGE            20
+#define ED_SELECTBOX_ID_CHANGE_REPLACE_WHEN    21
+#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE     22
+#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE      23
+
+#define ED_NUM_SELECTBOX                       24
 
 #define ED_SELECTBOX_ID_LEVEL_FIRST    ED_SELECTBOX_ID_TIME_OR_STEPS
-#define ED_SELECTBOX_ID_LEVEL_LAST     ED_SELECTBOX_ID_TIME_OR_STEPS
+#define ED_SELECTBOX_ID_LEVEL_LAST     ED_SELECTBOX_ID_GAME_ENGINE_TYPE
 
 #define ED_SELECTBOX_ID_CUSTOM1_FIRST  ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
 #define ED_SELECTBOX_ID_CUSTOM1_LAST   ED_SELECTBOX_ID_CUSTOM_WALK_TO_ACTION
 #define ED_GRAPHICBUTTON_ID_CHANGE_LAST   ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE
 
 /* values for checkbutton gadgets */
-#define ED_CHECKBUTTON_ID_DOUBLE_SPEED         0
-#define ED_CHECKBUTTON_ID_GRAVITY              1
-#define ED_CHECKBUTTON_ID_RANDOM_RESTRICTED    2
-#define ED_CHECKBUTTON_ID_STICK_ELEMENT                3
-#define ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS     4
-#define ED_CHECKBUTTON_ID_USE_SPRING_BUG       5
-#define ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE   6
+#define ED_CHECKBUTTON_ID_INITIAL_GRAVITY      0
+#define ED_CHECKBUTTON_ID_RANDOM_RESTRICTED    1
+#define ED_CHECKBUTTON_ID_STICK_ELEMENT                2
+#define ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS     3
+#define ED_CHECKBUTTON_ID_USE_SPRING_BUG       4
+#define ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE   5
+#define ED_CHECKBUTTON_ID_DOUBLE_SPEED         6
 #define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD     7
 #define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD  8
 #define ED_CHECKBUTTON_ID_INSTANT_RELOCATION   9
 
 #define ED_NUM_CHECKBUTTONS                    37
 
-#define ED_CHECKBUTTON_ID_LEVEL_FIRST  ED_CHECKBUTTON_ID_DOUBLE_SPEED
+#define ED_CHECKBUTTON_ID_LEVEL_FIRST  ED_CHECKBUTTON_ID_INITIAL_GRAVITY
 #define ED_CHECKBUTTON_ID_LEVEL_LAST   ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
 
 #define ED_CHECKBUTTON_ID_CUSTOM1_FIRST        ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC
 
 /* values for drawing area gadgets */
 #define ED_DRAWING_ID_DRAWING_LEVEL            0
-#define ED_DRAWING_ID_ELEMENT_CONTENT_0                1
-#define ED_DRAWING_ID_ELEMENT_CONTENT_1                2
-#define ED_DRAWING_ID_ELEMENT_CONTENT_2                3
-#define ED_DRAWING_ID_ELEMENT_CONTENT_3                4
-#define ED_DRAWING_ID_ELEMENT_CONTENT_4                5
-#define ED_DRAWING_ID_ELEMENT_CONTENT_5                6
-#define ED_DRAWING_ID_ELEMENT_CONTENT_6                7
-#define ED_DRAWING_ID_ELEMENT_CONTENT_7                8
-#define ED_DRAWING_ID_AMOEBA_CONTENT           9
-#define ED_DRAWING_ID_CUSTOM_GRAPHIC           10
-#define ED_DRAWING_ID_CUSTOM_CONTENT           11
-#define ED_DRAWING_ID_CUSTOM_MOVE_ENTER                12
-#define ED_DRAWING_ID_CUSTOM_MOVE_LEAVE                13
-#define ED_DRAWING_ID_CUSTOM_CHANGE_TARGET     14
-#define ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT    15
-#define ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER    16
-#define ED_DRAWING_ID_GROUP_CONTENT            17
-#define ED_DRAWING_ID_RANDOM_BACKGROUND                18
-
-#define ED_NUM_DRAWING_AREAS                   19
+#define ED_DRAWING_ID_YAMYAM_CONTENT_0         1
+#define ED_DRAWING_ID_YAMYAM_CONTENT_1         2
+#define ED_DRAWING_ID_YAMYAM_CONTENT_2         3
+#define ED_DRAWING_ID_YAMYAM_CONTENT_3         4
+#define ED_DRAWING_ID_YAMYAM_CONTENT_4         5
+#define ED_DRAWING_ID_YAMYAM_CONTENT_5         6
+#define ED_DRAWING_ID_YAMYAM_CONTENT_6         7
+#define ED_DRAWING_ID_YAMYAM_CONTENT_7         8
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_0     9
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_1     10
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_2     11
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_3     12
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_4     13
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_5     14
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_6     15
+#define ED_DRAWING_ID_MAGIC_BALL_CONTENT_7     16
+#define ED_DRAWING_ID_AMOEBA_CONTENT           17
+#define ED_DRAWING_ID_CUSTOM_GRAPHIC           18
+#define ED_DRAWING_ID_CUSTOM_CONTENT           19
+#define ED_DRAWING_ID_CUSTOM_MOVE_ENTER                20
+#define ED_DRAWING_ID_CUSTOM_MOVE_LEAVE                21
+#define ED_DRAWING_ID_CUSTOM_CHANGE_TARGET     22
+#define ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT    23
+#define ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER    24
+#define ED_DRAWING_ID_GROUP_CONTENT            25
+#define ED_DRAWING_ID_RANDOM_BACKGROUND                26
+
+#define ED_NUM_DRAWING_AREAS                   27
 
 
 /*
@@ -843,6 +879,9 @@ static struct
   char *text;
 } control_info[ED_NUM_CTRL_BUTTONS] =
 {
+  /* note: some additional characters are already reserved for "cheat mode"
+     shortcuts (":XYZ" style) -- for details, see "events.c" */
+
   { 's',       "draw single items"                     },
   { 'd',       "draw connected items"                  },
   { 'l',       "draw lines"                            },
@@ -897,7 +936,7 @@ static struct
   char *text_above, *text_left, *text_right;
 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
 {
-  /* ---------- level and editor settings ---------------------------------- */
+  /* ---------- current level number --------------------------------------- */
 
   {
     DX + 5 - SX,                       DY + 3 - SY,
@@ -907,8 +946,11 @@ static struct
     &level_nr,
     NULL,                              NULL, NULL
   },
+
+  /* ---------- level and editor settings ---------------------------------- */
+
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(2),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(4),
     MIN_LEV_FIELDX,                    MAX_LEV_FIELDX,
     GADGET_ID_LEVEL_XSIZE_DOWN,                GADGET_ID_LEVEL_XSIZE_UP,
     GADGET_ID_LEVEL_XSIZE_TEXT,                GADGET_ID_NONE,
@@ -916,7 +958,7 @@ static struct
     "playfield size:",                 NULL, "width",
   },
   {
-    -1,                                        ED_COUNTER_YPOS(2),
+    -1,                                        ED_LEVEL_SETTINGS_YPOS(4),
     MIN_LEV_FIELDY,                    MAX_LEV_FIELDY,
     GADGET_ID_LEVEL_YSIZE_DOWN,                GADGET_ID_LEVEL_YSIZE_UP,
     GADGET_ID_LEVEL_YSIZE_TEXT,                GADGET_ID_LEVEL_XSIZE_UP,
@@ -924,15 +966,15 @@ static struct
     NULL,                              " ", "height",
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(3),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(6),
     0,                                 999,
     GADGET_ID_LEVEL_GEMSLIMIT_DOWN,    GADGET_ID_LEVEL_GEMSLIMIT_UP,
     GADGET_ID_LEVEL_GEMSLIMIT_TEXT,    GADGET_ID_NONE,
     &level.gems_needed,
-    "number of gems to collect:",      NULL, NULL
+    NULL, "number of gems to collect:",        NULL
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(4),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(8),
     0,                                 9999,
     GADGET_ID_LEVEL_TIMELIMIT_DOWN,    GADGET_ID_LEVEL_TIMELIMIT_UP,
     GADGET_ID_LEVEL_TIMELIMIT_TEXT,    GADGET_ID_NONE,
@@ -940,7 +982,7 @@ static struct
     "time or step limit to solve level:", NULL, NULL
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(5),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(10),
     0,                                 255,
     GADGET_ID_LEVEL_TIMESCORE_DOWN,    GADGET_ID_LEVEL_TIMESCORE_UP,
     GADGET_ID_LEVEL_TIMESCORE_TEXT,    GADGET_ID_NONE,
@@ -948,7 +990,7 @@ static struct
     "score for each 10 sec/steps left:", NULL, NULL
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER2_YPOS(8),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_COUNTER2_YPOS(8),
     1,                                 100,
     GADGET_ID_LEVEL_RANDOM_DOWN,       GADGET_ID_LEVEL_RANDOM_UP,
     GADGET_ID_LEVEL_RANDOM_TEXT,       GADGET_ID_NONE,
@@ -959,23 +1001,31 @@ static struct
   /* ---------- element settings: configure (various elements) ------------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
+    MIN_SCORE,                         MAX_SCORE,
+    GADGET_ID_ELEMENT_VALUE1_DOWN,     GADGET_ID_ELEMENT_VALUE1_UP,
+    GADGET_ID_ELEMENT_VALUE1_TEXT,     GADGET_ID_NONE,
+    NULL,                              /* will be set when used */
+    NULL,                              NULL, NULL
+  },
+  {
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     MIN_SCORE,                         MAX_SCORE,
-    GADGET_ID_ELEMENT_SCORE_DOWN,      GADGET_ID_ELEMENT_SCORE_UP,
-    GADGET_ID_ELEMENT_SCORE_TEXT,      GADGET_ID_NONE,
+    GADGET_ID_ELEMENT_VALUE2_DOWN,     GADGET_ID_ELEMENT_VALUE2_UP,
+    GADGET_ID_ELEMENT_VALUE2_TEXT,     GADGET_ID_NONE,
     NULL,                              /* will be set when used */
     NULL,                              NULL, NULL
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(3),
     MIN_ELEMENT_CONTENTS,              MAX_ELEMENT_CONTENTS,
-    GADGET_ID_ELEMENT_CONTENT_DOWN,    GADGET_ID_ELEMENT_CONTENT_UP,
-    GADGET_ID_ELEMENT_CONTENT_TEXT,    GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_DOWN,     GADGET_ID_YAMYAM_CONTENT_UP,
+    GADGET_ID_YAMYAM_CONTENT_TEXT,     GADGET_ID_NONE,
     &level.num_yamyam_contents,
     NULL,                              NULL, "number of content areas"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
     MIN_ENVELOPE_XSIZE,                        MAX_ENVELOPE_XSIZE,
     GADGET_ID_ENVELOPE_XSIZE_DOWN,     GADGET_ID_ENVELOPE_XSIZE_UP,
     GADGET_ID_ENVELOPE_XSIZE_TEXT,     GADGET_ID_NONE,
@@ -983,7 +1033,7 @@ static struct
     NULL,                              NULL, "width",
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(0),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(0),
     MIN_ENVELOPE_YSIZE,                        MAX_ENVELOPE_YSIZE,
     GADGET_ID_ENVELOPE_YSIZE_DOWN,     GADGET_ID_ENVELOPE_YSIZE_UP,
     GADGET_ID_ENVELOPE_YSIZE_TEXT,     GADGET_ID_ENVELOPE_XSIZE_UP,
@@ -994,7 +1044,7 @@ static struct
   /* ---------- element settings: configure 1 (custom elements) ------------ */
 
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(6),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(6),
     MIN_SCORE,                         MAX_SCORE,
     GADGET_ID_CUSTOM_SCORE_DOWN,       GADGET_ID_CUSTOM_SCORE_UP,
     GADGET_ID_CUSTOM_SCORE_TEXT,       GADGET_ID_NONE,
@@ -1002,7 +1052,7 @@ static struct
     NULL,                              "score", " "
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(6),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(6),
     MIN_COLLECT_COUNT,                 MAX_COLLECT_COUNT,
     GADGET_ID_CUSTOM_GEMCOUNT_DOWN,    GADGET_ID_CUSTOM_GEMCOUNT_UP,
     GADGET_ID_CUSTOM_GEMCOUNT_TEXT,    GADGET_ID_CUSTOM_SCORE_UP,
@@ -1010,7 +1060,7 @@ static struct
     NULL,                              "count", NULL
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(7),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(7),
     0,                                 255,
     GADGET_ID_PUSH_DELAY_FIX_DOWN,     GADGET_ID_PUSH_DELAY_FIX_UP,
     GADGET_ID_PUSH_DELAY_FIX_TEXT,     GADGET_ID_NONE,
@@ -1018,7 +1068,7 @@ static struct
     NULL,                              "push delay", NULL
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(7),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(7),
     0,                                 255,
     GADGET_ID_PUSH_DELAY_RND_DOWN,     GADGET_ID_PUSH_DELAY_RND_UP,
     GADGET_ID_PUSH_DELAY_RND_TEXT,     GADGET_ID_PUSH_DELAY_FIX_UP,
@@ -1026,7 +1076,7 @@ static struct
     NULL,                              "+random", NULL
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(8),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(8),
     0,                                 255,
     GADGET_ID_DROP_DELAY_FIX_DOWN,     GADGET_ID_DROP_DELAY_FIX_UP,
     GADGET_ID_DROP_DELAY_FIX_TEXT,     GADGET_ID_NONE,
@@ -1034,7 +1084,7 @@ static struct
     NULL,                              "drop delay", NULL
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(8),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(8),
     0,                                 255,
     GADGET_ID_DROP_DELAY_RND_DOWN,     GADGET_ID_DROP_DELAY_RND_UP,
     GADGET_ID_DROP_DELAY_RND_TEXT,     GADGET_ID_DROP_DELAY_FIX_UP,
@@ -1045,7 +1095,7 @@ static struct
   /* ---------- element settings: configure 2 (custom elements) ------------ */
 
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(5),
     0,                                 999,
     GADGET_ID_MOVE_DELAY_FIX_DOWN,     GADGET_ID_MOVE_DELAY_FIX_UP,
     GADGET_ID_MOVE_DELAY_FIX_TEXT,     GADGET_ID_NONE,
@@ -1053,7 +1103,7 @@ static struct
     NULL,                              "move delay", NULL
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(5),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(5),
     0,                                 999,
     GADGET_ID_MOVE_DELAY_RND_DOWN,     GADGET_ID_MOVE_DELAY_RND_UP,
     GADGET_ID_MOVE_DELAY_RND_TEXT,     GADGET_ID_MOVE_DELAY_FIX_UP,
@@ -1061,7 +1111,7 @@ static struct
     NULL,                              "+random", NULL
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(12),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(12),
     0,                                 255,
     GADGET_ID_EXPLOSION_DELAY_DOWN,    GADGET_ID_EXPLOSION_DELAY_UP,
     GADGET_ID_EXPLOSION_DELAY_TEXT,    GADGET_ID_NONE,
@@ -1069,7 +1119,7 @@ static struct
     NULL,                              "explosion delay", NULL
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(13),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(13),
     0,                                 255,
     GADGET_ID_IGNITION_DELAY_DOWN,     GADGET_ID_IGNITION_DELAY_UP,
     GADGET_ID_IGNITION_DELAY_TEXT,     GADGET_ID_NONE,
@@ -1080,7 +1130,7 @@ static struct
   /* ---------- element settings: configure (group elements) --------------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(5),
     MIN_ELEMENTS_IN_GROUP,             MAX_ELEMENTS_IN_GROUP,
     GADGET_ID_GROUP_CONTENT_DOWN,      GADGET_ID_GROUP_CONTENT_UP,
     GADGET_ID_GROUP_CONTENT_TEXT,      GADGET_ID_NONE,
@@ -1091,7 +1141,7 @@ static struct
   /* ---------- element settings: advanced (custom elements) --------------- */
 
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(2),
     0,                                 999,
     GADGET_ID_CHANGE_DELAY_FIX_DOWN,   GADGET_ID_CHANGE_DELAY_FIX_UP,
     GADGET_ID_CHANGE_DELAY_FIX_TEXT,   GADGET_ID_NONE,
@@ -1099,7 +1149,7 @@ static struct
     NULL,                              "delay", NULL,
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(2),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(2),
     0,                                 999,
     GADGET_ID_CHANGE_DELAY_RND_DOWN,   GADGET_ID_CHANGE_DELAY_RND_UP,
     GADGET_ID_CHANGE_DELAY_RND_TEXT,   GADGET_ID_CHANGE_DELAY_FIX_UP,
@@ -1107,7 +1157,7 @@ static struct
     NULL,                              "+random", NULL
   },
   {
-    ED_SETTINGS_XPOS(3),               ED_SETTINGS_YPOS(12),
+    ED_ELEMENT_SETTINGS_XPOS(3),       ED_ELEMENT_SETTINGS_YPOS(12),
     0,                                 100,
     GADGET_ID_CHANGE_CONT_RND_DOWN,    GADGET_ID_CHANGE_CONT_RND_UP,
     GADGET_ID_CHANGE_CONT_RND_TEXT,    GADGET_ID_NONE,
@@ -1126,14 +1176,14 @@ static struct
 } textinput_info[ED_NUM_TEXTINPUT] =
 {
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(0),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(0),
     GADGET_ID_LEVEL_NAME,
     MAX_LEVEL_NAME_LEN,
     level.name,
     "Title:", "Title"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(1),
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(2),
     GADGET_ID_LEVEL_AUTHOR,
     MAX_LEVEL_AUTHOR_LEN,
     level.author,
@@ -1158,7 +1208,7 @@ static struct
 } textarea_info[ED_NUM_TEXTAREAS] =
 {
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_ENVELOPE_INFO,
     MAX_ENVELOPE_XSIZE, MAX_ENVELOPE_YSIZE,
     NULL,
@@ -1174,6 +1224,14 @@ static struct ValueTextInfo options_time_or_steps[] =
   { -1,                                NULL                            }
 };
 
+static struct ValueTextInfo options_game_engine_type[] =
+{
+  { GAME_ENGINE_TYPE_RND,      "Rocks'n'Diamonds"              },
+  { GAME_ENGINE_TYPE_EM,       "Emerald Mine"                  },
+
+  { -1,                                NULL                            }
+};
+
 static struct ValueTextInfo options_access_type[] =
 {
   { EP_WALKABLE,               "walkable"                      },
@@ -1201,6 +1259,7 @@ static struct ValueTextInfo options_access_protected[] =
 
 static struct ValueTextInfo options_access_direction[] =
 {
+  { MV_NO_DIRECTIONS,          "no direction"                  },
   { MV_LEFT,                   "left"                          },
   { MV_RIGHT,                  "right"                         },
   { MV_UP,                     "up"                            },
@@ -1272,6 +1331,7 @@ static struct ValueTextInfo options_move_direction[] =
 
 static struct ValueTextInfo options_move_stepsize[] =
 {
+  { 0,                         "not moving"                    },
   { 1,                         "very slow"                     },
   { 2,                         "slow"                          },
   { 4,                         "normal"                        },
@@ -1358,9 +1418,11 @@ static struct ValueTextInfo options_change_direct_action[] =
 #else
   { CE_HITTING_SOMETHING,      "collision"                     },
 #endif
-#if 1
+
+#if 0
   { CE_BLOCKED,                        "blocked"                       },
 #endif
+
   { CE_IMPACT,                 "impact (on something)"         },
   { CE_SMASHED,                        "smashed (from above)"          },
 
@@ -1369,22 +1431,22 @@ static struct ValueTextInfo options_change_direct_action[] =
 
 static struct ValueTextInfo options_change_other_action[] =
 {
-  { CE_OTHER_GETS_TOUCHED,     "player touches"                },
-  { CE_OTHER_GETS_PRESSED,     "player presses"                },
-  { CE_OTHER_GETS_PUSHED,      "player pushes"                 },
-  { CE_OTHER_GETS_ENTERED,     "player enters"                 },
-  { CE_OTHER_GETS_LEFT,                "player leaves"                 },
-  { CE_OTHER_GETS_DIGGED,      "player digs"                   },
-  { CE_OTHER_GETS_COLLECTED,   "player collects"               },
-  { CE_OTHER_GETS_DROPPED,     "player drops/throws"           },
-  { CE_OTHER_IS_TOUCHING,      "touching"                      },
+  { CE_PLAYER_TOUCHES_X,       "player touches"                },
+  { CE_PLAYER_PRESSES_X,       "player presses"                },
+  { CE_PLAYER_PUSHES_X,                "player pushes"                 },
+  { CE_PLAYER_ENTERS_X,                "player enters"                 },
+  { CE_PLAYER_LEAVES_X,                "player leaves"                 },
+  { CE_PLAYER_DIGS_X,          "player digs"                   },
+  { CE_PLAYER_COLLECTS_X,      "player collects"               },
+  { CE_PLAYER_DROPS_X,         "player drops/throws"           },
+  { CE_TOUCHING_X,             "touching"                      },
 #if 1
-  { CE_OTHER_IS_HITTING,       "hitting"                       },
-  { CE_OTHER_GETS_HIT,         "hit by"                        },
+  { CE_HITTING_X,              "hitting"                       },
+  { CE_HIT_BY_X,               "hit by"                        },
 #endif
-  { CE_OTHER_IS_SWITCHING,     "switch of"                     },
-  { CE_OTHER_IS_CHANGING,      "change by page of"             },
-  { CE_OTHER_IS_EXPLODING,     "explosion of"                  },
+  { CE_SWITCH_OF_X,            "switch of"                     },
+  { CE_CHANGE_OF_X,            "change by page of"             },
+  { CE_EXPLOSION_OF_X,         "explosion of"                  },
 
   { -1,                                NULL                            }
 };
@@ -1495,18 +1557,26 @@ static struct
   /* ---------- level and editor settings ---------------------------------- */
 
   {
-    -1,                                        ED_COUNTER_YPOS(4),
+    -1,                                        ED_LEVEL_SETTINGS_YPOS(8),
     GADGET_ID_TIME_OR_STEPS,           GADGET_ID_LEVEL_TIMELIMIT_UP,
     -1,
     options_time_or_steps,
     &level.use_step_counter,
     NULL, "(0 => no limit)",           "time or step limit"
   },
+  {
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(5),
+    GADGET_ID_GAME_ENGINE_TYPE,                GADGET_ID_NONE,
+    -1,
+    options_game_engine_type,
+    &level.game_engine_type,
+    "game engine:", NULL,              "game engine"
+  },
 
   /* ---------- element settings: configure 1 (custom elements) ----------- */
 
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CUSTOM_ACCESS_TYPE,      GADGET_ID_NONE,
     -1,
     options_access_type,
@@ -1514,7 +1584,7 @@ static struct
     NULL, NULL,                                "type of access to this field"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(3),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CUSTOM_ACCESS_LAYER,     GADGET_ID_CUSTOM_ACCESS_TYPE,
     -1,
     options_access_layer,
@@ -1522,7 +1592,7 @@ static struct
     NULL, NULL,                                "layer of access for this field"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(3),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CUSTOM_ACCESS_PROTECTED, GADGET_ID_CUSTOM_ACCESS_LAYER,
     -1,
     options_access_protected,
@@ -1530,7 +1600,7 @@ static struct
     NULL, NULL,                                "protected access for this field"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(4),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_CUSTOM_ACCESS_DIRECTION, GADGET_ID_NONE,
     -1,
     options_access_direction,
@@ -1538,7 +1608,7 @@ static struct
     "from", NULL,                      "access direction for this field"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(5),
     GADGET_ID_CUSTOM_WALK_TO_ACTION,   GADGET_ID_NONE,
     -1,
     options_walk_to_action,
@@ -1549,7 +1619,7 @@ static struct
   /* ---------- element settings: configure 2 (custom elements) ----------- */
 
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_CUSTOM_MOVE_PATTERN,     GADGET_ID_NONE,
     -1,
     options_move_pattern,
@@ -1557,7 +1627,7 @@ static struct
     "can move", NULL,                  "element move pattern"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_MOVE_DIRECTION,   GADGET_ID_NONE,
     -1,
     options_move_direction,
@@ -1565,7 +1635,7 @@ static struct
     "starts moving", NULL,             "initial element move direction"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(4),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_CUSTOM_MOVE_STEPSIZE,    GADGET_ID_NONE,
     -1,
     options_move_stepsize,
@@ -1573,7 +1643,7 @@ static struct
     "move/fall speed", NULL,           "speed of element movement"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE,  GADGET_ID_NONE,
     -1,
     options_move_leave_type,
@@ -1581,7 +1651,7 @@ static struct
     "can dig:    can", ":",            "leave behind or change element"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(7),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(7),
     GADGET_ID_CUSTOM_SMASH_TARGETS,    GADGET_ID_CUSTOM_CAN_SMASH,
     -1,
     options_smash_targets,
@@ -1589,7 +1659,7 @@ static struct
     "can smash", NULL,                 "elements that can be smashed"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(8),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(8),
     GADGET_ID_CUSTOM_SLIPPERY_TYPE,    GADGET_ID_NONE,
     -1,
     options_slippery_type,
@@ -1597,7 +1667,7 @@ static struct
     "slippery", NULL,                  "where other elements fall down"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(9),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(9),
     GADGET_ID_CUSTOM_DEADLINESS,       GADGET_ID_NONE,
     -1,
     options_deadliness,
@@ -1605,7 +1675,7 @@ static struct
     "deadly when", NULL,               "deadliness of element"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(10),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(10),
     GADGET_ID_CUSTOM_EXPLOSION_TYPE,   GADGET_ID_NONE,
     -1,
     options_explosion_type,
@@ -1616,7 +1686,7 @@ static struct
   /* ---------- element settings: advanced (custom elements) --------------- */
 
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CHANGE_TIME_UNITS,       GADGET_ID_NONE,
     -1,
     options_time_units,
@@ -1624,7 +1694,7 @@ static struct
     "delay time given in", NULL,       "delay time units for change"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(4),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_CHANGE_DIRECT_ACTION,    GADGET_ID_NONE,
     -1,
     options_change_direct_action,
@@ -1632,7 +1702,7 @@ static struct
     NULL, NULL,                                "type of direct action"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(5),
     GADGET_ID_CHANGE_OTHER_ACTION,     GADGET_ID_NONE,
     -1,
     options_change_other_action,
@@ -1640,7 +1710,7 @@ static struct
     NULL, "element:",                  "type of other element action"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(6),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(6),
     GADGET_ID_CHANGE_SIDE,             GADGET_ID_NONE,
     -1,
     options_change_trigger_side,
@@ -1648,7 +1718,7 @@ static struct
     "at", "side",                      "element side that causes change"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(7),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(7),
     GADGET_ID_CHANGE_PLAYER,           GADGET_ID_NONE,
     -1,
     options_change_trigger_player,
@@ -1656,7 +1726,7 @@ static struct
     "player:", " ",                    "player that causes change"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(7),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(7),
     GADGET_ID_CHANGE_PAGE,             GADGET_ID_CHANGE_PLAYER,
     -1,
     options_change_trigger_page,
@@ -1664,7 +1734,7 @@ static struct
     "page:", NULL,                     "change page that causes change"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(10),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(10),
     GADGET_ID_CHANGE_REPLACE_WHEN,     GADGET_ID_NONE,
     -1,
     options_change_replace_when,
@@ -1672,7 +1742,7 @@ static struct
     "replace when", NULL,              "which elements can be replaced"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(14),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(14),
     GADGET_ID_SELECT_CHANGE_PAGE,      GADGET_ID_NONE,
     3,
     options_change_page,
@@ -1683,7 +1753,7 @@ static struct
   /* ---------- element settings: configure (group elements) --------------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(6),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(6),
     GADGET_ID_GROUP_CHOICE_MODE,       GADGET_ID_NONE,
     -1,
     options_group_choice_mode,
@@ -1704,69 +1774,69 @@ static struct
 {
 #if 1
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_INFO,         GADGET_ID_NONE,
     8,                                 "Info",                 
     NULL, NULL,                                "Show information about element"
   },
   {
-    ED_SETTINGS_XPOS(0) + 124,         ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0) + 124, ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CONFIG,       GADGET_ID_NONE,
     8,                                 "Config",
     NULL, NULL,                                "Configure element properties"
   },
   {
-    ED_SETTINGS_XPOS(0) + 124,         ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0) + 124, ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CONFIG_1,     GADGET_ID_NONE,
     8,                                 "Config 1",
     NULL, NULL,                                "Configure custom element properties"
   },
   {
-    ED_SETTINGS_XPOS(0) + 248,         ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0) + 248, ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CONFIG_2,     GADGET_ID_NONE,
     8,                                 "Config 2",
     NULL, NULL,                                "Configure custom element properties"
   },
   {
-    ED_SETTINGS_XPOS(0) + 372,         ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0) + 372, ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CHANGE,       GADGET_ID_NONE,
     8,                                 "Change",
     NULL, NULL,                                "Custom element change configuration"
   },
 #else
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_INFO,         GADGET_ID_NONE,
     11,                                        "Information",                  
     NULL, NULL,                                "Show information about element"
   },
   {
-    ED_SETTINGS_XPOS(0) + 166,         ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0) + 166, ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CONFIG,       GADGET_ID_NONE,
     11,                                        "Configure",
     NULL, NULL,                                "Configure element properties"
   },
   {
-    ED_SETTINGS_XPOS(0) + 332,         ED_COUNTER_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0) + 332, ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CHANGE,       GADGET_ID_NONE,
     11,                                        "Advanced",
     NULL, NULL,                                "Advanced element configuration"
   },
 #endif
   {
-    -1,                                        ED_SETTINGS_YPOS(2),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_SAVE_AS_TEMPLATE,                GADGET_ID_CUSTOM_USE_TEMPLATE,
     -1,                                        "Save",
     " ", "As Template",                        "Save current settings as new template"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(14),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(14),
     GADGET_ID_ADD_CHANGE_PAGE,         GADGET_ID_PASTE_CHANGE_PAGE,
     -1,                                        "New",
     NULL, NULL,                                "Add new change page"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(14),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(14),
     GADGET_ID_DEL_CHANGE_PAGE,         GADGET_ID_ADD_CHANGE_PAGE,
     -1,                                        "Delete",
     NULL, NULL,                                "Delete current change page"
@@ -1785,28 +1855,28 @@ static struct
 {
   {
     ED_BUTTON_MINUS_XPOS,              ED_BUTTON_COUNT_YPOS,
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(14),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(14),
     ED_BUTTON_COUNT_XSIZE,             ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_PREV_CHANGE_PAGE,                GADGET_ID_NONE,
     NULL, NULL,                                "select previous change page"
   },
   {
     ED_BUTTON_PLUS_XPOS,               ED_BUTTON_COUNT_YPOS,
-    -1,                                        ED_SETTINGS_YPOS(14),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(14),
     ED_BUTTON_COUNT_XSIZE,             ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_NEXT_CHANGE_PAGE,                GADGET_ID_SELECT_CHANGE_PAGE,
     NULL, "change page",               "select next change page"
   },
   {
     ED_COPY_CHANGE_PAGE_XPOS,          ED_COPY_CHANGE_PAGE_YPOS,
-    -1,                                        ED_SETTINGS_YPOS(14),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(14),
     ED_BUTTON_COUNT_XSIZE,             ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_COPY_CHANGE_PAGE,                GADGET_ID_NEXT_CHANGE_PAGE,
     " ", NULL,                         "copy settings from this change page"
   },
   {
     ED_PASTE_CHANGE_PAGE_XPOS,         ED_PASTE_CHANGE_PAGE_YPOS,
-    -1,                                        ED_SETTINGS_YPOS(14),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(14),
     ED_BUTTON_COUNT_XSIZE,             ED_BUTTON_COUNT_YSIZE,
     GADGET_ID_PASTE_CHANGE_PAGE,       GADGET_ID_COPY_CHANGE_PAGE,
     NULL, NULL,                                "paste settings to this change page"
@@ -1934,19 +2004,14 @@ static struct
   /* ---------- level and editor settings ---------------------------------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(6) - MINI_TILEY,
-    GADGET_ID_DOUBLE_SPEED,            GADGET_ID_NONE,
-    &level.double_speed,
-    NULL, "double speed movement",     "set movement speed of player"
-  },
-  {
-    -1,                                        ED_COUNTER_YPOS(6) - MINI_TILEY,
-    GADGET_ID_GRAVITY,                 GADGET_ID_DOUBLE_SPEED,
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_LEVEL_SETTINGS_YPOS(11),
+    GADGET_ID_INITIAL_GRAVITY,         GADGET_ID_NONE,
     &level.initial_gravity,
-    " ", "gravity",                    "set level gravity"
+    NULL,
+    "initial gravity",                 "set initial level gravity"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_COUNTER2_YPOS(9) - MINI_TILEY,
+    ED_LEVEL_SETTINGS_XPOS(0),         ED_COUNTER2_YPOS(9) - MINI_TILEY,
     GADGET_ID_RANDOM_RESTRICTED,       GADGET_ID_NONE,
     &random_placement_background_restricted,
     NULL,
@@ -1956,77 +2021,84 @@ static struct
   /* ---------- element settings: configure (various elements) ------------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
     GADGET_ID_STICK_ELEMENT,           GADGET_ID_NONE,
     &stick_element_properties_window,
     NULL,
     "stick this screen to edit content","stick this screen to edit content"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_EM_SLIPPERY_GEMS,                GADGET_ID_NONE,
     &level.em_slippery_gems,
     NULL,
     "slip down from certain flat walls","use EM style slipping behaviour"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_USE_SPRING_BUG,          GADGET_ID_NONE,
     &level.use_spring_bug,
     NULL,
     "use spring pushing bug",          "use odd spring pushing behaviour"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
     GADGET_ID_GROW_INTO_DIGGABLE,      GADGET_ID_NONE,
     &level.grow_into_diggable,
     NULL,
     "can grow into anything diggable", "grow into more than just sand"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(4),
+    GADGET_ID_DOUBLE_SPEED,            GADGET_ID_NONE,
+    &level.double_speed,
+    NULL,
+    "double speed movement",           "set initial movement speed of player"
+  },
+  {
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_BLOCK_LAST_FIELD,                GADGET_ID_NONE,
     &level.block_last_field,
     NULL,
     "block last field when moving",    "player blocks last field when moving"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_SP_BLOCK_LAST_FIELD,     GADGET_ID_NONE,
     &level.sp_block_last_field,
     NULL,
     "block last field when moving",    "player blocks last field when moving"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_INSTANT_RELOCATION,      GADGET_ID_NONE,
     &level.instant_relocation,
     NULL,
     "no scrolling when relocating",    "player gets relocated without delay"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CAN_PASS_TO_WALKABLE,    GADGET_ID_NONE,
     &level.can_pass_to_walkable,
     NULL,
     "can pass to walkable element",    "player can pass to empty or walkable"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
     GADGET_ID_CAN_FALL_INTO_ACID,      GADGET_ID_NONE,
     &custom_element_properties[EP_CAN_MOVE_INTO_ACID],
     NULL,
     "can fall into acid (with gravity)","player can fall into acid pool"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(0),
     GADGET_ID_CAN_MOVE_INTO_ACID,      GADGET_ID_NONE,
     &custom_element_properties[EP_CAN_MOVE_INTO_ACID],
     NULL,
     "can move into acid",              "element can move into acid pool"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_DONT_COLLIDE_WITH,       GADGET_ID_NONE,
     &custom_element_properties[EP_DONT_COLLIDE_WITH],
     NULL,
@@ -2036,9 +2108,11 @@ static struct
   /* ---------- element settings: configure 1 (custom elements) ----------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_CUSTOM_USE_GRAPHIC,      GADGET_ID_NONE,
     &custom_element.use_gfx_element,
+
+    /* !!! add separate "use existing element sound" !!! */
 #if 0
     NULL, "use graphic/sound of element:", "use existing graphic and sound"
 #else
@@ -2046,31 +2120,31 @@ static struct
 #endif
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_USE_TEMPLATE,     GADGET_ID_NONE,
     &level.use_custom_template,
     NULL, "use template",              "use template for custom properties"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(3),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(3),
     GADGET_ID_CUSTOM_ACCESSIBLE,       GADGET_ID_NONE,
     &custom_element_properties[EP_ACCESSIBLE],
     NULL, NULL,                                "player can walk to or pass this field"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(10),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(10),
     GADGET_ID_CUSTOM_GRAV_REACHABLE,   GADGET_ID_NONE,
     &custom_element_properties[EP_GRAVITY_REACHABLE],
     NULL, "reachable despite gravity", "player can walk/dig despite gravity"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(5),
     GADGET_ID_CUSTOM_WALK_TO_OBJECT,   GADGET_ID_NONE,
     &custom_element_properties[EP_WALK_TO_OBJECT],
     NULL, NULL,                                "player can dig/collect/push element"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(9),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(9),
     GADGET_ID_CUSTOM_INDESTRUCTIBLE,   GADGET_ID_NONE,
     &custom_element_properties[EP_INDESTRUCTIBLE],
     NULL, "indestructible",            "element is indestructible"
@@ -2079,55 +2153,55 @@ static struct
   /* ---------- element settings: configure 2 (custom elements) ----------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_CUSTOM_CAN_MOVE,         GADGET_ID_NONE,
     &custom_element_properties[EP_CAN_MOVE],
     NULL, NULL,                                "element can move with some pattern"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(7),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(7),
     GADGET_ID_CUSTOM_CAN_FALL,         GADGET_ID_NONE,
     &custom_element_properties[EP_CAN_FALL],
     NULL, "can fall",                  "element can fall down"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(7),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(7),
     GADGET_ID_CUSTOM_CAN_SMASH,                GADGET_ID_CUSTOM_CAN_FALL,
     &custom_element_properties[EP_CAN_SMASH],
     " ", NULL,                         "element can smash other elements"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(8),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(8),
     GADGET_ID_CUSTOM_SLIPPERY,         GADGET_ID_NONE,
     &custom_element_properties[EP_SLIPPERY],
     NULL, NULL,                                "other elements can fall down from it"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(9),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(9),
     GADGET_ID_CUSTOM_DEADLY,           GADGET_ID_NONE,
     &custom_element_properties[EP_DEADLY],
     NULL, NULL,                                "element can kill the player"
   },
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(10),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(10),
     GADGET_ID_CUSTOM_CAN_EXPLODE,      GADGET_ID_NONE,
     &custom_element_properties[EP_CAN_EXPLODE],
     NULL, NULL,                                "element can explode"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(11),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(11),
     GADGET_ID_CUSTOM_EXPLODE_FIRE,     GADGET_ID_NONE,
     &custom_element_properties[EP_EXPLODES_BY_FIRE],
     NULL, "by fire",                   "element can explode by fire/explosion"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(11),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(11),
     GADGET_ID_CUSTOM_EXPLODE_SMASH,    GADGET_ID_CUSTOM_EXPLODE_FIRE,
     &custom_element_properties[EP_EXPLODES_SMASHED],
     " ", "smashed",                    "element can explode when smashed"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(11),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(11),
     GADGET_ID_CUSTOM_EXPLODE_IMPACT,   GADGET_ID_CUSTOM_EXPLODE_SMASH,
     &custom_element_properties[EP_EXPLODES_IMPACT],
     " ", "impact",                     "element can explode on impact"
@@ -2136,49 +2210,49 @@ static struct
   /* ---------- element settings: advanced (custom elements) --------------- */
 
   {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(1),
     GADGET_ID_CUSTOM_CAN_CHANGE,       GADGET_ID_NONE,
     &custom_element_change.can_change,
     NULL, "element changes to:",       "element can change to other element"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(2),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(2),
     GADGET_ID_CHANGE_DELAY,            GADGET_ID_NONE,
     &custom_element_change_events[CE_DELAY],
     NULL, NULL,                                "element changes after delay"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(4),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(4),
     GADGET_ID_CHANGE_BY_DIRECT_ACT,    GADGET_ID_NONE,
     &custom_element_change_events[CE_BY_DIRECT_ACTION],
     NULL, NULL,                                "element changes by direct action"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(5),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(5),
     GADGET_ID_CHANGE_BY_OTHER_ACT,     GADGET_ID_NONE,
     &custom_element_change_events[CE_BY_OTHER_ACTION],
     NULL, NULL,                                "element changes by other element"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(8),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(8),
     GADGET_ID_CHANGE_USE_EXPLOSION,    GADGET_ID_NONE,
     &custom_element_change.explode,
     NULL, "explode instead of change", "element explodes instead of change"
   },
   {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(9),
+    ED_ELEMENT_SETTINGS_XPOS(1),       ED_ELEMENT_SETTINGS_YPOS(9),
     GADGET_ID_CHANGE_USE_CONTENT,      GADGET_ID_NONE,
     &custom_element_change.use_target_content,
     NULL, "use extended change target:","element changes to more elements"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(11),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(11),
     GADGET_ID_CHANGE_ONLY_COMPLETE,    GADGET_ID_NONE,
     &custom_element_change.only_if_complete,
     NULL, "replace all or nothing",    "only replace when all can be changed"
   },
   {
-    ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(12),
+    ED_ELEMENT_SETTINGS_XPOS(2),       ED_ELEMENT_SETTINGS_YPOS(12),
     GADGET_ID_CHANGE_USE_RANDOM,       GADGET_ID_NONE,
     &custom_element_change.use_random_replace,
     NULL, NULL,                                "use percentage for random replace"
@@ -2208,49 +2282,100 @@ static struct
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(0),    ED_AREA_YAMYAM_CONTENT_YPOS(0),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_0,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_0,                GADGET_ID_NONE,
     NULL, NULL,                                "1"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(1),    ED_AREA_YAMYAM_CONTENT_YPOS(1),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_1,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_1,                GADGET_ID_NONE,
     NULL, NULL,                                "2"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(2),    ED_AREA_YAMYAM_CONTENT_YPOS(2),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_2,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_2,                GADGET_ID_NONE,
     NULL, NULL,                                "3"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(3),    ED_AREA_YAMYAM_CONTENT_YPOS(3),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_3,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_3,                GADGET_ID_NONE,
     NULL, NULL,                                "4"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(4),    ED_AREA_YAMYAM_CONTENT_YPOS(4),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_4,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_4,                GADGET_ID_NONE,
     NULL, NULL,                                "5"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(5),    ED_AREA_YAMYAM_CONTENT_YPOS(5),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_5,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_5,                GADGET_ID_NONE,
     NULL, NULL,                                "6"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(6),    ED_AREA_YAMYAM_CONTENT_YPOS(6),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_6,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_6,                GADGET_ID_NONE,
     NULL, NULL,                                "7"
   },
   {
     ED_AREA_YAMYAM_CONTENT_XPOS(7),    ED_AREA_YAMYAM_CONTENT_YPOS(7),
     3, 3,
-    GADGET_ID_ELEMENT_CONTENT_7,       GADGET_ID_NONE,
+    GADGET_ID_YAMYAM_CONTENT_7,                GADGET_ID_NONE,
+    NULL, NULL,                                "8"
+  },
+
+  /* ---------- magic ball content ----------------------------------------- */
+
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(0),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(0),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_0,    GADGET_ID_NONE,
+    NULL, NULL,                                "1"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(1),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(1),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_1,    GADGET_ID_NONE,
+    NULL, NULL,                                "2"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(2),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(2),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_2,    GADGET_ID_NONE,
+    NULL, NULL,                                "3"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(3),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(3),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_3,    GADGET_ID_NONE,
+    NULL, NULL,                                "4"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(4),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(4),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_4,    GADGET_ID_NONE,
+    NULL, NULL,                                "5"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(5),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(5),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_5,    GADGET_ID_NONE,
+    NULL, NULL,                                "6"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(6),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(6),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_6,    GADGET_ID_NONE,
+    NULL, NULL,                                "7"
+  },
+  {
+    ED_AREA_MAGIC_BALL_CONTENT_XPOS(7),        ED_AREA_MAGIC_BALL_CONTENT_YPOS(7),
+    3, 3,
+    GADGET_ID_MAGIC_BALL_CONTENT_7,    GADGET_ID_NONE,
     NULL, NULL,                                "8"
   },
 
@@ -2341,7 +2466,7 @@ static struct
   /* ---------- random background (for random painting) -------------------- */
 
   {
-    -1,                                        ED_SETTINGS_YPOS(14),
+    -1,                                        ED_ELEMENT_SETTINGS_YPOS(14),
     1, 1,
     GADGET_ID_RANDOM_BACKGROUND,       GADGET_ID_RANDOM_RESTRICTED,
     NULL, NULL,                                NULL
@@ -2573,6 +2698,132 @@ static int *editor_el_emerald_mine_ptr = editor_el_emerald_mine;
 static int num_editor_hl_emerald_mine=SIZEOF_ARRAY_INT(editor_hl_emerald_mine);
 static int num_editor_el_emerald_mine=SIZEOF_ARRAY_INT(editor_el_emerald_mine);
 
+static int editor_hl_emerald_mine_club[] =
+{
+  EL_CHAR('E'),
+  EL_CHAR('M'),
+  EL_CHAR('E'),
+  EL_CHAR('-'),
+
+  EL_CHAR('R'),
+  EL_CHAR('A'),
+  EL_CHAR('L'),
+  EL_CHAR('D'),
+
+  EL_CHAR('M'),
+  EL_CHAR('I'),
+  EL_CHAR('N'),
+  EL_CHAR('E'),
+
+  EL_CHAR('C'),
+  EL_CHAR('L'),
+  EL_CHAR('U'),
+  EL_CHAR('B'),
+};
+
+static int editor_el_emerald_mine_club[] =
+{
+  EL_EMC_KEY_5,
+  EL_EMC_KEY_6,
+  EL_EMC_KEY_7,
+  EL_EMC_KEY_8,
+
+  EL_EMC_GATE_5,
+  EL_EMC_GATE_6,
+  EL_EMC_GATE_7,
+  EL_EMC_GATE_8,
+
+  EL_EMC_GATE_5_GRAY,
+  EL_EMC_GATE_6_GRAY,
+  EL_EMC_GATE_7_GRAY,
+  EL_EMC_GATE_8_GRAY,
+
+  EL_EMC_STEELWALL_1,
+  EL_EMC_STEELWALL_2,
+  EL_EMC_STEELWALL_3,
+  EL_EMC_STEELWALL_4,
+
+  EL_EMC_WALL_13,
+  EL_EMC_WALL_14,
+  EL_EMC_WALL_15,
+  EL_EMC_WALL_16,
+
+  EL_EMC_WALL_SLIPPERY_1,
+  EL_EMC_WALL_SLIPPERY_2,
+  EL_EMC_WALL_SLIPPERY_3,
+  EL_EMC_WALL_SLIPPERY_4,
+
+  EL_EMC_WALL_1,
+  EL_EMC_WALL_2,
+  EL_EMC_WALL_3,
+  EL_EMC_WALL_4,
+
+  EL_EMC_WALL_5,
+  EL_EMC_WALL_6,
+  EL_EMC_WALL_7,
+  EL_EMC_WALL_8,
+
+  EL_EMC_WALL_9,
+  EL_EMC_WALL_10,
+  EL_EMC_WALL_11,
+  EL_EMC_WALL_12,
+
+#if RELEASE_311
+  EL_EMPTY,
+#else
+  EL_EMC_ANDROID,
+#endif
+  EL_BALLOON,
+  EL_BALLOON_SWITCH_ANY,
+#if RELEASE_311
+  EL_EMPTY,
+#else
+  EL_BALLOON_SWITCH_NONE,
+#endif
+
+  EL_BALLOON_SWITCH_LEFT,
+  EL_BALLOON_SWITCH_RIGHT,
+  EL_BALLOON_SWITCH_UP,
+  EL_BALLOON_SWITCH_DOWN,
+
+  EL_EMC_GRASS,
+  EL_EMC_PLANT,
+#if RELEASE_311
+  EL_EMPTY,
+  EL_EMPTY,
+#else
+  EL_EMC_LENSES,
+  EL_EMC_MAGNIFIER,
+#endif
+
+#if RELEASE_311
+  EL_EMPTY,
+  EL_EMPTY,
+#else
+  EL_EMC_MAGIC_BALL,
+  EL_EMC_MAGIC_BALL_SWITCH,
+#endif
+  EL_SPRING,
+#if RELEASE_311
+  EL_EMPTY,
+#else
+  EL_EMC_SPRING_BUMPER,
+#endif
+
+#if RELEASE_311
+  EL_EMPTY,
+#else
+  EL_EMC_DRIPPER,
+#endif
+  EL_EMC_FAKE_GRASS,
+  EL_EMPTY,
+  EL_EMPTY,
+};
+static int *editor_hl_emerald_mine_club_ptr = editor_hl_emerald_mine_club;
+static int *editor_el_emerald_mine_club_ptr = editor_el_emerald_mine_club;
+static int num_editor_hl_emerald_mine_club=SIZEOF_ARRAY_INT(editor_hl_emerald_mine_club);
+static int num_editor_el_emerald_mine_club=SIZEOF_ARRAY_INT(editor_el_emerald_mine_club);
+
 static int editor_hl_more[] =
 {
   EL_CHAR('M'),
@@ -2650,13 +2901,8 @@ static int editor_el_more[] =
 
   EL_SPACESHIP,
   EL_MOLE_DOWN,
-  EL_BALLOON,
-  EL_BALLOON_SWITCH_ANY,
-
-  EL_BALLOON_SWITCH_LEFT,
-  EL_BALLOON_SWITCH_RIGHT,
-  EL_BALLOON_SWITCH_UP,
-  EL_BALLOON_SWITCH_DOWN,
+  EL_EMPTY,
+  EL_EMPTY,
 
   EL_SATELLITE,
   EL_EXPANDABLE_WALL_HORIZONTAL,
@@ -2667,16 +2913,6 @@ static int editor_el_more[] =
   EL_INVISIBLE_WALL,
   EL_SPEED_PILL,
   EL_BLACK_ORB,
-
-  EL_EMC_STEELWALL_1,
-  EL_EMC_WALL_1,
-  EL_EMC_WALL_2,
-  EL_EMC_WALL_3,
-
-  EL_EMC_WALL_4,
-  EL_EMC_WALL_5,
-  EL_EMC_WALL_6,
-  EL_EMC_WALL_7,
 };
 static int *editor_hl_more_ptr = editor_hl_more;
 static int *editor_el_more_ptr = editor_el_more;
@@ -2902,7 +3138,7 @@ static int editor_hl_dx_boulderdash[] =
 
 static int editor_el_dx_boulderdash[] =
 {
-  EL_SPRING,
+  EL_EMPTY,
   EL_TUBE_RIGHT_DOWN,
   EL_TUBE_HORIZONTAL_DOWN,
   EL_TUBE_LEFT_DOWN,
@@ -3550,6 +3786,11 @@ editor_elements_info[] =
     &editor_hl_emerald_mine_ptr,       &num_editor_hl_emerald_mine,
     &editor_el_emerald_mine_ptr,       &num_editor_el_emerald_mine
   },
+  {
+    &setup.editor.el_emerald_mine_club,
+    &editor_hl_emerald_mine_club_ptr,  &num_editor_hl_emerald_mine_club,
+    &editor_el_emerald_mine_club_ptr,  &num_editor_el_emerald_mine_club
+  },
   {
     &setup.editor.el_more,
     &editor_hl_more_ptr,               &num_editor_hl_more,
@@ -3886,7 +4127,11 @@ static void ReinitializeElementList()
 
   checked_free(editor_elements);
 
+#if 0
   if (!initialized)
+#else
+  /* reload user defined element list for each invocation of level editor */
+#endif
   {
     /* initialize optional user defined element list */
     LoadUserDefinedEditorElementList(&editor_el_user_defined_ptr,
@@ -4085,10 +4330,10 @@ static void DrawDrawingArea(int id)
     for (x = 0; x < group_element_info.num_elements; x++)
       DrawMiniGraphicExt(drawto, gi->x + x * MINI_TILEX, gi->y,
                         el2edimg(group_element_info.element[x]));
-  else if (id >= ED_DRAWING_ID_ELEMENT_CONTENT_0 &&
-          id <= ED_DRAWING_ID_ELEMENT_CONTENT_7)
+  else if (id >= ED_DRAWING_ID_YAMYAM_CONTENT_0 &&
+          id <= ED_DRAWING_ID_YAMYAM_CONTENT_7)
   {
-    int nr = id - ED_DRAWING_ID_ELEMENT_CONTENT_0;
+    int nr = id - ED_DRAWING_ID_YAMYAM_CONTENT_0;
 
     for (y = 0; y < 3; y++)
       for (x = 0; x < 3; x++)
@@ -4096,6 +4341,17 @@ static void DrawDrawingArea(int id)
                           gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
                           el2edimg(level.yamyam_content[nr][x][y]));
   }
+  else if (id >= ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 &&
+          id <= ED_DRAWING_ID_MAGIC_BALL_CONTENT_7)
+  {
+    int nr = id - ED_DRAWING_ID_MAGIC_BALL_CONTENT_0;
+
+    for (y = 0; y < 3; y++)
+      for (x = 0; x < 3; x++)
+       DrawMiniGraphicExt(drawto,
+                          gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
+                          el2edimg(level.ball_content[nr][x][y]));
+  }
 }
 
 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
@@ -5151,8 +5407,9 @@ static void MapCounterButtons(int id)
   int y;       /* set after gadget position was modified */
 #endif
 
-  /* set position for "score" counter gadget */
-  if (id == ED_COUNTER_ID_ELEMENT_SCORE)
+  /* set position for "value1/value2" counter gadgets (score in most cases) */
+  if (id == ED_COUNTER_ID_ELEMENT_VALUE1 ||
+      id == ED_COUNTER_ID_ELEMENT_VALUE2)
   {
     ModifyGadget(gi_down, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
     ModifyGadget(gi_text, GDI_Y, SY + counterbutton_info[id].y, GDI_END);
@@ -5509,6 +5766,8 @@ static void ResetUndoBuffer()
   undo_buffer_position = -1;
   undo_buffer_steps = -1;
   CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
+
+  level.changed = FALSE;
 }
 
 static void DrawEditModeWindow()
@@ -5526,15 +5785,18 @@ static void DrawEditModeWindow()
 
 static boolean LevelChanged()
 {
-  boolean level_changed = FALSE;
+  boolean field_changed = FALSE;
   int x, y;
 
+  if (leveldir_current->readonly)
+    return FALSE;
+
   for (y = 0; y < lev_fieldy; y++) 
     for (x = 0; x < lev_fieldx; x++)
       if (Feld[x][y] != level.field[x][y])
-       level_changed = TRUE;
+       field_changed = TRUE;
 
-  return level_changed;
+  return (level.changed || field_changed);
 }
 
 static boolean LevelContainsPlayer()
@@ -5542,6 +5804,8 @@ static boolean LevelContainsPlayer()
   boolean player_found = FALSE;
   int x, y;
 
+  return TRUE;         /* !!! CURRENTLY DEACTIVATED !!! */
+
   for (y = 0; y < lev_fieldy; y++) 
     for (x = 0; x < lev_fieldx; x++)
       if (Feld[x][y] == EL_PLAYER_1 ||
@@ -5741,6 +6005,8 @@ static boolean CopyCustomElement(int element_old, int element_new,
     element_old = (IS_CUSTOM_ELEMENT(element_new) ?
                   EL_INTERNAL_CLIPBOARD_CUSTOM : EL_INTERNAL_CLIPBOARD_GROUP);
     copy_mode = GADGET_ID_CUSTOM_COPY_TO;
+
+    level.changed = TRUE;
   }
   else if (IS_CUSTOM_ELEMENT(element_old) && !IS_CUSTOM_ELEMENT(element_new))
   {
@@ -5754,6 +6020,10 @@ static boolean CopyCustomElement(int element_old, int element_new,
 
     return FALSE;
   }
+  else
+  {
+    level.changed = TRUE;
+  }
 
   if (copy_mode == GADGET_ID_CUSTOM_COPY_FROM)
   {
@@ -5933,20 +6203,20 @@ static void CopyCustomElementPropertiesToEditor(int element)
 
   /* set "change by other element action" selectbox help value */
   custom_element_change.other_action =
-    (HAS_CHANGE_EVENT(element, CE_OTHER_GETS_TOUCHED) ? CE_OTHER_GETS_TOUCHED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PRESSED) ? CE_OTHER_GETS_PRESSED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PUSHED) ? CE_OTHER_GETS_PUSHED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_ENTERED) ? CE_OTHER_GETS_ENTERED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_LEFT) ? CE_OTHER_GETS_LEFT :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DIGGED) ? CE_OTHER_GETS_DIGGED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_COLLECTED) ? CE_OTHER_GETS_COLLECTED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DROPPED) ? CE_OTHER_GETS_DROPPED :
-     HAS_CHANGE_EVENT(element, CE_OTHER_IS_TOUCHING) ? CE_OTHER_IS_TOUCHING :
-     HAS_CHANGE_EVENT(element, CE_OTHER_IS_HITTING) ? CE_OTHER_IS_HITTING :
-     HAS_CHANGE_EVENT(element, CE_OTHER_GETS_HIT) ? CE_OTHER_GETS_HIT :
-     HAS_CHANGE_EVENT(element, CE_OTHER_IS_SWITCHING) ? CE_OTHER_IS_SWITCHING :
-     HAS_CHANGE_EVENT(element, CE_OTHER_IS_CHANGING) ? CE_OTHER_IS_CHANGING :
-     HAS_CHANGE_EVENT(element, CE_OTHER_IS_EXPLODING) ? CE_OTHER_IS_EXPLODING :
+    (HAS_CHANGE_EVENT(element, CE_PLAYER_TOUCHES_X) ? CE_PLAYER_TOUCHES_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_PRESSES_X) ? CE_PLAYER_PRESSES_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_PUSHES_X) ? CE_PLAYER_PUSHES_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_ENTERS_X) ? CE_PLAYER_ENTERS_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_LEAVES_X) ? CE_PLAYER_LEAVES_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_DIGS_X) ? CE_PLAYER_DIGS_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_COLLECTS_X) ? CE_PLAYER_COLLECTS_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_DROPS_X) ? CE_PLAYER_DROPS_X :
+     HAS_CHANGE_EVENT(element, CE_TOUCHING_X) ? CE_TOUCHING_X :
+     HAS_CHANGE_EVENT(element, CE_HITTING_X) ? CE_HITTING_X :
+     HAS_CHANGE_EVENT(element, CE_HIT_BY_X) ? CE_HIT_BY_X :
+     HAS_CHANGE_EVENT(element, CE_SWITCH_OF_X) ? CE_SWITCH_OF_X :
+     HAS_CHANGE_EVENT(element, CE_CHANGE_OF_X) ? CE_CHANGE_OF_X :
+     HAS_CHANGE_EVENT(element, CE_EXPLOSION_OF_X) ? CE_EXPLOSION_OF_X :
      custom_element_change.other_action);
 }
 
@@ -5999,6 +6269,7 @@ static void CopyCustomElementPropertiesToGame(int element)
 
   /* mark that this custom element has been modified */
   custom_element.modified_settings = TRUE;
+  level.changed = TRUE;
 
   if (level.use_custom_template)
   {
@@ -6121,20 +6392,20 @@ static void CopyCustomElementPropertiesToGame(int element)
     custom_element_change_events[CE_BY_DIRECT_ACTION];
 
   /* set other element action change event from checkbox and selectbox */
-  custom_element_change_events[CE_OTHER_GETS_TOUCHED] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_PRESSED] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_PUSHED] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_ENTERED] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_LEFT] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_DIGGED] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_COLLECTED] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_DROPPED] = FALSE;
-  custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE;
-  custom_element_change_events[CE_OTHER_IS_HITTING] = FALSE;
-  custom_element_change_events[CE_OTHER_GETS_HIT] = FALSE;
-  custom_element_change_events[CE_OTHER_IS_SWITCHING] = FALSE;
-  custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE;
-  custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE;
+  custom_element_change_events[CE_PLAYER_TOUCHES_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_PRESSES_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_PUSHES_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_ENTERS_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_LEAVES_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_DIGS_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_COLLECTS_X] = FALSE;
+  custom_element_change_events[CE_PLAYER_DROPS_X] = FALSE;
+  custom_element_change_events[CE_TOUCHING_X] = FALSE;
+  custom_element_change_events[CE_HITTING_X] = FALSE;
+  custom_element_change_events[CE_HIT_BY_X] = FALSE;
+  custom_element_change_events[CE_SWITCH_OF_X] = FALSE;
+  custom_element_change_events[CE_CHANGE_OF_X] = FALSE;
+  custom_element_change_events[CE_EXPLOSION_OF_X] = FALSE;
   custom_element_change_events[custom_element_change.other_action] =
     custom_element_change_events[CE_BY_OTHER_ACTION];
 
@@ -6156,6 +6427,7 @@ static void CopyGroupElementPropertiesToGame(int element)
 
   /* mark that this group element has been modified */
   element_info[element].modified_settings = TRUE;
+  level.changed = TRUE;
 }
 
 static void CopyClassicElementPropertiesToGame(int element)
@@ -6540,24 +6812,27 @@ static void DrawCustomChangeContentArea()
   MapDrawingArea(id);
 }
 
-static void DrawElementContentAreas()
+static void DrawYamYamContentAreas()
 {
   int x = SX + ED_AREA_YAMYAM_CONTENT_XPOS(3) + 4 * MINI_TILEX;
   int y = SY + ED_AREA_YAMYAM_CONTENT_YPOS(0) + ED_BORDER_AREA_YSIZE;
   int i;
 
   /* display counter to choose number of element content areas */
-  MapCounterButtons(ED_COUNTER_ID_ELEMENT_CONTENT);
+  MapCounterButtons(ED_COUNTER_ID_YAMYAM_CONTENT);
 
   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
   {
-    int id = ED_DRAWING_ID_ELEMENT_CONTENT_0 + i;
-    int font_height = getFontHeight(FONT_TEXT_1);
+    int id = ED_DRAWING_ID_YAMYAM_CONTENT_0 + i;
 
     if (i < level.num_yamyam_contents)
+    {
       MapDrawingArea(id);
+    }
     else
     {
+      int font_height = getFontHeight(FONT_TEXT_1);
+
       UnmapDrawingArea(id);
 
       /* delete content areas in case of reducing number of them */
@@ -6573,6 +6848,20 @@ static void DrawElementContentAreas()
   DrawText(x, y + 2 * MINI_TILEY, "smashed", FONT_TEXT_1);
 }
 
+static void DrawMagicBallContentAreas()
+{
+  int x = SX + ED_AREA_MAGIC_BALL_CONTENT_XPOS(3) + 4 * MINI_TILEX;
+  int y = SY + ED_AREA_MAGIC_BALL_CONTENT_YPOS(0) + ED_BORDER_AREA_YSIZE;
+  int i;
+
+  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+    MapDrawingArea(ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 + i);
+
+  DrawText(x, y + 0 * MINI_TILEY, "generated", FONT_TEXT_1);
+  DrawText(x, y + 1 * MINI_TILEY, "when",      FONT_TEXT_1);
+  DrawText(x, y + 2 * MINI_TILEY, "active",    FONT_TEXT_1);
+}
+
 static void DrawGroupElementArea(int element)
 {
   int num_elements = group_element_info.num_elements;
@@ -6643,8 +6932,8 @@ char *getElementDescriptionFilename(int element)
 static boolean PrintInfoText(char *text, int font_nr, int start_line)
 {
   int font_height = getFontHeight(font_nr);
-  int pad_x = ED_SETTINGS_XPOS(0);
-  int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
+  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
   int sx = SX + pad_x;
   int sy = SY + pad_y;
   int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1;
@@ -6664,8 +6953,8 @@ static int PrintElementDescriptionFromFile(char *filename, int start_line)
   int font_nr = FONT_TEXT_2;
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-  int pad_x = ED_SETTINGS_XPOS(0);
-  int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
+  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
   int sx = SX + pad_x;
   int sy = SY + pad_y + start_line * font_height;
   int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width;
@@ -6682,8 +6971,8 @@ static int PrintElementDescriptionFromFile(char *filename, int start_line)
   int font_nr = FONT_TEXT_2;
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-  int pad_x = ED_SETTINGS_XPOS(0);
-  int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
+  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
   int sx = SX + pad_x;
   int sy = SY + pad_y;
   int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width;
@@ -6877,8 +7166,8 @@ static void DrawPropertiesInfo()
   int font2_nr = FONT_TEXT_2;
   int font1_width = getFontWidth(font1_nr);
   int font2_height = getFontHeight(font2_nr);
-  int pad_x = ED_SETTINGS_XPOS(0);
-  int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
+  int pad_x = ED_ELEMENT_SETTINGS_XPOS(0);
+  int pad_y = ED_ELEMENT_SETTINGS_YPOS(0) + ED_BORDER_SIZE;
   int screen_line = 0;
   int i, x, y;
 
@@ -6944,9 +7233,13 @@ static void DrawPropertiesInfo()
 
 #define TEXT_COLLECTING                "Score for collecting"
 #define TEXT_SMASHING          "Score for smashing"
+#define TEXT_SLURPING          "Score for slurping"
 #define TEXT_CRACKING          "Score for cracking"
-#define TEXT_SPEED             "Speed of amoeba growth"
+#define TEXT_AMOEBA_SPEED      "Speed of amoeba growth"
 #define TEXT_DURATION          "Duration when activated"
+#define TEXT_BALL_DELAY                "Element generation delay"
+#define TEXT_MOVE_SPEED                "Speed of android moving"
+#define TEXT_CLONE_SPEED       "Speed of android cloning"
 
 static struct
 {
@@ -7017,12 +7310,28 @@ static struct
   { EL_EM_KEY_3_FILE,  &level.score[SC_KEY],           TEXT_COLLECTING },
   { EL_EM_KEY_4_FILE,  &level.score[SC_KEY],           TEXT_COLLECTING },
 #endif
-  { EL_AMOEBA_WET,     &level.amoeba_speed,            TEXT_SPEED      },
-  { EL_AMOEBA_DRY,     &level.amoeba_speed,            TEXT_SPEED      },
-  { EL_AMOEBA_FULL,    &level.amoeba_speed,            TEXT_SPEED      },
-  { EL_BD_AMOEBA,      &level.amoeba_speed,            TEXT_SPEED      },
+  { EL_EMC_KEY_5,      &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EMC_KEY_6,      &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EMC_KEY_7,      &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EMC_KEY_8,      &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_AMOEBA_WET,     &level.amoeba_speed,            TEXT_AMOEBA_SPEED },
+  { EL_AMOEBA_DRY,     &level.amoeba_speed,            TEXT_AMOEBA_SPEED },
+  { EL_AMOEBA_FULL,    &level.amoeba_speed,            TEXT_AMOEBA_SPEED },
+  { EL_BD_AMOEBA,      &level.amoeba_speed,            TEXT_AMOEBA_SPEED },
   { EL_MAGIC_WALL,     &level.time_magic_wall,         TEXT_DURATION   },
   { EL_ROBOT_WHEEL,    &level.time_wheel,              TEXT_DURATION   },
+
+#if 1
+  { EL_EMC_ANDROID,    &level.android_move_time,       TEXT_MOVE_SPEED },
+  { EL_EMC_ANDROID,    &level.android_clone_time,      TEXT_CLONE_SPEED },
+  { EL_EMC_MAGIC_BALL, &level.ball_time,               TEXT_BALL_DELAY },
+  { EL_EMC_LENSES,     &level.lenses_score,            TEXT_COLLECTING },
+  { EL_EMC_MAGNIFIER,  &level.magnify_score,           TEXT_COLLECTING },
+  { EL_ROBOT,          &level.slurp_score,             TEXT_SLURPING   },
+  { EL_EMC_LENSES,     &level.lenses_time,             TEXT_DURATION   },
+  { EL_EMC_MAGNIFIER,  &level.magnify_time,            TEXT_DURATION   },
+#endif
+
   { -1,                        NULL,                           NULL            }
 };
 
@@ -7050,6 +7359,8 @@ static boolean checkPropertiesConfig(int element)
 
 static void DrawPropertiesConfig()
 {
+  int max_num_element_counters = 2;
+  int num_element_counters = 0;
   int i;
 
   if (!checkPropertiesConfig(properties_element))
@@ -7059,25 +7370,32 @@ static void DrawPropertiesConfig()
     return;
   }
 
-  /* check if there are elements where a score can be chosen for */
+  /* check if there are elements where a value can be chosen for */
   for (i = 0; elements_with_counter[i].element != -1; i++)
   {
     if (elements_with_counter[i].element == properties_element)
     {
-      int counter_id = ED_COUNTER_ID_ELEMENT_SCORE;
+      int counter_id = ED_COUNTER_ID_ELEMENT_VALUE1 + num_element_counters;
 
       counterbutton_info[counter_id].y =
-       ED_SETTINGS_YPOS((HAS_CONTENT(properties_element) ? 1 : 0) +
+       ED_ELEMENT_SETTINGS_YPOS((HAS_CONTENT(properties_element) ? 1 : 0) +
                         (CAN_GROW(properties_element) ? 1 : 0) +
                         (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0) +
-                        (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 :0));
+                        (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 : 0)+
+                        num_element_counters);
 
       counterbutton_info[counter_id].value = elements_with_counter[i].value;
       counterbutton_info[counter_id].text_right= elements_with_counter[i].text;
 
+      /* !!! CHANGE THIS FOR CERTAIN ELEMENTS !!! */
+      counterbutton_info[counter_id].min_value = MIN_SCORE;
+      counterbutton_info[counter_id].max_value = MAX_SCORE;
+
       MapCounterButtons(counter_id);
 
-      break;
+      num_element_counters++;
+      if (num_element_counters >= max_num_element_counters)
+       break;
     }
   }
 
@@ -7088,10 +7406,13 @@ static void DrawPropertiesConfig()
 
     if (IS_AMOEBOID(properties_element))
       MapDrawingArea(ED_DRAWING_ID_AMOEBA_CONTENT);
-    else
-      DrawElementContentAreas();
+    else if (properties_element == EL_YAMYAM)
+      DrawYamYamContentAreas();
   }
 
+  if (properties_element == EL_EMC_MAGIC_BALL)
+    DrawMagicBallContentAreas();
+
   if (ELEM_IS_PLAYER(properties_element))
   {
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID);
@@ -7100,6 +7421,7 @@ static void DrawPropertiesConfig()
                         ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD);
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INSTANT_RELOCATION);
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE);
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DOUBLE_SPEED);
   }
 
   if (IS_GEM(properties_element))
@@ -7112,9 +7434,9 @@ static void DrawPropertiesConfig()
   {
     /* set position for checkbutton for "can move into acid" */
     checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].x =
-      ED_SETTINGS_XPOS(IS_CUSTOM_ELEMENT(properties_element) ? 1 : 0);
+      ED_ELEMENT_SETTINGS_XPOS(IS_CUSTOM_ELEMENT(properties_element) ? 1 : 0);
     checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].y =
-      ED_SETTINGS_YPOS(IS_CUSTOM_ELEMENT(properties_element) ? 6 :
+      ED_ELEMENT_SETTINGS_YPOS(IS_CUSTOM_ELEMENT(properties_element) ? 6 :
                       HAS_CONTENT(properties_element) ? 1 : 0);
 
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID);
@@ -7129,7 +7451,7 @@ static void DrawPropertiesConfig()
   if (CAN_GROW(properties_element))
   {
     checkbutton_info[ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE].y =
-      ED_SETTINGS_YPOS(HAS_CONTENT(properties_element) ? 1 : 0);
+      ED_ELEMENT_SETTINGS_YPOS(HAS_CONTENT(properties_element) ? 1 : 0);
 
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE);
   }
@@ -7288,7 +7610,7 @@ static void DrawElementName(int x, int y, int element)
   int font_nr = FONT_TEXT_1;
   int font_width = getFontWidth(font_nr);
   int font_height = getFontHeight(font_nr);
-  int max_text_width = SXSIZE - x - ED_SETTINGS_XPOS(0);
+  int max_text_width = SXSIZE - x - ED_ELEMENT_SETTINGS_XPOS(0);
   int max_chars_per_line = max_text_width / font_width;
   char buffer[max_chars_per_line + 1];
 
@@ -7604,6 +7926,7 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y,
 #define CB_BRUSH_TO_LEVEL      2
 #define CB_DELETE_OLD_CURSOR   3
 #define CB_DUMP_BRUSH          4
+#define CB_DUMP_BRUSH_SMALL    5
 
 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
                         int button, int mode)
@@ -7615,7 +7938,8 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
   int new_element = BUTTON_ELEMENT(button);
   int x, y;
 
-  if (mode == CB_DUMP_BRUSH)
+  if (mode == CB_DUMP_BRUSH ||
+      mode == CB_DUMP_BRUSH_SMALL)
   {
     if (!draw_with_brush)
     {
@@ -7662,10 +7986,12 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
 
        if (IS_CUSTOM_ELEMENT(element))
          element_mapped = EL_CUSTOM_START;
-       else if (element > EL_ENVELOPE_4)
-         element_mapped = EL_CHAR_QUESTION;    /* change to EL_UNKNOWN ... */
+       else if (IS_GROUP_ELEMENT(element))
+         element_mapped = EL_GROUP_START;
+       else if (element >= NUM_FILE_ELEMENTS)
+         element_mapped = EL_UNKNOWN;
 
-       printf("`%03d", element_mapped);
+       printf("%c%03d", (mode == CB_DUMP_BRUSH ? '`' : '¸'), element_mapped);
 #endif
       }
 
@@ -7794,6 +8120,11 @@ void DumpBrush()
   CopyBrushExt(0, 0, 0, 0, 0, CB_DUMP_BRUSH);
 }
 
+void DumpBrush_Small()
+{
+  CopyBrushExt(0, 0, 0, 0, 0, CB_DUMP_BRUSH_SMALL);
+}
+
 static void FloodFill(int from_x, int from_y, int fill_element)
 {
   int i,x,y;
@@ -7903,6 +8234,8 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
          DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
        else
          DrawLevelText(0, 0, 0, TEXT_END);
+
+       level.changed = TRUE;
       }
       break;
 
@@ -7991,56 +8324,56 @@ static void CopyLevelToUndoBuffer(int mode)
   SetBorderElement();
   if (BorderElement != last_border_element)
     DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+
+  level.changed = TRUE;
 }
 
 static void RandomPlacement(int new_element)
 {
   static boolean free_position[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-  int num_free_positions;
-  int num_percentage;
-  int num_elements;
+  int num_free_positions = 0;
+  int num_percentage, num_elements;
   int x, y;
 
-  /* determine number of free positions for the new elements */
-  /* (maybe this statement should be formatted a bit more readable...) */
-  num_free_positions = 0;
-  for (x = 0; x < lev_fieldx; x++)
-    for (y = 0; y < lev_fieldy; y++)
-      if ((free_position[x][y] =
-          ((random_placement_background_restricted &&
-            Feld[x][y] == random_placement_background_element) ||
-           (!random_placement_background_restricted &&
-            Feld[x][y] != new_element))) == TRUE)
-       num_free_positions++;
+  /* determine number of free positions for randomly placing the new element */
+  for (x = 0; x < lev_fieldx; x++) for (y = 0; y < lev_fieldy; y++)
+  {
+    free_position[x][y] =
+      (random_placement_background_restricted ?
+       Feld[x][y] == random_placement_background_element :
+       Feld[x][y] != new_element);
+
+    if (free_position[x][y])
+      num_free_positions++;
+  }
 
   /* determine number of new elements to place there */
   num_percentage = num_free_positions * random_placement_value / 100;
   num_elements = (random_placement_method == RANDOM_USE_PERCENTAGE ?
                  num_percentage : random_placement_value);
 
-  /* if not more free positions than elements to place, fill whole level */
-  if (num_elements >= num_free_positions)
+  /* if less free positions than elements to place, fill all these positions */
+  if (num_free_positions < num_elements)
   {
     for (x = 0; x < lev_fieldx; x++)
       for (y = 0; y < lev_fieldy; y++)
-       Feld[x][y] = new_element;
-
-    DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
-    CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
-    return;
+       if (free_position[x][y])
+         Feld[x][y] = new_element;
   }
-
-  while (num_elements > 0)
+  else
   {
-    x = RND(lev_fieldx);
-    y = RND(lev_fieldy);
-
-    /* don't place element at the same position twice */
-    if (free_position[x][y])
+    while (num_elements > 0)
     {
-      free_position[x][y] = FALSE;
-      Feld[x][y] = new_element;
-      num_elements--;
+      x = RND(lev_fieldx);
+      y = RND(lev_fieldy);
+
+      /* don't place element at the same position twice */
+      if (free_position[x][y])
+      {
+       free_position[x][y] = FALSE;
+       Feld[x][y] = new_element;
+       num_elements--;
+      }
     }
   }
 
@@ -8253,9 +8586,13 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        }
        else if (id == GADGET_ID_RANDOM_BACKGROUND)
          random_placement_background_element = new_element;
-       else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
-                id <= GADGET_ID_ELEMENT_CONTENT_7)
-         level.yamyam_content[id - GADGET_ID_ELEMENT_CONTENT_0][sx][sy] =
+       else if (id >= GADGET_ID_YAMYAM_CONTENT_0 &&
+                id <= GADGET_ID_YAMYAM_CONTENT_7)
+         level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0][sx][sy] =
+           new_element;
+       else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
+                id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
+         level.ball_content[id - GADGET_ID_MAGIC_BALL_CONTENT_0][sx][sy] =
            new_element;
       }
       break;
@@ -8375,13 +8712,20 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        PickDrawingElement(button, group_element_info.element[sx]);
       else if (id == GADGET_ID_RANDOM_BACKGROUND)
        PickDrawingElement(button, random_placement_background_element);
-      else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
-              id <= GADGET_ID_ELEMENT_CONTENT_7)
+      else if (id >= GADGET_ID_YAMYAM_CONTENT_0 &&
+              id <= GADGET_ID_YAMYAM_CONTENT_7)
       {
-       int i = id - GADGET_ID_ELEMENT_CONTENT_0;
+       int i = id - GADGET_ID_YAMYAM_CONTENT_0;
 
        PickDrawingElement(button, level.yamyam_content[i][sx][sy]);
       }
+      else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
+              id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
+      {
+       int i = id - GADGET_ID_MAGIC_BALL_CONTENT_0;
+
+       PickDrawingElement(button, level.ball_content[i][sx][sy]);
+      }
 
       break;
 
@@ -8408,11 +8752,12 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
     if ((level_changed && pressed) || (!level_changed && released))
       return;
 
-    if (level_changed && !Request("Level has changed! Discard changes ?",
+    if (level_changed && !Request("Level has changed ! Discard changes ?",
                                  REQ_ASK))
     {
       if (gadget_id == counterbutton_info[counter_id].gadget_id_text)
        ModifyEditorCounter(counter_id, *counter_value);
+
       return;
     }
   }
@@ -8422,10 +8767,20 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
   else
     ModifyEditorCounter(counter_id, *counter_value + step);
 
+  if (counter_id == ED_COUNTER_ID_SELECT_LEVEL)
+  {
+      LoadLevel(level_nr);
+      TapeErase();
+      ResetUndoBuffer();
+      DrawEditModeWindow();
+
+      return;
+  }
+
   switch (counter_id)
   {
-    case ED_COUNTER_ID_ELEMENT_CONTENT:
-      DrawElementContentAreas();
+    case ED_COUNTER_ID_YAMYAM_CONTENT:
+      DrawYamYamContentAreas();
       break;
 
     case ED_COUNTER_ID_GROUP_CONTENT:
@@ -8444,13 +8799,6 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
       lev_fieldy = level.fieldy;
       break;
 
-    case ED_COUNTER_ID_SELECT_LEVEL:
-      LoadLevel(level_nr);
-      TapeErase();
-      ResetUndoBuffer();
-      DrawEditModeWindow();
-      break;
-
     default:
       break;
   }
@@ -8460,6 +8808,8 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
       (counter_id >= ED_COUNTER_ID_CHANGE_FIRST &&
        counter_id <= ED_COUNTER_ID_CHANGE_LAST))
     CopyElementPropertiesToGame(properties_element);
+
+  level.changed = TRUE;
 }
 
 static void HandleTextInputGadgets(struct GadgetInfo *gi)
@@ -8474,6 +8824,8 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi)
 
     ModifyEditorElementList(); /* update changed button info text */
   }
+
+  level.changed = TRUE;
 }
 
 static void HandleTextAreaGadgets(struct GadgetInfo *gi)
@@ -8481,6 +8833,8 @@ static void HandleTextAreaGadgets(struct GadgetInfo *gi)
   int type_id = gi->custom_type_id;
 
   strcpy(textarea_info[type_id].value, gi->textarea.value);
+
+  level.changed = TRUE;
 }
 
 static void HandleSelectboxGadgets(struct GadgetInfo *gi)
@@ -8501,7 +8855,11 @@ static void HandleSelectboxGadgets(struct GadgetInfo *gi)
           (type_id >= ED_SELECTBOX_ID_CHANGE_FIRST &&
            type_id <= ED_SELECTBOX_ID_CHANGE_LAST) ||
           (type_id == ED_SELECTBOX_ID_GROUP_CHOICE_MODE))
+  {
     CopyElementPropertiesToGame(properties_element);
+
+    level.changed = TRUE;
+  }
 }
 
 static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
@@ -8542,6 +8900,8 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
     setElementChangeInfoToDefaults(ei->change);
 
     DrawPropertiesWindow();
+
+    level.changed = TRUE;
   }
   else if (type_id == ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE &&
           custom_element.num_change_pages > MIN_CHANGE_PAGES)
@@ -8555,6 +8915,8 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
     setElementChangePages(ei, ei->num_change_pages - 1);
 
     DrawPropertiesWindow();
+
+    level.changed = TRUE;
   }
 }
 
@@ -8588,9 +8950,13 @@ static void HandleGraphicbuttonGadgets(struct GadgetInfo *gi)
       element_info[EL_INTERNAL_CLIPBOARD_CHANGE].change_page[0] =
        ei->change_page[current_change_page];
     else if (type_id == ED_GRAPHICBUTTON_ID_PASTE_CHANGE_PAGE)
+    {
       ei->change_page[current_change_page] =
        element_info[EL_INTERNAL_CLIPBOARD_CHANGE].change_page[0];
 
+      level.changed = TRUE;
+    }
+
     DrawPropertiesWindow();
   }
 }
@@ -8599,6 +8965,8 @@ static void HandleRadiobuttons(struct GadgetInfo *gi)
 {
   *radiobutton_info[gi->custom_type_id].value =
     radiobutton_info[gi->custom_type_id].checked_value;
+
+  level.changed = TRUE;
 }
 
 static void HandleCheckbuttons(struct GadgetInfo *gi)
@@ -8641,6 +9009,8 @@ static void HandleCheckbuttons(struct GadgetInfo *gi)
 
     DrawEditModeWindow();
   }
+
+  level.changed = TRUE;
 }
 
 static void HandleControlButtons(struct GadgetInfo *gi)
@@ -8906,6 +9276,7 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       for (x = 0; x < MAX_LEV_FIELDX; x++) 
        for (y = 0; y < MAX_LEV_FIELDY; y++) 
          Feld[x][y] = (button == 1 ? EL_EMPTY : new_element);
+
       CopyLevelToUndoBuffer(GADGET_ID_CLEAR);
 
       DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
@@ -8918,7 +9289,7 @@ static void HandleControlButtons(struct GadgetInfo *gi)
        break;
       }
 
-      if (!LevelContainsPlayer)
+      if (!LevelContainsPlayer())
        Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
       else
       {
@@ -8935,11 +9306,13 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
        if (new_level)
          Request("Level saved !", REQ_CONFIRM);
+
+       level.changed = FALSE;
       }
       break;
 
     case GADGET_ID_TEST:
-      if (!LevelContainsPlayer)
+      if (!LevelContainsPlayer())
        Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
       else
       {
@@ -8949,6 +9322,8 @@ static void HandleControlButtons(struct GadgetInfo *gi)
        CopyPlayfield(level.field, FieldBackup);
        CopyPlayfield(Feld, level.field);
 
+       CopyNativeLevel_RND_to_Native(&level);
+
        UnmapLevelEditorGadgets();
        UndrawSpecialEditorDoor();
 
@@ -9342,9 +9717,12 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
       element = group_element_info.element[sx];
     else if (id == GADGET_ID_RANDOM_BACKGROUND)
       element = random_placement_background_element;
-    else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
-            id <= GADGET_ID_ELEMENT_CONTENT_7)
-      element = level.yamyam_content[id - GADGET_ID_ELEMENT_CONTENT_0][sx][sy];
+    else if (id >= GADGET_ID_YAMYAM_CONTENT_0 &&
+            id <= GADGET_ID_YAMYAM_CONTENT_7)
+      element = level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0][sx][sy];
+    else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
+            id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
+      element = level.ball_content[id -GADGET_ID_MAGIC_BALL_CONTENT_0][sx][sy];
 
     strncpy(infotext, getElementInfoText(element), max_infotext_len);
   }
@@ -9370,10 +9748,14 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
       sprintf(infotext, "Group element position: %d", sx + 1);
     else if (id == GADGET_ID_RANDOM_BACKGROUND)
       strcpy(infotext, "Random placement background");
-    else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
-            id <= GADGET_ID_ELEMENT_CONTENT_7)
+    else if (id >= GADGET_ID_YAMYAM_CONTENT_0 &&
+            id <= GADGET_ID_YAMYAM_CONTENT_7)
+      sprintf(infotext, "Content area %d position: %d, %d",
+             id - GADGET_ID_YAMYAM_CONTENT_0 + 1, sx, sy);
+    else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
+            id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
       sprintf(infotext, "Content area %d position: %d, %d",
-             id - GADGET_ID_ELEMENT_CONTENT_0 + 1, sx, sy);
+             id - GADGET_ID_MAGIC_BALL_CONTENT_0 + 1, sx, sy);
   }
 
   infotext[max_infotext_len] = '\0';
@@ -9386,7 +9768,7 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed)
 {
   if (!ask_if_level_has_changed ||
       !LevelChanged() ||
-      Request("Level has changed! Exit without saving ?",
+      Request("Level has changed ! Exit without saving ?",
              REQ_ASK | REQ_STAY_OPEN))
   {
 #if 1
@@ -9401,9 +9783,6 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed)
   else
   {
     CloseDoor(DOOR_CLOSE_1);
-    BlitBitmap(bitmap_db_door, bitmap_db_door,
-              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
-              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-    OpenDoor(DOOR_OPEN_1);
+    OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
   }
 }
index f1f44184b847dc13e1ccd0e2b8153fcc9cb2fd07..62617108c26776cc2fe827ff51c2b72437ed26b2 100644 (file)
 #define MAX_ELEM_X             4
 #define MAX_ELEM_Y             10
 
-extern int element_shift;
-extern int editor_element[];
-extern int elements_in_list;
-
 void CreateLevelEditorGadgets();
 void FreeLevelEditorGadgets();
 void UnmapLevelEditorGadgets();
@@ -35,5 +31,6 @@ void RequestExitLevelEditor(boolean);
 void PrintEditorElementList();
 
 void DumpBrush();
+void DumpBrush_Small();
 
 #endif
diff --git a/src/engines.h b/src/engines.h
new file mode 100644 (file)
index 0000000..54a5432
--- /dev/null
@@ -0,0 +1,31 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2004 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* engines.h                                                *
+***********************************************************/
+
+#ifndef ENGINES_H
+#define ENGINES_H
+
+#include "libgame/libgame.h"
+
+
+/* ========================================================================= */
+/* functions and definitions exported from main program to game_em           */
+/* ========================================================================= */
+
+extern void SetBitmaps_EM(Bitmap **);
+extern void UpdateEngineValues(int, int);
+extern void DrawAllGameValues(int, int, int, int, int);
+extern int getGameFrameDelay_EM(int);
+extern void PlayLevelSound_EM(int, int, int, int);
+extern void InitGraphicInfo_EM(void);
+
+#endif /* ENGINES_H */
index fdb4b6cecdb41334606fdd8669dad338f12372dc..debb368b11c0d06426fc6b00898a04af2f1b7a37 100644 (file)
@@ -53,13 +53,42 @@ int FilterMouseMotionEvents(const Event *event)
   }
 
   /* skip mouse motion events without pressed button outside level editor */
-  if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR &&
-      game_status != GAME_MODE_PLAYING)
+  if (button_status == MB_RELEASED &&
+      game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
     return 0;
   else
     return 1;
 }
 
+/* to prevent delay problems, skip mouse motion events if the very next
+   event is also a mouse motion event (and therefore effectively only
+   handling the last of a row of mouse motion events in the event queue) */
+
+boolean SkipPressedMouseMotionEvent(const Event *event)
+{
+  /* nothing to do if the current event is not a mouse motion event */
+  if (event->type != EVENT_MOTIONNOTIFY)
+    return FALSE;
+
+  /* only skip motion events with pressed button outside level editor */
+  if (button_status == MB_RELEASED ||
+      game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
+    return FALSE;
+
+  if (PendingEvent())
+  {
+    Event next_event;
+
+    PeekEvent(&next_event);
+
+    /* if next event is also a mouse motion event, skip the current one */
+    if (next_event.type == EVENT_MOTIONNOTIFY)
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
 /* this is only really needed for non-SDL targets to filter unwanted events;
    when using SDL with properly installed event filter, this function can be
    replaced with a simple "NextEvent()" call, but it doesn't hurt either */
@@ -68,9 +97,19 @@ static boolean NextValidEvent(Event *event)
 {
   while (PendingEvent())
   {
+    boolean handle_this_event = FALSE;
+
     NextEvent(event);
 
     if (FilterMouseMotionEvents(event))
+      handle_this_event = TRUE;
+
+#if 1
+    if (SkipPressedMouseMotionEvent(event))
+      handle_this_event = FALSE;
+#endif
+
+    if (handle_this_event)
       return TRUE;
   }
 
@@ -283,6 +322,11 @@ void HandleButtonEvent(ButtonEvent *event)
   else
     button_status = MB_RELEASED;
 
+#if 0
+  printf("::: button %s\n", event->type == EVENT_BUTTONPRESS ?
+       "pressed" : "released");
+#endif
+
   HandleButton(event->x, event->y, button_status);
 }
 
@@ -298,6 +342,10 @@ void HandleMotionEvent(MotionEvent *event)
 
   motion_status = TRUE;
 
+#if 0
+  printf("::: %d, %d\n", event->x, event->y);
+#endif
+
   HandleButton(event->x, event->y, button_status);
 }
 
@@ -347,6 +395,7 @@ void HandleFocusEvent(FocusChangeEvent *event)
       Delay(100);
       KeyboardAutoRepeatOffUnlessAutoplay();
     }
+
     if (old_joystick_status != -1)
       joystick.status = old_joystick_status;
   }
@@ -520,6 +569,10 @@ static void HandleKeysSpecial(Key key)
     {
       DumpBrush();
     }
+    else if (is_string_suffix(cheat_input, ":DDB"))
+    {
+      DumpBrush_Small();
+    }
   }
 }
 
@@ -873,6 +926,11 @@ void HandleKey(Key key, int key_status)
          printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
          break;
 
+       case KSYM_v:
+         printf("::: currently using game engine version %d\n",
+                game.engine_version);
+         break;
+
 #if 0
 
        case KSYM_z:
index 3d4670f0b0f76bedc515645cd3e1a7e234839bb7..93ab6bc8e1b564612179ae24109ec3be17b2684c 100644 (file)
@@ -29,7 +29,7 @@
 #define CHUNK_SIZE_NONE                -1      /* do not write chunk size    */
 #define FILE_VERS_CHUNK_SIZE   8       /* size of file version chunk */
 #define LEVEL_HEADER_SIZE      80      /* size of level file header  */
-#define LEVEL_HEADER_UNUSED    1       /* unused level header bytes  */
+#define LEVEL_HEADER_UNUSED    0       /* unused level header bytes  */
 #define LEVEL_CHUNK_CNT2_SIZE  160     /* size of level CNT2 chunk   */
 #define LEVEL_CHUNK_CNT2_UNUSED        11      /* unused CNT2 chunk bytes    */
 #define LEVEL_CHUNK_CNT3_HEADER        16      /* size of level CNT3 header  */
 #define TAPE_COOKIE_TMPL       "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x"
 #define SCORE_COOKIE           "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
 
-/* values for level file type identifier */
-#define LEVEL_FILE_TYPE_UNKNOWN                0
-#define LEVEL_FILE_TYPE_RND            1
-#define LEVEL_FILE_TYPE_BD             2
-#define LEVEL_FILE_TYPE_EM             3
-#define LEVEL_FILE_TYPE_SP             4
-#define LEVEL_FILE_TYPE_DX             5
-#define LEVEL_FILE_TYPE_SB             6
-#define LEVEL_FILE_TYPE_DC             7
-
-#define LEVEL_FILE_TYPE_RND_PACKED     (10 + LEVEL_FILE_TYPE_RND)
-#define LEVEL_FILE_TYPE_EM_PACKED      (10 + LEVEL_FILE_TYPE_EM)
-
-#define IS_SINGLE_LEVEL_FILE(x)                (x < 10)
-#define IS_PACKED_LEVEL_FILE(x)                (x > 10)
+static struct
+{
+  int filetype;
+  char *id;
+}
+filetype_id_list[] =
+{
+  { LEVEL_FILE_TYPE_RND,       "RND"   },
+  { LEVEL_FILE_TYPE_BD,                "BD"    },
+  { LEVEL_FILE_TYPE_EM,                "EM"    },
+  { LEVEL_FILE_TYPE_SP,                "SP"    },
+  { LEVEL_FILE_TYPE_DX,                "DX"    },
+  { LEVEL_FILE_TYPE_SB,                "SB"    },
+  { LEVEL_FILE_TYPE_DC,                "DC"    },
+  { -1,                                NULL    },
+};
 
 
 /* ========================================================================= */
@@ -87,11 +88,12 @@ void setElementChangePages(struct ElementInfo *ei, int change_pages)
 
 void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 {
-  int x, y;
+  int i, x, y;
 
   change->can_change = FALSE;
 
-  change->events = CE_BITMASK_DEFAULT;
+  for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+    change->has_event[i] = FALSE;
 
   change->trigger_player = CH_PLAYER_ANY;
   change->trigger_side = CH_SIDE_ANY;
@@ -127,9 +129,14 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 static void setLevelInfoToDefaults(struct LevelInfo *level)
 {
   static boolean clipboard_elements_initialized = FALSE;
-
   int i, j, x, y;
 
+  setLevelInfoToDefaults_EM();
+
+  level->native_em_level = &native_em_level;
+
+  level->game_engine_type = GAME_ENGINE_TYPE_RND;
+
   level->file_version = FILE_VERSION_ACTUAL;
   level->game_version = GAME_VERSION_ACTUAL;
 
@@ -159,18 +166,43 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->double_speed = FALSE;
   level->initial_gravity = FALSE;
   level->em_slippery_gems = FALSE;
-  level->block_last_field = FALSE;
-  level->sp_block_last_field = TRUE;
   level->instant_relocation = FALSE;
   level->can_pass_to_walkable = FALSE;
   level->grow_into_diggable = TRUE;
 
+  level->block_last_field = FALSE;     /* EM does not block by default */
+  level->sp_block_last_field = TRUE;   /* SP blocks the last field */
+
+#if 0  /* !!! THIS IS NOT A LEVEL SETTING => LOGIC MOVED TO "game.c" !!! */
+  level->block_delay = 8;              /* when blocking, block 8 frames */
+  level->sp_block_delay = 9;           /* SP indeed blocks 9 frames, not 8 */
+#endif
+
   level->can_move_into_acid_bits = ~0; /* everything can move into acid */
-  level->dont_collide_with_bits = ~0;  /* always deadly when colliding  */
+  level->dont_collide_with_bits = ~0;  /* always deadly when colliding */
 
   level->use_spring_bug = FALSE;
   level->use_step_counter = FALSE;
 
+  /* values for the new EMC elements */
+  level->android_move_time = 10;
+  level->android_clone_time = 10;
+  level->ball_random = FALSE;
+  level->ball_state_initial = FALSE;
+  level->ball_time = 10;
+  level->lenses_score = 10;
+  level->magnify_score = 10;
+  level->slurp_score = 10;
+  level->lenses_time = 10;
+  level->magnify_time = 10;
+  level->wind_direction_initial = MV_NO_MOVING;
+  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+    for (x = 0; x < 3; x++)
+      for (y = 0; y < 3; y++)
+       level->ball_content[i][x][y] = EL_EMPTY;
+  for (i = 0; i < 16; i++)
+    level->android_array[i] = FALSE;
+
   level->use_custom_template = FALSE;
 
   for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
@@ -310,6 +342,8 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
 
   level->no_valid_file = FALSE;
 
+  level->changed = FALSE;
+
   if (leveldir_current == NULL)                /* only when dumping level */
     return;
 
@@ -398,34 +432,14 @@ static int getFileTypeFromBasename(char *basename)
   return LEVEL_FILE_TYPE_UNKNOWN;
 }
 
-static char *getSingleLevelBasename(int nr, int type)
+static char *getSingleLevelBasename(int nr)
 {
   static char basename[MAX_FILENAME_LEN];
-  char *level_filename = getStringCopy(leveldir_current->level_filename);
-
-  if (level_filename == NULL)
-    level_filename = getStringCat2("%03d.", LEVELFILE_EXTENSION);
 
-  switch (type)
-  {
-    case LEVEL_FILE_TYPE_RND:
-      if (nr < 0)
-       sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
-      else
-       sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
-      break;
-
-    case LEVEL_FILE_TYPE_EM:
-      sprintf(basename, "%d", nr);
-      break;
-
-    case LEVEL_FILE_TYPE_UNKNOWN:
-    default:
-      sprintf(basename, level_filename, nr);
-      break;
-  }
-
-  free(level_filename);
+  if (nr < 0)
+    sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
+  else
+    sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
 
   return basename;
 }
@@ -468,9 +482,9 @@ static char *getPackedLevelBasename(int type)
   return basename;
 }
 
-static char *getSingleLevelFilename(int nr, int type)
+static char *getSingleLevelFilename(int nr)
 {
-  return getLevelFilenameFromBasename(getSingleLevelBasename(nr, type));
+  return getLevelFilenameFromBasename(getSingleLevelBasename(nr));
 }
 
 #if 0
@@ -482,9 +496,10 @@ static char *getPackedLevelFilename(int type)
 
 char *getDefaultLevelFilename(int nr)
 {
-  return getSingleLevelFilename(nr, LEVEL_FILE_TYPE_RND);
+  return getSingleLevelFilename(nr);
 }
 
+#if 0
 static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
                                                 int type)
 {
@@ -493,6 +508,23 @@ static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
   lfi->basename = getSingleLevelBasename(lfi->nr, lfi->type);
   lfi->filename = getLevelFilenameFromBasename(lfi->basename);
 }
+#endif
+
+static void setLevelFileInfo_FormatLevelFilename(struct LevelFileInfo *lfi,
+                                                int type, char *format, ...)
+{
+  static char basename[MAX_FILENAME_LEN];
+  va_list ap;
+
+  va_start(ap, format);
+  vsprintf(basename, format, ap);
+  va_end(ap);
+
+  lfi->type = type;
+  lfi->packed = FALSE;
+  lfi->basename = basename;
+  lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+}
 
 static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi,
                                                 int type)
@@ -503,7 +535,37 @@ static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi,
   lfi->filename = getLevelFilenameFromBasename(lfi->basename);
 }
 
-static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
+static int getFiletypeFromID(char *filetype_id)
+{
+  char *filetype_id_lower;
+  int filetype = LEVEL_FILE_TYPE_UNKNOWN;
+  int i;
+
+  if (filetype_id == NULL)
+    return LEVEL_FILE_TYPE_UNKNOWN;
+
+  filetype_id_lower = getStringToLower(filetype_id);
+
+  for (i = 0; filetype_id_list[i].id != NULL; i++)
+  {
+    char *id_lower = getStringToLower(filetype_id_list[i].id);
+    
+    if (strcmp(filetype_id_lower, id_lower) == 0)
+      filetype = filetype_id_list[i].filetype;
+
+    free(id_lower);
+
+    if (filetype != LEVEL_FILE_TYPE_UNKNOWN)
+      break;
+  }
+
+  free(filetype_id_lower);
+
+  return filetype;
+}
+
+#if 0
+static void OLD_determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
 {
   /* special case: level number is negative => check for level template file */
   if (lfi->nr < 0)
@@ -515,8 +577,11 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
 
   if (leveldir_current->level_filename != NULL)
   {
+    int filetype = getFiletypeFromID(leveldir_current->level_filetype);
+
     /* check for file name/pattern specified in "levelinfo.conf" */
-    setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
+    setLevelFileInfo_SingleLevelFilename(lfi, filetype);
+
     if (fileExists(lfi->filename))
       return;
   }
@@ -539,6 +604,79 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
   /* no known level file found -- try to use default values */
   setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
 }
+#endif
+
+static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
+{
+  int nr = lfi->nr;
+
+  /* special case: level number is negative => check for level template file */
+  if (nr < 0)
+  {
+    setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                        "template.%s", LEVELFILE_EXTENSION);
+
+    /* no fallback if template file not existing */
+    return;
+  }
+
+  /* special case: check for file name/pattern specified in "levelinfo.conf" */
+  if (leveldir_current->level_filename != NULL)
+  {
+    int filetype = getFiletypeFromID(leveldir_current->level_filetype);
+
+    setLevelFileInfo_FormatLevelFilename(lfi, filetype,
+                                        leveldir_current->level_filename, nr);
+    if (fileExists(lfi->filename))
+      return;
+  }
+
+  /* check for native Rocks'n'Diamonds level file */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                      "%03d.%s", nr, LEVELFILE_EXTENSION);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V1) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "a%c%c",
+                                      'a' + (nr / 10) % 26, '0' + nr % 10);
+  if (fileExists(lfi->filename))
+    return;
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "A%c%c",
+                                      'A' + (nr / 10) % 26, '0' + nr % 10);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V2 to V5) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%d", nr);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V6 / single mode) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02ds", nr);
+  if (fileExists(lfi->filename))
+    return;
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dS", nr);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V6 / teamwork mode) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dt", nr);
+  if (fileExists(lfi->filename))
+    return;
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dT", nr);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for various packed level file formats */
+  setLevelFileInfo_PackedLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* no known level file found -- use default values (and fail later) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                      "%03d.%s", nr, LEVELFILE_EXTENSION);
+}
 
 static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi)
 {
@@ -546,6 +684,20 @@ static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi)
     lfi->type = getFileTypeFromBasename(lfi->basename);
 }
 
+#if 1
+static void setLevelFileInfo(struct LevelFileInfo *level_file_info, int nr)
+{
+  /* always start with reliable default values */
+  setFileInfoToDefaults(level_file_info);
+
+  level_file_info->nr = nr;    /* set requested level number */
+
+  determineLevelFileInfo_Filename(level_file_info);
+  determineLevelFileInfo_Filetype(level_file_info);
+}
+
+#else
+
 static struct LevelFileInfo *getLevelFileInfo(int nr)
 {
   static struct LevelFileInfo level_file_info;
@@ -560,7 +712,7 @@ static struct LevelFileInfo *getLevelFileInfo(int nr)
 
   return &level_file_info;
 }
-
+#endif
 
 /* ------------------------------------------------------------------------- */
 /* functions for loading R'n'D level                                         */
@@ -709,6 +861,8 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
   level->can_pass_to_walkable  = (getFile8Bit(file) == 1 ? TRUE : FALSE);
   level->grow_into_diggable    = (getFile8Bit(file) == 1 ? TRUE : FALSE);
 
+  level->game_engine_type      = getFile8Bit(file);
+
   ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED);
 
   return chunk_size;
@@ -937,6 +1091,7 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
   for (i = 0; i < num_changed_custom_elements; i++)
   {
     int element = getFile16BitBE(file);
+    unsigned long event_bits;
 
     if (!IS_CUSTOM_ELEMENT(element))
     {
@@ -975,7 +1130,10 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
        element_info[element].content[x][y] =
          getMappedElement(getFile16BitBE(file));
 
-    element_info[element].change->events = getFile32BitBE(file);
+    event_bits = getFile32BitBE(file);
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (event_bits & (1 << j))
+       element_info[element].change->has_event[j] = TRUE;
 
     element_info[element].change->target_element =
       getMappedElement(getFile16BitBE(file));
@@ -1017,7 +1175,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   struct ElementInfo *ei;
   int chunk_size_expected;
   int element;
-  int i, x, y;
+  int i, j, x, y;
 
   element = getFile16BitBE(file);
 
@@ -1099,11 +1257,15 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   for (i = 0; i < ei->num_change_pages; i++)
   {
     struct ElementChangeInfo *change = &ei->change_page[i];
+    unsigned long event_bits;
 
     /* always start with reliable default values */
     setElementChangeInfoToDefaults(change);
 
-    change->events = getFile32BitBE(file);
+    event_bits = getFile32BitBE(file);
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (event_bits & (1 << j))
+       change->has_event[j] = TRUE;
 
     change->target_element = getMappedElement(getFile16BitBE(file));
 
@@ -1336,6 +1498,8 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
 /* functions for loading EM level                                            */
 /* ------------------------------------------------------------------------- */
 
+#if 0
+
 static int map_em_element_yam(int element)
 {
   switch (element)
@@ -1648,16 +1812,13 @@ static int map_em_element_field(int element)
 #define EM_LEVEL_XSIZE                 64
 #define EM_LEVEL_YSIZE                 32
 
-static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
-                                    struct LevelFileInfo *level_file_info)
+static void OLD_LoadLevelFromFileInfo_EM(struct LevelInfo *level,
+                                        struct LevelFileInfo *level_file_info)
 {
   char *filename = level_file_info->filename;
   FILE *file;
   unsigned char leveldata[EM_LEVEL_SIZE];
   unsigned char *header = &leveldata[EM_LEVEL_XSIZE * EM_LEVEL_YSIZE];
-  unsigned char code0 = 0x65;
-  unsigned char code1 = 0x11;
-  boolean level_is_crypted = FALSE;
   int nr = level_file_info->nr;
   int i, x, y;
 
@@ -1670,7 +1831,7 @@ static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
     return;
   }
 
-  for(i = 0; i < EM_LEVEL_SIZE; i++)
+  for (i = 0; i < EM_LEVEL_SIZE; i++)
     leveldata[i] = fgetc(file);
 
   fclose(file);
@@ -1681,20 +1842,20 @@ static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
   if ((leveldata[0] == 0xf1 ||
        leveldata[0] == 0xf5) && leveldata[2] == 0xe7 && leveldata[3] == 0xee)
   {
-    level_is_crypted = TRUE;
+    unsigned char code0 = 0x65;
+    unsigned char code1 = 0x11;
 
     if (leveldata[0] == 0xf5)  /* error in crypted Emerald Mine 2 levels */
       leveldata[0] = 0xf1;
-  }
 
-  if (level_is_crypted)                /* decode crypted level data */
-  {
-    for(i = 0; i < EM_LEVEL_SIZE; i++)
+    /* decode crypted level data */
+
+    for (i = 0; i < EM_LEVEL_SIZE; i++)
     {
       leveldata[i] ^= code0;
       leveldata[i] -= code1;
 
-      code0  = (code0 + 7) & 0xff;
+      code0 = (code0 + 7) & 0xff;
     }
   }
 
@@ -1727,9 +1888,9 @@ static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
 
   level->num_yamyam_contents = 4;
 
-  for(i = 0; i < level->num_yamyam_contents; i++)
-    for(y = 0; y < 3; y++)
-      for(x = 0; x < 3; x++)
+  for (i = 0; i < level->num_yamyam_contents; i++)
+    for (y = 0; y < 3; y++)
+      for (x = 0; x < 3; x++)
        level->yamyam_content[i][x][y] =
          map_em_element_yam(header[i * 9 + y * 3 + x]);
 
@@ -1757,6 +1918,231 @@ static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
   level->field[x][y] = EL_PLAYER_2;
 }
 
+#else
+
+void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
+{
+  static int ball_xy[8][2] =
+  {
+    { 0, 0 },
+    { 1, 0 },
+    { 2, 0 },
+    { 0, 1 },
+    { 2, 1 },
+    { 0, 2 },
+    { 1, 2 },
+    { 2, 2 },
+  };
+  struct LevelInfo_EM *level_em = level->native_em_level;
+  struct LEVEL *lev = level_em->lev;
+  struct PLAYER *ply1 = level_em->ply1;
+  struct PLAYER *ply2 = level_em->ply2;
+  int i, j, x, y;
+
+  lev->width  = MIN(level->fieldx, EM_MAX_CAVE_WIDTH);
+  lev->height = MIN(level->fieldy, EM_MAX_CAVE_HEIGHT);
+
+  lev->time_seconds     = level->time;
+  lev->required_initial = level->gems_needed;
+
+  lev->emerald_score   = level->score[SC_EMERALD];
+  lev->diamond_score   = level->score[SC_DIAMOND];
+  lev->alien_score     = level->score[SC_ROBOT];
+  lev->tank_score      = level->score[SC_SPACESHIP];
+  lev->bug_score       = level->score[SC_BUG];
+  lev->eater_score     = level->score[SC_YAMYAM];
+  lev->nut_score       = level->score[SC_NUT];
+  lev->dynamite_score  = level->score[SC_DYNAMITE];
+  lev->key_score       = level->score[SC_KEY];
+  lev->exit_score      = level->score[SC_TIME_BONUS];
+
+  for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
+    for (y = 0; y < 3; y++)
+      for (x = 0; x < 3; x++)
+       lev->eater_array[i][y * 3 + x] =
+         map_element_RND_to_EM(level->yamyam_content[i][x][y]);
+
+  lev->amoeba_time             = level->amoeba_speed;
+  lev->wonderwall_time_initial = level->time_magic_wall;
+  lev->wheel_time              = level->time_wheel;
+
+  lev->android_move_time       = level->android_move_time;
+  lev->android_clone_time      = level->android_clone_time;
+  lev->ball_random             = level->ball_random;
+  lev->ball_state_initial      = level->ball_state_initial;
+  lev->ball_time               = level->ball_time;
+
+  lev->lenses_score            = level->lenses_score;
+  lev->magnify_score           = level->magnify_score;
+  lev->slurp_score             = level->slurp_score;
+
+  lev->lenses_time             = level->lenses_time;
+  lev->magnify_time            = level->magnify_time;
+  lev->wind_direction_initial  = level->wind_direction_initial;
+
+  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+    for (j = 0; j < 8; j++)
+      lev->ball_array[i][j] =
+       map_element_RND_to_EM(level->
+                             ball_content[i][ball_xy[j][0]][ball_xy[j][1]]);
+
+  for (i = 0; i < 16; i++)
+    lev->android_array[i] = FALSE;     /* !!! YET TO COME !!! */
+
+  /* first fill the complete playfield with the default border element */
+  for (y = 0; y < EM_MAX_CAVE_HEIGHT; y++)
+    for (x = 0; x < EM_MAX_CAVE_WIDTH; x++)
+      level_em->cave[x][y] = ZBORDER;
+
+  /* then copy the real level contents from level file into the playfield */
+  for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++)
+  {
+    int new_element = map_element_RND_to_EM(level->field[x][y]);
+
+    if (level->field[x][y] == EL_AMOEBA_DEAD)
+      new_element = map_element_RND_to_EM(EL_AMOEBA_WET);
+
+    level_em->cave[x + 1][y + 1] = new_element;
+  }
+
+  ply1->x_initial = 0;
+  ply1->y_initial = 0;
+
+  ply2->x_initial = 0;
+  ply2->y_initial = 0;
+
+  /* initialize player positions and delete players from the playfield */
+  for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++)
+  {
+    if (level->field[x][y] == EL_PLAYER_1)
+    {
+      ply1->x_initial = x + 1;
+      ply1->y_initial = y + 1;
+      level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY);
+    }
+    else if (level->field[x][y] == EL_PLAYER_2)
+    {
+      ply2->x_initial = x + 1;
+      ply2->y_initial = y + 1;
+      level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY);
+    }
+  }
+}
+
+void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
+{
+  static int ball_xy[8][2] =
+  {
+    { 0, 0 },
+    { 1, 0 },
+    { 2, 0 },
+    { 0, 1 },
+    { 2, 1 },
+    { 0, 2 },
+    { 1, 2 },
+    { 2, 2 },
+  };
+  struct LevelInfo_EM *level_em = level->native_em_level;
+  struct LEVEL *lev = level_em->lev;
+  struct PLAYER *ply1 = level_em->ply1;
+  struct PLAYER *ply2 = level_em->ply2;
+  int i, j, x, y;
+
+  level->fieldx = MIN(lev->width,  MAX_LEV_FIELDX);
+  level->fieldy = MIN(lev->height, MAX_LEV_FIELDY);
+
+  level->time        = lev->time_seconds;
+  level->gems_needed = lev->required_initial;
+
+  sprintf(level->name, "Level %d", level->file_info.nr);
+
+  level->score[SC_EMERALD]     = lev->emerald_score;
+  level->score[SC_DIAMOND]     = lev->diamond_score;
+  level->score[SC_ROBOT]       = lev->alien_score;
+  level->score[SC_SPACESHIP]   = lev->tank_score;
+  level->score[SC_BUG]         = lev->bug_score;
+  level->score[SC_YAMYAM]      = lev->eater_score;
+  level->score[SC_NUT]         = lev->nut_score;
+  level->score[SC_DYNAMITE]    = lev->dynamite_score;
+  level->score[SC_KEY]         = lev->key_score;
+  level->score[SC_TIME_BONUS]  = lev->exit_score;
+
+  level->num_yamyam_contents = MAX_ELEMENT_CONTENTS;
+
+  for (i = 0; i < level->num_yamyam_contents; i++)
+    for (y = 0; y < 3; y++)
+      for (x = 0; x < 3; x++)
+       level->yamyam_content[i][x][y] =
+         map_element_EM_to_RND(lev->eater_array[i][y * 3 + x]);
+
+  level->amoeba_speed          = lev->amoeba_time;
+  level->time_magic_wall       = lev->wonderwall_time_initial;
+  level->time_wheel            = lev->wheel_time;
+
+  level->android_move_time     = lev->android_move_time;
+  level->android_clone_time    = lev->android_clone_time;
+  level->ball_random           = lev->ball_random;
+  level->ball_state_initial    = lev->ball_state_initial;
+  level->ball_time             = lev->ball_time;
+
+  level->lenses_score          = lev->lenses_score;
+  level->magnify_score         = lev->magnify_score;
+  level->slurp_score           = lev->slurp_score;
+
+  level->lenses_time           = lev->lenses_time;
+  level->magnify_time          = lev->magnify_time;
+  level->wind_direction_initial        = lev->wind_direction_initial;
+
+  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+    for (j = 0; j < 8; j++)
+      level->ball_content[i][ball_xy[j][0]][ball_xy[j][1]] =
+       map_element_EM_to_RND(lev->ball_array[i][j]);
+
+  for (i = 0; i < 16; i++)
+    level->android_array[i] = FALSE;   /* !!! YET TO COME !!! */
+
+  /* convert the playfield (some elements need special treatment) */
+  for (y = 0; y < level->fieldy; y++) for (x = 0; x < level->fieldx; x++)
+  {
+    int new_element = map_element_EM_to_RND(level_em->cave[x + 1][y + 1]);
+
+    if (new_element == EL_AMOEBA_WET && level->amoeba_speed == 0)
+      new_element = EL_AMOEBA_DEAD;
+
+    level->field[x][y] = new_element;
+  }
+
+  /* in case of both players set to the same field, use the first player */
+  level->field[ply2->x_initial - 1][ply2->y_initial - 1] = EL_PLAYER_2;
+  level->field[ply1->x_initial - 1][ply1->y_initial - 1] = EL_PLAYER_1;
+
+#if 0
+  printf("::: native Emerald Mine file version: %d\n", level_em->file_version);
+#endif
+}
+
+static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
+                                    struct LevelFileInfo *level_file_info)
+{
+  if (!LoadNativeLevel_EM(level_file_info->filename))
+    level->no_valid_file = TRUE;
+}
+
+#endif
+
+void CopyNativeLevel_RND_to_Native(struct LevelInfo *level)
+{
+  if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
+    CopyNativeLevel_RND_to_EM(level);
+}
+
+void CopyNativeLevel_Native_to_RND(struct LevelInfo *level)
+{
+  if (level->game_engine_type == GAME_ENGINE_TYPE_EM)
+    CopyNativeLevel_EM_to_RND(level);
+}
+
+
 /* ------------------------------------------------------------------------- */
 /* functions for loading SP level                                            */
 /* ------------------------------------------------------------------------- */
@@ -1908,13 +2294,13 @@ static void LoadLevelFromFileStream_SP(FILE *file, struct LevelInfo *level,
   level->time_wheel = 0;
   level->amoeba_content = EL_EMPTY;
 
-  for(i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
+  for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
     level->score[i] = 0;               /* !!! CORRECT THIS !!! */
 
   /* there are no yamyams in supaplex levels */
-  for(i = 0; i < level->num_yamyam_contents; i++)
-    for(y = 0; y < 3; y++)
-      for(x = 0; x < 3; x++)
+  for (i = 0; i < level->num_yamyam_contents; i++)
+    for (y = 0; y < 3; y++)
+      for (x = 0; x < 3; x++)
        level->yamyam_content[i][x][y] = EL_EMPTY;
 }
 
@@ -2115,6 +2501,7 @@ void LoadLevelFromFileInfo(struct LevelInfo *level,
 
     case LEVEL_FILE_TYPE_EM:
       LoadLevelFromFileInfo_EM(level, level_file_info);
+      level->game_engine_type = GAME_ENGINE_TYPE_EM;
       break;
 
     case LEVEL_FILE_TYPE_SP:
@@ -2125,6 +2512,18 @@ void LoadLevelFromFileInfo(struct LevelInfo *level,
       LoadLevelFromFileInfo_RND(level, level_file_info);
       break;
   }
+
+  /* if level file is invalid, restore level structure to default values */
+  if (level->no_valid_file)
+    setLevelInfoToDefaults(level);
+
+  if (level->game_engine_type == GAME_ENGINE_TYPE_UNKNOWN)
+    level->game_engine_type = GAME_ENGINE_TYPE_RND;
+
+  if (level_file_info->type == LEVEL_FILE_TYPE_RND)
+    CopyNativeLevel_RND_to_Native(level);
+  else
+    CopyNativeLevel_Native_to_RND(level);
 }
 
 void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
@@ -2197,13 +2596,18 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
     if (level->game_version == VERSION_IDENT(2,0,1,0))
       level->em_slippery_gems = TRUE;
 
+    /* springs could be pushed over pits before (pre-release version) 2.2.0 */
     if (level->game_version < VERSION_IDENT(2,2,0,0))
       level->use_spring_bug = TRUE;
 
+    /* only few elements were able to actively move into acid before 3.1.0 */
+    /* trigger settings did not exist before 3.1.0; set to default "any" */
     if (level->game_version < VERSION_IDENT(3,1,0,0))
     {
       int i, j;
 
+      /* correct "can move into acid" settings (all zero in old levels) */
+
       level->can_move_into_acid_bits = 0; /* nothing can move into acid */
       level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */
 
@@ -2215,6 +2619,8 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
        SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, TRUE);
 
+      /* correct trigger settings (stored as zero == "none" in old levels) */
+
       for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
       {
        int element = EL_CUSTOM_START + i;
@@ -2229,8 +2635,28 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
        }
       }
     }
+
+#if 0  /* !!! MOVED TO "game.c", BECAUSE CAN CHANGE INSIDE LEVEL EDITOR !!! */
+#if 1  /* USE_NEW_BLOCK_STYLE */
+    /* blocking the last field when moving was corrected in version 3.1.1 */
+    if (level->game_version < VERSION_IDENT(3,1,1,0))
+    {
+#if 0
+      printf("::: %d\n", level->block_last_field);
+#endif
+
+      /* even "not blocking" was blocking the last field for one frame */
+      level->block_delay    = (level->block_last_field    ? 7 : 1);
+      level->sp_block_delay = (level->sp_block_last_field ? 7 : 1);
+
+      level->block_last_field = TRUE;
+      level->sp_block_last_field = TRUE;
+    }
+#endif
+#endif
+
   }
-  else
+  else         /* always use the latest game engine version */
   {
 #if 0
     printf("\n::: ALWAYS USE LATEST ENGINE FOR THIS LEVEL: [%d] '%s'\n",
@@ -2295,7 +2721,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
       }
 
       /* order of checking and copying events to be mapped is important */
-      for (j = CE_OTHER_GETS_COLLECTED; j >= CE_HITTING_SOMETHING; j--)
+      for (j = CE_PLAYER_COLLECTS_X; j >= CE_HITTING_SOMETHING; j--)
       {
        if (HAS_CHANGE_EVENT(element, j - 1))
        {
@@ -2352,6 +2778,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
   }
 
   /* initialize "can_explode" field for old levels which did not store this */
+  /* !!! CHECK THIS -- "<= 3,1,0,0" IS PROBABLY WRONG !!! */
   if (level->game_version <= VERSION_IDENT(3,1,0,0))
   {
     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -2367,6 +2794,22 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
     }
   }
 
+  /* correct previously hard-coded move delay values for maze runner style */
+  if (level->game_version < VERSION_IDENT(3,1,1,0))
+  {
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+    {
+      int element = EL_CUSTOM_START + i;
+
+      if (element_info[element].move_pattern & MV_MAZE_RUNNER_STYLE)
+      {
+       /* previously hard-coded and therefore ignored */
+       element_info[element].move_delay_fixed = 9;
+       element_info[element].move_delay_random = 0;
+      }
+    }
+  }
+
 #if 0
   /* set default push delay values (corrected since version 3.0.7-1) */
   if (level->game_version < VERSION_IDENT(3,0,7,1))
@@ -2459,6 +2902,16 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
 
 void LoadLevelTemplate(int nr)
 {
+#if 1
+  char *filename;
+
+  setLevelFileInfo(&level_template.file_info, nr);
+  filename = level_template.file_info.filename;
+
+  LoadLevelFromFileInfo(&level_template, &level_template.file_info);
+
+#else
+
 #if 1
   struct LevelFileInfo *level_file_info = getLevelFileInfo(nr);
   char *filename = level_file_info->filename;
@@ -2469,15 +2922,31 @@ void LoadLevelTemplate(int nr)
 
   LoadLevelFromFilename_RND(&level_template, filename);
 #endif
+#endif
 
+#if 1
+  LoadLevel_InitVersion(&level_template, filename);
+  LoadLevel_InitElements(&level_template, filename);
+#else
   LoadLevel_InitVersion(&level, filename);
   LoadLevel_InitElements(&level, filename);
+#endif
 
   ActivateLevelTemplate();
 }
 
 void LoadLevel(int nr)
 {
+#if 1
+  char *filename;
+
+  setLevelFileInfo(&level.file_info, nr);
+  filename = level.file_info.filename;
+
+  LoadLevelFromFileInfo(&level, &level.file_info);
+
+#else
+
 #if 1
   struct LevelFileInfo *level_file_info = getLevelFileInfo(nr);
   char *filename = level_file_info->filename;
@@ -2487,6 +2956,7 @@ void LoadLevel(int nr)
   char *filename = getLevelFilename(nr);
 
   LoadLevelFromFilename_RND(&level, filename);
+#endif
 #endif
 
   if (level.use_custom_template)
@@ -2552,6 +3022,8 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
   putFile8Bit(file, (level->can_pass_to_walkable ? 1 : 0));
   putFile8Bit(file, (level->grow_into_diggable ? 1 : 0));
 
+  putFile8Bit(file, level->game_engine_type);
+
   WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED);
 }
 
@@ -2806,7 +3278,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
 static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
-  int i, x, y;
+  int i, j, x, y;
 
   putFile16BitBE(file, element);
 
@@ -2868,8 +3340,13 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
   for (i = 0; i < ei->num_change_pages; i++)
   {
     struct ElementChangeInfo *change = &ei->change_page[i];
+    unsigned long event_bits = 0;
 
-    putFile32BitBE(file, change->events);
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (change->has_event[j])
+       event_bits |= (1 << j);
+
+    putFile32BitBE(file, event_bits);
 
     putFile16BitBE(file, change->target_element);
 
@@ -3218,7 +3695,7 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
 
   for (i = 0; i < tape->length; i++)
   {
-    if (i >= MAX_TAPELEN)
+    if (i >= MAX_TAPE_LEN)
       break;
 
     for (j = 0; j < MAX_PLAYERS; j++)
@@ -3507,7 +3984,7 @@ void SaveTape(int nr)
   InitTapeDirectory(leveldir_current->subdir);
 
   /* if a tape still exists, ask to overwrite it */
-  if (access(filename, F_OK) == 0)
+  if (fileExists(filename))
   {
     new_tape = FALSE;
     if (!Request("Replace old tape ?", REQ_ASK))
@@ -3553,7 +4030,7 @@ void SaveTape(int nr)
   tape.changed = FALSE;
 
   if (new_tape)
-    Request("tape saved !", REQ_CONFIRM);
+    Request("Tape saved !", REQ_CONFIRM);
 }
 
 void DumpTape(struct TapeInfo *tape)
@@ -3579,12 +4056,14 @@ void DumpTape(struct TapeInfo *tape)
   printf_line("-", 79);
   printf("Tape of Level %03d (file version %08d, game version %08d)\n",
         tape->level_nr, tape->file_version, tape->game_version);
+  printf("                  (effective engine version %08d)\n",
+        tape->engine_version);
   printf("Level series identifier: '%s'\n", tape->level_identifier);
   printf_line("-", 79);
 
   for (i = 0; i < tape->length; i++)
   {
-    if (i >= MAX_TAPELEN)
+    if (i >= MAX_TAPE_LEN)
       break;
 
     printf("%03d: ", i);
@@ -3715,33 +4194,35 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_QUICK_DOORS                        10
 #define SETUP_TOKEN_TEAM_MODE                  11
 #define SETUP_TOKEN_HANDICAP                   12
-#define SETUP_TOKEN_TIME_LIMIT                 13
-#define SETUP_TOKEN_FULLSCREEN                 14
-#define SETUP_TOKEN_ASK_ON_ESCAPE              15
-#define SETUP_TOKEN_GRAPHICS_SET               16
-#define SETUP_TOKEN_SOUNDS_SET                 17
-#define SETUP_TOKEN_MUSIC_SET                  18
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    19
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      20
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       21
-
-#define NUM_GLOBAL_SETUP_TOKENS                        22
+#define SETUP_TOKEN_SKIP_LEVELS                        13
+#define SETUP_TOKEN_TIME_LIMIT                 14
+#define SETUP_TOKEN_FULLSCREEN                 15
+#define SETUP_TOKEN_ASK_ON_ESCAPE              16
+#define SETUP_TOKEN_GRAPHICS_SET               17
+#define SETUP_TOKEN_SOUNDS_SET                 18
+#define SETUP_TOKEN_MUSIC_SET                  19
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    20
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      21
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       22
+
+#define NUM_GLOBAL_SETUP_TOKENS                        23
 
 /* editor setup */
 #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH      0
 #define SETUP_TOKEN_EDITOR_EL_EMERALD_MINE     1
-#define SETUP_TOKEN_EDITOR_EL_MORE             2
-#define SETUP_TOKEN_EDITOR_EL_SOKOBAN          3
-#define SETUP_TOKEN_EDITOR_EL_SUPAPLEX         4
-#define SETUP_TOKEN_EDITOR_EL_DIAMOND_CAVES    5
-#define SETUP_TOKEN_EDITOR_EL_DX_BOULDERDASH   6
-#define SETUP_TOKEN_EDITOR_EL_CHARS            7
-#define SETUP_TOKEN_EDITOR_EL_CUSTOM           8
-#define SETUP_TOKEN_EDITOR_EL_CUSTOM_MORE      9
-#define SETUP_TOKEN_EDITOR_EL_HEADLINES                10
-#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED     11
-
-#define NUM_EDITOR_SETUP_TOKENS                        12
+#define SETUP_TOKEN_EDITOR_EL_EMERALD_MINE_CLUB        2
+#define SETUP_TOKEN_EDITOR_EL_MORE             3
+#define SETUP_TOKEN_EDITOR_EL_SOKOBAN          4
+#define SETUP_TOKEN_EDITOR_EL_SUPAPLEX         5
+#define SETUP_TOKEN_EDITOR_EL_DIAMOND_CAVES    6
+#define SETUP_TOKEN_EDITOR_EL_DX_BOULDERDASH   7
+#define SETUP_TOKEN_EDITOR_EL_CHARS            8
+#define SETUP_TOKEN_EDITOR_EL_CUSTOM           9
+#define SETUP_TOKEN_EDITOR_EL_CUSTOM_MORE      10
+#define SETUP_TOKEN_EDITOR_EL_HEADLINES                11
+#define SETUP_TOKEN_EDITOR_EL_USER_DEFINED     12
+
+#define NUM_EDITOR_SETUP_TOKENS                        13
 
 /* shortcut setup */
 #define SETUP_TOKEN_SHORTCUT_SAVE_GAME         0
@@ -3804,6 +4285,7 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_SWITCH, &si.quick_doors,      "quick_doors"                   },
   { TYPE_SWITCH, &si.team_mode,                "team_mode"                     },
   { TYPE_SWITCH, &si.handicap,         "handicap"                      },
+  { TYPE_SWITCH, &si.skip_levels,      "skip_levels"                   },
   { TYPE_SWITCH, &si.time_limit,       "time_limit"                    },
   { TYPE_SWITCH, &si.fullscreen,       "fullscreen"                    },
   { TYPE_SWITCH, &si.ask_on_escape,    "ask_on_escape"                 },
@@ -3819,6 +4301,7 @@ static struct TokenInfo editor_setup_tokens[] =
 {
   { TYPE_SWITCH, &sei.el_boulderdash,  "editor.el_boulderdash"         },
   { TYPE_SWITCH, &sei.el_emerald_mine, "editor.el_emerald_mine"        },
+  { TYPE_SWITCH, &sei.el_emerald_mine_club,"editor.el_emerald_mine_club"},
   { TYPE_SWITCH, &sei.el_more,         "editor.el_more"                },
   { TYPE_SWITCH, &sei.el_sokoban,      "editor.el_sokoban"             },
   { TYPE_SWITCH, &sei.el_supaplex,     "editor.el_supaplex"            },
@@ -3904,6 +4387,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->quick_doors = FALSE;
   si->team_mode = FALSE;
   si->handicap = TRUE;
+  si->skip_levels = TRUE;
   si->time_limit = TRUE;
   si->fullscreen = FALSE;
   si->ask_on_escape = TRUE;
@@ -3915,16 +4399,17 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->override_level_sounds = FALSE;
   si->override_level_music = FALSE;
 
-  si->editor.el_boulderdash = TRUE;
-  si->editor.el_emerald_mine = TRUE;
-  si->editor.el_more = TRUE;
-  si->editor.el_sokoban = TRUE;
-  si->editor.el_supaplex = TRUE;
-  si->editor.el_diamond_caves = TRUE;
-  si->editor.el_dx_boulderdash = TRUE;
-  si->editor.el_chars = TRUE;
-  si->editor.el_custom = TRUE;
-  si->editor.el_custom_more = FALSE;
+  si->editor.el_boulderdash       = TRUE;
+  si->editor.el_emerald_mine      = TRUE;
+  si->editor.el_emerald_mine_club = TRUE;
+  si->editor.el_more              = TRUE;
+  si->editor.el_sokoban           = TRUE;
+  si->editor.el_supaplex          = TRUE;
+  si->editor.el_diamond_caves     = TRUE;
+  si->editor.el_dx_boulderdash    = TRUE;
+  si->editor.el_chars             = TRUE;
+  si->editor.el_custom            = TRUE;
+  si->editor.el_custom_more       = FALSE;
 
   si->editor.el_headlines = TRUE;
   si->editor.el_user_defined = FALSE;
@@ -4231,7 +4716,19 @@ void LoadUserDefinedEditorElementList(int **elements, int *num_elements)
   {
     char *value = getHashEntry(element_hash, list->token);
 
-    if (value)
+    if (value == NULL)         /* try to find obsolete token mapping */
+    {
+      char *mapped_token = get_mapped_token(list->token);
+
+      if (mapped_token != NULL)
+      {
+       value = getHashEntry(element_hash, mapped_token);
+
+       free(mapped_token);
+      }
+    }
+
+    if (value != NULL)
     {
       (*elements)[(*num_elements)++] = atoi(value);
     }
index 1dffbe610ef77a0af56582303f241aab4d088e72..9a0cf0ff04b476086d101b065db3ffcc7d830de0 100644 (file)
 
 #include "main.h"
 
+
+#define LEVEL_PACKED_START             100
+#define PACKED_LEVELS(x)               (LEVEL_PACKED_START + x)
+
+#define LEVEL_FILE_TYPE_RND_PACKED     PACKED_LEVELS(LEVEL_FILE_TYPE_RND)
+#define LEVEL_FILE_TYPE_EM_PACKED      PACKED_LEVELS(LEVEL_FILE_TYPE_EM)
+
+#define IS_SINGLE_LEVEL_FILE(x)                (x < LEVEL_PACKED_START)
+#define IS_PACKED_LEVEL_FILE(x)                (x > LEVEL_PACKED_START)
+
+
 void setElementChangePages(struct ElementInfo *, int);
 void setElementChangeInfoToDefaults(struct ElementChangeInfo *);
 
@@ -28,6 +39,9 @@ void SaveLevel(int);
 void SaveLevelTemplate();
 void DumpLevel(struct LevelInfo *);
 
+void CopyNativeLevel_RND_to_Native(struct LevelInfo *);
+void CopyNativeLevel_Native_to_RND(struct LevelInfo *);
+
 void LoadTapeFromFilename(char *);
 void LoadTape(int);
 void LoadSolutionTape(int);
index 762035dc5656bc5479fc3158d263620b0675cb1c..b0d7ec6bfd1a670820bce99d0111fd67b8c7db58 100644 (file)
 /* EXPERIMENTAL STUFF */
 #define USE_NEW_AMOEBA_CODE    FALSE
 
+/* EXPERIMENTAL STUFF */
+#define USE_NEW_STUFF                  (TRUE                           * 1)
+
+#define USE_NEW_MOVE_STYLE             (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_NEW_MOVE_DELAY             (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_NEW_PUSH_DELAY             (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_NEW_BLOCK_STYLE            (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_NEW_SP_SLIPPERY            (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_NEW_RANDOMIZE              (TRUE   * USE_NEW_STUFF         * 1)
+
+#define USE_CAN_MOVE_NOT_MOVING                (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_PREVIOUS_MOVE_DIR          (TRUE   * USE_NEW_STUFF         * 1)
+
+#define USE_PUSH_BUGFIX                        (TRUE   * USE_NEW_STUFF         * 1)
+#if 0
+#define USE_BLOCK_DELAY_BUGFIX         (TRUE   * USE_NEW_STUFF         * 1)
+#endif
+#define USE_GRAVITY_BUGFIX_NEW         (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_GRAVITY_BUGFIX_OLD         (TRUE   * USE_NEW_STUFF         * 0)
+
+#define USE_PENGUIN_COLLECT_BUGFIX     (TRUE   * USE_NEW_STUFF         * 1)
+
+#define USE_IMPACT_BUGFIX              (TRUE   * USE_NEW_STUFF         * 1)
+
+#define USE_HITTING_SOMETHING_BUGFIX   (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_HIT_BY_SOMETHING_BUGFIX    (TRUE   * USE_NEW_STUFF         * 1)
+
+#define USE_DROP_BUGFIX                        (TRUE   * USE_NEW_STUFF         * 1)
+
+#define USE_CHANGE_TO_TRIGGERED                (TRUE   * USE_NEW_STUFF         * 1)
+
+
 /* for DigField() */
 #define DF_NO_PUSH             0
 #define DF_DIG                 1
 
 /* forward declaration for internal use */
 
+static void AdvanceFrameAndPlayerCounters(int);
+
 static boolean MovePlayerOneStep(struct PlayerInfo *, int, int, int, int);
 static boolean MovePlayer(struct PlayerInfo *, int, int);
 static void ScrollPlayer(struct PlayerInfo *, int);
@@ -647,10 +681,9 @@ access_direction_list[] =
   { EL_UNDEFINED,                      MV_NO_MOVING                         }
 };
 
-static unsigned long trigger_events[MAX_NUM_ELEMENTS];
+static boolean trigger_events[MAX_NUM_ELEMENTS][NUM_CHANGE_EVENTS];
 
-#define IS_AUTO_CHANGING(e)    (element_info[e].change_events & \
-                                CH_EVENT_BIT(CE_DELAY))
+#define IS_AUTO_CHANGING(e)    (element_info[e].has_change_event[CE_DELAY])
 #define IS_JUST_CHANGING(x, y) (ChangeDelay[x][y] != 0)
 #define IS_CHANGING(x, y)      (IS_AUTO_CHANGING(Feld[x][y]) || \
                                 IS_JUST_CHANGING(x, y))
@@ -761,6 +794,65 @@ static void InitPlayerField(int x, int y, int element, boolean init_game)
                                level.sp_block_last_field :
                                level.block_last_field);
 
+#if USE_NEW_BLOCK_STYLE
+#if 1
+
+    /* ---------- initialize player's last field block delay --------------- */
+
+    /* always start with reliable default value (no adjustment needed) */
+    player->block_delay_adjustment = 0;
+
+    /* special case 1: in Supaplex, Murphy blocks last field one more frame */
+    if (player->block_last_field && element == EL_SP_MURPHY)
+      player->block_delay_adjustment = 1;
+
+    /* special case 2: in game engines before 3.1.1, blocking was different */
+    if (game.use_block_last_field_bug)
+      player->block_delay_adjustment = (player->block_last_field ? -1 : 1);
+
+#if 0
+    /* blocking the last field when moving was corrected in version 3.1.1 */
+    if (game.use_block_last_field_bug)
+    {
+      /* even "not blocking" was blocking the last field for one frame */
+      level.block_delay    = (level.block_last_field    ? 7 : 1);
+      level.sp_block_delay = (level.sp_block_last_field ? 7 : 1);
+
+      level.block_last_field = TRUE;
+      level.sp_block_last_field = TRUE;
+    }
+#endif
+
+#if 0  /* !!! THIS IS NOT A LEVEL SETTING => REMOVED !!! */
+    level.block_delay = 8;             /* when blocking, block 8 frames */
+    level.sp_block_delay = 9;          /* SP indeed blocks 9 frames, not 8 */
+#endif
+
+#if 0
+    printf("::: %d, %d\n", level.block_delay, level.sp_block_delay);
+#endif
+
+#else
+
+#if 1
+    player->block_delay = (player->block_last_field ?
+                          (element == EL_SP_MURPHY ?
+                           level.sp_block_delay :
+                           level.block_delay) : 0);
+#else
+    player->block_delay = (element == EL_SP_MURPHY ?
+                          (player->block_last_field ? 7 : 1) :
+                          (player->block_last_field ? 7 : 1));
+#endif
+
+#endif
+
+#if 0
+    printf("::: block_last_field == %d, block_delay = %d\n",
+          player->block_last_field, player->block_delay);
+#endif
+#endif
+
     if (!options.network || player->connected)
     {
       player->active = TRUE;
@@ -1030,12 +1122,13 @@ inline void DrawGameValue_Dynamite(int value)
   DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
 }
 
-inline void DrawGameValue_Keys(struct PlayerInfo *player)
+inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
 {
   int i;
 
-  for (i = 0; i < MAX_KEYS; i++)
-    if (player->key[i])
+  /* currently only 4 of 8 possible keys are displayed */
+  for (i = 0; i < STD_NUM_KEYS; i++)
+    if (key[i])
       DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
                         el2edimg(EL_KEY_1 + i));
 }
@@ -1077,19 +1170,45 @@ inline void DrawGameValue_Level(int value)
   }
 }
 
-void DrawGameDoorValues()
+void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
+                      int key_bits)
 {
+  int key[MAX_NUM_KEYS];
   int i;
 
+  for (i = 0; i < MAX_NUM_KEYS; i++)
+    key[i] = key_bits & (1 << i);
+
   DrawGameValue_Level(level_nr);
 
-  for (i = 0; i < MAX_PLAYERS; i++)
-    DrawGameValue_Keys(&stored_player[i]);
+  DrawGameValue_Emeralds(emeralds);
+  DrawGameValue_Dynamite(dynamite);
+  DrawGameValue_Score(score);
+  DrawGameValue_Time(time);
+
+  DrawGameValue_Keys(key);
+}
+
+void DrawGameDoorValues()
+{
+  int i;
+
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    DrawGameDoorValues_EM();
+
+    return;
+  }
+
+  DrawGameValue_Level(level_nr);
 
   DrawGameValue_Emeralds(local_player->gems_still_needed);
   DrawGameValue_Dynamite(local_player->inventory_size);
   DrawGameValue_Score(local_player->score);
   DrawGameValue_Time(TimeLeft);
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    DrawGameValue_Keys(stored_player[i].key);
 }
 
 static void resolve_group_element(int group_element, int recursion_depth)
@@ -1158,12 +1277,80 @@ static void resolve_group_element(int group_element, int recursion_depth)
 
 static void InitGameEngine()
 {
-  int i, j, k;
+  int i, j, k, l;
 
   /* set game engine from tape file when re-playing, else from level file */
   game.engine_version = (tape.playing ? tape.engine_version :
                         level.game_version);
 
+  /* ---------------------------------------------------------------------- */
+  /* set flags for bugs and changes according to active game engine version */
+  /* ---------------------------------------------------------------------- */
+
+  /*
+    Summary of bugfix/change:
+    Fixed handling for custom elements that change when pushed by the player.
+
+    Fixed/changed in version:
+    3.1.0
+
+    Description:
+    Before 3.1.0, custom elements that "change when pushing" changed directly
+    after the player started pushing them (until then handled in "DigField()").
+    Since 3.1.0, these custom elements are not changed until the "pushing"
+    move of the element is finished (now handled in "ContinueMoving()").
+
+    Affected levels/tapes:
+    The first condition is generally needed for all levels/tapes before version
+    3.1.0, which might use the old behaviour before it was changed; known tapes
+    that are affected are some tapes from the level set "Walpurgis Gardens" by
+    Jamie Cullen.
+    The second condition is an exception from the above case and is needed for
+    the special case of tapes recorded with game (not engine!) version 3.1.0 or
+    above (including some development versions of 3.1.0), but before it was
+    known that this change would break tapes like the above and was fixed in
+    3.1.1, so that the changed behaviour was active although the engine version
+    while recording maybe was before 3.1.0. There is at least one tape that is
+    affected by this exception, which is the tape for the one-level set "Bug
+    Machine" by Juergen Bonhagen.
+  */
+
+  game.use_change_when_pushing_bug =
+    (game.engine_version < VERSION_IDENT(3,1,0,0) &&
+     !(tape.playing &&
+       tape.game_version >= VERSION_IDENT(3,1,0,0) &&
+       tape.game_version <  VERSION_IDENT(3,1,1,0)));
+
+  /*
+    Summary of bugfix/change:
+    Fixed handling for blocking the field the player leaves when moving.
+
+    Fixed/changed in version:
+    3.1.1
+
+    Description:
+    Before 3.1.1, when "block last field when moving" was enabled, the field
+    the player is leaving when moving was blocked for the time of the move,
+    and was directly unblocked afterwards. This resulted in the last field
+    being blocked for exactly one less than the number of frames of one player
+    move. Additionally, even when blocking was disabled, the last field was
+    blocked for exactly one frame.
+    Since 3.1.1, due to changes in player movement handling, the last field
+    is not blocked at all when blocking is disabled. When blocking is enabled,
+    the last field is blocked for exactly the number of frames of one player
+    move. Additionally, if the player is Murphy, the hero of Supaplex, the
+    last field is blocked for exactly one more than the number of frames of
+    one player move.
+
+    Affected levels/tapes:
+    (!!! yet to be determined -- probably many !!!)
+  */
+
+  game.use_block_last_field_bug =
+    (game.engine_version < VERSION_IDENT(3,1,1,0));
+
+  /* ---------------------------------------------------------------------- */
+
   /* dynamically adjust element properties according to game engine version */
   InitElementPropertiesEngine(game.engine_version);
 
@@ -1186,6 +1373,15 @@ static void InitGameEngine()
 
   /* ---------- initialize player's initial move delay --------------------- */
 
+#if USE_NEW_MOVE_DELAY
+  /* dynamically adjust player properties according to level information */
+  game.initial_move_delay_value =
+    (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+
+  /* dynamically adjust player properties according to game engine version */
+  game.initial_move_delay = (game.engine_version <= VERSION_IDENT(2,0,1,0) ?
+                            game.initial_move_delay_value : 0);
+#else
   /* dynamically adjust player properties according to game engine version */
   game.initial_move_delay =
     (game.engine_version <= VERSION_IDENT(2,0,1,0) ? INITIAL_MOVE_DELAY_ON :
@@ -1194,6 +1390,7 @@ static void InitGameEngine()
   /* dynamically adjust player properties according to level information */
   game.initial_move_delay_value =
     (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+#endif
 
   /* ---------- initialize player's initial push delay --------------------- */
 
@@ -1219,9 +1416,10 @@ static void InitGameEngine()
       ei->change->delay_frames = 1;
     }
 
-    ei->change_events = CE_BITMASK_DEFAULT;
     for (j = 0; j < NUM_CHANGE_EVENTS; j++)
     {
+      ei->has_change_event[j] = FALSE;
+
       ei->event_page_nr[j] = 0;
       ei->event_page[j] = &ei->change_page[0];
     }
@@ -1240,7 +1438,7 @@ static void InitGameEngine()
     ei->change->change_function      = ch_delay->change_function;
     ei->change->post_change_function = ch_delay->post_change_function;
 
-    ei->change_events |= CH_EVENT_BIT(CE_DELAY);
+    ei->has_change_event[CE_DELAY] = TRUE;
 
 #if 1
     SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
@@ -1261,10 +1459,10 @@ static void InitGameEngine()
       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
       {
        /* only add event page for the first page found with this event */
-       if (ei->change_page[j].events & CH_EVENT_BIT(k) &&
-           !(ei->change_events & CH_EVENT_BIT(k)))
+       if (ei->change_page[j].has_event[k] && !(ei->has_change_event[k]))
        {
-         ei->change_events |= CH_EVENT_BIT(k);
+         ei->has_change_event[k] = TRUE;
+
          ei->event_page_nr[k] = j;
          ei->event_page[k] = &ei->change_page[j];
        }
@@ -1281,7 +1479,7 @@ static void InitGameEngine()
 
     /* only add custom elements that change after fixed/random frame delay */
     if (CAN_CHANGE(element) && HAS_CHANGE_EVENT(element, CE_DELAY))
-      element_info[element].change_events |= CH_EVENT_BIT(CE_DELAY);
+      element_info[element].has_change_event[CE_DELAY] = TRUE;
   }
 #endif
 
@@ -1302,7 +1500,8 @@ static void InitGameEngine()
 
   /* initialize trigger events information */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-    trigger_events[i] = EP_BITMASK_DEFAULT;
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      trigger_events[i][j] = FALSE;
 
 #if 1
   /* add trigger events from element change event properties */
@@ -1315,20 +1514,26 @@ static void InitGameEngine()
       if (!ei->change_page[j].can_change)
        continue;
 
-      if (ei->change_page[j].events & CH_EVENT_BIT(CE_BY_OTHER_ACTION))
+      if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
       {
        int trigger_element = ei->change_page[j].trigger_element;
 
-       if (IS_GROUP_ELEMENT(trigger_element))
+       for (k = 0; k < NUM_CHANGE_EVENTS; k++)
        {
-         struct ElementGroupInfo *group = element_info[trigger_element].group;
+         if (ei->change_page[j].has_event[k])
+         {
+           if (IS_GROUP_ELEMENT(trigger_element))
+           {
+             struct ElementGroupInfo *group =
+               element_info[trigger_element].group;
 
-         for (k = 0; k < group->num_elements_resolved; k++)
-           trigger_events[group->element_resolved[k]]
-             |= ei->change_page[j].events;
+             for (l = 0; l < group->num_elements_resolved; l++)
+               trigger_events[group->element_resolved[l]][k] = TRUE;
+           }
+           else
+             trigger_events[trigger_element][k] = TRUE;
+         }
        }
-       else
-         trigger_events[trigger_element] |= ei->change_page[j].events;
       }
     }
   }
@@ -1336,8 +1541,9 @@ static void InitGameEngine()
   /* add trigger events from element change event properties */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     if (HAS_CHANGE_EVENT(i, CE_BY_OTHER_ACTION))
-      trigger_events[element_info[i].change->trigger_element] |=
-       element_info[i].change->events;
+      for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+       if (element_info[i].change->has_event[j])
+         trigger_events[element_info[i].change->trigger_element][j] = TRUE;
 #endif
 
   /* ---------- initialize push delay -------------------------------------- */
@@ -1368,8 +1574,16 @@ static void InitGameEngine()
     {
       if (IS_SP_ELEMENT(i))
       {
+#if USE_NEW_MOVE_STYLE
+       /* set SP push delay to just enough to push under a falling zonk */
+       int delay = (game.engine_version >= VERSION_IDENT(3,1,1,0) ? 8 : 6);
+
+       element_info[i].push_delay_fixed  = delay;
+       element_info[i].push_delay_random = 0;
+#else
        element_info[i].push_delay_fixed  = 6;  /* just enough to escape ... */
        element_info[i].push_delay_random = 0;  /* ... from falling zonk     */
+#endif
       }
     }
   }
@@ -1476,7 +1690,7 @@ void InitGame()
     player->lights_still_needed = 0;
     player->friends_still_needed = 0;
 
-    for (j = 0; j < MAX_KEYS; j++)
+    for (j = 0; j < MAX_NUM_KEYS; j++)
       player->key[j] = FALSE;
 
     player->dynabomb_count = 0;
@@ -1494,7 +1708,9 @@ void InitGame()
 
     player->use_murphy_graphic = FALSE;
 
-    player->block_last_field = FALSE;
+    player->block_last_field = FALSE;  /* initialized in InitPlayerField() */
+    player->block_delay_adjustment = 0;        /* initialized in InitPlayerField() */
+
     player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
 
     player->actual_frame_counter = 0;
@@ -1563,6 +1779,11 @@ void InitGame()
     player->switch_x = -1;
     player->switch_y = -1;
 
+#if USE_DROP_BUGFIX
+    player->drop_x = -1;
+    player->drop_y = -1;
+#endif
+
     player->show_envelope = 0;
 
     player->move_delay       = game.initial_move_delay;
@@ -1570,8 +1791,13 @@ void InitGame()
 
     player->move_delay_reset_counter = 0;
 
-    player->push_delay = 0;
+#if USE_NEW_PUSH_DELAY
+    player->push_delay       = -1;     /* initialized when pushing starts */
+    player->push_delay_value = game.initial_push_delay_value;
+#else
+    player->push_delay       = 0;
     player->push_delay_value = game.initial_push_delay_value;
+#endif
 
     player->drop_delay = 0;
 
@@ -1600,6 +1826,7 @@ void InitGame()
 #endif
 
   ZX = ZY = -1;
+  ExitX = ExitY = -1;
 
   FrameCounter = 0;
   TimeFrames = 0;
@@ -1652,8 +1879,8 @@ void InitGame()
       Stop[x][y] = FALSE;
       Pushed[x][y] = FALSE;
 
-      Changed[x][y] = CE_BITMASK_DEFAULT;
-      ChangeEvent[x][y] = CE_BITMASK_DEFAULT;
+      Changed[x][y] = FALSE;
+      ChangeEvent[x][y] = -1;
 
       ExplodePhase[x][y] = 0;
       ExplodeDelay[x][y] = 0;
@@ -1754,6 +1981,11 @@ void InitGame()
          player->element_nr = some_player->element_nr;
 #endif
 
+#if USE_NEW_BLOCK_STYLE
+         player->block_last_field       = some_player->block_last_field;
+         player->block_delay_adjustment = some_player->block_delay_adjustment;
+#endif
+
          StorePlayer[jx][jy] = player->element_nr;
          player->jx = player->last_jx = jx;
          player->jy = player->last_jy = jy;
@@ -1956,18 +2188,27 @@ void InitGame()
 
   CloseDoor(DOOR_CLOSE_1);
 
-  DrawLevel();
-  DrawAllPlayers();
+  /* !!! FIX THIS (START) !!! */
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    InitGameEngine_EM();
+  }
+  else
+  {
+    DrawLevel();
+    DrawAllPlayers();
 
-  /* after drawing the level, correct some elements */
-  if (game.timegate_time_left == 0)
-    CloseAllOpenTimegates();
+    /* after drawing the level, correct some elements */
+    if (game.timegate_time_left == 0)
+      CloseAllOpenTimegates();
 
-  if (setup.soft_scrolling)
-    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+    if (setup.soft_scrolling)
+      BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
 
-  redraw_mask |= REDRAW_FROM_BACKBUFFER;
-  FadeToFront();
+    redraw_mask |= REDRAW_FROM_BACKBUFFER;
+    FadeToFront();
+  }
+  /* !!! FIX THIS (END) !!! */
 
   /* copy default game door content to main double buffer */
   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
@@ -2008,6 +2249,15 @@ void InitGame()
 #endif
 }
 
+void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y)
+{
+  /* this is used for non-R'n'D game engines to update certain engine values */
+
+  /* needed to determine if sounds are played within the visible screen area */
+  scroll_x = actual_scroll_x;
+  scroll_y = actual_scroll_y;
+}
+
 void InitMovDir(int x, int y)
 {
   int i, element = Feld[x][y];
@@ -2278,8 +2528,9 @@ void GameWon()
   }
 
   /* close exit door after last player */
-  if ((Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
-       Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN) && AllPlayersGone)
+  if (AllPlayersGone && ExitX >= 0 && ExitY >= 0 &&
+      (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
+       Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN))
   {
     int element = Feld[ExitX][ExitY];
 
@@ -2290,7 +2541,9 @@ void GameWon()
   }
 
   /* Hero disappears */
-  DrawLevelField(ExitX, ExitY);
+  if (ExitX >= 0 && ExitY >= 0)
+    DrawLevelField(ExitX, ExitY);
+
   BackToFront();
 
   if (tape.playing)
@@ -2399,6 +2652,37 @@ int NewHiScore()
   return position;
 }
 
+inline static int getElementMoveStepsize(int x, int y)
+{
+  int element = Feld[x][y];
+  int direction = MovDir[x][y];
+  int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+  int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
+  int horiz_move = (dx != 0);
+  int sign = (horiz_move ? dx : dy);
+  int step = sign * element_info[element].move_stepsize;
+
+  /* special values for move stepsize for spring and things on conveyor belt */
+  if (horiz_move)
+  {
+#if 0
+    if (element == EL_SPRING)
+      step = sign * MOVE_STEPSIZE_NORMAL * 2;
+    else if (CAN_FALL(element) && !CAN_MOVE(element) &&
+            y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+      step = sign * MOVE_STEPSIZE_NORMAL / 2;
+#else
+    if (CAN_FALL(element) &&
+       y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+      step = sign * MOVE_STEPSIZE_NORMAL / 2;
+    else if (element == EL_SPRING)
+      step = sign * MOVE_STEPSIZE_NORMAL * 2;
+#endif
+  }
+
+  return step;
+}
+
 void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
 {
   if (player->GfxAction != action || player->GfxDir != dir)
@@ -2438,6 +2722,27 @@ void InitMovingField(int x, int y, int direction)
   if (!WasJustMoving[x][y] || direction != MovDir[x][y])
     ResetGfxAnimation(x, y);
 
+#if USE_CAN_MOVE_NOT_MOVING
+
+  MovDir[x][y] = direction;
+  GfxDir[x][y] = direction;
+  GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ?
+                    ACTION_FALLING : ACTION_MOVING);
+
+  if (getElementMoveStepsize(x, y) != 0)       /* moving or being moved */
+  {
+    if (Feld[newx][newy] == EL_EMPTY)
+      Feld[newx][newy] = EL_BLOCKED;
+
+    MovDir[newx][newy] = MovDir[x][y];
+    GfxFrame[newx][newy] = GfxFrame[x][y];
+    GfxRandom[newx][newy] = GfxRandom[x][y];
+    GfxAction[newx][newy] = GfxAction[x][y];
+    GfxDir[newx][newy] = GfxDir[x][y];
+  }
+
+#else
+
   MovDir[newx][newy] = MovDir[x][y] = direction;
   GfxDir[x][y] = direction;
 
@@ -2453,6 +2758,7 @@ void InitMovingField(int x, int y, int direction)
   GfxRandom[newx][newy] = GfxRandom[x][y];
   GfxAction[newx][newy] = GfxAction[x][y];
   GfxDir[newx][newy] = GfxDir[x][y];
+#endif
 }
 
 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
@@ -2887,7 +3193,12 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
     {
       ScrollPlayer(player, SCROLL_GO_ON);
       ScrollScreen(NULL, SCROLL_GO_ON);
+
+#if USE_NEW_MOVE_DELAY
+      AdvanceFrameAndPlayerCounters(player->index_nr);
+#else
       FrameCounter++;
+#endif
 
       DrawPlayer(player);
 
@@ -2908,7 +3219,7 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
                               player->index_bit, leave_side);
 
   CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
-                                     CE_OTHER_GETS_LEFT,
+                                     CE_PLAYER_LEAVES_X,
                                      player->index_bit, leave_side);
 #endif
 
@@ -2960,7 +3271,7 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
                               player->index_bit, enter_side);
 
   CheckTriggeredElementChangeByPlayer(jx, jy, element,
-                                     CE_OTHER_GETS_ENTERED,
+                                     CE_PLAYER_ENTERS_X,
                                      player->index_bit, enter_side);
 #endif
 }
@@ -3007,8 +3318,15 @@ void Explode(int ex, int ey, int phase, int mode)
       return;
 #endif
 
+#if 1
+    if (mode == EX_TYPE_NORMAL ||
+       mode == EX_TYPE_CENTER ||
+       mode == EX_TYPE_CROSS)
+      PlayLevelSoundAction(ex, ey, ACTION_EXPLODING);
+#else
     if (mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER)
       PlayLevelSoundAction(ex, ey, ACTION_EXPLODING);
+#endif
 
     /* remove things displayed in background while burning dynamite */
     if (Back[ex][ey] != EL_EMPTY && !IS_INDESTRUCTIBLE(Back[ex][ey]))
@@ -3097,7 +3415,11 @@ void Explode(int ex, int ey, int phase, int mode)
        continue;
 #endif
 
-#if 1
+      /* no idea why this was changed from 3.0.8 to 3.1.0 -- this causes buggy
+        behaviour, for example when touching a yamyam that explodes to rocks
+        with active deadly shield, a rock is created under the player !!! */
+      /* (case 1 (surely buggy): >= 3.1.0, case 2 (maybe buggy): <= 3.0.8) */
+#if 0
       if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)) &&
          (game.engine_version < VERSION_IDENT(3,1,0,0) ||
           (x == ex && y == ey && mode != EX_TYPE_BORDER)))
@@ -3720,7 +4042,7 @@ void Bang(int x, int y)
       break;
   }
 
-  CheckTriggeredElementChange(x, y, element, CE_OTHER_IS_EXPLODING);
+  CheckTriggeredElementChange(x, y, element, CE_EXPLOSION_OF_X);
 }
 
 void SplashAcid(int x, int y)
@@ -4014,6 +4336,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
          Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
 
        DrawLevelField(x, y);
+
+       /* uncrumble neighbour fields, if needed */
+       if (element == EL_INVISIBLE_SAND)
+         DrawLevelFieldCrumbledSandNeighbours(x, y);
       }
       else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
               element == EL_INVISIBLE_WALL_ACTIVE ||
@@ -4023,6 +4349,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
          Feld[x][y] = getInvisibleFromInvisibleActiveElement(element);
 
        DrawLevelField(x, y);
+
+       /* re-crumble neighbour fields, if needed */
+       if (element == EL_INVISIBLE_SAND)
+         DrawLevelFieldCrumbledSandNeighbours(x, y);
       }
     }
   }
@@ -4072,46 +4402,19 @@ static void ActivateTimegateSwitch(int x, int y)
   Feld[x][y] = EL_TIMEGATE_SWITCH_ACTIVE;
 }
 
-inline static int getElementMoveStepsize(int x, int y)
-{
-  int element = Feld[x][y];
-  int direction = MovDir[x][y];
-  int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
-  int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
-  int horiz_move = (dx != 0);
-  int sign = (horiz_move ? dx : dy);
-  int step = sign * element_info[element].move_stepsize;
-
-  /* special values for move stepsize for spring and things on conveyor belt */
-  if (horiz_move)
-  {
-#if 0
-    if (element == EL_SPRING)
-      step = sign * MOVE_STEPSIZE_NORMAL * 2;
-    else if (CAN_FALL(element) && !CAN_MOVE(element) &&
-            y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
-      step = sign * MOVE_STEPSIZE_NORMAL / 2;
-#else
-    if (CAN_FALL(element) &&
-       y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
-      step = sign * MOVE_STEPSIZE_NORMAL / 2;
-    else if (element == EL_SPRING)
-      step = sign * MOVE_STEPSIZE_NORMAL * 2;
-#endif
-  }
-
-  return step;
-}
-
 void Impact(int x, int y)
 {
-  boolean lastline = (y == lev_fieldy-1);
+  boolean last_line = (y == lev_fieldy - 1);
   boolean object_hit = FALSE;
-  boolean impact = (lastline || object_hit);
+  boolean impact = (last_line || object_hit);
   int element = Feld[x][y];
   int smashed = EL_STEELWALL;
 
-  if (!lastline)       /* check if element below was hit */
+#if 0
+  printf("IMPACT!\n");
+#endif
+
+  if (!last_line)      /* check if element below was hit */
   {
     if (Feld[x][y + 1] == EL_PLAYER_IS_LEAVING)
       return;
@@ -4132,10 +4435,10 @@ void Impact(int x, int y)
     if (object_hit)
       smashed = MovingOrBlocked2Element(x, y + 1);
 
-    impact = (lastline || object_hit);
+    impact = (last_line || object_hit);
   }
 
-  if (!lastline && smashed == EL_ACID) /* element falls into acid */
+  if (!last_line && smashed == EL_ACID)        /* element falls into acid */
   {
     SplashAcid(x, y + 1);
     return;
@@ -4317,10 +4620,10 @@ void Impact(int x, int y)
          CheckElementChangeBySide(x, y + 1, smashed, element,
                                   CE_SWITCHED, CH_SIDE_TOP);
          CheckTriggeredElementChangeBySide(x, y + 1, smashed,
-                                           CE_OTHER_IS_SWITCHING,CH_SIDE_TOP);
+                                           CE_SWITCH_OF_X, CH_SIDE_TOP);
 #else
          CheckTriggeredElementChangeBySide(x, y + 1, smashed,
-                                           CE_OTHER_IS_SWITCHING,CH_SIDE_TOP);
+                                           CE_SWITCH_OF_X, CH_SIDE_TOP);
          CheckElementChangeBySide(x, y + 1, smashed, element,
                                   CE_SWITCHED, CH_SIDE_TOP);
 #endif
@@ -4334,7 +4637,7 @@ void Impact(int x, int y)
   }
 
   /* play sound of magic wall / mill */
-  if (!lastline &&
+  if (!last_line &&
       (Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE ||
        Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE))
   {
@@ -4347,7 +4650,7 @@ void Impact(int x, int y)
   }
 
   /* play sound of object that hits the ground */
-  if (lastline || object_hit)
+  if (last_line || object_hit)
     PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
 }
 
@@ -4570,8 +4873,15 @@ inline static void TurnRoundExt(int x, int y)
     xx = x + move_xy[MovDir[x][y]].x;
     yy = y + move_xy[MovDir[x][y]].y;
 
+#if 1
+    /* !!! this bugfix breaks at least BD2K3, level 010 !!! [re-recorded] */
+    if (!IN_LEV_FIELD(xx, yy) ||
+        (!IS_FREE(xx, yy) && !IS_FOOD_PIG(Feld[xx][yy])))
+      MovDir[x][y] = old_move_dir;
+#else
     if (!IS_FREE(xx, yy) && !IS_FOOD_PIG(Feld[xx][yy]))
       MovDir[x][y] = old_move_dir;
+#endif
 
     MovDelay[x][y] = 0;
   }
@@ -4834,6 +5144,11 @@ inline static void TurnRoundExt(int x, int y)
     boolean can_turn_right =
       CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
 
+#if USE_CAN_MOVE_NOT_MOVING
+    if (element_info[element].move_stepsize == 0)      /* not moving */
+      return;
+#endif
+
     if (move_pattern == MV_TURNING_LEFT)
       MovDir[x][y] = left_dir;
     else if (move_pattern == MV_TURNING_RIGHT)
@@ -4944,6 +5259,16 @@ inline static void TurnRoundExt(int x, int y)
       boolean first_horiz = RND(2);
       int new_move_dir = MovDir[x][y];
 
+#if USE_CAN_MOVE_NOT_MOVING
+      if (element_info[element].move_stepsize == 0)    /* not moving */
+      {
+       first_horiz = (ABS(attr_x - x) >= ABS(attr_y - y));
+       MovDir[x][y] &= (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
+
+       return;
+      }
+#endif
+
       MovDir[x][y] =
        new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
       Moving2Blocked(x, y, &newx, &newy);
@@ -5037,7 +5362,13 @@ inline static void TurnRoundExt(int x, int y)
 
     MovDir[x][y] = new_move_dir;
     if (old_move_dir != new_move_dir)
+    {
+#if 1
+      MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
+#else
       MovDelay[x][y] = 9;
+#endif
+    }
   }
 }
 
@@ -5256,6 +5587,15 @@ void StartMoving(int x, int y)
     else if ((game.engine_version >= VERSION_IDENT(3,1,0,0) &&
              CheckCollision[x][y] && !IS_FREE(x, y + 1)) ||
 
+#if USE_IMPACT_BUGFIX
+            (game.engine_version >= VERSION_IDENT(3,0,7,0) &&
+             CAN_FALL(element) && WasJustFalling[x][y] &&
+             (Feld[x][y + 1] == EL_BLOCKED || IS_PLAYER(x, y + 1))) ||
+
+            (game.engine_version < VERSION_IDENT(2,2,0,7) &&
+             CAN_FALL(element) && WasJustMoving[x][y] && !Pushed[x][y + 1] &&
+             (Feld[x][y + 1] == EL_BLOCKED)))
+#else
             (game.engine_version >= VERSION_IDENT(3,0,7,0) &&
              CAN_SMASH(element) && WasJustFalling[x][y] &&
              (Feld[x][y + 1] == EL_BLOCKED || IS_PLAYER(x, y + 1))) ||
@@ -5263,6 +5603,7 @@ void StartMoving(int x, int y)
             (game.engine_version < VERSION_IDENT(2,2,0,7) &&
              CAN_SMASH(element) && WasJustMoving[x][y] && !Pushed[x][y + 1] &&
              (Feld[x][y + 1] == EL_BLOCKED)))
+#endif
 
 #else
 #if 1
@@ -5293,6 +5634,11 @@ void StartMoving(int x, int y)
 
       CheckCollision[x][y] = 0;
 
+#if 0
+      if (IS_PLAYER(x, y + 1))
+       printf("::: we ARE now killing the player [%d]\n", FrameCounter);
+#endif
+
       Impact(x, y);
     }
     else if (IS_FREE(x, y + 1) && element == EL_SPRING && level.use_spring_bug)
@@ -5360,13 +5706,39 @@ void StartMoving(int x, int y)
        can_fall_both = (can_fall_left && can_fall_right);
       }
 
+#if USE_NEW_SP_SLIPPERY
+      /* !!! better use the same properties as for custom elements here !!! */
+      else if (game.engine_version >= VERSION_IDENT(3,1,1,0) &&
+              can_fall_both && IS_SP_ELEMENT(Feld[x][y + 1]))
+      {
+       can_fall_right = FALSE;         /* slip down on left side */
+       can_fall_both = FALSE;
+      }
+#endif
+
+#if 1
+      if (can_fall_both)
+      {
+       if (game.emulation == EMU_BOULDERDASH ||
+           element == EL_BD_ROCK || element == EL_BD_DIAMOND)
+         can_fall_right = FALSE;       /* slip down on left side */
+       else
+         can_fall_left = !(can_fall_right = RND(2));
+
+       can_fall_both = FALSE;
+      }
+#endif
+
       if (can_fall_any)
       {
+#if 0
        if (can_fall_both &&
            (game.emulation != EMU_BOULDERDASH &&
             element != EL_BD_ROCK && element != EL_BD_DIAMOND))
          can_fall_left = !(can_fall_right = RND(2));
+#endif
 
+       /* if not determined otherwise, prefer left side for slipping down */
        InitMovingField(x, y, can_fall_left ? MV_LEFT : MV_RIGHT);
        started_moving = TRUE;
       }
@@ -5457,8 +5829,8 @@ void StartMoving(int x, int y)
             WasJustMoving[x][y],
             HAS_ANY_CHANGE_EVENT(element, CE_HITTING_SOMETHING),
             HAS_ANY_CHANGE_EVENT(element, CE_HIT_BY_SOMETHING),
-            HAS_ANY_CHANGE_EVENT(element, CE_OTHER_IS_HITTING),
-            HAS_ANY_CHANGE_EVENT(element, CE_OTHER_GETS_HIT));
+            HAS_ANY_CHANGE_EVENT(element, CE_HITTING_X),
+            HAS_ANY_CHANGE_EVENT(element, CE_HIT_BY_X));
 #endif
 
 #if 1
@@ -5849,7 +6221,16 @@ void StartMoving(int x, int y)
 #if 1
       Store[newx][newy] = EL_EMPTY;
       if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
+      {
+#if USE_CHANGE_TO_TRIGGERED
+       int move_leave_element = element_info[element].move_leave_element;
+
+       Store[newx][newy] = (move_leave_element == EL_TRIGGER_ELEMENT ?
+                            new_element : move_leave_element);
+#else
        Store[newx][newy] = element_info[element].move_leave_element;
+#endif
+      }
 #else
       Store[newx][newy] = EL_EMPTY;
       if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)) ||
@@ -6080,6 +6461,10 @@ void StartMoving(int x, int y)
     ContinueMoving(x, y);
 }
 
+void dummy()
+{
+}
+
 void ContinueMoving(int x, int y)
 {
   int element = Feld[x][y];
@@ -6098,6 +6483,7 @@ void ContinueMoving(int x, int y)
 #else
   boolean pushed_by_player = Pushed[x][y];
 #endif
+  boolean last_line = (newy == lev_fieldy - 1);
 
   MovPos[x][y] += getElementMoveStepsize(x, y);
 
@@ -6213,7 +6599,9 @@ void ContinueMoving(int x, int y)
 #endif
 
   Store[x][y] = EL_EMPTY;
-  MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
+  MovPos[x][y] = 0;
+  MovDir[x][y] = 0;
+  MovDelay[x][y] = 0;
   MovDelay[newx][newy] = 0;
 
   if (CAN_CHANGE(element))
@@ -6227,8 +6615,8 @@ void ContinueMoving(int x, int y)
 
   ChangeDelay[x][y] = 0;
   ChangePage[x][y] = -1;
-  Changed[x][y] = CE_BITMASK_DEFAULT;
-  ChangeEvent[x][y] = CE_BITMASK_DEFAULT;
+  Changed[x][y] = FALSE;
+  ChangeEvent[x][y] = -1;
 
   /* copy animation control values to new field */
   GfxFrame[newx][newy]  = GfxFrame[x][y];
@@ -6238,7 +6626,10 @@ void ContinueMoving(int x, int y)
 
   Pushed[x][y] = Pushed[newx][newy] = FALSE;
 
+#if 0
+  /* do this after checking for left-behind element */
   ResetGfxAnimation(x, y);     /* reset animation values for old field */
+#endif
 
 #if 1
   /* some elements can leave other elements behind after moving */
@@ -6254,8 +6645,20 @@ void ContinueMoving(int x, int y)
   {
     int move_leave_element = ei->move_leave_element;
 
+#if USE_CHANGE_TO_TRIGGERED
+    if (ei->move_leave_type == LEAVE_TYPE_LIMITED &&
+        ei->move_leave_element == EL_TRIGGER_ELEMENT)
+      move_leave_element = stored;
+#endif
+
     Feld[x][y] = move_leave_element;
-    InitField(x, y, FALSE);
+
+#if USE_PREVIOUS_MOVE_DIR
+    if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS)
+      MovDir[x][y] = direction;
+#endif
+
+    InitField(x, y, FALSE);
 
     if (GFX_CRUMBLED(Feld[x][y]))
       DrawLevelFieldCrumbledSandNeighbours(x, y);
@@ -6283,6 +6686,11 @@ void ContinueMoving(int x, int y)
   ei->can_leave_element = FALSE;
 #endif
 
+#if 1
+  /* do this after checking for left-behind element */
+  ResetGfxAnimation(x, y);     /* reset animation values for old field */
+#endif
+
 #if 0
   /* 2.1.1 (does not work correctly for spring) */
   if (!CAN_MOVE(element))
@@ -6368,12 +6776,37 @@ void ContinueMoving(int x, int y)
   else if (element == EL_PENGUIN)
     TestIfFriendTouchesBadThing(newx, newy);
 
+#if USE_NEW_MOVE_STYLE
+#if 0
   if (CAN_FALL(element) && direction == MV_DOWN &&
-      (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1)))
+      !last_line && IS_PLAYER(x, newy + 1))
+    printf("::: we would now kill the player [%d]\n", FrameCounter);
+#endif
+
+  /* give the player one last chance (one more frame) to move away */
+  if (CAN_FALL(element) && direction == MV_DOWN &&
+      (last_line || (!IS_FREE(x, newy + 1) &&
+                    (!IS_PLAYER(x, newy + 1) ||
+                     game.engine_version < VERSION_IDENT(3,1,1,0)))))
     Impact(x, newy);
+#else
+  if (CAN_FALL(element) && direction == MV_DOWN &&
+      (last_line || !IS_FREE(x, newy + 1)))
+    Impact(x, newy);
+#endif
+
+#if 1
 
+#if USE_PUSH_BUGFIX
 #if 1
+  if (pushed_by_player && !game.use_change_when_pushing_bug)
+#else
+  if (pushed_by_player && game.engine_version >= VERSION_IDENT(3,1,0,0))
+#endif
+#else
   if (pushed_by_player)
+#endif
+
   {
 #if 1
     int dig_side = MV_DIR_OPPOSITE(direction);
@@ -6391,7 +6824,7 @@ void ContinueMoving(int x, int y)
 
     CheckElementChangeByPlayer(newx, newy, element, CE_PUSHED_BY_PLAYER,
                               player->index_bit, dig_side);
-    CheckTriggeredElementChangeByPlayer(newx,newy,element,CE_OTHER_GETS_PUSHED,
+    CheckTriggeredElementChangeByPlayer(newx,newy, element, CE_PLAYER_PUSHES_X,
                                        player->index_bit, dig_side);
   }
 #endif
@@ -6438,7 +6871,7 @@ void ContinueMoving(int x, int y)
                                 CE_HIT_BY_SOMETHING, opposite_direction);
 
        if (IS_CUSTOM_ELEMENT(hitting_element) &&
-           HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
+           HAS_ANY_CHANGE_EVENT(hitting_element, CE_HITTING_X))
        {
          for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
          {
@@ -6446,19 +6879,19 @@ void ContinueMoving(int x, int y)
              &element_info[hitting_element].change_page[i];
 
            if (change->can_change &&
-               change->events & CH_EVENT_BIT(CE_OTHER_IS_HITTING) &&
+               change->has_event[CE_HITTING_X] &&
                change->trigger_side & touched_side &&
                change->trigger_element == touched_element)
            {
              CheckElementChangeByPage(newx, newy, hitting_element,
-                                      touched_element, CE_OTHER_IS_HITTING,i);
+                                      touched_element, CE_HITTING_X, i);
              break;
            }
          }
        }
 
        if (IS_CUSTOM_ELEMENT(touched_element) &&
-           HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_HIT))
+           HAS_ANY_CHANGE_EVENT(touched_element, CE_HIT_BY_X))
        {
          for (i = 0; i < element_info[touched_element].num_change_pages; i++)
          {
@@ -6466,12 +6899,12 @@ void ContinueMoving(int x, int y)
              &element_info[touched_element].change_page[i];
 
            if (change->can_change &&
-               change->events & CH_EVENT_BIT(CE_OTHER_GETS_HIT) &&
+               change->has_event[CE_HIT_BY_X] &&
                change->trigger_side & hitting_side &&
                change->trigger_element == hitting_element)
            {
              CheckElementChangeByPage(nextx, nexty, touched_element,
-                                      hitting_element, CE_OTHER_GETS_HIT, i);
+                                      hitting_element, CE_HIT_BY_X,i);
              break;
            }
          }
@@ -7501,6 +7934,8 @@ static void ChangeElementNowExt(int x, int y, int target_element)
     RelocatePlayer(x, y, target_element);
 
 #if 1
+  Changed[x][y] = TRUE;                /* ignore all further changes in this frame */
+#else
   Changed[x][y] |= ChangeEvent[x][y];  /* ignore same changes in this frame */
 #endif
 
@@ -7518,30 +7953,35 @@ static boolean ChangeElementNow(int x, int y, int element, int page)
   int old_element = Feld[x][y];
 
   /* always use default change event to prevent running into a loop */
-  if (ChangeEvent[x][y] == CE_BITMASK_DEFAULT)
-    ChangeEvent[x][y] = CH_EVENT_BIT(CE_DELAY);
+  if (ChangeEvent[x][y] == -1)
+    ChangeEvent[x][y] = CE_DELAY;
 
-  if (ChangeEvent[x][y] == CH_EVENT_BIT(CE_DELAY))
+  if (ChangeEvent[x][y] == CE_DELAY)
   {
     /* reset actual trigger element and player */
     change->actual_trigger_element = EL_EMPTY;
     change->actual_trigger_player = EL_PLAYER_1;
   }
 
-  /* do not change already changed elements with same change event */
-#if 0
-  if (Changed[x][y] & ChangeEvent[x][y])
+#if 1
+  /* do not change any elements that have already changed in this frame */
+  if (Changed[x][y])
     return FALSE;
 #else
-  if (Changed[x][y])
+  /* do not change already changed elements with same change event */
+  if (Changed[x][y] & ChangeEvent[x][y])
     return FALSE;
 #endif
 
+#if 1
+  Changed[x][y] = TRUE;                /* ignore all further changes in this frame */
+#else
   Changed[x][y] |= ChangeEvent[x][y];  /* ignore same changes in this frame */
+#endif
 
 #if 0
   /* !!! indirect change before direct change !!! */
-  CheckTriggeredElementChangeByPage(x,y,Feld[x][y], CE_OTHER_IS_CHANGING,page);
+  CheckTriggeredElementChangeByPage(x, y, Feld[x][y], CE_CHANGE_OF_X, page);
 #endif
 
   if (change->explode)
@@ -7710,7 +8150,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page)
 
 #if 1
   /* this uses direct change before indirect change */
-  CheckTriggeredElementChangeByPage(x,y,old_element,CE_OTHER_IS_CHANGING,page);
+  CheckTriggeredElementChangeByPage(x, y, old_element, CE_CHANGE_OF_X, page);
 #endif
 
   return TRUE;
@@ -7808,7 +8248,7 @@ static boolean CheckTriggeredElementChangeExt(int lx, int ly,
   int i, j, x, y;
   int trigger_page_bits = (trigger_page < 0 ? CH_PAGE_ANY : 1 << trigger_page);
 
-  if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event)))
+  if (!(trigger_events[trigger_element][trigger_event]))
     return FALSE;
 
   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -7826,14 +8266,14 @@ static boolean CheckTriggeredElementChangeExt(int lx, int ly,
       struct ElementChangeInfo *change = &element_info[element].change_page[j];
 
       if (change->can_change &&
-         change->events & CH_EVENT_BIT(trigger_event) &&
+         change->has_event[trigger_event] &&
          change->trigger_side & trigger_side &&
          change->trigger_player & trigger_player &&
          change->trigger_page & trigger_page_bits &&
          IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element))
       {
 #if 0
-       if (!(change->events & CH_EVENT_BIT(trigger_event)))
+       if (!(change->has_event[trigger_event]))
          printf("::: !!! %d triggers %d: using wrong page %d [event %d]\n",
                 trigger_element-EL_CUSTOM_START+1, i+1, j, trigger_event);
 #endif
@@ -7861,7 +8301,7 @@ static boolean CheckTriggeredElementChangeExt(int lx, int ly,
       if (Feld[x][y] == element)
       {
        ChangeDelay[x][y] = 1;
-       ChangeEvent[x][y] = CH_EVENT_BIT(trigger_event);
+       ChangeEvent[x][y] = trigger_event;
        ChangeElement(x, y, page);
       }
     }
@@ -7912,7 +8352,7 @@ static boolean CheckElementChangeExt(int x, int y,
       struct ElementChangeInfo *change = &element_info[element].change_page[i];
 
       if (change->can_change &&
-         change->events & CH_EVENT_BIT(trigger_event) &&
+         change->has_event[trigger_event] &&
          change->trigger_side & trigger_side &&
          change->trigger_player & trigger_player)
       {
@@ -7950,7 +8390,7 @@ static boolean CheckElementChangeExt(int x, int y,
 #endif
 
   ChangeDelay[x][y] = 1;
-  ChangeEvent[x][y] = CH_EVENT_BIT(trigger_event);
+  ChangeEvent[x][y] = trigger_event;
   ChangeElement(x, y, trigger_page);
 
   return TRUE;
@@ -8300,10 +8740,49 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
 }
 #endif
 
+void AdvanceFrameAndPlayerCounters(int player_nr)
+{
+  int i;
+
+  /* advance frame counters (global frame counter and time frame counter) */
+  FrameCounter++;
+  TimeFrames++;
+
+  /* advance player counters (counters for move delay, move animation etc.) */
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    boolean advance_player_counters = (player_nr == -1 || player_nr == i);
+    int move_frames =
+      MOVE_DELAY_NORMAL_SPEED /  stored_player[i].move_delay_value;
+
+    if (!advance_player_counters)      /* not all players may be affected */
+      continue;
+
+    stored_player[i].Frame += move_frames;
+
+    if (stored_player[i].MovPos != 0)
+      stored_player[i].StepFrame += move_frames;
+
+#if USE_NEW_MOVE_DELAY
+    if (stored_player[i].move_delay > 0)
+      stored_player[i].move_delay--;
+#endif
+
+#if USE_NEW_PUSH_DELAY
+    /* due to bugs in previous versions, counter must count up, not down */
+    if (stored_player[i].push_delay != -1)
+      stored_player[i].push_delay++;
+#endif
+
+    if (stored_player[i].drop_delay > 0)
+      stored_player[i].drop_delay--;
+  }
+}
+
 void GameActions()
 {
-  static unsigned long action_delay = 0;
-  unsigned long action_delay_value;
+  static unsigned long game_frame_delay = 0;
+  unsigned long game_frame_delay_value;
   int magic_wall_x = 0, magic_wall_y = 0;
   int i, x, y, element, graphic;
   byte *recorded_player_action;
@@ -8315,15 +8794,15 @@ void GameActions()
   if (game_status != GAME_MODE_PLAYING)
     return;
 
-  action_delay_value =
+  game_frame_delay_value =
     (tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay);
 
   if (tape.playing && tape.warp_forward && !tape.pausing)
-    action_delay_value = 0;
+    game_frame_delay_value = 0;
 
   /* ---------- main game synchronization point ---------- */
 
-  WaitUntilDelayReached(&action_delay, action_delay_value);
+  WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
 
   if (network_playing && !network_player_action_received)
   {
@@ -8362,6 +8841,7 @@ void GameActions()
   recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
 
 #if 1
+  /* !!! CHECK THIS (tape.pausing is always FALSE here!) !!! */
   if (recorded_player_action == NULL && tape.pausing)
     return;
 #endif
@@ -8494,7 +8974,7 @@ void GameActions()
 #endif
 
 #if 1
-  /* for downwards compatibility, the following code emulates a fixed bug that
+  /* for backwards compatibility, the following code emulates a fixed bug that
      occured when pushing elements (causing elements that just made their last
      pushing step to already (if possible) make their first falling step in the
      same game frame, which is bad); this code is also needed to use the famous
@@ -8538,8 +9018,18 @@ void GameActions()
 
   for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
   {
-    Changed[x][y] = CE_BITMASK_DEFAULT;
-    ChangeEvent[x][y] = CE_BITMASK_DEFAULT;
+    Changed[x][y] = FALSE;
+    ChangeEvent[x][y] = -1;
+
+#if USE_NEW_BLOCK_STYLE
+    /* this must be handled before main playfield loop */
+    if (Feld[x][y] == EL_PLAYER_IS_LEAVING)
+    {
+      MovDelay[x][y]--;
+      if (MovDelay[x][y] <= 0)
+       RemoveField(x, y);
+    }
+#endif
 
 #if DEBUG
     if (ChangePage[x][y] != -1 && ChangeDelay[x][y] != 1)
@@ -8991,7 +9481,9 @@ void GameActions()
           stored_player[0].StepFrame);
 #endif
 
-#if 1
+#if USE_NEW_MOVE_DELAY
+  AdvanceFrameAndPlayerCounters(-1);   /* advance counters for all players */
+#else
   FrameCounter++;
   TimeFrames++;
 
@@ -9005,6 +9497,11 @@ void GameActions()
     if (stored_player[i].MovPos != 0)
       stored_player[i].StepFrame += move_frames;
 
+#if USE_NEW_MOVE_DELAY
+    if (stored_player[i].move_delay > 0)
+      stored_player[i].move_delay--;
+#endif
+
     if (stored_player[i].drop_delay > 0)
       stored_player[i].drop_delay--;
   }
@@ -9018,6 +9515,12 @@ void GameActions()
     local_player->show_envelope = 0;
   }
 #endif
+
+#if USE_NEW_RANDOMIZE
+  /* use random number generator in every frame to make it less predictable */
+  if (game.engine_version >= VERSION_IDENT(3,1,1,0))
+    RND(1);
+#endif
 }
 
 static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y)
@@ -9129,6 +9632,11 @@ static boolean canFallDown(struct PlayerInfo *player)
 
   return (IN_LEV_FIELD(jx, jy + 1) &&
          (IS_FREE(jx, jy + 1) ||
+#if USE_NEW_BLOCK_STYLE
+#if USE_GRAVITY_BUGFIX_OLD
+          Feld[jx][jy + 1] == EL_PLAYER_IS_LEAVING ||
+#endif
+#endif
           (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)) &&
          IS_WALKABLE_FROM(Feld[jx][jy], MV_DOWN) &&
          !IS_WALKABLE_INSIDE(Feld[jx][jy]));
@@ -9407,7 +9915,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 
   /* check if DigField() has caused relocation of the player */
   if (player->jx != jx || player->jy != jy)
-    return MF_NO_ACTION;
+    return MF_NO_ACTION;       /* <-- !!! CHECK THIS [-> MF_ACTION ?] !!! */
 
   StorePlayer[jx][jy] = 0;
   player->last_jx = jx;
@@ -9432,7 +9940,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 #if 0
   if (IS_CUSTOM_ELEMENT(Feld[jx][jy]))
   {
-    CheckTriggeredElementChangeBySide(jx, jy, Feld[jx][jy], CE_OTHER_GETS_LEFT,
+    CheckTriggeredElementChangeBySide(jx, jy, Feld[jx][jy], CE_PLAYER_LEAVES_X,
                                      leave_side);
     CheckElementChangeBySide(jx,jy, Feld[jx][jy],CE_LEFT_BY_PLAYER,leave_side);
   }
@@ -9440,7 +9948,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
   if (IS_CUSTOM_ELEMENT(Feld[new_jx][new_jy]))
   {
     CheckTriggeredElementChangeBySide(new_jx, new_jy, Feld[new_jx][new_jy],
-                                     CE_OTHER_GETS_ENTERED, enter_side);
+                                     CE_PLAYER_ENTERS_X, enter_side);
     CheckElementChangeBySide(new_jx, new_jy, Feld[new_jx][new_jy],
                             CE_ENTERED_BY_PLAYER, enter_side);
   }
@@ -9484,14 +9992,38 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 #else
 
 #if 1
+
+#if 0
+  printf("::: %d <= %d < %d ?\n", player->move_delay, FrameCounter,
+        player->move_delay + player->move_delay_value);
+#endif
+
+#if USE_NEW_MOVE_DELAY
+  if (player->move_delay > 0)
+#else
   if (!FrameReached(&player->move_delay, player->move_delay_value))
+#endif
+  {
+#if 0
+    printf("::: can NOT move\n");
+#endif
+
     return FALSE;
+  }
 #else
   if (!FrameReached(&player->move_delay, player->move_delay_value) &&
       !(tape.playing && tape.file_version < FILE_VERSION_2_0))
     return FALSE;
 #endif
 
+#endif
+
+#if 0
+  printf("::: COULD move now\n");
+#endif
+
+#if USE_NEW_MOVE_DELAY
+  player->move_delay = -1;             /* set to "uninitialized" value */
 #endif
 
   /* store if player is automatically moved to next field */
@@ -9519,7 +10051,13 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     {
       ScrollPlayer(player, SCROLL_GO_ON);
       ScrollScreen(NULL, SCROLL_GO_ON);
+
+#if USE_NEW_MOVE_DELAY
+      AdvanceFrameAndPlayerCounters(player->index_nr);
+#else
       FrameCounter++;
+#endif
+
       DrawAllPlayers();
       BackToFront();
     }
@@ -9623,6 +10161,10 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 
   if (moved & MF_MOVING)
   {
+#if 0
+    printf("::: REALLY moves now\n");
+#endif
+
     if (old_jx != jx && old_jy == jy)
       player->MovDir = (old_jx < jx ? MV_RIGHT : MV_LEFT);
     else if (old_jx == jx && old_jy != jy)
@@ -9677,7 +10219,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
                                   player->index_bit, leave_side);
 
       CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
-                                         CE_OTHER_GETS_LEFT,
+                                         CE_PLAYER_LEAVES_X,
                                          player->index_bit, leave_side);
 
       if (IS_CUSTOM_ELEMENT(new_element))
@@ -9685,7 +10227,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
                                   player->index_bit, enter_side);
 
       CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
-                                         CE_OTHER_GETS_ENTERED,
+                                         CE_PLAYER_ENTERS_X,
                                          player->index_bit, enter_side);
 #endif
 
@@ -9702,8 +10244,23 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     player->last_move_dir = MV_NO_MOVING;
     */
     player->is_moving = FALSE;
+
+#if USE_NEW_MOVE_STYLE
+    /* player is ALLOWED to move, but CANNOT move (something blocks his way) */
+    /* ensure that the player is also allowed to move in the next frame */
+    /* (currently, the player is forced to wait eight frames before he can try
+       again!!!) */
+
+    if (game.engine_version >= VERSION_IDENT(3,1,1,0))
+      player->move_delay = 0;  /* allow direct movement in the next frame */
+#endif
   }
 
+#if USE_NEW_MOVE_DELAY
+  if (player->move_delay == -1)                /* not yet initialized by DigField() */
+    player->move_delay = player->move_delay_value;
+#endif
+
   if (game.engine_version < VERSION_IDENT(3,0,7,0))
   {
     TestIfHeroTouchesBadThing(jx, jy);
@@ -9730,8 +10287,74 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
     player->actual_frame_counter = FrameCounter;
     player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
 
+#if 0
+    printf("::: %06d: %d,%d: %d (%d) [%d]\n",
+          FrameCounter,
+          last_jx, last_jy, Feld[last_jx][last_jy], EL_EXPLOSION,
+          player->block_delay);
+#endif
+
+#if USE_NEW_BLOCK_STYLE
+
+#if 0
+    if (player->block_delay <= 0)
+      printf("::: ALERT! block_delay == %d\n", player->block_delay);
+#endif
+
+    if ((player->block_last_field || player->block_delay_adjustment > 0) &&
+       Feld[last_jx][last_jy] == EL_EMPTY)
+    {
+      int last_field_block_delay = 0;  /* start with no blocking at all */
+      int block_delay_adjustment = player->block_delay_adjustment;
+
+      /* if player blocks last field, add delay for exactly one move */
+      if (player->block_last_field)
+      {
+       last_field_block_delay += player->move_delay_value;
+
+#if USE_GRAVITY_BUGFIX_NEW
+       /* when blocking enabled, prevent moving up despite gravity */
+       if (game.gravity && player->MovDir == MV_UP)
+         block_delay_adjustment = -1;
+#endif
+      }
+
+      /* add block delay adjustment (also possible when not blocking) */
+      last_field_block_delay += block_delay_adjustment;
+
+#if 0
+#if USE_BLOCK_DELAY_BUGFIX
+      /* when blocking enabled, correct block delay for fast movement */
+      if (player->block_last_field &&
+         player->move_delay_value < MOVE_DELAY_NORMAL_SPEED)
+       last_field_block_delay =
+         player->move_delay_value + player->block_delay_adjustment;
+#endif
+#endif
+
+#if 0
+#if USE_GRAVITY_BUGFIX_NEW
+      /* when blocking enabled, correct block delay for gravity movement */
+      if (player->block_last_field &&
+         game.gravity && player->MovDir == MV_UP)
+       last_field_block_delay = player->move_delay_value - 1;
+#endif
+#endif
+
+      Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
+      MovDelay[last_jx][last_jy] = last_field_block_delay + 1;
+    }
+#else
+#if USE_NEW_MOVE_STYLE
+    if ((game.engine_version < VERSION_IDENT(3,1,1,0) ||
+        player->block_last_field) &&
+       Feld[last_jx][last_jy] == EL_EMPTY)
+      Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
+#else
     if (Feld[last_jx][last_jy] == EL_EMPTY)
       Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
+#endif
+#endif
 
 #if 0
     DrawPlayer(player);
@@ -9745,9 +10368,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
   player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
   player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
 
+#if USE_NEW_BLOCK_STYLE
+#else
   if (!player->block_last_field &&
       Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
+#if 1
+    RemoveField(last_jx, last_jy);
+#else
     Feld[last_jx][last_jy] = EL_EMPTY;
+#endif
+#endif
 
   /* before DrawPlayer() to draw correct player graphic for this case */
   if (player->MovPos == 0)
@@ -9784,9 +10414,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
     }
 #endif
 
+#if USE_NEW_BLOCK_STYLE
+#else
     if (player->block_last_field &&
        Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
+#if 1
+      RemoveField(last_jx, last_jy);
+#else
       Feld[last_jx][last_jy] = EL_EMPTY;
+#endif
+#endif
 
     player->last_jx = jx;
     player->last_jy = jy;
@@ -9839,7 +10476,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
                                   player->index_bit, leave_side);
 
       CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
-                                         CE_OTHER_GETS_LEFT,
+                                         CE_PLAYER_LEAVES_X,
                                          player->index_bit, leave_side);
 
       if (IS_CUSTOM_ELEMENT(new_element))
@@ -9847,7 +10484,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
                                   player->index_bit, enter_side);
 
       CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
-                                         CE_OTHER_GETS_ENTERED,
+                                         CE_PLAYER_ENTERS_X,
                                          player->index_bit, enter_side);
 #endif
 
@@ -9984,11 +10621,11 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
       CheckElementChangeByPlayer(xx, yy, border_element, CE_TOUCHED_BY_PLAYER,
                                 player->index_bit, border_side);
       CheckTriggeredElementChangeByPlayer(xx, yy, border_element,
-                                         CE_OTHER_GETS_TOUCHED,
+                                         CE_PLAYER_TOUCHES_X,
                                          player->index_bit, border_side);
 #else
       CheckTriggeredElementChangeByPlayer(xx, yy, border_element,
-                                         CE_OTHER_GETS_TOUCHED,
+                                         CE_PLAYER_TOUCHES_X,
                                          player->index_bit, border_side);
       CheckElementChangeByPlayer(xx, yy, border_element, CE_TOUCHED_BY_PLAYER,
                                 player->index_bit, border_side);
@@ -10009,11 +10646,11 @@ void TestIfPlayerTouchesCustomElement(int x, int y)
       CheckElementChangeByPlayer(x, y, center_element, CE_TOUCHED_BY_PLAYER,
                                 player->index_bit, center_side);
       CheckTriggeredElementChangeByPlayer(x, y, center_element,
-                                         CE_OTHER_GETS_TOUCHED,
+                                         CE_PLAYER_TOUCHES_X,
                                          player->index_bit, center_side);
 #else
       CheckTriggeredElementChangeByPlayer(x, y, center_element,
-                                         CE_OTHER_GETS_TOUCHED,
+                                         CE_PLAYER_TOUCHES_X,
                                          player->index_bit, center_side);
       CheckElementChangeByPlayer(x, y, center_element, CE_TOUCHED_BY_PLAYER,
                                 player->index_bit, center_side);
@@ -10076,7 +10713,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
 
     /* check for change of center element (but change it only once) */
     if (IS_CUSTOM_ELEMENT(center_element) &&
-       HAS_ANY_CHANGE_EVENT(center_element, CE_OTHER_IS_TOUCHING) &&
+       HAS_ANY_CHANGE_EVENT(center_element, CE_TOUCHING_X) &&
        !change_center_element)
     {
       for (j = 0; j < element_info[center_element].num_change_pages; j++)
@@ -10085,7 +10722,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
          &element_info[center_element].change_page[j];
 
        if (change->can_change &&
-           change->events & CH_EVENT_BIT(CE_OTHER_IS_TOUCHING) &&
+           change->has_event[CE_TOUCHING_X] &&
            change->trigger_side & border_side &&
 #if 1
            IS_EQUAL_OR_IN_GROUP(border_element, change->trigger_element)
@@ -10105,7 +10742,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
 
     /* check for change of border element */
     if (IS_CUSTOM_ELEMENT(border_element) &&
-       HAS_ANY_CHANGE_EVENT(border_element, CE_OTHER_IS_TOUCHING))
+       HAS_ANY_CHANGE_EVENT(border_element, CE_TOUCHING_X))
     {
       for (j = 0; j < element_info[border_element].num_change_pages; j++)
       {
@@ -10113,7 +10750,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
          &element_info[border_element].change_page[j];
 
        if (change->can_change &&
-           change->events & CH_EVENT_BIT(CE_OTHER_IS_TOUCHING) &&
+           change->has_event[CE_TOUCHING_X] &&
            change->trigger_side & center_side &&
 #if 1
            IS_EQUAL_OR_IN_GROUP(center_element, change->trigger_element)
@@ -10127,7 +10764,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
 #endif
 
          CheckElementChangeByPage(xx, yy, border_element, center_element,
-                                  CE_OTHER_IS_TOUCHING, j);
+                                  CE_TOUCHING_X, j);
          break;
        }
       }
@@ -10141,7 +10778,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
 #endif
 
     CheckElementChangeByPage(x, y, center_element, border_trigger_element,
-                            CE_OTHER_IS_TOUCHING, center_element_change_page);
+                            CE_TOUCHING_X, center_element_change_page);
   }
 }
 
@@ -10171,8 +10808,11 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
   touched_element = (IN_LEV_FIELD(hitx, hity) ?
                     MovingOrBlocked2Element(hitx, hity) : EL_STEELWALL);
 
+#if !USE_HITTING_SOMETHING_BUGFIX
+  /* "hitting something" is also true when hitting the playfield border */
   CheckElementChangeBySide(x, y, hitting_element, touched_element,
                           CE_HITTING_SOMETHING, direction);
+#endif
 
   if (IN_LEV_FIELD(hitx, hity))
   {
@@ -10194,11 +10834,13 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
     {
       int i;
 
+#if !USE_HIT_BY_SOMETHING_BUGFIX
       CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
                               CE_HIT_BY_SOMETHING, opposite_direction);
+#endif
 
       if (IS_CUSTOM_ELEMENT(hitting_element) &&
-         HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
+         HAS_ANY_CHANGE_EVENT(hitting_element, CE_HITTING_X))
       {
        for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
        {
@@ -10206,7 +10848,7 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
            &element_info[hitting_element].change_page[i];
 
          if (change->can_change &&
-             change->events & CH_EVENT_BIT(CE_OTHER_IS_HITTING) &&
+             change->has_event[CE_HITTING_X] &&
              change->trigger_side & touched_side &&
          
 #if 1
@@ -10217,14 +10859,14 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
              )
          {
            CheckElementChangeByPage(x, y, hitting_element, touched_element,
-                                    CE_OTHER_IS_HITTING, i);
+                                    CE_HITTING_X, i);
            break;
          }
        }
       }
 
       if (IS_CUSTOM_ELEMENT(touched_element) &&
-         HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_HIT))
+         HAS_ANY_CHANGE_EVENT(touched_element, CE_HIT_BY_X))
       {
        for (i = 0; i < element_info[touched_element].num_change_pages; i++)
        {
@@ -10232,7 +10874,7 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
            &element_info[touched_element].change_page[i];
 
          if (change->can_change &&
-             change->events & CH_EVENT_BIT(CE_OTHER_GETS_HIT) &&
+             change->has_event[CE_HIT_BY_X] &&
              change->trigger_side & hitting_side &&
 #if 1
              IS_EQUAL_OR_IN_GROUP(hitting_element, change->trigger_element)
@@ -10242,13 +10884,24 @@ void TestIfElementHitsCustomElement(int x, int y, int direction)
              )
          {
            CheckElementChangeByPage(hitx, hity, touched_element,
-                                    hitting_element, CE_OTHER_GETS_HIT, i);
+                                    hitting_element, CE_HIT_BY_X, i);
            break;
          }
        }
       }
+
+#if USE_HIT_BY_SOMETHING_BUGFIX
+      CheckElementChangeBySide(hitx, hity, touched_element, hitting_element,
+                              CE_HIT_BY_SOMETHING, opposite_direction);
+#endif
     }
   }
+
+#if USE_HITTING_SOMETHING_BUGFIX
+  /* "hitting something" is also true when hitting the playfield border */
+  CheckElementChangeBySide(x, y, hitting_element, touched_element,
+                          CE_HITTING_SOMETHING, direction);
+#endif
 }
 
 #if 0
@@ -10313,7 +10966,7 @@ void TestIfElementSmashesCustomElement(int x, int y, int direction)
            &element_info[hitting_element].change_page[i];
 
          if (change->can_change &&
-             change->events & CH_EVENT_BIT(CE_OTHER_IS_SMASHING) &&
+             change->has_event[CE_OTHER_IS_SMASHING] &&
              change->trigger_side & touched_side &&
          
 #if 1
@@ -10339,7 +10992,7 @@ void TestIfElementSmashesCustomElement(int x, int y, int direction)
            &element_info[touched_element].change_page[i];
 
          if (change->can_change &&
-             change->events & CH_EVENT_BIT(CE_OTHER_GETS_SMASHED) &&
+             change->has_event[CE_OTHER_GETS_SMASHED] &&
              change->trigger_side & hitting_side &&
 #if 1
              IS_EQUAL_OR_IN_GROUP(hitting_element, change->trigger_element)
@@ -10752,7 +11405,11 @@ int DigField(struct PlayerInfo *player,
     if (mode == DF_NO_PUSH)    /* player just stopped pushing */
     {
       player->is_switching = FALSE;
+#if USE_NEW_PUSH_DELAY
+      player->push_delay = -1;
+#else
       player->push_delay = 0;
+#endif
 
       return MF_NO_ACTION;
     }
@@ -10975,14 +11632,14 @@ int DigField(struct PlayerInfo *player,
          return MF_NO_ACTION;  /* player cannot walk here due to gravity */
 #endif
 
-       if (IS_GATE(element))
+       if (IS_RND_GATE(element))
        {
-         if (!player->key[element - EL_GATE_1])
+         if (!player->key[RND_GATE_NR(element)])
            return MF_NO_ACTION;
        }
-       else if (IS_GATE_GRAY(element))
+       else if (IS_RND_GATE_GRAY(element))
        {
-         if (!player->key[element - EL_GATE_1_GRAY])
+         if (!player->key[RND_GATE_GRAY_NR(element)])
            return MF_NO_ACTION;
        }
        else if (element == EL_EXIT_OPEN ||
@@ -11045,12 +11702,12 @@ int DigField(struct PlayerInfo *player,
 
        if (IS_EM_GATE(element))
        {
-         if (!player->key[element - EL_EM_GATE_1])
+         if (!player->key[EM_GATE_NR(element)])
            return MF_NO_ACTION;
        }
        else if (IS_EM_GATE_GRAY(element))
        {
-         if (!player->key[element - EL_EM_GATE_1_GRAY])
+         if (!player->key[EM_GATE_GRAY_NR(element)])
            return MF_NO_ACTION;
        }
        else if (IS_SP_PORT(element))
@@ -11108,7 +11765,7 @@ int DigField(struct PlayerInfo *player,
 
        PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
 
-       CheckTriggeredElementChangeByPlayer(x, y, element,CE_OTHER_GETS_DIGGED,
+       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X,
                                            player->index_bit, dig_side);
 
 #if 1
@@ -11161,15 +11818,11 @@ int DigField(struct PlayerInfo *player,
        {
          player->dynabomb_xl = TRUE;
        }
-       else if ((element >= EL_KEY_1 && element <= EL_KEY_4) ||
-                (element >= EL_EM_KEY_1 && element <= EL_EM_KEY_4))
+       else if (IS_KEY(element))
        {
-         int key_nr = (element >= EL_KEY_1 && element <= EL_KEY_4 ?
-                       element - EL_KEY_1 : element - EL_EM_KEY_1);
-
-         player->key[key_nr] = TRUE;
+         player->key[KEY_NR(element)] = TRUE;
 
-         DrawGameValue_Keys(player);
+         DrawGameValue_Keys(player->key);
 
          redraw_mask |= REDRAW_DOOR_1;
        }
@@ -11210,7 +11863,7 @@ int DigField(struct PlayerInfo *player,
 
        if (is_player)
          CheckTriggeredElementChangeByPlayer(x, y, element,
-                                             CE_OTHER_GETS_COLLECTED,
+                                             CE_PLAYER_COLLECTS_X,
                                              player->index_bit, dig_side);
 
 #if 1
@@ -11315,16 +11968,56 @@ int DigField(struct PlayerInfo *player,
        if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
          return MF_NO_ACTION;
 
+#if USE_NEW_PUSH_DELAY
+
+#if 0
+       if ( (player->push_delay == -1) != (player->push_delay2 == 0) )
+         printf("::: ALERT: %d, %d [%d / %d]\n",
+                player->push_delay, player->push_delay2,
+                FrameCounter, FrameCounter / 50);
+#endif
+
+       if (player->push_delay == -1)   /* new pushing; restart delay */
+         player->push_delay = 0;
+#else
        if (player->push_delay == 0)    /* new pushing; restart delay */
          player->push_delay = FrameCounter;
+#endif
+
+#if USE_NEW_PUSH_DELAY
+#if 0
+       if ( (player->push_delay > 0) != (!xxx_fr) )
+         printf("::: PUSH BUG! %d, (%d -> %d) %d [%d / %d]\n",
+                player->push_delay,
+                xxx_pdv2, player->push_delay2, player->push_delay_value,
+                FrameCounter, FrameCounter / 50);
+#endif
+
+#if 0
+       if (player->push_delay > 0 &&
+           !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
+           element != EL_SPRING && element != EL_BALLOON)
+#else
+       /* !!! */
+       if (player->push_delay < player->push_delay_value &&
+           !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
+           element != EL_SPRING && element != EL_BALLOON)
+#endif
 
+#else
        if (!FrameReached(&player->push_delay, player->push_delay_value) &&
            !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
            element != EL_SPRING && element != EL_BALLOON)
+#endif
        {
          /* make sure that there is no move delay before next try to push */
+#if USE_NEW_MOVE_DELAY
+         if (game.engine_version >= VERSION_IDENT(3,0,7,1))
+           player->move_delay = 0;
+#else
          if (game.engine_version >= VERSION_IDENT(3,0,7,1))
            player->move_delay = INITIAL_MOVE_DELAY_OFF;
+#endif
 
          return MF_NO_ACTION;
        }
@@ -11384,22 +12077,40 @@ int DigField(struct PlayerInfo *player,
        else
          player->push_delay_value = -1;        /* get new value later */
 
+#if USE_PUSH_BUGFIX
+       /* now: check for element change _after_ element has been pushed! */
+#if 1
+       if (game.use_change_when_pushing_bug)
+#else
+       if (game.engine_version < VERSION_IDENT(3,1,0,0))
+#endif
+       {
+         CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
+                                    player->index_bit, dig_side);
+         CheckTriggeredElementChangeByPlayer(x,y, element, CE_PLAYER_PUSHES_X,
+                                             player->index_bit, dig_side);
+       }
+
+#else
+
 #if 1
        /* check for element change _after_ element has been pushed! */
 #else
 
 #if 1
-      /* !!! TEST ONLY !!! */
+       /* !!! TEST ONLY !!! */
        CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
                                   player->index_bit, dig_side);
-       CheckTriggeredElementChangeByPlayer(x, y, element,CE_OTHER_GETS_PUSHED,
+       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PUSHES_X,
                                            player->index_bit, dig_side);
 #else
-       CheckTriggeredElementChangeByPlayer(x, y, element,CE_OTHER_GETS_PUSHED,
+       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PUSHES_X,
                                            player->index_bit, dig_side);
        CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
                                   player->index_bit, dig_side);
 #endif
+#endif
+
 #endif
 
        break;
@@ -11409,7 +12120,7 @@ int DigField(struct PlayerInfo *player,
        if (PLAYER_SWITCHING(player, x, y))
        {
          CheckTriggeredElementChangeByPlayer(x,y, element,
-                                             CE_OTHER_GETS_PRESSED,
+                                             CE_PLAYER_PRESSES_X,
                                              player->index_bit, dig_side);
 
          return MF_ACTION;
@@ -11485,6 +12196,7 @@ int DigField(struct PlayerInfo *player,
          Feld[x][y] = EL_LAMP_ACTIVE;
          local_player->lights_still_needed--;
 
+         ResetGfxAnimation(x, y);
          DrawLevelField(x, y);
        }
        else if (element == EL_TIME_ORB_FULL)
@@ -11493,6 +12205,7 @@ int DigField(struct PlayerInfo *player,
          TimeLeft += 10;
          DrawGameValue_Time(TimeLeft);
 
+         ResetGfxAnimation(x, y);
          DrawLevelField(x, y);
 
 #if 0
@@ -11501,10 +12214,10 @@ int DigField(struct PlayerInfo *player,
        }
 
        CheckTriggeredElementChangeByPlayer(x, y, element,
-                                           CE_OTHER_IS_SWITCHING,
+                                           CE_SWITCH_OF_X,
                                            player->index_bit, dig_side);
 
-       CheckTriggeredElementChangeByPlayer(x,y, element,CE_OTHER_GETS_PRESSED,
+       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
                                            player->index_bit, dig_side);
 
        return MF_ACTION;
@@ -11522,11 +12235,11 @@ int DigField(struct PlayerInfo *player,
          CheckElementChangeByPlayer(x, y, element, CE_SWITCHED,
                                     player->index_bit, dig_side);
          CheckTriggeredElementChangeByPlayer(x, y, element,
-                                             CE_OTHER_IS_SWITCHING,
+                                             CE_SWITCH_OF_X,
                                              player->index_bit, dig_side);
 #else
          CheckTriggeredElementChangeByPlayer(x, y, element,
-                                             CE_OTHER_IS_SWITCHING,
+                                             CE_SWITCH_OF_X,
                                              player->index_bit, dig_side);
          CheckElementChangeByPlayer(x, y, element, CE_SWITCHED,
                                     player->index_bit, dig_side);
@@ -11537,10 +12250,10 @@ int DigField(struct PlayerInfo *player,
        /* !!! TEST ONLY !!! (this breaks "machine", level 000) */
        CheckElementChangeByPlayer(x, y, element, CE_PRESSED_BY_PLAYER,
                                   player->index_bit, dig_side);
-       CheckTriggeredElementChangeByPlayer(x,y, element,CE_OTHER_GETS_PRESSED,
+       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
                                            player->index_bit, dig_side);
 #else
-       CheckTriggeredElementChangeByPlayer(x,y, element,CE_OTHER_GETS_PRESSED,
+       CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
                                            player->index_bit, dig_side);
        CheckElementChangeByPlayer(x, y, element, CE_PRESSED_BY_PLAYER,
                                   player->index_bit, dig_side);
@@ -11550,10 +12263,19 @@ int DigField(struct PlayerInfo *player,
       return MF_NO_ACTION;
   }
 
+#if USE_NEW_PUSH_DELAY
+  player->push_delay = -1;
+#else
   player->push_delay = 0;
+#endif
 
-  if (Feld[x][y] != element)           /* really digged/collected something */
-    player->is_collecting = !player->is_digging;
+#if USE_PENGUIN_COLLECT_BUGFIX
+  if (is_player)               /* function can also be called by EL_PENGUIN */
+#endif
+  {
+    if (Feld[x][y] != element)         /* really digged/collected something */
+      player->is_collecting = !player->is_digging;
+  }
 
   return MF_MOVING;
 }
@@ -11667,6 +12389,15 @@ boolean DropElement(struct PlayerInfo *player)
                      EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr :
                      EL_UNDEFINED);
 
+#if USE_DROP_BUGFIX
+  /* do not drop an element on top of another element; when holding drop key
+     pressed without moving, dropped element must move away before the next
+     element can be dropped (this is especially important if the next element
+     is dynamite, which can be placed on background for historical reasons) */
+  if (PLAYER_DROPPING(player, dropx, dropy) && Feld[dropx][dropy] != EL_EMPTY)
+    return MF_ACTION;
+#endif
+
   if (IS_THROWABLE(drop_element))
   {
     dropx += GET_DX_FROM_DIR(drop_direction);
@@ -11744,7 +12475,7 @@ boolean DropElement(struct PlayerInfo *player)
 
 #if 1
     /* needed if previous element just changed to "empty" in the last frame */
-    Changed[dropx][dropy] = 0;         /* allow another change */
+    Changed[dropx][dropy] = FALSE;             /* allow another change */
 #endif
 
 #if 1
@@ -11752,11 +12483,11 @@ boolean DropElement(struct PlayerInfo *player)
     CheckElementChangeByPlayer(dropx, dropy, new_element, CE_DROPPED_BY_PLAYER,
                               player->index_bit, drop_side);
     CheckTriggeredElementChangeByPlayer(dropx, dropy, new_element,
-                                       CE_OTHER_GETS_DROPPED,
+                                       CE_PLAYER_DROPS_X,
                                        player->index_bit, drop_side);
 #else
     CheckTriggeredElementChangeByPlayer(dropx, dropy, new_element,
-                                       CE_OTHER_GETS_DROPPED,
+                                       CE_PLAYER_DROPS_X,
                                        player->index_bit, drop_side);
     CheckElementChangeByPlayer(dropx, dropy, new_element, CE_DROPPED_BY_PLAYER,
                               player->index_bit, drop_side);
@@ -11814,7 +12545,7 @@ boolean DropElement(struct PlayerInfo *player)
     nexty = dropy + GET_DY_FROM_DIR(move_direction);
 
 #if 1
-    Changed[dropx][dropy] = 0;         /* allow another change */
+    Changed[dropx][dropy] = FALSE;             /* allow another change */
     CheckCollision[dropx][dropy] = 2;
 #else
 
@@ -11833,7 +12564,7 @@ boolean DropElement(struct PlayerInfo *player)
     /* !!! commented out from 3.1.0-4 to 3.1.0-5 !!! */
     else
     {
-      Changed[dropx][dropy] = 0;       /* allow another change */
+      Changed[dropx][dropy] = FALSE;   /* allow another change */
 
 #if 1
       TestIfElementHitsCustomElement(dropx, dropy, move_direction);
@@ -11863,6 +12594,10 @@ boolean DropElement(struct PlayerInfo *player)
 
   player->is_dropping = TRUE;
 
+#if USE_DROP_BUGFIX
+  player->drop_x = dropx;
+  player->drop_y = dropy;
+#endif
 
   return TRUE;
 }
@@ -11985,6 +12720,168 @@ static void PlayLevelMusic()
     PlayMusic(MAP_NOCONF_MUSIC(level_nr));     /* from music dir */
 }
 
+void PlayLevelSound_EM(int x, int y, int element_em, int sample)
+{
+  int element = (element_em > -1 ? map_element_EM_to_RND(element_em) : 0);
+
+#if 0
+  if (sample == SAMPLE_bug)
+    printf("::: PlayLevelSound_EM: %d, %d: %d\n", x, y, sample);
+#endif
+
+  switch (sample)
+  {
+    case SAMPLE_blank:
+      PlayLevelSoundElementAction(x, y, element, ACTION_WALKING);
+      break;
+
+    case SAMPLE_roll:
+      PlayLevelSoundElementAction(x, y, element, ACTION_PUSHING);
+      break;
+
+    case SAMPLE_stone:
+      PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
+      break;
+
+    case SAMPLE_nut:
+      PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
+      break;
+
+    case SAMPLE_crack:
+      PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING);
+      break;
+
+    case SAMPLE_bug:
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
+      break;
+
+    case SAMPLE_tank:
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
+      break;
+
+    case SAMPLE_android_clone:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING);
+      break;
+
+    case SAMPLE_android_move:
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
+      break;
+
+    case SAMPLE_spring:
+      PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
+      break;
+
+    case SAMPLE_slurp:
+      PlayLevelSoundElementAction(x, y, element, ACTION_SLURPED_BY_SPRING);
+      break;
+
+    case SAMPLE_eater:
+      PlayLevelSoundElementAction(x, y, element, ACTION_WAITING);
+      break;
+
+    case SAMPLE_eater_eat:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
+      break;
+
+    case SAMPLE_alien:
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
+      break;
+
+    case SAMPLE_collect:
+      PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING);
+      break;
+
+    case SAMPLE_diamond:
+      PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
+      break;
+
+    case SAMPLE_squash:
+      /* !!! CHECK THIS !!! */
+#if 1
+      PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING);
+#else
+      PlayLevelSoundElementAction(x, y, element, ACTION_SMASHED_BY_ROCK);
+#endif
+      break;
+
+    case SAMPLE_wonderfall:
+      PlayLevelSoundElementAction(x, y, element, ACTION_FILLING);
+      break;
+
+    case SAMPLE_drip:
+      PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
+      break;
+
+    case SAMPLE_push:
+      PlayLevelSoundElementAction(x, y, element, ACTION_PUSHING);
+      break;
+
+    case SAMPLE_dirt:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
+      break;
+
+    case SAMPLE_acid:
+      PlayLevelSoundElementAction(x, y, element, ACTION_SPLASHING);
+      break;
+
+    case SAMPLE_ball:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING);
+      break;
+
+    case SAMPLE_grow:
+      PlayLevelSoundElementAction(x, y, element, ACTION_GROWING);
+      break;
+
+    case SAMPLE_wonder:
+      PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE);
+      break;
+
+    case SAMPLE_door:
+      PlayLevelSoundElementAction(x, y, element, ACTION_PASSING);
+      break;
+
+    case SAMPLE_exit_open:
+      PlayLevelSoundElementAction(x, y, element, ACTION_OPENING);
+      break;
+
+    case SAMPLE_exit_leave:
+      PlayLevelSoundElementAction(x, y, element, ACTION_PASSING);
+      break;
+
+    case SAMPLE_dynamite:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING);
+      break;
+
+    case SAMPLE_tick:
+      PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE);
+      break;
+
+    case SAMPLE_press:
+      PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVATING);
+      break;
+
+    case SAMPLE_wheel:
+      PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE);
+      break;
+
+    case SAMPLE_boom:
+      PlayLevelSoundElementAction(x, y, element, ACTION_EXPLODING);
+      break;
+
+    case SAMPLE_die:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DYING);
+      break;
+
+    case SAMPLE_time:
+      PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
+      break;
+
+    default:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DEFAULT);
+      break;
+  }
+}
+
 void RaiseScore(int value)
 {
   local_player->score += value;
@@ -12054,6 +12951,14 @@ void RaiseScoreElement(int element)
     case EL_KEY_2:
     case EL_KEY_3:
     case EL_KEY_4:
+    case EL_EM_KEY_1:
+    case EL_EM_KEY_2:
+    case EL_EM_KEY_3:
+    case EL_EM_KEY_4:
+    case EL_EMC_KEY_5:
+    case EL_EMC_KEY_6:
+    case EL_EMC_KEY_7:
+    case EL_EMC_KEY_8:
       RaiseScore(level.score[SC_KEY]);
       break;
     default:
index ba51836515b64bcb36dda560b81aa80201a53fb8..4bca9fd69f8253151c8dc6194e2e4cc3256f9f7f 100644 (file)
 #include "main.h"
 
 void GetPlayerConfig(void);
+
+void DrawGameValue_Time(int);
 void DrawGameDoorValues(void);
+
 void InitGameSound();
 void InitGame(void);
+
+void UpdateEngineValues(int, int);
+
 void InitMovDir(int, int);
 void InitAmoebaNr(int, int);
 void GameWon(void);
@@ -76,6 +82,7 @@ boolean SnapField(struct PlayerInfo *, int, int);
 boolean DropElement(struct PlayerInfo *);
 
 void InitPlayLevelSound();
+void PlayLevelSound_EM(int, int, int, int);
 
 void RaiseScore(int);
 void RaiseScoreElement(int);
diff --git a/src/game_em/Makefile b/src/game_em/Makefile
new file mode 100644 (file)
index 0000000..aec69d0
--- /dev/null
@@ -0,0 +1,69 @@
+# =============================================================================
+# Rocks'n'Diamonds Makefile (game_em)
+# -----------------------------------------------------------------------------
+# (c) 1995-2005 Holger Schemel <info@artsoft.org>
+# -----------------------------------------------------------------------------
+# Emerald Mine for X11 Â© 2000,2001 David Tritscher
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# configuration
+# -----------------------------------------------------------------------------
+
+SRCS = cave.c          \
+       convert.c       \
+       graphics.c      \
+       init.c          \
+       input.c         \
+       main.c          \
+       sound.c         \
+       synchro_1.c     \
+       synchro_2.c     \
+       synchro_3.c     \
+       tab_generate.c  \
+       ulaw_generate.c
+
+OBJS = cave.o          \
+       convert.o       \
+       graphics.o      \
+       init.o          \
+       input.o         \
+       main.o          \
+       sound.o         \
+       synchro_1.o     \
+       synchro_2.o     \
+       synchro_3.o     \
+       tab_generate.o  \
+       ulaw_generate.o
+
+GAME_EM = game_em.a
+
+
+# -----------------------------------------------------------------------------
+# build targets
+# -----------------------------------------------------------------------------
+
+all: $(GAME_EM)
+
+$(GAME_EM): $(OBJS)
+       $(AR) cru $(GAME_EM) $(OBJS)
+       $(RANLIB) $(GAME_EM)
+
+.c.o:
+       $(CC) $(PROFILING) $(CFLAGS) -c $*.c
+
+clean:
+       $(RM) $(OBJS)
+       $(RM) $(GAME_EM)
+
+
+# -----------------------------------------------------------------------------
+# development only
+# -----------------------------------------------------------------------------
+
+depend:
+       for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/src/game_em/cave.c b/src/game_em/cave.c
new file mode 100644 (file)
index 0000000..22ea317
--- /dev/null
@@ -0,0 +1,101 @@
+/* 2000-08-10T16:43:50Z
+ *
+ * cave data structures
+ */
+
+#include "global.h"
+#include "tile.h"
+#include "level.h"
+
+
+struct LevelInfo_EM native_em_level;
+
+void setLevelInfoToDefaults_EM(void)
+{
+  int i;
+
+  native_em_level.file_version = FILE_VERSION_EM_ACTUAL;
+
+  native_em_level.lev = &lev;
+  native_em_level.ply1 = &ply1;
+  native_em_level.ply2 = &ply2;
+
+  lev.width = 64;
+  lev.height = 32;
+
+  ply1.x_initial = 0;
+  ply1.y_initial = 0;
+
+  ply2.x_initial = 0;
+  ply2.y_initial = 0;
+
+  lev.lenses_cnt_initial = 0;
+  lev.magnify_cnt_initial = 0;
+
+  lev.wheel_cnt_initial = 0;
+  lev.wheel_x_initial = 1;
+  lev.wheel_y_initial = 1;
+
+  lev.wind_time = 9999;
+  lev.wind_cnt_initial = 0;
+
+  lev.wonderwall_state_initial = 0;
+  lev.wonderwall_time_initial = 0;
+
+  for (i = 0; i < TILE_MAX; i++)
+    lev.android_array[i] = Xblank;
+
+  lev.home_initial = 1;                /* initial number of players in this level */
+
+  ply1.alive_initial = (lev.home_initial >= 1);
+  ply2.alive_initial = (lev.home_initial >= 2);
+}
+
+
+/* load cave
+ * 
+ * completely initializes the level structure, ready for a game
+ */
+
+#define MAX_EM_LEVEL_SIZE              16384
+
+boolean LoadNativeLevel_EM(char *filename)
+{
+  unsigned char raw_leveldata[MAX_EM_LEVEL_SIZE];
+  int raw_leveldata_length;
+  int file_version;
+  FILE *file;
+
+  /* always start with reliable default values */
+  setLevelInfoToDefaults_EM();
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    Error(ERR_WARN, "cannot open level '%s' -- using empty level", filename);
+
+    return FALSE;
+  }
+
+  raw_leveldata_length = fread(raw_leveldata, 1, MAX_EM_LEVEL_SIZE, file);
+
+  fclose(file);
+
+  if (raw_leveldata_length <= 0)
+  {
+    Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+
+    return FALSE;
+  }
+
+  if (!(file_version = cleanup_em_level(raw_leveldata, raw_leveldata_length)))
+  {
+    Error(ERR_WARN, "unknown EM level '%s' -- using empty level", filename);
+
+    return FALSE;
+  }
+
+  convert_em_level(raw_leveldata, file_version);
+  prepare_em_level();
+
+  return TRUE;
+}
diff --git a/src/game_em/convert.c b/src/game_em/convert.c
new file mode 100644 (file)
index 0000000..6287eea
--- /dev/null
@@ -0,0 +1,967 @@
+/* 2000-08-20T09:41:18Z
+ *
+ * identify all emerald mine caves and turn them into v6 format.
+ * fixes illegal tiles, acid, wheel, limits times, cleans flags.
+ *
+ * these tables weed out bad tiles for older caves (eg. wheel on -> wheel off)
+ * and clean up v6 caves (acid, number limits) which should(!) be
+ * inconsequential, but no doubt it will break some caves.
+ */
+
+#include "global.h"
+#include "tile.h"
+#include "level.h"
+
+
+static unsigned char remap_v6[256] =
+{
+  /* filter crap for v6 */
+
+  0,0,2,2,         4,4,118,118,     8,9,10,11,       12,13,14,15,
+  16,16,18,18,     20,21,22,23,     24,25,26,27,     28,28,118,28,
+  0,16,2,18,       36,37,37,37,     40,41,42,43,     44,45,128,128,
+  128,148,148,     148,45,45,45,    148,0,57,58,     59,60,61,62,63,
+
+  64,65,66,67,     68,69,69,69,     69,73,74,75,     118,75,75,75,
+  75,75,75,75,     75,153,153,153,  153,153,153,153, 153,153,153,153,
+  153,153,153,99,  100,68,68,68,    68,68,68,68,     68,118,118,118,
+  118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
+
+  128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
+  144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
+  160,161,162,163, 164,165,165,118, 168,169,170,171, 172,173,174,175,
+  176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,191,
+
+  192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207,
+  208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
+  224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
+  240,241,242,243, 244,245,153,153, 153,153,153,153, 153,153,153,153
+};
+
+static unsigned char remap_v5[256] =
+{
+  /* filter crap for v5 */
+
+  0,0,2,2,         4,4,118,118,     8,9,10,11,       12,13,14,15,
+  16,16,18,18,     20,21,22,23,     24,25,26,27,     28,28,118,28,
+  0,16,2,18,       36,37,37,37,     147,41,42,43,    44,45,128,128,
+  128,148,148,148, 45,45,45,148,    0,57,58,59,      60,61,62,63,
+
+  64,65,66,67,     68,153,153,153,  153,153,153,153, 153,153,153,153,
+  153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
+  153,153,153,153, 153,68,68,68,68, 68,68,68,68,118, 118,118,
+  118,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
+
+  128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
+  144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159,
+  160,153,153,153, 153,153,153,118, 168,169,170,171, 172,173,174,175,
+  176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,68,153,
+
+  153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
+  208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
+  224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
+  240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
+};
+
+static unsigned char remap_v4[256] =
+{
+  /* filter crap for v4 */
+
+  0,0,2,2,         4,4,118,118,     8,9,10,11,       12,13,14,15,
+  16,16,18,18,     20,21,22,23,     24,25,26,27,     28,28,118,28,
+  0,16,2,18,       36,37,37,37,     147,41,42,43,    44,45,128,128,
+  128,148,148,148, 45,45,45,148,    0,153,153,59,    60,61,62,63,
+
+  64,65,66,153,    153,153,153,153, 153,153,153,153, 153,153,153,153,
+  153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
+  153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153,
+  153,118,114,115, 131,118,118,119, 120,121,122,118, 118,118,118,118,
+
+  128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143,
+  144,145,146,147, 148,149,150,151, 152,68,154,155,  156,157,158,160,
+  160,160,160,160, 160,160,160,160, 160,160,160,160, 160,160,160,175,
+  153,153,153,153, 153,153,153,153, 153,153,153,153, 153,153,68,153,
+
+  153,153,153,153, 153,153,153,153, 200,201,202,203, 204,205,206,207,
+  208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223,
+  224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239,
+  240,241,153,153, 153,153,153,153, 153,153,153,153, 153,153,153,153
+};
+
+static unsigned char remap_v4eater[28] =
+{
+  /* filter crap for v4 */
+
+  128,18,2,0,4,8,16,20,28,37,
+  41,45,130,129,131,132,133,134,135,136,
+  146,147,175,65,66,64,2,18
+};
+
+int cleanup_em_level(unsigned char *src, int length)
+{
+  int file_version = 0;
+  int i;
+
+  if (length >= 2172 &&
+      src[2106] == 255 &&
+      src[2107] == 54 &&
+      src[2108] == 48 &&
+      src[2109] == 48)
+  {
+    /* ---------- this cave has V6 file format ---------- */
+    file_version = FILE_VERSION_EM_V6;
+
+    for (i = 0; i < 2048; i++)
+      src[i] = remap_v6[src[i]];
+    for (i = 2048; i < 2084; i++)
+      src[i] = remap_v6[src[i]];
+    for (i = 2112; i < 2148; i++)
+      src[i] = remap_v6[src[i]];
+  }
+  else if (length >= 2110 &&
+          src[2106] == 255 &&
+          src[2107] == 53 &&
+          src[2108] == 48 &&
+          src[2109] == 48)
+  {
+    /* ---------- this cave has V5 file format ---------- */
+    file_version = FILE_VERSION_EM_V5;
+
+    for (i = 0; i < 2048; i++)
+      src[i] = remap_v5[src[i]];
+    for (i = 2048; i < 2084; i++)
+      src[i] = remap_v5[src[i]];
+    for (i = 2112; i < 2148; i++)
+      src[i] = src[i - 64];
+  }
+#if 0
+  else if (length >= 2106)     /* !!! TEST ONLY: SHOW BROKEN LEVELS !!! */
+#else
+  else if (length >= 2106 &&
+          src[1983] == 116)
+#endif
+  {
+    /* ---------- this cave has V4 file format ---------- */
+    file_version = FILE_VERSION_EM_V4;
+
+    for (i = 0; i < 2048; i++)
+      src[i] = remap_v4[src[i]];
+    for (i = 2048; i < 2084; i++)
+      src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
+    for (i = 2112; i < 2148; i++) src[i] = src[i - 64];
+  }
+  else if (length >= 2106 &&
+          src[0] == 241 &&
+          src[1983] == 27)
+  {
+    unsigned char j = 94;
+
+    /* ---------- this cave has V3 file format ---------- */
+    file_version = FILE_VERSION_EM_V3;
+
+    for (i = 0; i < 2106; i++)
+      src[i] = (src[i] ^ (j += 7)) - 0x11;
+    src[1] = 131;
+    for (i = 0; i < 2048; i++)
+      src[i] = remap_v4[src[i]];
+    for (i = 2048; i < 2084; i++)
+      src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
+    for (i = 2112; i < 2148; i++)
+      src[i] = src[i - 64];
+  }
+#if 1
+  else if (length >= 2106 &&
+          src[0] == 245 &&
+          src[1983] == 27)
+  {
+    unsigned char j = 94;
+
+    /* ---------- this cave has V3 file format ---------- */
+    file_version = FILE_VERSION_EM_V3;
+
+    for (i = 0; i < 2106; i++)
+      src[i] = (src[i] ^ (j += 7)) - 0x11;
+    src[1] = 131;
+    for (i = 0; i < 2048; i++)
+      src[i] = remap_v4[src[i]];
+    for (i = 2048; i < 2084; i++)
+      src[i] = remap_v4eater[src[i] >= 28 ? 0 : src[i]];
+    for (i = 2112; i < 2148; i++)
+      src[i] = src[i - 64];
+  }
+#endif
+  else
+  {
+    /* ---------- this cave has unknown file format ---------- */
+
+#if 1
+    printf("::: %d, %d\n", src[0], src[1983]);
+#endif
+
+    return 0;
+  }
+
+  if (file_version < FILE_VERSION_EM_V6)
+  {
+    /* id */
+    src[2106] = 255;
+    src[2107] = 54;
+    src[2108] = 48;
+    src[2109] = 48;
+
+    /* time */
+    i = src[2094] * 10;
+    src[2110] = i >> 8;
+    src[2111] = i;
+
+    for (i = 2148; i < 2172; i++)
+      src[i] = 0;
+
+    /* ball data */
+    src[2159] = 128;
+  }
+
+  /* ---------- at this stage, the cave data always has V6 format ---------- */
+
+  /* fix wheel */
+  for (i = 0; i < 2048; i++)
+    if (src[i] == 40)
+      break;
+  for (i++; i < 2048; i++)
+    if (src[i] == 40)
+      src[i] = 147;
+
+#if 0
+  /* fix acid */
+  for (i = 64; i < 2048; i++)
+    if (src[i] == 63)          /* replace element above 'Xacid_s' ... */
+      src[i - 64] = 101;       /* ... with 'Xacid_1' */
+
+#else
+
+  /* fix acid */
+  for (i = 64; i < 2048; i++)
+  {
+    if (src[i] == 63)          /* 'Xacid_s' (acid pool, bottom middle) */
+    {
+      if (file_version == FILE_VERSION_EM_V4 &&
+         i < 2048 - 64 && src[i + 64] == 63)
+       src[i - 64] = 255;      /* replace element above with 'Xfake_acid_1' */
+      else
+       src[i - 64] = 101;      /* replace element above with 'Xacid_1' */
+    }
+  }
+#endif
+
+  /* fix acid in eater 1 */
+  for (i = 2051; i < 2057; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 2 */
+  for (i = 2060; i < 2066; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 3 */
+  for (i = 2069; i < 2075; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 4 */
+  for (i = 2078; i < 2084; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 5 */
+  for (i = 2115; i < 2121; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 6 */
+  for (i = 2124; i < 2130; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 7 */
+  for (i = 2133; i < 2139; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* fix acid in eater 8 */
+  for (i = 2142; i < 2148; i++)
+    if (src[i] == 63)
+      src[i - 3] = 101;
+
+  /* old style time */
+  src[2094] = 0;
+
+  /* player 1 pos */
+  src[2096] &= 7;
+  src[src[2096] << 8 | src[2097]] = 128;
+
+  /* player 2 pos */
+  src[2098] &= 7;
+  src[src[2098] << 8 | src[2099]] = 128;
+
+  /* amoeba speed */
+  if ((src[2100] << 8 | src[2101]) > 9999)
+  {
+    src[2100] = 39;
+    src[2101] = 15;
+  }
+
+  /* time wonderwall */
+  if ((src[2102] << 8 | src[2103]) > 9999)
+  {
+    src[2102] = 39;
+    src[2103] = 15;
+  }
+
+  /* time */
+  if ((src[2110] << 8 | src[2111]) > 9999)
+  {
+    src[2110] = 39;
+    src[2111] = 15;
+  }
+
+  /* wind direction */
+  i = src[2149];
+  i &= 15;
+  i &= -i;
+  src[2149] = i;
+
+  /* time lenses */
+  if ((src[2154] << 8 | src[2155]) > 9999)
+  {
+    src[2154] = 39;
+    src[2155] = 15;
+  }
+
+  /* time magnify */
+  if ((src[2156] << 8 | src[2157]) > 9999)
+  {
+    src[2156] = 39;
+    src[2157] = 15;
+  }
+
+  /* ball object */
+  src[2158] = 0;
+  src[2159] = remap_v6[src[2159]];
+
+  /* ball pause */
+  if ((src[2160] << 8 | src[2161]) > 9999)
+  {
+    src[2160] = 39;
+    src[2161] = 15;
+  }
+
+  /* ball data */
+  src[2162] &= 129;
+  if (src[2162] & 1)
+    src[2163] = 0;
+
+  /* android move pause */
+  if ((src[2164] << 8 | src[2165]) > 9999)
+  {
+    src[2164] = 39;
+    src[2165] = 15;
+  }
+
+  /* android clone pause */
+  if ((src[2166] << 8 | src[2167]) > 9999)
+  {
+    src[2166] = 39;
+    src[2167] = 15;
+  }
+
+  /* android data */
+  src[2168] &= 31;
+
+  /* size of v6 cave */
+  length = 2172;
+
+#if 1
+  if (options.debug)
+    printf("::: EM level file version: %d\n", file_version);
+#endif
+
+  return file_version;
+}
+
+/* 2000-07-30T00:26:00Z
+ *
+ * Read emerald mine caves version 6
+ *
+ * v4 and v5 emerald mine caves are converted to v6 (which completely supports
+ * older versions)
+ * 
+ * converting to the internal format loses /significant/ information which can
+ * break lots of caves.
+ * 
+ * major incompatibilities:
+ * - borderless caves behave completely differently, the player no longer
+ *   "warps" to the other side.
+ * - a compile time option for spring can make it behave differently when it
+ *   rolls.
+ * - a compile time option for rolling objects (stone, nut, spring, bomb) only
+ *   in eater.
+ * - acid is always deadly even with no base beneath it (this breaks cave 0 in
+ *   downunder mine 16)
+ *
+ * so far all below have not broken any caves:
+ *
+ * - active wheel inside an eater will not function, eater explosions will not
+ *   change settings.
+ * - initial collect objects (emerald, diamond, dynamite) don't exist.
+ * - initial rolling objects will be moved manually and made into sitting
+ *   objects.
+ * - drips always appear from dots.
+ * - more than one thing can fall into acid at the same time.
+ * - acid explodes when the player walks into it, rather than splashing.
+ * - simultaneous explosions may be in a slightly different order.
+ * - quicksand states have been reduced.
+ * - acid base is effectively an indestructable wall now which can affect eater
+ *   explosions.
+ * - android can clone forever with a clone pause of 0 (emeralds, diamonds,
+ *   nuts, stones, bombs, springs).
+ *
+ * 2001-03-12T02:46:55Z
+ * - rolling stuff is now allowed in the cave, i didn't like making this
+ *   decision.
+ * - if BAD_ROLL is not defined, initial rolling objects are moved by hand.
+ * - initial collect objects break some cave in elvis mine 5.
+ * - different timing for wonderwall break some cave in exception mine 2.
+ * - i think i'm pretty locked into always using the bad roll. *sigh*
+ * - rolling spring is now turned into regular spring. it appears the emc
+ *   editor only uses the force code for initially moving spring. i will
+ *   follow this in my editor.
+ */
+
+static unsigned short remap_emerald[256] =
+{
+  Xstone,              Xstone,         Xdiamond,       Xdiamond,
+  Xalien,              Xalien,         Xblank,         Xblank,
+  Xtank_n,             Xtank_e,        Xtank_s,        Xtank_w,
+  Xtank_gon,           Xtank_goe,      Xtank_gos,      Xtank_gow,
+
+  Xbomb,               Xbomb,          Xemerald,       Xemerald,
+  Xbug_n,              Xbug_e,         Xbug_s,         Xbug_w,
+  Xbug_gon,            Xbug_goe,       Xbug_gos,       Xbug_gow,
+  Xdrip_eat,           Xdrip_eat,      Xdrip_eat,      Xdrip_eat,
+
+  Xstone,              Xbomb,          Xdiamond,       Xemerald,
+  Xwonderwall,         Xnut,           Xnut,           Xnut,
+  Xwheel,              Xeater_n,       Xeater_s,       Xeater_w,
+  Xeater_e,            Xsand_stone,    Xblank,         Xblank,
+
+  Xblank,              Xsand,          Xsand,          Xsand,
+  Xsand_stone,         Xsand_stone,    Xsand_stone,    Xsand,
+  Xstone,              Xgrow_ew,       Xgrow_ns,       Xdynamite_1,
+  Xdynamite_2,         Xdynamite_3,    Xdynamite_4,    Xacid_s,
+
+  Xexit_1,             Xexit_2,        Xexit_3,        Xballoon,
+  Xplant,              Xspring,        Xspring,        Xspring,
+  Xspring,             Xball_1,        Xball_2,        Xandroid,
+  Xblank,              Xandroid,       Xandroid,       Xandroid,
+
+  Xandroid,            Xandroid,       Xandroid,       Xandroid,
+  Xandroid,            Xblank,         Xblank,         Xblank,
+  Xblank,              Xblank,         Xblank,         Xblank,
+  Xblank,              Xblank,         Xblank,         Xblank,
+
+#ifdef BAD_ROLL
+
+  Xblank,              Xblank,         Xblank,         Xspring_force_w,
+  Xspring_force_e,     Xacid_1,        Xacid_2,        Xacid_3,
+  Xacid_4,             Xacid_5,        Xacid_6,        Xacid_7,
+  Xacid_8,             Xblank,         Xblank,         Xblank,
+
+  Xblank,              Xblank,         Xnut_force_w,   Xnut_force_e,
+  Xsteel_1,            Xblank,         Xblank,         Xbomb_force_w,
+  Xbomb_force_e,       Xstone_force_w, Xstone_force_e, Xblank,
+  Xblank,              Xblank,         Xblank,         Xblank,
+
+#else
+
+  Xblank,              Xblank,         Xblank,         Xspring,
+  Xspring,             Xacid_1,        Xacid_2,        Xacid_3,
+  Xacid_4,             Xacid_5,        Xacid_6,        Xacid_7,
+  Xacid_8,             Xblank,         Xblank,         Xblank,
+
+  Xblank,              Xblank,         Xnut,           Xnut,
+  Xsteel_1,            Xblank,         Xblank,         Xbomb,
+  Xbomb,               Xstone,         Xstone,         Xblank,
+  Xblank,              Xblank,         Xblank,         Xblank,
+
+#endif
+
+  Xblank,              Xround_wall_1,  Xgrass,         Xsteel_1,
+  Xwall_1,             Xkey_1,         Xkey_2,         Xkey_3,
+  Xkey_4,              Xdoor_1,        Xdoor_2,        Xdoor_3,
+  Xdoor_4,             Xdripper,       Xfake_door_1,   Xfake_door_2,
+
+  Xfake_door_3,                Xfake_door_4,   Xwonderwall,    Xwheel,
+  Xsand,               Xacid_nw,       Xacid_ne,       Xacid_sw,
+  Xacid_se,            Xfake_blank,    Xamoeba_1,      Xamoeba_2,
+  Xamoeba_3,           Xamoeba_4,      Xexit,          Xalpha_arrow_w,
+
+  Xfake_grass,         Xlenses,        Xmagnify,       Xfake_blank,
+  Xfake_grass,         Xswitch,        Xswitch,        Xblank,
+  Xdecor_8,            Xdecor_9,       Xdecor_10,      Xdecor_5,
+  Xalpha_comma,                Xalpha_quote,   Xalpha_minus,   Xdynamite,
+
+  Xsteel_3,            Xdecor_6,       Xdecor_7,       Xsteel_2,
+  Xround_wall_2,       Xdecor_2,       Xdecor_4,       Xdecor_3,
+  Xwind_nesw,          Xwind_e,        Xwind_s,        Xwind_w,
+  Xwind_n,             Xdirt,          Xplant,         Xkey_5,
+
+  Xkey_6,              Xkey_7,         Xkey_8,         Xdoor_5,
+  Xdoor_6,             Xdoor_7,        Xdoor_8,        Xbumper,
+  Xalpha_a,            Xalpha_b,       Xalpha_c,       Xalpha_d,
+  Xalpha_e,            Xalpha_f,       Xalpha_g,       Xalpha_h,
+
+  Xalpha_i,            Xalpha_j,       Xalpha_k,       Xalpha_l,
+  Xalpha_m,            Xalpha_n,       Xalpha_o,       Xalpha_p,
+  Xalpha_q,            Xalpha_r,       Xalpha_s,       Xalpha_t,
+  Xalpha_u,            Xalpha_v,       Xalpha_w,       Xalpha_x,
+
+  Xalpha_y,            Xalpha_z,       Xalpha_0,       Xalpha_1,
+  Xalpha_2,            Xalpha_3,       Xalpha_4,       Xalpha_5,
+  Xalpha_6,            Xalpha_7,       Xalpha_8,       Xalpha_9,
+  Xalpha_perio,                Xalpha_excla,   Xalpha_colon,   Xalpha_quest,
+
+  Xalpha_arrow_e,      Xdecor_1,       Xfake_door_5,   Xfake_door_6,
+  Xfake_door_7,                Xfake_door_8,   Xblank,         Xblank,
+  Xblank,              Xblank,         Xblank,         Xblank,
+#if 0
+  Xblank,              Xblank,         Xblank,         Xblank,
+#else
+  /* special elements added to solve compatibility problems */
+  Xblank,              Xblank,         Xblank,         Xfake_acid_1
+#endif
+};
+
+void convert_em_level(unsigned char *src, int file_version)
+{
+  static int eater_offset[8] =
+  {
+    0x800, 0x809, 0x812, 0x81B, 0x840, 0x849, 0x852, 0x85B
+  };
+  unsigned int i, x, y, temp;
+
+#if 1
+  lev.time_seconds = src[0x83E] << 8 | src[0x83F];
+  if (lev.time_seconds > 9999)
+    lev.time_seconds = 9999;
+#else
+  temp = ((src[0x83E] << 8 | src[0x83F]) * 25 + 3) / 4;
+  if (temp == 0 || temp > 9999)
+    temp = 9999;
+  lev.time_initial = temp;
+#endif
+
+  lev.required_initial = src[0x82F];
+
+  temp = src[0x830] << 8 | src[0x831];
+  ply1.x_initial = (temp & 63) + 1;
+  ply1.y_initial = (temp >> 6 & 31) + 1;
+  temp = src[0x832] << 8 | src[0x833];
+  ply2.x_initial = (temp & 63) + 1;
+  ply2.y_initial = (temp >> 6 & 31) + 1;
+
+  temp = (src[0x834] << 8 | src[0x835]) * 28;
+  if (temp > 9999)
+    temp = 9999;
+  lev.amoeba_time = temp;
+
+  lev.android_move_time = src[0x874] << 8 | src[0x875];
+  lev.android_clone_time = src[0x876] << 8 | src[0x877];
+
+  lev.ball_random = src[0x872] & 1 ? 1 : 0;
+  lev.ball_state_initial = src[0x872] & 128 ? 1 : 0;
+  lev.ball_time = src[0x870] << 8 | src[0x871];
+
+  lev.emerald_score = src[0x824];
+  lev.diamond_score = src[0x825];
+  lev.alien_score = src[0x826];
+  lev.tank_score = src[0x827];
+  lev.bug_score = src[0x828];
+  lev.eater_score = src[0x829];
+  lev.nut_score = src[0x82A];
+  lev.dynamite_score = src[0x82B];
+  lev.key_score = src[0x82C];
+  lev.exit_score = src[0x82D] * 8 / 5;
+  lev.lenses_score = src[0x867];
+  lev.magnify_score = src[0x868];
+  lev.slurp_score = src[0x869];
+
+  lev.lenses_time = src[0x86A] << 8 | src[0x86B];
+  lev.magnify_time = src[0x86C] << 8 | src[0x86D];
+  lev.wheel_time = src[0x838] << 8 | src[0x839];
+
+  lev.wind_cnt_initial = src[0x865] & 15 ? lev.wind_time : 0;
+  temp = src[0x865];
+  lev.wind_direction_initial = (temp & 8 ? 0 :
+                               temp & 1 ? 1 :
+                               temp & 2 ? 2 :
+                               temp & 4 ? 3 : 0);
+
+  lev.wonderwall_time_initial = src[0x836] << 8 | src[0x837];
+
+  for (i = 0; i < 8; i++)
+    for (x = 0; x < 9; x++)
+      lev.eater_array[i][x] = remap_emerald[src[eater_offset[i] + x]];
+
+  temp = remap_emerald[src[0x86F]];
+  for (y = 0; y < 8; y++)
+  {
+    if (src[0x872] & 1)
+    {
+      for (x = 0; x < 8; x++)
+       lev.ball_array[y][x] = temp;
+    }
+    else
+    {
+      lev.ball_array[y][1] = (src[0x873] & 1)  ? temp : Xblank; /* north */
+      lev.ball_array[y][6] = (src[0x873] & 2)  ? temp : Xblank; /* south */
+      lev.ball_array[y][3] = (src[0x873] & 4)  ? temp : Xblank; /* west */
+      lev.ball_array[y][4] = (src[0x873] & 8)  ? temp : Xblank; /* east */
+      lev.ball_array[y][7] = (src[0x873] & 16) ? temp : Xblank; /* southeast */
+      lev.ball_array[y][5] = (src[0x873] & 32) ? temp : Xblank; /* southwest */
+      lev.ball_array[y][2] = (src[0x873] & 64) ? temp : Xblank; /* northeast */
+      lev.ball_array[y][0] = (src[0x873] & 128)? temp : Xblank; /* northwest */
+    }
+  }
+
+  temp = src[0x878] << 8 | src[0x879];
+
+  if (temp & 1)
+  {
+    lev.android_array[Xemerald] =
+      lev.android_array[Xemerald_pause] =
+      lev.android_array[Xemerald_fall] =
+      lev.android_array[Yemerald_sB] =
+      lev.android_array[Yemerald_eB] =
+      lev.android_array[Yemerald_wB] = Xemerald;
+  }
+
+  if (temp & 2)
+  {
+    lev.android_array[Xdiamond] =
+      lev.android_array[Xdiamond_pause] =
+      lev.android_array[Xdiamond_fall] =
+      lev.android_array[Ydiamond_sB] =
+      lev.android_array[Ydiamond_eB] =
+      lev.android_array[Ydiamond_wB] = Xdiamond;
+  }
+
+  if (temp & 4)
+  {
+    lev.android_array[Xstone] =
+      lev.android_array[Xstone_pause] =
+      lev.android_array[Xstone_fall] =
+      lev.android_array[Ystone_sB] =
+      lev.android_array[Ystone_eB] =
+      lev.android_array[Ystone_wB] = Xstone;
+  }
+
+  if (temp & 8)
+  {
+    lev.android_array[Xbomb] =
+      lev.android_array[Xbomb_pause] =
+      lev.android_array[Xbomb_fall] =
+      lev.android_array[Ybomb_sB] =
+      lev.android_array[Ybomb_eB] =
+      lev.android_array[Ybomb_wB] = Xbomb;
+  }
+
+  if (temp & 16)
+  {
+    lev.android_array[Xnut] =
+      lev.android_array[Xnut_pause] =
+      lev.android_array[Xnut_fall] =
+      lev.android_array[Ynut_sB] =
+      lev.android_array[Ynut_eB] =
+      lev.android_array[Ynut_wB] = Xnut;
+  }
+
+  if (temp & 32)
+  {
+    lev.android_array[Xtank_n] =
+      lev.android_array[Xtank_gon] =
+      lev.android_array[Ytank_nB] =
+      lev.android_array[Ytank_n_e] =
+      lev.android_array[Ytank_n_w] = Xtank_n;
+
+    lev.android_array[Xtank_e] =
+      lev.android_array[Xtank_goe] =
+      lev.android_array[Ytank_eB] =
+      lev.android_array[Ytank_e_s] =
+      lev.android_array[Ytank_e_n] = Xtank_e;
+
+    lev.android_array[Xtank_s] =
+      lev.android_array[Xtank_gos] =
+      lev.android_array[Ytank_sB] =
+      lev.android_array[Ytank_s_w] =
+      lev.android_array[Ytank_s_e] = Xtank_s;
+
+    lev.android_array[Xtank_w] =
+      lev.android_array[Xtank_gow] =
+      lev.android_array[Ytank_wB] =
+      lev.android_array[Ytank_w_n] =
+      lev.android_array[Ytank_w_s] = Xtank_w;
+  }
+
+  if (temp & 64)
+  {
+    lev.android_array[Xeater_n] = lev.android_array[Yeater_nB] = Xeater_n;
+    lev.android_array[Xeater_e] = lev.android_array[Yeater_eB] = Xeater_e;
+    lev.android_array[Xeater_s] = lev.android_array[Yeater_sB] = Xeater_s;
+    lev.android_array[Xeater_w] = lev.android_array[Yeater_wB] = Xeater_w;
+  }
+
+  if (temp & 128)
+  {
+    lev.android_array[Xbug_n] =
+      lev.android_array[Xbug_gon] =
+      lev.android_array[Ybug_nB] =
+      lev.android_array[Ybug_n_e] =
+      lev.android_array[Ybug_n_w] = Xbug_gon;
+
+    lev.android_array[Xbug_e] =
+      lev.android_array[Xbug_goe] =
+      lev.android_array[Ybug_eB] =
+      lev.android_array[Ybug_e_s] =
+      lev.android_array[Ybug_e_n] = Xbug_goe;
+
+    lev.android_array[Xbug_s] =
+      lev.android_array[Xbug_gos] =
+      lev.android_array[Ybug_sB] =
+      lev.android_array[Ybug_s_w] =
+      lev.android_array[Ybug_s_e] = Xbug_gos;
+
+    lev.android_array[Xbug_w] =
+      lev.android_array[Xbug_gow] =
+      lev.android_array[Ybug_wB] =
+      lev.android_array[Ybug_w_n] =
+      lev.android_array[Ybug_w_s] = Xbug_gow;
+  }
+
+  if (temp & 256)
+  {
+    lev.android_array[Xalien] = lev.android_array[Xalien_pause] =
+      lev.android_array[Yalien_nB] = lev.android_array[Yalien_eB] =
+      lev.android_array[Yalien_sB] = lev.android_array[Yalien_wB] = Xalien;
+  }
+
+  if (temp & 512)
+  {
+    lev.android_array[Xspring] =
+      lev.android_array[Xspring_pause] =
+      lev.android_array[Xspring_e] =
+      lev.android_array[Yspring_eB] =
+      lev.android_array[Yspring_kill_eB] =
+      lev.android_array[Xspring_w] =
+      lev.android_array[Yspring_wB] =
+      lev.android_array[Yspring_kill_wB] =
+      lev.android_array[Xspring_fall] =
+      lev.android_array[Yspring_sB] = Xspring;
+  }
+
+  if (temp & 1024)
+  {
+    lev.android_array[Yballoon_nB] =
+      lev.android_array[Yballoon_eB] =
+      lev.android_array[Yballoon_sB] =
+      lev.android_array[Yballoon_wB] =
+      lev.android_array[Xballoon] = Xballoon;
+  }
+
+  if (temp & 2048)
+  {
+    lev.android_array[Xdripper] =
+      lev.android_array[XdripperB] =
+      lev.android_array[Xamoeba_1] =
+      lev.android_array[Xamoeba_2] =
+      lev.android_array[Xamoeba_3] =
+      lev.android_array[Xamoeba_4] =
+      lev.android_array[Xamoeba_5] =
+      lev.android_array[Xamoeba_6] =
+      lev.android_array[Xamoeba_7] =
+      lev.android_array[Xamoeba_8] = Xdrip_eat;
+  }
+
+  if (temp & 4096)
+  {
+    lev.android_array[Xdynamite] = Xdynamite;
+  }
+
+  for (temp = 1; temp < 2047; temp++)
+  {
+    switch (src[temp])
+    {
+      case 0x24:                               /* wonderwall */
+       lev.wonderwall_state_initial = 1;
+       lev.wonderwall_time_initial = 9999;
+       break;
+
+      case 0x28:                               /* wheel */
+       lev.wheel_x_initial = temp & 63;
+       lev.wheel_y_initial = temp >> 6;
+       lev.wheel_cnt_initial = lev.wheel_time;
+       break;
+
+#ifndef BAD_ROLL
+      case 0x63:                               /* spring roll left */
+       src[temp - 1] = 0x45;
+       src[temp] = 0x80;
+       break;
+
+      case 0x64:                               /* spring roll right */
+       src[temp + 1] = 0x45;
+       src[temp] = 0x80;
+       break;
+
+      case 0x72:                               /* nut roll left */
+       src[temp - 1] = 0x25;
+       src[temp] = 0x80;
+       break;
+
+      case 0x73:                               /* nut roll right */
+       src[temp + 1] = 0x25;
+       src[temp] = 0x80;
+       break;
+
+      case 0x77:                               /* bomb roll left */
+       src[temp - 1] = 0x10;
+       src[temp] = 0x80;
+       break;
+
+      case 0x78:                               /* bomb roll right */
+       src[temp + 1] = 0x10;
+       src[temp] = 0x80;
+       break;
+
+      case 0x79:                               /* stone roll left */
+       src[temp - 1] = 0x00;
+       src[temp] = 0x80;
+       break;
+
+      case 0x7A:                               /* stone roll right */
+       src[temp + 1] = 0x00;
+       src[temp] = 0x80;
+       break;
+#endif
+
+      case 0xA3:                               /* fake blank */
+       lev.lenses_cnt_initial = 9999;
+       break;
+
+      case 0xA4:                               /* fake grass */
+       lev.magnify_cnt_initial = 9999;
+       break;
+    }
+  }
+
+  /* first fill the complete playfield with the default border element */
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      native_em_level.cave[x][y] = ZBORDER;
+
+  /* then copy the real level contents from level file into the playfield */
+  temp = 0;
+  for (y = 0; y < lev.height; y++)
+    for (x = 0; x < lev.width; x++)
+      native_em_level.cave[x + 1][y + 1] = remap_emerald[src[temp++]];
+
+  /* at last, set the two players at their positions in the playfield */
+  if (ply1.alive_initial)
+    native_em_level.cave[ply1.x_initial][ply1.y_initial] = Zplayer;
+  if (ply2.alive_initial)
+    native_em_level.cave[ply2.x_initial][ply2.y_initial] = Zplayer;
+
+  native_em_level.file_version = file_version;
+}
+
+void prepare_em_level(void)
+{
+  unsigned int x, y;
+
+  /* reset all runtime variables to their initial values */
+
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Cave[y][x] = native_em_level.cave[x][y];
+
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Next[y][x] = Cave[y][x];
+
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Draw[y][x] = Cave[y][x];
+
+#if 1
+  lev.time_initial = lev.time_seconds;
+#else
+  lev.time_initial = (lev.time_seconds * 50 + 7) / 8;
+#endif
+  lev.time = lev.time_initial;
+
+  lev.required = lev.required_initial;
+  lev.score = 0;
+
+  lev.android_move_cnt  = lev.android_move_time;
+  lev.android_clone_cnt = lev.android_clone_time;
+
+  lev.ball_pos = 0;
+  lev.ball_state = lev.ball_state_initial;
+  lev.ball_cnt = lev.ball_time;
+
+  lev.eater_pos = 0;
+  lev.shine_cnt = 0;
+
+  lev.lenses_cnt = lev.lenses_cnt_initial;
+  lev.magnify_cnt = lev.magnify_cnt_initial;
+
+  lev.wheel_cnt = lev.wheel_cnt_initial;
+  lev.wheel_x   = lev.wheel_x_initial;
+  lev.wheel_y   = lev.wheel_y_initial;
+
+  lev.wind_cnt       = lev.wind_cnt_initial;
+  lev.wind_direction = lev.wind_direction_initial;
+
+  lev.wonderwall_state = lev.wonderwall_state_initial;
+  lev.wonderwall_time  = lev.wonderwall_time_initial;
+
+  lev.home = lev.home_initial;
+
+  lev.killed_out_of_time = FALSE;
+
+  ply1.num = 0;
+  ply1.alive = ply1.alive_initial;
+  ply1.dynamite = 0;
+  ply1.dynamite_cnt = 0;
+  ply1.keys = 0;
+  ply1.anim = 0;
+  ply1.oldx = ply1.x = ply1.x_initial;
+  ply1.oldy = ply1.y = ply1.y_initial;
+  ply1.last_move_dir = MV_NO_MOVING;
+  ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0;
+  ply1.joy_snap = ply1.joy_drop = 0;
+  ply1.joy_stick = ply1.joy_spin = 0;
+
+  ply2.num = 1;
+  ply2.alive = ply2.alive_initial;
+  ply2.dynamite = 0;
+  ply2.dynamite_cnt = 0;
+  ply2.keys = 0;
+  ply2.anim = 0;
+  ply2.oldx = ply2.x = ply2.x_initial;
+  ply2.oldy = ply2.y = ply2.y_initial;
+  ply2.last_move_dir = MV_NO_MOVING;
+  ply2.joy_n = ply2.joy_e = ply2.joy_s = ply2.joy_w = 0;
+  ply2.joy_snap = ply1.joy_drop = 0;
+  ply2.joy_stick = ply2.joy_spin = 0;
+}
diff --git a/src/game_em/display.h b/src/game_em/display.h
new file mode 100644 (file)
index 0000000..f6a82af
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+#include "main_em.h"
+
+#define ORIG_TILEX             16
+#define ORIG_TILEY             16
+#define ORIG_SCOREX            8
+#define ORIG_SCOREY            9
+#define ORIG_GFXMENUFONTX      14
+#define ORIG_GFXMENUFONTY      16
+#define ORIG_MENUFONTX         12
+#define ORIG_MENUFONTY         16
+
+#define ZOOM_FACTOR            2
+
+#define TILEX                  (ORIG_TILEX             * ZOOM_FACTOR)
+#define TILEY                  (ORIG_TILEY             * ZOOM_FACTOR)
+#define SCOREX                 (ORIG_SCOREX            * ZOOM_FACTOR)
+#define SCOREY                 (ORIG_SCOREY            * ZOOM_FACTOR)
+#define GFXMENUFONTX           (ORIG_GFXMENUFONTX      * ZOOM_FACTOR)
+#define GFXMENUFONTY           (ORIG_GFXMENUFONTY      * ZOOM_FACTOR)
+#define MENUFONTX              (ORIG_MENUFONTX         * ZOOM_FACTOR)
+#define MENUFONTY              (ORIG_MENUFONTY         * ZOOM_FACTOR)
+
+#define ORIG_SCR_MENUX         20
+#define ORIG_SCR_MENUY         12
+#define SCR_MENUX              17
+#define SCR_MENUY              12
+#define SCR_FIELDX             17
+#define SCR_FIELDY             17
+#define MAX_BUF_XSIZE          (SCR_FIELDX + 2)
+#define MAX_BUF_YSIZE          (SCR_FIELDY + 2)
+
+/* often used screen positions */
+#define ORIG_MENU_SX           ((ORIG_SCR_MENUX - SCR_MENUX) * TILEX / 2)
+#define ORIG_MENU_SY           0
+#define SY                     8
+#define SX                     8
+#define SY                     8
+#define SXSIZE                 (SCR_FIELDX * TILEX)
+#define SYSIZE                 (SCR_FIELDY * TILEY)
+
+#if 1
+#define FRAMES_PER_SECOND      50
+
+#define ROUNDED_DIVIDE(x, y)   (((x) + (y) - 1) / (y))
+
+#define SECONDS_TO_FRAMES(x)   ((x) * FRAMES_PER_SECOND)
+#define FRAMES_TO_SECONDS(x)   ((x) / FRAMES_PER_SECOND)
+
+#define SECONDS_TO_CYCLES(x)   ROUNDED_DIVIDE((x) * FRAMES_PER_SECOND, 8)
+#define CYCLES_TO_SECONDS(x)   ROUNDED_DIVIDE((x) * 8, FRAMES_PER_SECOND)
+
+#define DISPLAY_TIME(x)                ROUNDED_DIVIDE(x, FRAMES_PER_SECOND)
+
+#else
+
+#define DISPLAY_TIME(x)                (((x) * 8 + 49) / 50)
+#endif
+
+extern Bitmap *screenBitmap;
+extern Bitmap *scoreBitmap;
+
+extern Bitmap *objBitmap;
+extern Bitmap *sprBitmap;
+extern Bitmap *ttlBitmap;
+extern Bitmap *botBitmap;
+
+extern Pixmap screenPixmap;
+extern Pixmap scorePixmap;
+extern Pixmap spriteBitmap;
+
+extern Pixmap objmaskBitmap;
+extern Pixmap sprmaskBitmap;
+
+extern GC spriteGC;
+
+#endif
diff --git a/src/game_em/game_em.h b/src/game_em/game_em.h
new file mode 100644 (file)
index 0000000..820d7aa
--- /dev/null
@@ -0,0 +1,46 @@
+/***********************************************************
+* Artsoft Retro-Game Library                               *
+*----------------------------------------------------------*
+* (c) 1994-2002 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
+*----------------------------------------------------------*
+* game_em.h                                                *
+***********************************************************/
+
+#ifndef GAME_EM_H
+#define GAME_EM_H
+
+#define GAME_EM_VERSION_1_0_0
+
+
+/* ========================================================================= */
+/* functions and definitions exported from game_em to main program           */
+/* ========================================================================= */
+
+#include "main_em.h"
+
+extern struct GlobalInfo_EM global_em_info;
+extern struct LevelInfo_EM native_em_level;
+extern struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8];
+extern struct GraphicInfo_EM graphic_info_em_player[2][SPR_MAX][8];
+
+extern void em_open_all();
+extern void em_close_all();
+
+extern void InitGameEngine_EM();
+extern void GameActions_EM(byte);
+
+extern unsigned int InitEngineRND_EM(long);
+
+extern void setLevelInfoToDefaults_EM();
+extern boolean LoadNativeLevel_EM(char *);
+
+extern void BlitScreenToBitmap_EM(Bitmap *);
+extern void RedrawPlayfield_EM();
+extern void DrawGameDoorValues_EM();
+
+#endif /* GAME_EM_H */
diff --git a/src/game_em/global.h b/src/game_em/global.h
new file mode 100644 (file)
index 0000000..2d30f24
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#include "main_em.h"
+
+#define EM_GFX_DIR     "graphics.EM"
+#define EM_SND_DIR     "sounds.EM"
+#define EM_LVL_DIR     "levels.EM"
+
+/* arbitrary maximum length of filenames (cos i am lazy) */
+#define MAXNAME 1024
+
+extern int debug;
+extern char *progname;
+extern char *arg_basedir;
+
+extern unsigned int frame;
+
+extern short ulaw_to_linear[256];
+extern unsigned char linear_to_ulaw[65536];
+
+/* all global function prototypes */
+
+int open_all(void);
+void close_all(void);
+
+void readjoy(byte);
+void input_eventloop(void);
+
+void blitscreen(void);
+void game_initscreen(void);
+void game_animscreen(void);
+
+void DrawGameDoorValues_EM();
+
+void play_sound(int, int, int);
+void sound_play(void);
+
+int cave_convert(char *);
+boolean LoadNativeLevel_EM(char *);
+
+void game_init_vars(void);
+void game_play_init(int, char *);
+void game_loop(byte);
+
+void synchro_1(void);
+void synchro_2(void);
+void synchro_3(void);
+
+int  cleanup_em_level(unsigned char *, int);
+void convert_em_level(unsigned char *, int);
+void prepare_em_level(void);
+
+int sound_thread(void);
+int read_sample(char *, short **, long *);
+
+void read_cave_list(void);
+void free_cave_list(void);
+
+#endif
diff --git a/src/game_em/graphics.c b/src/game_em/graphics.c
new file mode 100644 (file)
index 0000000..06f974a
--- /dev/null
@@ -0,0 +1,435 @@
+/* 2000-08-13T14:36:17Z
+ *
+ * graphics manipulation crap
+ */
+
+#include "global.h"
+#include "display.h"
+#include "level.h"
+
+
+unsigned int frame;            /* current screen frame */
+unsigned int screen_x;         /* current scroll position */
+unsigned int screen_y;
+
+/* tiles currently on screen */
+static unsigned int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
+static unsigned int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE];
+
+
+/* copy the entire screen to the window at the scroll position
+ *
+ * perhaps use mit-shm to speed this up
+ */
+
+void BlitScreenToBitmap_EM(Bitmap *target_bitmap)
+{
+  unsigned int x = screen_x % (MAX_BUF_XSIZE * TILEX);
+  unsigned int y = screen_y % (MAX_BUF_YSIZE * TILEY);
+
+  if (x < 2 * TILEX && y < 2 * TILEY)
+  {
+    BlitBitmap(screenBitmap, target_bitmap, x, y,
+              SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY);
+  }
+  else if (x < 2 * TILEX && y >= 2 * TILEY)
+  {
+    BlitBitmap(screenBitmap, target_bitmap, x, y,
+              SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y,
+              SX, SY);
+    BlitBitmap(screenBitmap, target_bitmap, x, 0,
+              SCR_FIELDX * TILEX, y - 2 * TILEY,
+              SX, SY + MAX_BUF_YSIZE * TILEY - y);
+  }
+  else if (x >= 2 * TILEX && y < 2 * TILEY)
+  {
+    BlitBitmap(screenBitmap, target_bitmap, x, y,
+              MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY,
+              SX, SY);
+    BlitBitmap(screenBitmap, target_bitmap, 0, y,
+              x - 2 * TILEX, SCR_FIELDY * TILEY,
+              SX + MAX_BUF_XSIZE * TILEX - x, SY);
+  }
+  else
+  {
+    BlitBitmap(screenBitmap, target_bitmap, x, y,
+              MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y,
+              SX, SY);
+    BlitBitmap(screenBitmap, target_bitmap, 0, y,
+              x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y,
+              SX + MAX_BUF_XSIZE * TILEX - x, SY);
+    BlitBitmap(screenBitmap, target_bitmap, x, 0,
+              MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY,
+              SX, SY + MAX_BUF_YSIZE * TILEY - y);
+    BlitBitmap(screenBitmap, target_bitmap, 0, 0,
+              x - 2 * TILEX, y - 2 * TILEY,
+              SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y);
+  }
+}
+
+void blitscreen(void)
+{
+  BlitScreenToBitmap_EM(window);
+}
+
+static void DrawLevelField_EM(int x, int y, int sx, int sy,
+                             boolean draw_masked)
+{
+  int tile = Draw[y][x];
+  struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
+  int src_x = g->src_x + g->src_offset_x;
+  int src_y = g->src_y + g->src_offset_y;
+  int dst_x = sx * TILEX + g->dst_offset_x;
+  int dst_y = sy * TILEY + g->dst_offset_y;
+  int width = g->width;
+  int height = g->height;
+
+  if (draw_masked)
+  {
+    if (width > 0 && height > 0)
+    {
+      SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
+                   dst_x - src_x, dst_y - src_y);
+      BlitBitmapMasked(g->bitmap, screenBitmap,
+                      src_x, src_y, width, height, dst_x, dst_y);
+    }
+  }
+  else
+  {
+    if ((width != TILEX || height != TILEY) && !g->preserve_background)
+      ClearRectangle(screenBitmap, sx * TILEX, sy * TILEY, TILEX, TILEY);
+
+    if (width > 0 && height > 0)
+      BlitBitmap(g->bitmap, screenBitmap,
+                src_x, src_y, width, height, dst_x, dst_y);
+  }
+}
+
+static void DrawLevelFieldCrumbled_EM(int x, int y, int sx, int sy,
+                                     int crm, boolean draw_masked)
+{
+  int tile = Draw[y][x];
+  struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
+  unsigned int i;
+
+  if (crm == 0)                /* no crumbled edges for this tile */
+    return;
+
+  for (i = 0; i < 4; i++)
+  {
+    if (crm & (1 << i))
+    {
+      int width, height, cx, cy;
+
+      if (i == 1 || i == 2)
+      {
+       width = g->crumbled_border_size;
+       height = TILEY;
+       cx = (i == 2 ? TILEX - g->crumbled_border_size : 0);
+       cy = 0;
+      }
+      else
+      {
+       width = TILEX;
+       height = g->crumbled_border_size;
+       cx = 0;
+       cy = (i == 3 ? TILEY - g->crumbled_border_size : 0);
+      }
+
+      if (width > 0 && height > 0)
+      {
+       int src_x = g->crumbled_src_x + cx;
+       int src_y = g->crumbled_src_y + cy;
+       int dst_x = sx * TILEX + cx;
+       int dst_y = sy * TILEY + cy;
+
+       if (draw_masked)
+       {
+         SetClipOrigin(g->crumbled_bitmap, g->crumbled_bitmap->stored_clip_gc,
+                       dst_x - src_x, dst_y - src_y);
+         BlitBitmapMasked(g->crumbled_bitmap, screenBitmap,
+                          src_x, src_y, width, height, dst_x, dst_y);
+       }
+       else
+         BlitBitmap(g->crumbled_bitmap, screenBitmap,
+                    src_x, src_y, width, height, dst_x, dst_y);
+      }
+    }
+  }
+}
+
+static void DrawLevelPlayer_EM(int x1, int y1, int player_nr, int anim,
+                              boolean draw_masked)
+{
+  struct GraphicInfo_EM *g = &graphic_info_em_player[player_nr][anim][frame];
+
+  int src_x = g->src_x, src_y = g->src_y;
+  int dst_x, dst_y;
+
+  if (draw_masked)
+  {
+    /* draw the player to current location */
+    dst_x = x1;
+    dst_y = y1;
+    SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
+                 dst_x - src_x, dst_y - src_y);
+    BlitBitmapMasked(g->bitmap, screenBitmap,
+                    src_x, src_y, TILEX, TILEY, dst_x, dst_y);
+
+    /* draw the player to opposite wrap-around column */
+    dst_x = x1 - MAX_BUF_XSIZE * TILEX;
+    dst_y = y1;
+    SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
+                 dst_x - src_x, dst_y - src_y);
+    BlitBitmapMasked(g->bitmap, screenBitmap,
+                    g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
+
+    /* draw the player to opposite wrap-around row */
+    dst_x = x1;
+    dst_y = y1 - MAX_BUF_YSIZE * TILEY;
+    SetClipOrigin(g->bitmap, g->bitmap->stored_clip_gc,
+                 dst_x - src_x, dst_y - src_y);
+    BlitBitmapMasked(g->bitmap, screenBitmap,
+                    g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
+  }
+  else
+  {
+    /* draw the player to current location */
+    dst_x = x1;
+    dst_y = y1;
+    BlitBitmap(g->bitmap, screenBitmap,
+              g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
+
+    /* draw the player to opposite wrap-around column */
+    dst_x = x1 - MAX_BUF_XSIZE * TILEX;
+    dst_y = y1;
+    BlitBitmap(g->bitmap, screenBitmap,
+              g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
+
+    /* draw the player to opposite wrap-around row */
+    dst_x = x1;
+    dst_y = y1 - MAX_BUF_YSIZE * TILEY;
+    BlitBitmap(g->bitmap, screenBitmap,
+              g->src_x, g->src_y, TILEX, TILEY, dst_x, dst_y);
+  }
+}
+
+/* draw differences between game tiles and screen tiles
+ *
+ * implicitly handles scrolling and restoring background under the sprites
+ *
+ * perhaps use mit-shm to speed this up
+ */
+
+static void animscreen(void)
+{
+  unsigned int x, y, i;
+  unsigned int left = screen_x / TILEX;
+  unsigned int top = screen_y / TILEY;
+  static int xy[4][2] =
+  {
+    { 0, -1 },
+    { -1, 0 },
+    { +1, 0 },
+    { 0, +1 }
+  };
+
+  for (y = top; y < top + MAX_BUF_YSIZE; y++)
+  {
+    for (x = left; x < left + MAX_BUF_XSIZE; x++)
+    {
+      int sx = x % MAX_BUF_XSIZE;
+      int sy = y % MAX_BUF_YSIZE;    
+      int tile = Draw[y][x];
+      struct GraphicInfo_EM *g = &graphic_info_em_object[tile][frame];
+      unsigned int obj = g->unique_identifier;
+      unsigned int crm = 0;
+
+      /* re-calculate crumbled state of this tile */
+      if (g->has_crumbled_graphics)
+      {
+       for (i = 0; i < 4; i++)
+       {
+         int xx = x + xy[i][0];
+         int yy = y + xy[i][1];
+         int tile_next;
+
+         if (xx < 0 || xx >= EM_MAX_CAVE_WIDTH ||
+             yy < 0 || yy >= EM_MAX_CAVE_HEIGHT)
+           continue;
+
+         tile_next = Draw[yy][xx];
+
+         if (!graphic_info_em_object[tile_next][frame].has_crumbled_graphics)
+           crm |= (1 << i);
+       }
+      }
+
+      /* only redraw screen tiles if they (or their crumbled state) changed */
+      if (screentiles[sy][sx] != obj || crumbled_state[sy][sx] != crm)
+      {
+       DrawLevelField_EM(x, y, sx, sy, FALSE);
+       DrawLevelFieldCrumbled_EM(x, y, sx, sy, crm, FALSE);
+
+       screentiles[sy][sx] = obj;
+       crumbled_state[sy][sx] = crm;
+      }
+    }
+  }
+}
+
+
+/* blit players to the screen
+ *
+ * handles transparency and movement
+ */
+
+static void blitplayer(struct PLAYER *ply)
+{
+  unsigned int x1, y1, x2, y2;
+
+  if (!ply->alive)
+    return;
+
+  /* x1/y1 are left/top and x2/y2 are right/down part of the player movement */
+  x1 = (frame * ply->oldx + (8 - frame) * ply->x) * TILEX / 8;
+  y1 = (frame * ply->oldy + (8 - frame) * ply->y) * TILEY / 8;
+  x2 = x1 + TILEX - 1;
+  y2 = y1 + TILEY - 1;
+
+  if ((unsigned int)(x2 - screen_x) < ((MAX_BUF_XSIZE - 1) * TILEX - 1) &&
+      (unsigned int)(y2 - screen_y) < ((MAX_BUF_YSIZE - 1) * TILEY - 1))
+  {
+    /* some casts to "int" are needed because of negative calculation values */
+    int dx = (int)ply->x - (int)ply->oldx;
+    int dy = (int)ply->y - (int)ply->oldy;
+    int old_x = (int)ply->oldx + (7 - (int)frame) * dx / 8;
+    int old_y = (int)ply->oldy + (7 - (int)frame) * dy / 8;
+    int new_x = old_x + SIGN(dx);
+    int new_y = old_y + SIGN(dy);
+    int old_sx = old_x % MAX_BUF_XSIZE;
+    int old_sy = old_y % MAX_BUF_XSIZE;
+    int new_sx = new_x % MAX_BUF_XSIZE;
+    int new_sy = new_y % MAX_BUF_XSIZE;
+#if 0
+    int old_crm = crumbled_state[old_sy][old_sx];
+#endif
+    int new_crm = crumbled_state[new_sy][new_sx];
+
+    /* only diggable elements can be crumbled in the classic EM engine */
+    boolean player_is_digging = (new_crm != 0);
+
+    x1 %= MAX_BUF_XSIZE * TILEX;
+    y1 %= MAX_BUF_YSIZE * TILEY;
+    x2 %= MAX_BUF_XSIZE * TILEX;
+    y2 %= MAX_BUF_YSIZE * TILEY;
+
+    if (player_is_digging)
+    {
+#if 0
+      /* draw the field the player is moving from (under the player) */
+      DrawLevelField_EM(old_x, old_y, old_sx, old_sy, FALSE);
+      DrawLevelFieldCrumbled_EM(old_x, old_y, old_sx, old_sy, old_crm, FALSE);
+#endif
+
+      /* draw the field the player is moving to (under the player) */
+      DrawLevelField_EM(new_x, new_y, new_sx, new_sy, FALSE);
+      DrawLevelFieldCrumbled_EM(new_x, new_y, new_sx, new_sy, new_crm, FALSE);
+
+      /* draw the player (masked) over the element he is just digging away */
+      DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, TRUE);
+
+#if 1
+      /* draw the field the player is moving from (masked over the player) */
+      DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
+#endif
+    }
+    else
+    {
+      /* draw the player under the element which is on the same field */
+      DrawLevelPlayer_EM(x1, y1, ply->num, ply->anim, FALSE);
+
+      /* draw the field the player is moving from (masked over the player) */
+      DrawLevelField_EM(old_x, old_y, old_sx, old_sy, TRUE);
+
+      /* draw the field the player is moving to (masked over the player) */
+      DrawLevelField_EM(new_x, new_y, new_sx, new_sy, TRUE);
+    }
+
+    /* mark screen tiles as dirty */
+    screentiles[old_sy][old_sx] = -1;
+    screentiles[new_sy][new_sx] = -1;
+  }
+}
+
+void game_initscreen(void)
+{
+  unsigned int x,y;
+
+  frame = 6;
+  screen_x = 0;
+  screen_y = 0;
+
+  for (y = 0; y < MAX_BUF_YSIZE; y++)
+  {
+    for (x = 0; x < MAX_BUF_XSIZE; x++)
+    {
+      screentiles[y][x] = -1;
+      crumbled_state[y][x] = 0;
+    }
+  }
+
+#if 1
+  DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
+                   lev.time, ply1.keys | ply2.keys);
+#else
+  DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
+                   DISPLAY_TIME(lev.time + 4), ply1.keys | ply2.keys);
+#endif
+}
+
+void RedrawPlayfield_EM()
+{
+  unsigned int x,y;
+
+  x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8
+    + ((SCR_FIELDX - 1) * TILEX) / 2;
+  y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8
+    + ((SCR_FIELDY - 1) * TILEY) / 2;
+
+  if (x > lev.width * TILEX)
+    x = lev.width * TILEX;
+  if (y > lev.height * TILEY)
+    y = lev.height * TILEY;
+
+  if (x < SCR_FIELDX * TILEX)
+    x = SCR_FIELDX * TILEY;
+  if (y < SCR_FIELDY * TILEY)
+    y = SCR_FIELDY * TILEY;
+
+  screen_x = x - (SCR_FIELDX - 1) * TILEX;
+  screen_y = y - (SCR_FIELDY - 1) * TILEY;
+
+  animscreen();
+  blitplayer(&ply1);
+  blitplayer(&ply2);
+  blitscreen();
+
+  FlushDisplay();
+}
+
+void game_animscreen(void)
+{
+  RedrawPlayfield_EM();
+}
+
+void DrawGameDoorValues_EM()
+{
+#if 1
+  DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
+                   lev.time, ply1.keys | ply2.keys);
+#else
+  DrawAllGameValues(lev.required, ply1.dynamite, lev.score,
+                   DISPLAY_TIME(lev.time), ply1.keys | ply2.keys);
+#endif
+}
diff --git a/src/game_em/init.c b/src/game_em/init.c
new file mode 100644 (file)
index 0000000..54759ee
--- /dev/null
@@ -0,0 +1,391 @@
+/* 2000-08-10T18:03:54Z
+ *
+ * open X11 display and sound
+ */
+
+#include <signal.h>
+
+#if !defined(TARGET_SDL)
+#include <sys/wait.h>
+#endif
+
+#include "main_em.h"
+
+#include "global.h"
+#include "display.h"
+#include "sample.h"
+#include "level.h"
+
+
+Bitmap *objBitmap;
+Bitmap *sprBitmap;
+
+Bitmap *screenBitmap;
+
+#if 0
+Pixmap spriteBitmap;
+#endif
+
+Pixmap objPixmap;
+Pixmap sprPixmap;
+
+#if 0
+Pixmap objmaskBitmap;
+Pixmap sprmaskBitmap;
+
+GC spriteGC;
+#endif
+
+char play[SAMPLE_MAX];
+int play_x[SAMPLE_MAX];
+int play_y[SAMPLE_MAX];
+int play_element[SAMPLE_MAX];
+
+static boolean use_native_em_sound = 0;
+
+struct GlobalInfo_EM global_em_info;
+
+#if defined(AUDIO_UNIX_NATIVE)
+static int sound_pid = -1;
+int sound_pipe[2] = { -1, -1 };                /* for communication */
+short *sound_data[SAMPLE_MAX];         /* pointer to sound data */
+long sound_length[SAMPLE_MAX];         /* length of sound data */
+
+static const char *sound_names[SAMPLE_MAX] =
+{
+  "00.blank.au",
+  "01.roll.au",
+  "02.stone.au",
+  "03.nut.au",
+  "04.crack.au",
+  "05.bug.au",
+  "06.tank.au",
+  "07.android.au",
+  "06.tank.au",                /* android moving */
+  "08.spring.au",
+  "09.slurp.au",
+  "10.eater.au",
+  "10.eater.au",       /* eater eating */
+  "11.alien.au",
+  "12.collect.au",
+  "13.diamond.au",
+  "14.squash.au",
+  "14.squash.au",
+  "15.drip.au",
+  "16.push.au",
+  "17.dirt.au",
+  "18.acid.au",
+  "19.ball.au",
+  "20.grow.au",
+  "21.wonder.au",
+  "22.door.au",
+  "23.exit.au",
+  "23.exit.au",
+  "24.dynamite.au",
+  "25.tick.au",
+  "26.press.au",
+  "27.wheel.au",
+  "28.boom.au",
+  "29.time.au",
+  "30.die.au"
+};
+static const int sound_volume[SAMPLE_MAX] =
+{
+  20,
+  100,
+  100,
+  100,
+  100,
+  20,
+  20,
+  100,
+  20,
+  100,
+  100,
+  50,
+  50,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  20,
+  100,
+  100,
+  100,
+  100,
+  100,
+  100,
+  20,
+  100,
+  100,
+  100
+};
+#endif
+
+char *progname;
+char *arg_basedir;
+
+extern void tab_generate();
+extern void tab_generate_graphics_info_em();
+extern void ulaw_generate();
+
+int open_all(void)
+{
+  Bitmap *emc_bitmaps[2];
+#if 0
+  XGCValues gcValues;
+#endif
+
+#if 1
+  SetBitmaps_EM(emc_bitmaps);
+
+  objBitmap = emc_bitmaps[0];
+  sprBitmap = emc_bitmaps[1];
+
+#if 0
+  objPixmap = emc_bitmaps[0]->drawable;
+  sprPixmap = emc_bitmaps[1]->drawable;
+
+  objmaskBitmap = emc_bitmaps[0]->clip_mask;
+  sprmaskBitmap = emc_bitmaps[1]->clip_mask;
+#endif
+
+  screenBitmap = CreateBitmap(MAX_BUF_XSIZE * TILEX, MAX_BUF_YSIZE * TILEY,
+                             DEFAULT_DEPTH);
+
+  global_em_info.screenbuffer = screenBitmap;
+
+#endif
+
+#if 0
+  spriteBitmap = XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
+  if (spriteBitmap == 0)
+    Error(ERR_EXIT, "failed to create sprite pixmap for EM engine");
+
+  gcValues.function =
+    objmaskBitmap ? GXcopyInverted : sprmaskBitmap ? GXcopy : GXset;
+  gcValues.graphics_exposures = False;
+  spriteGC = XCreateGC(display, spriteBitmap, GCFunction | GCGraphicsExposures,
+                      &gcValues);
+  if (spriteGC == 0)
+    Error(ERR_EXIT, "failed to create sprite GC for EM engine");
+#endif
+
+  /* ----------------------------------------------------------------- */
+
+#if defined(AUDIO_UNIX_NATIVE)
+
+#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
+
+  if (use_native_em_sound)
+  {
+    char name[MAXNAME+2];
+    int i;
+
+    for (i = 0; i < SAMPLE_MAX; i++)
+    {
+      name[MAXNAME] = 0;
+
+      if (arg_basedir)
+      {
+       snprintf(name, MAXNAME+2, "%s/%s/%s", arg_basedir, EM_SND_DIR,
+                sound_names[i]);
+      }
+      else
+      {
+       snprintf(name, MAXNAME+2, "%s/%s", EM_SND_DIR, sound_names[i]);
+      }
+
+      if (name[MAXNAME])
+       Error(ERR_EXIT, "buffer overflow when reading sounds directory");
+
+      if (read_sample(name, &sound_data[i], &sound_length[i]))
+       return(1);
+
+      {
+       short *ptr, *stop;
+       int mult = sound_volume[i] * 65536 / (100 * MIXER_MAX);
+       stop = sound_data[i] + sound_length[i];
+       for (ptr = sound_data[i]; ptr < stop; ptr++)
+         *ptr = (*ptr * mult) / 65536;
+      }
+    }
+
+    if (pipe(sound_pipe) == -1)
+    {
+      Error(ERR_WARN, "unable to create sound pipe for EM engine -- no sound");
+
+      return(1);
+    }
+
+    sound_pid = fork();
+    if (sound_pid == -1)
+    {
+      Error(ERR_WARN, "unable to fork sound thread for EM engine -- no sound");
+
+      return(1);
+    }
+
+    close(sound_pipe[sound_pid == 0]);
+    sound_pipe[sound_pid == 0] = -1;
+    if (sound_pid == 0)
+      _exit(sound_thread());
+
+    signal(SIGPIPE, SIG_IGN); /* dont crash if sound process dies */
+  }
+
+#endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
+
+#endif /* AUDIO_UNIX_NATIVE */
+
+  return(0);
+}
+
+void em_open_all()
+{
+  /* pre-calculate some data */
+  tab_generate();
+#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
+  ulaw_generate();
+#endif
+
+  progname = "emerald mine";
+
+  if (open_all() != 0)
+    Error(ERR_EXIT, "em_open_all(): open_all() failed");
+
+  /* after "open_all()", because we need the graphic bitmaps to be defined */
+  tab_generate_graphics_info_em();
+
+  game_init_vars();
+}
+
+void em_close_all(void)
+{
+#if defined(AUDIO_UNIX_NATIVE)
+  int i;
+
+  if (sound_pid != -1)
+  {
+    kill(sound_pid, SIGTERM);
+    waitpid(sound_pid, 0, 0);
+  }
+
+  if (sound_pipe[0] != -1)
+    close(sound_pipe[0]);
+  if (sound_pipe[1] != -1)
+    close(sound_pipe[1]);
+
+  for (i = 0; i < SAMPLE_MAX; i++)
+    if (sound_data[i])
+      free(sound_data[i]);
+#endif
+
+#if 0
+  if (spriteGC)
+    XFreeGC(display, spriteGC);
+
+  if (spriteBitmap)
+    XFreePixmap(display, spriteBitmap);
+#endif
+}
+
+/* ---------------------------------------------------------------------- */
+
+extern unsigned int screen_x;
+extern unsigned int screen_y;
+
+void play_element_sound(int x, int y, int sample, int element)
+{
+#if 0
+  unsigned int left = screen_x / TILEX;
+  unsigned int top  = screen_y / TILEY;
+
+  if ((x == -1 && y == -1) ||  /* play sound in the middle of the screen */
+      ((unsigned int)(y - top)  <= SCR_FIELDY &&
+       (unsigned int)(x - left) <= SCR_FIELDX))
+#endif
+  {
+#if 1
+    PlayLevelSound_EM(x, y, element, sample);
+#else
+    play[sample] = 1;
+    play_x[sample] = x;
+    play_y[sample] = y;
+    play_element[sample] = element;
+#endif
+  }
+}
+
+void play_sound(int x, int y, int sample)
+{
+  play_element_sound(x, y, sample, -1);
+}
+
+void sound_play(void)
+{
+  if (!use_native_em_sound)
+  {
+    int i;
+
+#if 0
+    UpdateEngineValues(screen_x / TILEX, screen_y / TILEY);
+#endif
+
+    return;
+
+    for (i = 0; i < SAMPLE_MAX; i++)
+      if (play[i])
+       PlayLevelSound_EM(play_x[i], play_y[i], play_element[i], i);
+  }
+
+#if defined(AUDIO_UNIX_NATIVE)
+  if (use_native_em_sound && sound_pipe[1] != -1)
+  {
+    if (write(sound_pipe[1], &play, sizeof(play)) == -1)
+    {
+      Error(ERR_WARN, "cannot write into pipe to child process -- no sounds");
+
+      if (sound_pipe[0] != -1)
+      {
+       close(sound_pipe[0]);
+       sound_pipe[0] = -1;
+      }
+
+      if (sound_pipe[1] != -1)
+      {
+       close(sound_pipe[1]);
+       sound_pipe[1] = -1;
+      }
+    }
+  }
+
+#endif
+
+  memset(play, 0, sizeof(play));
+}
+
+unsigned int InitEngineRND_EM(long seed)
+{
+  if (seed == NEW_RANDOMIZE)
+  {
+    int simple_rnd = SimpleRND(1000);
+    int i;
+
+    for (i = 0; i < simple_rnd || RandomEM == NEW_RANDOMIZE; i++)
+      RandomEM = RandomEM * 129 + 1;
+
+    seed = RandomEM;
+  }
+
+  RandomEM = seed;
+
+  return (unsigned int) seed;
+}
diff --git a/src/game_em/input.c b/src/game_em/input.c
new file mode 100644 (file)
index 0000000..7418f0b
--- /dev/null
@@ -0,0 +1,174 @@
+/* 2000-08-13T15:29:40Z
+ *
+ * handle input from x11 and keyboard and joystick
+ */
+
+#include "global.h"
+#include "display.h"
+#include "level.h"
+
+
+unsigned long RandomEM;
+
+struct PLAYER ply1;
+struct PLAYER ply2;
+struct LEVEL lev;
+
+unsigned short **Boom;
+unsigned short **Cave;
+unsigned short **Next;
+unsigned short **Draw;
+
+static unsigned short *Index[4][HEIGHT];
+static unsigned short Array[4][HEIGHT][WIDTH];
+
+extern unsigned int screen_x;
+extern unsigned int screen_y;
+
+void game_init_vars(void)
+{
+  int x, y;
+
+  RandomEM = 1684108901;
+
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Array[0][y][x] = ZBORDER;
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Array[1][y][x] = ZBORDER;
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Array[2][y][x] = ZBORDER;
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Array[3][y][x] = Xblank;
+
+  for (y = 0; y < HEIGHT; y++)
+    Index[0][y] = Array[0][y];
+  for (y = 0; y < HEIGHT; y++)
+    Index[1][y] = Array[1][y];
+  for (y = 0; y < HEIGHT; y++)
+    Index[2][y] = Array[2][y];
+  for (y = 0; y < HEIGHT; y++)
+    Index[3][y] = Array[3][y];
+
+  Cave = Index[0];
+  Next = Index[1];
+  Draw = Index[2];
+  Boom = Index[3];
+}
+
+void InitGameEngine_EM()
+{
+  prepare_em_level();
+
+  game_initscreen();
+  game_animscreen();
+}
+
+void GameActions_EM(byte action)
+{
+  static unsigned long game_frame_delay = 0;
+#if 1
+  unsigned long game_frame_delay_value = getGameFrameDelay_EM(20);
+#else
+  unsigned long game_frame_delay_value = getGameFrameDelay_EM(25);
+#endif
+
+#if 0
+  /* this is done in screens.c/HandleGameActions() by calling BackToFront() */
+  XSync(display, False);       /* block until all graphics are drawn */
+#endif
+
+  WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
+
+  game_animscreen();
+
+  RandomEM = RandomEM * 129 + 1;
+
+  frame = (frame - 1) & 7;
+
+  readjoy(action);
+
+  UpdateEngineValues(screen_x / TILEX, screen_y / TILEY);
+
+  if (frame == 7)
+  {
+    synchro_1();
+    synchro_2();
+  }
+
+  if (frame == 6)
+  {
+    synchro_3();
+    sound_play();
+
+    if (game_frame_delay_value > 0)    /* do not redraw values in warp mode */
+      DrawGameDoorValues_EM();
+  }
+
+#if 0
+  if (lev.time_initial == 0)
+    lev.time++;
+  else if (lev.time > 0)
+    lev.time--;
+#endif
+
+#if 0
+  if (lev.time_initial > 0 &&
+      lev.time > 0 && lev.time <= 50 && lev.time % 5 == 0 && setup.time_limit)
+    play_sound(-1, -1, SAMPLE_time);
+#endif
+}
+
+
+/* read input device for players */
+
+void readjoy(byte action)
+{
+  unsigned int north = 0, east = 0, south = 0, west = 0;
+  unsigned int snap = 0, drop = 0;
+
+  if (action & JOY_LEFT)
+    west = 1;
+
+  if (action & JOY_RIGHT)
+    east = 1;
+
+  if (action & JOY_UP)
+    north = 1;
+
+  if (action & JOY_DOWN)
+    south = 1;
+
+  if (action & JOY_BUTTON_1)
+    snap = 1;
+
+  if (action & JOY_BUTTON_2)
+    drop = 1;
+
+#if 1
+  ply1.joy_snap = snap;
+  ply1.joy_drop = drop;
+  if (ply1.joy_stick || (north | east | south | west))
+  {
+    ply1.joy_n = north;
+    ply1.joy_e = east;
+    ply1.joy_s = south;
+    ply1.joy_w = west;
+  }
+
+#else
+
+  ply2.joy_snap = snap;
+  ply2.joy_drop = drop;
+  if (ply2.joy_stick || (north | east | south | west))
+  {
+    ply2.joy_n = north;
+    ply2.joy_e = east;
+    ply2.joy_s = south;
+    ply2.joy_w = west;
+  }
+#endif
+}
diff --git a/src/game_em/level.h b/src/game_em/level.h
new file mode 100644 (file)
index 0000000..46ba9e4
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef LEVEL_H
+#define LEVEL_H
+
+#include "main_em.h"
+#include "tile.h"
+
+#define WIDTH          EM_MAX_CAVE_WIDTH
+#define HEIGHT         EM_MAX_CAVE_HEIGHT
+
+#if 0
+
+struct LEVEL
+{
+  unsigned int home;     /* number of players that have to go home */
+                         /* 0 == all players home */
+
+  unsigned int width;    /* world width */
+  unsigned int height;   /* world height */
+  unsigned int time;     /* time remaining */
+  unsigned int required; /* emeralds needed */
+  unsigned int score;    /* score */
+
+  /* fill in all below /every/ time you read a level */
+  unsigned int alien_score;           /* alien popped by stone/spring score */
+  unsigned int amoeba_time;           /* amoeba speed */
+  unsigned int android_move_cnt;      /* android move time counter */
+  unsigned int android_move_time;     /* android move reset time */
+  unsigned int android_clone_cnt;     /* android clone time counter */
+  unsigned int android_clone_time;    /* android clone reset time */
+  unsigned int ball_cnt;              /* ball time counter */
+  unsigned int ball_pos;              /* ball array pos counter */
+  unsigned int ball_random;           /* ball is random flag */
+  unsigned int ball_state;            /* ball currently on flag */
+  unsigned int ball_time;             /* ball reset time */
+  unsigned int bug_score;             /* bug popped by stone/spring score */
+  unsigned int diamond_score;         /* diamond collect score */
+  unsigned int dynamite_score;        /* dynamite collect scoer*/
+  unsigned int eater_pos;             /* eater array pos */
+  unsigned int eater_score;           /* eater popped by stone/spring score */
+  unsigned int emerald_score;         /* emerald collect score */
+  unsigned int exit_score;            /* exit score */
+  unsigned int key_score;             /* key collect score */
+  unsigned int lenses_cnt;            /* lenses time counter */
+  unsigned int lenses_score;          /* lenses collect score */
+  unsigned int lenses_time;           /* lenses reset time */
+  unsigned int magnify_cnt;           /* magnify time counter */
+  unsigned int magnify_score;         /* magnify collect score */
+  unsigned int magnify_time;          /* magnify reset time */
+  unsigned int nut_score;             /* nut crack score */
+  unsigned int shine_cnt;             /* shine counter for emerald/diamond */
+  unsigned int slurp_score;           /* slurp alien score */
+  unsigned int tank_score;            /* tank popped by stone/spring */
+  unsigned int wheel_cnt;             /* wheel time counter */
+  unsigned int wheel_x;               /* wheel x pos */
+  unsigned int wheel_y;               /* wheel y pos */
+  unsigned int wheel_time;            /* wheel reset time */
+  unsigned int wind_cnt;              /* wind time counter */
+  unsigned int wind_direction;        /* wind direction */
+  unsigned int wind_time;             /* wind reset time */
+  unsigned int wonderwall_state;      /* wonderwall currently on flag */
+  unsigned int wonderwall_time;       /* wonderwall time */
+  unsigned short eater_array[8][9];   /* eater data */
+  unsigned short ball_array[8][8];    /* ball data */
+  unsigned short android_array[TILE_MAX]; /* android clone table */
+};
+
+struct PLAYER
+{
+  unsigned int num;
+  unsigned int alive;
+  unsigned int dynamite;
+  unsigned int dynamite_cnt;
+  unsigned int keys;
+  unsigned int anim;
+  unsigned int x;
+  unsigned int y;
+  unsigned int oldx;
+  unsigned int oldy;
+
+  unsigned joy_n:1;
+  unsigned joy_e:1;
+  unsigned joy_s:1;
+  unsigned joy_w:1;
+  unsigned joy_snap:1;
+  unsigned joy_drop:1;
+  unsigned joy_stick:1;
+  unsigned joy_spin:1;
+};
+
+#endif
+
+extern unsigned long RandomEM;
+
+extern struct PLAYER ply1;
+extern struct PLAYER ply2;
+extern struct LEVEL lev;
+
+extern struct LevelInfo_EM native_em_level;
+extern struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8];
+extern struct GraphicInfo_EM graphic_info_em_player[2][SPR_MAX][8];
+
+extern unsigned short **Boom;
+extern unsigned short **Cave;
+extern unsigned short **Next;
+extern unsigned short **Draw;
+
+#endif
diff --git a/src/game_em/main.c b/src/game_em/main.c
new file mode 100644 (file)
index 0000000..85f92c9
--- /dev/null
@@ -0,0 +1,8 @@
+/* Emerald Mine
+ * 
+ * David Tritscher
+ * 
+ * v0.0 2000-01-06T06:43:39Z
+ *
+ * set everything up and close everything down
+ */
diff --git a/src/game_em/main_em.h b/src/game_em/main_em.h
new file mode 100644 (file)
index 0000000..17cb9f7
--- /dev/null
@@ -0,0 +1,674 @@
+#ifndef MAIN_EM_H
+#define MAIN_EM_H
+
+#include "../engines.h"
+
+
+/* 2000-07-30T11:06:03Z ---------------------------------------------------- */
+
+#define EM_MAX_CAVE_WIDTH              102
+#define EM_MAX_CAVE_HEIGHT             102
+
+/* define these for backwards compatibility */
+#define EM_ENGINE_BAD_ROLL
+#define EM_ENGINE_BAD_SPRING
+
+
+/*
+  -----------------------------------------------------------------------------
+  definition of elements used in the Emerald Mine Club engine;
+  the element names have the following properties:
+  - elements that start with an 'X' can be stored in a level file;
+  - elements that start with an 'Y' indicate moving elements;
+  - elements that end with a 'B' are the "backside" of a moving element.
+  -----------------------------------------------------------------------------
+*/
+
+enum
+{
+  Xblank = 0,          /* still */
+  Yacid_splash_eB,     /* hmm */
+  Yacid_splash_wB,     /* hmm */
+
+#ifdef EM_ENGINE_BAD_ROLL
+  Xstone_force_e,      /* only use these in eater */
+  Xstone_force_w,
+  Xnut_force_e,
+  Xnut_force_w,
+  Xspring_force_e,
+  Xspring_force_w,
+  Xemerald_force_e,
+  Xemerald_force_w,
+  Xdiamond_force_e,
+  Xdiamond_force_w,
+  Xbomb_force_e,
+  Xbomb_force_w,
+#endif
+
+  Xstone,
+  Xstone_pause,
+  Xstone_fall,
+  Ystone_s,
+  Ystone_sB,
+  Ystone_e,
+  Ystone_eB,
+  Ystone_w,
+  Ystone_wB,
+  Xnut,
+  Xnut_pause,
+  Xnut_fall,
+  Ynut_s,
+  Ynut_sB,
+  Ynut_e,
+  Ynut_eB,
+  Ynut_w,
+  Ynut_wB,
+  Xbug_n,
+  Xbug_e,
+  Xbug_s,
+  Xbug_w,
+  Xbug_gon,
+  Xbug_goe,
+  Xbug_gos,
+  Xbug_gow,
+  Ybug_n,
+  Ybug_nB,
+  Ybug_e,
+  Ybug_eB,
+  Ybug_s,
+  Ybug_sB,
+  Ybug_w,
+  Ybug_wB,
+  Ybug_w_n,
+  Ybug_n_e,
+  Ybug_e_s,
+  Ybug_s_w,
+  Ybug_e_n,
+  Ybug_s_e,
+  Ybug_w_s,
+  Ybug_n_w,
+  Ybug_stone,
+  Ybug_spring,
+  Xtank_n,
+  Xtank_e,
+  Xtank_s,
+  Xtank_w,
+  Xtank_gon,
+  Xtank_goe,
+  Xtank_gos,
+  Xtank_gow,
+  Ytank_n,
+  Ytank_nB,
+  Ytank_e,
+  Ytank_eB,
+  Ytank_s,
+  Ytank_sB,
+  Ytank_w,
+  Ytank_wB,
+  Ytank_w_n,
+  Ytank_n_e,
+  Ytank_e_s,
+  Ytank_s_w,
+  Ytank_e_n,
+  Ytank_s_e,
+  Ytank_w_s,
+  Ytank_n_w,
+  Ytank_stone,
+  Ytank_spring,
+  Xandroid,
+  Xandroid_1_n,
+  Xandroid_2_n,
+  Xandroid_1_e,
+  Xandroid_2_e,
+  Xandroid_1_w,
+  Xandroid_2_w,
+  Xandroid_1_s,
+  Xandroid_2_s,
+  Yandroid_n,
+  Yandroid_nB,
+  Yandroid_ne,
+  Yandroid_neB,
+  Yandroid_e,
+  Yandroid_eB,
+  Yandroid_se,
+  Yandroid_seB,
+  Yandroid_s,
+  Yandroid_sB,
+  Yandroid_sw,
+  Yandroid_swB,
+  Yandroid_w,
+  Yandroid_wB,
+  Yandroid_nw,
+  Yandroid_nwB,
+  Xspring,
+  Xspring_pause,
+  Xspring_e,
+  Xspring_w,
+  Xspring_fall,
+  Yspring_s,
+  Yspring_sB,
+  Yspring_e,
+  Yspring_eB,
+  Yspring_w,
+  Yspring_wB,
+  Yspring_kill_e,
+  Yspring_kill_eB,
+  Yspring_kill_w,
+  Yspring_kill_wB,
+  Xeater_n,
+  Xeater_e,
+  Xeater_w,
+  Xeater_s,
+  Yeater_n,
+  Yeater_nB,
+  Yeater_e,
+  Yeater_eB,
+  Yeater_s,
+  Yeater_sB,
+  Yeater_w,
+  Yeater_wB,
+  Yeater_stone,
+  Yeater_spring,
+  Xalien,
+  Xalien_pause,
+  Yalien_n,
+  Yalien_nB,
+  Yalien_e,
+  Yalien_eB,
+  Yalien_s,
+  Yalien_sB,
+  Yalien_w,
+  Yalien_wB,
+  Yalien_stone,
+  Yalien_spring,
+  Xemerald,
+  Xemerald_pause,
+  Xemerald_fall,
+  Xemerald_shine,
+  Yemerald_s,
+  Yemerald_sB,
+  Yemerald_e,
+  Yemerald_eB,
+  Yemerald_w,
+  Yemerald_wB,
+  Yemerald_eat,
+  Yemerald_stone,
+  Xdiamond,
+  Xdiamond_pause,
+  Xdiamond_fall,
+  Xdiamond_shine,
+  Ydiamond_s,
+  Ydiamond_sB,
+  Ydiamond_e,
+  Ydiamond_eB,
+  Ydiamond_w,
+  Ydiamond_wB,
+  Ydiamond_eat,
+  Ydiamond_stone,
+  Xdrip_fall,
+  Xdrip_stretch,
+  Xdrip_stretchB,
+  Xdrip_eat,
+  Ydrip_s1,
+  Ydrip_s1B,
+  Ydrip_s2,
+  Ydrip_s2B,
+  Xbomb,
+  Xbomb_pause,
+  Xbomb_fall,
+  Ybomb_s,
+  Ybomb_sB,
+  Ybomb_e,
+  Ybomb_eB,
+  Ybomb_w,
+  Ybomb_wB,
+  Ybomb_eat,
+  Xballoon,
+  Yballoon_n,
+  Yballoon_nB,
+  Yballoon_e,
+  Yballoon_eB,
+  Yballoon_s,
+  Yballoon_sB,
+  Yballoon_w,
+  Yballoon_wB,
+  Xgrass,
+  Ygrass_nB,
+  Ygrass_eB,
+  Ygrass_sB,
+  Ygrass_wB,
+  Xdirt,
+  Ydirt_nB,
+  Ydirt_eB,
+  Ydirt_sB,
+  Ydirt_wB,
+  Xacid_ne,
+  Xacid_se,
+  Xacid_s,
+  Xacid_sw,
+  Xacid_nw,
+  Xacid_1,
+  Xacid_2,
+  Xacid_3,
+  Xacid_4,
+  Xacid_5,
+  Xacid_6,
+  Xacid_7,
+  Xacid_8,
+  Xball_1,
+  Xball_1B,
+  Xball_2,
+  Xball_2B,
+  Yball_eat,
+
+#if 1
+  Ykey_1_eat,
+  Ykey_2_eat,
+  Ykey_3_eat,
+  Ykey_4_eat,
+  Ykey_5_eat,
+  Ykey_6_eat,
+  Ykey_7_eat,
+  Ykey_8_eat,
+  Ylenses_eat,
+  Ymagnify_eat,
+  Ygrass_eat,
+  Ydirt_eat,
+#endif
+
+  Xgrow_ns,
+  Ygrow_ns_eat,
+  Xgrow_ew,
+  Ygrow_ew_eat,
+  Xwonderwall,
+  XwonderwallB,
+  Xamoeba_1,
+  Xamoeba_2,
+  Xamoeba_3,
+  Xamoeba_4,
+  Xamoeba_5,
+  Xamoeba_6,
+  Xamoeba_7,
+  Xamoeba_8,
+  Xdoor_1,
+  Xdoor_2,
+  Xdoor_3,
+  Xdoor_4,
+  Xdoor_5,
+  Xdoor_6,
+  Xdoor_7,
+  Xdoor_8,
+  Xkey_1,
+  Xkey_2,
+  Xkey_3,
+  Xkey_4,
+  Xkey_5,
+  Xkey_6,
+  Xkey_7,
+  Xkey_8,
+  Xwind_n,
+  Xwind_e,
+  Xwind_s,
+  Xwind_w,
+  Xwind_nesw,
+  Xwind_stop,
+  Xexit,
+  Xexit_1,
+  Xexit_2,
+  Xexit_3,
+  Xdynamite,
+  Ydynamite_eat,
+  Xdynamite_1,
+  Xdynamite_2,
+  Xdynamite_3,
+  Xdynamite_4,
+  Xbumper,
+  XbumperB,
+  Xwheel,
+  XwheelB,
+  Xswitch,
+  XswitchB,
+  Xsand,
+  Xsand_stone,
+  Xsand_stonein_1,
+  Xsand_stonein_2,
+  Xsand_stonein_3,
+  Xsand_stonein_4,
+  Xsand_stonesand_1,
+  Xsand_stonesand_2,
+  Xsand_stonesand_3,
+  Xsand_stonesand_4,
+  Xsand_stoneout_1,
+  Xsand_stoneout_2,
+  Xsand_sandstone_1,
+  Xsand_sandstone_2,
+  Xsand_sandstone_3,
+  Xsand_sandstone_4,
+  Xplant,
+  Yplant,
+  Xlenses,
+  Xmagnify,
+  Xdripper,
+  XdripperB,
+  Xfake_blank,
+  Xfake_blankB,
+  Xfake_grass,
+  Xfake_grassB,
+  Xfake_door_1,
+  Xfake_door_2,
+  Xfake_door_3,
+  Xfake_door_4,
+  Xfake_door_5,
+  Xfake_door_6,
+  Xfake_door_7,
+  Xfake_door_8,
+
+#if 1
+  Xfake_acid_1,
+  Xfake_acid_2,
+  Xfake_acid_3,
+  Xfake_acid_4,
+  Xfake_acid_5,
+  Xfake_acid_6,
+  Xfake_acid_7,
+  Xfake_acid_8,
+#endif
+
+  Xsteel_1,
+  Xsteel_2,
+  Xsteel_3,
+  Xsteel_4,
+  Xwall_1,
+  Xwall_2,
+  Xwall_3,
+  Xwall_4,
+  Xround_wall_1,
+  Xround_wall_2,
+  Xround_wall_3,
+  Xround_wall_4,
+  Xdecor_1,
+  Xdecor_2,
+  Xdecor_3,
+  Xdecor_4,
+  Xdecor_5,
+  Xdecor_6,
+  Xdecor_7,
+  Xdecor_8,
+  Xdecor_9,
+  Xdecor_10,
+  Xdecor_11,
+  Xdecor_12,
+  Xalpha_0,
+  Xalpha_1,
+  Xalpha_2,
+  Xalpha_3,
+  Xalpha_4,
+  Xalpha_5,
+  Xalpha_6,
+  Xalpha_7,
+  Xalpha_8,
+  Xalpha_9,
+  Xalpha_excla,
+  Xalpha_quote,
+  Xalpha_comma,
+  Xalpha_minus,
+  Xalpha_perio,
+  Xalpha_colon,
+  Xalpha_quest,
+  Xalpha_a,
+  Xalpha_b,
+  Xalpha_c,
+  Xalpha_d,
+  Xalpha_e,
+  Xalpha_f,
+  Xalpha_g,
+  Xalpha_h,
+  Xalpha_i,
+  Xalpha_j,
+  Xalpha_k,
+  Xalpha_l,
+  Xalpha_m,
+  Xalpha_n,
+  Xalpha_o,
+  Xalpha_p,
+  Xalpha_q,
+  Xalpha_r,
+  Xalpha_s,
+  Xalpha_t,
+  Xalpha_u,
+  Xalpha_v,
+  Xalpha_w,
+  Xalpha_x,
+  Xalpha_y,
+  Xalpha_z,
+  Xalpha_arrow_e,
+  Xalpha_arrow_w,
+  Xalpha_copyr,
+
+  Xboom_bug,           /* passed from explode to synchro (linked explosion);
+                          transition to explode_normal */
+  Xboom_bomb,          /* passed from explode to synchro (linked explosion);
+                          transition to explode_normal */
+  Xboom_android,       /* passed from explode to synchro;
+                          transition to boom_2 */
+  Xboom_1,             /* passed from explode to synchro;
+                          transition to boom_2 */
+  Xboom_2,             /* transition to boom[] */
+
+  Znormal,             /* passed from synchro to explode, only in next[];
+                          no picture */
+  Zdynamite,           /* passed from synchro to explode, only in next[];
+                          no picture */
+  Zplayer,             /* special code to indicate player;
+                          no picture */
+  ZBORDER,             /* special code to indicate border;
+                          no picture */
+
+  TILE_MAX
+};
+
+enum
+{
+  SPR_still = 0,
+  SPR_walk  = 1,
+  SPR_push  = 5,
+  SPR_spray = 9,
+
+  SPR_MAX   = 13
+};
+
+enum
+{
+  SAMPLE_blank = 0,    /* player walks on blank */
+  SAMPLE_roll,         /* player pushes stone/bomb/nut/spring */
+  SAMPLE_stone,                /* stone hits ground */
+  SAMPLE_nut,          /* nut hits ground */
+  SAMPLE_crack,                /* stone hits nut */
+  SAMPLE_bug,          /* bug moves */
+  SAMPLE_tank,         /* tank moves */
+  SAMPLE_android_clone,        /* android places something */
+  SAMPLE_android_move, /* android moves */
+  SAMPLE_spring,       /* spring hits ground/wall/bumper, stone hits spring */
+  SAMPLE_slurp,                /* spring kills alien */
+  SAMPLE_eater,                /* eater sits */
+  SAMPLE_eater_eat,    /* eater eats diamond */
+  SAMPLE_alien,                /* alien moves */
+  SAMPLE_collect,      /* player collects object */
+  SAMPLE_diamond,      /* diamond/emerald hits ground */
+  SAMPLE_squash,       /* stone squashes diamond */
+  SAMPLE_wonderfall,   /* object falls thru wonderwall */
+  SAMPLE_drip,         /* drip hits ground */
+  SAMPLE_push,         /* player pushes balloon/android */
+  SAMPLE_dirt,         /* player walks on dirt */
+  SAMPLE_acid,         /* acid splashes */
+  SAMPLE_ball,         /* ball places something */
+  SAMPLE_grow,         /* growing wall grows */
+  SAMPLE_wonder,       /* wonderwall is active */
+  SAMPLE_door,         /* player goes thru door (gate) */
+  SAMPLE_exit_open,    /* exit opens */
+  SAMPLE_exit_leave,   /* player goes into exit */
+  SAMPLE_dynamite,     /* player places dynamite */
+  SAMPLE_tick,         /* dynamite ticks */
+  SAMPLE_press,                /* player presses wheel/wind/switch */
+  SAMPLE_wheel,                /* wheel moves */
+  SAMPLE_boom,         /* explosion */
+  SAMPLE_time,         /* time runs out */
+  SAMPLE_die,          /* player dies */
+
+  SAMPLE_MAX
+};
+
+struct LEVEL
+{
+  unsigned int home_initial;           /* number of players (initial) */
+  unsigned int home;                   /* number of players not yet at home */
+                                       /* 0 == all players at home */
+
+  unsigned int width;                  /* playfield width */
+  unsigned int height;                 /* playfield height */
+
+  unsigned int time_seconds;           /* available time (seconds) */
+  unsigned int time_initial;           /* available time (initial) */
+  unsigned int time;                   /* time remaining (runtime) */
+
+  boolean killed_out_of_time;          /* kill player due to time out */
+
+  unsigned int required_initial;       /* emeralds needed (initial) */
+  unsigned int required;               /* emeralds needed (runtime) */
+
+  unsigned int score;                  /* score */
+
+  /* all below entries must be filled every time a level is read */
+
+  unsigned int alien_score;            /* score for killing alien */
+  unsigned int amoeba_time;            /* amoeba speed */
+  unsigned int android_move_cnt_initial;/* android move counter (initial) */
+  unsigned int android_move_cnt;       /* android move counter */
+  unsigned int android_move_time;      /* android move reset time */
+  unsigned int android_clone_cnt_initial;/* android clone counter (initial) */
+  unsigned int android_clone_cnt;      /* android clone counter */
+  unsigned int android_clone_time;     /* android clone reset time */
+  unsigned int ball_cnt;               /* ball counter */
+  unsigned int ball_pos;               /* ball array pos counter */
+  unsigned int ball_random;            /* ball is random flag */
+  unsigned int ball_state_initial;     /* ball active flag (initial) */
+  unsigned int ball_state;             /* ball active flag */
+  unsigned int ball_time;              /* ball reset time */
+  unsigned int bug_score;              /* score for killing bug */
+  unsigned int diamond_score;          /* score for collecting diamond */
+  unsigned int dynamite_score;         /* score for collecting dynamite */
+  unsigned int eater_pos;              /* eater array pos */
+  unsigned int eater_score;            /* score for killing eater */
+  unsigned int emerald_score;          /* score for collecting emerald */
+  unsigned int exit_score;             /* score for entering exit */
+  unsigned int key_score;              /* score for colleting key */
+  unsigned int lenses_cnt_initial;     /* lenses counter (initial) */
+  unsigned int lenses_cnt;             /* lenses counter */
+  unsigned int lenses_score;           /* score for collecting lenses */
+  unsigned int lenses_time;            /* lenses reset time */
+  unsigned int magnify_cnt_initial;    /* magnify counter (initial) */
+  unsigned int magnify_cnt;            /* magnify counter */
+  unsigned int magnify_score;          /* score for collecting magnifier */
+  unsigned int magnify_time;           /* magnify reset time */
+  unsigned int nut_score;              /* score for cracking nut */
+  unsigned int shine_cnt;              /* shine counter for emerald/diamond */
+  unsigned int slurp_score;            /* score for slurping alien */
+  unsigned int tank_score;             /* score for killing tank */
+  unsigned int wheel_cnt_initial;      /* wheel counter (initial) */
+  unsigned int wheel_cnt;              /* wheel counter */
+  unsigned int wheel_x_initial;                /* wheel x pos (initial) */
+  unsigned int wheel_x;                        /* wheel x pos */
+  unsigned int wheel_y_initial;                /* wheel y pos (initial) */
+  unsigned int wheel_y;                        /* wheel y pos */
+  unsigned int wheel_time;             /* wheel reset time */
+  unsigned int wind_cnt_initial;       /* wind counter (initial) */
+  unsigned int wind_cnt;               /* wind time counter */
+  unsigned int wind_direction_initial; /* wind direction (initial) */
+  unsigned int wind_direction;         /* wind direction */
+  unsigned int wind_time;              /* wind reset time */
+  unsigned int wonderwall_state_initial;/* wonderwall active flag (initial) */
+  unsigned int wonderwall_state;       /* wonderwall active flag */
+  unsigned int wonderwall_time_initial;        /* wonderwall time (initial) */
+  unsigned int wonderwall_time;                /* wonderwall time */
+  unsigned short eater_array[8][9];    /* eater data */
+  unsigned short ball_array[8][8];     /* ball data */
+  unsigned short android_array[TILE_MAX];/* android clone table */
+};
+
+struct PLAYER
+{
+  unsigned int num;
+  unsigned int alive_initial;
+  unsigned int alive;
+
+  unsigned int dynamite;
+  unsigned int dynamite_cnt;
+  unsigned int keys;
+  unsigned int anim;
+
+  unsigned int x_initial;
+  unsigned int y_initial;
+  unsigned int x;
+  unsigned int y;
+  unsigned int oldx;
+  unsigned int oldy;
+
+  unsigned int last_move_dir;
+
+  unsigned joy_n:1;
+  unsigned joy_e:1;
+  unsigned joy_s:1;
+  unsigned joy_w:1;
+  unsigned joy_snap:1;
+  unsigned joy_drop:1;
+  unsigned joy_stick:1;
+  unsigned joy_spin:1;
+};
+
+
+/* ------------------------------------------------------------------------- */
+/* definitions and structures for use by the main game functions             */
+/* ------------------------------------------------------------------------- */
+
+/* values for native Emerald Mine game version */
+#define FILE_VERSION_EM_V3     3
+#define FILE_VERSION_EM_V4     4
+#define FILE_VERSION_EM_V5     5
+#define FILE_VERSION_EM_V6     6
+
+#define FILE_VERSION_EM_ACTUAL FILE_VERSION_EM_V6
+
+struct GlobalInfo_EM
+{
+  Bitmap *screenbuffer;
+};
+
+struct LevelInfo_EM
+{
+  int file_version;
+
+  unsigned short cave[EM_MAX_CAVE_WIDTH][EM_MAX_CAVE_HEIGHT];
+
+  struct LEVEL *lev;
+  struct PLAYER *ply1, *ply2;
+};
+
+struct GraphicInfo_EM
+{
+  Bitmap *bitmap;
+  int src_x, src_y;
+  int src_offset_x, src_offset_y;
+  int dst_offset_x, dst_offset_y;
+  int width, height;
+
+  Bitmap *crumbled_bitmap;
+  int crumbled_src_x, crumbled_src_y;
+  int crumbled_border_size;
+
+  boolean has_crumbled_graphics;
+  boolean preserve_background;
+
+  int unique_identifier;       /* used to identify needed screen updates */
+};
+
+#endif /* MAIN_EM_H */
diff --git a/src/game_em/sample.h b/src/game_em/sample.h
new file mode 100644 (file)
index 0000000..90c45a9
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef SAMPLE_H
+#define SAMPLE_H
+
+#include "main_em.h"
+
+
+#if 0
+
+enum
+{
+  SAMPLE_blank = 0,    /* player walks on blank */
+  SAMPLE_roll,         /* player pushes stone/bomb/nut/spring */
+  SAMPLE_stone,                /* stone hits ground */
+  SAMPLE_nut,          /* nut hits ground */
+  SAMPLE_crack,                /* stone hits nut */
+  SAMPLE_bug,          /* bug moves */
+  SAMPLE_tank,         /* tank moves */
+  SAMPLE_android_clone,        /* android places something */
+  SAMPLE_android_move, /* android moves */
+  SAMPLE_spring,       /* spring hits ground/wall/bumper, stone hits spring */
+  SAMPLE_slurp,                /* spring kills alien */
+  SAMPLE_eater,                /* eater sits */
+  SAMPLE_eater_eat,    /* eater eats diamond */
+  SAMPLE_alien,                /* alien moves */
+  SAMPLE_collect,      /* player collects object */
+  SAMPLE_diamond,      /* diamond/emerald hits ground */
+  SAMPLE_squash,       /* stone squashes diamond */
+  SAMPLE_wonderfall,   /* object falls thru wonderwall */
+  SAMPLE_drip,         /* drip hits ground */
+  SAMPLE_push,         /* player pushes balloon/android */
+  SAMPLE_dirt,         /* player walks on dirt */
+  SAMPLE_acid,         /* acid splashes */
+  SAMPLE_ball,         /* ball places something */
+  SAMPLE_grow,         /* growing wall grows */
+  SAMPLE_wonder,       /* wonderwall moves (is active) */
+  SAMPLE_door,         /* player goes thru door */
+  SAMPLE_exit_open,    /* exit opens */
+  SAMPLE_exit_leave,   /* player goes into exit */
+  SAMPLE_dynamite,     /* player places dynamite */
+  SAMPLE_tick,         /* dynamite ticks */
+  SAMPLE_press,                /* player presses wheel/wind/switch */
+  SAMPLE_wheel,                /* wheel moves */
+  SAMPLE_boom,         /* explosion */
+  SAMPLE_time,         /* time runs out */
+  SAMPLE_die,          /* player dies */
+
+  SAMPLE_MAX
+};
+
+#endif
+
+extern void play_sound(int, int, int);
+extern void play_element_sound(int, int, int, int);
+
+extern char play[SAMPLE_MAX];
+extern int sound_pipe[2];
+extern short *sound_data[SAMPLE_MAX];
+extern long sound_length[SAMPLE_MAX];
+
+#define MIXER_MAX 4    /* maximum number of samples we can play at once */
+
+#if defined(AUDIO_UNIX_NATIVE)
+
+enum
+{
+  AUDIO_ULAW = 0,
+  AUDIO_U8
+};
+
+#endif /* AUDIO_UNIX_NATIVE */
+
+#endif /* SAMPLE_H */
diff --git a/src/game_em/sound.c b/src/game_em/sound.c
new file mode 100644 (file)
index 0000000..9bdd2be
--- /dev/null
@@ -0,0 +1,520 @@
+/* 2000-08-10T17:39:15Z
+ *
+ * handle sounds in emerald mine
+ */
+
+#include "main_em.h"
+
+
+#if defined(AUDIO_UNIX_NATIVE)
+
+#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
+
+#ifdef PLATFORM_LINUX
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+#endif
+
+#ifdef PLATFORM_BSD
+#include <ioctl.h>
+#include <soundcard.h>
+#endif
+
+#include "global.h"
+#include "sample.h"
+
+static char audioname[] = "/dev/audio";
+
+static const int sound_priority[SAMPLE_MAX] =
+{
+  SAMPLE_exit_open,
+  SAMPLE_exit_leave,
+  SAMPLE_die,
+  SAMPLE_time,
+  SAMPLE_boom,
+  SAMPLE_tick,
+  SAMPLE_collect,
+  SAMPLE_roll,
+  SAMPLE_push,
+  SAMPLE_dynamite,
+  SAMPLE_press,
+  SAMPLE_door,
+  SAMPLE_dirt,
+  SAMPLE_blank,
+  SAMPLE_android_clone,
+  SAMPLE_android_move,
+  SAMPLE_ball,
+  SAMPLE_grow,
+  SAMPLE_squash,
+  SAMPLE_wonderfall,
+  SAMPLE_crack,
+  SAMPLE_slurp,
+  SAMPLE_drip,
+  SAMPLE_wonder,
+  SAMPLE_wheel,
+  SAMPLE_stone,
+  SAMPLE_spring,
+  SAMPLE_diamond,
+  SAMPLE_nut,
+  SAMPLE_bug,
+  SAMPLE_tank,
+  SAMPLE_eater,
+  SAMPLE_eater_eat,
+  SAMPLE_alien,
+  SAMPLE_acid
+};
+
+int sound_thread(void)
+{
+  int audio_fd; /* file descriptor of /dev/audio or -1 if not open */
+  int audio_format;
+  int sample_rate;
+  int fragment_size;
+  unsigned char *audio_buffer; /* actual buffer pumped to /dev/audio */
+  short *mix_buffer;
+
+  char sound_play[SAMPLE_MAX]; /* if set, we should be playing these sounds */
+  long sound_pos[SAMPLE_MAX]; /* position in the sound */
+  int mix_play[MIXER_MAX]; /* which sounds we have chosen to mix (calculated each time) */
+  int mix_count;
+  int i;
+
+ loop:
+
+  audio_fd = -1;
+  audio_format = AUDIO_ULAW; /* defaults for non-OSS /dev/audio */
+  sample_rate = 8000;
+  fragment_size = 256;
+  audio_buffer = 0;
+  mix_buffer = 0;
+  mix_count = 0;
+
+  memset(sound_play, 0, sizeof(sound_play)); /* not playing any sounds */
+
+  for (;;)
+  {
+    for (;;)
+    {
+
+      /* pick sounds to play, if any */
+      if (sound_play[SAMPLE_exit_open] ||
+         sound_play[SAMPLE_exit_leave] ||
+         sound_play[SAMPLE_die])
+       sound_play[SAMPLE_boom] = 0; /* no explosions if player goes home */
+
+      mix_count = 0;
+      for (i = 0; i < SAMPLE_MAX; i++)
+      {
+       if (sound_play[sound_priority[i]])
+       {
+         mix_play[mix_count++] = sound_priority[i];
+
+         if (mix_count == MIXER_MAX)
+           break; /* cant mix too many sounds at once */
+       }
+      }
+
+      /* check for incoming messages */
+      if (mix_count || audio_fd != -1)
+      {
+       /* dont block if we are playing sounds */
+       fd_set rfds;
+       struct timeval tv;
+       FD_ZERO(&rfds);
+       FD_SET(sound_pipe[0], &rfds);
+       tv.tv_sec = 0;
+       tv.tv_usec = 0; /* (900000 * fragment_size / sample_rate) */
+       i = select(sound_pipe[0] + 1, &rfds, 0, 0, &tv); /* dont block */
+
+       if (i == -1)
+       {
+         Error(ERR_WARN, "select() failed in sound thread");
+
+         goto fail;
+       }
+
+       if (i == 0)
+         break; /* no messages */
+      }
+
+      /* get a message and start a sound */
+      i = read(sound_pipe[0], &play, sizeof(play));
+
+      if (i == -1)
+      {
+       Error(ERR_WARN, "read() failed in sound thread");
+
+       goto fail;
+      }
+
+      if (i == 0)
+      {
+       Error(ERR_WARN, "reading sound failed in sound thread");
+
+       goto fail;
+      }
+
+      if (i != sizeof(play))
+      {
+       Error(ERR_WARN, "bad message length in sound thread");
+
+       goto fail;
+      }
+
+      for (i = 0; i < SAMPLE_MAX; i++)
+      {
+       if (play[i])
+       {
+         sound_play[i] = 1; /* play this sound */
+         sound_pos[i] = 0; /* start it from the start */
+       }
+      }
+    }
+
+    /* open the audio device if there are sounds to play */
+    if (mix_count && audio_fd == -1)
+    {
+      audio_fd = open(audioname, O_WRONLY);
+
+      if (audio_fd == -1)
+       goto reset;
+
+#ifdef OPEN_SOUND_SYSTEM
+      i = 0x00020008;
+
+      if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i) == -1)
+      {
+       Error(ERR_WARN, "unable to set fragment size in sound thread");
+
+       goto reset;
+      }
+
+      if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i) == -1)
+      {
+       Error(ERR_WARN, "unable to query audio format in sound thread");
+
+       goto reset;
+      }
+
+      /* prefer 8 bit unsigned and fall back on mu-law */
+      audio_format = (i & AFMT_U8) ? AFMT_U8 : AFMT_MU_LAW;
+
+      i = audio_format;
+      if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &i) == -1)
+      {
+       Error(ERR_WARN, "unable to set audio format in sound thread");
+
+       goto reset;
+      }
+
+      if (i == AFMT_MU_LAW)
+      {
+       audio_format = AUDIO_ULAW;
+      }
+      else if (i == AFMT_U8)
+      {
+       audio_format = AUDIO_U8;
+      }
+      else
+      {
+       Error(ERR_WARN, "audio format required by device not supported");
+
+       goto reset;
+      }
+
+      i = 1;
+      if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &i) == -1)
+      {
+       Error(ERR_WARN, "unable to set channels to mono in sound thread");
+
+       goto reset;
+      }
+
+      if (i != 1)
+      {
+       Error(ERR_WARN, "channels required by device not supported");
+
+       goto reset;
+      }
+
+      i = 8000;
+      if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &i) == -1)
+      {
+       Error(ERR_WARN, "unable to set sampling rate in sound thread");
+
+       goto reset;
+      }
+
+      sample_rate = i;
+      if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &i) == -1)
+      {
+       Error(ERR_WARN, "unable to get block size in sound thread");
+
+       goto reset;
+      }
+
+      fragment_size = i;
+
+#else
+      if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) == -1)
+      {
+       Error(ERR_WARN, "unable to make audio non blocking in sound thread");
+
+       goto reset;
+      }
+
+#endif /* OPEN_SOUND_SYSTEM */
+
+      audio_buffer = malloc(fragment_size * sizeof(*audio_buffer));
+      if (audio_buffer == 0)
+      {
+       Error(ERR_WARN, "unable to malloc audio buffer in sound thread");
+
+       goto fail;
+      }
+
+      mix_buffer = malloc(fragment_size * sizeof(*mix_buffer));
+      if (mix_buffer == 0)
+      {
+       Error(ERR_WARN, "unable to malloc mixing buffer in sound thread");
+
+       goto fail;
+      }
+    }
+
+    /* close the audio device if no sounds are playing */
+    if (mix_count == 0 && audio_fd != -1)
+    {
+      close(audio_fd);
+      free(audio_buffer);
+      free(mix_buffer);
+      audio_fd = -1;
+      audio_buffer = 0;
+      mix_buffer = 0;
+    }
+
+    /* if we are playing sounds and the audio device is open, mix them */
+    if (mix_count && audio_fd != -1)
+    {
+      /* prepare mix buffer */
+      memset(mix_buffer, 0, fragment_size * sizeof(*mix_buffer));
+
+      for (i = 0; i < mix_count; i++)
+      {
+       register short *mix_ptr = mix_buffer;
+       register short *sound_ptr =
+         sound_data[mix_play[i]] + sound_pos[mix_play[i]];
+       register long count =
+         sound_length[mix_play[i]] - sound_pos[mix_play[i]];
+
+       if (count > fragment_size)
+         count = fragment_size;
+
+       while (count--)
+         *mix_ptr++ += *sound_ptr++; /* mix the sounds in */
+      }
+
+      switch(audio_format)
+      {
+        case AUDIO_ULAW:
+         for (i = 0; i < fragment_size; i++)
+           audio_buffer[i] = linear_to_ulaw[mix_buffer[i] + 32768];
+         break;
+
+        case AUDIO_U8:
+         for (i = 0; i < fragment_size; i++)
+           audio_buffer[i] = (mix_buffer[i] + 32768) >> 8;
+         break;
+      }
+
+      /* advance sound pointers */
+      for (i = 0; i < SAMPLE_MAX; i++)
+      {
+       if (sound_play[i])
+       {
+         if (sound_pos[i] + fragment_size < sound_length[i])
+         {
+           sound_pos[i] += fragment_size;
+         }
+         else
+         {
+           sound_play[i] = 0;
+         }
+       }
+      }
+
+      /* send the data to the audio device */
+      i = write(audio_fd, audio_buffer, fragment_size);
+      if (i == -1)
+      {
+       Error(ERR_WARN, "cannot write to audio device in sound thread");
+
+       goto reset;
+      }
+
+      if (i != fragment_size)
+      {
+       Error(ERR_WARN, "bad write length to audio device in sound thread");
+
+       goto reset;
+      }
+    }
+  } /* for */
+
+ reset:
+
+  if (audio_fd != -1)
+    close(audio_fd);
+  if (audio_buffer)
+    free(audio_buffer);
+  if (mix_buffer)
+    free(mix_buffer);
+
+  goto loop; /* back to top */
+
+ fail:
+  if (audio_fd != -1)
+    close(audio_fd);
+  if (audio_buffer)
+    free(audio_buffer);
+  if (mix_buffer)
+    free(mix_buffer);
+
+  return(0);
+}
+
+int read_sample(char *name, short **data, long *length)
+{
+  int result;
+  FILE *file = 0;
+  short *dataptr = 0;
+  long datalength;
+
+  int i, actual, ch;
+  unsigned char buffer[24];
+  unsigned long temp;
+
+  file = fopen(name, "rb");
+  if (file == 0)
+  {
+    Error(ERR_WARN, "cannot open file '%s' in sound thread", name);
+
+    result = 1;
+    goto fail;
+  }
+
+  actual = fread(buffer, 1, 24, file);
+  if (actual == -1)
+  {
+    Error(ERR_WARN, "cannot read file '%s' in sound thread", name);
+
+    result = 1;
+    goto fail;
+  }
+
+  if (actual < 24)
+  {
+    Error(ERR_WARN, "premature eof of file '%s' in sound thread", name);
+
+    result = 1;
+    goto fail;
+  }
+
+  /* magic */
+  temp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
+  if (temp != 0x2e736e64)
+  {
+    Error(ERR_WARN, "unrecognized format of file '%s' in sound thread", name);
+
+    result = 1;
+    goto fail;
+  }
+
+  /* header length */
+  temp = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
+  if (temp < 24)
+  {
+    Error(ERR_WARN, "bad header length of file '%s' in sound thread", name);
+
+    result = 1;
+    goto fail;
+  }
+
+  actual = temp;
+  for (i = 24; i < actual; i++)
+  {
+    /* skip the rest of the header */
+    ch = fgetc(file);
+    if (ch == EOF)
+      break;
+  }
+
+ /* data length */
+  temp = buffer[8] << 24 | buffer[9] << 16 | buffer[10] << 8 | buffer[11];
+  datalength = temp;
+
+  /* encoding */
+  temp = buffer[12] << 24 | buffer[13] << 16 | buffer[14] << 8 | buffer[15];
+  if (temp != 1)
+  {
+    fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
+           "bad encoding type", temp);
+    result = 1;
+    goto fail;
+  }
+
+  /* sample rate */
+  temp = buffer[16] << 24 | buffer[17] << 16 | buffer[18] << 8 | buffer[19];
+  if (temp != 8000)
+  {
+    fprintf(stderr, "%s: \"%s\": %s (%ld != 8000)\n", progname, name,
+           "bad sample rate", temp);
+    result = 1;
+    goto fail;
+  }
+
+  /* channels */
+  temp = buffer[20] << 24 | buffer[21] << 16 | buffer[22] << 8 | buffer[23];
+  if (temp != 1)
+  {
+    fprintf(stderr, "%s: \"%s\": %s (%ld != 1)\n", progname, name,
+           "unsupported channels", temp);
+    result = 1;
+    goto fail;
+  }
+
+  dataptr = malloc(datalength * sizeof(*dataptr));
+  if (dataptr == 0)
+  {
+    Error(ERR_WARN, "unable to malloc buffer for file '%s' in sound thread",
+         name);
+
+    result = 1;
+    goto fail;
+  }
+
+  for (i = 0; i < datalength; i++)
+  {
+    ch = fgetc(file);
+    if (ch == EOF) break;
+    dataptr[i] = ulaw_to_linear[ch];
+  }
+
+  fclose(file);
+  file = 0;
+
+  *data = dataptr;
+  *length = datalength;
+  result = 0;
+
+ fail:
+
+  if (file)
+    fclose(file);
+
+  return(result);
+}
+
+#endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
+
+#endif /* AUDIO_UNIX_NATIVE */
diff --git a/src/game_em/synchro_1.c b/src/game_em/synchro_1.c
new file mode 100644 (file)
index 0000000..124751d
--- /dev/null
@@ -0,0 +1,1274 @@
+/* first part of synchro.
+ *
+ * game logic for players.
+ *
+ * large switch statement for tiles the player interacts with.
+ */
+
+#include "tile.h"
+#include "level.h"
+#include "sample.h"
+#include "display.h"
+
+
+static void check_player(struct PLAYER *);
+static void kill_player(struct PLAYER *);
+static boolean player_digfield(struct PLAYER *, int, int);
+static boolean player_killed(struct PLAYER *);
+
+void synchro_1(void)
+{
+ /* must test for death and actually kill separately */
+  boolean ply1_kill = player_killed(&ply1);
+  boolean ply2_kill = player_killed(&ply2);
+
+  if (ply1.alive && ply1_kill)
+    kill_player(&ply1);
+  if (ply2.alive && ply2_kill)
+    kill_player(&ply2);
+
+#if 0
+  ply1.alive = 1; /* debugging */
+#endif
+
+  ply1.oldx = ply1.x;
+  ply1.oldy = ply1.y;
+  ply1.anim = SPR_still;
+  ply2.oldx = ply2.x;
+  ply2.oldy = ply2.y;
+  ply2.anim = SPR_still;
+
+  if (RandomEM & 256)
+  {
+    if (ply1.alive) check_player(&ply1);
+    if (ply2.alive) check_player(&ply2);
+  }
+  else
+  {
+    if (ply2.alive) check_player(&ply2);
+    if (ply1.alive) check_player(&ply1);
+  }
+
+  if (ply1.alive)
+  {
+    if (Cave[ply1.oldy][ply1.oldx] == Zplayer)
+    {
+      Cave[ply1.oldy][ply1.oldx] = Xblank;
+      Next[ply1.oldy][ply1.oldx] = Xblank;
+    }
+
+    if (Cave[ply1.y][ply1.x] == Xblank)
+    {
+      Cave[ply1.y][ply1.x] = Zplayer;
+      Next[ply1.y][ply1.x] = Zplayer;
+    }
+  }
+
+  if (ply2.alive)
+  {
+    if (Cave[ply2.oldy][ply2.oldx] == Zplayer)
+    {
+      Cave[ply2.oldy][ply2.oldx] = Xblank;
+      Next[ply2.oldy][ply2.oldx] = Xblank;
+    }
+
+    if (Cave[ply2.y][ply2.x] == Xblank)
+    {
+      Cave[ply2.y][ply2.x] = Zplayer;
+      Next[ply2.y][ply2.x] = Zplayer;
+    }
+  }
+}
+
+static boolean player_killed(struct PLAYER *ply)
+{
+  register unsigned int x = ply->x;
+  register unsigned int y = ply->y;
+
+  if (!ply->alive)
+    return FALSE;
+
+#if 1
+  if (lev.killed_out_of_time && setup.time_limit)
+    return TRUE;
+#else
+  if (lev.time_initial > 0 && lev.time == 0 && setup.time_limit)
+    return TRUE;
+#endif
+
+  switch(Cave[y-1][x])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      return TRUE;
+  }
+
+  switch(Cave[y][x+1])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      return TRUE;
+  }
+
+  switch(Cave[y+1][x])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      return TRUE;
+  }
+
+  switch(Cave[y][x-1])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      return TRUE;
+  }
+
+  switch(Cave[y][x])
+  {
+    case Xblank:
+    case Yacid_splash_eB:
+    case Yacid_splash_wB:
+    case Zplayer:
+    case Xdynamite_1:
+    case Xdynamite_2:
+    case Xdynamite_3:
+    case Xdynamite_4:
+#if 1
+    case Xfake_acid_1:
+    case Xfake_acid_2:
+    case Xfake_acid_3:
+    case Xfake_acid_4:
+    case Xfake_acid_5:
+    case Xfake_acid_6:
+    case Xfake_acid_7:
+    case Xfake_acid_8:
+#endif
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+static void kill_player(struct PLAYER *ply)
+{
+  register unsigned int x = ply->x;
+  register unsigned int y = ply->y;
+
+  ply->alive = 0;
+
+  switch(Cave[y-1][x])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+      Cave[y-1][x] = Xboom_bug;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      Cave[y-1][x] = Xboom_bomb;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+  }
+
+  switch(Cave[y][x+1])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+      Cave[y][x+1] = Xboom_bug;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      Cave[y][x+1] = Xboom_bomb;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+  }
+
+  switch(Cave[y+1][x])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+      Cave[y+1][x] = Xboom_bug;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      Cave[y+1][x] = Xboom_bomb;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+  }
+
+  switch(Cave[y][x-1])
+  {
+    case Xbug_n:
+    case Xbug_e:
+    case Xbug_s:
+    case Xbug_w:
+    case Xbug_gon:
+    case Xbug_goe:
+    case Xbug_gos:
+    case Xbug_gow:
+      Cave[y][x-1] = Xboom_bug;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+
+    case Xtank_n:
+    case Xtank_e:
+    case Xtank_s:
+    case Xtank_w:
+    case Xtank_gon:
+    case Xtank_goe:
+    case Xtank_gos:
+    case Xtank_gow:
+      Cave[y][x-1] = Xboom_bomb;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Zplayer);
+#endif
+      break;
+  }
+
+  switch(Cave[y][x])
+  {
+    case Xexit_1:
+    case Xexit_2:
+    case Xexit_3:
+      play_element_sound(x, y, SAMPLE_exit_leave, Xexit_1);
+      break;
+
+    default:
+      play_element_sound(x, y, SAMPLE_die, Zplayer);
+      break;
+  }
+
+  switch(Cave[y][x])
+  {
+#if 1
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      break;
+#endif
+
+    default:
+      Cave[y][x] = Xboom_1;
+      Boom[y][x] = Xblank;
+      break;
+  }
+}
+
+static void check_player(struct PLAYER *ply)
+{
+  unsigned int oldx = ply->x;
+  unsigned int oldy = ply->y;
+  register unsigned int x = oldx;
+  register unsigned int y = oldy;
+  unsigned int anim = 0;
+  int dx = 0, dy = 0;
+
+#if 0
+  printf("::: up == %d, down == %d, left == %d, right == %d, fire == %d [spin == %d, stick == %d]\n",
+        ply->joy_n, ply->joy_s, ply->joy_w, ply->joy_e, ply->joy_fire,
+        ply->joy_spin, ply->joy_stick);
+#endif
+
+#if 1
+  if (ply->joy_w)              /* west */
+  {
+    x--;
+    dx = -1;
+    anim = 3;
+  }
+  else if (ply->joy_e)         /* east */
+  {
+    x++;
+    dx = 1;
+    anim = 1;
+  }
+
+  if (ply->joy_n)              /* north */
+  {
+    y--;
+    dy = -1;
+    anim = 0;
+  }
+  else if (ply->joy_s)         /* south */
+  {
+    y++;
+    dy = 1;
+    anim = 2;
+  }
+
+#else
+
+  if ((ply->joy_spin = !ply->joy_spin))
+  {
+    if (ply->joy_n)            /* north */
+    {
+      y--;
+      dy = -1;
+      anim = 0;
+    }
+    else if (ply->joy_e)       /* east */
+    {
+      x++;
+      dx = 1;
+      anim = 1;
+    }
+    else if (ply->joy_s)       /* south */
+    {
+      y++;
+      dy = 1;
+      anim = 2;
+    }
+    else if (ply->joy_w)       /* west */
+    {
+      x--;
+      dx = -1;
+      anim = 3;
+    }
+  }
+  else
+  {
+    if (ply->joy_w)            /* west */
+    {
+      x--;
+      dx = -1;
+      anim = 3;
+    }
+    else if (ply->joy_s)       /* south */
+    {
+      y++;
+      dy = 1;
+      anim = 2;
+    }
+    else if (ply->joy_e)       /* east */
+    {
+      x++;
+      dx = 1;
+      anim = 1;
+    }
+    else if (ply->joy_n)       /* north */
+    {
+      y--;
+      dy = -1;
+      anim = 0;
+    }
+  }
+#endif
+
+  if (dx == 0 && dy == 0)
+  {
+    ply->joy_stick = 0;
+
+    if (ply->joy_drop)
+    {
+      if (++ply->dynamite_cnt == 5 && ply->dynamite)
+      {
+       Cave[y][x] = Xdynamite_1;
+       play_element_sound(x, y, SAMPLE_dynamite, Xdynamite_1);
+       ply->dynamite--;
+      }
+    }
+    else
+    {
+      ply->dynamite_cnt = 0;
+    }
+
+    RandomEM += 7;     /* be a bit more random if the player doesn't move */
+
+    return;
+  }
+
+  ply->joy_stick = 1;
+  ply->joy_n = ply->joy_e = ply->joy_s = ply->joy_w = 0;
+  ply->dynamite_cnt = 0; /* reset dynamite timer if we move */
+  ply->joy_spin = !ply->joy_spin;
+
+  if (ply->joy_snap == 0)              /* player wants to move */
+  {
+    boolean moved = FALSE;
+
+    if (ply->last_move_dir & MV_HORIZONTAL)
+    {
+      if (!(moved = player_digfield(ply, 0, dy)))
+       moved = player_digfield(ply, dx, 0);
+    }
+    else
+    {
+      if (!(moved = player_digfield(ply, dx, 0)))
+       moved = player_digfield(ply, 0, dy);
+    }
+
+    if (moved)
+    {
+      if (oldx != ply->x)
+       ply->last_move_dir = (dx < 0 ? MV_LEFT : MV_RIGHT);
+      else if (oldy != ply->y)
+       ply->last_move_dir = (dy < 0 ? MV_UP : MV_DOWN);
+    }
+  }
+  else                                 /* player wants to snap */
+  {
+    player_digfield(ply, dx, dy);
+  }
+}
+
+static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
+{
+  int anim = (dx < 0 ? 3 : dx > 0 ? 1 : dy < 0 ? 0 : dy > 0 ? 2 : 2);
+  unsigned int oldx = ply->x;
+  unsigned int oldy = ply->y;
+  register unsigned int x = oldx + dx;
+  register unsigned int y = oldy + dy;
+  boolean result = TRUE;
+
+  if (!dx && !dy)                      /* no direction specified */
+    return FALSE;
+
+  if (dx && dy && ply->joy_snap)       /* more than one direction specified */
+    return FALSE;
+
+  if (ply->joy_snap == 0)              /* player wants to move */
+  {
+    int element = Cave[y][x];
+
+    switch(Cave[y][x])
+    {
+      /* fire is released */
+      case Xblank:
+      case Yacid_splash_eB:
+      case Yacid_splash_wB:
+       Cave[y][x] = Zplayer;
+       Next[y][x] = Zplayer;
+#if 1
+      case Xfake_acid_1:
+      case Xfake_acid_2:
+      case Xfake_acid_3:
+      case Xfake_acid_4:
+      case Xfake_acid_5:
+      case Xfake_acid_6:
+      case Xfake_acid_7:
+      case Xfake_acid_8:
+#endif
+       play_element_sound(x, y, SAMPLE_blank, Xblank);
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+#if 1
+      case Xacid_1:
+      case Xacid_2:
+      case Xacid_3:
+      case Xacid_4:
+      case Xacid_5:
+      case Xacid_6:
+      case Xacid_7:
+      case Xacid_8:
+#endif
+       if (Cave[y-1][x+1] == Xblank)
+         Cave[y-1][x+1] = Yacid_splash_eB;
+       if (Cave[y-1][x-1] == Xblank)
+         Cave[y-1][x-1] = Yacid_splash_wB;
+       play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+
+      case Xboom_android:
+      case Xboom_1:
+      case Xbug_n:
+      case Xbug_e:
+      case Xbug_s:
+      case Xbug_w:
+      case Xbug_gon:
+      case Xbug_goe:
+      case Xbug_gos:
+      case Xbug_gow:
+      case Xtank_n:
+      case Xtank_e:
+      case Xtank_s:
+      case Xtank_w:
+      case Xtank_gon:
+      case Xtank_goe:
+      case Xtank_gos:
+      case Xtank_gow:
+#if 0
+      case Xacid_1:
+      case Xacid_2:
+      case Xacid_3:
+      case Xacid_4:
+      case Xacid_5:
+      case Xacid_6:
+      case Xacid_7:
+      case Xacid_8:
+#endif
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xgrass:
+       Cave[y][x] = (dy ? (dy < 0 ? Ygrass_nB : Ygrass_sB) :
+                     (dx > 0 ? Ygrass_eB : Ygrass_wB));
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_dirt, Xgrass);
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xdirt:
+       Cave[y][x] = (dy ? (dy < 0 ? Ydirt_nB : Ydirt_sB) :
+                     (dx > 0 ? Ydirt_eB : Ydirt_wB));
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_dirt, Xdirt);
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xdiamond:
+      case Xdiamond_pause:
+       Cave[y][x] = Ydiamond_eat;
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.diamond_score;
+       lev.required = lev.required < 3 ? 0 : lev.required - 3;
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xemerald:
+      case Xemerald_pause:
+       Cave[y][x] = Yemerald_eat;
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.emerald_score;
+       lev.required = lev.required < 1 ? 0 : lev.required - 1;
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xdynamite:
+       Cave[y][x] = Ydynamite_eat;
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.dynamite_score;
+       ply->dynamite = ply->dynamite > 9998 ? 9999 : ply->dynamite + 1;
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xkey_1:
+       ply->keys |= 0x01;
+       Cave[y][x] = Ykey_1_eat;
+       goto key_walk;
+
+      case Xkey_2:
+       ply->keys |= 0x02;
+       Cave[y][x] = Ykey_2_eat;
+       goto key_walk;
+
+      case Xkey_3:
+       ply->keys |= 0x04;
+       Cave[y][x] = Ykey_3_eat;
+       goto key_walk;
+
+      case Xkey_4:
+       ply->keys |= 0x08;
+       Cave[y][x] = Ykey_4_eat;
+       goto key_walk;
+
+      case Xkey_5:
+       ply->keys |= 0x10;
+       Cave[y][x] = Ykey_5_eat;
+       goto key_walk;
+
+      case Xkey_6:
+       ply->keys |= 0x20;
+       Cave[y][x] = Ykey_6_eat;
+       goto key_walk;
+
+      case Xkey_7:
+       ply->keys |= 0x40;
+       Cave[y][x] = Ykey_7_eat;
+       goto key_walk;
+
+      case Xkey_8:
+       ply->keys |= 0x80;
+       Cave[y][x] = Ykey_8_eat;
+       goto key_walk;
+
+      key_walk:
+
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.key_score;
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xlenses:
+       Cave[y][x] = Ylenses_eat;
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.lenses_score;
+       lev.lenses_cnt = lev.lenses_time;
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xmagnify:
+       Cave[y][x] = Ymagnify_eat;
+       Next[y][x] = Zplayer;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.magnify_score;
+       lev.magnify_cnt = lev.magnify_time;
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xstone:
+       if (dy)
+         break;
+
+       switch(Cave[y][x+dx])
+       {
+          case Xacid_1:
+          case Xacid_2:
+          case Xacid_3:
+          case Xacid_4:
+          case Xacid_5:
+          case Xacid_6:
+          case Xacid_7:
+          case Xacid_8:
+           if (Cave[y-1][x+dx+1] == Xblank)
+             Cave[y-1][x+dx+1] = Yacid_splash_eB;
+           if (Cave[y-1][x+dx-1] == Xblank)
+             Cave[y-1][x+dx-1] = Yacid_splash_wB;
+           play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+           goto stone_walk;
+
+          case Xblank:
+          case Yacid_splash_eB:
+          case Yacid_splash_wB:
+           Cave[y][x+dx] = dx > 0 ? Ystone_e : Ystone_w;
+           Next[y][x+dx] = Xstone_pause;
+
+          stone_walk:
+
+           Cave[y][x] = dx > 0 ? Ystone_eB : Ystone_wB;
+           Next[y][x] = Zplayer;
+           play_element_sound(x, y, SAMPLE_roll, Xstone);
+           ply->x = x;
+       }
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xbomb:
+       if (dy)
+         break;
+
+       switch(Cave[y][x+dx])
+       {
+          case Xacid_1:
+          case Xacid_2:
+          case Xacid_3:
+          case Xacid_4:
+          case Xacid_5:
+          case Xacid_6:
+          case Xacid_7:
+          case Xacid_8:
+           if (Cave[y-1][x+dx+1] == Xblank)
+             Cave[y-1][x+dx+1] = Yacid_splash_eB;
+           if (Cave[y-1][x+dx-1] == Xblank)
+             Cave[y-1][x+dx-1] = Yacid_splash_wB;
+           play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+           goto bomb_walk;
+
+         case Xblank:
+          case Yacid_splash_eB:
+          case Yacid_splash_wB:
+           Cave[y][x+dx] = dx > 0 ? Ybomb_e : Ybomb_w;
+           Next[y][x+dx] = Xbomb_pause;
+
+          bomb_walk:
+
+           Cave[y][x] = dx > 0 ? Ybomb_eB : Ybomb_wB;
+           Next[y][x] = Zplayer;
+           play_element_sound(x, y, SAMPLE_roll, Xbomb);
+           ply->x = x;
+       }
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xnut:
+       if (dy)
+         break;
+
+       switch(Cave[y][x+dx])
+       {
+          case Xacid_1:
+          case Xacid_2:
+          case Xacid_3:
+          case Xacid_4:
+          case Xacid_5:
+          case Xacid_6:
+          case Xacid_7:
+          case Xacid_8:
+           if (Cave[y-1][x+dx+1] == Xblank)
+             Cave[y-1][x+dx+1] = Yacid_splash_eB;
+           if (Cave[y-1][x+dx-1] == Xblank)
+             Cave[y-1][x+dx-1] = Yacid_splash_wB;
+           play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+           goto nut_walk;
+
+          case Xblank:
+          case Yacid_splash_eB:
+          case Yacid_splash_wB:
+           Cave[y][x+dx] = dx > 0 ? Ynut_e : Ynut_w;
+           Next[y][x+dx] = Xnut_pause;
+
+          nut_walk:
+
+           Cave[y][x] = dx > 0 ? Ynut_eB : Ynut_wB;
+           Next[y][x] = Zplayer;
+           play_element_sound(x, y, SAMPLE_roll, Xnut);
+           ply->x = x;
+       }
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xspring:
+       if (dy)
+         break;
+
+       switch(Cave[y][x+dx])
+       {
+          case Xalien:
+          case Xalien_pause:
+           Cave[y][x] = dx > 0 ? Yspring_kill_eB : Yspring_kill_wB;
+           Cave[y][x+dx] = dx > 0 ? Yspring_kill_e : Yspring_kill_w;
+           Next[y][x] = Zplayer;
+           Next[y][x+dx] = dx > 0 ? Xspring_e : Xspring_w;
+           play_element_sound(x, y, SAMPLE_slurp, Xalien);
+           lev.score += lev.slurp_score;
+           ply->x = x;
+           break;
+
+          case Xacid_1:
+          case Xacid_2:
+          case Xacid_3:
+          case Xacid_4:
+          case Xacid_5:
+          case Xacid_6:
+          case Xacid_7:
+          case Xacid_8:
+           if (Cave[y-1][x+dx+1] == Xblank)
+             Cave[y-1][x+dx+1] = Yacid_splash_eB;
+           if (Cave[y-1][x+dx-1] == Xblank)
+             Cave[y-1][x+dx-1] = Yacid_splash_wB;
+           play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+           goto spring_walk;
+
+          case Xblank:
+          case Yacid_splash_eB:
+          case Yacid_splash_wB:
+           Cave[y][x+dx] = dx > 0 ? Yspring_e : Yspring_w;
+           Next[y][x+dx] = dx > 0 ? Xspring_e : Xspring_w;
+
+         spring_walk:
+           Cave[y][x] = dx > 0 ? Yspring_eB : Yspring_wB;
+           Next[y][x] = Zplayer;
+           play_element_sound(x, y, SAMPLE_roll, Xspring);
+           ply->x = x;
+       }
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xspring_pause:
+      case Xstone_pause:
+      case Xbomb_pause:
+      case Xnut_pause:
+      case Xsand_stonein_1:
+      case Xsand_stonein_2:
+      case Xsand_stonein_3:
+      case Xsand_stonein_4:
+       if (dy)
+         break;
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xballoon:
+       switch(Cave[y+dy][x+dx])
+       {
+          case Xacid_1:
+          case Xacid_2:
+          case Xacid_3:
+          case Xacid_4:
+          case Xacid_5:
+          case Xacid_6:
+          case Xacid_7:
+          case Xacid_8:
+           if (Cave[y+dy-1][x+dx+1] == Xblank)
+             Cave[y+dy-1][x+dx+1] = Yacid_splash_eB;
+           if (Cave[y+dy-1][x+dx-1] == Xblank)
+             Cave[y+dy-1][x+dx-1] = Yacid_splash_wB;
+           play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+           goto balloon_walk;
+
+          case Xblank:
+          case Yacid_splash_eB:
+          case Yacid_splash_wB:
+           Cave[y+dy][x+dx] = (dy ? (dy < 0 ? Yballoon_n : Yballoon_s) :
+                               (dx > 0 ? Yballoon_e : Yballoon_w));
+           Next[y+dy][x+dx] = Xballoon;
+
+         balloon_walk:
+           Cave[y][x] = (dy ? (dy < 0 ? Yballoon_nB : Yballoon_sB) :
+                         (dx > 0 ? Yballoon_eB : Yballoon_wB));
+           Next[y][x] = Zplayer;
+           play_element_sound(x, y, SAMPLE_push, Xballoon);
+           ply->x = x;
+           ply->y = y;
+       }
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xandroid:
+      case Xandroid_1_n:
+      case Xandroid_2_n:
+      case Xandroid_1_e:
+      case Xandroid_2_e:
+      case Xandroid_1_s:
+      case Xandroid_2_s:
+      case Xandroid_1_w:
+      case Xandroid_2_w:
+       switch(Cave[y+dy][x+dx])
+       {
+          case Xacid_1:
+          case Xacid_2:
+          case Xacid_3:
+          case Xacid_4:
+          case Xacid_5:
+          case Xacid_6:
+          case Xacid_7:
+          case Xacid_8:
+           if (Cave[y+dy-1][x+dx+1] == Xblank)
+             Cave[y+dy-1][x+dx+1] = Yacid_splash_eB;
+           if (Cave[y+dy-1][x+dx-1] == Xblank)
+             Cave[y+dy-1][x+dx-1] = Yacid_splash_wB;
+           play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+           goto android_walk;
+
+          case Xblank:
+          case Yacid_splash_eB:
+          case Yacid_splash_wB:
+           Cave[y+dy][x+dx] = (dy ? (dy < 0 ? Yandroid_n : Yandroid_s) :
+                               (dx > 0 ? Yandroid_e : Yandroid_w));
+           Next[y+dy][x+dx] = (dy ? (dy < 0 ? Xandroid_2_n : Xandroid_2_s) :
+                               (dx > 0 ? Xandroid_2_e : Xandroid_2_w));
+
+         android_walk:
+           Cave[y][x] = (dy ? (dy < 0 ? Yandroid_nB : Yandroid_sB) :
+                         (dx > 0 ? Yandroid_eB : Yandroid_wB));
+           Next[y][x] = Zplayer;
+           play_element_sound(x, y, SAMPLE_push, Xandroid);
+           ply->x = x;
+           ply->y = y;
+       }
+
+       ply->anim = SPR_push + anim;
+       break;
+
+      case Xdoor_1:
+      case Xfake_door_1:
+       if (ply->keys & 0x01)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_2:
+      case Xfake_door_2:
+       if (ply->keys & 0x02)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_3:
+      case Xfake_door_3:
+       if (ply->keys & 0x04)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_4:
+      case Xfake_door_4:
+       if (ply->keys & 0x08)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_5:
+      case Xfake_door_5:
+       if (ply->keys & 0x10)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_6:
+      case Xfake_door_6:
+       if (ply->keys & 0x20)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_7:
+      case Xfake_door_7:
+       if (ply->keys & 0x40)
+         goto door_walk;
+       else
+         break;
+
+      case Xdoor_8:
+      case Xfake_door_8:
+       if (ply->keys & 0x80)
+         goto door_walk;
+       else
+         break;
+
+      door_walk:
+       if (!tab_blank[Cave[y+dy][x+dx]])
+         break;
+
+       Cave[y+dy][x+dx] = Zplayer;
+       Next[y+dy][x+dx] = Zplayer;
+       play_element_sound(x, y, SAMPLE_door, element);
+       ply->anim = SPR_walk + anim;
+       ply->x = x + dx;
+       ply->y = y + dy;
+       break;
+
+      case Xwheel:
+       play_element_sound(x, y, SAMPLE_press, element);
+       lev.wheel_cnt = lev.wheel_time;
+       lev.wheel_x = x;
+       lev.wheel_y = y;
+       break;
+
+      case Xwind_n:
+       lev.wind_direction = 0;
+       goto wind_walk;
+
+      case Xwind_e:
+       lev.wind_direction = 1;
+       goto wind_walk;
+
+      case Xwind_s:
+       lev.wind_direction = 2;
+       goto wind_walk;
+
+      case Xwind_w:
+       lev.wind_direction = 3;
+       goto wind_walk;
+
+      case Xwind_nesw:
+       lev.wind_direction = dy ? (dy < 0 ? 0 : 2) : (dx > 0 ? 1 : 3);
+       goto wind_walk;
+
+      wind_walk:
+       play_element_sound(x, y, SAMPLE_press, element);
+       lev.wind_cnt = lev.wind_time;
+       break;
+
+      case Xwind_stop:
+       play_element_sound(x, y, SAMPLE_press, element);
+       lev.wind_cnt = 0;
+       break;
+
+      case Xswitch:
+       play_element_sound(x, y, SAMPLE_press, element);
+       lev.ball_cnt = lev.ball_time;
+       lev.ball_state = !lev.ball_state;
+       break;
+
+      case Xplant:
+       Cave[y][x] = Yplant;
+       Next[y][x] = Xplant;
+       play_element_sound(x, y, SAMPLE_blank, Xplant);
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+       break;
+
+      case Xexit_1:
+      case Xexit_2:
+      case Xexit_3:
+       play_element_sound(x, y, SAMPLE_exit_leave, Xexit_1);
+
+       lev.home--;
+
+#if 0
+       /* !!! CHECK SCORE CALCULATION !!! */
+       if (lev.home == 0 && lev.time_initial > 0)      /* game won */
+         lev.score += lev.time * lev.exit_score / 100;
+#endif
+
+       ply->anim = SPR_walk + anim;
+       ply->x = x;
+       ply->y = y;
+
+       break;
+    }
+
+    if (ply->x == oldx && ply->y == oldy)      /* no movement */
+      result = FALSE;
+  }
+  else                                 /* player wants to snap */
+  {
+    int element = Cave[y][x];
+
+    switch(Cave[y][x])
+    {
+      /* fire is pressed */
+
+      case Xgrass:
+       Cave[y][x] = Ygrass_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_dirt, element);
+       ply->anim = SPR_spray + anim;
+       break;
+
+      case Xdirt:
+       Cave[y][x] = Ydirt_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_dirt, element);
+       ply->anim = SPR_spray + anim;
+       break;
+
+      case Xdiamond:
+      case Xdiamond_pause:
+       Cave[y][x] = Ydiamond_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.diamond_score;
+       lev.required = lev.required < 3 ? 0 : lev.required - 3;
+       ply->anim = SPR_walk + anim;
+       break;
+
+      case Xemerald:
+      case Xemerald_pause:
+       Cave[y][x] = Yemerald_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.emerald_score;
+       lev.required = lev.required < 1 ? 0 : lev.required - 1;
+       ply->anim = SPR_walk + anim;
+       break;
+
+      case Xdynamite:
+       Cave[y][x] = Ydynamite_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.dynamite_score;
+       ply->dynamite = ply->dynamite > 9998 ? 9999 : ply->dynamite + 1;
+       ply->anim = SPR_walk + anim;
+       break;
+
+      case Xkey_1:
+       ply->keys |= 0x01;
+       Cave[y][x] = Ykey_1_eat;
+       goto key_shoot;
+
+      case Xkey_2:
+       ply->keys |= 0x02;
+       Cave[y][x] = Ykey_2_eat;
+       goto key_shoot;
+
+      case Xkey_3:
+       ply->keys |= 0x04;
+       Cave[y][x] = Ykey_3_eat;
+       goto key_shoot;
+
+      case Xkey_4:
+       ply->keys |= 0x08;
+       Cave[y][x] = Ykey_4_eat;
+       goto key_shoot;
+
+      case Xkey_5:
+       ply->keys |= 0x10;
+       Cave[y][x] = Ykey_5_eat;
+       goto key_shoot;
+
+      case Xkey_6:
+       ply->keys |= 0x20;
+       Cave[y][x] = Ykey_6_eat;
+       goto key_shoot;
+
+      case Xkey_7:
+       ply->keys |= 0x40;
+       Cave[y][x] = Ykey_7_eat;
+       goto key_shoot;
+
+      case Xkey_8:
+       ply->keys |= 0x80;
+       Cave[y][x] = Ykey_8_eat;
+       goto key_shoot;
+
+      key_shoot:
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.key_score;
+       ply->anim = SPR_walk + anim;
+       break;
+
+      case Xlenses:
+       Cave[y][x] = Ylenses_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.lenses_score;
+       lev.lenses_cnt = lev.lenses_time;
+       ply->anim = SPR_walk + anim;
+       break;
+
+      case Xmagnify:
+       Cave[y][x] = Ymagnify_eat;
+       Next[y][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_collect, element);
+       lev.score += lev.magnify_score;
+       lev.magnify_cnt = lev.magnify_time;
+       ply->anim = SPR_walk + anim;
+       break;
+
+      default:
+       result = FALSE;
+    }
+  }
+
+  return result;
+}
diff --git a/src/game_em/synchro_2.c b/src/game_em/synchro_2.c
new file mode 100644 (file)
index 0000000..3dff9e6
--- /dev/null
@@ -0,0 +1,4900 @@
+/* second part of synchro.
+ *
+ * game logic for monsters.
+ *
+ * one giant switch statement to process everything.
+ *
+ * this whole thing is a major bottleneck. the compiler must use registers.
+ * compilers suck.
+ */
+
+#include "display.h"
+#include "tile.h"
+#include "level.h"
+#include "sample.h"
+
+
+#define RANDOM (random = random << 31 | random >> 1)
+
+void synchro_2(void)
+{
+  register unsigned int x = 0;
+  register unsigned int y = 1;
+  register unsigned long random = RandomEM;
+  register unsigned short *cave_cache = Cave[y]; /* might be a win */
+  unsigned long score = 0;
+
+  unsigned int temp = 0;       /* initialized to make compilers happy */
+  unsigned int dx; /* only needed to find closest player */
+  unsigned int dy;
+  int element;
+
+ loop:
+
+  element = cave_cache[++x];
+
+  switch (element)
+  {
+    default:
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+#ifdef BAD_ROLL
+    case Xstone_force_e:
+      switch (Cave[y][x+1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xstone;
+         Next[y][x] = Xstone;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ystone_eB;
+         Cave[y][x+1] = Ystone_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xstone_pause;
+         goto loop;
+      }
+
+    case Xstone_force_w:
+      switch (Cave[y][x-1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xstone;
+         Next[y][x] = Xstone;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ystone_wB;
+         Cave[y][x-1] = Ystone_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xstone_pause;
+         goto loop;
+      }
+
+    case Xnut_force_e:
+      switch (Cave[y][x+1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xnut;
+         Next[y][x] = Xnut;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ynut_eB;
+         Cave[y][x+1] = Ynut_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xnut_pause;
+         goto loop;
+      }
+
+    case Xnut_force_w:
+      switch (Cave[y][x-1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xnut;
+         Next[y][x] = Xnut;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ynut_wB;
+         Cave[y][x-1] = Ynut_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xnut_pause;
+         goto loop;
+       }
+
+    case Xspring_force_e:
+      switch (Cave[y][x+1])
+      {
+        case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xspring;
+         Next[y][x] = Xspring;
+         goto loop;
+
+       default:
+         Cave[y][x] = Yspring_eB;
+         Cave[y][x+1] = Yspring_e;
+         Next[y][x] = Xblank;
+
+#ifdef BAD_SPRING
+         Next[y][x+1] = Xspring_e;
+#else
+         Next[y][x+1] = Xspring_pause;
+#endif
+
+         goto loop;
+      }
+
+    case Xspring_force_w:
+      switch (Cave[y][x-1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xspring;
+         Next[y][x] = Xspring;
+         goto loop;
+
+       default:
+         Cave[y][x] = Yspring_wB;
+         Cave[y][x-1] = Yspring_w;
+         Next[y][x] = Xblank;
+
+#ifdef BAD_SPRING
+         Next[y][x-1] = Xspring_w;
+#else  
+         Next[y][x-1] = Xspring_pause;
+#endif 
+         goto loop;
+       }
+
+    case Xemerald_force_e:
+      switch (Cave[y][x+1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xemerald;
+         Next[y][x] = Xemerald;
+         goto loop;
+
+       default:
+         Cave[y][x] = Yemerald_eB;
+         Cave[y][x+1] = Yemerald_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xemerald_pause;
+         goto loop;
+       }
+
+    case Xemerald_force_w:
+      switch (Cave[y][x-1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xemerald;
+         Next[y][x] = Xemerald;
+         goto loop;
+
+       default:
+         Cave[y][x] = Yemerald_wB;
+         Cave[y][x-1] = Yemerald_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xemerald_pause;
+         goto loop;
+       }
+
+    case Xdiamond_force_e:
+      switch (Cave[y][x+1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xdiamond;
+         Next[y][x] = Xdiamond;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ydiamond_eB;
+         Cave[y][x+1] = Ydiamond_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xdiamond_pause;
+         goto loop;
+       }
+
+    case Xdiamond_force_w:
+      switch (Cave[y][x-1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xdiamond;
+         Next[y][x] = Xdiamond;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ydiamond_wB;
+         Cave[y][x-1] = Ydiamond_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xdiamond_pause;
+         goto loop;
+       }
+
+    case Xbomb_force_e:
+      switch (Cave[y][x+1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xbomb;
+         Next[y][x] = Xbomb;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybomb_eB;
+         Cave[y][x+1] = Ybomb_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xbomb_pause;
+         goto loop;
+       }
+
+    case Xbomb_force_w:
+      switch (Cave[y][x-1])
+      {
+       case ZBORDER:
+       case Znormal:
+       case Zdynamite:
+       case Xboom_bug:
+       case Xboom_bomb:
+       case Xboom_android:
+       case Xboom_1:
+       case Zplayer:
+         Cave[y][x] = Xbomb;
+         Next[y][x] = Xbomb;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybomb_wB;
+         Cave[y][x-1] = Ybomb_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xbomb_pause;
+         goto loop;
+       }
+#endif /* BAD_ROLL */
+
+    /* --------------------------------------------------------------------- */
+
+    case Xstone:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ystone_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+#if 1
+        case Xfake_acid_1:
+        case Xfake_acid_2:
+        case Xfake_acid_3:
+        case Xfake_acid_4:
+        case Xfake_acid_5:
+        case Xfake_acid_6:
+        case Xfake_acid_7:
+        case Xfake_acid_8:
+#endif
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Ystone_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xstone_fall;
+         goto loop;
+
+       case Xsand:
+         Cave[y][x] = Xsand_stonein_1;
+         Cave[y+1][x] = Xsand_sandstone_1;
+         Next[y][x] = Xsand_stonein_2;
+         Next[y+1][x] = Xsand_sandstone_2;
+         goto loop;
+
+        case Xspring:
+       case Xspring_pause:
+       case Xspring_e:
+       case Xspring_w:
+       case Xandroid:
+       case Xandroid_1_n:
+       case Xandroid_2_n:
+       case Xandroid_1_e:
+       case Xandroid_2_e:
+       case Xandroid_1_s:
+       case Xandroid_2_s:
+       case Xandroid_1_w:
+       case Xandroid_2_w:
+       case Xstone:
+       case Xstone_pause:
+       case Xemerald:
+       case Xemerald_pause:
+       case Xdiamond:
+       case Xdiamond_pause:
+       case Xbomb:
+       case Xbomb_pause:
+       case Xballoon:
+       case Xacid_ne:
+       case Xacid_nw:
+       case Xball_1:
+       case Xball_2:
+       case Xnut:
+       case Xnut_pause:
+       case Xgrow_ns:
+       case Xgrow_ew:
+       case Xkey_1:
+       case Xkey_2:
+       case Xkey_3:
+       case Xkey_4:
+       case Xkey_5:
+       case Xkey_6:
+       case Xkey_7:
+       case Xkey_8:
+       case Xbumper:
+       case Xswitch:
+       case Xlenses:
+       case Xmagnify:
+       case Xround_wall_1:
+       case Xround_wall_2:
+       case Xround_wall_3:
+       case Xround_wall_4:
+         if (RANDOM & 1)
+         {
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ystone_eB;
+             Cave[y][x+1] = Ystone_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xstone_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ystone_wB;
+             Cave[y][x-1] = Ystone_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xstone_pause;
+             goto loop;
+           }
+         }
+         else
+         {
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ystone_wB;
+             Cave[y][x-1] = Ystone_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xstone_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ystone_eB;
+             Cave[y][x+1] = Ystone_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xstone_pause;
+             goto loop;
+           }
+         }
+
+        default:
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xstone_pause:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ystone_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+#if 1
+        case Xfake_acid_1:
+        case Xfake_acid_2:
+        case Xfake_acid_3:
+        case Xfake_acid_4:
+        case Xfake_acid_5:
+        case Xfake_acid_6:
+        case Xfake_acid_7:
+        case Xfake_acid_8:
+#endif
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Ystone_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xstone_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xstone;
+         Next[y][x] = Xstone;
+         goto loop;
+       }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xstone_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ystone_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Zplayer:
+#if 1
+        case Xfake_acid_1:
+        case Xfake_acid_2:
+        case Xfake_acid_3:
+        case Xfake_acid_4:
+        case Xfake_acid_5:
+        case Xfake_acid_6:
+        case Xfake_acid_7:
+        case Xfake_acid_8:
+#endif
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Ystone_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xstone_fall;
+         goto loop;
+
+       case Xnut:
+       case Xnut_pause:
+         Cave[y+1][x] = Yemerald_stone;
+         Next[y][x] = Xstone;
+         Next[y+1][x] = Xemerald;
+         play_element_sound(x, y, SAMPLE_crack, Xnut);
+         score += lev.nut_score;
+         goto loop;
+
+       case Xbug_n:
+       case Xbug_e:
+       case Xbug_s:
+       case Xbug_w:
+       case Xbug_gon:
+       case Xbug_goe:
+       case Xbug_gos:
+       case Xbug_gow:
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Ybug_stone;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xemerald;
+         Boom[y][x] = Xemerald;
+         Boom[y][x+1] = Xemerald;
+         Boom[y+1][x-1] = Xemerald;
+         Boom[y+1][x] = Xdiamond;
+         Boom[y+1][x+1] = Xemerald;
+         Boom[y+2][x-1] = Xemerald;
+         Boom[y+2][x] = Xemerald;
+         Boom[y+2][x+1] = Xemerald;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         score += lev.bug_score;
+         goto loop;
+
+       case Xtank_n:
+       case Xtank_e:
+       case Xtank_s:
+       case Xtank_w:
+       case Xtank_gon:
+       case Xtank_goe:
+       case Xtank_gos:
+       case Xtank_gow:
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Ytank_stone;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+         Boom[y+2][x-1] = Xblank;
+         Boom[y+2][x] = Xblank;
+         Boom[y+2][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         score += lev.tank_score;
+         goto loop;
+
+       case Xspring:
+         if (RANDOM & 1)
+         {
+           switch (Cave[y+1][x+1])
+           {
+             case Xblank:
+             case Yacid_splash_eB:
+             case Yacid_splash_wB:
+             case Xalien:
+             case Xalien_pause:
+               Cave[y+1][x] = Xspring_e;
+               break;
+
+             default:
+               Cave[y+1][x] = Xspring_w;
+               break;
+           }
+         }
+         else
+         {
+           switch (Cave[y+1][x-1])
+           {
+             case Xblank:
+             case Yacid_splash_eB:
+             case Yacid_splash_wB:
+             case Xalien:
+             case Xalien_pause:
+               Cave[y+1][x] = Xspring_w;
+               break;
+             default:
+               Cave[y+1][x] = Xspring_e;
+               break;
+           }
+         }
+
+         Next[y][x] = Xstone;
+         goto loop;
+
+       case Xeater_n:
+       case Xeater_e:
+       case Xeater_s:
+       case Xeater_w:
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Yeater_stone;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = lev.eater_array[lev.eater_pos][0];
+         Boom[y][x] = lev.eater_array[lev.eater_pos][1];
+         Boom[y][x+1] = lev.eater_array[lev.eater_pos][2];
+         Boom[y+1][x-1] = lev.eater_array[lev.eater_pos][3];
+         Boom[y+1][x] = lev.eater_array[lev.eater_pos][4];
+         Boom[y+1][x+1] = lev.eater_array[lev.eater_pos][5];
+         Boom[y+2][x-1] = lev.eater_array[lev.eater_pos][6];
+         Boom[y+2][x] = lev.eater_array[lev.eater_pos][7];
+         Boom[y+2][x+1] = lev.eater_array[lev.eater_pos][8];
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         lev.eater_pos = (lev.eater_pos + 1) & 7;
+         score += lev.eater_score;
+         goto loop;
+
+       case Xalien:
+       case Xalien_pause:
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Yalien_stone;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+         Boom[y+2][x-1] = Xblank;
+         Boom[y+2][x] = Xblank;
+         Boom[y+2][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         score += lev.alien_score;
+         goto loop;
+
+       case Xdiamond:
+       case Xdiamond_pause:
+         switch (Cave[y+2][x])
+         {
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+           case Zplayer:
+           case Xbug_n:
+           case Xbug_e:
+           case Xbug_s:
+           case Xbug_w:
+           case Xbug_gon:
+           case Xbug_goe:
+           case Xbug_gos:
+           case Xbug_gow:
+           case Xtank_n:
+           case Xtank_e:
+           case Xtank_s:
+           case Xtank_w:
+           case Xtank_gon:
+           case Xtank_goe:
+           case Xtank_gos:
+           case Xtank_gow:
+           case Xspring_fall:
+           case Xandroid:
+           case Xandroid_1_n:
+           case Xandroid_2_n:
+           case Xandroid_1_e:
+           case Xandroid_2_e:
+           case Xandroid_1_s:
+           case Xandroid_2_s:
+           case Xandroid_1_w:
+           case Xandroid_2_w:
+           case Xstone_fall:
+           case Xemerald_fall:
+           case Xdiamond_fall:
+           case Xbomb_fall:
+           case Xacid_s:
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+           case Xnut_fall:
+           case Xplant:
+           case Yplant:
+             Next[y][x] = Xstone;
+             play_element_sound(x, y, SAMPLE_stone, Xstone);
+             goto loop;
+         }
+
+         Cave[y][x] = Ystone_sB;
+         Cave[y+1][x] = Ydiamond_stone;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xstone_pause;
+         play_element_sound(x, y, SAMPLE_squash, Xdiamond);
+         goto loop;
+
+       case Xbomb:
+       case Xbomb_pause:
+         Cave[y+1][x] = Ybomb_eat;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+         Boom[y+2][x-1] = Xblank;
+         Boom[y+2][x] = Xblank;
+         Boom[y+2][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         goto loop;
+
+       case Xwonderwall:
+         if (lev.wonderwall_time)
+         {
+           lev.wonderwall_state = 1;
+           Cave[y][x] = Ystone_sB;
+
+           if (tab_blank[Cave[y+2][x]])
+           {
+             Cave[y+2][x] = Yemerald_s;
+             Next[y+2][x] = Xemerald_fall;
+           }
+
+           Next[y][x] = Xblank;
+           play_element_sound(x, y, SAMPLE_wonderfall, Xwonderwall);
+           goto loop;
+         }
+
+       default:
+         Cave[y][x] = Xstone;
+         Next[y][x] = Xstone;
+         play_element_sound(x, y, SAMPLE_stone, Xstone);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xnut:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ynut_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ynut_sB;
+         Cave[y+1][x] = Ynut_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xnut_fall;
+         goto loop;
+
+       case Xspring:
+       case Xspring_pause:
+       case Xspring_e:
+       case Xspring_w:
+       case Xandroid:
+       case Xandroid_1_n:
+       case Xandroid_2_n:
+       case Xandroid_1_e:
+       case Xandroid_2_e:
+       case Xandroid_1_s:
+       case Xandroid_2_s:
+       case Xandroid_1_w:
+       case Xandroid_2_w:
+       case Xstone:
+       case Xstone_pause:
+       case Xemerald:
+       case Xemerald_pause:
+       case Xdiamond:
+       case Xdiamond_pause:
+       case Xbomb:
+       case Xbomb_pause:
+       case Xballoon:
+       case Xacid_ne:
+       case Xacid_nw:
+       case Xball_1:
+       case Xball_2:
+       case Xnut:
+       case Xnut_pause:
+       case Xgrow_ns:
+       case Xgrow_ew:
+       case Xkey_1:
+       case Xkey_2:
+       case Xkey_3:
+       case Xkey_4:
+       case Xkey_5:
+       case Xkey_6:
+       case Xkey_7:
+       case Xkey_8:
+       case Xbumper:
+       case Xswitch:
+       case Xround_wall_1:
+       case Xround_wall_2:
+       case Xround_wall_3:
+       case Xround_wall_4:
+         if (RANDOM & 1)
+         {
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ynut_eB;
+             Cave[y][x+1] = Ynut_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xnut_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ynut_wB;
+             Cave[y][x-1] = Ynut_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xnut_pause;
+             goto loop;
+           }
+         }
+         else
+         {
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ynut_wB;
+             Cave[y][x-1] = Ynut_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xnut_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ynut_eB;
+             Cave[y][x+1] = Ynut_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xnut_pause;
+             goto loop;
+           }
+         }
+
+        default:
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+
+    case Xnut_pause:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ynut_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ynut_sB;
+         Cave[y+1][x] = Ynut_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xnut_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xnut;
+         Next[y][x] = Xnut;
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xnut_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ynut_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Zplayer:
+         Cave[y][x] = Ynut_sB;
+         Cave[y+1][x] = Ynut_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xnut_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xnut;
+         Next[y][x] = Xnut;
+         play_element_sound(x, y, SAMPLE_nut, Xnut);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbug_n:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+      switch (Cave[y][x+1])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ybug_n_e;
+         Next[y][x] = Xbug_goe;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         goto bug_gon;
+       }
+
+    case Xbug_gon:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+    bug_gon:
+
+      switch (Cave[y-1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybug_nB;
+         if (Cave[y-2][x+1] == Xblank)
+           Cave[y-2][x+1] = Yacid_splash_eB;
+         if (Cave[y-2][x-1] == Xblank)
+           Cave[y-2][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ybug_nB;
+         Cave[y-1][x] = Ybug_n;
+         Next[y][x] = Xblank;
+         Next[y-1][x] = Xbug_n;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybug_n_w;
+         Next[y][x] = Xbug_gow;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbug_e:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+      switch (Cave[y+1][x])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ybug_e_s;
+         Next[y][x] = Xbug_gos;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         goto bug_goe;
+      }
+
+    case Xbug_goe:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+    bug_goe:
+
+      switch (Cave[y][x+1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybug_eB;
+         if (Cave[y-1][x+2] == Xblank)
+           Cave[y-1][x+2] = Yacid_splash_eB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ybug_eB;
+         Cave[y][x+1] = Ybug_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xbug_e;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybug_e_n;
+         Next[y][x] = Xbug_gon;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbug_s:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+      switch (Cave[y][x-1])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ybug_s_w;
+         Next[y][x] = Xbug_gow;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         goto bug_gos;
+      }
+
+    case Xbug_gos:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+    bug_gos:
+
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybug_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ybug_sB;
+         Cave[y+1][x] = Ybug_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xbug_s;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybug_s_e;
+         Next[y][x] = Xbug_goe;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbug_w:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+      switch (Cave[y-1][x])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ybug_w_n;
+         Next[y][x] = Xbug_gon;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         goto bug_gow;
+      }
+
+    case Xbug_gow:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto bug_boom;
+
+    bug_gow:
+
+      switch (Cave[y][x-1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybug_wB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_eB;
+         if (Cave[y-1][x-2] == Xblank)
+           Cave[y-1][x-2] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ybug_wB;
+         Cave[y][x-1] = Ybug_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xbug_w;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybug_w_s;
+         Next[y][x] = Xbug_gos;
+         play_element_sound(x, y, SAMPLE_bug, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xtank_n:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+      switch (Cave[y][x-1])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ytank_n_w;
+         Next[y][x] = Xtank_gow;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         goto tank_gon;
+      }
+
+    case Xtank_gon:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+    tank_gon:
+
+      switch (Cave[y-1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ytank_nB;
+         if (Cave[y-2][x+1] == Xblank)
+           Cave[y-2][x+1] = Yacid_splash_eB;
+         if (Cave[y-2][x-1] == Xblank)
+           Cave[y-2][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ytank_nB;
+         Cave[y-1][x] = Ytank_n;
+         Next[y][x] = Xblank;
+         Next[y-1][x] = Xtank_n;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ytank_n_e;
+         Next[y][x] = Xtank_goe;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xtank_e:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+      switch (Cave[y-1][x])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ytank_e_n;
+         Next[y][x] = Xtank_gon;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         goto tank_goe;
+      }
+
+    case Xtank_goe:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+    tank_goe:
+
+      switch (Cave[y][x+1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ytank_eB;
+         if (Cave[y-1][x+2] == Xblank)
+           Cave[y-1][x+2] = Yacid_splash_eB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ytank_eB;
+         Cave[y][x+1] = Ytank_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xtank_e;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ytank_e_s;
+         Next[y][x] = Xtank_gos;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xtank_s:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+      switch (Cave[y][x+1])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ytank_s_e;
+         Next[y][x] = Xtank_goe;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         goto tank_gos;
+      }
+
+    case Xtank_gos:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+    tank_gos:
+
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ytank_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ytank_sB;
+         Cave[y+1][x] = Ytank_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xtank_s;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ytank_s_w;
+         Next[y][x] = Xtank_gow;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xtank_w:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+      switch (Cave[y+1][x])
+      {
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+       case Zplayer:
+         Cave[y][x] = Ytank_w_s;
+         Next[y][x] = Xtank_gos;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         goto tank_gow;
+      }
+
+    case Xtank_gow:
+      if (tab_amoeba[Cave[y-1][x]] ||
+         tab_amoeba[Cave[y][x+1]] ||
+         tab_amoeba[Cave[y+1][x]] ||
+         tab_amoeba[Cave[y][x-1]])
+       goto tank_boom;
+
+    tank_gow:
+
+      switch (Cave[y][x-1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ytank_wB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_eB;
+         if (Cave[y-1][x-2] == Xblank)
+           Cave[y-1][x-2] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ytank_wB;
+         Cave[y][x-1] = Ytank_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xtank_w;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+
+       default:
+         Cave[y][x] = Ytank_w_n;
+         Next[y][x] = Xtank_gon;
+         play_element_sound(x, y, SAMPLE_tank, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xandroid:
+
+    android:
+
+      if (lev.android_clone_cnt == 0)
+      {
+       if (Cave[y-1][x-1] != Xblank &&
+           Cave[y-1][x]   != Xblank &&
+           Cave[y-1][x+1] != Xblank &&
+           Cave[y][x-1]   != Xblank &&
+           Cave[y][x+1]   != Xblank &&
+           Cave[y+1][x-1] != Xblank &&
+           Cave[y+1][x]   != Xblank &&
+           Cave[y+1][x+1] != Xblank)
+         goto android_move;
+
+       switch (RANDOM & 7)
+       {
+         /* randomly find an object to clone */
+
+         case 0: /* S,NE,W,NW,SE,E,SW,N */
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           goto android_move;
+
+         case 1: /* NW,SE,N,S,NE,SW,E,W */
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           goto android_move;
+
+         case 2: /* SW,E,S,W,N,NW,SE,NE */
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           goto android_move;
+
+         case 3: /* N,SE,NE,E,W,S,NW,SW */
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           goto android_move;
+
+         case 4: /* SE,NW,E,NE,SW,W,N,S */
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           goto android_move;
+
+         case 5: /* NE,W,SE,SW,S,N,E,NW */
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           goto android_move;
+
+         case 6: /* E,N,SW,S,NW,NE,SE,W */
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           goto android_move;
+
+         case 7: /* W,SW,NW,N,E,SE,NE,S */
+           temp= lev.android_array[Cave[y][x-1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x-1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y][x+1]];   if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y-1][x+1]]; if (temp != Xblank) break;
+           temp= lev.android_array[Cave[y+1][x]];   if (temp != Xblank) break;
+           goto android_move;
+       }
+
+       Next[y][x] = temp;      /* the item we chose to clone */
+       play_element_sound(x, y, SAMPLE_android_clone, temp);
+
+       switch (RANDOM & 7)
+       {
+         /* randomly find a direction to move */
+
+         case 0: /* S,NE,W,NW,SE,E,SW,N */
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           goto android_move;
+
+         case 1: /* NW,SE,N,S,NE,SW,E,W */
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           goto android_move;
+
+         case 2: /* SW,E,S,W,N,NW,SE,NE */
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           goto android_move;
+
+         case 3: /* N,SE,NE,E,W,S,NW,SW */
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           goto android_move;
+
+         case 4: /* SE,NW,E,NE,SW,W,N,S */
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           goto android_move;
+
+         case 5: /* NE,W,SE,SW,S,N,E,NW */
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           goto android_move;
+
+         case 6: /* E,N,SW,S,NW,NE,SE,W */
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           goto android_move;
+
+         case 7: /* W,SW,NW,N,E,SE,NE,S */
+           if (Cave[y][x-1] == Xblank)   goto android_w;
+           if (Cave[y+1][x-1] == Xblank) goto android_sw;
+           if (Cave[y-1][x-1] == Xblank) goto android_nw;
+           if (Cave[y-1][x] == Xblank)   goto android_n;
+           if (Cave[y][x+1] == Xblank)   goto android_e;
+           if (Cave[y+1][x+1] == Xblank) goto android_se;
+           if (Cave[y-1][x+1] == Xblank) goto android_ne;
+           if (Cave[y+1][x] == Xblank)   goto android_s;
+           goto android_move;
+       }
+      }
+
+    android_move:
+      if (lev.android_move_cnt == 0)
+      {
+       if (Cave[y-1][x-1] == Zplayer ||
+           Cave[y-1][x]   == Zplayer ||
+           Cave[y-1][x+1] == Zplayer ||
+           Cave[y][x-1]   == Zplayer ||
+           Cave[y][x+1]   == Zplayer ||
+           Cave[y+1][x-1] == Zplayer ||
+           Cave[y+1][x]   == Zplayer ||
+           Cave[y+1][x+1] == Zplayer)
+         goto android_still;
+
+       if (ply1.alive && ply2.alive)
+       {
+         if ((ply1.x > x ? ply1.x - x : x - ply1.x) +
+             (ply1.y > y ? ply1.y - y : y - ply1.y) <
+             (ply2.x > x ? ply2.x - x : x - ply2.x) +
+             (ply2.y > y ? ply2.y - y : y - ply2.y))
+         {
+           dx = ply1.x;
+           dy = ply1.y;
+         }
+         else
+         {
+           dx = ply2.x;
+           dy = ply2.y;
+         }
+       }
+       else if (ply1.alive)
+       {
+         dx = ply1.x;
+         dy = ply1.y;
+       }
+       else if (ply2.alive)
+       {
+         dx = ply2.x;
+         dy = ply2.y;
+       }
+       else
+       {
+         dx = 0;
+         dy = 0;
+       }
+
+       Next[y][x] = Xblank;    /* assume we will move */
+       temp = ((x < dx) + 1 - (x > dx)) + ((y < dy) + 1 - (y > dy)) * 3;
+
+       if (RANDOM & 1)
+       {
+         switch (temp)
+         {
+           /* attempt clockwise move first if direct path is blocked */
+
+           case 0: /* north west */
+             if (tab_android_move[Cave[y-1][x-1]]) goto android_nw;
+             if (tab_android_move[Cave[y-1][x]])   goto android_n;
+             if (tab_android_move[Cave[y][x-1]])   goto android_w;
+             break;
+
+           case 1: /* north */
+             if (tab_android_move[Cave[y-1][x]])   goto android_n;
+             if (tab_android_move[Cave[y-1][x+1]]) goto android_ne;
+             if (tab_android_move[Cave[y-1][x-1]]) goto android_nw;
+             break;
+
+           case 2: /* north east */
+             if (tab_android_move[Cave[y-1][x+1]]) goto android_ne;
+             if (tab_android_move[Cave[y][x+1]])   goto android_e;
+             if (tab_android_move[Cave[y-1][x]])   goto android_n;
+             break;
+
+           case 3: /* west */
+             if (tab_android_move[Cave[y][x-1]])   goto android_w;
+             if (tab_android_move[Cave[y-1][x-1]]) goto android_nw;
+             if (tab_android_move[Cave[y+1][x-1]]) goto android_sw;
+             break;
+
+           case 4: /* nowhere */
+             break;
+
+           case 5: /* east */
+             if (tab_android_move[Cave[y][x+1]])   goto android_e;
+             if (tab_android_move[Cave[y+1][x+1]]) goto android_se;
+             if (tab_android_move[Cave[y-1][x+1]]) goto android_ne;
+             break;
+
+           case 6: /* south west */
+             if (tab_android_move[Cave[y+1][x-1]]) goto android_sw;
+             if (tab_android_move[Cave[y][x-1]])   goto android_w;
+             if (tab_android_move[Cave[y+1][x]])   goto android_s;
+             break;
+
+           case 7: /* south */
+             if (tab_android_move[Cave[y+1][x]])   goto android_s;
+             if (tab_android_move[Cave[y+1][x-1]]) goto android_sw;
+             if (tab_android_move[Cave[y+1][x+1]]) goto android_se;
+             break;
+
+           case 8: /* south east */
+             if (tab_android_move[Cave[y+1][x+1]]) goto android_se;
+             if (tab_android_move[Cave[y+1][x]])   goto android_s;
+             if (tab_android_move[Cave[y][x+1]])   goto android_e;
+             break;
+         }
+       }
+       else
+       {
+         switch (temp)
+         {
+           /* attempt counterclockwise move first if direct path is blocked */
+
+           case 0: /* north west */
+             if (tab_android_move[Cave[y-1][x-1]]) goto android_nw;
+             if (tab_android_move[Cave[y][x-1]])   goto android_w;
+             if (tab_android_move[Cave[y-1][x]])   goto android_n;
+             break;
+
+           case 1: /* north */
+             if (tab_android_move[Cave[y-1][x]])   goto android_n;
+             if (tab_android_move[Cave[y-1][x-1]]) goto android_nw;
+             if (tab_android_move[Cave[y-1][x+1]]) goto android_ne;
+             break;
+
+           case 2: /* north east */
+             if (tab_android_move[Cave[y-1][x+1]]) goto android_ne;
+             if (tab_android_move[Cave[y-1][x]])   goto android_n;
+             if (tab_android_move[Cave[y][x+1]])   goto android_e;
+             break;
+
+           case 3: /* west */
+             if (tab_android_move[Cave[y][x-1]])   goto android_w;
+             if (tab_android_move[Cave[y+1][x-1]]) goto android_sw;
+             if (tab_android_move[Cave[y-1][x-1]]) goto android_nw;
+             break;
+
+           case 4: /* nowhere */
+             break;
+
+           case 5: /* east */
+             if (tab_android_move[Cave[y][x+1]])   goto android_e;
+             if (tab_android_move[Cave[y-1][x+1]]) goto android_ne;
+             if (tab_android_move[Cave[y+1][x+1]]) goto android_se;
+             break;
+
+           case 6: /* south west */
+             if (tab_android_move[Cave[y+1][x-1]]) goto android_sw;
+             if (tab_android_move[Cave[y+1][x]])   goto android_s;
+             if (tab_android_move[Cave[y][x-1]])   goto android_w;
+             break;
+
+           case 7: /* south */
+             if (tab_android_move[Cave[y+1][x]])   goto android_s;
+             if (tab_android_move[Cave[y+1][x+1]]) goto android_se;
+             if (tab_android_move[Cave[y+1][x-1]]) goto android_sw;
+             break;
+
+           case 8: /* south east */
+             if (tab_android_move[Cave[y+1][x+1]]) goto android_se;
+             if (tab_android_move[Cave[y][x+1]])   goto android_e;
+             if (tab_android_move[Cave[y+1][x]])   goto android_s;
+             break;
+         }
+       }
+      }
+
+    android_still:
+
+      Next[y][x] = Xandroid;
+      goto loop;
+
+    android_n:
+
+      Cave[y][x] = Yandroid_nB;
+      Cave[y-1][x] = Yandroid_n;
+      Next[y-1][x] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_ne:
+
+      Cave[y][x] = Yandroid_neB;
+      Cave[y-1][x+1] = Yandroid_ne;
+      Next[y-1][x+1] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_e:
+
+      Cave[y][x] = Yandroid_eB;
+      Cave[y][x+1] = Yandroid_e;
+      Next[y][x+1] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_se:
+
+      Cave[y][x] = Yandroid_seB;
+      Cave[y+1][x+1] = Yandroid_se;
+      Next[y+1][x+1] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_s:
+
+      Cave[y][x] = Yandroid_sB;
+      Cave[y+1][x] = Yandroid_s;
+      Next[y+1][x] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_sw:
+
+      Cave[y][x] = Yandroid_swB;
+      Cave[y+1][x-1] = Yandroid_sw;
+      Next[y+1][x-1] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_w:
+
+      Cave[y][x] = Yandroid_wB;
+      Cave[y][x-1] = Yandroid_w;
+      Next[y][x-1] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    android_nw:
+
+      Cave[y][x] = Yandroid_nwB;
+      Cave[y-1][x-1] = Yandroid_nw;
+      Next[y-1][x-1] = Xandroid;
+      play_element_sound(x, y, SAMPLE_android_move, element);
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xandroid_1_n:
+      switch (Cave[y-1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_nB;
+         if (Cave[y-2][x+1] == Xblank)
+           Cave[y-2][x+1] = Yacid_splash_eB;
+         if (Cave[y-2][x-1] == Xblank)
+           Cave[y-2][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_nB;
+         Cave[y-1][x] = Yandroid_n;
+         Next[y][x] = Xblank;
+         Next[y-1][x] = Xandroid;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    case Xandroid_2_n:
+      switch (Cave[y-1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_nB;
+         if (Cave[y-2][x+1] == Xblank)
+           Cave[y-2][x+1] = Yacid_splash_eB;
+         if (Cave[y-2][x-1] == Xblank)
+           Cave[y-2][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_nB;
+         Cave[y-1][x] = Yandroid_n;
+         Next[y][x] = Xblank;
+         Next[y-1][x] = Xandroid_1_n;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xandroid_1_e:
+      switch (Cave[y][x+1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_eB;
+         if (Cave[y-1][x+2] == Xblank)
+           Cave[y-1][x+2] = Yacid_splash_eB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_eB;
+         Cave[y][x+1] = Yandroid_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xandroid;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    case Xandroid_2_e:
+      switch (Cave[y][x+1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_eB;
+         if (Cave[y-1][x+2] == Xblank)
+           Cave[y-1][x+2] = Yacid_splash_eB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_eB;
+         Cave[y][x+1] = Yandroid_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xandroid_1_e;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xandroid_1_s:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_sB;
+         Cave[y+1][x] = Yandroid_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xandroid;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    case Xandroid_2_s:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_sB;
+         Cave[y+1][x] = Yandroid_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xandroid_1_s;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xandroid_1_w:
+      switch (Cave[y][x-1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_wB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_eB;
+         if (Cave[y-1][x-2] == Xblank)
+           Cave[y-1][x-2] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_wB;
+         Cave[y][x-1] = Yandroid_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xandroid;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    case Xandroid_2_w:
+      switch (Cave[y][x-1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yandroid_wB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_eB;
+         if (Cave[y-1][x-2] == Xblank)
+           Cave[y-1][x-2] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yandroid_wB;
+         Cave[y][x-1] = Yandroid_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xandroid_1_w;
+         play_element_sound(x, y, SAMPLE_android_move, element);
+         goto loop;
+
+       default:
+         goto android;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xspring:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yspring_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xspring_fall;
+         goto loop;
+
+       case Xspring:
+       case Xspring_pause:
+       case Xspring_e:
+       case Xspring_w:
+       case Xandroid:
+       case Xandroid_1_n:
+       case Xandroid_2_n:
+       case Xandroid_1_e:
+       case Xandroid_2_e:
+       case Xandroid_1_s:
+       case Xandroid_2_s:
+       case Xandroid_1_w:
+       case Xandroid_2_w:
+       case Xstone:
+       case Xstone_pause:
+       case Xemerald:
+       case Xemerald_pause:
+       case Xdiamond:
+       case Xdiamond_pause:
+       case Xbomb:
+       case Xbomb_pause:
+       case Xballoon:
+       case Xacid_ne:
+       case Xacid_nw:
+       case Xball_1:
+       case Xball_2:
+       case Xnut:
+       case Xnut_pause:
+       case Xgrow_ns:
+       case Xgrow_ew:
+       case Xkey_1:
+       case Xkey_2:
+       case Xkey_3:
+       case Xkey_4:
+       case Xkey_5:
+       case Xkey_6:
+       case Xkey_7:
+       case Xkey_8:
+       case Xbumper:
+       case Xswitch:
+       case Xround_wall_1:
+       case Xround_wall_2:
+       case Xround_wall_3:
+       case Xround_wall_4:
+         if (RANDOM & 1)
+         {
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Yspring_eB;
+             Cave[y][x+1] = Yspring_e;
+             if (Cave[y+1][x] == Xbumper)
+               Cave[y+1][x] = XbumperB;
+             Next[y][x] = Xblank;
+
+#ifdef BAD_SPRING
+             Next[y][x+1] = Xspring_e;
+#else  
+             Next[y][x+1] = Xspring_pause;
+#endif
+
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Yspring_wB;
+             Cave[y][x-1] = Yspring_w;
+             if (Cave[y+1][x] == Xbumper)
+               Cave[y+1][x] = XbumperB;
+             Next[y][x] = Xblank;
+
+#ifdef BAD_SPRING
+             Next[y][x-1] = Xspring_w;
+#else
+             Next[y][x-1] = Xspring_pause;
+#endif
+
+             goto loop;
+           }
+         }
+         else
+         {
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Yspring_wB;
+             Cave[y][x-1] = Yspring_w;
+             if (Cave[y+1][x] == Xbumper)
+               Cave[y+1][x] = XbumperB;
+             Next[y][x] = Xblank;
+
+#ifdef BAD_SPRING
+             Next[y][x-1] = Xspring_w;
+#else
+             Next[y][x-1] = Xspring_pause;
+#endif
+
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Yspring_eB;
+             Cave[y][x+1] = Yspring_e;
+             if (Cave[y+1][x] == Xbumper)
+               Cave[y+1][x] = XbumperB;
+             Next[y][x] = Xblank;
+
+#ifdef BAD_SPRING
+             Next[y][x+1] = Xspring_e;
+#else
+             Next[y][x+1] = Xspring_pause;
+#endif
+
+             goto loop;
+           }
+         }
+
+       default:
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xspring_pause:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yspring_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xspring_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xspring;
+         Next[y][x] = Xspring;
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xspring_e:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yspring_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xspring_fall;
+         goto loop;
+
+       case Xbumper:
+         Cave[y+1][x] = XbumperB;
+      }
+
+      switch (Cave[y][x+1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_eB;
+         if (Cave[y-1][x+2] == Xblank)
+           Cave[y-1][x+2] = Yacid_splash_eB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Yalien_nB:
+       case Yalien_eB:
+       case Yalien_sB:
+       case Yalien_wB:
+         Cave[y][x] = Yspring_eB;
+         Cave[y][x+1] = Yspring_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xspring_e;
+         goto loop;
+
+       case Xalien:
+       case Xalien_pause:
+       case Yalien_n:
+       case Yalien_e:
+       case Yalien_s:
+       case Yalien_w:
+         Cave[y][x] = Yspring_kill_eB;
+         Cave[y][x+1] = Yspring_kill_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xspring_e;
+         play_element_sound(x, y, SAMPLE_slurp, Xalien);
+         score += lev.slurp_score;
+         goto loop;
+
+       case Xbumper:
+       case XbumperB:
+         Cave[y][x+1] = XbumperB;
+         Next[y][x] = Xspring_w;
+         play_element_sound(x, y, SAMPLE_spring, Xspring);
+         goto loop;
+
+       default:
+         Cave[y][x] = Xspring;
+         Next[y][x] = Xspring;
+         play_element_sound(x, y, SAMPLE_spring, Xspring);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xspring_w:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yspring_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xspring_fall;
+         goto loop;
+
+       case Xbumper:
+         Cave[y+1][x] = XbumperB;
+      }
+
+      switch (Cave[y][x-1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_wB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_eB;
+         if (Cave[y-1][x-2] == Xblank)
+           Cave[y-1][x-2] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Yalien_nB:
+       case Yalien_eB:
+       case Yalien_sB:
+       case Yalien_wB:
+         Cave[y][x] = Yspring_wB;
+         Cave[y][x-1] = Yspring_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xspring_w;
+         goto loop;
+
+       case Xalien:
+       case Xalien_pause:
+       case Yalien_n:
+       case Yalien_e:
+       case Yalien_s:
+       case Yalien_w:
+         Cave[y][x] = Yspring_kill_wB;
+         Cave[y][x-1] = Yspring_kill_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xspring_w;
+         play_element_sound(x, y, SAMPLE_slurp, Xalien);
+         score += lev.slurp_score;
+         goto loop;
+
+       case Xbumper:
+       case XbumperB:
+         Cave[y][x-1] = XbumperB;
+         Next[y][x] = Xspring_e;
+         play_element_sound(x, y, SAMPLE_spring, Xspring);
+         goto loop;
+
+       default:
+         Cave[y][x] = Xspring;
+         Next[y][x] = Xspring;
+         play_element_sound(x, y, SAMPLE_spring, Xspring);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xspring_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yspring_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Zplayer:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yspring_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xspring_fall;
+         goto loop;
+
+       case Xbomb:
+       case Xbomb_pause:
+         Cave[y+1][x] = Ybomb_eat;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+         Boom[y+2][x-1] = Xblank;
+         Boom[y+2][x] = Xblank;
+         Boom[y+2][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         goto loop;
+
+       case Xbug_n:
+       case Xbug_e:
+       case Xbug_s:
+       case Xbug_w:
+       case Xbug_gon:
+       case Xbug_goe:
+       case Xbug_gos:
+       case Xbug_gow:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Ybug_spring;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xemerald;
+         Boom[y][x] = Xemerald;
+         Boom[y][x+1] = Xemerald;
+         Boom[y+1][x-1] = Xemerald;
+         Boom[y+1][x] = Xdiamond;
+         Boom[y+1][x+1] = Xemerald;
+         Boom[y+2][x-1] = Xemerald;
+         Boom[y+2][x] = Xemerald;
+         Boom[y+2][x+1] = Xemerald;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         score += lev.bug_score;
+         goto loop;
+
+       case Xtank_n:
+       case Xtank_e:
+       case Xtank_s:
+       case Xtank_w:
+       case Xtank_gon:
+       case Xtank_goe:
+       case Xtank_gos:
+       case Xtank_gow:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Ytank_spring;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+         Boom[y+2][x-1] = Xblank;
+         Boom[y+2][x] = Xblank;
+         Boom[y+2][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         score += lev.tank_score;
+         goto loop;
+
+       case Xeater_n:
+       case Xeater_e:
+       case Xeater_s:
+       case Xeater_w:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yeater_spring;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = lev.eater_array[lev.eater_pos][0];
+         Boom[y][x] = lev.eater_array[lev.eater_pos][1];
+         Boom[y][x+1] = lev.eater_array[lev.eater_pos][2];
+         Boom[y+1][x-1] = lev.eater_array[lev.eater_pos][3];
+         Boom[y+1][x] = lev.eater_array[lev.eater_pos][4];
+         Boom[y+1][x+1] = lev.eater_array[lev.eater_pos][5];
+         Boom[y+2][x-1] = lev.eater_array[lev.eater_pos][6];
+         Boom[y+2][x] = lev.eater_array[lev.eater_pos][7];
+         Boom[y+2][x+1] = lev.eater_array[lev.eater_pos][8];
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         lev.eater_pos = (lev.eater_pos + 1) & 7;
+         score += lev.eater_score;
+         goto loop;
+
+       case Xalien:
+       case Xalien_pause:
+         Cave[y][x] = Yspring_sB;
+         Cave[y+1][x] = Yalien_spring;
+         Next[y+1][x] = Znormal;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+         Boom[y+2][x-1] = Xblank;
+         Boom[y+2][x] = Xblank;
+         Boom[y+2][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         score += lev.alien_score;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xspring;
+         Next[y][x] = Xspring;
+         play_element_sound(x, y, SAMPLE_spring, Xspring);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xeater_n:
+      if (Cave[y][x+1] == Xdiamond)
+      {
+       Cave[y][x+1] = Ydiamond_eat;
+       Next[y][x+1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y+1][x] == Xdiamond)
+      {
+       Cave[y+1][x] = Ydiamond_eat;
+       Next[y+1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y][x-1] == Xdiamond)
+      {
+       Cave[y][x-1] = Ydiamond_eat;
+       Next[y][x-1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y-1][x] == Xdiamond)
+      {
+       Cave[y-1][x] = Ydiamond_eat;
+       Next[y-1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      switch (Cave[y-1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yeater_nB;
+         if (Cave[y-2][x+1] == Xblank)
+           Cave[y-2][x+1] = Yacid_splash_eB;
+         if (Cave[y-2][x-1] == Xblank)
+           Cave[y-2][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Yeater_nB;
+         Cave[y-1][x] = Yeater_n;
+         Next[y][x] = Xblank;
+         Next[y-1][x] = Xeater_n;
+         goto loop;
+
+       default:
+         Next[y][x] = RANDOM & 1 ? Xeater_e : Xeater_w;
+         play_element_sound(x, y, SAMPLE_eater, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xeater_e:
+      if (Cave[y+1][x] == Xdiamond)
+      {
+       Cave[y+1][x] = Ydiamond_eat;
+       Next[y+1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y][x-1] == Xdiamond)
+      {
+       Cave[y][x-1] = Ydiamond_eat;
+       Next[y][x-1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y-1][x] == Xdiamond)
+      {
+       Cave[y-1][x] = Ydiamond_eat;
+       Next[y-1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y][x+1] == Xdiamond)
+      {
+       Cave[y][x+1] = Ydiamond_eat;
+       Next[y][x+1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      switch (Cave[y][x+1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yeater_eB;
+         if (Cave[y-1][x+2] == Xblank)
+           Cave[y-1][x+2] = Yacid_splash_eB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Yeater_eB;
+         Cave[y][x+1] = Yeater_e;
+         Next[y][x] = Xblank;
+         Next[y][x+1] = Xeater_e;
+         goto loop;
+
+       default:
+         Next[y][x] = RANDOM & 1 ? Xeater_n : Xeater_s;
+         play_element_sound(x, y, SAMPLE_eater, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xeater_s:
+      if (Cave[y][x-1] == Xdiamond)
+      {
+       Cave[y][x-1] = Ydiamond_eat;
+       Next[y][x-1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y-1][x] == Xdiamond)
+      {
+       Cave[y-1][x] = Ydiamond_eat;
+       Next[y-1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y][x+1] == Xdiamond)
+      {
+       Cave[y][x+1] = Ydiamond_eat;
+       Next[y][x+1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y+1][x] == Xdiamond)
+      {
+       Cave[y+1][x] = Ydiamond_eat;
+       Next[y+1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yeater_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Yeater_sB;
+         Cave[y+1][x] = Yeater_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xeater_s;
+         goto loop;
+
+       default:
+         Next[y][x] = RANDOM & 1 ? Xeater_e : Xeater_w;
+         play_element_sound(x, y, SAMPLE_eater, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xeater_w:
+      if (Cave[y-1][x] == Xdiamond)
+      {
+       Cave[y-1][x] = Ydiamond_eat;
+       Next[y-1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y][x+1] == Xdiamond)
+      {
+       Cave[y][x+1] = Ydiamond_eat;
+       Next[y][x+1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y+1][x] == Xdiamond)
+      {
+       Cave[y+1][x] = Ydiamond_eat;
+       Next[y+1][x] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      if (Cave[y][x-1] == Xdiamond)
+      {
+       Cave[y][x-1] = Ydiamond_eat;
+       Next[y][x-1] = Xblank;
+       play_element_sound(x, y, SAMPLE_eater_eat, element);
+       goto loop;
+      }
+
+      switch (Cave[y][x-1])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yeater_wB;
+         if (Cave[y-1][x] == Xblank)
+           Cave[y-1][x] = Yacid_splash_eB;
+         if (Cave[y-1][x-2] == Xblank)
+           Cave[y-1][x-2] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Yeater_wB;
+         Cave[y][x-1] = Yeater_w;
+         Next[y][x] = Xblank;
+         Next[y][x-1] = Xeater_w;
+         goto loop;
+
+       default:
+         Next[y][x] = RANDOM & 1 ? Xeater_n : Xeater_s;
+         play_element_sound(x, y, SAMPLE_eater, element);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xalien:
+      if (lev.wheel_cnt)
+      {
+       dx = lev.wheel_x;
+       dy = lev.wheel_y;
+      }
+      else if (ply1.alive && ply2.alive)
+      {
+       if ((ply1.x > x ? ply1.x - x : x - ply1.x) +
+           (ply1.y > y ? ply1.y - y : y - ply1.y) <
+           (ply2.x > x ? ply2.x - x : x - ply2.x) +
+           (ply2.y > y ? ply2.y - y : y - ply2.y))
+       {
+         dx = ply1.x;
+         dy = ply1.y;
+       }
+       else
+       {
+         dx = ply2.x;
+         dy = ply2.y;
+       }
+      }
+      else if (ply1.alive)
+      {
+       dx = ply1.x;
+       dy = ply1.y;
+      }
+      else if (ply2.alive)
+      {
+       dx = ply2.x;
+       dy = ply2.y;
+      }
+      else
+      {
+       dx = 0;
+       dy = 0;
+      }
+
+      if (RANDOM & 1)
+      {
+       if (y > dy)
+       {
+         switch (Cave[y-1][x])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yalien_nB;
+             if (Cave[y-2][x+1] == Xblank)
+               Cave[y-2][x+1] = Yacid_splash_eB;
+             if (Cave[y-2][x-1] == Xblank)
+               Cave[y-2][x-1] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+           case Xplant:
+           case Yplant:
+           case Zplayer:
+             Cave[y][x] = Yalien_nB;
+             Cave[y-1][x] = Yalien_n;
+             Next[y][x] = Xblank;
+             Next[y-1][x] = Xalien_pause;
+             play_element_sound(x, y, SAMPLE_alien, Xalien);
+             goto loop;
+         }
+       }
+       else if (y < dy)
+       {
+         switch (Cave[y+1][x])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yalien_sB;
+             Next[y][x] = Xblank;
+             if (Cave[y][x+1] == Xblank)
+               Cave[y][x+1] = Yacid_splash_eB;
+             if (Cave[y][x-1] == Xblank)
+               Cave[y][x-1] = Yacid_splash_wB;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+           case Xplant:
+           case Yplant:
+           case Zplayer:
+             Cave[y][x] = Yalien_sB;
+             Cave[y+1][x] = Yalien_s;
+             Next[y][x] = Xblank;
+             Next[y+1][x] = Xalien_pause;
+             play_element_sound(x, y, SAMPLE_alien, Xalien);
+             goto loop;
+         }
+       }
+      }
+      else
+      {
+       if (x < dx)
+       {
+         switch (Cave[y][x+1])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yalien_eB;
+             if (Cave[y-1][x+2] == Xblank)
+               Cave[y-1][x+2] = Yacid_splash_eB;
+             if (Cave[y-1][x] == Xblank)
+               Cave[y-1][x] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+           case Xplant:
+           case Yplant:
+           case Zplayer:
+             Cave[y][x] = Yalien_eB;
+             Cave[y][x+1] = Yalien_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xalien_pause;
+             play_element_sound(x, y, SAMPLE_alien, Xalien);
+             goto loop;
+         }
+       }
+       else if (x > dx)
+       {
+         switch (Cave[y][x-1])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yalien_wB;
+             if (Cave[y-1][x] == Xblank)
+               Cave[y-1][x] = Yacid_splash_eB;
+             if (Cave[y-1][x-2] == Xblank)
+               Cave[y-1][x-2] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+           case Xplant:
+           case Yplant:
+           case Zplayer:
+             Cave[y][x] = Yalien_wB;
+             Cave[y][x-1] = Yalien_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xalien_pause;
+             play_element_sound(x, y, SAMPLE_alien, Xalien);
+             goto loop;
+         }
+       }
+      }
+
+      goto loop;
+
+    case Xalien_pause:
+      Next[y][x] = Xalien;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xemerald:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yemerald_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yemerald_sB;
+         Cave[y+1][x] = Yemerald_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xemerald_fall;
+         goto loop;
+
+       case Xspring:
+       case Xspring_pause:
+       case Xspring_e:
+       case Xspring_w:
+       case Xandroid:
+       case Xandroid_1_n:
+       case Xandroid_2_n:
+       case Xandroid_1_e:
+       case Xandroid_2_e:
+       case Xandroid_1_s:
+       case Xandroid_2_s:
+       case Xandroid_1_w:
+       case Xandroid_2_w:
+       case Xstone:
+       case Xstone_pause:
+       case Xemerald:
+       case Xemerald_pause:
+       case Xdiamond:
+       case Xdiamond_pause:
+       case Xbomb:
+       case Xbomb_pause:
+       case Xballoon:
+       case Xacid_ne:
+       case Xacid_nw:
+       case Xball_1:
+       case Xball_2:
+       case Xnut:
+       case Xnut_pause:
+       case Xgrow_ns:
+       case Xgrow_ew:
+       case Xwonderwall:
+       case Xkey_1:
+       case Xkey_2:
+       case Xkey_3:
+       case Xkey_4:
+       case Xkey_5:
+       case Xkey_6:
+       case Xkey_7:
+       case Xkey_8:
+       case Xbumper:
+       case Xswitch:
+       case Xsteel_1:
+       case Xsteel_2:
+       case Xsteel_3:
+       case Xsteel_4:
+       case Xwall_1:
+       case Xwall_2:
+       case Xwall_3:
+       case Xwall_4:
+       case Xround_wall_1:
+       case Xround_wall_2:
+       case Xround_wall_3:
+       case Xround_wall_4:
+         if (RANDOM & 1)
+         {
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Yemerald_eB;
+             Cave[y][x+1] = Yemerald_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xemerald_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Yemerald_wB;
+             Cave[y][x-1] = Yemerald_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xemerald_pause;
+             goto loop;
+           }
+         }
+         else
+         {
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Yemerald_wB;
+             Cave[y][x-1] = Yemerald_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xemerald_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Yemerald_eB;
+             Cave[y][x+1] = Yemerald_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xemerald_pause;
+             goto loop;
+           }
+         }
+
+        default:
+         if (++lev.shine_cnt > 50)
+         {
+           lev.shine_cnt = RANDOM & 7;
+           Cave[y][x] = Xemerald_shine;
+         }
+
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xemerald_pause:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yemerald_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Yemerald_sB;
+         Cave[y+1][x] = Yemerald_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xemerald_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xemerald;
+         Next[y][x] = Xemerald;
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xemerald_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Yemerald_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Zplayer:
+         Cave[y][x] = Yemerald_sB;
+         Cave[y+1][x] = Yemerald_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xemerald_fall;
+         goto loop;
+
+       case Xwonderwall:
+         if (lev.wonderwall_time)
+         {
+           lev.wonderwall_state = 1;
+           Cave[y][x] = Yemerald_sB;
+           if (tab_blank[Cave[y+2][x]])
+           {
+             Cave[y+2][x] = Ydiamond_s;
+             Next[y+2][x] = Xdiamond_fall;
+           }
+
+           Next[y][x] = Xblank;
+           play_element_sound(x, y, SAMPLE_wonderfall, Xwonderwall);
+           goto loop;
+         }
+
+       default:
+         Cave[y][x] = Xemerald;
+         Next[y][x] = Xemerald;
+         play_element_sound(x, y, SAMPLE_diamond, Xemerald);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdiamond:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ydiamond_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ydiamond_sB;
+         Cave[y+1][x] = Ydiamond_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xdiamond_fall;
+         goto loop;
+
+       case Xspring:
+       case Xspring_pause:
+       case Xspring_e:
+       case Xspring_w:
+       case Xandroid:
+       case Xandroid_1_n:
+       case Xandroid_2_n:
+       case Xandroid_1_e:
+       case Xandroid_2_e:
+       case Xandroid_1_s:
+       case Xandroid_2_s:
+       case Xandroid_1_w:
+       case Xandroid_2_w:
+       case Xstone:
+       case Xstone_pause:
+       case Xemerald:
+       case Xemerald_pause:
+       case Xdiamond:
+       case Xdiamond_pause:
+       case Xbomb:
+       case Xbomb_pause:
+       case Xballoon:
+       case Xacid_ne:
+       case Xacid_nw:
+       case Xball_1:
+       case Xball_2:
+       case Xnut:
+       case Xnut_pause:
+       case Xgrow_ns:
+       case Xgrow_ew:
+       case Xwonderwall:
+       case Xkey_1:
+       case Xkey_2:
+       case Xkey_3:
+       case Xkey_4:
+       case Xkey_5:
+       case Xkey_6:
+       case Xkey_7:
+       case Xkey_8:
+       case Xbumper:
+       case Xswitch:
+       case Xsteel_1:
+       case Xsteel_2:
+       case Xsteel_3:
+       case Xsteel_4:
+       case Xwall_1:
+       case Xwall_2:
+       case Xwall_3:
+       case Xwall_4:
+       case Xround_wall_1:
+       case Xround_wall_2:
+       case Xround_wall_3:
+       case Xround_wall_4:
+         if (RANDOM & 1)
+         {
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ydiamond_eB;
+             Cave[y][x+1] = Ydiamond_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xdiamond_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ydiamond_wB;
+             Cave[y][x-1] = Ydiamond_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xdiamond_pause;
+             goto loop;
+           }
+         }
+         else
+         {
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ydiamond_wB;
+             Cave[y][x-1] = Ydiamond_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xdiamond_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ydiamond_eB;
+             Cave[y][x+1] = Ydiamond_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xdiamond_pause;
+             goto loop;
+           }
+         }
+
+       default:
+         if (++lev.shine_cnt > 50)
+         {
+           lev.shine_cnt = RANDOM & 7;
+           Cave[y][x] = Xdiamond_shine;
+         }
+
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdiamond_pause:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ydiamond_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ydiamond_sB;
+         Cave[y+1][x] = Ydiamond_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xdiamond_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xdiamond;
+         Next[y][x] = Xdiamond;
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdiamond_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ydiamond_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Zplayer:
+         Cave[y][x] = Ydiamond_sB;
+         Cave[y+1][x] = Ydiamond_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xdiamond_fall;
+         goto loop;
+
+       case Xwonderwall:
+         if (lev.wonderwall_time)
+         {
+           lev.wonderwall_state = 1;
+           Cave[y][x] = Ydiamond_sB;
+           if (tab_blank[Cave[y+2][x]])
+           {
+             Cave[y+2][x] = Ystone_s;
+             Next[y+2][x] = Xstone_fall;
+           }
+
+           Next[y][x] = Xblank;
+           play_element_sound(x, y, SAMPLE_wonderfall, Xwonderwall);
+           goto loop;
+         }
+
+       default:
+         Cave[y][x] = Xdiamond;
+         Next[y][x] = Xdiamond;
+         play_element_sound(x, y, SAMPLE_diamond, Xdiamond);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdrip_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ydrip_s1B;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xdrip_stretchB;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+       case Xplant:
+       case Yplant:
+       case Zplayer:
+         Cave[y][x] = Ydrip_s1B;
+         Cave[y+1][x] = Ydrip_s1;
+         Next[y][x] = Xdrip_stretchB;
+         Next[y+1][x] = Xdrip_stretch;
+         goto loop;
+
+       default:
+         switch (RANDOM & 7)
+         {
+           case 0:
+             temp = Xamoeba_1;
+             break;
+
+           case 1:
+             temp = Xamoeba_2;
+             break;
+
+           case 2:
+             temp = Xamoeba_3;
+             break;
+
+           case 3:
+             temp = Xamoeba_4;
+             break;
+
+           case 4:
+             temp = Xamoeba_5;
+             break;
+
+           case 5:
+             temp = Xamoeba_6;
+             break;
+
+           case 6:
+             temp = Xamoeba_7;
+             break;
+
+           case 7:
+             temp = Xamoeba_8;
+             break;
+         }
+
+         Cave[y][x] = temp;
+         Next[y][x] = temp;
+         play_element_sound(x, y, SAMPLE_drip, Xdrip_fall);
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdrip_stretch:
+      Cave[y][x] = Ydrip_s2;
+      Next[y][x] = Xdrip_fall;
+      goto loop;
+
+    case Xdrip_stretchB:
+      Cave[y][x] = Ydrip_s2B;
+      Next[y][x] = Xblank;
+      goto loop;
+
+    case Xdrip_eat:
+      Next[y][x] = Xdrip_fall;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbomb:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybomb_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ybomb_sB;
+         Cave[y+1][x] = Ybomb_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xbomb_fall;
+         goto loop;
+
+       case Xspring:
+       case Xspring_pause:
+       case Xspring_e:
+       case Xspring_w:
+       case Xandroid:
+       case Xandroid_1_n:
+       case Xandroid_2_n:
+       case Xandroid_1_e:
+       case Xandroid_2_e:
+       case Xandroid_1_s:
+       case Xandroid_2_s:
+       case Xandroid_1_w:
+       case Xandroid_2_w:
+       case Xstone:
+       case Xstone_pause:
+       case Xemerald:
+       case Xemerald_pause:
+       case Xdiamond:
+       case Xdiamond_pause:
+       case Xbomb:
+       case Xbomb_pause:
+       case Xballoon:
+       case Xacid_ne:
+       case Xacid_nw:
+       case Xball_1:
+       case Xball_2:
+       case Xnut:
+       case Xnut_pause:
+       case Xgrow_ns:
+       case Xgrow_ew:
+       case Xkey_1:
+       case Xkey_2:
+       case Xkey_3:
+       case Xkey_4:
+       case Xkey_5:
+       case Xkey_6:
+       case Xkey_7:
+       case Xkey_8:
+       case Xbumper:
+       case Xswitch:
+       case Xround_wall_1:
+       case Xround_wall_2:
+       case Xround_wall_3:
+       case Xround_wall_4:
+         if (RANDOM & 1)
+         {
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ybomb_eB;
+             Cave[y][x+1] = Ybomb_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xbomb_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ybomb_wB;
+             Cave[y][x-1] = Ybomb_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xbomb_pause;
+             goto loop;
+           }
+         }
+         else
+         {
+           if (tab_blank[Cave[y][x-1]] && tab_acid[Cave[y+1][x-1]])
+           {
+             Cave[y][x] = Ybomb_wB;
+             Cave[y][x-1] = Ybomb_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xbomb_pause;
+             goto loop;
+           }
+
+           if (tab_blank[Cave[y][x+1]] && tab_acid[Cave[y+1][x+1]])
+           {
+             Cave[y][x] = Ybomb_eB;
+             Cave[y][x+1] = Ybomb_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xbomb_pause;
+             goto loop;
+           }
+         }
+
+       default:
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbomb_pause:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybomb_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ybomb_sB;
+         Cave[y+1][x] = Ybomb_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xbomb_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Xbomb;
+         Next[y][x] = Xbomb;
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xbomb_fall:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Ybomb_sB;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xblank;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Ybomb_sB;
+         Cave[y+1][x] = Ybomb_s;
+         Next[y][x] = Xblank;
+         Next[y+1][x] = Xbomb_fall;
+         goto loop;
+
+       default:
+         Cave[y][x] = Ybomb_eat;
+         Next[y][x] = Znormal;
+         Boom[y-1][x-1] = Xblank;
+         Boom[y-1][x] = Xblank;
+         Boom[y-1][x+1] = Xblank;
+         Boom[y][x-1] = Xblank;
+         Boom[y][x] = Xblank;
+         Boom[y][x+1] = Xblank;
+         Boom[y+1][x-1] = Xblank;
+         Boom[y+1][x] = Xblank;
+         Boom[y+1][x+1] = Xblank;
+#if 0
+         play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+         goto loop;
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xballoon:
+      if (lev.wind_cnt == 0)
+       goto loop;
+
+      switch (lev.wind_direction)
+      {
+       case 0: /* north */
+         switch (Cave[y-1][x])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yballoon_nB;
+             if (Cave[y-2][x+1] == Xblank)
+               Cave[y-2][x+1] = Yacid_splash_eB;
+             if (Cave[y-2][x-1] == Xblank)
+               Cave[y-2][x-1] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+             Cave[y][x] = Yballoon_nB;
+             Cave[y-1][x] = Yballoon_n;
+             Next[y][x] = Xblank;
+             Next[y-1][x] = Xballoon;
+             goto loop;
+
+           default:
+             goto loop;
+         }
+
+        case 1: /* east */
+         switch (Cave[y][x+1])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yballoon_eB;
+             if (Cave[y-1][x+2] == Xblank)
+               Cave[y-1][x+2] = Yacid_splash_eB;
+             if (Cave[y-1][x] == Xblank)
+               Cave[y-1][x] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+             Cave[y][x] = Yballoon_eB;
+             Cave[y][x+1] = Yballoon_e;
+             Next[y][x] = Xblank;
+             Next[y][x+1] = Xballoon;
+             goto loop;
+
+           default:
+             goto loop;
+         }
+
+        case 2: /* south */
+         switch (Cave[y+1][x])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yballoon_sB;
+             if (Cave[y][x+1] == Xblank)
+               Cave[y][x+1] = Yacid_splash_eB;
+             if (Cave[y][x-1] == Xblank)
+               Cave[y][x-1] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+             Cave[y][x] = Yballoon_sB;
+             Cave[y+1][x] = Yballoon_s;
+             Next[y][x] = Xblank;
+             Next[y+1][x] = Xballoon;
+             goto loop;
+
+           default:
+             goto loop;
+         }
+
+        case 3: /* west */
+         switch (Cave[y][x-1])
+         {
+           case Xacid_1:
+           case Xacid_2:
+           case Xacid_3:
+           case Xacid_4:
+           case Xacid_5:
+           case Xacid_6:
+           case Xacid_7:
+           case Xacid_8:
+             Cave[y][x] = Yballoon_wB;
+             if (Cave[y-1][x] == Xblank)
+               Cave[y-1][x] = Yacid_splash_eB;
+             if (Cave[y-1][x-2] == Xblank)
+               Cave[y-1][x-2] = Yacid_splash_wB;
+             Next[y][x] = Xblank;
+             play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+             goto loop;
+
+           case Xblank:
+           case Yacid_splash_eB:
+           case Yacid_splash_wB:
+             Cave[y][x] = Yballoon_wB;
+             Cave[y][x-1] = Yballoon_w;
+             Next[y][x] = Xblank;
+             Next[y][x-1] = Xballoon;
+             goto loop;
+
+           default:
+             goto loop;
+         }
+      }
+
+    /* --------------------------------------------------------------------- */
+
+    case Xacid_1:
+      Next[y][x] = Xacid_2;
+      goto loop;
+
+    case Xacid_2:
+      Next[y][x] = Xacid_3;
+      goto loop;
+
+    case Xacid_3:
+      Next[y][x] = Xacid_4;
+      goto loop;
+
+    case Xacid_4:
+      Next[y][x] = Xacid_5;
+      goto loop;
+
+    case Xacid_5:
+      Next[y][x] = Xacid_6;
+      goto loop;
+
+    case Xacid_6:
+      Next[y][x] = Xacid_7;
+      goto loop;
+
+    case Xacid_7:
+      Next[y][x] = Xacid_8;
+      goto loop;
+
+    case Xacid_8:
+      Next[y][x] = Xacid_1;
+      goto loop;
+
+    case Xfake_acid_1:
+      Next[y][x] = Xfake_acid_2;
+      goto loop;
+
+    case Xfake_acid_2:
+      Next[y][x] = Xfake_acid_3;
+      goto loop;
+
+    case Xfake_acid_3:
+      Next[y][x] = Xfake_acid_4;
+      goto loop;
+
+    case Xfake_acid_4:
+      Next[y][x] = Xfake_acid_5;
+      goto loop;
+
+    case Xfake_acid_5:
+      Next[y][x] = Xfake_acid_6;
+      goto loop;
+
+    case Xfake_acid_6:
+      Next[y][x] = Xfake_acid_7;
+      goto loop;
+
+    case Xfake_acid_7:
+      Next[y][x] = Xfake_acid_8;
+      goto loop;
+
+    case Xfake_acid_8:
+      Next[y][x] = Xfake_acid_1;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xball_1:
+      if (lev.ball_state == 0)
+       goto loop;
+
+      Cave[y][x] = Xball_1B;
+      Next[y][x] = Xball_2;
+      if (lev.ball_cnt)
+       goto loop;
+
+      goto ball_common;
+
+    case Xball_2:
+      if (lev.ball_state == 0)
+       goto loop;
+
+      Cave[y][x] = Xball_2B;
+      Next[y][x] = Xball_1;
+      if (lev.ball_cnt)
+       goto loop;
+
+      goto ball_common;
+
+    ball_common:
+
+      play_element_sound(x, y, SAMPLE_ball, element);
+      if (lev.ball_random)
+      {
+       switch (RANDOM & 7)
+       {
+         case 0:
+           if (lev.ball_array[lev.ball_pos][0] != Xblank &&
+               tab_blank[Cave[y-1][x-1]])
+           {
+             Cave[y-1][x-1] = Yball_eat;
+             Next[y-1][x-1] = lev.ball_array[lev.ball_pos][0];
+           }
+           break;
+
+         case 1:
+           if (lev.ball_array[lev.ball_pos][1] != Xblank &&
+               tab_blank[Cave[y-1][x]])
+           {
+             Cave[y-1][x] = Yball_eat;
+             Next[y-1][x] = lev.ball_array[lev.ball_pos][1];
+           }
+           break;
+
+         case 2:
+           if (lev.ball_array[lev.ball_pos][2] != Xblank &&
+               tab_blank[Cave[y-1][x+1]])
+           {
+             Cave[y-1][x+1] = Yball_eat;
+             Next[y-1][x+1] = lev.ball_array[lev.ball_pos][2];
+           }
+           break;
+
+         case 3:
+           if (lev.ball_array[lev.ball_pos][3] != Xblank &&
+               tab_blank[Cave[y][x-1]])
+           {
+             Cave[y][x-1] = Yball_eat;
+             Next[y][x-1] = lev.ball_array[lev.ball_pos][3];
+           }
+           break;
+
+         case 4:
+           if (lev.ball_array[lev.ball_pos][4] != Xblank &&
+               tab_blank[Cave[y][x+1]])
+           {
+             Cave[y][x+1] = Yball_eat;
+             Next[y][x+1] = lev.ball_array[lev.ball_pos][4];
+           }
+           break;
+
+         case 5:
+           if (lev.ball_array[lev.ball_pos][5] != Xblank &&
+               tab_blank[Cave[y+1][x-1]])
+           {
+             Cave[y+1][x-1] = Yball_eat;
+             Next[y+1][x-1] = lev.ball_array[lev.ball_pos][5];
+           }
+           break;
+
+         case 6:
+           if (lev.ball_array[lev.ball_pos][6] != Xblank &&
+               tab_blank[Cave[y+1][x]])
+           {
+             Cave[y+1][x] = Yball_eat;
+             Next[y+1][x] = lev.ball_array[lev.ball_pos][6];
+           }
+           break;
+
+         case 7:
+           if (lev.ball_array[lev.ball_pos][7] != Xblank &&
+               tab_blank[Cave[y+1][x+1]])
+           {
+             Cave[y+1][x+1] = Yball_eat;
+             Next[y+1][x+1] = lev.ball_array[lev.ball_pos][7];
+           }
+           break;
+       }
+      }
+      else
+      {
+       if (lev.ball_array[lev.ball_pos][0] != Xblank &&
+           tab_blank[Cave[y-1][x-1]])
+       {
+         Cave[y-1][x-1] = Yball_eat;
+         Next[y-1][x-1] = lev.ball_array[lev.ball_pos][0];
+       }
+
+       if (lev.ball_array[lev.ball_pos][1] != Xblank &&
+           tab_blank[Cave[y-1][x]])
+       {
+         Cave[y-1][x] = Yball_eat;
+         Next[y-1][x] = lev.ball_array[lev.ball_pos][1];
+       }
+
+       if (lev.ball_array[lev.ball_pos][2] != Xblank &&
+           tab_blank[Cave[y-1][x+1]])
+       {
+         Cave[y-1][x+1] = Yball_eat;
+         Next[y-1][x+1] = lev.ball_array[lev.ball_pos][2];
+       }
+
+       if (lev.ball_array[lev.ball_pos][3] != Xblank &&
+           tab_blank[Cave[y][x-1]])
+       {
+         Cave[y][x-1] = Yball_eat;
+         Next[y][x-1] = lev.ball_array[lev.ball_pos][3];
+       }
+
+       if (lev.ball_array[lev.ball_pos][4] != Xblank &&
+           tab_blank[Cave[y][x+1]])
+       {
+         Cave[y][x+1] = Yball_eat;
+         Next[y][x+1] = lev.ball_array[lev.ball_pos][4];
+       }
+
+       if (lev.ball_array[lev.ball_pos][5] != Xblank &&
+           tab_blank[Cave[y+1][x-1]])
+       {
+         Cave[y+1][x-1] = Yball_eat;
+         Next[y+1][x-1] = lev.ball_array[lev.ball_pos][5];
+       }
+
+       if (lev.ball_array[lev.ball_pos][6] != Xblank &&
+           tab_blank[Cave[y+1][x]])
+       {
+         Cave[y+1][x] = Yball_eat;
+         Next[y+1][x] = lev.ball_array[lev.ball_pos][6];
+       }
+
+       if (lev.ball_array[lev.ball_pos][7] != Xblank &&
+           tab_blank[Cave[y+1][x+1]])
+       {
+         Cave[y+1][x+1] = Yball_eat;
+         Next[y+1][x+1] = lev.ball_array[lev.ball_pos][7];
+       }
+      }
+
+      lev.ball_pos = (lev.ball_pos + 1) & 7;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xgrow_ns:
+      if (tab_blank[Cave[y-1][x]])
+      {
+       Cave[y-1][x] = Ygrow_ns_eat;
+       Next[y-1][x] = Xgrow_ns;
+       play_element_sound(x, y, SAMPLE_grow, Xgrow_ns);
+      }
+
+      if (tab_blank[Cave[y+1][x]])
+      {
+       Cave[y+1][x] = Ygrow_ns_eat;
+       Next[y+1][x] = Xgrow_ns;
+       play_element_sound(x, y, SAMPLE_grow, Xgrow_ns);
+      }
+
+      goto loop;
+
+    case Xgrow_ew:
+      if (tab_blank[Cave[y][x+1]])
+      {
+       Cave[y][x+1] = Ygrow_ew_eat;
+       Next[y][x+1] = Xgrow_ew;
+       play_element_sound(x, y, SAMPLE_grow, Xgrow_ew);
+      }
+
+      if (tab_blank[Cave[y][x-1]])
+      {
+       Cave[y][x-1] = Ygrow_ew_eat;
+       Next[y][x-1] = Xgrow_ew;
+       play_element_sound(x, y, SAMPLE_grow, Xgrow_ew);
+      }
+
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xwonderwall:
+      if (lev.wonderwall_time && lev.wonderwall_state)
+      {
+       Cave[y][x] = XwonderwallB;
+       play_element_sound(x, y, SAMPLE_wonder, Xwonderwall);
+      }
+
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xexit:
+      if (lev.required > 0)
+       goto loop;
+
+      temp = RANDOM & 63;
+      if (temp < 21)
+      {
+       Cave[y][x] = Xexit_1;
+       Next[y][x] = Xexit_2;
+      }
+      else if (temp < 42)
+      {
+       Cave[y][x] = Xexit_2;
+       Next[y][x] = Xexit_3;
+      }
+      else
+      {
+       Cave[y][x] = Xexit_3;
+       Next[y][x] = Xexit_1;
+      }
+
+      play_element_sound(x, y, SAMPLE_exit_open, Xexit);
+
+      goto loop;
+
+    case Xexit_1:
+      Next[y][x] = Xexit_2;
+      goto loop;
+
+    case Xexit_2:
+      Next[y][x] = Xexit_3;
+      goto loop;
+
+    case Xexit_3:
+      Next[y][x] = Xexit_1;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdynamite_1:
+      play_element_sound(x, y, SAMPLE_tick, Xdynamite_1);
+      Next[y][x] = Xdynamite_2;
+      goto loop;
+
+    case Xdynamite_2:
+      play_element_sound(x, y, SAMPLE_tick, Xdynamite_2);
+      Next[y][x] = Xdynamite_3;
+      goto loop;
+
+    case Xdynamite_3:
+      play_element_sound(x, y, SAMPLE_tick, Xdynamite_3);
+      Next[y][x] = Xdynamite_4;
+      goto loop;
+
+    case Xdynamite_4:
+      play_element_sound(x, y, SAMPLE_tick, Xdynamite_4);
+      Next[y][x] = Zdynamite;
+      Boom[y-1][x-1] = Xblank;
+      Boom[y-1][x] = Xblank;
+      Boom[y-1][x+1] = Xblank;
+      Boom[y][x-1] = Xblank;
+      Boom[y][x] = Xblank;
+      Boom[y][x+1] = Xblank;
+      Boom[y+1][x-1] = Xblank;
+      Boom[y+1][x] = Xblank;
+      Boom[y+1][x+1] = Xblank;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xwheel:
+      if (lev.wheel_cnt && x == lev.wheel_x && y == lev.wheel_y)
+       Cave[y][x] = XwheelB;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xswitch:
+      if (lev.ball_state)
+       Cave[y][x] = XswitchB;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xsand_stone:
+      switch (Cave[y+1][x])
+      {
+       case Xacid_1:
+       case Xacid_2:
+       case Xacid_3:
+       case Xacid_4:
+       case Xacid_5:
+       case Xacid_6:
+       case Xacid_7:
+       case Xacid_8:
+         Cave[y][x] = Xsand_stonesand_3;
+         if (Cave[y][x+1] == Xblank)
+           Cave[y][x+1] = Yacid_splash_eB;
+         if (Cave[y][x-1] == Xblank)
+           Cave[y][x-1] = Yacid_splash_wB;
+         Next[y][x] = Xsand_stonesand_4;
+         play_element_sound(x, y, SAMPLE_acid, Xacid_1);
+         goto loop;
+
+       case Xblank:
+       case Yacid_splash_eB:
+       case Yacid_splash_wB:
+         Cave[y][x] = Xsand_stonesand_3;
+         Cave[y+1][x] = Xsand_stoneout_1;
+         Next[y][x] = Xsand_stonesand_4;
+         Next[y+1][x] = Xsand_stoneout_2;
+         goto loop;
+
+       case Xsand:
+         Cave[y][x] = Xsand_stonesand_1;
+         Cave[y+1][x] = Xsand_sandstone_1;
+         Next[y][x] = Xsand_stonesand_2;
+         Next[y+1][x] = Xsand_sandstone_2;
+         goto loop;
+
+       default:
+         goto loop;
+      }
+
+    case Xsand_stonein_1:
+      Next[y][x] = Xsand_stonein_2;
+      goto loop;
+
+    case Xsand_stonein_2:
+      Next[y][x] = Xsand_stonein_3;
+      goto loop;
+
+    case Xsand_stonein_3:
+      Next[y][x] = Xsand_stonein_4;
+      goto loop;
+
+    case Xsand_stonein_4:
+      Next[y][x] = Xblank;
+      goto loop;
+
+    case Xsand_stonesand_1:
+      Next[y][x] = Xsand_stonesand_2;
+      goto loop;
+
+    case Xsand_stonesand_2:
+      Next[y][x] = Xsand_stonesand_3;
+      goto loop;
+
+    case Xsand_stonesand_3:
+      Next[y][x] = Xsand_stonesand_4;
+      goto loop;
+
+    case Xsand_stonesand_4:
+      Next[y][x] = Xsand;
+      goto loop;
+
+    case Xsand_stoneout_1:
+      Next[y][x] = Xsand_stoneout_2;
+      goto loop;
+
+    case Xsand_stoneout_2:
+      Next[y][x] = Xstone_fall;
+      goto loop;
+
+    case Xsand_sandstone_1:
+      Next[y][x] = Xsand_sandstone_2;
+      goto loop;
+
+    case Xsand_sandstone_2:
+      Next[y][x] = Xsand_sandstone_3;
+      goto loop;
+
+    case Xsand_sandstone_3:
+      Next[y][x] = Xsand_sandstone_4;
+      goto loop;
+
+    case Xsand_sandstone_4:
+      Next[y][x] = Xsand_stone;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xdripper:
+      if (lev.lenses_cnt)
+       Cave[y][x] = XdripperB;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xfake_blank:
+      if (lev.lenses_cnt)
+       Cave[y][x] = Xfake_blankB;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xfake_grass:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xfake_grassB;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xfake_door_1:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_1;
+      goto loop;
+
+    case Xfake_door_2:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_2;
+      goto loop;
+
+    case Xfake_door_3:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_3;
+      goto loop;
+
+    case Xfake_door_4:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_4;
+      goto loop;
+
+    case Xfake_door_5:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_5;
+      goto loop;
+
+    case Xfake_door_6:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_6;
+      goto loop;
+
+    case Xfake_door_7:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_7;
+      goto loop;
+
+    case Xfake_door_8:
+      if (lev.magnify_cnt)
+       Cave[y][x] = Xdoor_8;
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case Xboom_bug:
+      bug_boom:
+      Next[y][x] = Znormal;
+      Boom[y-1][x-1] = Xemerald;
+      Boom[y-1][x] = Xemerald;
+      Boom[y-1][x+1] = Xemerald;
+      Boom[y][x-1] = Xemerald;
+      Boom[y][x] = Xdiamond;
+      Boom[y][x+1] = Xemerald;
+      Boom[y+1][x-1] = Xemerald;
+      Boom[y+1][x] = Xemerald;
+      Boom[y+1][x+1] = Xemerald;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+      goto loop;
+
+    case Xboom_bomb:
+
+    tank_boom:
+
+      Next[y][x] = Znormal;
+      Boom[y-1][x-1] = Xblank;
+      Boom[y-1][x] = Xblank;
+      Boom[y-1][x+1] = Xblank;
+      Boom[y][x-1] = Xblank;
+      Boom[y][x] = Xblank;
+      Boom[y][x+1] = Xblank;
+      Boom[y+1][x-1] = Xblank;
+      Boom[y+1][x] = Xblank;
+      Boom[y+1][x+1] = Xblank;
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, element);
+#endif
+      goto loop;
+
+    case Xboom_android:
+#if 0
+      play_element_sound(x, y, SAMPLE_boom, Xandroid);
+#endif
+    case Xboom_1:
+      Next[y][x] = Xboom_2;
+#if 1
+      play_sound(x, y, SAMPLE_boom);
+#endif
+      goto loop;
+
+    case Xboom_2:
+      Next[y][x] = Boom[y][x];
+      goto loop;
+
+    /* --------------------------------------------------------------------- */
+
+    case ZBORDER:
+      if (++y < HEIGHT - 1)
+      {
+       x = 0;
+       cave_cache = Cave[y];
+       goto loop;
+      }
+
+      goto done;
+  }
+
+#undef RANDOM
+#undef PLAY
+#undef PLAY_FORCE
+
+ done:
+
+  if (ply1.alive || ply2.alive)
+    lev.score += score; /* only get a score if someone is alive */
+
+  RandomEM = random;
+
+  {
+    void *temp = Cave;
+
+    /* triple buffering */
+    Cave = Next;
+    Next = Draw;
+    Draw = temp;
+  }
+}
diff --git a/src/game_em/synchro_3.c b/src/game_em/synchro_3.c
new file mode 100644 (file)
index 0000000..449ecab
--- /dev/null
@@ -0,0 +1,132 @@
+/* third part of synchro.
+ *
+ * handle global elements.
+ *
+ * this should be spread over the frames for reduced cpu load.
+ */
+
+#include "tile.h"
+#include "level.h"
+#include "sample.h"
+
+
+void synchro_3(void)
+{
+  register unsigned int x;
+  register unsigned int y;
+  register unsigned int count;
+  register unsigned long random;
+
+  /* update variables */
+
+  if (lev.score > 9999)
+    lev.score = 9999;
+
+#if 0
+#if 1
+  if (lev.time_initial == 0)
+    lev.time++;
+  else if (lev.time > 0)
+    lev.time--;
+#else
+  if (lev.time)
+    lev.time--;
+#endif
+#endif
+
+  if (lev.android_move_cnt-- == 0)
+    lev.android_move_cnt = lev.android_move_time;
+  if (lev.android_clone_cnt-- == 0)
+    lev.android_clone_cnt = lev.android_clone_time;
+  if (lev.ball_state)
+    if (lev.ball_cnt-- == 0)
+      lev.ball_cnt = lev.ball_time;
+  if (lev.lenses_cnt)
+    lev.lenses_cnt--;
+  if (lev.magnify_cnt)
+    lev.magnify_cnt--;
+  if (lev.wheel_cnt)
+    lev.wheel_cnt--;
+  if (lev.wind_cnt)
+    lev.wind_cnt--;
+  if (lev.wonderwall_time && lev.wonderwall_state)
+    lev.wonderwall_time--;
+
+#if 0
+  if (lev.time_initial > 0 &&
+      lev.time > 0 && lev.time <= 50 && lev.time % 5 == 0 && setup.time_limit)
+    play_sound(-1, -1, SAMPLE_time);
+#endif
+
+  if (lev.wheel_cnt)
+    play_element_sound(lev.wheel_x, lev.wheel_y, SAMPLE_wheel, Xwheel);
+
+  /* grow amoeba */
+
+  random = RandomEM;
+
+  for (count = lev.amoeba_time; count--;)
+  {
+    x = (random >> 10) % (WIDTH - 2);
+    y = (random >> 20) % (HEIGHT - 2);
+    switch (Cave[y][x])
+    {
+      case Xblank:
+      case Yacid_splash_eB:
+      case Yacid_splash_wB:
+      case Xgrass:
+      case Xdirt:
+      case Xsand:
+      case Xplant:
+      case Yplant:
+       if (tab_amoeba[Cave[y-1][x]] ||
+           tab_amoeba[Cave[y][x+1]] ||
+           tab_amoeba[Cave[y+1][x]] ||
+           tab_amoeba[Cave[y][x-1]])
+         Cave[y][x] = Xdrip_eat;
+    }
+
+    random = random * 129 + 1;
+  }
+
+  RandomEM = random;
+
+  /* handle explosions */
+
+  for (y = 1; y < HEIGHT - 1; y++)
+    for (x = 1; x < WIDTH - 1; x++)
+    {
+      switch (Cave[y][x])
+      {
+        case Znormal:
+         Cave[y][x] = Xboom_1;
+         Cave[y-1][x] = tab_explode_normal[Cave[y-1][x]];
+         Cave[y][x-1] = tab_explode_normal[Cave[y][x-1]];
+         Cave[y][x+1] = tab_explode_normal[Cave[y][x+1]];
+         Cave[y+1][x] = tab_explode_normal[Cave[y+1][x]];
+         Cave[y-1][x-1] = tab_explode_normal[Cave[y-1][x-1]];
+         Cave[y-1][x+1] = tab_explode_normal[Cave[y-1][x+1]];
+         Cave[y+1][x-1] = tab_explode_normal[Cave[y+1][x-1]];
+         Cave[y+1][x+1] = tab_explode_normal[Cave[y+1][x+1]];
+         break;
+
+        case Zdynamite:
+         Cave[y][x] = Xboom_1;
+         Cave[y-1][x] = tab_explode_dynamite[Cave[y-1][x]];
+         Cave[y][x-1] = tab_explode_dynamite[Cave[y][x-1]];
+         Cave[y][x+1] = tab_explode_dynamite[Cave[y][x+1]];
+         Cave[y+1][x] = tab_explode_dynamite[Cave[y+1][x]];
+         Cave[y-1][x-1] = tab_explode_dynamite[Cave[y-1][x-1]];
+         Cave[y-1][x+1] = tab_explode_dynamite[Cave[y-1][x+1]];
+         Cave[y+1][x-1] = tab_explode_dynamite[Cave[y+1][x-1]];
+         Cave[y+1][x+1] = tab_explode_dynamite[Cave[y+1][x+1]];
+         break;
+      }
+    }
+
+  /* triple buffering */
+
+  for (y = 0; y < HEIGHT; y++)
+    for (x = 0; x < WIDTH; x++)
+      Next[y][x] = Cave[y][x];
+}
diff --git a/src/game_em/tab_generate.c b/src/game_em/tab_generate.c
new file mode 100644 (file)
index 0000000..75c47b3
--- /dev/null
@@ -0,0 +1,4692 @@
+/* 2000-04-19T13:26:05Z
+ *
+ * construct some tables to be included directly in emerald mine source.
+ * i made this because dynamically building the tables every time sucks and i
+ * need to be able to easily modify tile.h.
+ *
+ * this is key data which almost everything depends on.
+ *
+ * this is supposed to be fairly easy to read and modify. the tab values
+ * are still hard coded constants but that should be less of a problem to
+ * modify.
+ */
+
+#include "tile.h"
+#include "display.h"
+
+
+/* ---------------------------------------------------------------------- */
+
+/* 0=stop 1=blank */
+int tile_blank[] =
+{
+  Xblank, 1,
+  Yacid_splash_eB, 1,
+  Yacid_splash_wB, 1,
+  TILE_MAX
+};
+
+/* 0=stop 1=acid */
+int tile_acid[] =
+{
+  Xblank, 1,
+  Yacid_splash_eB, 1,
+  Yacid_splash_wB, 1,
+  Xacid_1, 1,
+  Xacid_2, 1,
+  Xacid_3, 1,
+  Xacid_4, 1,
+  Xacid_5, 1,
+  Xacid_6, 1,
+  Xacid_7, 1,
+  Xacid_8, 1,
+  TILE_MAX
+};
+
+/* 0=stop 1=amoeba */
+int tile_amoeba[] =
+{
+  Xdripper, 1,
+  XdripperB, 1,
+  Xamoeba_1, 1,
+  Xamoeba_2, 1,
+  Xamoeba_3, 1,
+  Xamoeba_4, 1,
+  Xamoeba_5, 1,
+  Xamoeba_6, 1,
+  Xamoeba_7, 1,
+  Xamoeba_8, 1,
+  TILE_MAX
+};
+
+/* 0=stop 1=move */
+int tile_android_move[] =
+{
+  Xblank, 1,
+  Yacid_splash_eB, 1,
+  Yacid_splash_wB, 1,
+  Xplant, 1,
+  TILE_MAX
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* explosions: special format */
+/* everything is initially filled with Xboom_1 */
+int tile_explode[] =
+{
+  ZBORDER,
+  Znormal,
+  Zdynamite,
+  Xboom_bug,
+  Xboom_bomb,
+  Xboom_android,
+  Xandroid,
+  Xandroid_1_n,
+  Xandroid_2_n,
+  Xandroid_1_e,
+  Xandroid_2_e,
+  Xandroid_1_s,
+  Xandroid_2_s,
+  Xandroid_1_w,
+  Xandroid_2_w,
+  Xacid_ne,
+  Xacid_nw,
+  Xacid_s,
+  Xacid_se,
+  Xacid_sw,
+  Xacid_1,
+  Xacid_2,
+  Xacid_3,
+  Xacid_4,
+  Xacid_5,
+  Xacid_6,
+  Xacid_7,
+  Xacid_8,
+  Xdoor_1,
+  Xdoor_2,
+  Xdoor_3,
+  Xdoor_4,
+  Xdoor_5,
+  Xdoor_6,
+  Xdoor_7,
+  Xdoor_8,
+  Xplant,
+  Yplant,
+  Xfake_door_1,
+  Xfake_door_2,
+  Xfake_door_3,
+  Xfake_door_4,
+  Xfake_door_5,
+  Xfake_door_6,
+  Xfake_door_7,
+  Xfake_door_8,
+  Xsteel_1,
+  Xsteel_2,
+  Xsteel_3,
+  Xsteel_4,
+  TILE_MAX,                    /* up till here are indestructable */
+
+  Xbug_n, Xboom_bug,
+  Xbug_e, Xboom_bug,
+  Xbug_s, Xboom_bug,
+  Xbug_w, Xboom_bug,
+  Xbug_gon, Xboom_bug,
+  Xbug_goe, Xboom_bug,
+  Xbug_gos, Xboom_bug,
+  Xbug_gow, Xboom_bug,
+  Xbomb, Xboom_bomb,
+  Xbomb_pause, Xboom_bomb,
+  Xbomb_fall, Xboom_bomb,
+  TILE_MAX,                    /* up till here are special explosions */
+
+  Xandroid, Xboom_android,
+  Xandroid_1_n, Xboom_android,
+  Xandroid_2_n, Xboom_android,
+  Xandroid_1_e, Xboom_android,
+  Xandroid_2_e, Xboom_android,
+  Xandroid_1_s, Xboom_android,
+  Xandroid_2_s, Xboom_android,
+  Xandroid_1_w, Xboom_android,
+  Xandroid_2_w, Xboom_android,
+  TILE_MAX                     /* up until here are dynamite explosions */
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* map the graphics file to internal tiles and animations
+ *
+ * one graphics icon maps to many tiles and animations
+ */
+
+int obj_map[] =
+{
+  /* special */
+
+  Ystone_sB, 7,
+  Xsand_stonein_4, 7,
+  -1,
+  Xsand_stonein_4, 5,
+  Xsand_stonein_4, 6,
+  -1,
+  Ystone_sB, 6,
+  Xsand_stonein_4, 3,
+  Xsand_stonein_4, 4,
+  -1,
+  Xsand_stonein_4, 1,
+  Xsand_stonein_4, 2,
+  -1,
+  Ystone_sB, 5,
+  Xsand_stonein_3, 7,
+  Xsand_stonein_4, 0,
+  -1,
+  Xsand_stonein_3, 5,
+  Xsand_stonein_3, 6,
+  -1,
+  Ystone_sB, 4,
+  Xsand_stonein_3, 3,
+  Xsand_stonein_3, 4,
+  -1,
+  Xsand_stonein_3, 1,
+  Xsand_stonein_3, 2,
+  -1,
+  Ystone_sB, 3,
+  Xsand_stonein_2, 7,
+  Xsand_stonein_3, 0,
+  -1,
+  Xsand_stonein_2, 5,
+  Xsand_stonein_2, 6,
+  -1,
+  Ystone_sB, 2,
+  Xsand_stonein_2, 3,
+  Xsand_stonein_2, 4,
+  -1,
+  Xsand_stonein_2, 1,
+  Xsand_stonein_2, 2,
+  -1,
+  Ystone_sB, 1,
+  Xsand_stonein_1, 7,
+  Xsand_stonein_2, 0,
+  -1,
+  Xsand_stonein_1, 5,
+  Xsand_stonein_1, 6,
+  -1,
+  Ystone_sB, 0,
+  Xsand_stonein_1, 3,
+  Xsand_stonein_1, 4,
+  -1,
+  Xsand_stonein_1, 1,
+  Xsand_stonein_1, 2,
+  -1,
+  Xstone, 0,
+  Xstone, 1,
+  Xstone, 2,
+  Xstone, 3,
+  Xstone, 4,
+  Xstone, 5,
+  Xstone, 6,
+  Xstone, 7,
+  Xstone_pause, 0,
+  Xstone_pause, 1,
+  Xstone_pause, 2,
+  Xstone_pause, 3,
+  Xstone_pause, 4,
+  Xstone_pause, 5,
+  Xstone_pause, 6,
+  Xstone_pause, 7,
+  Xstone_fall, 0,
+  Xstone_fall, 1,
+  Xstone_fall, 2,
+  Xstone_fall, 3,
+  Xstone_fall, 4,
+  Xstone_fall, 5,
+  Xstone_fall, 6,
+  Xstone_fall, 7,
+
+#ifdef BAD_ROLL
+  Xstone_force_e, 0,
+  Xstone_force_e, 1,
+  Xstone_force_e, 2,
+  Xstone_force_e, 3,
+  Xstone_force_e, 4,
+  Xstone_force_e, 5,
+  Xstone_force_e, 6,
+  Xstone_force_e, 7,
+  Xstone_force_w, 0,
+  Xstone_force_w, 1,
+  Xstone_force_w, 2,
+  Xstone_force_w, 3,
+  Xstone_force_w, 4,
+  Xstone_force_w, 5,
+  Xstone_force_w, 6,
+  Xstone_force_w, 7,
+#endif
+
+  Ystone_s, 7,
+  Xsand_stoneout_2, 7,
+  Xsand_stonein_1, 0,
+  Ystone_e, 7,
+  Ystone_w, 7,
+  Ydiamond_stone, 7,
+  -1,
+  -1,
+  Ystone_s, 6,
+  Xsand_stoneout_2, 6,
+  -1,
+  -1,
+  Ystone_s, 5,
+  Xsand_stoneout_2, 5,
+  -1,
+  -1,
+  Ystone_s, 4,
+  Xsand_stoneout_2, 4,
+  -1,
+  Xsand_stoneout_2, 3,
+  -1,
+  Ystone_s, 3,
+  Xsand_stoneout_2, 2,
+  -1,
+  Xsand_stoneout_2, 1,
+  -1,
+  Ystone_s, 2,
+  Xsand_stoneout_2, 0,
+  -1,
+  Xsand_stoneout_1, 7,
+  Xsand_stoneout_1, 6,
+  -1,
+  Ystone_s, 1,
+  Xsand_stoneout_1, 5,
+  -1,
+  Xsand_stoneout_1, 4,
+  Xsand_stoneout_1, 3,
+  -1,
+  Ystone_s, 0,
+  Xsand_stoneout_1, 2,
+  -1,
+  Xsand_stoneout_1, 1,
+  Xsand_stoneout_1, 0,
+  -1,
+
+#if 0
+  /* use normal "Xblank" instead of explicit x==0, y==2 empty space graphic */
+  Ynut_sB, 7,
+#endif
+
+  -1,
+  -1,
+  Ynut_sB, 6,
+  -1,
+  -1,
+  Ynut_sB, 5,
+  -1,
+  -1,
+  Ynut_sB, 4,
+  -1,
+  -1,
+  Ynut_sB, 3,
+  -1,
+  -1,
+  Ynut_sB, 2,
+  -1,
+  -1,
+  Ynut_sB, 1,
+  -1,
+  -1,
+  Ynut_sB, 0,
+  -1,
+  -1,
+  Ynut_s, 7,
+  Ynut_e, 7,
+  Ynut_w, 7,
+  Xnut, 0,
+  Xnut, 1,
+  Xnut, 2,
+  Xnut, 3,
+  Xnut, 4,
+  Xnut, 5,
+  Xnut, 6,
+  Xnut, 7,
+  Xnut_pause, 0,
+  Xnut_pause, 1,
+  Xnut_pause, 2,
+  Xnut_pause, 3,
+  Xnut_pause, 4,
+  Xnut_pause, 5,
+  Xnut_pause, 6,
+  Xnut_pause, 7,
+  Xnut_fall, 0,
+  Xnut_fall, 1,
+  Xnut_fall, 2,
+  Xnut_fall, 3,
+  Xnut_fall, 4,
+  Xnut_fall, 5,
+  Xnut_fall, 6,
+  Xnut_fall, 7,
+
+#ifdef BAD_ROLL
+  Xnut_force_e, 0,
+  Xnut_force_e, 1,
+  Xnut_force_e, 2,
+  Xnut_force_e, 3,
+  Xnut_force_e, 4,
+  Xnut_force_e, 5,
+  Xnut_force_e, 6,
+  Xnut_force_e, 7,
+  Xnut_force_w, 0,
+  Xnut_force_w, 1,
+  Xnut_force_w, 2,
+  Xnut_force_w, 3,
+  Xnut_force_w, 4,
+  Xnut_force_w, 5,
+  Xnut_force_w, 6,
+  Xnut_force_w, 7,
+#endif
+
+  -1,
+  -1,
+  Ynut_s, 6,
+  -1,
+  -1,
+  Ynut_s, 5,
+  -1,
+  -1,
+  Ynut_s, 4,
+  -1,
+  -1,
+  Ynut_s, 3,
+  -1,
+  -1,
+  Ynut_s, 2,
+  -1,
+  -1,
+  Ynut_s, 1,
+  -1,
+  -1,
+  Ynut_s, 0,
+  -1,
+  -1,
+
+/* normal */
+
+  Xblank, 0,
+  Xblank, 1,
+  Xblank, 2,
+  Xblank, 3,
+  Xblank, 4,
+  Xblank, 5,
+  Xblank, 6,
+  Xblank, 7,
+  Xfake_blank, 0,
+  Xfake_blank, 1,
+  Xfake_blank, 2,
+  Xfake_blank, 3,
+  Xfake_blank, 4,
+  Xfake_blank, 5,
+  Xfake_blank, 6,
+  Xfake_blank, 7,
+  Xdripper, 0,
+  Xdripper, 1,
+  Xdripper, 2,
+  Xdripper, 3,
+  Xdripper, 4,
+  Xdripper, 5,
+  Xdripper, 6,
+  Xdripper, 7,
+  Zplayer, 0,
+  Zplayer, 1,
+  Zplayer, 2,
+  Zplayer, 3,
+  Zplayer, 4,
+  Zplayer, 5,
+  Zplayer, 6,
+  Zplayer, 7,
+  Ydynamite_eat, 3,
+  Ydynamite_eat, 4,
+  Ydynamite_eat, 5,
+  Ydynamite_eat, 6,
+  Ydynamite_eat, 7,
+  -1,
+  -1,
+  -1,
+  -1,
+  -1,
+
+  Ystone_eB, 6,
+  Ystone_w, 0,
+  -1,
+  Ystone_e, 6,
+  Ystone_wB, 0,
+  -1,
+  Ystone_eB, 5,
+  Ystone_w, 1,
+  -1,
+  Ystone_e, 5,
+  Ystone_wB, 1,
+  -1,
+  Ystone_eB, 4,
+  Ystone_w, 2,
+  -1,
+  Ystone_e, 4,
+  Ystone_wB, 2,
+  -1,
+  Ystone_eB, 3,
+  Ystone_w, 3,
+  -1,
+  Ystone_e, 3,
+  Ystone_wB, 3,
+  -1,
+  Ystone_eB, 2,
+  Ystone_w, 4,
+  -1,
+  Ystone_e, 2,
+  Ystone_wB, 4,
+  -1,
+  Ystone_eB, 1,
+  Ystone_w, 5,
+  -1,
+  Ystone_e, 1,
+  Ystone_wB, 5,
+  -1,
+  Ystone_eB, 0,
+  Ystone_w, 6,
+  -1,
+  Ystone_e, 0,
+  Ystone_wB, 6,
+  -1,
+
+  Ynut_eB, 6,
+  Ynut_w, 0,
+  -1,
+  Ynut_e, 6,
+  Ynut_wB, 0,
+  -1,
+  Ynut_eB, 5,
+  Ynut_w, 1,
+  -1,
+  Ynut_e, 5,
+  Ynut_wB, 1,
+  -1,
+  Ynut_eB, 4,
+  Ynut_w, 2,
+  -1,
+  Ynut_e, 4,
+  Ynut_wB, 2,
+  -1,
+  Ynut_eB, 3,
+  Ynut_w, 3,
+  -1,
+  Ynut_e, 3,
+  Ynut_wB, 3,
+  -1,
+  Ynut_eB, 2,
+  Ynut_w, 4,
+  -1,
+  Ynut_e, 2,
+  Ynut_wB, 4,
+  -1,
+  Ynut_eB, 1,
+  Ynut_w, 5,
+  -1,
+  Ynut_e, 1,
+  Ynut_wB, 5,
+  -1,
+  Ynut_eB, 0,
+  Ynut_w, 6,
+  -1,
+  Ynut_e, 0,
+  Ynut_wB, 6,
+  -1,
+
+  Ybug_w_n, 7,
+  Ybug_e_n, 7,
+  Ybug_n, 7,
+  Xbug_n, 0,
+  Xbug_n, 1,
+  Xbug_n, 2,
+  Xbug_n, 3,
+  Xbug_n, 4,
+  Xbug_n, 5,
+  Xbug_n, 6,
+  Xbug_n, 7,
+  Xbug_gon, 0,
+  Xbug_gon, 1,
+  Xbug_gon, 2,
+  Xbug_gon, 3,
+  Xbug_gon, 4,
+  Xbug_gon, 5,
+  Xbug_gon, 6,
+  Xbug_gon, 7,
+  -1,
+  Ybug_n_e, 7,
+  Ybug_s_e, 7,
+  Ybug_e, 7,
+  Xbug_e, 0,
+  Xbug_e, 1,
+  Xbug_e, 2,
+  Xbug_e, 3,
+  Xbug_e, 4,
+  Xbug_e, 5,
+  Xbug_e, 6,
+  Xbug_e, 7,
+  Xbug_goe, 0,
+  Xbug_goe, 1,
+  Xbug_goe, 2,
+  Xbug_goe, 3,
+  Xbug_goe, 4,
+  Xbug_goe, 5,
+  Xbug_goe, 6,
+  Xbug_goe, 7,
+  -1,
+  Ybug_e_s, 7,
+  Ybug_w_s, 7,
+  Ybug_s, 7,
+  Xbug_s, 0,
+  Xbug_s, 1,
+  Xbug_s, 2,
+  Xbug_s, 3,
+  Xbug_s, 4,
+  Xbug_s, 5,
+  Xbug_s, 6,
+  Xbug_s, 7,
+  Xbug_gos, 0,
+  Xbug_gos, 1,
+  Xbug_gos, 2,
+  Xbug_gos, 3,
+  Xbug_gos, 4,
+  Xbug_gos, 5,
+  Xbug_gos, 6,
+  Xbug_gos, 7,
+  -1,
+  Ybug_n_w, 7,
+  Ybug_s_w, 7,
+  Ybug_w, 7,
+  Xbug_w, 0,
+  Xbug_w, 1,
+  Xbug_w, 2,
+  Xbug_w, 3,
+  Xbug_w, 4,
+  Xbug_w, 5,
+  Xbug_w, 6,
+  Xbug_w, 7,
+  Xbug_gow, 0,
+  Xbug_gow, 1,
+  Xbug_gow, 2,
+  Xbug_gow, 3,
+  Xbug_gow, 4,
+  Xbug_gow, 5,
+  Xbug_gow, 6,
+  Xbug_gow, 7,
+  -1,
+  Ybug_n, 0,
+  -1,
+  Ybug_nB, 0,
+  -1,
+  Ybug_n, 1,
+  -1,
+  Ybug_nB, 1,
+  -1,
+  Ybug_n, 2,
+  -1,
+  Ybug_nB, 2,
+  -1,
+  Ybug_n, 3,
+  -1,
+  Ybug_nB, 3,
+  -1,
+  Ybug_n, 4,
+  -1,
+  Ybug_nB, 4,
+  -1,
+  Ybug_n, 5,
+  -1,
+  Ybug_nB, 5,
+  -1,
+  Ybug_n, 6,
+  -1,
+  Ybug_nB, 6,
+  -1,
+  Ybug_eB, 6,
+  -1,
+  Ybug_e, 6,
+  -1,
+  Ybug_eB, 5,
+  -1,
+  Ybug_e, 5,
+  -1,
+  Ybug_eB, 4,
+  -1,
+  Ybug_e, 4,
+  -1,
+  Ybug_eB, 3,
+  -1,
+  Ybug_e, 3,
+  -1,
+  Ybug_eB, 2,
+  -1,
+  Ybug_e, 2,
+  -1,
+  Ybug_eB, 1,
+  -1,
+  Ybug_e, 1,
+  -1,
+  Ybug_eB, 0,
+  -1,
+  Ybug_e, 0,
+  -1,
+  Ybug_sB, 6,
+  -1,
+  Ybug_s, 6,
+  -1,
+  Ybug_sB, 5,
+  -1,
+  Ybug_s, 5,
+  -1,
+  Ybug_sB, 4,
+  -1,
+  Ybug_s, 4,
+  -1,
+  Ybug_sB, 3,
+  -1,
+  Ybug_s, 3,
+  -1,
+  Ybug_sB, 2,
+  -1,
+  Ybug_s, 2,
+  -1,
+  Ybug_sB, 1,
+  -1,
+  Ybug_s, 1,
+  -1,
+  Ybug_sB, 0,
+  -1,
+  Ybug_s, 0,
+  -1,
+  Ybug_w, 0,
+  -1,
+  Ybug_wB, 0,
+  -1,
+  Ybug_w, 1,
+  -1,
+  Ybug_wB, 1,
+  -1,
+  Ybug_w, 2,
+  -1,
+  Ybug_wB, 2,
+  -1,
+  Ybug_w, 3,
+  -1,
+  Ybug_wB, 3,
+  -1,
+  Ybug_w, 4,
+  -1,
+  Ybug_wB, 4,
+  -1,
+  Ybug_w, 5,
+  -1,
+  Ybug_wB, 5,
+  -1,
+  Ybug_w, 6,
+  -1,
+  Ybug_wB, 6,
+  -1,
+  Ybug_n_e, 0,
+  Ybug_e_n, 6,
+  -1,
+  Ybug_n_e, 1,
+  Ybug_e_n, 5,
+  -1,
+  Ybug_n_e, 2,
+  Ybug_e_n, 4,
+  -1,
+  Ybug_n_e, 3,
+  Ybug_e_n, 3,
+  -1,
+  Ybug_n_e, 4,
+  Ybug_e_n, 2,
+  -1,
+  Ybug_n_e, 5,
+  Ybug_e_n, 1,
+  -1,
+  Ybug_n_e, 6,
+  Ybug_e_n, 0,
+  -1,
+  Ybug_e_s, 0,
+  Ybug_s_e, 6,
+  -1,
+  Ybug_e_s, 1,
+  Ybug_s_e, 5,
+  -1,
+  Ybug_e_s, 2,
+  Ybug_s_e, 4,
+  -1,
+  Ybug_e_s, 3,
+  Ybug_s_e, 3,
+  -1,
+  Ybug_e_s, 4,
+  Ybug_s_e, 2,
+  -1,
+  Ybug_e_s, 5,
+  Ybug_s_e, 1,
+  -1,
+  Ybug_e_s, 6,
+  Ybug_s_e, 0,
+  -1,
+  Ybug_s_w, 0,
+  Ybug_w_s, 6,
+  -1,
+  Ybug_s_w, 1,
+  Ybug_w_s, 5,
+  -1,
+  Ybug_s_w, 2,
+  Ybug_w_s, 4,
+  -1,
+  Ybug_s_w, 3,
+  Ybug_w_s, 3,
+  -1,
+  Ybug_s_w, 4,
+  Ybug_w_s, 2,
+  -1,
+  Ybug_s_w, 5,
+  Ybug_w_s, 1,
+  -1,
+  Ybug_s_w, 6,
+  Ybug_w_s, 0,
+  -1,
+  Ybug_n_w, 6,
+  Ybug_w_n, 0,
+  -1,
+  Ybug_n_w, 5,
+  Ybug_w_n, 1,
+  -1,
+  Ybug_n_w, 4,
+  Ybug_w_n, 2,
+  -1,
+  Ybug_n_w, 3,
+  Ybug_w_n, 3,
+  -1,
+  Ybug_n_w, 2,
+  Ybug_w_n, 4,
+  -1,
+  Ybug_n_w, 1,
+  Ybug_w_n, 5,
+  -1,
+  Ybug_n_w, 0,
+  Ybug_w_n, 6,
+  -1,
+  Ybug_stone, 0,
+  -1,
+  Ybug_stone, 1,
+  -1,
+  Ybug_stone, 2,
+  -1,
+  Ybug_stone, 3,
+  -1,
+  Ybug_stone, 4,
+  -1,
+  Ybug_stone, 5,
+  -1,
+  Ybug_stone, 6,
+  -1,
+  Ybug_spring, 0,
+  -1,
+  Ybug_spring, 1,
+  -1,
+  Ybug_spring, 2,
+  -1,
+  Ybug_spring, 3,
+  -1,
+  Ybug_spring, 4,
+  -1,
+  Ybug_spring, 5,
+  -1,
+  Ybug_spring, 6,
+  -1,
+
+  Ytank_w_n, 7,
+  Ytank_e_n, 7,
+  Ytank_n, 7,
+  Xtank_n, 0,
+  Xtank_n, 1,
+  Xtank_n, 2,
+  Xtank_n, 3,
+  Xtank_n, 4,
+  Xtank_n, 5,
+  Xtank_n, 6,
+  Xtank_n, 7,
+  Xtank_gon, 0,
+  Xtank_gon, 1,
+  Xtank_gon, 2,
+  Xtank_gon, 3,
+  Xtank_gon, 4,
+  Xtank_gon, 5,
+  Xtank_gon, 6,
+  Xtank_gon, 7,
+  -1,
+  Ytank_n_e, 7,
+  Ytank_s_e, 7,
+  Ytank_e, 7,
+  Xtank_e, 0,
+  Xtank_e, 1,
+  Xtank_e, 2,
+  Xtank_e, 3,
+  Xtank_e, 4,
+  Xtank_e, 5,
+  Xtank_e, 6,
+  Xtank_e, 7,
+  Xtank_goe, 0,
+  Xtank_goe, 1,
+  Xtank_goe, 2,
+  Xtank_goe, 3,
+  Xtank_goe, 4,
+  Xtank_goe, 5,
+  Xtank_goe, 6,
+  Xtank_goe, 7,
+  -1,
+  Ytank_e_s, 7,
+  Ytank_w_s, 7,
+  Ytank_s, 7,
+  Xtank_s, 0,
+  Xtank_s, 1,
+  Xtank_s, 2,
+  Xtank_s, 3,
+  Xtank_s, 4,
+  Xtank_s, 5,
+  Xtank_s, 6,
+  Xtank_s, 7,
+  Xtank_gos, 0,
+  Xtank_gos, 1,
+  Xtank_gos, 2,
+  Xtank_gos, 3,
+  Xtank_gos, 4,
+  Xtank_gos, 5,
+  Xtank_gos, 6,
+  Xtank_gos, 7,
+  -1,
+  Ytank_n_w, 7,
+  Ytank_s_w, 7,
+  Ytank_w, 7,
+  Xtank_w, 0,
+  Xtank_w, 1,
+  Xtank_w, 2,
+  Xtank_w, 3,
+  Xtank_w, 4,
+  Xtank_w, 5,
+  Xtank_w, 6,
+  Xtank_w, 7,
+  Xtank_gow, 0,
+  Xtank_gow, 1,
+  Xtank_gow, 2,
+  Xtank_gow, 3,
+  Xtank_gow, 4,
+  Xtank_gow, 5,
+  Xtank_gow, 6,
+  Xtank_gow, 7,
+  -1,
+  Ytank_n, 0,
+  -1,
+  Ytank_nB, 0,
+  -1,
+  Ytank_n, 1,
+  -1,
+  Ytank_nB, 1,
+  -1,
+  Ytank_n, 2,
+  -1,
+  Ytank_nB, 2,
+  -1,
+  Ytank_n, 3,
+  -1,
+  Ytank_nB, 3,
+  -1,
+  Ytank_n, 4,
+  -1,
+  Ytank_nB, 4,
+  -1,
+  Ytank_n, 5,
+  -1,
+  Ytank_nB, 5,
+  -1,
+  Ytank_n, 6,
+  -1,
+  Ytank_nB, 6,
+  -1,
+  Ytank_eB, 6,
+  -1,
+  Ytank_e, 6,
+  -1,
+  Ytank_eB, 5,
+  -1,
+  Ytank_e, 5,
+  -1,
+  Ytank_eB, 4,
+  -1,
+  Ytank_e, 4,
+  -1,
+  Ytank_eB, 3,
+  -1,
+  Ytank_e, 3,
+  -1,
+  Ytank_eB, 2,
+  -1,
+  Ytank_e, 2,
+  -1,
+  Ytank_eB, 1,
+  -1,
+  Ytank_e, 1,
+  -1,
+  Ytank_eB, 0,
+  -1,
+  Ytank_e, 0,
+  -1,
+  Ytank_sB, 6,
+  -1,
+  Ytank_s, 6,
+  -1,
+  Ytank_sB, 5,
+  -1,
+  Ytank_s, 5,
+  -1,
+  Ytank_sB, 4,
+  -1,
+  Ytank_s, 4,
+  -1,
+  Ytank_sB, 3,
+  -1,
+  Ytank_s, 3,
+  -1,
+  Ytank_sB, 2,
+  -1,
+  Ytank_s, 2,
+  -1,
+  Ytank_sB, 1,
+  -1,
+  Ytank_s, 1,
+  -1,
+  Ytank_sB, 0,
+  -1,
+  Ytank_s, 0,
+  -1,
+  Ytank_w, 0,
+  -1,
+  Ytank_wB, 0,
+  -1,
+  Ytank_w, 1,
+  -1,
+  Ytank_wB, 1,
+  -1,
+  Ytank_w, 2,
+  -1,
+  Ytank_wB, 2,
+  -1,
+  Ytank_w, 3,
+  -1,
+  Ytank_wB, 3,
+  -1,
+  Ytank_w, 4,
+  -1,
+  Ytank_wB, 4,
+  -1,
+  Ytank_w, 5,
+  -1,
+  Ytank_wB, 5,
+  -1,
+  Ytank_w, 6,
+  -1,
+  Ytank_wB, 6,
+  -1,
+  Ytank_n_e, 0,
+  Ytank_e_n, 6,
+  -1,
+  Ytank_n_e, 1,
+  Ytank_e_n, 5,
+  -1,
+  Ytank_n_e, 2,
+  Ytank_e_n, 4,
+  -1,
+  Ytank_n_e, 3,
+  Ytank_e_n, 3,
+  -1,
+  Ytank_n_e, 4,
+  Ytank_e_n, 2,
+  -1,
+  Ytank_n_e, 5,
+  Ytank_e_n, 1,
+  -1,
+  Ytank_n_e, 6,
+  Ytank_e_n, 0,
+  -1,
+  Ytank_e_s, 0,
+  Ytank_s_e, 6,
+  -1,
+  Ytank_e_s, 1,
+  Ytank_s_e, 5,
+  -1,
+  Ytank_e_s, 2,
+  Ytank_s_e, 4,
+  -1,
+  Ytank_e_s, 3,
+  Ytank_s_e, 3,
+  -1,
+  Ytank_e_s, 4,
+  Ytank_s_e, 2,
+  -1,
+  Ytank_e_s, 5,
+  Ytank_s_e, 1,
+  -1,
+  Ytank_e_s, 6,
+  Ytank_s_e, 0,
+  -1,
+  Ytank_s_w, 0,
+  Ytank_w_s, 6,
+  -1,
+  Ytank_s_w, 1,
+  Ytank_w_s, 5,
+  -1,
+  Ytank_s_w, 2,
+  Ytank_w_s, 4,
+  -1,
+  Ytank_s_w, 3,
+  Ytank_w_s, 3,
+  -1,
+  Ytank_s_w, 4,
+  Ytank_w_s, 2,
+  -1,
+  Ytank_s_w, 5,
+  Ytank_w_s, 1,
+  -1,
+  Ytank_s_w, 6,
+  Ytank_w_s, 0,
+  -1,
+  Ytank_n_w, 6,
+  Ytank_w_n, 0,
+  -1,
+  Ytank_n_w, 5,
+  Ytank_w_n, 1,
+  -1,
+  Ytank_n_w, 4,
+  Ytank_w_n, 2,
+  -1,
+  Ytank_n_w, 3,
+  Ytank_w_n, 3,
+  -1,
+  Ytank_n_w, 2,
+  Ytank_w_n, 4,
+  -1,
+  Ytank_n_w, 1,
+  Ytank_w_n, 5,
+  -1,
+  Ytank_n_w, 0,
+  Ytank_w_n, 6,
+  -1,
+  Ytank_stone, 0,
+  -1,
+  Ytank_stone, 1,
+  -1,
+  Ytank_stone, 2,
+  -1,
+  Ytank_stone, 3,
+  -1,
+  Ytank_stone, 4,
+  -1,
+  Ytank_stone, 5,
+  -1,
+  Ytank_stone, 6,
+  -1,
+  Ytank_spring, 0,
+  -1,
+  Ytank_spring, 1,
+  -1,
+  Ytank_spring, 2,
+  -1,
+  Ytank_spring, 3,
+  -1,
+  Ytank_spring, 4,
+  -1,
+  Ytank_spring, 5,
+  -1,
+  Ytank_spring, 6,
+  -1,
+
+  Yandroid_n, 7,
+  Yandroid_ne, 7,
+  Yandroid_e, 7,
+  Yandroid_se, 7,
+  Yandroid_s, 7,
+  Yandroid_sw, 7,
+  Yandroid_w, 7,
+  Yandroid_nw, 7,
+  Xandroid, 7,
+  Xandroid_1_n, 7,
+  Xandroid_2_n, 7,
+  Xandroid_1_e, 7,
+  Xandroid_2_e, 7,
+  Xandroid_1_w, 7,
+  Xandroid_2_w, 7,
+  Xandroid_1_s, 7,
+  Xandroid_2_s, 7,
+  -1,
+  Xandroid, 0,
+  Xandroid_1_n, 0,
+  Xandroid_2_n, 0,
+  Xandroid_1_e, 0,
+  Xandroid_2_e, 0,
+  Xandroid_1_w, 0,
+  Xandroid_2_w, 0,
+  Xandroid_1_s, 0,
+  Xandroid_2_s, 0,
+  -1,
+  Xandroid, 1,
+  Xandroid_1_n, 1,
+  Xandroid_2_n, 1,
+  Xandroid_1_e, 1,
+  Xandroid_2_e, 1,
+  Xandroid_1_w, 1,
+  Xandroid_2_w, 1,
+  Xandroid_1_s, 1,
+  Xandroid_2_s, 1,
+  -1,
+  Xandroid, 2,
+  Xandroid_1_n, 2,
+  Xandroid_2_n, 2,
+  Xandroid_1_e, 2,
+  Xandroid_2_e, 2,
+  Xandroid_1_w, 2,
+  Xandroid_2_w, 2,
+  Xandroid_1_s, 2,
+  Xandroid_2_s, 2,
+  -1,
+  Xandroid, 3,
+  Xandroid_1_n, 3,
+  Xandroid_2_n, 3,
+  Xandroid_1_e, 3,
+  Xandroid_2_e, 3,
+  Xandroid_1_w, 3,
+  Xandroid_2_w, 3,
+  Xandroid_1_s, 3,
+  Xandroid_2_s, 3,
+  -1,
+  Xandroid, 4,
+  Xandroid_1_n, 4,
+  Xandroid_2_n, 4,
+  Xandroid_1_e, 4,
+  Xandroid_2_e, 4,
+  Xandroid_1_w, 4,
+  Xandroid_2_w, 4,
+  Xandroid_1_s, 4,
+  Xandroid_2_s, 4,
+  -1,
+  Xandroid, 5,
+  Xandroid_1_n, 5,
+  Xandroid_2_n, 5,
+  Xandroid_1_e, 5,
+  Xandroid_2_e, 5,
+  Xandroid_1_w, 5,
+  Xandroid_2_w, 5,
+  Xandroid_1_s, 5,
+  Xandroid_2_s, 5,
+  -1,
+  Xandroid, 6,
+  Xandroid_1_n, 6,
+  Xandroid_2_n, 6,
+  Xandroid_1_e, 6,
+  Xandroid_2_e, 6,
+  Xandroid_1_w, 6,
+  Xandroid_2_w, 6,
+  Xandroid_1_s, 6,
+  Xandroid_2_s, 6,
+  -1,
+  Yandroid_n, 0,
+  Yandroid_sB, 6,
+  -1,
+  Yandroid_nB, 0,
+  Yandroid_s, 6,
+  -1,
+  Yandroid_n, 1,
+  Yandroid_sB, 5,
+  -1,
+  Yandroid_nB, 1,
+  Yandroid_s, 5,
+  -1,
+  Yandroid_n, 2,
+  Yandroid_sB, 4,
+  Xboom_android, 0,
+  -1,
+  Yandroid_nB, 2,
+  Yandroid_s, 4,
+  Xboom_android, 1,
+  -1,
+  Yandroid_n, 3,
+  Yandroid_sB, 3,
+  Xboom_android, 2,
+  -1,
+  Yandroid_nB, 3,
+  Yandroid_s, 3,
+  Xboom_android, 3,
+  -1,
+  Yandroid_n, 4,
+  Yandroid_sB, 2,
+  Xboom_android, 4,
+  -1,
+  Yandroid_nB, 4,
+  Yandroid_s, 2,
+  Xboom_android, 5,
+  -1,
+  Yandroid_n, 5,
+  Yandroid_sB, 1,
+  Xboom_android, 6,
+  -1,
+  Yandroid_nB, 5,
+  Yandroid_s, 1,
+  -1,
+  Yandroid_n, 6,
+  Yandroid_sB, 0,
+  -1,
+  Yandroid_nB, 6,
+  Yandroid_s, 0,
+  -1,
+  Yandroid_eB, 6,
+  Yandroid_w, 0,
+  -1,
+  Yandroid_e, 6,
+  Yandroid_wB, 0,
+  -1,
+  Yandroid_eB, 5,
+  Yandroid_w, 1,
+  -1,
+  Yandroid_e, 5,
+  Yandroid_wB, 1,
+  -1,
+  Yandroid_eB, 4,
+  Yandroid_w, 2,
+  -1,
+  Yandroid_e, 4,
+  Yandroid_wB, 2,
+  -1,
+  Yandroid_eB, 3,
+  Yandroid_w, 3,
+  -1,
+  Yandroid_e, 3,
+  Yandroid_wB, 3,
+  -1,
+  Yandroid_eB, 2,
+  Yandroid_w, 4,
+  -1,
+  Yandroid_e, 2,
+  Yandroid_wB, 4,
+  -1,
+  Yandroid_eB, 1,
+  Yandroid_w, 5,
+  -1,
+  Yandroid_e, 1,
+  Yandroid_wB, 5,
+  -1,
+  Yandroid_eB, 0,
+  Yandroid_w, 6,
+  -1,
+  Yandroid_e, 0,
+  Yandroid_wB, 6,
+  -1,
+  Yandroid_neB, 6,
+  Yandroid_sw, 0,
+  -1,
+  Yandroid_ne, 6,
+  Yandroid_swB, 0,
+  -1,
+  Yandroid_neB, 5,
+  Yandroid_sw, 1,
+  -1,
+  Yandroid_ne, 5,
+  Yandroid_swB, 1,
+  -1,
+  Yandroid_neB, 4,
+  Yandroid_sw, 2,
+  -1,
+  Yandroid_ne, 4,
+  Yandroid_swB, 2,
+  -1,
+  Yandroid_neB, 3,
+  Yandroid_sw, 3,
+  -1,
+  Yandroid_ne, 3,
+  Yandroid_swB, 3,
+  -1,
+  Yandroid_neB, 2,
+  Yandroid_sw, 4,
+  -1,
+  Yandroid_ne, 2,
+  Yandroid_swB, 4,
+  -1,
+  Yandroid_neB, 1,
+  Yandroid_sw, 5,
+  -1,
+  Yandroid_ne, 1,
+  Yandroid_swB, 5,
+  -1,
+  Yandroid_neB, 0,
+  Yandroid_sw, 6,
+  -1,
+  Yandroid_ne, 0,
+  Yandroid_swB, 6,
+  -1,
+  Yandroid_nw, 0,
+  Yandroid_seB, 6,
+  -1,
+  Yandroid_nwB, 0,
+  Yandroid_se, 6,
+  -1,
+  Yandroid_nw, 1,
+  Yandroid_seB, 5,
+  -1,
+  Yandroid_nwB, 1,
+  Yandroid_se, 5,
+  -1,
+  Yandroid_nw, 2,
+  Yandroid_seB, 4,
+  -1,
+  Yandroid_nwB, 2,
+  Yandroid_se, 4,
+  -1,
+  Yandroid_nw, 3,
+  Yandroid_seB, 3,
+  -1,
+  Yandroid_nwB, 3,
+  Yandroid_se, 3,
+  -1,
+  Yandroid_nw, 4,
+  Yandroid_seB, 2,
+  -1,
+  Yandroid_nwB, 4,
+  Yandroid_se, 2,
+  -1,
+  Yandroid_nw, 5,
+  Yandroid_seB, 1,
+  -1,
+  Yandroid_nwB, 5,
+  Yandroid_se, 1,
+  -1,
+  Yandroid_nw, 6,
+  Yandroid_seB, 0,
+  -1,
+  Yandroid_nwB, 6,
+  Yandroid_se, 0,
+  -1,
+
+  Yspring_e, 7,
+  Yspring_w, 7,
+  Yspring_kill_e, 7,
+  Yspring_kill_w, 7,
+  Yspring_s, 7,
+  Xspring, 0,
+  Xspring, 1,
+  Xspring, 2,
+  Xspring, 3,
+  Xspring, 4,
+  Xspring, 5,
+  Xspring, 6,
+  Xspring, 7,
+  Xspring_pause, 0,
+  Xspring_pause, 1,
+  Xspring_pause, 2,
+  Xspring_pause, 3,
+  Xspring_pause, 4,
+  Xspring_pause, 5,
+  Xspring_pause, 6,
+  Xspring_pause, 7,
+  Xspring_e, 0,
+  Xspring_e, 1,
+  Xspring_e, 2,
+  Xspring_e, 3,
+  Xspring_e, 4,
+  Xspring_e, 5,
+  Xspring_e, 6,
+  Xspring_e, 7,
+  Xspring_w, 0,
+  Xspring_w, 1,
+  Xspring_w, 2,
+  Xspring_w, 3,
+  Xspring_w, 4,
+  Xspring_w, 5,
+  Xspring_w, 6,
+  Xspring_w, 7,
+  Xspring_fall, 0,
+  Xspring_fall, 1,
+  Xspring_fall, 2,
+  Xspring_fall, 3,
+  Xspring_fall, 4,
+  Xspring_fall, 5,
+  Xspring_fall, 6,
+  Xspring_fall, 7,
+
+#ifdef BAD_ROLL
+  Xspring_force_e, 0,
+  Xspring_force_e, 1,
+  Xspring_force_e, 2,
+  Xspring_force_e, 3,
+  Xspring_force_e, 4,
+  Xspring_force_e, 5,
+  Xspring_force_e, 6,
+  Xspring_force_e, 7,
+  Xspring_force_w, 0,
+  Xspring_force_w, 1,
+  Xspring_force_w, 2,
+  Xspring_force_w, 3,
+  Xspring_force_w, 4,
+  Xspring_force_w, 5,
+  Xspring_force_w, 6,
+  Xspring_force_w, 7,
+#endif
+
+  -1,
+  Yspring_sB, 6,
+  -1,
+  Yspring_s, 6,
+  -1,
+  Yspring_sB, 5,
+  -1,
+  Yspring_s, 5,
+  -1,
+  Yspring_sB, 4,
+  -1,
+  Yspring_s, 4,
+  -1,
+  Yspring_sB, 3,
+  -1,
+  Yspring_s, 3,
+  -1,
+  Yspring_sB, 2,
+  -1,
+  Yspring_s, 2,
+  -1,
+  Yspring_sB, 1,
+  -1,
+  Yspring_s, 1,
+  -1,
+  Yspring_sB, 0,
+  -1,
+  Yspring_s, 0,
+  -1,
+  Yspring_eB, 6,
+  Yspring_w, 0,
+  -1,
+  Yspring_e, 6,
+  Yspring_wB, 0,
+  -1,
+  Yspring_eB, 5,
+  Yspring_w, 1,
+  -1,
+  Yspring_e, 5,
+  Yspring_wB, 1,
+  -1,
+  Yspring_eB, 4,
+  Yspring_w, 2,
+  -1,
+  Yspring_e, 4,
+  Yspring_wB, 2,
+  -1,
+  Yspring_eB, 3,
+  Yspring_w, 3,
+  -1,
+  Yspring_e, 3,
+  Yspring_wB, 3,
+  -1,
+  Yspring_eB, 2,
+  Yspring_w, 4,
+  -1,
+  Yspring_e, 2,
+  Yspring_wB, 4,
+  -1,
+  Yspring_eB, 1,
+  Yspring_w, 5,
+  -1,
+  Yspring_e, 1,
+  Yspring_wB, 5,
+  -1,
+  Yspring_eB, 0,
+  Yspring_w, 6,
+  -1,
+  Yspring_e, 0,
+  Yspring_wB, 6,
+  -1,
+  Yspring_kill_eB, 6,
+  -1,
+  Yspring_kill_e, 6,
+  -1,
+  Yspring_kill_eB, 5,
+  -1,
+  Yspring_kill_e, 5,
+  -1,
+  Yspring_kill_eB, 4,
+  -1,
+  Yspring_kill_e, 4,
+  -1,
+  Yspring_kill_eB, 3,
+  -1,
+  Yspring_kill_e, 3,
+  -1,
+  Yspring_kill_eB, 2,
+  -1,
+  Yspring_kill_e, 2,
+  -1,
+  Yspring_kill_eB, 1,
+  -1,
+  Yspring_kill_e, 1,
+  -1,
+  Yspring_kill_eB, 0,
+  -1,
+  Yspring_kill_e, 0,
+  -1,
+  Yspring_kill_w, 0,
+  -1,
+  Yspring_kill_wB, 0,
+  -1,
+  Yspring_kill_w, 1,
+  -1,
+  Yspring_kill_wB, 1,
+  -1,
+  Yspring_kill_w, 2,
+  -1,
+  Yspring_kill_wB, 2,
+  -1,
+  Yspring_kill_w, 3,
+  -1,
+  Yspring_kill_wB, 3,
+  -1,
+  Yspring_kill_w, 4,
+  -1,
+  Yspring_kill_wB, 4,
+  -1,
+  Yspring_kill_w, 5,
+  -1,
+  Yspring_kill_wB, 5,
+  -1,
+  Yspring_kill_w, 6,
+  -1,
+  Yspring_kill_wB, 6,
+  -1,
+
+  Xeater_n, 0,
+  Xeater_e, 0,
+  Xeater_w, 0,
+  Xeater_s, 0,
+  Xeater_n, 7,
+  Xeater_e, 7,
+  Xeater_s, 7,
+  Xeater_w, 7,
+  Yeater_n, 7,
+  Yeater_e, 7,
+  Yeater_s, 7,
+  Yeater_w, 7,
+  -1,
+  Xeater_n, 1,
+  Xeater_e, 1,
+  Xeater_w, 1,
+  Xeater_s, 1,
+  Xeater_n, 6,
+  Xeater_e, 6,
+  Xeater_w, 6,
+  Xeater_s, 6,
+  -1,
+  Xeater_n, 2,
+  Xeater_e, 2,
+  Xeater_w, 2,
+  Xeater_s, 2,
+  Xeater_n, 5,
+  Xeater_e, 5,
+  Xeater_w, 5,
+  Xeater_s, 5,
+  -1,
+  Xeater_n, 3,
+  Xeater_e, 3,
+  Xeater_w, 3,
+  Xeater_s, 3,
+  Xeater_n, 4,
+  Xeater_e, 4,
+  Xeater_w, 4,
+  Xeater_s, 4,
+  -1,
+  Yeater_n, 0,
+  Yeater_sB, 6,
+  -1,
+  Yeater_nB, 0,
+  Yeater_s, 6,
+  -1,
+  Yeater_n, 1,
+  Yeater_sB, 5,
+  -1,
+  Yeater_nB, 1,
+  Yeater_s, 5,
+  -1,
+  Yeater_n, 2,
+  Yeater_sB, 4,
+  -1,
+  Yeater_nB, 2,
+  Yeater_s, 4,
+  -1,
+  Yeater_n, 3,
+  Yeater_sB, 3,
+  -1,
+  Yeater_nB, 3,
+  Yeater_s, 3,
+  -1,
+  Yeater_n, 4,
+  Yeater_sB, 2,
+  -1,
+  Yeater_nB, 4,
+  Yeater_s, 2,
+  -1,
+  Yeater_n, 5,
+  Yeater_sB, 1,
+  -1,
+  Yeater_nB, 5,
+  Yeater_s, 1,
+  -1,
+  Yeater_n, 6,
+  Yeater_sB, 0,
+  -1,
+  Yeater_nB, 6,
+  Yeater_s, 0,
+  -1,
+  Yeater_eB, 6,
+  Yeater_w, 0,
+  -1,
+  Yeater_e, 6,
+  Yeater_wB, 0,
+  -1,
+  Yeater_eB, 5,
+  Yeater_w, 1,
+  -1,
+  Yeater_e, 5,
+  Yeater_wB, 1,
+  -1,
+  Yeater_eB, 4,
+  Yeater_w, 2,
+  -1,
+  Yeater_e, 4,
+  Yeater_wB, 2,
+  -1,
+  Yeater_eB, 3,
+  Yeater_w, 3,
+  -1,
+  Yeater_e, 3,
+  Yeater_wB, 3,
+  -1,
+  Yeater_eB, 2,
+  Yeater_w, 4,
+  -1,
+  Yeater_e, 2,
+  Yeater_wB, 4,
+  -1,
+  Yeater_eB, 1,
+  Yeater_w, 5,
+  -1,
+  Yeater_e, 1,
+  Yeater_wB, 5,
+  -1,
+  Yeater_eB, 0,
+  Yeater_w, 6,
+  -1,
+  Yeater_e, 0,
+  Yeater_wB, 6,
+  -1,
+  Yeater_stone, 0,
+  -1,
+  Yeater_stone, 1,
+  -1,
+  Yeater_stone, 2,
+  -1,
+  Yeater_stone, 3,
+  -1,
+  Yeater_stone, 4,
+  -1,
+  Yeater_stone, 5,
+  -1,
+  Yeater_stone, 6,
+  -1,
+  Yeater_spring, 0,
+  -1,
+  Yeater_spring, 1,
+  -1,
+  Yeater_spring, 2,
+  -1,
+  Yeater_spring, 3,
+  -1,
+  Yeater_spring, 4,
+  -1,
+  Yeater_spring, 5,
+  -1,
+  Yeater_spring, 6,
+  -1,
+
+  Xalien, 0,
+  Xalien_pause, 0,
+  Xalien, 7,
+  Xalien_pause, 7,
+  Yalien_n, 7,
+  Yalien_e, 7,
+  Yalien_s, 7,
+  Yalien_w, 7,
+  -1,
+  Xalien, 1,
+  Xalien_pause, 1,
+  Xalien, 6,
+  Xalien_pause, 6,
+  -1,
+  Xalien, 2,
+  Xalien_pause, 2,
+  Xalien, 5,
+  Xalien_pause, 5,
+  -1,
+  Xalien, 3,
+  Xalien_pause, 3,
+  Xalien, 4,
+  Xalien_pause, 4,
+  -1,
+  Yalien_n, 0,
+  Yalien_sB, 6,
+  -1,
+  Yalien_nB, 0,
+  Yalien_s, 6,
+  -1,
+  Yalien_n, 1,
+  Yalien_sB, 5,
+  -1,
+  Yalien_nB, 1,
+  Yalien_s, 5,
+  -1,
+  Yalien_n, 2,
+  Yalien_sB, 4,
+  -1,
+  Yalien_nB, 2,
+  Yalien_s, 4,
+  -1,
+  Yalien_n, 3,
+  Yalien_sB, 3,
+  -1,
+  Yalien_nB, 3,
+  Yalien_s, 3,
+  -1,
+  Yalien_n, 4,
+  Yalien_sB, 2,
+  -1,
+  Yalien_nB, 4,
+  Yalien_s, 2,
+  -1,
+  Yalien_n, 5,
+  Yalien_sB, 1,
+  -1,
+  Yalien_nB, 5,
+  Yalien_s, 1,
+  -1,
+  Yalien_n, 6,
+  Yalien_sB, 0,
+  -1,
+  Yalien_nB, 6,
+  Yalien_s, 0,
+  -1,
+  Yalien_eB, 6,
+  Yalien_w, 0,
+  -1,
+  Yalien_e, 6,
+  Yalien_wB, 0,
+  -1,
+  Yalien_eB, 5,
+  Yalien_w, 1,
+  -1,
+  Yalien_e, 5,
+  Yalien_wB, 1,
+  -1,
+  Yalien_eB, 4,
+  Yalien_w, 2,
+  -1,
+  Yalien_e, 4,
+  Yalien_wB, 2,
+  -1,
+  Yalien_eB, 3,
+  Yalien_w, 3,
+  -1,
+  Yalien_e, 3,
+  Yalien_wB, 3,
+  -1,
+  Yalien_eB, 2,
+  Yalien_w, 4,
+  -1,
+  Yalien_e, 2,
+  Yalien_wB, 4,
+  -1,
+  Yalien_eB, 1,
+  Yalien_w, 5,
+  -1,
+  Yalien_e, 1,
+  Yalien_wB, 5,
+  -1,
+  Yalien_eB, 0,
+  Yalien_w, 6,
+  -1,
+  Yalien_e, 0,
+  Yalien_wB, 6,
+  -1,
+  Yalien_stone, 0,
+  -1,
+  Yalien_stone, 1,
+  -1,
+  Yalien_stone, 2,
+  -1,
+  Yalien_stone, 3,
+  -1,
+  Yalien_stone, 4,
+  -1,
+  Yalien_stone, 5,
+  -1,
+  Yalien_stone, 6,
+  -1,
+  Yalien_spring, 0,
+  -1,
+  Yalien_spring, 1,
+  -1,
+  Yalien_spring, 2,
+  -1,
+  Yalien_spring, 3,
+  -1,
+  Yalien_spring, 4,
+  -1,
+  Yalien_spring, 5,
+  -1,
+  Yalien_spring, 6,
+  -1,
+
+  Xemerald, 0,
+  Xemerald, 1,
+  Xemerald, 2,
+  Xemerald, 3,
+  Xemerald, 4,
+  Xemerald, 5,
+  Xemerald, 6,
+  Xemerald, 7,
+  Xemerald_pause, 0,
+  Xemerald_pause, 1,
+  Xemerald_pause, 2,
+  Xemerald_pause, 3,
+  Xemerald_pause, 4,
+  Xemerald_pause, 5,
+  Xemerald_pause, 6,
+  Xemerald_pause, 7,
+  Xemerald_fall, 0,
+  Xemerald_fall, 1,
+  Xemerald_fall, 2,
+  Xemerald_fall, 3,
+  Xemerald_fall, 4,
+  Xemerald_fall, 5,
+  Xemerald_fall, 6,
+  Xemerald_fall, 7,
+
+#ifdef BAD_ROLL
+  Xemerald_force_e, 0,
+  Xemerald_force_e, 1,
+  Xemerald_force_e, 2,
+  Xemerald_force_e, 3,
+  Xemerald_force_e, 4,
+  Xemerald_force_e, 5,
+  Xemerald_force_e, 6,
+  Xemerald_force_e, 7,
+  Xemerald_force_w, 0,
+  Xemerald_force_w, 1,
+  Xemerald_force_w, 2,
+  Xemerald_force_w, 3,
+  Xemerald_force_w, 4,
+  Xemerald_force_w, 5,
+  Xemerald_force_w, 6,
+  Xemerald_force_w, 7,
+#endif
+
+  Xemerald_shine, 0,
+  Xemerald_shine, 7,
+  Yemerald_stone, 7,
+  Yemerald_s, 7,
+  Yemerald_e, 7,
+  Yemerald_w, 7,
+  -1,
+  Xemerald_shine, 1,
+  Xemerald_shine, 6,
+  -1,
+  Xemerald_shine, 2,
+  Xemerald_shine, 5,
+  -1,
+  Xemerald_shine, 3,
+  Xemerald_shine, 4,
+  -1,
+  Yemerald_sB, 6,
+  -1,
+  Yemerald_s, 6,
+  -1,
+  Yemerald_sB, 5,
+  -1,
+  Yemerald_s, 5,
+  -1,
+  Yemerald_sB, 4,
+  -1,
+  Yemerald_s, 4,
+  -1,
+  Yemerald_sB, 3,
+  -1,
+  Yemerald_s, 3,
+  -1,
+  Yemerald_sB, 2,
+  -1,
+  Yemerald_s, 2,
+  -1,
+  Yemerald_sB, 1,
+  -1,
+  Yemerald_s, 1,
+  -1,
+  Yemerald_sB, 0,
+  -1,
+  Yemerald_s, 0,
+  -1,
+  Yemerald_eB, 6,
+  Yemerald_w, 0,
+  -1,
+  Yemerald_e, 6,
+  Yemerald_wB, 0,
+  -1,
+  Yemerald_eB, 5,
+  Yemerald_w, 1,
+  -1,
+  Yemerald_e, 5,
+  Yemerald_wB, 1,
+  -1,
+  Yemerald_eB, 4,
+  Yemerald_w, 2,
+  -1,
+  Yemerald_e, 4,
+  Yemerald_wB, 2,
+  -1,
+  Yemerald_eB, 3,
+  Yemerald_w, 3,
+  -1,
+  Yemerald_e, 3,
+  Yemerald_wB, 3,
+  -1,
+  Yemerald_eB, 2,
+  Yemerald_w, 4,
+  -1,
+  Yemerald_e, 2,
+  Yemerald_wB, 4,
+  -1,
+  Yemerald_eB, 1,
+  Yemerald_w, 5,
+  -1,
+  Yemerald_e, 1,
+  Yemerald_wB, 5,
+  -1,
+  Yemerald_eB, 0,
+  Yemerald_w, 6,
+  -1,
+  Yemerald_e, 0,
+  Yemerald_wB, 6,
+  -1,
+  Yemerald_eat, 6,
+  -1,
+  Yemerald_eat, 5,
+  -1,
+  Yemerald_eat, 4,
+  -1,
+  Yemerald_eat, 3,
+  -1,
+  Yemerald_eat, 2,
+  -1,
+  Yemerald_eat, 1,
+  -1,
+  Yemerald_eat, 0,
+  -1,
+  Yemerald_stone, 0,
+  -1,
+  Yemerald_stone, 1,
+  -1,
+  Yemerald_stone, 2,
+  -1,
+  Yemerald_stone, 3,
+  -1,
+  Yemerald_stone, 4,
+  -1,
+  Yemerald_stone, 5,
+  -1,
+  Yemerald_stone, 6,
+  -1,
+
+  Xdiamond, 0,
+  Xdiamond, 1,
+  Xdiamond, 2,
+  Xdiamond, 3,
+  Xdiamond, 4,
+  Xdiamond, 5,
+  Xdiamond, 6,
+  Xdiamond, 7,
+  Xdiamond_pause, 0,
+  Xdiamond_pause, 1,
+  Xdiamond_pause, 2,
+  Xdiamond_pause, 3,
+  Xdiamond_pause, 4,
+  Xdiamond_pause, 5,
+  Xdiamond_pause, 6,
+  Xdiamond_pause, 7,
+  Xdiamond_fall, 0,
+  Xdiamond_fall, 1,
+  Xdiamond_fall, 2,
+  Xdiamond_fall, 3,
+  Xdiamond_fall, 4,
+  Xdiamond_fall, 5,
+  Xdiamond_fall, 6,
+  Xdiamond_fall, 7,
+
+#ifdef BAD_ROLL
+  Xdiamond_force_e, 0,
+  Xdiamond_force_e, 1,
+  Xdiamond_force_e, 2,
+  Xdiamond_force_e, 3,
+  Xdiamond_force_e, 4,
+  Xdiamond_force_e, 5,
+  Xdiamond_force_e, 6,
+  Xdiamond_force_e, 7,
+  Xdiamond_force_w, 0,
+  Xdiamond_force_w, 1,
+  Xdiamond_force_w, 2,
+  Xdiamond_force_w, 3,
+  Xdiamond_force_w, 4,
+  Xdiamond_force_w, 5,
+  Xdiamond_force_w, 6,
+  Xdiamond_force_w, 7,
+#endif
+
+  Xdiamond_shine, 0,
+  Xdiamond_shine, 7,
+  Ydiamond_s, 7,
+  Ydiamond_e, 7,
+  Ydiamond_w, 7,
+  -1,
+  Xdiamond_shine, 1,
+  Xdiamond_shine, 6,
+  -1,
+  Xdiamond_shine, 2,
+  Xdiamond_shine, 5,
+  -1,
+  Xdiamond_shine, 3,
+  Xdiamond_shine, 4,
+  -1,
+  Ydiamond_sB, 6,
+  -1,
+  Ydiamond_s, 6,
+  -1,
+  Ydiamond_sB, 5,
+  -1,
+  Ydiamond_s, 5,
+  -1,
+  Ydiamond_sB, 4,
+  -1,
+  Ydiamond_s, 4,
+  -1,
+  Ydiamond_sB, 3,
+  -1,
+  Ydiamond_s, 3,
+  -1,
+  Ydiamond_sB, 2,
+  -1,
+  Ydiamond_s, 2,
+  -1,
+  Ydiamond_sB, 1,
+  -1,
+  Ydiamond_s, 1,
+  -1,
+  Ydiamond_sB, 0,
+  -1,
+  Ydiamond_s, 0,
+  -1,
+  Ydiamond_eB, 6,
+  Ydiamond_w, 0,
+  -1,
+  Ydiamond_e, 6,
+  Ydiamond_wB, 0,
+  -1,
+  Ydiamond_eB, 5,
+  Ydiamond_w, 1,
+  -1,
+  Ydiamond_e, 5,
+  Ydiamond_wB, 1,
+  -1,
+  Ydiamond_eB, 4,
+  Ydiamond_w, 2,
+  -1,
+  Ydiamond_e, 4,
+  Ydiamond_wB, 2,
+  -1,
+  Ydiamond_eB, 3,
+  Ydiamond_w, 3,
+  -1,
+  Ydiamond_e, 3,
+  Ydiamond_wB, 3,
+  -1,
+  Ydiamond_eB, 2,
+  Ydiamond_w, 4,
+  -1,
+  Ydiamond_e, 2,
+  Ydiamond_wB, 4,
+  -1,
+  Ydiamond_eB, 1,
+  Ydiamond_w, 5,
+  -1,
+  Ydiamond_e, 1,
+  Ydiamond_wB, 5,
+  -1,
+  Ydiamond_eB, 0,
+  Ydiamond_w, 6,
+  -1,
+  Ydiamond_e, 0,
+  Ydiamond_wB, 6,
+  -1,
+  Ydiamond_eat, 6,
+  -1,
+  Ydiamond_eat, 5,
+  -1,
+  Ydiamond_eat, 4,
+  -1,
+  Ydiamond_eat, 3,
+  -1,
+  Ydiamond_eat, 2,
+  -1,
+  Ydiamond_eat, 1,
+  -1,
+  Ydiamond_eat, 0,
+  -1,
+  Ydiamond_stone, 0,
+  -1,
+  Ydiamond_stone, 1,
+  -1,
+  Ydiamond_stone, 2,
+  -1,
+  Ydiamond_stone, 3,
+  -1,
+  Ydiamond_stone, 4,
+  -1,
+  Ydiamond_stone, 5,
+  -1,
+  Ydiamond_stone, 6,
+  -1,
+
+  Xdrip_fall, 0,
+  Xdrip_fall, 1,
+  Xdrip_fall, 2,
+  Xdrip_fall, 3,
+  Xdrip_fall, 4,
+  Xdrip_fall, 5,
+  Xdrip_fall, 6,
+  Xdrip_fall, 7,
+  Xdrip_eat, 7,
+  Ydrip_s2, 7,
+  -1,
+  Ydrip_s2B, 6,
+  -1,
+  Ydrip_s2, 6,
+  -1,
+  Ydrip_s2B, 5,
+  -1,
+  Ydrip_s2, 5,
+  -1,
+  Ydrip_s2B, 4,
+  -1,
+  Ydrip_s2, 4,
+  -1,
+  Ydrip_s2B, 3,
+  -1,
+  Ydrip_s2, 3,
+  -1,
+  Ydrip_s2B, 2,
+  -1,
+  Ydrip_s2, 2,
+  -1,
+  Ydrip_s2B, 1,
+  -1,
+  Ydrip_s2, 1,
+  -1,
+  Ydrip_s2B, 0,
+  -1,
+  Ydrip_s2, 0,
+  -1,
+  Xdrip_stretchB, 0,
+  Xdrip_stretchB, 1,
+  Xdrip_stretchB, 2,
+  Xdrip_stretchB, 3,
+  Xdrip_stretchB, 4,
+  Xdrip_stretchB, 5,
+  Xdrip_stretchB, 6,
+  Xdrip_stretchB, 7,
+  Ydrip_s1B, 7,
+  -1,
+  Xdrip_stretch, 0,
+  Xdrip_stretch, 1,
+  Xdrip_stretch, 2,
+  Xdrip_stretch, 3,
+  Xdrip_stretch, 4,
+  Xdrip_stretch, 5,
+  Xdrip_stretch, 6,
+  Xdrip_stretch, 7,
+  Ydrip_s1, 7,
+  -1,
+  Ydrip_s1B, 6,
+  -1,
+  Ydrip_s1, 6,
+  -1,
+  Ydrip_s1B, 5,
+  -1,
+  Ydrip_s1, 5,
+  -1,
+  Ydrip_s1B, 4,
+  -1,
+  Ydrip_s1, 4,
+  -1,
+  Ydrip_s1B, 3,
+  -1,
+  Ydrip_s1, 3,
+  -1,
+  Ydrip_s1B, 2,
+  -1,
+  Ydrip_s1, 2,
+  -1,
+  Ydrip_s1B, 1,
+  -1,
+  Ydrip_s1, 1,
+  -1,
+  Ydrip_s1B, 0,
+  -1,
+  Ydrip_s1, 0,
+  -1,
+  Xdrip_eat, 0,
+  -1,
+  Xdrip_eat, 1,
+  -1,
+  Xdrip_eat, 2,
+  -1,
+  Xdrip_eat, 3,
+  -1,
+  Xdrip_eat, 4,
+  -1,
+  Xdrip_eat, 5,
+  -1,
+  Xdrip_eat, 6,
+  -1,
+
+  Xbomb, 0,
+  Xbomb, 1,
+  Xbomb, 2,
+  Xbomb, 3,
+  Xbomb, 4,
+  Xbomb, 5,
+  Xbomb, 6,
+  Xbomb, 7,
+  Xbomb_pause, 0,
+  Xbomb_pause, 1,
+  Xbomb_pause, 2,
+  Xbomb_pause, 3,
+  Xbomb_pause, 4,
+  Xbomb_pause, 5,
+  Xbomb_pause, 6,
+  Xbomb_pause, 7,
+  Xbomb_fall, 0,
+  Xbomb_fall, 1,
+  Xbomb_fall, 2,
+  Xbomb_fall, 3,
+  Xbomb_fall, 4,
+  Xbomb_fall, 5,
+  Xbomb_fall, 6,
+  Xbomb_fall, 7,
+
+#ifdef BAD_ROLL
+  Xbomb_force_e, 0,
+  Xbomb_force_e, 1,
+  Xbomb_force_e, 2,
+  Xbomb_force_e, 3,
+  Xbomb_force_e, 4,
+  Xbomb_force_e, 5,
+  Xbomb_force_e, 6,
+  Xbomb_force_e, 7,
+  Xbomb_force_w, 0,
+  Xbomb_force_w, 1,
+  Xbomb_force_w, 2,
+  Xbomb_force_w, 3,
+  Xbomb_force_w, 4,
+  Xbomb_force_w, 5,
+  Xbomb_force_w, 6,
+  Xbomb_force_w, 7,
+#endif
+
+  Ybomb_s, 7,
+  Ybomb_e, 7,
+  Ybomb_w, 7,
+  -1,
+  Ybomb_sB, 6,
+  -1,
+  Ybomb_s, 6,
+  -1,
+  Ybomb_sB, 5,
+  -1,
+  Ybomb_s, 5,
+  -1,
+  Ybomb_sB, 4,
+  -1,
+  Ybomb_s, 4,
+  -1,
+  Ybomb_sB, 3,
+  -1,
+  Ybomb_s, 3,
+  -1,
+  Ybomb_sB, 2,
+  -1,
+  Ybomb_s, 2,
+  -1,
+  Ybomb_sB, 1,
+  -1,
+  Ybomb_s, 1,
+  -1,
+  Ybomb_sB, 0,
+  -1,
+  Ybomb_s, 0,
+  -1,
+  Ybomb_eB, 6,
+  Ybomb_w, 0,
+  -1,
+  Ybomb_e, 6,
+  Ybomb_wB, 0,
+  -1,
+  Ybomb_eB, 5,
+  Ybomb_w, 1,
+  -1,
+  Ybomb_e, 5,
+  Ybomb_wB, 1,
+  -1,
+  Ybomb_eB, 4,
+  Ybomb_w, 2,
+  -1,
+  Ybomb_e, 4,
+  Ybomb_wB, 2,
+  -1,
+  Ybomb_eB, 3,
+  Ybomb_w, 3,
+  -1,
+  Ybomb_e, 3,
+  Ybomb_wB, 3,
+  -1,
+  Ybomb_eB, 2,
+  Ybomb_w, 4,
+  -1,
+  Ybomb_e, 2,
+  Ybomb_wB, 4,
+  -1,
+  Ybomb_eB, 1,
+  Ybomb_w, 5,
+  -1,
+  Ybomb_e, 1,
+  Ybomb_wB, 5,
+  -1,
+  Ybomb_eB, 0,
+  Ybomb_w, 6,
+  -1,
+  Ybomb_e, 0,
+  Ybomb_wB, 6,
+  -1,
+  Ybomb_eat, 6,
+  -1,
+  Ybomb_eat, 5,
+  -1,
+  Ybomb_eat, 4,
+  -1,
+  Ybomb_eat, 3,
+  -1,
+  Ybomb_eat, 2,
+  -1,
+  Ybomb_eat, 1,
+  -1,
+  Ybomb_eat, 0,
+  -1,
+
+  Yballoon_n, 7,
+  Yballoon_e, 7,
+  Yballoon_s, 7,
+  Yballoon_w, 7,
+  Xballoon, 0,
+  Xballoon, 1,
+  Xballoon, 2,
+  Xballoon, 3,
+  Xballoon, 4,
+  Xballoon, 5,
+  Xballoon, 6,
+  Xballoon, 7,
+  -1,
+  Yballoon_n, 0,
+  Yballoon_sB, 6,
+  -1,
+  Yballoon_nB, 0,
+  Yballoon_s, 6,
+  -1,
+  Yballoon_n, 1,
+  Yballoon_sB, 5,
+  -1,
+  Yballoon_nB, 1,
+  Yballoon_s, 5,
+  -1,
+  Yballoon_n, 2,
+  Yballoon_sB, 4,
+  -1,
+  Yballoon_nB, 2,
+  Yballoon_s, 4,
+  -1,
+  Yballoon_n, 3,
+  Yballoon_sB, 3,
+  -1,
+  Yballoon_nB, 3,
+  Yballoon_s, 3,
+  -1,
+  Yballoon_n, 4,
+  Yballoon_sB, 2,
+  -1,
+  Yballoon_nB, 4,
+  Yballoon_s, 2,
+  -1,
+  Yballoon_n, 5,
+  Yballoon_sB, 1,
+  -1,
+  Yballoon_nB, 5,
+  Yballoon_s, 1,
+  -1,
+  Yballoon_n, 6,
+  Yballoon_sB, 0,
+  -1,
+  Yballoon_nB, 6,
+  Yballoon_s, 0,
+  -1,
+  Yballoon_eB, 6,
+  Yballoon_w, 0,
+  -1,
+  Yballoon_e, 6,
+  Yballoon_wB, 0,
+  -1,
+  Yballoon_eB, 5,
+  Yballoon_w, 1,
+  -1,
+  Yballoon_e, 5,
+  Yballoon_wB, 1,
+  -1,
+  Yballoon_eB, 4,
+  Yballoon_w, 2,
+  -1,
+  Yballoon_e, 4,
+  Yballoon_wB, 2,
+  -1,
+  Yballoon_eB, 3,
+  Yballoon_w, 3,
+  -1,
+  Yballoon_e, 3,
+  Yballoon_wB, 3,
+  -1,
+  Yballoon_eB, 2,
+  Yballoon_w, 4,
+  -1,
+  Yballoon_e, 2,
+  Yballoon_wB, 4,
+  -1,
+  Yballoon_eB, 1,
+  Yballoon_w, 5,
+  -1,
+  Yballoon_e, 1,
+  Yballoon_wB, 5,
+  -1,
+  Yballoon_eB, 0,
+  Yballoon_w, 6,
+  -1,
+  Yballoon_e, 0,
+  Yballoon_wB, 6,
+  -1,
+
+  Xgrass, 0,
+  Xgrass, 1,
+  Xgrass, 2,
+  Xgrass, 3,
+  Xgrass, 4,
+  Xgrass, 5,
+  Xgrass, 6,
+  Xgrass, 7,
+  Xfake_grass, 0,
+  Xfake_grass, 1,
+  Xfake_grass, 2,
+  Xfake_grass, 3,
+  Xfake_grass, 4,
+  Xfake_grass, 5,
+  Xfake_grass, 6,
+  Xfake_grass, 7,
+  -1,
+  Ygrass_nB, 6,
+  -1,
+  Ygrass_nB, 5,
+  -1,
+  Ygrass_nB, 4,
+  -1,
+  Ygrass_nB, 3,
+  -1,
+  Ygrass_nB, 2,
+  -1,
+  Ygrass_nB, 1,
+  -1,
+  Ygrass_nB, 0,
+  -1,
+  Ygrass_eB, 6,
+  -1,
+  Ygrass_eB, 5,
+  -1,
+  Ygrass_eB, 4,
+  -1,
+  Ygrass_eB, 3,
+  -1,
+  Ygrass_eB, 2,
+  -1,
+  Ygrass_eB, 1,
+  -1,
+  Ygrass_eB, 0,
+  -1,
+  Ygrass_sB, 6,
+  -1,
+  Ygrass_sB, 5,
+  -1,
+  Ygrass_sB, 4,
+  -1,
+  Ygrass_sB, 3,
+  -1,
+  Ygrass_sB, 2,
+  -1,
+  Ygrass_sB, 1,
+  -1,
+  Ygrass_sB, 0,
+  -1,
+  Ygrass_wB, 6,
+  -1,
+  Ygrass_wB, 5,
+  -1,
+  Ygrass_wB, 4,
+  -1,
+  Ygrass_wB, 3,
+  -1,
+  Ygrass_wB, 2,
+  -1,
+  Ygrass_wB, 1,
+  -1,
+  Ygrass_wB, 0,
+  -1,
+
+  Xdirt, 0,
+  Xdirt, 1,
+  Xdirt, 2,
+  Xdirt, 3,
+  Xdirt, 4,
+  Xdirt, 5,
+  Xdirt, 6,
+  Xdirt, 7,
+  -1,
+  Ydirt_nB, 6,
+  -1,
+  Ydirt_nB, 5,
+  -1,
+  Ydirt_nB, 4,
+  -1,
+  Ydirt_nB, 3,
+  -1,
+  Ydirt_nB, 2,
+  -1,
+  Ydirt_nB, 1,
+  -1,
+  Ydirt_nB, 0,
+  -1,
+  Ydirt_eB, 6,
+  -1,
+  Ydirt_eB, 5,
+  -1,
+  Ydirt_eB, 4,
+  -1,
+  Ydirt_eB, 3,
+  -1,
+  Ydirt_eB, 2,
+  -1,
+  Ydirt_eB, 1,
+  -1,
+  Ydirt_eB, 0,
+  -1,
+  Ydirt_sB, 6,
+  -1,
+  Ydirt_sB, 5,
+  -1,
+  Ydirt_sB, 4,
+  -1,
+  Ydirt_sB, 3,
+  -1,
+  Ydirt_sB, 2,
+  -1,
+  Ydirt_sB, 1,
+  -1,
+  Ydirt_sB, 0,
+  -1,
+  Ydirt_wB, 6,
+  -1,
+  Ydirt_wB, 5,
+  -1,
+  Ydirt_wB, 4,
+  -1,
+  Ydirt_wB, 3,
+  -1,
+  Ydirt_wB, 2,
+  -1,
+  Ydirt_wB, 1,
+  -1,
+  Ydirt_wB, 0,
+  -1,
+
+  Xacid_nw, 0,
+  Xacid_nw, 1,
+  Xacid_nw, 2,
+  Xacid_nw, 3,
+  Xacid_nw, 4,
+  Xacid_nw, 5,
+  Xacid_nw, 6,
+  Xacid_nw, 7,
+  -1,
+  Xacid_ne, 0,
+  Xacid_ne, 1,
+  Xacid_ne, 2,
+  Xacid_ne, 3,
+  Xacid_ne, 4,
+  Xacid_ne, 5,
+  Xacid_ne, 6,
+  Xacid_ne, 7,
+  -1,
+  Xacid_sw, 0,
+  Xacid_sw, 1,
+  Xacid_sw, 2,
+  Xacid_sw, 3,
+  Xacid_sw, 4,
+  Xacid_sw, 5,
+  Xacid_sw, 6,
+  Xacid_sw, 7,
+  -1,
+  Xacid_s, 0,
+  Xacid_s, 1,
+  Xacid_s, 2,
+  Xacid_s, 3,
+  Xacid_s, 4,
+  Xacid_s, 5,
+  Xacid_s, 6,
+  Xacid_s, 7,
+  -1,
+  Xacid_se, 0,
+  Xacid_se, 1,
+  Xacid_se, 2,
+  Xacid_se, 3,
+  Xacid_se, 4,
+  Xacid_se, 5,
+  Xacid_se, 6,
+  Xacid_se, 7,
+  -1,
+  Xacid_1, 0,
+  Xacid_1, 1,
+  Xacid_1, 2,
+  Xacid_1, 3,
+  Xacid_1, 4,
+  Xacid_1, 5,
+  Xacid_1, 6,
+  Xacid_1, 7,
+  -1,
+  Xacid_2, 0,
+  Xacid_2, 1,
+  Xacid_2, 2,
+  Xacid_2, 3,
+  Xacid_2, 4,
+  Xacid_2, 5,
+  Xacid_2, 6,
+  Xacid_2, 7,
+  -1,
+  Xacid_3, 0,
+  Xacid_3, 1,
+  Xacid_3, 2,
+  Xacid_3, 3,
+  Xacid_3, 4,
+  Xacid_3, 5,
+  Xacid_3, 6,
+  Xacid_3, 7,
+  -1,
+  Xacid_4, 0,
+  Xacid_4, 1,
+  Xacid_4, 2,
+  Xacid_4, 3,
+  Xacid_4, 4,
+  Xacid_4, 5,
+  Xacid_4, 6,
+  Xacid_4, 7,
+  -1,
+  Xacid_5, 0,
+  Xacid_5, 1,
+  Xacid_5, 2,
+  Xacid_5, 3,
+  Xacid_5, 4,
+  Xacid_5, 5,
+  Xacid_5, 6,
+  Xacid_5, 7,
+  -1,
+  Xacid_6, 0,
+  Xacid_6, 1,
+  Xacid_6, 2,
+  Xacid_6, 3,
+  Xacid_6, 4,
+  Xacid_6, 5,
+  Xacid_6, 6,
+  Xacid_6, 7,
+  -1,
+  Xacid_7, 0,
+  Xacid_7, 1,
+  Xacid_7, 2,
+  Xacid_7, 3,
+  Xacid_7, 4,
+  Xacid_7, 5,
+  Xacid_7, 6,
+  Xacid_7, 7,
+  -1,
+  Xacid_8, 0,
+  Xacid_8, 1,
+  Xacid_8, 2,
+  Xacid_8, 3,
+  Xacid_8, 4,
+  Xacid_8, 5,
+  Xacid_8, 6,
+  Xacid_8, 7,
+  -1,
+  Yacid_splash_wB, 4,
+  Yacid_splash_wB, 5,
+  -1,
+  Yacid_splash_wB, 2,
+  Yacid_splash_wB, 3,
+  -1,
+  Yacid_splash_wB, 0,
+  Yacid_splash_wB, 1,
+  -1,
+  Yacid_splash_eB, 4,
+  Yacid_splash_eB, 5,
+  -1,
+  Yacid_splash_eB, 2,
+  Yacid_splash_eB, 3,
+  -1,
+  Yacid_splash_eB, 0,
+  Yacid_splash_eB, 1,
+  -1,
+
+  Xball_2B, 7,
+  Xball_1, 0,
+  Xball_1, 1,
+  Xball_1, 2,
+  Xball_1, 3,
+  Xball_1, 4,
+  Xball_1, 5,
+  Xball_1, 6,
+  Xball_1, 7,
+  -1,
+  Xball_1B, 0,
+  -1,
+  Xball_1B, 1,
+  -1,
+  Xball_1B, 2,
+  -1,
+  Xball_1B, 3,
+  -1,
+  Xball_1B, 4,
+  -1,
+  Xball_1B, 5,
+  -1,
+  Xball_1B, 6,
+  -1,
+  Xball_1B, 7,
+  Xball_2, 0,
+  Xball_2, 1,
+  Xball_2, 2,
+  Xball_2, 3,
+  Xball_2, 4,
+  Xball_2, 5,
+  Xball_2, 6,
+  Xball_2, 7,
+  -1,
+  Xball_2B, 0,
+  -1,
+  Xball_2B, 1,
+  -1,
+  Xball_2B, 2,
+  -1,
+  Xball_2B, 3,
+  -1,
+  Xball_2B, 4,
+  -1,
+  Xball_2B, 5,
+  -1,
+  Xball_2B, 6,
+  -1,
+
+  Ygrow_ew_eat, 7,
+  Xgrow_ew, 0,
+  Xgrow_ew, 1,
+  Xgrow_ew, 2,
+  Xgrow_ew, 3,
+  Xgrow_ew, 4,
+  Xgrow_ew, 5,
+  Xgrow_ew, 6,
+  Xgrow_ew, 7,
+  -1,
+  Ygrow_ew_eat, 0,
+  -1,
+  Ygrow_ew_eat, 1,
+  -1,
+  Ygrow_ew_eat, 2,
+  -1,
+  Ygrow_ew_eat, 3,
+  -1,
+  Ygrow_ew_eat, 4,
+  -1,
+  Ygrow_ew_eat, 5,
+  -1,
+  Ygrow_ew_eat, 6,
+  -1,
+  Ygrow_ns_eat, 7,
+  Xgrow_ns, 0,
+  Xgrow_ns, 1,
+  Xgrow_ns, 2,
+  Xgrow_ns, 3,
+  Xgrow_ns, 4,
+  Xgrow_ns, 5,
+  Xgrow_ns, 6,
+  Xgrow_ns, 7,
+  -1,
+  Ygrow_ns_eat, 0,
+  -1,
+  Ygrow_ns_eat, 1,
+  -1,
+  Ygrow_ns_eat, 2,
+  -1,
+  Ygrow_ns_eat, 3,
+  -1,
+  Ygrow_ns_eat, 4,
+  -1,
+  Ygrow_ns_eat, 5,
+  -1,
+  Ygrow_ns_eat, 6,
+  -1,
+
+  XwonderwallB, 7,
+  Xwonderwall, 0,
+  Xwonderwall, 1,
+  Xwonderwall, 2,
+  Xwonderwall, 3,
+  Xwonderwall, 4,
+  Xwonderwall, 5,
+  Xwonderwall, 6,
+  Xwonderwall, 7,
+  -1,
+  XwonderwallB, 0,
+  -1,
+  XwonderwallB, 1,
+  -1,
+  XwonderwallB, 2,
+  -1,
+  XwonderwallB, 3,
+  -1,
+  XwonderwallB, 4,
+  -1,
+  XwonderwallB, 5,
+  -1,
+  XwonderwallB, 6,
+  -1,
+
+  Xamoeba_1, 0,
+  Xamoeba_1, 1,
+  Xamoeba_1, 2,
+  Xamoeba_1, 3,
+  Xamoeba_1, 4,
+  Xamoeba_1, 5,
+  Xamoeba_1, 6,
+  Xamoeba_1, 7,
+  -1,
+  Xamoeba_2, 0,
+  Xamoeba_2, 1,
+  Xamoeba_2, 2,
+  Xamoeba_2, 3,
+  Xamoeba_2, 4,
+  Xamoeba_2, 5,
+  Xamoeba_2, 6,
+  Xamoeba_2, 7,
+  -1,
+  Xamoeba_3, 0,
+  Xamoeba_3, 1,
+  Xamoeba_3, 2,
+  Xamoeba_3, 3,
+  Xamoeba_3, 4,
+  Xamoeba_3, 5,
+  Xamoeba_3, 6,
+  Xamoeba_3, 7,
+  -1,
+  Xamoeba_4, 0,
+  Xamoeba_4, 1,
+  Xamoeba_4, 2,
+  Xamoeba_4, 3,
+  Xamoeba_4, 4,
+  Xamoeba_4, 5,
+  Xamoeba_4, 6,
+  Xamoeba_4, 7,
+  -1,
+  Xamoeba_5, 0,
+  Xamoeba_5, 1,
+  Xamoeba_5, 2,
+  Xamoeba_5, 3,
+  Xamoeba_5, 4,
+  Xamoeba_5, 5,
+  Xamoeba_5, 6,
+  Xamoeba_5, 7,
+  -1,
+  Xamoeba_6, 0,
+  Xamoeba_6, 1,
+  Xamoeba_6, 2,
+  Xamoeba_6, 3,
+  Xamoeba_6, 4,
+  Xamoeba_6, 5,
+  Xamoeba_6, 6,
+  Xamoeba_6, 7,
+  -1,
+  Xamoeba_7, 0,
+  Xamoeba_7, 1,
+  Xamoeba_7, 2,
+  Xamoeba_7, 3,
+  Xamoeba_7, 4,
+  Xamoeba_7, 5,
+  Xamoeba_7, 6,
+  Xamoeba_7, 7,
+  -1,
+  Xamoeba_8, 0,
+  Xamoeba_8, 1,
+  Xamoeba_8, 2,
+  Xamoeba_8, 3,
+  Xamoeba_8, 4,
+  Xamoeba_8, 5,
+  Xamoeba_8, 6,
+  Xamoeba_8, 7,
+  -1,
+
+  Xdoor_1, 0,
+  Xdoor_1, 1,
+  Xdoor_1, 2,
+  Xdoor_1, 3,
+  Xdoor_1, 4,
+  Xdoor_1, 5,
+  Xdoor_1, 6,
+  Xdoor_1, 7,
+  -1,
+  Xdoor_2, 0,
+  Xdoor_2, 1,
+  Xdoor_2, 2,
+  Xdoor_2, 3,
+  Xdoor_2, 4,
+  Xdoor_2, 5,
+  Xdoor_2, 6,
+  Xdoor_2, 7,
+  -1,
+  Xdoor_3, 0,
+  Xdoor_3, 1,
+  Xdoor_3, 2,
+  Xdoor_3, 3,
+  Xdoor_3, 4,
+  Xdoor_3, 5,
+  Xdoor_3, 6,
+  Xdoor_3, 7,
+  -1,
+  Xdoor_4, 0,
+  Xdoor_4, 1,
+  Xdoor_4, 2,
+  Xdoor_4, 3,
+  Xdoor_4, 4,
+  Xdoor_4, 5,
+  Xdoor_4, 6,
+  Xdoor_4, 7,
+  -1,
+  Xdoor_5, 0,
+  Xdoor_5, 1,
+  Xdoor_5, 2,
+  Xdoor_5, 3,
+  Xdoor_5, 4,
+  Xdoor_5, 5,
+  Xdoor_5, 6,
+  Xdoor_5, 7,
+  -1,
+  Xdoor_6, 0,
+  Xdoor_6, 1,
+  Xdoor_6, 2,
+  Xdoor_6, 3,
+  Xdoor_6, 4,
+  Xdoor_6, 5,
+  Xdoor_6, 6,
+  Xdoor_6, 7,
+  -1,
+  Xdoor_7, 0,
+  Xdoor_7, 1,
+  Xdoor_7, 2,
+  Xdoor_7, 3,
+  Xdoor_7, 4,
+  Xdoor_7, 5,
+  Xdoor_7, 6,
+  Xdoor_7, 7,
+  -1,
+  Xdoor_8, 0,
+  Xdoor_8, 1,
+  Xdoor_8, 2,
+  Xdoor_8, 3,
+  Xdoor_8, 4,
+  Xdoor_8, 5,
+  Xdoor_8, 6,
+  Xdoor_8, 7,
+  -1,
+  Xkey_1, 0,
+  Xkey_1, 1,
+  Xkey_1, 2,
+  Xkey_1, 3,
+  Xkey_1, 4,
+  Xkey_1, 5,
+  Xkey_1, 6,
+  Xkey_1, 7,
+  -1,
+  Xkey_2, 0,
+  Xkey_2, 1,
+  Xkey_2, 2,
+  Xkey_2, 3,
+  Xkey_2, 4,
+  Xkey_2, 5,
+  Xkey_2, 6,
+  Xkey_2, 7,
+  -1,
+  Xkey_3, 0,
+  Xkey_3, 1,
+  Xkey_3, 2,
+  Xkey_3, 3,
+  Xkey_3, 4,
+  Xkey_3, 5,
+  Xkey_3, 6,
+  Xkey_3, 7,
+  -1,
+  Xkey_4, 0,
+  Xkey_4, 1,
+  Xkey_4, 2,
+  Xkey_4, 3,
+  Xkey_4, 4,
+  Xkey_4, 5,
+  Xkey_4, 6,
+  Xkey_4, 7,
+  -1,
+  Xkey_5, 0,
+  Xkey_5, 1,
+  Xkey_5, 2,
+  Xkey_5, 3,
+  Xkey_5, 4,
+  Xkey_5, 5,
+  Xkey_5, 6,
+  Xkey_5, 7,
+  -1,
+  Xkey_6, 0,
+  Xkey_6, 1,
+  Xkey_6, 2,
+  Xkey_6, 3,
+  Xkey_6, 4,
+  Xkey_6, 5,
+  Xkey_6, 6,
+  Xkey_6, 7,
+  -1,
+  Xkey_7, 0,
+  Xkey_7, 1,
+  Xkey_7, 2,
+  Xkey_7, 3,
+  Xkey_7, 4,
+  Xkey_7, 5,
+  Xkey_7, 6,
+  Xkey_7, 7,
+  -1,
+  Xkey_8, 0,
+  Xkey_8, 1,
+  Xkey_8, 2,
+  Xkey_8, 3,
+  Xkey_8, 4,
+  Xkey_8, 5,
+  Xkey_8, 6,
+  Xkey_8, 7,
+  -1,
+
+  Xwind_n, 0,
+  Xwind_n, 1,
+  Xwind_n, 2,
+  Xwind_n, 3,
+  Xwind_n, 4,
+  Xwind_n, 5,
+  Xwind_n, 6,
+  Xwind_n, 7,
+  -1,
+  Xwind_e, 0,
+  Xwind_e, 1,
+  Xwind_e, 2,
+  Xwind_e, 3,
+  Xwind_e, 4,
+  Xwind_e, 5,
+  Xwind_e, 6,
+  Xwind_e, 7,
+  -1,
+  Xwind_s, 0,
+  Xwind_s, 1,
+  Xwind_s, 2,
+  Xwind_s, 3,
+  Xwind_s, 4,
+  Xwind_s, 5,
+  Xwind_s, 6,
+  Xwind_s, 7,
+  -1,
+  Xwind_w, 0,
+  Xwind_w, 1,
+  Xwind_w, 2,
+  Xwind_w, 3,
+  Xwind_w, 4,
+  Xwind_w, 5,
+  Xwind_w, 6,
+  Xwind_w, 7,
+  -1,
+  Xwind_nesw, 0,
+  Xwind_nesw, 1,
+  Xwind_nesw, 2,
+  Xwind_nesw, 3,
+  Xwind_nesw, 4,
+  Xwind_nesw, 5,
+  Xwind_nesw, 6,
+  Xwind_nesw, 7,
+  -1,
+  Xwind_stop, 0,
+  Xwind_stop, 1,
+  Xwind_stop, 2,
+  Xwind_stop, 3,
+  Xwind_stop, 4,
+  Xwind_stop, 5,
+  Xwind_stop, 6,
+  Xwind_stop, 7,
+  -1,
+
+  Xexit, 0,
+  Xexit, 1,
+  Xexit, 2,
+  Xexit, 3,
+  Xexit, 4,
+  Xexit, 5,
+  Xexit, 6,
+  Xexit, 7,
+  -1,
+  Xexit_1, 0,
+  Xexit_1, 1,
+  Xexit_1, 2,
+  -1,
+  Xexit_1, 3,
+  Xexit_1, 4,
+  Xexit_1, 5,
+  Xexit_3, 7,
+  Xexit_3, 6,
+  Xexit_3, 5,
+  -1,
+  Xexit_1, 6,
+  Xexit_1, 7,
+  Xexit_2, 0,
+  Xexit_3, 4,
+  Xexit_3, 3,
+  Xexit_3, 2,
+  -1,
+  Xexit_2, 1,
+  Xexit_2, 2,
+  Xexit_2, 3,
+  Xexit_3, 1,
+  Xexit_3, 0,
+  Xexit_2, 7,
+  -1,
+  Xexit_2, 4,
+  Xexit_2, 5,
+  Xexit_2, 6,
+  -1,
+
+  Ydynamite_eat, 0,
+  Ydynamite_eat, 1,
+  Ydynamite_eat, 2,
+  Xdynamite, 0,
+  Xdynamite, 1,
+  Xdynamite, 2,
+  Xdynamite, 3,
+  Xdynamite, 4,
+  Xdynamite, 5,
+  Xdynamite, 6,
+  Xdynamite, 7,
+  -1,
+  Xdynamite_4, 0,
+  Xdynamite_4, 1,
+  Xdynamite_4, 2,
+  Xdynamite_4, 3,
+  Xdynamite_4, 4,
+  Xdynamite_4, 5,
+  Xdynamite_4, 6,
+  Xdynamite_4, 7,
+  -1,
+  Xdynamite_3, 0,
+  Xdynamite_3, 1,
+  Xdynamite_3, 2,
+  Xdynamite_3, 3,
+  Xdynamite_3, 4,
+  Xdynamite_3, 5,
+  Xdynamite_3, 6,
+  Xdynamite_3, 7,
+  -1,
+  Xdynamite_2, 0,
+  Xdynamite_2, 1,
+  Xdynamite_2, 2,
+  Xdynamite_2, 3,
+  Xdynamite_2, 4,
+  Xdynamite_2, 5,
+  Xdynamite_2, 6,
+  Xdynamite_2, 7,
+  -1,
+  Xdynamite_1, 0,
+  Xdynamite_1, 1,
+  Xdynamite_1, 2,
+  Xdynamite_1, 3,
+  Xdynamite_1, 4,
+  Xdynamite_1, 5,
+  Xdynamite_1, 6,
+  Xdynamite_1, 7,
+  -1,
+
+  Xbumper, 0,
+  Xbumper, 1,
+  Xbumper, 2,
+  Xbumper, 3,
+  Xbumper, 4,
+  Xbumper, 5,
+  Xbumper, 6,
+  Xbumper, 7,
+  XbumperB, 0,
+  XbumperB, 7,
+  -1,
+  XbumperB, 1,
+  XbumperB, 6,
+  -1,
+  XbumperB, 2,
+  XbumperB, 5,
+  -1,
+  XbumperB, 3,
+  XbumperB, 4,
+  -1,
+
+  Xwheel, 0,
+  Xwheel, 1,
+  Xwheel, 2,
+  Xwheel, 3,
+  Xwheel, 4,
+  Xwheel, 5,
+  Xwheel, 6,
+  Xwheel, 7,
+  XwheelB, 7,
+  XwheelB, 6,
+  XwheelB, 5,
+  XwheelB, 4,
+  -1,
+  XwheelB, 3,
+  XwheelB, 2,
+  XwheelB, 1,
+  XwheelB, 0,
+  -1,
+
+  XswitchB, 0,
+  XswitchB, 1,
+  XswitchB, 2,
+  XswitchB, 3,
+  XswitchB, 4,
+  XswitchB, 5,
+  XswitchB, 6,
+  XswitchB, 7,
+  -1,
+  Xswitch, 0,
+  Xswitch, 1,
+  Xswitch, 2,
+  Xswitch, 3,
+  Xswitch, 4,
+  Xswitch, 5,
+  Xswitch, 6,
+  Xswitch, 7,
+  -1,
+
+  Xsand, 0,
+  Xsand, 1,
+  Xsand, 2,
+  Xsand, 3,
+  Xsand, 4,
+  Xsand, 5,
+  Xsand, 6,
+  Xsand, 7,
+  Xsand_stone, 0,
+  Xsand_stone, 1,
+  Xsand_stone, 2,
+  Xsand_stone, 3,
+  Xsand_stone, 4,
+  Xsand_stone, 5,
+  Xsand_stone, 6,
+  Xsand_stone, 7,
+  Xsand_stonesand_1, 0,
+  Xsand_stonesand_1, 1,
+  Xsand_stonesand_1, 2,
+  Xsand_stonesand_1, 3,
+  Xsand_stonesand_1, 4,
+  Xsand_stonesand_1, 5,
+  Xsand_stonesand_1, 6,
+  Xsand_stonesand_1, 7,
+  Xsand_stonesand_2, 0,
+  Xsand_stonesand_2, 1,
+  Xsand_stonesand_2, 2,
+  Xsand_stonesand_2, 3,
+  Xsand_stonesand_2, 4,
+  Xsand_stonesand_2, 5,
+  Xsand_stonesand_2, 6,
+  Xsand_stonesand_2, 7,
+  Xsand_stonesand_3, 0,
+  Xsand_stonesand_3, 1,
+  Xsand_stonesand_3, 2,
+  Xsand_stonesand_3, 3,
+  Xsand_stonesand_3, 4,
+  Xsand_stonesand_3, 5,
+  Xsand_stonesand_3, 6,
+  Xsand_stonesand_3, 7,
+  Xsand_stonesand_4, 0,
+  Xsand_stonesand_4, 1,
+  Xsand_stonesand_4, 2,
+  Xsand_stonesand_4, 3,
+  Xsand_stonesand_4, 4,
+  Xsand_stonesand_4, 5,
+  Xsand_stonesand_4, 6,
+  Xsand_stonesand_4, 7,
+  Xsand_sandstone_1, 0,
+  Xsand_sandstone_1, 1,
+  Xsand_sandstone_1, 2,
+  Xsand_sandstone_1, 3,
+  Xsand_sandstone_1, 4,
+  Xsand_sandstone_1, 5,
+  Xsand_sandstone_1, 6,
+  Xsand_sandstone_1, 7,
+  Xsand_sandstone_2, 0,
+  Xsand_sandstone_2, 1,
+  Xsand_sandstone_2, 2,
+  Xsand_sandstone_2, 3,
+  Xsand_sandstone_2, 4,
+  Xsand_sandstone_2, 5,
+  Xsand_sandstone_2, 6,
+  Xsand_sandstone_2, 7,
+  Xsand_sandstone_3, 0,
+  Xsand_sandstone_3, 1,
+  Xsand_sandstone_3, 2,
+  Xsand_sandstone_3, 3,
+  Xsand_sandstone_3, 4,
+  Xsand_sandstone_3, 5,
+  Xsand_sandstone_3, 6,
+  Xsand_sandstone_3, 7,
+  Xsand_sandstone_4, 0,
+  Xsand_sandstone_4, 1,
+  Xsand_sandstone_4, 2,
+  Xsand_sandstone_4, 3,
+  Xsand_sandstone_4, 4,
+  Xsand_sandstone_4, 5,
+  Xsand_sandstone_4, 6,
+  Xsand_sandstone_4, 7,
+  -1,
+
+  Xplant, 0,
+  Xplant, 1,
+  Xplant, 2,
+  Xplant, 3,
+  Xplant, 4,
+  Xplant, 5,
+  Xplant, 6,
+  Xplant, 7,
+  Yplant, 0,
+  Yplant, 1,
+  Yplant, 2,
+  Yplant, 3,
+  Yplant, 4,
+  Yplant, 5,
+  Yplant, 6,
+  Yplant, 7,
+  -1,
+
+  Xlenses, 0,
+  Xlenses, 1,
+  Xlenses, 2,
+  Xlenses, 3,
+  Xlenses, 4,
+  Xlenses, 5,
+  Xlenses, 6,
+  Xlenses, 7,
+  -1,
+
+  Xmagnify, 0,
+  Xmagnify, 1,
+  Xmagnify, 2,
+  Xmagnify, 3,
+  Xmagnify, 4,
+  Xmagnify, 5,
+  Xmagnify, 6,
+  Xmagnify, 7,
+  -1,
+
+  XdripperB, 0,
+  XdripperB, 1,
+  XdripperB, 2,
+  XdripperB, 3,
+  XdripperB, 4,
+  XdripperB, 5,
+  XdripperB, 6,
+  XdripperB, 7,
+  -1,
+
+  Xfake_blankB, 0,
+  Xfake_blankB, 1,
+  Xfake_blankB, 2,
+  Xfake_blankB, 3,
+  Xfake_blankB, 4,
+  Xfake_blankB, 5,
+  Xfake_blankB, 6,
+  Xfake_blankB, 7,
+  -1,
+
+  Xfake_grassB, 0,
+  Xfake_grassB, 1,
+  Xfake_grassB, 2,
+  Xfake_grassB, 3,
+  Xfake_grassB, 4,
+  Xfake_grassB, 5,
+  Xfake_grassB, 6,
+  Xfake_grassB, 7,
+  -1,
+
+  Xfake_door_1, 0,
+  Xfake_door_1, 1,
+  Xfake_door_1, 2,
+  Xfake_door_1, 3,
+  Xfake_door_1, 4,
+  Xfake_door_1, 5,
+  Xfake_door_1, 6,
+  Xfake_door_1, 7,
+  Xfake_door_2, 0,
+  Xfake_door_2, 1,
+  Xfake_door_2, 2,
+  Xfake_door_2, 3,
+  Xfake_door_2, 4,
+  Xfake_door_2, 5,
+  Xfake_door_2, 6,
+  Xfake_door_2, 7,
+  Xfake_door_3, 0,
+  Xfake_door_3, 1,
+  Xfake_door_3, 2,
+  Xfake_door_3, 3,
+  Xfake_door_3, 4,
+  Xfake_door_3, 5,
+  Xfake_door_3, 6,
+  Xfake_door_3, 7,
+  Xfake_door_4, 0,
+  Xfake_door_4, 1,
+  Xfake_door_4, 2,
+  Xfake_door_4, 3,
+  Xfake_door_4, 4,
+  Xfake_door_4, 5,
+  Xfake_door_4, 6,
+  Xfake_door_4, 7,
+  Xfake_door_5, 0,
+  Xfake_door_5, 1,
+  Xfake_door_5, 2,
+  Xfake_door_5, 3,
+  Xfake_door_5, 4,
+  Xfake_door_5, 5,
+  Xfake_door_5, 6,
+  Xfake_door_5, 7,
+  Xfake_door_6, 0,
+  Xfake_door_6, 1,
+  Xfake_door_6, 2,
+  Xfake_door_6, 3,
+  Xfake_door_6, 4,
+  Xfake_door_6, 5,
+  Xfake_door_6, 6,
+  Xfake_door_6, 7,
+  Xfake_door_7, 0,
+  Xfake_door_7, 1,
+  Xfake_door_7, 2,
+  Xfake_door_7, 3,
+  Xfake_door_7, 4,
+  Xfake_door_7, 5,
+  Xfake_door_7, 6,
+  Xfake_door_7, 7,
+  Xfake_door_8, 0,
+  Xfake_door_8, 1,
+  Xfake_door_8, 2,
+  Xfake_door_8, 3,
+  Xfake_door_8, 4,
+  Xfake_door_8, 5,
+  Xfake_door_8, 6,
+  Xfake_door_8, 7,
+  -1,
+
+  Xsteel_1, 0,
+  Xsteel_1, 1,
+  Xsteel_1, 2,
+  Xsteel_1, 3,
+  Xsteel_1, 4,
+  Xsteel_1, 5,
+  Xsteel_1, 6,
+  Xsteel_1, 7,
+  -1,
+  Xsteel_2, 0,
+  Xsteel_2, 1,
+  Xsteel_2, 2,
+  Xsteel_2, 3,
+  Xsteel_2, 4,
+  Xsteel_2, 5,
+  Xsteel_2, 6,
+  Xsteel_2, 7,
+  -1,
+  Xsteel_3, 0,
+  Xsteel_3, 1,
+  Xsteel_3, 2,
+  Xsteel_3, 3,
+  Xsteel_3, 4,
+  Xsteel_3, 5,
+  Xsteel_3, 6,
+  Xsteel_3, 7,
+  -1,
+  Xsteel_4, 0,
+  Xsteel_4, 1,
+  Xsteel_4, 2,
+  Xsteel_4, 3,
+  Xsteel_4, 4,
+  Xsteel_4, 5,
+  Xsteel_4, 6,
+  Xsteel_4, 7,
+  -1,
+  Xwall_1, 0,
+  Xwall_1, 1,
+  Xwall_1, 2,
+  Xwall_1, 3,
+  Xwall_1, 4,
+  Xwall_1, 5,
+  Xwall_1, 6,
+  Xwall_1, 7,
+  -1,
+  Xwall_2, 0,
+  Xwall_2, 1,
+  Xwall_2, 2,
+  Xwall_2, 3,
+  Xwall_2, 4,
+  Xwall_2, 5,
+  Xwall_2, 6,
+  Xwall_2, 7,
+  -1,
+  Xwall_3, 0,
+  Xwall_3, 1,
+  Xwall_3, 2,
+  Xwall_3, 3,
+  Xwall_3, 4,
+  Xwall_3, 5,
+  Xwall_3, 6,
+  Xwall_3, 7,
+  -1,
+  Xwall_4, 0,
+  Xwall_4, 1,
+  Xwall_4, 2,
+  Xwall_4, 3,
+  Xwall_4, 4,
+  Xwall_4, 5,
+  Xwall_4, 6,
+  Xwall_4, 7,
+  -1,
+  Xround_wall_1, 0,
+  Xround_wall_1, 1,
+  Xround_wall_1, 2,
+  Xround_wall_1, 3,
+  Xround_wall_1, 4,
+  Xround_wall_1, 5,
+  Xround_wall_1, 6,
+  Xround_wall_1, 7,
+  -1,
+  Xround_wall_2, 0,
+  Xround_wall_2, 1,
+  Xround_wall_2, 2,
+  Xround_wall_2, 3,
+  Xround_wall_2, 4,
+  Xround_wall_2, 5,
+  Xround_wall_2, 6,
+  Xround_wall_2, 7,
+  -1,
+  Xround_wall_3, 0,
+  Xround_wall_3, 1,
+  Xround_wall_3, 2,
+  Xround_wall_3, 3,
+  Xround_wall_3, 4,
+  Xround_wall_3, 5,
+  Xround_wall_3, 6,
+  Xround_wall_3, 7,
+  -1,
+  Xround_wall_4, 0,
+  Xround_wall_4, 1,
+  Xround_wall_4, 2,
+  Xround_wall_4, 3,
+  Xround_wall_4, 4,
+  Xround_wall_4, 5,
+  Xround_wall_4, 6,
+  Xround_wall_4, 7,
+  -1,
+  Xdecor_1, 0,
+  Xdecor_1, 1,
+  Xdecor_1, 2,
+  Xdecor_1, 3,
+  Xdecor_1, 4,
+  Xdecor_1, 5,
+  Xdecor_1, 6,
+  Xdecor_1, 7,
+  -1,
+  Xdecor_2, 0,
+  Xdecor_2, 1,
+  Xdecor_2, 2,
+  Xdecor_2, 3,
+  Xdecor_2, 4,
+  Xdecor_2, 5,
+  Xdecor_2, 6,
+  Xdecor_2, 7,
+  -1,
+  Xdecor_3, 0,
+  Xdecor_3, 1,
+  Xdecor_3, 2,
+  Xdecor_3, 3,
+  Xdecor_3, 4,
+  Xdecor_3, 5,
+  Xdecor_3, 6,
+  Xdecor_3, 7,
+  -1,
+  Xdecor_4, 0,
+  Xdecor_4, 1,
+  Xdecor_4, 2,
+  Xdecor_4, 3,
+  Xdecor_4, 4,
+  Xdecor_4, 5,
+  Xdecor_4, 6,
+  Xdecor_4, 7,
+  -1,
+  Xdecor_5, 0,
+  Xdecor_5, 1,
+  Xdecor_5, 2,
+  Xdecor_5, 3,
+  Xdecor_5, 4,
+  Xdecor_5, 5,
+  Xdecor_5, 6,
+  Xdecor_5, 7,
+  -1,
+  Xdecor_6, 0,
+  Xdecor_6, 1,
+  Xdecor_6, 2,
+  Xdecor_6, 3,
+  Xdecor_6, 4,
+  Xdecor_6, 5,
+  Xdecor_6, 6,
+  Xdecor_6, 7,
+  -1,
+  Xdecor_7, 0,
+  Xdecor_7, 1,
+  Xdecor_7, 2,
+  Xdecor_7, 3,
+  Xdecor_7, 4,
+  Xdecor_7, 5,
+  Xdecor_7, 6,
+  Xdecor_7, 7,
+  -1,
+  Xdecor_8, 0,
+  Xdecor_8, 1,
+  Xdecor_8, 2,
+  Xdecor_8, 3,
+  Xdecor_8, 4,
+  Xdecor_8, 5,
+  Xdecor_8, 6,
+  Xdecor_8, 7,
+  -1,
+  Xdecor_9, 0,
+  Xdecor_9, 1,
+  Xdecor_9, 2,
+  Xdecor_9, 3,
+  Xdecor_9, 4,
+  Xdecor_9, 5,
+  Xdecor_9, 6,
+  Xdecor_9, 7,
+  -1,
+  Xdecor_10, 0,
+  Xdecor_10, 1,
+  Xdecor_10, 2,
+  Xdecor_10, 3,
+  Xdecor_10, 4,
+  Xdecor_10, 5,
+  Xdecor_10, 6,
+  Xdecor_10, 7,
+  -1,
+  Xdecor_11, 0,
+  Xdecor_11, 1,
+  Xdecor_11, 2,
+  Xdecor_11, 3,
+  Xdecor_11, 4,
+  Xdecor_11, 5,
+  Xdecor_11, 6,
+  Xdecor_11, 7,
+  -1,
+  Xdecor_12, 0,
+  Xdecor_12, 1,
+  Xdecor_12, 2,
+  Xdecor_12, 3,
+  Xdecor_12, 4,
+  Xdecor_12, 5,
+  Xdecor_12, 6,
+  Xdecor_12, 7,
+  -1,
+  Xalpha_excla, 0,
+  Xalpha_excla, 1,
+  Xalpha_excla, 2,
+  Xalpha_excla, 3,
+  Xalpha_excla, 4,
+  Xalpha_excla, 5,
+  Xalpha_excla, 6,
+  Xalpha_excla, 7,
+  -1,
+  Xalpha_quote, 0,
+  Xalpha_quote, 1,
+  Xalpha_quote, 2,
+  Xalpha_quote, 3,
+  Xalpha_quote, 4,
+  Xalpha_quote, 5,
+  Xalpha_quote, 6,
+  Xalpha_quote, 7,
+  -1,
+  Xalpha_comma, 0,
+  Xalpha_comma, 1,
+  Xalpha_comma, 2,
+  Xalpha_comma, 3,
+  Xalpha_comma, 4,
+  Xalpha_comma, 5,
+  Xalpha_comma, 6,
+  Xalpha_comma, 7,
+  -1,
+  Xalpha_minus, 0,
+  Xalpha_minus, 1,
+  Xalpha_minus, 2,
+  Xalpha_minus, 3,
+  Xalpha_minus, 4,
+  Xalpha_minus, 5,
+  Xalpha_minus, 6,
+  Xalpha_minus, 7,
+  -1,
+  Xalpha_perio, 0,
+  Xalpha_perio, 1,
+  Xalpha_perio, 2,
+  Xalpha_perio, 3,
+  Xalpha_perio, 4,
+  Xalpha_perio, 5,
+  Xalpha_perio, 6,
+  Xalpha_perio, 7,
+  -1,
+  Xalpha_0, 0,
+  Xalpha_0, 1,
+  Xalpha_0, 2,
+  Xalpha_0, 3,
+  Xalpha_0, 4,
+  Xalpha_0, 5,
+  Xalpha_0, 6,
+  Xalpha_0, 7,
+  -1,
+  Xalpha_1, 0,
+  Xalpha_1, 1,
+  Xalpha_1, 2,
+  Xalpha_1, 3,
+  Xalpha_1, 4,
+  Xalpha_1, 5,
+  Xalpha_1, 6,
+  Xalpha_1, 7,
+  -1,
+  Xalpha_2, 0,
+  Xalpha_2, 1,
+  Xalpha_2, 2,
+  Xalpha_2, 3,
+  Xalpha_2, 4,
+  Xalpha_2, 5,
+  Xalpha_2, 6,
+  Xalpha_2, 7,
+  -1,
+  Xalpha_3, 0,
+  Xalpha_3, 1,
+  Xalpha_3, 2,
+  Xalpha_3, 3,
+  Xalpha_3, 4,
+  Xalpha_3, 5,
+  Xalpha_3, 6,
+  Xalpha_3, 7,
+  -1,
+  Xalpha_4, 0,
+  Xalpha_4, 1,
+  Xalpha_4, 2,
+  Xalpha_4, 3,
+  Xalpha_4, 4,
+  Xalpha_4, 5,
+  Xalpha_4, 6,
+  Xalpha_4, 7,
+  -1,
+  Xalpha_5, 0,
+  Xalpha_5, 1,
+  Xalpha_5, 2,
+  Xalpha_5, 3,
+  Xalpha_5, 4,
+  Xalpha_5, 5,
+  Xalpha_5, 6,
+  Xalpha_5, 7,
+  -1,
+  Xalpha_6, 0,
+  Xalpha_6, 1,
+  Xalpha_6, 2,
+  Xalpha_6, 3,
+  Xalpha_6, 4,
+  Xalpha_6, 5,
+  Xalpha_6, 6,
+  Xalpha_6, 7,
+  -1,
+  Xalpha_7, 0,
+  Xalpha_7, 1,
+  Xalpha_7, 2,
+  Xalpha_7, 3,
+  Xalpha_7, 4,
+  Xalpha_7, 5,
+  Xalpha_7, 6,
+  Xalpha_7, 7,
+  -1,
+  Xalpha_8, 0,
+  Xalpha_8, 1,
+  Xalpha_8, 2,
+  Xalpha_8, 3,
+  Xalpha_8, 4,
+  Xalpha_8, 5,
+  Xalpha_8, 6,
+  Xalpha_8, 7,
+  -1,
+  Xalpha_9, 0,
+  Xalpha_9, 1,
+  Xalpha_9, 2,
+  Xalpha_9, 3,
+  Xalpha_9, 4,
+  Xalpha_9, 5,
+  Xalpha_9, 6,
+  Xalpha_9, 7,
+  -1,
+  Xalpha_colon, 0,
+  Xalpha_colon, 1,
+  Xalpha_colon, 2,
+  Xalpha_colon, 3,
+  Xalpha_colon, 4,
+  Xalpha_colon, 5,
+  Xalpha_colon, 6,
+  Xalpha_colon, 7,
+  -1,
+  Xalpha_arrow_w, 0,
+  Xalpha_arrow_w, 1,
+  Xalpha_arrow_w, 2,
+  Xalpha_arrow_w, 3,
+  Xalpha_arrow_w, 4,
+  Xalpha_arrow_w, 5,
+  Xalpha_arrow_w, 6,
+  Xalpha_arrow_w, 7,
+  -1,
+  Xalpha_arrow_e, 0,
+  Xalpha_arrow_e, 1,
+  Xalpha_arrow_e, 2,
+  Xalpha_arrow_e, 3,
+  Xalpha_arrow_e, 4,
+  Xalpha_arrow_e, 5,
+  Xalpha_arrow_e, 6,
+  Xalpha_arrow_e, 7,
+  -1,
+  Xalpha_quest, 0,
+  Xalpha_quest, 1,
+  Xalpha_quest, 2,
+  Xalpha_quest, 3,
+  Xalpha_quest, 4,
+  Xalpha_quest, 5,
+  Xalpha_quest, 6,
+  Xalpha_quest, 7,
+  -1,
+  Xalpha_a, 0,
+  Xalpha_a, 1,
+  Xalpha_a, 2,
+  Xalpha_a, 3,
+  Xalpha_a, 4,
+  Xalpha_a, 5,
+  Xalpha_a, 6,
+  Xalpha_a, 7,
+  -1,
+  Xalpha_b, 0,
+  Xalpha_b, 1,
+  Xalpha_b, 2,
+  Xalpha_b, 3,
+  Xalpha_b, 4,
+  Xalpha_b, 5,
+  Xalpha_b, 6,
+  Xalpha_b, 7,
+  -1,
+  Xalpha_c, 0,
+  Xalpha_c, 1,
+  Xalpha_c, 2,
+  Xalpha_c, 3,
+  Xalpha_c, 4,
+  Xalpha_c, 5,
+  Xalpha_c, 6,
+  Xalpha_c, 7,
+  -1,
+  Xalpha_d, 0,
+  Xalpha_d, 1,
+  Xalpha_d, 2,
+  Xalpha_d, 3,
+  Xalpha_d, 4,
+  Xalpha_d, 5,
+  Xalpha_d, 6,
+  Xalpha_d, 7,
+  -1,
+  Xalpha_e, 0,
+  Xalpha_e, 1,
+  Xalpha_e, 2,
+  Xalpha_e, 3,
+  Xalpha_e, 4,
+  Xalpha_e, 5,
+  Xalpha_e, 6,
+  Xalpha_e, 7,
+  -1,
+  Xalpha_f, 0,
+  Xalpha_f, 1,
+  Xalpha_f, 2,
+  Xalpha_f, 3,
+  Xalpha_f, 4,
+  Xalpha_f, 5,
+  Xalpha_f, 6,
+  Xalpha_f, 7,
+  -1,
+  Xalpha_g, 0,
+  Xalpha_g, 1,
+  Xalpha_g, 2,
+  Xalpha_g, 3,
+  Xalpha_g, 4,
+  Xalpha_g, 5,
+  Xalpha_g, 6,
+  Xalpha_g, 7,
+  -1,
+  Xalpha_h, 0,
+  Xalpha_h, 1,
+  Xalpha_h, 2,
+  Xalpha_h, 3,
+  Xalpha_h, 4,
+  Xalpha_h, 5,
+  Xalpha_h, 6,
+  Xalpha_h, 7,
+  -1,
+  Xalpha_i, 0,
+  Xalpha_i, 1,
+  Xalpha_i, 2,
+  Xalpha_i, 3,
+  Xalpha_i, 4,
+  Xalpha_i, 5,
+  Xalpha_i, 6,
+  Xalpha_i, 7,
+  -1,
+  Xalpha_j, 0,
+  Xalpha_j, 1,
+  Xalpha_j, 2,
+  Xalpha_j, 3,
+  Xalpha_j, 4,
+  Xalpha_j, 5,
+  Xalpha_j, 6,
+  Xalpha_j, 7,
+  -1,
+  Xalpha_k, 0,
+  Xalpha_k, 1,
+  Xalpha_k, 2,
+  Xalpha_k, 3,
+  Xalpha_k, 4,
+  Xalpha_k, 5,
+  Xalpha_k, 6,
+  Xalpha_k, 7,
+  -1,
+  Xalpha_l, 0,
+  Xalpha_l, 1,
+  Xalpha_l, 2,
+  Xalpha_l, 3,
+  Xalpha_l, 4,
+  Xalpha_l, 5,
+  Xalpha_l, 6,
+  Xalpha_l, 7,
+  -1,
+  Xalpha_m, 0,
+  Xalpha_m, 1,
+  Xalpha_m, 2,
+  Xalpha_m, 3,
+  Xalpha_m, 4,
+  Xalpha_m, 5,
+  Xalpha_m, 6,
+  Xalpha_m, 7,
+  -1,
+  Xalpha_n, 0,
+  Xalpha_n, 1,
+  Xalpha_n, 2,
+  Xalpha_n, 3,
+  Xalpha_n, 4,
+  Xalpha_n, 5,
+  Xalpha_n, 6,
+  Xalpha_n, 7,
+  -1,
+  Xalpha_o, 0,
+  Xalpha_o, 1,
+  Xalpha_o, 2,
+  Xalpha_o, 3,
+  Xalpha_o, 4,
+  Xalpha_o, 5,
+  Xalpha_o, 6,
+  Xalpha_o, 7,
+  -1,
+  Xalpha_p, 0,
+  Xalpha_p, 1,
+  Xalpha_p, 2,
+  Xalpha_p, 3,
+  Xalpha_p, 4,
+  Xalpha_p, 5,
+  Xalpha_p, 6,
+  Xalpha_p, 7,
+  -1,
+  Xalpha_q, 0,
+  Xalpha_q, 1,
+  Xalpha_q, 2,
+  Xalpha_q, 3,
+  Xalpha_q, 4,
+  Xalpha_q, 5,
+  Xalpha_q, 6,
+  Xalpha_q, 7,
+  -1,
+  Xalpha_r, 0,
+  Xalpha_r, 1,
+  Xalpha_r, 2,
+  Xalpha_r, 3,
+  Xalpha_r, 4,
+  Xalpha_r, 5,
+  Xalpha_r, 6,
+  Xalpha_r, 7,
+  -1,
+  Xalpha_s, 0,
+  Xalpha_s, 1,
+  Xalpha_s, 2,
+  Xalpha_s, 3,
+  Xalpha_s, 4,
+  Xalpha_s, 5,
+  Xalpha_s, 6,
+  Xalpha_s, 7,
+  -1,
+  Xalpha_t, 0,
+  Xalpha_t, 1,
+  Xalpha_t, 2,
+  Xalpha_t, 3,
+  Xalpha_t, 4,
+  Xalpha_t, 5,
+  Xalpha_t, 6,
+  Xalpha_t, 7,
+  -1,
+  Xalpha_u, 0,
+  Xalpha_u, 1,
+  Xalpha_u, 2,
+  Xalpha_u, 3,
+  Xalpha_u, 4,
+  Xalpha_u, 5,
+  Xalpha_u, 6,
+  Xalpha_u, 7,
+  -1,
+  Xalpha_v, 0,
+  Xalpha_v, 1,
+  Xalpha_v, 2,
+  Xalpha_v, 3,
+  Xalpha_v, 4,
+  Xalpha_v, 5,
+  Xalpha_v, 6,
+  Xalpha_v, 7,
+  -1,
+  Xalpha_w, 0,
+  Xalpha_w, 1,
+  Xalpha_w, 2,
+  Xalpha_w, 3,
+  Xalpha_w, 4,
+  Xalpha_w, 5,
+  Xalpha_w, 6,
+  Xalpha_w, 7,
+  -1,
+  Xalpha_x, 0,
+  Xalpha_x, 1,
+  Xalpha_x, 2,
+  Xalpha_x, 3,
+  Xalpha_x, 4,
+  Xalpha_x, 5,
+  Xalpha_x, 6,
+  Xalpha_x, 7,
+  -1,
+  Xalpha_y, 0,
+  Xalpha_y, 1,
+  Xalpha_y, 2,
+  Xalpha_y, 3,
+  Xalpha_y, 4,
+  Xalpha_y, 5,
+  Xalpha_y, 6,
+  Xalpha_y, 7,
+  -1,
+  Xalpha_z, 0,
+  Xalpha_z, 1,
+  Xalpha_z, 2,
+  Xalpha_z, 3,
+  Xalpha_z, 4,
+  Xalpha_z, 5,
+  Xalpha_z, 6,
+  Xalpha_z, 7,
+  -1,
+  Xalpha_copyr, 0,
+  Xalpha_copyr, 1,
+  Xalpha_copyr, 2,
+  Xalpha_copyr, 3,
+  Xalpha_copyr, 4,
+  Xalpha_copyr, 5,
+  Xalpha_copyr, 6,
+  Xalpha_copyr, 7,
+  -1,
+
+  Yball_eat, 7,
+  Yball_eat, 6,
+  Yball_eat, 5,
+  Ykey_1_eat, 7,
+  Ykey_1_eat, 6,
+  Ykey_1_eat, 5,
+  Ykey_2_eat, 7,
+  Ykey_2_eat, 6,
+  Ykey_2_eat, 5,
+  Ykey_3_eat, 7,
+  Ykey_3_eat, 6,
+  Ykey_3_eat, 5,
+  Ykey_4_eat, 7,
+  Ykey_4_eat, 6,
+  Ykey_4_eat, 5,
+  Ykey_5_eat, 7,
+  Ykey_5_eat, 6,
+  Ykey_5_eat, 5,
+  Ykey_6_eat, 7,
+  Ykey_6_eat, 6,
+  Ykey_6_eat, 5,
+  Ykey_7_eat, 7,
+  Ykey_7_eat, 6,
+  Ykey_7_eat, 5,
+  Ykey_8_eat, 7,
+  Ykey_8_eat, 6,
+  Ykey_8_eat, 5,
+  Ylenses_eat, 7,
+  Ylenses_eat, 6,
+  Ylenses_eat, 5,
+  Ymagnify_eat, 7,
+  Ymagnify_eat, 6,
+  Ymagnify_eat, 5,
+  Ygrass_eat, 7,
+  Ygrass_eat, 6,
+  Ygrass_eat, 5,
+  Ydirt_eat, 7,
+  Ydirt_eat, 6,
+  Ydirt_eat, 5,
+  Xboom_2, 7,
+  Xboom_2, 6,
+  Xboom_2, 5,
+  -1,
+  Yball_eat, 4,
+  Yball_eat, 3,
+  Yball_eat, 2,
+  Ykey_1_eat, 4,
+  Ykey_1_eat, 3,
+  Ykey_1_eat, 2,
+  Ykey_2_eat, 4,
+  Ykey_2_eat, 3,
+  Ykey_2_eat, 2,
+  Ykey_3_eat, 4,
+  Ykey_3_eat, 3,
+  Ykey_3_eat, 2,
+  Ykey_4_eat, 4,
+  Ykey_4_eat, 3,
+  Ykey_4_eat, 2,
+  Ykey_5_eat, 4,
+  Ykey_5_eat, 3,
+  Ykey_5_eat, 2,
+  Ykey_6_eat, 4,
+  Ykey_6_eat, 3,
+  Ykey_6_eat, 2,
+  Ykey_7_eat, 4,
+  Ykey_7_eat, 3,
+  Ykey_7_eat, 2,
+  Ykey_8_eat, 4,
+  Ykey_8_eat, 3,
+  Ykey_8_eat, 2,
+  Ylenses_eat, 4,
+  Ylenses_eat, 3,
+  Ylenses_eat, 2,
+  Ymagnify_eat, 4,
+  Ymagnify_eat, 3,
+  Ymagnify_eat, 2,
+  Ygrass_eat, 4,
+  Ygrass_eat, 3,
+  Ygrass_eat, 2,
+  Ydirt_eat, 4,
+  Ydirt_eat, 3,
+  Ydirt_eat, 2,
+  Xboom_2, 4,
+  Xboom_2, 3,
+  Xboom_2, 2,
+  -1,
+  Yball_eat, 1,
+  Yball_eat, 0,
+  Ykey_1_eat, 1,
+  Ykey_1_eat, 0,
+  Ykey_2_eat, 1,
+  Ykey_2_eat, 0,
+  Ykey_3_eat, 1,
+  Ykey_3_eat, 0,
+  Ykey_4_eat, 1,
+  Ykey_4_eat, 0,
+  Ykey_5_eat, 1,
+  Ykey_5_eat, 0,
+  Ykey_6_eat, 1,
+  Ykey_6_eat, 0,
+  Ykey_7_eat, 1,
+  Ykey_7_eat, 0,
+  Ykey_8_eat, 1,
+  Ykey_8_eat, 0,
+  Ylenses_eat, 1,
+  Ylenses_eat, 0,
+  Ymagnify_eat, 1,
+  Ymagnify_eat, 0,
+  Ygrass_eat, 1,
+  Ygrass_eat, 0,
+  Ydirt_eat, 1,
+  Ydirt_eat, 0,
+  Xboom_2, 1,
+  Xboom_2, 0,
+  Xboom_1, 7,
+  -1,
+  Xboom_1, 6,
+  Xboom_1, 5,
+  Xboom_android, 7,
+  -1,
+  Xboom_1, 4,
+  Xboom_1, 3,
+  Xboom_bug, 4,
+  Xboom_bomb, 4,
+  Xboom_bug, 3,
+  Xboom_bomb, 3,
+  -1,
+  Xboom_1, 2,
+  Xboom_1, 1,
+  Xboom_bug, 6,
+  Xboom_bomb, 6,
+  Xboom_bug, 5,
+  Xboom_bomb, 5,
+  Xboom_bug, 2,
+  Xboom_bomb, 2,
+  Xboom_bug, 1,
+  Xboom_bomb, 1,
+  -1,
+  Xboom_bug, 0,
+  Xboom_bug, 7,
+  Xboom_bomb, 0,
+  Xboom_bomb, 7,
+  Xboom_1, 0,
+  Ybug_stone, 7,
+  Ybug_spring, 7,
+  Ytank_stone, 7,
+  Ytank_spring, 7,
+  Yeater_stone, 7,
+  Yeater_spring, 7,
+  Yalien_stone, 7,
+  Yalien_spring, 7,
+  Ybomb_eat, 7,
+  -1
+};
+
+int spr_map[] =
+{
+  SPR_walk + 0,                0,      0, 1, 2, 3, 4, 5, 6, 7,
+  SPR_walk + 1,                0,      8, 9, 10, 11, 12, 13, 14, 15,
+  SPR_walk + 2,                0,      16, 17, 18, 19, 20, 21, 22, 23,
+  SPR_walk + 3,                0,      24, 25, 26, 27, 28, 29, 30, 31,
+
+  SPR_push + 0,                0,      32, 33, 34, 35, 36, 35, 34, 33,
+  SPR_push + 1,                0,      37, 38, 39, 40, 41, 40, 39, 38,
+  SPR_push + 2,                0,      42, 43, 44, 45, 46, 45, 44, 43,
+  SPR_push + 3,                0,      47, 48, 49, 50, 51, 50, 49, 48,
+
+  SPR_spray + 0,       0,      52, 52, 52, 52, 52, 52, 52, 52,
+  SPR_spray + 1,       0,      53, 53, 53, 53, 53, 53, 53, 53,
+  SPR_spray + 2,       0,      54, 54, 54, 54, 54, 54, 54, 54,
+  SPR_spray + 3,       0,      55, 55, 55, 55, 55, 55, 55, 55,
+
+  SPR_walk + 0,                1,      56, 57, 58, 59, 60, 61, 62, 63,
+  SPR_walk + 1,                1,      64, 65, 66, 67, 68, 69, 70, 71,
+  SPR_walk + 2,                1,      72, 73, 74, 75, 76, 77, 78, 79,
+  SPR_walk + 3,                1,      80, 81, 82, 83, 84, 85, 86, 87,
+
+  SPR_push + 0,                1,      88, 89, 90, 91, 92, 91, 90, 89,
+  SPR_push + 1,                1,      93, 94, 95, 96, 97, 96, 95, 94,
+  SPR_push + 2,                1,      98, 99, 100, 101, 102, 101, 100, 99,
+  SPR_push + 3,                1,      103, 104, 105, 106, 107, 106, 105, 104,
+
+  SPR_spray + 0,       1,      108, 108, 108, 108, 108, 108, 108, 108,
+  SPR_spray + 1,       1,      109, 109, 109, 109, 109, 109, 109, 109,
+  SPR_spray + 2,       1,      110, 110, 110, 110, 110, 110, 110, 110,
+  SPR_spray + 3,       1,      111, 111, 111, 111, 111, 111, 111, 111,
+
+  SPR_still,           0,      112,112, 112, 112, 112, 112, 112, 112,
+  SPR_still,           1,      113,113, 113, 113, 113, 113, 113, 113,
+
+  SPR_MAX
+};
+
+
+/* 0=stop 1=blank */
+unsigned char tab_blank[TILE_MAX];
+
+/* 0=stop 1=acid */
+unsigned char tab_acid[TILE_MAX];
+
+/* 0=stop 1=amoeba */
+unsigned char tab_amoeba[TILE_MAX];
+
+/* 0=stop 1=move */
+unsigned char tab_android_move[TILE_MAX];
+
+/* normal explosion */
+unsigned short tab_explode_normal[TILE_MAX];
+
+/* dynamite explosion */
+unsigned short tab_explode_dynamite[TILE_MAX];
+
+/* map tiles to coords */
+unsigned short map_obj[8][TILE_MAX];
+
+/* map sprites to coords */
+unsigned short map_spr[2][8][13];
+
+/* map ascii to coords */
+unsigned short map_ttl[128];
+
+/* map tiles and frames to graphic info */
+struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8];
+
+/* map player number, frames and action to graphic info */
+struct GraphicInfo_EM graphic_info_em_player[2][SPR_MAX][8];
+
+void create_tab(int *invert, unsigned char *array)
+{
+  int i;
+  int buffer[TILE_MAX];
+
+  for (i = 0; i < TILE_MAX; i++)
+    buffer[i] = 0;
+
+  for (;invert[0] < TILE_MAX; invert += 2)
+    buffer[invert[0]] = invert[1];
+
+  for (i = 0; i < TILE_MAX; i++)
+    array[i] = buffer[i];
+}
+
+void create_explode()
+{
+  int i;
+  int *tile = tile_explode;
+  int buffer[TILE_MAX];
+
+  for (i = 0; i < TILE_MAX; i++)
+    buffer[i] = Xboom_1;
+  while ((i = *tile++) < TILE_MAX)
+    buffer[i] = i;                     /* these tiles are indestructable */
+  while ((i = *tile++) < TILE_MAX)
+    buffer[i] = *tile++;               /* these tiles are special */
+
+  for (i = 0; i < TILE_MAX; i++)
+    tab_explode_normal[i] = buffer[i];
+
+  while ((i = *tile++) < TILE_MAX)
+    buffer[i] = *tile++;               /* these tiles for dynamite */
+
+  for (i = 0; i < TILE_MAX; i++)
+    tab_explode_dynamite[i] = buffer[i];
+}
+
+void create_obj()
+{
+  int i, j;
+  int *map = obj_map;
+  int buffer[8][TILE_MAX];
+
+#if 0
+
+  int debug = 0;
+
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < TILE_MAX; j++)
+      buffer[i][j] = 0;
+
+  for (i = 0; i < 64; i++)
+  {
+    for (;*map != -1; map += 2)
+    {
+      if (map[0] < 0 || map[0] >= TILE_MAX || map[1] < 0 || map[1] >= 8)
+      {
+       fprintf(stderr, "obj_map: bad tile (%d, %d) @ %d+%d\n",
+               map[0], map[1], i / 16, i % 16);
+       debug = 1;
+       continue;
+      }
+      buffer[map[1]][map[0]]++;
+    }
+    map++;
+  }
+
+  for (i = 0; i < 896; i++)
+  {
+    for (;*map != -1; map += 2)
+    {
+      if (map[0] < 0 || map[0] >= TILE_MAX || map[1] < 0 || map[1] >= 8)
+      {
+       fprintf(stderr, "obj_map: bad tile (%d, %d) @ %d\n", map[0], map[1], i);
+       debug = 1;
+       continue;
+      }
+      buffer[map[1]][map[0]]++;
+    }
+    map++;
+  }
+
+  for (i = 0; i < TILE_MAX; i++)
+  {
+    for (j = 0; j < 8; j++)
+    {
+      switch(buffer[j][i])
+      {
+        case 0:
+         fprintf(stderr, "obj_map: uninitialized (%d, %d)\n", i, j);
+         debug = 1;
+         break;
+        case 1:
+         break; /* good */
+        default:
+         fprintf(stderr, "obj_map: duplicate (%d, %d)\n", i, j);
+         debug = 1;
+         break;
+      }
+    }
+  }
+
+  if (sizeof(obj_map) / sizeof(*obj_map) != map - obj_map)
+  {
+    fprintf(stderr, "obj_map: bad end (%d != %d)\n",
+           sizeof(obj_map) / sizeof(*obj_map), map - obj_map);
+    debug = 1;
+  }
+
+  if (debug == 0)
+    fprintf(stderr, "obj_map: looks good, now disable debug code\n");
+
+  abort();
+
+#else
+
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < TILE_MAX; j++)
+      buffer[i][j] = Xblank;
+
+  /* special case for first 64 entries */
+  for (i = 0; i < 64; i++)
+  {
+    for (;*map != -1; map += 2)
+      buffer[map[1]][map[0]] = i;
+    map++;
+  }
+
+  /* now regular entries */
+  for (i = 0; i < 896 * 16; i += 16)
+  {
+    for (;*map != -1; map += 2)
+      buffer[map[1]][map[0]] = i;
+    map++;
+  }
+
+  for (i = 0; i < 8; i++)
+    for (j = 0; j < TILE_MAX; j++)
+      map_obj[i][j] = buffer[7 - i][j];
+
+#endif
+}
+
+void create_obj_graphics_info_em()
+{
+  int i, j;
+
+  for (i = 0; i < TILE_MAX; i++)
+  {
+    for (j = 0; j < 8; j++)
+    {
+      struct GraphicInfo_EM *g = &graphic_info_em_object[i][j];
+      int obj = map_obj[j][i];
+
+      g->bitmap = objBitmap;
+      g->src_x = (obj / 512) * TILEX;
+      g->src_y = (obj % 512) * TILEY / 16;
+      g->src_offset_x = 0;
+      g->src_offset_y = 0;
+      g->dst_offset_x = 0;
+      g->dst_offset_y = 0;
+      g->width = TILEX;
+      g->height = TILEY;
+
+      g->crumbled_bitmap = NULL;
+      g->crumbled_src_x = 0;
+      g->crumbled_src_y = 0;
+      g->crumbled_border_size = 0;
+
+      g->has_crumbled_graphics = FALSE;
+      g->preserve_background = FALSE;
+
+      /* create unique graphic identifier to decide if tile must be redrawn */
+      g->unique_identifier = obj;
+    }
+  }
+}
+
+void create_spr()
+{
+  int i, j, k;
+  int *map = spr_map;
+  int buffer[2][8][SPR_MAX];
+
+  while (*map < SPR_MAX)
+  {
+    i = *map++;
+    j = *map++;
+
+    for (k = 0; k < 8; k++)
+      buffer[j][k][i] = *map++;
+  }
+
+  for (i = 0; i < 2; i++)
+    for (j = 0; j < 8; j++)
+      for (k = 0; k < SPR_MAX; k++)
+       map_spr[i][j][k] = buffer[i][7 - j][k];
+}
+
+void create_spr_graphics_info_em()
+{
+  int i, j, k;
+
+  for (i = 0; i < 2; i++)
+  {
+    for (j = 0; j < SPR_MAX; j++)
+    {
+      for (k = 0; k < 8; k++)
+      {
+       struct GraphicInfo_EM *g = &graphic_info_em_player[i][j][k];
+       int spr = map_spr[i][k][j];
+
+       g->bitmap = sprBitmap;
+       g->src_x = (spr / 8) * TILEX;
+       g->src_y = (spr % 8) * TILEY;
+       g->src_offset_x = 0;
+       g->src_offset_y = 0;
+       g->dst_offset_x = 0;
+       g->dst_offset_y = 0;
+       g->width = TILEX;
+       g->height = TILEY;
+
+       g->has_crumbled_graphics = FALSE;
+       g->crumbled_bitmap = NULL;
+       g->crumbled_src_x = 0;
+       g->crumbled_src_y = 0;
+       g->crumbled_border_size = 0;
+
+       g->unique_identifier = 0;
+      }
+    }
+  }
+}
+
+void tab_generate()
+{
+  create_tab(tile_blank, tab_blank);
+  create_tab(tile_acid, tab_acid);
+  create_tab(tile_amoeba, tab_amoeba);
+  create_tab(tile_android_move, tab_android_move);
+  create_explode();
+  create_obj();
+  create_spr();
+}
+
+void tab_generate_graphics_info_em()
+{
+  create_obj_graphics_info_em();
+  create_spr_graphics_info_em();
+
+  InitGraphicInfo_EM();
+}
diff --git a/src/game_em/tile.h b/src/game_em/tile.h
new file mode 100644 (file)
index 0000000..6b6dc3e
--- /dev/null
@@ -0,0 +1,454 @@
+#ifndef TILE_H
+#define TILE_H
+
+#include "main_em.h"
+
+#ifdef EM_ENGINE_BAD_ROLL
+#define BAD_ROLL
+#endif
+
+#ifdef EM_ENGINE_BAD_SPRING
+#define BAD_SPRING
+#endif
+
+
+#if 0
+
+/* 2000-07-30T11:06:03Z
+ */
+
+/* define these for backwards compatibility */
+#define BAD_ROLL
+#define BAD_SPRING
+
+enum
+{
+  Xblank = 0, /* still */
+  Yacid_splash_eB, /* hmm */
+  Yacid_splash_wB, /* hmm */
+
+#ifdef BAD_ROLL
+  Xstone_force_e, /* only use these in eater */
+  Xstone_force_w,
+  Xnut_force_e,
+  Xnut_force_w,
+  Xspring_force_e,
+  Xspring_force_w,
+  Xemerald_force_e,
+  Xemerald_force_w,
+  Xdiamond_force_e,
+  Xdiamond_force_w,
+  Xbomb_force_e,
+  Xbomb_force_w,
+#endif
+
+  Xstone,
+  Xstone_pause,
+  Xstone_fall,
+  Ystone_s,
+  Ystone_sB,
+  Ystone_e,
+  Ystone_eB,
+  Ystone_w,
+  Ystone_wB,
+  Xnut,
+  Xnut_pause,
+  Xnut_fall,
+  Ynut_s,
+  Ynut_sB,
+  Ynut_e,
+  Ynut_eB,
+  Ynut_w,
+  Ynut_wB,
+  Xbug_n,
+  Xbug_e,
+  Xbug_s,
+  Xbug_w,
+  Xbug_gon,
+  Xbug_goe,
+  Xbug_gos,
+  Xbug_gow,
+  Ybug_n,
+  Ybug_nB,
+  Ybug_e,
+  Ybug_eB,
+  Ybug_s,
+  Ybug_sB,
+  Ybug_w,
+  Ybug_wB,
+  Ybug_w_n,
+  Ybug_n_e,
+  Ybug_e_s,
+  Ybug_s_w,
+  Ybug_e_n,
+  Ybug_s_e,
+  Ybug_w_s,
+  Ybug_n_w,
+  Ybug_stone,
+  Ybug_spring,
+  Xtank_n,
+  Xtank_e,
+  Xtank_s,
+  Xtank_w,
+  Xtank_gon,
+  Xtank_goe,
+  Xtank_gos,
+  Xtank_gow,
+  Ytank_n,
+  Ytank_nB,
+  Ytank_e,
+  Ytank_eB,
+  Ytank_s,
+  Ytank_sB,
+  Ytank_w,
+  Ytank_wB,
+  Ytank_w_n,
+  Ytank_n_e,
+  Ytank_e_s,
+  Ytank_s_w,
+  Ytank_e_n,
+  Ytank_s_e,
+  Ytank_w_s,
+  Ytank_n_w,
+  Ytank_stone,
+  Ytank_spring,
+  Xandroid,
+  Xandroid_1_n,
+  Xandroid_2_n,
+  Xandroid_1_e,
+  Xandroid_2_e,
+  Xandroid_1_w,
+  Xandroid_2_w,
+  Xandroid_1_s,
+  Xandroid_2_s,
+  Yandroid_n,
+  Yandroid_nB,
+  Yandroid_ne,
+  Yandroid_neB,
+  Yandroid_e,
+  Yandroid_eB,
+  Yandroid_se,
+  Yandroid_seB,
+  Yandroid_s,
+  Yandroid_sB,
+  Yandroid_sw,
+  Yandroid_swB,
+  Yandroid_w,
+  Yandroid_wB,
+  Yandroid_nw,
+  Yandroid_nwB,
+  Xspring,
+  Xspring_pause,
+  Xspring_e,
+  Xspring_w,
+  Xspring_fall,
+  Yspring_s,
+  Yspring_sB,
+  Yspring_e,
+  Yspring_eB,
+  Yspring_w,
+  Yspring_wB,
+  Yspring_kill_e,
+  Yspring_kill_eB,
+  Yspring_kill_w,
+  Yspring_kill_wB,
+  Xeater_n,
+  Xeater_e,
+  Xeater_w,
+  Xeater_s,
+  Yeater_n,
+  Yeater_nB,
+  Yeater_e,
+  Yeater_eB,
+  Yeater_s,
+  Yeater_sB,
+  Yeater_w,
+  Yeater_wB,
+  Yeater_stone,
+  Yeater_spring,
+  Xalien,
+  Xalien_pause,
+  Yalien_n,
+  Yalien_nB,
+  Yalien_e,
+  Yalien_eB,
+  Yalien_s,
+  Yalien_sB,
+  Yalien_w,
+  Yalien_wB,
+  Yalien_stone,
+  Yalien_spring,
+  Xemerald,
+  Xemerald_pause,
+  Xemerald_fall,
+  Xemerald_shine,
+  Yemerald_s,
+  Yemerald_sB,
+  Yemerald_e,
+  Yemerald_eB,
+  Yemerald_w,
+  Yemerald_wB,
+  Yemerald_eat,
+  Yemerald_stone,
+  Xdiamond,
+  Xdiamond_pause,
+  Xdiamond_fall,
+  Xdiamond_shine,
+  Ydiamond_s,
+  Ydiamond_sB,
+  Ydiamond_e,
+  Ydiamond_eB,
+  Ydiamond_w,
+  Ydiamond_wB,
+  Ydiamond_eat,
+  Ydiamond_stone,
+  Xdrip_fall,
+  Xdrip_stretch,
+  Xdrip_stretchB,
+  Xdrip_eat,
+  Ydrip_s1,
+  Ydrip_s1B,
+  Ydrip_s2,
+  Ydrip_s2B,
+  Xbomb,
+  Xbomb_pause,
+  Xbomb_fall,
+  Ybomb_s,
+  Ybomb_sB,
+  Ybomb_e,
+  Ybomb_eB,
+  Ybomb_w,
+  Ybomb_wB,
+  Ybomb_eat,
+  Xballoon,
+  Yballoon_n,
+  Yballoon_nB,
+  Yballoon_e,
+  Yballoon_eB,
+  Yballoon_s,
+  Yballoon_sB,
+  Yballoon_w,
+  Yballoon_wB,
+  Xgrass,
+  Ygrass_nB,
+  Ygrass_eB,
+  Ygrass_sB,
+  Ygrass_wB,
+  Xdirt,
+  Ydirt_nB,
+  Ydirt_eB,
+  Ydirt_sB,
+  Ydirt_wB,
+  Xacid_ne,
+  Xacid_se,
+  Xacid_s,
+  Xacid_sw,
+  Xacid_nw,
+  Xacid_1,
+  Xacid_2,
+  Xacid_3,
+  Xacid_4,
+  Xacid_5,
+  Xacid_6,
+  Xacid_7,
+  Xacid_8,
+  Xball_1,
+  Xball_1B,
+  Xball_2,
+  Xball_2B,
+  Yball_eat,
+  Xgrow_ns,
+  Ygrow_ns_eat,
+  Xgrow_ew,
+  Ygrow_ew_eat,
+  Xwonderwall,
+  XwonderwallB,
+  Xamoeba_1,
+  Xamoeba_2,
+  Xamoeba_3,
+  Xamoeba_4,
+  Xamoeba_5,
+  Xamoeba_6,
+  Xamoeba_7,
+  Xamoeba_8,
+  Xdoor_1,
+  Xdoor_2,
+  Xdoor_3,
+  Xdoor_4,
+  Xdoor_5,
+  Xdoor_6,
+  Xdoor_7,
+  Xdoor_8,
+  Xkey_1,
+  Xkey_2,
+  Xkey_3,
+  Xkey_4,
+  Xkey_5,
+  Xkey_6,
+  Xkey_7,
+  Xkey_8,
+  Xwind_n,
+  Xwind_e,
+  Xwind_s,
+  Xwind_w,
+  Xwind_nesw,
+  Xwind_stop,
+  Xexit,
+  Xexit_1,
+  Xexit_2,
+  Xexit_3,
+  Xdynamite,
+  Ydynamite_eat,
+  Xdynamite_1,
+  Xdynamite_2,
+  Xdynamite_3,
+  Xdynamite_4,
+  Xbumper,
+  XbumperB,
+  Xwheel,
+  XwheelB,
+  Xswitch,
+  XswitchB,
+  Xsand,
+  Xsand_stone,
+  Xsand_stonein_1,
+  Xsand_stonein_2,
+  Xsand_stonein_3,
+  Xsand_stonein_4,
+  Xsand_stonesand_1,
+  Xsand_stonesand_2,
+  Xsand_stonesand_3,
+  Xsand_stonesand_4,
+  Xsand_stoneout_1,
+  Xsand_stoneout_2,
+  Xsand_sandstone_1,
+  Xsand_sandstone_2,
+  Xsand_sandstone_3,
+  Xsand_sandstone_4,
+  Xplant,
+  Yplant,
+  Xlenses,
+  Xmagnify,
+  Xdripper,
+  XdripperB,
+  Xfake_blank,
+  Xfake_blankB,
+  Xfake_grass,
+  Xfake_grassB,
+  Xfake_door_1,
+  Xfake_door_2,
+  Xfake_door_3,
+  Xfake_door_4,
+  Xfake_door_5,
+  Xfake_door_6,
+  Xfake_door_7,
+  Xfake_door_8,
+  Xsteel_1,
+  Xsteel_2,
+  Xsteel_3,
+  Xsteel_4,
+  Xwall_1,
+  Xwall_2,
+  Xwall_3,
+  Xwall_4,
+  Xround_wall_1,
+  Xround_wall_2,
+  Xround_wall_3,
+  Xround_wall_4,
+  Xdecor_1,
+  Xdecor_2,
+  Xdecor_3,
+  Xdecor_4,
+  Xdecor_5,
+  Xdecor_6,
+  Xdecor_7,
+  Xdecor_8,
+  Xdecor_9,
+  Xdecor_10,
+  Xdecor_11,
+  Xdecor_12,
+  Xalpha_0,
+  Xalpha_1,
+  Xalpha_2,
+  Xalpha_3,
+  Xalpha_4,
+  Xalpha_5,
+  Xalpha_6,
+  Xalpha_7,
+  Xalpha_8,
+  Xalpha_9,
+  Xalpha_excla,
+  Xalpha_quote,
+  Xalpha_comma,
+  Xalpha_minus,
+  Xalpha_perio,
+  Xalpha_colon,
+  Xalpha_quest,
+  Xalpha_a,
+  Xalpha_b,
+  Xalpha_c,
+  Xalpha_d,
+  Xalpha_e,
+  Xalpha_f,
+  Xalpha_g,
+  Xalpha_h,
+  Xalpha_i,
+  Xalpha_j,
+  Xalpha_k,
+  Xalpha_l,
+  Xalpha_m,
+  Xalpha_n,
+  Xalpha_o,
+  Xalpha_p,
+  Xalpha_q,
+  Xalpha_r,
+  Xalpha_s,
+  Xalpha_t,
+  Xalpha_u,
+  Xalpha_v,
+  Xalpha_w,
+  Xalpha_x,
+  Xalpha_y,
+  Xalpha_z,
+  Xalpha_arrow_e,
+  Xalpha_arrow_w,
+  Xalpha_copyr,
+
+  Xboom_bug, /* passed from explode to synchro (linked explosion); transition to explode_normal */
+  Xboom_bomb, /* passed from explode to synchro (linked explosion); transition to explode_normal */
+  Xboom_android, /* passed from explode to synchro; transition to boom_2 */
+  Xboom_1, /* passed from explode to synchro; transition to boom_2 */
+  Xboom_2, /* transition to boom[] */
+
+  Znormal, /* no picture */ /* this tile is passed from synchro to explode, only in next[] */
+  Zdynamite, /* no picture */ /* this tile is passed from synchro to explode, only in next[] */
+  Zplayer, /* no picture */ /* special code to indicate player */
+  ZBORDER, /* no picture */ /* special code to indicate border */
+
+  TILE_MAX
+};
+
+enum
+{
+  SPR_still = 0,
+  SPR_walk  = 1,
+  SPR_push  = 5,
+  SPR_spray = 9,
+
+  SPR_MAX   = 13
+};
+
+#endif
+
+extern unsigned char tab_blank[TILE_MAX];
+extern unsigned char tab_acid[TILE_MAX];
+extern unsigned char tab_amoeba[TILE_MAX];
+extern unsigned char tab_android_move[TILE_MAX];
+extern unsigned short tab_explode_normal[TILE_MAX];
+extern unsigned short tab_explode_dynamite[TILE_MAX];
+
+extern unsigned short map_obj[8][TILE_MAX];
+extern unsigned short map_spr[2][8][SPR_MAX];
+extern unsigned short map_ttl[128];
+
+#endif
diff --git a/src/game_em/ulaw_generate.c b/src/game_em/ulaw_generate.c
new file mode 100644 (file)
index 0000000..7c06c30
--- /dev/null
@@ -0,0 +1,136 @@
+/* 2000-08-10T04:29:10Z
+ *
+ * generate ulaw<->linear conversion tables to be included
+ * directly in emerald mine source
+ */
+
+#include "main_em.h"
+
+
+#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
+
+int calc_ulaw_to_linear(unsigned char);
+unsigned char calc_linear_to_ulaw(int);
+
+int buffer[65536];
+
+/* convert from 8 bit ulaw to signed 16 bit linear */
+short ulaw_to_linear[256];
+
+/* convert from signed 16 bit linear to 8 bit ulaw */
+unsigned char linear_to_ulaw[65536];
+
+void ulaw_generate()
+{
+  int i;
+
+  for(i = 0; i < 256; i++)
+    ulaw_to_linear[i] = calc_ulaw_to_linear(i);
+
+  for(i = -32768; i < 32768; i++)
+    linear_to_ulaw[i + 32768] = calc_linear_to_ulaw(i);
+}
+
+/*
+** This routine converts from ulaw to 16 bit linear.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711  (very difficult to follow)
+** 2) MIL-STD-188-113,"Interoperability and Performance Standards
+**     for Analog-to_Digital Conversion Techniques,"
+**     17 February 1987
+**
+** Input: 8 bit ulaw sample
+** Output: signed 16 bit linear sample
+*/
+
+int calc_ulaw_to_linear(unsigned char ulawbyte)
+{
+  static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
+  int sign, exponent, mantissa, sample;
+
+  ulawbyte = ~ ulawbyte;
+  sign = ( ulawbyte & 0x80 );
+  exponent = ( ulawbyte >> 4 ) & 0x07;
+  mantissa = ulawbyte & 0x0F;
+  sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
+  if (sign != 0)
+    sample = -sample;
+
+  return(sample);
+}
+
+/*
+** This routine converts from linear to ulaw.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** Joe Campbell: Department of Defense
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711  (very difficult to follow)
+** 2) "A New Digital Technique for Implementation of Any
+**     Continuous PCM Companding Law," Villeret, Michel,
+**     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
+**     1973, pg. 11.12-11.17
+** 3) MIL-STD-188-113,"Interoperability and Performance Standards
+**     for Analog-to_Digital Conversion Techniques,"
+**     17 February 1987
+**
+** Input: Signed 16 bit linear sample
+** Output: 8 bit ulaw sample
+*/
+
+#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
+#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+
+unsigned char calc_linear_to_ulaw(int sample)
+{
+  static int exp_lut[256] =
+  {
+    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+  };
+
+  int sign, exponent, mantissa;
+  unsigned char ulawbyte;
+
+/* Get the sample into sign-magnitude. */
+  sign = (sample >> 8) & 0x80; /* set aside the sign */
+  if (sign != 0)
+    sample = -sample; /* get magnitude */
+  if (sample > CLIP)
+    sample = CLIP; /* clip the magnitude */
+
+/* Convert from 16 bit linear to ulaw. */
+  sample = sample + BIAS;
+  exponent = exp_lut[( sample >> 7 ) & 0xFF];
+  mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
+  ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
+#ifdef ZEROTRAP
+  if (ulawbyte == 0)
+    ulawbyte = 0x02; /* optional CCITT trap */
+#endif
+
+  return(ulawbyte);
+}
+
+#endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) */
index 02b29cdc66275026b1f57773c30654ef56a791c0..1f58073285447eaab1dac4f132d8be8288442f8c 100644 (file)
 #define CONFIG_TOKEN_FONT_INITIAL              "font.initial"
 
 
-struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
+static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
 
+static int copy_properties[][5] =
+{
+  {
+    EL_BUG,
+    EL_BUG_LEFT,               EL_BUG_RIGHT,
+    EL_BUG_UP,                 EL_BUG_DOWN
+  },
+  {
+    EL_SPACESHIP,
+    EL_SPACESHIP_LEFT,         EL_SPACESHIP_RIGHT,
+    EL_SPACESHIP_UP,           EL_SPACESHIP_DOWN
+  },
+  {
+    EL_BD_BUTTERFLY,
+    EL_BD_BUTTERFLY_LEFT,      EL_BD_BUTTERFLY_RIGHT,
+    EL_BD_BUTTERFLY_UP,                EL_BD_BUTTERFLY_DOWN
+  },
+  {
+    EL_BD_FIREFLY,
+    EL_BD_FIREFLY_LEFT,                EL_BD_FIREFLY_RIGHT,
+    EL_BD_FIREFLY_UP,          EL_BD_FIREFLY_DOWN
+  },
+  {
+    EL_PACMAN,
+    EL_PACMAN_LEFT,            EL_PACMAN_RIGHT,
+    EL_PACMAN_UP,              EL_PACMAN_DOWN
+  },
+  {
+    EL_MOLE,
+    EL_MOLE_LEFT,              EL_MOLE_RIGHT,
+    EL_MOLE_UP,                        EL_MOLE_DOWN
+  },
+  {
+    -1,
+    -1, -1, -1, -1
+  }
+};
 
 static void InitTileClipmasks()
 {
@@ -239,6 +276,11 @@ void InitGadgets()
   gadgets_initialized = TRUE;
 }
 
+inline void InitElementSmallImagesScaledUp(int graphic)
+{
+  CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
+}
+
 void InitElementSmallImages()
 {
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
@@ -247,18 +289,40 @@ void InitElementSmallImages()
 
   /* initialize normal images from static configuration */
   for (i = 0; element_to_graphic[i].element > -1; i++)
-    CreateImageWithSmallImages(element_to_graphic[i].graphic);
+    InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
 
   /* initialize special images from static configuration */
   for (i = 0; element_to_special_graphic[i].element > -1; i++)
-    CreateImageWithSmallImages(element_to_special_graphic[i].graphic);
+    InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
 
-  /* initialize images from dynamic configuration */
+  /* initialize images from dynamic configuration (may be elements or other) */
+#if 1
+  for (i = 0; i < num_property_mappings; i++)
+    InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+#else
+  /* !!! THIS DOES NOT WORK -- "artwork_index" is graphic, not element !!! */
+  /* !!! ALSO, non-element graphics might need scaling-up !!! */
   for (i = 0; i < num_property_mappings; i++)
     if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
-      CreateImageWithSmallImages(property_mapping[i].artwork_index);
+      InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+#endif
+
+#if 0
+  /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
+  for (i = IMG_EMC_OBJECT; i <= IMG_EMC_SPRITE; i++)
+    InitElementSmallImagesScaledUp(i);
+#endif
 }
 
+#if 1
+/* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
+void SetBitmaps_EM(Bitmap **em_bitmap)
+{
+  em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
+  em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
+}
+#endif
+
 static int getFontBitmapID(int font_nr)
 {
   int special = -1;
@@ -448,8 +512,10 @@ void InitElementGraphicInfo()
     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
        base_graphic != -1)
     {
-      boolean base_redefined = getImageListEntry(base_graphic)->redefined;
-      boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
+      boolean base_redefined =
+       getImageListEntryFromImageID(base_graphic)->redefined;
+      boolean act_dir_redefined =
+       getImageListEntryFromImageID(graphic)->redefined;
 
       /* if the base graphic ("emerald", for example) has been redefined,
         but not the action graphic ("emerald.falling", for example), do not
@@ -560,6 +626,11 @@ void InitElementGraphicInfo()
     }
   }
 
+#if 1
+  /* set hardcoded definitions for some runtime elements without graphic */
+  element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
+#endif
+
 #if 1
   /* now set all undefined/invalid graphics to -1 to set to default after it */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
@@ -590,6 +661,94 @@ void InitElementGraphicInfo()
   }
 #endif
 
+#if 1
+  /* adjust graphics with 2nd tile for movement according to direction
+     (do this before correcting '-1' values to minimize calculations) */
+  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+  {
+    for (act = 0; act < NUM_ACTIONS; act++)
+    {
+      for (dir = 0; dir < NUM_DIRECTIONS; dir++)
+      {
+       int graphic = element_info[i].direction_graphic[act][dir];
+       int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
+
+       if (act == ACTION_FALLING)      /* special case */
+         graphic = element_info[i].graphic[act];
+
+       if (graphic != -1 &&
+           graphic_info[graphic].double_movement &&
+           graphic_info[graphic].swap_double_tiles != 0)
+       {
+         struct GraphicInfo *g = &graphic_info[graphic];
+         int src_x_front = g->src_x;
+         int src_y_front = g->src_y;
+         int src_x_back = g->src_x + g->offset2_x;
+         int src_y_back = g->src_y + g->offset2_y;
+         boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
+                                                  g->offset_y != 0);
+         boolean front_is_left_or_upper = (src_x_front < src_x_back ||
+                                           src_y_front < src_y_back);
+#if 0
+         boolean second_tile_is_back =
+           ((move_dir == MV_BIT_LEFT  && front_is_left_or_upper) ||
+            (move_dir == MV_BIT_UP    && front_is_left_or_upper));
+         boolean second_tile_is_front =
+           ((move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
+            (move_dir == MV_BIT_DOWN  && front_is_left_or_upper));
+         boolean second_tile_should_be_front =
+           (g->second_tile_is_start == 0);
+         boolean second_tile_should_be_back =
+           (g->second_tile_is_start == 1);
+#endif
+         boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
+         boolean swap_movement_tiles_autodetected =
+           (!frames_are_ordered_diagonally &&
+            ((move_dir == MV_BIT_LEFT  && !front_is_left_or_upper) ||
+             (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
+             (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
+             (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
+         Bitmap *dummy;
+
+#if 0
+         printf("::: CHECKING element %d ('%s'), '%s', dir %d [(%d -> %d, %d), %d => %d]\n",
+                i, element_info[i].token_name,
+                element_action_info[act].suffix, move_dir,
+                g->swap_double_tiles,
+                swap_movement_tiles_never,
+                swap_movement_tiles_always,
+                swap_movement_tiles_autodetected,
+                swap_movement_tiles);
+#endif
+
+         /* swap frontside and backside graphic tile coordinates, if needed */
+         if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
+         {
+           /* get current (wrong) backside tile coordinates */
+           getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
+                               TRUE);
+
+           /* set frontside tile coordinates to backside tile coordinates */
+           g->src_x = src_x_back;
+           g->src_y = src_y_back;
+
+           /* invert tile offset to point to new backside tile coordinates */
+           g->offset2_x *= -1;
+           g->offset2_y *= -1;
+
+           /* do not swap front and backside tiles again after correction */
+           g->swap_double_tiles = 0;
+
+#if 0
+           printf("    CORRECTED\n");
+#endif
+         }
+       }
+      }
+    }
+  }
+#endif
+
   /* now set all '-1' values to element specific default values */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
@@ -600,8 +759,14 @@ void InitElementGraphicInfo()
 
     if (default_graphic == -1)
       default_graphic = IMG_UNKNOWN;
+#if 1
+    if (default_crumbled == -1)
+      default_crumbled = default_graphic;
+#else
+    /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
     if (default_crumbled == -1)
       default_crumbled = IMG_EMPTY;
+#endif
 
     for (dir = 0; dir < NUM_DIRECTIONS; dir++)
     {
@@ -612,8 +777,14 @@ void InitElementGraphicInfo()
 
       if (default_direction_graphic[dir] == -1)
        default_direction_graphic[dir] = default_graphic;
+#if 1
+      if (default_direction_crumbled[dir] == -1)
+       default_direction_crumbled[dir] = default_direction_graphic[dir];
+#else
+      /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
       if (default_direction_crumbled[dir] == -1)
        default_direction_crumbled[dir] = default_crumbled;
+#endif
     }
 
     for (act = 0; act < NUM_ACTIONS; act++)
@@ -629,6 +800,10 @@ void InitElementGraphicInfo()
       /* generic default action graphic (defined by "[default]" directive) */
       int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
       int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
+      int default_remove_graphic = IMG_EMPTY;
+
+      if (act_remove && default_action_graphic != -1)
+       default_remove_graphic = default_action_graphic;
 
       /* look for special default action graphic (classic game specific) */
       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
@@ -646,6 +821,7 @@ void InitElementGraphicInfo()
        default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
 
 #if 1
+      /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
       /* !!! make this better !!! */
       if (i == EL_EMPTY_SPACE)
       {
@@ -656,47 +832,81 @@ void InitElementGraphicInfo()
 
       if (default_action_graphic == -1)
        default_action_graphic = default_graphic;
+#if 1
+      if (default_action_crumbled == -1)
+       default_action_crumbled = default_action_graphic;
+#else
+      /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
       if (default_action_crumbled == -1)
        default_action_crumbled = default_crumbled;
+#endif
 
       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
       {
+       /* use action graphic as the default direction graphic, if undefined */
        int default_action_direction_graphic = element_info[i].graphic[act];
        int default_action_direction_crumbled = element_info[i].crumbled[act];
 
        /* no graphic for current action -- use default direction graphic */
        if (default_action_direction_graphic == -1)
          default_action_direction_graphic =
-           (act_remove ? IMG_EMPTY :
+           (act_remove ? default_remove_graphic :
             act_turning ?
             element_info[i].direction_graphic[ACTION_TURNING][dir] :
+            default_action_graphic != default_graphic ?
+            default_action_graphic :
             default_direction_graphic[dir]);
+
+       if (element_info[i].direction_graphic[act][dir] == -1)
+         element_info[i].direction_graphic[act][dir] =
+           default_action_direction_graphic;
+
+#if 1
+       if (default_action_direction_crumbled == -1)
+         default_action_direction_crumbled =
+           element_info[i].direction_graphic[act][dir];
+#else
        if (default_action_direction_crumbled == -1)
          default_action_direction_crumbled =
-           (act_remove ? IMG_EMPTY :
+           (act_remove ? default_remove_graphic :
             act_turning ?
             element_info[i].direction_crumbled[ACTION_TURNING][dir] :
+            default_action_crumbled != default_crumbled ?
+            default_action_crumbled :
             default_direction_crumbled[dir]);
+#endif
 
-       if (element_info[i].direction_graphic[act][dir] == -1)
-         element_info[i].direction_graphic[act][dir] =
-           default_action_direction_graphic;
        if (element_info[i].direction_crumbled[act][dir] == -1)
          element_info[i].direction_crumbled[act][dir] =
            default_action_direction_crumbled;
+
+#if 0
+       if (i == EL_EMC_GRASS &&
+           act == ACTION_DIGGING &&
+           dir == MV_BIT_DOWN)
+         printf("::: direction_crumbled == %d, %d, %d\n",
+                element_info[i].direction_crumbled[act][dir],
+                default_action_direction_crumbled,
+                element_info[i].crumbled[act]);
+#endif
       }
 
       /* no graphic for this specific action -- use default action graphic */
       if (element_info[i].graphic[act] == -1)
        element_info[i].graphic[act] =
-         (act_remove ? IMG_EMPTY :
+         (act_remove ? default_remove_graphic :
           act_turning ? element_info[i].graphic[ACTION_TURNING] :
           default_action_graphic);
+#if 1
+      if (element_info[i].crumbled[act] == -1)
+       element_info[i].crumbled[act] = element_info[i].graphic[act];
+#else
       if (element_info[i].crumbled[act] == -1)
        element_info[i].crumbled[act] =
-         (act_remove ? IMG_EMPTY :
+         (act_remove ? default_remove_graphic :
           act_turning ? element_info[i].crumbled[ACTION_TURNING] :
           default_action_crumbled);
+#endif
     }
   }
 
@@ -761,8 +971,10 @@ void InitElementSpecialGraphicInfo()
     int special = element_to_special_graphic[i].special;
     int graphic = element_to_special_graphic[i].graphic;
     int base_graphic = el2baseimg(element);
-    boolean base_redefined = getImageListEntry(base_graphic)->redefined;
-    boolean special_redefined = getImageListEntry(graphic)->redefined;
+    boolean base_redefined =
+      getImageListEntryFromImageID(base_graphic)->redefined;
+    boolean special_redefined =
+      getImageListEntryFromImageID(graphic)->redefined;
 
     /* if the base graphic ("emerald", for example) has been redefined,
        but not the special graphic ("emerald.EDITOR", for example), do not
@@ -809,14 +1021,75 @@ static int get_element_from_token(char *token)
   return -1;
 }
 
-static void set_graphic_parameters(int graphic, char **parameter_raw)
+static int get_scaled_graphic_width(int graphic)
 {
-  Bitmap *src_bitmap = getBitmapFromImageID(graphic);
+  int original_width = getOriginalImageWidthFromImageID(graphic);
+  int scale_up_factor = graphic_info[graphic].scale_up_factor;
+
+  return original_width * scale_up_factor;
+}
+
+static int get_scaled_graphic_height(int graphic)
+{
+  int original_height = getOriginalImageHeightFromImageID(graphic);
+  int scale_up_factor = graphic_info[graphic].scale_up_factor;
+
+  return original_height * scale_up_factor;
+}
+
+static void set_graphic_parameters(int graphic, int graphic_copy_from)
+{
+  struct FileInfo *image = getImageListEntryFromImageID(graphic_copy_from);
+  char **parameter_raw = image->parameter;
+  Bitmap *src_bitmap = getBitmapFromImageID(graphic_copy_from);
   int parameter[NUM_GFX_ARGS];
   int anim_frames_per_row = 1, anim_frames_per_col = 1;
   int anim_frames_per_line = 1;
   int i;
 
+#if 1
+#if 1
+
+  /* !!! NEW ARTWORK FALLBACK CODE !!! NEARLY UNTESTED !!! */
+  /* if fallback to default artwork is done, also use the default parameters */
+  if (image->fallback_to_default)
+  {
+#if 0
+    printf("::: FALLBACK for %d\n", graphic_copy_from);
+#endif
+
+    parameter_raw = image->default_parameter;
+  }
+
+#else
+
+  /* !!! ARTWORK FALLBACK CODE !!! NEARLY UNTESTED !!! */
+  /* (better try to set a "fallback -> use default parameters" flag) */
+  if (src_bitmap)
+  {
+    int len_source_filename = strlen(src_bitmap->source_filename);
+    int len_default_filename = strlen(image->default_filename);
+    int pos_basename = len_source_filename - len_default_filename;
+    char *source_basename = &src_bitmap->source_filename[pos_basename];
+
+#if 0
+    printf("::: src_bitmap->source_filename -> '%s'\n",
+          src_bitmap->source_filename);
+    printf("::: image->default_filename     -> '%s'\n",
+          image->default_filename);
+    printf("::: image->filename             -> '%s'\n",
+          image->filename);
+#endif
+
+    /* check if there was a fallback to the default artwork file */
+    if (strcmp(image->filename, image->default_filename) != 0 &&
+       pos_basename >= 0 &&
+       strcmp(source_basename, image->default_filename) == 0)
+      parameter_raw = image->default_parameter;
+  }
+#endif
+#endif
+
   /* get integer values from string parameters */
   for (i = 0; i < NUM_GFX_ARGS; i++)
   {
@@ -837,9 +1110,13 @@ static void set_graphic_parameters(int graphic, char **parameter_raw)
   graphic_info[graphic].height = TILEY;
   graphic_info[graphic].offset_x = 0;  /* one or both of these values ... */
   graphic_info[graphic].offset_y = 0;  /* ... will be corrected later */
+  graphic_info[graphic].offset2_x = 0; /* one or both of these values ... */
+  graphic_info[graphic].offset2_y = 0; /* ... will be corrected later */
+  graphic_info[graphic].swap_double_tiles = -1;        /* auto-detect tile swapping */
   graphic_info[graphic].crumbled_like = -1;    /* do not use clone element */
   graphic_info[graphic].diggable_like = -1;    /* do not use clone element */
   graphic_info[graphic].border_size = TILEX / 8;  /* "CRUMBLED" border size */
+  graphic_info[graphic].scale_up_factor = 1;   /* default: no scaling up */
   graphic_info[graphic].anim_delay_fixed = 0;
   graphic_info[graphic].anim_delay_random = 0;
   graphic_info[graphic].post_delay_fixed = 0;
@@ -863,10 +1140,20 @@ static void set_graphic_parameters(int graphic, char **parameter_raw)
   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
     graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
 
+  /* optional zoom factor for scaling up the image to a larger size */
+  if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
+    graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
+  if (graphic_info[graphic].scale_up_factor < 1)
+    graphic_info[graphic].scale_up_factor = 1;         /* no scaling */
+
   if (src_bitmap)
   {
-    anim_frames_per_row = src_bitmap->width  / graphic_info[graphic].width;
-    anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
+    /* get final bitmap size (with scaling, but without small images) */
+    int src_bitmap_width  = get_scaled_graphic_width(graphic);
+    int src_bitmap_height = get_scaled_graphic_height(graphic);
+
+    anim_frames_per_row = src_bitmap_width  / graphic_info[graphic].width;
+    anim_frames_per_col = src_bitmap_height / graphic_info[graphic].height;
   }
 
   /* correct x or y offset dependent of vertical or horizontal frame order */
@@ -891,6 +1178,32 @@ static void set_graphic_parameters(int graphic, char **parameter_raw)
   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
     graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
 
+  /* optionally, moving animations may have separate start and end graphics */
+  graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
+
+  if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
+    parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
+
+  /* correct x or y offset2 dependent of vertical or horizontal frame order */
+  if (parameter[GFX_ARG_2ND_VERTICAL]) /* frames are ordered vertically */
+    graphic_info[graphic].offset2_y =
+      (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
+       parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
+  else                                 /* frames are ordered horizontally */
+    graphic_info[graphic].offset2_x =
+      (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
+       parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
+
+  /* optionally, the x and y offset of 2nd graphic can be specified directly */
+  if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
+    graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
+  if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
+    graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
+
+  /* optionally, the second movement tile can be specified as start tile */
+  if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
+    graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
+
   /* automatically determine correct number of frames, if not defined */
   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
     graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
@@ -968,8 +1281,6 @@ static void set_graphic_parameters(int graphic, char **parameter_raw)
 static void InitGraphicInfo()
 {
   int fallback_graphic = IMG_CHAR_EXCLAM;
-  struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
-  Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
   int num_images = getImageListSize();
   int i;
 
@@ -1007,10 +1318,10 @@ static void InitGraphicInfo()
 
   for (i = 0; i < num_images; i++)
   {
-    struct FileInfo *image = getImageListEntry(i);
     Bitmap *src_bitmap;
     int src_x, src_y;
     int first_frame, last_frame;
+    int src_bitmap_width, src_bitmap_height;
 
 #if 0
     printf("::: image: '%s' [%d]\n", image->token, i);
@@ -1022,18 +1333,22 @@ static void InitGraphicInfo()
           getTokenFromImageID(i));
 #endif
 
-    set_graphic_parameters(i, image->parameter);
+    set_graphic_parameters(i, i);
 
     /* now check if no animation frames are outside of the loaded image */
 
     if (graphic_info[i].bitmap == NULL)
       continue;                /* skip check for optional images that are undefined */
 
+    /* get final bitmap size (with scaling, but without small images) */
+    src_bitmap_width  = get_scaled_graphic_width(i);
+    src_bitmap_height = get_scaled_graphic_height(i);
+
     first_frame = 0;
     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
     if (src_x < 0 || src_y < 0 ||
-       src_x + TILEX > src_bitmap->width ||
-       src_y + TILEY > src_bitmap->height)
+       src_x + TILEX > src_bitmap_width ||
+       src_y + TILEY > src_bitmap_height)
     {
       Error(ERR_RETURN_LINE, "-");
       Error(ERR_RETURN, "warning: error found in config file:");
@@ -1048,21 +1363,24 @@ static void InitGraphicInfo()
            src_x, src_y);
       Error(ERR_RETURN, "custom graphic rejected for this element/action");
 
+#if 0
+      Error(ERR_RETURN, "scale_up_factor == %d", scale_up_factor);
+#endif
+
       if (i == fallback_graphic)
        Error(ERR_EXIT, "fatal error: no fallback graphic available");
 
       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
       Error(ERR_RETURN_LINE, "-");
 
-      set_graphic_parameters(i, fallback_image->default_parameter);
-      graphic_info[i].bitmap = fallback_bitmap;
+      set_graphic_parameters(i, fallback_graphic);
     }
 
     last_frame = graphic_info[i].anim_frames - 1;
     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
     if (src_x < 0 || src_y < 0 ||
-       src_x + TILEX > src_bitmap->width ||
-       src_y + TILEY > src_bitmap->height)
+       src_x + TILEX > src_bitmap_width ||
+       src_y + TILEY > src_bitmap_height)
     {
       Error(ERR_RETURN_LINE, "-");
       Error(ERR_RETURN, "warning: error found in config file:");
@@ -1083,12 +1401,11 @@ static void InitGraphicInfo()
       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
       Error(ERR_RETURN_LINE, "-");
 
-      set_graphic_parameters(i, fallback_image->default_parameter);
-      graphic_info[i].bitmap = fallback_bitmap;
+      set_graphic_parameters(i, fallback_graphic);
     }
 
 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
-    /* currently we need only a tile clip mask from the first frame */
+    /* currently we only need a tile clip mask from the first frame */
     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
 
     if (copy_clipmask_gc == None)
@@ -1212,11 +1529,28 @@ static void InitElementSoundInfo()
        default_action_sound = element_info[i].sound[ACTION_DEFAULT];
 #endif
 
+#if 1
+      /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
+      /* !!! make this better !!! */
+      if (i == EL_EMPTY_SPACE)
+       default_action_sound = element_info[EL_DEFAULT].sound[act];
+#endif
+
       /* no sound for this specific action -- use default action sound */
       if (element_info[i].sound[act] == -1)
        element_info[i].sound[act] = default_action_sound;
     }
   }
+
+#if 1
+  /* copy sound settings to some elements that are only stored in level file
+     in native R'n'D levels, but are used by game engine in native EM levels */
+  for (i = 0; copy_properties[i][0] != -1; i++)
+    for (j = 1; j <= 4; j++)
+      for (act = 0; act < NUM_ACTIONS; act++)
+       element_info[copy_properties[i][j]].sound[act] =
+         element_info[copy_properties[i][0]].sound[act];
+#endif
 }
 
 static void InitGameModeSoundInfo()
@@ -1266,6 +1600,12 @@ static void set_sound_parameters(int sound, char **parameter_raw)
   /* explicit loop mode setting in configuration overrides default value */
   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
+
+  /* sound volume to change the original volume when loading the sound file */
+  sound_info[sound].volume = parameter[SND_ARG_VOLUME];
+
+  /* sound priority to give certain sounds a higher or lower priority */
+  sound_info[sound].volume = parameter[SND_ARG_VOLUME];
 }
 
 static void InitSoundInfo()
@@ -1347,6 +1687,22 @@ static void InitSoundInfo()
 
   free(sound_effect_properties);
 
+#if 0
+  /* !!! MOVED TO "InitElementSoundInfo()" !!! */
+  /* !!! everything defined here gets overwritten there !!! */
+
+  /* copy sound settings to some elements that are only stored in level file
+     in native R'n'D levels, but are used by game engine in native EM levels */
+  for (i = 0; i < NUM_ACTIONS; i++)
+    for (j = 0; copy_properties[j][0] != -1; j++)
+      for (k = 1; k <= 4; k++)
+       element_info[copy_properties[j][k]].sound[i] =
+         element_info[copy_properties[j][0]].sound[i];
+
+  printf("::: bug   -> %d\n", element_info[EL_BUG].sound[ACTION_MOVING]);
+  printf("::: bug_r -> %d\n", element_info[EL_BUG_RIGHT].sound[ACTION_MOVING]);
+#endif
+
 #if 0
   /* !!! now handled in InitElementSoundInfo() !!! */
   /* initialize element/sound mapping from dynamic configuration */
@@ -1546,9 +1902,11 @@ static void ReinitializeGraphics()
   InitElementGraphicInfo();            /* element game graphic mapping */
   InitElementSpecialGraphicInfo();     /* element special graphic mapping */
 
-  InitElementSmallImages();            /* create editor and preview images */
+  InitElementSmallImages();            /* scale images to all needed sizes */
   InitFontGraphicInfo();               /* initialize text drawing functions */
 
+  InitGraphicInfo_EM();                        /* graphic mapping for EM engine */
+
   SetMainBackgroundImage(IMG_BACKGROUND);
   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
 
@@ -1734,6 +2092,7 @@ void InitElementPropertiesStatic()
     EL_TRAP,
     EL_INVISIBLE_SAND,
     EL_INVISIBLE_SAND_ACTIVE,
+    EL_EMC_GRASS,
 
     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
     /* (if amoeba can grow into anything diggable, maybe keep these out) */
@@ -1741,6 +2100,7 @@ void InitElementPropertiesStatic()
     EL_LANDMINE,
     EL_TRAP_ACTIVE,
     EL_SP_BUGGY_BASE_ACTIVE,
+    EL_EMC_PLANT,
 #endif
     -1
   };
@@ -1761,6 +2121,10 @@ void InitElementPropertiesStatic()
     EL_EM_KEY_2,
     EL_EM_KEY_3,
     EL_EM_KEY_4,
+    EL_EMC_KEY_5,
+    EL_EMC_KEY_6,
+    EL_EMC_KEY_7,
+    EL_EMC_KEY_8,
     EL_DYNAMITE,
     EL_DYNABOMB_INCREASE_NUMBER,
     EL_DYNABOMB_INCREASE_SIZE,
@@ -1778,6 +2142,8 @@ void InitElementPropertiesStatic()
     EL_ENVELOPE_3,
     EL_ENVELOPE_4,
     EL_SPEED_PILL,
+    EL_EMC_LENSES,
+    EL_EMC_MAGNIFIER,
     -1
   };
 
@@ -1806,6 +2172,7 @@ void InitElementPropertiesStatic()
     EL_LANDMINE,
     EL_TRAP_ACTIVE,
     EL_SP_BUGGY_BASE_ACTIVE,
+    EL_EMC_PLANT,
 #endif
     -1
   };
@@ -1907,6 +2274,14 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EMC_GATE_5,
+    EL_EMC_GATE_6,
+    EL_EMC_GATE_7,
+    EL_EMC_GATE_8,
+    EL_EMC_GATE_5_GRAY,
+    EL_EMC_GATE_6_GRAY,
+    EL_EMC_GATE_7_GRAY,
+    EL_EMC_GATE_8_GRAY,
     EL_SWITCHGATE_OPEN,
     EL_SWITCHGATE_OPENING,
     EL_SWITCHGATE_CLOSED,
@@ -1971,6 +2346,10 @@ void InitElementPropertiesStatic()
     EL_STEELWALL_SLIPPERY,
     EL_PEARL,
     EL_CRYSTAL,
+    EL_EMC_WALL_SLIPPERY_1,
+    EL_EMC_WALL_SLIPPERY_2,
+    EL_EMC_WALL_SLIPPERY_3,
+    EL_EMC_WALL_SLIPPERY_4,
     -1
   };
 
@@ -1999,6 +2378,7 @@ void InitElementPropertiesStatic()
     EL_SP_ELECTRON,
     EL_BALLOON,
     EL_SPRING,
+    EL_EMC_ANDROID,
     -1
   };
 
@@ -2149,6 +2529,11 @@ void InitElementPropertiesStatic()
     EL_PENGUIN,
     EL_PIG,
     EL_DRAGON,
+
+#if 0  /* USE_GRAVITY_BUGFIX_OLD */
+    EL_PLAYER_IS_LEAVING,      /* needed for gravity + "block last field" */
+#endif
+
     -1
   };
 
@@ -2183,6 +2568,14 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EMC_GATE_5,
+    EL_EMC_GATE_6,
+    EL_EMC_GATE_7,
+    EL_EMC_GATE_8,
+    EL_EMC_GATE_5_GRAY,
+    EL_EMC_GATE_6_GRAY,
+    EL_EMC_GATE_7_GRAY,
+    EL_EMC_GATE_8_GRAY,
     EL_SWITCHGATE_OPEN,
     EL_TIMEGATE_OPEN,
     -1
@@ -2243,6 +2636,7 @@ void InitElementPropertiesStatic()
     EL_SATELLITE,
     EL_SP_DISK_YELLOW,
     EL_BALLOON,
+    EL_EMC_ANDROID,
     -1
   };
 
@@ -2275,6 +2669,14 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EMC_GATE_5,
+    EL_EMC_GATE_6,
+    EL_EMC_GATE_7,
+    EL_EMC_GATE_8,
+    EL_EMC_GATE_5_GRAY,
+    EL_EMC_GATE_6_GRAY,
+    EL_EMC_GATE_7_GRAY,
+    EL_EMC_GATE_8_GRAY,
     EL_SWITCHGATE_OPEN,
     EL_TIMEGATE_OPEN,
 
@@ -2368,6 +2770,7 @@ void InitElementPropertiesStatic()
     EL_SP_GRAVITY_OFF_PORT_RIGHT,
     EL_SP_GRAVITY_OFF_PORT_UP,
     EL_SP_GRAVITY_OFF_PORT_DOWN,
+    EL_EMC_GRASS,
     -1
   };
 
@@ -2424,6 +2827,7 @@ void InitElementPropertiesStatic()
     EL_BALLOON_SWITCH_ANY,
     EL_LAMP,
     EL_TIME_ORB_FULL,
+    EL_EMC_MAGIC_BALL_SWITCH,
     -1
   };
 
@@ -2938,6 +3342,14 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EMC_GATE_5,
+    EL_EMC_GATE_6,
+    EL_EMC_GATE_7,
+    EL_EMC_GATE_8,
+    EL_EMC_GATE_5_GRAY,
+    EL_EMC_GATE_6_GRAY,
+    EL_EMC_GATE_7_GRAY,
+    EL_EMC_GATE_8_GRAY,
     -1
   };
 
@@ -3019,6 +3431,10 @@ void InitElementPropertiesStatic()
     EL_EM_KEY_2,
     EL_EM_KEY_3,
     EL_EM_KEY_4,
+    EL_EMC_KEY_5,
+    EL_EMC_KEY_6,
+    EL_EMC_KEY_7,
+    EL_EMC_KEY_8,
     EL_GATE_1,
     EL_GATE_2,
     EL_GATE_3,
@@ -3035,6 +3451,14 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EMC_GATE_5,
+    EL_EMC_GATE_6,
+    EL_EMC_GATE_7,
+    EL_EMC_GATE_8,
+    EL_EMC_GATE_5_GRAY,
+    EL_EMC_GATE_6_GRAY,
+    EL_EMC_GATE_7_GRAY,
+    EL_EMC_GATE_8_GRAY,
     EL_DYNAMITE,
     EL_INVISIBLE_STEELWALL,
     EL_INVISIBLE_WALL,
@@ -3136,6 +3560,10 @@ void InitElementPropertiesStatic()
     EL_EMC_STEELWALL_2,
     EL_EMC_STEELWALL_3,
     EL_EMC_STEELWALL_4,
+    EL_EMC_WALL_SLIPPERY_1,
+    EL_EMC_WALL_SLIPPERY_2,
+    EL_EMC_WALL_SLIPPERY_3,
+    EL_EMC_WALL_SLIPPERY_4,
     EL_EMC_WALL_1,
     EL_EMC_WALL_2,
     EL_EMC_WALL_3,
@@ -3144,6 +3572,14 @@ void InitElementPropertiesStatic()
     EL_EMC_WALL_6,
     EL_EMC_WALL_7,
     EL_EMC_WALL_8,
+    EL_EMC_WALL_9,
+    EL_EMC_WALL_10,
+    EL_EMC_WALL_11,
+    EL_EMC_WALL_12,
+    EL_EMC_WALL_13,
+    EL_EMC_WALL_14,
+    EL_EMC_WALL_15,
+    EL_EMC_WALL_16,
     -1
   };
 
@@ -3231,44 +3667,6 @@ void InitElementPropertiesStatic()
     { NULL,                    -1                      }
   };
 
-  static int copy_properties[][5] =
-  {
-    {
-      EL_BUG,
-      EL_BUG_LEFT,             EL_BUG_RIGHT,
-      EL_BUG_UP,               EL_BUG_DOWN
-    },
-    {
-      EL_SPACESHIP,
-      EL_SPACESHIP_LEFT,       EL_SPACESHIP_RIGHT,
-      EL_SPACESHIP_UP,         EL_SPACESHIP_DOWN
-    },
-    {
-      EL_BD_BUTTERFLY,
-      EL_BD_BUTTERFLY_LEFT,    EL_BD_BUTTERFLY_RIGHT,
-      EL_BD_BUTTERFLY_UP,      EL_BD_BUTTERFLY_DOWN
-    },
-    {
-      EL_BD_FIREFLY,
-      EL_BD_FIREFLY_LEFT,      EL_BD_FIREFLY_RIGHT,
-      EL_BD_FIREFLY_UP,                EL_BD_FIREFLY_DOWN
-    },
-    {
-      EL_PACMAN,
-      EL_PACMAN_LEFT,          EL_PACMAN_RIGHT,
-      EL_PACMAN_UP,            EL_PACMAN_DOWN
-    },
-    {
-      EL_MOLE,
-      EL_MOLE_LEFT,            EL_MOLE_RIGHT,
-      EL_MOLE_UP,              EL_MOLE_DOWN
-    },
-    {
-      -1,
-      -1, -1, -1, -1
-    }
-  };
-
   int i, j, k;
 
   /* always start with reliable default values (element has no properties) */
@@ -3552,8 +3950,15 @@ void InitElementPropertiesEngine(int engine_version)
        SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
 
     /* ---------- GFX_CRUMBLED --------------------------------------------- */
+#if 1
+    SET_PROPERTY(i, EP_GFX_CRUMBLED,
+                element_info[i].crumbled[ACTION_DEFAULT] !=
+                element_info[i].graphic[ACTION_DEFAULT]);
+#else
+    /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
     SET_PROPERTY(i, EP_GFX_CRUMBLED,
                 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
+#endif
   }
 
 #if 0
@@ -3655,6 +4060,19 @@ void InitElementPropertiesEngine(int engine_version)
 
 static void InitGlobal()
 {
+  int i;
+
+  for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
+  {
+    /* check if element_name_info entry defined for each element in "main.h" */
+    if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
+      Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
+
+    element_info[i].token_name = element_name_info[i].token_name;
+    element_info[i].class_name = element_name_info[i].class_name;
+    element_info[i].editor_description=element_name_info[i].editor_description;
+  }
+
   global.autoplay_leveldir = NULL;
   global.convert_leveldir = NULL;
 
@@ -3758,7 +4176,7 @@ void Execute_Command(char *command)
   {
     char *filename = &command[11];
 
-    if (access(filename, F_OK) != 0)
+    if (!fileExists(filename))
       Error(ERR_EXIT, "cannot open file '%s'", filename);
 
     LoadLevelFromFilename(&level, filename);
@@ -3770,7 +4188,7 @@ void Execute_Command(char *command)
   {
     char *filename = &command[10];
 
-    if (access(filename, F_OK) != 0)
+    if (!fileExists(filename))
       Error(ERR_EXIT, "cannot open file '%s'", filename);
 
     LoadTapeFromFilename(filename);
@@ -3780,17 +4198,57 @@ void Execute_Command(char *command)
   }
   else if (strncmp(command, "autoplay ", 9) == 0)
   {
-    char *str_copy = getStringCopy(&command[9]);
-    char *str_ptr = strchr(str_copy, ' ');
+    char *str_ptr = getStringCopy(&command[9]);        /* read command parameters */
+
+    while (*str_ptr != '\0')                   /* continue parsing string */
+    {
+      /* cut leading whitespace from string, replace it by string terminator */
+      while (*str_ptr == ' ' || *str_ptr == '\t')
+       *str_ptr++ = '\0';
+
+      if (*str_ptr == '\0')                    /* end of string reached */
+       break;
+
+      if (global.autoplay_leveldir == NULL)    /* read level set string */
+      {
+       global.autoplay_leveldir = str_ptr;
+       global.autoplay_all = TRUE;             /* default: play all tapes */
+
+       for (i = 0; i < MAX_TAPES_PER_SET; i++)
+         global.autoplay_level[i] = FALSE;
+      }
+      else                                     /* read level number string */
+      {
+       int level_nr = atoi(str_ptr);           /* get level_nr value */
 
-    global.autoplay_leveldir = str_copy;
-    global.autoplay_level_nr = -1;
+       if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
+         global.autoplay_level[level_nr] = TRUE;
 
-    if (str_ptr != NULL)
+       global.autoplay_all = FALSE;
+      }
+
+      /* advance string pointer to the next whitespace (or end of string) */
+      while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
+       str_ptr++;
+    }
+
+#if 0
+    printf("level set == '%s'\n", global.autoplay_leveldir);
+
+    if (global.autoplay_all)
+      printf("play all levels\n");
+    else
     {
-      *str_ptr++ = '\0';                       /* terminate leveldir string */
-      global.autoplay_level_nr = atoi(str_ptr);        /* get level_nr value */
+      printf("play the following levels:");
+
+      for (i = 0; i < MAX_TAPES_PER_SET; i++)
+       if (global.autoplay_level[i])
+         printf(" %03d", i);
+
+      printf("\n");
     }
+#endif
+
   }
   else if (strncmp(command, "convert ", 8) == 0)
   {
@@ -3800,7 +4258,7 @@ void Execute_Command(char *command)
     global.convert_leveldir = str_copy;
     global.convert_level_nr = -1;
 
-    if (str_ptr != NULL)
+    if (str_ptr != NULL)                       /* level number follows */
     {
       *str_ptr++ = '\0';                       /* terminate leveldir string */
       global.convert_level_nr = atoi(str_ptr); /* get level_nr value */
@@ -4252,7 +4710,12 @@ static char *getNewArtworkIdentifier(int type)
             artwork_current_identifier) != 0)
     artwork_new_identifier = artwork_current_identifier;
 
+#if 1
+  *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
+#else
+  /* newer versions of gcc do not like this anymore :-/ */
   *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
+#endif
 
 #if 0
   if (type == ARTWORK_TYPE_GRAPHICS)
@@ -4357,7 +4820,7 @@ void KeyboardAutoRepeatOffUnlessAutoplay()
 
 void OpenAll()
 {
-  InitGlobal();                /* initialize some global variables */
+  InitGlobal();                        /* initialize some global variables */
 
   if (options.execute_command)
     Execute_Command(options.execute_command);
@@ -4369,7 +4832,8 @@ void OpenAll()
 #else
     Error(ERR_WARN, "networking only supported in Unix version");
 #endif
-    exit(0);   /* never reached */
+
+    exit(0);                   /* never reached, server loops forever */
   }
 
   InitSetup();
@@ -4419,6 +4883,10 @@ void OpenAll()
 
   game_status = GAME_MODE_MAIN;
 
+#if 1
+  em_open_all();
+#endif
+
   DrawMainMenu();
 
   InitNetworkServer();
@@ -4431,6 +4899,10 @@ void CloseAllAndExit(int exit_value)
   FreeAllMusic();
   CloseAudio();                /* called after freeing sounds (needed for SDL) */
 
+#if 1
+  em_close_all();
+#endif
+
   FreeAllImages();
   FreeTileClipmasks();
 
index ca22ef6e1662a2c7acd76fb2accae3b710fd36b2..08f999e3e6df1a51179d58384a4d774e92a85e2e 100644 (file)
 #include "main.h"
 
 #if 1
-#define setMoveIntoAcidProperty(l, e, v)       \
+#define setMoveIntoAcidProperty(l, e, v)                       \
        (setBitfieldProperty(&(l)->can_move_into_acid_bits,     \
                             EP_CAN_MOVE_INTO_ACID, e, v))
-#define getMoveIntoAcidProperty(l, e)          \
+#define getMoveIntoAcidProperty(l, e)                          \
        (getBitfieldProperty(&(l)->can_move_into_acid_bits,     \
                             EP_CAN_MOVE_INTO_ACID, e))
-#define setDontCollideWithProperty(l, e, v)    \
-       (setBitfieldProperty(&(l)->can_move_into_acid_bits,     \
+#define setDontCollideWithProperty(l, e, v)                    \
+       (setBitfieldProperty(&(l)->dont_collide_with_bits,      \
                             EP_DONT_COLLIDE_WITH, e, v))
-#define getDontCollideWithProperty(l, e)       \
-       (getBitfieldProperty(&(l)->can_move_into_acid_bits,     \
+#define getDontCollideWithProperty(l, e)                       \
+       (getBitfieldProperty(&(l)->dont_collide_with_bits,      \
                             EP_DONT_COLLIDE_WITH, e))
 
 void setBitfieldProperty(int *, int, int, boolean);
index 4d5b28c6b3eae4baadc7ddfe80b82ab7b7e874da..497fb24e79e6f0bb0a9ba33dd93e40b780d3e528 100644 (file)
@@ -1,7 +1,7 @@
 # =============================================================================
 # Rocks'n'Diamonds Makefile (libgame)
 # -----------------------------------------------------------------------------
-# (c) 1995-2003 Holger Schemel <info@artsoft.org>
+# (c) 1995-2005 Holger Schemel <info@artsoft.org>
 # =============================================================================
 
 # -----------------------------------------------------------------------------
index 8601256cbf3ed1b2da04be5a9422d40f62bf6efd..5ac104c8a254688839d0f1111ce3f17efa951fc0 100644 (file)
@@ -744,11 +744,11 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        break;
 
       case GDI_TYPE:
-       gi->type = va_arg(ap, unsigned long);
+       gi->type = va_arg(ap, unsigned int);
        break;
 
       case GDI_STATE:
-       gi->state = va_arg(ap, unsigned long);
+       gi->state = va_arg(ap, unsigned int);
        break;
 
       case GDI_ACTIVE:
@@ -770,30 +770,33 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        break;
 
       case GDI_RADIO_NR:
-       gi->radio_nr = va_arg(ap, unsigned long);
+       gi->radio_nr = va_arg(ap, unsigned int);
        break;
 
       case GDI_NUMBER_VALUE:
-       gi->textinput.number_value = va_arg(ap, long);
+       gi->textinput.number_value = va_arg(ap, int);
        sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
+       strcpy(gi->textinput.last_value, gi->textinput.value);
        gi->textinput.cursor_position = strlen(gi->textinput.value);
        break;
 
       case GDI_NUMBER_MIN:
-       gi->textinput.number_min = va_arg(ap, long);
+       gi->textinput.number_min = va_arg(ap, int);
        if (gi->textinput.number_value < gi->textinput.number_min)
        {
          gi->textinput.number_value = gi->textinput.number_min;
          sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
+         strcpy(gi->textinput.last_value, gi->textinput.value);
        }
        break;
 
       case GDI_NUMBER_MAX:
-       gi->textinput.number_max = va_arg(ap, long);
+       gi->textinput.number_max = va_arg(ap, int);
        if (gi->textinput.number_value > gi->textinput.number_max)
        {
          gi->textinput.number_value = gi->textinput.number_max;
          sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
+         strcpy(gi->textinput.last_value, gi->textinput.value);
        }
        break;
 
@@ -805,12 +808,15 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
            max_textsize = MIN(gi->textinput.size, MAX_GADGET_TEXTSIZE - 1);
 
          strncpy(gi->textinput.value, va_arg(ap, char *), max_textsize);
+         strcpy(gi->textinput.last_value, gi->textinput.value);
+
          gi->textinput.value[max_textsize] = '\0';
          gi->textinput.cursor_position = strlen(gi->textinput.value);
 
          /* same tag also used for other gadget definitions */
          strcpy(gi->textbutton.value, gi->textinput.value);
          strcpy(gi->textarea.value, gi->textinput.value);
+         strcpy(gi->textarea.last_value, gi->textinput.value);
        }
        break;
 
@@ -821,10 +827,17 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 
          gi->textinput.size = max_textsize;
          gi->textinput.value[max_textsize] = '\0';
+         strcpy(gi->textinput.last_value, gi->textinput.value);
 
          /* same tag also used for other gadget definitions */
-         strcpy(gi->textbutton.value, gi->textinput.value);
-         gi->textbutton.size = gi->textinput.size;
+
+         gi->textarea.size = max_textsize;
+         gi->textarea.value[max_textsize] = '\0';
+         strcpy(gi->textarea.last_value, gi->textinput.value);
+
+         gi->textbutton.size = max_textsize;
+         gi->textbutton.value[max_textsize] = '\0';
+
          gi->selectbox.size = gi->textinput.size;
        }
        break;
@@ -906,7 +919,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        break;
 
       case GDI_EVENT_MASK:
-       gi->event_mask = va_arg(ap, unsigned long);
+       gi->event_mask = va_arg(ap, unsigned int);
        break;
 
       case GDI_AREA_SIZE:
@@ -1055,7 +1068,11 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     getFontCharSource(font_nr, FONT_ASCII_CURSOR, &src_bitmap, &src_x, &src_y);
     src_x += font_width / 2;
     src_y += font_height / 2;
-    gi->selectbox.inverse_color = GetPixel(src_bitmap, src_x, src_y);
+
+    /* there may be esoteric cases with missing or too small font bitmap */
+    if (src_bitmap != NULL &&
+       src_x < src_bitmap->width && src_y < src_bitmap->height)
+      gi->selectbox.inverse_color = GetPixel(src_bitmap, src_x, src_y);
 
     /* always start with closed selectbox */
     gi->selectbox.open = FALSE;
@@ -1088,16 +1105,23 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
   if (gi->type & GD_TYPE_SCROLLBAR)
   {
     struct GadgetScrollbar *gs = &gi->scrollbar;
+    int scrollbar_size_cmp;
 
     if (gi->width == 0 || gi->height == 0 ||
        gs->items_max == 0 || gs->items_visible == 0)
       Error(ERR_EXIT, "scrollbar gadget incomplete (missing tags)");
 
     /* calculate internal scrollbar values */
+    gs->size_min = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ?
+                   gi->width : gi->height);
     gs->size_max = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ?
                    gi->height : gi->width);
-    gs->size = gs->size_max * gs->items_visible / gs->items_max;
-    gs->position = gs->size_max * gs->item_position / gs->items_max;
+
+    scrollbar_size_cmp = gs->size_max * gs->items_visible / gs->items_max;
+    gs->size = MAX(scrollbar_size_cmp, gs->size_min);
+    gs->size_max_cmp = (gs->size_max - (gs->size - scrollbar_size_cmp));
+
+    gs->position = gs->size_max_cmp * gs->item_position / gs->items_max;
     gs->position_max = gs->size_max - gs->size;
     gs->correction = gs->size_max / gs->items_max / 2;
 
@@ -1296,21 +1320,33 @@ void RemapAllGadgets()
   MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP);
 }
 
-static boolean anyTextInputGadgetActive()
+boolean anyTextInputGadgetActive()
 {
   return (last_gi && (last_gi->type & GD_TYPE_TEXT_INPUT) && last_gi->mapped);
 }
 
-static boolean anyTextAreaGadgetActive()
+boolean anyTextAreaGadgetActive()
 {
   return (last_gi && (last_gi->type & GD_TYPE_TEXT_AREA) && last_gi->mapped);
 }
 
-static boolean anySelectboxGadgetActive()
+boolean anySelectboxGadgetActive()
 {
   return (last_gi && (last_gi->type & GD_TYPE_SELECTBOX) && last_gi->mapped);
 }
 
+boolean anyScrollbarGadgetActive()
+{
+  return (last_gi && (last_gi->type & GD_TYPE_SCROLLBAR) && last_gi->mapped);
+}
+
+boolean anyTextGadgetActive()
+{
+  return (anyTextInputGadgetActive() ||
+         anyTextAreaGadgetActive() ||
+         anySelectboxGadgetActive());
+}
+
 static boolean insideSelectboxLine(struct GadgetInfo *gi, int mx, int my)
 {
   return(gi != NULL &&
@@ -1327,15 +1363,11 @@ static boolean insideSelectboxArea(struct GadgetInfo *gi, int mx, int my)
         my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height);
 }
 
-boolean anyTextGadgetActive()
-{
-  return (anyTextInputGadgetActive() ||
-         anyTextAreaGadgetActive() ||
-         anySelectboxGadgetActive());
-}
-
 void ClickOnGadget(struct GadgetInfo *gi, int button)
 {
+  if (!gi->mapped)
+    return;
+
   /* simulate releasing mouse button over last gadget, if still pressed */
   if (button_status)
     HandleGadgets(-1, -1, 0);
@@ -1429,14 +1461,35 @@ boolean HandleGadgets(int mx, int my, int button)
       button != 0 && !motion_status && new_gi != last_gi)
 #endif
   {
-    CheckRangeOfNumericInputGadget(last_gi);   /* in case of numeric gadget */
+    struct GadgetInfo *gi = last_gi;
+    boolean gadget_changed = (gi->event_mask & GD_EVENT_TEXT_LEAVING);
 
-    DrawGadget(last_gi, DG_UNPRESSED, last_gi->direct_draw);
+    /* check if text gadget has changed its value */
+    if (gi->type & GD_TYPE_TEXT_INPUT)
+    {
+      CheckRangeOfNumericInputGadget(gi);
 
-    last_gi->event.type = GD_EVENT_TEXT_LEAVING;
+      if (strcmp(gi->textinput.value, gi->textinput.last_value) != 0)
+       strcpy(gi->textinput.last_value, gi->textinput.value);
+      else
+       gadget_changed = FALSE;
+    }
 
-    if (last_gi->event_mask & GD_EVENT_TEXT_LEAVING)
-      last_gi->callback_action(last_gi);
+    /* selectbox does not change its value when closed by clicking outside */
+    if (gi->type & GD_TYPE_SELECTBOX)
+      gadget_changed = FALSE;
+
+    DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
+
+    gi->event.type = GD_EVENT_TEXT_LEAVING;
+
+#if 1
+    if (gadget_changed && !(gi->type & GD_TYPE_SELECTBOX))
+      gi->callback_action(gi);
+#else
+    if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
+      gi->callback_action(gi);
+#endif
 
     last_gi = NULL;
 
@@ -1664,7 +1717,7 @@ boolean HandleGadgets(int mx, int my, int button)
 
        if (gs->item_position < 0)
          gs->item_position = 0;
-       if (gs->item_position > gs->items_max - gs->items_visible)
+       else if (gs->item_position > gs->items_max - gs->items_visible)
          gs->item_position = gs->items_max - gs->items_visible;
 
        if (old_item_position != gs->item_position)
@@ -1746,13 +1799,22 @@ boolean HandleGadgets(int mx, int my, int button)
 
       gs->position = scrollbar_mouse_pos - gs->drag_position;
 
-      if (gs->position < 0)
+      /* make sure to always precisely reach end positions when dragging */
+      if (gs->position <= 0)
+      {
        gs->position = 0;
-      if (gs->position > gs->position_max)
+       gs->item_position = 0;
+      }
+      else if (gs->position >= gs->position_max)
+      {
        gs->position = gs->position_max;
-
-      gs->item_position =
-       gs->items_max * (gs->position + gs->correction) / gs->size_max;
+       gs->item_position = gs->items_max - gs->items_visible;
+      }
+      else
+      {
+       gs->item_position =
+         gs->items_max * (gs->position + gs->correction) / gs->size_max_cmp;
+      }
 
       if (gs->item_position < 0)
        gs->item_position = 0;
@@ -1781,20 +1843,29 @@ boolean HandleGadgets(int mx, int my, int button)
   if (gadget_released_inside)
   {
     boolean deactivate_gadget = TRUE;
+    boolean gadget_changed = TRUE;
 
     if (gi->type & GD_TYPE_SELECTBOX)
     {
 #if 1
       if (mouse_released_where_pressed ||
          !gadget_released_inside_select_area)       /* selectbox stays open */
+      {
        deactivate_gadget = FALSE;
+       gadget_changed = FALSE;
+      }
 #else
       if (gadget_released_inside_select_line ||
          gadget_released_off_borders)               /* selectbox stays open */
+      {
        deactivate_gadget = FALSE;
+       gadget_changed = FALSE;
+      }
 #endif
-      else
+      else if (gi->selectbox.index != gi->selectbox.current_index)
        gi->selectbox.index = gi->selectbox.current_index;
+      else
+       gadget_changed = FALSE;
     }
 
     if (deactivate_gadget &&
@@ -1805,8 +1876,15 @@ boolean HandleGadgets(int mx, int my, int button)
     gi->state = GD_BUTTON_UNPRESSED;
     gi->event.type = GD_EVENT_RELEASED;
 
+#if 1
+    if ((gi->event_mask & GD_EVENT_RELEASED) && gadget_changed)
+    {
+      gi->callback_action(gi);
+    }
+#else
     if ((gi->event_mask & GD_EVENT_RELEASED) && deactivate_gadget)
       gi->callback_action(gi);
+#endif
   }
 
   if (gadget_released_off_borders)
@@ -1856,10 +1934,24 @@ boolean HandleGadgetsKeyInput(Key key)
 
   if (key == KSYM_Return)      /* valid for both text input and selectbox */
   {
+    boolean gadget_changed = (gi->event_mask & GD_EVENT_TEXT_RETURN);
+
     if (gi->type & GD_TYPE_TEXT_INPUT)
+    {
       CheckRangeOfNumericInputGadget(gi);
+
+      if (strcmp(gi->textinput.value, gi->textinput.last_value) != 0)
+       strcpy(gi->textinput.last_value, gi->textinput.value);
+      else
+       gadget_changed = FALSE;
+    }
     else if (gi->type & GD_TYPE_SELECTBOX)
-      gi->selectbox.index = gi->selectbox.current_index;
+    {
+      if (gi->selectbox.index != gi->selectbox.current_index)
+       gi->selectbox.index = gi->selectbox.current_index;
+      else
+       gadget_changed = FALSE;
+    }
 
     if (gi->type & GD_TYPE_TEXT_AREA)
     {
@@ -1876,8 +1968,13 @@ boolean HandleGadgetsKeyInput(Key key)
       last_gi = NULL;
     }
 
+#if 1
+    if (gadget_changed)
+      gi->callback_action(gi);
+#else
     if (gi->event_mask & GD_EVENT_TEXT_RETURN)
       gi->callback_action(gi);
+#endif
   }
   else if (gi->type & GD_TYPE_TEXT_INPUT)      /* only valid for text input */
   {
index 4e1dd0f789d5e70beaf1107c1f615440e1ab7d40..ac14cb81f2b1d0e9dfecd733629c1c63799caa33 100644 (file)
@@ -152,6 +152,7 @@ struct GadgetTextButton
 struct GadgetTextInput
 {
   char value[MAX_GADGET_TEXTSIZE];     /* text string in input field */
+  char last_value[MAX_GADGET_TEXTSIZE];        /* last text string in input field */
   int cursor_position;                 /* actual text cursor position */
   int number_value;                    /* integer value, if numeric */
   int number_min;                      /* minimal allowed numeric value */
@@ -162,6 +163,7 @@ struct GadgetTextInput
 struct GadgetTextArea
 {
   char value[MAX_GADGET_TEXTSIZE];     /* text string in input field */
+  char last_value[MAX_GADGET_TEXTSIZE];        /* last text string in input field */
   int cursor_position;                 /* actual text cursor position */
   int cursor_x;                                /* actual x cursor position */
   int cursor_y;                                /* actual y cursor position */
@@ -193,7 +195,9 @@ struct GadgetScrollbar
   int items_max;                       /* number of items to access */
   int items_visible;                   /* number of visible items */
   int item_position;                   /* actual item position */
+  int size_min;                                /* minimal scrollbar size */
   int size_max;                                /* this is either width or height */
+  int size_max_cmp;                    /* needed for minimal scrollbar size */
   int size;                            /* scrollbar size on screen */
   int position;                                /* scrollbar position on screen */
   int position_max;                    /* bottom/right scrollbar position */
@@ -209,8 +213,8 @@ struct GadgetInfo
   char info_text[MAX_INFO_TEXTSIZE];   /* short popup info text */
   int x, y;                            /* gadget position */
   int width, height;                   /* gadget size */
-  unsigned long type;                  /* type (button, text input, ...) */
-  unsigned long state;                 /* state (pressed, released, ...) */
+  unsigned int type;                   /* type (button, text input, ...) */
+  unsigned int state;                  /* state (pressed, released, ...) */
   boolean checked;                     /* check/radio button state */
   int radio_nr;                                /* number of radio button series */
   boolean mapped;                      /* gadget is mapped on the screen */
@@ -222,7 +226,7 @@ struct GadgetInfo
   struct GadgetDesign design[2];       /* 0: normal; 1: pressed */
   struct GadgetDesign alt_design[2];   /* alternative design */
   struct GadgetDecoration deco;                /* decoration on top of gadget */
-  unsigned long event_mask;            /* possible events for this gadget */
+  unsigned int event_mask;             /* possible events for this gadget */
   struct GadgetEvent event;            /* actual gadget event */
   gadget_function callback_info;       /* function for pop-up info text */
   gadget_function callback_action;     /* function for gadget action */
@@ -246,7 +250,12 @@ void UnmapGadget(struct GadgetInfo *);
 void UnmapAllGadgets();
 void RemapAllGadgets();
 
+boolean anyTextInputGadgetActive();
+boolean anyTextAreaGadgetActive();
+boolean anySelectboxGadgetActive();
+boolean anyScrollbarGadgetActive();
 boolean anyTextGadgetActive();
+
 void ClickOnGadget(struct GadgetInfo *, int);
 
 boolean HandleGadgets(int, int, int);
index 108fd39c3fc4d80033e2748b64170bc1ee5f88a1..09ec64f6f869f423e7192d3c3ded3bce679cc6d6 100644 (file)
@@ -136,8 +136,73 @@ static Pixmap Image_to_Mask(Image *image, Display *display, Window window)
     dst_ptr += bytes_per_row;  /* continue with leftmost byte of next row */
   }
 
-  mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
-                                     image->width, image->height);
+  if ((mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data,
+                                          image->width, image->height))
+      == None)
+    Error(ERR_EXIT, "Image_to_Mask(): XCreateBitmapFromData() failed");
+
+  free(mask_data);
+
+  return mask_pixmap;
+}
+
+Pixmap Pixmap_to_Mask(Pixmap src_pixmap, int src_width, int src_height)
+{
+  XImage *src_ximage;
+  byte *src_ptr, *dst_ptr, *dst_ptr2;
+  int bits_per_pixel;
+  int bytes_per_pixel;
+  unsigned int bytes_per_row;
+  unsigned int x, y, i;
+  byte bitmask;
+  byte *mask_data;
+  Pixmap mask_pixmap;
+
+  /* copy source pixmap to temporary image */
+  if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
+                             AllPlanes, ZPixmap)) == NULL)
+    Error(ERR_EXIT, "Pixmap_to_Mask(): XGetImage() failed");
+
+  bits_per_pixel = src_ximage->bits_per_pixel;
+  bytes_per_pixel = (bits_per_pixel + 7) / 8;
+
+  bytes_per_row = (src_width + 7) / 8;
+  mask_data = checked_calloc(bytes_per_row * src_height);
+
+  src_ptr = (byte *)src_ximage->data;
+  dst_ptr = mask_data;
+
+  /* create bitmap data which can be used by 'XCreateBitmapFromData()'
+   * directly to create a pixmap of depth 1 for use as a clip mask for
+   * the corresponding image pixmap
+   */
+
+  for (y = 0; y < src_height; y++)
+  {
+    bitmask = 0x01;            /* start with leftmost bit in the byte     */
+    dst_ptr2 = dst_ptr;                /* start with leftmost byte in the row     */
+
+    for (x = 0; x < src_width; x++)
+    {
+      for (i = 0; i < bytes_per_pixel; i++)
+       if (*src_ptr++)         /* source pixel solid? (pixel index != 0)  */
+         *dst_ptr2 |= bitmask; /* then write a bit into the image mask    */
+
+      if ((bitmask <<= 1) == 0)        /* bit at rightmost byte position reached? */
+      {
+       bitmask = 0x01;         /* start again with leftmost bit position  */
+       dst_ptr2++;             /* continue with next byte in image mask   */
+      }
+    }
+
+    dst_ptr += bytes_per_row;  /* continue with leftmost byte of next row */
+  }
+
+  if ((mask_pixmap = XCreateBitmapFromData(display, window->drawable,
+                                          (char *)mask_data,
+                                          src_width, src_height)) == None)
+    Error(ERR_EXIT, "Pixmap_to_Mask(): XCreateBitmapFromData() failed");
+
   free(mask_data);
 
   return mask_pixmap;
@@ -569,8 +634,10 @@ XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual,
   -----------------------------------------------------------------------------
   ZoomPixmap
 
-  Important note: The scaling code currently only supports scaling down the
-  image by a power of 2 -- scaling up is currently not supported at all!
+  Important note: The scaling code currently only supports scaling of the image
+  up or down by a power of 2 -- other scaling factors currently not supported!
+  Also not supported is scaling of pixmap masks (with depth 1); to scale them,
+  better use Pixmap_to_Mask() for now.
   -----------------------------------------------------------------------------
 */
 
@@ -582,24 +649,39 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
   byte *src_ptr, *dst_ptr;
   int bits_per_pixel;
   int bytes_per_pixel;
-  int x, y, i;
-  int zoom_factor = src_width / dst_width;     /* currently very limited! */
+  int x, y, xx, yy, i;
   int row_skip, col_skip;
+  int zoom_factor;
+  boolean scale_down = (src_width > dst_width);
+
+  if (scale_down)
+  {
+    zoom_factor = src_width / dst_width;
+
+    /* adjust source image size to integer multiple of destination size */
+    src_width  = dst_width  * zoom_factor;
+    src_height = dst_height * zoom_factor;
+  }
+  else
+  {
+    zoom_factor = dst_width / src_width;
 
-  /* adjust source image size to integer multiple of destination image size */
-  src_width  = dst_width  * zoom_factor;
-  src_height = dst_height * zoom_factor;
+    /* no adjustment needed when scaling up (some pixels may be left blank) */
+  }
 
   /* copy source pixmap to temporary image */
-  src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
-                        AllPlanes, ZPixmap);
+  if ((src_ximage = XGetImage(display, src_pixmap, 0, 0, src_width, src_height,
+                             AllPlanes, ZPixmap)) == NULL)
+    Error(ERR_EXIT, "ZoomPixmap(): XGetImage() failed");
 
   bits_per_pixel = src_ximage->bits_per_pixel;
   bytes_per_pixel = (bits_per_pixel + 7) / 8;
 
-  dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
-                           0, NULL, dst_width, dst_height,
-                           8, dst_width * bytes_per_pixel);
+  if ((dst_ximage = XCreateImage(display, visual, src_ximage->depth, ZPixmap,
+                                0, NULL, dst_width, dst_height,
+                                8, dst_width * bytes_per_pixel)) == NULL)
+    Error(ERR_EXIT, "ZoomPixmap(): XCreateImage() failed");
+
   dst_ximage->data =
     checked_malloc(dst_width * dst_height * bytes_per_pixel);
   dst_ximage->byte_order = src_ximage->byte_order;
@@ -607,14 +689,40 @@ void ZoomPixmap(Display *display, GC gc, Pixmap src_pixmap, Pixmap dst_pixmap,
   src_ptr = (byte *)src_ximage->data;
   dst_ptr = (byte *)dst_ximage->data;
 
-  col_skip = (zoom_factor - 1) * bytes_per_pixel;
-  row_skip = col_skip * src_width;
+  if (scale_down)
+  {
+    col_skip = (zoom_factor - 1) * bytes_per_pixel;
+    row_skip = col_skip * src_width;
+
+    /* scale image down by scaling factor 'zoom_factor' */
+    for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
+      for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
+       for (i = 0; i < bytes_per_pixel; i++)
+         *dst_ptr++ = *src_ptr++;
+  }
+  else
+  {
+    row_skip = src_width * bytes_per_pixel;
 
-  /* scale image down by scaling factor 'zoom_factor' */
-  for (y = 0; y < src_height; y += zoom_factor, src_ptr += row_skip)
-    for (x = 0; x < src_width; x += zoom_factor, src_ptr += col_skip)
-      for (i = 0; i < bytes_per_pixel; i++)
-       *dst_ptr++ = *src_ptr++;
+    /* scale image up by scaling factor 'zoom_factor' */
+    for (y = 0; y < src_height; y++)
+    {
+      for (yy = 0; yy < zoom_factor; yy++)
+      {
+       if (yy > 0)
+         src_ptr -= row_skip;
+
+       for (x = 0; x < src_width; x++)
+       {
+         for (xx = 0; xx < zoom_factor; xx++)
+           for (i = 0; i < bytes_per_pixel; i++)
+             *dst_ptr++ = *(src_ptr + i);
+
+         src_ptr += bytes_per_pixel;
+       }
+      }
+    }
+  }
 
   /* copy scaled image to destination pixmap */
   XPutImage(display, dst_pixmap, gc, dst_ximage, 0, 0, 0, 0,
@@ -712,7 +820,12 @@ struct ImageInfo
   int num_references;
 
   Bitmap *bitmap;
-  boolean contains_small_images;
+
+  int original_width;                  /* original image file width */
+  int original_height;                 /* original image file height */
+
+  boolean contains_small_images;       /* set after adding small images */
+  boolean scaled_up;                   /* set after scaling up */
 };
 typedef struct ImageInfo ImageInfo;
 
@@ -738,7 +851,11 @@ static void *Load_PCX(char *filename)
 
   img_info->source_filename = getStringCopy(filename);
 
+  img_info->original_width  = img_info->bitmap->width;
+  img_info->original_height = img_info->bitmap->height;
+
   img_info->contains_small_images = FALSE;
+  img_info->scaled_up = FALSE;
 
   return img_info;
 }
@@ -765,7 +882,7 @@ int getImageListSize()
          image_info->num_dynamic_file_list_entries);
 }
 
-struct FileInfo *getImageListEntry(int pos)
+struct FileInfo *getImageListEntryFromImageID(int pos)
 {
   int num_list_entries = image_info->num_file_list_entries;
   int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
@@ -787,33 +904,30 @@ static ImageInfo *getImageInfoEntryFromImageID(int pos)
 
 Bitmap *getBitmapFromImageID(int pos)
 {
-#if 0
-  int num_list_entries = image_info->num_file_list_entries;
-  int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
-  ImageInfo **img_info =
-    (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
-                  image_info->dynamic_artwork_list);
-
-  return (img_info[list_pos] != NULL ? img_info[list_pos]->bitmap : NULL);
-#else
   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
   return (img_info != NULL ? img_info->bitmap : NULL);
-#endif
 }
 
-char *getTokenFromImageID(int graphic)
+int getOriginalImageWidthFromImageID(int pos)
 {
-#if 0
-  /* !!! this does not work for dynamic artwork (crash!) !!! */
-  struct FileInfo *file_list = (struct FileInfo *)image_info->file_list;
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  return (img_info != NULL ? img_info->original_width : 0);
+}
+
+int getOriginalImageHeightFromImageID(int pos)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  return (img_info != NULL ? img_info->original_height : 0);
+}
 
-  return file_list[graphic].token;
-#else
-  struct FileInfo *file_list = getImageListEntry(graphic);
+char *getTokenFromImageID(int graphic)
+{
+  struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
 
   return (file_list != NULL ? file_list->token : NULL);
-#endif
 }
 
 int getImageIDFromToken(char *token)
@@ -845,7 +959,7 @@ struct PropertyMapping *getImageListPropertyMapping()
 }
 
 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
-                  struct ConfigInfo *config_suffix_list,
+                  struct ConfigTypeInfo *config_suffix_list,
                   char **base_prefixes, char **ext1_suffixes,
                   char **ext2_suffixes, char **ext3_suffixes,
                   char **ignore_tokens)
@@ -929,16 +1043,23 @@ void ReloadCustomImages()
   ReloadCustomArtworkList(image_info);
 }
 
-void CreateImageWithSmallImages(int pos)
+void CreateImageWithSmallImages(int pos, int zoom_factor)
 {
   ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
   if (img_info == NULL || img_info->contains_small_images)
     return;
 
-  CreateBitmapWithSmallBitmaps(img_info->bitmap);
+  CreateBitmapWithSmallBitmaps(img_info->bitmap, zoom_factor);
 
   img_info->contains_small_images = TRUE;
+  img_info->scaled_up = TRUE;
+
+#if 0
+  if (zoom_factor)
+    printf("CreateImageWithSmallImages: '%s' zoomed by factor %d\n",
+          img_info->source_filename, zoom_factor);
+#endif
 
 #if 0
   printf("CreateImageWithSmallImages: '%s' done\n", img_info->source_filename);
index e48e04cc83d43e5a12895f467bf5460d6b9edc16..3a2ac2023158aed2ddfb9f60c51d3bc9a87ce232 100644 (file)
@@ -68,6 +68,8 @@ Image *newImage(unsigned int, unsigned int, unsigned int);
 void freeImage(Image *);
 void freeXImage(Image *, XImageInfo *);
 
+Pixmap Pixmap_to_Mask(Pixmap, int, int);
+
 void ZoomPixmap(Display *, GC, Pixmap, Pixmap, int, int, int, int);
 
 int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
@@ -75,18 +77,20 @@ int Read_PCX_to_Pixmap(Display *, Window, GC, char *, Pixmap *, Pixmap *);
 #endif /* TARGET_X11 */
 
 int getImageListSize();
-struct FileInfo *getImageListEntry(int);
+struct FileInfo *getImageListEntryFromImageID(int);
 Bitmap *getBitmapFromImageID(int);
+int getOriginalImageWidthFromImageID(int);
+int getOriginalImageHeightFromImageID(int);
 char *getTokenFromImageID(int);
 int getImageIDFromToken(char *);
 char *getImageConfigFilename();
 int getImageListPropertyMappingSize();
 struct PropertyMapping *getImageListPropertyMapping();
-void InitImageList(struct ConfigInfo *, int, struct ConfigInfo *,
+void InitImageList(struct ConfigInfo *, int, struct ConfigTypeInfo *,
                   char **, char **, char **, char **, char **);
 
 void ReloadCustomImages();
-void CreateImageWithSmallImages(int);
+void CreateImageWithSmallImages(int, int);
 
 void FreeAllImages();
 
index d9cad1289ddd7d9fbabd79f76219bb4be0c5e91d..c2d0c192cc0d6323458f7d698eb0d4bfcf0f4f1c 100644 (file)
@@ -26,6 +26,8 @@
 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
 void UnixInitJoysticks()
 {
+  static boolean unix_joystick_subsystem_initialized = FALSE;
+  boolean print_warning = !unix_joystick_subsystem_initialized;
   int i;
 
   for (i = 0; i < MAX_PLAYERS; i++)
@@ -44,18 +46,24 @@ void UnixInitJoysticks()
 
     if (access(device_name, R_OK) != 0)
     {
-      Error(ERR_WARN, "cannot access joystick device '%s'", device_name);
+      if (print_warning)
+       Error(ERR_WARN, "cannot access joystick device '%s'", device_name);
+
       continue;
     }
 
     if ((joystick.fd[i] = open(device_name, O_RDONLY)) < 0)
     {
-      Error(ERR_WARN, "cannot open joystick device '%s'", device_name);
+      if (print_warning)
+       Error(ERR_WARN, "cannot open joystick device '%s'", device_name);
+
       continue;
     }
 
     joystick.status = JOYSTICK_ACTIVATED;
   }
+
+  unix_joystick_subsystem_initialized = TRUE;
 }
 
 boolean UnixReadJoystick(int fd, int *x, int *y, boolean *b1, boolean *b2)
index ba3796259bf2e02bd579dee4fba25d6593434e09..3881d202338a5d3ab1971a35cf080fab644b2241 100644 (file)
@@ -337,26 +337,24 @@ static char *get_corrected_real_name(char *real_name)
   char *from_ptr = real_name;
   char *to_ptr   = real_name_new;
 
-  if (strchr(real_name, 'ß') == NULL)  /* name does not contain 'ß' */
-  {
-    strncpy(real_name_new, real_name, MAX_USERNAME_LEN);
-    real_name_new[MAX_USERNAME_LEN] = '\0';
-
-    return real_name_new;
-  }
-
-  /* the user's real name may contain a 'ß' character (german sharp s),
-     which has no equivalent in upper case letters (which our fonts use) */
+  /* copy the name string, but not more than MAX_USERNAME_LEN characters */
   while (*from_ptr && (long)(to_ptr - real_name_new) < MAX_USERNAME_LEN - 1)
   {
-    if (*from_ptr != 'ß')
-      *to_ptr++ = *from_ptr++;
-    else
+    /* the name field read from "passwd" file may also contain additional
+       user information, separated by commas, which will be removed here */
+    if (*from_ptr == ',')
+      break;
+
+    /* the user's real name may contain 'ß' characters (german sharp s),
+       which have no equivalent in upper case letters (used by our fonts) */
+    if (*from_ptr == 'ß')
     {
       from_ptr++;
       *to_ptr++ = 's';
       *to_ptr++ = 's';
     }
+    else
+      *to_ptr++ = *from_ptr++;
   }
 
   *to_ptr = '\0';
@@ -458,6 +456,51 @@ char *getHomeDir()
 }
 
 
+/* ------------------------------------------------------------------------- */
+/* path manipulation functions                                               */
+/* ------------------------------------------------------------------------- */
+
+static char *getLastPathSeparatorPtr(char *filename)
+{
+  char *last_separator = strrchr(filename, '/');
+
+#if !defined(PLATFORM_UNIX)
+  if (last_separator == NULL)  /* also try DOS/Windows variant */
+    last_separator = strrchr(filename, '\\');
+#endif
+
+  return last_separator;
+}
+
+static char *getBaseNamePtr(char *filename)
+{
+  char *last_separator = getLastPathSeparatorPtr(filename);
+
+  if (last_separator != NULL)
+    return last_separator + 1; /* separator found: strip base path */
+  else
+    return filename;           /* no separator found: filename has no path */
+}
+
+char *getBaseName(char *filename)
+{
+  return getStringCopy(getBaseNamePtr(filename));
+}
+
+char *getBasePath(char *filename)
+{
+  char *basepath = getStringCopy(filename);
+  char *last_separator = getLastPathSeparatorPtr(basepath);
+
+  if (last_separator != NULL)
+    *last_separator = '\0';    /* separator found: strip basename */
+  else
+    basepath = ".";            /* no separator found: use current path */
+
+  return basepath;
+}
+
+
 /* ------------------------------------------------------------------------- */
 /* various string functions                                                  */
 /* ------------------------------------------------------------------------- */
@@ -531,19 +574,34 @@ void setString(char **old_value, char *new_value)
 
 void GetOptions(char *argv[], void (*print_usage_function)(void))
 {
+  char *ro_base_path = RO_BASE_PATH;
+  char *rw_base_path = RW_BASE_PATH;
   char **options_left = &argv[1];
 
+#if !defined(PLATFORM_MACOSX)
+  /* if the program is configured to start from current directory (default),
+     determine program package directory (KDE/Konqueror does not do this by
+     itself and fails otherwise); on Mac OS X, the program binary is stored
+     in an application package directory -- do not try to use this directory
+     as the program data directory (Mac OS X handles this correctly anyway) */
+
+  if (strcmp(ro_base_path, ".") == 0)
+    ro_base_path = program.command_basepath;
+  if (strcmp(rw_base_path, ".") == 0)
+    rw_base_path = program.command_basepath;
+#endif
+
   /* initialize global program options */
   options.display_name = NULL;
   options.server_host = NULL;
   options.server_port = 0;
-  options.ro_base_directory = RO_BASE_PATH;
-  options.rw_base_directory = RW_BASE_PATH;
-  options.level_directory = RO_BASE_PATH "/" LEVELS_DIRECTORY;
-  options.graphics_directory = RO_BASE_PATH "/" GRAPHICS_DIRECTORY;
-  options.sounds_directory = RO_BASE_PATH "/" SOUNDS_DIRECTORY;
-  options.music_directory = RO_BASE_PATH "/" MUSIC_DIRECTORY;
-  options.docs_directory = RO_BASE_PATH "/" DOCS_DIRECTORY;
+  options.ro_base_directory = ro_base_path;
+  options.rw_base_directory = rw_base_path;
+  options.level_directory    = getPath2(ro_base_path, LEVELS_DIRECTORY);
+  options.graphics_directory = getPath2(ro_base_path, GRAPHICS_DIRECTORY);
+  options.sounds_directory   = getPath2(ro_base_path, SOUNDS_DIRECTORY);
+  options.music_directory    = getPath2(ro_base_path, MUSIC_DIRECTORY);
+  options.docs_directory     = getPath2(ro_base_path, DOCS_DIRECTORY);
   options.execute_command = NULL;
   options.serveronly = FALSE;
   options.network = FALSE;
@@ -610,22 +668,17 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
        Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
 
       /* this should be extended to separate options for ro and rw data */
-      options.ro_base_directory = option_arg;
-      options.rw_base_directory = option_arg;
+      options.ro_base_directory = ro_base_path = option_arg;
+      options.rw_base_directory = rw_base_path = option_arg;
       if (option_arg == next_option)
        options_left++;
 
       /* adjust paths for sub-directories in base directory accordingly */
-      options.level_directory =
-       getPath2(options.ro_base_directory, LEVELS_DIRECTORY);
-      options.graphics_directory =
-       getPath2(options.ro_base_directory, GRAPHICS_DIRECTORY);
-      options.sounds_directory =
-       getPath2(options.ro_base_directory, SOUNDS_DIRECTORY);
-      options.music_directory =
-       getPath2(options.ro_base_directory, MUSIC_DIRECTORY);
-      options.docs_directory =
-       getPath2(options.ro_base_directory, DOCS_DIRECTORY);
+      options.level_directory    = getPath2(ro_base_path, LEVELS_DIRECTORY);
+      options.graphics_directory = getPath2(ro_base_path, GRAPHICS_DIRECTORY);
+      options.sounds_directory   = getPath2(ro_base_path, SOUNDS_DIRECTORY);
+      options.music_directory    = getPath2(ro_base_path, MUSIC_DIRECTORY);
+      options.docs_directory     = getPath2(ro_base_path, DOCS_DIRECTORY);
     }
     else if (strncmp(option, "-levels", option_len) == 0)
     {
@@ -1504,6 +1557,9 @@ void dumpList(ListNode *node_first)
 
 boolean fileExists(char *filename)
 {
+  if (filename == NULL)
+    return FALSE;
+
 #if 0
   printf("checking file '%s'\n", filename);
 #endif
@@ -1557,27 +1613,21 @@ boolean fileHasSuffix(char *basename, char *suffix)
 
 boolean FileIsGraphic(char *filename)
 {
-  char *basename = strrchr(filename, '/');
-
-  basename = (basename != NULL ? basename + 1 : filename);
+  char *basename = getBaseNamePtr(filename);
 
   return fileHasSuffix(basename, "pcx");
 }
 
 boolean FileIsSound(char *filename)
 {
-  char *basename = strrchr(filename, '/');
-
-  basename = (basename != NULL ? basename + 1 : filename);
+  char *basename = getBaseNamePtr(filename);
 
   return fileHasSuffix(basename, "wav");
 }
 
 boolean FileIsMusic(char *filename)
 {
-  char *basename = strrchr(filename, '/');
-
-  basename = (basename != NULL ? basename + 1 : filename);
+  char *basename = getBaseNamePtr(filename);
 
   if (FileIsSound(basename))
     return TRUE;
@@ -1612,6 +1662,27 @@ boolean FileIsArtworkType(char *basename, int type)
 /* functions for loading artwork configuration information                   */
 /* ------------------------------------------------------------------------- */
 
+char *get_mapped_token(char *token)
+{
+  /* !!! make this dynamically configurable (init.c:InitArtworkConfig) !!! */
+  static char *map_token_prefix[][2] =
+  {
+    { "char_procent",          "char_percent"  },
+    { NULL,                                    }
+  };
+  int i;
+
+  for (i = 0; map_token_prefix[i][0] != NULL; i++)
+  {
+    int len_token_prefix = strlen(map_token_prefix[i][0]);
+
+    if (strncmp(token, map_token_prefix[i][0], len_token_prefix) == 0)
+      return getStringCat2(map_token_prefix[i][1], &token[len_token_prefix]);
+  }
+
+  return NULL;
+}
+
 /* This function checks if a string <s> of the format "string1, string2, ..."
    exactly contains a string <s_contained>. */
 
@@ -1707,7 +1778,7 @@ static void FreeCustomArtworkList(struct ArtworkListInfo *,
                                  struct ListNodeInfo ***, int *);
 
 struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
-                                          struct ConfigInfo *suffix_list,
+                                          struct ConfigTypeInfo *suffix_list,
                                           char **ignore_tokens,
                                           int num_file_list_entries)
 {
@@ -1742,6 +1813,9 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
        setString(&file_list[i].default_parameter[j], suffix_list[j].value);
        setString(&file_list[i].parameter[j], suffix_list[j].value);
       }
+
+      file_list[i].redefined = FALSE;
+      file_list[i].fallback_to_default = FALSE;
     }
   }
 
@@ -1842,7 +1916,7 @@ static boolean token_suffix_match(char *token, char *suffix, int start_pos)
 #define KNOWN_TOKEN_VALUE      "[KNOWN_TOKEN_VALUE]"
 
 static void read_token_parameters(SetupFileHash *setup_file_hash,
-                                 struct ConfigInfo *suffix_list,
+                                 struct ConfigTypeInfo *suffix_list,
                                  struct FileInfo *file_list_entry)
 {
   /* check for config token that is the base token without any suffixes */
@@ -1895,7 +1969,7 @@ static void read_token_parameters(SetupFileHash *setup_file_hash,
 static void add_dynamic_file_list_entry(struct FileInfo **list,
                                        int *num_list_entries,
                                        SetupFileHash *extra_file_hash,
-                                       struct ConfigInfo *suffix_list,
+                                       struct ConfigTypeInfo *suffix_list,
                                        int num_suffix_list_entries,
                                        char *token)
 {
@@ -1916,6 +1990,9 @@ static void add_dynamic_file_list_entry(struct FileInfo **list,
   new_list_entry->filename = NULL;
   new_list_entry->parameter = checked_calloc(parameter_array_size);
 
+  new_list_entry->redefined = FALSE;
+  new_list_entry->fallback_to_default = FALSE;
+
   read_token_parameters(extra_file_hash, suffix_list, new_list_entry);
 }
 
@@ -1944,7 +2021,7 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
                                          char *filename)
 {
   struct FileInfo *file_list = artwork_info->file_list;
-  struct ConfigInfo *suffix_list = artwork_info->suffix_list;
+  struct ConfigTypeInfo *suffix_list = artwork_info->suffix_list;
   char **base_prefixes = artwork_info->base_prefixes;
   char **ext1_suffixes = artwork_info->ext1_suffixes;
   char **ext2_suffixes = artwork_info->ext2_suffixes;
@@ -1987,6 +2064,29 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
   /* at this point, we do not need the setup file hash anymore -- free it */
   freeSetupFileHash(setup_file_hash);
 
+#if 1
+  /* map deprecated to current tokens (using prefix match and replace) */
+  BEGIN_HASH_ITERATION(valid_file_hash, itr)
+  {
+    char *token = HASH_ITERATION_TOKEN(itr);
+    char *mapped_token = get_mapped_token(token);
+
+    if (mapped_token != NULL)
+    {
+      char *value = HASH_ITERATION_VALUE(itr);
+
+      /* add mapped token */
+      setHashEntry(valid_file_hash, mapped_token, value);
+
+      /* ignore old token (by setting it to "known" keyword) */
+      setHashEntry(valid_file_hash, token, known_token_value);
+
+      free(mapped_token);
+    }
+  }
+  END_HASH_ITERATION(valid_file_hash, itr)
+#endif
+
   /* read parameters for all known config file tokens */
   for (i = 0; i < num_file_list_entries; i++)
     read_token_parameters(valid_file_hash, suffix_list, &file_list[i]);
@@ -2030,6 +2130,10 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
     boolean base_prefix_found = FALSE;
     boolean parameter_suffix_found = FALSE;
 
+#if 0
+    printf("::: examining '%s' -> '%s'\n", token, HASH_ITERATION_VALUE(itr));
+#endif
+
     /* skip all parameter definitions (handled by read_token_parameters()) */
     for (i = 0; i < num_suffix_list_entries && !parameter_suffix_found; i++)
     {
@@ -2336,6 +2440,7 @@ void LoadArtworkConfig(struct ArtworkListInfo *artwork_info)
       setString(&file_list[i].parameter[j], file_list[i].default_parameter[j]);
 
     file_list[i].redefined = FALSE;
+    file_list[i].fallback_to_default = FALSE;
   }
 
   /* free previous dynamic artwork file array */
@@ -2404,6 +2509,127 @@ static void deleteArtworkListEntry(struct ArtworkListInfo *artwork_info,
   }
 }
 
+#if 1
+static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
+                                   struct ListNodeInfo **listnode,
+                                   struct FileInfo *file_list_entry)
+{
+  char *init_text[] =
+  {
+    "Loading graphics:",
+    "Loading sounds:",
+    "Loading music:"
+  };
+
+  ListNode *node;
+  char *basename = file_list_entry->filename;
+  char *filename = getCustomArtworkFilename(basename, artwork_info->type);
+
+#if 0
+  if (strcmp(file_list_entry->token, "background.DOOR") == 0)
+    printf("::: replaceArtworkListEntry: '%s' => '%s'\n",
+          basename, filename);
+#endif
+
+  if (filename == NULL)
+  {
+    Error(ERR_WARN, "cannot find artwork file '%s'", basename);
+
+    basename = file_list_entry->default_filename;
+
+    /* dynamic artwork has no default filename / skip empty default artwork */
+    if (basename == NULL || strcmp(basename, UNDEFINED_FILENAME) == 0)
+      return;
+
+    file_list_entry->fallback_to_default = TRUE;
+
+    Error(ERR_WARN, "trying default artwork file '%s'", basename);
+
+    filename = getCustomArtworkFilename(basename, artwork_info->type);
+
+    if (filename == NULL)
+    {
+      int error_mode = ERR_WARN;
+
+      /* we can get away without sounds and music, but not without graphics */
+      if (*listnode == NULL && artwork_info->type == ARTWORK_TYPE_GRAPHICS)
+       error_mode = ERR_EXIT;
+
+      Error(error_mode, "cannot find default artwork file '%s'", basename);
+
+      return;
+    }
+  }
+
+  /* check if the old and the new artwork file are the same */
+  if (*listnode && strcmp((*listnode)->source_filename, filename) == 0)
+  {
+    /* The old and new artwork are the same (have the same filename and path).
+       This usually means that this artwork does not exist in this artwork set
+       and a fallback to the existing artwork is done. */
+
+#if 0
+    printf("[artwork '%s' already exists (same list entry)]\n", filename);
+#endif
+
+    return;
+  }
+
+  /* delete existing artwork file entry */
+  deleteArtworkListEntry(artwork_info, listnode);
+
+  /* check if the new artwork file already exists in the list of artworks */
+  if ((node = getNodeFromKey(artwork_info->content_list, filename)) != NULL)
+  {
+#if 0
+      printf("[artwork '%s' already exists (other list entry)]\n", filename);
+#endif
+
+      *listnode = (struct ListNodeInfo *)node->content;
+      (*listnode)->num_references++;
+
+      return;
+  }
+
+#if 0
+  if (strcmp(file_list_entry->token, "background.DOOR") == 0)
+    printf("::: replaceArtworkListEntry: LOAD IT'\n");
+#endif
+
+#if 0
+  printf("::: %s: '%s'\n", init_text[artwork_info->type], basename);
+#endif
+
+  DrawInitText(init_text[artwork_info->type], 120, FC_GREEN);
+  DrawInitText(basename, 150, FC_YELLOW);
+
+  if ((*listnode = artwork_info->load_artwork(filename)) != NULL)
+  {
+#if 0
+      printf("[adding new artwork '%s']\n", filename);
+#endif
+
+    (*listnode)->num_references = 1;
+    addNodeToList(&artwork_info->content_list, (*listnode)->source_filename,
+                 *listnode);
+  }
+  else
+  {
+    int error_mode = ERR_WARN;
+
+#if 1
+    /* we can get away without sounds and music, but not without graphics */
+    if (artwork_info->type == ARTWORK_TYPE_GRAPHICS)
+      error_mode = ERR_EXIT;
+#endif
+
+    Error(error_mode, "cannot load artwork file '%s'", basename);
+    return;
+  }
+}
+
+#else
+
 static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
                                    struct ListNodeInfo **listnode,
                                    char *basename)
@@ -2423,6 +2649,9 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
     int error_mode = ERR_WARN;
 
 #if 1
+    /* !!! NEW ARTWORK FALLBACK CODE !!! NEARLY UNTESTED !!! */
+    /* before failing, try fallback to default artwork */
+#else
     /* we can get away without sounds and music, but not without graphics */
     if (*listnode == NULL && artwork_info->type == ARTWORK_TYPE_GRAPHICS)
       error_mode = ERR_EXIT;
@@ -2493,6 +2722,33 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
     return;
   }
 }
+#endif
+
+#if 1
+static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info,
+                             struct ListNodeInfo **listnode,
+                             struct FileInfo *file_list_entry)
+{
+#if 0
+  printf("GOT CUSTOM ARTWORK FILE '%s'\n", filename);
+#endif
+
+#if 0
+  if (strcmp(file_list_entry->token, "background.DOOR") == 0)
+    printf("::: -> '%s' -> '%s'\n",
+          file_list_entry->token, file_list_entry->filename);
+#endif
+
+  if (strcmp(file_list_entry->filename, UNDEFINED_FILENAME) == 0)
+  {
+    deleteArtworkListEntry(artwork_info, listnode);
+    return;
+  }
+
+  replaceArtworkListEntry(artwork_info, listnode, file_list_entry);
+}
+
+#else
 
 static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info,
                              struct ListNodeInfo **listnode,
@@ -2510,6 +2766,38 @@ static void LoadCustomArtwork(struct ArtworkListInfo *artwork_info,
 
   replaceArtworkListEntry(artwork_info, listnode, basename);
 }
+#endif
+
+#if 1
+static void LoadArtworkToList(struct ArtworkListInfo *artwork_info,
+                             struct ListNodeInfo **listnode,
+                             struct FileInfo *file_list_entry)
+{
+#if 0
+  if (artwork_info->artwork_list == NULL ||
+      list_pos >= artwork_info->num_file_list_entries)
+    return;
+#endif
+
+#if 0
+  printf("loading artwork '%s' ...  [%d]\n",
+        file_list_entry->filename, getNumNodes(artwork_info->content_list));
+#endif
+
+#if 1
+  LoadCustomArtwork(artwork_info, listnode, file_list_entry);
+#else
+  LoadCustomArtwork(artwork_info, &artwork_info->artwork_list[list_pos],
+                   basename);
+#endif
+
+#if 0
+  printf("loading artwork '%s' done [%d]\n",
+        basename, getNumNodes(artwork_info->content_list));
+#endif
+}
+
+#else
 
 static void LoadArtworkToList(struct ArtworkListInfo *artwork_info,
                              struct ListNodeInfo **listnode,
@@ -2538,6 +2826,7 @@ static void LoadArtworkToList(struct ArtworkListInfo *artwork_info,
         basename, getNumNodes(artwork_info->content_list));
 #endif
 }
+#endif
 
 void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
 {
@@ -2556,22 +2845,51 @@ void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
   for (i = 0; i < num_file_list_entries; i++)
   {
 #if 0
-    if (strcmp(file_list[i].token, "background") == 0)
+    if (strcmp(file_list[i].token, "background.DOOR") == 0)
       printf("::: '%s' -> '%s'\n", file_list[i].token, file_list[i].filename);
 #endif
 
+#if 1
+    LoadArtworkToList(artwork_info, &artwork_info->artwork_list[i],
+                     &file_list[i]);
+#else
     LoadArtworkToList(artwork_info, &artwork_info->artwork_list[i],
                      file_list[i].filename, i);
+#endif
+
+#if 0
+    if (strcmp(file_list[i].token, "background.DOOR") == 0)
+    {
+      Bitmap *bitmap = getBitmapFromImageID(i);
+
+      printf("::: BITMAP: %08lx\n", bitmap);
+
+#if 0
+      BlitBitmap(bitmap, window, 0, 0, 100, 280, 0, 0);
+#endif
+    }
+#endif
 
 #if 0
+    /* !!! NEW ARTWORK FALLBACK CODE !!! NEARLY UNTESTED !!! */
     if (artwork_info->artwork_list[i] == NULL &&
-       strcmp(file_list[i].default_filename, file_list[i].filename) != 0)
+       strcmp(file_list[i].filename, UNDEFINED_FILENAME) != 0 &&
+       strcmp(file_list[i].default_filename, file_list[i].filename) != 0 &&
+       strcmp(file_list[i].default_filename, UNDEFINED_FILENAME) != 0)
     {
       Error(ERR_WARN, "trying default artwork file '%s'",
            file_list[i].default_filename);
 
       LoadArtworkToList(artwork_info, &artwork_info->artwork_list[i],
                        file_list[i].default_filename, i);
+
+      /* even the fallback to default artwork was not successful -- fail now */
+      if (artwork_info->artwork_list[i] == NULL &&
+         artwork_info->type == ARTWORK_TYPE_GRAPHICS)
+       Error(ERR_EXIT, "cannot find artwork file '%s' or default file '%s'",
+             file_list[i].filename, file_list[i].default_filename);
+
+      file_list[i].fallback_to_default = TRUE;
     }
 #endif
   }
@@ -2583,14 +2901,21 @@ void ReloadCustomArtworkList(struct ArtworkListInfo *artwork_info)
 
   for (i = 0; i < num_dynamic_file_list_entries; i++)
   {
+#if 1
+    LoadArtworkToList(artwork_info, &artwork_info->dynamic_artwork_list[i],
+                     &dynamic_file_list[i]);
+#else
     LoadArtworkToList(artwork_info, &artwork_info->dynamic_artwork_list[i],
                      dynamic_file_list[i].filename, i);
+#endif
 
 #if 0
     printf("::: '%s', '0x%08x'\n",
           dynamic_file_list[i].filename,
           dynamic_file_list[i].default_filename);
 #endif
+
+    /* dynamic artwork does not have default filename! */
   }
 
 #if 0
index 2f3a957ab5097fb06c0972a3869b591fc5a74d2f..b89be4e87d6382ef19d4305f876d28364a97692f 100644 (file)
@@ -27,7 +27,7 @@
 /* values for InitRND() */
 #define NEW_RANDOMIZE                  -1
 
-#define InitRND(seed)                  init_random_number(0, seed)
+#define InitEngineRND(seed)            init_random_number(0, seed)
 #define InitSimpleRND(seed)            init_random_number(1, seed)
 #define RND(max)                       get_random_number(0, max)
 #define SimpleRND(max)                 get_random_number(1, max)
@@ -94,6 +94,9 @@ char *getLoginName(void);
 char *getRealName(void);
 char *getHomeDir(void);
 
+char *getBasePath(char *);
+char *getBaseName(char *);
+
 char *getPath2(char *, char *);
 char *getPath3(char *, char *, char*);
 char *getStringCat2(char *, char *);
@@ -162,11 +165,14 @@ boolean FileIsSound(char *);
 boolean FileIsMusic(char *);
 boolean FileIsArtworkType(char *, int);
 
+char *get_mapped_token(char *);
+
 int get_parameter_value(char *, char *, int);
 int get_auto_parameter_value(char *, char *);
 
 struct FileInfo *getFileListFromConfigList(struct ConfigInfo *,
-                                          struct ConfigInfo *, char **, int);
+                                          struct ConfigTypeInfo *,
+                                          char **, int);
 void LoadArtworkConfig(struct ArtworkListInfo *);
 void ReloadCustomArtworkList(struct ArtworkListInfo *);
 void FreeCustomArtworkLists(struct ArtworkListInfo *);
index 5e1683619d8053a003a5273eabf58e15d2c3a165..baabd7e102080c53bae2efeb6eb7f610bd205bce 100644 (file)
 
 #if defined(__FreeBSD__)
 #define PLATFORM_FREEBSD
+#define PLATFORM_BSD
 #endif
 
 #if defined(__NetBSD__)
 #define PLATFORM_NETBSD
+#define PLATFORM_BSD
 #endif
 
 #if defined(__bsdi__)
 #define PLATFORM_BSDI
+#define PLATFORM_BSD
 #endif
 
 #if defined(sparc) && defined(sun)
index e9d10df51f3a8103acb3520b27615e00cb487e1c..b127c7844055152de46fc5f8474abd93c5be1237 100644 (file)
@@ -1116,9 +1116,8 @@ int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
   -----------------------------------------------------------------------------
   zoomSurface()
 
-  Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
+  Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
   'zoomx' and 'zoomy' are scaling factors for width and height.
-  If 'smooth' is 1 then the destination 32bit surface is anti-aliased.
   If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
   into a 32bit RGBA format on the fly.
   -----------------------------------------------------------------------------
@@ -1441,6 +1440,7 @@ void HandleJoystickEvent(Event *event)
 void SDLInitJoysticks()
 {
   static boolean sdl_joystick_subsystem_initialized = FALSE;
+  boolean print_warning = !sdl_joystick_subsystem_initialized;
   int i;
 
   if (!sdl_joystick_subsystem_initialized)
@@ -1460,11 +1460,19 @@ void SDLInitJoysticks()
     int joystick_nr = getJoystickNrFromDeviceName(device_name);
 
     if (joystick_nr >= SDL_NumJoysticks())
+    {
+      if (setup.input[i].use_joystick && print_warning)
+       Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
+
       joystick_nr = -1;
+    }
 
     /* misuse joystick file descriptor variable to store joystick number */
     joystick.fd[i] = joystick_nr;
 
+    if (joystick_nr == -1)
+      continue;
+
     /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
     if (SDLCheckJoystickOpened(joystick_nr))
       SDLCloseJoystick(joystick_nr);
@@ -1474,7 +1482,9 @@ void SDLInitJoysticks()
 
     if (!SDLOpenJoystick(joystick_nr))
     {
-      Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
+      if (print_warning)
+       Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
+
       continue;
     }
 
index dc01ad4c9ecdbdcbffec3c9cf9a7117909d9877b..7c4fc88085bc28bace615f82fec30a274e7901a5 100644 (file)
@@ -41,10 +41,11 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
 
 #define LEVELCOLOR(n)  (IS_LEVELCLASS_TUTORIAL(n) ?            FC_BLUE :    \
                         IS_LEVELCLASS_CLASSICS(n) ?            FC_RED :     \
-                        IS_LEVELCLASS_BD(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_BD(n) ?                  FC_YELLOW :  \
                         IS_LEVELCLASS_EM(n) ?                  FC_YELLOW :  \
-                        IS_LEVELCLASS_SP(n) ?                  FC_GREEN :   \
+                        IS_LEVELCLASS_SP(n) ?                  FC_YELLOW :  \
                         IS_LEVELCLASS_DX(n) ?                  FC_YELLOW :  \
+                        IS_LEVELCLASS_SB(n) ?                  FC_YELLOW :  \
                         IS_LEVELCLASS_CONTRIB(n) ?             FC_GREEN :   \
                         IS_LEVELCLASS_PRIVATE(n) ?             FC_RED :     \
                         FC_BLUE)
@@ -55,14 +56,15 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
                         IS_LEVELCLASS_EM(n) ?                  3 :     \
                         IS_LEVELCLASS_SP(n) ?                  4 :     \
                         IS_LEVELCLASS_DX(n) ?                  5 :     \
-                        IS_LEVELCLASS_CONTRIB(n) ?             6 :     \
-                        IS_LEVELCLASS_PRIVATE(n) ?             7 :     \
+                        IS_LEVELCLASS_SB(n) ?                  6 :     \
+                        IS_LEVELCLASS_CONTRIB(n) ?             7 :     \
+                        IS_LEVELCLASS_PRIVATE(n) ?             8 :     \
                         9)
 
 #define ARTWORKCOLOR(n)        (IS_ARTWORKCLASS_CLASSICS(n) ?          FC_RED :     \
-                        IS_ARTWORKCLASS_CONTRIB(n) ?           FC_YELLOW :  \
+                        IS_ARTWORKCLASS_CONTRIB(n) ?           FC_GREEN :   \
                         IS_ARTWORKCLASS_PRIVATE(n) ?           FC_RED :     \
-                        IS_ARTWORKCLASS_LEVEL(n) ?             FC_GREEN :   \
+                        IS_ARTWORKCLASS_LEVEL(n) ?             FC_YELLOW :  \
                         FC_BLUE)
 
 #define ARTWORKSORTING(n) (IS_ARTWORKCLASS_CLASSICS(n) ?       0 :     \
@@ -71,10 +73,14 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] =
                           IS_ARTWORKCLASS_PRIVATE(n) ?         3 :     \
                           9)
 
-#define TOKEN_VALUE_POSITION           40
-#define TOKEN_COMMENT_POSITION         60
+#define TOKEN_VALUE_POSITION_SHORT             32
+#define TOKEN_VALUE_POSITION_DEFAULT           40
+#define TOKEN_COMMENT_POSITION_DEFAULT         60
 
-#define MAX_COOKIE_LEN                 256
+#define MAX_COOKIE_LEN                         256
+
+static int token_value_position   = TOKEN_VALUE_POSITION_DEFAULT;
+static int token_comment_position = TOKEN_COMMENT_POSITION_DEFAULT;
 
 
 /* ------------------------------------------------------------------------- */
@@ -148,7 +154,7 @@ static char *getLevelDirFromTreeInfo(TreeInfo *node)
 
   checked_free(level_dir);
 
-  level_dir = getPath2((node->user_defined ? getUserLevelDir(NULL) :
+  level_dir = getPath2((node->in_user_dir ? getUserLevelDir(NULL) :
                        options.level_directory), node->fullpath);
 
   return level_dir;
@@ -296,8 +302,8 @@ char *setLevelArtworkDir(TreeInfo *ti)
   if (ti == NULL || leveldir_current == NULL)
     return NULL;
 
-  artwork_path_ptr = &(LEVELDIR_ARTWORK_PATH(leveldir_current, ti->type));
-  artwork_set_ptr  = &(LEVELDIR_ARTWORK_SET( leveldir_current, ti->type));
+  artwork_path_ptr = LEVELDIR_ARTWORK_PATH_PTR(leveldir_current, ti->type);
+  artwork_set_ptr  = LEVELDIR_ARTWORK_SET_PTR( leveldir_current, ti->type);
 
   checked_free(*artwork_path_ptr);
 
@@ -404,7 +410,12 @@ char *getEditorSetupFilename()
   static char *filename = NULL;
 
   checked_free(filename);
+  filename = getPath2(getCurrentLevelDir(), EDITORSETUP_FILENAME);
+
+  if (fileExists(filename))
+    return filename;
 
+  checked_free(filename);
   filename = getPath2(getSetupDir(), EDITORSETUP_FILENAME);
 
   return filename;
@@ -438,8 +449,8 @@ char *getLevelSetInfoFilename()
   char *basenames[] =
   {
     "README",
-    "README.txt",
     "README.TXT",
+    "README.txt",
     "Readme",
     "Readme.txt",
     "readme",
@@ -452,8 +463,8 @@ char *getLevelSetInfoFilename()
   for (i = 0; basenames[i] != NULL; i++)
   {
     checked_free(filename);
-
     filename = getPath2(getCurrentLevelDir(), basenames[i]);
+
     if (fileExists(filename))
       return filename;
   }
@@ -769,7 +780,7 @@ static void SaveUserLevelInfo();
 
 void InitUserLevelDirectory(char *level_subdir)
 {
-  if (access(getUserLevelDir(level_subdir), F_OK) != 0)
+  if (!fileExists(getUserLevelDir(level_subdir)))
   {
     createDirectory(getUserDataDir(), "user data", PERMS_PRIVATE);
     createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE);
@@ -929,7 +940,7 @@ void dumpTreeInfo(TreeInfo *node, int depth)
 
 #if 1
     printf("subdir == '%s' ['%s', '%s'] [%d])\n",
-          node->subdir, node->fullpath, node->basepath, node->user_defined);
+          node->subdir, node->fullpath, node->basepath, node->in_user_dir);
 #else
     printf("subdir == '%s' (%s) [%s] (%d)\n",
           node->subdir, node->name, node->identifier, node->sort_priority);
@@ -1103,7 +1114,7 @@ void createDirectory(char *dir, char *text, int permission_class)
   mode_t group_umask = ~(dir_mode & S_IRWXG);
   posix_umask(normal_umask & group_umask);
 
-  if (access(dir, F_OK) != 0)
+  if (!fileExists(dir))
     if (posix_mkdir(dir, dir_mode) != 0)
       Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
 
@@ -1198,7 +1209,7 @@ char *getFormattedSetupEntry(char *token, char *value)
 
   /* start with the token and some spaces to format output line */
   sprintf(entry, "%s:", token);
-  for (i = strlen(entry); i < TOKEN_VALUE_POSITION; i++)
+  for (i = strlen(entry); i < token_value_position; i++)
     strcat(entry, " ");
 
   /* continue with the token's value */
@@ -1406,17 +1417,18 @@ static void *loadSetupFileData(char *filename, boolean use_hash)
   boolean read_continued_line = FALSE;
   FILE *file;
 
-  if (use_hash)
-    setup_file_data = newSetupFileHash();
-  else
-    insert_ptr = setup_file_data = newSetupFileList("", "");
-
   if (!(file = fopen(filename, MODE_READ)))
   {
     Error(ERR_WARN, "cannot open configuration file '%s'", filename);
+
     return NULL;
   }
 
+  if (use_hash)
+    setup_file_data = newSetupFileHash();
+  else
+    insert_ptr = setup_file_data = newSetupFileList("", "");
+
   while (!feof(file))
   {
     /* read next line of input file */
@@ -1573,20 +1585,22 @@ void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash,
 #define LEVELINFO_TOKEN_NAME_SORTING   2
 #define LEVELINFO_TOKEN_AUTHOR         3
 #define LEVELINFO_TOKEN_IMPORTED_FROM  4
-#define LEVELINFO_TOKEN_LEVELS         5
-#define LEVELINFO_TOKEN_FIRST_LEVEL    6
-#define LEVELINFO_TOKEN_SORT_PRIORITY  7
-#define LEVELINFO_TOKEN_LATEST_ENGINE  8
-#define LEVELINFO_TOKEN_LEVEL_GROUP    9
-#define LEVELINFO_TOKEN_READONLY       10
-#define LEVELINFO_TOKEN_GRAPHICS_SET   11
-#define LEVELINFO_TOKEN_SOUNDS_SET     12
-#define LEVELINFO_TOKEN_MUSIC_SET      13
-#define LEVELINFO_TOKEN_FILENAME       14
-#define LEVELINFO_TOKEN_FILETYPE       15
-#define LEVELINFO_TOKEN_HANDICAP       16
-
-#define NUM_LEVELINFO_TOKENS           17
+#define LEVELINFO_TOKEN_IMPORTED_BY    5
+#define LEVELINFO_TOKEN_LEVELS         6
+#define LEVELINFO_TOKEN_FIRST_LEVEL    7
+#define LEVELINFO_TOKEN_SORT_PRIORITY  8
+#define LEVELINFO_TOKEN_LATEST_ENGINE  9
+#define LEVELINFO_TOKEN_LEVEL_GROUP    10
+#define LEVELINFO_TOKEN_READONLY       11
+#define LEVELINFO_TOKEN_GRAPHICS_SET   12
+#define LEVELINFO_TOKEN_SOUNDS_SET     13
+#define LEVELINFO_TOKEN_MUSIC_SET      14
+#define LEVELINFO_TOKEN_FILENAME       15
+#define LEVELINFO_TOKEN_FILETYPE       16
+#define LEVELINFO_TOKEN_HANDICAP       17
+#define LEVELINFO_TOKEN_SKIP_LEVELS    18
+
+#define NUM_LEVELINFO_TOKENS           19
 
 static LevelDirTree ldi;
 
@@ -1598,6 +1612,7 @@ static struct TokenInfo levelinfo_tokens[] =
   { TYPE_STRING,       &ldi.name_sorting,      "name_sorting"  },
   { TYPE_STRING,       &ldi.author,            "author"        },
   { TYPE_STRING,       &ldi.imported_from,     "imported_from" },
+  { TYPE_STRING,       &ldi.imported_by,       "imported_by"   },
   { TYPE_INTEGER,      &ldi.levels,            "levels"        },
   { TYPE_INTEGER,      &ldi.first_level,       "first_level"   },
   { TYPE_INTEGER,      &ldi.sort_priority,     "sort_priority" },
@@ -1609,7 +1624,8 @@ static struct TokenInfo levelinfo_tokens[] =
   { TYPE_STRING,       &ldi.music_set,         "music_set"     },
   { TYPE_STRING,       &ldi.level_filename,    "filename"      },
   { TYPE_STRING,       &ldi.level_filetype,    "filetype"      },
-  { TYPE_BOOLEAN,      &ldi.handicap,          "handicap"      }
+  { TYPE_BOOLEAN,      &ldi.handicap,          "handicap"      },
+  { TYPE_BOOLEAN,      &ldi.skip_levels,       "skip_levels"   }
 };
 
 static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
@@ -1640,6 +1656,7 @@ static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
   ldi->sort_priority = LEVELCLASS_UNDEFINED;   /* default: least priority */
   ldi->latest_engine = FALSE;                  /* default: get from level */
   ldi->parent_link = FALSE;
+  ldi->in_user_dir = FALSE;
   ldi->user_defined = FALSE;
   ldi->color = 0;
   ldi->class_desc = NULL;
@@ -1647,6 +1664,7 @@ static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
   if (ldi->type == TREE_TYPE_LEVEL_DIR)
   {
     ldi->imported_from = NULL;
+    ldi->imported_by = NULL;
 
     ldi->graphics_set = NULL;
     ldi->sounds_set = NULL;
@@ -1665,6 +1683,7 @@ static void setTreeInfoToDefaults(TreeInfo *ldi, int type)
     ldi->handicap_level = 0;
     ldi->readonly = TRUE;
     ldi->handicap = TRUE;
+    ldi->skip_levels = FALSE;
   }
 }
 
@@ -1703,6 +1722,7 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
   ldi->sort_priority = parent->sort_priority;
   ldi->latest_engine = parent->latest_engine;
   ldi->parent_link = FALSE;
+  ldi->in_user_dir = parent->in_user_dir;
   ldi->user_defined = parent->user_defined;
   ldi->color = parent->color;
   ldi->class_desc = getStringCopy(parent->class_desc);
@@ -1710,6 +1730,7 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
   if (ldi->type == TREE_TYPE_LEVEL_DIR)
   {
     ldi->imported_from = getStringCopy(parent->imported_from);
+    ldi->imported_by = getStringCopy(parent->imported_by);
 
     ldi->graphics_set = NULL;
     ldi->sounds_set = NULL;
@@ -1728,6 +1749,7 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
     ldi->handicap_level = 0;
     ldi->readonly = TRUE;
     ldi->handicap = TRUE;
+    ldi->skip_levels = FALSE;
   }
 
 #else
@@ -1751,6 +1773,7 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ldi, TreeInfo *parent)
   ldi->author = getStringCopy(parent->author);
 
   ldi->imported_from = getStringCopy(parent->imported_from);
+  ldi->imported_by = getStringCopy(parent->imported_by);
   ldi->class_desc = getStringCopy(parent->class_desc);
 
   ldi->graphics_set = NULL;
@@ -1787,6 +1810,7 @@ static void freeTreeInfo(TreeInfo *ldi)
   if (ldi->type == TREE_TYPE_LEVEL_DIR)
   {
     checked_free(ldi->imported_from);
+    checked_free(ldi->imported_by);
 
     checked_free(ldi->graphics_set);
     checked_free(ldi->sounds_set);
@@ -1930,10 +1954,21 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
 {
   char *directory_path = getPath2(level_directory, directory_name);
   char *filename = getPath2(directory_path, LEVELINFO_FILENAME);
-  SetupFileHash *setup_file_hash = loadSetupFileHash(filename);
+  SetupFileHash *setup_file_hash;
   LevelDirTree *leveldir_new = NULL;
   int i;
 
+  /* unless debugging, silently ignore directories without "levelinfo.conf" */
+  if (!options.debug && !fileExists(filename))
+  {
+    free(directory_path);
+    free(filename);
+
+    return FALSE;
+  }
+
+  setup_file_hash = loadSetupFileHash(filename);
+
   if (setup_file_hash == NULL)
   {
     Error(ERR_WARN, "ignoring level directory '%s'", directory_path);
@@ -1999,13 +2034,24 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first,
     leveldir_new->first_level + leveldir_new->levels - 1;
 
 #if 1
-  leveldir_new->user_defined =
+  leveldir_new->in_user_dir =
     (strcmp(leveldir_new->basepath, options.level_directory) != 0);
 #else
-  leveldir_new->user_defined =
+  leveldir_new->in_user_dir =
     (leveldir_new->basepath == options.level_directory ? FALSE : TRUE);
 #endif
 
+#if 1
+  /* adjust sort priority if user's private level directory was detected */
+  if (leveldir_new->sort_priority == LEVELCLASS_UNDEFINED &&
+      leveldir_new->in_user_dir &&
+      strcmp(leveldir_new->subdir, getLoginName()) == 0)
+    leveldir_new->sort_priority = LEVELCLASS_PRIVATE_START;
+#endif
+
+  leveldir_new->user_defined =
+    (leveldir_new->in_user_dir && IS_LEVELCLASS_PRIVATE(leveldir_new));
+
   leveldir_new->color = LEVELCOLOR(leveldir_new);
 #if 1
   setString(&leveldir_new->class_desc, getLevelClassDescription(leveldir_new));
@@ -2132,7 +2178,7 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
   TreeInfo *artwork_new = NULL;
   int i;
 
-  if (access(filename, F_OK) == 0)             /* file exists */
+  if (fileExists(filename))
     setup_file_hash = loadSetupFileHash(filename);
 
   if (setup_file_hash == NULL) /* no config file -- look for artwork files */
@@ -2225,10 +2271,10 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first,
   }
 
 #if 1
-  artwork_new->user_defined =
+  artwork_new->in_user_dir =
     (strcmp(artwork_new->basepath, OPTIONS_ARTWORK_DIRECTORY(type)) != 0);
 #else
-  artwork_new->user_defined =
+  artwork_new->in_user_dir =
     (artwork_new->basepath == OPTIONS_ARTWORK_DIRECTORY(type) ? FALSE : TRUE);
 #endif
 
@@ -2609,11 +2655,13 @@ static void SaveUserLevelInfo()
   setString(&level_info->author, getRealName());
   level_info->levels = 100;
   level_info->first_level = 1;
+#if 0
   level_info->sort_priority = LEVELCLASS_PRIVATE_START;
   level_info->readonly = FALSE;
   setString(&level_info->graphics_set, GFX_CLASSIC_SUBDIR);
   setString(&level_info->sounds_set,   SND_CLASSIC_SUBDIR);
   setString(&level_info->music_set,    MUS_CLASSIC_SUBDIR);
+#endif
 #else
   ldi.name = getStringCopy(getLoginName());
   ldi.author = getStringCopy(getRealName());
@@ -2626,17 +2674,36 @@ static void SaveUserLevelInfo()
   ldi.music_set = getStringCopy(MUS_CLASSIC_SUBDIR);
 #endif
 
+  token_value_position = TOKEN_VALUE_POSITION_SHORT;
+
   fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
                                                 getCookie("LEVELINFO")));
 
   ldi = *level_info;
   for (i = 0; i < NUM_LEVELINFO_TOKENS; i++)
+  {
+#if 1
+    if (i == LEVELINFO_TOKEN_NAME ||
+       i == LEVELINFO_TOKEN_AUTHOR ||
+       i == LEVELINFO_TOKEN_LEVELS ||
+       i == LEVELINFO_TOKEN_FIRST_LEVEL)
+      fprintf(file, "%s\n", getSetupLine(levelinfo_tokens, "", i));
+
+    /* just to make things nicer :) */
+    if (i == LEVELINFO_TOKEN_AUTHOR)
+      fprintf(file, "\n");     
+#else
     if (i != LEVELINFO_TOKEN_IDENTIFIER &&
        i != LEVELINFO_TOKEN_NAME_SORTING &&
        i != LEVELINFO_TOKEN_IMPORTED_FROM &&
+       i != LEVELINFO_TOKEN_IMPORTED_BY &&
        i != LEVELINFO_TOKEN_FILENAME &&
        i != LEVELINFO_TOKEN_FILETYPE)
       fprintf(file, "%s\n", getSetupLine(levelinfo_tokens, "", i));
+#endif
+  }
+
+  token_value_position = TOKEN_VALUE_POSITION_DEFAULT;
 
   fclose(file);
 
@@ -2718,7 +2785,7 @@ char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr)
     {
       /* add at least one whitespace */
       strcat(line, " ");
-      for (i = strlen(line); i < TOKEN_COMMENT_POSITION; i++)
+      for (i = strlen(line); i < token_comment_position; i++)
        strcat(line, " ");
 
       strcat(line, "# ");
@@ -2800,7 +2867,7 @@ static void checkSeriesInfo()
 
   /* check for more levels besides the 'levels' field of 'levelinfo.conf' */
 
-  level_directory = getPath2((leveldir_current->user_defined ?
+  level_directory = getPath2((leveldir_current->in_user_dir ?
                              getUserLevelDir(NULL) :
                              options.level_directory),
                             leveldir_current->fullpath);
index 6e0636ea2a0d99f035f82722866d904cf3c2cec5..67a4c28287dc997a173b487e758dcc71a96cd805 100644 (file)
@@ -103,9 +103,11 @@ typedef struct hashtable     SetupFileHash;
 #define LEVELCLASS_SP_END              699
 #define LEVELCLASS_DX_START            700
 #define LEVELCLASS_DX_END              799
+#define LEVELCLASS_SB_START            800
+#define LEVELCLASS_SB_END              899
 
 #define LEVELCLASS_PREDEFINED_START    LEVELCLASS_TUTORIAL_START
-#define LEVELCLASS_PREDEFINED_END      LEVELCLASS_DX_END
+#define LEVELCLASS_PREDEFINED_END      LEVELCLASS_SB_END
 
 #define LEVELCLASS_TUTORIAL            LEVELCLASS_TUTORIAL_START
 #define LEVELCLASS_CLASSICS            LEVELCLASS_CLASSICS_START
@@ -115,6 +117,7 @@ typedef struct hashtable     SetupFileHash;
 #define LEVELCLASS_EM                  LEVELCLASS_EM_START
 #define LEVELCLASS_SP                  LEVELCLASS_SP_START
 #define LEVELCLASS_DX                  LEVELCLASS_DX_START
+#define LEVELCLASS_SB                  LEVELCLASS_SB_START
 
 #define LEVELCLASS_UNDEFINED           999
 
@@ -142,6 +145,9 @@ typedef struct hashtable     SetupFileHash;
 #define IS_LEVELCLASS_DX(p)                                            \
        ((p)->sort_priority >= LEVELCLASS_DX_START &&                   \
         (p)->sort_priority <= LEVELCLASS_DX_END)
+#define IS_LEVELCLASS_SB(p)                                            \
+       ((p)->sort_priority >= LEVELCLASS_SB_START &&                   \
+        (p)->sort_priority <= LEVELCLASS_SB_END)
 #define IS_LEVELCLASS_UNDEFINED(p)                                     \
        ((p)->sort_priority < LEVELCLASS_PREDEFINED_START ||            \
         (p)->sort_priority > LEVELCLASS_PREDEFINED_END)
@@ -154,6 +160,7 @@ typedef struct hashtable     SetupFileHash;
                         IS_LEVELCLASS_EM(n) ? LEVELCLASS_EM :             \
                         IS_LEVELCLASS_SP(n) ? LEVELCLASS_SP :             \
                         IS_LEVELCLASS_DX(n) ? LEVELCLASS_DX :             \
+                        IS_LEVELCLASS_SB(n) ? LEVELCLASS_SB :             \
                         LEVELCLASS_UNDEFINED)
 
 /* sort priorities of artwork */
index b9fd88c66a460dd72e58300cba60644236440794..6eb1de14df23ca62529752743f0fd5ef64f406d5 100644 (file)
@@ -2035,7 +2035,7 @@ struct PropertyMapping *getMusicListPropertyMapping()
 }
 
 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
-                  struct ConfigInfo *config_suffix_list,
+                  struct ConfigTypeInfo *config_suffix_list,
                   char **base_prefixes, char **ext1_suffixes,
                   char **ext2_suffixes, char **ext3_suffixes,
                   char **ignore_tokens)
@@ -2115,7 +2115,7 @@ void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
 }
 
 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
-                  struct ConfigInfo *config_suffix_list,
+                  struct ConfigTypeInfo *config_suffix_list,
                   char **base_prefixes, char **ext1_suffixes,
                   char **ext2_suffixes, char **ext3_suffixes,
                   char **ignore_tokens)
index 17a1cee2e2e9e8cceb951f1911958659aaa41b53..ca1e26a6009dc1cc98750396cb2ac7ea2de89299 100644 (file)
@@ -153,9 +153,9 @@ int getSoundListPropertyMappingSize();
 int getMusicListPropertyMappingSize();
 struct PropertyMapping *getSoundListPropertyMapping();
 struct PropertyMapping *getMusicListPropertyMapping();
-void InitSoundList(struct ConfigInfo *, int, struct ConfigInfo *,
+void InitSoundList(struct ConfigInfo *, int, struct ConfigTypeInfo *,
                   char **, char **, char **, char **, char **);
-void InitMusicList(struct ConfigInfo *, int, struct ConfigInfo *,
+void InitMusicList(struct ConfigInfo *, int, struct ConfigTypeInfo *,
                   char **, char **, char **, char **, char **);
 void InitReloadCustomSounds(char *);
 void InitReloadCustomMusic(char *);
index 8f26dc77fb97e7933f5ed2f24c71d453b0dfd5d9..8e65d97056a32dd2baebed276d6016ab46dedc30 100644 (file)
@@ -21,6 +21,7 @@
 #endif
 
 #include "system.h"
+#include "image.h"
 #include "sound.h"
 #include "setup.h"
 #include "joystick.h"
@@ -74,8 +75,8 @@ void InitProgramInfo(char *argv0,
                     char *cookie_prefix, char *filename_prefix,
                     int program_version)
 {
-  program.command_basename =
-    (strrchr(argv0, '/') ? strrchr(argv0, '/') + 1 : argv0);
+  program.command_basepath = getBasePath(argv0);
+  program.command_basename = getBaseName(argv0);
 
   program.userdata_directory = userdata_directory;
   program.program_title = program_title;
@@ -212,6 +213,8 @@ static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
 
 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
 {
+  /* !!! THIS DOES NOT WORK !!! REPLACED BITMAPS MAY HAVE SAME ADDRESS !!! */
+#if 0
   static Bitmap *main_bitmap_tile = NULL;
   static Bitmap *door_bitmap_tile = NULL;
 
@@ -225,14 +228,15 @@ void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
   else if (mask == REDRAW_DOOR_1)
   {
     if (background_bitmap_tile == door_bitmap_tile)
-      return;  /* main background tile has not changed */
+      return;          /* main background tile has not changed */
 
     door_bitmap_tile = background_bitmap_tile;
   }
-  else         /* should not happen */
+  else                 /* should not happen */
     return;
+#endif
 
-  if (background_bitmap_tile)
+  if (background_bitmap_tile != NULL)
     gfx.background_bitmap_mask |= mask;
   else
     gfx.background_bitmap_mask &= ~mask;
@@ -248,10 +252,12 @@ void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
     DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
                       gfx.real_sx, gfx.real_sy,
                       gfx.full_sxsize, gfx.full_sysize);
-  else
+  else if (mask == REDRAW_DOOR_1)
+  {
     DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
                       gfx.dx, gfx.dy,
                       gfx.dxsize, gfx.dysize);
+  }
 }
 
 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
@@ -438,8 +444,13 @@ inline boolean DrawingDeactivated(int x, int y, int width, int height)
 
 inline boolean DrawingOnBackground(int x, int y)
 {
+#if 1
+  return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
+         CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
+#else
   return ((gfx.draw_background_mask & gfx.background_bitmap_mask) &&
          CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
+#endif
 }
 
 inline void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
@@ -812,45 +823,114 @@ Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
   return dst_bitmap;
 }
 
-void CreateBitmapWithSmallBitmaps(Bitmap *src_bitmap)
+void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
 {
-  Bitmap *tmp_bitmap, *tmp_bitmap_2, *tmp_bitmap_8;
-  int src_width, src_height;
-  int tmp_width, tmp_height;
+  Bitmap swap_bitmap;
+  Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_8;
+  int width_1, height_1, width_2, height_2, width_8, height_8;
+  int new_width, new_height;
+
+  width_1  = old_bitmap->width  * zoom_factor;
+  height_1 = old_bitmap->height * zoom_factor;
+  width_2  = width_1  / 2;
+  height_2 = height_1 / 2;
+  width_8  = width_1  / 8;
+  height_8 = height_1 / 8;
+
+  /* get image with normal size (this might require scaling up) */
+  if (zoom_factor != 1)
+    tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
+  else
+    tmp_bitmap_1 = old_bitmap;
+
+  /* get image with 1/2 of normal size (for use in the level editor) */
+  if (zoom_factor != 2)
+    tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
+  else
+    tmp_bitmap_2 = old_bitmap;
+
+  /* get image with 1/8 of normal size (for use on the preview screen) */
+  if (zoom_factor != 8)
+    tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_1, width_1 / 8, height_1 / 8);
+  else
+    tmp_bitmap_8 = old_bitmap;
+
+  /* if image was scaled up, create new clipmask for normal size image */
+  if (zoom_factor != 1)
+  {
+#if defined(TARGET_X11)
+    if (old_bitmap->clip_mask)
+      XFreePixmap(display, old_bitmap->clip_mask);
+
+    old_bitmap->clip_mask =
+      Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
 
-  src_width  = src_bitmap->width;
-  src_height = src_bitmap->height;
+    XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
+#else
+    SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
+
+    if (old_bitmap->surface_masked)
+      SDL_FreeSurface(old_bitmap->surface_masked);
+
+    SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
+                   SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
+    if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
+      Error(ERR_EXIT, "SDL_DisplayFormat() failed");
+    SDL_SetColorKey(tmp_surface_1, 0, 0);      /* reset transparent pixel */
+#endif
+  }
+
+  new_width  = width_1;
+  new_height = height_1 + (height_1 + 1) / 2;     /* prevent odd height */
 
-  tmp_width  = src_width;
-  tmp_height = src_height + (src_height + 1) / 2;     /* prevent odd height */
+  new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
 
-  tmp_bitmap = CreateBitmap(tmp_width, tmp_height, DEFAULT_DEPTH);
+  BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
+  BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
+            0, height_1);
+  BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
+            3 * width_1 / 4, height_1);
 
-  tmp_bitmap_2 = ZoomBitmap(src_bitmap, src_width / 2, src_height / 2);
-  tmp_bitmap_8 = ZoomBitmap(src_bitmap, src_width / 8, src_height / 8);
+  if (zoom_factor != 1)
+    FreeBitmap(tmp_bitmap_1);
 
-  BlitBitmap(src_bitmap, tmp_bitmap, 0, 0, src_width, src_height, 0, 0);
-  BlitBitmap(tmp_bitmap_2, tmp_bitmap, 0, 0, src_width / 2, src_height / 2,
-            0, src_height);
-  BlitBitmap(tmp_bitmap_8, tmp_bitmap, 0, 0, src_width / 8, src_height / 8,
-            3 * src_width / 4, src_height);
+  if (zoom_factor != 2)
+    FreeBitmap(tmp_bitmap_2);
 
-  FreeBitmap(tmp_bitmap_2);
-  FreeBitmap(tmp_bitmap_8);
+  if (zoom_factor != 8)
+    FreeBitmap(tmp_bitmap_8);
+
+#if 0
 
 #if defined(TARGET_SDL)
-  /* !!! what about the old src_bitmap->surface ??? FIX ME !!! */
-  src_bitmap->surface = tmp_bitmap->surface;
-  tmp_bitmap->surface = NULL;
+  /* !!! what about the old old_bitmap->surface ??? FIX ME !!! */
+  old_bitmap->surface = new_bitmap->surface;
+  new_bitmap->surface = NULL;
 #else
   /* !!! see above !!! */
-  src_bitmap->drawable = tmp_bitmap->drawable;
-  tmp_bitmap->drawable = None;
+  old_bitmap->drawable = new_bitmap->drawable;
+  new_bitmap->drawable = None;
+#endif
+
+#else
+
+  /* replace image with extended image (containing normal, 1/2 and 1/8 size) */
+#if defined(TARGET_SDL)
+  swap_bitmap.surface = old_bitmap->surface;
+  old_bitmap->surface = new_bitmap->surface;
+  new_bitmap->surface = swap_bitmap.surface;
+#else
+  swap_bitmap.drawable = old_bitmap->drawable;
+  old_bitmap->drawable = new_bitmap->drawable;
+  new_bitmap->drawable = swap_bitmap.drawable;
 #endif
 
-  src_bitmap->height = tmp_bitmap->height;
+#endif
+
+  old_bitmap->width  = new_bitmap->width;
+  old_bitmap->height = new_bitmap->height;
 
-  FreeBitmap(tmp_bitmap);
+  FreeBitmap(new_bitmap);
 }
 
 
@@ -1073,6 +1153,15 @@ inline void NextEvent(Event *event)
 #endif
 }
 
+inline void PeekEvent(Event *event)
+{
+#if defined(TARGET_SDL)
+  SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
+#else
+  XPeekEvent(display, event);
+#endif
+}
+
 inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
 {
 #if defined(TARGET_SDL)
index 74a74a67e150ce4cd9baaaa8c709f675d730e4a6..0b210ed01f0584645db71364b390fbfa5700432a 100644 (file)
 #define BUTTON_1               4
 #define BUTTON_2               5
 
-/* values for move direction and special "button" key bitmasks */
+/* values for move directions and special "button" key bitmasks */
 #define MV_NO_MOVING           0
 #define MV_LEFT                        (1 << MV_BIT_LEFT)
 #define MV_RIGHT               (1 << MV_BIT_RIGHT)
 #define MV_UP                  (1 << MV_BIT_UP)
 #define MV_DOWN                        (1 << MV_BIT_DOWN)
 
+#define MV_HORIZONTAL          (MV_LEFT | MV_RIGHT)
+#define MV_VERTICAL            (MV_UP   | MV_DOWN)
+#define MV_ALL_DIRECTIONS      (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)
+#define MV_ANY_DIRECTION       (MV_ALL_DIRECTIONS)
+#define MV_NO_DIRECTIONS       (MV_NO_MOVING)
+
 #define KEY_BUTTON_1           (1 << BUTTON_1)
 #define KEY_BUTTON_2           (1 << BUTTON_2)
 #define KEY_MOTION             (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)
 
 
 /* values for artwork handling */
+#define LEVELDIR_ARTWORK_SET_PTR(leveldir, type)                       \
+                               ((type) == ARTWORK_TYPE_GRAPHICS ?      \
+                                &(leveldir)->graphics_set :            \
+                                (type) == ARTWORK_TYPE_SOUNDS ?        \
+                                &(leveldir)->sounds_set :              \
+                                &(leveldir)->music_set)
+
 #define LEVELDIR_ARTWORK_SET(leveldir, type)                           \
                                ((type) == ARTWORK_TYPE_GRAPHICS ?      \
                                 (leveldir)->graphics_set :             \
                                 (leveldir)->sounds_set :               \
                                 (leveldir)->music_set)
 
+#define LEVELDIR_ARTWORK_PATH_PTR(leveldir, type)                      \
+                               ((type) == ARTWORK_TYPE_GRAPHICS ?      \
+                                &(leveldir)->graphics_path :           \
+                                (type) == ARTWORK_TYPE_SOUNDS ?        \
+                                &(leveldir)->sounds_path :             \
+                                &(leveldir)->music_path)
+
 #define LEVELDIR_ARTWORK_PATH(leveldir, type)                          \
                                ((type) == ARTWORK_TYPE_GRAPHICS ?      \
                                 (leveldir)->graphics_path :            \
                                 (artwork).snd_first :  \
                                 (artwork).mus_first)
 
+#define ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type)                  \
+                               ((type) == ARTWORK_TYPE_GRAPHICS ?      \
+                                &(artwork).gfx_current_identifier :    \
+                                (type) == ARTWORK_TYPE_SOUNDS ?        \
+                                &(artwork).snd_current_identifier :    \
+                                &(artwork).mus_current_identifier)
+
 #define ARTWORK_CURRENT_IDENTIFIER(artwork, type)                      \
                                ((type) == ARTWORK_TYPE_GRAPHICS ?      \
                                 (artwork).gfx_current_identifier :     \
@@ -406,8 +433,9 @@ typedef int (*EventFilter)(const Event *);
 
 struct ProgramInfo
 {
-  char *command_basename;
-  char *userdata_directory;
+  char *command_basepath;      /* directory that contains the program */
+  char *command_basename;      /* base filename of the program binary */
+  char *userdata_directory;    /* personal user data directory */
 
   char *program_title;
   char *window_title;
@@ -550,6 +578,7 @@ struct SetupEditorInfo
 {
   boolean el_boulderdash;
   boolean el_emerald_mine;
+  boolean el_emerald_mine_club;
   boolean el_more;
   boolean el_sokoban;
   boolean el_supaplex;
@@ -594,6 +623,7 @@ struct SetupInfo
   boolean quick_doors;
   boolean team_mode;
   boolean handicap;
+  boolean skip_levels;
   boolean time_limit;
   boolean fullscreen;
   boolean ask_on_escape;
@@ -634,6 +664,7 @@ struct TreeInfo
   char *name_sorting;  /* optional sorting name for correct name sorting */
   char *author;                /* level or artwork author name */
   char *imported_from; /* optional comment for imported levels or artwork */
+  char *imported_by;   /* optional comment for imported levels or artwork */
 
   char *graphics_set;  /* optional custom graphics set (level tree only) */
   char *sounds_set;    /* optional custom sounds set (level tree only) */
@@ -654,9 +685,11 @@ struct TreeInfo
 
   boolean level_group; /* directory contains more level series directories */
   boolean parent_link; /* entry links back to parent directory */
-  boolean user_defined;        /* user defined levels are stored in home directory */
+  boolean in_user_dir; /* user defined levels are stored in home directory */
+  boolean user_defined;        /* levels in user directory and marked as "private" */
   boolean readonly;    /* readonly levels can not be changed with editor */
   boolean handicap;    /* level set has no handicap when set to "false" */
+  boolean skip_levels; /* levels can be skipped when set to "true" */
 
   int color;           /* color to use on selection screen for this level */
   char *class_desc;    /* description of level series class */
@@ -691,6 +724,12 @@ struct ValueTextInfo
 };
 
 struct ConfigInfo
+{
+  char *token;
+  char *value;
+};
+
+struct ConfigTypeInfo
 {
   char *token;
   char *value;
@@ -714,6 +753,7 @@ struct FileInfo
   char **parameter;                            /* array of file parameters */
 
   boolean redefined;
+  boolean fallback_to_default;
 };
 
 struct SetupFileList
@@ -750,7 +790,7 @@ struct ArtworkListInfo
   struct FileInfo *dynamic_file_list;          /* dynamic artwrk file array */
 
   int num_suffix_list_entries;
-  struct ConfigInfo *suffix_list;              /* parameter suffixes array */
+  struct ConfigTypeInfo *suffix_list;          /* parameter suffixes array */
 
   int num_base_prefixes;
   int num_ext1_suffixes;
@@ -867,7 +907,7 @@ Bitmap *LoadCustomImage(char *);
 void ReloadCustomImage(Bitmap *, char *);
 
 Bitmap *ZoomBitmap(Bitmap *, int, int);
-void CreateBitmapWithSmallBitmaps(Bitmap *);
+void CreateBitmapWithSmallBitmaps(Bitmap *, int);
 
 void SetMouseCursor(int);
 
@@ -878,6 +918,7 @@ inline void SetAudioMode(boolean);
 inline void InitEventFilter(EventFilter);
 inline boolean PendingEvent(void);
 inline void NextEvent(Event *event);
+inline void PeekEvent(Event *event);
 inline Key GetEventKey(KeyEvent *, boolean);
 inline KeyMod HandleKeyModState(Key, int);
 inline KeyMod GetKeyModState();
index 558f180c526865d33504600f409218996c9de100..22790dc84d96cb511599da53ab68829df0ef1d6a 100644 (file)
@@ -44,7 +44,7 @@ typedef unsigned char byte;
 #endif
 
 #ifndef SIGN
-#define SIGN(a)                ((a) < 0 ? -1 : ((a)>0 ? 1 : 0))
+#define SIGN(a)                ((a) < 0 ? -1 : ((a) > 0 ? 1 : 0))
 #endif
 
 #define SIZEOF_ARRAY(array, type)      (sizeof(array) / sizeof(type))
index 6d5cb0a9ffe513e25af43487da2dad744eb53aff..f03e961cd8c461e1d1abf5368ee5139ca24a9909 100644 (file)
@@ -106,8 +106,8 @@ static DrawWindow *X11InitWindow()
 #endif
   int screen_width, screen_height;
   int win_xpos, win_ypos;
-  unsigned long pen_fg = WhitePixel(display,screen);
-  unsigned long pen_bg = BlackPixel(display,screen);
+  unsigned long pen_fg = WhitePixel(display, screen);
+  unsigned long pen_bg = BlackPixel(display, screen);
   const int width = video.width, height = video.height;
   int i;
 
index 81319ed6b8899c868f75dea121e7f51b0d9b6b44..f2db9290d0f05161acc2f816c3ce3f116f79c589 100644 (file)
@@ -56,8 +56,8 @@ short                 StorePlayer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short                  Back[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 boolean                        Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 boolean                        Pushed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-unsigned long          Changed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-unsigned long          ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+boolean                        Changed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+short                  ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short                  WasJustMoving[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short                  WasJustFalling[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 short                  CheckCollision[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
@@ -122,7 +122,10 @@ SetupFileHash          *helptext_info = NULL;
 /* element definitions                                                       */
 /* ------------------------------------------------------------------------- */
 
-struct ElementInfo element_info[MAX_NUM_ELEMENTS + 1] =
+struct ElementInfo element_info[MAX_NUM_ELEMENTS + 1];
+
+/* this contains predefined structure elements to initialize "element_info" */
+struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] =
 {
   /* keyword to start parser: "ELEMENT_INFO_START" <-- do not change! */
 
@@ -747,7 +750,7 @@ struct ElementInfo element_info[MAX_NUM_ELEMENTS + 1] =
     "letter '$'"
   },
   {
-    "char_procent",
+    "char_percent",
     "char",
     "letter '%'"
   },
@@ -1779,7 +1782,7 @@ struct ElementInfo element_info[MAX_NUM_ELEMENTS + 1] =
   {
     "balloon_switch_any",
     "balloon_switch",
-    "send balloon in any direction"
+    "send balloon in pressed direction"
   },
   {
     "emc_steelwall_1",
@@ -3456,6 +3459,196 @@ struct ElementInfo element_info[MAX_NUM_ELEMENTS + 1] =
     "sp_port",
     "gravity off port (leading up)"
   },
+  {
+    "balloon_switch_none",
+    "balloon_switch",
+    "stop moving balloon"
+  },
+  {
+    "emc_gate_5",
+    "gate",
+    "door 5 (EMC style)",
+  },
+  {
+    "emc_gate_6",
+    "gate",
+    "door 6 (EMC style)",
+  },
+  {
+    "emc_gate_7",
+    "gate",
+    "door 7 (EMC style)",
+  },
+  {
+    "emc_gate_8",
+    "gate",
+    "door 8 (EMC style)",
+  },
+  {
+    "emc_gate_5_gray",
+    "gate",
+    "gray door (EMC style, key 5)",
+  },
+  {
+    "emc_gate_6_gray",
+    "gate",
+    "gray door (EMC style, key 6)",
+  },
+  {
+    "emc_gate_7_gray",
+    "gate",
+    "gray door (EMC style, key 7)",
+  },
+  {
+    "emc_gate_8_gray",
+    "gate",
+    "gray door (EMC style, key 8)",
+  },
+  {
+    "emc_key_5",
+    "key",
+    "key 5 (EMC style)",
+  },
+  {
+    "emc_key_6",
+    "key",
+    "key 6 (EMC style)",
+  },
+  {
+    "emc_key_7",
+    "key",
+    "key 7 (EMC style)",
+  },
+  {
+    "emc_key_8",
+    "key",
+    "key 8 (EMC style)",
+  },
+  {
+    "emc_android",
+    "emc_android",
+    "android",
+  },
+  {
+    "emc_grass",
+    "emc_grass",
+    "grass",
+  },
+  {
+    "emc_magic_ball",
+    "emc_magic_ball",
+    "magic ball",
+  },
+  {
+    "emc_magic_ball.active",
+    "emc_magic_ball",
+    "magic ball (activated)",
+  },
+  {
+    "emc_magic_ball_switch",
+    "emc_magic_ball_switch",
+    "magic ball switch (off)",
+  },
+  {
+    "emc_magic_ball_switch.active",
+    "emc_magic_ball_switch",
+    "magic ball switch (on)",
+  },
+  {
+    "emc_spring_bumper",
+    "emc_spring_bumper",
+    "spring bumper",
+  },
+  {
+    "emc_plant",
+    "emc_plant",
+    "plant",
+  },
+  {
+    "emc_lenses",
+    "emc_lenses",
+    "lenses",
+  },
+  {
+    "emc_magnifier",
+    "emc_magnifier",
+    "magnifier",
+  },
+  {
+    "emc_wall_9",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_10",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_11",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_12",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_13",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_14",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_15",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_16",
+    "wall",
+    "normal wall"
+  },
+  {
+    "emc_wall_slippery_1",
+    "wall",
+    "slippery wall"
+  },
+  {
+    "emc_wall_slippery_2",
+    "wall",
+    "slippery wall"
+  },
+  {
+    "emc_wall_slippery_3",
+    "wall",
+    "slippery wall"
+  },
+  {
+    "emc_wall_slippery_4",
+    "wall",
+    "slippery wall"
+  },
+  {
+    "emc_fake_grass",
+    "fake grass",
+    "fake grass"
+  },
+  {
+    "emc_fake_acid",
+    "fake acid",
+    "fake acid"
+  },
+  {
+    "emc_dripper",
+    "dripper",
+    "dripper"
+  },
 
   /* ----------------------------------------------------------------------- */
   /* "real" (and therefore drawable) runtime elements                        */
@@ -3995,6 +4188,11 @@ struct ElementActionInfo element_action_info[NUM_ACTIONS + 1 + 1] =
   { ".turning_from_right",     ACTION_TURNING_FROM_RIGHT,      FALSE   },
   { ".turning_from_up",                ACTION_TURNING_FROM_UP,         FALSE   },
   { ".turning_from_down",      ACTION_TURNING_FROM_DOWN,       FALSE   },
+  { ".smashed_by_rock",                ACTION_SMASHED_BY_ROCK,         FALSE   },
+  { ".smashed_by_spring",      ACTION_SMASHED_BY_SPRING,       FALSE   },
+  { ".slurped_by_spring",      ACTION_SLURPED_BY_SPRING,       FALSE   },
+  { ".twinkling",              ACTION_TWINKLING,               FALSE   },
+  { ".splashing",              ACTION_SPLASHING,               FALSE   },
   { ".other",                  ACTION_OTHER,                   FALSE   },
 
   /* empty suffix always matches -- check as last entry in InitSoundInfo() */
@@ -4037,8 +4235,8 @@ struct TokenIntPtrInfo image_config_vars[] =
 {
   { "global.num_toons",                &global.num_toons                          },
 
-  { "menu.draw_xoffset",       &menu.draw_xoffset_default                 },
-  { "menu.draw_yoffset",       &menu.draw_yoffset_default                 },
+  { "menu.draw_xoffset",       &menu.draw_xoffset[GFX_SPECIAL_ARG_DEFAULT]},
+  { "menu.draw_yoffset",       &menu.draw_yoffset[GFX_SPECIAL_ARG_DEFAULT]},
   { "menu.draw_xoffset.MAIN",  &menu.draw_xoffset[GFX_SPECIAL_ARG_MAIN]   },
   { "menu.draw_yoffset.MAIN",  &menu.draw_yoffset[GFX_SPECIAL_ARG_MAIN]   },
   { "menu.draw_xoffset.LEVELS",        &menu.draw_xoffset[GFX_SPECIAL_ARG_LEVELS] },
@@ -4054,7 +4252,7 @@ struct TokenIntPtrInfo image_config_vars[] =
 
   { "menu.scrollbar_xoffset",  &menu.scrollbar_xoffset                    },
 
-  { "menu.list_size",          &menu.list_size_default                    },
+  { "menu.list_size",          &menu.list_size[GFX_SPECIAL_ARG_DEFAULT]   },
   { "menu.list_size.LEVELS",   &menu.list_size[GFX_SPECIAL_ARG_LEVELS]    },
   { "menu.list_size.SCORES",   &menu.list_size[GFX_SPECIAL_ARG_SCORES]    },
   { "menu.list_size.INFO",     &menu.list_size[GFX_SPECIAL_ARG_INFO]      },
@@ -4162,7 +4360,7 @@ static void print_usage()
         "  \"print helptext.conf\"            print default helptext config\n"
         "  \"dump level FILE\"                dump level data from FILE\n"
         "  \"dump tape FILE\"                 dump tape data from FILE\n"
-        "  \"autoplay LEVELDIR [NR]\"         play level tapes for LEVELDIR\n"
+        "  \"autoplay LEVELDIR [NR ...]\"     play level tapes for LEVELDIR\n"
         "  \"convert LEVELDIR [NR]\"          convert levels in LEVELDIR\n"
         "\n",
         program.command_basename);
index 0bf9a3656e22650716758a556dfda283bb39f93b..2a2714a830ab47b1ec5b2f1ddd289e024e0e14a2 100644 (file)
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 
 #include "libgame/libgame.h"
+#include "game_em/game_em.h"
 
 #include "conf_gfx.h"  /* include auto-generated data structure definitions */
 #include "conf_snd.h"  /* include auto-generated data structure definitions */
 #define CE_HITTING_SOMETHING   5
 #define CE_IMPACT              6
 #define CE_SMASHED             7
-#define CE_OTHER_IS_TOUCHING   8
-#define CE_OTHER_IS_CHANGING   9
-#define CE_OTHER_IS_EXPLODING  10
-#define CE_OTHER_GETS_TOUCHED  11
-#define CE_OTHER_GETS_PRESSED  12
-#define CE_OTHER_GETS_PUSHED   13
-#define CE_OTHER_GETS_COLLECTED        14
-#define CE_OTHER_GETS_DROPPED  15
+#define CE_TOUCHING_X          8
+#define CE_CHANGE_OF_X         9
+#define CE_EXPLOSION_OF_X      10
+#define CE_PLAYER_TOUCHES_X    11
+#define CE_PLAYER_PRESSES_X    12
+#define CE_PLAYER_PUSHES_X     13
+#define CE_PLAYER_COLLECTS_X   14
+#define CE_PLAYER_DROPS_X      15
 #define CE_BY_PLAYER_OBSOLETE  16      /* obsolete; now CE_BY_DIRECT_ACTION */
 #define CE_BY_COLLISION_OBSOLETE 17    /* obsolete; now CE_BY_DIRECT_ACTION */
 #define CE_BY_OTHER_ACTION     18      /* activates other element events */
 #define CE_BY_DIRECT_ACTION    19      /* activates direct element events */
-#define CE_OTHER_GETS_DIGGED   20
+#define CE_PLAYER_DIGS_X       20
 #define CE_ENTERED_BY_PLAYER   21
 #define CE_LEFT_BY_PLAYER      22
-#define CE_OTHER_GETS_ENTERED  23
-#define CE_OTHER_GETS_LEFT     24
+#define CE_PLAYER_ENTERS_X     23
+#define CE_PLAYER_LEAVES_X     24
 #define CE_SWITCHED            25
-#define CE_OTHER_IS_SWITCHING  26
+#define CE_SWITCH_OF_X         26
 #define CE_HIT_BY_SOMETHING    27
-#define CE_OTHER_IS_HITTING    28
-#define CE_OTHER_GETS_HIT      29
+#define CE_HITTING_X           28
+#define CE_HIT_BY_X            29
 #define CE_BLOCKED             30
 
 #define NUM_CHANGE_EVENTS      31
 
 #define CE_BITMASK_DEFAULT     0
 
+#if 1
+
+#define CH_EVENT_VAR(e,c)      (element_info[e].change->has_event[c])
+#define CH_ANY_EVENT_VAR(e,c)  (element_info[e].has_change_event[c])
+
+#define PAGE_HAS_CHANGE_EVENT(p,c)  ((p)->has_event[c])
+#define HAS_CHANGE_EVENT(e,c)      (IS_CUSTOM_ELEMENT(e) &&            \
+                                    CH_EVENT_VAR(e,c))
+#define HAS_ANY_CHANGE_EVENT(e,c)   (IS_CUSTOM_ELEMENT(e) &&           \
+                                    CH_ANY_EVENT_VAR(e,c))
+
+#define SET_CHANGE_EVENT(e,c,v)     (IS_CUSTOM_ELEMENT(e) ?            \
+                                    CH_EVENT_VAR(e,c) = (v) : 0)
+#define SET_ANY_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ?            \
+                                    CH_ANY_EVENT_VAR(e,c) = (v) : 0)
+
+#else
+
 #define CH_EVENT_BIT(c)                (1 << (c))
 #define CH_EVENT_VAR(e)                (element_info[e].change->events)
 #define CH_ANY_EVENT_VAR(e)    (element_info[e].change_events)
                                 ((v) ?                                   \
                                  (CH_EVENT_VAR(e) |=  CH_EVENT_BIT(c)) : \
                                  (CH_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
+#define SET_ANY_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ?              \
+                              ((v) ?                                     \
+                               (CH_ANY_EVENT_VAR(e) |=  CH_EVENT_BIT(c)) : \
+                               (CH_ANY_EVENT_VAR(e) &= ~CH_EVENT_BIT(c))) : 0)
+#endif
 
 /* values for change side for custom elements */
 #define CH_SIDE_NONE           MV_NO_MOVING
 #define MV_BIT_TURNING_RANDOM  16
 
 /* values for custom move patterns */
-#define MV_HORIZONTAL          (MV_LEFT | MV_RIGHT)
-#define MV_VERTICAL            (MV_UP   | MV_DOWN)
-#define MV_ALL_DIRECTIONS      (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)
-#define MV_ANY_DIRECTION       (MV_ALL_DIRECTIONS)
 #define MV_TOWARDS_PLAYER      (1 << MV_BIT_TOWARDS_PLAYER)
 #define MV_AWAY_FROM_PLAYER    (1 << MV_BIT_AWAY_FROM_PLAYER)
 #define MV_ALONG_LEFT_SIDE     (1 << MV_BIT_ALONG_LEFT_SIDE)
 #define IS_ENVELOPE(e)         ((e) >= EL_ENVELOPE_1 &&                \
                                 (e) <= EL_ENVELOPE_4)
 
-#define IS_GATE(e)             ((e) >= EL_GATE_1 &&                    \
+#define IS_RND_KEY(e)          ((e) >= EL_KEY_1 &&                     \
+                                (e) <= EL_KEY_4)
+#define IS_EM_KEY(e)           ((e) >= EL_EM_KEY_1 &&                  \
+                                (e) <= EL_EM_KEY_4)
+#define IS_EMC_KEY(e)          ((e) >= EL_EMC_KEY_5 &&                 \
+                                (e) <= EL_EMC_KEY_8)
+#define IS_KEY(e)              (IS_RND_KEY(e) ||                       \
+                                IS_EM_KEY(e) ||                        \
+                                IS_EMC_KEY(e))
+#define RND_KEY_NR(e)          ((e) - EL_KEY_1)
+#define EM_KEY_NR(e)           ((e) - EL_EM_KEY_1)
+#define EMC_KEY_NR(e)          ((e) - EL_EMC_KEY_5 + 4)
+#define KEY_NR(e)              (IS_RND_KEY(e) ? RND_KEY_NR(e) :        \
+                                IS_EM_KEY(e) ?  EM_KEY_NR(e) :         \
+                                IS_EMC_KEY(e) ? EMC_KEY_NR(e) : 0)
+
+#define IS_RND_GATE(e)         ((e) >= EL_GATE_1 &&                    \
                                 (e) <= EL_GATE_4)
-
-#define IS_GATE_GRAY(e)                ((e) >= EL_GATE_1_GRAY &&               \
-                                (e) <= EL_GATE_4_GRAY)
-
 #define IS_EM_GATE(e)          ((e) >= EL_EM_GATE_1 &&                 \
                                 (e) <= EL_EM_GATE_4)
-
+#define IS_EMC_GATE(e)         ((e) >= EL_EMC_GATE_5 &&                \
+                                (e) <= EL_EMC_GATE_8)
+#define IS_GATE(e)             (IS_RND_GATE(e) ||                      \
+                                IS_EM_GATE(e) ||                       \
+                                IS_EMC_GATE(e))
+#define RND_GATE_NR(e)         ((e) - EL_GATE_1)
+#define EM_GATE_NR(e)          ((e) - EL_EM_GATE_1)
+#define EMC_GATE_NR(e)         ((e) - EL_EMC_GATE_5 + 4)
+#define GATE_NR(e)             (IS_RND_GATE(e) ? RND_GATE_NR(e) :      \
+                                IS_EM_GATE(e) ?  EM_GATE_NR(e) :       \
+                                IS_EMC_GATE(e) ? EMC_GATE_NR(e) : 0)
+
+#define IS_RND_GATE_GRAY(e)    ((e) >= EL_GATE_1_GRAY &&               \
+                                (e) <= EL_GATE_4_GRAY)
 #define IS_EM_GATE_GRAY(e)     ((e) >= EL_EM_GATE_1_GRAY &&            \
                                 (e) <= EL_EM_GATE_4_GRAY)
+#define IS_EMC_GATE_GRAY(e)    ((e) >= EL_EMC_GATE_5_GRAY &&           \
+                                (e) <= EL_EMC_GATE_8_GRAY)
+#define IS_GATE_GRAY(e)                (IS_RND_GATE_GRAY(e) ||                 \
+                                IS_EM_GATE_GRAY(e) ||                  \
+                                IS_EMC_GATE_GRAY(e))
+#define RND_GATE_GRAY_NR(e)    ((e) - EL_GATE_1_GRAY)
+#define EM_GATE_GRAY_NR(e)     ((e) - EL_EM_GATE_1_GRAY)
+#define EMC_GATE_GRAY_NR(e)    ((e) - EL_EMC_GATE_5_GRAY + 4)
+#define GATE_GRAY_NR(e)                (IS_RND_GATE_GRAY(e) ? RND_GATE_GRAY_NR(e) :  \
+                                IS_EM_GATE_GRAY(e) ?  EM_GATE_GRAY_NR(e) :   \
+                                IS_EMC_GATE_GRAY(e) ? EMC_GATE_GRAY_NR(e) : 0)
 
 #define GFX_ELEMENT(e)         (element_info[e].use_gfx_element ?      \
                                 element_info[e].gfx_element : e)
 #define PLAYER_SWITCHING(p,x,y)        ((p)->is_switching &&                   \
                                 (p)->switch_x == (x) && (p)->switch_y == (y))
 
+#define PLAYER_DROPPING(p,x,y) ((p)->is_dropping &&                    \
+                                (p)->drop_x == (x) && (p)->drop_y == (y))
+
 #define PLAYER_NR_GFX(g,i)     ((g) + i * (IMG_PLAYER_2 - IMG_PLAYER_1))
 
 #define ANIM_FRAMES(g)         (graphic_info[g].anim_frames)
 #define MAX_LEVEL_NAME_LEN     32
 #define MAX_LEVEL_AUTHOR_LEN   32
 #define MAX_ELEMENT_NAME_LEN   32
-#define MAX_TAPELEN            (1000 * FRAMES_PER_SECOND) /* max.time x fps */
+#define MAX_TAPE_LEN           (1000 * FRAMES_PER_SECOND) /* max.time x fps */
+#define MAX_TAPES_PER_SET      1024
 #define MAX_SCORE_ENTRIES      100
 #define MAX_NUM_AMOEBA         100
 #define MAX_INVENTORY_SIZE     1000
-#define MAX_KEYS               4
+#define STD_NUM_KEYS           4
+#define MAX_NUM_KEYS           8
 #define NUM_BELTS              4
 #define NUM_BELT_PARTS         3
 #define MIN_ENVELOPE_XSIZE     1
 #define MIN_ELEMENT_CONTENTS   1
 #define STD_ELEMENT_CONTENTS   4
 #define MAX_ELEMENT_CONTENTS   8
+#define NUM_MAGIC_BALL_CONTENTS        8
 
 #define LEVEL_SCORE_ELEMENTS   16      /* level elements with score */
 
 #define VY                     400
 #define EX                     DX
 #define EY                     (VY - 44)
-#define TILEX                  32
-#define TILEY                  32
-#define MINI_TILEX             (TILEX / 2)
-#define MINI_TILEY             (TILEY / 2)
-#define MICRO_TILEX            (TILEX / 8)
-#define MICRO_TILEY            (TILEY / 8)
+#define TILESIZE               32
+#define TILEX                  TILESIZE
+#define TILEY                  TILESIZE
+#define MINI_TILESIZE          (TILESIZE / 2)
+#define MINI_TILEX             MINI_TILESIZE
+#define MINI_TILEY             MINI_TILESIZE
+#define MICRO_TILESIZE         (TILESIZE / 8)
+#define MICRO_TILEX            MICRO_TILESIZE
+#define MICRO_TILEY            MICRO_TILESIZE
 #define MIDPOSX                        (SCR_FIELDX / 2)
 #define MIDPOSY                        (SCR_FIELDY / 2)
 #define SXSIZE                 (SCR_FIELDX * TILEX)
 #define EYSIZE                 (VYSIZE + 44)
 #define FULL_SXSIZE            (2 + SXSIZE + 2)
 #define FULL_SYSIZE            (2 + SYSIZE + 2)
-#define MICROLEV_XSIZE         ((STD_LEV_FIELDX + 2) * MICRO_TILEX)
-#define MICROLEV_YSIZE         ((STD_LEV_FIELDY + 2) * MICRO_TILEY)
-#define MICROLEV_XPOS          (SX + (SXSIZE - MICROLEV_XSIZE) / 2)
-#define MICROLEV_YPOS          (SX + 12 * TILEY - MICRO_TILEY)
-#define MICROLABEL_YPOS                (MICROLEV_YPOS + MICROLEV_YSIZE + 7)
+#define MICROLEVEL_XSIZE       ((STD_LEV_FIELDX + 2) * MICRO_TILEX)
+#define MICROLEVEL_YSIZE       ((STD_LEV_FIELDY + 2) * MICRO_TILEY)
+#define MICROLEVEL_XPOS                (SX + (SXSIZE - MICROLEVEL_XSIZE) / 2)
+#define MICROLEVEL_YPOS                (SX + 12 * TILEY - MICRO_TILEY)
+#define MICROLABEL1_YPOS       (MICROLEVEL_YPOS - 36)
+#define MICROLABEL2_YPOS       (MICROLEVEL_YPOS + MICROLEVEL_YSIZE + 7)
 
 
 /* score for elements */
 #define EL_SP_GRAVITY_OFF_PORT_LEFT    665
 #define EL_SP_GRAVITY_OFF_PORT_UP      666
 
-#define NUM_FILE_ELEMENTS              667
+
+/* the following EMC style elements are currently not implemented in R'n'D */
+#define EL_BALLOON_SWITCH_NONE         667
+#define EL_EMC_GATE_5                  668
+#define EL_EMC_GATE_6                  669
+#define EL_EMC_GATE_7                  670
+#define EL_EMC_GATE_8                  671
+#define EL_EMC_GATE_5_GRAY             672
+#define EL_EMC_GATE_6_GRAY             673
+#define EL_EMC_GATE_7_GRAY             674
+#define EL_EMC_GATE_8_GRAY             675
+#define EL_EMC_KEY_5                   676
+#define EL_EMC_KEY_6                   677
+#define EL_EMC_KEY_7                   678
+#define EL_EMC_KEY_8                   679
+#define EL_EMC_ANDROID                 680
+#define EL_EMC_GRASS                   681
+#define EL_EMC_MAGIC_BALL              682
+#define EL_EMC_MAGIC_BALL_ACTIVE       683
+#define EL_EMC_MAGIC_BALL_SWITCH       684
+#define EL_EMC_MAGIC_BALL_SWITCH_ACTIVE        685
+#define EL_EMC_SPRING_BUMPER           686
+#define EL_EMC_PLANT                   687
+#define EL_EMC_LENSES                  688
+#define EL_EMC_MAGNIFIER               689
+#define EL_EMC_WALL_9                  690
+#define EL_EMC_WALL_10                 691
+#define EL_EMC_WALL_11                 692
+#define EL_EMC_WALL_12                 693
+#define EL_EMC_WALL_13                 694
+#define EL_EMC_WALL_14                 695
+#define EL_EMC_WALL_15                 696
+#define EL_EMC_WALL_16                 697
+#define EL_EMC_WALL_SLIPPERY_1         698
+#define EL_EMC_WALL_SLIPPERY_2         699
+#define EL_EMC_WALL_SLIPPERY_3         700
+#define EL_EMC_WALL_SLIPPERY_4         701
+#define EL_EMC_FAKE_GRASS              702
+#define EL_EMC_FAKE_ACID               703
+#define EL_EMC_DRIPPER                 704
+
+#define NUM_FILE_ELEMENTS              705
 
 
 /* "real" (and therefore drawable) runtime elements */
 /* dummy elements (never used as game elements, only used as graphics) */
 #define EL_FIRST_DUMMY                 (EL_FIRST_RUNTIME_UNREAL + 18)
 
-#define EL_STEELWALL_TOPLEFT                   (EL_FIRST_DUMMY + 0)
-#define EL_STEELWALL_TOPRIGHT                  (EL_FIRST_DUMMY + 1)
-#define EL_STEELWALL_BOTTOMLEFT                        (EL_FIRST_DUMMY + 2)
-#define EL_STEELWALL_BOTTOMRIGHT               (EL_FIRST_DUMMY + 3)
-#define EL_STEELWALL_HORIZONTAL                        (EL_FIRST_DUMMY + 4)
-#define EL_STEELWALL_VERTICAL                  (EL_FIRST_DUMMY + 5)
-#define EL_INVISIBLE_STEELWALL_TOPLEFT         (EL_FIRST_DUMMY + 6)
-#define EL_INVISIBLE_STEELWALL_TOPRIGHT                (EL_FIRST_DUMMY + 7)
-#define EL_INVISIBLE_STEELWALL_BOTTOMLEFT      (EL_FIRST_DUMMY + 8)
-#define EL_INVISIBLE_STEELWALL_BOTTOMRIGHT     (EL_FIRST_DUMMY + 9)
-#define EL_INVISIBLE_STEELWALL_HORIZONTAL      (EL_FIRST_DUMMY + 10)
-#define EL_INVISIBLE_STEELWALL_VERTICAL                (EL_FIRST_DUMMY + 11)
-#define EL_DYNABOMB                            (EL_FIRST_DUMMY + 12)
-#define EL_DYNABOMB_ACTIVE                     (EL_FIRST_DUMMY + 13)
-#define EL_DYNABOMB_PLAYER_1                   (EL_FIRST_DUMMY + 14)
-#define EL_DYNABOMB_PLAYER_2                   (EL_FIRST_DUMMY + 15)
-#define EL_DYNABOMB_PLAYER_3                   (EL_FIRST_DUMMY + 16)
-#define EL_DYNABOMB_PLAYER_4                   (EL_FIRST_DUMMY + 17)
-#define EL_SHIELD_NORMAL_ACTIVE                        (EL_FIRST_DUMMY + 18)
-#define EL_SHIELD_DEADLY_ACTIVE                        (EL_FIRST_DUMMY + 19)
-#define EL_AMOEBA                              (EL_FIRST_DUMMY + 20)
-#define EL_DEFAULT                             (EL_FIRST_DUMMY + 21)
-#define EL_BD_DEFAULT                          (EL_FIRST_DUMMY + 22)
-#define EL_SP_DEFAULT                          (EL_FIRST_DUMMY + 23)
-#define EL_SB_DEFAULT                          (EL_FIRST_DUMMY + 24)
+#define EL_STEELWALL_TOPLEFT           (EL_FIRST_DUMMY + 0)
+#define EL_STEELWALL_TOPRIGHT          (EL_FIRST_DUMMY + 1)
+#define EL_STEELWALL_BOTTOMLEFT                (EL_FIRST_DUMMY + 2)
+#define EL_STEELWALL_BOTTOMRIGHT       (EL_FIRST_DUMMY + 3)
+#define EL_STEELWALL_HORIZONTAL                (EL_FIRST_DUMMY + 4)
+#define EL_STEELWALL_VERTICAL          (EL_FIRST_DUMMY + 5)
+#define EL_INVISIBLE_STEELWALL_TOPLEFT    (EL_FIRST_DUMMY + 6)
+#define EL_INVISIBLE_STEELWALL_TOPRIGHT           (EL_FIRST_DUMMY + 7)
+#define EL_INVISIBLE_STEELWALL_BOTTOMLEFT  (EL_FIRST_DUMMY + 8)
+#define EL_INVISIBLE_STEELWALL_BOTTOMRIGHT (EL_FIRST_DUMMY + 9)
+#define EL_INVISIBLE_STEELWALL_HORIZONTAL  (EL_FIRST_DUMMY + 10)
+#define EL_INVISIBLE_STEELWALL_VERTICAL           (EL_FIRST_DUMMY + 11)
+#define EL_DYNABOMB                    (EL_FIRST_DUMMY + 12)
+#define EL_DYNABOMB_ACTIVE             (EL_FIRST_DUMMY + 13)
+#define EL_DYNABOMB_PLAYER_1           (EL_FIRST_DUMMY + 14)
+#define EL_DYNABOMB_PLAYER_2           (EL_FIRST_DUMMY + 15)
+#define EL_DYNABOMB_PLAYER_3           (EL_FIRST_DUMMY + 16)
+#define EL_DYNABOMB_PLAYER_4           (EL_FIRST_DUMMY + 17)
+#define EL_SHIELD_NORMAL_ACTIVE                (EL_FIRST_DUMMY + 18)
+#define EL_SHIELD_DEADLY_ACTIVE                (EL_FIRST_DUMMY + 19)
+#define EL_AMOEBA                      (EL_FIRST_DUMMY + 20)
+#define EL_DEFAULT                     (EL_FIRST_DUMMY + 21)
+#define EL_BD_DEFAULT                  (EL_FIRST_DUMMY + 22)
+#define EL_SP_DEFAULT                  (EL_FIRST_DUMMY + 23)
+#define EL_SB_DEFAULT                  (EL_FIRST_DUMMY + 24)
 
 /* internal elements (only used for internal purposes like copying) */
-#define EL_FIRST_INTERNAL                      (EL_FIRST_DUMMY + 25)
+#define EL_FIRST_INTERNAL              (EL_FIRST_DUMMY + 25)
 
-#define EL_INTERNAL_CLIPBOARD_CUSTOM           (EL_FIRST_INTERNAL + 0)
-#define EL_INTERNAL_CLIPBOARD_CHANGE           (EL_FIRST_INTERNAL + 1)
-#define EL_INTERNAL_CLIPBOARD_GROUP            (EL_FIRST_INTERNAL + 2)
-#define EL_INTERNAL_DUMMY                      (EL_FIRST_INTERNAL + 3)
+#define EL_INTERNAL_CLIPBOARD_CUSTOM   (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_CLIPBOARD_CHANGE   (EL_FIRST_INTERNAL + 1)
+#define EL_INTERNAL_CLIPBOARD_GROUP    (EL_FIRST_INTERNAL + 2)
+#define EL_INTERNAL_DUMMY              (EL_FIRST_INTERNAL + 3)
 
-#define EL_INTERNAL_CLIPBOARD_START            (EL_FIRST_INTERNAL + 0)
-#define EL_INTERNAL_CLIPBOARD_END              (EL_FIRST_INTERNAL + 2)
-#define EL_INTERNAL_START                      (EL_FIRST_INTERNAL + 0)
-#define EL_INTERNAL_END                                (EL_FIRST_INTERNAL + 3)
+#define EL_INTERNAL_CLIPBOARD_START    (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_CLIPBOARD_END      (EL_FIRST_INTERNAL + 2)
+#define EL_INTERNAL_START              (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_END                        (EL_FIRST_INTERNAL + 3)
 
-#define MAX_NUM_ELEMENTS                       (EL_FIRST_INTERNAL + 4)
+#define MAX_NUM_ELEMENTS               (EL_FIRST_INTERNAL + 4)
 
 
 /* values for graphics/sounds action types */
-#define ACTION_DEFAULT                         0
-#define ACTION_WAITING                         1
-#define ACTION_FALLING                         2
-#define ACTION_MOVING                          3
-#define ACTION_DIGGING                         4
-#define ACTION_SNAPPING                                5
-#define ACTION_COLLECTING                      6
-#define ACTION_DROPPING                                7
-#define ACTION_PUSHING                         8
-#define ACTION_WALKING                         9
-#define ACTION_PASSING                         10
-#define ACTION_IMPACT                          11
-#define ACTION_BREAKING                                12
-#define ACTION_ACTIVATING                      13
-#define ACTION_DEACTIVATING                    14
-#define ACTION_OPENING                         15
-#define ACTION_CLOSING                         16
-#define ACTION_ATTACKING                       17
-#define ACTION_GROWING                         18
-#define ACTION_SHRINKING                       19
-#define ACTION_ACTIVE                          20
-#define ACTION_FILLING                         21
-#define ACTION_EMPTYING                                22
-#define ACTION_CHANGING                                23
-#define ACTION_EXPLODING                       24
-#define ACTION_BORING                          25
-#define ACTION_BORING_1                                26
-#define ACTION_BORING_2                                27
-#define ACTION_BORING_3                                28
-#define ACTION_BORING_4                                29
-#define ACTION_BORING_5                                30
-#define ACTION_BORING_6                                31
-#define ACTION_BORING_7                                32
-#define ACTION_BORING_8                                33
-#define ACTION_BORING_9                                34
-#define ACTION_BORING_10                       35
-#define ACTION_SLEEPING                                36
-#define ACTION_SLEEPING_1                      37
-#define ACTION_SLEEPING_2                      38
-#define ACTION_SLEEPING_3                      39
-#define ACTION_AWAKENING                       40
-#define ACTION_DYING                           41
-#define ACTION_TURNING                         42
-#define ACTION_TURNING_FROM_LEFT               43
-#define ACTION_TURNING_FROM_RIGHT              44
-#define ACTION_TURNING_FROM_UP                 45
-#define ACTION_TURNING_FROM_DOWN               46
-#define ACTION_OTHER                           47
-
-#define NUM_ACTIONS                            48
-
-#define ACTION_BORING_LAST                     ACTION_BORING_10
-#define ACTION_SLEEPING_LAST                   ACTION_SLEEPING_3
+#define ACTION_DEFAULT                 0
+#define ACTION_WAITING                 1
+#define ACTION_FALLING                 2
+#define ACTION_MOVING                  3
+#define ACTION_DIGGING                 4
+#define ACTION_SNAPPING                        5
+#define ACTION_COLLECTING              6
+#define ACTION_DROPPING                        7
+#define ACTION_PUSHING                 8
+#define ACTION_WALKING                 9
+#define ACTION_PASSING                 10
+#define ACTION_IMPACT                  11
+#define ACTION_BREAKING                        12
+#define ACTION_ACTIVATING              13
+#define ACTION_DEACTIVATING            14
+#define ACTION_OPENING                 15
+#define ACTION_CLOSING                 16
+#define ACTION_ATTACKING               17
+#define ACTION_GROWING                 18
+#define ACTION_SHRINKING               19
+#define ACTION_ACTIVE                  20
+#define ACTION_FILLING                 21
+#define ACTION_EMPTYING                        22
+#define ACTION_CHANGING                        23
+#define ACTION_EXPLODING               24
+#define ACTION_BORING                  25
+#define ACTION_BORING_1                        26
+#define ACTION_BORING_2                        27
+#define ACTION_BORING_3                        28
+#define ACTION_BORING_4                        29
+#define ACTION_BORING_5                        30
+#define ACTION_BORING_6                        31
+#define ACTION_BORING_7                        32
+#define ACTION_BORING_8                        33
+#define ACTION_BORING_9                        34
+#define ACTION_BORING_10               35
+#define ACTION_SLEEPING                        36
+#define ACTION_SLEEPING_1              37
+#define ACTION_SLEEPING_2              38
+#define ACTION_SLEEPING_3              39
+#define ACTION_AWAKENING               40
+#define ACTION_DYING                   41
+#define ACTION_TURNING                 42
+#define ACTION_TURNING_FROM_LEFT       43
+#define ACTION_TURNING_FROM_RIGHT      44
+#define ACTION_TURNING_FROM_UP         45
+#define ACTION_TURNING_FROM_DOWN       46
+#define ACTION_SMASHED_BY_ROCK         47
+#define ACTION_SMASHED_BY_SPRING       48
+#define ACTION_SLURPED_BY_SPRING       49
+#define ACTION_TWINKLING               50
+#define ACTION_SPLASHING               51
+#define ACTION_OTHER                   52
+
+#define NUM_ACTIONS                    53
+
+#define ACTION_BORING_LAST             ACTION_BORING_10
+#define ACTION_SLEEPING_LAST           ACTION_SLEEPING_3
 
 
 /* values for special image configuration suffixes (must match game mode) */
-#define GFX_SPECIAL_ARG_DEFAULT                        0
-#define GFX_SPECIAL_ARG_MAIN                   1
-#define GFX_SPECIAL_ARG_LEVELS                 2
-#define GFX_SPECIAL_ARG_SCORES                 3
-#define GFX_SPECIAL_ARG_EDITOR                 4
-#define GFX_SPECIAL_ARG_INFO                   5
-#define GFX_SPECIAL_ARG_SETUP                  6
-#define GFX_SPECIAL_ARG_PLAYING                        7
-#define GFX_SPECIAL_ARG_DOOR                   8
-#define GFX_SPECIAL_ARG_PREVIEW                        9
-#define GFX_SPECIAL_ARG_CRUMBLED               10
+#define GFX_SPECIAL_ARG_DEFAULT                0
+#define GFX_SPECIAL_ARG_MAIN           1
+#define GFX_SPECIAL_ARG_LEVELS         2
+#define GFX_SPECIAL_ARG_SCORES         3
+#define GFX_SPECIAL_ARG_EDITOR         4
+#define GFX_SPECIAL_ARG_INFO           5
+#define GFX_SPECIAL_ARG_SETUP          6
+#define GFX_SPECIAL_ARG_PLAYING                7
+#define GFX_SPECIAL_ARG_DOOR           8
+#define GFX_SPECIAL_ARG_PREVIEW                9
+#define GFX_SPECIAL_ARG_CRUMBLED       10
 
-#define NUM_SPECIAL_GFX_ARGS                   11
+#define NUM_SPECIAL_GFX_ARGS           11
 
 
 /* values for image configuration suffixes */
-#define GFX_ARG_X                              0
-#define GFX_ARG_Y                              1
-#define GFX_ARG_XPOS                           2
-#define GFX_ARG_YPOS                           3
-#define GFX_ARG_WIDTH                          4
-#define GFX_ARG_HEIGHT                         5
-#define GFX_ARG_OFFSET                         6
-#define GFX_ARG_VERTICAL                       7
-#define GFX_ARG_XOFFSET                                8
-#define GFX_ARG_YOFFSET                                9
-#define GFX_ARG_FRAMES                         10
-#define GFX_ARG_FRAMES_PER_LINE                        11
-#define GFX_ARG_START_FRAME                    12
-#define GFX_ARG_DELAY                          13
-#define GFX_ARG_ANIM_MODE                      14
-#define GFX_ARG_GLOBAL_SYNC                    15
-#define GFX_ARG_CRUMBLED_LIKE                  16
-#define GFX_ARG_DIGGABLE_LIKE                  17
-#define GFX_ARG_BORDER_SIZE                    18
-#define GFX_ARG_STEP_OFFSET                    19
-#define GFX_ARG_STEP_DELAY                     20
-#define GFX_ARG_DIRECTION                      21
-#define GFX_ARG_POSITION                       22
-#define GFX_ARG_DRAW_XOFFSET                   23
-#define GFX_ARG_DRAW_YOFFSET                   24
-#define GFX_ARG_DRAW_MASKED                    25
-#define GFX_ARG_ANIM_DELAY_FIXED               26
-#define GFX_ARG_ANIM_DELAY_RANDOM              27
-#define GFX_ARG_POST_DELAY_FIXED               28
-#define GFX_ARG_POST_DELAY_RANDOM              29
-#define GFX_ARG_NAME                           30
-
-#define NUM_GFX_ARGS                           31
+#define GFX_ARG_X                      0
+#define GFX_ARG_Y                      1
+#define GFX_ARG_XPOS                   2
+#define GFX_ARG_YPOS                   3
+#define GFX_ARG_WIDTH                  4
+#define GFX_ARG_HEIGHT                 5
+#define GFX_ARG_VERTICAL               6
+#define GFX_ARG_OFFSET                 7
+#define GFX_ARG_XOFFSET                        8
+#define GFX_ARG_YOFFSET                        9
+#define GFX_ARG_2ND_MOVEMENT_TILE      10
+#define GFX_ARG_2ND_VERTICAL           11
+#define GFX_ARG_2ND_OFFSET             12
+#define GFX_ARG_2ND_XOFFSET            13
+#define GFX_ARG_2ND_YOFFSET            14
+#define GFX_ARG_2ND_SWAP_TILES         15      
+#define GFX_ARG_FRAMES                 16
+#define GFX_ARG_FRAMES_PER_LINE                17
+#define GFX_ARG_START_FRAME            18
+#define GFX_ARG_DELAY                  19
+#define GFX_ARG_ANIM_MODE              20
+#define GFX_ARG_GLOBAL_SYNC            21
+#define GFX_ARG_CRUMBLED_LIKE          22
+#define GFX_ARG_DIGGABLE_LIKE          23
+#define GFX_ARG_BORDER_SIZE            24
+#define GFX_ARG_STEP_OFFSET            25
+#define GFX_ARG_STEP_DELAY             26
+#define GFX_ARG_DIRECTION              27
+#define GFX_ARG_POSITION               28
+#define GFX_ARG_DRAW_XOFFSET           29
+#define GFX_ARG_DRAW_YOFFSET           30
+#define GFX_ARG_DRAW_MASKED            31
+#define GFX_ARG_ANIM_DELAY_FIXED       32
+#define GFX_ARG_ANIM_DELAY_RANDOM      33
+#define GFX_ARG_POST_DELAY_FIXED       34
+#define GFX_ARG_POST_DELAY_RANDOM      35
+#define GFX_ARG_NAME                   36
+#define GFX_ARG_SCALE_UP_FACTOR                37
+
+#define NUM_GFX_ARGS                   38
 
 
 /* values for sound configuration suffixes */
-#define SND_ARG_MODE_LOOP                      0
+#define SND_ARG_MODE_LOOP              0
+#define SND_ARG_VOLUME                 1
+#define SND_ARG_PRIORITY               2
 
-#define NUM_SND_ARGS                           1
+#define NUM_SND_ARGS                   3
 
 
 /* values for music configuration suffixes */
-#define MUS_ARG_MODE_LOOP                      0
+#define MUS_ARG_MODE_LOOP              0
 
-#define NUM_MUS_ARGS                           1
+#define NUM_MUS_ARGS                   1
 
 
 /* values for font configuration */
-#define FONT_INITIAL_1                         0
-#define FONT_INITIAL_2                         1
-#define FONT_INITIAL_3                         2
-#define FONT_INITIAL_4                         3
-#define FONT_TITLE_1                           4
-#define FONT_TITLE_2                           5
-#define FONT_MENU_1                            6
-#define FONT_MENU_2                            7
-#define FONT_TEXT_1_ACTIVE                     8
-#define FONT_TEXT_2_ACTIVE                     9
-#define FONT_TEXT_3_ACTIVE                     10
-#define FONT_TEXT_4_ACTIVE                     11
-#define FONT_TEXT_1                            12
-#define FONT_TEXT_2                            13
-#define FONT_TEXT_3                            14
-#define FONT_TEXT_4                            15
-#define FONT_ENVELOPE_1                                16
-#define FONT_ENVELOPE_2                                17
-#define FONT_ENVELOPE_3                                18
-#define FONT_ENVELOPE_4                                19
-#define FONT_INPUT_1_ACTIVE                    20
-#define FONT_INPUT_2_ACTIVE                    21
-#define FONT_INPUT_1                           22
-#define FONT_INPUT_2                           23
-#define FONT_OPTION_OFF                                24
-#define FONT_OPTION_ON                         25
-#define FONT_VALUE_1                           26
-#define FONT_VALUE_2                           27
-#define FONT_VALUE_OLD                         28
-#define FONT_LEVEL_NUMBER                      29
-#define FONT_TAPE_RECORDER                     30
-#define FONT_GAME_INFO                         31
-
-#define NUM_FONTS                              32
-#define NUM_INITIAL_FONTS                      4
+#define FONT_INITIAL_1                 0
+#define FONT_INITIAL_2                 1
+#define FONT_INITIAL_3                 2
+#define FONT_INITIAL_4                 3
+#define FONT_TITLE_1                   4
+#define FONT_TITLE_2                   5
+#define FONT_MENU_1                    6
+#define FONT_MENU_2                    7
+#define FONT_TEXT_1_ACTIVE             8
+#define FONT_TEXT_2_ACTIVE             9
+#define FONT_TEXT_3_ACTIVE             10
+#define FONT_TEXT_4_ACTIVE             11
+#define FONT_TEXT_1                    12
+#define FONT_TEXT_2                    13
+#define FONT_TEXT_3                    14
+#define FONT_TEXT_4                    15
+#define FONT_ENVELOPE_1                        16
+#define FONT_ENVELOPE_2                        17
+#define FONT_ENVELOPE_3                        18
+#define FONT_ENVELOPE_4                        19
+#define FONT_INPUT_1_ACTIVE            20
+#define FONT_INPUT_2_ACTIVE            21
+#define FONT_INPUT_1                   22
+#define FONT_INPUT_2                   23
+#define FONT_OPTION_OFF                        24
+#define FONT_OPTION_ON                 25
+#define FONT_VALUE_1                   26
+#define FONT_VALUE_2                   27
+#define FONT_VALUE_OLD                 28
+#define FONT_LEVEL_NUMBER              29
+#define FONT_TAPE_RECORDER             30
+#define FONT_GAME_INFO                 31
+
+#define NUM_FONTS                      32
+#define NUM_INITIAL_FONTS              4
 
 /* values for game_status (must match special image configuration suffixes) */
-#define GAME_MODE_DEFAULT                      0
-#define GAME_MODE_MAIN                         1
-#define GAME_MODE_LEVELS                       2
-#define GAME_MODE_SCORES                       3
-#define GAME_MODE_EDITOR                       4
-#define GAME_MODE_INFO                         5
-#define GAME_MODE_SETUP                                6
-#define GAME_MODE_PLAYING                      7
-#define GAME_MODE_PSEUDO_DOOR                  8
-#define GAME_MODE_PSEUDO_PREVIEW               9
-#define GAME_MODE_PSEUDO_CRUMBLED              10
+#define GAME_MODE_DEFAULT              0
+#define GAME_MODE_MAIN                 1
+#define GAME_MODE_LEVELS               2
+#define GAME_MODE_SCORES               3
+#define GAME_MODE_EDITOR               4
+#define GAME_MODE_INFO                 5
+#define GAME_MODE_SETUP                        6
+#define GAME_MODE_PLAYING              7
+#define GAME_MODE_PSEUDO_DOOR          8
+#define GAME_MODE_PSEUDO_PREVIEW       9
+#define GAME_MODE_PSEUDO_CRUMBLED      10
 
 /* there are no special config file suffixes for these modes */
-#define GAME_MODE_PSEUDO_TYPENAME              11
-#define GAME_MODE_QUIT                         12
+#define GAME_MODE_PSEUDO_TYPENAME      11
+#define GAME_MODE_QUIT                 12
 
 /* special definitions currently only used for custom artwork configuration */
-#define MUSIC_PREFIX_BACKGROUND                        0
-#define NUM_MUSIC_PREFIXES                     1
-#define MAX_LEVELS                             1000
+#define MUSIC_PREFIX_BACKGROUND                0
+#define NUM_MUSIC_PREFIXES             1
+#define MAX_LEVELS                     1000
 
 /* definitions for demo animation lists */
-#define HELPANIM_LIST_NEXT                     -1
-#define HELPANIM_LIST_END                      -999
+#define HELPANIM_LIST_NEXT             -1
+#define HELPANIM_LIST_END              -999
 
 
 /* program information and versioning definitions */
 
-#define PROGRAM_VERSION_MAJOR  3
-#define PROGRAM_VERSION_MINOR  1
-#define PROGRAM_VERSION_PATCH  0
-#define PROGRAM_VERSION_BUILD  5
+#define RELEASE_311                    TRUE
+
+#if RELEASE_311
+#define PROGRAM_VERSION_MAJOR          3
+#define PROGRAM_VERSION_MINOR          1
+#define PROGRAM_VERSION_PATCH          1
+#define PROGRAM_VERSION_BUILD          0
+#else
+/* !!! make sure that packaging script can find unique version number !!! */
+#define X_PROGRAM_VERSION_MAJOR                3
+#define X_PROGRAM_VERSION_MINOR                2
+#define X_PROGRAM_VERSION_PATCH                0
+#define X_PROGRAM_VERSION_BUILD                3
+#endif
 
-#define PROGRAM_TITLE_STRING   "Rocks'n'Diamonds"
-#define PROGRAM_AUTHOR_STRING  "Holger Schemel"
-#define PROGRAM_COPYRIGHT_STRING "Copyright Â©1995-2004 by Holger Schemel"
+#define PROGRAM_TITLE_STRING           "Rocks'n'Diamonds"
+#define PROGRAM_AUTHOR_STRING          "Holger Schemel"
+#define PROGRAM_COPYRIGHT_STRING       "Copyright Â©1995-2005 by Holger Schemel"
 
-#define ICON_TITLE_STRING      PROGRAM_TITLE_STRING
-#define COOKIE_PREFIX          "ROCKSNDIAMONDS"
-#define FILENAME_PREFIX                "Rocks"
+#define ICON_TITLE_STRING              PROGRAM_TITLE_STRING
+#define COOKIE_PREFIX                  "ROCKSNDIAMONDS"
+#define FILENAME_PREFIX                        "Rocks"
 
 #if defined(PLATFORM_UNIX)
-#define USERDATA_DIRECTORY     ".rocksndiamonds"
+#define USERDATA_DIRECTORY             ".rocksndiamonds"
 #elif defined(PLATFORM_WIN32)
-#define USERDATA_DIRECTORY     PROGRAM_TITLE_STRING
+#define USERDATA_DIRECTORY             PROGRAM_TITLE_STRING
 #else
-#define USERDATA_DIRECTORY     "userdata"
+#define USERDATA_DIRECTORY             "userdata"
 #endif
 
-#define X11_ICON_FILENAME      "rocks_icon.xbm"
-#define X11_ICONMASK_FILENAME  "rocks_iconmask.xbm"
-#define MSDOS_POINTER_FILENAME "mouse.pcx"
+#define X11_ICON_FILENAME              "rocks_icon.xbm"
+#define X11_ICONMASK_FILENAME          "rocks_iconmask.xbm"
+#define MSDOS_POINTER_FILENAME         "mouse.pcx"
 
 /* file version numbers for resource files (levels, tapes, score, setup, etc.)
 ** currently supported/known file version numbers:
 **     1.4 (still in use)
 **     2.0 (actual)
 */
-#define FILE_VERSION_1_0       VERSION_IDENT(1,0,0,0)
-#define FILE_VERSION_1_2       VERSION_IDENT(1,2,0,0)
-#define FILE_VERSION_1_4       VERSION_IDENT(1,4,0,0)
-#define FILE_VERSION_2_0       VERSION_IDENT(2,0,0,0)
+#define FILE_VERSION_1_0               VERSION_IDENT(1,0,0,0)
+#define FILE_VERSION_1_2               VERSION_IDENT(1,2,0,0)
+#define FILE_VERSION_1_4               VERSION_IDENT(1,4,0,0)
+#define FILE_VERSION_2_0               VERSION_IDENT(2,0,0,0)
 
 /* file version does not change for every program version, but is changed
    when new features are introduced that are incompatible with older file
    versions, so that they can be treated accordingly */
-#define FILE_VERSION_ACTUAL    FILE_VERSION_2_0
+#define FILE_VERSION_ACTUAL            FILE_VERSION_2_0
 
-#define GAME_VERSION_1_0       FILE_VERSION_1_0
-#define GAME_VERSION_1_2       FILE_VERSION_1_2
-#define GAME_VERSION_1_4       FILE_VERSION_1_4
-#define GAME_VERSION_2_0       FILE_VERSION_2_0
+#define GAME_VERSION_1_0               FILE_VERSION_1_0
+#define GAME_VERSION_1_2               FILE_VERSION_1_2
+#define GAME_VERSION_1_4               FILE_VERSION_1_4
+#define GAME_VERSION_2_0               FILE_VERSION_2_0
 
-#define GAME_VERSION_ACTUAL    VERSION_IDENT(PROGRAM_VERSION_MAJOR, \
-                                             PROGRAM_VERSION_MINOR, \
-                                             PROGRAM_VERSION_PATCH, \
-                                             PROGRAM_VERSION_BUILD)
+#define GAME_VERSION_ACTUAL            VERSION_IDENT(PROGRAM_VERSION_MAJOR, \
+                                                     PROGRAM_VERSION_MINOR, \
+                                                     PROGRAM_VERSION_PATCH, \
+                                                     PROGRAM_VERSION_BUILD)
 
 /* values for game_emulation */
-#define EMU_NONE               0
-#define EMU_BOULDERDASH                1
-#define EMU_SOKOBAN            2
-#define EMU_SUPAPLEX           3
+#define EMU_NONE                       0
+#define EMU_BOULDERDASH                        1
+#define EMU_SOKOBAN                    2
+#define EMU_SUPAPLEX                   3
+
+/* values for level file type identifier */
+#define LEVEL_FILE_TYPE_UNKNOWN                0
+#define LEVEL_FILE_TYPE_RND            1
+#define LEVEL_FILE_TYPE_BD             2
+#define LEVEL_FILE_TYPE_EM             3
+#define LEVEL_FILE_TYPE_SP             4
+#define LEVEL_FILE_TYPE_DX             5
+#define LEVEL_FILE_TYPE_SB             6
+#define LEVEL_FILE_TYPE_DC             7
+
+#define NUM_LEVEL_FILE_TYPES           8
+
+/* values for game engine type identifier */
+#define GAME_ENGINE_TYPE_UNKNOWN       LEVEL_FILE_TYPE_UNKNOWN
+#define GAME_ENGINE_TYPE_RND           LEVEL_FILE_TYPE_RND
+#define GAME_ENGINE_TYPE_EM            LEVEL_FILE_TYPE_EM
+
+#define NUM_ENGINE_TYPES               3
+
 
 struct MenuInfo
 {
-  int draw_xoffset_default;
-  int draw_yoffset_default;
   int draw_xoffset[NUM_SPECIAL_GFX_ARGS];
   int draw_yoffset[NUM_SPECIAL_GFX_ARGS];
 
   int scrollbar_xoffset;
 
-  int list_size_default;
   int list_size[NUM_SPECIAL_GFX_ARGS];
 
   int sound[NUM_SPECIAL_GFX_ARGS];
@@ -1381,6 +1529,8 @@ struct PlayerInfo
   boolean use_murphy_graphic;
 
   boolean block_last_field;
+  int block_delay_adjustment;  /* needed for different engine versions */
+
   boolean can_fall_into_acid;
 
   boolean LevelSolved, GameOver;
@@ -1414,16 +1564,27 @@ struct PlayerInfo
   int num_special_action_sleeping;
 
   int switch_x, switch_y;
+  int drop_x, drop_y;
 
   int show_envelope;
 
+#if 1  /* USE_NEW_MOVE_DELAY */
+  int move_delay;
+  int move_delay_value;
+#else
   unsigned long move_delay;
   int move_delay_value;
+#endif
 
   int move_delay_reset_counter;
 
+#if 1  /* USE_NEW_PUSH_DELAY */
+  int push_delay;
+  int push_delay_value;
+#else
   unsigned long push_delay;
   unsigned long push_delay_value;
+#endif
 
   unsigned long actual_frame_counter;
 
@@ -1436,7 +1597,7 @@ struct PlayerInfo
   int sokobanfields_still_needed;
   int lights_still_needed;
   int friends_still_needed;
-  int key[4];
+  int key[MAX_NUM_KEYS];
   int dynabomb_count, dynabomb_size, dynabombs_left, dynabomb_xl;
   int shield_normal_time_left;
   int shield_deadly_time_left;
@@ -1462,6 +1623,13 @@ struct LevelFileInfo
 
 struct LevelInfo
 {
+  struct LevelFileInfo file_info;
+
+  int game_engine_type;
+
+  /* level stored in native format for the alternative native game engines */
+  struct LevelInfo_EM *native_em_level;
+
   int file_version;    /* file format version the level is stored with    */
   int game_version;    /* game release version the level was created with */
 
@@ -1471,7 +1639,7 @@ struct LevelInfo
 
   int fieldx, fieldy;
 
-  int time;
+  int time;                            /* available time (seconds) */
   int gems_needed;
 
   char name[MAX_LEVEL_NAME_LEN + 1];
@@ -1493,19 +1661,40 @@ struct LevelInfo
   int time_light;
   int time_timegate;
 
+  /* values for the new EMC elements */
+  int android_move_time;
+  int android_clone_time;
+  boolean ball_random;
+  boolean ball_state_initial;
+  int ball_time;
+  int lenses_score;
+  int magnify_score;
+  int slurp_score;
+  int lenses_time;
+  int magnify_time;
+  int wind_direction_initial;
+  int ball_content[NUM_MAGIC_BALL_CONTENTS][3][3];
+  boolean android_array[16];
+
   int can_move_into_acid_bits; /* bitfield to store property for elements */
   int dont_collide_with_bits;  /* bitfield to store property for elements */
 
   boolean double_speed;
   boolean initial_gravity;
   boolean em_slippery_gems;    /* EM style "gems slip from wall" behaviour */
-  boolean block_last_field;    /* player blocks previous field while moving */
-  boolean sp_block_last_field; /* player blocks previous field while moving */
   boolean use_spring_bug;      /* for compatibility with old levels */
   boolean instant_relocation;  /* no visual delay when relocating player */
   boolean can_pass_to_walkable;        /* player can pass to empty or walkable tile */
   boolean grow_into_diggable;  /* amoeba can grow into anything diggable */
 
+  boolean block_last_field;    /* player blocks previous field while moving */
+  boolean sp_block_last_field; /* player blocks previous field while moving */
+
+#if 0  /* !!! THIS IS NOT A LEVEL SETTING => LOGIC MOVED TO "game.c" !!! */
+  int block_delay;             /* delay for blocking previous field */
+  int sp_block_delay;          /* delay for blocking previous field */
+#endif
+
   /* ('int' instead of 'boolean' because used as selectbox value in editor) */
   int use_step_counter;                /* count steps instead of seconds for level */
 
@@ -1514,6 +1703,8 @@ struct LevelInfo
   boolean use_custom_template; /* use custom properties from template file */
 
   boolean no_valid_file;       /* set when level file missing or invalid */
+
+  boolean changed;             /* set when level was changed in the editor */
 };
 
 struct TapeInfo
@@ -1547,7 +1738,7 @@ struct TapeInfo
   {
     byte action[MAX_PLAYERS];
     byte delay;
-  } pos[MAX_TAPELEN];
+  } pos[MAX_TAPE_LEN];
 
   boolean no_valid_file;       /* set when tape file missing or invalid */
 };
@@ -1565,6 +1756,11 @@ struct GameInfo
   int initial_move_delay_value;
   int initial_push_delay_value;
 
+  /* flags to handle bugs in and changes between different engine versions */
+  /* (for the latest engine version, these flags should always be "FALSE") */
+  boolean use_change_when_pushing_bug;
+  boolean use_block_last_field_bug;
+
   /* variable within running game */
   int yamyam_content_nr;
   boolean magic_wall_active;
@@ -1589,7 +1785,8 @@ struct GameInfo
 struct GlobalInfo
 {
   char *autoplay_leveldir;
-  int autoplay_level_nr;
+  int autoplay_level[MAX_TAPES_PER_SET];
+  boolean autoplay_all;
 
   char *convert_leveldir;
   int convert_level_nr;
@@ -1605,7 +1802,11 @@ struct ElementChangeInfo
 {
   boolean can_change;          /* use or ignore this change info */
 
+#if 1
+  boolean has_event[NUM_CHANGE_EVENTS];                /* change events */
+#else
   unsigned long events;                /* change events */
+#endif
 
   int trigger_player;          /* player triggering change */
   int trigger_side;            /* side triggering change */
@@ -1662,6 +1863,15 @@ struct ElementGroupInfo
   int choice_pos;              /* current element choice position */
 };
 
+struct ElementNameInfo
+{
+  /* ---------- token and description strings ---------- */
+
+  char *token_name;            /* element token used in config files */
+  char *class_name;            /* element class used in config files */
+  char *editor_description;    /* pre-defined description for level editor */
+};
+
 struct ElementInfo
 {
   /* ---------- token and description strings ---------- */
@@ -1730,7 +1940,11 @@ struct ElementInfo
 
   /* ---------- internal values used at runtime when playing ---------- */
 
+#if 1
+  boolean has_change_event[NUM_CHANGE_EVENTS];
+#else
   unsigned long change_events; /* bitfield for combined change events */
+#endif
 
   int event_page_nr[NUM_CHANGE_EVENTS]; /* page number for each event */
   struct ElementChangeInfo *event_page[NUM_CHANGE_EVENTS]; /* page for event */
@@ -1775,6 +1989,9 @@ struct GraphicInfo
   int src_x, src_y;            /* start position of animation frames */
   int width, height;           /* width/height of each animation frame */
   int offset_x, offset_y;      /* x/y offset to next animation frame */
+  int offset2_x, offset2_y;    /* x/y offset to second movement tile */
+  boolean double_movement;     /* animation has second movement tile */
+  int swap_double_tiles;       /* explicitely force or forbid tile swapping */
   int anim_frames;
   int anim_frames_per_line;
   int anim_start_frame;
@@ -1784,6 +2001,7 @@ struct GraphicInfo
   int crumbled_like;           /* element for cloning crumble graphics */
   int diggable_like;           /* element for cloning digging graphics */
   int border_size;             /* border size for "crumbled" graphics */
+  int scale_up_factor;         /* optional factor for scaling image up */
 
   int anim_delay_fixed;                /* optional delay values for bored and   */
   int anim_delay_random;       /* sleeping player animations (animation */
@@ -1806,6 +2024,8 @@ struct GraphicInfo
 struct SoundInfo
 {
   boolean loop;
+  int volume;
+  int priority;
 };
 
 struct MusicInfo
@@ -1904,8 +2124,8 @@ extern short                      StorePlayer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short                   Back[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern boolean                 Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern boolean                 Pushed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-extern unsigned long           Changed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-extern unsigned long           ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern boolean                 Changed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short                   ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short                   WasJustMoving[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short                   WasJustFalling[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern short                   CheckCollision[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
@@ -1961,6 +2181,7 @@ extern struct GlobalInfo  global;
 extern struct MenuInfo         menu;
 extern struct DoorInfo         door_1, door_2;
 extern struct ElementInfo      element_info[];
+extern struct ElementNameInfo  element_name_info[];
 extern struct ElementActionInfo        element_action_info[];
 extern struct ElementDirectionInfo element_direction_info[];
 extern struct SpecialSuffixInfo special_suffix_info[];
@@ -1973,12 +2194,12 @@ extern struct MusicInfo        *music_info;
 extern struct MusicFileInfo    *music_file_info;
 extern struct HelpAnimInfo     *helpanim_info;
 extern SetupFileHash           *helptext_info;
+extern struct ConfigTypeInfo   image_config_suffix[];
+extern struct ConfigTypeInfo   sound_config_suffix[];
+extern struct ConfigTypeInfo   music_config_suffix[];
 extern struct ConfigInfo       image_config[];
 extern struct ConfigInfo       sound_config[];
 extern struct ConfigInfo       music_config[];
-extern struct ConfigInfo       image_config_suffix[];
-extern struct ConfigInfo       sound_config_suffix[];
-extern struct ConfigInfo       music_config_suffix[];
 extern struct ConfigInfo       helpanim_config[];
 extern struct ConfigInfo       helptext_config[];
 
index 12901f035f76b63fdb3e47d1217f3da7afe9e6bd..7d783a9b21a3f672e3f5c13ce5574d63db856b8a 100644 (file)
@@ -97,12 +97,13 @@ static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
 static int setup_mode = SETUP_MODE_MAIN;
 static int info_mode = INFO_MODE_MAIN;
 
-#define mSX (SX + (game_status >= GAME_MODE_MAIN &&    \
-                  game_status <= GAME_MODE_SETUP ?     \
-                  menu.draw_xoffset[game_status] : menu.draw_xoffset_default))
-#define mSY (SY + (game_status >= GAME_MODE_MAIN &&    \
-                  game_status <= GAME_MODE_SETUP ?     \
-                  menu.draw_yoffset[game_status] : menu.draw_yoffset_default))
+#define DRAW_OFFSET_MODE(x)    (x >= GAME_MODE_MAIN &&                 \
+                                x <= GAME_MODE_SETUP ? x :             \
+                                x == GAME_MODE_PSEUDO_TYPENAME ?       \
+                                GAME_MODE_MAIN : GAME_MODE_DEFAULT)
+
+#define mSX (SX + menu.draw_xoffset[DRAW_OFFSET_MODE(game_status)])
+#define mSY (SY + menu.draw_yoffset[DRAW_OFFSET_MODE(game_status)])
 
 #define NUM_MENU_ENTRIES_ON_SCREEN (menu.list_size[game_status] > 2 ?  \
                                    menu.list_size[game_status] :       \
@@ -308,7 +309,7 @@ void DrawMainMenu()
   DrawText(mSX + level_width + 5 * 32, mSY + 3*32, int2str(level_nr,3),
           FONT_VALUE_1);
 
-  DrawMicroLevel(MICROLEV_XPOS, MICROLEV_YPOS, TRUE);
+  DrawMicroLevel(MICROLEVEL_XPOS, MICROLEVEL_YPOS, TRUE);
 
   DrawTextF(mSX + 32 + level_width - 2, mSY + 3*32 + 1, FONT_TEXT_3, "%d-%d",
            leveldir_current->first_level, leveldir_current->last_level);
@@ -346,6 +347,7 @@ void DrawMainMenu()
   OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
 }
 
+#if 0
 static void gotoTopLevelDir()
 {
   /* move upwards to top level directory */
@@ -374,9 +376,11 @@ static void gotoTopLevelDir()
     leveldir_current = leveldir_current->node_parent;
   }
 }
+#endif
 
 void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 {
+  static unsigned long level_delay = 0;
   static int choice = 5;
   int x = 0;
   int y = choice;
@@ -402,9 +406,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
   if (y == 1 && ((x == 10 && level_nr > leveldir_current->first_level) ||
                 (x == 14 && level_nr < leveldir_current->last_level)) &&
-      button)
+      button && DelayReached(&level_delay, GADGET_FRAME_DELAY))
   {
-    static unsigned long level_delay = 0;
     int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
     int old_level_nr = level_nr;
     int new_level_nr;
@@ -415,11 +418,25 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
     if (new_level_nr > leveldir_current->last_level)
       new_level_nr = leveldir_current->last_level;
 
+#if 1
     if (setup.handicap && new_level_nr > leveldir_current->handicap_level)
+    {
+      /* skipping levels is only allowed when trying to skip single level */
+      if (setup.skip_levels && step == 1 &&
+         Request("Level still unsolved ! Skip despite handicap ?", REQ_ASK))
+      {
+       leveldir_current->handicap_level++;
+       SaveLevelSetup_SeriesInfo();
+      }
+
       new_level_nr = leveldir_current->handicap_level;
+    }
+#else
+    if (setup.handicap && new_level_nr > leveldir_current->handicap_level)
+      new_level_nr = leveldir_current->handicap_level;
+#endif
 
-    if (new_level_nr != old_level_nr &&
-       DelayReached(&level_delay, GADGET_FRAME_DELAY))
+    if (new_level_nr != old_level_nr)
     {
       level_nr = new_level_nr;
 
@@ -427,7 +444,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
               FONT_VALUE_1);
 
       LoadLevel(level_nr);
-      DrawMicroLevel(MICROLEV_XPOS, MICROLEV_YPOS, TRUE);
+      DrawMicroLevel(MICROLEVEL_XPOS, MICROLEVEL_YPOS, TRUE);
 
       TapeErase();
       LoadTape(level_nr);
@@ -466,7 +483,9 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
          SaveLevelSetup_LastSeries();
          SaveLevelSetup_SeriesInfo();
 
+#if 0
          gotoTopLevelDir();
+#endif
 
          DrawChooseLevel();
        }
@@ -524,7 +543,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
 
   if (game_status == GAME_MODE_MAIN)
   {
-    DrawMicroLevel(MICROLEV_XPOS, MICROLEV_YPOS, FALSE);
+    DrawMicroLevel(MICROLEVEL_XPOS, MICROLEVEL_YPOS, FALSE);
     DoAnimation();
   }
 }
@@ -1481,6 +1500,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
   int num_entries = numTreeInfoInGroup(ti);
   int num_page_entries;
   int last_game_status = game_status;  /* save current game status */
+  boolean position_set_by_scrollbar = (dx == 999);
 
   /* force LEVELS draw offset on choose level and artwork setup screen */
   game_status = GAME_MODE_LEVELS;
@@ -1512,7 +1532,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
       ti->cl_cursor = entry_pos - ti->cl_first;
     }
 
-    if (dx == 999)     /* first entry is set by scrollbar position */
+    if (position_set_by_scrollbar)
       ti->cl_first = dy;
     else
       AdjustChooseTreeScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL,
@@ -1634,7 +1654,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
     return;
   }
 
-  if (IN_VIS_FIELD(x, y) &&
+  if (!anyScrollbarGadgetActive() &&
+      IN_VIS_FIELD(x, y) &&
       mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x &&
       y >= 0 && y < num_page_entries)
   {
@@ -1942,6 +1963,7 @@ static struct TokenInfo setup_info_game[] =
 {
   { TYPE_SWITCH,       &setup.team_mode,       "Team-Mode:"            },
   { TYPE_SWITCH,       &setup.handicap,        "Handicap:"             },
+  { TYPE_SWITCH,       &setup.skip_levels,     "Skip Levels:"          },
   { TYPE_SWITCH,       &setup.time_limit,      "Timelimit:"            },
   { TYPE_SWITCH,       &setup.autorecord,      "Auto-Record:"          },
   { TYPE_EMPTY,                NULL,                   ""                      },
@@ -1957,6 +1979,7 @@ static struct TokenInfo setup_info_editor[] =
 #endif
   { TYPE_SWITCH,       &setup.editor.el_boulderdash,   "BoulderDash:"  },
   { TYPE_SWITCH,       &setup.editor.el_emerald_mine,  "Emerald Mine:" },
+  { TYPE_SWITCH,       &setup.editor.el_emerald_mine_club,"E.M. Club:" },
   { TYPE_SWITCH,       &setup.editor.el_more,          "More:"         },
   { TYPE_SWITCH,       &setup.editor.el_sokoban,       "Sokoban:"      },
   { TYPE_SWITCH,       &setup.editor.el_supaplex,      "Supaplex:"     },
@@ -2944,17 +2967,133 @@ void HandleGameActions()
   if (game_status != GAME_MODE_PLAYING)
     return;
 
-  if (local_player->LevelSolved)
-    GameWon();
+  /* !!! FIX THIS (START) !!! */
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    byte *recorded_player_action;
+    byte summarized_player_action = 0;
+    byte tape_action[MAX_PLAYERS];
+    int i;
 
-  if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
-    TapeStop();
+    if (level.native_em_level->lev->home == 0) /* all players at home */
+    {
+      GameWon();
 
-  GameActions();
-  BackToFront();
+      if (!TAPE_IS_STOPPED(tape))
+       TapeStop();
+
+      if (game_status != GAME_MODE_PLAYING)
+       return;
+    }
+
+    if (level.native_em_level->ply1->alive == 0 &&
+       level.native_em_level->ply2->alive == 0)        /* all dead */
+      AllPlayersGone = TRUE;
+
+    if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
+      TapeStop();
+
+    /* --- game actions --- */
+
+    if (tape.pausing)
+    {
+      /* don't use 100% CPU while in pause mode -- this should better be solved
+        like in the R'n'D game engine! */
+
+      Delay(10);
+
+      return;
+    }
+
+    recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
+
+#if 1
+    /* !!! CHECK THIS (tape.pausing is always FALSE here!) !!! */
+    if (recorded_player_action == NULL && tape.pausing)
+      return;
+#endif
 
-  if (tape.auto_play && !tape.playing)
-    AutoPlayTape();    /* continue automatically playing next tape */
+    for (i = 0; i < MAX_PLAYERS; i++)
+    {
+      summarized_player_action |= stored_player[i].action;
+
+      if (!network_playing)
+       stored_player[i].effective_action = stored_player[i].action;
+    }
+
+    if (!options.network && !setup.team_mode)
+      local_player->effective_action = summarized_player_action;
+
+    if (recorded_player_action != NULL)
+      for (i = 0; i < MAX_PLAYERS; i++)
+       stored_player[i].effective_action = recorded_player_action[i];
+
+    for (i = 0; i < MAX_PLAYERS; i++)
+    {
+      tape_action[i] = stored_player[i].effective_action;
+
+      /* !!! (this does not happen in the EM engine) !!! */
+      if (tape.recording && tape_action[i] && !tape.player_participates[i])
+       tape.player_participates[i] = TRUE;  /* player just appeared from CE */
+    }
+
+    /* only save actions from input devices, but not programmed actions */
+    if (tape.recording)
+      TapeRecordAction(tape_action);
+
+    GameActions_EM(local_player->effective_action);
+
+    if (TimeFrames >= FRAMES_PER_SECOND)
+    {
+      TimeFrames = 0;
+      TapeTime++;
+
+      if (!level.use_step_counter)
+      {
+       TimePlayed++;
+
+       if (TimeLeft > 0)
+       {
+         TimeLeft--;
+
+         if (TimeLeft <= 10 && setup.time_limit)
+           PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
+
+         DrawGameValue_Time(TimeLeft);
+
+         if (!TimeLeft && setup.time_limit)
+           level.native_em_level->lev->killed_out_of_time = TRUE;
+       }
+       else if (level.time == 0 && level.native_em_level->lev->home > 0)
+         DrawGameValue_Time(TimePlayed);
+
+       level.native_em_level->lev->time =
+         (level.time == 0 ? TimePlayed : TimeLeft);
+      }
+
+      if (tape.recording || tape.playing)
+       DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
+    }
+
+    FrameCounter++;
+    TimeFrames++;
+
+    BackToFront();
+  }
+  else
+  {
+    if (local_player->LevelSolved)
+      GameWon();
+
+    if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
+      TapeStop();
+
+    GameActions();
+    BackToFront();
+
+    if (tape.auto_play && !tape.playing)
+      AutoPlayTape();  /* continue automatically playing next tape */
+  }
 }
 
 /* ---------- new screen button stuff -------------------------------------- */
index 66ca33c035107081a8ae9274c113ad9323db5794..172af415b67bdf451da87957f3dd39926853aa0d 100644 (file)
@@ -776,8 +776,10 @@ void TapeHaltRecording()
 
 void TapeStopRecording()
 {
+#if 0
   if (!tape.recording)
     return;
+#endif
 
   TapeHaltRecording();
 
@@ -800,7 +802,7 @@ void TapeRecordAction(byte action[MAX_PLAYERS])
     return;
 #endif
 
-  if (tape.counter >= MAX_TAPELEN - 1)
+  if (tape.counter >= MAX_TAPE_LEN - 1)
   {
     TapeStopRecording();
     return;
@@ -923,8 +925,10 @@ static void TapeStartGamePlaying()
 
 void TapeStopPlaying()
 {
+#if 0
   if (!tape.playing)
     return;
+#endif
 
   tape.playing = FALSE;
   tape.pausing = FALSE;
@@ -944,7 +948,7 @@ byte *TapePlayAction()
   if (!tape.playing || tape.pausing)
     return NULL;
 
-  if (tape.pause_before_death) /* STOP 10s BEFORE PLAYER GETS KILLED... */
+  if (tape.pause_before_death) /* stop 10 seconds before player gets killed */
   {
     if (!(FrameCounter % 20))
     {
@@ -965,6 +969,7 @@ byte *TapePlayAction()
     if (TapeTime > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH)
     {
       TapeTogglePause(TAPE_TOGGLE_MANUAL);
+
       return NULL;
     }
   }
@@ -983,6 +988,7 @@ byte *TapePlayAction()
        DrawVideoDisplay(VIDEO_STATE_WARP2_ON, VIDEO_DISPLAY_SYMBOL_ONLY);
     }
   }
+
 #if 0
   /* !!! this makes things much slower !!! */
   else if (tape.warp_forward)
@@ -1152,13 +1158,19 @@ void TapeQuickSave()
 
 void TapeQuickLoad()
 {
+  char *filename = getTapeFilename(level_nr);
+
+  if (!fileExists(filename))
+  {
+    Request("No tape for this level !", REQ_CONFIRM);
+
+    return;
+  }
+
   if (tape.recording && !Request("Stop recording and load tape ?",
                                 REQ_ASK | REQ_STAY_CLOSED))
   {
-    BlitBitmap(bitmap_db_door, bitmap_db_door,
-              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-    OpenDoor(DOOR_OPEN_1);
+    OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
 
     return;
   }
@@ -1176,8 +1188,12 @@ void TapeQuickLoad()
 
       tape.quick_resume = TRUE;
     }
-    else
-      Request("No tape for this level !", REQ_CONFIRM);
+    else       /* this should not happen (basically checked above) */
+    {
+      int reopen_door = (game_status == GAME_MODE_PLAYING ? REQ_REOPEN : 0);
+
+      Request("No tape for this level !", REQ_CONFIRM | reopen_door);
+    }
   }
 }
 
@@ -1199,8 +1215,6 @@ void InsertSolutionTape()
  * tape autoplay functions
  * ------------------------------------------------------------------------- */
 
-#define MAX_NUM_AUTOPLAY_LEVELS                1000
-
 void AutoPlayTape()
 {
   static LevelDirTree *autoplay_leveldir = NULL;
@@ -1208,7 +1222,9 @@ void AutoPlayTape()
   static int autoplay_level_nr = -1;
   static int num_levels_played = 0;
   static int num_levels_solved = 0;
-  static boolean levels_failed[MAX_NUM_AUTOPLAY_LEVELS];
+  static int num_tape_missing = 0;
+  static boolean level_failed[MAX_TAPES_PER_SET];
+  static boolean tape_missing[MAX_TAPES_PER_SET];
   int i;
 
   if (autoplay_initialized)
@@ -1217,10 +1233,11 @@ void AutoPlayTape()
     printf("%s.\n", tape.auto_play_level_solved ? "solved" : "NOT SOLVED");
 
     num_levels_played++;
+
     if (tape.auto_play_level_solved)
       num_levels_solved++;
-    else if (level_nr >= 0 && level_nr < MAX_NUM_AUTOPLAY_LEVELS)
-      levels_failed[level_nr] = TRUE;
+    else if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
+      level_failed[level_nr] = TRUE;
   }
   else
   {
@@ -1236,11 +1253,10 @@ void AutoPlayTape()
 
     leveldir_current = autoplay_leveldir;
 
-    if (global.autoplay_level_nr != -1)
-    {
-      autoplay_leveldir->first_level = global.autoplay_level_nr;
-      autoplay_leveldir->last_level  = global.autoplay_level_nr;
-    }
+    if (autoplay_leveldir->first_level < 0)
+      autoplay_leveldir->first_level = 0;
+    if (autoplay_leveldir->last_level >= MAX_TAPES_PER_SET)
+      autoplay_leveldir->last_level = MAX_TAPES_PER_SET - 1;
 
     autoplay_level_nr = autoplay_leveldir->first_level;
 
@@ -1254,8 +1270,11 @@ void AutoPlayTape()
     printf_line("=", 79);
     printf("\n");
 
-    for (i = 0; i < MAX_NUM_AUTOPLAY_LEVELS; i++)
-      levels_failed[i] = FALSE;
+    for (i = 0; i < MAX_TAPES_PER_SET; i++)
+    {
+      level_failed[i] = FALSE;
+      tape_missing[i] = FALSE;
+    }
 
     autoplay_initialized = TRUE;
   }
@@ -1264,6 +1283,9 @@ void AutoPlayTape()
   {
     level_nr = autoplay_level_nr++;
 
+    if (!global.autoplay_all && !global.autoplay_level[level_nr])
+      continue;
+
     TapeErase();
 
     printf("Level %03d: ", level_nr);
@@ -1282,6 +1304,10 @@ void AutoPlayTape()
     if (TAPE_IS_EMPTY(tape))
 #endif
     {
+      num_tape_missing++;
+      if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
+       tape_missing[level_nr] = TRUE;
+
       printf("(no tape)\n");
       continue;
     }
@@ -1308,11 +1334,21 @@ void AutoPlayTape()
   if (num_levels_played != num_levels_solved)
   {
     printf(", FAILED:");
-    for (i = 0; i < MAX_NUM_AUTOPLAY_LEVELS; i++)
-      if (levels_failed[i])
+    for (i = 0; i < MAX_TAPES_PER_SET; i++)
+      if (level_failed[i])
        printf(" %03d", i);
   }
 
+#if 0
+  if (num_tape_missing > 0)
+  {
+    printf(", NO TAPE:");
+    for (i = 0; i < MAX_TAPES_PER_SET; i++)
+      if (tape_missing[i])
+       printf(" %03d", i);
+  }
+#endif
+
   printf("\n");
   printf_line("=", 79);
 
index 68bac2efc88e6a42384e0569bc558ae04d0238ba..eedf5d60284157f4aa9c79b60d0d49ff43cde1ad 100644 (file)
@@ -123,7 +123,12 @@ void SetDrawtoField(int mode)
 
 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
 {
-  if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
+  if (game_status == GAME_MODE_PLAYING &&
+      level.game_engine_type == GAME_ENGINE_TYPE_EM)
+  {
+    BlitScreenToBitmap_EM(backbuffer);
+  }
+  else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
   {
     if (force_redraw)
     {
@@ -436,9 +441,9 @@ void SetDoorBackgroundImage(int graphic)
                          graphic_info[IMG_BACKGROUND].bitmap);
 }
 
-void DrawBackground(int dest_x, int dest_y, int width, int height)
+void DrawBackground(int dst_x, int dst_y, int width, int height)
 {
-  ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
+  ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
 
   redraw_mask |= REDRAW_FIELD;
 }
@@ -511,1524 +516,1689 @@ inline int getGraphicAnimationFrame(int graphic, int sync_frame)
                           sync_frame);
 }
 
-inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
-                                   int graphic, int sync_frame, int mask_mode)
+inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
+                               int *x, int *y, boolean get_backside)
 {
-  int frame = getGraphicAnimationFrame(graphic, sync_frame);
+  struct GraphicInfo *g = &graphic_info[graphic];
+  int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
+  int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
 
-  if (mask_mode == USE_MASKING)
-    DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
-  else
-    DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
+  *bitmap = g->bitmap;
+
+  if (g->offset_y == 0)                /* frames are ordered horizontally */
+  {
+    int max_width = g->anim_frames_per_line * g->width;
+#if 1
+    int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
+
+    *x = pos % max_width;
+    *y = src_y % g->height + pos / max_width * g->height;
+#else
+    *x = (src_x + frame * g->offset_x) % max_width;
+    *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
+#endif
+  }
+  else if (g->offset_x == 0)   /* frames are ordered vertically */
+  {
+    int max_height = g->anim_frames_per_line * g->height;
+#if 1
+    int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
+
+    *x = src_x % g->width + pos / max_height * g->width;
+    *y = pos % max_height;
+#else
+    *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
+    *y = (src_y + frame * g->offset_y) % max_height;
+#endif
+  }
+  else                         /* frames are ordered diagonally */
+  {
+    *x = src_x + frame * g->offset_x;
+    *y = src_y + frame * g->offset_y;
+  }
 }
 
-inline void DrawGraphicAnimation(int x, int y, int graphic)
+void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
 {
-  int lx = LEVELX(x), ly = LEVELY(y);
+  getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
+}
 
+void DrawGraphic(int x, int y, int graphic, int frame)
+{
+#if DEBUG
   if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
+    printf("DrawGraphic(): This should never happen!\n");
     return;
+  }
+#endif
 
-  DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
-                         graphic, GfxFrame[lx][ly], NO_MASKING);
+  DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
   MarkTileDirty(x, y);
 }
 
-void DrawLevelGraphicAnimation(int x, int y, int graphic)
+void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
+                   int frame)
 {
-  DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+
+  getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+  BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
 }
 
-void DrawLevelElementAnimation(int x, int y, int element)
+void DrawGraphicThruMask(int x, int y, int graphic, int frame)
 {
-#if 1
-  int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
-  DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
-#else
-  DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
+#if DEBUG
+  if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
+    printf("DrawGraphicThruMask(): This should never happen!\n");
+    return;
+  }
 #endif
+
+  DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
+                        frame);
+  MarkTileDirty(x, y);
 }
 
-inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
+                           int frame)
 {
-  int sx = SCREENX(x), sy = SCREENY(y);
+  Bitmap *src_bitmap;
+  int src_x, src_y;
 
-  if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
-    return;
+  getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
-  if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
-    return;
+  SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+               dst_x - src_x, dst_y - src_y);
+  BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
+}
 
-  DrawGraphicAnimation(sx, sy, graphic);
+void DrawMiniGraphic(int x, int y, int graphic)
+{
+  DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
+  MarkTileDirty(x / 2, y / 2);
+}
 
-  if (GFX_CRUMBLED(Feld[x][y]))
-    DrawLevelFieldCrumbledSand(x, y);
+void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+{
+  struct GraphicInfo *g = &graphic_info[graphic];
+  int mini_startx = 0;
+  int mini_starty = g->bitmap->height * 2 / 3;
+
+  *bitmap = g->bitmap;
+  *x = mini_startx + g->src_x / 2;
+  *y = mini_starty + g->src_y / 2;
 }
 
-void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
+void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
 {
-  int sx = SCREENX(x), sy = SCREENY(y);
-  int graphic;
+  Bitmap *src_bitmap;
+  int src_x, src_y;
 
-  if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
-    return;
+  getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
+}
 
-  graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
+                                           int graphic, int frame,
+                                           int cut_mode, int mask_mode)
+{
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int dst_x, dst_y;
+  int width = TILEX, height = TILEY;
+  int cx = 0, cy = 0;
 
-  if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+  if (dx || dy)                        /* shifted graphic */
+  {
+    if (x < BX1)               /* object enters playfield from the left */
+    {
+      x = BX1;
+      width = dx;
+      cx = TILEX - dx;
+      dx = 0;
+    }
+    else if (x > BX2)          /* object enters playfield from the right */
+    {
+      x = BX2;
+      width = -dx;
+      dx = TILEX + dx;
+    }
+    else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
+    {
+      width += dx;
+      cx = -dx;
+      dx = 0;
+    }
+    else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
+      width -= dx;
+    else if (dx)               /* general horizontal movement */
+      MarkTileDirty(x + SIGN(dx), y);
+
+    if (y < BY1)               /* object enters playfield from the top */
+    {
+      if (cut_mode==CUT_BELOW) /* object completely above top border */
+       return;
+
+      y = BY1;
+      height = dy;
+      cy = TILEY - dy;
+      dy = 0;
+    }
+    else if (y > BY2)          /* object enters playfield from the bottom */
+    {
+      y = BY2;
+      height = -dy;
+      dy = TILEY + dy;
+    }
+    else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
+    {
+      height += dy;
+      cy = -dy;
+      dy = 0;
+    }
+    else if (dy > 0 && cut_mode == CUT_ABOVE)
+    {
+      if (y == BY2)            /* object completely above bottom border */
+       return;
+
+      height = dy;
+      cy = TILEY - dy;
+      dy = TILEY;
+      MarkTileDirty(x, y + 1);
+    }                          /* object leaves playfield to the bottom */
+    else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
+      height -= dy;
+    else if (dy)               /* general vertical movement */
+      MarkTileDirty(x, y + SIGN(dy));
+  }
+
+#if DEBUG
+  if (!IN_SCR_FIELD(x, y))
+  {
+    printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
+    printf("DrawGraphicShifted(): This should never happen!\n");
     return;
+  }
+#endif
 
-  DrawGraphicAnimation(sx, sy, graphic);
+  if (width > 0 && height > 0)
+  {
+    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
-  if (GFX_CRUMBLED(element))
-    DrawLevelFieldCrumbledSand(x, y);
+    src_x += cx;
+    src_y += cy;
+
+    dst_x = FX + x * TILEX + dx;
+    dst_y = FY + y * TILEY + dy;
+
+    if (mask_mode == USE_MASKING)
+    {
+      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+                   dst_x - src_x, dst_y - src_y);
+      BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
+                      dst_x, dst_y);
+    }
+    else
+      BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
+                dst_x, dst_y);
+
+    MarkTileDirty(x, y);
+  }
 }
 
-static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
+inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
+                                           int graphic, int frame,
+                                           int cut_mode, int mask_mode)
 {
-  if (player->use_murphy_graphic)
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int dst_x, dst_y;
+  int width = TILEX, height = TILEY;
+  int x1 = x;
+  int y1 = y;
+  int x2 = x + SIGN(dx);
+  int y2 = y + SIGN(dy);
+  int anim_frames = graphic_info[graphic].anim_frames;
+  int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
+
+  /* re-calculate animation frame for two-tile movement animation */
+  frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+  if (IN_SCR_FIELD(x1, y1))    /* movement start graphic inside screen area */
   {
-    /* this works only because currently only one player can be "murphy" ... */
-    static int last_horizontal_dir = MV_LEFT;
-    int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
+    getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
 
-    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
-      last_horizontal_dir = move_dir;
+    dst_x = FX + x1 * TILEX;
+    dst_y = FY + y1 * TILEY;
 
-    if (graphic == IMG_SP_MURPHY)      /* undefined => use special graphic */
+    if (mask_mode == USE_MASKING)
     {
-      int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
+      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+                   dst_x - src_x, dst_y - src_y);
+      BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
+                      dst_x, dst_y);
+    }
+    else
+      BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
+                dst_x, dst_y);
 
-      graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
+    MarkTileDirty(x1, y1);
+  }
+
+  if (IN_SCR_FIELD(x2, y2))    /* movement end graphic inside screen area */
+  {
+    getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
+
+    dst_x = FX + x2 * TILEX;
+    dst_y = FY + y2 * TILEY;
+
+    if (mask_mode == USE_MASKING)
+    {
+      SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+                   dst_x - src_x, dst_y - src_y);
+      BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
+                      dst_x, dst_y);
     }
+    else
+      BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
+                dst_x, dst_y);
 
-    return graphic;
+    MarkTileDirty(x2, y2);
   }
-  else
-    return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
+
+#if 0
+  printf("::: DONE DrawGraphicShiftedDouble");
+  BackToFront();
+  Delay(1000);
+#endif
 }
 
-static boolean equalGraphics(int graphic1, int graphic2)
+static void DrawGraphicShifted(int x, int y, int dx, int dy,
+                              int graphic, int frame,
+                              int cut_mode, int mask_mode)
 {
-  struct GraphicInfo *g1 = &graphic_info[graphic1];
-  struct GraphicInfo *g2 = &graphic_info[graphic2];
+  if (graphic < 0)
+  {
+    DrawGraphic(x, y, graphic, frame);
 
-  return (g1->bitmap      == g2->bitmap &&
-         g1->src_x       == g2->src_x &&
-         g1->src_y       == g2->src_y &&
-         g1->anim_frames == g2->anim_frames &&
-         g1->anim_delay  == g2->anim_delay &&
-         g1->anim_mode   == g2->anim_mode);
+    return;
+  }
+
+  if (graphic_info[graphic].double_movement)   /* EM style movement images */
+    DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
+  else
+    DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
 }
 
-void DrawAllPlayers()
+void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
+                               int frame, int cut_mode)
 {
-  int i;
+  DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
+}
 
-  for (i = 0; i < MAX_PLAYERS; i++)
-    if (stored_player[i].active)
-      DrawPlayer(&stored_player[i]);
-}
-
-void DrawPlayerField(int x, int y)
-{
-  if (!IS_PLAYER(x, y))
-    return;
-
-  DrawPlayer(PLAYERINFO(x, y));
-}
-
-void DrawPlayer(struct PlayerInfo *player)
+void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
+                         int cut_mode, int mask_mode)
 {
-  int jx = player->jx;
-  int jy = player->jy;
-  int move_dir = player->MovDir;
-#if 0
-  int last_jx = player->last_jx;
-  int last_jy = player->last_jy;
-  int next_jx = jx + (jx - last_jx);
-  int next_jy = jy + (jy - last_jy);
-  boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
-#else
-  int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
-  int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? +1 : 0);
-  int last_jx = (player->is_moving ? jx - dx : jx);
-  int last_jy = (player->is_moving ? jy - dy : jy);
-  int next_jx = jx + dx;
-  int next_jy = jy + dy;
-  boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
-#endif
-  int sx = SCREENX(jx), sy = SCREENY(jy);
-  int sxx = 0, syy = 0;
-  int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
+  int lx = LEVELX(x), ly = LEVELY(y);
   int graphic;
-  int action = ACTION_DEFAULT;
-  int last_player_graphic = getPlayerGraphic(player, move_dir);
-  int last_player_frame = player->Frame;
-  int frame = 0;
-
-  if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
-    return;
+  int frame;
 
-#if DEBUG
-  if (!IN_LEV_FIELD(jx, jy))
+  if (IN_LEV_FIELD(lx, ly))
   {
-    printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
-    printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
-    printf("DrawPlayerField(): This should never happen!\n");
-    return;
-  }
-#endif
-
-  if (element == EL_EXPLOSION)
-    return;
-
-  action = (player->is_pushing    ? ACTION_PUSHING         :
-           player->is_digging    ? ACTION_DIGGING         :
-           player->is_collecting ? ACTION_COLLECTING      :
-           player->is_moving     ? ACTION_MOVING          :
-           player->is_snapping   ? ACTION_SNAPPING        :
-           player->is_dropping   ? ACTION_DROPPING        :
-           player->is_waiting    ? player->action_waiting : ACTION_DEFAULT);
-
-  InitPlayerGfxAnimation(player, action, move_dir);
+    SetRandomAnimationValue(lx, ly);
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things in the field the player is leaving, if needed               */
-  /* ----------------------------------------------------------------------- */
+    graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
+    frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
 
-#if 1
-  if (player->is_moving)
-#else
-  if (player_is_moving)
-#endif
-  {
-    if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
+    /* do not use double (EM style) movement graphic when not moving */
+    if (graphic_info[graphic].double_movement && !dx && !dy)
     {
-      DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
-
-      if (last_element == EL_DYNAMITE_ACTIVE ||
-         last_element == EL_SP_DISK_RED_ACTIVE)
-       DrawDynamite(last_jx, last_jy);
-      else
-       DrawLevelFieldThruMask(last_jx, last_jy);
+      graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
+      frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
     }
-    else if (last_element == EL_DYNAMITE_ACTIVE ||
-            last_element == EL_SP_DISK_RED_ACTIVE)
-      DrawDynamite(last_jx, last_jy);
-    else
-      DrawLevelField(last_jx, last_jy);
-
-    if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
-      DrawLevelElement(next_jx, next_jy, EL_EMPTY);
+  }
+  else /* border element */
+  {
+    graphic = el2img(element);
+    frame = getGraphicAnimationFrame(graphic, -1);
   }
 
-  if (!IN_SCR_FIELD(sx, sy))
-    return;
-
-  if (setup.direct_draw)
-    SetDrawtoField(DRAW_BUFFERED);
+  if (element == EL_EXPANDABLE_WALL)
+  {
+    boolean left_stopped = FALSE, right_stopped = FALSE;
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things behind the player, if needed                                */
-  /* ----------------------------------------------------------------------- */
+    if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
+      left_stopped = TRUE;
+    if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
+      right_stopped = TRUE;
 
-  if (Back[jx][jy])
-    DrawLevelElement(jx, jy, Back[jx][jy]);
-  else if (IS_ACTIVE_BOMB(element))
-    DrawLevelElement(jx, jy, EL_EMPTY);
-  else
-  {
-    if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
+    if (left_stopped && right_stopped)
+      graphic = IMG_WALL;
+    else if (left_stopped)
     {
-      if (GFX_CRUMBLED(GfxElement[jx][jy]))
-       DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
-      else
-      {
-       int old_element = GfxElement[jx][jy];
-       int old_graphic = el_act_dir2img(old_element, action, move_dir);
-       int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
-
-       DrawGraphic(sx, sy, old_graphic, frame);
-      }
+      graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
+      frame = graphic_info[graphic].anim_frames - 1;
     }
-    else
+    else if (right_stopped)
     {
-      GfxElement[jx][jy] = EL_UNDEFINED;
-
-      DrawLevelField(jx, jy);
+      graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
+      frame = graphic_info[graphic].anim_frames - 1;
     }
   }
 
-  /* ----------------------------------------------------------------------- */
-  /* draw player himself                                                     */
-  /* ----------------------------------------------------------------------- */
-
-#if 1
-
-  graphic = getPlayerGraphic(player, move_dir);
-
-  /* in the case of changed player action or direction, prevent the current
-     animation frame from being restarted for identical animations */
-  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
-    player->Frame = last_player_frame;
+  if (dx || dy)
+    DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
+  else if (mask_mode == USE_MASKING)
+    DrawGraphicThruMask(x, y, graphic, frame);
+  else
+    DrawGraphic(x, y, graphic, frame);
+}
 
-#else
+void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
+                        int cut_mode, int mask_mode)
+{
+  if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+    DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
+                        cut_mode, mask_mode);
+}
 
-  if (player->use_murphy_graphic)
-  {
-    static int last_horizontal_dir = MV_LEFT;
+void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
+                             int cut_mode)
+{
+  DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
+}
 
-    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
-      last_horizontal_dir = move_dir;
+void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
+                            int cut_mode)
+{
+  DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
+}
 
-    graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
+void DrawLevelElementThruMask(int x, int y, int element)
+{
+  DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
+}
 
-    if (graphic == IMG_SP_MURPHY)      /* undefined => use special graphic */
-    {
-      int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
+void DrawLevelFieldThruMask(int x, int y)
+{
+  DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
+}
 
-      graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
-    }
-  }
-  else
-    graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
+#define TILE_GFX_ELEMENT(x, y)                                             \
+       (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?   \
+        GfxElement[x][y] : Feld[x][y])
 
+static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
+{
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int sx = SCREENX(x), sy = SCREENY(y);
+  int element;
+  int width, height, cx, cy, i;
+#if 1
+  int crumbled_border_size = graphic_info[graphic].border_size;
+#else
+  int snip = TILEX / 8;        /* number of border pixels from "crumbled graphic" */
 #endif
-
-  frame = getGraphicAnimationFrame(graphic, player->Frame);
-
-  if (player->GfxPos)
+  static int xy[4][2] =
   {
-    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
-      sxx = player->GfxPos;
-    else
-      syy = player->GfxPos;
-  }
+    { 0, -1 },
+    { -1, 0 },
+    { +1, 0 },
+    { 0, +1 }
+  };
 
-  if (!setup.soft_scrolling && ScreenMovPos)
-    sxx = syy = 0;
+#if 0
+  if (x == 0 && y == 7)
+    printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
+          crumbled_border_size);
+#endif
 
-  DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+  if (!IN_LEV_FIELD(x, y))
+    return;
 
-  if (SHIELD_ON(player))
+  element = TILE_GFX_ELEMENT(x, y);
+
+  /* crumble field itself */
+  if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
   {
-    int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
-                  IMG_SHIELD_NORMAL_ACTIVE);
-    int frame = getGraphicAnimationFrame(graphic, -1);
+    if (!IN_SCR_FIELD(sx, sy))
+      return;
 
-    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
-  }
+    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
-  /* ----------------------------------------------------------------------- */
-  /* draw things the player is pushing, if needed                            */
-  /* ----------------------------------------------------------------------- */
-
-#if 0
-  printf("::: %d, %d [%d, %d] [%d]\n",
-        player->is_pushing, player_is_moving, player->GfxAction,
-        player->is_moving, player_is_moving);
-#endif
+    for (i = 0; i < 4; i++)
+    {
+      int xx = x + xy[i][0];
+      int yy = y + xy[i][1];
 
 #if 1
-  if (player->is_pushing && player->is_moving)
+      element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
+                BorderElement);
 #else
-  if (player->is_pushing && player_is_moving)
+      element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
 #endif
-  {
-    int px = SCREENX(next_jx), py = SCREENY(next_jy);
 
-    if (Back[next_jx][next_jy])
-      DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+      /* check if neighbour field is of same type */
+      if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
+       continue;
 
-    if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
-      DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
-                                NO_CUTTING);
-    else
-    {
-      int element = MovingOrBlocked2Element(next_jx, next_jy);
-      int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
-#if 1
-      int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
-#else
-      int frame = getGraphicAnimationFrame(graphic, player->Frame);
+#if 0
+      if (Feld[x][y] == EL_CUSTOM_START + 123)
+       printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
+              i, Feld[x][y], element,
+              GFX_CRUMBLED(element), IS_MOVING(x, y));
 #endif
 
-      DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
-                        NO_CUTTING, NO_MASKING);
-    }
-  }
-
-  /* ----------------------------------------------------------------------- */
-  /* draw things in front of player (active dynamite or dynabombs)           */
-  /* ----------------------------------------------------------------------- */
+      if (i == 1 || i == 2)
+      {
+       width = crumbled_border_size;
+       height = TILEY;
+       cx = (i == 2 ? TILEX - crumbled_border_size : 0);
+       cy = 0;
+      }
+      else
+      {
+       width = TILEX;
+       height = crumbled_border_size;
+       cx = 0;
+       cy = (i == 3 ? TILEY - crumbled_border_size : 0);
+      }
 
-  if (IS_ACTIVE_BOMB(element))
-  {
-    graphic = el2img(element);
-    frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
+    }
 
-    if (game.emulation == EMU_SUPAPLEX)
-      DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
-    else
-      DrawGraphicThruMask(sx, sy, graphic, frame);
+    MarkTileDirty(sx, sy);
   }
-
-  if (player_is_moving && last_element == EL_EXPLOSION)
+  else         /* crumble neighbour fields */
   {
-    int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
-    int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
-    int phase = ExplodePhase[last_jx][last_jy] - 1;
-    int frame = getGraphicAnimationFrame(graphic, phase - delay);
-
-    if (phase >= delay)
-      DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
-  }
-
-  /* ----------------------------------------------------------------------- */
-  /* draw elements the player is just walking/passing through/under          */
-  /* ----------------------------------------------------------------------- */
+#if 0
+    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+#endif
 
-  if (player_is_moving)
-  {
-    /* handle the field the player is leaving ... */
-    if (IS_ACCESSIBLE_INSIDE(last_element))
-      DrawLevelField(last_jx, last_jy);
-    else if (IS_ACCESSIBLE_UNDER(last_element))
-      DrawLevelFieldThruMask(last_jx, last_jy);
-  }
+    for (i = 0; i < 4; i++)
+    {
+      int xx = x + xy[i][0];
+      int yy = y + xy[i][1];
+      int sxx = sx + xy[i][0];
+      int syy = sy + xy[i][1];
 
 #if 1
-  /* do not redraw accessible elements if the player is just pushing them */
-  if (!player_is_moving || !player->is_pushing)
-  {
-    /* ... and the field the player is entering */
-    if (IS_ACCESSIBLE_INSIDE(element))
-      DrawLevelField(jx, jy);
-    else if (IS_ACCESSIBLE_UNDER(element))
-      DrawLevelFieldThruMask(jx, jy);
-  }
+      if (!IN_LEV_FIELD(xx, yy) ||
+         !IN_SCR_FIELD(sxx, syy) ||
+         IS_MOVING(xx, yy))
+       continue;
 
-#else
+      element = TILE_GFX_ELEMENT(xx, yy);
 
-#if 0
-  /* !!! I have forgotton what this should be good for !!! */
-  /* !!! causes player being visible when pushing from within tubes !!! */
-  if (!player->is_pushing)
-#endif
-  {
-    /* ... and the field the player is entering */
-    if (IS_ACCESSIBLE_INSIDE(element))
-      DrawLevelField(jx, jy);
-    else if (IS_ACCESSIBLE_UNDER(element))
-      DrawLevelFieldThruMask(jx, jy);
-  }
+      if (!GFX_CRUMBLED(element))
+       continue;
+#else
+      if (!IN_LEV_FIELD(xx, yy) ||
+         !IN_SCR_FIELD(sxx, syy) ||
+         !GFX_CRUMBLED(Feld[xx][yy]) ||
+         IS_MOVING(xx, yy))
+       continue;
 #endif
 
-  if (setup.direct_draw)
-  {
-    int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
-    int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
-    int x_size = TILEX * (1 + ABS(jx - last_jx));
-    int y_size = TILEY * (1 + ABS(jy - last_jy));
-
-    BlitBitmap(drawto_field, window,
-              dest_x, dest_y, x_size, y_size, dest_x, dest_y);
-    SetDrawtoField(DRAW_DIRECT);
-  }
-
-  MarkTileDirty(sx, sy);
-}
-
-void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
-{
-  struct GraphicInfo *g = &graphic_info[graphic];
+#if 1
+      graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
+      crumbled_border_size = graphic_info[graphic].border_size;
 
-  *bitmap = g->bitmap;
+      getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+#endif
 
-  if (g->offset_y == 0)                /* frames are ordered horizontally */
-  {
-    int max_width = g->anim_frames_per_line * g->width;
+      if (i == 1 || i == 2)
+      {
+       width = crumbled_border_size;
+       height = TILEY;
+       cx = (i == 1 ? TILEX - crumbled_border_size : 0);
+       cy = 0;
+      }
+      else
+      {
+       width = TILEX;
+       height = crumbled_border_size;
+       cx = 0;
+       cy = (i == 0 ? TILEY - crumbled_border_size : 0);
+      }
 
-    *x = (g->src_x + frame * g->offset_x) % max_width;
-    *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
-  }
-  else if (g->offset_x == 0)   /* frames are ordered vertically */
-  {
-    int max_height = g->anim_frames_per_line * g->height;
+      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
 
-    *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
-    *y = (g->src_y + frame * g->offset_y) % max_height;
-  }
-  else                         /* frames are ordered diagonally */
-  {
-    *x = g->src_x + frame * g->offset_x;
-    *y = g->src_y + frame * g->offset_y;
+      MarkTileDirty(sxx, syy);
+    }
   }
 }
 
-void DrawGraphic(int x, int y, int graphic, int frame)
+void DrawLevelFieldCrumbledSand(int x, int y)
 {
-#if DEBUG
-  if (!IN_SCR_FIELD(x, y))
-  {
-    printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
-    printf("DrawGraphic(): This should never happen!\n");
-    return;
-  }
-#endif
-
-  DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
-  MarkTileDirty(x, y);
-}
+#if 1
+  int graphic;
 
-void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
-                   int frame)
-{
-  Bitmap *src_bitmap;
-  int src_x, src_y;
+  if (!IN_LEV_FIELD(x, y))
+    return;
 
-  getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-  BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
-}
+  graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
 
-void DrawGraphicThruMask(int x, int y, int graphic, int frame)
-{
-#if DEBUG
-  if (!IN_SCR_FIELD(x, y))
-  {
-    printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
-    printf("DrawGraphicThruMask(): This should never happen!\n");
-    return;
-  }
+  DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
+#else
+  DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
 #endif
-
-  DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
-                        frame);
-  MarkTileDirty(x, y);
 }
 
-void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
-                           int frame)
+void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
+                                      int step_frame)
 {
 #if 1
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  GC drawing_gc;
-
-  getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-  drawing_gc = src_bitmap->stored_clip_gc;
+  int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
+  int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
 #else
-  GC drawing_gc = src_bitmap->stored_clip_gc;
-  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
-  int src_x = graphic_info[graphic].src_x;
-  int src_y = graphic_info[graphic].src_y;
-  int offset_x = graphic_info[graphic].offset_x;
-  int offset_y = graphic_info[graphic].offset_y;
-
-  src_x += frame * offset_x;
-  src_y += frame * offset_y;
-
+  int graphic1 = el_act_dir2img(EL_SAND,          ACTION_DIGGING, direction);
+  int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
 #endif
+  int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
+  int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
+  int sx = SCREENX(x), sy = SCREENY(y);
 
-  SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
-  BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
+  DrawGraphic(sx, sy, graphic1, frame1);
+  DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
 }
 
-void DrawMiniGraphic(int x, int y, int graphic)
+void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
 {
-  DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
-  MarkTileDirty(x / 2, y / 2);
-}
-
-void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+  int sx = SCREENX(x), sy = SCREENY(y);
+  static int xy[4][2] =
+  {
+    { 0, -1 },
+    { -1, 0 },
+    { +1, 0 },
+    { 0, +1 }
+  };
+  int i;
+
+  for (i = 0; i < 4; i++)
+  {
+    int xx = x + xy[i][0];
+    int yy = y + xy[i][1];
+    int sxx = sx + xy[i][0];
+    int syy = sy + xy[i][1];
+
+    if (!IN_LEV_FIELD(xx, yy) ||
+       !IN_SCR_FIELD(sxx, syy) ||
+       !GFX_CRUMBLED(Feld[xx][yy]) ||
+       IS_MOVING(xx, yy))
+      continue;
+
+    DrawLevelField(xx, yy);
+  }
+}
+
+static int getBorderElement(int x, int y)
 {
-  struct GraphicInfo *g = &graphic_info[graphic];
-  int mini_startx = 0;
-  int mini_starty = g->bitmap->height * 2 / 3;
+  int border[7][2] =
+  {
+    { EL_STEELWALL_TOPLEFT,            EL_INVISIBLE_STEELWALL_TOPLEFT     },
+    { EL_STEELWALL_TOPRIGHT,           EL_INVISIBLE_STEELWALL_TOPRIGHT    },
+    { EL_STEELWALL_BOTTOMLEFT,         EL_INVISIBLE_STEELWALL_BOTTOMLEFT  },
+    { EL_STEELWALL_BOTTOMRIGHT,                EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
+    { EL_STEELWALL_VERTICAL,           EL_INVISIBLE_STEELWALL_VERTICAL    },
+    { EL_STEELWALL_HORIZONTAL,         EL_INVISIBLE_STEELWALL_HORIZONTAL  },
+    { EL_STEELWALL,                    EL_INVISIBLE_STEELWALL             }
+  };
+  int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
+  int steel_position = (x == -1                && y == -1              ? 0 :
+                       x == lev_fieldx && y == -1              ? 1 :
+                       x == -1         && y == lev_fieldy      ? 2 :
+                       x == lev_fieldx && y == lev_fieldy      ? 3 :
+                       x == -1         || x == lev_fieldx      ? 4 :
+                       y == -1         || y == lev_fieldy      ? 5 : 6);
 
-  *bitmap = g->bitmap;
-  *x = mini_startx + g->src_x / 2;
-  *y = mini_starty + g->src_y / 2;
+  return border[steel_position][steel_type];
 }
 
-void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
+void DrawScreenElement(int x, int y, int element)
 {
-  Bitmap *src_bitmap;
-  int src_x, src_y;
+  DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+  DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
+}
 
-  getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
-  BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
+void DrawLevelElement(int x, int y, int element)
+{
+  if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+    DrawScreenElement(SCREENX(x), SCREENY(y), element);
 }
 
-void DrawGraphicShifted(int x, int y, int dx, int dy, int graphic, int frame,
-                       int cut_mode, int mask_mode)
+void DrawScreenField(int x, int y)
 {
-  Bitmap *src_bitmap;
-  GC drawing_gc;
-  int src_x, src_y;
-  int width = TILEX, height = TILEY;
-  int cx = 0, cy = 0;
-  int dest_x, dest_y;
+  int lx = LEVELX(x), ly = LEVELY(y);
+  int element, content;
 
-  if (graphic < 0)
+  if (!IN_LEV_FIELD(lx, ly))
   {
-    DrawGraphic(x, y, graphic, frame);
+    if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
+      element = EL_EMPTY;
+    else
+      element = getBorderElement(lx, ly);
+
+    DrawScreenElement(x, y, element);
     return;
   }
 
-  if (dx || dy)                        /* shifted graphic */
+  element = Feld[lx][ly];
+  content = Store[lx][ly];
+
+  if (IS_MOVING(lx, ly))
   {
-    if (x < BX1)               /* object enters playfield from the left */
-    {
-      x = BX1;
-      width = dx;
-      cx = TILEX - dx;
-      dx = 0;
-    }
-    else if (x > BX2)          /* object enters playfield from the right */
-    {
-      x = BX2;
-      width = -dx;
-      dx = TILEX + dx;
-    }
-    else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
-    {
-      width += dx;
-      cx = -dx;
-      dx = 0;
-    }
-    else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
-      width -= dx;
-    else if (dx)               /* general horizontal movement */
-      MarkTileDirty(x + SIGN(dx), y);
+    int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
+    boolean cut_mode = NO_CUTTING;
 
-    if (y < BY1)               /* object enters playfield from the top */
-    {
-      if (cut_mode==CUT_BELOW) /* object completely above top border */
-       return;
+    if (element == EL_QUICKSAND_EMPTYING ||
+       element == EL_MAGIC_WALL_EMPTYING ||
+       element == EL_BD_MAGIC_WALL_EMPTYING ||
+       element == EL_AMOEBA_DROPPING)
+      cut_mode = CUT_ABOVE;
+    else if (element == EL_QUICKSAND_FILLING ||
+            element == EL_MAGIC_WALL_FILLING ||
+            element == EL_BD_MAGIC_WALL_FILLING)
+      cut_mode = CUT_BELOW;
 
-      y = BY1;
-      height = dy;
-      cy = TILEY - dy;
-      dy = 0;
-    }
-    else if (y > BY2)          /* object enters playfield from the bottom */
-    {
-      y = BY2;
-      height = -dy;
-      dy = TILEY + dy;
-    }
-    else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
-    {
-      height += dy;
-      cy = -dy;
-      dy = 0;
-    }
-    else if (dy > 0 && cut_mode == CUT_ABOVE)
+    if (cut_mode == CUT_ABOVE)
+      DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
+    else
+      DrawScreenElement(x, y, EL_EMPTY);
+
+    if (horiz_move)
+      DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
+    else if (cut_mode == NO_CUTTING)
+      DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
+    else
+      DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
+
+    if (content == EL_ACID)
     {
-      if (y == BY2)            /* object completely above bottom border */
-       return;
+      int dir = MovDir[lx][ly];
+      int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
+      int newly = ly + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
 
-      height = dy;
-      cy = TILEY - dy;
-      dy = TILEY;
-      MarkTileDirty(x, y + 1);
-    }                          /* object leaves playfield to the bottom */
-    else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
-      height -= dy;
-    else if (dy)               /* general vertical movement */
-      MarkTileDirty(x, y + SIGN(dy));
+      DrawLevelElementThruMask(newlx, newly, EL_ACID);
+    }
   }
+  else if (IS_BLOCKED(lx, ly))
+  {
+    int oldx, oldy;
+    int sx, sy;
+    int horiz_move;
+    boolean cut_mode = NO_CUTTING;
+    int element_old, content_old;
 
-#if 1
-  getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-#else
-  src_bitmap = graphic_info[graphic].bitmap;
-  src_x = graphic_info[graphic].src_x;
-  src_y = graphic_info[graphic].src_y;
-  offset_x = graphic_info[graphic].offset_x;
-  offset_y = graphic_info[graphic].offset_y;
-
-  src_x += frame * offset_x;
-  src_y += frame * offset_y;
-#endif
+    Blocked2Moving(lx, ly, &oldx, &oldy);
+    sx = SCREENX(oldx);
+    sy = SCREENY(oldy);
+    horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
+                 MovDir[oldx][oldy] == MV_RIGHT);
 
-  drawing_gc = src_bitmap->stored_clip_gc;
+    element_old = Feld[oldx][oldy];
+    content_old = Store[oldx][oldy];
 
-  src_x += cx;
-  src_y += cy;
+    if (element_old == EL_QUICKSAND_EMPTYING ||
+       element_old == EL_MAGIC_WALL_EMPTYING ||
+       element_old == EL_BD_MAGIC_WALL_EMPTYING ||
+       element_old == EL_AMOEBA_DROPPING)
+      cut_mode = CUT_ABOVE;
 
-  dest_x = FX + x * TILEX + dx;
-  dest_y = FY + y * TILEY + dy;
+    DrawScreenElement(x, y, EL_EMPTY);
 
-#if DEBUG
-  if (!IN_SCR_FIELD(x,y))
-  {
-    printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
-    printf("DrawGraphicShifted(): This should never happen!\n");
-    return;
+    if (horiz_move)
+      DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
+                              NO_CUTTING);
+    else if (cut_mode == NO_CUTTING)
+      DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
+                              cut_mode);
+    else
+      DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
+                              cut_mode);
   }
-#endif
+  else if (IS_DRAWABLE(element))
+    DrawScreenElement(x, y, element);
+  else
+    DrawScreenElement(x, y, EL_EMPTY);
+}
 
-  if (mask_mode == USE_MASKING)
+void DrawLevelField(int x, int y)
+{
+  if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+    DrawScreenField(SCREENX(x), SCREENY(y));
+  else if (IS_MOVING(x, y))
   {
-    SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
-    BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
-                    dest_x, dest_y);
+    int newx,newy;
+
+    Moving2Blocked(x, y, &newx, &newy);
+    if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
+      DrawScreenField(SCREENX(newx), SCREENY(newy));
   }
-  else
-    BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
-              dest_x, dest_y);
+  else if (IS_BLOCKED(x, y))
+  {
+    int oldx, oldy;
 
-  MarkTileDirty(x, y);
+    Blocked2Moving(x, y, &oldx, &oldy);
+    if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
+      DrawScreenField(SCREENX(oldx), SCREENY(oldy));
+  }
 }
 
-void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
-                               int frame, int cut_mode)
+void DrawMiniElement(int x, int y, int element)
 {
-  DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
+  int graphic;
+
+  graphic = el2edimg(element);
+  DrawMiniGraphic(x, y, graphic);
 }
 
-void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
-                         int cut_mode, int mask_mode)
+void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
 {
-  int lx = LEVELX(x), ly = LEVELY(y);
-  int graphic;
-  int frame;
-
-  if (IN_LEV_FIELD(lx, ly))
-  {
-    SetRandomAnimationValue(lx, ly);
+  int x = sx + scroll_x, y = sy + scroll_y;
 
-    graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
-    frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
-  }
-  else /* border element */
-  {
-    graphic = el2img(element);
-    frame = getGraphicAnimationFrame(graphic, -1);
-  }
-
-  if (element == EL_EXPANDABLE_WALL)
-  {
-    boolean left_stopped = FALSE, right_stopped = FALSE;
-
-    if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
-      left_stopped = TRUE;
-    if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
-      right_stopped = TRUE;
-
-    if (left_stopped && right_stopped)
-      graphic = IMG_WALL;
-    else if (left_stopped)
-    {
-      graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
-      frame = graphic_info[graphic].anim_frames - 1;
-    }
-    else if (right_stopped)
-    {
-      graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
-      frame = graphic_info[graphic].anim_frames - 1;
-    }
-  }
-
-  if (dx || dy)
-    DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
-  else if (mask_mode == USE_MASKING)
-    DrawGraphicThruMask(x, y, graphic, frame);
+  if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
+    DrawMiniElement(sx, sy, EL_EMPTY);
+  else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
+    DrawMiniElement(sx, sy, Feld[x][y]);
   else
-    DrawGraphic(x, y, graphic, frame);
+    DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
 }
 
-void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
-                        int cut_mode, int mask_mode)
+void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
+                           int x, int y, int xsize, int ysize, int font_nr)
 {
-  if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-    DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
-                        cut_mode, mask_mode);
-}
+  int font_width  = getFontWidth(font_nr);
+  int font_height = getFontHeight(font_nr);
+  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int dst_x = SX + startx + x * font_width;
+  int dst_y = SY + starty + y * font_height;
+  int width  = graphic_info[graphic].width;
+  int height = graphic_info[graphic].height;
+  int inner_width  = MAX(width  - 2 * font_width,  font_width);
+  int inner_height = MAX(height - 2 * font_height, font_height);
+  int inner_sx = (width >= 3 * font_width ? font_width : 0);
+  int inner_sy = (height >= 3 * font_height ? font_height : 0);
+  boolean draw_masked = graphic_info[graphic].draw_masked;
 
-void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
-                             int cut_mode)
-{
-  DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
-}
+  getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
 
-void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
-                            int cut_mode)
-{
-  DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
-}
+  if (src_bitmap == NULL || width < font_width || height < font_height)
+  {
+    ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
+    return;
+  }
 
-void DrawLevelElementThruMask(int x, int y, int element)
-{
-  DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
-}
+  src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - font_width  :
+           inner_sx + (x - 1) * font_width  % inner_width);
+  src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
+           inner_sy + (y - 1) * font_height % inner_height);
 
-void DrawLevelFieldThruMask(int x, int y)
-{
-  DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
+  if (draw_masked)
+  {
+    SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+                 dst_x - src_x, dst_y - src_y);
+    BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
+                    dst_x, dst_y);
+  }
+  else
+    BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
+              dst_x, dst_y);
 }
 
-#define TILE_GFX_ELEMENT(x, y)                                             \
-       (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?   \
-        GfxElement[x][y] : Feld[x][y])
-
-static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
+void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
 {
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  int sx = SCREENX(x), sy = SCREENY(y);
-  int element;
-  int width, height, cx, cy, i;
+  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
 #if 1
-  int crumbled_border_size = graphic_info[graphic].border_size;
+  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+  int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
 #else
-  int snip = TILEX / 8;        /* number of border pixels from "crumbled graphic" */
+  boolean draw_masked = graphic_info[graphic].draw_masked;
+  int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
 #endif
-  static int xy[4][2] =
+  boolean ffwd_delay = (tape.playing && tape.fast_forward);
+  boolean no_delay = (tape.warp_forward);
+  unsigned long anim_delay = 0;
+  int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+  int anim_delay_value = (no_delay ? 0 : frame_delay_value);
+  int font_nr = FONT_ENVELOPE_1 + envelope_nr;
+  int font_width = getFontWidth(font_nr);
+  int font_height = getFontHeight(font_nr);
+  int max_xsize = level.envelope_xsize[envelope_nr];
+  int max_ysize = level.envelope_ysize[envelope_nr];
+  int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
+  int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
+  int xend = max_xsize;
+  int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
+  int xstep = (xstart < xend ? 1 : 0);
+  int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
+  int x, y;
+
+  for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
   {
-    { 0, -1 },
-    { -1, 0 },
-    { +1, 0 },
-    { 0, +1 }
-  };
+    int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
+    int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
+    int sx = (SXSIZE - xsize * font_width)  / 2;
+    int sy = (SYSIZE - ysize * font_height) / 2;
+    int xx, yy;
 
-#if 0
-  if (x == 0 && y == 7)
-    printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
-          crumbled_border_size);
-#endif
+    SetDrawtoField(DRAW_BUFFERED);
 
-  if (!IN_LEV_FIELD(x, y))
-    return;
+    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
 
-  element = TILE_GFX_ELEMENT(x, y);
+    SetDrawtoField(DRAW_BACKBUFFER);
 
-  /* crumble field itself */
-  if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
-  {
-    if (!IN_SCR_FIELD(sx, sy))
-      return;
+    for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
+      DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
 
-    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+    DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
+                      level.envelope_text[envelope_nr], font_nr, max_xsize,
+                      xsize - 2, ysize - 2, mask_mode);
 
-    for (i = 0; i < 4; i++)
-    {
-      int xx = x + xy[i][0];
-      int yy = y + xy[i][1];
+    redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+    BackToFront();
 
-#if 1
-      element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
-                BorderElement);
-#else
-      element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
-#endif
+    WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+  }
+}
 
-      /* check if neighbour field is of same type */
-      if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
-       continue;
+void ShowEnvelope(int envelope_nr)
+{
+  int element = EL_ENVELOPE_1 + envelope_nr;
+  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
+  int sound_opening = element_info[element].sound[ACTION_OPENING];
+  int sound_closing = element_info[element].sound[ACTION_CLOSING];
+  boolean ffwd_delay = (tape.playing && tape.fast_forward);
+  boolean no_delay = (tape.warp_forward);
+  int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
+  int wait_delay_value = (no_delay ? 0 : normal_delay_value);
+  int anim_mode = graphic_info[graphic].anim_mode;
+  int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
+                       anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
 
-#if 0
-      if (Feld[x][y] == EL_CUSTOM_START + 123)
-       printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
-              i, Feld[x][y], element,
-              GFX_CRUMBLED(element), IS_MOVING(x, y));
-#endif
+  game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
 
-      if (i == 1 || i == 2)
-      {
-       width = crumbled_border_size;
-       height = TILEY;
-       cx = (i == 2 ? TILEX - crumbled_border_size : 0);
-       cy = 0;
-      }
-      else
-      {
-       width = TILEX;
-       height = crumbled_border_size;
-       cx = 0;
-       cy = (i == 3 ? TILEY - crumbled_border_size : 0);
-      }
+  PlaySoundStereo(sound_opening, SOUND_MIDDLE);
 
-      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-                width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
-    }
+  if (anim_mode == ANIM_DEFAULT)
+    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
 
-    MarkTileDirty(sx, sy);
-  }
-  else         /* crumble neighbour fields */
-  {
-#if 0
-    getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-#endif
+  AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
 
-    for (i = 0; i < 4; i++)
-    {
-      int xx = x + xy[i][0];
-      int yy = y + xy[i][1];
-      int sxx = sx + xy[i][0];
-      int syy = sy + xy[i][1];
+  if (tape.playing)
+    Delay(wait_delay_value);
+  else
+    WaitForEventToContinue();
 
-#if 1
-      if (!IN_LEV_FIELD(xx, yy) ||
-         !IN_SCR_FIELD(sxx, syy) ||
-         IS_MOVING(xx, yy))
-       continue;
+  PlaySoundStereo(sound_closing, SOUND_MIDDLE);
 
-      element = TILE_GFX_ELEMENT(xx, yy);
+  if (anim_mode != ANIM_NONE)
+    AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
 
-      if (!GFX_CRUMBLED(element))
-       continue;
-#else
-      if (!IN_LEV_FIELD(xx, yy) ||
-         !IN_SCR_FIELD(sxx, syy) ||
-         !GFX_CRUMBLED(Feld[xx][yy]) ||
-         IS_MOVING(xx, yy))
-       continue;
-#endif
-
-#if 1
-      graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
-      crumbled_border_size = graphic_info[graphic].border_size;
-
-      getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
-#endif
+  if (anim_mode == ANIM_DEFAULT)
+    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
 
-      if (i == 1 || i == 2)
-      {
-       width = crumbled_border_size;
-       height = TILEY;
-       cx = (i == 1 ? TILEX - crumbled_border_size : 0);
-       cy = 0;
-      }
-      else
-      {
-       width = TILEX;
-       height = crumbled_border_size;
-       cx = 0;
-       cy = (i == 0 ? TILEY - crumbled_border_size : 0);
-      }
+  game.envelope_active = FALSE;
 
-      BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-                width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
+  SetDrawtoField(DRAW_BUFFERED);
 
-      MarkTileDirty(sxx, syy);
-    }
-  }
+  redraw_mask |= REDRAW_FIELD;
+  BackToFront();
 }
 
-void DrawLevelFieldCrumbledSand(int x, int y)
+void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
 {
-#if 1
-  int graphic;
-
-  if (!IN_LEV_FIELD(x, y))
-    return;
-
-  graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
+  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+  int mini_startx = src_bitmap->width * 3 / 4;
+  int mini_starty = src_bitmap->height * 2 / 3;
+  int src_x = mini_startx + graphic_info[graphic].src_x / 8;
+  int src_y = mini_starty + graphic_info[graphic].src_y / 8;
 
-  DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
-#else
-  DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
-#endif
+  *bitmap = src_bitmap;
+  *x = src_x;
+  *y = src_y;
 }
 
-void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
-                                      int step_frame)
+void DrawMicroElement(int xpos, int ypos, int element)
 {
-#if 1
-  int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
-  int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
-#else
-  int graphic1 = el_act_dir2img(EL_SAND,          ACTION_DIGGING, direction);
-  int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
-#endif
-  int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
-  int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
-  int sx = SCREENX(x), sy = SCREENY(y);
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int graphic = el2preimg(element);
 
-  DrawGraphic(sx, sy, graphic1, frame1);
-  DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
+  getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+  BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
+            xpos, ypos);
 }
 
-void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
+void DrawLevel()
 {
-  int sx = SCREENX(x), sy = SCREENY(y);
-  static int xy[4][2] =
-  {
-    { 0, -1 },
-    { -1, 0 },
-    { +1, 0 },
-    { 0, +1 }
-  };
-  int i;
+  int x,y;
 
-  for (i = 0; i < 4; i++)
-  {
-    int xx = x + xy[i][0];
-    int yy = y + xy[i][1];
-    int sxx = sx + xy[i][0];
-    int syy = sy + xy[i][1];
+  SetDrawBackgroundMask(REDRAW_NONE);
+  ClearWindow();
 
-    if (!IN_LEV_FIELD(xx, yy) ||
-       !IN_SCR_FIELD(sxx, syy) ||
-       !GFX_CRUMBLED(Feld[xx][yy]) ||
-       IS_MOVING(xx, yy))
-      continue;
+  for (x = BX1; x <= BX2; x++)
+    for (y = BY1; y <= BY2; y++)
+      DrawScreenField(x, y);
 
-    DrawLevelField(xx, yy);
-  }
+  redraw_mask |= REDRAW_FIELD;
 }
 
-static int getBorderElement(int x, int y)
+void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
 {
-  int border[7][2] =
-  {
-    { EL_STEELWALL_TOPLEFT,            EL_INVISIBLE_STEELWALL_TOPLEFT     },
-    { EL_STEELWALL_TOPRIGHT,           EL_INVISIBLE_STEELWALL_TOPRIGHT    },
-    { EL_STEELWALL_BOTTOMLEFT,         EL_INVISIBLE_STEELWALL_BOTTOMLEFT  },
-    { EL_STEELWALL_BOTTOMRIGHT,                EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
-    { EL_STEELWALL_VERTICAL,           EL_INVISIBLE_STEELWALL_VERTICAL    },
-    { EL_STEELWALL_HORIZONTAL,         EL_INVISIBLE_STEELWALL_HORIZONTAL  },
-    { EL_STEELWALL,                    EL_INVISIBLE_STEELWALL             }
-  };
-  int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
-  int steel_position = (x == -1                && y == -1              ? 0 :
-                       x == lev_fieldx && y == -1              ? 1 :
-                       x == -1         && y == lev_fieldy      ? 2 :
-                       x == lev_fieldx && y == lev_fieldy      ? 3 :
-                       x == -1         || x == lev_fieldx      ? 4 :
-                       y == -1         || y == lev_fieldy      ? 5 : 6);
+  int x,y;
 
-  return border[steel_position][steel_type];
-}
+  for (x = 0; x < size_x; x++)
+    for (y = 0; y < size_y; y++)
+      DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
 
-void DrawScreenElement(int x, int y, int element)
-{
-  DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
-  DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
+  redraw_mask |= REDRAW_FIELD;
 }
 
-void DrawLevelElement(int x, int y, int element)
+static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
 {
-  if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-    DrawScreenElement(SCREENX(x), SCREENY(y), element);
-}
+  int x, y;
 
-void DrawScreenField(int x, int y)
-{
-  int lx = LEVELX(x), ly = LEVELY(y);
-  int element, content;
+  DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
 
-  if (!IN_LEV_FIELD(lx, ly))
+  if (lev_fieldx < STD_LEV_FIELDX)
+    xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
+  if (lev_fieldy < STD_LEV_FIELDY)
+    ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
+
+  xpos += MICRO_TILEX;
+  ypos += MICRO_TILEY;
+
+  for (x = -1; x <= STD_LEV_FIELDX; x++)
   {
-    if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
-      element = EL_EMPTY;
-    else
-      element = getBorderElement(lx, ly);
+    for (y = -1; y <= STD_LEV_FIELDY; y++)
+    {
+      int lx = from_x + x, ly = from_y + y;
 
-    DrawScreenElement(x, y, element);
-    return;
+      if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
+       DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
+                        level.field[lx][ly]);
+      else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
+              && BorderElement != EL_EMPTY)
+       DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
+                        getBorderElement(lx, ly));
+    }
   }
 
-  element = Feld[lx][ly];
-  content = Store[lx][ly];
+  redraw_mask |= REDRAW_MICROLEVEL;
+}
 
-  if (IS_MOVING(lx, ly))
-  {
-    int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
-    boolean cut_mode = NO_CUTTING;
+#define MICROLABEL_EMPTY               0
+#define MICROLABEL_LEVEL_NAME          1
+#define MICROLABEL_LEVEL_AUTHOR_HEAD   2
+#define MICROLABEL_LEVEL_AUTHOR                3
+#define MICROLABEL_IMPORTED_FROM_HEAD  4
+#define MICROLABEL_IMPORTED_FROM       5
+#define MICROLABEL_IMPORTED_BY_HEAD    6
+#define MICROLABEL_IMPORTED_BY         7
 
-    if (element == EL_QUICKSAND_EMPTYING ||
-       element == EL_MAGIC_WALL_EMPTYING ||
-       element == EL_BD_MAGIC_WALL_EMPTYING ||
-       element == EL_AMOEBA_DROPPING)
-      cut_mode = CUT_ABOVE;
-    else if (element == EL_QUICKSAND_FILLING ||
-            element == EL_MAGIC_WALL_FILLING ||
-            element == EL_BD_MAGIC_WALL_FILLING)
-      cut_mode = CUT_BELOW;
+static void DrawMicroLevelLabelExt(int mode)
+{
+  char label_text[MAX_OUTPUT_LINESIZE + 1];
+  int max_len_label_text;
+  int font_nr = FONT_TEXT_2;
+  int i;
 
-    if (cut_mode == CUT_ABOVE)
-      DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
-    else
-      DrawScreenElement(x, y, EL_EMPTY);
+  if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
+      mode == MICROLABEL_IMPORTED_FROM_HEAD ||
+      mode == MICROLABEL_IMPORTED_BY_HEAD)
+    font_nr = FONT_TEXT_3;
 
-    if (horiz_move)
-      DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
-    else if (cut_mode == NO_CUTTING)
-      DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
-    else
-      DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
+  max_len_label_text = SXSIZE / getFontWidth(font_nr);
 
-    if (content == EL_ACID)
-    {
-      int dir = MovDir[lx][ly];
-      int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
-      int newly = ly + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
+#if 1
 
-      DrawLevelElementThruMask(newlx, newly, EL_ACID);
-    }
-  }
-  else if (IS_BLOCKED(lx, ly))
+  for (i = 0; i < max_len_label_text; i++)
+    label_text[i] = ' ';
+  label_text[max_len_label_text] = '\0';
+
+  if (strlen(label_text) > 0)
   {
-    int oldx, oldy;
-    int sx, sy;
-    int horiz_move;
-    boolean cut_mode = NO_CUTTING;
-    int element_old, content_old;
+    int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
+    int lypos = MICROLABEL2_YPOS;
 
-    Blocked2Moving(lx, ly, &oldx, &oldy);
-    sx = SCREENX(oldx);
-    sy = SCREENY(oldy);
-    horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
-                 MovDir[oldx][oldy] == MV_RIGHT);
+    DrawText(lxpos, lypos, label_text, font_nr);
+  }
 
-    element_old = Feld[oldx][oldy];
-    content_old = Store[oldx][oldy];
+#else
 
-    if (element_old == EL_QUICKSAND_EMPTYING ||
-       element_old == EL_MAGIC_WALL_EMPTYING ||
-       element_old == EL_BD_MAGIC_WALL_EMPTYING ||
-       element_old == EL_AMOEBA_DROPPING)
-      cut_mode = CUT_ABOVE;
+  DrawBackground(SX, MICROLABEL2_YPOS, SXSIZE, getFontHeight(font_nr));
 
-    DrawScreenElement(x, y, EL_EMPTY);
+#endif
 
-    if (horiz_move)
-      DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
-                              NO_CUTTING);
-    else if (cut_mode == NO_CUTTING)
-      DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
-                              cut_mode);
-    else
-      DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
-                              cut_mode);
+  strncpy(label_text,
+         (mode == MICROLABEL_LEVEL_NAME ? level.name :
+          mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
+          mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
+          mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
+          mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
+          mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
+          mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
+         max_len_label_text);
+  label_text[max_len_label_text] = '\0';
+
+  if (strlen(label_text) > 0)
+  {
+    int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
+    int lypos = MICROLABEL2_YPOS;
+
+    DrawText(lxpos, lypos, label_text, font_nr);
   }
-  else if (IS_DRAWABLE(element))
-    DrawScreenElement(x, y, element);
-  else
-    DrawScreenElement(x, y, EL_EMPTY);
+
+  redraw_mask |= REDRAW_MICROLEVEL;
 }
 
-void DrawLevelField(int x, int y)
+void DrawMicroLevel(int xpos, int ypos, boolean restart)
 {
-  if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-    DrawScreenField(SCREENX(x), SCREENY(y));
-  else if (IS_MOVING(x, y))
+  static unsigned long scroll_delay = 0;
+  static unsigned long label_delay = 0;
+  static int from_x, from_y, scroll_direction;
+  static int label_state, label_counter;
+  int last_game_status = game_status;  /* save current game status */
+
+  /* force PREVIEW font on preview level */
+  game_status = GAME_MODE_PSEUDO_PREVIEW;
+
+  if (restart)
   {
-    int newx,newy;
+    from_x = from_y = 0;
+    scroll_direction = MV_RIGHT;
+    label_state = 1;
+    label_counter = 0;
 
-    Moving2Blocked(x, y, &newx, &newy);
-    if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
-      DrawScreenField(SCREENX(newx), SCREENY(newy));
+    DrawMicroLevelExt(xpos, ypos, from_x, from_y);
+    DrawMicroLevelLabelExt(label_state);
+
+    /* initialize delay counters */
+    DelayReached(&scroll_delay, 0);
+    DelayReached(&label_delay, 0);
+
+    if (leveldir_current->name)
+    {
+      char label_text[MAX_OUTPUT_LINESIZE + 1];
+      int font_nr = FONT_TEXT_1;
+      int max_len_label_text = SXSIZE / getFontWidth(font_nr);
+      int lxpos, lypos;
+
+      strncpy(label_text, leveldir_current->name, max_len_label_text);
+      label_text[max_len_label_text] = '\0';
+
+      lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
+      lypos = SY + MICROLABEL1_YPOS;
+
+      DrawText(lxpos, lypos, label_text, font_nr);
+    }
+
+    game_status = last_game_status;    /* restore current game status */
+
+    return;
   }
-  else if (IS_BLOCKED(x, y))
+
+  /* scroll micro level, if needed */
+  if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
+      DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
   {
-    int oldx, oldy;
+    switch (scroll_direction)
+    {
+      case MV_LEFT:
+       if (from_x > 0)
+         from_x--;
+       else
+         scroll_direction = MV_UP;
+       break;
 
-    Blocked2Moving(x, y, &oldx, &oldy);
-    if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
-      DrawScreenField(SCREENX(oldx), SCREENY(oldy));
+      case MV_RIGHT:
+       if (from_x < lev_fieldx - STD_LEV_FIELDX)
+         from_x++;
+       else
+         scroll_direction = MV_DOWN;
+       break;
+
+      case MV_UP:
+       if (from_y > 0)
+         from_y--;
+       else
+         scroll_direction = MV_RIGHT;
+       break;
+
+      case MV_DOWN:
+       if (from_y < lev_fieldy - STD_LEV_FIELDY)
+         from_y++;
+       else
+         scroll_direction = MV_LEFT;
+       break;
+
+      default:
+       break;
+    }
+
+    DrawMicroLevelExt(xpos, ypos, from_x, from_y);
   }
-}
 
-void DrawMiniElement(int x, int y, int element)
-{
-  int graphic;
+  /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
+  /* redraw micro level label, if needed */
+  if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
+      strcmp(level.author, ANONYMOUS_NAME) != 0 &&
+      strcmp(level.author, leveldir_current->name) != 0 &&
+      DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
+  {
+    int max_label_counter = 23;
 
-  graphic = el2edimg(element);
-  DrawMiniGraphic(x, y, graphic);
+    if (leveldir_current->imported_from != NULL &&
+       strlen(leveldir_current->imported_from) > 0)
+      max_label_counter += 14;
+    if (leveldir_current->imported_by != NULL &&
+       strlen(leveldir_current->imported_by) > 0)
+      max_label_counter += 14;
+
+    label_counter = (label_counter + 1) % max_label_counter;
+    label_state = (label_counter >= 0 && label_counter <= 7 ?
+                  MICROLABEL_LEVEL_NAME :
+                  label_counter >= 9 && label_counter <= 12 ?
+                  MICROLABEL_LEVEL_AUTHOR_HEAD :
+                  label_counter >= 14 && label_counter <= 21 ?
+                  MICROLABEL_LEVEL_AUTHOR :
+                  label_counter >= 23 && label_counter <= 26 ?
+                  MICROLABEL_IMPORTED_FROM_HEAD :
+                  label_counter >= 28 && label_counter <= 35 ?
+                  MICROLABEL_IMPORTED_FROM :
+                  label_counter >= 37 && label_counter <= 40 ?
+                  MICROLABEL_IMPORTED_BY_HEAD :
+                  label_counter >= 42 && label_counter <= 49 ?
+                  MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
+
+    if (leveldir_current->imported_from == NULL &&
+       (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
+        label_state == MICROLABEL_IMPORTED_FROM))
+      label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
+                    MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
+
+    DrawMicroLevelLabelExt(label_state);
+  }
+
+  game_status = last_game_status;      /* restore current game status */
 }
 
-void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
+inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+                                   int graphic, int sync_frame, int mask_mode)
 {
-  int x = sx + scroll_x, y = sy + scroll_y;
+  int frame = getGraphicAnimationFrame(graphic, sync_frame);
 
-  if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
-    DrawMiniElement(sx, sy, EL_EMPTY);
-  else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
-    DrawMiniElement(sx, sy, Feld[x][y]);
+  if (mask_mode == USE_MASKING)
+    DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
   else
-    DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
+    DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
 }
 
-void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
-                           int x, int y, int xsize, int ysize, int font_nr)
+inline void DrawGraphicAnimation(int x, int y, int graphic)
 {
-  int font_width  = getFontWidth(font_nr);
-  int font_height = getFontHeight(font_nr);
-  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  int dst_x = SX + startx + x * font_width;
-  int dst_y = SY + starty + y * font_height;
-  int width  = graphic_info[graphic].width;
-  int height = graphic_info[graphic].height;
-  int inner_width  = MAX(width  - 2 * font_width,  font_width);
-  int inner_height = MAX(height - 2 * font_height, font_height);
-  int inner_sx = (width >= 3 * font_width ? font_width : 0);
-  int inner_sy = (height >= 3 * font_height ? font_height : 0);
-  boolean draw_masked = graphic_info[graphic].draw_masked;
-
-  getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+  int lx = LEVELX(x), ly = LEVELY(y);
 
-  if (src_bitmap == NULL || width < font_width || height < font_height)
-  {
-    ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
+  if (!IN_SCR_FIELD(x, y))
     return;
-  }
 
-  src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - font_width  :
-           inner_sx + (x - 1) * font_width  % inner_width);
-  src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
-           inner_sy + (y - 1) * font_height % inner_height);
+  DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+                         graphic, GfxFrame[lx][ly], NO_MASKING);
+  MarkTileDirty(x, y);
+}
 
-  if (draw_masked)
-  {
-    SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
-                 dst_x - src_x, dst_y - src_y);
-    BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
-                    dst_x, dst_y);
-  }
-  else
-    BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
-              dst_x, dst_y);
+void DrawLevelGraphicAnimation(int x, int y, int graphic)
+{
+  DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
 }
 
-void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
+void DrawLevelElementAnimation(int x, int y, int element)
 {
-  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
 #if 1
-  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
-  int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+  int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+
+  DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
 #else
-  boolean draw_masked = graphic_info[graphic].draw_masked;
-  int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+  DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
 #endif
-  boolean ffwd_delay = (tape.playing && tape.fast_forward);
-  boolean no_delay = (tape.warp_forward);
-  unsigned long anim_delay = 0;
-  int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
-  int anim_delay_value = (no_delay ? 0 : frame_delay_value);
-  int font_nr = FONT_ENVELOPE_1 + envelope_nr;
-  int font_width = getFontWidth(font_nr);
-  int font_height = getFontHeight(font_nr);
-  int max_xsize = level.envelope_xsize[envelope_nr];
-  int max_ysize = level.envelope_ysize[envelope_nr];
-  int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
-  int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
-  int xend = max_xsize;
-  int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
-  int xstep = (xstart < xend ? 1 : 0);
-  int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
-  int x, y;
-
-  for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
-  {
-    int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
-    int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
-    int sx = (SXSIZE - xsize * font_width)  / 2;
-    int sy = (SYSIZE - ysize * font_height) / 2;
-    int xx, yy;
-
-    SetDrawtoField(DRAW_BUFFERED);
-
-    BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+}
 
-    SetDrawtoField(DRAW_BACKBUFFER);
+inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+{
+  int sx = SCREENX(x), sy = SCREENY(y);
 
-    for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
-      DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
+  if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
+    return;
 
-    DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
-                      level.envelope_text[envelope_nr], font_nr, max_xsize,
-                      xsize - 2, ysize - 2, mask_mode);
+  if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+    return;
 
-    redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
-    BackToFront();
+  DrawGraphicAnimation(sx, sy, graphic);
 
-    WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
-  }
+  if (GFX_CRUMBLED(Feld[x][y]))
+    DrawLevelFieldCrumbledSand(x, y);
 }
 
-void ShowEnvelope(int envelope_nr)
+void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
 {
-  int element = EL_ENVELOPE_1 + envelope_nr;
-  int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
-  int sound_opening = element_info[element].sound[ACTION_OPENING];
-  int sound_closing = element_info[element].sound[ACTION_CLOSING];
-  boolean ffwd_delay = (tape.playing && tape.fast_forward);
-  boolean no_delay = (tape.warp_forward);
-  int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
-  int wait_delay_value = (no_delay ? 0 : normal_delay_value);
-  int anim_mode = graphic_info[graphic].anim_mode;
-  int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
-                       anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
-
-  game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+  int sx = SCREENX(x), sy = SCREENY(y);
+  int graphic;
 
-  PlaySoundStereo(sound_opening, SOUND_MIDDLE);
+  if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
+    return;
 
-  if (anim_mode == ANIM_DEFAULT)
-    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
+  graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
 
-  AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
+  if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+    return;
 
-  if (tape.playing)
-    Delay(wait_delay_value);
-  else
-    WaitForEventToContinue();
+  DrawGraphicAnimation(sx, sy, graphic);
 
-  PlaySoundStereo(sound_closing, SOUND_MIDDLE);
+  if (GFX_CRUMBLED(element))
+    DrawLevelFieldCrumbledSand(x, y);
+}
 
-  if (anim_mode != ANIM_NONE)
-    AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
+static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
+{
+  if (player->use_murphy_graphic)
+  {
+    /* this works only because currently only one player can be "murphy" ... */
+    static int last_horizontal_dir = MV_LEFT;
+    int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
 
-  if (anim_mode == ANIM_DEFAULT)
-    AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      last_horizontal_dir = move_dir;
 
-  game.envelope_active = FALSE;
+    if (graphic == IMG_SP_MURPHY)      /* undefined => use special graphic */
+    {
+      int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
 
-  SetDrawtoField(DRAW_BUFFERED);
+      graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
+    }
 
-  redraw_mask |= REDRAW_FIELD;
-  BackToFront();
+    return graphic;
+  }
+  else
+    return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
 }
 
-void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+static boolean equalGraphics(int graphic1, int graphic2)
 {
-  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
-  int mini_startx = src_bitmap->width * 3 / 4;
-  int mini_starty = src_bitmap->height * 2 / 3;
-  int src_x = mini_startx + graphic_info[graphic].src_x / 8;
-  int src_y = mini_starty + graphic_info[graphic].src_y / 8;
+  struct GraphicInfo *g1 = &graphic_info[graphic1];
+  struct GraphicInfo *g2 = &graphic_info[graphic2];
 
-  *bitmap = src_bitmap;
-  *x = src_x;
-  *y = src_y;
+  return (g1->bitmap      == g2->bitmap &&
+         g1->src_x       == g2->src_x &&
+         g1->src_y       == g2->src_y &&
+         g1->anim_frames == g2->anim_frames &&
+         g1->anim_delay  == g2->anim_delay &&
+         g1->anim_mode   == g2->anim_mode);
 }
 
-void DrawMicroElement(int xpos, int ypos, int element)
+void DrawAllPlayers()
 {
-  Bitmap *src_bitmap;
-  int src_x, src_y;
-  int graphic = el2preimg(element);
+  int i;
 
-  getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
-  BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
-            xpos, ypos);
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (stored_player[i].active)
+      DrawPlayer(&stored_player[i]);
 }
 
-void DrawLevel()
+void DrawPlayerField(int x, int y)
 {
-  int x,y;
-
-  SetDrawBackgroundMask(REDRAW_NONE);
-  ClearWindow();
-
-  for (x = BX1; x <= BX2; x++)
-    for (y = BY1; y <= BY2; y++)
-      DrawScreenField(x, y);
+  if (!IS_PLAYER(x, y))
+    return;
 
-  redraw_mask |= REDRAW_FIELD;
+  DrawPlayer(PLAYERINFO(x, y));
 }
 
-void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
+void DrawPlayer(struct PlayerInfo *player)
 {
-  int x,y;
+  int jx = player->jx;
+  int jy = player->jy;
+  int move_dir = player->MovDir;
+#if 0
+  int last_jx = player->last_jx;
+  int last_jy = player->last_jy;
+  int next_jx = jx + (jx - last_jx);
+  int next_jy = jy + (jy - last_jy);
+  boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
+#else
+  int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
+  int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? +1 : 0);
+  int last_jx = (player->is_moving ? jx - dx : jx);
+  int last_jy = (player->is_moving ? jy - dy : jy);
+  int next_jx = jx + dx;
+  int next_jy = jy + dy;
+  boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
+#endif
+  int sx = SCREENX(jx), sy = SCREENY(jy);
+  int sxx = 0, syy = 0;
+  int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
+  int graphic;
+  int action = ACTION_DEFAULT;
+  int last_player_graphic = getPlayerGraphic(player, move_dir);
+  int last_player_frame = player->Frame;
+  int frame = 0;
 
-  for (x = 0; x < size_x; x++)
-    for (y = 0; y < size_y; y++)
-      DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
+  if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
+    return;
 
-  redraw_mask |= REDRAW_FIELD;
-}
+#if DEBUG
+  if (!IN_LEV_FIELD(jx, jy))
+  {
+    printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
+    printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
+    printf("DrawPlayerField(): This should never happen!\n");
+    return;
+  }
+#endif
 
-static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
-{
-  int x, y;
+  if (element == EL_EXPLOSION)
+    return;
 
-  DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
+  action = (player->is_pushing    ? ACTION_PUSHING         :
+           player->is_digging    ? ACTION_DIGGING         :
+           player->is_collecting ? ACTION_COLLECTING      :
+           player->is_moving     ? ACTION_MOVING          :
+           player->is_snapping   ? ACTION_SNAPPING        :
+           player->is_dropping   ? ACTION_DROPPING        :
+           player->is_waiting    ? player->action_waiting : ACTION_DEFAULT);
 
-  if (lev_fieldx < STD_LEV_FIELDX)
-    xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
-  if (lev_fieldy < STD_LEV_FIELDY)
-    ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
+  InitPlayerGfxAnimation(player, action, move_dir);
 
-  xpos += MICRO_TILEX;
-  ypos += MICRO_TILEY;
+  /* ----------------------------------------------------------------------- */
+  /* draw things in the field the player is leaving, if needed               */
+  /* ----------------------------------------------------------------------- */
 
-  for (x = -1; x <= STD_LEV_FIELDX; x++)
+#if 1
+  if (player->is_moving)
+#else
+  if (player_is_moving)
+#endif
   {
-    for (y = -1; y <= STD_LEV_FIELDY; y++)
+    if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
     {
-      int lx = from_x + x, ly = from_y + y;
+      DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
 
-      if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
-       DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
-                        level.field[lx][ly]);
-      else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
-              && BorderElement != EL_EMPTY)
-       DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
-                        getBorderElement(lx, ly));
+      if (last_element == EL_DYNAMITE_ACTIVE ||
+         last_element == EL_SP_DISK_RED_ACTIVE)
+       DrawDynamite(last_jx, last_jy);
+      else
+       DrawLevelFieldThruMask(last_jx, last_jy);
     }
+    else if (last_element == EL_DYNAMITE_ACTIVE ||
+            last_element == EL_SP_DISK_RED_ACTIVE)
+      DrawDynamite(last_jx, last_jy);
+    else
+      DrawLevelField(last_jx, last_jy);
+
+    if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
+      DrawLevelElement(next_jx, next_jy, EL_EMPTY);
   }
 
-  redraw_mask |= REDRAW_MICROLEVEL;
-}
+  if (!IN_SCR_FIELD(sx, sy))
+    return;
 
-#define MICROLABEL_EMPTY               0
-#define MICROLABEL_LEVEL_NAME          1
-#define MICROLABEL_CREATED_BY          2
-#define MICROLABEL_LEVEL_AUTHOR                3
-#define MICROLABEL_IMPORTED_FROM       4
-#define MICROLABEL_LEVEL_IMPORT_INFO   5
+  if (setup.direct_draw)
+    SetDrawtoField(DRAW_BUFFERED);
 
-static void DrawMicroLevelLabelExt(int mode)
-{
-  char label_text[MAX_OUTPUT_LINESIZE + 1];
-  int max_len_label_text;
-  int font_nr = FONT_TEXT_2;
+  /* ----------------------------------------------------------------------- */
+  /* draw things behind the player, if needed                                */
+  /* ----------------------------------------------------------------------- */
 
-  if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
-    font_nr = FONT_TEXT_3;
+  if (Back[jx][jy])
+    DrawLevelElement(jx, jy, Back[jx][jy]);
+  else if (IS_ACTIVE_BOMB(element))
+    DrawLevelElement(jx, jy, EL_EMPTY);
+  else
+  {
+    if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
+    {
+      if (GFX_CRUMBLED(GfxElement[jx][jy]))
+       DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
+      else
+      {
+       int old_element = GfxElement[jx][jy];
+       int old_graphic = el_act_dir2img(old_element, action, move_dir);
+       int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
 
-  max_len_label_text = SXSIZE / getFontWidth(font_nr);
+       DrawGraphic(sx, sy, old_graphic, frame);
+      }
+    }
+    else
+    {
+      GfxElement[jx][jy] = EL_UNDEFINED;
 
-  DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
+      DrawLevelField(jx, jy);
+    }
+  }
 
-  strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
-                      mode == MICROLABEL_CREATED_BY ? "created by" :
-                      mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
-                      mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
-                      mode == MICROLABEL_LEVEL_IMPORT_INFO ?
-                      leveldir_current->imported_from : ""),
-         max_len_label_text);
-  label_text[max_len_label_text] = '\0';
+  /* ----------------------------------------------------------------------- */
+  /* draw player himself                                                     */
+  /* ----------------------------------------------------------------------- */
 
-  if (strlen(label_text) > 0)
-  {
-    int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
-    int lypos = MICROLABEL_YPOS;
+#if 1
 
-    DrawText(lxpos, lypos, label_text, font_nr);
-  }
-
-  redraw_mask |= REDRAW_MICROLEVEL;
-}
+  graphic = getPlayerGraphic(player, move_dir);
 
-void DrawMicroLevel(int xpos, int ypos, boolean restart)
-{
-  static unsigned long scroll_delay = 0;
-  static unsigned long label_delay = 0;
-  static int from_x, from_y, scroll_direction;
-  static int label_state, label_counter;
-  int last_game_status = game_status;  /* save current game status */
+  /* in the case of changed player action or direction, prevent the current
+     animation frame from being restarted for identical animations */
+  if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+    player->Frame = last_player_frame;
 
-  /* force PREVIEW font on preview level */
-  game_status = GAME_MODE_PSEUDO_PREVIEW;
+#else
 
-  if (restart)
+  if (player->use_murphy_graphic)
   {
-    from_x = from_y = 0;
-    scroll_direction = MV_RIGHT;
-    label_state = 1;
-    label_counter = 0;
+    static int last_horizontal_dir = MV_LEFT;
 
-    DrawMicroLevelExt(xpos, ypos, from_x, from_y);
-    DrawMicroLevelLabelExt(label_state);
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      last_horizontal_dir = move_dir;
 
-    /* initialize delay counters */
-    DelayReached(&scroll_delay, 0);
-    DelayReached(&label_delay, 0);
+    graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
 
-    if (leveldir_current->name)
+    if (graphic == IMG_SP_MURPHY)      /* undefined => use special graphic */
     {
-      int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
-      int lxpos = SX + (SXSIZE - text_width) / 2;
-      int lypos = SY + 352;
+      int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
 
-      DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
+      graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
     }
+  }
+  else
+    graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
 
-    game_status = last_game_status;    /* restore current game status */
+#endif
 
-    return;
+  frame = getGraphicAnimationFrame(graphic, player->Frame);
+
+  if (player->GfxPos)
+  {
+    if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+      sxx = player->GfxPos;
+    else
+      syy = player->GfxPos;
   }
 
-  /* scroll micro level, if needed */
-  if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
-      DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
+  if (!setup.soft_scrolling && ScreenMovPos)
+    sxx = syy = 0;
+
+  DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+
+  if (SHIELD_ON(player))
   {
-    switch (scroll_direction)
-    {
-      case MV_LEFT:
-       if (from_x > 0)
-         from_x--;
-       else
-         scroll_direction = MV_UP;
-       break;
+    int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+                  IMG_SHIELD_NORMAL_ACTIVE);
+    int frame = getGraphicAnimationFrame(graphic, -1);
 
-      case MV_RIGHT:
-       if (from_x < lev_fieldx - STD_LEV_FIELDX)
-         from_x++;
-       else
-         scroll_direction = MV_DOWN;
-       break;
+    DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+  }
 
-      case MV_UP:
-       if (from_y > 0)
-         from_y--;
-       else
-         scroll_direction = MV_RIGHT;
-       break;
+  /* ----------------------------------------------------------------------- */
+  /* draw things the player is pushing, if needed                            */
+  /* ----------------------------------------------------------------------- */
 
-      case MV_DOWN:
-       if (from_y < lev_fieldy - STD_LEV_FIELDY)
-         from_y++;
-       else
-         scroll_direction = MV_LEFT;
-       break;
+#if 0
+  printf("::: %d, %d [%d, %d] [%d]\n",
+        player->is_pushing, player_is_moving, player->GfxAction,
+        player->is_moving, player_is_moving);
+#endif
 
-      default:
-       break;
+#if 1
+  if (player->is_pushing && player->is_moving)
+#else
+  if (player->is_pushing && player_is_moving)
+#endif
+  {
+#if 1
+    int px = SCREENX(jx), py = SCREENY(jy);
+    int pxx = (TILEX - ABS(sxx)) * dx;
+    int pyy = (TILEY - ABS(syy)) * dy;
+#else
+    int px = SCREENX(next_jx), py = SCREENY(next_jy);
+    int pxx = sxx;
+    int pyy = syy;
+#endif
+
+#if 1
+    int graphic;
+    int frame;
+
+    if (!IS_MOVING(jx, jy))            /* push movement already finished */
+      element = Feld[next_jx][next_jy];
+
+    graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+    frame = getGraphicAnimationFrame(graphic, player->StepFrame);
+
+    /* draw background element under pushed element (like the Sokoban field) */
+    if (Back[next_jx][next_jy])
+      DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+
+    /* masked drawing is needed for EMC style (double) movement graphics */
+    DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
+
+#else
+    if (Back[next_jx][next_jy])
+      DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+
+    if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
+      DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
+                                NO_CUTTING);
+    else
+    {
+      int element = MovingOrBlocked2Element(next_jx, next_jy);
+      int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+#if 1
+      int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
+#else
+      int frame = getGraphicAnimationFrame(graphic, player->Frame);
+#endif
+
+#if 1
+      /* masked drawing is needed for EMC style (double) movement graphics */
+      DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
+                                NO_CUTTING);
+#else
+      DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
+                        NO_CUTTING, NO_MASKING);
+#endif
     }
+#endif
+  }
 
-    DrawMicroLevelExt(xpos, ypos, from_x, from_y);
+  /* ----------------------------------------------------------------------- */
+  /* draw things in front of player (active dynamite or dynabombs)           */
+  /* ----------------------------------------------------------------------- */
+
+  if (IS_ACTIVE_BOMB(element))
+  {
+    graphic = el2img(element);
+    frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+
+    if (game.emulation == EMU_SUPAPLEX)
+      DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
+    else
+      DrawGraphicThruMask(sx, sy, graphic, frame);
   }
 
-  /* redraw micro level label, if needed */
-  if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
-      strcmp(level.author, ANONYMOUS_NAME) != 0 &&
-      strcmp(level.author, leveldir_current->name) != 0 &&
-      DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
+  if (player_is_moving && last_element == EL_EXPLOSION)
   {
-    int max_label_counter = 23;
+    int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
+    int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
+    int phase = ExplodePhase[last_jx][last_jy] - 1;
+    int frame = getGraphicAnimationFrame(graphic, phase - delay);
 
-    if (leveldir_current->imported_from != NULL)
-      max_label_counter += 14;
+    if (phase >= delay)
+      DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
+  }
 
-    label_counter = (label_counter + 1) % max_label_counter;
-    label_state = (label_counter >= 0 && label_counter <= 7 ?
-                  MICROLABEL_LEVEL_NAME :
-                  label_counter >= 9 && label_counter <= 12 ?
-                  MICROLABEL_CREATED_BY :
-                  label_counter >= 14 && label_counter <= 21 ?
-                  MICROLABEL_LEVEL_AUTHOR :
-                  label_counter >= 23 && label_counter <= 26 ?
-                  MICROLABEL_IMPORTED_FROM :
-                  label_counter >= 28 && label_counter <= 35 ?
-                  MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
-    DrawMicroLevelLabelExt(label_state);
+  /* ----------------------------------------------------------------------- */
+  /* draw elements the player is just walking/passing through/under          */
+  /* ----------------------------------------------------------------------- */
+
+  if (player_is_moving)
+  {
+    /* handle the field the player is leaving ... */
+    if (IS_ACCESSIBLE_INSIDE(last_element))
+      DrawLevelField(last_jx, last_jy);
+    else if (IS_ACCESSIBLE_UNDER(last_element))
+      DrawLevelFieldThruMask(last_jx, last_jy);
   }
 
-  game_status = last_game_status;      /* restore current game status */
+#if 1
+  /* do not redraw accessible elements if the player is just pushing them */
+  if (!player_is_moving || !player->is_pushing)
+  {
+    /* ... and the field the player is entering */
+    if (IS_ACCESSIBLE_INSIDE(element))
+      DrawLevelField(jx, jy);
+    else if (IS_ACCESSIBLE_UNDER(element))
+      DrawLevelFieldThruMask(jx, jy);
+  }
+
+#else
+
+#if 0
+  /* !!! I have forgotton what this should be good for !!! */
+  /* !!! causes player being visible when pushing from within tubes !!! */
+  if (!player->is_pushing)
+#endif
+  {
+    /* ... and the field the player is entering */
+    if (IS_ACCESSIBLE_INSIDE(element))
+      DrawLevelField(jx, jy);
+    else if (IS_ACCESSIBLE_UNDER(element))
+      DrawLevelFieldThruMask(jx, jy);
+  }
+#endif
+
+  if (setup.direct_draw)
+  {
+    int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
+    int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
+    int x_size = TILEX * (1 + ABS(jx - last_jx));
+    int y_size = TILEY * (1 + ABS(jy - last_jy));
+
+    BlitBitmap(drawto_field, window,
+              dst_x, dst_y, x_size, y_size, dst_x, dst_y);
+    SetDrawtoField(DRAW_DIRECT);
+  }
+
+  MarkTileDirty(sx, sy);
 }
 
+/* ------------------------------------------------------------------------- */
+
 void WaitForEventToContinue()
 {
   boolean still_wait = TRUE;
@@ -2102,6 +2272,12 @@ boolean Request(char *text, unsigned int req_state)
     }
   }
 
+#if 1
+  if (game_status == GAME_MODE_PLAYING &&
+      level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    BlitScreenToBitmap_EM(backbuffer);
+#endif
+
 #if 1
   /* disable deactivated drawing when quick-loading level tape recording */
   if (tape.playing && tape.deactivate_display)
@@ -2116,7 +2292,7 @@ boolean Request(char *text, unsigned int req_state)
   /* pause network game while waiting for request to answer */
   if (options.network &&
       game_status == GAME_MODE_PLAYING &&
-      req_state & REQUEST_WAIT_FOR)
+      req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_PausePlaying();
 #endif
 
@@ -2128,12 +2304,15 @@ boolean Request(char *text, unsigned int req_state)
 
   UnmapAllGadgets();
 
-  CloseDoor(DOOR_CLOSE_1);
+  if (old_door_state & DOOR_OPEN_1)
+  {
+    CloseDoor(DOOR_CLOSE_1);
 
-  /* save old door content */
-  BlitBitmap(bitmap_db_door, bitmap_db_door,
-            DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-            DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+    /* save old door content */
+    BlitBitmap(bitmap_db_door, bitmap_db_door,
+              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
+  }
 
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
@@ -2206,7 +2385,7 @@ boolean Request(char *text, unsigned int req_state)
   ClearEventQueue();
 #endif
 
-  if (!(req_state & REQUEST_WAIT_FOR))
+  if (!(req_state & REQUEST_WAIT_FOR_INPUT))
   {
     SetDrawBackgroundMask(REDRAW_FIELD);
 
@@ -2350,13 +2529,9 @@ boolean Request(char *text, unsigned int req_state)
   {
     CloseDoor(DOOR_CLOSE_1);
 
-    if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
-    {
-      BlitBitmap(bitmap_db_door, bitmap_db_door,
-                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
-                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-      OpenDoor(DOOR_OPEN_1);
-    }
+    if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
+       (req_state & REQ_REOPEN))
+      OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
   }
 
   RemapAllGadgets();
@@ -2367,7 +2542,7 @@ boolean Request(char *text, unsigned int req_state)
   /* continue network game after request */
   if (options.network &&
       game_status == GAME_MODE_PLAYING &&
-      req_state & REQUEST_WAIT_FOR)
+      req_state & REQUEST_WAIT_FOR_INPUT)
     SendToServer_ContinuePlaying();
 #endif
 
@@ -2382,33 +2557,42 @@ boolean Request(char *text, unsigned int req_state)
 
 unsigned int OpenDoor(unsigned int door_state)
 {
-  unsigned int new_door_state;
-
   if (door_state & DOOR_COPY_BACK)
   {
-    BlitBitmap(bitmap_db_door, bitmap_db_door,
-              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
-              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+    if (door_state & DOOR_OPEN_1)
+      BlitBitmap(bitmap_db_door, bitmap_db_door,
+                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
+                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+    if (door_state & DOOR_OPEN_2)
+      BlitBitmap(bitmap_db_door, bitmap_db_door,
+                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
+                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+
     door_state &= ~DOOR_COPY_BACK;
   }
 
-  new_door_state = MoveDoor(door_state);
-
-  return(new_door_state);
+  return MoveDoor(door_state);
 }
 
 unsigned int CloseDoor(unsigned int door_state)
 {
-  unsigned int new_door_state;
+  unsigned int old_door_state = GetDoorState();
 
-  BlitBitmap(backbuffer, bitmap_db_door,
-            DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
-  BlitBitmap(backbuffer, bitmap_db_door,
-            VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
+  if (!(door_state & DOOR_NO_COPY_BACK))
+  {
+    if (old_door_state & DOOR_OPEN_1)
+      BlitBitmap(backbuffer, bitmap_db_door,
+                DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+    if (old_door_state & DOOR_OPEN_2)
+      BlitBitmap(backbuffer, bitmap_db_door,
+                VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
 
-  new_door_state = MoveDoor(door_state);
+    door_state &= ~DOOR_NO_COPY_BACK;
+  }
 
-  return(new_door_state);
+  return MoveDoor(door_state);
 }
 
 unsigned int GetDoorState()
@@ -2503,7 +2687,7 @@ unsigned int MoveDoor(unsigned int door_state)
        {
          BlitBitmap(bitmap_db_door, drawto,
                     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
-                    DXSIZE,DYSIZE - i / 2, DX, DY);
+                    DXSIZE, DYSIZE - i / 2, DX, DY);
 
          ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
        }
@@ -2804,85 +2988,2588 @@ static struct
   }
 };
 
-void CreateToolButtons()
+void CreateToolButtons()
+{
+  int i;
+
+  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+  {
+    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+    Bitmap *deco_bitmap = None;
+    int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
+    struct GadgetInfo *gi;
+    unsigned long event_mask;
+    int gd_xoffset, gd_yoffset;
+    int gd_x1, gd_x2, gd_y;
+    int id = i;
+
+    event_mask = GD_EVENT_RELEASED;
+
+    gd_xoffset = toolbutton_info[i].xpos;
+    gd_yoffset = toolbutton_info[i].ypos;
+    gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
+    gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
+    gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
+
+    if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+    {
+      int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+
+      getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
+                          &deco_bitmap, &deco_x, &deco_y);
+      deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
+      deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
+    }
+
+    gi = CreateGadget(GDI_CUSTOM_ID, id,
+                     GDI_INFO_TEXT, toolbutton_info[i].infotext,
+                     GDI_X, DX + toolbutton_info[i].x,
+                     GDI_Y, DY + toolbutton_info[i].y,
+                     GDI_WIDTH, toolbutton_info[i].width,
+                     GDI_HEIGHT, toolbutton_info[i].height,
+                     GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+                     GDI_STATE, GD_BUTTON_UNPRESSED,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+                     GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
+                     GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
+                     GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
+                     GDI_DECORATION_SHIFTING, 1, 1,
+                     GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_ACTION, HandleToolButtons,
+                     GDI_END);
+
+    if (gi == NULL)
+      Error(ERR_EXIT, "cannot create gadget");
+
+    tool_gadget[id] = gi;
+  }
+}
+
+void FreeToolButtons()
+{
+  int i;
+
+  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+    FreeGadget(tool_gadget[i]);
+}
+
+static void UnmapToolButtons()
+{
+  int i;
+
+  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+    UnmapGadget(tool_gadget[i]);
+}
+
+static void HandleToolButtons(struct GadgetInfo *gi)
+{
+  request_gadget_id = gi->custom_id;
+}
+
+#if 1
+
+static struct Mapping_EM_to_RND_object
+{
+  int element_em;
+  boolean is_rnd_to_em_mapping;                /* unique mapping EM <-> RND */
+  boolean is_backside;                 /* backside of moving element */
+
+  int element_rnd;
+  int action;
+  int direction;
+}
+em_object_mapping_list[] =
+{
+  {
+    Xblank,                            TRUE,   FALSE,
+    EL_EMPTY,                          -1, -1
+  },
+  {
+    Yacid_splash_eB,                   FALSE,  FALSE,
+    EL_ACID_SPLASH_RIGHT,              -1, -1
+  },
+  {
+    Yacid_splash_wB,                   FALSE,  FALSE,
+    EL_ACID_SPLASH_LEFT,               -1, -1
+  },
+
+#ifdef EM_ENGINE_BAD_ROLL
+  {
+    Xstone_force_e,                    FALSE,  FALSE,
+    EL_ROCK,                           -1, MV_BIT_RIGHT
+  },
+  {
+    Xstone_force_w,                    FALSE,  FALSE,
+    EL_ROCK,                           -1, MV_BIT_LEFT
+  },
+  {
+    Xnut_force_e,                      FALSE,  FALSE,
+    EL_NUT,                            -1, MV_BIT_RIGHT
+  },
+  {
+    Xnut_force_w,                      FALSE,  FALSE,
+    EL_NUT,                            -1, MV_BIT_LEFT
+  },
+  {
+    Xspring_force_e,                   FALSE,  FALSE,
+    EL_SPRING,                         -1, MV_BIT_RIGHT
+  },
+  {
+    Xspring_force_w,                   FALSE,  FALSE,
+    EL_SPRING,                         -1, MV_BIT_LEFT
+  },
+  {
+    Xemerald_force_e,                  FALSE,  FALSE,
+    EL_EMERALD,                                -1, MV_BIT_RIGHT
+  },
+  {
+    Xemerald_force_w,                  FALSE,  FALSE,
+    EL_EMERALD,                                -1, MV_BIT_LEFT
+  },
+  {
+    Xdiamond_force_e,                  FALSE,  FALSE,
+    EL_DIAMOND,                                -1, MV_BIT_RIGHT
+  },
+  {
+    Xdiamond_force_w,                  FALSE,  FALSE,
+    EL_DIAMOND,                                -1, MV_BIT_LEFT
+  },
+  {
+    Xbomb_force_e,                     FALSE,  FALSE,
+    EL_BOMB,                           -1, MV_BIT_RIGHT
+  },
+  {
+    Xbomb_force_w,                     FALSE,  FALSE,
+    EL_BOMB,                           -1, MV_BIT_LEFT
+  },
+#endif /* EM_ENGINE_BAD_ROLL */
+
+  {
+    Xstone,                            TRUE,   FALSE,
+    EL_ROCK,                           -1, -1
+  },
+  {
+    Xstone_pause,                      FALSE,  FALSE,
+    EL_ROCK,                           -1, -1
+  },
+  {
+    Xstone_fall,                       FALSE,  FALSE,
+    EL_ROCK,                           -1, -1
+  },
+  {
+    Ystone_s,                          FALSE,  FALSE,
+    EL_ROCK,                           ACTION_FALLING, -1
+  },
+  {
+    Ystone_sB,                         FALSE,  TRUE,
+    EL_ROCK,                           ACTION_FALLING, -1
+  },
+  {
+    Ystone_e,                          FALSE,  FALSE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ystone_eB,                         FALSE,  TRUE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ystone_w,                          FALSE,  FALSE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ystone_wB,                         FALSE,  TRUE,
+    EL_ROCK,                           ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Xnut,                              TRUE,   FALSE,
+    EL_NUT,                            -1, -1
+  },
+  {
+    Xnut_pause,                                FALSE,  FALSE,
+    EL_NUT,                            -1, -1
+  },
+  {
+    Xnut_fall,                         FALSE,  FALSE,
+    EL_NUT,                            -1, -1
+  },
+  {
+    Ynut_s,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_FALLING, -1
+  },
+  {
+    Ynut_sB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_FALLING, -1
+  },
+  {
+    Ynut_e,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ynut_eB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ynut_w,                            FALSE,  FALSE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ynut_wB,                           FALSE,  TRUE,
+    EL_NUT,                            ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Xbug_n,                            TRUE,   FALSE,
+    EL_BUG_UP,                         -1, -1
+  },
+  {
+    Xbug_e,                            TRUE,   FALSE,
+    EL_BUG_RIGHT,                      -1, -1
+  },
+  {
+    Xbug_s,                            TRUE,   FALSE,
+    EL_BUG_DOWN,                       -1, -1
+  },
+  {
+    Xbug_w,                            TRUE,   FALSE,
+    EL_BUG_LEFT,                       -1, -1
+  },
+  {
+    Xbug_gon,                          FALSE,  FALSE,
+    EL_BUG_UP,                         -1, -1
+  },
+  {
+    Xbug_goe,                          FALSE,  FALSE,
+    EL_BUG_RIGHT,                      -1, -1
+  },
+  {
+    Xbug_gos,                          FALSE,  FALSE,
+    EL_BUG_DOWN,                       -1, -1
+  },
+  {
+    Xbug_gow,                          FALSE,  FALSE,
+    EL_BUG_LEFT,                       -1, -1
+  },
+  {
+    Ybug_n,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Ybug_nB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Ybug_e,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ybug_eB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ybug_s,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Ybug_sB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Ybug_w,                            FALSE,  FALSE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ybug_wB,                           FALSE,  TRUE,
+    EL_BUG,                            ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ybug_w_n,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+  },
+  {
+    Ybug_n_e,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+  },
+  {
+    Ybug_e_s,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+  },
+  {
+    Ybug_s_w,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+  },
+  {
+    Ybug_e_n,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+  },
+  {
+    Ybug_s_e,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+  },
+  {
+    Ybug_w_s,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+  },
+  {
+    Ybug_n_w,                          FALSE,  FALSE,
+    EL_BUG,                            ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+  },
+  {
+    Ybug_stone,                                FALSE,  FALSE,
+    EL_BUG,                            ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Ybug_spring,                       FALSE,  FALSE,
+    EL_BUG,                            ACTION_SMASHED_BY_SPRING, -1
+  },
+  {
+    Xtank_n,                           TRUE,   FALSE,
+    EL_SPACESHIP_UP,                   -1, -1
+  },
+  {
+    Xtank_e,                           TRUE,   FALSE,
+    EL_SPACESHIP_RIGHT,                        -1, -1
+  },
+  {
+    Xtank_s,                           TRUE,   FALSE,
+    EL_SPACESHIP_DOWN,                 -1, -1
+  },
+  {
+    Xtank_w,                           TRUE,   FALSE,
+    EL_SPACESHIP_LEFT,                 -1, -1
+  },
+  {
+    Xtank_gon,                         FALSE,  FALSE,
+    EL_SPACESHIP_UP,                   -1, -1
+  },
+  {
+    Xtank_goe,                         FALSE,  FALSE,
+    EL_SPACESHIP_RIGHT,                        -1, -1
+  },
+  {
+    Xtank_gos,                         FALSE,  FALSE,
+    EL_SPACESHIP_DOWN,                 -1, -1
+  },
+  {
+    Xtank_gow,                         FALSE,  FALSE,
+    EL_SPACESHIP_LEFT,                 -1, -1
+  },
+  {
+    Ytank_n,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Ytank_nB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Ytank_e,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ytank_eB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ytank_s,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Ytank_sB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Ytank_w,                           FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ytank_wB,                          FALSE,  TRUE,
+    EL_SPACESHIP,                      ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ytank_w_n,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+  },
+  {
+    Ytank_n_e,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+  },
+  {
+    Ytank_e_s,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+  },
+  {
+    Ytank_s_w,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+  },
+  {
+    Ytank_e_n,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+  },
+  {
+    Ytank_s_e,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+  },
+  {
+    Ytank_w_s,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+  },
+  {
+    Ytank_n_w,                         FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+  },
+  {
+    Ytank_stone,                       FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Ytank_spring,                      FALSE,  FALSE,
+    EL_SPACESHIP,                      ACTION_SMASHED_BY_SPRING, -1
+  },
+  {
+    Xandroid,                          TRUE,   FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, -1
+  },
+  {
+    Xandroid_1_n,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
+  },
+  {
+    Xandroid_2_n,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_UP
+  },
+  {
+    Xandroid_1_e,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
+  },
+  {
+    Xandroid_2_e,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_RIGHT
+  },
+  {
+    Xandroid_1_w,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
+  },
+  {
+    Xandroid_2_w,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_LEFT
+  },
+  {
+    Xandroid_1_s,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
+  },
+  {
+    Xandroid_2_s,                      FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_ACTIVE, MV_BIT_DOWN
+  },
+  {
+    Yandroid_n,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yandroid_nB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yandroid_ne,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+  },
+  {
+    Yandroid_neB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+  },
+  {
+    Yandroid_e,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yandroid_eB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yandroid_se,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+  },
+  {
+    Yandroid_seB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+  },
+  {
+    Yandroid_s,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yandroid_sB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yandroid_sw,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+  },
+  {
+    Yandroid_swB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+  },
+  {
+    Yandroid_w,                                FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yandroid_wB,                       FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yandroid_nw,                       FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+  },
+  {
+    Yandroid_nwB,                      FALSE,  TRUE,
+    EL_EMC_ANDROID,                    ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+  },
+  {
+    Xspring,                           TRUE,   FALSE,
+    EL_SPRING,                         -1, -1
+  },
+  {
+    Xspring_pause,                     FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
+  },
+  {
+    Xspring_e,                         FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
+  },
+  {
+    Xspring_w,                         FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
+  },
+  {
+    Xspring_fall,                      FALSE,  FALSE,
+    EL_SPRING,                         -1, -1
+  },
+  {
+    Yspring_s,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_FALLING, -1
+  },
+  {
+    Yspring_sB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_FALLING, -1
+  },
+  {
+    Yspring_e,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yspring_eB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yspring_w,                         FALSE,  FALSE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yspring_wB,                                FALSE,  TRUE,
+    EL_SPRING,                         ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yspring_kill_e,                    FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
+  },
+  {
+    Yspring_kill_eB,                   FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
+  },
+  {
+    Yspring_kill_w,                    FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
+  },
+  {
+    Yspring_kill_wB,                   FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
+  },
+  {
+    Xeater_n,                          TRUE,   FALSE,
+    EL_YAMYAM,                         -1, -1
+  },
+  {
+    Xeater_e,                          FALSE,  FALSE,
+    EL_YAMYAM,                         -1, -1
+  },
+  {
+    Xeater_w,                          FALSE,  FALSE,
+    EL_YAMYAM,                         -1, -1
+  },
+  {
+    Xeater_s,                          FALSE,  FALSE,
+    EL_YAMYAM,                         -1, -1
+  },
+  {
+    Yeater_n,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yeater_nB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yeater_e,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yeater_eB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yeater_s,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yeater_sB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yeater_w,                          FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yeater_wB,                         FALSE,  TRUE,
+    EL_YAMYAM,                         ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yeater_stone,                      FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Yeater_spring,                     FALSE,  FALSE,
+    EL_YAMYAM,                         ACTION_SMASHED_BY_SPRING, -1
+  },
+  {
+    Xalien,                            TRUE,   FALSE,
+    EL_ROBOT,                          -1, -1
+  },
+  {
+    Xalien_pause,                      FALSE,  FALSE,
+    EL_ROBOT,                          -1, -1
+  },
+  {
+    Yalien_n,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yalien_nB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yalien_e,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yalien_eB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yalien_s,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yalien_sB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yalien_w,                          FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yalien_wB,                         FALSE,  TRUE,
+    EL_ROBOT,                          ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yalien_stone,                      FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Yalien_spring,                     FALSE,  FALSE,
+    EL_ROBOT,                          ACTION_SMASHED_BY_SPRING, -1
+  },
+  {
+    Xemerald,                          TRUE,   FALSE,
+    EL_EMERALD,                                -1, -1
+  },
+  {
+    Xemerald_pause,                    FALSE,  FALSE,
+    EL_EMERALD,                                -1, -1
+  },
+  {
+    Xemerald_fall,                     FALSE,  FALSE,
+    EL_EMERALD,                                -1, -1
+  },
+  {
+    Xemerald_shine,                    FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_TWINKLING, -1
+  },
+  {
+    Yemerald_s,                                FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_FALLING, -1
+  },
+  {
+    Yemerald_sB,                       FALSE,  TRUE,
+    EL_EMERALD,                                ACTION_FALLING, -1
+  },
+  {
+    Yemerald_e,                                FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yemerald_eB,                       FALSE,  TRUE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yemerald_w,                                FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yemerald_wB,                       FALSE,  TRUE,
+    EL_EMERALD,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yemerald_eat,                      FALSE,  FALSE,
+    EL_EMERALD,                                ACTION_COLLECTING, -1
+  },
+  {
+    Yemerald_stone,                    FALSE,  FALSE,
+    EL_NUT,                            ACTION_BREAKING, -1
+  },
+  {
+    Xdiamond,                          TRUE,   FALSE,
+    EL_DIAMOND,                                -1, -1
+  },
+  {
+    Xdiamond_pause,                    FALSE,  FALSE,
+    EL_DIAMOND,                                -1, -1
+  },
+  {
+    Xdiamond_fall,                     FALSE,  FALSE,
+    EL_DIAMOND,                                -1, -1
+  },
+  {
+    Xdiamond_shine,                    FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_TWINKLING, -1
+  },
+  {
+    Ydiamond_s,                                FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_FALLING, -1
+  },
+  {
+    Ydiamond_sB,                       FALSE,  TRUE,
+    EL_DIAMOND,                                ACTION_FALLING, -1
+  },
+  {
+    Ydiamond_e,                                FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ydiamond_eB,                       FALSE,  TRUE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ydiamond_w,                                FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ydiamond_wB,                       FALSE,  TRUE,
+    EL_DIAMOND,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ydiamond_eat,                      FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_COLLECTING, -1
+  },
+  {
+    Ydiamond_stone,                    FALSE,  FALSE,
+    EL_DIAMOND,                                ACTION_SMASHED_BY_ROCK, -1
+  },
+  {
+    Xdrip_fall,                                TRUE,   FALSE,
+    EL_AMOEBA_DROP,                    -1, -1
+  },
+  {
+    Xdrip_stretch,                     FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+  },
+  {
+    Xdrip_stretchB,                    FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+  },
+  {
+    Xdrip_eat,                         FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_GROWING, -1
+  },
+  {
+    Ydrip_s1,                          FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+  },
+  {
+    Ydrip_s1B,                         FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+  },
+  {
+    Ydrip_s2,                          FALSE,  FALSE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+  },
+  {
+    Ydrip_s2B,                         FALSE,  TRUE,
+    EL_AMOEBA_DROP,                    ACTION_FALLING, -1
+  },
+  {
+    Xbomb,                             TRUE,   FALSE,
+    EL_BOMB,                           -1, -1
+  },
+  {
+    Xbomb_pause,                       FALSE,  FALSE,
+    EL_BOMB,                           -1, -1
+  },
+  {
+    Xbomb_fall,                                FALSE,  FALSE,
+    EL_BOMB,                           -1, -1
+  },
+  {
+    Ybomb_s,                           FALSE,  FALSE,
+    EL_BOMB,                           ACTION_FALLING, -1
+  },
+  {
+    Ybomb_sB,                          FALSE,  TRUE,
+    EL_BOMB,                           ACTION_FALLING, -1
+  },
+  {
+    Ybomb_e,                           FALSE,  FALSE,
+    EL_BOMB,                           ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ybomb_eB,                          FALSE,  TRUE,
+    EL_BOMB,                           ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Ybomb_w,                           FALSE,  FALSE,
+    EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ybomb_wB,                          FALSE,  TRUE,
+    EL_BOMB,                           ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Ybomb_eat,                         FALSE,  FALSE,
+    EL_BOMB,                           ACTION_ACTIVATING, -1
+  },
+  {
+    Xballoon,                          TRUE,   FALSE,
+    EL_BALLOON,                                -1, -1
+  },
+  {
+    Yballoon_n,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yballoon_nB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_UP
+  },
+  {
+    Yballoon_e,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yballoon_eB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_RIGHT
+  },
+  {
+    Yballoon_s,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yballoon_sB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_DOWN
+  },
+  {
+    Yballoon_w,                                FALSE,  FALSE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Yballoon_wB,                       FALSE,  TRUE,
+    EL_BALLOON,                                ACTION_MOVING, MV_BIT_LEFT
+  },
+  {
+    Xgrass,                            TRUE,   FALSE,
+    EL_EMC_GRASS,                      -1, -1
+  },
+  {
+    Ygrass_nB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_UP
+  },
+  {
+    Ygrass_eB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_RIGHT
+  },
+  {
+    Ygrass_sB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_DOWN
+  },
+  {
+    Ygrass_wB,                         FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_DIGGING, MV_BIT_LEFT
+  },
+  {
+    Xdirt,                             TRUE,   FALSE,
+    EL_SAND,                           -1, -1
+  },
+  {
+    Ydirt_nB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_UP
+  },
+  {
+    Ydirt_eB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_RIGHT
+  },
+  {
+    Ydirt_sB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_DOWN
+  },
+  {
+    Ydirt_wB,                          FALSE,  FALSE,
+    EL_SAND,                           ACTION_DIGGING, MV_BIT_LEFT
+  },
+  {
+    Xacid_ne,                          TRUE,   FALSE,
+    EL_ACID_POOL_TOPRIGHT,             -1, -1
+  },
+  {
+    Xacid_se,                          TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOMRIGHT,          -1, -1
+  },
+  {
+    Xacid_s,                           TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOM,               -1, -1
+  },
+  {
+    Xacid_sw,                          TRUE,   FALSE,
+    EL_ACID_POOL_BOTTOMLEFT,           -1, -1
+  },
+  {
+    Xacid_nw,                          TRUE,   FALSE,
+    EL_ACID_POOL_TOPLEFT,              -1, -1
+  },
+  {
+    Xacid_1,                           TRUE,   FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_2,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_3,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_4,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_5,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_6,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_7,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xacid_8,                           FALSE,  FALSE,
+    EL_ACID,                           -1, -1
+  },
+  {
+    Xball_1,                           TRUE,   FALSE,
+    EL_EMC_MAGIC_BALL,                 -1, -1
+  },
+  {
+    Xball_1B,                          FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+  },
+  {
+    Xball_2,                           FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+  },
+  {
+    Xball_2B,                          FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_ACTIVE, -1
+  },
+  {
+    Yball_eat,                         FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL,                 ACTION_DROPPING, -1
+  },
+  {
+    Ykey_1_eat,                                FALSE,  FALSE,
+    EL_EM_KEY_1,                       ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_2_eat,                                FALSE,  FALSE,
+    EL_EM_KEY_2,                       ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_3_eat,                                FALSE,  FALSE,
+    EL_EM_KEY_3,                       ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_4_eat,                                FALSE,  FALSE,
+    EL_EM_KEY_4,                       ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_5_eat,                                FALSE,  FALSE,
+    EL_EMC_KEY_5,                      ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_6_eat,                                FALSE,  FALSE,
+    EL_EMC_KEY_6,                      ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_7_eat,                                FALSE,  FALSE,
+    EL_EMC_KEY_7,                      ACTION_COLLECTING, -1
+  },
+  {
+    Ykey_8_eat,                                FALSE,  FALSE,
+    EL_EMC_KEY_8,                      ACTION_COLLECTING, -1
+  },
+  {
+    Ylenses_eat,                       FALSE,  FALSE,
+    EL_EMC_LENSES,                     ACTION_COLLECTING, -1
+  },
+  {
+    Ymagnify_eat,                      FALSE,  FALSE,
+    EL_EMC_MAGNIFIER,                  ACTION_COLLECTING, -1
+  },
+  {
+    Ygrass_eat,                                FALSE,  FALSE,
+    EL_EMC_GRASS,                      ACTION_SNAPPING, -1
+  },
+  {
+    Ydirt_eat,                         FALSE,  FALSE,
+    EL_SAND,                           ACTION_SNAPPING, -1
+  },
+  {
+    Xgrow_ns,                          TRUE,   FALSE,
+    EL_EXPANDABLE_WALL_VERTICAL,       -1, -1
+  },
+  {
+    Ygrow_ns_eat,                      FALSE,  FALSE,
+    EL_EXPANDABLE_WALL_VERTICAL,       ACTION_GROWING, -1
+  },
+  {
+    Xgrow_ew,                          TRUE,   FALSE,
+    EL_EXPANDABLE_WALL_HORIZONTAL,     -1, -1
+  },
+  {
+    Ygrow_ew_eat,                      FALSE,  FALSE,
+    EL_EXPANDABLE_WALL_HORIZONTAL,     ACTION_GROWING, -1
+  },
+  {
+    Xwonderwall,                       TRUE,   FALSE,
+    EL_MAGIC_WALL,                     -1, -1
+  },
+  {
+    XwonderwallB,                      FALSE,  FALSE,
+    EL_MAGIC_WALL,                     ACTION_ACTIVE, -1
+  },
+  {
+    Xamoeba_1,                         TRUE,   FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_2,                         FALSE,  FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_3,                         FALSE,  FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_4,                         FALSE,  FALSE,
+    EL_AMOEBA_DRY,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_5,                         TRUE,   FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_6,                         FALSE,  FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_7,                         FALSE,  FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+  },
+  {
+    Xamoeba_8,                         FALSE,  FALSE,
+    EL_AMOEBA_WET,                     ACTION_OTHER, -1
+  },
+  {
+    Xdoor_1,                           TRUE,   FALSE,
+    EL_EM_GATE_1,                      -1, -1
+  },
+  {
+    Xdoor_2,                           TRUE,   FALSE,
+    EL_EM_GATE_2,                      -1, -1
+  },
+  {
+    Xdoor_3,                           TRUE,   FALSE,
+    EL_EM_GATE_3,                      -1, -1
+  },
+  {
+    Xdoor_4,                           TRUE,   FALSE,
+    EL_EM_GATE_4,                      -1, -1
+  },
+  {
+    Xdoor_5,                           TRUE,   FALSE,
+    EL_EMC_GATE_5,                     -1, -1
+  },
+  {
+    Xdoor_6,                           TRUE,   FALSE,
+    EL_EMC_GATE_6,                     -1, -1
+  },
+  {
+    Xdoor_7,                           TRUE,   FALSE,
+    EL_EMC_GATE_7,                     -1, -1
+  },
+  {
+    Xdoor_8,                           TRUE,   FALSE,
+    EL_EMC_GATE_8,                     -1, -1
+  },
+  {
+    Xkey_1,                            TRUE,   FALSE,
+    EL_EM_KEY_1,                       -1, -1
+  },
+  {
+    Xkey_2,                            TRUE,   FALSE,
+    EL_EM_KEY_2,                       -1, -1
+  },
+  {
+    Xkey_3,                            TRUE,   FALSE,
+    EL_EM_KEY_3,                       -1, -1
+  },
+  {
+    Xkey_4,                            TRUE,   FALSE,
+    EL_EM_KEY_4,                       -1, -1
+  },
+  {
+    Xkey_5,                            TRUE,   FALSE,
+    EL_EMC_KEY_5,                      -1, -1
+  },
+  {
+    Xkey_6,                            TRUE,   FALSE,
+    EL_EMC_KEY_6,                      -1, -1
+  },
+  {
+    Xkey_7,                            TRUE,   FALSE,
+    EL_EMC_KEY_7,                      -1, -1
+  },
+  {
+    Xkey_8,                            TRUE,   FALSE,
+    EL_EMC_KEY_8,                      -1, -1
+  },
+  {
+    Xwind_n,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_UP,              -1, -1
+  },
+  {
+    Xwind_e,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_RIGHT,           -1, -1
+  },
+  {
+    Xwind_s,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_DOWN,            -1, -1
+  },
+  {
+    Xwind_w,                           TRUE,   FALSE,
+    EL_BALLOON_SWITCH_LEFT,            -1, -1
+  },
+  {
+    Xwind_nesw,                                TRUE,   FALSE,
+    EL_BALLOON_SWITCH_ANY,             -1, -1
+  },
+  {
+    Xwind_stop,                                TRUE,   FALSE,
+    EL_BALLOON_SWITCH_NONE,            -1, -1
+  },
+  {
+    Xexit,                             TRUE,   FALSE,
+    EL_EXIT_CLOSED,                    -1, -1
+  },
+  {
+    Xexit_1,                           TRUE,   FALSE,
+    EL_EXIT_OPEN,                      -1, -1
+  },
+  {
+    Xexit_2,                           FALSE,  FALSE,
+    EL_EXIT_OPEN,                      -1, -1
+  },
+  {
+    Xexit_3,                           FALSE,  FALSE,
+    EL_EXIT_OPEN,                      -1, -1
+  },
+  {
+    Xdynamite,                         TRUE,   FALSE,
+    EL_DYNAMITE,                       -1, -1
+  },
+  {
+    Ydynamite_eat,                     FALSE,  FALSE,
+    EL_DYNAMITE,                       ACTION_COLLECTING, -1
+  },
+  {
+    Xdynamite_1,                       TRUE,   FALSE,
+    EL_DYNAMITE_ACTIVE,                        -1, -1
+  },
+  {
+    Xdynamite_2,                       FALSE,  FALSE,
+    EL_DYNAMITE_ACTIVE,                        -1, -1
+  },
+  {
+    Xdynamite_3,                       FALSE,  FALSE,
+    EL_DYNAMITE_ACTIVE,                        -1, -1
+  },
+  {
+    Xdynamite_4,                       FALSE,  FALSE,
+    EL_DYNAMITE_ACTIVE,                        -1, -1
+  },
+  {
+    Xbumper,                           TRUE,   FALSE,
+    EL_EMC_SPRING_BUMPER,              -1, -1
+  },
+  {
+    XbumperB,                          FALSE,  FALSE,
+    EL_EMC_SPRING_BUMPER,              ACTION_ACTIVE, -1
+  },
+  {
+    Xwheel,                            TRUE,   FALSE,
+    EL_ROBOT_WHEEL,                    -1, -1
+  },
+  {
+    XwheelB,                           FALSE,  FALSE,
+    EL_ROBOT_WHEEL,                    ACTION_ACTIVE, -1
+  },
+  {
+    Xswitch,                           TRUE,   FALSE,
+    EL_EMC_MAGIC_BALL_SWITCH,          -1, -1
+  },
+  {
+    XswitchB,                          FALSE,  FALSE,
+    EL_EMC_MAGIC_BALL_SWITCH,          ACTION_ACTIVE, -1
+  },
+  {
+    Xsand,                             TRUE,   FALSE,
+    EL_QUICKSAND_EMPTY,                        -1, -1
+  },
+  {
+    Xsand_stone,                       TRUE,   FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_stonein_1,                   FALSE,  FALSE,
+    EL_ROCK,                           ACTION_FILLING, -1
+  },
+  {
+    Xsand_stonein_2,                   FALSE,  FALSE,
+    EL_ROCK,                           ACTION_FILLING, -1
+  },
+  {
+    Xsand_stonein_3,                   FALSE,  FALSE,
+    EL_ROCK,                           ACTION_FILLING, -1
+  },
+  {
+    Xsand_stonein_4,                   FALSE,  FALSE,
+    EL_ROCK,                           ACTION_FILLING, -1
+  },
+  {
+    Xsand_stonesand_1,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_stonesand_2,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_stonesand_3,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_stonesand_4,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_stoneout_1,                  FALSE,  FALSE,
+    EL_ROCK,                           ACTION_EMPTYING, -1
+  },
+  {
+    Xsand_stoneout_2,                  FALSE,  FALSE,
+    EL_ROCK,                           ACTION_EMPTYING, -1
+  },
+  {
+    Xsand_sandstone_1,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_sandstone_2,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_sandstone_3,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xsand_sandstone_4,                 FALSE,  FALSE,
+    EL_QUICKSAND_FULL,                 -1, -1
+  },
+  {
+    Xplant,                            TRUE,   FALSE,
+    EL_EMC_PLANT,                      -1, -1
+  },
+  {
+    Yplant,                            FALSE,  FALSE,
+    EL_EMC_PLANT,                      -1, -1
+  },
+  {
+    Xlenses,                           TRUE,   FALSE,
+    EL_EMC_LENSES,                     -1, -1
+  },
+  {
+    Xmagnify,                          TRUE,   FALSE,
+    EL_EMC_MAGNIFIER,                  -1, -1
+  },
+  {
+    Xdripper,                          TRUE,   FALSE,
+    EL_EMC_DRIPPER,                    -1, -1
+  },
+  {
+    XdripperB,                         FALSE,  FALSE,
+    EL_EMC_DRIPPER,                    ACTION_ACTIVE, -1
+  },
+  {
+    Xfake_blank,                       TRUE,   FALSE,
+    EL_INVISIBLE_WALL,                 -1, -1
+  },
+  {
+    Xfake_blankB,                      FALSE,  FALSE,
+    EL_INVISIBLE_WALL,                 ACTION_ACTIVE, -1
+  },
+  {
+    Xfake_grass,                       TRUE,   FALSE,
+    EL_EMC_FAKE_GRASS,                 -1, -1
+  },
+  {
+    Xfake_grassB,                      FALSE,  FALSE,
+    EL_EMC_FAKE_GRASS,                 ACTION_ACTIVE, -1
+  },
+  {
+    Xfake_door_1,                      TRUE,   FALSE,
+    EL_EM_GATE_1_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_2,                      TRUE,   FALSE,
+    EL_EM_GATE_2_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_3,                      TRUE,   FALSE,
+    EL_EM_GATE_3_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_4,                      TRUE,   FALSE,
+    EL_EM_GATE_4_GRAY,                 -1, -1
+  },
+  {
+    Xfake_door_5,                      TRUE,   FALSE,
+    EL_EMC_GATE_5_GRAY,                        -1, -1
+  },
+  {
+    Xfake_door_6,                      TRUE,   FALSE,
+    EL_EMC_GATE_6_GRAY,                        -1, -1
+  },
+  {
+    Xfake_door_7,                      TRUE,   FALSE,
+    EL_EMC_GATE_7_GRAY,                        -1, -1
+  },
+  {
+    Xfake_door_8,                      TRUE,   FALSE,
+    EL_EMC_GATE_8_GRAY,                        -1, -1
+  },
+  {
+    Xfake_acid_1,                      TRUE,   FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_2,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_3,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_4,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_5,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_6,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_7,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xfake_acid_8,                      FALSE,  FALSE,
+    EL_EMC_FAKE_ACID,                  -1, -1
+  },
+  {
+    Xsteel_1,                          TRUE,   FALSE,
+    EL_STEELWALL,                      -1, -1
+  },
+  {
+    Xsteel_2,                          TRUE,   FALSE,
+    EL_EMC_STEELWALL_2,                        -1, -1
+  },
+  {
+    Xsteel_3,                          TRUE,   FALSE,
+    EL_EMC_STEELWALL_3,                        -1, -1
+  },
+  {
+    Xsteel_4,                          TRUE,   FALSE,
+    EL_EMC_STEELWALL_4,                        -1, -1
+  },
+  {
+    Xwall_1,                           TRUE,   FALSE,
+    EL_WALL,                           -1, -1
+  },
+  {
+    Xwall_2,                           TRUE,   FALSE,
+    EL_EMC_WALL_14,                    -1, -1
+  },
+  {
+    Xwall_3,                           TRUE,   FALSE,
+    EL_EMC_WALL_15,                    -1, -1
+  },
+  {
+    Xwall_4,                           TRUE,   FALSE,
+    EL_EMC_WALL_16,                    -1, -1
+  },
+  {
+    Xround_wall_1,                     TRUE,   FALSE,
+    EL_WALL_SLIPPERY,                  -1, -1
+  },
+  {
+    Xround_wall_2,                     TRUE,   FALSE,
+    EL_EMC_WALL_SLIPPERY_2,            -1, -1
+  },
+  {
+    Xround_wall_3,                     TRUE,   FALSE,
+    EL_EMC_WALL_SLIPPERY_3,            -1, -1
+  },
+  {
+    Xround_wall_4,                     TRUE,   FALSE,
+    EL_EMC_WALL_SLIPPERY_4,            -1, -1
+  },
+  {
+    Xdecor_1,                          TRUE,   FALSE,
+    EL_EMC_WALL_8,                     -1, -1
+  },
+  {
+    Xdecor_2,                          TRUE,   FALSE,
+    EL_EMC_WALL_6,                     -1, -1
+  },
+  {
+    Xdecor_3,                          TRUE,   FALSE,
+    EL_EMC_WALL_4,                     -1, -1
+  },
+  {
+    Xdecor_4,                          TRUE,   FALSE,
+    EL_EMC_WALL_7,                     -1, -1
+  },
+  {
+    Xdecor_5,                          TRUE,   FALSE,
+    EL_EMC_WALL_5,                     -1, -1
+  },
+  {
+    Xdecor_6,                          TRUE,   FALSE,
+    EL_EMC_WALL_9,                     -1, -1
+  },
+  {
+    Xdecor_7,                          TRUE,   FALSE,
+    EL_EMC_WALL_10,                    -1, -1
+  },
+  {
+    Xdecor_8,                          TRUE,   FALSE,
+    EL_EMC_WALL_1,                     -1, -1
+  },
+  {
+    Xdecor_9,                          TRUE,   FALSE,
+    EL_EMC_WALL_2,                     -1, -1
+  },
+  {
+    Xdecor_10,                         TRUE,   FALSE,
+    EL_EMC_WALL_3,                     -1, -1
+  },
+  {
+    Xdecor_11,                         TRUE,   FALSE,
+    EL_EMC_WALL_11,                    -1, -1
+  },
+  {
+    Xdecor_12,                         TRUE,   FALSE,
+    EL_EMC_WALL_12,                    -1, -1
+  },
+  {
+    Xalpha_0,                          TRUE,   FALSE,
+    EL_CHAR('0'),                      -1, -1
+  },
+  {
+    Xalpha_1,                          TRUE,   FALSE,
+    EL_CHAR('1'),                      -1, -1
+  },
+  {
+    Xalpha_2,                          TRUE,   FALSE,
+    EL_CHAR('2'),                      -1, -1
+  },
+  {
+    Xalpha_3,                          TRUE,   FALSE,
+    EL_CHAR('3'),                      -1, -1
+  },
+  {
+    Xalpha_4,                          TRUE,   FALSE,
+    EL_CHAR('4'),                      -1, -1
+  },
+  {
+    Xalpha_5,                          TRUE,   FALSE,
+    EL_CHAR('5'),                      -1, -1
+  },
+  {
+    Xalpha_6,                          TRUE,   FALSE,
+    EL_CHAR('6'),                      -1, -1
+  },
+  {
+    Xalpha_7,                          TRUE,   FALSE,
+    EL_CHAR('7'),                      -1, -1
+  },
+  {
+    Xalpha_8,                          TRUE,   FALSE,
+    EL_CHAR('8'),                      -1, -1
+  },
+  {
+    Xalpha_9,                          TRUE,   FALSE,
+    EL_CHAR('9'),                      -1, -1
+  },
+  {
+    Xalpha_excla,                      TRUE,   FALSE,
+    EL_CHAR('!'),                      -1, -1
+  },
+  {
+    Xalpha_quote,                      TRUE,   FALSE,
+    EL_CHAR('"'),                      -1, -1
+  },
+  {
+    Xalpha_comma,                      TRUE,   FALSE,
+    EL_CHAR(','),                      -1, -1
+  },
+  {
+    Xalpha_minus,                      TRUE,   FALSE,
+    EL_CHAR('-'),                      -1, -1
+  },
+  {
+    Xalpha_perio,                      TRUE,   FALSE,
+    EL_CHAR('.'),                      -1, -1
+  },
+  {
+    Xalpha_colon,                      TRUE,   FALSE,
+    EL_CHAR(':'),                      -1, -1
+  },
+  {
+    Xalpha_quest,                      TRUE,   FALSE,
+    EL_CHAR('?'),                      -1, -1
+  },
+  {
+    Xalpha_a,                          TRUE,   FALSE,
+    EL_CHAR('A'),                      -1, -1
+  },
+  {
+    Xalpha_b,                          TRUE,   FALSE,
+    EL_CHAR('B'),                      -1, -1
+  },
+  {
+    Xalpha_c,                          TRUE,   FALSE,
+    EL_CHAR('C'),                      -1, -1
+  },
+  {
+    Xalpha_d,                          TRUE,   FALSE,
+    EL_CHAR('D'),                      -1, -1
+  },
+  {
+    Xalpha_e,                          TRUE,   FALSE,
+    EL_CHAR('E'),                      -1, -1
+  },
+  {
+    Xalpha_f,                          TRUE,   FALSE,
+    EL_CHAR('F'),                      -1, -1
+  },
+  {
+    Xalpha_g,                          TRUE,   FALSE,
+    EL_CHAR('G'),                      -1, -1
+  },
+  {
+    Xalpha_h,                          TRUE,   FALSE,
+    EL_CHAR('H'),                      -1, -1
+  },
+  {
+    Xalpha_i,                          TRUE,   FALSE,
+    EL_CHAR('I'),                      -1, -1
+  },
+  {
+    Xalpha_j,                          TRUE,   FALSE,
+    EL_CHAR('J'),                      -1, -1
+  },
+  {
+    Xalpha_k,                          TRUE,   FALSE,
+    EL_CHAR('K'),                      -1, -1
+  },
+  {
+    Xalpha_l,                          TRUE,   FALSE,
+    EL_CHAR('L'),                      -1, -1
+  },
+  {
+    Xalpha_m,                          TRUE,   FALSE,
+    EL_CHAR('M'),                      -1, -1
+  },
+  {
+    Xalpha_n,                          TRUE,   FALSE,
+    EL_CHAR('N'),                      -1, -1
+  },
+  {
+    Xalpha_o,                          TRUE,   FALSE,
+    EL_CHAR('O'),                      -1, -1
+  },
+  {
+    Xalpha_p,                          TRUE,   FALSE,
+    EL_CHAR('P'),                      -1, -1
+  },
+  {
+    Xalpha_q,                          TRUE,   FALSE,
+    EL_CHAR('Q'),                      -1, -1
+  },
+  {
+    Xalpha_r,                          TRUE,   FALSE,
+    EL_CHAR('R'),                      -1, -1
+  },
+  {
+    Xalpha_s,                          TRUE,   FALSE,
+    EL_CHAR('S'),                      -1, -1
+  },
+  {
+    Xalpha_t,                          TRUE,   FALSE,
+    EL_CHAR('T'),                      -1, -1
+  },
+  {
+    Xalpha_u,                          TRUE,   FALSE,
+    EL_CHAR('U'),                      -1, -1
+  },
+  {
+    Xalpha_v,                          TRUE,   FALSE,
+    EL_CHAR('V'),                      -1, -1
+  },
+  {
+    Xalpha_w,                          TRUE,   FALSE,
+    EL_CHAR('W'),                      -1, -1
+  },
+  {
+    Xalpha_x,                          TRUE,   FALSE,
+    EL_CHAR('X'),                      -1, -1
+  },
+  {
+    Xalpha_y,                          TRUE,   FALSE,
+    EL_CHAR('Y'),                      -1, -1
+  },
+  {
+    Xalpha_z,                          TRUE,   FALSE,
+    EL_CHAR('Z'),                      -1, -1
+  },
+  {
+    Xalpha_arrow_e,                    TRUE,   FALSE,
+    EL_CHAR('>'),                      -1, -1
+  },
+  {
+    Xalpha_arrow_w,                    TRUE,   FALSE,
+    EL_CHAR('<'),                      -1, -1
+  },
+  {
+    Xalpha_copyr,                      TRUE,   FALSE,
+    EL_CHAR('©'),                      -1, -1
+  },
+  {
+    Xalpha_copyr,                      TRUE,   FALSE,
+    EL_CHAR('©'),                      -1, -1
+  },
+
+  {
+    Xboom_bug,                         FALSE,  FALSE,
+    EL_BUG,                            ACTION_EXPLODING, -1
+  },
+  {
+    Xboom_bomb,                                FALSE,  FALSE,
+    EL_BOMB,                           ACTION_EXPLODING, -1
+  },
+  {
+    Xboom_android,                     FALSE,  FALSE,
+    EL_EMC_ANDROID,                    ACTION_OTHER, -1
+  },
+  {
+    Xboom_1,                           FALSE,  FALSE,
+    EL_DEFAULT,                                ACTION_EXPLODING, -1
+  },
+  {
+    Xboom_2,                           FALSE,  FALSE,
+    EL_DEFAULT,                                ACTION_EXPLODING, -1
+  },
+  {
+    Znormal,                           FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
+  },
+  {
+    Zdynamite,                         FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
+  },
+  {
+    Zplayer,                           FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
+  },
+  {
+    ZBORDER,                           FALSE,  FALSE,
+    EL_EMPTY,                          -1, -1
+  },
+
+  {
+    -1,                                        FALSE,  FALSE,
+    -1,                                        -1, -1
+  }
+};
+
+static struct Mapping_EM_to_RND_player
+{
+  int action_em;
+  int player_nr;
+
+  int element_rnd;
+  int action;
+  int direction;
+}
+em_player_mapping_list[] =
+{
+  {
+    SPR_walk + 0,                      0,
+    EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_UP,
+  },
+  {
+    SPR_walk + 1,                      0,
+    EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_walk + 2,                      0,
+    EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_DOWN,
+  },
+  {
+    SPR_walk + 3,                      0,
+    EL_PLAYER_1,                       ACTION_MOVING, MV_BIT_LEFT,
+  },
+  {
+    SPR_push + 0,                      0,
+    EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_UP,
+  },
+  {
+    SPR_push + 1,                      0,
+    EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_push + 2,                      0,
+    EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_DOWN,
+  },
+  {
+    SPR_push + 3,                      0,
+    EL_PLAYER_1,                       ACTION_PUSHING, MV_BIT_LEFT,
+  },
+  {
+    SPR_spray + 0,                     0,
+    EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_UP,
+  },
+  {
+    SPR_spray + 1,                     0,
+    EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_spray + 2,                     0,
+    EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_DOWN,
+  },
+  {
+    SPR_spray + 3,                     0,
+    EL_PLAYER_1,                       ACTION_SNAPPING, MV_BIT_LEFT,
+  },
+  {
+    SPR_walk + 0,                      1,
+    EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_UP,
+  },
+  {
+    SPR_walk + 1,                      1,
+    EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_walk + 2,                      1,
+    EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_DOWN,
+  },
+  {
+    SPR_walk + 3,                      1,
+    EL_PLAYER_2,                       ACTION_MOVING, MV_BIT_LEFT,
+  },
+  {
+    SPR_push + 0,                      1,
+    EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_UP,
+  },
+  {
+    SPR_push + 1,                      1,
+    EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_push + 2,                      1,
+    EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_DOWN,
+  },
+  {
+    SPR_push + 3,                      1,
+    EL_PLAYER_2,                       ACTION_PUSHING, MV_BIT_LEFT,
+  },
+  {
+    SPR_spray + 0,                     1,
+    EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_UP,
+  },
+  {
+    SPR_spray + 1,                     1,
+    EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_RIGHT,
+  },
+  {
+    SPR_spray + 2,                     1,
+    EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_DOWN,
+  },
+  {
+    SPR_spray + 3,                     1,
+    EL_PLAYER_2,                       ACTION_SNAPPING, MV_BIT_LEFT,
+  },
+  {
+    SPR_still,                         0,
+    EL_PLAYER_1,                       ACTION_DEFAULT, -1,
+  },
+  {
+    SPR_still,                         1,
+    EL_PLAYER_2,                       ACTION_DEFAULT, -1,
+  },
+
+  {
+    -1,                                        -1,
+    -1,                                        -1, -1
+  }
+};
+
+int map_element_RND_to_EM(int element_rnd)
+{
+  static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
+  static boolean mapping_initialized = FALSE;
+
+  if (!mapping_initialized)
+  {
+    int i;
+
+    /* return "Xalpha_quest" for all undefined elements in mapping array */
+    for (i = 0; i < NUM_FILE_ELEMENTS; i++)
+      mapping_RND_to_EM[i] = Xalpha_quest;
+
+    for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+      if (em_object_mapping_list[i].is_rnd_to_em_mapping)
+       mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
+         em_object_mapping_list[i].element_em;
+
+    mapping_initialized = TRUE;
+  }
+
+  if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
+    return mapping_RND_to_EM[element_rnd];
+
+  Error(ERR_WARN, "invalid RND level element %d", element_rnd);
+
+  return EL_UNKNOWN;
+}
+
+int map_element_EM_to_RND(int element_em)
+{
+  static unsigned short mapping_EM_to_RND[TILE_MAX];
+  static boolean mapping_initialized = FALSE;
+
+  if (!mapping_initialized)
+  {
+    int i;
+
+    /* return "EL_UNKNOWN" for all undefined elements in mapping array */
+    for (i = 0; i < TILE_MAX; i++)
+      mapping_EM_to_RND[i] = EL_UNKNOWN;
+
+    for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+      mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+       em_object_mapping_list[i].element_rnd;
+
+    mapping_initialized = TRUE;
+  }
+
+  if (element_em >= 0 && element_em < TILE_MAX)
+    return mapping_EM_to_RND[element_em];
+
+  Error(ERR_WARN, "invalid EM level element %d", element_em);
+
+  return EL_UNKNOWN;
+}
+
+#else
+
+int map_element_RND_to_EM(int element_rnd)
 {
-  int i;
+  static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
+  static boolean mapping_initialized = FALSE;
 
-  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
+  struct
   {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    Bitmap *deco_bitmap = None;
-    int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
-    struct GadgetInfo *gi;
-    unsigned long event_mask;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y;
-    int id = i;
+    int element_em;
+    int element_rnd;
+  }
+  mapping_RND_to_EM_list[] =
+  {
+    { Xblank,                  EL_EMPTY                        },
+    { Xstone,                  EL_ROCK                         },
+    { Xnut,                    EL_NUT                          },
+    { Xbug_n,                  EL_BUG_UP                       },
+    { Xbug_e,                  EL_BUG_RIGHT                    },
+    { Xbug_s,                  EL_BUG_DOWN                     },
+    { Xbug_w,                  EL_BUG_LEFT                     },
+    { Xtank_n,                 EL_SPACESHIP_UP                 },
+    { Xtank_e,                 EL_SPACESHIP_RIGHT              },
+    { Xtank_s,                 EL_SPACESHIP_DOWN               },
+    { Xtank_w,                 EL_SPACESHIP_LEFT               },
+    { Xandroid,                        EL_EMC_ANDROID                  },
+    { Xandroid_1_n,            EL_EMC_ANDROID_UP               },
+    { Xandroid_1_e,            EL_EMC_ANDROID_RIGHT            },
+    { Xandroid_1_w,            EL_EMC_ANDROID_LEFT             },
+    { Xandroid_1_s,            EL_EMC_ANDROID_DOWN             },
+    { Xspring,                 EL_SPRING                       },
+    { Xeater_n,                        EL_YAMYAM                       },
+    { Xalien,                  EL_ROBOT                        },
+    { Xemerald,                        EL_EMERALD                      },
+    { Xdiamond,                        EL_DIAMOND                      },
+    { Xdrip_fall,              EL_AMOEBA_DROP                  },
+    { Xbomb,                   EL_BOMB                         },
+    { Xballoon,                        EL_BALLOON                      },
+    { Xgrass,                  EL_EMC_GRASS                    },
+    { Xdirt,                   EL_SAND                         },
+    { Xacid_ne,                        EL_ACID_POOL_TOPRIGHT           },
+    { Xacid_se,                        EL_ACID_POOL_BOTTOMRIGHT        },
+    { Xacid_s,                 EL_ACID_POOL_BOTTOM             },
+    { Xacid_sw,                        EL_ACID_POOL_BOTTOMLEFT         },
+    { Xacid_nw,                        EL_ACID_POOL_TOPLEFT            },
+    { Xacid_1,                 EL_ACID                         },
+    { Xball_1,                 EL_EMC_MAGIC_BALL               },
+    { Xgrow_ns,                        EL_EMC_GROW                     },
+    { Xwonderwall,             EL_MAGIC_WALL                   },
+    { Xamoeba_1,               EL_AMOEBA_WET                   },
+    { Xdoor_1,                 EL_EM_GATE_1                    },
+    { Xdoor_2,                 EL_EM_GATE_2                    },
+    { Xdoor_3,                 EL_EM_GATE_3                    },
+    { Xdoor_4,                 EL_EM_GATE_4                    },
+    { Xdoor_5,                 EL_EMC_GATE_5                   },
+    { Xdoor_6,                 EL_EMC_GATE_6                   },
+    { Xdoor_7,                 EL_EMC_GATE_7                   },
+    { Xdoor_8,                 EL_EMC_GATE_8                   },
+    { Xkey_1,                  EL_EM_KEY_1                     },
+    { Xkey_2,                  EL_EM_KEY_2                     },
+    { Xkey_3,                  EL_EM_KEY_3                     },
+    { Xkey_4,                  EL_EM_KEY_4                     },
+    { Xkey_5,                  EL_EMC_KEY_5                    },
+    { Xkey_6,                  EL_EMC_KEY_6                    },
+    { Xkey_7,                  EL_EMC_KEY_7                    },
+    { Xkey_8,                  EL_EMC_KEY_8                    },
+    { Xwind_n,                 EL_BALLOON_SWITCH_UP            },
+    { Xwind_e,                 EL_BALLOON_SWITCH_RIGHT         },
+    { Xwind_s,                 EL_BALLOON_SWITCH_DOWN          },
+    { Xwind_w,                 EL_BALLOON_SWITCH_LEFT          },
+    { Xwind_nesw,              EL_BALLOON_SWITCH_ANY           },
+    { Xwind_stop,              EL_BALLOON_SWITCH_NONE          },
+    { Xexit,                   EL_EXIT_CLOSED                  },
+    { Xexit_1,                 EL_EXIT_OPEN                    },
+    { Xdynamite,               EL_DYNAMITE                     },
+    { Xdynamite_1,             EL_DYNAMITE_ACTIVE              },
+    { Xbumper,                 EL_EMC_BUMPER                   },
+    { Xwheel,                  EL_ROBOT_WHEEL                  },
+    { Xswitch,                 EL_UNKNOWN                      },
+    { Xsand,                   EL_QUICKSAND_EMPTY              },
+    { Xsand_stone,             EL_QUICKSAND_FULL               },
+    { Xplant,                  EL_EMC_PLANT                    },
+    { Xlenses,                 EL_EMC_LENSES                   },
+    { Xmagnify,                        EL_EMC_MAGNIFIER                },
+    { Xdripper,                        EL_UNKNOWN                      },
+    { Xfake_blank,             EL_INVISIBLE_WALL               },
+    { Xfake_grass,             EL_INVISIBLE_SAND               },
+    { Xfake_door_1,            EL_EM_GATE_1_GRAY               },
+    { Xfake_door_2,            EL_EM_GATE_2_GRAY               },
+    { Xfake_door_3,            EL_EM_GATE_3_GRAY               },
+    { Xfake_door_4,            EL_EM_GATE_4_GRAY               },
+    { Xfake_door_5,            EL_EMC_GATE_5_GRAY              },
+    { Xfake_door_6,            EL_EMC_GATE_6_GRAY              },
+    { Xfake_door_7,            EL_EMC_GATE_7_GRAY              },
+    { Xfake_door_8,            EL_EMC_GATE_8_GRAY              },
+    { Xsteel_1,                        EL_STEELWALL                    },
+    { Xsteel_2,                        EL_UNKNOWN                      },
+    { Xsteel_3,                        EL_EMC_STEELWALL_1              },
+    { Xsteel_4,                        EL_UNKNOWN                      },
+    { Xwall_1,                 EL_WALL                         },
+    { Xwall_2,                 EL_UNKNOWN                      },
+    { Xwall_3,                 EL_UNKNOWN                      },
+    { Xwall_4,                 EL_UNKNOWN                      },
+    { Xround_wall_1,           EL_WALL_SLIPPERY                },
+    { Xround_wall_2,           EL_UNKNOWN                      },
+    { Xround_wall_3,           EL_UNKNOWN                      },
+    { Xround_wall_4,           EL_UNKNOWN                      },
+    { Xdecor_1,                        EL_UNKNOWN                      },
+    { Xdecor_2,                        EL_EMC_WALL_6                   },
+    { Xdecor_3,                        EL_EMC_WALL_4                   },
+    { Xdecor_4,                        EL_EMC_WALL_5                   },
+    { Xdecor_5,                        EL_EMC_WALL_7                   },
+    { Xdecor_6,                        EL_EMC_WALL_8                   },
+    { Xdecor_7,                        EL_UNKNOWN                      },
+    { Xdecor_8,                        EL_EMC_WALL_1                   },
+    { Xdecor_9,                        EL_EMC_WALL_2                   },
+    { Xdecor_10,               EL_EMC_WALL_3                   },
+    { Xdecor_11,               EL_UNKNOWN                      },
+    { Xdecor_12,               EL_UNKNOWN                      },
+    { Xalpha_0,                        EL_CHAR('0')                    },
+    { Xalpha_1,                        EL_CHAR('1')                    },
+    { Xalpha_2,                        EL_CHAR('2')                    },
+    { Xalpha_3,                        EL_CHAR('3')                    },
+    { Xalpha_4,                        EL_CHAR('4')                    },
+    { Xalpha_5,                        EL_CHAR('5')                    },
+    { Xalpha_6,                        EL_CHAR('6')                    },
+    { Xalpha_7,                        EL_CHAR('7')                    },
+    { Xalpha_8,                        EL_CHAR('8')                    },
+    { Xalpha_9,                        EL_CHAR('9')                    },
+    { Xalpha_excla,            EL_CHAR('!')                    },
+    { Xalpha_quote,            EL_CHAR('"')                    },
+    { Xalpha_comma,            EL_CHAR(',')                    },
+    { Xalpha_minus,            EL_CHAR('-')                    },
+    { Xalpha_perio,            EL_CHAR('.')                    },
+    { Xalpha_colon,            EL_CHAR(':')                    },
+    { Xalpha_quest,            EL_CHAR('?')                    },
+    { Xalpha_a,                        EL_CHAR('A')                    },
+    { Xalpha_b,                        EL_CHAR('B')                    },
+    { Xalpha_c,                        EL_CHAR('C')                    },
+    { Xalpha_d,                        EL_CHAR('D')                    },
+    { Xalpha_e,                        EL_CHAR('E')                    },
+    { Xalpha_f,                        EL_CHAR('F')                    },
+    { Xalpha_g,                        EL_CHAR('G')                    },
+    { Xalpha_h,                        EL_CHAR('H')                    },
+    { Xalpha_i,                        EL_CHAR('I')                    },
+    { Xalpha_j,                        EL_CHAR('J')                    },
+    { Xalpha_k,                        EL_CHAR('K')                    },
+    { Xalpha_l,                        EL_CHAR('L')                    },
+    { Xalpha_m,                        EL_CHAR('M')                    },
+    { Xalpha_n,                        EL_CHAR('N')                    },
+    { Xalpha_o,                        EL_CHAR('O')                    },
+    { Xalpha_p,                        EL_CHAR('P')                    },
+    { Xalpha_q,                        EL_CHAR('Q')                    },
+    { Xalpha_r,                        EL_CHAR('R')                    },
+    { Xalpha_s,                        EL_CHAR('S')                    },
+    { Xalpha_t,                        EL_CHAR('T')                    },
+    { Xalpha_u,                        EL_CHAR('U')                    },
+    { Xalpha_v,                        EL_CHAR('V')                    },
+    { Xalpha_w,                        EL_CHAR('W')                    },
+    { Xalpha_x,                        EL_CHAR('X')                    },
+    { Xalpha_y,                        EL_CHAR('Y')                    },
+    { Xalpha_z,                        EL_CHAR('Z')                    },
+    { Xalpha_arrow_e,          EL_CHAR('>')                    },
+    { Xalpha_arrow_w,          EL_CHAR('<')                    },
+    { Xalpha_copyr,            EL_CHAR('©')                    },
+
+    { Zplayer,                 EL_PLAYER_1                     },
+    { Zplayer,                 EL_PLAYER_2                     },
+    { Zplayer,                 EL_PLAYER_3                     },
+    { Zplayer,                 EL_PLAYER_4                     },
+
+    { ZBORDER,                 EL_EMC_LEVEL_BORDER             },
+
+    { -1,                      -1                              }
+  };
 
-    event_mask = GD_EVENT_RELEASED;
+  if (!mapping_initialized)
+  {
+    int i;
 
-    gd_xoffset = toolbutton_info[i].xpos;
-    gd_yoffset = toolbutton_info[i].ypos;
-    gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
-    gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
-    gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
+    /* return "Xalpha_quest" for all undefined elements in mapping array */
+    for (i = 0; i < NUM_FILE_ELEMENTS; i++)
+      mapping_RND_to_EM[i] = Xalpha_quest;
 
-    if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
-    {
-      int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+    for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
+      mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
+       mapping_RND_to_EM_list[i].element_em;
 
-      getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
-                          &deco_bitmap, &deco_x, &deco_y);
-      deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
-      deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
-    }
+    mapping_initialized = TRUE;
+  }
 
-    gi = CreateGadget(GDI_CUSTOM_ID, id,
-                     GDI_INFO_TEXT, toolbutton_info[i].infotext,
-                     GDI_X, DX + toolbutton_info[i].x,
-                     GDI_Y, DY + toolbutton_info[i].y,
-                     GDI_WIDTH, toolbutton_info[i].width,
-                     GDI_HEIGHT, toolbutton_info[i].height,
-                     GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
-                     GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
-                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
-                     GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
-                     GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
-                     GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
-                     GDI_DECORATION_SHIFTING, 1, 1,
-                     GDI_EVENT_MASK, event_mask,
-                     GDI_CALLBACK_ACTION, HandleToolButtons,
-                     GDI_END);
+  if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
+    return mapping_RND_to_EM[element_rnd];
 
-    if (gi == NULL)
-      Error(ERR_EXIT, "cannot create gadget");
+  Error(ERR_WARN, "invalid RND level element %d", element_rnd);
 
-    tool_gadget[id] = gi;
-  }
+  return EL_UNKNOWN;
 }
 
-void FreeToolButtons()
+int map_element_EM_to_RND(int element_em)
 {
-  int i;
+  static unsigned short mapping_EM_to_RND[TILE_MAX];
+  static boolean mapping_initialized = FALSE;
 
-  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
-    FreeGadget(tool_gadget[i]);
-}
+  struct
+  {
+    int element_em;
+    int element_rnd;
+  }
+  em_object_mapping_list[] =
+  {
+    { Xblank,                  EL_EMPTY                        },
+    { Yacid_splash_eB,         EL_EMPTY                        },
+    { Yacid_splash_wB,         EL_EMPTY                        },
+
+#ifdef EM_ENGINE_BAD_ROLL
+    { Xstone_force_e,          EL_ROCK                         },
+    { Xstone_force_w,          EL_ROCK                         },
+    { Xnut_force_e,            EL_NUT                          },
+    { Xnut_force_w,            EL_NUT                          },
+    { Xspring_force_e,         EL_SPRING                       },
+    { Xspring_force_w,         EL_SPRING                       },
+    { Xemerald_force_e,                EL_EMERALD                      },
+    { Xemerald_force_w,                EL_EMERALD                      },
+    { Xdiamond_force_e,                EL_DIAMOND                      },
+    { Xdiamond_force_w,                EL_DIAMOND                      },
+    { Xbomb_force_e,           EL_BOMB                         },
+    { Xbomb_force_w,           EL_BOMB                         },
+#endif
 
-static void UnmapToolButtons()
-{
-  int i;
+    { Xstone,                  EL_ROCK                         },
+    { Xstone_pause,            EL_ROCK                         },
+    { Xstone_fall,             EL_ROCK                         },
+    { Ystone_s,                        EL_ROCK                         },
+    { Ystone_sB,               EL_ROCK                         },
+    { Ystone_e,                        EL_ROCK                         },
+    { Ystone_eB,               EL_ROCK                         },
+    { Ystone_w,                        EL_ROCK                         },
+    { Ystone_wB,               EL_ROCK                         },
+    { Xnut,                    EL_NUT                          },
+    { Xnut_pause,              EL_NUT                          },
+    { Xnut_fall,               EL_NUT                          },
+    { Ynut_s,                  EL_NUT                          },
+    { Ynut_sB,                 EL_NUT                          },
+    { Ynut_e,                  EL_NUT                          },
+    { Ynut_eB,                 EL_NUT                          },
+    { Ynut_w,                  EL_NUT                          },
+    { Ynut_wB,                 EL_NUT                          },
+    { Xbug_n,                  EL_BUG_UP                       },
+    { Xbug_e,                  EL_BUG_RIGHT                    },
+    { Xbug_s,                  EL_BUG_DOWN                     },
+    { Xbug_w,                  EL_BUG_LEFT                     },
+    { Xbug_gon,                        EL_BUG_UP                       },
+    { Xbug_goe,                        EL_BUG_RIGHT                    },
+    { Xbug_gos,                        EL_BUG_DOWN                     },
+    { Xbug_gow,                        EL_BUG_LEFT                     },
+    { Ybug_n,                  EL_BUG_UP                       },
+    { Ybug_nB,                 EL_BUG_UP                       },
+    { Ybug_e,                  EL_BUG_RIGHT                    },
+    { Ybug_eB,                 EL_BUG_RIGHT                    },
+    { Ybug_s,                  EL_BUG_DOWN                     },
+    { Ybug_sB,                 EL_BUG_DOWN                     },
+    { Ybug_w,                  EL_BUG_LEFT                     },
+    { Ybug_wB,                 EL_BUG_LEFT                     },
+    { Ybug_w_n,                        EL_BUG_UP                       },
+    { Ybug_n_e,                        EL_BUG_RIGHT                    },
+    { Ybug_e_s,                        EL_BUG_DOWN                     },
+    { Ybug_s_w,                        EL_BUG_LEFT                     },
+    { Ybug_e_n,                        EL_BUG_UP                       },
+    { Ybug_s_e,                        EL_BUG_RIGHT                    },
+    { Ybug_w_s,                        EL_BUG_DOWN                     },
+    { Ybug_n_w,                        EL_BUG_LEFT                     },
+    { Ybug_stone,              EL_ROCK                         },
+    { Ybug_spring,             EL_SPRING                       },
+    { Xtank_n,                 EL_SPACESHIP_UP                 },
+    { Xtank_e,                 EL_SPACESHIP_RIGHT              },
+    { Xtank_s,                 EL_SPACESHIP_DOWN               },
+    { Xtank_w,                 EL_SPACESHIP_LEFT               },
+    { Xtank_gon,               EL_SPACESHIP_UP                 },
+    { Xtank_goe,               EL_SPACESHIP_RIGHT              },
+    { Xtank_gos,               EL_SPACESHIP_DOWN               },
+    { Xtank_gow,               EL_SPACESHIP_LEFT               },
+    { Ytank_n,                 EL_SPACESHIP_UP                 },
+    { Ytank_nB,                        EL_SPACESHIP_UP                 },
+    { Ytank_e,                 EL_SPACESHIP_RIGHT              },
+    { Ytank_eB,                        EL_SPACESHIP_RIGHT              },
+    { Ytank_s,                 EL_SPACESHIP_DOWN               },
+    { Ytank_sB,                        EL_SPACESHIP_DOWN               },
+    { Ytank_w,                 EL_SPACESHIP_LEFT               },
+    { Ytank_wB,                        EL_SPACESHIP_LEFT               },
+    { Ytank_w_n,               EL_SPACESHIP_UP                 },
+    { Ytank_n_e,               EL_SPACESHIP_RIGHT              },
+    { Ytank_e_s,               EL_SPACESHIP_DOWN               },
+    { Ytank_s_w,               EL_SPACESHIP_LEFT               },
+    { Ytank_e_n,               EL_SPACESHIP_UP                 },
+    { Ytank_s_e,               EL_SPACESHIP_RIGHT              },
+    { Ytank_w_s,               EL_SPACESHIP_DOWN               },
+    { Ytank_n_w,               EL_SPACESHIP_LEFT               },
+    { Ytank_stone,             EL_ROCK                         },
+    { Ytank_spring,            EL_SPRING                       },
+    { Xandroid,                        EL_EMC_ANDROID                  },
+    { Xandroid_1_n,            EL_EMC_ANDROID_UP               },
+    { Xandroid_2_n,            EL_EMC_ANDROID_UP               },
+    { Xandroid_1_e,            EL_EMC_ANDROID_RIGHT            },
+    { Xandroid_2_e,            EL_EMC_ANDROID_RIGHT            },
+    { Xandroid_1_w,            EL_EMC_ANDROID_LEFT             },
+    { Xandroid_2_w,            EL_EMC_ANDROID_LEFT             },
+    { Xandroid_1_s,            EL_EMC_ANDROID_DOWN             },
+    { Xandroid_2_s,            EL_EMC_ANDROID_DOWN             },
+    { Yandroid_n,              EL_EMC_ANDROID_UP               },
+    { Yandroid_nB,             EL_EMC_ANDROID_UP               },
+    { Yandroid_ne,             EL_EMC_ANDROID_RIGHT_UP         },
+    { Yandroid_neB,            EL_EMC_ANDROID_RIGHT_UP         },
+    { Yandroid_e,              EL_EMC_ANDROID_RIGHT            },
+    { Yandroid_eB,             EL_EMC_ANDROID_RIGHT            },
+    { Yandroid_se,             EL_EMC_ANDROID_RIGHT_DOWN       },
+    { Yandroid_seB,            EL_EMC_ANDROID_RIGHT_DOWN       },
+    { Yandroid_s,              EL_EMC_ANDROID_DOWN             },
+    { Yandroid_sB,             EL_EMC_ANDROID_DOWN             },
+    { Yandroid_sw,             EL_EMC_ANDROID_LEFT_DOWN        },
+    { Yandroid_swB,            EL_EMC_ANDROID_LEFT_DOWN        },
+    { Yandroid_w,              EL_EMC_ANDROID_LEFT             },
+    { Yandroid_wB,             EL_EMC_ANDROID_LEFT             },
+    { Yandroid_nw,             EL_EMC_ANDROID_LEFT_UP          },
+    { Yandroid_nwB,            EL_EMC_ANDROID_LEFT_UP          },
+    { Xspring,                 EL_SPRING                       },
+    { Xspring_pause,           EL_SPRING                       },
+    { Xspring_e,               EL_SPRING                       },
+    { Xspring_w,               EL_SPRING                       },
+    { Xspring_fall,            EL_SPRING                       },
+    { Yspring_s,               EL_SPRING                       },
+    { Yspring_sB,              EL_SPRING                       },
+    { Yspring_e,               EL_SPRING                       },
+    { Yspring_eB,              EL_SPRING                       },
+    { Yspring_w,               EL_SPRING                       },
+    { Yspring_wB,              EL_SPRING                       },
+    { Yspring_kill_e,          EL_SPRING                       },
+    { Yspring_kill_eB,         EL_SPRING                       },
+    { Yspring_kill_w,          EL_SPRING                       },
+    { Yspring_kill_wB,         EL_SPRING                       },
+    { Xeater_n,                        EL_YAMYAM                       },
+    { Xeater_e,                        EL_YAMYAM                       },
+    { Xeater_w,                        EL_YAMYAM                       },
+    { Xeater_s,                        EL_YAMYAM                       },
+    { Yeater_n,                        EL_YAMYAM                       },
+    { Yeater_nB,               EL_YAMYAM                       },
+    { Yeater_e,                        EL_YAMYAM                       },
+    { Yeater_eB,               EL_YAMYAM                       },
+    { Yeater_s,                        EL_YAMYAM                       },
+    { Yeater_sB,               EL_YAMYAM                       },
+    { Yeater_w,                        EL_YAMYAM                       },
+    { Yeater_wB,               EL_YAMYAM                       },
+    { Yeater_stone,            EL_ROCK                         },
+    { Yeater_spring,           EL_SPRING                       },
+    { Xalien,                  EL_ROBOT                        },
+    { Xalien_pause,            EL_ROBOT                        },
+    { Yalien_n,                        EL_ROBOT                        },
+    { Yalien_nB,               EL_ROBOT                        },
+    { Yalien_e,                        EL_ROBOT                        },
+    { Yalien_eB,               EL_ROBOT                        },
+    { Yalien_s,                        EL_ROBOT                        },
+    { Yalien_sB,               EL_ROBOT                        },
+    { Yalien_w,                        EL_ROBOT                        },
+    { Yalien_wB,               EL_ROBOT                        },
+    { Yalien_stone,            EL_ROCK                         },
+    { Yalien_spring,           EL_SPRING                       },
+    { Xemerald,                        EL_EMERALD                      },
+    { Xemerald_pause,          EL_EMERALD                      },
+    { Xemerald_fall,           EL_EMERALD                      },
+    { Xemerald_shine,          EL_EMERALD                      },
+    { Yemerald_s,              EL_EMERALD                      },
+    { Yemerald_sB,             EL_EMERALD                      },
+    { Yemerald_e,              EL_EMERALD                      },
+    { Yemerald_eB,             EL_EMERALD                      },
+    { Yemerald_w,              EL_EMERALD                      },
+    { Yemerald_wB,             EL_EMERALD                      },
+    { Yemerald_eat,            EL_EMERALD                      },
+    { Yemerald_stone,          EL_ROCK                         },
+    { Xdiamond,                        EL_DIAMOND                      },
+    { Xdiamond_pause,          EL_DIAMOND                      },
+    { Xdiamond_fall,           EL_DIAMOND                      },
+    { Xdiamond_shine,          EL_DIAMOND                      },
+    { Ydiamond_s,              EL_DIAMOND                      },
+    { Ydiamond_sB,             EL_DIAMOND                      },
+    { Ydiamond_e,              EL_DIAMOND                      },
+    { Ydiamond_eB,             EL_DIAMOND                      },
+    { Ydiamond_w,              EL_DIAMOND                      },
+    { Ydiamond_wB,             EL_DIAMOND                      },
+    { Ydiamond_eat,            EL_DIAMOND                      },
+    { Ydiamond_stone,          EL_ROCK                         },
+    { Xdrip_fall,              EL_AMOEBA_DROP                  },
+    { Xdrip_stretch,           EL_AMOEBA_DROP                  },
+    { Xdrip_stretchB,          EL_AMOEBA_DROP                  },
+    { Xdrip_eat,               EL_AMOEBA_DROP                  },
+    { Ydrip_s1,                        EL_AMOEBA_DROP                  },
+    { Ydrip_s1B,               EL_AMOEBA_DROP                  },
+    { Ydrip_s2,                        EL_AMOEBA_DROP                  },
+    { Ydrip_s2B,               EL_AMOEBA_DROP                  },
+    { Xbomb,                   EL_BOMB                         },
+    { Xbomb_pause,             EL_BOMB                         },
+    { Xbomb_fall,              EL_BOMB                         },
+    { Ybomb_s,                 EL_BOMB                         },
+    { Ybomb_sB,                        EL_BOMB                         },
+    { Ybomb_e,                 EL_BOMB                         },
+    { Ybomb_eB,                        EL_BOMB                         },
+    { Ybomb_w,                 EL_BOMB                         },
+    { Ybomb_wB,                        EL_BOMB                         },
+    { Ybomb_eat,               EL_BOMB                         },
+    { Xballoon,                        EL_BALLOON                      },
+    { Yballoon_n,              EL_BALLOON                      },
+    { Yballoon_nB,             EL_BALLOON                      },
+    { Yballoon_e,              EL_BALLOON                      },
+    { Yballoon_eB,             EL_BALLOON                      },
+    { Yballoon_s,              EL_BALLOON                      },
+    { Yballoon_sB,             EL_BALLOON                      },
+    { Yballoon_w,              EL_BALLOON                      },
+    { Yballoon_wB,             EL_BALLOON                      },
+    { Xgrass,                  EL_SAND                         },
+    { Ygrass_nB,               EL_SAND                         },
+    { Ygrass_eB,               EL_SAND                         },
+    { Ygrass_sB,               EL_SAND                         },
+    { Ygrass_wB,               EL_SAND                         },
+    { Xdirt,                   EL_SAND                         },
+    { Ydirt_nB,                        EL_SAND                         },
+    { Ydirt_eB,                        EL_SAND                         },
+    { Ydirt_sB,                        EL_SAND                         },
+    { Ydirt_wB,                        EL_SAND                         },
+    { Xacid_ne,                        EL_ACID_POOL_TOPRIGHT           },
+    { Xacid_se,                        EL_ACID_POOL_BOTTOMRIGHT        },
+    { Xacid_s,                 EL_ACID_POOL_BOTTOM             },
+    { Xacid_sw,                        EL_ACID_POOL_BOTTOMLEFT         },
+    { Xacid_nw,                        EL_ACID_POOL_TOPLEFT            },
+    { Xacid_1,                 EL_ACID                         },
+    { Xacid_2,                 EL_ACID                         },
+    { Xacid_3,                 EL_ACID                         },
+    { Xacid_4,                 EL_ACID                         },
+    { Xacid_5,                 EL_ACID                         },
+    { Xacid_6,                 EL_ACID                         },
+    { Xacid_7,                 EL_ACID                         },
+    { Xacid_8,                 EL_ACID                         },
+    { Xball_1,                 EL_EMC_MAGIC_BALL               },
+    { Xball_1B,                        EL_EMC_MAGIC_BALL               },
+    { Xball_2,                 EL_EMC_MAGIC_BALL               },
+    { Xball_2B,                        EL_EMC_MAGIC_BALL               },
+    { Yball_eat,               EL_EMC_MAGIC_BALL               },
+    { Xgrow_ns,                        EL_EMC_GROW                     },
+    { Ygrow_ns_eat,            EL_EMC_GROW                     },
+    { Xgrow_ew,                        EL_EMC_GROW                     },
+    { Ygrow_ew_eat,            EL_EMC_GROW                     },
+    { Xwonderwall,             EL_MAGIC_WALL                   },
+    { XwonderwallB,            EL_MAGIC_WALL                   },
+    { Xamoeba_1,               EL_AMOEBA_WET                   },
+    { Xamoeba_2,               EL_AMOEBA_WET                   },
+    { Xamoeba_3,               EL_AMOEBA_WET                   },
+    { Xamoeba_4,               EL_AMOEBA_WET                   },
+    { Xamoeba_5,               EL_AMOEBA_WET                   },
+    { Xamoeba_6,               EL_AMOEBA_WET                   },
+    { Xamoeba_7,               EL_AMOEBA_WET                   },
+    { Xamoeba_8,               EL_AMOEBA_WET                   },
+    { Xdoor_1,                 EL_EM_GATE_1                    },
+    { Xdoor_2,                 EL_EM_GATE_2                    },
+    { Xdoor_3,                 EL_EM_GATE_3                    },
+    { Xdoor_4,                 EL_EM_GATE_4                    },
+    { Xdoor_5,                 EL_EMC_GATE_5                   },
+    { Xdoor_6,                 EL_EMC_GATE_6                   },
+    { Xdoor_7,                 EL_EMC_GATE_7                   },
+    { Xdoor_8,                 EL_EMC_GATE_8                   },
+    { Xkey_1,                  EL_EM_KEY_1                     },
+    { Xkey_2,                  EL_EM_KEY_2                     },
+    { Xkey_3,                  EL_EM_KEY_3                     },
+    { Xkey_4,                  EL_EM_KEY_4                     },
+    { Xkey_5,                  EL_EMC_KEY_5                    },
+    { Xkey_6,                  EL_EMC_KEY_6                    },
+    { Xkey_7,                  EL_EMC_KEY_7                    },
+    { Xkey_8,                  EL_EMC_KEY_8                    },
+    { Xwind_n,                 EL_BALLOON_SWITCH_UP            },
+    { Xwind_e,                 EL_BALLOON_SWITCH_RIGHT         },
+    { Xwind_s,                 EL_BALLOON_SWITCH_DOWN          },
+    { Xwind_w,                 EL_BALLOON_SWITCH_LEFT          },
+    { Xwind_nesw,              EL_BALLOON_SWITCH_ANY           },
+    { Xwind_stop,              EL_BALLOON_SWITCH_NONE          },
+    { Xexit,                   EL_EXIT_CLOSED                  },
+    { Xexit_1,                 EL_EXIT_OPEN                    },
+    { Xexit_2,                 EL_EXIT_OPEN                    },
+    { Xexit_3,                 EL_EXIT_OPEN                    },
+    { Xdynamite,               EL_DYNAMITE                     },
+    { Ydynamite_eat,           EL_DYNAMITE                     },
+    { Xdynamite_1,             EL_DYNAMITE_ACTIVE              },
+    { Xdynamite_2,             EL_DYNAMITE_ACTIVE              },
+    { Xdynamite_3,             EL_DYNAMITE_ACTIVE              },
+    { Xdynamite_4,             EL_DYNAMITE_ACTIVE              },
+    { Xbumper,                 EL_EMC_BUMPER                   },
+    { XbumperB,                        EL_EMC_BUMPER                   },
+    { Xwheel,                  EL_ROBOT_WHEEL                  },
+    { XwheelB,                 EL_ROBOT_WHEEL                  },
+    { Xswitch,                 EL_UNKNOWN                      },
+    { XswitchB,                        EL_UNKNOWN                      },
+    { Xsand,                   EL_QUICKSAND_EMPTY              },
+    { Xsand_stone,             EL_QUICKSAND_FULL               },
+    { Xsand_stonein_1,         EL_QUICKSAND_FULL               },
+    { Xsand_stonein_2,         EL_QUICKSAND_FULL               },
+    { Xsand_stonein_3,         EL_QUICKSAND_FULL               },
+    { Xsand_stonein_4,         EL_QUICKSAND_FULL               },
+    { Xsand_stonesand_1,       EL_QUICKSAND_FULL               },
+    { Xsand_stonesand_2,       EL_QUICKSAND_FULL               },
+    { Xsand_stonesand_3,       EL_QUICKSAND_FULL               },
+    { Xsand_stonesand_4,       EL_QUICKSAND_FULL               },
+    { Xsand_stoneout_1,                EL_QUICKSAND_FULL               },
+    { Xsand_stoneout_2,                EL_QUICKSAND_FULL               },
+    { Xsand_sandstone_1,       EL_QUICKSAND_FULL               },
+    { Xsand_sandstone_2,       EL_QUICKSAND_FULL               },
+    { Xsand_sandstone_3,       EL_QUICKSAND_FULL               },
+    { Xsand_sandstone_4,       EL_QUICKSAND_FULL               },
+    { Xplant,                  EL_EMC_PLANT                    },
+    { Yplant,                  EL_EMC_PLANT                    },
+    { Xlenses,                 EL_EMC_LENSES                   },
+    { Xmagnify,                        EL_EMC_MAGNIFIER                },
+    { Xdripper,                        EL_UNKNOWN                      },
+    { XdripperB,               EL_UNKNOWN                      },
+    { Xfake_blank,             EL_INVISIBLE_WALL               },
+    { Xfake_blankB,            EL_INVISIBLE_WALL               },
+    { Xfake_grass,             EL_INVISIBLE_SAND               },
+    { Xfake_grassB,            EL_INVISIBLE_SAND               },
+    { Xfake_door_1,            EL_EM_GATE_1_GRAY               },
+    { Xfake_door_2,            EL_EM_GATE_2_GRAY               },
+    { Xfake_door_3,            EL_EM_GATE_3_GRAY               },
+    { Xfake_door_4,            EL_EM_GATE_4_GRAY               },
+    { Xfake_door_5,            EL_EMC_GATE_5_GRAY              },
+    { Xfake_door_6,            EL_EMC_GATE_6_GRAY              },
+    { Xfake_door_7,            EL_EMC_GATE_7_GRAY              },
+    { Xfake_door_8,            EL_EMC_GATE_8_GRAY              },
+    { Xsteel_1,                        EL_STEELWALL                    },
+    { Xsteel_2,                        EL_UNKNOWN                      },
+    { Xsteel_3,                        EL_EMC_STEELWALL_1              },
+    { Xsteel_4,                        EL_UNKNOWN                      },
+    { Xwall_1,                 EL_WALL                         },
+    { Xwall_2,                 EL_UNKNOWN                      },
+    { Xwall_3,                 EL_UNKNOWN                      },
+    { Xwall_4,                 EL_UNKNOWN                      },
+    { Xround_wall_1,           EL_WALL_SLIPPERY                },
+    { Xround_wall_2,           EL_UNKNOWN                      },
+    { Xround_wall_3,           EL_UNKNOWN                      },
+    { Xround_wall_4,           EL_UNKNOWN                      },
+    { Xdecor_1,                        EL_UNKNOWN                      },
+    { Xdecor_2,                        EL_EMC_WALL_6                   },
+    { Xdecor_3,                        EL_EMC_WALL_4                   },
+    { Xdecor_4,                        EL_EMC_WALL_5                   },
+    { Xdecor_5,                        EL_EMC_WALL_7                   },
+    { Xdecor_6,                        EL_EMC_WALL_8                   },
+    { Xdecor_7,                        EL_UNKNOWN                      },
+    { Xdecor_8,                        EL_EMC_WALL_1                   },
+    { Xdecor_9,                        EL_EMC_WALL_2                   },
+    { Xdecor_10,               EL_EMC_WALL_3                   },
+    { Xdecor_11,               EL_UNKNOWN                      },
+    { Xdecor_12,               EL_UNKNOWN                      },
+    { Xalpha_0,                        EL_CHAR('0')                    },
+    { Xalpha_1,                        EL_CHAR('1')                    },
+    { Xalpha_2,                        EL_CHAR('2')                    },
+    { Xalpha_3,                        EL_CHAR('3')                    },
+    { Xalpha_4,                        EL_CHAR('4')                    },
+    { Xalpha_5,                        EL_CHAR('5')                    },
+    { Xalpha_6,                        EL_CHAR('6')                    },
+    { Xalpha_7,                        EL_CHAR('7')                    },
+    { Xalpha_8,                        EL_CHAR('8')                    },
+    { Xalpha_9,                        EL_CHAR('9')                    },
+    { Xalpha_excla,            EL_CHAR('!')                    },
+    { Xalpha_quote,            EL_CHAR('"')                    },
+    { Xalpha_comma,            EL_CHAR(',')                    },
+    { Xalpha_minus,            EL_CHAR('-')                    },
+    { Xalpha_perio,            EL_CHAR('.')                    },
+    { Xalpha_colon,            EL_CHAR(':')                    },
+    { Xalpha_quest,            EL_CHAR('?')                    },
+    { Xalpha_a,                        EL_CHAR('A')                    },
+    { Xalpha_b,                        EL_CHAR('B')                    },
+    { Xalpha_c,                        EL_CHAR('C')                    },
+    { Xalpha_d,                        EL_CHAR('D')                    },
+    { Xalpha_e,                        EL_CHAR('E')                    },
+    { Xalpha_f,                        EL_CHAR('F')                    },
+    { Xalpha_g,                        EL_CHAR('G')                    },
+    { Xalpha_h,                        EL_CHAR('H')                    },
+    { Xalpha_i,                        EL_CHAR('I')                    },
+    { Xalpha_j,                        EL_CHAR('J')                    },
+    { Xalpha_k,                        EL_CHAR('K')                    },
+    { Xalpha_l,                        EL_CHAR('L')                    },
+    { Xalpha_m,                        EL_CHAR('M')                    },
+    { Xalpha_n,                        EL_CHAR('N')                    },
+    { Xalpha_o,                        EL_CHAR('O')                    },
+    { Xalpha_p,                        EL_CHAR('P')                    },
+    { Xalpha_q,                        EL_CHAR('Q')                    },
+    { Xalpha_r,                        EL_CHAR('R')                    },
+    { Xalpha_s,                        EL_CHAR('S')                    },
+    { Xalpha_t,                        EL_CHAR('T')                    },
+    { Xalpha_u,                        EL_CHAR('U')                    },
+    { Xalpha_v,                        EL_CHAR('V')                    },
+    { Xalpha_w,                        EL_CHAR('W')                    },
+    { Xalpha_x,                        EL_CHAR('X')                    },
+    { Xalpha_y,                        EL_CHAR('Y')                    },
+    { Xalpha_z,                        EL_CHAR('Z')                    },
+    { Xalpha_arrow_e,          EL_CHAR('>')                    },
+    { Xalpha_arrow_w,          EL_CHAR('<')                    },
+    { Xalpha_copyr,            EL_CHAR('©')                    },
+
+    { Zplayer,                 EL_PLAYER_1                     },
+
+    { ZBORDER,                 EL_EMC_LEVEL_BORDER             },
+
+    { -1,                      -1                              }
+  };
 
-  for (i = 0; i < NUM_TOOL_BUTTONS; i++)
-    UnmapGadget(tool_gadget[i]);
-}
+  if (!mapping_initialized)
+  {
+    int i;
 
-static void HandleToolButtons(struct GadgetInfo *gi)
-{
-  request_gadget_id = gi->custom_id;
+    /* return "EL_UNKNOWN" for all undefined elements in mapping array */
+    for (i = 0; i < TILE_MAX; i++)
+      mapping_EM_to_RND[i] = EL_UNKNOWN;
+
+    for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+      mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+       em_object_mapping_list[i].element_rnd;
+
+    mapping_initialized = TRUE;
+  }
+
+  if (element_em >= 0 && element_em < TILE_MAX)
+    return mapping_EM_to_RND[element_em];
+
+  Error(ERR_WARN, "invalid EM level element %d", element_em);
+
+  return EL_UNKNOWN;
 }
 
+#endif
+
 int get_next_element(int element)
 {
   switch(element)
@@ -2899,21 +5586,51 @@ int get_next_element(int element)
   }
 }
 
+#if 0
+int el_act_dir2img(int element, int action, int direction)
+{
+  element = GFX_ELEMENT(element);
+
+  if (direction == MV_NO_MOVING)
+    return element_info[element].graphic[action];
+
+  direction = MV_DIR_BIT(direction);
+
+  return element_info[element].direction_graphic[action][direction];
+}
+#else
 int el_act_dir2img(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
   direction = MV_DIR_BIT(direction);   /* default: MV_NO_MOVING => MV_DOWN */
 
+  /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_graphic[action][direction];
 }
+#endif
 
+#if 0
+static int el_act_dir2crm(int element, int action, int direction)
+{
+  element = GFX_ELEMENT(element);
+
+  if (direction == MV_NO_MOVING)
+    return element_info[element].crumbled[action];
+
+  direction = MV_DIR_BIT(direction);
+
+  return element_info[element].direction_crumbled[action][direction];
+}
+#else
 static int el_act_dir2crm(int element, int action, int direction)
 {
   element = GFX_ELEMENT(element);
   direction = MV_DIR_BIT(direction);   /* default: MV_NO_MOVING => MV_DOWN */
 
+  /* direction_graphic[][] == graphic[] for undefined direction graphics */
   return element_info[element].direction_crumbled[action][direction];
 }
+#endif
 
 int el_act2img(int element, int action)
 {
@@ -2961,3 +5678,675 @@ int el2preimg(int element)
 
   return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
 }
+
+int getGameFrameDelay_EM(int native_em_game_frame_delay)
+{
+  int game_frame_delay_value;
+
+  game_frame_delay_value =
+    (tape.playing && tape.fast_forward ? FfwdFrameDelay :
+     GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
+     GameFrameDelay);
+
+  if (tape.playing && tape.warp_forward && !tape.pausing)
+    game_frame_delay_value = 0;
+
+  return game_frame_delay_value;
+}
+
+unsigned int InitRND(long seed)
+{
+  if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+    return InitEngineRND_EM(seed);
+  else
+    return InitEngineRND(seed);
+}
+
+#define DEBUG_EM_GFX   0
+
+void InitGraphicInfo_EM(void)
+{
+  struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
+  struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
+  int i, j, p;
+
+#if DEBUG_EM_GFX
+  if (graphic_info_em_object[0][0].bitmap == NULL)
+  {
+    /* EM graphics not yet initialized in em_open_all() */
+
+    return;
+  }
+#endif
+
+  /* always start with reliable default values */
+  for (i = 0; i < TILE_MAX; i++)
+  {
+    object_mapping[i].element_rnd = EL_UNKNOWN;
+    object_mapping[i].is_backside = FALSE;
+    object_mapping[i].action = ACTION_DEFAULT;
+    object_mapping[i].direction = MV_NO_MOVING;
+  }
+
+  /* always start with reliable default values */
+  for (p = 0; p < 2; p++)
+  {
+    for (i = 0; i < SPR_MAX; i++)
+    {
+      player_mapping[p][i].element_rnd = EL_UNKNOWN;
+      player_mapping[p][i].action = ACTION_DEFAULT;
+      player_mapping[p][i].direction = MV_NO_MOVING;
+    }
+  }
+
+  for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+  {
+    int e = em_object_mapping_list[i].element_em;
+
+    object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
+    object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
+
+    if (em_object_mapping_list[i].action != -1)
+      object_mapping[e].action = em_object_mapping_list[i].action;
+
+    if (em_object_mapping_list[i].direction != -1)
+      object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
+  }
+
+  for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
+  {
+    int a = em_player_mapping_list[i].action_em;
+    int p = em_player_mapping_list[i].player_nr;
+
+    player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
+
+    if (em_player_mapping_list[i].action != -1)
+      player_mapping[p][a].action = em_player_mapping_list[i].action;
+
+    if (em_player_mapping_list[i].direction != -1)
+      player_mapping[p][a].direction =
+       (1 << em_player_mapping_list[i].direction);
+  }
+
+  for (i = 0; i < TILE_MAX; i++)
+  {
+    int element = object_mapping[i].element_rnd;
+    int action = object_mapping[i].action;
+    int direction = object_mapping[i].direction;
+    boolean is_backside = object_mapping[i].is_backside;
+    boolean action_removing = (action == ACTION_DIGGING ||
+                              action == ACTION_SNAPPING ||
+                              action == ACTION_COLLECTING);
+    boolean action_exploding = ((action == ACTION_EXPLODING ||
+                                action == ACTION_SMASHED_BY_ROCK ||
+                                action == ACTION_SMASHED_BY_SPRING) &&
+                               element != EL_DIAMOND);
+    boolean action_active = (action == ACTION_ACTIVE);
+    boolean action_other = (action == ACTION_OTHER);
+
+    for (j = 0; j < 8; j++)
+    {
+      int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
+                              j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
+                              j < 7 ? element :
+                              i == Xdrip_stretch ? element :
+                              i == Xdrip_stretchB ? element :
+                              i == Ydrip_s1 ? element :
+                              i == Ydrip_s1B ? element :
+                              i == Xball_1B ? element :
+                              i == Xball_2 ? element :
+                              i == Xball_2B ? element :
+                              i == Yball_eat ? element :
+                              i == Ykey_1_eat ? element :
+                              i == Ykey_2_eat ? element :
+                              i == Ykey_3_eat ? element :
+                              i == Ykey_4_eat ? element :
+                              i == Ykey_5_eat ? element :
+                              i == Ykey_6_eat ? element :
+                              i == Ykey_7_eat ? element :
+                              i == Ykey_8_eat ? element :
+                              i == Ylenses_eat ? element :
+                              i == Ymagnify_eat ? element :
+                              i == Ygrass_eat ? element :
+                              i == Ydirt_eat ? element :
+                              i == Yspring_kill_e ? EL_SPRING :
+                              i == Yspring_kill_w ? EL_SPRING :
+                              i == Yemerald_stone ? EL_EMERALD :
+                              i == Ydiamond_stone ? EL_ROCK :
+                              i == Xsand_stonein_4 ? EL_EMPTY :
+                              i == Xsand_stoneout_2 ? EL_ROCK :
+                              is_backside ? EL_EMPTY :
+                              action_removing ? EL_EMPTY :
+                              element);
+      int effective_action = (j < 7 ? action :
+                             i == Xdrip_stretch ? action :
+                             i == Xdrip_stretchB ? action :
+                             i == Ydrip_s1 ? action :
+                             i == Ydrip_s1B ? action :
+                             i == Xball_1B ? action :
+                             i == Xball_2 ? action :
+                             i == Xball_2B ? action :
+                             i == Yball_eat ? action :
+                             i == Ykey_1_eat ? action :
+                             i == Ykey_2_eat ? action :
+                             i == Ykey_3_eat ? action :
+                             i == Ykey_4_eat ? action :
+                             i == Ykey_5_eat ? action :
+                             i == Ykey_6_eat ? action :
+                             i == Ykey_7_eat ? action :
+                             i == Ykey_8_eat ? action :
+                             i == Ylenses_eat ? action :
+                             i == Ymagnify_eat ? action :
+                             i == Ygrass_eat ? action :
+                             i == Ydirt_eat ? action :
+                             i == Xsand_stonein_1 ? action :
+                             i == Xsand_stonein_2 ? action :
+                             i == Xsand_stonein_3 ? action :
+                             i == Xsand_stonein_4 ? action :
+                             i == Xsand_stoneout_1 ? action :
+                             i == Xsand_stoneout_2 ? action :
+                             i == Xboom_android ? ACTION_EXPLODING :
+                             action_exploding ? ACTION_EXPLODING :
+                             action_active ? action :
+                             action_other ? action :
+                             ACTION_DEFAULT);
+      int graphic = (el_act_dir2img(effective_element, effective_action,
+                                   direction));
+      int crumbled = (el_act_dir2crm(effective_element, effective_action,
+                                    direction));
+      int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
+      int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
+      boolean has_crumbled_graphics = (base_crumbled != base_graphic);
+      struct GraphicInfo *g = &graphic_info[graphic];
+      struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+      Bitmap *src_bitmap;
+      int src_x, src_y;
+      /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
+      boolean special_animation = (action != ACTION_DEFAULT &&
+                                  g->anim_frames == 3 &&
+                                  g->anim_delay == 2 &&
+                                  g->anim_mode & ANIM_LINEAR);
+      int sync_frame = (i == Xdrip_stretch ? 7 :
+                       i == Xdrip_stretchB ? 7 :
+                       i == Ydrip_s2 ? j + 8 :
+                       i == Ydrip_s2B ? j + 8 :
+                       i == Xacid_1 ? 0 :
+                       i == Xacid_2 ? 10 :
+                       i == Xacid_3 ? 20 :
+                       i == Xacid_4 ? 30 :
+                       i == Xacid_5 ? 40 :
+                       i == Xacid_6 ? 50 :
+                       i == Xacid_7 ? 60 :
+                       i == Xacid_8 ? 70 :
+                       i == Xfake_acid_1 ? 0 :
+                       i == Xfake_acid_2 ? 10 :
+                       i == Xfake_acid_3 ? 20 :
+                       i == Xfake_acid_4 ? 30 :
+                       i == Xfake_acid_5 ? 40 :
+                       i == Xfake_acid_6 ? 50 :
+                       i == Xfake_acid_7 ? 60 :
+                       i == Xfake_acid_8 ? 70 :
+                       i == Xball_2 ? 7 :
+                       i == Xball_2B ? j + 8 :
+                       i == Yball_eat ? j + 1 :
+                       i == Ykey_1_eat ? j + 1 :
+                       i == Ykey_2_eat ? j + 1 :
+                       i == Ykey_3_eat ? j + 1 :
+                       i == Ykey_4_eat ? j + 1 :
+                       i == Ykey_5_eat ? j + 1 :
+                       i == Ykey_6_eat ? j + 1 :
+                       i == Ykey_7_eat ? j + 1 :
+                       i == Ykey_8_eat ? j + 1 :
+                       i == Ylenses_eat ? j + 1 :
+                       i == Ymagnify_eat ? j + 1 :
+                       i == Ygrass_eat ? j + 1 :
+                       i == Ydirt_eat ? j + 1 :
+                       i == Xamoeba_1 ? 0 :
+                       i == Xamoeba_2 ? 1 :
+                       i == Xamoeba_3 ? 2 :
+                       i == Xamoeba_4 ? 3 :
+                       i == Xamoeba_5 ? 0 :
+                       i == Xamoeba_6 ? 1 :
+                       i == Xamoeba_7 ? 2 :
+                       i == Xamoeba_8 ? 3 :
+                       i == Xexit_2 ? j + 8 :
+                       i == Xexit_3 ? j + 16 :
+                       i == Xdynamite_1 ? 0 :
+                       i == Xdynamite_2 ? 20 :
+                       i == Xdynamite_3 ? 40 :
+                       i == Xdynamite_4 ? 60 :
+                       i == Xsand_stonein_1 ? j + 1 :
+                       i == Xsand_stonein_2 ? j + 9 :
+                       i == Xsand_stonein_3 ? j + 17 :
+                       i == Xsand_stonein_4 ? j + 25 :
+                       i == Xsand_stoneout_1 && j == 0 ? 0 :
+                       i == Xsand_stoneout_1 && j == 1 ? 0 :
+                       i == Xsand_stoneout_1 && j == 2 ? 1 :
+                       i == Xsand_stoneout_1 && j == 3 ? 2 :
+                       i == Xsand_stoneout_1 && j == 4 ? 2 :
+                       i == Xsand_stoneout_1 && j == 5 ? 3 :
+                       i == Xsand_stoneout_1 && j == 6 ? 4 :
+                       i == Xsand_stoneout_1 && j == 7 ? 4 :
+                       i == Xsand_stoneout_2 && j == 0 ? 5 :
+                       i == Xsand_stoneout_2 && j == 1 ? 6 :
+                       i == Xsand_stoneout_2 && j == 2 ? 7 :
+                       i == Xsand_stoneout_2 && j == 3 ? 8 :
+                       i == Xsand_stoneout_2 && j == 4 ? 9 :
+                       i == Xsand_stoneout_2 && j == 5 ? 11 :
+                       i == Xsand_stoneout_2 && j == 6 ? 13 :
+                       i == Xsand_stoneout_2 && j == 7 ? 15 :
+                       i == Xboom_bug && j == 1 ? 2 :
+                       i == Xboom_bug && j == 2 ? 2 :
+                       i == Xboom_bug && j == 3 ? 4 :
+                       i == Xboom_bug && j == 4 ? 4 :
+                       i == Xboom_bug && j == 5 ? 2 :
+                       i == Xboom_bug && j == 6 ? 2 :
+                       i == Xboom_bug && j == 7 ? 0 :
+                       i == Xboom_bomb && j == 1 ? 2 :
+                       i == Xboom_bomb && j == 2 ? 2 :
+                       i == Xboom_bomb && j == 3 ? 4 :
+                       i == Xboom_bomb && j == 4 ? 4 :
+                       i == Xboom_bomb && j == 5 ? 2 :
+                       i == Xboom_bomb && j == 6 ? 2 :
+                       i == Xboom_bomb && j == 7 ? 0 :
+                       i == Xboom_android && j == 7 ? 6 :
+                       i == Xboom_1 && j == 1 ? 2 :
+                       i == Xboom_1 && j == 2 ? 2 :
+                       i == Xboom_1 && j == 3 ? 4 :
+                       i == Xboom_1 && j == 4 ? 4 :
+                       i == Xboom_1 && j == 5 ? 6 :
+                       i == Xboom_1 && j == 6 ? 6 :
+                       i == Xboom_1 && j == 7 ? 8 :
+                       i == Xboom_2 && j == 0 ? 8 :
+                       i == Xboom_2 && j == 1 ? 8 :
+                       i == Xboom_2 && j == 2 ? 10 :
+                       i == Xboom_2 && j == 3 ? 10 :
+                       i == Xboom_2 && j == 4 ? 10 :
+                       i == Xboom_2 && j == 5 ? 12 :
+                       i == Xboom_2 && j == 6 ? 12 :
+                       i == Xboom_2 && j == 7 ? 12 :
+                       special_animation && j == 4 ? 3 :
+                       effective_action != action ? 0 :
+                       j);
+
+#if DEBUG_EM_GFX
+      Bitmap *debug_bitmap = g_em->bitmap;
+      int debug_src_x = g_em->src_x;
+      int debug_src_y = g_em->src_y;
+#endif
+
+      int frame = getAnimationFrame(g->anim_frames,
+                                   g->anim_delay,
+                                   g->anim_mode,
+                                   g->anim_start_frame,
+                                   sync_frame);
+
+      getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
+                         g->double_movement && is_backside);
+
+#if 1
+      g_em->bitmap = src_bitmap;
+      g_em->src_x = src_x;
+      g_em->src_y = src_y;
+      g_em->src_offset_x = 0;
+      g_em->src_offset_y = 0;
+      g_em->dst_offset_x = 0;
+      g_em->dst_offset_y = 0;
+      g_em->width  = TILEX;
+      g_em->height = TILEY;
+
+      g_em->crumbled_bitmap = NULL;
+      g_em->crumbled_src_x = 0;
+      g_em->crumbled_src_y = 0;
+      g_em->crumbled_border_size = 0;
+
+      g_em->has_crumbled_graphics = FALSE;
+      g_em->preserve_background = FALSE;
+#endif
+
+#if 0
+      if (effective_element == EL_EMC_GRASS &&
+         effective_action == ACTION_DIGGING)
+       printf("::: %d\n", crumbled);
+#endif
+
+#if 0
+      if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
+       printf("::: empty crumbled: %d [%s], %d, %d\n",
+              effective_element, element_info[effective_element].token_name,
+              effective_action, direction);
+#endif
+
+      /* if element can be crumbled, but certain action graphics are just empty
+        space (like snapping sand with the original R'n'D graphics), do not
+        treat these empty space graphics as crumbled graphics in EMC engine */
+      if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
+      {
+       getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
+
+       g_em->has_crumbled_graphics = TRUE;
+       g_em->crumbled_bitmap = src_bitmap;
+       g_em->crumbled_src_x = src_x;
+       g_em->crumbled_src_y = src_y;
+       g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+      }
+
+#if 1
+      if (!g->double_movement && (effective_action == ACTION_FALLING ||
+                                 effective_action == ACTION_MOVING ||
+                                 effective_action == ACTION_PUSHING))
+      {
+       int move_dir =
+         (effective_action == ACTION_FALLING ? MV_DOWN : direction);
+       int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
+       int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
+       int num_steps = (i == Ydrip_s1 ||
+                        i == Ydrip_s1B ||
+                        i == Ydrip_s2 ||
+                        i == Ydrip_s2B ? 16 : 8);
+       int cx = ABS(dx) * (TILEX / num_steps);
+       int cy = ABS(dy) * (TILEY / num_steps);
+       int step_frame = (i == Ydrip_s2 ||
+                         i == Ydrip_s2B ? j + 8 : j) + 1;
+       int step = (is_backside ? step_frame : num_steps - step_frame);
+
+       if (is_backside)        /* tile where movement starts */
+       {
+         if (dx < 0 || dy < 0)
+         {
+           g_em->src_offset_x = cx * step;
+           g_em->src_offset_y = cy * step;
+         }
+         else
+         {
+           g_em->dst_offset_x = cx * step;
+           g_em->dst_offset_y = cy * step;
+         }
+       }
+       else                    /* tile where movement ends */
+       {
+         if (dx < 0 || dy < 0)
+         {
+           g_em->dst_offset_x = cx * step;
+           g_em->dst_offset_y = cy * step;
+         }
+         else
+         {
+           g_em->src_offset_x = cx * step;
+           g_em->src_offset_y = cy * step;
+         }
+       }
+
+       g_em->width  = TILEX - cx * step;
+       g_em->height = TILEY - cy * step;
+      }
+
+#if 0
+      if (effective_action == ACTION_SMASHED_BY_ROCK &&
+         element_info[effective_element].graphic[effective_action] ==
+         element_info[effective_element].graphic[ACTION_DEFAULT])
+      {
+       int move_dir = MV_DOWN;
+       int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
+       int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
+       int num_steps = 8;
+       int cx = ABS(dx) * (TILEX / num_steps);
+       int cy = ABS(dy) * (TILEY / num_steps);
+       int step_frame = j + 1;
+       int step = (is_backside ? step_frame : num_steps - step_frame);
+
+       graphic = (el_act_dir2img(EL_ROCK, ACTION_FALLING, MV_DOWN));
+       g = &graphic_info[graphic];
+       sync_frame = j;
+       frame = getAnimationFrame(g->anim_frames,
+                                 g->anim_delay,
+                                 g->anim_mode,
+                                 g->anim_start_frame,
+                                 sync_frame);
+       getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
+                           g->double_movement && is_backside);
+
+       g_em->bitmap = src_bitmap;
+       g_em->src_x = src_x;
+       g_em->src_y = src_y;
+       g_em->src_offset_x = 0;
+       g_em->src_offset_y = 0;
+       g_em->dst_offset_x = 0;
+       g_em->dst_offset_y = 0;
+
+       if (is_backside)        /* tile where movement starts */
+       {
+         if (dx < 0 || dy < 0)
+         {
+           g_em->src_offset_x = cx * step;
+           g_em->src_offset_y = cy * step;
+         }
+         else
+         {
+           g_em->dst_offset_x = cx * step;
+           g_em->dst_offset_y = cy * step;
+         }
+       }
+       else                    /* tile where movement ends */
+       {
+         if (dx < 0 || dy < 0)
+         {
+           g_em->dst_offset_x = cx * step;
+           g_em->dst_offset_y = cy * step;
+         }
+         else
+         {
+           g_em->src_offset_x = cx * step;
+           g_em->src_offset_y = cy * step;
+         }
+       }
+
+       g_em->width  = TILEX - cx * step;
+       g_em->height = TILEY - cy * step;
+
+#if 0
+       printf("::: -> '%s'\n", element_info[effective_element].token_name);
+#endif
+      }
+#endif
+
+#endif
+
+      /* create unique graphic identifier to decide if tile must be redrawn */
+      /* bit 31 - 16 (16 bit): EM style element
+        bit 15 - 12 ( 4 bit): EM style frame
+        bit 11 -  6 ( 6 bit): graphic width
+        bit  5 -  0 ( 6 bit): graphic height */
+      g_em->unique_identifier =
+       (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
+
+#if DEBUG_EM_GFX
+      if (g_em->bitmap != debug_bitmap ||
+         g_em->src_x != debug_src_x ||
+         g_em->src_y != debug_src_y ||
+         g_em->src_offset_x != 0 ||
+         g_em->src_offset_y != 0 ||
+         g_em->dst_offset_x != 0 ||
+         g_em->dst_offset_y != 0 ||
+         g_em->width != TILEX ||
+         g_em->height != TILEY)
+      {
+       static int last_i = -1;
+
+       if (i != last_i)
+       {
+         printf("\n");
+         last_i = i;
+       }
+
+       printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
+              i, element, element_info[element].token_name,
+              element_action_info[effective_action].suffix, direction);
+
+       if (element != effective_element)
+         printf(" [%d ('%s')]",
+                effective_element,
+                element_info[effective_element].token_name);
+
+       printf("\n");
+
+       if (g_em->bitmap != debug_bitmap)
+         printf("    %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
+                j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
+
+       if (g_em->src_x != debug_src_x ||
+           g_em->src_y != debug_src_y)
+         printf("    frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
+                j, (is_backside ? 'B' : 'F'),
+                g_em->src_x, g_em->src_y,
+                g_em->src_x / 32, g_em->src_y / 32,
+                debug_src_x, debug_src_y,
+                debug_src_x / 32, debug_src_y / 32);
+
+       if (g_em->src_offset_x != 0 ||
+           g_em->src_offset_y != 0 ||
+           g_em->dst_offset_x != 0 ||
+           g_em->dst_offset_y != 0)
+         printf("    %d (%d): offsets %d,%d and %d,%d should be all 0\n",
+                j, is_backside,
+                g_em->src_offset_x, g_em->src_offset_y,
+                g_em->dst_offset_x, g_em->dst_offset_y);
+
+       if (g_em->width != TILEX ||
+           g_em->height != TILEY)
+         printf("    %d (%d): size %d,%d should be %d,%d\n",
+                j, is_backside,
+                g_em->width, g_em->height, TILEX, TILEY);
+      }
+#endif
+
+    }
+  }
+
+#if 1
+  for (i = 0; i < TILE_MAX; i++)
+  {
+    for (j = 0; j < 8; j++)
+    {
+      int element = object_mapping[i].element_rnd;
+      int action = object_mapping[i].action;
+
+      if (action == ACTION_SMASHED_BY_ROCK &&
+         element_info[element].graphic[action] ==
+         element_info[element].graphic[ACTION_DEFAULT])
+      {
+       /* no separate animation for "smashed by rock" -- use rock instead */
+       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+       struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
+
+       g_em->bitmap            = g_xx->bitmap;
+       g_em->src_x             = g_xx->src_x;
+       g_em->src_y             = g_xx->src_y;
+       g_em->src_offset_x      = g_xx->src_offset_x;
+       g_em->src_offset_y      = g_xx->src_offset_y;
+       g_em->dst_offset_x      = g_xx->dst_offset_x;
+       g_em->dst_offset_y      = g_xx->dst_offset_y;
+       g_em->width             = g_xx->width;
+       g_em->height            = g_xx->height;
+
+       g_em->preserve_background = TRUE;
+      }
+    }
+  }
+#endif
+
+  for (p = 0; p < 2; p++)
+  {
+    for (i = 0; i < SPR_MAX; i++)
+    {
+      int element = player_mapping[p][i].element_rnd;
+      int action = player_mapping[p][i].action;
+      int direction = player_mapping[p][i].direction;
+
+      for (j = 0; j < 8; j++)
+      {
+       int effective_element = element;
+       int effective_action = action;
+       int graphic = (direction == MV_NO_MOVING ?
+                      el_act2img(effective_element, effective_action) :
+                      el_act_dir2img(effective_element, effective_action,
+                                     direction));
+       struct GraphicInfo *g = &graphic_info[graphic];
+       struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
+       Bitmap *src_bitmap;
+       int src_x, src_y;
+       int sync_frame = j;
+
+#if DEBUG_EM_GFX
+       Bitmap *debug_bitmap = g_em->bitmap;
+       int debug_src_x = g_em->src_x;
+       int debug_src_y = g_em->src_y;
+#endif
+
+       int frame = getAnimationFrame(g->anim_frames,
+                                     g->anim_delay,
+                                     g->anim_mode,
+                                     g->anim_start_frame,
+                                     sync_frame);
+
+       getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
+
+#if 1
+       g_em->bitmap = src_bitmap;
+       g_em->src_x = src_x;
+       g_em->src_y = src_y;
+       g_em->src_offset_x = 0;
+       g_em->src_offset_y = 0;
+       g_em->dst_offset_x = 0;
+       g_em->dst_offset_y = 0;
+       g_em->width  = TILEX;
+       g_em->height = TILEY;
+#endif
+
+#if DEBUG_EM_GFX
+       if (g_em->bitmap != debug_bitmap ||
+           g_em->src_x != debug_src_x ||
+           g_em->src_y != debug_src_y)
+       {
+         static int last_i = -1;
+
+         if (i != last_i)
+         {
+           printf("\n");
+           last_i = i;
+         }
+
+         printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
+                p, i, element, element_info[element].token_name,
+                element_action_info[effective_action].suffix, direction);
+
+         if (element != effective_element)
+           printf(" [%d ('%s')]",
+                  effective_element,
+                  element_info[effective_element].token_name);
+
+         printf("\n");
+
+         if (g_em->bitmap != debug_bitmap)
+           printf("    %d: different bitmap! (0x%08x != 0x%08x)\n",
+                  j, (int)(g_em->bitmap), (int)(debug_bitmap));
+
+         if (g_em->src_x != debug_src_x ||
+             g_em->src_y != debug_src_y)
+           printf("    frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
+                  j,
+                  g_em->src_x, g_em->src_y,
+                  g_em->src_x / 32, g_em->src_y / 32,
+                  debug_src_x, debug_src_y,
+                  debug_src_x / 32, debug_src_y / 32);
+       }
+#endif
+
+      }
+    }
+  }
+
+#if DEBUG_EM_GFX
+  exit(0);
+#endif
+}
index 022473a95dba8be9b015f17b144c55867e8071ed..f41b0f83308646597b2ce278531ed6bb77c087ca 100644 (file)
 #define DOOR_ACTION_2          (DOOR_OPEN_2 | DOOR_CLOSE_2)
 #define DOOR_ACTION            (DOOR_ACTION_1 | DOOR_ACTION_2)
 #define DOOR_COPY_BACK         (1 << 4)
-#define DOOR_NO_DELAY          (1 << 5)
-#define DOOR_GET_STATE         (1 << 6)
-#define DOOR_SET_STATE         (1 << 7)
+#define DOOR_NO_COPY_BACK      (1 << 5)
+#define DOOR_NO_DELAY          (1 << 6)
+#define DOOR_GET_STATE         (1 << 7)
+#define DOOR_SET_STATE         (1 << 8)
 
 /* for Request */
 #define REQ_ASK                        (1 << 0)
-#define REQ_OPEN               (1 << 1)
-#define REQ_CLOSE              (1 << 2)
-#define REQ_CONFIRM            (1 << 3)
+#define REQ_CONFIRM            (1 << 1)
+#define REQ_PLAYER             (1 << 2)
+#define REQ_STAY_OPEN          (1 << 3)
 #define REQ_STAY_CLOSED                (1 << 4)
-#define REQ_STAY_OPEN          (1 << 5)
-#define REQ_PLAYER             (1 << 6)
+#define REQ_REOPEN             (1 << 5)
 
-#define REQUEST_WAIT_FOR       (REQ_ASK | REQ_CONFIRM | REQ_PLAYER)
+#define REQUEST_WAIT_FOR_INPUT (REQ_ASK | REQ_CONFIRM | REQ_PLAYER)
 
 void DumpTile(int, int);
 
@@ -85,6 +85,7 @@ void DrawAllPlayers(void);
 void DrawPlayerField(int, int);
 void DrawPlayer(struct PlayerInfo *);
 
+void getGraphicSourceExt(int, int, Bitmap **, int *, int *, boolean);
 void getGraphicSource(int, int, Bitmap **, int *, int *);
 void DrawGraphic(int, int, int, int);
 void DrawGraphicExt(DrawBuffer *, int, int, int, int);
@@ -95,8 +96,6 @@ void DrawMiniGraphic(int, int, int);
 void getMiniGraphicSource(int, Bitmap **, int *, int *);
 void DrawMiniGraphicExt(DrawBuffer *, int, int, int);
 
-void DrawGraphicShifted(int, int, int, int, int, int, int, int);
-void DrawGraphicShiftedThruMask(int, int, int, int, int, int, int);
 void DrawScreenElementExt(int, int, int, int, int, int, int);
 void DrawLevelElementExt(int, int, int, int, int, int, int);
 void DrawScreenElementShifted(int, int, int, int, int, int);
@@ -137,6 +136,9 @@ void UndrawSpecialEditorDoor();
 void CreateToolButtons();
 void FreeToolButtons();
 
+int map_element_RND_to_EM(int);
+int map_element_EM_to_RND(int);
+
 int get_next_element(int);
 int el_act_dir2img(int, int, int);
 int el_act2img(int, int);
@@ -146,4 +148,7 @@ int el2img(int);
 int el2edimg(int);
 int el2preimg(int);
 
+unsigned int InitRND(long);
+void InitGraphicInfo_EM(void);
+
 #endif /* TOOLS_H */