I was going to upload the file but the board won't let me here (same with the actual executable), so I'll post the code in here. I did however upload fivelet.txt which is a pretty decently sized dictionary file for 5 letter words in the desired format my program wants. fivelet.txt (You're going to want to put that in the same directory as rollo_champ.cpp).
Here's the code:
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
if (permissible.find_first_of(toupper(c)) == string::npos) return false;
else return true;
}
void makeUpper(string & g)
{
for (int j=0; j<g.size(); j++) g[j] = toupper(g[j]);
}
bool matchTest(string & g, vector < pair< string, int > > * f)
{
for (int q=0; q<f->size(); q++) { if (scoreWord(f->at(q).first, g) != f->at(q).second) { return false; } }
return true;
}
int scoreWord(string & testWord, string & theWord)
{
if (testWord.size() != theWord.size()) return -1;
int score = 0;
for (int x=0; x<testWord.size(); x++)
{
if (testWord.at(x) == theWord.at(x)) score++;
}
return score;
}
bool matchGivenLetters(string & g, string & csa)
{
for (int y=0; y<g.size(); y++)
{
if (csa.at(y) != '?' && csa.at(y) != g.at(y)) return false;
}
return true;
}
/* ROLLO CHAMP (rollo_champ.cpp)
by Unreality (N.R.)
Mon Mar 7, 2011 through Sun Mar 13, 2011
*/
using namespace std;
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
bool guessTest(string &, int, bool);
bool guessCharTest(char,bool);
void makeUpper(string &);
bool matchTest(string &, vector < pair< string, int > > *);
int scoreWord(string &,string &);
bool matchGivenLetters(string &, string &);
int main()
{
// Phase I: retrieve dictionary
///////////////////////////////
cout << endl;
fstream inf;
bool prompt = true;
string fname;
while (prompt)
{
cout << "Enter filename of your space-delimited ROLLO dictionary file (enter a dot to use fivelet.txt)\n\t";
cin >> fname; if (fname==".") fname="fivelet.txt";
// attempt to open file
inf.open(fname.c_str());
// valid?
prompt = inf.fail();
if (prompt) cout << "\nThat file does not exist!\n";
}
// Phase II: retrieve gamestate
///////////////////////////////
int numL=5; string numLS;
cout << "Number of Letters per ROLLO word (default 5): ";
cin >> numLS;
numL = atoi(numLS.c_str());
if (numL < 1) numL = 5;
cout << "Enter the " << numL << "-lettered word as it is known, using question marks for unknown letters:\n";
cout << endl;
prompt = true;
string cs;
while (prompt)
{
cout << " "; for (int iz=0; iz<numL; iz++) cout << "_"; cout << "\n>: ";
cin >> cs;
makeUpper(cs);
prompt = !guessTest(cs, numL, true);
if (prompt) cout << "\nMust be a valid (A-Z or '?') " << numL << "-lettered word... try again.\n";
}
cout << "\n\nNow enter the words guessed so far and their scores.";
cout << "\n\nEnter a " << numL << " for the score to cancel adding the guess (if you make a mistake).";
cout << "\n\nEnter just a tilde to analyze current guesses. Enter a hyphen to analyze and then quit.";
cout << "\n\nTo edit a prior guess, enter a $ followed by the word, then a colon, then the new guess value. Enter " << numL << " for the guess value to delete that entry.\n\n";
string guess=""; int guessval=0;
vector < pair< string, int > > guesses;
vector<string> fit;
bool dontQuit = true, firstTime = true, getGuesses, addWord, commencePhaseThree, reopenFile;
while(dontQuit)
{
getGuesses = true;
commencePhaseThree = true;
reopenFile = false;
int guessesAdded = 0;
// collect guesses / more guesses
while (getGuesses)
{
prompt = true;
while (prompt)
{
// get the guess
cout << "Guess:\t";
cin >> guess;
// process the guess
if (guess == "-") { prompt = false; getGuesses = false; dontQuit = false; }
else if (guess == "~") { prompt = false; getGuesses = false; }
else if (guess.at(0) == '$')
{
if (guess.size() < 3+numL)
{
cout << "An edit string should be of the form $word:newscore";
if (guesses.size() > 0) cout << ", e.g. $" << guesses.at(0).first << ":" << ( (guesses.at(0).second == 1) ? "2" : "1" );
else cout << ".";
cout << "\nOr have newscore be " << numL << " to delete the guess.\n";
prompt = false; getGuesses = false; commencePhaseThree = false;
}
else
{
makeUpper(guess);
int newGuessVal = atoi(guess.substr(numL+2).c_str());
if (newGuessVal == numL)
{
// delete the guess
vector < pair< string, int > > newguesses;
bool foundGuess = false;
for (int myit = 0; myit < guesses.size(); myit++)
{
if (guesses.at(myit).first != guess.substr(1,numL))
{
newguesses.push_back(guesses.at(myit));
}
else
{
foundGuess = true;
}
}
guesses = newguesses;
if (foundGuess)
{ cout << "(Deleted " << guess.substr(1,numL) << ")\n"; reopenFile = true; }
else
{ cout << "Guess Not Found\n"; commencePhaseThree = false; }
}
else if (newGuessVal >= 0 && newGuessVal < numL)
{
// edit the guess
bool foundGuess=false;
for (int myit = 0; myit < guesses.size(); myit++)
{ if (guesses.at(myit).first == guess.substr(1,numL))
{ foundGuess=true; guesses.at(myit).second = newGuessVal; } }
if (foundGuess)
{ cout << "(Score of " << guess.substr(1,numL) << " changed to " << newGuessVal << ")\n"; reopenFile = true; }
else
{ cout << "Guess Not Found\n"; commencePhaseThree = false; }
}
else { cout << "That's out of the range of possible scores. No change occurred.\n"; commencePhaseThree = false; }
prompt = false; getGuesses = false;
}
}
else
{
prompt = !guessTest(guess, numL, false);
if (prompt) cout << "Invalid Guess, try again.\n";
}
}
if (getGuesses)
{
// guess is valid : attach a score to it
makeUpper(guess);
prompt = true;
while (prompt)
{
cout << "Score of Guess (" << guess << "):\t";
cin >> numLS;
// Because of the annoying nature of atoi (returning 0 for non-numerics),
// there's no way to distinguish an invalid string from one in which you wanted to say was zero.
// That means the way to actually say a guess scored 0 letters is to type just exactly 0 for the input.
if (numLS=="0") { guessval = 0; prompt = false; addWord = true; }
else
{
// zero isn't the score so now atoi can be checked for equality with zero
// in order to catch non-numeric inputs...
guessval = atoi(numLS.c_str());
if (guessval <= 0 || guessval > numL) { cout << "That's not a feasible score, try again. Enter " << numL << " for the score to cancel adding this word.\n"; }
else if (guessval == numL) { cout << "Word not added.\n"; prompt = false; addWord = false; }
else { prompt = false; addWord = true; }
}
}
// anything that sets prompt false in the above While loop must also decide on a value for addWord
if (addWord) { guesses.push_back(make_pair(guess, guessval)); guessesAdded++; }
cout << endl;
}
}
// Phase III: reduce possibilities with logic and linguistics (based on dictionary file)
// begin by reducing the dictionary to include only words that fit the already known letters
// and would score correctly given the guesses so far.
// If the dictionary has already been scanned, then just look at the guesses added and make
// sure the words match up to them, removing words that don't satisfy the new guesses' requirements.
// (Unless a previous guess has been edited or deleted; this changes everything and needs a re-read from the dictionary file).
//
// I have proved that this method extracts the maximum information from the known situation, as far as you can logic (it would be pure logic
// if the dictionary file contained all 26^(numL) "words", but linguistic logic is factored in too because the dictionary
// is already its own filter from the getgo, deciding which words are acceptable.
if (commencePhaseThree)
{
cout << "\nSummary of Guesses\n";
int constCompare = guesses.size() - guessesAdded;
for (int i=0; i<guesses.size(); i++)
{
cout << guesses.at(i).first << " (" << guesses.at(i).second << ")" << ( (i >= constCompare) ? (" *\n") : ("\n") );
}
if (guessesAdded > 0) cout << "*";
cout << "(Added " << guessesAdded << " guess" << ( (guessesAdded == 1) ? ("") : ("es") ) << ")\n";
string wd;
vector < pair< string, int > > * ff = &guesses;
if (firstTime) // used the very first time the eligible words are calculated (future times just remove words that no longer match all guesses)
{
while (!inf.eof())
{
inf >> wd;
makeUpper(wd);
if (guessTest(wd, numL, false) && matchGivenLetters(wd,/*scored*/cs) && matchTest(wd, ff)) fit.push_back(wd);
}
inf.close();
firstTime=false;
}
else if (reopenFile) // used after an edit or deletion of an already made guess (because that changes everything so the file needs re-reading)
{
fit.clear();
inf.open(fname.c_str());
while (!inf.eof())
{
inf >> wd;
makeUpper(wd);
if (guessTest(wd, numL, false) && matchGivenLetters(wd,cs) && matchTest(wd, ff)) fit.push_back(wd);
}
inf.close();
}
else // remove words that no longer match with all the guesses
{
int remcount = 0;
bool * keepWords = new bool[fit.size()];
for (int ndex=0; ndex<fit.size(); ndex++)
{
if (!matchTest(fit.at(ndex), ff))
{
cout << "Removed " << fit.at(ndex) << endl;
remcount++;
keepWords[ndex] = false;
}
else keepWords[ndex] = true;
}
// remove them (can't remove them in the above loop because that would change fit's size and indices while fit is being looped over, a big no no)
vector<string> newfit;
for (int ndex=0; ndex<fit.size(); ndex++) if (keepWords[ndex]) newfit.push_back(fit.at(ndex));
fit = newfit;
// announce the removal
if (remcount > 0) cout << "(Removed " << remcount << " word" << ( (remcount==1) ? ("") : ("s") ) << ")" << endl;
}
cout << "\nPossibilities\n";
for (int i=0; i<fit.size(); i++) cout << fit[i] << endl;
if (fit.size() == 0) cout << "NONE" << endl;
else cout << "Count: " << fit.size() << endl << endl;
}
//////////////////////////
} // the only way to get out of here is for dontQuit to be false, which is only if they guessed a hyphen
// program finished
cout << "\nThanks for using Rollo Champ.\tby N. R. [Unreality] 2011\n";
return 0;
}
bool guessTest(string & g, int n, bool questionMarkAllowed)
{
if (g.size() != n) return false;
for (int j=0; j<n; j++)
{
if (!guessCharTest(g.at(j), questionMarkAllowed)) return false;
}
return true;
}
bool guessCharTest(char c, bool questionMarkAllowed)
{
string permissible = ((questionMarkAllowed)?("ABCDEFGHIJKLMNOPQRSTUVWXYZ?")
Compile this with your favorite c++ compiler (works fine with make and g++ and I'm sure most other if not all compilers, assuming you have the standard libraries and such). If you have make (esp on the OSX) you can just do this:
make rollo_champ
or with g++ (which is more common, make just calls that anyway)
g++ rollo_champ.cpp -o rollo_champ
Then run the executable (./rollo_champ)
I've been working at it to make sure it's entirely people-friendly. There's only so many things I could've anticipated though, so if you download it help me out and try to break it with faulty inputs
I know something like this has the potential to take the fun out of ROLLO but I thought it was interesting to make anyway so why not share it I guess. Basically you just give it the dictionary file and then enter the guesses and their scores as given by the host (you can edit & remove guesses too, and continually update it, etc) to narrow down the dictionary. Maybe the tool could be helpful in other games or situations, idk. (at the least it's portable to rollo games played with not 5 letters). Anyway enjoy
Question
unreality
I was going to upload the file but the board won't let me here (same with the actual executable), so I'll post the code in here. I did however upload fivelet.txt which is a pretty decently sized dictionary file for 5 letter words in the desired format my program wants. fivelet.txt (You're going to want to put that in the same directory as rollo_champ.cpp).
Here's the code:
I've been working at it to make sure it's entirely people-friendly. There's only so many things I could've anticipated though, so if you download it help me out and try to break it with faulty inputs
I know something like this has the potential to take the fun out of ROLLO but I thought it was interesting to make anyway so why not share it I guess. Basically you just give it the dictionary file and then enter the guesses and their scores as given by the host (you can edit & remove guesses too, and continually update it, etc) to narrow down the dictionary. Maybe the tool could be helpful in other games or situations, idk. (at the least it's portable to rollo games played with not 5 letters). Anyway enjoy
Link to comment
Share on other sites
5 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.