using System.Collections.Generic;
using System.Globalization;
public static void Main()
var seed = "9b8946df0e7431dc816a45fed394747aab29dd9129544dfd33cee4898be49824";
foreach(var kvp in TraitsGenerator.GetIlluvialSimStatModifiers(seed, new int [] {5, 4, 3, 1, 2, 6})){
Console.WriteLine($"{kvp.Key}={kvp.Value}");
var strongSeed = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
foreach(var kvp in TraitsGenerator.GetIlluvialSimStatModifiers(strongSeed, new int [] {5, 4, 3, 1, 2, 6})){
Console.WriteLine($"strong seed {kvp.Key}={kvp.Value}");
var exampleSeed = "3ba0be17afdc723f189c0439c5cadf8af0ca9cd385e571173271491fb545908c";
foreach(var kvp in TraitsGenerator.GetIlluvialSimStatModifiers(exampleSeed, new int [] {5, 4, 3, 1, 2, 6})){
Console.WriteLine($"exampleSeed {kvp.Key}={kvp.Value}");
public static class TraitsGenerator
private const double DecayFactor = 0.6;
public static int CalculateTraitPurity(string seed, int[] priorityList)
var cellValues = GetCellValues(seed).ToArray();
for (var i = 0; i < priorityList.Length; i++)
var normalizedValue = (double) cellValues[i] / 0xFFFF;
var weight = CalculateWeight(i + 1, DecayFactor);
weightedSum += normalizedValue * weight;
var traitPurity = weightedSum / totalWeights;
return (int)Math.Round(SigmoidTransform(traitPurity) * 100, MidpointRounding.AwayFromZero);
private static double CalculateWeight(int priorityIndex, double decayFactor)
return Math.Pow(decayFactor, priorityIndex - 1);
private static double SigmoidTransform(double value)
return 1 / (1 + Math.Exp(-11 * (value - 0.5)));
public static IEnumerable<int> GetCellValues(string seed)
return Enumerable.Range(0, 16).Select(i => GetCellValue(seed, i));
public static int GetCellValue(string seed, int index)
if (index < 0 || seed.Length < index * 4)
throw new ArgumentException($"Invalid index: {index}");
var val = seed.Substring(index * 4, 4);
return int.Parse(val, NumberStyles.HexNumber);
public static int GetScaledCellValue(string seed, int index, int min, int max)
var x = (double) GetCellValue(seed, index);
return Math.Clamp((int) ((x / 0xffff) * (max - min) + min), min, max - 1);
public static IReadOnlyDictionary<string, int> GetIlluvialSimStatModifiers(string seed, int[] priorityList)
var modValues = Enumerable.Range(0, 6)
.Select(i => !string.IsNullOrEmpty(seed) ? GetScaledCellValue(seed, i, 0, 6) : 0).ToList();
return new Dictionary<string, int>
{ "AttackDamage", modValues[0] },
{ "AttackSpeed", modValues[1] },
{ "Health", modValues[2] },
{ "MovementSpeed", modValues[3] },
{ "OmegaPower", modValues[4] },
{ "Resistance", modValues[5] },
{ "TraitPurity", CalculateTraitPurity(seed, priorityList) }