rocks_n_diamonds-1.0
authorHolger Schemel <info@artsoft.org>
Wed, 9 Apr 1997 22:27:35 +0000 (00:27 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:30:16 +0000 (10:30 +0200)
23 files changed:
CHANGES
src/Makefile
src/buttons.c
src/buttons.h
src/editor.c
src/events.c
src/events.h
src/files.c
src/files.h
src/game.c
src/game.h
src/init.c
src/init.h
src/main.c
src/main.h
src/misc.c
src/misc.h
src/screens.c
src/screens.h
src/tape.c [new file with mode: 0644]
src/tape.h [new file with mode: 0644]
src/tools.c
src/tools.h

diff --git a/CHANGES b/CHANGES
index 5ad2b64..441f3d0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,23 @@
 
+Release Version 1.0 [9 APR 97]
+------------------------------
+       - the game now contains many really playable levels,
+         not only a few levels for testing
+       - the game is now even better playable by keyboard
+         (now you have the same gameplay functionality
+         compared to playing with a joystick. Especially
+         there are diagonal directions with keyboard playing
+         and the fire buttons are mapped to the shift keys)
+       - a lot of new elements for better emulation of levels
+         from the games "Boulderdash", "Emerald Mine" and
+         "Sokoban". New elements to build "Dynablaster" style
+         levels.
+       - enhanced functionality of the level tape recorder
+         to make it possible to go on with a game at any tape
+         position
+
 Prerelease Version 0.9b [4 NOV 95]
-------------------------------------
+----------------------------------
        - the game is now completely Freeware
        - the game is now better playable by keyboard
          (in the last version, the player was making more than
index 7333fb2..273cecd 100644 (file)
@@ -22,16 +22,15 @@ CONFIG = $(GAME_DIR) $(SOUNDS) $(JOYSTICK)  \
         $(SCORE_ENTRIES) $(XPM_INCLUDE_FILE)
 
 # DEBUG = -DDEBUG -g -ansi -pedantic -Wall
-DEBUG = -DDEBUG -g -Wall
-DEBUG = -O6
+DEBUG = -DDEBUG -g -Wall
+DEBUG = -O6
 
 # SYSTEM = -Aa -D_HPUX_SOURCE -Dhpux   # for HP-UX (obsolete)
 # SYSTEM = -DSYSV -Ae                  # for HP-UX
 # SYSTEM = -DSYSV                      # for systems without 'usleep()'
 # INCL = -I/usr/include/X11R5          # for HP-UX and others
-# LIBS = -lXpm -lX11 -lm
 # LIBS = -L/usr/lib/X11R5 -lXpm -lX11 -lm # for HP-UX and others
-LIBS = -lXpm -lXpm -lXpm -lX11 -lm     # triple -lXpm; else I got an error...
+LIBS = -L/usr/X11R6/lib -lXpm -lX11 -lm
 
 # CFLAGS = -O2 $(CONFIG) $(SYSTEM)
 CFLAGS = $(DEBUG) $(CONFIG) $(SYSTEM) $(INCL)
@@ -46,6 +45,7 @@ SRCS =        main.c          \
        editor.c        \
        buttons.c       \
        files.c         \
+       tape.c          \
        sound.c
 
 OBJS = main.o          \
@@ -58,6 +58,7 @@ OBJS =        main.o          \
        editor.o        \
        buttons.o       \
        files.o         \
+       tape.o          \
        sound.o
 
 all:   $(OBJS)
@@ -68,10 +69,3 @@ all: $(OBJS)
 
 clean:
        $(RM) $(OBJS)
-
-depend:
-       for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend
-
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
index 8b82545..7b0279e 100644 (file)
@@ -16,6 +16,7 @@
 #include "tools.h"
 #include "misc.h"
 #include "editor.h"
+#include "tape.h"
 
 /****************************************************************/
 /********** drawing buttons and corresponding displays **********/
@@ -24,7 +25,7 @@
 void DrawVideoDisplay(unsigned long state, unsigned long value)
 {
   int i;
-  int part1 = 0, part2 = 1;
+  int part_label = 0, part_symbol = 1;
   int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
   static char *monatsname[12] =
   {
@@ -33,55 +34,55 @@ void DrawVideoDisplay(unsigned long state, unsigned long value)
   };
   static int video_pos[10][2][4] =
   {
-    VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
-    VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE,
-    VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
-    VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE,
-
-    VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
-    VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE,
-    VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
-    VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE,
-
-    VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
-    VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE,
-    VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
-    VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE,
-
-    VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
-    VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE,
-    VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
-    VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE,
-
-    0,0,
-    0,0,
-    VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
-    VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE,
-
-    VIDEO_BUTTON_PLAY_XPOS, VIDEO_BUTTON_ANY_YPOS,
-    VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
-    0,0,
-    0,0,
-
-    VIDEO_BUTTON_REC_XPOS, VIDEO_BUTTON_ANY_YPOS,
-    VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
-    0,0,
-    0,0,
-
-    VIDEO_BUTTON_PAUSE_XPOS, VIDEO_BUTTON_ANY_YPOS,
-    VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
-    0,0,
-    0,0,
-
-    VIDEO_BUTTON_STOP_XPOS, VIDEO_BUTTON_ANY_YPOS,
-    VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
-    0,0,
-    0,0,
-
-    VIDEO_BUTTON_EJECT_XPOS, VIDEO_BUTTON_ANY_YPOS,
-    VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
-    0,0,
-    0,0
+    {{ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
+       VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE },
+     { VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
+       VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE }},
+
+    {{ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
+       VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE },
+     { VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
+       VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE }},
+
+    {{ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
+       VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE },
+     { VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
+       VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE }},
+
+    {{ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
+       VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE },
+     { VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
+       VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE }},
+
+    {{ 0,0,
+       0,0 },
+     { VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
+       VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE }},
+
+    {{ VIDEO_BUTTON_PLAY_XPOS, VIDEO_BUTTON_ANY_YPOS,
+       VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE },
+     { 0,0,
+       0,0 }},
+
+    {{ VIDEO_BUTTON_REC_XPOS, VIDEO_BUTTON_ANY_YPOS,
+       VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE },
+     { 0,0,
+       0,0 }},
+
+    {{ VIDEO_BUTTON_PAUSE_XPOS, VIDEO_BUTTON_ANY_YPOS,
+       VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE },
+     { 0,0,
+       0,0 }},
+
+    {{ VIDEO_BUTTON_STOP_XPOS, VIDEO_BUTTON_ANY_YPOS,
+       VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE },
+     { 0,0,
+       0,0 }},
+
+    {{ VIDEO_BUTTON_EJECT_XPOS, VIDEO_BUTTON_ANY_YPOS,
+       VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE },
+     { 0,0,
+       0,0 }}
   };
 
   for(i=0;i<20;i++)
@@ -95,25 +96,38 @@ void DrawVideoDisplay(unsigned long state, unsigned long value)
       else
        cx = DOOR_GFX_PAGEX3;   /* i gerade => STATE_OFF / PRESS_ON */
 
-      if (video_pos[pos][part1][0])
+      if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY)
        XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-                 cx + video_pos[pos][part1][xpos],
-                 cy + video_pos[pos][part1][ypos],
-                 video_pos[pos][part1][xsize],
-                 video_pos[pos][part1][ysize],
-                 VX + video_pos[pos][part1][xpos],
-                 VY + video_pos[pos][part1][ypos]);
-      if (video_pos[pos][part2][0])
+                 cx + video_pos[pos][part_label][xpos],
+                 cy + video_pos[pos][part_label][ypos],
+                 video_pos[pos][part_label][xsize],
+                 video_pos[pos][part_label][ysize],
+                 VX + video_pos[pos][part_label][xpos],
+                 VY + video_pos[pos][part_label][ypos]);
+      if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY)
        XCopyArea(display,pix[PIX_DOOR],drawto,gc,
-                 cx + video_pos[pos][part2][xpos],
-                 cy + video_pos[pos][part2][ypos],
-                 video_pos[pos][part2][xsize],
-                 video_pos[pos][part2][ysize],
-                 VX + video_pos[pos][part2][xpos],
-                 VY + video_pos[pos][part2][ypos]);
+                 cx + video_pos[pos][part_symbol][xpos],
+                 cy + video_pos[pos][part_symbol][ypos],
+                 video_pos[pos][part_symbol][xsize],
+                 video_pos[pos][part_symbol][ysize],
+                 VX + video_pos[pos][part_symbol][xpos],
+                 VY + video_pos[pos][part_symbol][ypos]);
     }
   }
 
+  if (state & VIDEO_STATE_FFWD_ON)
+  {
+    int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2;
+
+    XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+             cx + VIDEO_PLAY_SYMBOL_XPOS,
+             cy + VIDEO_PLAY_SYMBOL_YPOS,
+             VIDEO_PLAY_SYMBOL_XSIZE - 2,
+             VIDEO_PLAY_SYMBOL_YSIZE,
+             VX + VIDEO_PLAY_SYMBOL_XPOS - 9,
+             VY + VIDEO_PLAY_SYMBOL_YPOS);
+  }
+
   if (state & VIDEO_STATE_DATE_ON)
   {
     int tag = value % 100;
@@ -161,7 +175,7 @@ void DrawCompleteVideoDisplay()
   if (tape.date && tape.length)
   {
     DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
-    DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+    DrawVideoDisplay(VIDEO_STATE_TIME_ON,tape.length_seconds);
   }
 
   XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
@@ -174,7 +188,7 @@ void DrawSoundDisplay(unsigned long state)
 
   pos = (state & BUTTON_SOUND_MUSIC ? SOUND_BUTTON_MUSIC_XPOS :
         state & BUTTON_SOUND_LOOPS ? SOUND_BUTTON_LOOPS_XPOS :
-        SOUND_BUTTON_SOUND_XPOS);
+        SOUND_BUTTON_SIMPLE_XPOS);
 
   if (state & BUTTON_ON)
     cy -= SOUND_BUTTON_YSIZE;
@@ -250,23 +264,23 @@ void DrawEditButton(unsigned long state)
   int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY2;
   static int edit_pos[6][4] =
   {
-    ED_BUTTON_CTRL_XPOS,ED_BUTTON_CTRL_YPOS,
-    ED_BUTTON_CTRL_XSIZE,ED_BUTTON_CTRL_YSIZE,
+   {ED_BUTTON_CTRL_XPOS,ED_BUTTON_CTRL_YPOS,
+    ED_BUTTON_CTRL_XSIZE,ED_BUTTON_CTRL_YSIZE},
 
-    ED_BUTTON_FILL_XPOS,ED_BUTTON_FILL_YPOS,
-    ED_BUTTON_FILL_XSIZE,ED_BUTTON_FILL_YSIZE,
+   {ED_BUTTON_FILL_XPOS,ED_BUTTON_FILL_YPOS,
+    ED_BUTTON_FILL_XSIZE,ED_BUTTON_FILL_YSIZE},
 
-    ED_BUTTON_LEFT_XPOS,ED_BUTTON_LEFT_YPOS,
-    ED_BUTTON_LEFT_XSIZE,ED_BUTTON_LEFT_YSIZE,
+   {ED_BUTTON_LEFT_XPOS,ED_BUTTON_LEFT_YPOS,
+    ED_BUTTON_LEFT_XSIZE,ED_BUTTON_LEFT_YSIZE},
 
-    ED_BUTTON_UP_XPOS,ED_BUTTON_UP_YPOS,
-    ED_BUTTON_UP_XSIZE,ED_BUTTON_UP_YSIZE,
+   {ED_BUTTON_UP_XPOS,ED_BUTTON_UP_YPOS,
+    ED_BUTTON_UP_XSIZE,ED_BUTTON_UP_YSIZE},
 
-    ED_BUTTON_DOWN_XPOS,ED_BUTTON_DOWN_YPOS,
-    ED_BUTTON_DOWN_XSIZE,ED_BUTTON_DOWN_YSIZE,
+   {ED_BUTTON_DOWN_XPOS,ED_BUTTON_DOWN_YPOS,
+    ED_BUTTON_DOWN_XSIZE,ED_BUTTON_DOWN_YSIZE},
 
-    ED_BUTTON_RIGHT_XPOS,ED_BUTTON_RIGHT_YPOS,
-    ED_BUTTON_RIGHT_XSIZE,ED_BUTTON_RIGHT_YSIZE
+   {ED_BUTTON_RIGHT_XPOS,ED_BUTTON_RIGHT_YPOS,
+    ED_BUTTON_RIGHT_XSIZE,ED_BUTTON_RIGHT_YSIZE}
   };
 
   if (state & ED_BUTTON_PRESSED)
@@ -294,17 +308,17 @@ void DrawCtrlButton(unsigned long state)
   int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY1+80;
   static int edit_pos[4][4] =
   {
-    ED_BUTTON_EDIT_XPOS,ED_BUTTON_EDIT_YPOS,
-    ED_BUTTON_EDIT_XSIZE,ED_BUTTON_EDIT_YSIZE,
+   {ED_BUTTON_EDIT_XPOS,ED_BUTTON_EDIT_YPOS,
+    ED_BUTTON_EDIT_XSIZE,ED_BUTTON_EDIT_YSIZE},
 
-    ED_BUTTON_CLEAR_XPOS,ED_BUTTON_CLEAR_YPOS,
-    ED_BUTTON_CLEAR_XSIZE,ED_BUTTON_CLEAR_YSIZE,
+   {ED_BUTTON_CLEAR_XPOS,ED_BUTTON_CLEAR_YPOS,
+    ED_BUTTON_CLEAR_XSIZE,ED_BUTTON_CLEAR_YSIZE},
 
-    ED_BUTTON_UNDO_XPOS,ED_BUTTON_UNDO_YPOS,
-    ED_BUTTON_UNDO_XSIZE,ED_BUTTON_UNDO_YSIZE,
+   {ED_BUTTON_UNDO_XPOS,ED_BUTTON_UNDO_YPOS,
+    ED_BUTTON_UNDO_XSIZE,ED_BUTTON_UNDO_YSIZE},
 
-    ED_BUTTON_EXIT_XPOS,ED_BUTTON_EXIT_YPOS,
-    ED_BUTTON_EXIT_XSIZE,ED_BUTTON_EXIT_YSIZE
+   {ED_BUTTON_EXIT_XPOS,ED_BUTTON_EXIT_YPOS,
+    ED_BUTTON_EXIT_XSIZE,ED_BUTTON_EXIT_YSIZE}
   };
 
   if (state & ED_BUTTON_PRESSED)
@@ -332,14 +346,14 @@ void DrawElemButton(int button_nr, int button_state)
   int from_x, from_y, to_x,to_y, size_x, size_y;
   static int edit_pos[3][4] =
   {
-    ED_BUTTON_EUP_XPOS,ED_BUTTON_EUP_YPOS,
-    ED_BUTTON_EUP_XSIZE,ED_BUTTON_EUP_YSIZE,
+   {ED_BUTTON_EUP_XPOS,ED_BUTTON_EUP_YPOS,
+    ED_BUTTON_EUP_XSIZE,ED_BUTTON_EUP_YSIZE},
 
-    ED_BUTTON_EDOWN_XPOS,ED_BUTTON_EDOWN_YPOS,
-    ED_BUTTON_EDOWN_XSIZE,ED_BUTTON_EDOWN_YSIZE,
+   {ED_BUTTON_EDOWN_XPOS,ED_BUTTON_EDOWN_YPOS,
+    ED_BUTTON_EDOWN_XSIZE,ED_BUTTON_EDOWN_YSIZE},
 
-    ED_BUTTON_ELEM_XPOS,ED_BUTTON_ELEM_YPOS,
-    ED_BUTTON_ELEM_XSIZE,ED_BUTTON_ELEM_YSIZE
+   {ED_BUTTON_ELEM_XPOS,ED_BUTTON_ELEM_YPOS,
+    ED_BUTTON_ELEM_XSIZE,ED_BUTTON_ELEM_YSIZE}
   };
 
   if (button_nr<ED_BUTTON_ELEM)
@@ -500,9 +514,9 @@ int CheckSoundButtons(int mx, int my, int button)
   static BOOL pressed = FALSE;
   int sound_state[3];
 
-  sound_state[0] = BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on);
-  sound_state[1] = BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on);
-  sound_state[2] = BUTTON_SOUND_SOUND | (BUTTON_ON * sound_on);
+  sound_state[0] = BUTTON_SOUND_MUSIC  | (BUTTON_ON * sound_music_on);
+  sound_state[1] = BUTTON_SOUND_LOOPS  | (BUTTON_ON * sound_loops_on);
+  sound_state[2] = BUTTON_SOUND_SIMPLE | (BUTTON_ON * sound_simple_on);
 
   if (button)
   {
index 98ac5ca..7d4153c 100644 (file)
 
 #include "main.h"
 
+/* tags to draw video display labels or symbols only */
+#define VIDEO_DISPLAY_DEFAULT          0
+#define VIDEO_DISPLAY_LABEL_ONLY       1
+#define VIDEO_DISPLAY_SYMBOL_ONLY      2
+
 /* some positions in the video tape control window */
 #define VIDEO_DISPLAY1_XPOS    5
 #define VIDEO_DISPLAY1_YPOS    5
@@ -56,9 +61,9 @@
 #define VIDEO_PLAY_LABEL_YPOS  (VIDEO_DISPLAY2_YPOS)
 #define VIDEO_PLAY_LABEL_XSIZE 22
 #define VIDEO_PLAY_LABEL_YSIZE 12
-#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS+50)
+#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS+52)
 #define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PLAY_SYMBOL_XSIZE        13
+#define VIDEO_PLAY_SYMBOL_XSIZE        11
 #define VIDEO_PLAY_SYMBOL_YSIZE        13
 #define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
 #define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS+20)
@@ -66,7 +71,7 @@
 #define VIDEO_PAUSE_LABEL_YSIZE        8
 #define VIDEO_PAUSE_SYMBOL_XPOS        (VIDEO_DISPLAY2_XPOS+35)
 #define VIDEO_PAUSE_SYMBOL_YPOS        (VIDEO_DISPLAY2_YPOS)
-#define VIDEO_PAUSE_SYMBOL_XSIZE 13
+#define VIDEO_PAUSE_SYMBOL_XSIZE 17
 #define VIDEO_PAUSE_SYMBOL_YSIZE 13
 #define VIDEO_TIME_XPOS                (VIDEO_DISPLAY2_XPOS+38)
 #define VIDEO_TIME_YPOS                (VIDEO_DISPLAY2_YPOS+14)
 #define VIDEO_PRESS_EJECT_OFF  (1L<<19)
 #define VIDEO_PRESS_EJECT      (VIDEO_PRESS_EJECT_OFF  | VIDEO_PRESS_EJECT_ON)
 
+/* special */
+#define VIDEO_STATE_FFWD_OFF   ((1L<<20) | VIDEO_STATE_PAUSE_OFF)
+#define VIDEO_STATE_FFWD_ON    (1L<<21)
+#define VIDEO_STATE_FFWD       (VIDEO_STATE_FFWD_OFF   | VIDEO_STATE_FFWD_ON)
+
 #define BUTTON_VIDEO_EJECT     1
 #define BUTTON_VIDEO_STOP      2
 #define BUTTON_VIDEO_PAUSE     3
 #define VIDEO_STATE_OFF                (VIDEO_STATE_PLAY_OFF   |       \
                                 VIDEO_STATE_REC_OFF    |       \
                                 VIDEO_STATE_PAUSE_OFF  |       \
+                                VIDEO_STATE_FFWD_OFF   |       \
                                 VIDEO_STATE_DATE_OFF   |       \
                                 VIDEO_STATE_TIME_OFF)
 #define VIDEO_PRESS_OFF                (VIDEO_PRESS_PLAY_OFF   |       \
 #define VIDEO_STATE_ON         (VIDEO_STATE_PLAY_ON    |       \
                                 VIDEO_STATE_REC_ON     |       \
                                 VIDEO_STATE_PAUSE_ON   |       \
+                                VIDEO_STATE_FFWD_ON    |       \
                                 VIDEO_STATE_DATE_ON    |       \
                                 VIDEO_STATE_TIME_ON)
 #define VIDEO_PRESS_ON         (VIDEO_PRESS_PLAY_ON    |       \
 #define SOUND_CONTROL_XPOS     5
 #define SOUND_CONTROL_YPOS     245
 #define SOUND_CONTROL_XSIZE    90
-#define SOUND_CONTROL_YSIZE    (SOUND_BUTTON_YSIZE)
-#define SOUND_BUTTON_MUSIC_XPOS        (SOUND_CONTROL_XPOS + 0 * SOUND_BUTTON_XSIZE)
-#define SOUND_BUTTON_LOOPS_XPOS        (SOUND_CONTROL_XPOS + 1 * SOUND_BUTTON_XSIZE)
-#define SOUND_BUTTON_SOUND_XPOS        (SOUND_CONTROL_XPOS + 2 * SOUND_BUTTON_XSIZE)
-#define SOUND_BUTTON_ANY_YPOS  (SOUND_CONTROL_YPOS)
+#define SOUND_CONTROL_YSIZE     (SOUND_BUTTON_YSIZE)
+#define SOUND_BUTTON_MUSIC_XPOS         (SOUND_CONTROL_XPOS + 0 * SOUND_BUTTON_XSIZE)
+#define SOUND_BUTTON_LOOPS_XPOS         (SOUND_CONTROL_XPOS + 1 * SOUND_BUTTON_XSIZE)
+#define SOUND_BUTTON_SIMPLE_XPOS (SOUND_CONTROL_XPOS + 2 * SOUND_BUTTON_XSIZE)
+#define SOUND_BUTTON_ANY_YPOS   (SOUND_CONTROL_YPOS)
 
 #define ON_SOUND_BUTTON(x,y)   ((x)>=(DX+SOUND_CONTROL_XPOS) &&        \
                                 (x)< (DX+SOUND_CONTROL_XPOS +          \
 /* values for sound control */
 #define BUTTON_SOUND_MUSIC     (1L<<0)
 #define BUTTON_SOUND_LOOPS     (1L<<1)
-#define BUTTON_SOUND_SOUND     (1L<<2)
+#define BUTTON_SOUND_SIMPLE    (1L<<2)
 #define BUTTON_RELEASED                0
 #define BUTTON_PRESSED         (1L<<3)
 #define BUTTON_OFF             0
 #define BUTTON_ON              (1L<<4)
-#define BUTTON_SOUND_MUSIC_OFF (BUTTON_SOUND_MUSIC | BUTTON_OFF)
-#define BUTTON_SOUND_LOOPS_OFF (BUTTON_SOUND_LOOPS | BUTTON_OFF)
-#define BUTTON_SOUND_SOUND_OFF (BUTTON_SOUND_SOUND | BUTTON_OFF)
-#define BUTTON_SOUND_MUSIC_ON  (BUTTON_SOUND_MUSIC | BUTTON_ON)
-#define BUTTON_SOUND_LOOPS_ON  (BUTTON_SOUND_LOOPS | BUTTON_ON)
-#define BUTTON_SOUND_SOUND_ON  (BUTTON_SOUND_SOUND | BUTTON_ON)
+#define BUTTON_SOUND_MUSIC_OFF (BUTTON_SOUND_MUSIC  | BUTTON_OFF)
+#define BUTTON_SOUND_LOOPS_OFF (BUTTON_SOUND_LOOPS  | BUTTON_OFF)
+#define BUTTON_SOUND_SIMPLE_OFF        (BUTTON_SOUND_SIMPLE | BUTTON_OFF)
+#define BUTTON_SOUND_MUSIC_ON  (BUTTON_SOUND_MUSIC  | BUTTON_ON)
+#define BUTTON_SOUND_LOOPS_ON  (BUTTON_SOUND_LOOPS  | BUTTON_ON)
+#define BUTTON_SOUND_SIMPLE_ON (BUTTON_SOUND_SIMPLE | BUTTON_ON)
 
 
 /* some positions in the game control window */
index 7c49768..871eafa 100644 (file)
@@ -29,6 +29,61 @@ static int new_element3 = EL_ERDREICH;
 int element_shift;
 int editor_element[] =
 {
+  EL_CHAR_A + ('B' - 'A'),
+  EL_CHAR_A + ('O' - 'A'),
+  EL_CHAR_A + ('U' - 'A'),
+  EL_CHAR_A + ('L' - 'A'),
+
+  EL_CHAR_MINUS,
+  EL_CHAR_A + ('D' - 'A'),
+  EL_CHAR_A + ('E' - 'A'),
+  EL_CHAR_A + ('R' - 'A'),
+
+  EL_CHAR_A + ('D' - 'A'),
+  EL_CHAR_A + ('A' - 'A'),
+  EL_CHAR_A + ('S' - 'A'),
+  EL_CHAR_A + ('H' - 'A'),
+
+  EL_SPIELFIGUR,
+  EL_LEERRAUM,
+  EL_ERDREICH,
+  EL_BETON,
+
+  EL_FELSBODEN,
+  EL_SIEB2_LEER,
+  EL_AUSGANG_ZU,
+  EL_AUSGANG_AUF,
+
+  EL_EDELSTEIN_BD,
+  EL_BUTTERFLY_O,
+  EL_FIREFLY_O,
+  EL_FELSBROCKEN,
+
+  EL_BUTTERFLY_L,
+  EL_FIREFLY_L,
+  EL_BUTTERFLY_R,
+  EL_FIREFLY_R,
+
+  EL_AMOEBE_BD,
+  EL_BUTTERFLY_U,
+  EL_FIREFLY_U,
+  EL_LEERRAUM,
+
+  EL_CHAR_A + ('E' - 'A'),
+  EL_CHAR_A + ('M' - 'A'),
+  EL_CHAR_A + ('E' - 'A'),
+  EL_CHAR_MINUS,
+
+  EL_CHAR_A + ('R' - 'A'),
+  EL_CHAR_A + ('A' - 'A'),
+  EL_CHAR_A + ('L' - 'A'),
+  EL_CHAR_A + ('D' - 'A'),
+
+  EL_CHAR_A + ('M' - 'A'),
+  EL_CHAR_A + ('I' - 'A'),
+  EL_CHAR_A + ('N' - 'A'),
+  EL_CHAR_A + ('E' - 'A'),
+
   EL_SPIELFIGUR,
   EL_LEERRAUM,
   EL_ERDREICH,
@@ -36,70 +91,54 @@ int editor_element[] =
 
   EL_BETON,
   EL_MAUERWERK,
-  EL_MAUER_LEBT,
   EL_FELSBODEN,
-
   EL_SIEB_LEER,
-  EL_SIEB2_LEER,
-  EL_KOKOSNUSS,
-  EL_BOMBE,
 
   EL_EDELSTEIN,
   EL_DIAMANT,
-  EL_EDELSTEIN2,
-  EL_EDELSTEIN3,
+  EL_KOKOSNUSS,
+  EL_BOMBE,
 
+  EL_ERZ_EDEL,
+  EL_ERZ_DIAM,
   EL_MORAST_LEER,
   EL_MORAST_VOLL,
+
+  EL_DYNAMIT_AUS,
+  EL_DYNAMIT,
   EL_AUSGANG_ZU,
   EL_AUSGANG_AUF,
 
-  EL_KAEFER,
-  EL_FLIEGER,
   EL_MAMPFER,
-  EL_MAMPFER2,
-
+  EL_KAEFER_O,
+  EL_FLIEGER_O,
   EL_ZOMBIE,
-  EL_PACMAN,
-  EL_DYNAMIT_AUS,
-  EL_DYNAMIT,
+
+  EL_KAEFER_L,
+  EL_FLIEGER_L,
+  EL_KAEFER_R,
+  EL_FLIEGER_R,
+
+  EL_ABLENK_AUS,
+  EL_KAEFER_U,
+  EL_FLIEGER_U,
+  EL_UNSICHTBAR,
 
   EL_BADEWANNE1,
   EL_SALZSAEURE,
   EL_BADEWANNE2,
-  EL_BADEWANNE,
+  EL_LEERRAUM,
 
   EL_BADEWANNE3,
   EL_BADEWANNE4,
   EL_BADEWANNE5,
-  EL_UNSICHTBAR,
+  EL_LEERRAUM,
 
   EL_TROPFEN,
   EL_AMOEBE_TOT,
   EL_AMOEBE_NASS,
   EL_AMOEBE_NORM,
 
-  EL_AMOEBE_VOLL,
-  EL_LIFE,
-  EL_LIFE_ASYNC,
-  EL_ABLENK_AUS,
-
-  EL_ERZ_EDEL,
-  EL_ERZ_DIAM,
-  EL_ERZ_EDEL2,
-  EL_ERZ_EDEL3,
-
-  EL_ZEIT_VOLL,
-  EL_ZEIT_LEER,
-
-  EL_DYNABOMB_NR,
-  EL_DYNABOMB_SZ,
-
-/*
-  EL_BIRNE_AUS,
-  EL_BIRNE_EIN,
-*/
-
   EL_SCHLUESSEL1,
   EL_SCHLUESSEL2,
   EL_SCHLUESSEL3,
@@ -115,20 +154,72 @@ int editor_element[] =
   EL_PFORTE3X,
   EL_PFORTE4X,
 
-  EL_KAEFER_R,
-  EL_KAEFER_O,
-  EL_KAEFER_L,
-  EL_KAEFER_U,
+  EL_CHAR_A + ('M' - 'A'),
+  EL_CHAR_A + ('O' - 'A'),
+  EL_CHAR_A + ('R' - 'A'),
+  EL_CHAR_A + ('E' - 'A'),
 
-  EL_FLIEGER_R,
-  EL_FLIEGER_O,
-  EL_FLIEGER_L,
-  EL_FLIEGER_U,
+  EL_AMOEBE_VOLL,
+  EL_EDELSTEIN_GELB,
+  EL_EDELSTEIN_ROT,
+  EL_EDELSTEIN_LILA,
 
-  EL_PACMAN_R,
+  EL_ERZ_EDEL_BD,
+  EL_ERZ_EDEL_GELB,
+  EL_ERZ_EDEL_ROT,
+  EL_ERZ_EDEL_LILA,
+
+  EL_LIFE,
   EL_PACMAN_O,
+  EL_ZEIT_VOLL,
+  EL_ZEIT_LEER,
+
   EL_PACMAN_L,
+  EL_MAMPFER2,
+  EL_PACMAN_R,
+  EL_MAUER_LEBT,
+
+  EL_LIFE_ASYNC,
   EL_PACMAN_U,
+  EL_BIRNE_AUS,
+  EL_BIRNE_EIN,
+
+  EL_DYNABOMB_NR,
+  EL_DYNABOMB_SZ,
+  EL_DYNABOMB_XL,
+  EL_BADEWANNE,
+
+  EL_CHAR_A + ('S' - 'A'),
+  EL_CHAR_A + ('O' - 'A'),
+  EL_CHAR_A + ('K' - 'A'),
+  EL_CHAR_A + ('O' - 'A'),
+
+  EL_CHAR_MINUS,
+  EL_CHAR_A + ('B' - 'A'),
+  EL_CHAR_A + ('A' - 'A'),
+  EL_CHAR_A + ('N' - 'A'),
+
+  EL_SOKOBAN_OBJEKT,
+  EL_SOKOBAN_FELD_LEER,
+  EL_SOKOBAN_FELD_VOLL,
+  EL_BETON,
+
+/*
+  EL_CHAR_A + ('D' - 'A'),
+  EL_CHAR_A + ('Y' - 'A'),
+  EL_CHAR_A + ('N' - 'A'),
+  EL_CHAR_A + ('A' - 'A'),
+
+  EL_CHAR_A + ('B' - 'A'),
+  EL_CHAR_A + ('L' - 'A'),
+  EL_CHAR_A + ('A' - 'A'),
+  EL_CHAR_A + ('S' - 'A'),
+
+  EL_CHAR_MINUS,
+  EL_CHAR_A + ('T' - 'A'),
+  EL_CHAR_A + ('E' - 'A'),
+  EL_CHAR_A + ('R' - 'A'),
+*/
 
   EL_CHAR_AUSRUF,
   EL_CHAR_ZOLL,
@@ -490,7 +581,7 @@ void FloodFill(int from_x, int from_y, int fill_element)
 {
   int i,x,y;
   int old_element;
-  static int check[4][2] = { -1,0, 0,-1, 1,0, 0,1 };
+  static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
   static int safety = 0;
 
   safety++;
@@ -558,69 +649,61 @@ void LevelEd(int mx, int my, int button)
   }
   else                         /********** EDIT/CTRL-FENSTER **********/
   {
+    static long choice_delay = 0;
     int choice = CheckElemButtons(mx,my,button);
     int elem_pos = choice-ED_BUTTON_ELEM;
 
-    switch(choice)
+    if (((choice == ED_BUTTON_EUP && element_shift>0) ||
+        (choice == ED_BUTTON_EDOWN &&
+         element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
+       DelayReached(&choice_delay,10))
     {
-      case ED_BUTTON_EUP:
-      case ED_BUTTON_EDOWN:
-        if ((choice==ED_BUTTON_EUP && element_shift>0) ||
-           (choice==ED_BUTTON_EDOWN &&
-            element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y))
-       {
-         int i, step;
-
-         step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
-                 elements_in_list);
-         element_shift += (choice==ED_BUTTON_EUP ? -step : step);
-         if (element_shift<0)
-           element_shift = 0;
-         if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
-           element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
-         if (element_shift % MAX_ELEM_X)
-           element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
-
-         for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
-           DrawElemButton(i+2,ED_BUTTON_RELEASED);
-         BackToFront();
-         Delay(100000);
-       }
-       break;
-      default:
-       if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
-       {
-         int new_element;
-
-         if (elem_pos+element_shift < elements_in_list)
-           new_element = editor_element[elem_pos+element_shift];
-         else
-           new_element = EL_LEERRAUM;
-
-         if (last_button==1)
-           new_element1 = new_element;
-         else if (last_button==2)
-           new_element2 = new_element;
-         else if (last_button==3)
-           new_element3 = new_element;
-
-         DrawMiniGraphicExtHiRes(drawto,gc,
-                                 DX+ED_WIN_MB_LEFT_XPOS,
-                                 DY+ED_WIN_MB_LEFT_YPOS,
-                                 el2gfx(new_element1));
-         DrawMiniGraphicExtHiRes(drawto,gc,
-                                 DX+ED_WIN_MB_MIDDLE_XPOS,
-                                 DY+ED_WIN_MB_MIDDLE_YPOS,
-                                 el2gfx(new_element2));
-         DrawMiniGraphicExtHiRes(drawto,gc,
-                                 DX+ED_WIN_MB_RIGHT_XPOS,
-                                 DY+ED_WIN_MB_RIGHT_YPOS,
-                                 el2gfx(new_element3));
-         redraw_mask |= REDRAW_DOOR_1;
-       }
-       break;
+      int i, step;
+
+      step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
+             elements_in_list);
+      element_shift += (choice==ED_BUTTON_EUP ? -step : step);
+      if (element_shift<0)
+       element_shift = 0;
+      if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
+       element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
+      if (element_shift % MAX_ELEM_X)
+       element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
+
+      for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
+       DrawElemButton(i+2,ED_BUTTON_RELEASED);
     }
+    else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
+    {
+      int new_element;
 
+      if (elem_pos+element_shift < elements_in_list)
+       new_element = editor_element[elem_pos+element_shift];
+      else
+       new_element = EL_LEERRAUM;
+
+      if (last_button==1)
+       new_element1 = new_element;
+      else if (last_button==2)
+       new_element2 = new_element;
+      else if (last_button==3)
+       new_element3 = new_element;
+
+      DrawMiniGraphicExtHiRes(drawto,gc,
+                             DX+ED_WIN_MB_LEFT_XPOS,
+                             DY+ED_WIN_MB_LEFT_YPOS,
+                             el2gfx(new_element1));
+      DrawMiniGraphicExtHiRes(drawto,gc,
+                             DX+ED_WIN_MB_MIDDLE_XPOS,
+                             DY+ED_WIN_MB_MIDDLE_YPOS,
+                             el2gfx(new_element2));
+      DrawMiniGraphicExtHiRes(drawto,gc,
+                             DX+ED_WIN_MB_RIGHT_XPOS,
+                             DY+ED_WIN_MB_RIGHT_YPOS,
+                             el2gfx(new_element3));
+      redraw_mask |= REDRAW_DOOR_1;
+    }
+  
     if (edit_mode)             /********** EDIT-FENSTER **********/
     {
       switch(CheckEditButtons(mx,my,button))
@@ -643,6 +726,8 @@ void LevelEd(int mx, int my, int button)
        case ED_BUTTON_LEFT:
          if (level_xpos>=0)
          {
+           if (!DelayReached(&choice_delay,10))
+             break;
            if (lev_fieldx<2*SCR_FIELDX-2)
              break;
 
@@ -653,13 +738,13 @@ void LevelEd(int mx, int my, int button)
              ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
            else
              DrawMiniLevel(level_xpos,level_ypos);
-           BackToFront();
-           Delay(100000);
          }
          break;
        case ED_BUTTON_RIGHT:
          if (level_xpos<=lev_fieldx-2*SCR_FIELDX)
          {
+           if (!DelayReached(&choice_delay,10))
+             break;
            if (lev_fieldx<2*SCR_FIELDX-2)
              break;
 
@@ -670,13 +755,13 @@ void LevelEd(int mx, int my, int button)
              ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
            else
              DrawMiniLevel(level_xpos,level_ypos);
-           BackToFront();
-           Delay(100000);
          }
          break;
        case ED_BUTTON_UP:
          if (level_ypos>=0)
          {
+           if (!DelayReached(&choice_delay,10))
+             break;
            if (lev_fieldy<2*SCR_FIELDY-2)
              break;
 
@@ -687,13 +772,13 @@ void LevelEd(int mx, int my, int button)
              ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
            else
              DrawMiniLevel(level_xpos,level_ypos);
-           BackToFront();
-           Delay(100000);
          }
          break;
        case ED_BUTTON_DOWN:
          if (level_ypos<=lev_fieldy-2*SCR_FIELDY)
          {
+           if (!DelayReached(&choice_delay,10))
+             break;
            if (lev_fieldy<2*SCR_FIELDY-2)
              break;
 
@@ -704,8 +789,6 @@ void LevelEd(int mx, int my, int button)
              ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
            else
              DrawMiniLevel(level_xpos,level_ypos);
-           BackToFront();
-           Delay(100000);
          }
          break;
        default:
@@ -758,7 +841,6 @@ void LevelEd(int mx, int my, int button)
     }
     else                       /********** KONTROLL-FENSTER **********/
     {
-      static long choice_delay = 0;
       int choice = CheckCountButtons(mx,my,button);
       int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
 
@@ -910,7 +992,8 @@ void LevelEd(int mx, int my, int button)
          }
          break;
        case ED_BUTTON_UNDO:
-         if (AreYouSure("Exit without saving ?",AYS_ASK | AYS_STAY_OPEN))
+         if (leveldir[leveldir_nr].readonly ||
+             AreYouSure("Exit without saving ?",AYS_ASK | AYS_STAY_OPEN))
          {
            CloseDoor(DOOR_CLOSE_BOTH);
            game_status=MAINMENU;
@@ -925,6 +1008,13 @@ void LevelEd(int mx, int my, int button)
        case ED_BUTTON_EXIT:
          {
            int figur_vorhanden = FALSE;
+
+           if (leveldir[leveldir_nr].readonly)
+           {
+             AreYouSure("This level is read only !",AYS_CONFIRM);
+             break;
+           }
+
            for(y=0;y<lev_fieldy;y++) 
              for(x=0;x<lev_fieldx;x++)
                if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1) 
index 9eb8d62..cbf6e1d 100644 (file)
@@ -18,6 +18,7 @@
 #include "game.h"
 #include "editor.h"
 #include "misc.h"
+#include "tape.h"
 
 void EventLoop(void)
 {
@@ -65,13 +66,11 @@ void EventLoop(void)
     else                       /* got no event, but don't be lazy... */
     {
       HandleNoXEvent();
-
-      XSync(display,FALSE);
-
-      if (game_status!=PLAYING)
-       Delay(10000);           /* don't use all CPU time when idle */
+      Delay(10000);            /* don't use all CPU time when idle */
     }
 
+    XSync(display,FALSE);
+
     if (game_status==EXITGAME)
       return;
   }
@@ -97,7 +96,7 @@ void ClearEventQueue()
        button_status = MB_RELEASED;
        break;
       case KeyRelease:
-       key_status = KEY_RELEASED;
+       key_joystick_mapping = 0;
        break;
       case FocusIn:
        HandleFocusEvent(FOCUS_IN);
@@ -132,7 +131,7 @@ void SleepWhileUnmapped()
        button_status = MB_RELEASED;
        break;
       case KeyRelease:
-       key_status = KEY_RELEASED;
+       key_joystick_mapping = 0;
        break;
       case MapNotify:
        window_unmapped = FALSE;
@@ -190,34 +189,30 @@ void HandleMotionEvent(XMotionEvent *event)
 
 void HandleKeyEvent(XKeyEvent *event)
 {
-  static KeySym old_keycode = 0;
-  int new_keycode = event->keycode;
-  KeySym new_key = XLookupKeysym(event,event->state);
-  int new_key_status = (event->type==KeyPress ? KEY_PRESSED : KEY_RELEASED);
+  int key_status = (event->type == KeyPress ? KEY_PRESSED : KEY_RELEASED);
+  unsigned int event_state = (game_status != PLAYING ? event->state : 0);
+  KeySym key = XLookupKeysym(event, event_state);
 
-  if (game_status==PLAYING &&
-      (old_keycode!=new_keycode || key_status!=new_key_status))
-  {
-    DigField(0,0,DF_NO_PUSH);
-    SnapField(0,0);
-  }
-
-  if (event->type==KeyPress)
-  {
-    key_status = KEY_PRESSED;
-    HandleKey(new_key);
-    old_keycode = new_keycode;
-  }
-  else if (key_status==KEY_PRESSED && old_keycode==new_keycode)
-    key_status = KEY_RELEASED;
+  HandleKey(key, key_status);
 }
 
 void HandleFocusEvent(int focus_status)
 {
+  static int old_joystick_status = -1;
+
   if (focus_status==FOCUS_OUT)
+  {
     XAutoRepeatOn(display);
-  else if (game_status==PLAYING)
-    XAutoRepeatOff(display);
+    old_joystick_status = joystick_status;
+    joystick_status = JOYSTICK_OFF;
+  }
+  else
+  {
+    if (game_status == PLAYING)
+      XAutoRepeatOff(display);
+    if (old_joystick_status != -1)
+      joystick_status = old_joystick_status;
+  }
 }
 
 void HandleButton(int mx, int my, int button)
@@ -263,41 +258,128 @@ void HandleButton(int mx, int my, int button)
       HandleSetupScreen(mx,my,0,0,button);
       break;
     case PLAYING:
-      if (!LevelSolved)
-      {
-       switch(GameActions(mx,my,button))
-       {
-         case ACT_GAME_OVER:
-           game_status = MAINMENU;
-           DrawMainMenu();
-           BackToFront();
-           break;
-         case ACT_NEW_GAME:
-           game_status = PLAYING;
-           InitGame();
-           break;
-         case ACT_GO_ON:
-           break;
-         default:
-           break;
-       }
-      }
-      BackToFront();
-      Delay(10000);
+      HandleGameActions();
       break;
     default:
       break;
   }
 }
 
-void HandleKey(KeySym key)
+int Gamespeed = 4;
+int Movemethod = 0;
+int Movespeed[2] = { 10, 3 };
+
+void HandleKey(KeySym key, int key_status)
 {
-  static KeySym old_key = 0;
+  int joy = 0;
 
-  if (!key)
-    key = old_key;
-  else
-    old_key = key;
+  /* Map cursor keys to joystick directions */
+
+  switch(key)
+  {
+    case XK_Left:              /* normale Richtungen */
+#ifdef XK_KP_Left
+    case XK_KP_Left:
+#endif
+    case XK_KP_4:
+    case XK_J:
+    case XK_j:
+      joy |= JOY_LEFT;
+      break;
+    case XK_Right:
+#ifdef XK_KP_Right
+    case XK_KP_Right:
+#endif
+    case XK_KP_6:
+    case XK_K:
+    case XK_k:
+      joy |= JOY_RIGHT;
+      break;
+    case XK_Up:
+#ifdef XK_KP_Up
+    case XK_KP_Up:
+#endif
+    case XK_KP_8:
+    case XK_I:
+    case XK_i:
+      joy |= JOY_UP;
+      break;
+    case XK_Down:
+#ifdef XK_KP_Down
+    case XK_KP_Down:
+#endif
+    case XK_KP_2:
+    case XK_M:
+    case XK_m:
+      joy |= JOY_DOWN;
+      break;
+#ifdef XK_KP_Home
+    case XK_KP_Home:           /* Diagonalrichtungen */
+#endif
+    case XK_KP_7:
+      joy |= JOY_UP | JOY_LEFT;
+      break;
+#ifdef XK_KP_Page_Up
+    case XK_KP_Page_Up:
+#endif
+    case XK_KP_9:
+      joy = JOY_UP | JOY_RIGHT;
+      break;
+#ifdef XK_KP_End
+    case XK_KP_End:
+#endif
+    case XK_KP_1:
+      joy |= JOY_DOWN | JOY_LEFT;
+      break;
+#ifdef XK_KP_Page_Down
+    case XK_KP_Page_Down:
+#endif
+    case XK_KP_3:
+      joy |= JOY_DOWN | JOY_RIGHT;
+      break;
+    case XK_S:                 /* Feld entfernen */
+    case XK_s:
+      joy |= JOY_BUTTON_1 | JOY_LEFT;
+      break;
+    case XK_D:
+    case XK_d:
+      joy |= JOY_BUTTON_1 | JOY_RIGHT;
+      break;
+    case XK_E:
+    case XK_e:
+      joy |= JOY_BUTTON_1 | JOY_UP;
+      break;
+    case XK_X:
+    case XK_x:
+      joy |= JOY_BUTTON_1 | JOY_DOWN;
+      break;
+    case XK_Shift_L:           /* Linker Feuerknopf */
+      joy |= JOY_BUTTON_1;
+      break;
+    case XK_Shift_R:           /* Rechter Feuerknopf */
+    case XK_B:                 /* (Bombe legen) */
+    case XK_b:
+      joy |= JOY_BUTTON_2;
+      break;
+    default:
+      break;
+  }
+
+  if (joy)
+  {
+    if (key_status == KEY_PRESSED)
+      key_joystick_mapping |= joy;
+    else
+      key_joystick_mapping &= ~joy;
+
+    HandleJoystick();
+
+    if (game_status != PLAYING)
+      key_joystick_mapping = 0;
+  }
+
+  if (key_status == KEY_RELEASED)
+    return;
 
   if (key==XK_Escape && game_status!=MAINMENU) /* quick quit to MAINMENU */
   {
@@ -319,8 +401,6 @@ void HandleKey(KeySym key)
     case CHOOSELEVEL:
     case SETUP:
     {
-      int dx = 0, dy = 0;
-
       switch(key)
       {
        case XK_Return:
@@ -331,55 +411,9 @@ void HandleKey(KeySym key)
          else if (game_status==SETUP)
            HandleSetupScreen(0,0,0,0,MB_MENU_CHOICE);
          break;
-       case XK_Left:
-#ifdef XK_KP_Left
-       case XK_KP_Left:
-#endif
-       case XK_KP_4:
-       case XK_J:
-       case XK_j:
-         dx = -1;
-         break;
-       case XK_Right:
-#ifdef XK_KP_Right
-       case XK_KP_Right:
-#endif
-       case XK_KP_6:
-       case XK_K:
-       case XK_k:
-         dx = 1;
-         break;
-       case XK_Up:
-#ifdef XK_KP_Up
-       case XK_KP_Up:
-#endif
-       case XK_KP_8:
-       case XK_I:
-       case XK_i:
-         dy = -1;
-         break;
-       case XK_Down:
-#ifdef XK_KP_Down
-       case XK_KP_Down:
-#endif
-       case XK_KP_2:
-       case XK_M:
-       case XK_m:
-         dy = 1;
-         break;
        default:
          break;
       }
-
-      if (dx || dy)
-      {
-       if (game_status==MAINMENU)
-         HandleMainMenu(0,0,dx,dy,MB_MENU_MARK);
-        else if (game_status==CHOOSELEVEL)
-          HandleChooseLevel(0,0,dx,dy,MB_MENU_MARK);
-       else if (game_status==SETUP)
-         HandleSetupScreen(0,0,dx,dy,MB_MENU_MARK);
-      }
       break;
     }
     case HELPSCREEN:
@@ -402,128 +436,89 @@ void HandleKey(KeySym key)
       break;
     case PLAYING:
     {
-      int mvx = 0, mvy = 0;
-      int sbx = 0, sby = 0;
-      int joy = 0;
-      BOOL bomb = FALSE;
-      BOOL moved = FALSE, snapped = FALSE, bombed = FALSE;
-
       switch(key)
       {
-       case XK_Left:           /* normale Richtungen */
-#ifdef XK_KP_Left
-       case XK_KP_Left:
-#endif
-       case XK_KP_4:
-       case XK_J:
-       case XK_j:
-         mvx = -1;
-         joy = JOY_LEFT;
+
+#ifdef DEBUG
+       case XK_0:
+       case XK_1:
+       case XK_2:
+       case XK_3:
+       case XK_4:
+       case XK_5:
+       case XK_6:
+       case XK_7:
+       case XK_8:
+       case XK_9:
+         Movespeed[Movemethod] = (Movemethod == 0 ? 4 : 0) + (key - XK_0);
+         printf("method == %d, speed == %d\n",
+                Movemethod, Movespeed[Movemethod]);
          break;
-       case XK_Right:
-#ifdef XK_KP_Right
-       case XK_KP_Right:
-#endif
-       case XK_KP_6:
-       case XK_K:
-       case XK_k:
-         mvx = 1;
-         joy = JOY_RIGHT;
+
+       case XK_a:
+         Movemethod = !Movemethod;
+         printf("method == %d, speed == %d\n",
+                Movemethod, Movespeed[Movemethod]);
          break;
-       case XK_Up:
-#ifdef XK_KP_Up
-       case XK_KP_Up:
-#endif
-       case XK_KP_8:
-       case XK_I:
-       case XK_i:
-         mvy = -1;
-         joy = JOY_UP;
+
+       case XK_f:
+         Gamespeed = 2;
+         printf("gamespeed == %d\n", Gamespeed);
          break;
-       case XK_Down:
-#ifdef XK_KP_Down
-       case XK_KP_Down:
-#endif
-       case XK_KP_2:
-       case XK_M:
-       case XK_m:
-         mvy = 1;
-         joy = JOY_DOWN;
+       case XK_g:
+         Gamespeed = 3;
+         printf("gamespeed == %d\n", Gamespeed);
          break;
-#ifdef XK_KP_Home
-       case XK_KP_Home:        /* Diagonalrichtungen */
-#endif
-       case XK_KP_7:
-         mvx = -1;
-         mvy = -1;
-         joy = JOY_UP | JOY_LEFT;
+       case XK_h:
+         Gamespeed = 4;
+         printf("gamespeed == %d\n", Gamespeed);
          break;
-#ifdef XK_KP_Page_Up
-       case XK_KP_Page_Up:
-#endif
-       case XK_KP_9:
-         mvx = 1;
-         mvy = -1;
-         joy = JOY_UP | JOY_RIGHT;
+       case XK_l:
+         Gamespeed = 10;
+         printf("gamespeed == %d\n", Gamespeed);
          break;
-#ifdef XK_KP_End
-       case XK_KP_End:
-#endif
-       case XK_KP_1:
-         mvx = -1;
-         mvy = 1;
-         joy = JOY_DOWN | JOY_LEFT;
+
+       case XK_Q:
+       case XK_q:
+         Dynamite = 1000;
          break;
-#ifdef XK_KP_Page_Down
-       case XK_KP_Page_Down:
 #endif
-       case XK_KP_3:
-         mvx = 1;
-         mvy = 1;
-         joy = JOY_DOWN | JOY_RIGHT;
-         break;
-       case XK_S:              /* Feld entfernen */
-       case XK_s:
-         sbx = -1;
-         joy = JOY_BUTTON_1 | JOY_LEFT;
-         break;
-       case XK_D:
-       case XK_d:
-         sbx = 1;
-         joy = JOY_BUTTON_1 | JOY_RIGHT;
-         break;
-       case XK_E:
-       case XK_e:
-         sby = -1;
-         joy = JOY_BUTTON_1 | JOY_UP;
-         break;
-       case XK_X:
+
        case XK_x:
-         sby = 1;
-         joy = JOY_BUTTON_1 | JOY_DOWN;
-         break;
-       case XK_B:              /* Bombe legen */
-       case XK_b:
-         bomb = TRUE;
-         joy = JOY_BUTTON_2;
-         break;
-       case XK_Q:
-         Dynamite = 1000;
+         /*
+         {
+           int i,j,k, num_steps = 4, step_size = TILEX / num_steps;
+
+           for(i=0;i<10;i++)
+           {
+             for(j=0;j<SCR_FIELDX;j++)
+             {
+               for(k=0;k<num_steps;k++)
+               {
+                 int xxx = j*TILEX+k*step_size;
+
+                 XCopyArea(display,backbuffer,window,gc,
+                           REAL_SX+xxx,REAL_SY,
+                           FULL_SXSIZE-xxx,FULL_SYSIZE,
+                           REAL_SX,REAL_SY);
+                 XCopyArea(display,backbuffer,window,gc,
+                           REAL_SX,REAL_SY,
+                           xxx,FULL_SYSIZE,
+                           REAL_SX+FULL_SXSIZE-xxx,REAL_SY);
+
+                 XFlush(display);
+                 XSync(display,FALSE);
+                 Delay(120000 / num_steps);
+               }
+             }
+           }
+         }
+         */
          break;
+
        default:
          break;
       }
-
-      if (mvx || mvy)
-       moved = MoveFigure(mvx,mvy);
-      else if (sbx || sby)
-       snapped = SnapField(sbx,sby);
-      else if (bomb)
-       bombed = PlaceBomb();
-
-      if (tape.recording && (moved || snapped || bombed))
-       TapeRecordAction(joy);
-
       break;
     }
     default:
@@ -533,7 +528,7 @@ void HandleKey(KeySym key)
 
 void HandleNoXEvent()
 {
-  if (button_status)
+  if (button_status && game_status!=PLAYING)
   {
     HandleButton(-1,-1,button_status);
     return;
@@ -550,33 +545,7 @@ void HandleNoXEvent()
       break;
     case PLAYING:
       HandleJoystick();
-      if (key_status)
-       HandleKey(0);
-      if (game_status!=PLAYING)
-       break;
-
-      if (!LevelSolved)
-      {
-       switch(GameActions(0,0,MB_NOT_PRESSED))
-       {
-         case ACT_GAME_OVER:
-           game_status = MAINMENU;
-           DrawMainMenu();
-           BackToFront();
-           break;
-         case ACT_NEW_GAME:
-           game_status = PLAYING;
-           InitGame();
-           break;
-         case ACT_GO_ON:
-           break;
-         default:
-           break;
-       }
-      }
-
-      Delay(10000);
-
+      HandleGameActions();
       break;
     default:
       break;
@@ -585,7 +554,9 @@ void HandleNoXEvent()
 
 void HandleJoystick()
 {
-  int joy      = Joystick();
+  int joystick = Joystick();
+  int keyboard = key_joystick_mapping;
+  int joy      = (tape.playing ? TapePlayAction() : (joystick | keyboard));
   int left     = joy & JOY_LEFT;
   int right    = joy & JOY_RIGHT;
   int up       = joy & JOY_UP;
@@ -593,10 +564,9 @@ void HandleJoystick()
   int button   = joy & JOY_BUTTON;
   int button1  = joy & JOY_BUTTON_1;
   int button2  = joy & JOY_BUTTON_2;
-  int newbutton        = (JoystickButton()==JOY_BUTTON_NEW_PRESSED);
-
-  if (button_status || key_status)
-    return;
+  int newbutton        = (JoystickButton() == JOY_BUTTON_NEW_PRESSED);
+  int dx       = (left ? -1    : right ? 1     : 0);
+  int dy       = (up   ? -1    : down  ? 1     : 0);
 
   switch(game_status)
   {
@@ -604,20 +574,10 @@ void HandleJoystick()
     case CHOOSELEVEL:
     case SETUP:
     {
-      int dx = 0, dy = 0;
       static long joystickmove_delay = 0;
 
-      if (DelayReached(&joystickmove_delay,15) || button)
-      {
-       if (left)
-         dx = -1;
-       else if (right)
-         dx = 1;
-       if (up)
-         dy = -1;
-       else if (down)
-         dy = 1;
-      }
+      if (joystick && !button && !DelayReached(&joystickmove_delay,15))
+       break;
 
       if (game_status==MAINMENU)
        HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
@@ -635,27 +595,15 @@ void HandleJoystick()
       break;
     case PLAYING:
     {
-      int mvx = 0, mvy = 0;
       BOOL moved = FALSE, snapped = FALSE, bombed = FALSE;
 
-      if (tape.playing)
-      {
-       joy     = TapePlayAction();
-
-       left    = joy & JOY_LEFT;
-       right   = joy & JOY_RIGHT;
-       up      = joy & JOY_UP;
-       down    = joy & JOY_DOWN;
-       button  = joy & JOY_BUTTON;
-       button1 = joy & JOY_BUTTON_1;
-       button2 = joy & JOY_BUTTON_2;
-      }
-      else if (tape.pausing)
+      if (tape.pausing)
        joy = 0;
 
       if (!joy)
       {
-       DigField(0,0,DF_NO_PUSH);
+       DigField(0,0,0,0,DF_NO_PUSH);
+       SnapField(0,0);
        break;
       }
 
@@ -667,22 +615,13 @@ void HandleJoystick()
        return;
       }
 
-      if (left)
-       mvx = -1;
-      else if (right)
-       mvx = 1;
-      if (up)
-       mvy = -1;
-      else if (down)
-       mvy = 1;
-
       if (button1)
-       snapped = SnapField(mvx,mvy);
+       snapped = SnapField(dx,dy);
       else
       {
        if (button2)
          bombed = PlaceBomb();
-       moved = MoveFigure(mvx,mvy);
+       moved = MoveFigure(dx,dy);
       }
 
       if (tape.recording && (moved || snapped || bombed))
@@ -692,7 +631,7 @@ void HandleJoystick()
        TapeRecordAction(joy);
       }
       else if (tape.playing && snapped)
-       SnapField(0,0);
+       SnapField(0,0);                 /* stop snapping */
 
       break;
     }
index 1916ea3..31948c1 100644 (file)
@@ -29,7 +29,7 @@ void HandleFocusEvent(int);
 void HandleNoXEvent(void);
 
 void HandleButton(int, int, int);
-void HandleKey(KeySym);
+void HandleKey(KeySym, int);
 void HandleJoystick();
 
 #endif
index 1efc0a1..1441cd0 100644 (file)
@@ -15,6 +15,7 @@
 #include "files.h"
 #include "tools.h"
 #include "misc.h"
+#include "tape.h"
 
 BOOL CreateNewScoreFile()
 {
@@ -24,7 +25,7 @@ BOOL CreateNewScoreFile()
   FILE *file;
 
   sprintf(filename,"%s/%s/%s",
-         SCORE_PATH,leveldir[leveldir_nr].filename,SCORE_FILENAME);
+         level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
 
   if (!(file=fopen(filename,"w")))
     return(FALSE);
@@ -34,7 +35,7 @@ BOOL CreateNewScoreFile()
   strncpy(empty_alias,EMPTY_ALIAS,MAX_NAMELEN-1);
 
   fputs(SCORE_COOKIE,file);            /* Formatkennung */
-  for(i=0;i<LEVELDIR_SIZE(leveldir[leveldir_nr]);i++)
+  for(i=0;i<leveldir[leveldir_nr].levels;i++)
   {
     for(j=0;j<MAX_SCORE_ENTRIES;j++)
     {
@@ -57,7 +58,7 @@ BOOL CreateNewNamesFile(int mode)
 
   if (mode==PLAYER_LEVEL)
     sprintf(filename,"%s/%s/%s",
-           NAMES_PATH,leveldir[leveldir_nr].filename,NAMES_FILENAME);
+           level_directory,leveldir[leveldir_nr].filename,NAMES_FILENAME);
   else
     sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
 
@@ -78,7 +79,7 @@ BOOL LoadLevelInfo()
   char cookie[MAX_FILENAME];
   FILE *file;
 
-  sprintf(filename,"%s/%s",LEVEL_PATH,LEVDIR_FILENAME);
+  sprintf(filename,"%s/%s",level_directory,LEVDIR_FILENAME);
 
   if (!(file=fopen(filename,"r")))
   {
@@ -100,8 +101,8 @@ BOOL LoadLevelInfo()
   {
     fscanf(file,"%s",leveldir[i].filename);
     fscanf(file,"%s",leveldir[i].name);
-    fscanf(file,"%d",&leveldir[i].num_ready);
-    fscanf(file,"%d",&leveldir[i].num_free);
+    fscanf(file,"%d",&leveldir[i].levels);
+    fscanf(file,"%d",&leveldir[i].readonly);
     if (feof(file))
       break;
 
@@ -125,7 +126,7 @@ void LoadLevel(int level_nr)
   FILE *file;
 
   sprintf(filename,"%s/%s/%d",
-         LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+         level_directory,leveldir[leveldir_nr].filename,level_nr);
 
   if (!(file=fopen(filename,"r")))
   {
@@ -137,6 +138,7 @@ void LoadLevel(int level_nr)
   {
     fgets(cookie,LEVEL_COOKIE_LEN,file);
     fgetc(file);
+
     if (strcmp(cookie,LEVEL_COOKIE))   /* ungültiges Format? */
     {
       fprintf(stderr,"%s: wrong format of level file '%s'!\n",
@@ -219,7 +221,7 @@ void LoadLevelTape(int level_nr)
   FILE *file;
 
   sprintf(filename,"%s/%s/%d.tape",
-         LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+         level_directory,leveldir[leveldir_nr].filename,level_nr);
 
   if ((file=fopen(filename,"r")))
   {
@@ -246,6 +248,8 @@ void LoadLevelTape(int level_nr)
 
   tape.level_nr = level_nr;
   tape.counter = 0;
+  tape.changed = FALSE;
+
   tape.recording = FALSE;
   tape.playing = FALSE;
   tape.pausing = FALSE;
@@ -260,13 +264,13 @@ void LoadLevelTape(int level_nr)
       break;
   }
 
+  fclose(file);
+
   if (i != tape.length)
     fprintf(stderr,"%s: level recording file '%s' corrupted!\n",
            progname,filename);
 
-  fclose(file);
-
-  master_tape = tape;
+  tape.length_seconds = GetTapeLength();
 }
 
 void LoadScore(int level_nr)
@@ -277,7 +281,7 @@ void LoadScore(int level_nr)
   FILE *file;
 
   sprintf(filename,"%s/%s/%s",
-         SCORE_PATH,leveldir[leveldir_nr].filename,SCORE_FILENAME);
+         level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
 
   if (!(file=fopen(filename,"r")))
   {
@@ -335,10 +339,11 @@ void LoadPlayerInfo(int mode)
   FILE *file;
   char *login_name = GetLoginName();
   struct PlayerInfo default_player, new_player;
+  int version_10_file = FALSE;
 
   if (mode==PLAYER_LEVEL)
     sprintf(filename,"%s/%s/%s",
-           NAMES_PATH,leveldir[leveldir_nr].filename,NAMES_FILENAME);
+           level_directory,leveldir[leveldir_nr].filename,NAMES_FILENAME);
   else
     sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
 
@@ -349,6 +354,7 @@ void LoadPlayerInfo(int mode)
   default_player.handicap = 0;
   default_player.setup = DEFAULT_SETUP;
   default_player.leveldir_nr = 0;
+  default_player.level_nr = 0;
 
   new_player = default_player;
 
@@ -369,7 +375,9 @@ void LoadPlayerInfo(int mode)
   if (file)
   {
     fgets(cookie,NAMES_COOKIE_LEN,file);
-    if (strcmp(cookie,NAMES_COOKIE))   /* ungültiges Format? */
+    if (!strcmp(cookie,NAMES_COOKIE_10))       /* altes Format? */
+      version_10_file = TRUE;
+    else if (strcmp(cookie,NAMES_COOKIE))      /* ungültiges Format? */
     {
       fprintf(stderr,"%s: wrong format of names file '%s'!\n",
              progname,filename);
@@ -381,7 +389,7 @@ void LoadPlayerInfo(int mode)
   if (!file)
   {
     player = default_player;
-    level_nr = default_player.handicap;
+    level_nr = default_player.level_nr;
     return;
   }
 
@@ -394,6 +402,14 @@ void LoadPlayerInfo(int mode)
     new_player.handicap = fgetc(file);
     new_player.setup = (fgetc(file)<<8) | fgetc(file);
     new_player.leveldir_nr = fgetc(file);
+    if (!version_10_file)
+    {
+      new_player.level_nr = fgetc(file);
+      for(i=0;i<10;i++)                /* currently unused bytes */
+       fgetc(file);
+    }
+    else
+      new_player.level_nr = new_player.handicap;
 
     if (feof(file))            /* Spieler noch nicht in Liste enthalten */
     {
@@ -415,6 +431,12 @@ void LoadPlayerInfo(int mode)
        fputc(new_player.setup / 256,file);
        fputc(new_player.setup % 256,file);
        fputc(new_player.leveldir_nr,file);
+       if (!version_10_file)
+       {
+         fputc(new_player.level_nr,file);
+         for(i=0;i<10;i++)     /* currently unused bytes */
+           fputc(0,file);
+       }
       }
       break;
     }
@@ -432,9 +454,12 @@ void LoadPlayerInfo(int mode)
       leveldir_nr = 0;
   }
   else
+  {
     player.handicap = new_player.handicap;
+    player.level_nr = new_player.level_nr;
+  }
 
-  level_nr = player.handicap;
+  level_nr = player.level_nr;
   fclose(file);
 }
 
@@ -445,7 +470,7 @@ void SaveLevel(int level_nr)
   FILE *file;
 
   sprintf(filename,"%s/%s/%d",
-         LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+         level_directory,leveldir[leveldir_nr].filename,level_nr);
 
   if (!(file=fopen(filename,"w")))
   {
@@ -496,7 +521,7 @@ void SaveLevelTape(int level_nr)
   BOOL new_tape = TRUE;
 
   sprintf(filename,"%s/%s/%d.tape",
-         LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+         level_directory,leveldir[leveldir_nr].filename,level_nr);
 
   /* Testen, ob bereits eine Aufnahme existiert */
   if ((file=fopen(filename,"r")))
@@ -518,8 +543,6 @@ void SaveLevelTape(int level_nr)
   fputs(LEVELREC_COOKIE,file);         /* Formatkennung */
   fputc(0x0a,file);
 
-  tape = master_tape;
-
   fputc((tape.random_seed >> 24) & 0xff,file);
   fputc((tape.random_seed >> 16) & 0xff,file);
   fputc((tape.random_seed >>  8) & 0xff,file);
@@ -545,6 +568,8 @@ void SaveLevelTape(int level_nr)
 
   chmod(filename, LEVREC_PERMS);
 
+  tape.changed = FALSE;
+
   if (new_tape)
     AreYouSure("tape saved !",AYS_CONFIRM);
 }
@@ -556,7 +581,7 @@ void SaveScore(int level_nr)
   FILE *file;
 
   sprintf(filename,"%s/%s/%s",
-         SCORE_PATH,leveldir[leveldir_nr].filename,SCORE_FILENAME);
+         level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
 
   if (!(file=fopen(filename,"r+")))
   {
@@ -585,10 +610,11 @@ void SavePlayerInfo(int mode)
   char cookie[MAX_FILENAME];
   FILE *file;
   struct PlayerInfo default_player;
+  int version_10_file = FALSE;
 
   if (mode==PLAYER_LEVEL)
     sprintf(filename,"%s/%s/%s",
-           NAMES_PATH,leveldir[leveldir_nr].filename,NAMES_FILENAME);
+           level_directory,leveldir[leveldir_nr].filename,NAMES_FILENAME);
   else
     sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
 
@@ -600,7 +626,9 @@ void SavePlayerInfo(int mode)
   }
 
   fgets(cookie,NAMES_COOKIE_LEN,file);
-  if (strcmp(cookie,NAMES_COOKIE))     /* ungültiges Format? */
+  if (!strcmp(cookie,NAMES_COOKIE_10)) /* altes Format? */
+    version_10_file = TRUE;
+  else if (strcmp(cookie,NAMES_COOKIE))        /* ungültiges Format? */
   {
     fprintf(stderr,"%s: wrong format of names file '%s'!\n",
            progname,filename);
@@ -617,17 +645,27 @@ void SavePlayerInfo(int mode)
     default_player.handicap = fgetc(file);
     default_player.setup = (fgetc(file)<<8) | fgetc(file);
     default_player.leveldir_nr = fgetc(file);
+    if (!version_10_file)
+    {
+      default_player.level_nr = fgetc(file);
+      for(i=0;i<10;i++)                /* currently unused bytes */
+       fgetc(file);
+    }
+    else
+      default_player.level_nr = default_player.handicap;
 
     if (feof(file))            /* Spieler noch nicht in Liste enthalten */
       break;
     else                       /* prüfen, ob Spieler in Liste enthalten */
       if (!strncmp(default_player.login_name,player.login_name,MAX_NAMELEN-1))
       {
-       fseek(file,-(2*MAX_NAMELEN+1+2+1),SEEK_CUR);
+       fseek(file,-(2*MAX_NAMELEN+1+2+1+(version_10_file ? 0 : 11)),SEEK_CUR);
        break;
       }
   }
 
+  player.level_nr = level_nr;
+
   for(i=0;i<MAX_NAMELEN;i++)
     fputc(player.login_name[i],file);
   for(i=0;i<MAX_NAMELEN;i++)
@@ -636,6 +674,12 @@ void SavePlayerInfo(int mode)
   fputc(player.setup / 256,file);
   fputc(player.setup % 256,file);
   fputc(player.leveldir_nr,file);
+  if (!version_10_file)
+  {
+    fputc(player.level_nr,file);
+    for(i=0;i<10;i++)          /* currently unused bytes */
+      fputc(0,file);
+  }
 
   fclose(file);
 }
index aee5e42..1489d28 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "main.h"
 
-/* names file mode: level or setup */
+/* names file mode: local level setup or global game setup */
 #define PLAYER_LEVEL   0
 #define PLAYER_SETUP   1
 
 #define SETUP_SOUND_MUSIC              (1<<3)
 #define SETUP_DIRECT_DRAW              (1<<4)
 #define SETUP_FADING                   (1<<5)
-#define SETUP_RECORD_EACH_GAME         (1<<6)
+#define SETUP_AUTO_RECORD              (1<<6)
 #define SETUP_2ND_JOYSTICK             (1<<7)
 #define SETUP_QUICK_DOORS              (1<<8)
+#define SETUP_SCROLL_DELAY             (1<<9)
 
 #define DEFAULT_SETUP                  (SETUP_TOONS |          \
                                         SETUP_SOUND |          \
 #define SETUP_SOUND_MUSIC_ON(x)                (((x) & SETUP_SOUND_MUSIC) != 0)
 #define SETUP_DIRECT_DRAW_ON(x)                (((x) & SETUP_DIRECT_DRAW) != 0)
 #define SETUP_FADING_ON(x)             (((x) & SETUP_FADING) != 0)
-#define SETUP_RECORD_EACH_GAME_ON(x)   (((x) & SETUP_RECORD_EACH_GAME) != 0)
+#define SETUP_AUTO_RECORD_ON(x)                (((x) & SETUP_AUTO_RECORD) != 0)
 #define SETUP_2ND_JOYSTICK_ON(x)       (((x) & SETUP_2ND_JOYSTICK) != 0)
 #define SETUP_QUICK_DOORS_ON(x)                (((x) & SETUP_QUICK_DOORS) != 0)
+#define SETUP_SCROLL_DELAY_ON(x)       (((x) & SETUP_SCROLL_DELAY) != 0)
 
 BOOL CreateNewScoreFile(void);
 BOOL CreateNewNamesFile(int);
index 46bbbf2..cda9257 100644 (file)
 #include "init.h"
 #include "buttons.h"
 #include "files.h"
+#include "tape.h"
+
+extern int Gamespeed;
+extern int Movemethod;
+extern int Movespeed[2];
 
 void GetPlayerConfig()
 {
@@ -33,15 +38,16 @@ void GetPlayerConfig()
     player.setup &= ~SETUP_SOUND_MUSIC;
   }
 
-  sound_on = SETUP_SOUND_ON(player.setup);
+  sound_on = sound_simple_on = SETUP_SOUND_ON(player.setup);
   sound_loops_on = SETUP_SOUND_LOOPS_ON(player.setup);
   sound_music_on = SETUP_SOUND_MUSIC_ON(player.setup);
   toons_on = SETUP_TOONS_ON(player.setup);
   direct_draw_on = SETUP_DIRECT_DRAW_ON(player.setup);
   fading_on = SETUP_FADING_ON(player.setup);
-  autorecord_on = SETUP_RECORD_EACH_GAME_ON(player.setup);
+  autorecord_on = SETUP_AUTO_RECORD_ON(player.setup);
   joystick_nr = SETUP_2ND_JOYSTICK_ON(player.setup);
   quick_doors = SETUP_QUICK_DOORS_ON(player.setup);
+  scroll_delay_on = SETUP_SCROLL_DELAY_ON(player.setup);
 
   if (joystick_nr != old_joystick_nr)
   {
@@ -54,29 +60,28 @@ void GetPlayerConfig()
 void InitGame()
 {
   int i,x,y;
+  BOOL emulate_bd = TRUE;      /* unless non-BOULDERDASH elements found */
+  BOOL emulate_sb = TRUE;      /* unless non-SOKOBAN     elements found */
 
   Dynamite = Score = 0;
   Gems = level.edelsteine;
+  SokobanFields = Lights = 0;
   DynaBombCount = DynaBombSize = DynaBombsLeft = 0;
+  DynaBombXL = FALSE;
   Key[0] = Key[1] = Key[2] = Key[3] = FALSE;
   MampferNr = 0;
+  FrameCounter = 0;
+  TimeFrames = 0;
   TimeLeft = level.time;
-  CheckMoving = TRUE;
-  CheckExploding = FALSE;
   LevelSolved = GameOver = SiebAktiv = FALSE;
   JX = JY = 0;
   ZX = ZY = -1;
 
-  if (tape.recording)
-    TapeStartRecording();
-  else if (tape.playing)
-    TapeStartPlaying();
-
-  DigField(0,0,DF_NO_PUSH);
+  DigField(0,0,0,0,DF_NO_PUSH);
   SnapField(0,0);
 
   for(i=0;i<MAX_NUM_AMOEBA;i++)
-    AmoebaCnt[i] = 0;
+    AmoebaCnt[i] = AmoebaCnt2[i] = 0;
 
   for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
   {
@@ -85,6 +90,11 @@ void InitGame()
     Store[x][y] = Store2[x][y] = Frame[x][y] = AmoebaNr[x][y] = 0;
     JustHit[x][y] = 0;
 
+    if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
+      emulate_bd = FALSE;
+    if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y]))
+      emulate_sb = FALSE;
+
     switch(Feld[x][y])
     {
       case EL_SPIELFIGUR:
@@ -118,6 +128,16 @@ void InitGame()
       case EL_FLIEGER_L:
       case EL_FLIEGER_U:
       case EL_FLIEGER:
+      case EL_BUTTERFLY_R:
+      case EL_BUTTERFLY_O:
+      case EL_BUTTERFLY_L:
+      case EL_BUTTERFLY_U:
+      case EL_BUTTERFLY:
+      case EL_FIREFLY_R:
+      case EL_FIREFLY_O:
+      case EL_FIREFLY_L:
+      case EL_FIREFLY_U:
+      case EL_FIREFLY:
       case EL_PACMAN_R:
       case EL_PACMAN_O:
       case EL_PACMAN_L:
@@ -129,6 +149,7 @@ void InitGame()
        InitMovDir(x,y);
        break;
       case EL_AMOEBE_VOLL:
+      case EL_AMOEBE_BD:
        InitAmoebaNr(x,y);
        break;
       case EL_TROPFEN:
@@ -138,11 +159,23 @@ void InitGame()
          Store[x][y] = EL_AMOEBE_NASS;
        }
        break;
+      case EL_DYNAMIT:
+       MovDelay[x][y] = 48;
+       break;
+      case EL_BIRNE_AUS:
+       Lights++;
+       break;
+      case EL_SOKOBAN_FELD_LEER:
+       SokobanFields++;
+       break;
       default:
        break;
     }
   }
 
+  game_emulation = (emulate_bd ? EMU_BOULDERDASH :
+                   emulate_sb ? EMU_SOKOBAN : EMU_NONE);
+
   scroll_x = scroll_y = -1;
   if (JX>=MIDPOSX-1)
     scroll_x =
@@ -151,6 +184,8 @@ void InitGame()
     scroll_y =
       (JY<=lev_fieldy-MIDPOSY ? JY-MIDPOSY : lev_fieldy-SCR_FIELDY+1);
 
+  CloseDoor(DOOR_CLOSE_1);
+
   DrawLevel();
   DrawLevelElement(JX,JY,EL_SPIELFIGUR);
   FadeToFront();
@@ -177,9 +212,9 @@ void InitGame()
   DrawGameButton(BUTTON_GAME_STOP);
   DrawGameButton(BUTTON_GAME_PAUSE);
   DrawGameButton(BUTTON_GAME_PLAY);
-  DrawSoundDisplay(BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on));
-  DrawSoundDisplay(BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on));
-  DrawSoundDisplay(BUTTON_SOUND_SOUND | (BUTTON_ON * sound_on));
+  DrawSoundDisplay(BUTTON_SOUND_MUSIC  | (BUTTON_ON * sound_music_on));
+  DrawSoundDisplay(BUTTON_SOUND_LOOPS  | (BUTTON_ON * sound_loops_on));
+  DrawSoundDisplay(BUTTON_SOUND_SIMPLE | (BUTTON_ON * sound_simple_on));
   XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
            DX+GAME_CONTROL_XPOS,DY+GAME_CONTROL_YPOS,
            GAME_CONTROL_XSIZE,2*GAME_CONTROL_YSIZE,
@@ -199,15 +234,15 @@ void InitMovDir(int x, int y)
   int i, element = Feld[x][y];
   static int xy[4][2] =
   {
-    0,+1,
-    +1,0,
-    0,-1,
-    -1,0
+    { 0,+1 },
+    { +1,0 },
+    { 0,-1 },
+    { -1,0 }
   };
   static int direction[2][4] =
   {
-    MV_RIGHT, MV_UP,   MV_LEFT,  MV_DOWN,
-    MV_LEFT,  MV_DOWN, MV_RIGHT, MV_UP
+    { MV_RIGHT, MV_UP,   MV_LEFT,  MV_DOWN },
+    { MV_LEFT,  MV_DOWN, MV_RIGHT, MV_UP }
   };
 
   switch(element)
@@ -226,6 +261,20 @@ void InitMovDir(int x, int y)
       Feld[x][y] = EL_FLIEGER;
       MovDir[x][y] = direction[0][element-EL_FLIEGER_R];
       break;
+    case EL_BUTTERFLY_R:
+    case EL_BUTTERFLY_O:
+    case EL_BUTTERFLY_L:
+    case EL_BUTTERFLY_U:
+      Feld[x][y] = EL_BUTTERFLY;
+      MovDir[x][y] = direction[0][element-EL_BUTTERFLY_R];
+      break;
+    case EL_FIREFLY_R:
+    case EL_FIREFLY_O:
+    case EL_FIREFLY_L:
+    case EL_FIREFLY_U:
+      Feld[x][y] = EL_FIREFLY;
+      MovDir[x][y] = direction[0][element-EL_FIREFLY_R];
+      break;
     case EL_PACMAN_R:
     case EL_PACMAN_O:
     case EL_PACMAN_L:
@@ -235,7 +284,10 @@ void InitMovDir(int x, int y)
       break;
     default:
       MovDir[x][y] = 1<<RND(4);
-      if (element!=EL_KAEFER && element!=EL_FLIEGER)
+      if (element != EL_KAEFER &&
+         element != EL_FLIEGER &&
+         element != EL_BUTTERFLY &&
+         element != EL_FIREFLY)
        break;
 
       for(i=0;i<4;i++)
@@ -247,12 +299,12 @@ void InitMovDir(int x, int y)
 
        if (!IN_LEV_FIELD(x1,y1) || !IS_FREE(x1,y1))
        {
-         if (element==EL_KAEFER)
+         if (element==EL_KAEFER || element==EL_BUTTERFLY)
          {
            MovDir[x][y] = direction[0][i];
            break;
          }
-         else if (element==EL_FLIEGER)
+         else if (element==EL_FLIEGER || element==EL_FIREFLY)
          {
            MovDir[x][y] = direction[1][i];
            break;
@@ -282,6 +334,7 @@ void InitAmoebaNr(int x, int y)
 
   AmoebaNr[x][y] = group_nr;
   AmoebaCnt[group_nr]++;
+  AmoebaCnt2[group_nr]++;
 }
 
 void GameWon()
@@ -289,34 +342,52 @@ void GameWon()
   int hi_pos;
   int bumplevel = FALSE;
 
-  if (sound_loops_on)
-    PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP);
+  LevelSolved = FALSE;
 
-  if (TimeLeft>0) 
+  if (TimeLeft)
   {
-    for(;TimeLeft>=0;TimeLeft--)
+    if (sound_loops_on)
+      PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP);
+
+    while(TimeLeft>0)
     {
       if (!sound_loops_on)
        PlaySoundStereo(SND_SIRR,PSND_MAX_RIGHT);
       if (TimeLeft && !(TimeLeft % 10))
        RaiseScore(level.score[SC_ZEITBONUS]);
+      if (TimeLeft > 100 && !(TimeLeft % 10))
+       TimeLeft -= 10;
+      else
+       TimeLeft--;
       DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
       BackToFront();
       Delay(10000);
     }
+
+    if (sound_loops_on)
+      StopSound(SND_SIRR);
   }
 
-  if (sound_loops_on)
-    StopSound(SND_SIRR);
   FadeSounds();
 
+  /* Hero disappears */
+  DrawLevelElement(JX,JY,Feld[JX][JY]);
+  JX = JY = -1;
+  BackToFront();
+
   if (tape.playing)
     return;
 
   CloseDoor(DOOR_CLOSE_1);
 
+  if (tape.recording)
+  {
+    TapeStop();
+    SaveLevelTape(tape.level_nr);      /* Ask to save tape */
+  }
+
   if (level_nr==player.handicap &&
-      level_nr<leveldir[leveldir_nr].num_ready-1)
+      level_nr<leveldir[leveldir_nr].levels-1)
   { 
     player.handicap++; 
     bumplevel = TRUE;
@@ -337,6 +408,7 @@ void GameWon()
       level_nr++;
     DrawMainMenu();
   }
+
   BackToFront();
 }
 
@@ -401,7 +473,6 @@ void InitMovingField(int x, int y, int direction)
   int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
   int newy = y + (direction==MV_UP   ? -1 : direction==MV_DOWN  ? +1 : 0);
 
-  CheckMoving = TRUE;
   MovDir[x][y] = direction;
   MovDir[newx][newy] = direction;
   if (Feld[newx][newy]==EL_LEERRAUM)
@@ -481,43 +552,58 @@ void RemoveMovingField(int x, int y)
 
 void DrawDynamite(int x, int y)
 {
-  int phase = (48-MovDelay[x][y])/6;
-
   if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
     return;
 
-  if (phase>6)
-    phase = 6;
-
   if (Store[x][y])
   {
     DrawGraphic(SCROLLX(x),SCROLLY(y),el2gfx(Store[x][y]));
-    if (PLAYER(x,y))
+    if (IS_PLAYER(x,y))
       DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
   }
-  else if (PLAYER(x,y))
+  else if (IS_PLAYER(x,y))
     DrawGraphic(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
 
-  if (Store[x][y] || PLAYER(x,y))
-    DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
+  if (Feld[x][y]==EL_DYNAMIT)
+  {
+    int phase = (48-MovDelay[x][y])/6;
+
+    if (phase>6)
+      phase = 6;
+
+    if (Store[x][y] || IS_PLAYER(x,y))
+      DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
+    else
+      DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
+  }
   else
-    DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
+  {
+    int phase = ((48-MovDelay[x][y])/3) % 8;
+
+    if (phase>3)
+      phase = 7-phase;
+
+    if (Store[x][y] || IS_PLAYER(x,y))
+      DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNABOMB+phase);
+    else
+      DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNABOMB+phase);
+  }
 }
 
 void CheckDynamite(int x, int y)
 {
-  CheckExploding = TRUE;
-
   if (MovDelay[x][y])          /* neues Dynamit / in Wartezustand */
   {
     MovDelay[x][y]--;
     if (MovDelay[x][y])
     {
       if (!(MovDelay[x][y] % 6))
-      {
-       DrawDynamite(x,y);
        PlaySoundLevel(x,y,SND_ZISCH);
-      }
+
+      if (Feld[x][y]==EL_DYNAMIT && !(MovDelay[x][y] % 6))
+       DrawDynamite(x,y);
+      else if (Feld[x][y]==EL_DYNABOMB && !(MovDelay[x][y] % 3))
+       DrawDynamite(x,y);
 
       return;
     }
@@ -555,8 +641,12 @@ void Explode(int ex, int ey, int phase, int mode)
       if (element==EL_EXPLODING)
        element = Store2[x][y];
 
-      if (PLAYER(ex,ey) || center_element==EL_KAEFER)
+      if (IS_PLAYER(ex,ey))
+       Store[x][y] = EL_EDELSTEIN_GELB;
+      else if (center_element==EL_KAEFER)
        Store[x][y] = ((x==ex && y==ey) ? EL_DIAMANT : EL_EDELSTEIN);
+      else if (center_element==EL_BUTTERFLY)
+       Store[x][y] = EL_EDELSTEIN_BD;
       else if (center_element==EL_MAMPFER)
        Store[x][y] = level.mampfer_inhalt[MampferNr][x-ex+1][y-ey+1];
       else if (center_element==EL_AMOEBA2DIAM)
@@ -565,18 +655,28 @@ void Explode(int ex, int ey, int phase, int mode)
        Store[x][y] = EL_EDELSTEIN;
       else if (element==EL_ERZ_DIAM)
        Store[x][y] = EL_DIAMANT;
-      else if (element==EL_ERZ_EDEL2)
-       Store[x][y] = EL_EDELSTEIN2;
-      else if (element==EL_ERZ_EDEL3)
-       Store[x][y] = EL_EDELSTEIN3;
+      else if (element==EL_ERZ_EDEL_BD)
+       Store[x][y] = EL_EDELSTEIN_BD;
+      else if (element==EL_ERZ_EDEL_GELB)
+       Store[x][y] = EL_EDELSTEIN_GELB;
+      else if (element==EL_ERZ_EDEL_ROT)
+       Store[x][y] = EL_EDELSTEIN_ROT;
+      else if (element==EL_ERZ_EDEL_LILA)
+       Store[x][y] = EL_EDELSTEIN_LILA;
       else if (!IS_PFORTE(Store[x][y]))
        Store[x][y] = EL_LEERRAUM;
 
       if (x!=ex || y!=ey || center_element==EL_AMOEBA2DIAM || mode==EX_BORDER)
        Store2[x][y] = element;
 
-      if (AmoebaNr[x][y] && (element==EL_AMOEBE_VOLL || element==EL_AMOEBING))
+      if (AmoebaNr[x][y] &&
+         (element==EL_AMOEBE_VOLL ||
+          element==EL_AMOEBE_BD ||
+          element==EL_AMOEBING))
+      {
        AmoebaCnt[AmoebaNr[x][y]]--;
+       AmoebaCnt2[AmoebaNr[x][y]]--;
+      }
 
       RemoveMovingField(x,y);
       Feld[x][y] = EL_EXPLODING;
@@ -604,12 +704,15 @@ void Explode(int ex, int ey, int phase, int mode)
   {
     int element = Store2[x][y];
 
-    if (PLAYER(x,y))
+    if (IS_PLAYER(x,y))
       KillHero();
     else if (element==EL_BOMBE ||
             element==EL_DYNAMIT ||
             element==EL_DYNAMIT_AUS ||
             element==EL_DYNABOMB ||
+            element==EL_DYNABOMB_NR ||
+            element==EL_DYNABOMB_SZ ||
+            element==EL_DYNABOMB_XL ||
             element==EL_KAEFER)
     {
       Feld[x][y] = Store2[x][y];
@@ -638,8 +741,6 @@ void Explode(int ex, int ey, int phase, int mode)
 
     DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EXPLOSION+(phase/delay-1));
   }
-
-  CheckExploding = TRUE;
 }
 
 void DynaExplode(int ex, int ey, int size)
@@ -647,10 +748,10 @@ void DynaExplode(int ex, int ey, int size)
   int i,j;
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
   Explode(ex,ey,0,EX_CENTER);
@@ -661,11 +762,19 @@ void DynaExplode(int ex, int ey, int size)
     {
       int x = ex+j*xy[i%4][0];
       int y = ey+j*xy[i%4][1];
+      int element;
 
       if (!IN_LEV_FIELD(x,y) || IS_MASSIV(Feld[x][y]))
        break;
 
+      element = Feld[x][y];
       Explode(x,y,0,EX_BORDER);
+
+      if (element != EL_LEERRAUM &&
+         element != EL_ERDREICH &&
+         element != EL_EXPLODING &&
+         !DynaBombXL)
+       break;
     }
   }
 
@@ -676,35 +785,35 @@ void Bang(int x, int y)
 {
   int element = Feld[x][y];
 
-  CheckExploding = TRUE;
   PlaySoundLevel(x,y,SND_ROAAAR);
 
   switch(element)
   {
     case EL_KAEFER:
-      RaiseScore(level.score[SC_KAEFER]);
-      break;
     case EL_FLIEGER:
-      RaiseScore(level.score[SC_FLIEGER]);
-      break;
+    case EL_BUTTERFLY:
+    case EL_FIREFLY:
     case EL_MAMPFER:
     case EL_MAMPFER2:
-      RaiseScore(level.score[SC_MAMPFER]);
-      break;
     case EL_ZOMBIE:
-      RaiseScore(level.score[SC_ZOMBIE]);
-      break;
     case EL_PACMAN:
-      RaiseScore(level.score[SC_PACMAN]);
+      RaiseScoreElement(element);
+      Explode(x,y,0,EX_NORMAL);
+      break;
+    case EL_DYNABOMB:
+    case EL_DYNABOMB_NR:
+    case EL_DYNABOMB_SZ:
+    case EL_DYNABOMB_XL:
+      DynaExplode(x,y,DynaBombSize);
+      break;
+    case EL_BIRNE_AUS:
+    case EL_BIRNE_EIN:
+      Explode(x,y,0,EX_CENTER);
       break;
     default:
+      Explode(x,y,0,EX_NORMAL);
       break;
   }
-
-  if (element==EL_DYNABOMB)
-    DynaExplode(x,y,DynaBombSize);
-  else
-    Explode(x,y,0,EX_NORMAL);
 }
 
 void Blurb(int x, int y)
@@ -731,8 +840,6 @@ void Blurb(int x, int y)
   {
     int graphic = (element==EL_BLURB_LEFT ? GFX_BLURB_LEFT : GFX_BLURB_RIGHT);
 
-    CheckExploding = TRUE;
-
     if (!MovDelay[x][y])       /* neue Phase / noch nicht gewartet */
       MovDelay[x][y] = 5;
 
@@ -780,7 +887,7 @@ void Impact(int x, int y)
   /* Auftreffendes Element ist Säuretropfen */
   if (element==EL_TROPFEN && (lastline || object_hit))
   {
-    if (object_hit && PLAYER(x,y+1))
+    if (object_hit && IS_PLAYER(x,y+1))
       KillHero();
     else
     {
@@ -793,24 +900,36 @@ void Impact(int x, int y)
   /* Welches Element kriegt was auf die Rübe? */
   if (!lastline && object_hit)
   {
-    int smashed = Feld[x][y+1];
+    int smashed = MovingOrBlocked2Element(x,y+1);
+
+    if (CAN_CHANGE(element) && 
+       (smashed==EL_SIEB_LEER || smashed==EL_SIEB2_LEER) && !SiebAktiv)
+      SiebAktiv = level.dauer_sieb * FRAMES_PER_SECOND;
 
-    if (PLAYER(x,y+1))
+    if (IS_PLAYER(x,y+1))
     {
       KillHero();
       return;
     }
-    else if (element==EL_FELSBROCKEN ||
-            element==EL_EDELSTEIN2 || element==EL_EDELSTEIN3)
+    else if (element==EL_EDELSTEIN_BD)
     {
-      if (IS_ENEMY(MovingOrBlocked2Element(x,y+1)))
+      if (IS_ENEMY(smashed) && IS_BD_ELEMENT(smashed))
+      {
+       Bang(x,y+1);
+       return;
+      }
+    }
+    else if (element==EL_FELSBROCKEN)
+    {
+      if (IS_ENEMY(smashed))
       {
        Bang(x,y+1);
        return;
       }
       else if (!IS_MOVING(x,y+1))
       {
-       if (smashed==EL_BOMBE)
+       if (smashed==EL_BOMBE ||
+           smashed==EL_BIRNE_AUS || smashed==EL_BIRNE_EIN)
        {
          Bang(x,y+1);
          return;
@@ -819,7 +938,7 @@ void Impact(int x, int y)
        {
          Feld[x][y+1] = EL_CRACKINGNUT;
          PlaySoundLevel(x,y,SND_KNACK);
-         RaiseScore(level.score[SC_KOKOSNUSS]);
+         RaiseScoreElement(EL_KOKOSNUSS);
          return;
        }
        else if (smashed==EL_DIAMANT)
@@ -832,9 +951,12 @@ void Impact(int x, int y)
     }
   }
 
-  /* Kein Geräusch beim Durchqueren des Siebes */
+  /* Geräusch beim Durchqueren des Siebes */
   if (!lastline && (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER))
+  {
+    PlaySoundLevel(x,y,SND_QUIRK);
     return;
+  }
 
   /* Geräusch beim Auftreffen */
   if (lastline || object_hit)
@@ -844,8 +966,10 @@ void Impact(int x, int y)
     switch(element)
     {
       case EL_EDELSTEIN:
-      case EL_EDELSTEIN2:
-      case EL_EDELSTEIN3:
+      case EL_EDELSTEIN_BD:
+      case EL_EDELSTEIN_GELB:
+      case EL_EDELSTEIN_ROT:
+      case EL_EDELSTEIN_LILA:
       case EL_DIAMANT:
         sound = SND_PLING;
        break;
@@ -878,167 +1002,155 @@ void Impact(int x, int y)
 
 void TurnRound(int x, int y)
 {
+  static struct
+  {
+    int x,y;
+  } move_xy[] =
+  {
+    { 0,0 },
+    {-1,0 },
+    {+1,0 },
+    { 0,0 },
+    { 0,-1 },
+    { 0,0 }, { 0,0 }, { 0,0 },
+    { 0,+1 }
+  };
+  static struct
+  {
+    int left,right,back;
+  } turn[] =
+  {
+    { 0,       0,              0 },
+    { MV_DOWN, MV_UP,          MV_RIGHT },
+    { MV_UP,   MV_DOWN,        MV_LEFT },
+    { 0,       0,              0 },
+    { MV_LEFT, MV_RIGHT,       MV_DOWN },
+    { 0,0,0 }, { 0,0,0 },      { 0,0,0 },
+    { MV_RIGHT,        MV_LEFT,        MV_UP }
+  };
+
   int element = Feld[x][y];
-  int direction = MovDir[x][y];
+  int old_move_dir = MovDir[x][y];
+  int left_dir = turn[old_move_dir].left;
+  int right_dir = turn[old_move_dir].right;
+  int back_dir = turn[old_move_dir].back;
+
+  int left_dx = move_xy[left_dir].x, left_dy = move_xy[left_dir].y;
+  int right_dx = move_xy[right_dir].x, right_dy = move_xy[right_dir].y;
+  int move_dx = move_xy[old_move_dir].x, move_dy = move_xy[old_move_dir].y;
+
+  int left_x = x+left_dx, left_y = y+left_dy;
+  int right_x = x+right_dx, right_y = y+right_dy;
+  int move_x = x+move_dx, move_y = y+move_dy;
 
-  if (element==EL_KAEFER)
+  if (element==EL_KAEFER || element==EL_BUTTERFLY)
   {
     TestIfBadThingHitsOtherBadThing(x,y);
 
-    if (MovDir[x][y]==MV_LEFT)
-    {
-      if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
-       MovDir[x][y]=MV_UP;
-      else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
-       MovDir[x][y]=MV_DOWN;
-    }
-    else if (MovDir[x][y]==MV_RIGHT)
-    {
-      if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
-       MovDir[x][y]=MV_DOWN;
-      else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
-       MovDir[x][y]=MV_UP;
-    }
-    else if (MovDir[x][y]==MV_UP)
-    {
-      if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
-       MovDir[x][y]=MV_RIGHT;
-      else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
-       MovDir[x][y]=MV_LEFT;
-    }
-    else if (MovDir[x][y]==MV_DOWN)
-    {
-      if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
-       MovDir[x][y]=MV_LEFT;
-      else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
-       MovDir[x][y]=MV_RIGHT;
-    }
+    if (IN_LEV_FIELD(right_x,right_y) &&
+       IS_FREE_OR_PLAYER(right_x,right_y))
+      MovDir[x][y] = right_dir;
+    else if (!IN_LEV_FIELD(move_x,move_y) ||
+            !IS_FREE_OR_PLAYER(move_x,move_y))
+      MovDir[x][y] = left_dir;
 
-    if (direction!=MovDir[x][y])
-      MovDelay[x][y]=5;
+    if (element==EL_KAEFER && MovDir[x][y] != old_move_dir)
+      MovDelay[x][y] = 5;
+    else if (element==EL_BUTTERFLY)    /* && MovDir[x][y]==left_dir) */
+      MovDelay[x][y] = 1;
   }
-  else if (element==EL_FLIEGER)
+  else if (element==EL_FLIEGER || element==EL_FIREFLY)
   {
     TestIfBadThingHitsOtherBadThing(x,y);
 
-    if (MovDir[x][y]==MV_LEFT)
-    {
-      if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
-       MovDir[x][y]=MV_DOWN;
-      else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
-       MovDir[x][y]=MV_UP;
-    }
-    else if (MovDir[x][y]==MV_RIGHT)
-    {
-      if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
-       MovDir[x][y]=MV_UP;
-      else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
-       MovDir[x][y]=MV_DOWN;
-    }
-    else if (MovDir[x][y]==MV_UP)
-    {
-      if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
-       MovDir[x][y]=MV_LEFT;
-      else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
-       MovDir[x][y]=MV_RIGHT;
-    }
-    else if (MovDir[x][y]==MV_DOWN)
-    {
-      if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
-       MovDir[x][y]=MV_RIGHT;
-      else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
-       MovDir[x][y]=MV_LEFT;
-    }
+    if (IN_LEV_FIELD(left_x,left_y) &&
+       IS_FREE_OR_PLAYER(left_x,left_y))
+      MovDir[x][y] = left_dir;
+    else if (!IN_LEV_FIELD(move_x,move_y) ||
+            !IS_FREE_OR_PLAYER(move_x,move_y))
+      MovDir[x][y] = right_dir;
 
-    if (direction!=MovDir[x][y])
-      MovDelay[x][y]=5;
+    if (element==EL_FLIEGER && MovDir[x][y] != old_move_dir)
+      MovDelay[x][y] = 5;
+    else if (element==EL_FIREFLY)      /* && MovDir[x][y]==right_dir) */
+      MovDelay[x][y] = 1;
   }
   else if (element==EL_MAMPFER)
   {
-    if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
-    {
-      MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
-      if (IN_LEV_FIELD(x,y-1) &&
-         (IS_FREE(x,y-1) || Feld[x][y-1]==EL_DIAMANT) &&
-         RND(2))
-       MovDir[x][y]=MV_UP;
-      if (IN_LEV_FIELD(x,y+1) &&
-         (IS_FREE(x,y+1) || Feld[x][y+1]==EL_DIAMANT) &&
-         RND(2))
-       MovDir[x][y]=MV_DOWN;
-    }
-    else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
-    {
-      MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
-      if (IN_LEV_FIELD(x-1,y) &&
-         (IS_FREE(x-1,y) || Feld[x-1][y]==EL_DIAMANT) &&
-         RND(2))
-       MovDir[x][y]=MV_LEFT;
-      if (IN_LEV_FIELD(x+1,y) &&
-         (IS_FREE(x+1,y) || Feld[x+1][y]==EL_DIAMANT) &&
-         RND(2))
-       MovDir[x][y]=MV_RIGHT;
-    }
+    BOOL can_turn_left = FALSE, can_turn_right = FALSE;
+
+    if (IN_LEV_FIELD(left_x,left_y) &&
+       (IS_FREE_OR_PLAYER(left_x,left_y) ||
+        Feld[left_x][left_y] == EL_DIAMANT))
+      can_turn_left = TRUE;
+    if (IN_LEV_FIELD(right_x,right_y) &&
+       (IS_FREE_OR_PLAYER(right_x,right_y) ||
+        Feld[right_x][right_y] == EL_DIAMANT))
+      can_turn_right = TRUE;
+
+    if (can_turn_left && can_turn_right)
+      MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
+    else if (can_turn_left)
+      MovDir[x][y] = (RND(2) ? left_dir : back_dir);
+    else if (can_turn_right)
+      MovDir[x][y] = (RND(2) ? right_dir : back_dir);
+    else
+      MovDir[x][y] = back_dir;
 
-    MovDelay[x][y]=8+8*RND(3);
+    MovDelay[x][y] = 8+8*RND(3);
   }
   else if (element==EL_MAMPFER2)
   {
-    if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
-    {
-      MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
-      if (IN_LEV_FIELD(x,y-1) &&
-         (IS_FREE(x,y-1) || IS_MAMPF2(Feld[x][y-1])) && RND(2))
-       MovDir[x][y]=MV_UP;
-      if (IN_LEV_FIELD(x,y+1) &&
-         (IS_FREE(x,y+1) || IS_MAMPF2(Feld[x][y+1])) && RND(2))
-       MovDir[x][y]=MV_DOWN;
-    }
-    else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
-    {
-      MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
-      if (IN_LEV_FIELD(x-1,y) &&
-         (IS_FREE(x-1,y) || IS_MAMPF2(Feld[x-1][y])) && RND(2))
-       MovDir[x][y]=MV_LEFT;
-      if (IN_LEV_FIELD(x+1,y) &&
-         (IS_FREE(x+1,y) || IS_MAMPF2(Feld[x+1][y])) && RND(2))
-       MovDir[x][y]=MV_RIGHT;
-    }
+    BOOL can_turn_left = FALSE, can_turn_right = FALSE;
+
+    if (IN_LEV_FIELD(left_x,left_y) &&
+       (IS_FREE_OR_PLAYER(left_x,left_y) ||
+        IS_MAMPF2(Feld[left_x][left_y])))
+      can_turn_left = TRUE;
+    if (IN_LEV_FIELD(right_x,right_y) &&
+       (IS_FREE_OR_PLAYER(right_x,right_y) ||
+        IS_MAMPF2(Feld[right_x][right_y])))
+      can_turn_right = TRUE;
+
+    if (can_turn_left && can_turn_right)
+      MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
+    else if (can_turn_left)
+      MovDir[x][y] = (RND(2) ? left_dir : back_dir);
+    else if (can_turn_right)
+      MovDir[x][y] = (RND(2) ? right_dir : back_dir);
+    else
+      MovDir[x][y] = back_dir;
 
-    MovDelay[x][y]=8+8*RND(3);
+    MovDelay[x][y] = 8+8*RND(3);
   }
   else if (element==EL_PACMAN)
   {
-    if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
-    {
-      MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
-      if (IN_LEV_FIELD(x,y-1) &&
-         (IS_FREE(x,y-1) || IS_AMOEBOID(Feld[x][y-1])) &&
-         RND(2))
-       MovDir[x][y]=MV_UP;
-      if (IN_LEV_FIELD(x,y+1) &&
-         (IS_FREE(x,y+1) || IS_AMOEBOID(Feld[x][y+1])) &&
-         RND(2))
-       MovDir[x][y]=MV_DOWN;
-    }
-    else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
-    {
-      MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
-      if (IN_LEV_FIELD(x-1,y) &&
-         (IS_FREE(x-1,y) || IS_AMOEBOID(Feld[x-1][y])) &&
-         RND(2))
-       MovDir[x][y]=MV_LEFT;
-      if (IN_LEV_FIELD(x+1,y) &&
-         (IS_FREE(x+1,y) || IS_AMOEBOID(Feld[x+1][y])) &&
-         RND(2))
-       MovDir[x][y]=MV_RIGHT;
-    }
+    BOOL can_turn_left = FALSE, can_turn_right = FALSE;
+
+    if (IN_LEV_FIELD(left_x,left_y) &&
+       (IS_FREE_OR_PLAYER(left_x,left_y) ||
+        IS_AMOEBOID(Feld[left_x][left_y])))
+      can_turn_left = TRUE;
+    if (IN_LEV_FIELD(right_x,right_y) &&
+       (IS_FREE_OR_PLAYER(right_x,right_y) ||
+        IS_AMOEBOID(Feld[right_x][right_y])))
+      can_turn_right = TRUE;
+
+    if (can_turn_left && can_turn_right)
+      MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
+    else if (can_turn_left)
+      MovDir[x][y] = (RND(2) ? left_dir : back_dir);
+    else if (can_turn_right)
+      MovDir[x][y] = (RND(2) ? right_dir : back_dir);
+    else
+      MovDir[x][y] = back_dir;
 
-    MovDelay[x][y]=3+RND(20);
+    MovDelay[x][y] = 3+RND(20);
   }
   else if (element==EL_ZOMBIE)
   {
     int attr_x = JX, attr_y = JY;
+    int newx, newy;
 
     if (ZX>=0 && ZY>=0)
     {
@@ -1046,19 +1158,23 @@ void TurnRound(int x, int y)
       attr_y = ZY;
     }
 
-    MovDir[x][y]=MV_NO_MOVING;
+    MovDir[x][y] = MV_NO_MOVING;
     if (attr_x<x)
-      MovDir[x][y]|=MV_LEFT;
+      MovDir[x][y] |= (GameOver ? MV_RIGHT : MV_LEFT);
     else if (attr_x>x)
-      MovDir[x][y]|=MV_RIGHT;
+      MovDir[x][y] |= (GameOver ? MV_LEFT : MV_RIGHT);
     if (attr_y<y)
-      MovDir[x][y]|=MV_UP;
+      MovDir[x][y] |= (GameOver ? MV_DOWN : MV_UP);
     else if (attr_y>y)
-      MovDir[x][y]|=MV_DOWN;
+      MovDir[x][y] |= (GameOver ? MV_UP : MV_DOWN);
     if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN)))
       MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN));
 
-    MovDelay[x][y] = 8+8*RND(2);
+    Moving2Blocked(x,y,&newx,&newy);
+    if (IN_LEV_FIELD(newx,newy) && IS_FREE_OR_PLAYER(newx,newy))
+      MovDelay[x][y] = 4+4*!RND(3);
+    else
+      MovDelay[x][y] = 8;
   }
 }
 
@@ -1081,8 +1197,6 @@ void StartMoving(int x, int y)
       }
       else if (Feld[x][y+1]==EL_MORAST_LEER)
       {
-       CheckMoving = TRUE;
-
        if (!MovDelay[x][y])
          MovDelay[x][y] = 16;
 
@@ -1120,14 +1234,13 @@ void StartMoving(int x, int y)
        Store[x][y] = EL_SIEB2_LEER;
       }
     }
-    else if (CAN_CHANGE(element) &&
+    else if (SiebAktiv && CAN_CHANGE(element) &&
             (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER))
     {
       InitMovingField(x,y,MV_DOWN);
       Store[x][y] =
        (Feld[x][y+1]==EL_SIEB_LEER ? EL_SIEB_VOLL : EL_SIEB2_VOLL);
       Store2[x][y+1] = element;
-      SiebAktiv = 330;
     }
     else if (CAN_SMASH(element) && Feld[x][y+1]==EL_SALZSAEURE)
     {
@@ -1150,15 +1263,16 @@ void StartMoving(int x, int y)
     }
     else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
     {
-      int left  = (x>0 && IS_FREE(x-1,y) &&
-                  (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE));
-      int right = (x<lev_fieldx-1 && IS_FREE(x+1,y) &&
-                  (IS_FREE(x+1,y+1) || Feld[x+1][y+1]==EL_SALZSAEURE));
+      BOOL left  = (x>0 && IS_FREE(x-1,y) &&
+                   (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE));
+      BOOL right = (x<lev_fieldx-1 && IS_FREE(x+1,y) &&
+                   (IS_FREE(x+1,y+1) || Feld[x+1][y+1]==EL_SALZSAEURE));
 
       if (left || right)
       {
-       if (left && right)
-         left = !(right=RND(2));
+       if (left && right && game_emulation != EMU_BOULDERDASH)
+         left = !(right = RND(2));
+
        InitMovingField(x,y,left ? MV_LEFT : MV_RIGHT);
       }
     }
@@ -1167,14 +1281,13 @@ void StartMoving(int x, int y)
   {
     int newx,newy;
 
-    CheckMoving = TRUE;
-
     if (!MovDelay[x][y])       /* neuer Schritt / noch nicht gewartet */
     {
-      if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER)
+      if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER ||
+         element==EL_BUTTERFLY || element==EL_FIREFLY)
       {
        TurnRound(x,y);
-       if (MovDelay[x][y] && (element==EL_KAEFER || element==EL_FLIEGER))
+       if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER))
          DrawLevelField(x,y);
       }
     }
@@ -1191,23 +1304,29 @@ void StartMoving(int x, int y)
          phase = 7-phase;
 
        if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
-         DrawGraphic(SCROLLX(x),SCROLLY(y),
-                     el2gfx(element)+phase);
+         DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(element)+phase);
 
        if ((element==EL_MAMPFER || element==EL_MAMPFER2)
            && MovDelay[x][y]%4==3)
          PlaySoundLevel(x,y,SND_NJAM);
       }
+      else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
+      {
+       int phase = (FrameCounter % 4) / 2;
+
+       if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+         DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(element)+phase);
+      }
 
       if (MovDelay[x][y])
        return;
     }
 
-    if (element==EL_KAEFER)
+    if (element==EL_KAEFER || element==EL_BUTTERFLY)
     {
       PlaySoundLevel(x,y,SND_KLAPPER);
     }
-    else if (element==EL_FLIEGER)
+    else if (element==EL_FLIEGER || element==EL_FIREFLY)
     {
       PlaySoundLevel(x,y,SND_ROEHR);
     }
@@ -1216,7 +1335,7 @@ void StartMoving(int x, int y)
 
     Moving2Blocked(x,y,&newx,&newy);   /* wohin soll's gehen? */
 
-    if (PLAYER(newx,newy))             /* Spieler erwischt */
+    if (IS_PLAYER(newx,newy))          /* Spieler erwischt */
     {
       MovDir[x][y] = 0;
       KillHero();
@@ -1236,8 +1355,12 @@ void StartMoving(int x, int y)
     else if (element==EL_MAMPFER2 && IN_LEV_FIELD(newx,newy) &&
             IS_MAMPF2(Feld[newx][newy]))
     {
-      if (AmoebaNr[newx][newy] && Feld[newx][newy]==EL_AMOEBE_VOLL)
-       AmoebaCnt[AmoebaNr[newx][newy]]--;
+      if (AmoebaNr[newx][newy])
+      {
+       AmoebaCnt2[AmoebaNr[newx][newy]]--;
+       if (Feld[newx][newy]==EL_AMOEBE_VOLL || Feld[newx][newy]==EL_AMOEBE_BD)
+         AmoebaCnt[AmoebaNr[newx][newy]]--;
+      }
 
       if (IS_MOVING(newx,newy))
        RemoveMovingField(newx,newy);
@@ -1250,8 +1373,12 @@ void StartMoving(int x, int y)
     else if (element==EL_PACMAN && IN_LEV_FIELD(newx,newy) &&
             IS_AMOEBOID(Feld[newx][newy]))
     {
-      if (AmoebaNr[newx][newy] && Feld[newx][newy]==EL_AMOEBE_VOLL)
-       AmoebaCnt[AmoebaNr[newx][newy]]--;
+      if (AmoebaNr[newx][newy])
+      {
+       AmoebaCnt2[AmoebaNr[newx][newy]]--;
+       if (Feld[newx][newy]==EL_AMOEBE_VOLL || Feld[newx][newy]==EL_AMOEBE_BD)
+         AmoebaCnt[AmoebaNr[newx][newy]]--;
+      }
 
       Feld[newx][newy] = EL_LEERRAUM;
       DrawLevelField(newx,newy);
@@ -1265,10 +1392,14 @@ void StartMoving(int x, int y)
     else if (!IN_LEV_FIELD(newx,newy) || !IS_FREE(newx,newy))
     {                                  /* gegen Wand gelaufen */
       TurnRound(x,y);
-      DrawLevelField(x,y);
+      if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER))
+       DrawLevelField(x,y);
       return;
     }
 
+    if (element==EL_ZOMBIE)
+      PlaySoundLevel(x,y,SND_SCHLURF);
+
     InitMovingField(x,y,MovDir[x][y]);
   }
 
@@ -1314,24 +1445,22 @@ void ContinueMoving(int x, int y)
     else if (Store[x][y]==EL_SIEB_VOLL)
     {
       Store[x][y] = 0;
-      Feld[newx][newy] = EL_SIEB_VOLL;
-      element = EL_SIEB_VOLL;
+      element = Feld[newx][newy] = (SiebAktiv ? EL_SIEB_VOLL : EL_SIEB_TOT);
     }
     else if (Store[x][y]==EL_SIEB_LEER)
     {
       Store[x][y] = Store2[x][y] = 0;
-      Feld[x][y] = EL_SIEB_LEER;
+      Feld[x][y] = (SiebAktiv ? EL_SIEB_LEER : EL_SIEB_TOT);
     }
     else if (Store[x][y]==EL_SIEB2_VOLL)
     {
       Store[x][y] = 0;
-      Feld[newx][newy] = EL_SIEB2_VOLL;
-      element = EL_SIEB2_VOLL;
+      element = Feld[newx][newy] = (SiebAktiv ? EL_SIEB2_VOLL : EL_SIEB2_TOT);
     }
     else if (Store[x][y]==EL_SIEB2_LEER)
     {
       Store[x][y] = Store2[x][y] = 0;
-      Feld[x][y] = EL_SIEB2_LEER;
+      Feld[x][y] = (SiebAktiv ? EL_SIEB2_LEER : EL_SIEB2_TOT);
     }
     else if (Store[x][y]==EL_SALZSAEURE)
     {
@@ -1345,7 +1474,8 @@ void ContinueMoving(int x, int y)
       Feld[x][y] = EL_AMOEBE_NASS;
     }
 
-    MovPos[x][y] = MovDir[x][y] = 0;
+    MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
+    MovDelay[newx][newy] = 0;
 
     if (!CAN_MOVE(element))
       MovDir[newx][newy] = 0;
@@ -1355,7 +1485,6 @@ void ContinueMoving(int x, int y)
 
     Stop[newx][newy] = TRUE;
     JustHit[x][newy] = 3;
-    CheckMoving = TRUE;
 
     if (DONT_TOUCH(element))   /* Käfer oder Flieger */
     {
@@ -1368,10 +1497,7 @@ void ContinueMoving(int x, int y)
       Impact(x,newy);
   }
   else                         /* noch in Bewegung */
-  {
     DrawLevelField(x,y);
-    CheckMoving = TRUE;
-  }
 }
 
 int AmoebeNachbarNr(int ax, int ay)
@@ -1381,10 +1507,10 @@ int AmoebeNachbarNr(int ax, int ay)
   int group_nr = 0;
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
   for(i=0;i<4;i++)
@@ -1408,10 +1534,10 @@ void AmoebenVereinigen(int ax, int ay)
   int new_group_nr = AmoebaNr[ax][ay];
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
   if (!new_group_nr)
@@ -1425,13 +1551,17 @@ void AmoebenVereinigen(int ax, int ay)
     if (!IN_LEV_FIELD(x,y))
       continue;
 
-    if ((Feld[x][y]==EL_AMOEBE_VOLL || Feld[x][y]==EL_AMOEBE_TOT) &&
+    if ((Feld[x][y]==EL_AMOEBE_VOLL ||
+        Feld[x][y]==EL_AMOEBE_BD ||
+        Feld[x][y]==EL_AMOEBE_TOT) &&
        AmoebaNr[x][y] != new_group_nr)
     {
       int old_group_nr = AmoebaNr[x][y];
 
       AmoebaCnt[new_group_nr] += AmoebaCnt[old_group_nr];
       AmoebaCnt[old_group_nr] = 0;
+      AmoebaCnt2[new_group_nr] += AmoebaCnt2[old_group_nr];
+      AmoebaCnt2[old_group_nr] = 0;
 
       for(yy=0;yy<lev_fieldy;yy++) for(xx=0;xx<lev_fieldx;xx++)
        if (AmoebaNr[xx][yy]==old_group_nr)
@@ -1446,10 +1576,10 @@ void AmoebeUmwandeln(int ax, int ay)
   int group_nr = AmoebaNr[ax][ay];
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
   if (Feld[ax][ay]==EL_AMOEBE_TOT)
@@ -1480,13 +1610,35 @@ void AmoebeUmwandeln(int ax, int ay)
   }
 }
 
+void AmoebeUmwandeln2(int ax, int ay, int new_element)
+{
+  int x,y;
+  int group_nr = AmoebaNr[ax][ay];
+  BOOL done = FALSE;
+
+  for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
+  {
+    if (AmoebaNr[x][y]==group_nr &&
+       (Feld[x][y]==EL_AMOEBE_TOT ||
+        Feld[x][y]==EL_AMOEBE_BD ||
+        Feld[x][y]==EL_AMOEBING))
+    {
+      AmoebaNr[x][y] = 0;
+      Feld[x][y] = new_element;
+      DrawLevelField(x,y);
+      done = TRUE;
+    }
+  }
+
+  if (done)
+    PlaySoundLevel(ax,ay,new_element==EL_FELSBROCKEN ? SND_KLOPF : SND_PLING);
+}
+
 void AmoebeWaechst(int x, int y)
 {
   static long sound_delay = 0;
   static int sound_delay_value = 0;
 
-  CheckExploding = TRUE;
-
   if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
   {
     MovDelay[x][y] = 4;
@@ -1520,14 +1672,12 @@ void AmoebeAbleger(int ax, int ay)
   int newax = ax, neway = ay;
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
-  CheckExploding = TRUE;
-
   if (!level.tempo_amoebe)
   {
     Feld[ax][ay] = EL_AMOEBE_TOT;
@@ -1536,7 +1686,7 @@ void AmoebeAbleger(int ax, int ay)
   }
 
   if (!MovDelay[ax][ay])       /* neue Amoebe / noch nicht gewartet */
-    MovDelay[ax][ay] = RND(33*20/(1+level.tempo_amoebe));
+    MovDelay[ax][ay] = RND(FRAMES_PER_SECOND * 25/(1+level.tempo_amoebe));
 
   if (MovDelay[ax][ay])                /* neue Amoebe / in Wartezustand */
   {
@@ -1585,7 +1735,7 @@ void AmoebeAbleger(int ax, int ay)
        neway = y;
        break;
       }
-      else if (PLAYER(x,y))
+      else if (IS_PLAYER(x,y))
        waiting_for_player = TRUE;
     }
 
@@ -1595,19 +1745,32 @@ void AmoebeAbleger(int ax, int ay)
       {
        Feld[ax][ay] = EL_AMOEBE_TOT;
        DrawLevelField(ax,ay);
+       AmoebaCnt[AmoebaNr[ax][ay]]--;
 
-       if (element==EL_AMOEBE_VOLL && --AmoebaCnt[AmoebaNr[ax][ay]]<=0)
-         AmoebeUmwandeln(ax,ay);
+       if (AmoebaCnt[AmoebaNr[ax][ay]]<=0)     /* Amöbe vollständig tot */
+       {
+         if (element==EL_AMOEBE_VOLL)
+           AmoebeUmwandeln(ax,ay);
+         else if (element==EL_AMOEBE_BD)
+           AmoebeUmwandeln2(ax,ay,level.amoebe_inhalt);
+       }
       }
       return;
     }
-    else if (element==EL_AMOEBE_VOLL)
+    else if (element==EL_AMOEBE_VOLL || element==EL_AMOEBE_BD)
     {
       int new_group_nr = AmoebaNr[ax][ay];
 
       AmoebaNr[newax][neway] = new_group_nr;
       AmoebaCnt[new_group_nr]++;
+      AmoebaCnt2[new_group_nr]++;
       AmoebenVereinigen(newax,neway);
+
+      if (AmoebaCnt2[new_group_nr] >= 200 && element==EL_AMOEBE_BD)
+      {
+       AmoebeUmwandeln2(newax,neway,EL_FELSBROCKEN);
+       return;
+      }
     }
   }
 
@@ -1638,8 +1801,6 @@ void Life(int ax, int ay)
   int life_time = 20;
   int element = Feld[ax][ay];
 
-  CheckExploding = TRUE;
-
   if (Stop[ax][ay])
     return;
 
@@ -1668,7 +1829,7 @@ void Life(int ax, int ay)
       if (!IN_LEV_FIELD(x,y) || (x==xx && y==yy))
        continue;
 
-      if (((Feld[x][y]==element || (element==EL_LIFE && PLAYER(x,y))) &&
+      if (((Feld[x][y]==element || (element==EL_LIFE && IS_PLAYER(x,y))) &&
           !Stop[x][y]) ||
          (IS_FREE(x,y) && Stop[x][y]))
        nachbarn++;
@@ -1700,10 +1861,9 @@ void Life(int ax, int ay)
 
 void Ablenk(int x, int y)
 {
-  CheckExploding = TRUE;
-
   if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
-    MovDelay[x][y] = 33*(level.dauer_ablenk/10);
+    MovDelay[x][y] = level.dauer_ablenk * FRAMES_PER_SECOND;
+
   if (MovDelay[x][y])          /* neue Phase / in Wartezustand */
   {
     MovDelay[x][y]--;
@@ -1717,16 +1877,14 @@ void Ablenk(int x, int y)
     }
   }
 
-  Feld[x][y]=EL_ABLENK_AUS;
+  Feld[x][y] = EL_ABLENK_AUS;
   DrawLevelField(x,y);
   if (ZX==x && ZY==y)
-    ZX=ZY=-1;
+    ZX = ZY = -1;
 }
 
 void Birne(int x, int y)
 {
-  CheckExploding = TRUE;
-
   if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
     MovDelay[x][y] = 400;
 
@@ -1756,26 +1914,11 @@ void Birne(int x, int y)
 
 void Blubber(int x, int y)
 {
-  CheckExploding = TRUE;
-
-  if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
-    MovDelay[x][y] = 20;
-
-  if (MovDelay[x][y])          /* neue Phase / in Wartezustand */
-  {
-    int blubber;
-
-    MovDelay[x][y]--;
-    blubber = MovDelay[x][y]/5;
-    if (!(MovDelay[x][y]%5) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
-      DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_GEBLUBBER+3-blubber);
-  }
+  DrawGraphicAnimation(x,y, GFX_GEBLUBBER, 4, 5, ANIM_NORMAL);
 }
 
 void NussKnacken(int x, int y)
 {
-  CheckExploding = TRUE;
-
   if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
     MovDelay[x][y] = 4;
 
@@ -1795,19 +1938,11 @@ void NussKnacken(int x, int y)
 
 void SiebAktivieren(int x, int y, int typ)
 {
-  CheckExploding = TRUE;
-
   if (SiebAktiv>1)
   {
     if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
       DrawGraphic(SCROLLX(x),SCROLLY(y),
                  (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%8)/2);
-
-/*
-    if (!(SiebAktiv%4))
-      PlaySoundLevel(x,y,SND_MIEP);
-*/
-
   }
   else
   {
@@ -1818,9 +1953,7 @@ void SiebAktivieren(int x, int y, int typ)
 
 void AusgangstuerPruefen(int x, int y)
 {
-  CheckExploding = TRUE;
-
-  if (!Gems)
+  if (!Gems && !SokobanFields && !Lights)
   {
     Feld[x][y] = EL_AUSGANG_ACT;
     PlaySoundLevel(x,y,SND_OEFFNEN);
@@ -1831,8 +1964,6 @@ void AusgangstuerOeffnen(int x, int y)
 {
   int speed = 3;
 
-  CheckExploding = TRUE;
-
   if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
     MovDelay[x][y] = 5*speed;
 
@@ -1855,44 +1986,59 @@ void AusgangstuerOeffnen(int x, int y)
 
 void AusgangstuerBlinken(int x, int y)
 {
-  CheckExploding = TRUE;
+  DrawGraphicAnimation(x,y, GFX_AUSGANG_AUF, 4, 2, ANIM_OSCILLATE);
+}
 
-  if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
-    MovDelay[x][y] = 16;
+void EdelsteinFunkeln(int x, int y)
+{
+  if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)) || IS_MOVING(x,y))
+    return;
 
-  if (MovDelay[x][y])          /* neue Phase / in Wartezustand */
+  if (Feld[x][y] == EL_EDELSTEIN_BD)
   {
-    int phase;
+    const int delay = 2;
+    const int frames = 4;
+    int phase = (FrameCounter % (delay*frames)) / delay;
 
-    MovDelay[x][y]--;
-    phase = (MovDelay[x][y] % 16)/2;
-    if (phase>3)
-      phase = 7-phase;
-    if (!(MovDelay[x][y]%2) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
-      DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_AUF+phase);
+    if (!(FrameCounter % delay))
+      DrawGraphic(SCROLLX(x),SCROLLY(y), GFX_EDELSTEIN_BD - phase);
   }
-}
+  else
+  {
+    if (!MovDelay[x][y])       /* neue Phase / noch nicht gewartet */
+      MovDelay[x][y] = 6*!SimpleRND(500);
 
-void EdelsteinFunkeln(int x, int y)
-{
-  int speed = 2;
+    if (MovDelay[x][y])                /* neue Phase / in Wartezustand */
+    {
+      MovDelay[x][y]--;
 
-  CheckExploding = TRUE;
+      if (direct_draw_on && MovDelay[x][y])
+       drawto_field = backbuffer;
 
-  if (IS_MOVING(x,y))
-    return;
+      DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(Feld[x][y]));
 
-  if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
-    MovDelay[x][y] = 4*speed;
+      if (MovDelay[x][y])
+      {
+       int src_x,src_y, dest_x,dest_y;
+       int phase = MovDelay[x][y]-1;
 
-  if (MovDelay[x][y])          /* neue Phase / in Wartezustand */
-  {
-    int phase;
+       src_x  = SX+GFX_PER_LINE*TILEX;
+       src_y  = SY+(phase > 2 ? 4-phase : phase)*TILEY;
+       dest_x = SX+SCROLLX(x)*TILEX;
+       dest_y = SY+SCROLLY(y)*TILEY;
 
-    MovDelay[x][y]--;
-    phase = MovDelay[x][y]/speed;
-    if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
-      DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EDELSTEIN2-phase);
+       XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y);
+       XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK],
+                 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
+
+       if (direct_draw_on)
+       {
+         XCopyArea(display,backbuffer,window,gc,
+                   dest_x,dest_y, TILEX,TILEY, dest_x,dest_y);
+         drawto_field = window;
+       }
+      }
+    }
   }
 }
 
@@ -1900,8 +2046,6 @@ void MauerWaechst(int x, int y)
 {
   int speed = 3;
 
-  CheckExploding = TRUE;
-
   if (!MovDelay[x][y])         /* neue Phase / noch nicht gewartet */
     MovDelay[x][y] = 3*speed;
 
@@ -1940,8 +2084,6 @@ void MauerAbleger(int ax, int ay)
   BOOL links_frei = FALSE, rechts_frei = FALSE;
   BOOL links_massiv = FALSE, rechts_massiv = FALSE;
 
-  CheckExploding = TRUE;
-
   if (!MovDelay[ax][ay])       /* neue Mauer / noch nicht gewartet */
     MovDelay[ax][ay] = 3;
 
@@ -1984,44 +2126,35 @@ void MauerAbleger(int ax, int ay)
     Feld[ax][ay] = EL_MAUERWERK;
 }
 
-int GameActions(int mx, int my, int button)
+void GameActions()
 {
-  static long time_delay=0, action_delay=0;
-  int Action;
+  static long action_delay=0;
+  long action_delay_value;
 
-  if (TimeLeft>0 && DelayReached(&time_delay,100) && !tape.pausing)
-  {
-    TimeLeft--;
-
-    if (tape.recording || tape.playing)
-      DrawVideoDisplay(VIDEO_STATE_TIME_ON,level.time-TimeLeft);
-
-    if (TimeLeft<=10)
-      PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
-
-    DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
-    BackToFront();
-  }
-
-  if (!TimeLeft)
-    KillHero();
-
-  Action = (CheckMoving || CheckExploding || SiebAktiv);
+  if (game_status != PLAYING)
+    return;
 
 /*
-  if (Action && DelayReached(&action_delay,3))
+  action_delay_value =
+    (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : GAME_FRAME_DELAY);
 */
 
-  if (DelayReached(&action_delay,3))
+  action_delay_value =
+    (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : Gamespeed);
+
+  if (DelayReached(&action_delay, action_delay_value))
   {
     int x,y,element;
+    int sieb_x = 0, sieb_y = 0;
+
+    FrameCounter++;
+    TimeFrames++;
 
     if (tape.pausing || (tape.playing && !TapePlayDelay()))
-      return(ACT_GO_ON);
+      return;
     else if (tape.recording)
       TapeRecordDelay();
 
-    CheckMoving = CheckExploding = FALSE;
     for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
     {
       Stop[x][y] = FALSE;
@@ -2033,13 +2166,19 @@ int GameActions(int mx, int my, int button)
     {
       element = Feld[x][y];
 
+      if (IS_INACTIVE(element))
+       continue;
+
+/*
       if (element==EL_LEERRAUM || element==EL_ERDREICH)
        continue;
+*/
 
       if (!IS_MOVING(x,y) && (CAN_FALL(element) || CAN_MOVE(element)))
       {
        StartMoving(x,y);
-       if (Feld[x][y]==EL_EDELSTEIN2)
+
+       if (IS_GEM(element))
          EdelsteinFunkeln(x,y);
       }
       else if (IS_MOVING(x,y))
@@ -2075,23 +2214,55 @@ int GameActions(int mx, int my, int button)
 
       if (SiebAktiv)
       {
+       BOOL sieb = FALSE;
+
        if (element==EL_SIEB_LEER || element==EL_SIEB_VOLL ||
            Store[x][y]==EL_SIEB_LEER)
-         SiebAktivieren(x,y,1);
+       {
+         SiebAktivieren(x, y, 1);
+         sieb = TRUE;
+       }
        else if (element==EL_SIEB2_LEER || element==EL_SIEB2_VOLL ||
                 Store[x][y]==EL_SIEB2_LEER)
-         SiebAktivieren(x,y,2);
+       {
+         SiebAktivieren(x, y, 2);
+         sieb = TRUE;
+       }
+
+       if (sieb && ABS(x-JX)+ABS(y-JY) < ABS(sieb_x-JX)+ABS(sieb_y-JY))
+       {
+         sieb_x = x;
+         sieb_y = y;
+       }
       }
     }
 
     if (SiebAktiv)
+    {
+      if (!(SiebAktiv%4))
+       PlaySoundLevel(sieb_x,sieb_y,SND_MIEP);
       SiebAktiv--;
+    }
+  }
 
-    if (CheckMoving || CheckExploding)
-      BackToFront();
+  if (TimeLeft>0 && TimeFrames>=25 && !tape.pausing)
+  {
+    TimeFrames = 0;
+    TimeLeft--;
+
+    if (tape.recording || tape.playing)
+      DrawVideoDisplay(VIDEO_STATE_TIME_ON,level.time-TimeLeft);
+
+    if (TimeLeft<=10)
+      PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
+
+    DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
+
+    if (!TimeLeft)
+      KillHero();
   }
 
-  return(ACT_GO_ON);
+  BackToFront();
 }
 
 void ScrollLevel(int dx, int dy)
@@ -2119,13 +2290,13 @@ void ScrollLevel(int dx, int dy)
   redraw_mask|=REDRAW_FIELD;
 }
 
-BOOL MoveFigureOneStep(int dx, int dy)
+BOOL MoveFigureOneStep(int dx, int dy, int real_dx, int real_dy)
 {
   int oldJX,oldJY, newJX = JX+dx,newJY = JY+dy;
   int element;
   int can_move;
 
-  if (!dx && !dy)
+  if (GameOver || (!dx && !dy))
     return(MF_NO_ACTION);
   if (!IN_LEV_FIELD(newJX,newJY))
     return(MF_NO_ACTION);
@@ -2153,7 +2324,7 @@ BOOL MoveFigureOneStep(int dx, int dy)
     return(MF_MOVING);
   }
 
-  can_move = DigField(newJX,newJY,DF_DIG);
+  can_move = DigField(newJX,newJY, real_dx,real_dy, DF_DIG);
   if (can_move != MF_MOVING)
     return(can_move);
 
@@ -2184,25 +2355,63 @@ BOOL MoveFigure(int dx, int dy)
   if (GameOver || (!dx && !dy))
     return(FALSE);
 
+/*
+  if (!DelayReached(&move_delay,8) && !tape.playing)
+    return(FALSE);
+*/
+
+/*
   if (!DelayReached(&move_delay,10) && !tape.playing)
     return(FALSE);
+*/
+
+/*
+  if (!FrameReached(&move_delay,2) && !tape.playing)
+    return(FALSE);
+*/
 
-  if (moved |= MoveFigureOneStep(dx,0))
-    moved |= MoveFigureOneStep(0,dy);
+  if (Movemethod == 0)
+  {
+    if (!DelayReached(&move_delay,Movespeed[0]) && !tape.playing)
+      return(FALSE);
+  }
   else
   {
-    moved |= MoveFigureOneStep(0,dy);
-    moved |= MoveFigureOneStep(dx,0);
+    if (!FrameReached(&move_delay,Movespeed[1]) && !tape.playing)
+      return(FALSE);
+  }
+
+  if (moved |= MoveFigureOneStep(dx,0, dx,dy))
+    moved |= MoveFigureOneStep(0,dy, dx,dy);
+  else
+  {
+    moved |= MoveFigureOneStep(0,dy, dx,dy);
+    moved |= MoveFigureOneStep(dx,0, dx,dy);
   }
 
   if (moved & MF_MOVING)
   {
     int old_scroll_x=scroll_x, old_scroll_y=scroll_y;
+    int offset = (scroll_delay_on ? 3 : 0);
 
+/*
     if (scroll_x!=JX-MIDPOSX && JX>=MIDPOSX-1 && JX<=lev_fieldx-MIDPOSX)
       scroll_x = JX-MIDPOSX;
     if (scroll_y!=JY-MIDPOSY && JY>=MIDPOSY-1 && JY<=lev_fieldy-MIDPOSY)
       scroll_y = JY-MIDPOSY;
+*/
+
+/*
+    printf("(scroll_x, scroll_y, JX, JY) == (%d, %d, %d, %d)\n",
+          scroll_x, scroll_y, JX, JY);
+*/
+
+    if ((scroll_x < JX-MIDPOSX-offset || scroll_x > JX-MIDPOSX+offset) &&
+       JX>=MIDPOSX-1-offset && JX<=lev_fieldx-(MIDPOSX-offset))
+      scroll_x = JX-MIDPOSX + (scroll_x < JX-MIDPOSX ? -offset : offset);
+    if ((scroll_y < JY-MIDPOSY-offset || scroll_y > JY-MIDPOSY+offset) &&
+       JY>=MIDPOSY-1-offset && JY<=lev_fieldy-(MIDPOSY-offset))
+      scroll_y = JY-MIDPOSY + (scroll_y < JY-MIDPOSY ? -offset : offset);
 
     if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y)
       ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y);
@@ -2217,8 +2426,10 @@ BOOL MoveFigure(int dx, int dy)
 
   BackToFront();
 
+/*
   if (LevelSolved)
     GameWon();
+*/
 
   return(moved);
 }
@@ -2228,10 +2439,10 @@ void TestIfHeroHitsBadThing()
   int i, killx = JX,killy = JY;
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
   static int harmless[4] =
   {
@@ -2277,10 +2488,10 @@ void TestIfBadThingHitsOtherBadThing(int badx, int bady)
   int i, killx=badx, killy=bady;
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
   for(i=0;i<4;i++)
@@ -2308,7 +2519,7 @@ void TestIfBadThingHitsOtherBadThing(int badx, int bady)
 
 void KillHero()
 {
-  if (PLAYER(-1,-1))
+  if (IS_PLAYER(-1,-1))
     return;
 
   if (IS_PFORTE(Feld[JX][JY]))
@@ -2318,17 +2529,19 @@ void KillHero()
   PlaySoundLevel(JX,JY,SND_LACHEN);
   Bang(JX,JY);
   GameOver = TRUE;
+  ZX = JX;
+  ZY = JY;
   JX = JY = -1;
 }
 
-int DigField(int x, int y, int mode)
+int DigField(int x, int y, int real_dx, int real_dy, int mode)
 {
   int dx = x-JX, dy = y-JY;
   int element;
   static long push_delay = 0;
-  static int push_delay_value = 20;
+  static int push_delay_value = 5;
 
-  if (mode==DF_NO_PUSH)
+  if (mode == DF_NO_PUSH)
   {
     push_delay = 0;
     return(MF_NO_ACTION);
@@ -2342,54 +2555,56 @@ int DigField(int x, int y, int mode)
   switch(element)
   {
     case EL_LEERRAUM:
-      CheckMoving = TRUE;
       break;
     case EL_ERDREICH:
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
       break;
     case EL_EDELSTEIN:
-    case EL_EDELSTEIN2:
-    case EL_EDELSTEIN3:
+    case EL_EDELSTEIN_BD:
+    case EL_EDELSTEIN_GELB:
+    case EL_EDELSTEIN_ROT:
+    case EL_EDELSTEIN_LILA:
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
+      MovDelay[x][y] = 0;      /* wegen EDELSTEIN_BD-Funkeln! */
       if (Gems>0)
        Gems--;
-      RaiseScore(level.score[SC_EDELSTEIN]);
+      RaiseScoreElement(EL_EDELSTEIN);
       DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
       PlaySoundLevel(x,y,SND_PONG);
       break;
     case EL_DIAMANT:
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
       Gems -= 3;
       if (Gems<0)
        Gems=0;
-      RaiseScore(level.score[SC_DIAMANT]);
+      RaiseScoreElement(EL_DIAMANT);
       DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
       PlaySoundLevel(x,y,SND_PONG);
       break;
     case EL_DYNAMIT_AUS:
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
       Dynamite++;
-      RaiseScore(level.score[SC_DYNAMIT]);
+      RaiseScoreElement(EL_DYNAMIT);
       DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
       PlaySoundLevel(x,y,SND_PONG);
       break;
     case EL_DYNABOMB_NR:
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
       DynaBombCount++;
       DynaBombsLeft++;
-      RaiseScore(level.score[SC_DYNAMIT]);
+      RaiseScoreElement(EL_DYNAMIT);
       PlaySoundLevel(x,y,SND_PONG);
       break;
     case EL_DYNABOMB_SZ:
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
       DynaBombSize++;
-      RaiseScore(level.score[SC_DYNAMIT]);
+      RaiseScoreElement(EL_DYNAMIT);
+      PlaySoundLevel(x,y,SND_PONG);
+      break;
+    case EL_DYNABOMB_XL:
+      Feld[x][y] = EL_LEERRAUM;
+      DynaBombXL = TRUE;
+      RaiseScoreElement(EL_DYNAMIT);
       PlaySoundLevel(x,y,SND_PONG);
       break;
     case EL_SCHLUESSEL1:
@@ -2400,9 +2615,8 @@ int DigField(int x, int y, int mode)
       int key_nr = element-EL_SCHLUESSEL1;
 
       Feld[x][y] = EL_LEERRAUM;
-      CheckMoving = TRUE;
       Key[key_nr] = TRUE;
-      RaiseScore(level.score[SC_SCHLUESSEL]);
+      RaiseScoreElement(EL_SCHLUESSEL);
       DrawMiniGraphicExtHiRes(drawto,gc,
                              DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
                              GFX_SCHLUESSEL1+key_nr);
@@ -2414,7 +2628,6 @@ int DigField(int x, int y, int mode)
     }
     case EL_ABLENK_AUS:
       Feld[x][y] = EL_ABLENK_EIN;
-      CheckExploding = TRUE;
       ZX=x;
       ZY=y;
       DrawLevelField(x,y);
@@ -2426,18 +2639,25 @@ int DigField(int x, int y, int mode)
     case EL_ZEIT_LEER:
       if (mode==DF_SNAP)
        return(MF_NO_ACTION);
-      if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy]!=EL_LEERRAUM)
+      if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy] != EL_LEERRAUM)
        return(MF_NO_ACTION);
 
-      if (Counter() > push_delay+4*push_delay_value)
-       push_delay = Counter();
-      if (!DelayReached(&push_delay,push_delay_value) && !tape.playing)
+      if (real_dy)
+      {
+       if (IN_LEV_FIELD(JX,JY+real_dy) && !IS_SOLID(Feld[JX][JY+real_dy]))
+         return(MF_NO_ACTION);
+      }
+
+      if (push_delay == 0)
+       push_delay = FrameCounter;
+      if (!FrameReached(&push_delay,push_delay_value) && !tape.playing)
        return(MF_NO_ACTION);
 
       Feld[x][y] = EL_LEERRAUM;
       Feld[x+dx][y+dy] = element;
-      push_delay_value = 10+RND(30);
-      CheckMoving = TRUE;
+
+      push_delay_value = 2+RND(8);
+
       DrawLevelField(x+dx,y+dy);
       if (element==EL_FELSBROCKEN)
        PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
@@ -2466,10 +2686,6 @@ int DigField(int x, int y, int mode)
       return(MF_NO_ACTION);
       break;
     case EL_AUSGANG_AUF:
-/*
-      if (mode==DF_SNAP || Gems>0)
-       return(MF_NO_ACTION);
-*/
       if (mode==DF_SNAP)
        return(MF_NO_ACTION);
       LevelSolved = GameOver = TRUE;
@@ -2477,21 +2693,84 @@ int DigField(int x, int y, int mode)
       break;
     case EL_BIRNE_AUS:
       Feld[x][y] = EL_BIRNE_EIN;
+      Lights--;
       DrawLevelField(x,y);
       PlaySoundLevel(x,y,SND_DENG);
       return(MF_ACTION);
       break;
     case EL_ZEIT_VOLL:
       Feld[x][y] = EL_ZEIT_LEER;
+      TimeLeft += 10;
+      DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
       DrawLevelField(x,y);
       PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
       return(MF_ACTION);
+      break;
+    case EL_SOKOBAN_FELD_LEER:
+      break;
+    case EL_SOKOBAN_FELD_VOLL:
+    case EL_SOKOBAN_OBJEKT:
+      if (mode==DF_SNAP)
+       return(MF_NO_ACTION);
+      if (!IN_LEV_FIELD(x+dx,y+dy)
+         || (Feld[x+dx][y+dy] != EL_LEERRAUM
+             && Feld[x+dx][y+dy] != EL_SOKOBAN_FELD_LEER))
+       return(MF_NO_ACTION);
+
+      if (dx && real_dy)
+      {
+       if (IN_LEV_FIELD(JX,JY+real_dy) && !IS_SOLID(Feld[JX][JY+real_dy]))
+         return(MF_NO_ACTION);
+      }
+      else if (dy && real_dx)
+      {
+       if (IN_LEV_FIELD(JX+real_dx,JY) && !IS_SOLID(Feld[JX+real_dx][JY]))
+         return(MF_NO_ACTION);
+      }
+
+      if (push_delay == 0)
+       push_delay = FrameCounter;
+      if (!FrameReached(&push_delay,push_delay_value) && !tape.playing)
+       return(MF_NO_ACTION);
+
+      if (element == EL_SOKOBAN_FELD_VOLL)
+      {
+       Feld[x][y] = EL_SOKOBAN_FELD_LEER;
+       SokobanFields++;
+      }
+      else
+       Feld[x][y] = EL_LEERRAUM;
+
+      if (Feld[x+dx][y+dy] == EL_SOKOBAN_FELD_LEER)
+      {
+       Feld[x+dx][y+dy] = EL_SOKOBAN_FELD_VOLL;
+       SokobanFields--;
+       if (element == EL_SOKOBAN_OBJEKT)
+         PlaySoundLevel(x,y,SND_DENG);
+      }
+      else
+       Feld[x+dx][y+dy] = EL_SOKOBAN_OBJEKT;
+
+      push_delay_value = 2;
+
+      DrawLevelField(x,y);
+      DrawLevelField(x+dx,y+dy);
+      PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
+
+      if (SokobanFields == 0 && game_emulation == EMU_SOKOBAN)
+      {
+       LevelSolved = GameOver = TRUE;
+       PlaySoundLevel(x,y,SND_BUING);
+      }
+
       break;
     default:
       return(MF_NO_ACTION);
       break;
   }
-  push_delay=0;
+
+  push_delay = 0;
+
   return(MF_MOVING);
 }
 
@@ -2512,7 +2791,7 @@ BOOL SnapField(int dx, int dy)
   if (snapped)
     return(FALSE);
 
-  if (!DigField(x,y,DF_SNAP))
+  if (!DigField(x,y, 0,0, DF_SNAP))
     return(FALSE);
 
   snapped = TRUE;
@@ -2524,12 +2803,19 @@ BOOL SnapField(int dx, int dy)
 
 BOOL PlaceBomb(void)
 {
+  int element;
+
+  if (GameOver)
+    return(FALSE);
+
+  element = Feld[JX][JY];
+
   if ((Dynamite==0 && DynaBombsLeft==0) ||
-      Feld[JX][JY]==EL_DYNAMIT || Feld[JX][JY]==EL_DYNABOMB)
+      element==EL_DYNAMIT || element==EL_DYNABOMB || element==EL_EXPLODING)
     return(FALSE);
 
-  if (Feld[JX][JY]!=EL_LEERRAUM)
-    Store[JX][JY] = Feld[JX][JY];
+  if (element!=EL_LEERRAUM)
+    Store[JX][JY] = element;
 
   if (Dynamite)
   {
@@ -2544,13 +2830,9 @@ BOOL PlaceBomb(void)
     Feld[JX][JY] = EL_DYNABOMB;
     MovDelay[JX][JY] = 48;
     DynaBombsLeft--;
-
-    /* ändern, wenn Maske für DYNABOMB vorliegt! */
-
-    DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT);
+    DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNABOMB);
   }
 
-  CheckExploding = TRUE;
   return(TRUE);
 }
 
@@ -2559,7 +2841,8 @@ void PlaySoundLevel(int x, int y, int sound_nr)
   int sx = SCROLLX(x), sy = SCROLLY(y);
   int volume, stereo;
 
-  if (!sound_loops_on && IS_LOOP_SOUND(sound_nr))
+  if ((!sound_simple_on && !IS_LOOP_SOUND(sound_nr)) ||
+      (!sound_loops_on && IS_LOOP_SOUND(sound_nr)))
     return;
 
   if (!IN_LEV_FIELD(x,y))
@@ -2586,196 +2869,44 @@ void RaiseScore(int value)
   BackToFront();
 }
 
-void TapeInitRecording()
-{
-  time_t zeit1 = time(NULL);
-  struct tm *zeit2 = localtime(&zeit1);
-
-  if (tape.recording || tape.playing)
-    return;
-
-  tape.level_nr = level_nr;
-  tape.recording = TRUE;
-  tape.pausing = TRUE;
-  tape.date =
-    10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday;
-
-  DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_ON,0);
-  DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
-  DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
-}
-
-void TapeStartRecording()
-{
-  tape.length = 0;
-  tape.counter = 0;
-  tape.pos[tape.counter].delay = 0;
-  tape.recording = TRUE;
-  tape.playing = FALSE;
-  tape.pausing = FALSE;
-  tape.random_seed = InitRND(NEW_RANDOMIZE);
-  DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_OFF,0);
-}
-
-void TapeStopRecording()
-{
-  if (!tape.recording)
-    return;
-
-  tape.length = tape.counter;
-  tape.recording = FALSE;
-  tape.pausing = FALSE;
-  DrawVideoDisplay(VIDEO_STATE_REC_OFF,0);
-
-  master_tape = tape;
-}
-
-void TapeRecordAction(int joy)
-{
-  if (!tape.recording || tape.pausing)
-    return;
-
-  if (tape.counter>=MAX_TAPELEN-1)
-  {
-    TapeStopRecording();
-    return;
-  }
-
-  if (joy)
-  {
-    tape.pos[tape.counter].joystickdata = joy;
-    tape.counter++;
-    tape.pos[tape.counter].delay = 0;
-  }
-}
-
-void TapeRecordDelay()
-{
-  if (!tape.recording || tape.pausing)
-    return;
-
-  if (tape.counter>=MAX_TAPELEN)
-  {
-    TapeStopRecording();
-    return;
-  }
-
-  tape.pos[tape.counter].delay++;
-
-  if (tape.pos[tape.counter].delay>=255)
-  {
-    tape.pos[tape.counter].joystickdata = 0;
-    tape.counter++;
-    tape.pos[tape.counter].delay = 0;
-  }
-}
-
-void TapeTogglePause()
-{
-  if (!tape.recording && !tape.playing)
-    return;
-
-  if (tape.pausing)
-  {
-    tape.pausing = FALSE;
-    DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
-    if (game_status==MAINMENU)
-      HandleMainMenu(SX+16,SY+7*32+16,0,0,MB_MENU_CHOICE);
-  }
-  else
-  {
-    tape.pausing = TRUE;
-    DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
-  }
-}
-
-void TapeInitPlaying()
-{
-  if (tape.recording || tape.playing || TAPE_IS_EMPTY(tape))
-    return;
-
-  tape.playing = TRUE;
-  tape.pausing = TRUE;
-  DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_ON,0);
-  DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
-  DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
-}
-
-void TapeStartPlaying()
-{
-  tape = master_tape;
-
-  tape.counter = 0;
-  tape.recording = FALSE;
-  tape.playing = TRUE;
-  tape.pausing = FALSE;
-  InitRND(tape.random_seed);
-  DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_OFF,0);
-}
-
-void TapeStopPlaying()
-{
-  if (!tape.playing)
-    return;
-
-  tape.playing = FALSE;
-  tape.pausing = FALSE;
-  DrawVideoDisplay(VIDEO_STATE_PLAY_OFF,0);
-}
-
-int TapePlayAction()
+void RaiseScoreElement(int element)
 {
-  if (!tape.playing || tape.pausing)
-    return(0);
-
-  if (tape.counter>=tape.length)
-  {
-    TapeStopPlaying();
-    return(0);
-  }
-
-  if (!tape.pos[tape.counter].delay)
-  {
-    tape.counter++;
-    return(tape.pos[tape.counter-1].joystickdata);
-  }
-  else
-    return(0);
-}
-
-BOOL TapePlayDelay()
-{
-  if (!tape.playing || tape.pausing)
-    return(0);
-
-  if (tape.counter>=tape.length)
-  {
-    TapeStopPlaying();
-    return(TRUE);
-  }
-
-  if (tape.pos[tape.counter].delay)
-  {
-    tape.pos[tape.counter].delay--;
-    return(TRUE);
-  }
-  else
-    return(FALSE);
-}
-
-void TapeStop()
-{
-  TapeStopRecording();
-  TapeStopPlaying();
-  DrawVideoDisplay(VIDEO_ALL_OFF,0);
-  if (tape.date && tape.length)
+  switch(element)
   {
-    DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
-    DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+    case EL_EDELSTEIN:
+      RaiseScore(level.score[SC_EDELSTEIN]);
+      break;
+    case EL_DIAMANT:
+      RaiseScore(level.score[SC_DIAMANT]);
+      break;
+    case EL_KAEFER:
+    case EL_BUTTERFLY:
+      RaiseScore(level.score[SC_KAEFER]);
+      break;
+    case EL_FLIEGER:
+    case EL_FIREFLY:
+      RaiseScore(level.score[SC_FLIEGER]);
+      break;
+    case EL_MAMPFER:
+    case EL_MAMPFER2:
+      RaiseScore(level.score[SC_MAMPFER]);
+      break;
+    case EL_ZOMBIE:
+      RaiseScore(level.score[SC_ZOMBIE]);
+      break;
+    case EL_PACMAN:
+      RaiseScore(level.score[SC_PACMAN]);
+      break;
+    case EL_KOKOSNUSS:
+      RaiseScore(level.score[SC_KOKOSNUSS]);
+      break;
+    case EL_DYNAMIT:
+      RaiseScore(level.score[SC_DYNAMIT]);
+      break;
+    case EL_SCHLUESSEL:
+      RaiseScore(level.score[SC_SCHLUESSEL]);
+      break;
+    default:
+      break;
   }
 }
-
-void TapeErase()
-{
-  tape.length = 0;
-}
index 56be763..a0a2107 100644 (file)
 
 #include "main.h"
 
-#define DF_DIG         0
-#define DF_SNAP                1
-#define DF_NO_PUSH     2
+#define DF_NO_PUSH             0
+#define DF_DIG                 1
+#define DF_SNAP                        2
 
-#define MF_NO_ACTION   0
-#define MF_MOVING      1
-#define MF_ACTION      2
+#define MF_NO_ACTION           0
+#define MF_MOVING              1
+#define MF_ACTION              2
 
-#define EX_NORMAL      0
-#define EX_CENTER      1
-#define EX_BORDER      2
+/* explosion position marks */
+#define EX_NORMAL              0
+#define EX_CENTER              1
+#define EX_BORDER              2
+
+/* fundamental game speed */
+#define GAME_FRAME_DELAY       4
+#define FFWD_FRAME_DELAY       1
+#define FRAMES_PER_SECOND      (100 / GAME_FRAME_DELAY)
 
 void GetPlayerConfig(void);
 void InitGame(void);
@@ -52,6 +58,7 @@ void StartMoving(int, int);
 void ContinueMoving(int, int);
 int AmoebeNachbarNr(int, int);
 void AmoebeUmwandeln(int, int);
+void AmoebeUmwandeln2(int, int, int);
 void AmoebeWaechst(int, int);
 void AmoebeAbleger(int, int);
 void Life(int, int);
@@ -65,30 +72,19 @@ void AusgangstuerBlinken(int, int);
 void EdelsteinFunkeln(int, int);
 void MauerWaechst(int, int);
 void MauerAbleger(int, int);
-int GameActions(int, int, int);
+void GameActions(void);
 void ScrollLevel(int, int);
+BOOL MoveFigureOneStep(int, int, int, int);
 BOOL MoveFigure(int, int);
 void TestIfHeroHitsBadThing(void);
 void TestIfBadThingHitsHero(void);
 void TestIfBadThingHitsOtherBadThing(int, int);
 void KillHero(void);
-int DigField(int, int, int);
+int DigField(int, int, int, int, int);
 BOOL SnapField(int, int);
 BOOL PlaceBomb(void);
 void PlaySoundLevel(int, int, int);
 void RaiseScore(int);
-void TapeInitRecording(void);
-void TapeStartRecording(void);
-void TapeStopRecording(void);
-void TapeRecordAction(int);
-void TapeRecordDelay(void);
-void TapeTogglePause(void);
-void TapeInitPlaying(void);
-void TapeStartPlaying(void);
-void TapeStopPlaying(void);
-int TapePlayAction(void);
-BOOL TapePlayDelay(void);
-void TapeStop(void);
-void TapeErase(void);
+void RaiseScoreElement(int);
 
 #endif
index 251d32d..2d9b304 100644 (file)
@@ -16,6 +16,7 @@
 #include "misc.h"
 #include "sound.h"
 #include "screens.h"
+#include "tools.h"
 #include "files.h"
 #include <signal.h>
 
@@ -36,13 +37,14 @@ void OpenAll(int argc, char *argv[])
 
   InitDisplay(argc, argv);
   InitWindow(argc, argv);
+
+  XMapWindow(display, window);
+  XFlush(display);
+
   InitGfx();
   InitElementProperties();
 
   DrawMainMenu();
-
-  XMapWindow(display, window);
-  XFlush(display);
 }
 
 void InitLevelAndPlayerInfo()
@@ -191,8 +193,8 @@ void InitWindow(int argc, char *argv[])
   XTextProperty windowName, iconName;
   XGCValues gc_values;
   unsigned long gc_valuemask;
-  char *window_name = "Rocks'n'Diamonds";
-  char *icon_name = "Rocks'n'Diamonds";
+  char *window_name = WINDOWTITLE_STRING;
+  char *icon_name = WINDOWTITLE_STRING;
   long window_event_mask;
   static struct PictureFile icon_pic =
   {
@@ -277,105 +279,39 @@ void InitWindow(int argc, char *argv[])
   gc = XCreateGC(display, window, gc_valuemask, &gc_values);
 }
 
+void DrawInitText(char *text, int ypos, int color)
+{
+  if (display && window && pix[PIX_SMALLFONT])
+  {
+    XFillRectangle(display,window,gc,0,ypos, WIN_XSIZE,FONT2_YSIZE);
+    DrawTextExt(window,gc,(WIN_XSIZE-strlen(text)*FONT2_XSIZE)/2,
+               ypos,text,FS_SMALL,color);
+    XFlush(display);
+  }
+}
+
 void InitGfx()
 {
-  int i,j,x,y;
-  int xpm_err, xbm_err;
-  unsigned int width,height;
-  int hot_x,hot_y;
-  XGCValues gc_values;
-  unsigned long gc_valuemask;
+  int i,j;
   XGCValues clip_gc_values;
   unsigned long clip_gc_valuemask;
-  char filename[256];
-  Pixmap shapemask;
-
   static struct PictureFile pic[NUM_PICTURES] =
   {
-    "RocksScreen.xpm",         "RocksScreenMaske.xbm",
-    "RocksDoor.xpm",           "RocksDoorMaske.xbm",
-    "RocksToons.xpm",          "RocksToonsMaske.xbm",
-    "RocksFont.xpm",           NULL,
-    "RocksFont2.xpm",          NULL
+    { "RocksScreen.xpm",       "RocksScreenMaske.xbm" },
+    { "RocksDoor.xpm",         "RocksDoorMaske.xbm" },
+    { "RocksToons.xpm",                "RocksToonsMaske.xbm" },
+    { "RocksFont.xpm",         NULL },
+    { "RocksFont2.xpm",                NULL }
   }; 
 
-  for(i=0;i<NUM_PICTURES;i++)
-  {
-    if (pic[i].picture_filename)
-    {
-      sprintf(filename,"%s/%s",GFX_PATH,pic[i].picture_filename);
-
-      xpm_att[i].valuemask = XpmCloseness;
-      xpm_att[i].closeness = 20000;
-      xpm_err = XpmReadFileToPixmap(display,window,filename,
-                                   &pix[i],&shapemask,&xpm_att[i]);
-      switch(xpm_err)
-      {
-       case XpmOpenFailed:
-          fprintf(stderr,"Xpm file open failed on '%s' !\n",filename);
-         CloseAll();
-         exit(-1);
-       case XpmFileInvalid:
-         fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
-         CloseAll();
-         exit(-1);
-       case XpmNoMemory:
-         fprintf(stderr,"Not enough memory !\n");      
-         CloseAll();
-         exit(1);
-       case XpmColorFailed:
-         fprintf(stderr,"Can`t get any colors...\n");
-         CloseAll();
-         exit(-1);
-       default:
-         break;
-      }
-      if (!pix[i])
-      {
-       fprintf(stderr, "%s: cannot read Xpm file '%s'.\n",
-               progname,filename);
-       CloseAll();
-       exit(-1);
-      }
-    }
-
-    if (pic[i].picturemask_filename)
-    {
-      sprintf(filename,"%s/%s",GFX_PATH,pic[i].picturemask_filename);
+  LoadGfx(PIX_SMALLFONT,&pic[PIX_SMALLFONT]);
+  DrawInitText(WINDOWTITLE_STRING,20,FC_YELLOW);
+  DrawInitText(COPYRIGHT_STRING,50,FC_RED);
+  DrawInitText("Loading graphics:",120,FC_GREEN);
 
-      xbm_err = XReadBitmapFile(display,window,filename,
-                               &width,&height,&clipmask[i],&hot_x,&hot_y);
-      switch(xbm_err)
-      {
-       case BitmapSuccess:
-          break;
-       case BitmapOpenFailed:
-         fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
-         CloseAll();
-         exit(-1);
-         break;
-       case BitmapFileInvalid:
-         fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
-         CloseAll();
-         exit(-1);
-         break;
-       case BitmapNoMemory:
-         fprintf(stderr,"No memory for file '%s' !\n",filename);
-         CloseAll();
-         exit(-1);
-         break;
-       default:
-         break;
-      }
-      if (!clipmask[i])
-      {
-       fprintf(stderr, "%s: cannot read X11 bitmap file '%s'.\n",
-               progname,filename);
-       CloseAll();
-       exit(-1);
-      }
-    }
-  }
+  for(i=0;i<NUM_PICTURES;i++)
+    if (i!=PIX_SMALLFONT)
+      LoadGfx(i,&pic[i]);
 
   pix[PIX_DB_BACK] = XCreatePixmap(display, window,
                                   WIN_XSIZE,WIN_YSIZE,
@@ -384,27 +320,13 @@ void InitGfx()
                                   3*DXSIZE,DYSIZE+VYSIZE,
                                   XDefaultDepth(display,screen));
 
-  clipmask[PIX_FADEMASK] = XCreatePixmap(display, window,
-                                        SXSIZE+TILEX,SYSIZE+TILEY,1);
-
-  if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR] || !clipmask[PIX_FADEMASK])
+  if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR])
   {
     fprintf(stderr, "%s: cannot create additional Pixmaps!\n",progname);
     CloseAll();
     exit(-1);
   }
 
-  /* create GC for drawing with bitplane depth */
-  gc_values.graphics_exposures = False;
-  gc_values.foreground = pen_bg;
-  gc_values.background = pen_bg;
-  gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
-  plane_gc = XCreateGC(display, clipmask[PIX_BACK], gc_valuemask, &gc_values);
-
-  for(y=0;y<=SCR_FIELDY;y++) for(x=0;x<=SCR_FIELDX;x++)
-    XCopyArea(display,clipmask[PIX_BACK],clipmask[PIX_FADEMASK],plane_gc,
-             SX+2*TILEX,SY+10*TILEY,TILEX,TILEY,x*TILEX,y*TILEY);
-
   for(i=0;i<NUM_PIXMAPS;i++)
   {
     if (clipmask[i])
@@ -423,8 +345,10 @@ void InitGfx()
 
   XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
            0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
-  XFillRectangle(display,backbuffer,gc,
+  XFillRectangle(display,pix[PIX_DB_BACK],gc,
                 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
+  XFillRectangle(display,pix[PIX_DB_DOOR],gc,
+                0,0, 3*DXSIZE,DYSIZE+VYSIZE);
 
   for(i=0;i<SCR_FIELDX;i++)
     for(j=0;j<SCR_FIELDY;j++)
@@ -433,6 +357,96 @@ void InitGfx()
   redraw_mask=REDRAW_ALL;
 }
 
+void LoadGfx(int pos, struct PictureFile *pic)
+{
+  int xpm_err, xbm_err;
+  unsigned int width,height;
+  int hot_x,hot_y;
+  char filename[256];
+  Pixmap shapemask;
+
+  /* Grafik laden */
+  if (pic->picture_filename)
+  {
+    DrawInitText(pic->picture_filename,150,FC_YELLOW);
+    sprintf(filename,"%s/%s",GFX_PATH,pic->picture_filename);
+
+    xpm_att[pos].valuemask = XpmCloseness;
+    xpm_att[pos].closeness = 20000;
+    xpm_err = XpmReadFileToPixmap(display,window,filename,
+                                 &pix[pos],&shapemask,&xpm_att[pos]);
+    switch(xpm_err)
+    {
+      case XpmOpenFailed:
+        fprintf(stderr,"Xpm file open failed on '%s' !\n",filename);
+       CloseAll();
+       exit(-1);
+      case XpmFileInvalid:
+       fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
+       CloseAll();
+       exit(-1);
+      case XpmNoMemory:
+       fprintf(stderr,"Not enough memory !\n");        
+       CloseAll();
+       exit(1);
+      case XpmColorFailed:
+       fprintf(stderr,"Can`t get any colors...\n");
+       CloseAll();
+       exit(-1);
+      default:
+       break;
+    }
+
+    if (!pix[pos])
+    {
+      fprintf(stderr, "%s: cannot read Xpm file '%s'.\n",
+             progname,filename);
+      CloseAll();
+      exit(-1);
+    }
+  }
+
+  /* zugehörige Maske laden (wenn vorhanden) */
+  if (pic->picturemask_filename)
+  {
+    DrawInitText(pic->picturemask_filename,150,FC_YELLOW);
+    sprintf(filename,"%s/%s",GFX_PATH,pic->picturemask_filename);
+
+    xbm_err = XReadBitmapFile(display,window,filename,
+                             &width,&height,&clipmask[pos],&hot_x,&hot_y);
+    switch(xbm_err)
+    {
+      case BitmapSuccess:
+        break;
+      case BitmapOpenFailed:
+       fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
+       CloseAll();
+       exit(-1);
+       break;
+      case BitmapFileInvalid:
+       fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
+       CloseAll();
+       exit(-1);
+       break;
+      case BitmapNoMemory:
+       fprintf(stderr,"No memory for file '%s' !\n",filename);
+       CloseAll();
+       exit(-1);
+       break;
+      default:
+       break;
+    }
+
+    if (!clipmask[pos])
+    {
+      fprintf(stderr, "%s: cannot read X11 bitmap file '%s'.\n",
+             progname,filename);
+      CloseAll();
+      exit(-1);
+    }
+  }
+}
+
 void InitElementProperties()
 {
   int i,j;
@@ -441,7 +455,8 @@ void InitElementProperties()
   {
     EL_AMOEBE_NASS,
     EL_AMOEBE_NORM,
-    EL_AMOEBE_VOLL
+    EL_AMOEBE_VOLL,
+    EL_AMOEBE_BD
   };
   static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
 
@@ -450,7 +465,8 @@ void InitElementProperties()
     EL_AMOEBE_TOT,
     EL_AMOEBE_NASS,
     EL_AMOEBE_NORM,
-    EL_AMOEBE_VOLL
+    EL_AMOEBE_VOLL,
+    EL_AMOEBE_BD
   };
   static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
 
@@ -499,6 +515,7 @@ void InitElementProperties()
     EL_AMOEBE_NASS,
     EL_AMOEBE_NORM,
     EL_AMOEBE_VOLL,
+    EL_AMOEBE_BD,
     EL_MORAST_VOLL,
     EL_MORAST_LEER,
     EL_SIEB_VOLL,
@@ -542,8 +559,10 @@ void InitElementProperties()
     EL_FELSBODEN,
     EL_FELSBROCKEN,
     EL_EDELSTEIN,
-    EL_EDELSTEIN2,
-    EL_EDELSTEIN3,
+    EL_EDELSTEIN_BD,
+    EL_EDELSTEIN_GELB,
+    EL_EDELSTEIN_ROT,
+    EL_EDELSTEIN_LILA,
     EL_DIAMANT,
     EL_BOMBE,
     EL_KOKOSNUSS,
@@ -562,6 +581,8 @@ void InitElementProperties()
   {
     EL_KAEFER,
     EL_FLIEGER,
+    EL_BUTTERFLY,
+    EL_FIREFLY,
     EL_MAMPFER,
     EL_MAMPFER2,
     EL_ZOMBIE,
@@ -594,8 +615,10 @@ void InitElementProperties()
   {
     EL_FELSBROCKEN,
     EL_EDELSTEIN,
-    EL_EDELSTEIN2,
-    EL_EDELSTEIN3,
+    EL_EDELSTEIN_BD,
+    EL_EDELSTEIN_GELB,
+    EL_EDELSTEIN_ROT,
+    EL_EDELSTEIN_LILA,
     EL_DIAMANT,
     EL_BOMBE,
     EL_KOKOSNUSS,
@@ -612,8 +635,10 @@ void InitElementProperties()
   {
     EL_FELSBROCKEN,
     EL_EDELSTEIN,
-    EL_EDELSTEIN2,
-    EL_EDELSTEIN3,
+    EL_EDELSTEIN_BD,
+    EL_EDELSTEIN_GELB,
+    EL_EDELSTEIN_ROT,
+    EL_EDELSTEIN_LILA,
     EL_DIAMANT,
     EL_SCHLUESSEL1,
     EL_SCHLUESSEL2,
@@ -631,8 +656,10 @@ void InitElementProperties()
   {
     EL_FELSBROCKEN,
     EL_EDELSTEIN,
-    EL_EDELSTEIN2,
-    EL_EDELSTEIN3,
+    EL_EDELSTEIN_BD,
+    EL_EDELSTEIN_GELB,
+    EL_EDELSTEIN_ROT,
+    EL_EDELSTEIN_LILA,
     EL_DIAMANT
   };
   static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
@@ -641,6 +668,8 @@ void InitElementProperties()
   {
     EL_KAEFER,
     EL_FLIEGER,
+    EL_BUTTERFLY,
+    EL_FIREFLY,
     EL_MAMPFER,
     EL_MAMPFER2,
     EL_ZOMBIE,
@@ -658,6 +687,14 @@ void InitElementProperties()
     EL_FLIEGER_O,
     EL_FLIEGER_L,
     EL_FLIEGER_U,
+    EL_BUTTERFLY_R,
+    EL_BUTTERFLY_O,
+    EL_BUTTERFLY_L,
+    EL_BUTTERFLY_U,
+    EL_FIREFLY_R,
+    EL_FIREFLY_O,
+    EL_FIREFLY_L,
+    EL_FIREFLY_U,
     EL_PACMAN_R,
     EL_PACMAN_O,
     EL_PACMAN_L,
@@ -668,7 +705,9 @@ void InitElementProperties()
   static int ep_dont_touch[] =
   {
     EL_KAEFER,
-    EL_FLIEGER
+    EL_FLIEGER,
+    EL_BUTTERFLY,
+    EL_FIREFLY
   };
   static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
 
@@ -676,6 +715,8 @@ void InitElementProperties()
   {
     EL_KAEFER,
     EL_FLIEGER,
+    EL_BUTTERFLY,
+    EL_FIREFLY,
     EL_MAMPFER,
     EL_MAMPFER2,
     EL_ZOMBIE,
@@ -690,6 +731,8 @@ void InitElementProperties()
     EL_ERDREICH,
     EL_KAEFER,
     EL_FLIEGER,
+    EL_BUTTERFLY,
+    EL_FIREFLY,
     EL_MAMPFER,
     EL_ZOMBIE,
     EL_PACMAN,
@@ -698,13 +741,117 @@ void InitElementProperties()
     EL_AMOEBE_NASS,
     EL_AMOEBE_NORM,
     EL_AMOEBE_VOLL,
+    EL_AMOEBE_BD,
     EL_EDELSTEIN,
-    EL_EDELSTEIN2,
-    EL_EDELSTEIN3,
+    EL_EDELSTEIN_BD,
+    EL_EDELSTEIN_GELB,
+    EL_EDELSTEIN_ROT,
+    EL_EDELSTEIN_LILA,
     EL_DIAMANT
   };
   static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int);
 
+  static int ep_bd_element[] =
+  {
+    EL_LEERRAUM,
+    EL_ERDREICH,
+    EL_FELSBODEN,
+    EL_FELSBROCKEN,
+    EL_EDELSTEIN_BD,
+    EL_SIEB2_LEER,
+    EL_AUSGANG_ZU,
+    EL_AUSGANG_AUF,
+    EL_BETON,
+    EL_SPIELFIGUR,
+    EL_FIREFLY,
+    EL_FIREFLY_1,
+    EL_FIREFLY_2,
+    EL_FIREFLY_3,
+    EL_FIREFLY_4,
+    EL_BUTTERFLY,
+    EL_BUTTERFLY_1,
+    EL_BUTTERFLY_2,
+    EL_BUTTERFLY_3,
+    EL_BUTTERFLY_4,
+    EL_AMOEBE_BD,
+    EL_CHAR_FRAGE
+  };
+  static int ep_bd_element_num = sizeof(ep_bd_element)/sizeof(int);
+
+  static int ep_sb_element[] =
+  {
+    EL_LEERRAUM,
+    EL_BETON,
+    EL_SOKOBAN_OBJEKT,
+    EL_SOKOBAN_FELD_LEER,
+    EL_SOKOBAN_FELD_VOLL,
+    EL_SPIELFIGUR
+  };
+  static int ep_sb_element_num = sizeof(ep_sb_element)/sizeof(int);
+
+  static int ep_gem[] =
+  {
+    EL_EDELSTEIN,
+    EL_EDELSTEIN_BD,
+    EL_EDELSTEIN_GELB,
+    EL_EDELSTEIN_ROT,
+    EL_EDELSTEIN_LILA,
+    EL_DIAMANT
+  };
+  static int ep_gem_num = sizeof(ep_gem)/sizeof(int);
+
+  static int ep_inactive[] =
+  {
+    EL_LEERRAUM,
+    EL_ERDREICH,
+    EL_MAUERWERK,
+    EL_FELSBODEN,
+    EL_SCHLUESSEL,
+    EL_BETON,
+    EL_AMOEBE_TOT,
+    EL_MORAST_LEER,
+    EL_BADEWANNE,
+    EL_ABLENK_AUS,
+    EL_SCHLUESSEL1,
+    EL_SCHLUESSEL2,
+    EL_SCHLUESSEL3,
+    EL_SCHLUESSEL4,
+    EL_PFORTE1,
+    EL_PFORTE2,
+    EL_PFORTE3,
+    EL_PFORTE4,
+    EL_PFORTE1X,
+    EL_PFORTE2X,
+    EL_PFORTE3X,
+    EL_PFORTE4X,
+    EL_DYNAMIT_AUS,
+    EL_UNSICHTBAR,
+    EL_BIRNE_AUS,
+    EL_BIRNE_EIN,
+    EL_ERZ_EDEL,
+    EL_ERZ_DIAM,
+    EL_ERZ_EDEL_BD,
+    EL_ERZ_EDEL_GELB,
+    EL_DYNABOMB_NR,
+    EL_DYNABOMB_SZ,
+    EL_DYNABOMB_XL,
+    EL_SOKOBAN_OBJEKT,
+    EL_SOKOBAN_FELD_LEER,
+    EL_SOKOBAN_FELD_VOLL,
+    EL_ERZ_EDEL_ROT,
+    EL_ERZ_EDEL_LILA,
+    EL_BADEWANNE1,
+    EL_BADEWANNE2,
+    EL_BADEWANNE3,
+    EL_BADEWANNE4,
+    EL_BADEWANNE5,
+    EL_SIEB_TOT,
+    EL_SIEB2_TOT,
+    EL_AMOEBA2DIAM,
+    EL_BLOCKED
+  };
+  static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int);
+
   static long ep_bit[] =
   {
     EP_BIT_AMOEBALIVE,
@@ -724,7 +871,11 @@ void InitElementProperties()
     EP_BIT_COULD_MOVE,
     EP_BIT_DONT_TOUCH,
     EP_BIT_DONT_GO_TO,
-    EP_BIT_MAMPF2
+    EP_BIT_MAMPF2,
+    EP_BIT_BD_ELEMENT,
+    EP_BIT_SB_ELEMENT,
+    EP_BIT_GEM,
+    EP_BIT_INACTIVE
   };
   static int *ep_array[] =
   {
@@ -745,7 +896,11 @@ void InitElementProperties()
     ep_could_move,
     ep_dont_touch,
     ep_dont_go_to,
-    ep_mampf2
+    ep_mampf2,
+    ep_bd_element,
+    ep_sb_element,
+    ep_gem,
+    ep_inactive
   };
   static int *ep_num[] =
   {
@@ -766,7 +921,11 @@ void InitElementProperties()
     &ep_could_move_num,
     &ep_dont_touch_num,
     &ep_dont_go_to_num,
-    &ep_mampf2_num
+    &ep_mampf2_num,
+    &ep_bd_element_num,
+    &ep_sb_element_num,
+    &ep_gem_num,
+    &ep_inactive_num
   };
   static int num_properties = sizeof(ep_num)/sizeof(int *);
 
@@ -777,7 +936,7 @@ void InitElementProperties()
     for(j=0;j<*(ep_num[i]);j++)
       Elementeigenschaften[(ep_array[i])[j]] |= ep_bit[i];
   for(i=EL_CHAR_START;i<EL_CHAR_END;i++)
-    Elementeigenschaften[i] |= EP_BIT_CHAR;
+    Elementeigenschaften[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
 }
 
 void CloseAll()
@@ -811,10 +970,8 @@ void CloseAll()
 
   if (gc)
     XFreeGC(display, gc);
-  if (plane_gc)
-    XFreeGC(display, plane_gc);
-
-  XCloseDisplay(display);
+  if (display)
+    XCloseDisplay(display);
 
   exit(0);
 }
index c96f484..43970fd 100644 (file)
@@ -25,6 +25,7 @@ void InitSoundProcess(void);
 void InitJoystick(void);
 void InitWindow(int, char **);
 void InitGfx(void);
+void LoadGfx(int, struct PictureFile *);
 void InitElementProperties(void);
 void CloseAll();
 
index 573ea9c..0c9d1f1 100644 (file)
@@ -20,8 +20,7 @@
 Display        *display;
 int            screen;
 Window         window;
-GC             gc, plane_gc;
-GC             clip_gc[NUM_PIXMAPS];
+GC             gc, clip_gc[NUM_PIXMAPS];
 Pixmap         pix[NUM_PIXMAPS];
 Pixmap         clipmask[NUM_PIXMAPS];
 XpmAttributes  xpm_att[NUM_PICTURES];
@@ -33,19 +32,23 @@ int         sound_device;
 char          *sound_device_name = SOUND_DEVICE;
 int            joystick_device = 0;
 char          *joystick_device_name[2] = { DEV_JOYSTICK_0, DEV_JOYSTICK_1 };
+char          *level_directory = LEVEL_PATH;
 int            width, height;
 unsigned long  pen_fg, pen_bg;
 
 int            game_status = MAINMENU;
+int            game_emulation = EMU_NONE;
 int            button_status = MB_NOT_PRESSED, motion_status = FALSE;
-int            key_status = KEY_NOT_PRESSED;
+int            key_joystick_mapping = 0;
 int            global_joystick_status = JOYSTICK_STATUS;
 int            joystick_status = JOYSTICK_STATUS;
-int            sound_status = SOUND_STATUS, sound_on=TRUE;
+int            sound_status = SOUND_STATUS, sound_on = TRUE;
 int            sound_loops_allowed = FALSE, sound_loops_on = FALSE;
 int            sound_music_on = FALSE;
+int            sound_simple_on = FALSE;
 int            toons_on = TRUE;
 int            direct_draw_on = FALSE;
+int            scroll_delay_on = FALSE;
 int            fading_on = FALSE;
 int            autorecord_on = FALSE;
 int            joystick_nr = 0;
@@ -66,31 +69,31 @@ int         Frame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 int            Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 int            JustHit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 int            AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-int            AmoebaCnt[MAX_NUM_AMOEBA];
+int            AmoebaCnt[MAX_NUM_AMOEBA], AmoebaCnt2[MAX_NUM_AMOEBA];
 long           Elementeigenschaften[MAX_ELEMENTS];
 
 int            level_nr, leveldir_nr, num_leveldirs;
 int            lev_fieldx,lev_fieldy, scroll_x,scroll_y;
 
 int            LevelSolved,GameOver, JX,JY, ZX,ZY;
-int            Gems,Dynamite,Key[4],TimeLeft,Score,MampferNr;
-int            DynaBombCount, DynaBombSize, DynaBombsLeft;
-int            CheckMoving,CheckExploding, SiebAktiv;
+int            FrameCounter,TimeFrames,TimeLeft,Score;
+int            Gems,SokobanFields,Lights,Dynamite,Key[4],MampferNr;
+int            DynaBombCount, DynaBombSize, DynaBombsLeft, DynaBombXL;
+int            SiebAktiv;
 
 struct LevelDirInfo    leveldir[MAX_LEVDIR_ENTRIES];
 struct LevelInfo       level;
 struct PlayerInfo      player;
 struct HiScore         highscore[MAX_SCORE_ENTRIES];
 struct SoundInfo       Sound[NUM_SOUNDS];
-struct RecordingInfo   tape,master_tape;
+struct RecordingInfo   tape;
 
 struct JoystickInfo joystick[2] =
 {
-  JOYSTICK_XLEFT, JOYSTICK_XRIGHT, JOYSTICK_XMIDDLE,
-  JOYSTICK_YUPPER, JOYSTICK_YLOWER, JOYSTICK_YMIDDLE,
-
-  JOYSTICK_XLEFT, JOYSTICK_XRIGHT, JOYSTICK_XMIDDLE,
-  JOYSTICK_YUPPER, JOYSTICK_YLOWER, JOYSTICK_YMIDDLE
+  { JOYSTICK_XLEFT, JOYSTICK_XRIGHT, JOYSTICK_XMIDDLE,
+    JOYSTICK_YUPPER, JOYSTICK_YLOWER, JOYSTICK_YMIDDLE },
+  { JOYSTICK_XLEFT, JOYSTICK_XRIGHT, JOYSTICK_XMIDDLE,
+    JOYSTICK_YUPPER, JOYSTICK_YLOWER, JOYSTICK_YMIDDLE }
 };
 
 /* data needed for playing sounds */
@@ -169,6 +172,9 @@ int main(int argc, char *argv[])
 {
   progname = argv[0];
 
+  if (argc>1)
+    level_directory = argv[1];
+
   OpenAll(argc,argv);
   EventLoop();
   CloseAll();
index 7d92afb..6cf2bb2 100644 (file)
@@ -66,10 +66,12 @@ typedef int BOOL;
 #define UNSCROLLY(a)   ((a)+scroll_y)
 #define IN_SCR_FIELD(x,y) ((x)>=0 && (x)<SCR_FIELDX && (y)>=0 &&(y)<SCR_FIELDY)
 #define IN_LEV_FIELD(x,y) ((x)>=0 && (x)<lev_fieldx && (y)>=0 &&(y)<lev_fieldy)
-#define PLAYER(x,y)    (JX==(x) && JY==(y))
-#define IS_FREE(x,y)   (Feld[x][y]==EL_LEERRAUM && !PLAYER(x,y))
-#define IS_MOVING(x,y) (MovPos[x][y]!=0)
-#define IS_BLOCKED(x,y)        (Feld[x][y]==EL_BLOCKED)
+
+#define IS_PLAYER(x,y)         (JX==(x) && JY==(y))
+#define IS_FREE(x,y)           (Feld[x][y]==EL_LEERRAUM && !IS_PLAYER(x,y))
+#define IS_FREE_OR_PLAYER(x,y) (Feld[x][y]==EL_LEERRAUM)
+#define IS_MOVING(x,y)         (MovPos[x][y]!=0)
+#define IS_BLOCKED(x,y)                (Feld[x][y]==EL_BLOCKED)
 
 #define EP_BIT_AMOEBALIVE      (1<<0)
 #define EP_BIT_AMOEBOID                (1<<1)
@@ -90,6 +92,10 @@ typedef int BOOL;
 #define EP_BIT_DONT_GO_TO      (1<<16)
 #define EP_BIT_MAMPF2          (1<<17)
 #define EP_BIT_CHAR            (1<<18)
+#define EP_BIT_BD_ELEMENT      (1<<19)
+#define EP_BIT_SB_ELEMENT      (1<<20)
+#define EP_BIT_GEM             (1<<21)
+#define EP_BIT_INACTIVE                (1<<22)
 
 #define IS_AMOEBALIVE(e)       (Elementeigenschaften[e] & EP_BIT_AMOEBALIVE)
 #define IS_AMOEBOID(e)         (Elementeigenschaften[e] & EP_BIT_AMOEBOID)
@@ -110,19 +116,24 @@ typedef int BOOL;
 #define DONT_GO_TO(e)          (Elementeigenschaften[e] & EP_BIT_DONT_GO_TO)
 #define IS_MAMPF2(e)           (Elementeigenschaften[e] & EP_BIT_MAMPF2)
 #define IS_CHAR(e)             (Elementeigenschaften[e] & EP_BIT_CHAR)
-
-#define EL_CHANGED(e)          ((e)==EL_FELSBROCKEN ? EL_EDELSTEIN :   \
-                                (e)==EL_EDELSTEIN   ? EL_DIAMANT :     \
-                                (e)==EL_EDELSTEIN2   ? EL_DIAMANT :    \
-                                (e)==EL_EDELSTEIN3   ? EL_DIAMANT :    \
+#define IS_BD_ELEMENT(e)       (Elementeigenschaften[e] & EP_BIT_BD_ELEMENT)
+#define IS_SB_ELEMENT(e)       (Elementeigenschaften[e] & EP_BIT_SB_ELEMENT)
+#define IS_GEM(e)              (Elementeigenschaften[e] & EP_BIT_GEM)
+#define IS_INACTIVE(e)         (Elementeigenschaften[e] & EP_BIT_INACTIVE)
+
+#define EL_CHANGED(e)          ((e)==EL_FELSBROCKEN    ? EL_EDELSTEIN :  \
+                                (e)==EL_EDELSTEIN      ? EL_DIAMANT :    \
+                                (e)==EL_EDELSTEIN_GELB ? EL_DIAMANT :    \
+                                (e)==EL_EDELSTEIN_ROT  ? EL_DIAMANT :    \
+                                (e)==EL_EDELSTEIN_LILA ? EL_DIAMANT :    \
                                 EL_FELSBROCKEN)
-#define EL_CHANGED2(e)         ((e)==EL_FELSBROCKEN ? EL_EDELSTEIN2 :  \
+#define EL_CHANGED2(e)         ((e)==EL_FELSBROCKEN ? EL_EDELSTEIN_BD :  \
                                 EL_FELSBROCKEN)
 #define IS_DRAWABLE(e)         ((e)<EL_BLOCKED)
 #define IS_NOT_DRAWABLE(e)     ((e)>=EL_BLOCKED)
 #define TIMESIZE               (TimeLeft*100/level.time)
-#define LEVELDIR_SIZE(x)       ((x).num_ready + (x).num_free)
 #define TAPE_IS_EMPTY(x)       ((x).length == 0)
+#define TAPE_IS_STOPPED(x)     (!(x).recording && !(x).playing &&!(x).pausing)
 
 /* Pixmaps with Xpm or X11 Bitmap files */
 #define PIX_BACK               0
@@ -133,10 +144,9 @@ typedef int BOOL;
 /* Pixmaps without them */
 #define PIX_DB_BACK            5
 #define PIX_DB_DOOR            6
-#define PIX_FADEMASK           7
 
 #define NUM_PICTURES           5
-#define NUM_PIXMAPS            8
+#define NUM_PIXMAPS            7
 
 /* boundaries of arrays etc. */
 #define MAX_NAMELEN            (10+1)
@@ -174,6 +184,7 @@ struct PlayerInfo
   int handicap;
   unsigned int setup;
   int leveldir_nr;
+  int level_nr;
 };
 
 struct LevelInfo
@@ -195,8 +206,8 @@ struct LevelDirInfo
 {
   char filename[MAX_LEVDIR_FILENAME];
   char name[MAX_LEVDIR_NAME];
-  int num_ready;
-  int num_free;
+  int levels;
+  int readonly;
 };
 
 struct RecordingInfo
@@ -206,7 +217,12 @@ struct RecordingInfo
   unsigned long date;
   unsigned long counter;
   unsigned long length;
+  unsigned long length_seconds;
+  unsigned int delay_played;
+  BOOL pause_before_death;
+  BOOL changed;
   BOOL recording, playing, pausing;
+  BOOL fast_forward;
   struct
   {
     unsigned char joystickdata;
@@ -223,8 +239,7 @@ struct JoystickInfo
 extern Display        *display;
 extern int             screen;
 extern Window                  window;
-extern GC                      gc, plane_gc;
-extern GC              clip_gc[];
+extern GC              gc, clip_gc[];
 extern XImage         *image[];
 extern Pixmap          clipmask[];
 extern Pixmap          pix[];
@@ -237,18 +252,22 @@ extern int                sound_device;
 extern char           *sound_device_name;
 extern int             joystick_device;
 extern char           *joystick_device_name[2];
+extern char           *level_directory;
 extern int                     width, height;
 extern unsigned long   pen_fg, pen_bg;
 
 extern int             game_status;
+extern int             game_emulation;
 extern int             button_status, motion_status;
-extern int             key_status;
+extern int             key_joystick_mapping;
 extern int             global_joystick_status, joystick_status;
 extern int             sound_status, sound_on;
 extern int             sound_loops_allowed, sound_loops_on;
 extern int             sound_music_on;
+extern int             sound_simple_on;
 extern int             toons_on;
 extern int             direct_draw_on;
+extern int             scroll_delay_on;
 extern int             fading_on;
 extern int             autorecord_on;
 extern int             joystick_nr;
@@ -269,68 +288,69 @@ extern int                Frame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern int             Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern int             JustHit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
 extern int             AmoebaNr[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-extern int             AmoebaCnt[MAX_NUM_AMOEBA];
+extern int             AmoebaCnt[MAX_NUM_AMOEBA], AmoebaCnt2[MAX_NUM_AMOEBA];
 extern long            Elementeigenschaften[MAX_ELEMENTS];
 
 extern int             level_nr, leveldir_nr, num_leveldirs;
 extern int             lev_fieldx,lev_fieldy, scroll_x,scroll_y;
 
 extern int             LevelSolved,GameOver, JX,JY, ZX,ZY;
-extern int             Gems,Dynamite,Key[4],TimeLeft,Score,MampferNr;
-extern int             DynaBombCount, DynaBombSize, DynaBombsLeft;
-extern int             CheckMoving,CheckExploding, SiebAktiv;
+extern int             FrameCounter,TimeFrames,TimeLeft,Score;
+extern int             Gems,SokobanFields,Lights,Dynamite,Key[4],MampferNr;
+extern int             DynaBombCount, DynaBombSize, DynaBombsLeft, DynaBombXL;
+extern int             SiebAktiv;
 
 extern struct LevelDirInfo     leveldir[];
 extern struct LevelInfo                level;
 extern struct PlayerInfo       player;
 extern struct HiScore          highscore[];
-extern struct RecordingInfo    tape, master_tape;
+extern struct RecordingInfo    tape;
 extern struct JoystickInfo     joystick[];
 
 extern int             background_loop[];
 extern int             num_bg_loops;
 
-extern char           *progname;
+extern char            *progname;
 
 
 /* often used screen positions */
-#define SX             8
-#define SY             8
-#define REAL_SX                (SX-2)
-#define REAL_SY                (SY-2)
-#define DX             566
-#define DY             60
-#define VX             DX
-#define VY             400
-#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 MIDPOSX                (SCR_FIELDX/2)
-#define MIDPOSY                (SCR_FIELDY/2)
-#define SXSIZE         (SCR_FIELDX*TILEX)
-#define SYSIZE         (SCR_FIELDY*TILEY)
-#define DXSIZE         100
-#define DYSIZE         280
-#define VXSIZE         DXSIZE
-#define VYSIZE         100
-#define FULL_SXSIZE    (2+SXSIZE+2)
-#define FULL_SYSIZE    (2+SYSIZE+2)
-#define MICROLEV_XPOS  (SX+4*32+16)
-#define MICROLEV_YPOS  (SX+12*32)
-#define MICROLEV_XSIZE (STD_LEV_FIELDX*MICRO_TILEX)
-#define MICROLEV_YSIZE (STD_LEV_FIELDY*MICRO_TILEY)
-#define MICROLABEL_YPOS        (MICROLEV_YPOS+MICROLEV_YSIZE+12)
-#define FONT1_XSIZE    32
-#define FONT1_YSIZE    32
-#define FONT2_XSIZE    14
-#define FONT2_YSIZE    14
-#define FONT3_XSIZE    11
-#define FONT3_YSIZE    14
-#define FONT4_XSIZE    16
-#define FONT4_YSIZE    16
+#define SX                     8
+#define SY                     8
+#define REAL_SX                        (SX-2)
+#define REAL_SY                        (SY-2)
+#define DX                     566
+#define DY                     60
+#define VX                     DX
+#define VY                     400
+#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 MIDPOSX                        (SCR_FIELDX/2)
+#define MIDPOSY                        (SCR_FIELDY/2)
+#define SXSIZE                 (SCR_FIELDX*TILEX)
+#define SYSIZE                 (SCR_FIELDY*TILEY)
+#define DXSIZE                 100
+#define DYSIZE                 280
+#define VXSIZE                 DXSIZE
+#define VYSIZE                 100
+#define FULL_SXSIZE            (2+SXSIZE+2)
+#define FULL_SYSIZE            (2+SYSIZE+2)
+#define MICROLEV_XPOS          (SX+4*32+16)
+#define MICROLEV_YPOS          (SX+12*32)
+#define MICROLEV_XSIZE         (STD_LEV_FIELDX*MICRO_TILEX)
+#define MICROLEV_YSIZE         (STD_LEV_FIELDY*MICRO_TILEY)
+#define MICROLABEL_YPOS                (MICROLEV_YPOS+MICROLEV_YSIZE+12)
+#define FONT1_XSIZE            32
+#define FONT1_YSIZE            32
+#define FONT2_XSIZE            14
+#define FONT2_YSIZE            14
+#define FONT3_XSIZE            11
+#define FONT3_YSIZE            14
+#define FONT4_XSIZE            16
+#define FONT4_YSIZE            16
 
 #define GFX_STARTX             SX
 #define GFX_STARTY             SY
@@ -349,364 +369,413 @@ extern char            *progname;
 **     256 - 511: flag elements, only used at runtime
 */
 /* "real" level elements */
-#define EL_LEERRAUM    0
-#define        EL_ERDREICH     1
-#define        EL_MAUERWERK    2
-#define        EL_FELSBODEN    3
-#define        EL_FELSBROCKEN  4
-#define        EL_SCHLUESSEL   5
-#define        EL_EDELSTEIN    6
-#define        EL_AUSGANG_ZU   7
-#define        EL_SPIELFIGUR   8
-#define EL_KAEFER      9
-#define EL_FLIEGER     10
-#define EL_MAMPFER     11
-#define EL_ZOMBIE      12
-#define EL_BETON       13
-#define EL_DIAMANT     14
-#define EL_AMOEBE_TOT  15
-#define EL_MORAST_LEER 16
-#define EL_MORAST_VOLL 17
-#define EL_TROPFEN     18
-#define EL_BOMBE       19
-#define EL_SIEB_LEER   20
-#define EL_SIEB_VOLL   21
-#define EL_SALZSAEURE  22
-#define EL_AMOEBE_NASS 23
-#define EL_AMOEBE_NORM 24
-#define EL_KOKOSNUSS   25
-#define EL_LIFE                26
-#define EL_LIFE_ASYNC  27
-#define EL_DYNAMIT     28
-#define EL_BADEWANNE   29
-#define EL_ABLENK_AUS  30
-#define EL_ABLENK_EIN  31
-#define EL_SCHLUESSEL1 32
-#define EL_SCHLUESSEL2 33
-#define EL_SCHLUESSEL3 34
-#define EL_SCHLUESSEL4 35
-#define EL_PFORTE1     36
-#define EL_PFORTE2     37
-#define EL_PFORTE3     38
-#define EL_PFORTE4     39
-#define EL_PFORTE1X    40
-#define EL_PFORTE2X    41
-#define EL_PFORTE3X    42
-#define EL_PFORTE4X    43
-#define EL_DYNAMIT_AUS 44
-#define EL_PACMAN      45
-#define EL_UNSICHTBAR  46
-#define EL_BIRNE_AUS   47
-#define EL_BIRNE_EIN   48
-#define EL_ERZ_EDEL    49
-#define EL_ERZ_DIAM    50
-#define EL_AMOEBE_VOLL 51
-#define EL_AMOEBA2DIAM 52
-#define EL_ZEIT_VOLL   53
-#define EL_ZEIT_LEER   54
-#define EL_MAUER_LEBT  55
-#define EL_EDELSTEIN2  56
-#define EL_EDELSTEIN3  57
-#define EL_ERZ_EDEL2   58
-#define EL_ERZ_EDEL3   59
-#define EL_MAMPFER2    60
-#define EL_SIEB2_LEER  61
-#define EL_SIEB2_VOLL  62
-#define EL_DYNABOMB    63
-#define EL_DYNABOMB_NR 64
-#define EL_DYNABOMB_SZ 65
-
-#define EL_SPIELER1    80
-#define EL_SPIELER2    81
-#define EL_SPIELER3    82
-#define EL_SPIELER4    83
-#define EL_KAEFER_R    84
-#define EL_KAEFER_O    85
-#define EL_KAEFER_L    86
-#define EL_KAEFER_U    87
-#define EL_FLIEGER_R   88
-#define EL_FLIEGER_O   89
-#define EL_FLIEGER_L   90
-#define EL_FLIEGER_U   91
-#define EL_PACMAN_R    92
-#define EL_PACMAN_O    93
-#define EL_PACMAN_L    94
-#define EL_PACMAN_U    95
-
-#define EL_BADEWANNE1  100
-#define EL_BADEWANNE2  101
-#define EL_BADEWANNE3  102
-#define EL_BADEWANNE4  103
-#define EL_BADEWANNE5  104
-#define EL_SIEB_TOT    105
-#define EL_AUSGANG_ACT 106
-#define EL_AUSGANG_AUF 107
-#define EL_SIEB2_TOT   108
-
-#define EL_CHAR_START  120
-#define EL_CHAR_ASCII0 (EL_CHAR_START-32)
-#define EL_CHAR_AUSRUF (EL_CHAR_ASCII0+33)
-#define EL_CHAR_ZOLL   (EL_CHAR_ASCII0+34)
-#define EL_CHAR_DOLLAR (EL_CHAR_ASCII0+36)
-#define EL_CHAR_PROZ   (EL_CHAR_ASCII0+37)
-#define EL_CHAR_APOSTR (EL_CHAR_ASCII0+39)
-#define EL_CHAR_KLAMM1 (EL_CHAR_ASCII0+40)
-#define EL_CHAR_KLAMM2 (EL_CHAR_ASCII0+41)
-#define EL_CHAR_PLUS   (EL_CHAR_ASCII0+43)
-#define EL_CHAR_KOMMA  (EL_CHAR_ASCII0+44)
-#define EL_CHAR_MINUS  (EL_CHAR_ASCII0+45)
-#define EL_CHAR_PUNKT  (EL_CHAR_ASCII0+46)
-#define EL_CHAR_SLASH  (EL_CHAR_ASCII0+47)
-#define EL_CHAR_0      (EL_CHAR_ASCII0+48)
-#define EL_CHAR_9      (EL_CHAR_ASCII0+57)
-#define EL_CHAR_DOPPEL (EL_CHAR_ASCII0+58)
-#define EL_CHAR_SEMIKL (EL_CHAR_ASCII0+59)
-#define EL_CHAR_LT     (EL_CHAR_ASCII0+60)
-#define EL_CHAR_GLEICH (EL_CHAR_ASCII0+61)
-#define EL_CHAR_GT     (EL_CHAR_ASCII0+62)
-#define EL_CHAR_FRAGE  (EL_CHAR_ASCII0+63)
-#define EL_CHAR_AT     (EL_CHAR_ASCII0+64)
-#define EL_CHAR_A      (EL_CHAR_ASCII0+65)
-#define EL_CHAR_Z      (EL_CHAR_ASCII0+90)
-#define EL_CHAR_AE     (EL_CHAR_ASCII0+91)
-#define EL_CHAR_OE     (EL_CHAR_ASCII0+92)
-#define EL_CHAR_UE     (EL_CHAR_ASCII0+93)
-#define EL_CHAR_COPY   (EL_CHAR_ASCII0+94)
-#define EL_CHAR_END    (EL_CHAR_START+79)
+#define EL_LEERRAUM            0
+#define        EL_ERDREICH             1
+#define        EL_MAUERWERK            2
+#define        EL_FELSBODEN            3
+#define        EL_FELSBROCKEN          4
+#define        EL_SCHLUESSEL           5
+#define        EL_EDELSTEIN            6
+#define        EL_AUSGANG_ZU           7
+#define        EL_SPIELFIGUR           8
+#define EL_KAEFER              9
+#define EL_FLIEGER             10
+#define EL_MAMPFER             11
+#define EL_ZOMBIE              12
+#define EL_BETON               13
+#define EL_DIAMANT             14
+#define EL_AMOEBE_TOT          15
+#define EL_MORAST_LEER         16
+#define EL_MORAST_VOLL         17
+#define EL_TROPFEN             18
+#define EL_BOMBE               19
+#define EL_SIEB_LEER           20
+#define EL_SIEB_VOLL           21
+#define EL_SALZSAEURE          22
+#define EL_AMOEBE_NASS         23
+#define EL_AMOEBE_NORM         24
+#define EL_KOKOSNUSS           25
+#define EL_LIFE                        26
+#define EL_LIFE_ASYNC          27
+#define EL_DYNAMIT             28
+#define EL_BADEWANNE           29
+#define EL_ABLENK_AUS          30
+#define EL_ABLENK_EIN          31
+#define EL_SCHLUESSEL1         32
+#define EL_SCHLUESSEL2         33
+#define EL_SCHLUESSEL3         34
+#define EL_SCHLUESSEL4         35
+#define EL_PFORTE1             36
+#define EL_PFORTE2             37
+#define EL_PFORTE3             38
+#define EL_PFORTE4             39
+#define EL_PFORTE1X            40
+#define EL_PFORTE2X            41
+#define EL_PFORTE3X            42
+#define EL_PFORTE4X            43
+#define EL_DYNAMIT_AUS         44
+#define EL_PACMAN              45
+#define EL_UNSICHTBAR          46
+#define EL_BIRNE_AUS           47
+#define EL_BIRNE_EIN           48
+#define EL_ERZ_EDEL            49
+#define EL_ERZ_DIAM            50
+#define EL_AMOEBE_VOLL         51
+#define EL_AMOEBE_BD           52
+#define EL_ZEIT_VOLL           53
+#define EL_ZEIT_LEER           54
+#define EL_MAUER_LEBT          55
+#define EL_EDELSTEIN_BD                56
+#define EL_EDELSTEIN_GELB      57
+#define EL_ERZ_EDEL_BD         58
+#define EL_ERZ_EDEL_GELB       59
+#define EL_MAMPFER2            60
+#define EL_SIEB2_LEER          61
+#define EL_SIEB2_VOLL          62
+#define EL_DYNABOMB            63
+#define EL_DYNABOMB_NR         64
+#define EL_DYNABOMB_SZ         65
+#define EL_DYNABOMB_XL         66
+#define EL_SOKOBAN_OBJEKT      67
+#define EL_SOKOBAN_FELD_LEER   68
+#define EL_SOKOBAN_FELD_VOLL   69
+#define EL_BUTTERFLY_R         70
+#define EL_BUTTERFLY_O         71
+#define EL_BUTTERFLY_L         72
+#define EL_BUTTERFLY_U         73
+#define EL_FIREFLY_R           74
+#define EL_FIREFLY_O           75
+#define EL_FIREFLY_L           76
+#define EL_FIREFLY_U           77
+#define EL_BUTTERFLY_1         EL_BUTTERFLY_U
+#define EL_BUTTERFLY_2         EL_BUTTERFLY_L
+#define EL_BUTTERFLY_3         EL_BUTTERFLY_O
+#define EL_BUTTERFLY_4         EL_BUTTERFLY_R
+#define EL_FIREFLY_1           EL_FIREFLY_L
+#define EL_FIREFLY_2           EL_FIREFLY_U
+#define EL_FIREFLY_3           EL_FIREFLY_R
+#define EL_FIREFLY_4           EL_FIREFLY_O
+#define EL_BUTTERFLY           78
+#define EL_FIREFLY             79
+#define EL_SPIELER1            80
+#define EL_SPIELER2            81
+#define EL_SPIELER3            82
+#define EL_SPIELER4            83
+#define EL_KAEFER_R            84
+#define EL_KAEFER_O            85
+#define EL_KAEFER_L            86
+#define EL_KAEFER_U            87
+#define EL_FLIEGER_R           88
+#define EL_FLIEGER_O           89
+#define EL_FLIEGER_L           90
+#define EL_FLIEGER_U           91
+#define EL_PACMAN_R            92
+#define EL_PACMAN_O            93
+#define EL_PACMAN_L            94
+#define EL_PACMAN_U            95
+#define EL_EDELSTEIN_ROT       96
+#define EL_EDELSTEIN_LILA      97
+#define EL_ERZ_EDEL_ROT                98
+#define EL_ERZ_EDEL_LILA       99
+#define EL_BADEWANNE1          100
+#define EL_BADEWANNE2          101
+#define EL_BADEWANNE3          102
+#define EL_BADEWANNE4          103
+#define EL_BADEWANNE5          104
+#define EL_SIEB_TOT            105
+#define EL_AUSGANG_ACT         106
+#define EL_AUSGANG_AUF         107
+#define EL_SIEB2_TOT           108
+#define EL_AMOEBA2DIAM         109
+
+#define EL_CHAR_START          120
+#define EL_CHAR_ASCII0         (EL_CHAR_START-32)
+#define EL_CHAR_AUSRUF         (EL_CHAR_ASCII0+33)
+#define EL_CHAR_ZOLL           (EL_CHAR_ASCII0+34)
+#define EL_CHAR_DOLLAR         (EL_CHAR_ASCII0+36)
+#define EL_CHAR_PROZ           (EL_CHAR_ASCII0+37)
+#define EL_CHAR_APOSTR         (EL_CHAR_ASCII0+39)
+#define EL_CHAR_KLAMM1         (EL_CHAR_ASCII0+40)
+#define EL_CHAR_KLAMM2         (EL_CHAR_ASCII0+41)
+#define EL_CHAR_PLUS           (EL_CHAR_ASCII0+43)
+#define EL_CHAR_KOMMA          (EL_CHAR_ASCII0+44)
+#define EL_CHAR_MINUS          (EL_CHAR_ASCII0+45)
+#define EL_CHAR_PUNKT          (EL_CHAR_ASCII0+46)
+#define EL_CHAR_SLASH          (EL_CHAR_ASCII0+47)
+#define EL_CHAR_0              (EL_CHAR_ASCII0+48)
+#define EL_CHAR_9              (EL_CHAR_ASCII0+57)
+#define EL_CHAR_DOPPEL         (EL_CHAR_ASCII0+58)
+#define EL_CHAR_SEMIKL         (EL_CHAR_ASCII0+59)
+#define EL_CHAR_LT             (EL_CHAR_ASCII0+60)
+#define EL_CHAR_GLEICH         (EL_CHAR_ASCII0+61)
+#define EL_CHAR_GT             (EL_CHAR_ASCII0+62)
+#define EL_CHAR_FRAGE          (EL_CHAR_ASCII0+63)
+#define EL_CHAR_AT             (EL_CHAR_ASCII0+64)
+#define EL_CHAR_A              (EL_CHAR_ASCII0+65)
+#define EL_CHAR_Z              (EL_CHAR_ASCII0+90)
+#define EL_CHAR_AE             (EL_CHAR_ASCII0+91)
+#define EL_CHAR_OE             (EL_CHAR_ASCII0+92)
+#define EL_CHAR_UE             (EL_CHAR_ASCII0+93)
+#define EL_CHAR_COPY           (EL_CHAR_ASCII0+94)
+#define EL_CHAR_END            (EL_CHAR_START+79)
 
 /* "unreal" runtime elements */
-#define EL_BLOCKED     300
-#define EL_EXPLODING   301
-#define EL_CRACKINGNUT 302
-#define EL_BLURB_LEFT  303
-#define EL_BLURB_RIGHT 304
-#define EL_AMOEBING    305
-#define EL_MAUERND     306
+#define EL_BLOCKED             300
+#define EL_EXPLODING           301
+#define EL_CRACKINGNUT         302
+#define EL_BLURB_LEFT          303
+#define EL_BLURB_RIGHT         304
+#define EL_AMOEBING            305
+#define EL_MAUERND             306
 
 /* names for the graphic objects */
 /* Zeile 0 (0) */
-#define GFX_LEERRAUM   (-1)
-#define        GFX_ERDREICH    0
-#define GFX_ERDENRAND  1
-#define GFX_MORAST_LEER        2
-#define GFX_MORAST_VOLL        3
-#define GFX_BETON      4
-#define        GFX_MAUERWERK   5
-#define        GFX_FELSBODEN   6
-#define GFX_DYNABOMB   7
-#define GFX_DYNABOMB_NR        GFX_DYNABOMB
-#define        GFX_EDELSTEIN   8
-#define GFX_DIAMANT    10
-#define        GFX_FELSBROCKEN 12
+#define GFX_LEERRAUM           (-1)
+#define        GFX_ERDREICH            0
+#define GFX_ERDENRAND          1
+#define GFX_MORAST_LEER                2
+#define GFX_MORAST_VOLL                3
+#define GFX_BETON              4
+#define        GFX_MAUERWERK           5
+#define        GFX_FELSBODEN           6
+#define        GFX_EDELSTEIN           8
+#define GFX_DIAMANT            10
+#define        GFX_FELSBROCKEN         12
 /* Zeile 1 (16) */
-#define GFX_BADEWANNE1 16
-#define GFX_SALZSAEURE 17
-#define GFX_BADEWANNE2 18
-#define GFX_UNSICHTBAR 19
-#define GFX_SCHLUESSEL1        20
-#define GFX_SCHLUESSEL2        21
-#define GFX_SCHLUESSEL3        22
-#define GFX_SCHLUESSEL4        23
-#define GFX_LIFE       24
-#define GFX_LIFE_ASYNC 25
-#define GFX_BADEWANNE  26
-#define GFX_BOMBE      27
-#define GFX_KOKOSNUSS  28
-#define GFX_CRACKINGNUT        29
+#define GFX_BADEWANNE1         16
+#define GFX_SALZSAEURE         17
+#define GFX_BADEWANNE2         18
+#define GFX_UNSICHTBAR         19
+#define GFX_SCHLUESSEL1                20
+#define GFX_SCHLUESSEL2                21
+#define GFX_SCHLUESSEL3                22
+#define GFX_SCHLUESSEL4                23
+#define GFX_LIFE               24
+#define GFX_LIFE_ASYNC         25
+#define GFX_BADEWANNE          26
+#define GFX_BOMBE              27
+#define GFX_KOKOSNUSS          28
+#define GFX_CRACKINGNUT                29
 /* Zeile 2 (32) */
-#define GFX_BADEWANNE3 32
-#define GFX_BADEWANNE4 33
-#define GFX_BADEWANNE5 34
-#define        GFX_SPIELFIGUR  35
-#define GFX_PFORTE1    36
-#define GFX_PFORTE2    37
-#define GFX_PFORTE3    38
-#define GFX_PFORTE4    39
-#define GFX_PFORTE1X   40
-#define GFX_PFORTE2X   41
-#define GFX_PFORTE3X   42
-#define GFX_PFORTE4X   43
+#define GFX_BADEWANNE3         32
+#define GFX_BADEWANNE4         33
+#define GFX_BADEWANNE5         34
+#define        GFX_SPIELFIGUR          35
+#define GFX_PFORTE1            36
+#define GFX_PFORTE2            37
+#define GFX_PFORTE3            38
+#define GFX_PFORTE4            39
+#define GFX_PFORTE1X           40
+#define GFX_PFORTE2X           41
+#define GFX_PFORTE3X           42
+#define GFX_PFORTE4X           43
 /* Zeile 3 (48) */
-#define GFX_DYNAMIT_AUS        48
-#define GFX_DYNAMIT    49
-#define GFX_FLIEGER    56
-#define GFX_FLIEGER_R  56
-#define GFX_FLIEGER_O  57
-#define GFX_FLIEGER_L  58
-#define GFX_FLIEGER_U  59
+#define GFX_DYNAMIT_AUS                48
+#define GFX_DYNAMIT            49
+#define GFX_FLIEGER            56
+#define GFX_FLIEGER_R          56
+#define GFX_FLIEGER_O          57
+#define GFX_FLIEGER_L          58
+#define GFX_FLIEGER_U          59
 /* Zeile 4 (64) */
-#define GFX_EXPLOSION  64
-#define GFX_KAEFER     72
-#define GFX_KAEFER_R   72
-#define GFX_KAEFER_O   73
-#define GFX_KAEFER_L   74
-#define GFX_KAEFER_U   75
+#define GFX_EXPLOSION          64
+#define GFX_KAEFER             72
+#define GFX_KAEFER_R           72
+#define GFX_KAEFER_O           73
+#define GFX_KAEFER_L           74
+#define GFX_KAEFER_U           75
 /* Zeile 5 (80) */
-#define GFX_MAMPFER    80
-#define GFX_ZOMBIE     84
-#define GFX_PACMAN     88
-#define GFX_PACMAN_R   88
-#define GFX_PACMAN_O   89
-#define GFX_PACMAN_L   90
-#define GFX_PACMAN_U   91
+#define GFX_MAMPFER            80
+#define GFX_ZOMBIE             84
+#define GFX_PACMAN             88
+#define GFX_PACMAN_R           88
+#define GFX_PACMAN_O           89
+#define GFX_PACMAN_L           90
+#define GFX_PACMAN_U           91
 /* Zeile 6 (96) */
-#define GFX_ABLENK     96
-#define GFX_ABLENK_EIN GFX_ABLENK
-#define GFX_ABLENK_AUS GFX_ABLENK
-#define GFX_AMOEBE_NASS        100
-#define GFX_TROPFEN    101
-#define GFX_AMOEBING   GFX_TROPFEN
-#define GFX_AMOEBE_LEBT        104
-#define GFX_AMOEBE_NORM        GFX_AMOEBE_LEBT
-#define GFX_AMOEBE_TOT 108
-#define GFX_AMOEBA2DIAM        GFX_AMOEBE_TOT
-#define GFX_BIRNE_AUS  112
-#define GFX_BIRNE_EIN  113
-#define GFX_ZEIT_VOLL  114
-#define GFX_ZEIT_LEER  115
+#define GFX_ABLENK             96
+#define GFX_ABLENK_EIN         GFX_ABLENK
+#define GFX_ABLENK_AUS         GFX_ABLENK
+#define GFX_AMOEBE_NASS                100
+#define GFX_TROPFEN            101
+#define GFX_AMOEBING           GFX_TROPFEN
+#define GFX_AMOEBE_LEBT                104
+#define GFX_AMOEBE_NORM                GFX_AMOEBE_LEBT
+#define GFX_AMOEBE_TOT         108
+#define GFX_AMOEBA2DIAM                GFX_AMOEBE_TOT
 /* Zeile 7 (112) */
-#define GFX_GEBLUBBER  124
+#define GFX_BIRNE_AUS          112
+#define GFX_BIRNE_EIN          113
+#define GFX_ZEIT_VOLL          114
+#define GFX_ZEIT_LEER          115
+#define GFX_AMOEBE_VOLL                120
+#define GFX_AMOEBE_BD          GFX_AMOEBE_VOLL
+#define GFX_SOKOBAN_OBJEKT     121
+#define GFX_SOKOBAN_FELD_LEER  122
+#define GFX_SOKOBAN_FELD_VOLL  123
+#define GFX_GEBLUBBER          124
 /* Zeile 8 (128) */
-#define GFX_SIEB_LEER  128
-#define GFX_SIEB_VOLL  GFX_SIEB_LEER
-#define GFX_SIEB_TOT   GFX_SIEB_LEER
-#define GFX_ERZ_EDEL   132
-#define GFX_ERZ_DIAM   133
-#define GFX_ERZ_EDEL2  134
-#define GFX_ERZ_EDEL3  135
-#define GFX_AMOEBE_VOLL        136
-#define GFX_KUGEL_ROT  140
-#define GFX_KUGEL_BLAU 141
-#define GFX_KUGEL_GELB 142
-#define GFX_KUGEL_GRAU 143
-#define GFX_DYNABOMB_SZ        GFX_KUGEL_GRAU
+#define GFX_SIEB_LEER          128
+#define GFX_SIEB_VOLL          GFX_SIEB_LEER
+#define GFX_SIEB_TOT           GFX_SIEB_LEER
+#define GFX_ERZ_EDEL           132
+#define GFX_ERZ_DIAM           133
+#define GFX_ERZ_EDEL_ROT       134
+#define GFX_ERZ_EDEL_LILA      135
+#define GFX_ERZ_EDEL_GELB      136
+#define GFX_ERZ_EDEL_BD                137
+#define GFX_EDELSTEIN_GELB     138
+#define GFX_KUGEL_ROT          140
+#define GFX_KUGEL_BLAU         141
+#define GFX_KUGEL_GELB         142
+#define GFX_KUGEL_GRAU         143
 /* Zeile 9 (144) */
-#define GFX_BLURB_LEFT 144
-#define GFX_BLURB_RIGHT        148
-#define GFX_EDELSTEIN3 152
+#define GFX_BLURB_LEFT         144
+#define GFX_BLURB_RIGHT                148
+#define GFX_EDELSTEIN_ROT      152
+#define GFX_EDELSTEIN_LILA     154
+#define GFX_DYNABOMB_XL                156
 /* Zeile 10 (160) */
-#define GFX_EDELSTEIN2 163
-#define GFX_MAUER_R1   165
-#define GFX_MAUER_R    167
-#define GFX_MAUER_L1   168
-#define GFX_MAUER_L    170
-#define GFX_MAUER_LEBT 171
-#define GFX_SIEB2_LEER 172
-#define GFX_SIEB2_VOLL GFX_SIEB2_LEER
-#define GFX_SIEB2_TOT  GFX_SIEB2_LEER
+#define GFX_EDELSTEIN_BD       163
+#define GFX_MAUER_R1           165
+#define GFX_MAUER_R            167
+#define GFX_MAUER_L1           168
+#define GFX_MAUER_L            170
+#define GFX_MAUER_LEBT         171
+#define GFX_SIEB2_LEER         172
+#define GFX_SIEB2_VOLL         GFX_SIEB2_LEER
+#define GFX_SIEB2_TOT          GFX_SIEB2_LEER
 /* Zeile 11 (176) */
-#define        GFX_AUSGANG_ZU  176
-#define        GFX_AUSGANG_ACT 177
-#define        GFX_AUSGANG_AUF 180
-#define GFX_MAMPFER2   184
-
-#define        GFX_SCHLUESSEL  GFX_SCHLUESSEL1
-
-#define GFX_SPIELER1   116
-#define GFX_SPIELER2   117
-#define GFX_SPIELER3   118
-#define GFX_SPIELER4   119
+#define        GFX_AUSGANG_ZU          176
+#define        GFX_AUSGANG_ACT         177
+#define        GFX_AUSGANG_AUF         180
+#define GFX_MAMPFER2           184
+#define GFX_DYNABOMB           188
+#define GFX_DYNABOMB_NR                188
+#define GFX_DYNABOMB_SZ                191
+/* Zeile 12 (192) */
+#define GFX_PFEIL_L            192
+#define GFX_PFEIL_R            193
+#define GFX_PFEIL_O            194
+#define GFX_PFEIL_U            195
+#define GFX_BUTTERFLY          196
+#define GFX_FIREFLY            198
+#define GFX_BUTTERFLY_R                200
+#define GFX_BUTTERFLY_O                201
+#define GFX_BUTTERFLY_L                202
+#define GFX_BUTTERFLY_U                203
+#define GFX_FIREFLY_R          204
+#define GFX_FIREFLY_O          205
+#define GFX_FIREFLY_L          206
+#define GFX_FIREFLY_U          207
+
+#define        GFX_SCHLUESSEL          GFX_SCHLUESSEL1
+
+#define GFX_SPIELER1           116
+#define GFX_SPIELER2           117
+#define GFX_SPIELER3           118
+#define GFX_SPIELER4           119
 
 /* nicht in "RocksScreen" sondern woanders :) */
-#define GFX_CHAR_START 256
-#define GFX_CHAR_ASCII0        (GFX_CHAR_START-32)
-#define GFX_CHAR_AUSRUF        (GFX_CHAR_ASCII0+33)
-#define GFX_CHAR_ZOLL  (GFX_CHAR_ASCII0+34)
-#define GFX_CHAR_DOLLAR        (GFX_CHAR_ASCII0+36)
-#define GFX_CHAR_PROZ  (GFX_CHAR_ASCII0+37)
-#define GFX_CHAR_APOSTR        (GFX_CHAR_ASCII0+39)
-#define GFX_CHAR_KLAMM1        (GFX_CHAR_ASCII0+40)
-#define GFX_CHAR_KLAMM2        (GFX_CHAR_ASCII0+41)
-#define GFX_CHAR_PLUS  (GFX_CHAR_ASCII0+43)
-#define GFX_CHAR_KOMMA (GFX_CHAR_ASCII0+44)
-#define GFX_CHAR_MINUS (GFX_CHAR_ASCII0+45)
-#define GFX_CHAR_PUNKT (GFX_CHAR_ASCII0+46)
-#define GFX_CHAR_SLASH (GFX_CHAR_ASCII0+47)
-#define GFX_CHAR_0     (GFX_CHAR_ASCII0+48)
-#define GFX_CHAR_9     (GFX_CHAR_ASCII0+57)
-#define GFX_CHAR_DOPPEL        (GFX_CHAR_ASCII0+58)
-#define GFX_CHAR_SEMIKL        (GFX_CHAR_ASCII0+59)
-#define GFX_CHAR_LT    (GFX_CHAR_ASCII0+60)
-#define GFX_CHAR_GLEICH        (GFX_CHAR_ASCII0+61)
-#define GFX_CHAR_GT    (GFX_CHAR_ASCII0+62)
-#define GFX_CHAR_FRAGE (GFX_CHAR_ASCII0+63)
-#define GFX_CHAR_AT    (GFX_CHAR_ASCII0+64)
-#define GFX_CHAR_A     (GFX_CHAR_ASCII0+65)
-#define GFX_CHAR_Z     (GFX_CHAR_ASCII0+90)
-#define GFX_CHAR_AE    (GFX_CHAR_ASCII0+91)
-#define GFX_CHAR_OE    (GFX_CHAR_ASCII0+92)
-#define GFX_CHAR_UE    (GFX_CHAR_ASCII0+93)
-#define GFX_CHAR_COPY  (GFX_CHAR_ASCII0+94)
-#define GFX_CHAR_END   (GFX_CHAR_START+79)
+#define GFX_CHAR_START         256
+#define GFX_CHAR_ASCII0                (GFX_CHAR_START-32)
+#define GFX_CHAR_AUSRUF                (GFX_CHAR_ASCII0+33)
+#define GFX_CHAR_ZOLL          (GFX_CHAR_ASCII0+34)
+#define GFX_CHAR_DOLLAR                (GFX_CHAR_ASCII0+36)
+#define GFX_CHAR_PROZ          (GFX_CHAR_ASCII0+37)
+#define GFX_CHAR_APOSTR                (GFX_CHAR_ASCII0+39)
+#define GFX_CHAR_KLAMM1                (GFX_CHAR_ASCII0+40)
+#define GFX_CHAR_KLAMM2                (GFX_CHAR_ASCII0+41)
+#define GFX_CHAR_PLUS          (GFX_CHAR_ASCII0+43)
+#define GFX_CHAR_KOMMA         (GFX_CHAR_ASCII0+44)
+#define GFX_CHAR_MINUS         (GFX_CHAR_ASCII0+45)
+#define GFX_CHAR_PUNKT         (GFX_CHAR_ASCII0+46)
+#define GFX_CHAR_SLASH         (GFX_CHAR_ASCII0+47)
+#define GFX_CHAR_0             (GFX_CHAR_ASCII0+48)
+#define GFX_CHAR_9             (GFX_CHAR_ASCII0+57)
+#define GFX_CHAR_DOPPEL                (GFX_CHAR_ASCII0+58)
+#define GFX_CHAR_SEMIKL                (GFX_CHAR_ASCII0+59)
+#define GFX_CHAR_LT            (GFX_CHAR_ASCII0+60)
+#define GFX_CHAR_GLEICH                (GFX_CHAR_ASCII0+61)
+#define GFX_CHAR_GT            (GFX_CHAR_ASCII0+62)
+#define GFX_CHAR_FRAGE         (GFX_CHAR_ASCII0+63)
+#define GFX_CHAR_AT            (GFX_CHAR_ASCII0+64)
+#define GFX_CHAR_A             (GFX_CHAR_ASCII0+65)
+#define GFX_CHAR_Z             (GFX_CHAR_ASCII0+90)
+#define GFX_CHAR_AE            (GFX_CHAR_ASCII0+91)
+#define GFX_CHAR_OE            (GFX_CHAR_ASCII0+92)
+#define GFX_CHAR_UE            (GFX_CHAR_ASCII0+93)
+#define GFX_CHAR_COPY          (GFX_CHAR_ASCII0+94)
+#define GFX_CHAR_END           (GFX_CHAR_START+79)
 
 /* score for elements */
-#define SC_EDELSTEIN   0
-#define SC_DIAMANT     1
-#define SC_KAEFER      2
-#define SC_FLIEGER     3
-#define SC_MAMPFER     4
-#define SC_ZOMBIE      5
-#define SC_PACMAN      6
-#define SC_KOKOSNUSS   7
-#define SC_DYNAMIT     8
-#define SC_SCHLUESSEL  9
-#define SC_ZEITBONUS   10
+#define SC_EDELSTEIN           0
+#define SC_DIAMANT             1
+#define SC_KAEFER              2
+#define SC_FLIEGER             3
+#define SC_MAMPFER             4
+#define SC_ZOMBIE              5
+#define SC_PACMAN              6
+#define SC_KOKOSNUSS           7
+#define SC_DYNAMIT             8
+#define SC_SCHLUESSEL          9
+#define SC_ZEITBONUS           10
 
 /* the names of the sounds */
-#define SND_ALCHEMY    0
-#define SND_AMOEBE     1
-#define SND_ANTIGRAV   2
-#define SND_AUTSCH     3
-#define SND_BLURB      4
-#define SND_BONG       5
-#define SND_BUING      6
-#define SND_CHASE      7
-#define SND_CZARDASZ   8
-#define SND_DENG       9
-#define SND_FUEL       10
-#define SND_GONG       11
-#define SND_HALLOFFAME 12
-#define SND_HOLZ       13
-#define SND_HUI                14
-#define SND_KABUMM     15
-#define SND_KINK       16
-#define SND_KLAPPER    17
-#define SND_KLING      18
-#define SND_KLOPF      19
-#define SND_KLUMPF     20
-#define SND_KNACK      21
-#define SND_KNURK      22
-#define SND_KRACH      23
-#define SND_LACHEN     24
-#define SND_LASER      25
-#define SND_MIEP       26
-#define SND_NETWORK    27
-#define SND_NJAM       28
-#define SND_OEFFNEN    29
-#define SND_PLING      30
-#define SND_PONG       31
-#define SND_PUSCH      32
-#define SND_QUIEK      33
-#define SND_QUIRK      34
-#define SND_RHYTHMLOOP 35
-#define SND_ROAAAR     36
-#define SND_ROEHR      37
-#define SND_RUMMS      38
-#define SND_SCHLOPP    39
-#define SND_SCHLURF    40
-#define SND_SCHRFF     41
-#define SND_SCHWIRR    42
-#define SND_SIRR       43
-#define SND_SLURP      44
-#define SND_SPROING    45
-#define SND_TWILIGHT   46
-#define SND_TYGER      47
-#define SND_VOYAGER    48
-#define SND_WARNTON    49
-#define SND_WHOOSH     50
-#define SND_ZISCH      51
-
-#define NUM_SOUNDS     52
+#define SND_ALCHEMY            0
+#define SND_AMOEBE             1
+#define SND_ANTIGRAV           2
+#define SND_AUTSCH             3
+#define SND_BLURB              4
+#define SND_BONG               5
+#define SND_BUING              6
+#define SND_CHASE              7
+#define SND_CZARDASZ           8
+#define SND_DENG               9
+#define SND_FUEL               10
+#define SND_GONG               11
+#define SND_HALLOFFAME         12
+#define SND_HOLZ               13
+#define SND_HUI                        14
+#define SND_KABUMM             15
+#define SND_KINK               16
+#define SND_KLAPPER            17
+#define SND_KLING              18
+#define SND_KLOPF              19
+#define SND_KLUMPF             20
+#define SND_KNACK              21
+#define SND_KNURK              22
+#define SND_KRACH              23
+#define SND_LACHEN             24
+#define SND_LASER              25
+#define SND_MIEP               26
+#define SND_NETWORK            27
+#define SND_NJAM               28
+#define SND_OEFFNEN            29
+#define SND_PLING              30
+#define SND_PONG               31
+#define SND_PUSCH              32
+#define SND_QUIEK              33
+#define SND_QUIRK              34
+#define SND_RHYTHMLOOP         35
+#define SND_ROAAAR             36
+#define SND_ROEHR              37
+#define SND_RUMMS              38
+#define SND_SCHLOPP            39
+#define SND_SCHLURF            40
+#define SND_SCHRFF             41
+#define SND_SCHWIRR            42
+#define SND_SIRR               43
+#define SND_SLURP              44
+#define SND_SPROING            45
+#define SND_TWILIGHT           46
+#define SND_TYGER              47
+#define SND_VOYAGER            48
+#define SND_WARNTON            49
+#define SND_WHOOSH             50
+#define SND_ZISCH              51
+
+#define NUM_SOUNDS             52
 
 #define IS_LOOP_SOUND(s)       ((s)==SND_KLAPPER || (s)==SND_ROEHR ||  \
                                 (s)==SND_NJAM || (s)==SND_MIEP)
@@ -720,43 +789,44 @@ extern char *sound_name[NUM_SOUNDS];
 extern struct SoundInfo Sound[NUM_SOUNDS];
 
 /* directions for moving */
-#define MV_NO_MOVING   0
-#define MV_LEFT                1
-#define MV_RIGHT       2
-#define MV_UP          4
-#define MV_DOWN                8
+#define MV_NO_MOVING           0
+#define MV_LEFT                        1
+#define MV_RIGHT               2
+#define MV_UP                  4
+#define MV_DOWN                        8
 
 /* font types */
-#define FS_SMALL       0
-#define FS_BIG         1
+#define FS_SMALL               0
+#define FS_BIG                 1
 /* font colors */
-#define FC_RED         0
-#define FC_BLUE                1
-#define FC_GREEN       2
-#define FC_YELLOW      3
-#define FC_SPECIAL1    4
-#define FC_SPECIAL2    5
+#define FC_RED                 0
+#define FC_BLUE                        1
+#define FC_GREEN               2
+#define FC_YELLOW              3
+#define FC_SPECIAL1            4
+#define FC_SPECIAL2            5
 
 /* values for game_status */
-#define MAINMENU       0
-#define PLAYING                1
-#define LEVELED                2
-#define HELPSCREEN     3
-#define CHOOSELEVEL    4
-#define TYPENAME       5
-#define HALLOFFAME     6
-#define SETUP          7
-#define EXITGAME       8
-
-/* return values for GameActions */
-#define ACT_GO_ON      0
-#define ACT_GAME_OVER  1
-#define ACT_NEW_GAME   2
+#define MAINMENU               0
+#define PLAYING                        1
+#define LEVELED                        2
+#define HELPSCREEN             3
+#define CHOOSELEVEL            4
+#define TYPENAME               5
+#define HALLOFFAME             6
+#define SETUP                  7
+#define EXITGAME               8
+
+/* values for game_emulation */
+#define EMU_NONE               0
+#define EMU_BOULDERDASH                1
+#define EMU_SOKOBAN            2
 
 /* values for the joystick */
 #define JOYSTICK_OFF           0
 #define        JOYSTICK_AVAILABLE      1
 #ifdef __FreeBSD__
+#include <machine/joystick.h>
 #define DEV_JOYSTICK_0         "/dev/joy0"
 #define DEV_JOYSTICK_1         "/dev/joy1"
 #else
@@ -786,57 +856,60 @@ extern struct SoundInfo Sound[NUM_SOUNDS];
 #define JOY_BUTTON_NEW_RELEASED        3
 
 #ifdef NO_JOYSTICK
-#define JOYSTICK_STATUS        JOYSTICK_OFF
+#define JOYSTICK_STATUS                JOYSTICK_OFF
 #else
-#define JOYSTICK_STATUS        JOYSTICK_AVAILABLE
+#define JOYSTICK_STATUS                JOYSTICK_AVAILABLE
 #endif
 
 #ifndef GAME_DIR
-#define GAME_DIR       "."
+#define GAME_DIR               "."
 #endif
 
 #ifndef GFX_PATH
-#define GFX_PATH       GAME_DIR "/graphics"
+#define GFX_PATH               GAME_DIR "/graphics"
 #endif
 #ifndef SND_PATH
-#define SND_PATH       GAME_DIR "/sounds"
+#define SND_PATH               GAME_DIR "/sounds"
 #endif
 #ifndef LEVEL_PATH
-#define LEVEL_PATH     GAME_DIR "/levels"
+#define LEVEL_PATH             GAME_DIR "/levels"
 #endif
 #ifndef SCORE_PATH
-#define SCORE_PATH     LEVEL_PATH
+#define SCORE_PATH             LEVEL_PATH
 #endif
 #ifndef NAMES_PATH
-#define NAMES_PATH     LEVEL_PATH
+#define NAMES_PATH             LEVEL_PATH
 #endif
 #ifndef CONFIG_PATH
-#define CONFIG_PATH    GAME_DIR
+#define CONFIG_PATH            GAME_DIR
 #endif
 #ifndef JOYDAT_PATH
-#define JOYDAT_PATH    GAME_DIR
+#define JOYDAT_PATH            GAME_DIR
 #endif
 
-#define SCORE_FILENAME "ROCKS.score"
-#define NAMES_FILENAME "ROCKS.names"
-#define LEVDIR_FILENAME        "ROCKS.levelinfo"
-#define JOYDAT_FILENAME        "ROCKS.joystick"
+#define SCORE_FILENAME         "ROCKS.score"
+#define NAMES_FILENAME         "ROCKS.names"
+#define LEVDIR_FILENAME                "ROCKS.levelinfo"
+#define JOYDAT_FILENAME                "ROCKS.joystick"
 
-#define JOYDAT_FILE    JOYDAT_PATH "/" JOYDAT_FILENAME
+#define JOYDAT_FILE            JOYDAT_PATH "/" JOYDAT_FILENAME
 
 #define LEVEL_PERMS    (S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH)
-#define SCORE_PERMS    LEVEL_PERMS
-#define NAMES_PERMS    LEVEL_PERMS
-#define LEVDIR_PERMS   LEVEL_PERMS
-#define LEVREC_PERMS   LEVEL_PERMS
-#define JOYDAT_PERMS   LEVEL_PERMS
-
-#define LEVEL_COOKIE   "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.0"
-#define SCORE_COOKIE   "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.0"
-#define NAMES_COOKIE   "ROCKSNDIAMONDS_NAMES_FILE_VERSION_1.0"
-#define LEVELDIR_COOKIE        "ROCKSNDIAMONDS_LEVELDIR_FILE_VERSION_1.0"
-#define LEVELREC_COOKIE        "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
-#define JOYSTICK_COOKIE        "ROCKSNDIAMONDS_JOYSTICK_FILE_VERSION_1.0"
+#define SCORE_PERMS            LEVEL_PERMS
+#define NAMES_PERMS            LEVEL_PERMS
+#define LEVDIR_PERMS           LEVEL_PERMS
+#define LEVREC_PERMS           LEVEL_PERMS
+#define JOYDAT_PERMS           LEVEL_PERMS
+
+/* old cookies */
+#define NAMES_COOKIE_10                "ROCKSNDIAMONDS_NAMES_FILE_VERSION_1.0"
+
+#define LEVEL_COOKIE           "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.0"
+#define SCORE_COOKIE           "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.0"
+#define NAMES_COOKIE           "ROCKSNDIAMONDS_NAMES_FILE_VERSION_1.1"
+#define LEVELDIR_COOKIE                "ROCKSNDIAMONDS_LEVELDIR_FILE_VERSION_1.0"
+#define LEVELREC_COOKIE                "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
+#define JOYSTICK_COOKIE                "ROCKSNDIAMONDS_JOYSTICK_FILE_VERSION_1.0"
 #define LEVEL_COOKIE_LEN       (strlen(LEVEL_COOKIE)+1)
 #define SCORE_COOKIE_LEN       (strlen(SCORE_COOKIE)+1)
 #define NAMES_COOKIE_LEN       (strlen(NAMES_COOKIE)+1)
@@ -844,69 +917,74 @@ extern struct SoundInfo Sound[NUM_SOUNDS];
 #define LEVELREC_COOKIE_LEN    (strlen(LEVELREC_COOKIE)+1)
 #define JOYSTICK_COOKIE_LEN    (strlen(JOYSTICK_COOKIE)+1)
 
+#define VERSION_STRING         "1.1"
+#define GAMETITLE_STRING       "Rocks'n'Diamonds"
+#define WINDOWTITLE_STRING     GAMETITLE_STRING " " VERSION_STRING
+#define COPYRIGHT_STRING       "Copyright ^1995-97 by Holger Schemel"
+
 /* Leerer Login- und Alias-Name */
-#define EMPTY_LOGIN    "NO_LOGIN"
-#define EMPTY_ALIAS    "NO_NAME"
+#define EMPTY_LOGIN            "NO_LOGIN"
+#define EMPTY_ALIAS            "NO_NAME"
 
 /* values for button_status */
-#define MB_NOT_PRESSED FALSE
-#define MB_RELEASED    FALSE
-#define MB_PRESSED     TRUE
-#define MB_MENU_CHOICE FALSE
-#define MB_MENU_MARK   TRUE
-#define MB_LEFT                1
-#define MB_MIDDLE      2
-#define MB_RIGHT       3
+#define MB_NOT_PRESSED         FALSE
+#define MB_RELEASED            FALSE
+#define MB_PRESSED             TRUE
+#define MB_MENU_CHOICE         FALSE
+#define MB_MENU_MARK           TRUE
+#define MB_LEFT                        1
+#define MB_MIDDLE              2
+#define MB_RIGHT               3
 
 /* values for key_status */
-#define KEY_NOT_PRESSED        FALSE
-#define KEY_RELEASED   FALSE
-#define KEY_PRESSED    TRUE
+#define KEY_NOT_PRESSED                FALSE
+#define KEY_RELEASED           FALSE
+#define KEY_PRESSED            TRUE
 
 /* values for focus_status */
-#define FOCUS_OUT      FALSE
-#define FOCUS_IN       TRUE
+#define FOCUS_OUT              FALSE
+#define FOCUS_IN               TRUE
 
 /* values for redraw_mask */
-#define REDRAW_ALL     (1L<<0)
-#define REDRAW_FIELD   (1L<<1)
-#define REDRAW_TILES   (1L<<2)
-#define REDRAW_DOOR_1  (1L<<3)
-#define REDRAW_VIDEO_1 (1L<<4)
-#define REDRAW_VIDEO_2 (1L<<5)
-#define REDRAW_VIDEO_3 (1L<<6)
-#define REDRAW_MICROLEV        (1L<<7)
+#define REDRAW_ALL             (1L<<0)
+#define REDRAW_FIELD           (1L<<1)
+#define REDRAW_TILES           (1L<<2)
+#define REDRAW_DOOR_1          (1L<<3)
+#define REDRAW_VIDEO_1         (1L<<4)
+#define REDRAW_VIDEO_2         (1L<<5)
+#define REDRAW_VIDEO_3         (1L<<6)
+#define REDRAW_MICROLEV                (1L<<7)
 #define REDRAW_DOOR_2  (REDRAW_VIDEO_1 | REDRAW_VIDEO_2 | REDRAW_VIDEO_3)
 #define REDRAW_DOORS   (REDRAW_DOOR_1 | REDRAW_DOOR_2)
 #define REDRAW_MAIN    (REDRAW_FIELD | REDRAW_TILES | REDRAW_MICROLEV)
-#define REDRAWTILES_TH SCR_FIELDX*SCR_FIELDY/2
+#define REDRAWTILES_TH         SCR_FIELDX*SCR_FIELDY/2
 
 /* positions in the game control window */
-#define XX_LEVEL       37
-#define YY_LEVEL       20
-#define XX_EMERALDS    29
-#define YY_EMERALDS    54
-#define XX_DYNAMITE    29
-#define YY_DYNAMITE    89
-#define XX_KEYS                18
-#define YY_KEYS                123
-#define XX_SCORE       15
-#define YY_SCORE       159
-#define XX_TIME                29
-#define YY_TIME                194
-
-#define DX_LEVEL       (DX+XX_LEVEL)
-#define DY_LEVEL       (DY+YY_LEVEL)
-#define DX_EMERALDS    (DX+XX_EMERALDS)
-#define DY_EMERALDS    (DY+YY_EMERALDS)
-#define DX_DYNAMITE    (DX+XX_DYNAMITE)
-#define DY_DYNAMITE    (DY+YY_DYNAMITE)
-#define DX_KEYS                (DX+XX_KEYS)
-#define DY_KEYS                (DY+YY_KEYS)
-#define DX_SCORE       (DX+XX_SCORE)
-#define DY_SCORE       (DY+YY_SCORE)
-#define DX_TIME                (DX+XX_TIME)
-#define DY_TIME                (DY+YY_TIME)
+#define XX_LEVEL               37
+#define YY_LEVEL               20
+#define XX_EMERALDS            29
+#define YY_EMERALDS            54
+#define XX_DYNAMITE            29
+#define YY_DYNAMITE            89
+#define XX_KEYS                        18
+#define YY_KEYS                        123
+#define XX_SCORE               15
+#define YY_SCORE               159
+#define XX_TIME                        29
+#define YY_TIME                        194
+
+#define DX_LEVEL               (DX+XX_LEVEL)
+#define DY_LEVEL               (DY+YY_LEVEL)
+#define DX_EMERALDS            (DX+XX_EMERALDS)
+#define DY_EMERALDS            (DY+YY_EMERALDS)
+#define DX_DYNAMITE            (DX+XX_DYNAMITE)
+#define DY_DYNAMITE            (DY+YY_DYNAMITE)
+#define DX_KEYS                        (DX+XX_KEYS)
+#define DY_KEYS                        (DY+YY_KEYS)
+#define DX_SCORE               (DX+XX_SCORE)
+#define DY_SCORE               (DY+YY_SCORE)
+#define DX_TIME                        (DX+XX_TIME)
+#define DY_TIME                        (DY+YY_TIME)
 
 /* Felder in PIX_DOOR */
 /* Bedeutung in PIX_DB_DOOR: (3 PAGEs)
index a17b1da..61683e6 100644 (file)
@@ -41,31 +41,31 @@ long mainCounter(int mode)
   long counter_ms;
 
   gettimeofday(&current_time,NULL);
-  if (mode==0 || current_time.tv_sec<base_time.tv_sec)
+  if (mode == INIT_COUNTER || current_time.tv_sec < base_time.tv_sec)
     base_time = current_time;
 
   counter_ms = (current_time.tv_sec - base_time.tv_sec)*1000
              + (current_time.tv_usec - base_time.tv_usec)/1000;
 
-  if (mode==1)
+  if (mode == READ_COUNTER_100)
     return(counter_ms/10);     /* return 1/100 secs since last init */
-  else
+  else /*    READ_COUNTER_1000 */
     return(counter_ms);                /* return 1/1000 secs since last init */
 }
 
 void InitCounter() /* set counter back to zero */
 {
-  mainCounter(0);
+  mainCounter(INIT_COUNTER);
 }
 
 long Counter() /* returns 1/100 secs since last call of InitCounter() */
 {
-  return(mainCounter(1));
+  return(mainCounter(READ_COUNTER_100));
 }
 
 long Counter2()        /* returns 1/1000 secs since last call of InitCounter() */
 {
-  return(mainCounter(2));
+  return(mainCounter(READ_COUNTER_1000));
 }
 
 void WaitCounter(long value)   /* wait for counter to reach value */
@@ -93,7 +93,7 @@ BOOL DelayReached(long *counter_var, int delay)
 {
   long actual_counter = Counter();
 
-  if (actual_counter>*counter_var+delay || actual_counter<*counter_var)
+  if (actual_counter >= *counter_var+delay || actual_counter < *counter_var)
   {
     *counter_var = actual_counter;
     return(TRUE);
@@ -102,6 +102,20 @@ BOOL DelayReached(long *counter_var, int delay)
     return(FALSE);
 }
 
+BOOL FrameReached(long *frame_counter_var, int frame_delay)
+{
+  long actual_frame_counter = FrameCounter;
+
+  if (actual_frame_counter >= *frame_counter_var+frame_delay
+      || actual_frame_counter < *frame_counter_var)
+  {
+    *frame_counter_var = actual_frame_counter;
+    return(TRUE);
+  }
+  else
+    return(FALSE);
+}
+
 unsigned long be2long(unsigned long *be)       /* big-endian -> longword */
 {
   unsigned char *ptr = (unsigned char *)be;
@@ -117,6 +131,16 @@ char *int2str(int ct, int nr)
   return(&str[strlen(str)-nr]);
 }
 
+unsigned int SimpleRND(unsigned int max)
+{
+  static unsigned long root = 654321;
+  struct timeval current_time;
+
+  gettimeofday(&current_time,NULL);
+  root = root * 4253261 + current_time.tv_sec + current_time.tv_usec;
+  return(root % max);
+}
+
 unsigned int RND(unsigned int max)
 {
   return(rand() % max);
@@ -171,22 +195,57 @@ void HandleAnimation(int mode)
   static BOOL anim_restart = TRUE;
   static BOOL reset_delay = TRUE;
   static int toon_nr = 0;
+  int draw_mode;
 
+/*
   if (!toons_on || game_status==PLAYING)
     return;
+*/
+
+/*
+  if (!toons_on || tape.playing || tape.recording)
+    return;
+*/
+
+  if (!toons_on)
+    return;
 
   switch(mode)
   {
     case ANIM_START:
       anim_restart = TRUE;
       reset_delay = TRUE;
+
+      /* Fill empty backbuffer for animation functions */
+      if (direct_draw_on && game_status==PLAYING)
+      {
+       int xx,yy;
+
+       drawto_field = backbuffer;
+
+       for(xx=0;xx<SCR_FIELDX;xx++)
+         for(yy=0;yy<SCR_FIELDY;yy++)
+           DrawScreenField(xx,yy);
+       DrawLevelElement(JX,JY,EL_SPIELFIGUR);
+
+       drawto_field = window;
+      }
+
       return;
       break;
     case ANIM_CONTINUE:
       break;
     case ANIM_STOP:
       redraw_mask |= REDRAW_FIELD;
+
+      /* Redraw background even when in direct drawing mode */
+      draw_mode = direct_draw_on;
+      direct_draw_on = FALSE;
+
       BackToFront();
+
+      direct_draw_on = draw_mode;
+
       return;
       break;
     default:
@@ -196,7 +255,7 @@ void HandleAnimation(int mode)
   if (reset_delay)
   {
     animstart_delay = Counter();
-    animstart_delay_value = RND(500);
+    animstart_delay_value = SimpleRND(500);
     reset_delay = FALSE;
   }
 
@@ -205,7 +264,7 @@ void HandleAnimation(int mode)
     if (!DelayReached(&animstart_delay,animstart_delay_value))
       return;
 
-    toon_nr = RND(NUM_TOONS);
+    toon_nr = SimpleRND(NUM_TOONS);
   }
 
   anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart);
@@ -226,59 +285,59 @@ BOOL AnimateToon(int toon_nr, BOOL restart)
   static int dest_x, dest_y;
   static struct AnimInfo toon[NUM_TOONS] =
   {
-    DWARF_XSIZE, DWARF_YSIZE,
+   {DWARF_XSIZE, DWARF_YSIZE,
     DWARF_X, DWARF_Y,
     DWARF_FRAMES,
     DWARF_FPS,
     DWARF_STEPSIZE,
     FALSE,
     ANIMDIR_RIGHT,
-    ANIMPOS_DOWN,
+    ANIMPOS_DOWN},
 
-    DWARF_XSIZE, DWARF_YSIZE,
+   {DWARF_XSIZE, DWARF_YSIZE,
     DWARF_X, DWARF2_Y,
     DWARF_FRAMES,
     DWARF_FPS,
     DWARF_STEPSIZE,
     FALSE,
     ANIMDIR_LEFT,
-    ANIMPOS_DOWN,
+    ANIMPOS_DOWN},
 
-    JUMPER_XSIZE, JUMPER_YSIZE,
+   {JUMPER_XSIZE, JUMPER_YSIZE,
     JUMPER_X, JUMPER_Y,
     JUMPER_FRAMES,
     JUMPER_FPS,
     JUMPER_STEPSIZE,
     FALSE,
     ANIMDIR_LEFT,
-    ANIMPOS_DOWN,
+    ANIMPOS_DOWN},
 
-    CLOWN_XSIZE, CLOWN_YSIZE,
+   {CLOWN_XSIZE, CLOWN_YSIZE,
     CLOWN_X, CLOWN_Y,
     CLOWN_FRAMES,
     CLOWN_FPS,
     CLOWN_STEPSIZE,
     FALSE,
     ANIMDIR_UP,
-    ANIMPOS_ANY,
+    ANIMPOS_ANY},
 
-    BIRD_XSIZE, BIRD_YSIZE,
+   {BIRD_XSIZE, BIRD_YSIZE,
     BIRD1_X, BIRD1_Y,
     BIRD_FRAMES,
     BIRD_FPS,
     BIRD_STEPSIZE,
     TRUE,
     ANIMDIR_RIGHT,
-    ANIMPOS_UPPER,
+    ANIMPOS_UPPER},
 
-    BIRD_XSIZE, BIRD_YSIZE,
+   {BIRD_XSIZE, BIRD_YSIZE,
     BIRD2_X, BIRD2_Y,
     BIRD_FRAMES,
     BIRD_FPS,
     BIRD_STEPSIZE,
     TRUE,
     ANIMDIR_LEFT,
-    ANIMPOS_UPPER
+    ANIMPOS_UPPER}
   };
   struct AnimInfo *anim = &toon[toon_nr];
 
@@ -296,9 +355,9 @@ BOOL AnimateToon(int toon_nr, BOOL restart)
       else if (anim->position==ANIMPOS_DOWN)
        pos_y = FULL_SYSIZE-anim->height;
       else if (anim->position==ANIMPOS_UPPER)
-       pos_y = RND((FULL_SYSIZE-anim->height)/2);
+       pos_y = SimpleRND((FULL_SYSIZE-anim->height)/2);
       else
-       pos_y = RND(FULL_SYSIZE-anim->height);
+       pos_y = SimpleRND(FULL_SYSIZE-anim->height);
 
       if (anim->direction==ANIMDIR_RIGHT)
       {
@@ -319,7 +378,7 @@ BOOL AnimateToon(int toon_nr, BOOL restart)
       else if (anim->position==ANIMPOS_RIGHT)
        pos_x = FULL_SXSIZE-anim->width;
       else
-       pos_x = RND(FULL_SXSIZE-anim->width);
+       pos_x = SimpleRND(FULL_SXSIZE-anim->width);
 
       if (anim->direction==ANIMDIR_DOWN)
       {
index dba3801..685c2b8 100644 (file)
@@ -80,7 +80,11 @@ struct AnimInfo
   int position;
 };
 
-#define NEW_RANDOMIZE  -1
+#define INIT_COUNTER           0
+#define READ_COUNTER_100       1
+#define READ_COUNTER_1000      2
+
+#define NEW_RANDOMIZE          -1
 
 void microsleep(unsigned long);
 long mainCounter(int);
@@ -91,8 +95,10 @@ void WaitCounter(long);
 void WaitCounter2(long);
 void Delay(long);
 BOOL DelayReached(long *, int);
+BOOL FrameReached(long *, int);
 unsigned long be2long(unsigned long *);
 char *int2str(int, int);
+unsigned int SimpleRND(unsigned int);
 unsigned int RND(unsigned int);
 unsigned int InitRND(long);
 char *GetLoginName(void);
index f26a200..3a8f0bb 100644 (file)
 #include "misc.h"
 #include "files.h"
 #include "buttons.h"
+#include "tape.h"
+
+void DrawHeadline()
+{
+  int x1 = SX+(SXSIZE - strlen(GAMETITLE_STRING) * FONT1_XSIZE) / 2;
+  int y1 = SY+8;
+  int x2 = SX+(SXSIZE - strlen(COPYRIGHT_STRING) * FONT2_XSIZE) / 2;
+  int y2 = SY+46;
+
+  DrawText(x1,y1, GAMETITLE_STRING, FS_BIG,FC_YELLOW);
+  DrawText(x2,y2, COPYRIGHT_STRING, FS_SMALL,FC_RED);
+}
 
 void DrawMainMenu()
 {
@@ -31,14 +43,12 @@ void DrawMainMenu()
   LoadLevel(level_nr);
 
   ClearWindow();
-  DrawText(SX+16, SY+8,  "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
-  DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
-          FS_SMALL,FC_RED);
+  DrawHeadline();
   DrawText(SX+32, SY+64, "Name:",FS_BIG,FC_GREEN);
   DrawText(SX+192,SY+64, player.alias_name,FS_BIG,FC_RED);
   DrawText(SX+32, SY+96, "Level:",FS_BIG,FC_GREEN);
   DrawText(SX+352,SY+96, int2str(level_nr,3),FS_BIG,
-          (level_nr<leveldir[leveldir_nr].num_ready ? FC_RED : FC_YELLOW));
+          (level_nr<leveldir[leveldir_nr].levels ? FC_RED : FC_YELLOW));
   DrawText(SX+32, SY+128,"Hall Of Fame",FS_BIG,FC_GREEN);
   DrawText(SX+32, SY+160,"Level Creator",FS_BIG,FC_GREEN);
   DrawText(SY+32, SY+192,"Info Screen",FS_BIG,FC_GREEN);
@@ -50,8 +60,8 @@ void DrawMainMenu()
 
   for(i=2;i<10;i++)
     DrawGraphic(0,i,GFX_KUGEL_BLAU);
-  DrawGraphic(10,3,GFX_KUGEL_BLAU);
-  DrawGraphic(14,3,GFX_KUGEL_BLAU);
+  DrawGraphic(10,3,GFX_PFEIL_L);
+  DrawGraphic(14,3,GFX_PFEIL_R);
 
   DrawText(SX+54+16,SY+326,"A Game by Artsoft Development",FS_SMALL,FC_BLUE);
   DrawText(SX+40+16,SY+344,"Graphics: Deluxe Paint IV Amiga",
@@ -79,7 +89,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
   static int redraw = TRUE;
   int x = (mx+32-SX)/32, y = (my+32-SY)/32;
 
-  if (redraw)
+  if (redraw || (!mx && !my && !dx && !dy))
   {
     DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
     redraw = FALSE;
@@ -113,7 +123,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
   }
 
   if (y==4 && ((x==11 && level_nr>0) ||
-              (x==15 && level_nr<LEVELDIR_SIZE(leveldir[leveldir_nr]))) &&
+              (x==15 && level_nr<leveldir[leveldir_nr].levels)) &&
       button)
   {
     static long level_delay = 0;
@@ -123,26 +133,19 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
     new_level_nr = level_nr + (x==11 ? -step : +step);
     if (new_level_nr<0)
       new_level_nr = 0;
-    if (new_level_nr>LEVELDIR_SIZE(leveldir[leveldir_nr])-1)
-      new_level_nr = LEVELDIR_SIZE(leveldir[leveldir_nr])-1;
+    if (new_level_nr>leveldir[leveldir_nr].levels-1)
+      new_level_nr = leveldir[leveldir_nr].levels-1;
 
-    if (old_level_nr==new_level_nr || !DelayReached(&level_delay,20))
+    if (old_level_nr==new_level_nr || !DelayReached(&level_delay,15))
       goto out;
 
     level_nr = new_level_nr;
 
-    if (level_nr>player.handicap && level_nr<leveldir[leveldir_nr].num_ready)
-    {
-      if (x==11 || leveldir[leveldir_nr].num_free==0)
-       level_nr = player.handicap;
-      else
-       level_nr = leveldir[leveldir_nr].num_ready;
-    }
+    if (level_nr>player.handicap)
+      level_nr = player.handicap;
 
-    DrawTextExt(drawto,gc,SX+352,SY+96, int2str(level_nr,3),FS_BIG,
-               (level_nr<leveldir[leveldir_nr].num_ready ?FC_RED :FC_YELLOW));
-    DrawTextExt(window,gc,SX+352,SY+96,        int2str(level_nr,3),FS_BIG,
-               (level_nr<leveldir[leveldir_nr].num_ready ?FC_RED :FC_YELLOW));
+    DrawTextExt(drawto,gc,SX+352,SY+96, int2str(level_nr,3), FS_BIG,FC_RED);
+    DrawTextExt(window,gc,SX+352,SY+96,        int2str(level_nr,3), FS_BIG,FC_RED);
 
     LoadLevel(level_nr);
     DrawMicroLevel(MICROLEV_XPOS,MICROLEV_YPOS);
@@ -150,6 +153,11 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
     TapeErase();
     LoadLevelTape(level_nr);
     DrawCompleteVideoDisplay();
+
+    /* needed because DrawMicroLevel() takes some time */
+    BackToFront();
+    XSync(display,FALSE);
+    DelayReached(&level_delay,0);      /* reset delay counter */
   }
   else if (x==1 && y>=3 && y<=10)
   {
@@ -174,48 +182,48 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button)
        if (num_leveldirs)
        {
          game_status = CHOOSELEVEL;
+         SavePlayerInfo(PLAYER_LEVEL);
          DrawChooseLevel();
-         redraw = TRUE;
        }
       }
       else if (y==5)
       {
        game_status = HALLOFFAME;
        DrawHallOfFame(-1);
-       redraw = TRUE;
       }
       else if (y==6)
       {
        game_status = LEVELED;
+       if (leveldir[leveldir_nr].readonly)
+         AreYouSure("This level is read only !",AYS_CONFIRM);
        DrawLevelEd();
-       redraw = TRUE;
       }
       else if (y==7)
       {
        game_status = HELPSCREEN;
        DrawHelpScreen();
-       redraw = TRUE;
       }
       else if (y==8)
       {
-       if (autorecord_on && !tape.playing)
-         TapeInitRecording();
+       if (autorecord_on)
+         TapeStartRecording();
 
        game_status = PLAYING;
        InitGame();
-       redraw = TRUE;
       }
       else if (y==9)
       {
        game_status = SETUP;
        DrawSetupScreen();
-       redraw = TRUE;
       }
       else if (y==10)
       {
+       SavePlayerInfo(PLAYER_LEVEL);
         if (AreYouSure("Do you really want to quit ?",AYS_ASK|AYS_STAY_CLOSED))
          game_status = EXITGAME;
       }
+
+      redraw = TRUE;
     }
   }
   BackToFront();
@@ -249,22 +257,29 @@ static int helpscreen_action[] =
   GFX_CHAR_A,30,3, GFX_CHAR_AUSRUF,32,3,                       HA_NEXT,
   GFX_EDELSTEIN,2,5,                                           HA_NEXT,
   GFX_DIAMANT,2,5,                                             HA_NEXT,
-  GFX_EDELSTEIN2,2,5,                                          HA_NEXT,
-  GFX_EDELSTEIN3,2,5,                                          HA_NEXT,
+  GFX_EDELSTEIN_BD,2,5,                                                HA_NEXT,
+  GFX_EDELSTEIN_GELB,2,5, GFX_EDELSTEIN_ROT,2,5,
+  GFX_EDELSTEIN_LILA,2,5,                                      HA_NEXT,
   GFX_FELSBROCKEN,4,5,                                         HA_NEXT,
   GFX_BOMBE,1,50, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10,                HA_NEXT,
   GFX_KOKOSNUSS,1,50, GFX_CRACKINGNUT,3,1, GFX_EDELSTEIN,1,10, HA_NEXT,
   GFX_ERZ_EDEL,1,50, GFX_EXPLOSION,8,1, GFX_EDELSTEIN,1,10,    HA_NEXT,
   GFX_ERZ_DIAM,1,50, GFX_EXPLOSION,8,1, GFX_DIAMANT,1,10,      HA_NEXT,
-  GFX_ERZ_EDEL2,1,50, GFX_EXPLOSION,8,1, GFX_EDELSTEIN2,1,10,  HA_NEXT,
-  GFX_ERZ_EDEL3,1,50, GFX_EXPLOSION,8,1, GFX_EDELSTEIN3,1,10,  HA_NEXT,
+  GFX_ERZ_EDEL_BD,1,50, GFX_EXPLOSION,8,1,GFX_EDELSTEIN_BD,1,10,HA_NEXT,
+  GFX_ERZ_EDEL_GELB,1,50, GFX_EXPLOSION,8,1,
+  GFX_EDELSTEIN_GELB,1,10, GFX_ERZ_EDEL_ROT,1,50,
+  GFX_EXPLOSION,8,1, GFX_EDELSTEIN_ROT,1,10,
+  GFX_ERZ_EDEL_LILA,1,50, GFX_EXPLOSION,8,1,
+  GFX_EDELSTEIN_LILA,1,10,                                     HA_NEXT,
   GFX_GEBLUBBER,4,4,                                           HA_NEXT,
   GFX_SCHLUESSEL1,4,33,                                                HA_NEXT,
   GFX_PFORTE1,4,33,                                            HA_NEXT,
   GFX_PFORTE1X,4,33,                                           HA_NEXT,
   GFX_DYNAMIT_AUS,1,100,                                       HA_NEXT,
   GFX_DYNAMIT,7,6, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10,       HA_NEXT,
-  GFX_DYNABOMB,1,33, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10,     HA_NEXT,
+  GFX_DYNABOMB+0,4,3, GFX_DYNABOMB+3,1,3, GFX_DYNABOMB+2,1,3,
+  GFX_DYNABOMB+1,1,3, GFX_DYNABOMB+0,1,3, GFX_EXPLOSION,8,1,
+  GFX_LEERRAUM,1,10,                                           HA_NEXT,
   GFX_DYNABOMB_NR,1,100,                                       HA_NEXT,
   GFX_DYNABOMB_SZ,1,100,                                       HA_NEXT,
   GFX_FLIEGER+4,1,3, GFX_FLIEGER+0,1,3, GFX_FLIEGER+4,1,3,
@@ -275,16 +290,18 @@ static int helpscreen_action[] =
   GFX_KAEFER+5,1,1, GFX_KAEFER+1,1,1, GFX_KAEFER+5,1,1,
   GFX_KAEFER+6,1,1, GFX_KAEFER+2,1,1, GFX_KAEFER+6,1,1,
   GFX_KAEFER+7,1,1, GFX_KAEFER+3,1,1, GFX_KAEFER+7,1,1,                HA_NEXT,
+  GFX_BUTTERFLY,1,1, GFX_BUTTERFLY+1,1,1,                      HA_NEXT,
+  GFX_FIREFLY,1,1, GFX_FIREFLY+1,1,1,                          HA_NEXT,
   GFX_PACMAN+0,1,3, GFX_PACMAN+4,1,2, GFX_PACMAN+0,1,3,
   GFX_PACMAN+1,1,3, GFX_PACMAN+5,1,2, GFX_PACMAN+1,1,3,
   GFX_PACMAN+2,1,3, GFX_PACMAN+6,1,2, GFX_PACMAN+2,1,3,
   GFX_PACMAN+3,1,3, GFX_PACMAN+7,1,2, GFX_PACMAN+3,1,3,                HA_NEXT,
   GFX_MAMPFER+0,4,0, GFX_MAMPFER+3,1,0, GFX_MAMPFER+2,1,0,
-  GFX_MAMPFER+1,1,0,                                           HA_NEXT,
+  GFX_MAMPFER+1,1,0, GFX_MAMPFER+0,1,0,                                HA_NEXT,
   GFX_MAMPFER2+0,4,0, GFX_MAMPFER2+3,1,0, GFX_MAMPFER2+2,1,0,
-  GFX_MAMPFER2+1,1,0,                                          HA_NEXT,
+  GFX_MAMPFER2+1,1,0, GFX_MAMPFER2+0,1,0,                      HA_NEXT,
   GFX_ZOMBIE+0,4,0, GFX_ZOMBIE+3,1,0, GFX_ZOMBIE+2,1,0,
-  GFX_ZOMBIE+1,1,0,                                            HA_NEXT,
+  GFX_ZOMBIE+1,1,0, GFX_ZOMBIE+0,1,0,                          HA_NEXT,
   GFX_ABLENK,4,1,                                              HA_NEXT,
   GFX_BIRNE_AUS,1,33, GFX_BIRNE_EIN,1,33,                      HA_NEXT,
   GFX_ZEIT_VOLL,1,33, GFX_ZEIT_LEER,1,33,                      HA_NEXT,
@@ -307,68 +324,70 @@ static int helpscreen_action[] =
 };
 static char *helpscreen_eltext[][2] =
 {
-  "THE HERO:",                         "(Is _this_ guy good old Rockford?)",
-  "Normal sand:",                      "You can dig through it",
-  "Empty field:",                      "You can walk through it",
-  "Quicksand: You cannot pass it,",    "but rocks can fall though it",
-  "Massive Wall:",                     "Nothing can go through it",
-  "Normal Wall: You can't go through", "it, but you can bomb it away",
-  "Growing Wall: Grows to the left or",        "right if there is an empty field",
-  "Invisible Wall: Behaves like normal","wall, but is invisible",
-  "Old Wall: Like normal wall, but",   "some things can fall down from it",
-  "Letter Wall: Looks like a letter,", "behaves like a normal wall",
-  "Emerald: You must collect enough of","them to finish a level",
-  "Diamond: Counts as 3 emeralds, but",        "can be destroyed by rocks",
-  "Diamond (BD style): Counts like one","emerald and behaves a bit different",
-  "Red emerald: Seems to behave like", "the BD style diamond",
-  "Rock: Smashes several things;",     "Can be moved by the player",
-  "Bomb: You can move it, but be",     "careful when dropping it",
-  "Nut: Throw a rock on it to open it;","Each nut contains an emerald",
-  "Wall with an emerald inside:",      "Bomb the wall away to get it",
-  "Wall with a diamond inside:",       "Bomb the wall away to get it",
-  "Wall with BD style diamond inside:",        "Bomb the wall away to get it",
-  "Wall with red emerald inside:",     "Bomb the wall away to get it",
-  "Acid: Things that fall in are gone",        "forever (including our hero)",
-  "Key: Opens the door that has the",  "same color (red/yellow/green/blue)",
-  "Door: Can be opened by the key",    "with the same color",
-  "Door: You have to find out the",    "right color of the key for it",
-  "Dynamite: Collect it and use it to",        "destroy walls or kill enemies",
-  "Dynamite: This one explodes after", "a few seconds",
-  "Dyna Bomb: Explodes in 4 directions","with variable explosion size",
-  "Dyna Bomb: Increases the number of",        "dyna bombs available at a time",
-  "Dyna Bomb: Increases the size of",  "explosion of dyna bombs",
-  "Spaceship: Moves at the left side", "of walls; don't touch it!",
-  "Bug: Moves at the right side of",   "walls; don't touch it!",
-  "Pacman: Eats the amoeba and you,",  "if you're not careful",
-  "Cruncher: Eats diamonds and you,",  "if you're not careful",
-  "Cruncher (BD style):",              "Eats almost everything",
-  "Robot: Tries to kill the player",   "",
-  "Magic Wheel: Touch it to get rid of","the robots for some seconds",
-  "Light Bulb: It seems to have no",   "special function, but looks nice",
-  "Extra Time Orb: Adds some seconds", "to the time available for the level",
-  "Amoeba Drop: Grows to an amoeba on",        "the ground - don't touch it",
-  "Dead Amoeba: Does not grow, but",   "can still kill bugs and spaceships",
-  "Normal Amoeba: Grows through empty",        "fields, sand and quicksand",
-  "Dropping Amoeba: This one makes",   "drops that grow to a new amoeba",
-  "Living Amoeba (BD style): Contains",        "other element, when surrounded",
-  "Game Of Life: Behaves like the well","known 'Game Of Life' (2333 style)",
-  "Biomaze: A bit like the 'Game Of",  "Life', but builds crazy mazes",
-  "Magic Wall: Changes rocks, emeralds","and diamonds when they pass it",
-  "Magic Wall (BD style):",            "Changes rocks and BD style diamonds",
-  "Exit door: Opens if you have enough","emeralds to finish the level",
-  "Open exit door: Enter here to leave","the level and exit the actual game",
+ {"THE HERO:",                         "(Is _this_ guy good old Rockford?)"},
+ {"Normal sand:",                      "You can dig through it"},
+ {"Empty field:",                      "You can walk through it"},
+ {"Quicksand: You cannot pass it,",    "but rocks can fall though it"},
+ {"Massive Wall:",                     "Nothing can go through it"},
+ {"Normal Wall: You can't go through", "it, but you can bomb it away"},
+ {"Growing Wall: Grows to the left or",        "right if there is an empty field"},
+ {"Invisible Wall: Behaves like normal","wall, but is invisible"},
+ {"Old Wall: Like normal wall, but",   "some things can fall down from it"},
+ {"Letter Wall: Looks like a letter,", "behaves like a normal wall"},
+ {"Emerald: You must collect enough of","them to finish a level"},
+ {"Diamond: Counts as 3 emeralds, but",        "can be destroyed by rocks"},
+ {"Diamond (BD style): Counts like one","emerald and behaves a bit different"},
+ {"Colorful Gems:",                    "Seem to behave like Emeralds"},
+ {"Rock: Smashes several things;",     "Can be moved by the player"},
+ {"Bomb: You can move it, but be",     "careful when dropping it"},
+ {"Nut: Throw a rock on it to open it;","Each nut contains an emerald"},
+ {"Wall with an emerald inside:",      "Bomb the wall away to get it"},
+ {"Wall with a diamond inside:",       "Bomb the wall away to get it"},
+ {"Wall with BD style diamond inside:",        "Bomb the wall away to get it"},
+ {"Wall with colorful gem inside:",    "Bomb the wall away to get it"},
+ {"Acid: Things that fall in are gone",        "forever (including our hero)"},
+ {"Key: Opens the door that has the",  "same color (red/yellow/green/blue)"},
+ {"Door: Can be opened by the key",    "with the same color"},
+ {"Door: You have to find out the",    "right color of the key for it"},
+ {"Dynamite: Collect it and use it to",        "destroy walls or kill enemies"},
+ {"Dynamite: This one explodes after", "a few seconds"},
+ {"Dyna Bomb: Explodes in 4 directions","with variable explosion size"},
+ {"Dyna Bomb: Increases the number of",        "dyna bombs available at a time"},
+ {"Dyna Bomb: Increases the size of",  "explosion of dyna bombs"},
+ {"Spaceship: Moves at the left side", "of walls; don't touch it!"},
+ {"Bug: Moves at the right side",      "of walls; don't touch it!"},
+ {"Butterfly: Moves at the right side",        "of walls; don't touch it!"},
+ {"Firefly: Moves at the left side",   "of walls; don't touch it!"},
+ {"Pacman: Eats the amoeba and you,",  "if you're not careful"},
+ {"Cruncher: Eats diamonds and you,",  "if you're not careful"},
+ {"Cruncher (BD style):",              "Eats almost everything"},
+ {"Robot: Tries to kill the player",   ""},
+ {"Magic Wheel: Touch it to get rid of","the robots for some seconds"},
+ {"Light Bulb: All of them must be",   "switched on to finish a level"},
+ {"Extra Time Orb: Adds some seconds", "to the time available for the level"},
+ {"Amoeba Drop: Grows to an amoeba on",        "the ground - don't touch it"},
+ {"Dead Amoeba: Does not grow, but",   "can still kill bugs and spaceships"},
+ {"Normal Amoeba: Grows through empty",        "fields, sand and quicksand"},
+ {"Dropping Amoeba: This one makes",   "drops that grow to a new amoeba"},
+ {"Living Amoeba (BD style): Contains",        "other element, when surrounded"},
+ {"Game Of Life: Behaves like the well","known 'Game Of Life' (2333 style)"},
+ {"Biomaze: A bit like the 'Game Of",  "Life', but builds crazy mazes"},
+ {"Magic Wall: Changes rocks, emeralds","and diamonds when they pass it"},
+ {"Magic Wall (BD style):",            "Changes rocks and BD style diamonds"},
+ {"Exit door: Opens if you have enough","emeralds to finish the level"},
+ {"Open exit door: Enter here to leave","the level and exit the actual game"},
 };
 static int num_helpscreen_els = sizeof(helpscreen_eltext)/(2*sizeof(char *));
 
 static char *helpscreen_music[][3] =
 {
-  "Alchemy",                   "Ian Boddy",            "Drive",
-  "The Chase",                 "Propaganda",           "A Secret Wish",
-  "Network 23",                        "Tangerine Dream",      "Exit",
-  "Czardasz",                  "Robert Pieculewicz",   "Czardasz",
-  "21st Century Common Man",   "Tangerine Dream",      "Tyger",
-  "Voyager",                   "The Alan Parsons Project","Pyramid",
-  "Twilight Painter",          "Tangerine Dream",      "Heartbreakers"
+  { "Alchemy",                 "Ian Boddy",            "Drive" },
+  { "The Chase",               "Propaganda",           "A Secret Wish" },
+  { "Network 23",              "Tangerine Dream",      "Exit" },
+  { "Czardasz",                        "Robert Pieculewicz",   "Czardasz" },
+  { "21st Century Common Man", "Tangerine Dream",      "Tyger" },
+  { "Voyager",                 "The Alan Parsons Project","Pyramid" },
+  { "Twilight Painter",                "Tangerine Dream",      "Heartbreakers" }
 };
 static int helpscreen_musicpos;
 
@@ -443,9 +462,7 @@ void DrawHelpScreenElText(int start)
   char text[FULL_SXSIZE/FONT2_XSIZE+10];
 
   ClearWindow();
-  DrawText(SX+16, SY+8,  "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
-  DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
-          FS_SMALL,FC_RED);
+  DrawHeadline();
 
   sprintf(text,"The game elements:");
   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
@@ -471,9 +488,7 @@ void DrawHelpScreenMusicText(int num)
 
   FadeSounds();
   ClearWindow();
-  DrawText(SX+16, SY+8,  "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
-  DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
-          FS_SMALL,FC_RED);
+  DrawHeadline();
 
   sprintf(text,"The game background music loops:");
   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
@@ -512,9 +527,7 @@ void DrawHelpScreenCreditsText()
 
   FadeSounds();
   ClearWindow();
-  DrawText(SX+16, SY+8,  "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
-  DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
-          FS_SMALL,FC_RED);
+  DrawHeadline();
 
   sprintf(text,"Program information:");
   DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
@@ -631,7 +644,7 @@ void CheckCheat()
   int old_handicap = player.handicap;
 
   if (!strcmp(player.alias_name,"Artsoft"))
-    player.handicap = MAX(0,leveldir[leveldir_nr].num_ready-1);
+    player.handicap = leveldir[leveldir_nr].levels-1;
 
   if (player.handicap != old_handicap)
   {
@@ -671,8 +684,8 @@ void HandleTypeName(int newxpos, KeySym key)
   }
   else if (key==XK_Delete && xpos>0)
   {
-    player.alias_name[xpos] = 0;
     xpos--;
+    player.alias_name[xpos] = 0;
     DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
     DrawGraphic(xpos+7,ypos,GFX_LEERRAUM);
   }
