rj-action-library/Runtime/Random/RandomEngine.cs

374 lines
7.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
public abstract class RandomEngine
{
public abstract float Next();
public float Value( float scalar )
{
return Next() * scalar;
}
public float Range( float a, float b)
{
return this.Next()*( b - a ) + a;
}
public float Sample( Curve curve )
{
return curve.Sample( Next() );
}
public float Polar()
{
return this.Next() * 2f - 1f;
}
public float Polar( float value )
{
return Polar() * value;
}
public bool Bool()
{
return this.Next() > 0.5f;
}
public bool Chance( float value )
{
return value / 100f >= Next();
}
public bool FlipCoin()
{
return Chance( 50f );
}
public float PercentageVariation( float variation )
{
var value = ( 100f - variation ) / 100f;
return Range( value, 1f / value );
}
public bool WithChanceOf( float value )
{
return ( this.Next() * 100 ) <= value ;
}
public Vector3 Between( Vector3 a, Vector3 b )
{
return a.Lerp( b, this.Next() );
}
public Color RandomHue( float saturation = 1f, float luminance = 0.5f)
{
var hue = Range( 0, 360 );
var color = new HSLColor( hue, saturation, luminance );
return color;
}
public Vector2 InRectangle( Vector2 min, Vector2 max )
{
var x = Mathf.Lerp( min.X, max.X, Next() );
var y = Mathf.Lerp( min.Y, max.Y, Next() );
return new Vector2( x, y );
}
public float AngleRadians()
{
return Range( 0, Mathf.Pi * 2f );
}
public Vector3 InCube()
{
return new Vector3( Polar(), Polar(), Polar() );
}
public Vector3 InsideCube( float size )
{
return InCube() * ( size * 0.5f );
}
public Vector3 InsideSphere()
{
var inCube = InCube();
if ( inCube.LengthSquared() > 1 )
{
inCube = inCube.Normalized() * Next();
}
return inCube;
}
public Vector3 OnSphere( float size )
{
return OnSphere() * size;
}
public Vector3 OnSphere()
{
var dir = InsideSphere();
while ( dir.LengthSquared() == 0 )
{
dir = InsideSphere();
}
return dir;
}
public Vector3 InSphere( float size )
{
return InsideSphere() * ( size * 0.5f );
}
public Color HSL( float hMin = 0 , float hMax = 360, float sMin = 1, float sMax = 1, float lMin = 0.5f, float lMax = 0.5f )
{
var h = Range( hMin, hMax );
var s = Range( sMin, sMax );
var l = Range( lMin, lMax );
return new HSLColor( h, s, l );
}
public int IntegerInclusive( int min, int max )
{
return (int) ( Mathf.Floor( this.Next() * ( max - min + 1 ) ) + min ) ;
}
public int IntegerInclusive( int max )
{
return IntegerInclusive( 0, max );
}
public int IntegerExclusive( int min, int max )
{
var nextValue = this.Next();
var randomValue = nextValue * ( max - min ) + min;
var value = (int) ( Mathf.Floor( randomValue ) );
return Mathf.Min( max - 1, value );
}
public int IntegerExclusive( int max )
{
return IntegerExclusive( 0, max );
}
public char From( string source )
{
var index = IntegerExclusive( source.Length );
return source[ index ];
}
public T From<T>( T[] array )
{
if ( array.Length == 0 )
{
return default ( T );
}
var index = IntegerExclusive( array.Length );
return array[ index ];
}
public T From<T>( HashSet<T> set )
{
var selectedIndex = IntegerExclusive( set.Count );
var currentIndex = 0;
foreach ( var e in set )
{
if ( selectedIndex == currentIndex )
{
return e;
}
currentIndex++;
}
return default( T );
}
public T FromValues<T>( T first, params T[] values )
{
if ( values.Length == 0 )
{
return first;
}
var index = IntegerExclusive( values.Length + 1 );
return index == 0 ? first : values[ index - 1 ];
}
public T From<T>( List<T> list )
{
if ( list.Count == 0 )
{
return default ( T );
}
var index = this.IntegerExclusive( 0, list.Count );
return list[ index ];
}
public T RemoveFrom<T>( List<T> list )
{
if ( list.Count == 0 )
{
return default ( T );
}
var index = this.IntegerExclusive( 0, list.Count );
var item = list[ index ];
list.RemoveAt( index );
return item;
}
public List<T> RemoveMutlipleFrom<T>( List<T> list, int amount )
{
if ( amount >= list.Count )
{
return list;
}
var items = new List<T>();
for ( int i = 0; i < amount; i++ )
{
var itemIndex = this.IntegerExclusive( 0, list.Count );
var item = list[ itemIndex ];
list.RemoveAt( itemIndex );
items.Add( item );
}
return items;
}
public T RemoveWeightedFrom<T>( List<T> list, List<float> weights )
{
if ( list == null || list.Count == 0 )
{
return default(T);
}
if ( list.Count == 1 )
{
return list[ 0 ];
}
var weightedSelection = RemoveMultipleWeightedFrom( list, weights, 1 );
return weightedSelection[ 0 ];
}
public List<T> RemoveMultipleWeightedFrom<T>( List<T> list, List<float> weights, int amount )
{
if ( amount >= list.Count )
{
return list;
}
var sumWeights = 0f;
weights.ForEach( w => sumWeights += w );
var selection = new List<T>();
for ( int i = 0; i < amount; i++ )
{
var number = Range( 0, sumWeights );
var index = _FindElementIndexWithWeights( weights, Range( 0, sumWeights ) );
var element = list[ index ];
var weight = weights[ index ];
list.RemoveAt( index );
sumWeights -= weight;
selection.Add( element );
}
return selection;
}
public int IndexFromUnnormalizedWeights( List<float> weights, float sumWeights = 0 )
{
if ( sumWeights <= 0 )
{
sumWeights = 0;
weights.ForEach( w => sumWeights += w );
}
return _FindElementIndexWithWeights( weights, Next() * sumWeights );
}
public int IndexFromCurveWeights( Curve curve, int numIndices )
{
var weights = new List<float>();
var sumWeights = 0f;
for ( int i = 0; i < numIndices; i++ )
{
var t = (float)i / ( numIndices - 1 );
var w = curve.Sample( t );
weights.Add( w );
sumWeights += w;
}
return IndexFromUnnormalizedWeights( weights, sumWeights );
}
public int IndexFromNormalizedWeights( List<float> weights, float sumWeights = 0 )
{
return IndexFromUnnormalizedWeights( weights, 1 );
}
int _FindElementIndexWithWeights( List<float> weights, float value )
{
var limit = 0f;
for ( int i = 0; i < weights.Count; i++ )
{
var before = limit;
limit += weights[ i ];
if ( before <= value && value < limit )
{
return i;
}
}
return weights.Count - 1;
}
}
public abstract class SeedableRandomEngine:RandomEngine
{
public abstract void SetSeed( int number );
public abstract object GetSeedState();
public abstract void SetSeedState( object seedState );
}
}