rnd-20080930-1-src
[rocksndiamonds.git] / src / game.c
index 057c8dd257c598303e17516e1c2ac29097d291c8..ce62844112c7360d8d833ad87ba72c7ae53325f7 100644 (file)
@@ -65,6 +65,8 @@
 
 #define USE_GFX_RESET_WHEN_NOT_MOVING  (USE_NEW_STUFF          * 1)
 
+#define USE_NEW_PLAYER_ASSIGNMENTS     (USE_NEW_STUFF          * 1)
+
 #define USE_DELAYED_GFX_REDRAW         (USE_NEW_STUFF          * 0)
 
 #if USE_DELAYED_GFX_REDRAW
@@ -4038,6 +4040,52 @@ void InitGame()
     if (game.belt_dir[i] == MV_NONE)
       game.belt_dir_nr[i] = 3;         /* not moving, next moving left */
 
+#if USE_NEW_PLAYER_ASSIGNMENTS
+  /* check if any connected player was not found in playfield */
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    struct PlayerInfo *player = &stored_player[i];
+
+    if (player->connected && !player->present)
+    {
+      for (j = 0; j < MAX_PLAYERS; j++)
+      {
+       struct PlayerInfo *some_player = &stored_player[j];
+       int jx = some_player->jx, jy = some_player->jy;
+
+       /* assign first free player found that is present in the playfield */
+       if (some_player->present && !some_player->connected)
+       {
+         player->present = FALSE;
+         player->active = FALSE;
+
+         some_player->present = TRUE;
+         some_player->active = TRUE;
+
+         /*
+         player->initial_element = some_player->initial_element;
+         player->artwork_element = some_player->artwork_element;
+
+         player->block_last_field       = some_player->block_last_field;
+         player->block_delay_adjustment = some_player->block_delay_adjustment;
+         */
+
+         StorePlayer[jx][jy] = some_player->element_nr;
+
+         some_player->jx = some_player->last_jx = jx;
+         some_player->jy = some_player->last_jy = jy;
+
+         if (local_player == player)
+           local_player = some_player;
+
+         break;
+       }
+      }
+    }
+  }
+
+#else
+
   /* check if any connected player was not found in playfield */
   for (i = 0; i < MAX_PLAYERS; i++)
   {
@@ -4066,6 +4114,7 @@ void InitGame()
          player->block_delay_adjustment = some_player->block_delay_adjustment;
 
          StorePlayer[jx][jy] = player->element_nr;
+
          player->jx = player->last_jx = jx;
          player->jy = player->last_jy = jy;
 
@@ -4074,6 +4123,7 @@ void InitGame()
       }
     }
   }
+#endif
 
   if (tape.playing)
   {
@@ -5591,6 +5641,21 @@ void RelocatePlayer(int jx, int jy, int el_player_raw)
 
   CheckTriggeredElementChangeByPlayer(jx, jy, element, CE_PLAYER_ENTERS_X,
                                      player->index_bit, enter_side);
+
+#if 1
+  if (player->is_switching)
+  {
+    /* ensure that relocation while still switching an element does not cause
+       a new element to be treated as also switched directly after relocation
+       (this is important for teleporter switches that teleport the player to
+       a place where another teleporter switch is in the same direction, which
+       would then incorrectly be treated as immediately switched before the
+       direction key that caused the switch was released) */
+
+    player->switch_x += jx - old_jx;
+    player->switch_y += jy - old_jy;
+  }
+#endif
 }
 
 void Explode(int ex, int ey, int phase, int mode)
@@ -10174,6 +10239,9 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_arg == CA_ARG_ELEMENT_TRIGGER ? change->actual_trigger_element :
      action_arg == CA_ARG_ELEMENT_TARGET  ? change->target_element :
      action_arg == CA_ARG_ELEMENT_ACTION  ? change->action_element :
+     action_arg == CA_ARG_INVENTORY_RM_TRIGGER ? change->actual_trigger_element:
+     action_arg == CA_ARG_INVENTORY_RM_TARGET  ? change->target_element :
+     action_arg == CA_ARG_INVENTORY_RM_ACTION  ? change->action_element :
      EL_EMPTY);
   int action_arg_element = GetElementFromGroupElement(action_arg_element_raw);
 
@@ -10377,6 +10445,33 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
+    case CA_SET_LEVEL_RANDOM_SEED:
+    {
+#if 1
+      /* ensure that setting a new random seed while playing is predictable */
+      InitRND(action_arg_number_new ? action_arg_number_new : RND(1000000) + 1);
+#else
+      InitRND(action_arg_number_new);
+#endif
+
+#if 0
+      printf("::: %d -> %d\n", action_arg_number_new, RND(10));
+#endif
+
+#if 0
+      {
+       int i;
+
+       printf("::: ");
+       for (i = 0; i < 9; i++)
+         printf("%d, ", RND(2));
+       printf("\n");
+      }
+#endif
+
+      break;
+    }
+
     /* ---------- player actions  ------------------------------------------ */
 
     case CA_MOVE_PLAYER:
@@ -10619,7 +10714,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
            player->inventory_infinite_element = EL_UNDEFINED;
            player->inventory_size = 0;
          }
-         else if (action_arg == CA_ARG_ELEMENT_RESET)
+         else if (action_arg == CA_ARG_INVENTORY_RESET)
          {
            player->inventory_infinite_element = EL_UNDEFINED;
            player->inventory_size = 0;
@@ -11070,6 +11165,7 @@ static void HandleElementChange(int x, int y, int page)
   int element = MovingOrBlocked2Element(x, y);
   struct ElementInfo *ei = &element_info[element];
   struct ElementChangeInfo *change = &ei->change_page[page];
+  boolean handle_action_before_change = FALSE;
 
 #ifdef DEBUG
   if (!CAN_CHANGE_OR_HAS_ACTION(element) &&
@@ -11152,6 +11248,15 @@ static void HandleElementChange(int x, int y, int page)
       return;
     }
 
+#if 1
+    /* special case: set new level random seed before changing element */
+    if (change->has_action && change->action_type == CA_SET_LEVEL_RANDOM_SEED)
+      handle_action_before_change = TRUE;
+
+    if (change->has_action && handle_action_before_change)
+      ExecuteCustomElementAction(x, y, element, page);
+#endif
+
     if (change->can_change)
     {
       if (ChangeElement(x, y, element, page))
@@ -11161,7 +11266,7 @@ static void HandleElementChange(int x, int y, int page)
       }
     }
 
-    if (change->has_action)
+    if (change->has_action && !handle_action_before_change)
       ExecuteCustomElementAction(x, y, element, page);
   }
 }
@@ -11957,7 +12062,7 @@ void GameActions()
   }
 
   if (game.restart_level)
-    StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
+    StartGameActions(options.network, setup.autorecord, level.random_seed);
 
   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
   {
@@ -13532,8 +13637,14 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
 
     if (Feld[jx][jy] == EL_EXIT_OPEN ||
        Feld[jx][jy] == EL_EM_EXIT_OPEN ||
+#if 1
+       Feld[jx][jy] == EL_EM_EXIT_OPENING ||
+#endif
        Feld[jx][jy] == EL_STEEL_EXIT_OPEN ||
        Feld[jx][jy] == EL_EM_STEEL_EXIT_OPEN ||
+#if 1
+       Feld[jx][jy] == EL_EM_STEEL_EXIT_OPENING ||
+#endif
        Feld[jx][jy] == EL_SP_EXIT_OPEN ||
        Feld[jx][jy] == EL_SP_EXIT_OPENING)     /* <-- special case */
     {
@@ -14670,8 +14781,14 @@ static int DigField(struct PlayerInfo *player,
     }
     else if (element == EL_EXIT_OPEN ||
             element == EL_EM_EXIT_OPEN ||
+#if 1
+            element == EL_EM_EXIT_OPENING ||
+#endif
             element == EL_STEEL_EXIT_OPEN ||
             element == EL_EM_STEEL_EXIT_OPEN ||
+#if 1
+            element == EL_EM_STEEL_EXIT_OPENING ||
+#endif
             element == EL_SP_EXIT_OPEN ||
             element == EL_SP_EXIT_OPENING)
     {