void Rack::load(const LetterString &tiles) { for (LetterString::const_iterator it = tiles.begin(); it != tiles.end(); ++it) { if (it != QUACKLE_NULL_MARK) m_tiles += *it; } }
LetterString Bag::someShuffledTiles() const { LongLetterString shuffled(shuffledTiles()); LetterString ret; int i = 0; for (LongLetterString::const_iterator it = shuffled.begin(); it != shuffled.end() && i < LETTER_STRING_MAXIMUM_LENGTH - 1; ++it, ++i) ret.push_back(*it); return ret; }
bool Bag::removeLetters(const LetterString &letters) { bool ret = true; const LetterString::const_iterator end(letters.end()); for (LetterString::const_iterator it = letters.begin(); it != end; ++it) if (!removeLetter(*it)) ret = false; return ret; }
LetterString Move::wordTilesWithNoPlayThru() const { LetterString word; LetterString used = usedTiles(); const LetterString::const_iterator end(used.end()); for (LetterString::const_iterator it = used.begin(); it != end; ++it) if (*it != QUACKLE_PLAYED_THRU_MARK) word += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(*it); return word; }
double CatchallEvaluator::equity(const GamePosition &position, const Move &move) const { //UVcout << "catchall being used on " << move.tiles() << endl; if (position.board().isEmpty()) { double adjustment = 0; if (move.action == Move::Place) { int start = move.startcol; if (move.startrow < start) start = move.startrow; LetterString wordTiles = move.tiles(); int length = wordTiles.length(); int consbits = 0; for (signed int i = wordTiles.length() - 1; i >= 0; i--) { consbits <<= 1; if (QUACKLE_ALPHABET_PARAMETERS->isVowel(QUACKLE_ALPHABET_PARAMETERS->clearBlankness(wordTiles[i]))) consbits |= 1; } adjustment = QUACKLE_STRATEGY_PARAMETERS->vcPlace(start, length, consbits); } else adjustment = 3.5; // UVcout << "placement adjustment for " << move << " is " << adjustment << endl; return ScorePlusLeaveEvaluator::equity(position, move) + adjustment; } else if (position.bag().size() > 0) { int leftInBagPlusSeven = position.bag().size() - move.usedTiles().length() + 7; double heuristicArray[13] = { 0.0, -8.0, 0.0, -0.5, -2.0, -3.5, -2.0, 2.0, 10.0, 7.0, 4.0, -1.0, -2.0 }; double timingHeuristic = 0.0; if (leftInBagPlusSeven < 13) timingHeuristic = heuristicArray[leftInBagPlusSeven]; return ScorePlusLeaveEvaluator::equity(position, move) + timingHeuristic; } else { return endgameResult(position, move) + move.score; } }
bool StrategyParameters::loadSyn2(const string &filename) { for (int i = 0; i < QUACKLE_FIRST_LETTER + QUACKLE_MAXIMUM_ALPHABET_SIZE; ++i) for (int j = 0; j < QUACKLE_FIRST_LETTER + QUACKLE_MAXIMUM_ALPHABET_SIZE; ++j) m_syn2[i][j] = 0; UVIFStream file(filename.c_str()); if (!file.is_open()) { cerr << "Could not open " << filename << " to load syn2" << endl; return false; } while (!file.eof()) { UVString letters; file >> letters; if (letters.empty()) continue; LetterString letterString = QUACKLE_ALPHABET_PARAMETERS->encode(letters); if (letterString.length() != 2) { UVcerr << "letter string " << letters << " can not be encoded into two letters while reading syn2" << endl; break; } if (file.eof()) break; double value; file >> value; m_syn2[(int)letterString[0]][(int)letterString[1]] = value; m_syn2[(int)letterString[1]][(int)letterString[0]] = value; } file.close(); return true; }
LetterString Bag::refill(Rack &rack, const LetterString &drawingOrder) { LetterString ret(drawingOrder); for (int number = QUACKLE_PARAMETERS->rackSize() - rack.tiles().length(); number > 0 && !m_tiles.empty(); --number) { if (drawingOrder.empty()) rack.setTiles(String::alphabetize(rack.tiles() + pluck())); else { removeLetter(String::back(ret)); rack.setTiles(String::alphabetize(rack.tiles() + String::back(ret))); String::pop_back(ret); } } return ret; }
bool Rack::unload(const LetterString &used) { // UVcout << *this << ".unload(" << used << ")" << endl; LetterString newtiles = m_tiles; bool ret = true; LetterString::const_iterator usedEnd(used.end()); for (LetterString::const_iterator usedIt = used.begin(); usedIt != usedEnd; ++usedIt) { bool found = false; LetterString::iterator newEnd(newtiles.end()); for (LetterString::iterator newIt = newtiles.begin(); newIt != newEnd; ++newIt) { if (*newIt == *usedIt) { *newIt = QUACKLE_NULL_MARK; found = true; break; } } if (!found) ret = false; } // UVcout << "newtiles: " << newtiles << endl; m_tiles.clear(); LetterString::const_iterator newEnd(newtiles.end()); for (LetterString::const_iterator newIt = newtiles.begin(); newIt != newEnd; ++newIt) if (*newIt != QUACKLE_NULL_MARK) m_tiles += *newIt; return ret; }
void Bag::toss(const LetterString &letters) { const LetterString::const_iterator end(letters.end()); for (LetterString::const_iterator it = letters.begin(); it != end; ++it) m_tiles.push_back(*it); }
MoveList Board::allWordsFormedBy(const Move &move) const { MoveList ret; if (move.tiles().length() > 1) ret.push_back(move); if (move.action == Move::Place) { if (m_empty) { ret.push_back(move); } else { LetterString word; if (move.horizontal) { int i = 0; for (const auto& it : move.tiles()) { if (m_letters[move.startrow][i + move.startcol] == QUACKLE_NULL_MARK) { word.clear(); word += it; int startRow = 0; for (int j = move.startrow - 1; j >= 0; --j) { if (m_letters[j][i + move.startcol] == QUACKLE_NULL_MARK) { startRow = j + 1; break; } else { word = m_letters[j][i + move.startcol] + word; } } for (int j = move.startrow + 1; j < m_height; ++j) { if (m_letters[j][i + move.startcol] == QUACKLE_NULL_MARK) j = m_height; else word += m_letters[j][i + move.startcol]; } if (word.length() > 1) { ret.push_back(Move::createPlaceMove(startRow, (i + move.startcol), /* vertical */ false, word)); } } i++; } } else { int i = 0; for (const auto& it : move.tiles()) { if (m_letters[i + move.startrow][move.startcol] == QUACKLE_NULL_MARK) { word.clear(); word += it; int startColumn = 0; for (int j = move.startcol - 1; j >= 0; --j) { if (m_letters[i + move.startrow][j] == QUACKLE_NULL_MARK) { startColumn = j + 1; break; } else { word = m_letters[i + move.startrow][j] + word; } } for (int j = move.startcol + 1; j < m_width; ++j) { if (m_letters[i + move.startrow][j] == QUACKLE_NULL_MARK) j = m_width; else word += m_letters[i + move.startrow][j]; } if (word.length() > 1) { ret.push_back(Move::createPlaceMove((i + move.startrow), startColumn, /* horizontal */ true, word)); } i++; } } } } } for (auto& it : ret) { it.setTiles(sanitizedTilesOfMove(it)); it.setPrettyTiles(prettyTilesOfMove(it)); it.score = score(it); } return ret; }
void Board::updateBritishness() { Generator generator; LetterString word; for (int row = 0; row < m_height; row++) { for (int col = 0; col < m_width; col++) { bool isBritish = false; if (m_letters[row][col] != QUACKLE_NULL_MARK) { word.clear(); word += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[row][col]); for (int j = row - 1; j >= 0; --j) { if (m_letters[j][col] == QUACKLE_NULL_MARK) break; else word = QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[j][col]) + word; } for (int j = row + 1; j < m_height; ++j) { if (m_letters[j][col] == QUACKLE_NULL_MARK) break; else word += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[j][col]); } if (word.length() > 1) { WordWithInfo wordWithInfo; wordWithInfo.wordLetterString = word; generator.storeWordInfo(&wordWithInfo); if (wordWithInfo.british) isBritish = true; } word.clear(); word += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[row][col]); for (int j = col - 1; j >= 0; --j) { if (m_letters[row][j] == QUACKLE_NULL_MARK) break; else word = QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[row][j]) + word; } for (int j = col + 1; j < m_width; ++j) { if (m_letters[row][j] == QUACKLE_NULL_MARK) break; else word += QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[row][j]); } if (word.length() > 1) { WordWithInfo wordWithInfo; wordWithInfo.wordLetterString = word; generator.storeWordInfo(&wordWithInfo); if (wordWithInfo.british) isBritish = true; } } m_isBritish[row][col] = isBritish; } } }