Aetheria/Assets/Scripts/MarkovNameGenerator.cs
hyperion51 ae98448942 Porting Galaxy Editor
Ported the galaxy editor code from the old Aetheria
2020-03-11 15:18:36 +00:00

126 lines
No EOL
4.1 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
//Generates random names based on the statistical weight of letter sequences
//in a collection of sample names
public class MarkovNameGenerator
{
//constructor
public MarkovNameGenerator(IEnumerable<string> sampleNames, int order, int minLength, int maxLength)
{
//fix parameter values
if (order < 1)
order = 1;
if (minLength < 1)
minLength = 1;
_order = order;
_minLength = minLength;
_maxLength = maxLength;
//split comma delimited lines
foreach (string line in sampleNames)
{
string[] tokens = line.Split(' ','-','\'','(',')');
foreach (string word in tokens)
{
string upper = word.Trim().ToUpper();
if (upper.Length < order + 1)
continue;
_samples.Add(upper + '|'); // Add end character
}
}
//Build chains
foreach (string word in _samples)
{
for (int letter = 0; letter < word.Length - order; letter++)
{
string token = word.Substring(letter, order);
List<char> entry = null;
if (_chains.ContainsKey(token))
entry = _chains[token];
else
{
entry = new List<char>();
_chains[token] = entry;
}
entry.Add(word[letter + order]);
}
}
}
//Get the next random name
public string NextName
{
get
{
string s = "";
do
{
int n = UnityEngine.Random.Range(0,_samples.Count);
//int nameLength = _samples[n].Length;
//s = _samples[n].Substring(UnityEngine.Random.Range(0, _samples[n].Length - _order), _order);//get a random token somewhere in middle of sample word
s = _samples[n].Substring(0, _order);//get a random token at the start of a sample word
while (true)//(s.Length < nameLength)
{
string token = s.Substring(s.Length - _order, _order);
char c = GetLetter(token);
if (c != '?' && c != '|')
s += c;//GetLetter(token);
else
break;
}
// if (s.Contains(" "))
// {
// string[] tokens = s.Split(' ');
// s = "";
// for (int t = 0; t < tokens.Length; t++)
// {
// if (tokens[t] == "")
// continue;
// if (tokens[t].Length == 1)
// tokens[t] = tokens[t].ToUpper();
// else
// tokens[t] = tokens[t].Substring(0, 1) + tokens[t].Substring(1).ToLower();
// if (s != "")
// s += " ";
// s += tokens[t];
// }
// }
// else
s = s.Substring(0, 1) + s.Substring(1).ToLower();
}
while (_used.Contains(s) || s.Length < _minLength || s.Length > _maxLength);
_used.Add(s);
return s;
}
}
//Reset the used names
public void Reset()
{
_used.Clear();
}
//private members
private Dictionary<string, List<char>> _chains = new Dictionary<string, List<char>>();
private List<string> _samples = new List<string>();
private static List<string> _used = new List<string>();
private int _order;
private int _minLength;
private int _maxLength;
//Get a random letter from the chain
private char GetLetter(string token)
{
if (!_chains.ContainsKey(token))
return '?';
List<char> letters = _chains[token];
int n = UnityEngine.Random.Range(0,letters.Count);
return letters[n];
}
}