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; }
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; } } }