Advertisement
eigenbom

Control Seed

Jun 29th, 2017
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.55 KB | None | 0 0
  1. /*
  2.  * Example of using a 'control seed' in procedural generation to
  3.  * force certain properties in the generation of worlds.  
  4.  * Originally discussed at: https://twitter.com/eigenbom/status/879479915610947585
  5.  *
  6.  * In this example I generate a 'town' of inhabitants. The distribution
  7.  * of peasants and duchesses is typically uniform. But two bits of the seed
  8.  * are reserved for overriding this distribution.
  9.  *
  10.  * In the code below I'm overriding every 4th town's distribution, but in a real
  11.  * game this would be predictable, so instead you could monitor the history of
  12.  * the previous N games and use that information to override the distribution.
  13.  * (E.g., if a player hasn't seen a rich/poor town in 4 games then dramatically
  14.  * increase the probability that one would occur.)
  15.  *
  16.  * The benefit of encoding the choice into the seed is that you can retain the
  17.  * deterministic reproduction of worlds for debugging or sharing. The seed is no
  18.  * longer a single number that is input into a RNG, but a more complex structure.
  19.  *
  20.  * Homework:
  21.  * - You don't need to use bitfields, add extra data in other types: e.g., array.
  22.  * - Record the N last seeds played and use that to determine the control bits.
  23.  * - A seed like this could be 'hacked', by discovering the correlation between
  24.  *   bits and world properties. To resist this: encrypt or obfuscate it.
  25.  *
  26.  * Example output:
  27.  * > clang++ seed.cpp -o seed --std=c++14; ./seed
  28.  * Rich:   D P D D D D D D
  29.  * Random: P P P P P D P P
  30.  * Random: P D P D D P P D
  31.  * Random: P P P P D P P P
  32.  * Rich:   D D P D D D D D
  33.  * Random: P P D D P P P P
  34.  * Random: P P P D D P D D
  35.  * Random: P P P P D P P D
  36.  * Poor:   P P P D P P P P
  37.  * Random: D D D D D D D P
  38.  *
  39.  * Ben Porter 2017
  40.  */
  41.  
  42. #include <iostream>
  43. #include <random>
  44. using namespace std;
  45.  
  46. // Seed structure with control mechanisms.
  47. struct Seed {
  48.     int rng: 16;      // 16 bits reserved for the RNG
  49.     int setWealth: 1; // setting this bit overrides the wealth of a town
  50.     int wealth: 1;    // 0 = poor, 1 = rich
  51. };
  52.  
  53. void generateTown(Seed seed){
  54.     // Setup RNG
  55.     auto engine = mt19937(seed.rng);
  56.     auto random = bind(uniform_real_distribution<>(0, 1), engine);
  57.  
  58.     // Set richness of town to vary around 0.4
  59.     float richness = 0.2 + random()*0.4; // normal balance
  60.     if (seed.setWealth){
  61.         // Force wealth
  62.         if (seed.wealth) richness = 0.9; // rich
  63.         else richness = 0.1; // poor
  64.     }
  65.  
  66.     // Print town type
  67.     if (seed.setWealth && seed.wealth) cout << "Rich:   ";
  68.     else if (seed.setWealth && !seed.wealth) cout << "Poor:   ";
  69.     else cout << "Random: ";
  70.     // Generate and print citizens
  71.     for (int i=0; i<8; i++){
  72.         // P = peasant, D = duchess
  73.         static const char* CITIZEN[2] = { "P", "D" };
  74.         int index = (random() >= richness)?0:1;
  75.         auto citizen = CITIZEN[index];
  76.         cout << citizen << " ";
  77.     }
  78.     cout << "\n";
  79. }
  80.  
  81. int main(){
  82.     auto engine = mt19937(time(NULL));
  83.     auto random = bind(uniform_real_distribution<>(0, 1), engine);
  84.     auto randint = bind(uniform_int_distribution<int>(0, 9999), engine);
  85.     const int NUM_TOWNS = 10;
  86.     for (int i=0; i<NUM_TOWNS; i++){
  87.         Seed seed = { randint(), 0, 0 };
  88.         if (i%4 == 0){
  89.             // Set every 4th town to be rich or poor
  90.             // NB: You could track the history of games
  91.             // and ensure the poor/rich towns alternate
  92.             seed.setWealth = 1;
  93.             seed.wealth = random() < 0.5 ? 0 : 1;
  94.         }
  95.         generateTown(seed);
  96.     }
  97.     return 0;
  98. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement