llListRandomize() wasn't very random

Signed-off-by: Diva Canto <diva@metaverseink.com>
fsassets
Cinder 2015-05-27 08:55:49 -06:00 committed by Diva Canto
parent f0533132eb
commit 0af17c9484
2 changed files with 58 additions and 6 deletions

View File

@ -3036,4 +3036,55 @@ namespace OpenSim.Framework
}
}
}
public class BetterRandom
{
private const int BufferSize = 1024; // must be a multiple of 4
private byte[] RandomBuffer;
private int BufferOffset;
private RNGCryptoServiceProvider rng;
public BetterRandom()
{
RandomBuffer = new byte[BufferSize];
rng = new RNGCryptoServiceProvider();
BufferOffset = RandomBuffer.Length;
}
private void FillBuffer()
{
rng.GetBytes(RandomBuffer);
BufferOffset = 0;
}
public int Next()
{
if (BufferOffset >= RandomBuffer.Length)
{
FillBuffer();
}
int val = BitConverter.ToInt32(RandomBuffer, BufferOffset) & 0x7fffffff;
BufferOffset += sizeof(int);
return val;
}
public int Next(int maxValue)
{
return Next() % maxValue;
}
public int Next(int minValue, int maxValue)
{
if (maxValue < minValue)
{
throw new ArgumentOutOfRangeException("maxValue must be greater than or equal to minValue");
}
int range = maxValue - minValue;
return minValue + Next(range);
}
public double NextDouble()
{
int val = Next();
return (double)val / int.MaxValue;
}
public void GetBytes(byte[] buff)
{
rng.GetBytes(buff);
}
}
}

View File

@ -5631,7 +5631,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_List llListRandomize(LSL_List src, int stride)
{
LSL_List result;
Random rand = new Random();
BetterRandom rand = new BetterRandom();
int chunkk;
int[] chunks;
@ -5647,24 +5647,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// If not, then return the src list. This also
// traps those cases where stride > length.
if (src.Length != stride && src.Length%stride == 0)
if (src.Length != stride && src.Length % stride == 0)
{
chunkk = src.Length/stride;
chunks = new int[chunkk];
for (int i = 0; i < chunkk; i++)
{
chunks[i] = i;
}
// Knuth shuffle the chunkk index
for (int i = chunkk - 1; i >= 1; i--)
for (int i = chunkk - 1; i > 0; i--)
{
// Elect an unrandomized chunk to swap
int index = rand.Next(i + 1);
int tmp;
// and swap position with first unrandomized chunk
tmp = chunks[i];
int tmp = chunks[i];
chunks[i] = chunks[index];
chunks[index] = tmp;
}
@ -5677,7 +5678,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
for (int j = 0; j < stride; j++)
{
result.Add(src.Data[chunks[i]*stride+j]);
result.Add(src.Data[chunks[i] * stride + j]);
}
}
}