/* * Quackle -- Crossword game artificial intelligence and analysis tool * Copyright (C) 2005-2006 Jason Katz-Brown and John O'Laughlin. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "alphabetparameters.h" #include "datamanager.h" using namespace Quackle; LetterString String::left(const LetterString &letterString, int number) { LetterString ret; int i = 0; LetterString::const_iterator myEnd(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); i < number && it != myEnd; ++it, ++i) ret += *it; return ret; } LetterString String::alphabetize(const LetterString &letterString) { LetterString ret = letterString; sort(ret.begin(), ret.end()); return ret; } LetterString String::clearBlankness(const LetterString &letterString) { LetterString ret; LetterString::const_iterator myEnd(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); it != myEnd; ++it) ret += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(*it); return ret; } LetterString String::setBlankness(const LetterString &letterString) { LetterString ret; LetterString::const_iterator myEnd(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); it != myEnd; ++it) ret += QUACKLE_ALPHABET_PARAMETERS->setBlankness(*it); return ret; } LetterString String::usedTiles(const LetterString &letterString) { LetterString used; const LetterString::const_iterator end(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); it != end; ++it) { if (*it == QUACKLE_BLANK_MARK || QUACKLE_ALPHABET_PARAMETERS->isBlankLetter(*it)) used += QUACKLE_BLANK_MARK; else if (QUACKLE_ALPHABET_PARAMETERS->isPlainLetter(*it)) used += *it; } return used; } void String::counts(const LetterString &letterString, char *countsArray) { for (int j = 0; j < QUACKLE_FIRST_LETTER + QUACKLE_MAXIMUM_ALPHABET_SIZE; j++) countsArray[j] = 0; const LetterString::const_iterator end(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); it != end; ++it) countsArray[*it]++; } void String::counts(const LongLetterString &letterString, char *countsArray) { for (int j = 0; j < QUACKLE_FIRST_LETTER + QUACKLE_MAXIMUM_ALPHABET_SIZE; j++) countsArray[j] = 0; const LongLetterString::const_iterator end(letterString.end()); for (LongLetterString::const_iterator it = letterString.begin(); it != end; ++it) countsArray[*it]++; } //////////// AlphabetParameters::AlphabetParameters() : m_length(0) { setAlphabet(emptyAlphabet()); } void AlphabetParameters::setAlphabet(const Alphabet &alphabet) { m_alphabet = alphabet; updateLength(); const Alphabet::const_iterator alphabetEnd(m_alphabet.end()); Alphabet::const_iterator alphabetIt; for (alphabetIt = m_alphabet.begin(); alphabetIt != alphabetEnd; ++alphabetIt) { assert(m_letterLookup.find(alphabetIt->text()) == m_letterLookup.end()); m_letterLookup[alphabetIt->text()] = alphabetIt - m_alphabet.begin(); } } void AlphabetParameters::setLetterParameter(Letter letter, const LetterParameter &letterParameter) { assert(m_letterLookup.find(letterParameter.text()) == m_letterLookup.end()); if (letter >= (int) m_alphabet.size()) { m_alphabet.resize(letter + 1); updateLength(); } m_alphabet[letter] = letterParameter; m_letterLookup[letterParameter.text()] = letter; } void AlphabetParameters::updateLength() { m_length = m_alphabet.size() - QUACKLE_FIRST_LETTER; } Alphabet AlphabetParameters::emptyAlphabet() { Alphabet ret(QUACKLE_FIRST_LETTER); ret[QUACKLE_NULL_MARK] = LetterParameter(QUACKLE_NULL_MARK, MARK_UV(" "), MARK_UV("")); ret[QUACKLE_BLANK_MARK] = LetterParameter(QUACKLE_BLANK_MARK, MARK_UV("?"), MARK_UV("")); ret[QUACKLE_PLAYED_THRU_MARK] = LetterParameter(QUACKLE_PLAYED_THRU_MARK, MARK_UV("."), MARK_UV("")); ret[QUACKLE_PLAYTHRU_START_MARK] = LetterParameter(QUACKLE_PLAYTHRU_START_MARK, MARK_UV("("), MARK_UV("")); ret[QUACKLE_PLAYTHRU_END_MARK] = LetterParameter(QUACKLE_PLAYTHRU_END_MARK, MARK_UV(")"), MARK_UV("")); return ret; } void AlphabetParameters::setCount(Letter letter, int count) { m_alphabet[letter].setCount(count); } void AlphabetParameters::setScore(Letter letter, int score) { m_alphabet[letter].setScore(score); } LetterString AlphabetParameters::clearBlankness(const LetterString &letterString) const { LetterString ret; const LetterString::const_iterator end(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); it != end; ++it) ret += clearBlankness(*it); return ret; } UVString AlphabetParameters::userVisible(const LetterString &letterString) const { UVString ret; const LetterString::const_iterator end(letterString.end()); for (LetterString::const_iterator it = letterString.begin(); it != end; ++it) ret += userVisible(*it); return ret; } UVString AlphabetParameters::userVisible(Letter letter) const { if (isBlankLetter(letter)) return letterParameter(letter - QUACKLE_BLANK_OFFSET).blankText(); else return letterParameter(letter).text(); } LetterString AlphabetParameters::encode(const UVString &word, UVString *leftover) const { LetterString ret; UVString leftoverQuery; const Alphabet::const_iterator alphabetEnd(m_alphabet.end()); LetterLookupMap::const_iterator lookupEnd = m_letterLookup.end(); const UVString::const_iterator end(word.end()); for (UVString::const_iterator it = word.begin(); it != end; ++it) { UVString query(leftoverQuery); query += *it; bool blank = false; Alphabet::const_iterator alphabetIt; LetterLookupMap::const_iterator lookupIt = m_letterLookup.find(query); if (lookupIt == lookupEnd) { for (alphabetIt = m_alphabet.begin(); alphabetIt != alphabetEnd; ++alphabetIt) if ((*alphabetIt).blankText() == query) break; if (alphabetIt == alphabetEnd) { leftoverQuery = query; continue; } blank = true; ret += blank? setBlankness((*alphabetIt).letter()) : (*alphabetIt).letter(); } else { ret += blank? setBlankness(m_alphabet[lookupIt->second].letter()) : m_alphabet[lookupIt->second].letter(); } leftoverQuery.clear(); } //UVcout << "encoded " << word << " to " << ret << endl; if (leftover) *leftover = leftoverQuery; return ret; } string AlphabetParameters::findAlphabetFile(const string &alphabet) { return DataManager::self()->findDataFile("alphabets", alphabet); } //////// EnglishAlphabetParameters::EnglishAlphabetParameters() { m_alphabetName = "default"; const int englishTileScores[26] = { 1, // A 3, // B 3, // C 2, // D 1, // E 4, // F 2, // G 4, // H 1, // I 8, // J 5, // K 1, // L 3, // M 1, // N 1, // O 3, // P 10,// Q 1, // R 1, // S 1, // T 1, // U 4, // V 4, // W 8, // X 4, // Y 10,// Z }; const int englishTileCounts[27] = { 9, // A 2, // B 2, // C 4, // D 12, // E 2, // F 3, // G 2, // H 9, // I 1, // J 1, // K 4, // L 2, // M 6, // N 8, // O 2, // P 1, // Q 6, // R 4, // S 6, // T 4, // U 2, // V 2, // W 1, // X 2, // Y 1, // Z 2, // ? }; Letter letter = QUACKLE_FIRST_LETTER; for (UVChar charIndex = MARK_UV('A'); charIndex <= MARK_UV('Z'); ++charIndex, ++letter) { UVString letterString; UVString lowerLetterString; letterString += charIndex; lowerLetterString += towlower(charIndex); const bool isVowel = (charIndex == MARK_UV('A')) || (charIndex == MARK_UV('E')) || (charIndex == MARK_UV('I')) || (charIndex == MARK_UV('O')) || (charIndex == MARK_UV('U')); const int score = englishTileScores[letter - QUACKLE_FIRST_LETTER]; const int count = englishTileCounts[letter - QUACKLE_FIRST_LETTER]; setLetterParameter(letter, LetterParameter(letter, letterString, lowerLetterString, score, count, isVowel)); } setCount(QUACKLE_BLANK_MARK, englishTileCounts[26]); } UVOStream &operator<<(UVOStream& o, const Quackle::LetterParameter &letterParameter) { o << letterParameter.letter() << " [" << letterParameter.text() << ", " << letterParameter.blankText() << "]"; return o; } UVOStream &operator<<(UVOStream& o, const Quackle::Alphabet &alphabet) { o << "Alphabet (size " << alphabet.size() << "): "; Alphabet::const_iterator end(alphabet.end()); for (Alphabet::const_iterator it = alphabet.begin(); it != end; ++it) o << (*it) << " "; return o; }