added correcting random numbers for predictable slime in BD engine
authorHolger Schemel <info@artsoft.org>
Mon, 18 Mar 2024 07:55:38 +0000 (08:55 +0100)
committerHolger Schemel <info@artsoft.org>
Mon, 18 Mar 2024 07:56:52 +0000 (08:56 +0100)
src/files.c
src/game_bd/bd_cave.h
src/game_bd/bd_caveobject.c
src/main.h

index e519b9b77c9567b881f9531326a5aa661d3a5c63..a150f89146217d1842a5ab5c32157be031638d14 100644 (file)
@@ -310,6 +310,11 @@ static struct LevelFileConfigInfo chunk_config_INFO[] =
     TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(23),
     &li.bd_gravity_affects_all,                TRUE
   },
+  {
+    -1,                                        -1,
+    TYPE_INTEGER,                      CONF_VALUE_8_BIT(24),
+    &li.bd_cave_random_seed_c64,       0
+  },
 
   {
     -1,                                        -1,
@@ -3984,9 +3989,11 @@ static void CopyNativeLevel_RND_to_BD(struct LevelInfo *level)
   cave->amoeba_2_looks_like        = map_element_RND_to_BD(level->bd_amoeba_2_content_looks_like);
 
   cave->slime_predictable              = level->bd_slime_is_predictable;
+  cave->slime_correct_random           = level->bd_slime_correct_random;
   cave->level_slime_permeability[0]    = level->bd_slime_permeability_rate * 10000;
   cave->level_slime_permeability_c64[0]        = level->bd_slime_permeability_bits_c64;
   cave->level_slime_seed_c64[0]                = level->bd_slime_random_seed_c64;
+  cave->level_rand[0]                  = level->bd_cave_random_seed_c64;
 
   // level name
   strncpy(cave->name, level->name, sizeof(GdString));
@@ -4072,9 +4079,11 @@ static void CopyNativeLevel_BD_to_RND(struct LevelInfo *level)
   level->bd_amoeba_2_content_looks_like        = map_element_BD_to_RND(cave->amoeba_2_looks_like);
 
   level->bd_slime_is_predictable       = cave->slime_predictable;
+  level->bd_slime_correct_random       = cave->slime_correct_random;
   level->bd_slime_permeability_rate    = cave->level_slime_permeability[bd_level_nr] / 10000;
   level->bd_slime_permeability_bits_c64        = cave->level_slime_permeability_c64[bd_level_nr];
   level->bd_slime_random_seed_c64      = cave->level_slime_seed_c64[bd_level_nr];
+  level->bd_cave_random_seed_c64       = cave->level_rand[bd_level_nr];
 
   // level name
   char *cave_name = getStringPrint("%s / %d", cave->name, bd_level_nr + 1);
index b3133512ce2d6f2f197e1825223b2175f7497ced..e76c9c5c037c3fbd6a72f33b3c7989a2cec88704 100644 (file)
@@ -432,6 +432,7 @@ typedef struct _gd_cave
   int level_slime_permeability_c64[5];  // Appearing in bd 2
   int level_slime_seed_c64[5];          // predictable slime random seed
   boolean slime_predictable;            // predictable random start for slime. yes for plck.
+  boolean slime_correct_random;         // correct random number generator for rendered caves
   GdElement slime_eats_1, slime_converts_1; // slime eats element x and converts to element x;
                                             // for example diamond -> falling diamond
   GdElement slime_eats_2, slime_converts_2; // this is usually stone -> stone_f
index 6d5ca42284c9dcd3d6208207a46fd274ace80d0e..cea246fafa57221ee772f9f7a48fbc9fac136b9e 100644 (file)
@@ -1488,6 +1488,9 @@ GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const unsigned
       gd_cave_store_rc(cave, x,           0, cave->initial_border, NULL);
       gd_cave_store_rc(cave, x, cave->h - 1, cave->initial_border, NULL);
     }
+
+    // store if random number generator needs correction for static random seed
+    cave->slime_correct_random = (data->level_rand[level] >= 0);
   }
   else
   {
@@ -1496,6 +1499,18 @@ GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const unsigned
     // initialize c64 predictable random for slime.
     // the values were taken from afl bd, see docs/internals.txt
     gd_cave_c64_random_set_seed(cave, 0, 0x1e);
+
+    // correct random number generator if cave was rendered with static random seed
+    if (cave->slime_correct_random)
+    {
+      int i;
+
+      // set static random seed used when rendering the cave
+      gd_cave_c64_random_set_seed(cave, 0, data->level_rand[level]);
+
+      for (i = 0; i < cave->w * (cave->h - 2); i++)
+       gd_cave_c64_random(cave);
+    }
   }
 
   if (data->level_slime_seed_c64[level] != -1)
index 96c72b29f9c66cdc28196a59d78c1a1657d29e06..36fbdb5cdc6783ea3700e37caed5cc7860f2e680 100644 (file)
@@ -3523,9 +3523,11 @@ struct LevelInfo
   boolean bd_voodoo_vanish_by_explosion;// BD voodoo doll can be destroyed by explosions
   int bd_voodoo_penalty_time;          // BD engine penalty time when voodoo doll destroyed
   boolean bd_slime_is_predictable;     // BD slime uses predictable random number generator
+  boolean bd_slime_correct_random;     // BD slime needs corrected random number generator
   int bd_slime_permeability_rate;      // BD slime permeability rate for unpredictable slime
   int bd_slime_permeability_bits_c64;  // BD slime permeability bits for predictable slime
   int bd_slime_random_seed_c64;                // BD slime random number seed for predictable slime
+  int bd_cave_random_seed_c64;         // BD cave random number seed for predictable slime
   boolean em_slippery_gems;            // EM style "gems slip from wall" behaviour
   boolean em_explodes_by_fire;         // EM style chain explosion behaviour
   boolean use_spring_bug;              // for compatibility with old levels