public override void Generate(Color[] pixels, int width, int height) { base.Generate(pixels, width, height); // An array which will contain the procedurally generated heights float[] heights = new float[width]; // Perform midpoint displacement Noise.MPD(heights, roughness, () => (float)PRNG.NextDouble()); // Normalize line to better fit in image MMath.Normalize( heights, height * imagePadding, height - height * imagePadding - 1); // Fill image with white Fill(pixels, Color.white); // Draw 2D landscape on image for (int x = 0; x < width; x++) { // Place the pixel in the image pixels[(int)heights[x] * width + x] = Color.black; // Create a line between unconnected neighbors if (x > 0 && Math.Abs(heights[x - 1] - heights[x]) > 1) { // Determine high and low neighbor points int xHigh, xLow; int toFill = Math.Abs((int)heights[x - 1] - (int)heights[x]) / 2; int yHigh = Math.Max((int)heights[x - 1], (int)heights[x]); int yLow = Math.Min((int)heights[x - 1], (int)heights[x]); if (yHigh == (int)heights[x - 1]) { xHigh = x - 1; xLow = x; } else { xHigh = x; xLow = x - 1; } // Vertically connect high and low neighbor points for (int dy = 1; dy <= toFill; dy++) { pixels[(yHigh - dy) * width + xHigh] = Color.black; if ((yHigh - dy) != (yLow + dy)) { pixels[(yLow + dy) * width + xLow] = Color.black; } } } } }
public override void Generate(float[,] heights) { // Apply faults for (int i = 0; i < numFaults; i++) { Landscape.FaultModifier( heights, meanDepth, () => (float)PRNG.NextDouble(), decreaseDistance); } }
public override void Generate(Color[] pixels, int width, int height) { base.Generate(pixels, width, height); // Fill vector of pixels with random black or white pixels for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { // Get a random value between 0 and 1 double val = PRNG.NextDouble(); // Determine color based on obtained random value Color color = val > blackChance ? Color.white : Color.black; // Set color in pixels array pixels[i * width + j] = color; } } }
// TODO Move CA1D generic functionality to libGameAI public override void Generate(Color[] pixels, int width, int height) { base.Generate(pixels, width, height); // Array of colors to generate according to the three previous // bits (2^3 = 8 values) Color[] ruleList = new Color[bitsInByte]; // Local copy of rule int localRule = rule; // Get colors to generate according to three previous bits for (int i = 0; i < bitsInByte; i++) { int bit = localRule & 1; ruleList[i] = bit == 1 ? Color.black : Color.white; localRule >>= 1; } // Initialize first (bottom) line if (singleCenterPixel) { for (int i = 0; i < width; i++) { pixels[i] = Color.white; } // Put just one black pixel in the middle pixels[width / 2] = Color.black; } else { // Randomly initialize the bottom line for (int i = 0; i < width; i++) { pixels[i] = PRNG.NextDouble() < 0.5 ? Color.white : Color.black; } } // Run cellular automata rule on image for (int i = 1; i < height; i++) { for (int j = 0; j < width; j++) { // Find indexes of rule bits in previous line int i2 = j > 0 ? j - 1 : width - 1; int i1 = j; int i0 = j < width - 1 ? j + 1 : 0; // Get bits in previous line int v2 = pixels[(i - 1) * width + i2] == Color.black ? 1 : 0; int v1 = pixels[(i - 1) * width + i1] == Color.black ? 1 : 0; int v0 = pixels[(i - 1) * width + i0] == Color.black ? 1 : 0; // Get rule index int ruleIdx = (v2 << 2) + (v1 << 1) + v0; // Apply rule to current position pixels[i * width + j] = ruleList[ruleIdx]; } } }
public override void Generate(float[,] heights) { Landscape.DiamondSquare(heights, maxInitHeight, roughness, () => (float)PRNG.NextDouble()); }
// TODO Move CA2D generic functionality to libGameAI public override void Generate(Color[] pixels, int width, int height) { base.Generate(pixels, width, height); Color[] aux; Color[] buf1 = new Color[pixels.Length]; Color[] buf2 = new Color[pixels.Length]; // Randomly place rocks in the scenario for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { // Put rock or floor, randomly buf1[i * width + j] = PRNG.NextDouble() < initRocks ? ROCK : FLOOR; } } // Run cellular automata for (int step = 0; step < steps; step++) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { // How many rocks around here? int numRocks = CountRocks(buf1, width, height, i, j, neighSize); // Put rock or floor, randomly buf2[i * width + j] = numRocks >= rockThreshold ? ROCK : FLOOR; } } // Swap buffers aux = buf1; buf1 = buf2; buf2 = aux; } // Post-process border rocks for visual effect if (drawRockOutline) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (buf1[i * width + j] == ROCK) { // How many rocks around here? int numRocks = CountRocks(buf1, width, height, i, j, 1); if (numRocks < 9) { // Put border rock buf1[i * width + j] = BORDER; } } } } } // Copy buf1 data to pixels for (int i = 0; i < pixels.Length; i++) { pixels[i] = buf1[i]; } }
public void TestPRNG() { const int iterations = 5000000; Console.WriteLine(); int trues = 0; int larger = 0; int smaller = 0; for (int i = 0; i < iterations; i++) { if (PRNG.NextBool()) { trues++; } int val = PRNG.Next(5, 8); // 5, 6 or 7 switch (val) { case 5: smaller++; break; case 6: break; case 7: larger++; break; default: Assert.Fail("Value " + val + " isn't 5, 6 or 7"); break; } // ranged var r1 = (int)PRNG.NextUInt32(); var r2 = (int)PRNG.NextUInt32(); if (r1 < r2) { var rr = PRNG.Next(r1, r2); Assert.IsTrue(rr >= r1 && rr < r2, rr.ToString() + " is not between " + r1 + " and " + r2); } else if (r1 > r2) { var rr = PRNG.Next(r2, r1); Assert.IsTrue(rr >= r2 && rr < r1, rr.ToString() + " is not between " + r2 + " and " + r1); } } var p = (double)trues / (double)iterations; Assert.IsTrue(p > 0.495 && p < 0.505); const double third = 1.0 / 3.0; const double offset = third * 0.05; const double low = third - offset; const double high = third + offset; p = (double)smaller / (double)iterations; Assert.IsTrue(p > low && p < high); p = (double)larger / (double)iterations; Assert.IsTrue(p > low && p < high); // make sure nextdouble() and nextfloat() don't generate numbers outside range var state = RandomSeed.GetUInt64(); for (int r = 0; r < 10000000; r++) { double d = PRNG.NextDouble(ref state); Assert.IsTrue(d >= 0.0 && d < 1.0); float f = PRNG.NextFloat(ref state); Assert.IsTrue(f >= 0.0f && f < 1.0f); } }