rnd-20051125-1-src
[rocksndiamonds.git] / src / files.c
index 6e1c770f0fcfb4afd19666a82c8e6ea7ad2afda9..f5275728156c3e921462a8cf5d030149262672b1 100644 (file)
@@ -88,11 +88,12 @@ void setElementChangePages(struct ElementInfo *ei, int change_pages)
 
 void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 {
-  int x, y;
+  int i, x, y;
 
   change->can_change = FALSE;
 
-  change->events = CE_BITMASK_DEFAULT;
+  for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+    change->has_event[i] = FALSE;
 
   change->trigger_player = CH_PLAYER_ANY;
   change->trigger_side = CH_SIDE_ANY;
@@ -113,6 +114,11 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
   change->random_percentage = 100;
   change->replace_when = CP_WHEN_EMPTY;
 
+  change->has_action = FALSE;
+  change->action_type = CA_NO_ACTION;
+  change->action_mode = CA_MODE_UNDEFINED;
+  change->action_arg = CA_ARG_UNDEFINED;
+
   for (x = 0; x < 3; x++)
     for (y = 0; y < 3; y++)
       change->target_content[x][y] = EL_EMPTY_SPACE;
@@ -171,8 +177,11 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
 
   level->block_last_field = FALSE;     /* EM does not block by default */
   level->sp_block_last_field = TRUE;   /* SP blocks the last field */
+
+#if 0  /* !!! THIS IS NOT A LEVEL SETTING => LOGIC MOVED TO "game.c" !!! */
   level->block_delay = 8;              /* when blocking, block 8 frames */
   level->sp_block_delay = 9;           /* SP indeed blocks 9 frames, not 8 */
+#endif
 
   level->can_move_into_acid_bits = ~0; /* everything can move into acid */
   level->dont_collide_with_bits = ~0;  /* always deadly when colliding */
@@ -289,6 +298,9 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
       element_info[element].explosion_delay = 16;
       element_info[element].ignition_delay = 8;
 
+      element_info[element].counter_initial = 0;
+      element_info[element].counter = 0;
+
       for (x = 0; x < 3; x++)
        for (y = 0; y < 3; y++)
          element_info[element].content[x][y] = EL_EMPTY_SPACE;
@@ -1087,6 +1099,7 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
   for (i = 0; i < num_changed_custom_elements; i++)
   {
     int element = getFile16BitBE(file);
+    unsigned long event_bits;
 
     if (!IS_CUSTOM_ELEMENT(element))
     {
@@ -1125,7 +1138,10 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
        element_info[element].content[x][y] =
          getMappedElement(getFile16BitBE(file));
 
-    element_info[element].change->events = getFile32BitBE(file);
+    event_bits = getFile32BitBE(file);
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (event_bits & (1 << j))
+       element_info[element].change->has_event[j] = TRUE;
 
     element_info[element].change->target_element =
       getMappedElement(getFile16BitBE(file));
@@ -1167,7 +1183,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   struct ElementInfo *ei;
   int chunk_size_expected;
   int element;
-  int i, x, y;
+  int i, j, x, y;
 
   element = getFile16BitBE(file);
 
@@ -1249,11 +1265,15 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   for (i = 0; i < ei->num_change_pages; i++)
   {
     struct ElementChangeInfo *change = &ei->change_page[i];
+    unsigned long event_bits;
 
     /* always start with reliable default values */
     setElementChangeInfoToDefaults(change);
 
-    change->events = getFile32BitBE(file);
+    event_bits = getFile32BitBE(file);
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (event_bits & (1 << j))
+       change->has_event[j] = TRUE;
 
     change->target_element = getMappedElement(getFile16BitBE(file));
 
@@ -1286,8 +1306,18 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
     change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ?
                            CH_PAGE_ANY : (1 << change->trigger_page));
 
+#if 1
+    change->has_action = getFile8Bit(file);
+    change->action_type = getFile8Bit(file);
+    change->action_mode = getFile8Bit(file);
+    change->action_arg = getFile16BitBE(file);
+
+    /* some free bytes for future change property values and padding */
+    ReadUnusedBytesFromFile(file, 1);
+#else
     /* some free bytes for future change property values and padding */
     ReadUnusedBytesFromFile(file, 6);
+#endif
 
 #else
 
@@ -2589,10 +2619,13 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       level->use_spring_bug = TRUE;
 
     /* only few elements were able to actively move into acid before 3.1.0 */
+    /* trigger settings did not exist before 3.1.0; set to default "any" */
     if (level->game_version < VERSION_IDENT(3,1,0,0))
     {
       int i, j;
 
+      /* correct "can move into acid" settings (all zero in old levels) */
+
       level->can_move_into_acid_bits = 0; /* nothing can move into acid */
       level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */
 
@@ -2604,6 +2637,8 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
        SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, TRUE);
 
+      /* correct trigger settings (stored as zero == "none" in old levels) */
+
       for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
       {
        int element = EL_CUSTOM_START + i;
@@ -2619,6 +2654,7 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       }
     }
 
+#if 0  /* !!! MOVED TO "game.c", BECAUSE CAN CHANGE INSIDE LEVEL EDITOR !!! */
 #if 1  /* USE_NEW_BLOCK_STYLE */
     /* blocking the last field when moving was corrected in version 3.1.1 */
     if (level->game_version < VERSION_IDENT(3,1,1,0))
@@ -2635,6 +2671,8 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       level->sp_block_last_field = TRUE;
     }
 #endif
+#endif
+
   }
   else         /* always use the latest game engine version */
   {
@@ -2683,7 +2721,8 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
   int i, j, x, y;
 
   /* map custom element change events that have changed in newer versions
-     (these following values were accidentally changed in version 3.0.1) */
+     (these following values were accidentally changed in version 3.0.1)
+     (this seems to be needed only for 'ab_levelset3' and 'ab_levelset4') */
   if (level->game_version <= VERSION_IDENT(3,0,0,0))
   {
     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -2691,7 +2730,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
       int element = EL_CUSTOM_START + i;
 
       /* order of checking and copying events to be mapped is important */
-      for (j = CE_BY_OTHER_ACTION; j >= CE_BY_PLAYER_OBSOLETE; j--)
+      for (j = CE_BY_OTHER_ACTION; j >= CE_COUNT_AT_ZERO; j--)
       {
        if (HAS_CHANGE_EVENT(element, j - 2))
        {
@@ -2701,7 +2740,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
       }
 
       /* order of checking and copying events to be mapped is important */
-      for (j = CE_OTHER_GETS_COLLECTED; j >= CE_HITTING_SOMETHING; j--)
+      for (j = CE_PLAYER_COLLECTS_X; j >= CE_HITTING_SOMETHING; j--)
       {
        if (HAS_CHANGE_EVENT(element, j - 1))
        {
@@ -2712,20 +2751,30 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
     }
   }
 
+#if 0
+  /* !!! TESTS SHOWED THAT THIS CODE SEGMENT IS NOT NEEDED FOR ANY LEVEL !!! */
+
   /* some custom element change events get mapped since version 3.0.3 */
-  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+#if 1
+  if (level->game_version >= VERSION_IDENT(3,0,3,0) &&
+      level->game_version <= VERSION_IDENT(3,2,0,3))
+#endif
   {
-    int element = EL_CUSTOM_START + i;
-
-    if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) ||
-       HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE))
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
     {
-      SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
-      SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
+      int element = EL_CUSTOM_START + i;
+
+      if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) ||
+         HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE))
+      {
+       SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
+       SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
 
-      SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
+       SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
+      }
     }
   }
