// CIRCLE with R=1 public static Vector2 Circle(ref NPack.MersenneTwister _rand) { float t = (float)_rand.Next(); float _2pi = (float)Math.PI * 2; float a = SpecialFunctions.ScaleFloatToRange(t, 0, _2pi, 0, Int32.MaxValue); return(new Vector2((float)Math.Cos(a), (float)Math.Sin(a))); }
private static Vector3 PickCubePoints(ref NPack.MersenneTwister _rand) { float x = SpecialFunctions.ScaleFloatToRange(_rand.NextSingle(true), -1, 1, 0, 1); float y = SpecialFunctions.ScaleFloatToRange(_rand.NextSingle(true), -1, 1, 0, 1); float z = SpecialFunctions.ScaleFloatToRange(_rand.NextSingle(true), -1, 1, 0, 1); return(new Vector3(x, y, z)); }
// CONSTRUCTOR public DiceRoll(int size, DiceType type, ref NPack.MersenneTwister _rand) { if (size < 1) { throw new ArgumentOutOfRangeException("Number of dices shlud be > 0"); } init(size, type, ref _rand); }
static void TestSuper() { Random random = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; SuperOptStrategy b = new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier); //PseudoOptStrategy b = new PseudoOptStrategy(); Game game = new Game(rules, b, pp_multiplier, random); game.PlayerMoney = 0; double expected_money = (double)game.PlayerMoney; game.Bet = 100; // 1$ int lowest = game.PlayerMoney, highest = game.PlayerMoney; int runs = 0; while (true) { double total_money = (game.PlayerMoney + pp_multiplier * game.PartyPoints) / 100.0; if (runs % 10000 == 0) { Console.WriteLine("runs: " + runs + " win: " + (double)game.PlayerMoney / 100.0 + "$" + " pp: " + game.party_points); Console.WriteLine("lowest: " + (double)lowest / 100.0 + "$" + " highest: " + (double)highest / 100.0 + "$"); Console.WriteLine("total: " + total_money + "$ | expected: " + expected_money / 100.0 + "$"); Console.WriteLine(); } game.StartRound(); game.DealRound(); expected_money += b.ShoeEV() * game.Bet; if (game.PlayerMoney < lowest) { lowest = game.PlayerMoney; } if (game.PlayerMoney > highest) { highest = game.PlayerMoney; } runs++; } }
public static Vector2 Disk(ref NPack.MersenneTwister _rand) { // t [0,1] , Theta [0,2pi) double t = _rand.NextSingle(true); // in range [0,1) then multiply this number by k to get a random number in the range [0,k) double theta = _rand.NextSingle(false) * 2 * Math.PI; return(new Vector2((float)(Math.Sqrt(t) * Math.Cos(theta)), (float)(Math.Sqrt(t) * Math.Sin(theta)))); }
/// FROM: http://unifycommunity.com/wiki/index.php?title=UnitSphere /// <summary> /// Returns a point on the unit sphere that is within a cone along the z-axis /// </summary> /// <param name="spotAngle">[0..180] specifies the angle of the cone. </param> public static Vector3 GetPointOnCap(float spotAngle, ref NPack.MersenneTwister _rand) { float angle1 = SpecialFunctions.ScaleFloatToRange(_rand.NextSingle(true), 0.0f, Mathf.PI * 2, 0, 1); float angle2 = SpecialFunctions.ScaleFloatToRange(_rand.NextSingle(true), 0.0f, spotAngle * Mathf.Deg2Rad, 0, 1); Vector3 V = new Vector3(Mathf.Sin(angle1), Mathf.Cos(angle1), 0); V *= Mathf.Sin(angle2); V.z = Mathf.Cos(angle2); return(V); }
public static Vector3 Volume(ref NPack.MersenneTwister _rand) { Vector3 pos = PickCubePoints(ref _rand); while (isNotInsideSphere(pos)) { pos = PickCubePoints(ref _rand); } return(pos); }
// RADIUS = 1 // Marsaglia Method (1972) I use for Surface and Volume // FROM http://stackoverflow.com/questions/5531827/random-point-on-a-given-sphere // ALSO: http://mathworld.wolfram.com/SpherePointPicking.html // 1. Pick a random point inside the [-1,1]x[-1,1]x[-1,1] cube // 2. If x*x + y*y + z*z > 1 repeat from 1 // 3. Normalize dividing x, y and z by Math.sqrt(x*x + y*y + z*z) public static Vector3 Surface(ref NPack.MersenneTwister _rand) { Vector3 pos = PickCubePoints(ref _rand); while (IsNotOnSurface(pos)) { pos = PickCubePoints(ref _rand); } return(Normalize(pos)); }
// INIT private void init(int size, DiceType type, ref NPack.MersenneTwister _rand) { _result = new int[size]; _dice_type = type; _size = size; for (int i = 0; i < _size; i++) { // Cast enum to int to get the value _result[i] = _rand.Next(1, (int)type); } }
static void Main(string[] args) { /*for (int roll = 1000; roll <= 50000; roll+=1000) * { * Console.WriteLine("{0}: P: {1:######} K: {2:######}", * roll, * system.BetSize(0, roll * 100) / 100, * kelly.BetSize(0.005, roll) / 100); * } * * for (double ev = 0; ev <= 0.0085; ev += 0.0005) * { * Console.WriteLine("{0:0.0000}: {1}", ev, kelly.BetSize(ev, 25000) / 100); * } * * return; */ /*Shoe shoe = new Shoe(8); * shoe.Remove(new CardSet(new Card[] { new Card("5c"), new Card("8c"), new Card("3h") })); * * BjEval.Eval.CacheDealerProbs(5, shoe.ToArray()); * Console.WriteLine(BjEval.Eval.DoubleEv(new SHand() { Total = 11, Soft = false }, 5, 100, shoe.ToArray())); * * return; */ //GeneralTest(); //CompareStrategies(); //TestSuper(); /*ProportionalBetting proportional = new ProportionalBetting(225, 25 * 100, 200 * 100); * KellyBetting kelly = new KellyBetting(0.008, 25 * 100, 200 * 100); * * double ev_cutoff = 0.0015; * * Random random = new NPack.MersenneTwister(); * * for (int i = 1; i <= 1000000; i++) * { * Console.WriteLine("STARTING TEST NUMBER " + i); * Console.WriteLine(); * MakeTestRun(string.Format("kelly1_{0}.txt", i), random, 200000, ev_cutoff, kelly, new FixedReset(-0.0064)); * MakeTestRun(string.Format("kelly2_{0}.txt", i), random, 200000, ev_cutoff, kelly, new SmartReset(-0.0068, -0.0025, 70)); * }*/ seed_gen = new NPack.MersenneTwister(); Thread thread1 = new Thread(new ThreadStart(TestLoop1)); thread1.Start(); TestLoop1(); }
// return as a floating point number an integer value that is a random deviate drawn // from a Possion Distribution of mean xm using randx as a source of uniform deviates public static float Normalize(ref NPack.MersenneTwister _rand, float xm) { // Davide Rambaldi: all moved to double precision double sq, alxm, g, oldm; // oldm is a flag for wheter xm has changed or not sincle last call sq = alxm = g = oldm = (-1.0); double em, t, y; if (xm < 12.0f) // Use direct method { if (xm != oldm) { oldm = xm; g = Math.Exp(-xm); // if x is new, compute the exponential } em = -1; t = 1.0f; // Instead of adding exponential deviates it is equivalent to multiply unifomr deviates // We never actually take the log, we compare the precomupted exponential do { ++em; t *= _rand.NextSingle(true); } while (t > g); } else { // Use REJECTION method // xm has changed? if (xm != oldm) { oldm = xm; sq = Math.Sqrt(2.0 * xm); alxm = Math.Log(xm); // Gammln is the natural log of a gamma function g = xm * alxm - SpecialFunctions.gammln(xm + 1.0f); } do { do { // y is the deviate from a Lorentzian comparison function y = Math.Tan(Math.PI * _rand.NextSingle(true)); em = sq * y + xm; } while (em < 0.0); em = Math.Floor(em); t = 0.9 * (1.0 + y * y) * Math.Exp(em * alxm - SpecialFunctions.gammln(em + 1.0f) - g); } while (_rand.NextSingle(true) > t); } return((float)em); }
public static float Normalize(ref NPack.MersenneTwister _rand, int ia) { int j; float am, e, s, v1, v2, x, y; if (ia < 1) { throw new ArgumentException("Error in Gamma Distribution. Argument ia should be an integer > 1"); } if (ia < 6) { // use direct method, addin waiting times x = 1.0f; for (j = 1; j <= ia; j++) { x *= _rand.NextSingle(true); } x = (float)-(Math.Log(x)); } else { do { do { // This four lines generate the tanget of random angle // Equivalent to y = tan( pi * rand()) do { v1 = _rand.NextSingle(true); v2 = 2.0f * _rand.NextSingle(true) - 1.0f; } while (v1 * v1 + v2 * v2 > 1.0f); y = v2 / v1; am = ia - 1; s = (float)Math.Sqrt(2.0 * am + 1.0f); x = s * y + am; // We decide wheter to reject x, Reject in 0 probability region } while (x <= 0.0f); e = (float)((1.0f + y * y) * Math.Exp(am * Math.Log(x / am) - s * y)); } while (_rand.NextSingle(true) > e); } return(x); }
static void TestLoop1() { KellyBetting kelly = new KellyBetting(0.008, 25 * 100, 25 * 100, 200 * 100); double ev_cutoff = 0.0015; Random random; lock (seed_gen) { random = new NPack.MersenneTwister(seed_gen.Next()); } int i = 0; while (true) { lock (lock_obj) { i = run_number++; } MakeTestRun(i, random, 200000, ev_cutoff, kelly, new FixedReset(-0.0068)); } }
public static Vector2 Circle(ref NPack.MersenneTwister _rand, UnityRandom.Normalization n, float t) { float r; switch (n) { case UnityRandom.Normalization.STDNORMAL: r = SpecialFunctions.ScaleFloatToRange((float)NormalDistribution.Normalize(_rand.NextSingle(true), t), 0, Int32.MaxValue, 0, 1); break; case UnityRandom.Normalization.POWERLAW: r = (float)PowerLaw.Normalize(_rand.NextSingle(true), t, 0, Int32.MaxValue); break; default: r = (float)_rand.Next(); break; } float _2pi = (float)Math.PI * 2; float a = SpecialFunctions.ScaleFloatToRange(r, 0, _2pi, 0, Int32.MaxValue); return(new Vector2((float)Math.Cos(a), (float)Math.Sin(a))); }
public static Vector2 Disk(ref NPack.MersenneTwister _rand, UnityRandom.Normalization n, float temp) { double t, theta; switch (n) { case UnityRandom.Normalization.STDNORMAL: t = NormalDistribution.Normalize(_rand.NextSingle(true), temp); theta = NormalDistribution.Normalize(_rand.NextSingle(true), temp) * 2 * Math.PI; break; case UnityRandom.Normalization.POWERLAW: t = PowerLaw.Normalize(_rand.NextSingle(true), temp, 0, 1); theta = PowerLaw.Normalize(_rand.NextSingle(true), temp, 0, 1) * 2 * Math.PI; break; default: t = (float)_rand.NextSingle(true); theta = _rand.NextSingle(false) * 2 * Math.PI; break; } return(new Vector2((float)(Math.Sqrt(t) * Math.Cos(theta)), (float)(Math.Sqrt(t) * Math.Sin(theta)))); }
static void TestLoop1() { KellyBetting kelly = new KellyBetting(0.008, 25 * 100, 25 * 100, 200 * 100); double ev_cutoff = 0.0015; Random random; lock (seed_gen) { random = new NPack.MersenneTwister(seed_gen.Next()); } int i = 0; while (true) { lock (lock_obj) { i = run_number++; } MakeTestRun(i, random, 200000, ev_cutoff, kelly, new FixedReset(-0.0068)); } }
// FIXME: NOT YET IMPLEMENTED IN UNITYRANDOM public static Vector3 GetPointOnRing(float innerSpotAngle, float outerSpotAngle, ref NPack.MersenneTwister _rand, Quaternion orientation) { return(orientation * GetPointOnRing(innerSpotAngle, outerSpotAngle, ref _rand)); }
static void CompareStrategies2() { Random masterRandom = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; SuperOptStrategy b1 = new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier); OptStrategy b2 = new OptStrategy(max_bet, ev_cutoff, pp_multiplier); BasicStrategy b3 = new BasicStrategy(max_bet, ev_cutoff, pp_multiplier); Game game1 = new Game(rules, b1, pp_multiplier, new NPack.MersenneTwister()); Game game2 = new Game(rules, b2, pp_multiplier, new NPack.MersenneTwister()); Game game3 = new Game(rules, b3, pp_multiplier, new NPack.MersenneTwister()); int runs = 0; double expected = 0; while (true) { if (runs % 10000 == 0) { double total1 = TotalMoney(game1); double total2 = TotalMoney(game2); double total3 = TotalMoney(game3); Console.WriteLine(); Console.WriteLine("Runs: {0}", runs); Console.WriteLine("Expected total: $ {0:0.00}", expected); Console.WriteLine("SuperOpt total: $ {1:0.00} ({2:0.00} c/hand)", b1.GetType(), total1, total1 * 100.0 / (double)runs); Console.WriteLine("Opt total: $ {1:0.00} ({2:0.00} c/hand)", b2.GetType(), total2, total2 * 100.0 / (double)runs); Console.WriteLine("Basic total: $ {1:0.00} ({2:0.00} c/hand)", b3.GetType(), total3, total3 * 100.0 / (double)runs); TextWriter writer = new StreamWriter("compare.txt", true); writer.WriteLine(string.Format("{0} {1} {2} {3} {4}", runs, expected, total1, total2, total3)); writer.Close(); } int seed = masterRandom.Next(); game1.Random = new NPack.MersenneTwister(seed); game2.Random = new NPack.MersenneTwister(seed); game3.Random = new NPack.MersenneTwister(seed); game1.ResetShoe(); game2.ResetShoe(); game3.ResetShoe(); int remove_count = masterRandom.Next(84); game1.RemoveCards(remove_count); game2.RemoveCards(remove_count); game3.RemoveCards(remove_count); expected += b1.ShoeEV() * b1.Bet(game1) / 100.0; game1.StartRound(); game2.StartRound(); game3.StartRound(); game1.DealRound(); game2.DealRound(); game3.DealRound(); runs++; } }
static void CompareStrategies() { Random masterRandom = new NPack.MersenneTwister(); Random random1 = new NPack.MersenneTwister(); Random random2 = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; DiffStrategy b1 = new DiffStrategy( new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier), new OptStrategy(max_bet, ev_cutoff, pp_multiplier) ); OptStrategy b2 = new OptStrategy(max_bet, ev_cutoff, pp_multiplier); Game game1 = new Game(rules, b1, pp_multiplier, random1); Game game2 = new Game(rules, b2, pp_multiplier, random2); int runs = 0; double expected = 0; double expected_diff = 0; int diff_count = 0; while (true) { if (runs % 1000 == 0) { double total1 = TotalMoney(game1); double total2 = TotalMoney(game2); Console.WriteLine(); Console.WriteLine("Runs: {0}", runs); Console.WriteLine("Expected total: $ {0:0.00}", expected); Console.WriteLine("SuperOpt total: $ {1:0.00} ({2:0.00} c/hand)", b1.GetType(), total1, total1 * 100.0 / (double)runs); Console.WriteLine("Opt total: $ {1:0.00} ({2:0.00} c/hand)", b2.GetType(), total2, total2 * 100.0 / (double)runs); Console.WriteLine("Different choices: {0:0} ({1:0.00}%)", diff_count, 100.0 * diff_count / (double)runs); Console.WriteLine("Difference: $ {0:0.00}", total1 - total2); Console.WriteLine("Expected difference: $ {0:0.00}", expected_diff); TextWriter writer = new StreamWriter("compare.txt", true); writer.WriteLine(string.Format("{0} {1} {2} {3}", runs, expected, TotalMoney(game1), TotalMoney(game2))); writer.Close(); } int seed = masterRandom.Next(); game1.Random = new NPack.MersenneTwister(seed); game2.Random = new NPack.MersenneTwister(seed); game1.ResetShoe(); game2.ResetShoe(); int remove_count = masterRandom.Next(84); game1.RemoveCards(remove_count); game2.RemoveCards(remove_count); expected += b1.ShoeEV() * b1.Bet(game1) / 100.0; game1.StartRound(); game2.StartRound(); game1.DealRound(); game2.DealRound(); if (b1.IsDiff) { expected_diff += game1.Bet * b1.Diff / 100.0; diff_count++; b1.IsDiff = false; } runs++; } }
// FIXME: NOT YET IMPLEMENTED IN UNITYRANDOM public static Vector3 GetPointOnRing(float innerSpotAngle, float outerSpotAngle, ref NPack.MersenneTwister _rand, Transform relativeTo, float radius) { return(relativeTo.TransformPoint(GetPointOnRing(innerSpotAngle, outerSpotAngle, ref _rand) * radius)); }
// FIXME: NOT YET IMPLEMENTED IN UNITYRANDOM public static Vector3 GetPointOnCap(float spotAngle, ref NPack.MersenneTwister _rand, Quaternion orientation) { return(orientation * GetPointOnCap(spotAngle, ref _rand)); }
static void CompareStrategies() { Random masterRandom = new NPack.MersenneTwister(); Random random1 = new NPack.MersenneTwister(); Random random2 = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; DiffStrategy b1 = new DiffStrategy( new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier), new OptStrategy(max_bet, ev_cutoff, pp_multiplier) ); OptStrategy b2 = new OptStrategy(max_bet, ev_cutoff, pp_multiplier); Game game1 = new Game(rules, b1, pp_multiplier, random1); Game game2 = new Game(rules, b2, pp_multiplier, random2); int runs = 0; double expected = 0; double expected_diff = 0; int diff_count = 0; while (true) { if (runs % 1000 == 0) { double total1 = TotalMoney(game1); double total2 = TotalMoney(game2); Console.WriteLine(); Console.WriteLine("Runs: {0}", runs); Console.WriteLine("Expected total: $ {0:0.00}", expected); Console.WriteLine("SuperOpt total: $ {1:0.00} ({2:0.00} c/hand)", b1.GetType(), total1, total1 * 100.0 / (double)runs); Console.WriteLine("Opt total: $ {1:0.00} ({2:0.00} c/hand)", b2.GetType(), total2, total2 * 100.0 / (double)runs); Console.WriteLine("Different choices: {0:0} ({1:0.00}%)", diff_count, 100.0 * diff_count / (double)runs); Console.WriteLine("Difference: $ {0:0.00}", total1 - total2); Console.WriteLine("Expected difference: $ {0:0.00}", expected_diff); TextWriter writer = new StreamWriter("compare.txt", true); writer.WriteLine(string.Format("{0} {1} {2} {3}", runs, expected, TotalMoney(game1), TotalMoney(game2))); writer.Close(); } int seed = masterRandom.Next(); game1.Random = new NPack.MersenneTwister(seed); game2.Random = new NPack.MersenneTwister(seed); game1.ResetShoe(); game2.ResetShoe(); int remove_count = masterRandom.Next(84); game1.RemoveCards(remove_count); game2.RemoveCards(remove_count); expected += b1.ShoeEV() * b1.Bet(game1) / 100.0; game1.StartRound(); game2.StartRound(); game1.DealRound(); game2.DealRound(); if (b1.IsDiff) { expected_diff += game1.Bet * b1.Diff / 100.0; diff_count++; b1.IsDiff = false; } runs++; } }
static void TestSuper() { Random random = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; SuperOptStrategy b = new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier); //PseudoOptStrategy b = new PseudoOptStrategy(); Game game = new Game(rules, b, pp_multiplier, random); game.PlayerMoney = 0; double expected_money = (double)game.PlayerMoney; game.Bet = 100; // 1$ int lowest = game.PlayerMoney, highest = game.PlayerMoney; int runs = 0; while (true) { double total_money = (game.PlayerMoney + pp_multiplier * game.PartyPoints) / 100.0; if (runs % 10000 == 0) { Console.WriteLine("runs: " + runs + " win: " + (double)game.PlayerMoney / 100.0 + "$" + " pp: " + game.party_points); Console.WriteLine("lowest: " + (double)lowest / 100.0 + "$" + " highest: " + (double)highest / 100.0 + "$"); Console.WriteLine("total: " + total_money + "$ | expected: " + expected_money / 100.0 + "$"); Console.WriteLine(); } game.StartRound(); game.DealRound(); expected_money += b.ShoeEV() * game.Bet; if (game.PlayerMoney < lowest) lowest = game.PlayerMoney; if (game.PlayerMoney > highest) highest = game.PlayerMoney; runs++; } }
public static Vector2 Area(ref NPack.MersenneTwister _rand) { // Move to -1, 1 space as for CIRCLE and SPHERE return(new Vector2((2 * _rand.NextSingle(true) - 1), (2 * _rand.NextSingle(true) - 1))); }
static void CompareStrategies2() { Random masterRandom = new NPack.MersenneTwister(); Rules rules = new Rules { Decks = 8, MinBet = 100, MaxBet = 20000, Splits = 3 }; int max_bet = 5000; double pp_multiplier = 4.0; double ev_cutoff = 0.0015; SuperOptStrategy b1 = new SuperOptStrategy(max_bet, ev_cutoff, pp_multiplier); OptStrategy b2 = new OptStrategy(max_bet, ev_cutoff, pp_multiplier); BasicStrategy b3 = new BasicStrategy(max_bet, ev_cutoff, pp_multiplier); Game game1 = new Game(rules, b1, pp_multiplier, new NPack.MersenneTwister()); Game game2 = new Game(rules, b2, pp_multiplier, new NPack.MersenneTwister()); Game game3 = new Game(rules, b3, pp_multiplier, new NPack.MersenneTwister()); int runs = 0; double expected = 0; while (true) { if (runs % 10000 == 0) { double total1 = TotalMoney(game1); double total2 = TotalMoney(game2); double total3 = TotalMoney(game3); Console.WriteLine(); Console.WriteLine("Runs: {0}", runs); Console.WriteLine("Expected total: $ {0:0.00}", expected); Console.WriteLine("SuperOpt total: $ {1:0.00} ({2:0.00} c/hand)", b1.GetType(), total1, total1 * 100.0 / (double)runs); Console.WriteLine("Opt total: $ {1:0.00} ({2:0.00} c/hand)", b2.GetType(), total2, total2 * 100.0 / (double)runs); Console.WriteLine("Basic total: $ {1:0.00} ({2:0.00} c/hand)", b3.GetType(), total3, total3 * 100.0 / (double)runs); TextWriter writer = new StreamWriter("compare.txt", true); writer.WriteLine(string.Format("{0} {1} {2} {3} {4}", runs, expected, total1, total2, total3)); writer.Close(); } int seed = masterRandom.Next(); game1.Random = new NPack.MersenneTwister(seed); game2.Random = new NPack.MersenneTwister(seed); game3.Random = new NPack.MersenneTwister(seed); game1.ResetShoe(); game2.ResetShoe(); game3.ResetShoe(); int remove_count = masterRandom.Next(84); game1.RemoveCards(remove_count); game2.RemoveCards(remove_count); game3.RemoveCards(remove_count); expected += b1.ShoeEV() * b1.Bet(game1) / 100.0; game1.StartRound(); game2.StartRound(); game3.StartRound(); game1.DealRound(); game2.DealRound(); game3.DealRound(); runs++; } }
// FIXME: NOT YET IMPLEMENTED IN UNITYRANDOM public static Vector3 GetPointOnCap(float spotAngle, ref NPack.MersenneTwister _rand, Transform relativeTo, float radius) { return(relativeTo.TransformPoint(GetPointOnCap(spotAngle, ref _rand) * radius)); }