Created
April 23, 2015 11:07
-
-
Save Keloran/f172042d1ea87bf07c7d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "./Markov.hpp" | |
namespace NordicArts { | |
namespace GameNS { | |
Markov::Markov() { | |
init(); | |
} | |
Markov::Markov(NordicOS::Logger *pLogger) : m_pLogger(pLogger) { | |
m_bDebug = true; | |
init(); | |
} | |
void Markov::init() { | |
// Set the locale | |
m_pLocale = boost::locale::generator().generate("en_US.UTF-8"); | |
// read the file | |
fillNameList(); | |
// generate the chance maps | |
generateFirstLetterMap(); | |
generateLastLetterMap(); | |
generateLetterToLetterMap(); | |
} | |
void Markov::setVariance(float fVariance) { | |
m_fVariance = fVariance; | |
} | |
std::string Markov::generateWord() { | |
std::string word = ""; | |
// Seed | |
NordicOS::Time::Time oTime; | |
NordicOS::Time::Time *pTime = &oTime; | |
srand(pTime->getNanoSeconds()); | |
// generate first letter | |
while (true) { | |
int randLetter = (rand() % 27); | |
char cLetter = m_cAlphabet[randLetter]; | |
std::string firstLetter = NordicOS::getString(cLetter); | |
double randChance = ((double)rand() / RAND_MAX); | |
double randLetterValue = m_mFirstLetterChance[firstLetter]; | |
double randMath = ((m_mFirstLetterChance[firstLetter] * 2) + .05); | |
if (randChance < randMath) { | |
word.append(firstLetter); | |
break; | |
} | |
} | |
// Seed | |
srand(pTime->getNanoSeconds()); | |
// generate word | |
while (true) { | |
int randLetter = (rand() % 27); | |
char cLetter = m_cAlphabet[randLetter]; | |
std::string nextLetter = NordicOS::getString(cLetter); | |
std::string lastLetter = NordicOS::getString(word.back()); | |
double nextLetterChance = ((m_mLetterToLetterChance[lastLetter][nextLetter] * 2) - m_fVariance); | |
double randChance = ((double)rand() / RAND_MAX); | |
if (randChance < nextLetterChance) { | |
word.append(nextLetter); | |
// check if word should end | |
lastLetter = NordicOS::getString(word.back()); | |
double extraChance = m_mLastLetterChance[lastLetter]; | |
double moreRand = ((double)rand() / RAND_MAX); | |
if ((word.size() >= 4) && (moreRand < ((extraChance * 1.5) + .05))) { | |
break; | |
} else if ((word.size() > 8) && (moreRand < .3)) { | |
break; | |
} | |
} | |
} | |
word = boost::locale::to_title(word, m_pLocale); | |
if (m_bDebug) { | |
std::string cString = "Word: "; | |
cString.append(word); | |
m_pLogger->log(cString); | |
} | |
return word; | |
} | |
void Markov::fillNameList() { | |
std::vector<std::string> names; | |
std::ifstream inFile("./GameFiles/Names/names-list"); | |
std::string cLine; | |
while (std::getline(inFile, cLine)) { | |
cLine = boost::locale::to_lower(cLine, m_pLocale); | |
names.push_back(cLine); | |
} | |
// Set the names | |
m_vNames = names; | |
} | |
void Markov::generateFirstLetterMap() { | |
std::map<std::string, double> map = getAlphabetMap(); | |
double total = 0; | |
for (std::string c : m_vNames) { | |
// create the char | |
char *name = new char[(c.size() + 1)]; | |
name[c.size()] = 0; | |
memcpy(name, c.c_str(), c.size()); | |
std::string s = NordicOS::getString(name[0]); | |
if (map.find(s) != map.end()) { | |
double mapValue = map[s]; | |
mapValue += 1; | |
map[s] = mapValue; | |
total++; | |
} | |
} | |
// find the percentage | |
for (int i = 0; i < m_cAlphabet[i] != '\0'; i++) { | |
// turn the character into a string | |
std::string s = NordicOS::getString(m_cAlphabet[i]); | |
// set value | |
map[s] = (map[s] / total); | |
} | |
m_mFirstLetterChance = map; | |
} | |
void Markov::generateLastLetterMap() { | |
std::map<std::string, double> map = getAlphabetMap(); | |
double total = 0; | |
for (std::string c : m_vNames) { | |
// create the char | |
char *name = new char[(c.size() + 1)]; | |
name[c.size()] = 0; | |
memcpy(name, c.c_str(), c.size()); | |
// turn the last letter into a string | |
std::string s = NordicOS::getString(name[(c.size() - 1)]); | |
if (map.find(s) != map.end()) { | |
double mapValue = map[s]; | |
mapValue += 1; | |
map[s] = mapValue; | |
total++; | |
} | |
} | |
for (int i = 0; i < m_cAlphabet[i] != '\0'; i++) { | |
// turn the character into a string | |
std::string s = NordicOS::getString(m_cAlphabet[i]); | |
// set value | |
map[s] = (map[s] / total); | |
} | |
m_mLastLetterChance = map; | |
} | |
void Markov::generateLetterToLetterMap() { | |
std::map<std::string, std::map<std::string, double> > map; | |
// create the map | |
for (int i = 0; i < m_cAlphabet[i] != '\0'; i++) { | |
std::string s = NordicOS::getString(m_cAlphabet[i]); | |
map[s] = getAlphabetMap(); | |
} | |
// count the amount of times 2 letter appear next to each other | |
for (std::string c : m_vNames) { | |
char *name = new char[(c.size() + 1)]; | |
name[c.size()] = 0; | |
memcpy(name, c.c_str(), c.size()); | |
for (int i = 0; i < name[i] != '\0'; i++) { | |
std::string firstChar = NordicOS::getString(name[i]); | |
std::string secondChar = NordicOS::getString(name[(i + 1)]); | |
if (map.find(firstChar) != map.end()) { | |
if (map[firstChar].find(secondChar) != map[firstChar].end()) { | |
double mapValue = map[firstChar][secondChar]; | |
mapValue += 1; | |
map[firstChar][secondChar] = mapValue; | |
} | |
} | |
} | |
} | |
for (int i = 0; i < m_cAlphabet[i] != '\0'; i++) { | |
std::string firstChar = NordicOS::getString(m_cAlphabet[i]); | |
double total = 0; | |
if (map.find(firstChar) != map.end()) { | |
for (std::map<std::string, double>::iterator i = map[firstChar].begin(); i != map[firstChar].end(); ++i) { | |
std::string secondChar = i->first; | |
if (map[firstChar].find(secondChar) != map[firstChar].end()) { | |
total += map[firstChar][secondChar]; | |
} | |
} | |
} | |
for (int j = 0; j < m_cAlphabet[j] != '\0'; j++) { | |
std::string secondChar = NordicOS::getString(m_cAlphabet[j]); | |
double mapValue = (map[firstChar][secondChar] / total); | |
map[firstChar][secondChar] = mapValue; | |
} | |
} | |
m_mLetterToLetterChance = map; | |
} | |
std::map<std::string, double> Markov::getAlphabetMap() { | |
std::map<std::string, double> map; | |
double d = 0; | |
for (int i = 0; i < m_cAlphabet[i] != '\0'; i++) { | |
std::string s = NordicOS::getString(m_cAlphabet[i]); | |
map[s] = d; | |
} | |
return map; | |
} | |
Markov::~Markov() { | |
m_pLogger = nullptr; | |
} | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef NordicArts_Game_Markov_H | |
#define NordicArts_Game_Markov_H | |
#include <boost/locale.hpp> | |
#include "../Includes.hpp" | |
#include <NordicOS/OS.hpp> | |
#include <NordicOS/Logger/Logger.hpp> | |
#include <NordicOS/Time/Time.hpp> | |
namespace NordicArts { | |
namespace GameNS { | |
class Markov { | |
// Variables | |
public: | |
protected: | |
private: | |
std::map<std::string, double> m_mFirstLetterChance; | |
std::map<std::string, double> m_mLastLetterChance; | |
std::map<std::string, std::map<std::string, double> > m_mLetterToLetterChance; | |
std::vector<std::string> m_vNames; | |
char m_cAlphabet[28] = "abcdefghijklmnopqrstuvqwxyz"; | |
float m_fVariance = 0.0f; | |
NordicOS::Logger *m_pLogger = nullptr; | |
bool m_bDebug; | |
// Methods | |
public: | |
Markov(); | |
Markov(NordicOS::Logger *pLogger); | |
virtual ~Markov(); | |
std::string generateWord(); | |
void setVariance(float fVariance); | |
protected: | |
private: | |
void init(); | |
void fillNameList(); | |
void generateFirstLetterMap(); | |
void generateLastLetterMap(); | |
void generateLetterToLetterMap(); | |
std::map<std::string, double> getAlphabetMap(); | |
std::locale m_pLocale; | |
}; | |
}; | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment