rnd-20051202-2-src
[rocksndiamonds.git] / src / game.c
index 239a6a7008911d93ad1e48920c546da37a8fd315..a78e341f983a3e429518c8e8bff1647f0a96983b 100644 (file)
 #define USE_NEW_AMOEBA_CODE    FALSE
 
 /* EXPERIMENTAL STUFF */
-#define USE_NEW_STUFF                  (TRUE                           * 1)
+#define USE_NEW_STUFF                  (                       * 1)
 
-#define USE_NEW_SP_SLIPPERY            (TRUE   * USE_NEW_STUFF         * 1)
-#define USE_NEW_COLLECT_COUNT          (TRUE   * USE_NEW_STUFF         * 1)
+#define USE_NEW_SP_SLIPPERY            (USE_NEW_STUFF          * 1)
+#define USE_NEW_COLLECT_COUNT          (USE_NEW_STUFF          * 1)
+#define USE_NEW_PLAYER_ANIM            (USE_NEW_STUFF          * 1)
+#define USE_NEW_ALL_SLIPPERY           (USE_NEW_STUFF          * 1)
+#define USE_NEW_PLAYER_SPEED           (USE_NEW_STUFF          * 1)
 
 
 /* for DigField() */
 #define INITIAL_MOVE_DELAY_ON  0
 
 /* values for player movement speed (which is in fact a delay value) */
+#define MOVE_DELAY_MIN_SPEED   32
 #define MOVE_DELAY_NORMAL_SPEED        8
 #define MOVE_DELAY_HIGH_SPEED  4
+#define MOVE_DELAY_MAX_SPEED   1
 
+#if 0
 #define DOUBLE_MOVE_DELAY(x)   (x = (x <= MOVE_DELAY_HIGH_SPEED ? x * 2 : x))
 #define HALVE_MOVE_DELAY(x)    (x = (x >= MOVE_DELAY_HIGH_SPEED ? x / 2 : x))
+#else
+#define DOUBLE_MOVE_DELAY(x)   (x = (x < MOVE_DELAY_MIN_SPEED ? x * 2 : x))
+#define HALVE_MOVE_DELAY(x)    (x = (x > MOVE_DELAY_MAX_SPEED ? x / 2 : x))
+#endif
 #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value))
 #define HALVE_PLAYER_SPEED(p)  (DOUBLE_MOVE_DELAY((p)->move_delay_value))
 
@@ -1701,6 +1711,26 @@ void InitGame()
                    emulate_sb ? EMU_SOKOBAN :
                    emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
 
+#if USE_NEW_ALL_SLIPPERY
+  /* initialize type of slippery elements */
+  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+  {
+    if (!IS_CUSTOM_ELEMENT(i))
+    {
+      /* default: elements slip down either to the left or right randomly */
+      element_info[i].slippery_type = SLIPPERY_ANY_RANDOM;
+
+      /* SP style elements prefer to slip down on the left side */
+      if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i))
+       element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
+
+      /* BD style elements prefer to slip down on the left side */
+      if (game.emulation == EMU_BOULDERDASH)
+       element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT;
+    }
+  }
+#endif
+
   /* initialize explosion and ignition delay */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
@@ -4759,11 +4789,26 @@ void StartMoving(int x, int y)
                                 Feld[x + 1][y + 1] == EL_ACID));
       boolean can_fall_any  = (can_fall_left || can_fall_right);
       boolean can_fall_both = (can_fall_left && can_fall_right);
+      int slippery_type = element_info[Feld[x][y + 1]].slippery_type;
 
-      if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1]))
+#if USE_NEW_ALL_SLIPPERY
+      if (can_fall_any && slippery_type != SLIPPERY_ANY_RANDOM)
       {
-       int slippery_type = element_info[Feld[x][y + 1]].slippery_type;
+       if (slippery_type == SLIPPERY_ANY_LEFT_RIGHT && can_fall_both)
+         can_fall_right = FALSE;
+       else if (slippery_type == SLIPPERY_ANY_RIGHT_LEFT && can_fall_both)
+         can_fall_left = FALSE;
+       else if (slippery_type == SLIPPERY_ONLY_LEFT)
+         can_fall_right = FALSE;
+       else if (slippery_type == SLIPPERY_ONLY_RIGHT)
+         can_fall_left = FALSE;
 
+       can_fall_any  = (can_fall_left || can_fall_right);
+       can_fall_both = FALSE;
+      }
+#else
+      if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1]))
+      {
        if (slippery_type == SLIPPERY_ONLY_LEFT)
          can_fall_right = FALSE;
        else if (slippery_type == SLIPPERY_ONLY_RIGHT)
@@ -4776,7 +4821,10 @@ void StartMoving(int x, int y)
        can_fall_any  = (can_fall_left || can_fall_right);
        can_fall_both = (can_fall_left && can_fall_right);
       }
+#endif
 
+#if USE_NEW_ALL_SLIPPERY
+#else
 #if USE_NEW_SP_SLIPPERY
       /* !!! better use the same properties as for custom elements here !!! */
       else if (game.engine_version >= VERSION_IDENT(3,1,1,0) &&
@@ -4786,7 +4834,19 @@ void StartMoving(int x, int y)
        can_fall_both = FALSE;
       }
 #endif
+#endif
 
+#if USE_NEW_ALL_SLIPPERY
+      if (can_fall_both)
+      {
+       if (element == EL_BD_ROCK || element == EL_BD_DIAMOND)
+         can_fall_right = FALSE;       /* slip down on left side */
+       else
+         can_fall_left = !(can_fall_right = RND(2));
+
+       can_fall_both = FALSE;
+      }
+#else
       if (can_fall_both)
       {
        if (game.emulation == EMU_BOULDERDASH ||
@@ -4797,6 +4857,7 @@ void StartMoving(int x, int y)
 
        can_fall_both = FALSE;
       }
+#endif
 
       if (can_fall_any)
       {
@@ -5314,11 +5375,6 @@ void StartMoving(int x, int y)
     ContinueMoving(x, y);
 }
 
-/* (emacs is confused here for some reason; this makes it happy again ;-) ) */
-void dummy()
-{
-}
-
 void ContinueMoving(int x, int y)
 {
   int element = Feld[x][y];
@@ -6650,6 +6706,14 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
        {
          int move_stepsize = TILEX / stored_player[i].move_delay_value;
 
+         if (action_mode == CA_MODE_ADD || action_mode == CA_MODE_SUBTRACT)
+         {
+           /* translate "+" and "-" to "*" and "/" with powers of two */
+           action_arg_number = 1 << action_arg_number;
+           action_mode = (action_mode == CA_MODE_ADD ? CA_MODE_MULTIPLY :
+                          CA_MODE_DIVIDE);
+         }
+
          move_stepsize =
            getModifiedActionNumber(move_stepsize,
                                    action_mode,
@@ -6663,8 +6727,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
          stored_player[i].move_delay_value = TILEX / move_stepsize;
 
 #if 0
-         printf("::: move_delay_value == %d\n",
-                stored_player[i].move_delay_value);
+         printf("::: move_delay_value == %d [%d]\n",
+                stored_player[i].move_delay_value, action_arg_number);
 #endif
        }
       }
@@ -7439,12 +7503,25 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     boolean advance_player_counters = (player_nr == -1 || player_nr == i);
-    int move_frames =
-      MOVE_DELAY_NORMAL_SPEED /  stored_player[i].move_delay_value;
+    int move_delay_value = stored_player[i].move_delay_value;
+    int move_frames = MOVE_DELAY_NORMAL_SPEED / move_delay_value;
 
     if (!advance_player_counters)      /* not all players may be affected */
       continue;
 
+#if USE_NEW_PLAYER_ANIM
+    if (move_frames == 0)      /* less than one move per game frame */
+    {
+      int stepsize = TILEX / move_delay_value;
+      int delay = move_delay_value / MOVE_DELAY_NORMAL_SPEED;
+      int count = (stored_player[i].is_moving ?
+                  ABS(stored_player[i].MovPos) / stepsize : FrameCounter);
+
+      if (count % delay == 0)
+       move_frames = 1;
+    }
+#endif
+
     stored_player[i].Frame += move_frames;
 
     if (stored_player[i].MovPos != 0)
@@ -7698,11 +7775,20 @@ void GameActions()
     if (IS_CHANGING(x, y) &&
        (game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y]))
     {
+      int page = element_info[element].event_page_nr[CE_DELAY];
 #if 0
-      ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] :
-                   element_info[element].event_page_nr[CE_DELAY]);
+      ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : page);
 #else
-      ChangeElement(x, y, element_info[element].event_page_nr[CE_DELAY]);
+
+#if 0
+      printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]);
+#endif
+
+      if (CAN_CHANGE(element))
+       ChangeElement(x, y, page);
+
+      if (HAS_ACTION(element) && ChangeDelay[x][y] == 0)
+       ExecuteCustomElementAction(x, y, element, page);
 #endif
 
       element = Feld[x][y];
@@ -8416,8 +8502,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
   int last_jx = player->last_jx, last_jy = player->last_jy;
   int move_stepsize = TILEX / player->move_delay_value;
 
-  if (!player->active || !player->MovPos)
+#if USE_NEW_PLAYER_SPEED
+  if (!player->active)
+    return;
+
+  if (player->MovPos == 0 && mode == SCROLL_GO_ON)     /* player not moving */
     return;
+#else
+  if (!player->active || player->MovPos == 0)
+    return;
+#endif
 
   if (mode == SCROLL_INIT)
   {
@@ -8447,20 +8541,47 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
       MovDelay[last_jx][last_jy] = last_field_block_delay + 1;
     }
 
+#if USE_NEW_PLAYER_SPEED
+    if (player->MovPos != 0)   /* player has not yet reached destination */
+      return;
+#else
     return;
+#endif
   }
   else if (!FrameReached(&player->actual_frame_counter, 1))
     return;
 
+#if 0
+    printf("::: player->MovPos: %d -> %d\n",
+          player->MovPos,
+          player->MovPos + (player->MovPos > 0 ? -1 : 1) * move_stepsize);
+#endif
+
+#if USE_NEW_PLAYER_SPEED
+    if (player->MovPos != 0)
+    {
+      player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
+      player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
+
+      /* before DrawPlayer() to draw correct player graphic for this case */
+      if (player->MovPos == 0)
+       CheckGravityMovement(player);
+    }
+#else
   player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
   player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
 
   /* before DrawPlayer() to draw correct player graphic for this case */
   if (player->MovPos == 0)
     CheckGravityMovement(player);
+#endif
 
   if (player->MovPos == 0)     /* player reached destination field */
   {
+#if 0
+    printf("::: player reached destination field\n");
+#endif
+
     if (player->move_delay_reset_counter > 0)
     {
       player->move_delay_reset_counter--;