Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Example of using a 'control seed' in procedural generation to
- * force certain properties in the generation of worlds.
- * Originally discussed at: https://twitter.com/eigenbom/status/879479915610947585
- *
- * In this example I generate a 'town' of inhabitants. The distribution
- * of peasants and duchesses is typically uniform. But two bits of the seed
- * are reserved for overriding this distribution.
- *
- * In the code below I'm overriding every 4th town's distribution, but in a real
- * game this would be predictable, so instead you could monitor the history of
- * the previous N games and use that information to override the distribution.
- * (E.g., if a player hasn't seen a rich/poor town in 4 games then dramatically
- * increase the probability that one would occur.)
- *
- * The benefit of encoding the choice into the seed is that you can retain the
- * deterministic reproduction of worlds for debugging or sharing. The seed is no
- * longer a single number that is input into a RNG, but a more complex structure.
- *
- * Homework:
- * - You don't need to use bitfields, add extra data in other types: e.g., array.
- * - Record the N last seeds played and use that to determine the control bits.
- * - A seed like this could be 'hacked', by discovering the correlation between
- * bits and world properties. To resist this: encrypt or obfuscate it.
- *
- * Example output:
- * > clang++ seed.cpp -o seed --std=c++14; ./seed
- * Rich: D P D D D D D D
- * Random: P P P P P D P P
- * Random: P D P D D P P D
- * Random: P P P P D P P P
- * Rich: D D P D D D D D
- * Random: P P D D P P P P
- * Random: P P P D D P D D
- * Random: P P P P D P P D
- * Poor: P P P D P P P P
- * Random: D D D D D D D P
- *
- * Ben Porter 2017
- */
- #include <iostream>
- #include <random>
- using namespace std;
- // Seed structure with control mechanisms.
- struct Seed {
- int rng: 16; // 16 bits reserved for the RNG
- int setWealth: 1; // setting this bit overrides the wealth of a town
- int wealth: 1; // 0 = poor, 1 = rich
- };
- void generateTown(Seed seed){
- // Setup RNG
- auto engine = mt19937(seed.rng);
- auto random = bind(uniform_real_distribution<>(0, 1), engine);
- // Set richness of town to vary around 0.4
- float richness = 0.2 + random()*0.4; // normal balance
- if (seed.setWealth){
- // Force wealth
- if (seed.wealth) richness = 0.9; // rich
- else richness = 0.1; // poor
- }
- // Print town type
- if (seed.setWealth && seed.wealth) cout << "Rich: ";
- else if (seed.setWealth && !seed.wealth) cout << "Poor: ";
- else cout << "Random: ";
- // Generate and print citizens
- for (int i=0; i<8; i++){
- // P = peasant, D = duchess
- static const char* CITIZEN[2] = { "P", "D" };
- int index = (random() >= richness)?0:1;
- auto citizen = CITIZEN[index];
- cout << citizen << " ";
- }
- cout << "\n";
- }
- int main(){
- auto engine = mt19937(time(NULL));
- auto random = bind(uniform_real_distribution<>(0, 1), engine);
- auto randint = bind(uniform_int_distribution<int>(0, 9999), engine);
- const int NUM_TOWNS = 10;
- for (int i=0; i<NUM_TOWNS; i++){
- Seed seed = { randint(), 0, 0 };
- if (i%4 == 0){
- // Set every 4th town to be rich or poor
- // NB: You could track the history of games
- // and ensure the poor/rich towns alternate
- seed.setWealth = 1;
- seed.wealth = random() < 0.5 ? 0 : 1;
- }
- generateTown(seed);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement