rnd-20060401-1-src
[rocksndiamonds.git] / src / game.c
index 8f5a51fe4fb9d77af9a4ec40888aba90f454fed9..9aab37fc95a4a740b86b9079c833d87707cf37c7 100644 (file)
                                 RND(element_info[e].move_delay_random))
 #define GET_MAX_MOVE_DELAY(e)  (   (element_info[e].move_delay_fixed) + \
                                    (element_info[e].move_delay_random))
-#define GET_NEW_CUSTOM_VALUE(e)        (   (element_info[e].ce_value_fixed_initial) +\
+#define GET_NEW_CE_VALUE(e)    (   (element_info[e].ce_value_fixed_initial) +\
                                 RND(element_info[e].ce_value_random_initial))
+#define GET_CE_SCORE(e)                (   (element_info[e].collect_score))
 #define GET_CHANGE_DELAY(c)    (   ((c)->delay_fixed  * (c)->delay_frames) + \
                                 RND((c)->delay_random * (c)->delay_frames))
 #define GET_CE_DELAY_VALUE(c)  (   ((c)->delay_fixed) + \
                                 RND((c)->delay_random))
 
+
 #if 1
 #define GET_VALID_RUNTIME_ELEMENT(e)                                   \
         ((e) >= NUM_RUNTIME_ELEMENTS ? EL_UNKNOWN : (e))
        ((e) >= NUM_FILE_ELEMENTS ? EL_UNKNOWN : (e))
 #endif
 
-#define GET_TARGET_ELEMENT(e, ch)                                      \
-       ((e) == EL_TRIGGER_PLAYER   ? (ch)->actual_trigger_player  :    \
-        (e) == EL_TRIGGER_ELEMENT  ? (ch)->actual_trigger_element :    \
-        (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value  : (e))
+#define GET_TARGET_ELEMENT(e, ch, cv, cs)                              \
+       ((e) == EL_TRIGGER_PLAYER   ? (ch)->actual_trigger_player    :  \
+        (e) == EL_TRIGGER_ELEMENT  ? (ch)->actual_trigger_element   :  \
+        (e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value  :  \
+        (e) == EL_TRIGGER_CE_SCORE ? (ch)->actual_trigger_ce_score  :  \
+        (e) == EL_CURRENT_CE_VALUE ? (cv) :                            \
+        (e) == EL_CURRENT_CE_SCORE ? (cs) : (e))
 
 #define CAN_GROW_INTO(e)                                               \
        ((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
@@ -1114,7 +1119,7 @@ static void InitField(int x, int y, boolean init_game)
 
 #if USE_NEW_CUSTOM_VALUE
        if (!element_info[element].use_last_ce_value || init_game)
-         CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]);
+         CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
 #endif
       }
 #else
@@ -1156,7 +1161,7 @@ static void InitField(int x, int y, boolean init_game)
 #if USE_NEW_CUSTOM_VALUE
 
 #if 1
-  CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]);
+  CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
 #else
   CustomValue[x][y] = element_info[Feld[x][y]].custom_value_initial;
 #endif
@@ -1646,6 +1651,7 @@ static void InitGameEngine()
       ei->change_page[j].actual_trigger_player = EL_PLAYER_1;
       ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
       ei->change_page[j].actual_trigger_ce_value = 0;
+      ei->change_page[j].actual_trigger_ce_score = 0;
     }
   }
 
@@ -2031,9 +2037,23 @@ void InitGame()
 
   game.envelope_active = FALSE;
 
-  game.centered_player_nr = game.centered_player_nr_next = -1; /* focus all */
+  /* set focus to local player for network games, else to all players */
+  game.centered_player_nr = (network_playing ? local_player->index_nr : -1);
+  game.centered_player_nr_next = game.centered_player_nr;
   game.set_centered_player = FALSE;
 
+  if (network_playing && tape.recording)
+  {
+    /* store client dependent player focus when recording network games */
+    tape.centered_player_nr_next = game.centered_player_nr_next;
+    tape.set_centered_player = TRUE;
+  }
+
+#if 0
+  printf("::: focus set to player %d [%d]\n",
+        game.centered_player_nr, local_player->index_nr);
+#endif
+
   for (i = 0; i < NUM_BELTS; i++)
   {
     game.belt_dir[i] = MV_NONE;
@@ -7830,6 +7850,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 {
   struct ElementInfo *ei = &element_info[element];
   struct ElementChangeInfo *change = &ei->change_page[page];
+  int target_element = change->target_element;
   int action_type = change->action_type;
   int action_mode = change->action_mode;
   int action_arg = change->action_arg;
@@ -7868,8 +7889,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_type == CA_SET_LEVEL_GEMS ? 999 :
      action_type == CA_SET_LEVEL_TIME ? 9999 :
      action_type == CA_SET_LEVEL_SCORE ? 99999 :
-     action_type == CA_SET_CE_SCORE ? 9999 :
      action_type == CA_SET_CE_VALUE ? 9999 :
+     action_type == CA_SET_CE_SCORE ? 9999 :
      CA_ARG_MAX);
 
   int action_arg_number_reset =
@@ -7877,12 +7898,12 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_type == CA_SET_LEVEL_GEMS ? level.gems_needed :
      action_type == CA_SET_LEVEL_TIME ? level.time :
      action_type == CA_SET_LEVEL_SCORE ? 0 :
-     action_type == CA_SET_CE_SCORE ? 0 :
 #if 1
-     action_type == CA_SET_CE_VALUE ? GET_NEW_CUSTOM_VALUE(element) :
+     action_type == CA_SET_CE_VALUE ? GET_NEW_CE_VALUE(element) :
 #else
      action_type == CA_SET_CE_VALUE ? ei->custom_value_initial :
 #endif
+     action_type == CA_SET_CE_SCORE ? 0 :
      0);
 
   int action_arg_number =
@@ -7893,18 +7914,20 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
      action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min :
      action_arg == CA_ARG_NUMBER_MAX ? action_arg_number_max :
      action_arg == CA_ARG_NUMBER_RESET ? action_arg_number_reset :
-     action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
 #if USE_NEW_CUSTOM_VALUE
      action_arg == CA_ARG_NUMBER_CE_VALUE ? CustomValue[x][y] :
 #else
      action_arg == CA_ARG_NUMBER_CE_VALUE ? ei->custom_value_initial :
 #endif
+     action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
      action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CE_DELAY_VALUE(change) :
      action_arg == CA_ARG_NUMBER_LEVEL_TIME ? level_time_value :
      action_arg == CA_ARG_NUMBER_LEVEL_GEMS ? local_player->gems_still_needed :
      action_arg == CA_ARG_NUMBER_LEVEL_SCORE ? local_player->score :
-     action_arg == CA_ARG_ELEMENT_CV_TARGET ? GET_NEW_CUSTOM_VALUE(change->target_element) :
+     action_arg == CA_ARG_ELEMENT_CV_TARGET ? GET_NEW_CE_VALUE(target_element):
      action_arg == CA_ARG_ELEMENT_CV_TRIGGER ? change->actual_trigger_ce_value:
+     action_arg == CA_ARG_ELEMENT_CS_TARGET ? GET_CE_SCORE(target_element) :
+     action_arg == CA_ARG_ELEMENT_CS_TRIGGER ? change->actual_trigger_ce_score:
      action_arg == CA_ARG_ELEMENT_NR_TARGET  ? change->target_element :
      action_arg == CA_ARG_ELEMENT_NR_TRIGGER ? change->actual_trigger_element :
      -1);
@@ -7913,8 +7936,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
     (action_type == CA_SET_LEVEL_GEMS ? local_player->gems_still_needed :
      action_type == CA_SET_LEVEL_TIME ? TimeLeft :
      action_type == CA_SET_LEVEL_SCORE ? local_player->score :
-     action_type == CA_SET_CE_SCORE ? ei->collect_score :
      action_type == CA_SET_CE_VALUE ? CustomValue[x][y] :
+     action_type == CA_SET_CE_SCORE ? ei->collect_score :
      0);
 
   int action_arg_number_new =
@@ -8175,13 +8198,6 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
 
     /* ---------- CE actions  ---------------------------------------------- */
 
-    case CA_SET_CE_SCORE:
-    {
-      ei->collect_score = action_arg_number_new;
-
-      break;
-    }
-
     case CA_SET_CE_VALUE:
     {
 #if USE_NEW_CUSTOM_VALUE
@@ -8211,6 +8227,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page)
       break;
     }
 
+    case CA_SET_CE_SCORE:
+    {
+      ei->collect_score = action_arg_number_new;
+
+      break;
+    }
+
     /* ---------- engine actions  ------------------------------------------ */
 
     case CA_SET_ENGINE_SCAN_MODE:
@@ -8311,7 +8334,10 @@ static void CreateElementFromChange(int x, int y, int element)
 
 static boolean ChangeElement(int x, int y, int element, int page)
 {
-  struct ElementChangeInfo *change = &element_info[element].change_page[page];
+  struct ElementInfo *ei = &element_info[element];
+  struct ElementChangeInfo *change = &ei->change_page[page];
+  int ce_value = CustomValue[x][y];
+  int ce_score = ei->collect_score;
   int target_element;
   int old_element = Feld[x][y];
 
@@ -8326,6 +8352,7 @@ static boolean ChangeElement(int x, int y, int element, int page)
     change->actual_trigger_player = EL_PLAYER_1;
     change->actual_trigger_side = CH_SIDE_NONE;
     change->actual_trigger_ce_value = 0;
+    change->actual_trigger_ce_score = 0;
   }
 
   /* do not change elements more than a specified maximum number of changes */
@@ -8430,7 +8457,8 @@ static boolean ChangeElement(int x, int y, int element, int page)
          ChangeEvent[ex][ey] = ChangeEvent[x][y];
 
          content_element = change->target_content.e[xx][yy];
-         target_element = GET_TARGET_ELEMENT(content_element, change);
+         target_element = GET_TARGET_ELEMENT(content_element, change,
+                                             ce_value, ce_score);
 
          CreateElementFromChange(ex, ey, target_element);
 
@@ -8451,7 +8479,8 @@ static boolean ChangeElement(int x, int y, int element, int page)
   }
   else
   {
-    target_element = GET_TARGET_ELEMENT(change->target_element, change);
+    target_element = GET_TARGET_ELEMENT(change->target_element, change,
+                                       ce_value, ce_score);
 
     if (element == EL_DIAGONAL_GROWING ||
        element == EL_DIAGONAL_SHRINKING)
@@ -8685,6 +8714,7 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
        change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
        change->actual_trigger_side = trigger_side;
        change->actual_trigger_ce_value = CustomValue[trigger_x][trigger_y];
+       change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
 
        if ((change->can_change && !change_done) || change->has_action)
        {
@@ -8789,6 +8819,7 @@ static boolean CheckElementChangeExt(int x, int y,
       change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
       change->actual_trigger_side = trigger_side;
       change->actual_trigger_ce_value = CustomValue[x][y];
+      change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
 
       /* special case: trigger element not at (x,y) position for some events */
       if (check_trigger_element)
@@ -8811,6 +8842,7 @@ static boolean CheckElementChangeExt(int x, int y,
        int yy = y + move_xy[MV_DIR_OPPOSITE(trigger_side)].dy;
 
        change->actual_trigger_ce_value = CustomValue[xx][yy];
+       change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element);
       }
 
       if (change->can_change && !change_done)
@@ -9168,6 +9200,11 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
 {
   int i;
 
+#if 0
+  Error(ERR_NETWORK_CLIENT, "advancing frame counter from %d to %d",
+       FrameCounter, FrameCounter + 1);
+#endif
+
   /* advance frame counters (global frame counter and time frame counter) */
   FrameCounter++;
   TimeFrames++;
@@ -9218,15 +9255,10 @@ void AdvanceFrameAndPlayerCounters(int player_nr)
 void StartGameActions(boolean init_network_game, boolean record_tape,
                      long random_seed)
 {
-#if 1
   unsigned long new_random_seed = InitRND(random_seed);
 
   if (record_tape)
     TapeStartRecording(new_random_seed);
-#else
-  if (record_tape)
-    TapeStartRecording(random_seed);
-#endif
 
 #if defined(NETWORK_AVALIABLE)
   if (init_network_game)
@@ -9241,10 +9273,6 @@ void StartGameActions(boolean init_network_game, boolean record_tape,
 
   game_status = GAME_MODE_PLAYING;
 
-#if 0
-  InitRND(random_seed);
-#endif
-
   InitGame();
 }
 
@@ -9311,11 +9339,19 @@ void GameActions()
 
     if (!network_player_action_received)
       return;          /* failed to get network player actions in time */
+
+    /* do not yet reset "network_player_action_received" (for tape.pausing) */
   }
 
   if (tape.pausing)
     return;
 
+  /* at this point we know that we really continue executing the game */
+
+#if 1
+  network_player_action_received = FALSE;
+#endif
+
   recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
 
   if (tape.set_centered_player)
@@ -9483,7 +9519,9 @@ void GameActions_RND()
     ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
   }
 
+#if 0
   network_player_action_received = FALSE;
+#endif
 
   ScrollScreen(NULL, SCROLL_GO_ON);
 
@@ -12673,7 +12711,7 @@ void RequestQuitGame(boolean ask_if_really_quit)
   {
 #if defined(NETWORK_AVALIABLE)
     if (options.network)
-      SendToServer_StopPlaying();
+      SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER);
     else
 #endif
     {
@@ -12850,7 +12888,10 @@ static void HandleGameButtons(struct GadgetInfo *gi)
   switch (id)
   {
     case GAME_CTRL_ID_STOP:
-      RequestQuitGame(TRUE);
+      if (tape.playing)
+       TapeStop();
+      else
+       RequestQuitGame(TRUE);
       break;
 
     case GAME_CTRL_ID_PAUSE:
@@ -12877,7 +12918,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
 #endif
        {
          tape.pausing = FALSE;
-         DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+         DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF, 0);
        }
       }
       break;