+#endif
 
   /* initialize "can_change" field for old levels with only one change page */
   if (level->game_version <= VERSION_IDENT(3,0,2,0))
@@ -2740,20 +2789,23 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
   }
 
   /* correct custom element values (for old levels without these options) */
-  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+  if (level->game_version < VERSION_IDENT(3,1,1,0))
   {
-    int element = EL_CUSTOM_START + i;
-    struct ElementInfo *ei = &element_info[element];
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+    {
+      int element = EL_CUSTOM_START + i;
+      struct ElementInfo *ei = &element_info[element];
 
-    if (ei->access_direction == MV_NO_MOVING)
-      ei->access_direction = MV_ALL_DIRECTIONS;
+      if (ei->access_direction == MV_NO_MOVING)
+       ei->access_direction = MV_ALL_DIRECTIONS;
 
-    for (j = 0; j < ei->num_change_pages; j++)
-    {
-      struct ElementChangeInfo *change = &ei->change_page[j];
+      for (j = 0; j < ei->num_change_pages; j++)
+      {
+       struct ElementChangeInfo *change = &ei->change_page[j];
 
-      if (change->trigger_side == CH_SIDE_NONE)
-       change->trigger_side = CH_SIDE_ANY;
+       if (change->trigger_side == CH_SIDE_NONE)
+         change->trigger_side = CH_SIDE_ANY;
+      }
     }
   }
 
@@ -3258,7 +3310,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
 static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
-  int i, x, y;
+  int i, j, x, y;
 
   putFile16BitBE(file, element);
 
@@ -3320,8 +3372,13 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
   for (i = 0; i < ei->num_change_pages; i++)
   {
     struct ElementChangeInfo *change = &ei->change_page[i];
+    unsigned long event_bits = 0;
+
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (change->has_event[j])
+       event_bits |= (1 << j);
 
-    putFile32BitBE(file, change->events);
+    putFile32BitBE(file, event_bits);
 
     putFile16BitBE(file, change->target_element);
 
@@ -3352,8 +3409,19 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
     putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE :
                       log_2(change->trigger_page)));
 
+#if 1
+
+    putFile8Bit(file, change->has_action);
+    putFile8Bit(file, change->action_type);
+    putFile8Bit(file, change->action_mode);
+    putFile16BitBE(file, change->action_arg);
+
+    /* some free bytes for future change property values and padding */
+    WriteUnusedBytesToFile(file, 1);
+#else
     /* some free bytes for future change property values and padding */
     WriteUnusedBytesToFile(file, 6);
+#endif
 
 #else
 
@@ -3670,7 +3738,7 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
 
   for (i = 0; i < tape->length; i++)
   {
-    if (i >= MAX_TAPELEN)
+    if (i >= MAX_TAPE_LEN)
       break;
 
     for (j = 0; j < MAX_PLAYERS; j++)
@@ -4038,7 +4106,7 @@ void DumpTape(struct TapeInfo *tape)
 
   for (i = 0; i < tape->length; i++)
   {
-    if (i >= MAX_TAPELEN)
+    if (i >= MAX_TAPE_LEN)
       break;
 
     printf("%03d: ", i);