@@ -684,7 +697,10 @@ void HandleTypeName(int newxpos, KeySym key)
     CheckCheat();
 
     game_status = MAINMENU;
+/*
     DrawMainMenu();
+*/
+
   }
   BackToFront();
 }
@@ -760,6 +776,9 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
       SavePlayerInfo(PLAYER_SETUP);
       CheckCheat();
 
+      TapeErase();
+      LoadLevelTape(level_nr);
+
       game_status = MAINMENU;
       DrawMainMenu();
       redraw = TRUE;
@@ -818,73 +837,51 @@ void HandleHallOfFame(int button)
 void DrawSetupScreen()
 {
   int i;
+  static struct setup
+  {
+    unsigned int bit;
+    char *text, *mode[2];
+    int color[2];
+  } setup[] =
+  {
+    {SETUP_SOUND,      "Sound:",       {"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_SOUND_LOOPS,        " Sound Loops:",{"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_SOUND_MUSIC,        " Game Music:", {"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_TOONS,      "Toons:",       {"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_DIRECT_DRAW,        "Buffered gfx:",{"off","on" },  {FC_BLUE,FC_YELLOW}},
+    {SETUP_SCROLL_DELAY,"Scroll Delay:",{"on", "off"}, {FC_YELLOW,FC_BLUE}},
+    {SETUP_FADING,     "Fading:",      {"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_QUICK_DOORS,        "Quick Doors:", {"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_AUTO_RECORD,        "Auto-Record:", {"on", "off"},  {FC_YELLOW,FC_BLUE}},
+    {SETUP_2ND_JOYSTICK,"Joystick:",   {"2nd","1st"},  {FC_YELLOW,FC_YELLOW}},
+    {0,                        "Cal. Joystick",{"",   ""},     {0,0}},
+    {0,                        "",             {"",   ""},     {0,0}},
+    {0,                        "Exit",         {"",   ""},     {0,0}},
+    {0,                        "Save and exit",{"",   ""},     {0,0}}
+  };
 
   CloseDoor(DOOR_CLOSE_2);
-
   ClearWindow();
   DrawText(SX+16, SY+16,  "SETUP",FS_BIG,FC_YELLOW);
-  DrawText(SX+32, SY+2*32,"Sound:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+3*32,"Sound loops:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+4*32,"Game music:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+5*32,"Toons:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+6*32,"Buffered gfx:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+7*32,"Fading:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+8*32,"Quick Doors:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+9*32,"Auto-Record:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+10*32,"Joystick:",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+11*32,"Cal. Joystick",FS_BIG,FC_GREEN);
-
-  DrawText(SX+32, SY+13*32,"Exit",FS_BIG,FC_GREEN);
-  DrawText(SX+32, SY+14*32,"Save and exit",FS_BIG,FC_GREEN);
-
-  if (SETUP_SOUND_ON(player.setup))
-    DrawText(SX+14*32, SY+2*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+2*32,"off",FS_BIG,FC_BLUE);
-
-  if (SETUP_SOUND_LOOPS_ON(player.setup))
-    DrawText(SX+14*32, SY+3*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+3*32,"off",FS_BIG,FC_BLUE);
-
-  if (SETUP_SOUND_MUSIC_ON(player.setup))
-    DrawText(SX+14*32, SY+4*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+4*32,"off",FS_BIG,FC_BLUE);
 
-  if (SETUP_TOONS_ON(player.setup))
-    DrawText(SX+14*32, SY+5*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+5*32,"off",FS_BIG,FC_BLUE);
-
-  if (!SETUP_DIRECT_DRAW_ON(player.setup))
-    DrawText(SX+14*32, SY+6*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+6*32,"off",FS_BIG,FC_BLUE);
-
-  if (SETUP_FADING_ON(player.setup))
-    DrawText(SX+14*32, SY+7*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+7*32,"off",FS_BIG,FC_BLUE);
-
-  if (SETUP_QUICK_DOORS_ON(player.setup))
-    DrawText(SX+14*32, SY+8*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+8*32,"off",FS_BIG,FC_BLUE);
-
-  if (SETUP_RECORD_EACH_GAME_ON(player.setup))
-    DrawText(SX+14*32, SY+9*32,"on",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+9*32,"off",FS_BIG,FC_BLUE);
-
-  if (SETUP_2ND_JOYSTICK_ON(player.setup))
-    DrawText(SX+14*32, SY+10*32,"2nd",FS_BIG,FC_YELLOW);
-  else
-    DrawText(SX+14*32, SY+10*32,"1st",FS_BIG,FC_YELLOW);
+  for(i=SETUP_SCREEN_POS_START;i<=SETUP_SCREEN_POS_END;i++)
+  {
+    int base = i - SETUP_SCREEN_POS_START;
 
-  for(i=2;i<15;i++)
-    if (i!=12)
+    if (i != SETUP_SCREEN_POS_EMPTY)
+    {
       DrawGraphic(0,i,GFX_KUGEL_BLAU);
+      DrawText(SX+32,SY+i*32, setup[base].text, FS_BIG,FC_GREEN);
+    }
+
+    if (i < SETUP_SCREEN_POS_EMPTY)
+    {
+      int setting_bit = setup[base].bit;
+      int setting_pos = ((player.setup & setting_bit) != 0 ? 0 : 1);
+      DrawText(SX+14*32, SY+i*32,setup[base].mode[setting_pos],
+              FS_BIG,setup[base].color[setting_pos]);
+    }
+  }
 
   FadeToFront();
   InitAnimation();
@@ -896,6 +893,9 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
   static int choice = 3;
   static int redraw = TRUE;
   int x = (mx+32-SX)/32, y = (my+32-SY)/32;
+  int pos_start = SETUP_SCREEN_POS_START + 1;
+  int pos_empty = SETUP_SCREEN_POS_EMPTY + 1;
+  int pos_end   = SETUP_SCREEN_POS_END   + 1;
 
   if (redraw)
   {
@@ -913,13 +913,13 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     else
       x = y = 0;
 
-    if (y==13)
-      y = (dy>0 ? 14 : 12);
+    if (y == pos_empty)
+      y = (dy>0 ? pos_empty+1 : pos_empty-1);
 
-    if (y<3)
-      y = 3;
-    else if (y>15)
-      y = 15;
+    if (y < pos_start)
+      y = pos_start;
+    else if (y > pos_end)
+      y = pos_end;
   }
 
   if (!mx && !my && !dx && !dy)
@@ -928,7 +928,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
     y = choice;
   }
 
-  if (x==1 && y>=3 && y<=15 && y!=13)
+  if (x==1 && y>=pos_start && y<=pos_end && y!=pos_empty)
   {
     if (button)
     {
@@ -946,7 +946,13 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
       if (y==3 && sound_status==SOUND_AVAILABLE)
       {
        if (SETUP_SOUND_ON(player.setup))
+       {
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+         DrawText(SX+14*32, SY+(yy+1)*32,"off",FS_BIG,FC_BLUE);
+         DrawText(SX+14*32, SY+(yy+2)*32,"off",FS_BIG,FC_BLUE);
+         player.setup &= ~SETUP_SOUND_LOOPS;
+         player.setup &= ~SETUP_SOUND_MUSIC;
+       }
        else
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        player.setup ^= SETUP_SOUND;
@@ -956,7 +962,11 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        if (SETUP_SOUND_LOOPS_ON(player.setup))
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
        else
+       {
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+         DrawText(SX+14*32, SY+(yy-1)*32,"on ",FS_BIG,FC_YELLOW);
+         player.setup |= SETUP_SOUND;
+       }
        player.setup ^= SETUP_SOUND_LOOPS;
       }
       else if (y==5 && sound_loops_allowed)
@@ -964,7 +974,11 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        if (SETUP_SOUND_MUSIC_ON(player.setup))
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
        else
+       {
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+         DrawText(SX+14*32, SY+(yy-2)*32,"on ",FS_BIG,FC_YELLOW);
+         player.setup |= SETUP_SOUND;
+       }
        player.setup ^= SETUP_SOUND_MUSIC;
       }
       else if (y==6)
@@ -984,6 +998,14 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
        player.setup ^= SETUP_DIRECT_DRAW;
       }
       else if (y==8)
+      {
+       if (SETUP_SCROLL_DELAY_ON(player.setup))
+         DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+       else
+         DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+       player.setup ^= SETUP_SCROLL_DELAY;
+      }
+      else if (y==9)
       {
        if (SETUP_FADING_ON(player.setup))
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -991,7 +1013,7 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        player.setup ^= SETUP_FADING;
       }
-      else if (y==9)
+      else if (y==10)
       {
        if (SETUP_QUICK_DOORS_ON(player.setup))
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
@@ -999,15 +1021,15 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
        player.setup ^= SETUP_QUICK_DOORS;
       }
-      else if (y==10)
+      else if (y==11)
       {
-       if (SETUP_RECORD_EACH_GAME_ON(player.setup))
+       if (SETUP_AUTO_RECORD_ON(player.setup))
          DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
        else
          DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
-       player.setup ^= SETUP_RECORD_EACH_GAME;
+       player.setup ^= SETUP_AUTO_RECORD;
       }
-      else if (y==11)
+      else if (y==12)
       {
        if (SETUP_2ND_JOYSTICK_ON(player.setup))
          DrawText(SX+14*32, SY+yy*32,"1st",FS_BIG,FC_YELLOW);
@@ -1015,14 +1037,14 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
          DrawText(SX+14*32, SY+yy*32,"2nd",FS_BIG,FC_YELLOW);
        player.setup ^= SETUP_2ND_JOYSTICK;
       }
-      else if (y==12)
+      else if (y==13)
       {
        CalibrateJoystick();
        redraw = TRUE;
       }
-      else if (y==14 || y==15)
+      else if (y==pos_end-1 || y==pos_end)
       {
-        if (y==15)
+        if (y==pos_end)
        {
          SavePlayerInfo(PLAYER_SETUP);
          SaveJoystickData();
@@ -1167,19 +1189,41 @@ void CalibrateJoystick()
   DrawSetupScreen();
 }
 
+void HandleGameActions()
+{
+  if (game_status != PLAYING)
+    return;
+
+  if (LevelSolved)
+    GameWon();
+
+  if (GameOver && !TAPE_IS_STOPPED(tape))
+    TapeStop();
+
+  GameActions();
+}
+
 void HandleVideoButtons(int mx, int my, int button)
 {
-  if (game_status!=MAINMENU && game_status!=PLAYING)
+  if (game_status != MAINMENU && game_status != PLAYING)
     return;
 
   switch(CheckVideoButtons(mx,my,button))
   {
     case BUTTON_VIDEO_EJECT:
       TapeStop();
-      if (!TAPE_IS_EMPTY(tape))
-       SaveLevelTape(tape.level_nr);
+      if (TAPE_IS_EMPTY(tape))
+      {
+       LoadLevelTape(level_nr);
+       if (TAPE_IS_EMPTY(tape))
+         AreYouSure("No tape for this level !",AYS_CONFIRM);
+      }
       else
-       AreYouSure("Tape is empty !",AYS_CONFIRM);
+      {
+       if (tape.changed)
+         SaveLevelTape(tape.level_nr);
+       TapeErase();
+      }
       DrawCompleteVideoDisplay();
       break;
     case BUTTON_VIDEO_STOP:
@@ -1189,25 +1233,68 @@ void HandleVideoButtons(int mx, int my, int button)
       TapeTogglePause();
       break;
     case BUTTON_VIDEO_REC:
-      if (tape.pausing)
-       TapeTogglePause();
-      else if (game_status==MAINMENU)
-       TapeInitRecording();
+      if (TAPE_IS_STOPPED(tape))
+      {
+       TapeStartRecording();
+       game_status = PLAYING;
+       InitGame();
+      }
+      else if (tape.pausing)
+      {
+       if (tape.playing)       /* PLAYING -> PAUSING -> RECORDING */
+       {
+         tape.pos[tape.counter].delay = tape.delay_played;
+         tape.playing = FALSE;
+         tape.recording = TRUE;
+
+         DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON,0);
+       }
+       else
+         TapeTogglePause();
+      }
       break;
     case BUTTON_VIDEO_PLAY:
-      if (tape.pausing)
-       TapeTogglePause();
-      else if (game_status==MAINMENU)
-       TapeInitPlaying();
+      if (TAPE_IS_EMPTY(tape))
+       break;
+
+      if (TAPE_IS_STOPPED(tape))
+      {
+       TapeStartPlaying();
+       game_status = PLAYING;
+       InitGame();
+      }
+      else if (tape.playing)
+      {
+       if (tape.pausing)                       /* PAUSE -> PLAY */
+         TapeTogglePause();
+       else if (!tape.fast_forward)            /* PLAY -> FAST FORWARD PLAY */
+       {
+         tape.fast_forward = TRUE;
+         DrawVideoDisplay(VIDEO_STATE_FFWD_ON, 0);
+       }
+       else if (!tape.pause_before_death)      /* FFWD PLAY -> + AUTO PAUSE */
+       {
+         tape.pause_before_death = TRUE;
+         DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, VIDEO_DISPLAY_LABEL_ONLY);
+       }
+       else                                    /* -> NORMAL PLAY */
+       {
+         tape.fast_forward = FALSE;
+         tape.pause_before_death = FALSE;
+         DrawVideoDisplay(VIDEO_STATE_FFWD_OFF | VIDEO_STATE_PAUSE_OFF, 0);
+       }
+      }
       break;
     default:
       break;
   }
+
+  BackToFront();
 }
 
 void HandleSoundButtons(int mx, int my, int button)
 {
-  if (game_status!=PLAYING)
+  if (game_status != PLAYING)
     return;
 
   switch(CheckSoundButtons(mx,my,button))
@@ -1222,8 +1309,8 @@ void HandleSoundButtons(int mx, int my, int button)
       }
       else if (sound_loops_allowed)
       { 
-       sound_music_on = TRUE;
-       player.setup |= SETUP_SOUND_MUSIC;
+       sound_on = sound_music_on = TRUE;
+       player.setup |= (SETUP_SOUND | SETUP_SOUND_MUSIC);
        PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
        DrawSoundDisplay(BUTTON_SOUND_MUSIC_ON);
       }
@@ -1239,42 +1326,52 @@ void HandleSoundButtons(int mx, int my, int button)
       }
       else if (sound_loops_allowed)
       { 
-       sound_loops_on = TRUE;
-       player.setup |= SETUP_SOUND_LOOPS;
+       sound_on = sound_loops_on = TRUE;
+       player.setup |= (SETUP_SOUND | SETUP_SOUND_LOOPS);
        DrawSoundDisplay(BUTTON_SOUND_LOOPS_ON);
       }
       else
        DrawSoundDisplay(BUTTON_SOUND_LOOPS_OFF);
       break;
-    case BUTTON_SOUND_SOUND:
-      if (sound_on)
+    case BUTTON_SOUND_SIMPLE:
+      if (sound_simple_on)
       { 
-       sound_on = FALSE;
+       sound_simple_on = FALSE;
        player.setup &= ~SETUP_SOUND;
-       DrawSoundDisplay(BUTTON_SOUND_SOUND_OFF);
+       DrawSoundDisplay(BUTTON_SOUND_SIMPLE_OFF);
       }
       else if (sound_status==SOUND_AVAILABLE)
       { 
-       sound_on = TRUE;
+       sound_on = sound_simple_on = TRUE;
        player.setup |= SETUP_SOUND;
-       DrawSoundDisplay(BUTTON_SOUND_SOUND_ON);
+       DrawSoundDisplay(BUTTON_SOUND_SIMPLE_ON);
       }
       else
-       DrawSoundDisplay(BUTTON_SOUND_SOUND_OFF);
+       DrawSoundDisplay(BUTTON_SOUND_SIMPLE_OFF);
       break;
     default:
       break;
   }
+
+  BackToFront();
 }
 
 void HandleGameButtons(int mx, int my, int button)
 {
-  if (game_status!=PLAYING)
+  if (game_status != PLAYING)
     return;
 
   switch(CheckGameButtons(mx,my,button))
   {
     case BUTTON_GAME_STOP:
+      if (GameOver)
+      {
+       CloseDoor(DOOR_CLOSE_1);
+       game_status = MAINMENU;
+       DrawMainMenu();
+       break;
+      }
+
       if (AreYouSure("Do you really want to quit the game ?",
                      AYS_ASK | AYS_STAY_CLOSED))
       { 
@@ -1306,4 +1403,6 @@ void HandleGameButtons(int mx, int my, int button)
     default:
       break;
   }
+
+  BackToFront();
 }
index 32a5840..a9c5f72 100644 (file)
 
 #include "main.h"
 
-void DrawMainMenu();
+#define SETUP_SCREEN_POS_START         2
+#define SETUP_SCREEN_POS_END           15
+#define SETUP_SCREEN_POS_EMPTY         (SETUP_SCREEN_POS_END - 2)
+
+void DrawHeadline(void);
+void DrawMainMenu(void);
 void HandleMainMenu(int, int, int, int, int);
 void DrawHelpScreenElAction(int);
 void DrawHelpScreenElText(int);
 void DrawHelpScreenMusicText(int);
 void DrawHelpScreenCreditsText(void);
-void DrawHelpScreen();
+void DrawHelpScreen(void);
 void HandleHelpScreen(int);
 void HandleTypeName(int, KeySym);
 void DrawChooseLevel(void);
 void HandleChooseLevel(int, int, int, int, int);
 void DrawHallOfFame(int);
 void HandleHallOfFame(int);
-void DrawSetupScreen();
+void DrawSetupScreen(void);
 void HandleSetupScreen(int, int, int, int, int);
 void CalibrateJoystick(void);
+void HandleGameActions(void);
 void HandleVideoButtons(int, int, int);
 void HandleSoundButtons(int, int, int);
 void HandleGameButtons(int, int, int);
diff --git a/src/tape.c b/src/tape.c
new file mode 100644 (file)
index 0000000..35929e8
--- /dev/null
@@ -0,0 +1,230 @@
+/***********************************************************
+*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+*----------------------------------------------------------*
+*  ©1997 Artsoft Development                               *
+*        Holger Schemel                                    *
+*        33604 Bielefeld                                   *
+*        Telefon: (0521) 290471                            *
+*        eMail: aeglos@valinor.owl.de                      *
+*               aeglos@uni-paderborn.de                    *
+*----------------------------------------------------------*
+*  tape.c                                                  *
+***********************************************************/
+
+#include "tape.h"
+#include "misc.h"
+#include "game.h"
+#include "buttons.h"
+
+void TapeStartRecording()
+{
+  time_t zeit1 = time(NULL);
+  struct tm *zeit2 = localtime(&zeit1);
+
+  if (!TAPE_IS_STOPPED(tape))
+    TapeStop();
+
+  tape.level_nr = level_nr;
+  tape.length = 0;
+  tape.counter = 0;
+  tape.pos[tape.counter].delay = 0;
+  tape.changed = TRUE;
+  tape.recording = TRUE;
+  tape.playing = FALSE;
+  tape.pausing = FALSE;
+  tape.date = 10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday;
+  tape.random_seed = InitRND(NEW_RANDOMIZE);
+
+  DrawVideoDisplay(VIDEO_STATE_REC_ON,0);
+  DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+  DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+}
+
+void TapeStopRecording()
+{
+  if (!tape.recording)
+    return;
+
+  tape.pos[tape.counter].joystickdata = 0;
+  tape.counter++;
+  tape.length = tape.counter;
+  tape.length_seconds = GetTapeLength();
+  tape.recording = FALSE;
+  tape.pausing = FALSE;
+  DrawVideoDisplay(VIDEO_STATE_REC_OFF,0);
+}
+
+void TapeRecordAction(int joy)
+{
+  if (!tape.recording || tape.pausing)
+    return;
+
+  if (tape.counter>=MAX_TAPELEN-1)
+  {
+    TapeStopRecording();
+    return;
+  }
+
+  if (joy)
+  {
+    tape.pos[tape.counter].joystickdata = joy;
+    tape.counter++;
+    tape.pos[tape.counter].delay = 0;
+  }
+}
+
+void TapeRecordDelay()
+{
+  if (!tape.recording || tape.pausing)
+    return;
+
+  if (tape.counter>=MAX_TAPELEN)
+  {
+    TapeStopRecording();
+    return;
+  }
+
+  tape.pos[tape.counter].delay++;
+
+  if (tape.pos[tape.counter].delay>=255)
+  {
+    tape.pos[tape.counter].joystickdata = 0;
+    tape.counter++;
+    tape.pos[tape.counter].delay = 0;
+  }
+}
+
+void TapeTogglePause()
+{
+  if (!tape.recording && !tape.playing)
+    return;
+
+  tape.pausing = !tape.pausing;
+  tape.fast_forward = FALSE;
+  tape.pause_before_death = FALSE;
+  DrawVideoDisplay(tape.pausing ?
+                  VIDEO_STATE_PAUSE_ON :
+                  VIDEO_STATE_PAUSE_OFF,0);
+}
+
+void TapeStartPlaying()
+{
+  if (TAPE_IS_EMPTY(tape))
+    return;
+
+  if (!TAPE_IS_STOPPED(tape))
+    TapeStop();
+
+  tape.counter = 0;
+  tape.delay_played = 0;
+  tape.pause_before_death = FALSE;
+  tape.recording = FALSE;
+  tape.playing = TRUE;
+  tape.pausing = FALSE;
+  tape.fast_forward = FALSE;
+  InitRND(tape.random_seed);
+
+  DrawVideoDisplay(VIDEO_STATE_PLAY_ON,0);
+  DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+  DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+}
+
+void TapeStopPlaying()
+{
+  if (!tape.playing)
+    return;
+
+  tape.playing = FALSE;
+  tape.pausing = FALSE;
+  DrawVideoDisplay(VIDEO_STATE_PLAY_OFF,0);
+}
+
+int TapePlayAction()
+{
+  if (!tape.playing || tape.pausing)
+    return(0);
+
+  if (tape.counter>=tape.length)
+  {
+    TapeStopPlaying();
+    return(0);
+  }
+
+  if (tape.delay_played == tape.pos[tape.counter].delay)
+  {
+    tape.delay_played = 0;
+    tape.counter++;
+    return(tape.pos[tape.counter-1].joystickdata);
+  }
+  else
+    return(0);
+}
+
+BOOL TapePlayDelay()
+{
+  if (!tape.playing || tape.pausing)
+    return(FALSE);
+
+  if (tape.pause_before_death) /* STOP 10s BEFORE PLAYER GETS KILLED... */
+  {
+    if (!(FrameCounter % 5))
+    {
+      if (2*(FrameCounter/10) == FrameCounter/5)
+       DrawVideoDisplay(VIDEO_STATE_PAUSE_ON, VIDEO_DISPLAY_LABEL_ONLY);
+      else
+       DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF, VIDEO_DISPLAY_LABEL_ONLY);
+    }
+
+    if (level.time-TimeLeft > tape.length_seconds - PAUSE_SECONDS_BEFORE_DEATH)
+    {
+      TapeTogglePause();
+      return(FALSE);
+    }
+  }
+
+  if (tape.counter>=tape.length)
+  {
+    TapeStopPlaying();
+    return(TRUE);
+  }
+
+  if (tape.delay_played < tape.pos[tape.counter].delay)
+  {
+    tape.delay_played++;
+    return(TRUE);
+  }
+  else
+    return(FALSE);
+}
+
+void TapeStop()
+{
+  TapeStopRecording();
+  TapeStopPlaying();
+
+  DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+  if (tape.date && tape.length)
+  {
+    DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+    DrawVideoDisplay(VIDEO_STATE_TIME_ON,tape.length_seconds);
+  }
+}
+
+void TapeErase()
+{
+  tape.length = 0;
+}
+
+unsigned int GetTapeLength()
+{
+  unsigned int tape_length = 0;
+  int i;
+
+  if (TAPE_IS_EMPTY(tape))
+    return(0);
+
+  for(i=0;i<tape.length;i++)
+    tape_length += tape.pos[i].delay;
+
+  return(tape_length * GAME_FRAME_DELAY / 100);
+}
diff --git a/src/tape.h b/src/tape.h
new file mode 100644 (file)
index 0000000..ca085e0
--- /dev/null
@@ -0,0 +1,34 @@
+/***********************************************************
+*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+*----------------------------------------------------------*
+*  ©1997 Artsoft Development                               *
+*        Holger Schemel                                    *
+*        33604 Bielefeld                                   *
+*        Telefon: (0521) 290471                            *
+*        eMail: aeglos@valinor.owl.de                      *
+*               aeglos@uni-paderborn.de                    *
+*----------------------------------------------------------*
+*  tape.c                                                  *
+***********************************************************/
+
+#ifndef TAPE_H
+#define TAPE_H
+
+#include "main.h"
+
+#define PAUSE_SECONDS_BEFORE_DEATH     3
+
+void TapeStartRecording(void);
+void TapeStopRecording(void);
+void TapeRecordAction(int);
+void TapeRecordDelay(void);
+void TapeTogglePause(void);
+void TapeStartPlaying(void);
+void TapeStopPlaying(void);
+int TapePlayAction(void);
+BOOL TapePlayDelay(void);
+void TapeStop(void);
+void TapeErase(void);
+unsigned int GetTapeLength(void);
+
+#endif
index 09da1bd..63c027f 100644 (file)
@@ -115,10 +115,13 @@ void BackToFront()
 
 void FadeToFront()
 {
+
+/*
   long fading_delay = 300000;
 
   if (fading_on && (redraw_mask & REDRAW_FIELD))
   {
+*/
 
 /*
     int x,y;
@@ -147,7 +150,7 @@ void FadeToFront()
     Delay(fading_delay);
 */
 
-
+/*
     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
              REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
@@ -174,6 +177,7 @@ void FadeToFront()
 
     redraw_mask &= ~REDRAW_MAIN;
   }
+*/
 
   BackToFront();
 }
@@ -185,7 +189,7 @@ void ClearWindow()
                 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
   redraw_mask|=REDRAW_FIELD;
 
-  if (game_status==PLAYING && direct_draw_on)
+  if (direct_draw_on && game_status==PLAYING)
   {
     drawto_field = window;
     XFillRectangle(display,drawto_field,gc,
@@ -247,6 +251,24 @@ void DrawTextExt(Drawable d, GC gc, int x, int y,
   }
 }
 
+void DrawGraphicAnimation(int x, int y, int graphic,
+                         int frames, int delay, int mode)
+{
+  int phase;
+
+  if (mode == ANIM_OSCILLATE)
+  {
+    int max_anim_frames = frames*2 - 2;
+    phase = (FrameCounter % (delay * max_anim_frames)) / delay;
+    phase = (phase < frames ? phase : max_anim_frames - phase);
+  }
+  else
+    phase = (FrameCounter % (delay * frames)) / delay;
+
+  if (!(FrameCounter % delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+    DrawGraphic(SCROLLX(x),SCROLLY(y), graphic + phase);
+}
+
 void DrawGraphic(int x, int y, int graphic)
 {
   DrawGraphicExt(drawto_field, gc, x, y, graphic);
@@ -433,33 +455,34 @@ void DrawElementShifted(int x, int y, int dx, int dy, int element,int cut_mode)
   int graphic = el2gfx(element);
   int phase = ABS(MovPos[ux][uy])/(TILEX/2);
   int dir = MovDir[ux][uy];
+
+/*
   int horiz_move = (dir==MV_LEFT || dir==MV_RIGHT);
+*/
 
   if (element==EL_PACMAN ||
       element==EL_KAEFER ||
-      element==EL_FLIEGER)
+      element==EL_FLIEGER ||
+      element==EL_BUTTERFLY ||
+      element==EL_FIREFLY)
   {
-    if (element==EL_PACMAN)
-      graphic = GFX_PACMAN + 4*!phase;
+    if (element==EL_BUTTERFLY || element==EL_FIREFLY)
+      graphic += !phase;
     else
+    {
       graphic += 4*!phase;
 
-    if (dir==MV_UP)
-      graphic += 1;
-    else if (dir==MV_LEFT)
-      graphic += 2;
-    else if (dir==MV_DOWN)
-      graphic += 3;
+      if (dir==MV_UP)
+       graphic += 1;
+      else if (dir==MV_LEFT)
+       graphic += 2;
+      else if (dir==MV_DOWN)
+       graphic += 3;
+    }
   }
-  else if ((element==EL_FELSBROCKEN ||
-           element==EL_EDELSTEIN || element==EL_EDELSTEIN2 ||
-           element==EL_EDELSTEIN3 || element==EL_DIAMANT)
-          && horiz_move && phase)
+  else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
   {
-    if (element==EL_FELSBROCKEN)
-      graphic += 2;
-    else
-      graphic += 1;
+    graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
   }
   else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
            element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
@@ -502,10 +525,10 @@ void ErdreichAnbroeckeln(int x, int y)
   int snip = 4;
   static int xy[4][2] =
   {
-    0,-1,
-    -1,0,
-    +1,0,
-    0,+1
+    { 0,-1 },
+    { -1,0 },
+    { +1,0 },
+    { 0,+1 }
   };
 
   if (!IN_LEV_FIELD(ux,uy))
@@ -794,6 +817,10 @@ void DrawMicroLevel(int xpos, int ypos)
                 xpos-MICRO_TILEX,ypos-MICRO_TILEY,
                 MICRO_TILEX*(STD_LEV_FIELDX+2),
                 MICRO_TILEY*(STD_LEV_FIELDY+2));
+  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;
 
   for(x=-1;x<=STD_LEV_FIELDX;x++)
     for(y=-1;y<=STD_LEV_FIELDY;y++)
@@ -833,6 +860,9 @@ int AYS_in_range(int x, int y)
 BOOL AreYouSure(char *text, unsigned int ays_state)
 {
   int mx,my, ty, result = -1;
+  unsigned int old_door_state;
+
+  old_door_state = GetDoorState();
 
   CloseDoor(DOOR_CLOSE_1);
 
@@ -883,11 +913,12 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
              DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
 
   OpenDoor(DOOR_OPEN_1);
+  ClearEventQueue();
 
   if (!(ays_state & AYS_ASK) && !(ays_state & AYS_CONFIRM))
     return(FALSE);
 
-  if (game_status!=MAINMENU)
+  if (game_status != MAINMENU)
     InitAnimation();
 
   button_status = MB_RELEASED;
@@ -916,7 +947,7 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
        {
          int choice;
 
-         if (event.type==MotionNotify)
+         if (event.type == MotionNotify)
          {
            motion_status = TRUE;
            mx = ((XMotionEvent *) &event)->x;
@@ -955,7 +986,6 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
          break;
        }
        case KeyPress:
-         key_status = KEY_PRESSED;
          switch(XLookupKeysym((XKeyEvent *)&event,
                               ((XKeyEvent *)&event)->state))
          {
@@ -977,7 +1007,7 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
          break;
       }
     }
-    else if (JoystickButton()==JOY_BUTTON_NEW_PRESSED)
+    else if (JoystickButton() == JOY_BUTTON_NEW_PRESSED)
     {
       int joy=Joystick();
 
@@ -988,15 +1018,14 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
     }
   }
 
-  if (game_status!=MAINMENU)
+  if (game_status != MAINMENU)
     StopAnimation();
 
   if (!(ays_state & AYS_STAY_OPEN))
   {
     CloseDoor(DOOR_CLOSE_1);
 
-    if (!(ays_state & AYS_STAY_CLOSED) &&
-       (game_status==PLAYING || game_status==LEVELED))
+    if (!(ays_state & AYS_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
     {
       XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
                DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
@@ -1008,8 +1037,10 @@ BOOL AreYouSure(char *text, unsigned int ays_state)
   return(result);
 }
 
-void OpenDoor(unsigned int door_state)
+unsigned int OpenDoor(unsigned int door_state)
 {
+  unsigned int new_door_state;
+
   if (door_state & DOOR_COPY_BACK)
   {
     XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
@@ -1018,27 +1049,47 @@ void OpenDoor(unsigned int door_state)
     door_state &= ~DOOR_COPY_BACK;
   }
 
-  MoveDoor(door_state);
+  new_door_state = MoveDoor(door_state);
+
+/*
   ClearEventQueue();
+*/
+
+  return(new_door_state);
 }
 
-void CloseDoor(unsigned int door_state)
+unsigned int CloseDoor(unsigned int door_state)
 {
+  unsigned int new_door_state;
+
   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
            DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
            VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
 
-  MoveDoor(door_state);
+  new_door_state = MoveDoor(door_state);
+
+/*
   ClearEventQueue();
+*/
+
+  return(new_door_state);
 }
 
-void MoveDoor(unsigned int door_state)
+unsigned int GetDoorState()
 {
-  static int door1 = DOOR_OPEN_1;
-  static int door2 = DOOR_CLOSE_2;
+  return(MoveDoor(DOOR_GET_STATE));
+}
+
+unsigned int MoveDoor(unsigned int door_state)
+{
+  static unsigned int door1 = DOOR_OPEN_1;
+  static unsigned int door2 = DOOR_CLOSE_2;
   int x, start, stepsize = 4, door_anim_delay = stepsize*5000;
 
+  if (door_state == DOOR_GET_STATE)
+    return(door1 | door2);
+
   if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
     door_state &= ~DOOR_OPEN_1;
   else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
@@ -1150,6 +1201,8 @@ void MoveDoor(unsigned int door_state)
     door1 = door_state & DOOR_ACTION_1;
   if (door_state & DOOR_ACTION_2)
     door2 = door_state & DOOR_ACTION_2;
+
+  return(door1 | door2);
 }
 
 int ReadPixel(Drawable d, int x, int y)
@@ -1320,6 +1373,16 @@ int el2gfx(int element)
     case EL_FLIEGER_O:         return(GFX_FLIEGER_O);
     case EL_FLIEGER_L:         return(GFX_FLIEGER_L);
     case EL_FLIEGER_U:         return(GFX_FLIEGER_U);
+    case EL_BUTTERFLY:         return(GFX_BUTTERFLY);
+    case EL_BUTTERFLY_R:       return(GFX_BUTTERFLY_R);
+    case EL_BUTTERFLY_O:       return(GFX_BUTTERFLY_O);
+    case EL_BUTTERFLY_L:       return(GFX_BUTTERFLY_L);
+    case EL_BUTTERFLY_U:       return(GFX_BUTTERFLY_U);
+    case EL_FIREFLY:           return(GFX_FIREFLY);
+    case EL_FIREFLY_R:         return(GFX_FIREFLY_R);
+    case EL_FIREFLY_O:         return(GFX_FIREFLY_O);
+    case EL_FIREFLY_L:         return(GFX_FIREFLY_L);
+    case EL_FIREFLY_U:         return(GFX_FIREFLY_U);
     case EL_MAMPFER:           return(GFX_MAMPFER);
     case EL_ZOMBIE:            return(GFX_ZOMBIE);
     case EL_BETON:             return(GFX_BETON);
@@ -1336,6 +1399,7 @@ int el2gfx(int element)
     case EL_AMOEBE_NASS:       return(GFX_AMOEBE_NASS);
     case EL_AMOEBE_NORM:       return(GFX_AMOEBE_NORM);
     case EL_AMOEBE_VOLL:       return(GFX_AMOEBE_VOLL);
+    case EL_AMOEBE_BD:         return(GFX_AMOEBE_BD);
     case EL_AMOEBA2DIAM:       return(GFX_AMOEBA2DIAM);
     case EL_KOKOSNUSS:         return(GFX_KOKOSNUSS);
     case EL_LIFE:              return(GFX_LIFE);
@@ -1375,10 +1439,14 @@ int el2gfx(int element)
     case EL_ZEIT_VOLL:         return(GFX_ZEIT_VOLL);
     case EL_ZEIT_LEER:         return(GFX_ZEIT_LEER);
     case EL_MAUER_LEBT:                return(GFX_MAUER_LEBT);
-    case EL_EDELSTEIN2:                return(GFX_EDELSTEIN2);
-    case EL_EDELSTEIN3:                return(GFX_EDELSTEIN3);
-    case EL_ERZ_EDEL2:         return(GFX_ERZ_EDEL2);
-    case EL_ERZ_EDEL3:         return(GFX_ERZ_EDEL3);
+    case EL_EDELSTEIN_BD:      return(GFX_EDELSTEIN_BD);
+    case EL_EDELSTEIN_GELB:    return(GFX_EDELSTEIN_GELB);
+    case EL_EDELSTEIN_ROT:     return(GFX_EDELSTEIN_ROT);
+    case EL_EDELSTEIN_LILA:    return(GFX_EDELSTEIN_LILA);
+    case EL_ERZ_EDEL_BD:       return(GFX_ERZ_EDEL_BD);
+    case EL_ERZ_EDEL_GELB:     return(GFX_ERZ_EDEL_GELB);
+    case EL_ERZ_EDEL_ROT:      return(GFX_ERZ_EDEL_ROT);
+    case EL_ERZ_EDEL_LILA:     return(GFX_ERZ_EDEL_LILA);
     case EL_MAMPFER2:          return(GFX_MAMPFER2);
     case EL_SIEB2_LEER:                return(GFX_SIEB2_LEER);
     case EL_SIEB2_VOLL:                return(GFX_SIEB2_VOLL);
@@ -1386,6 +1454,10 @@ int el2gfx(int element)
     case EL_DYNABOMB:          return(GFX_DYNABOMB);
     case EL_DYNABOMB_NR:       return(GFX_DYNABOMB_NR);
     case EL_DYNABOMB_SZ:       return(GFX_DYNABOMB_SZ);
+    case EL_DYNABOMB_XL:       return(GFX_DYNABOMB_XL);
+    case EL_SOKOBAN_OBJEKT:    return(GFX_SOKOBAN_OBJEKT);
+    case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER);
+    case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL);
     default:
     {
       if (IS_CHAR(element))
index bec2205..ce4ab0f 100644 (file)
 
 #include <sys/time.h>
 
+/* für DrawGraphicAnimation */
+#define ANIM_NORMAL    0
+#define ANIM_OSCILLATE 1
+
 /* für DrawElementShifted */
 #define CUT_NO_CUTTING 0
 #define CUT_ABOVE      1
@@ -38,6 +42,7 @@
 #define DOOR_ACTION    (DOOR_ACTION_1 | DOOR_ACTION_2)
 #define DOOR_COPY_BACK 16
 #define DOOR_NO_DELAY  32
+#define DOOR_GET_STATE 64
 
 /* für AreYouSure */
 #define AYS_ASK                1
@@ -52,6 +57,7 @@ void FadeToFront();
 void ClearWindow();
 void DrawText(int, int, char *, int, int);
 void DrawTextExt(Drawable, GC, int, int, char *, int, int);
+void DrawGraphicAnimation(int, int, int, int, int, int);
 void DrawGraphic(int, int, int);
 void DrawGraphicExt(Drawable, GC, int, int, int);
 void DrawGraphicExtHiRes(Drawable, GC, int, int, int);
@@ -74,9 +80,10 @@ void DrawLevel(void);
 void DrawMiniLevel(int, int);
 void DrawMicroLevel(int, int);
 BOOL AreYouSure(char *, unsigned int);
-void OpenDoor(unsigned int);
-void CloseDoor(unsigned int);
-void MoveDoor(unsigned int);
+unsigned int OpenDoor(unsigned int);
+unsigned int CloseDoor(unsigned int);
+unsigned int GetDoorState(void);
+unsigned int MoveDoor(unsigned int);
 int ReadPixel(Drawable, int, int);
 void CheckJoystickData(void);
 int JoystickPosition(int, int, int);