374 lines
7.9 KiB
C#
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 );
|
|
}
|
|
}
|