UVString Move::debugString() const { UVOStringStream ss; ss << toString() << " (score = " << score << ", equity = " << equity << ", win% = " << win; if (m_scoreAddition != 0) ss << ", scoreAddition = " << m_scoreAddition; ss << ")"; return ss.str(); }
UVString Move::positionString() const { UVOStringStream ss; if (horizontal) { ss << startrow + 1; ss << (char)('A' + startcol); } else { ss << (char)('A' + startcol); ss << startrow + 1; } return ss.str(); }
UVString Move::toString() const { UVOStringStream ss; if (action == Quackle::Move::Pass) ss << "- "; else if (action == Quackle::Move::Exchange) ss << "-" << QUACKLE_ALPHABET_PARAMETERS->userVisible(m_tiles); else if (action == Quackle::Move::Nonmove) ss << "nonmove"; else if (action == Quackle::Move::TimePenalty) ss << "timepenalty " << score; else if (action == Quackle::Move::UnusedTilesBonus) ss << "(" << QUACKLE_ALPHABET_PARAMETERS->userVisible(m_tiles) << ")"; else if (action == Quackle::Move::Place) { ss << positionString(); ss << " " << QUACKLE_ALPHABET_PARAMETERS->userVisible(m_tiles); } return ss.str(); }
void Reporter::reportGame(const Game &game, ComputerPlayer *computerPlayer, UVString *report) { UVOStringStream s; UVString header; reportHeader(game, &header); s << header; const PositionList::const_iterator end(game.history().end()); for (PositionList::const_iterator it = game.history().begin(); it != end; ++it) { UVString subreport; reportPosition(*it, computerPlayer, &subreport); s << subreport << MARK_UV('\n'); } UVString stats; reportGameStatistics(game, &stats); s << stats; *report = s.str(); }
UVString Player::storeInformationToString() const { UVOStringStream ss; ss << m_id << ';' << m_playerType << ';' << (m_playerType == ComputerPlayerType? m_computerPlayer->id() : (m_racksAreKnown? 0 : 1)) << ';' << m_name; return ss.str(); }
UVString Board::htmlBoard(const int tileSize) const { UVOStringStream ss; const int tdWidth = tileSize; const int tdHeight = tdWidth; const UVString nothingBgcolor = "gainsboro"; const UVString markBgcolor = "tan"; const UVString centerAlign = "valign=\"middle\" align=\"center\""; ss << "<table bgcolor=dimgrey>\n"; ss << "<tr>\n"; ss << "<td bgcolor=\"" << markBgcolor << "\" " << centerAlign << ">" << " " << "</td>"; for (int col = 0; col < m_width; ++col) ss << "<td width=" << tdWidth << " bgcolor=\"" << markBgcolor << "\" " << centerAlign << ">" << (UVChar)(MARK_UV('A') + col) << "</td>"; ss << "</tr>\n"; for (int row = 0; row < m_height; row++) { ss << "<tr>\n"; ss << "<td height=" << tdHeight << " bgcolor=\"" << markBgcolor << "\" " << centerAlign << ">" << row + 1 << "</td>\n"; for (int col = 0; col < m_width; col++) { UVString bgcolor = nothingBgcolor; if (letterMultiplier(row, col) == 2) bgcolor = "cornflowerblue"; else if (letterMultiplier(row, col) == 3) bgcolor = "slateblue"; else if (letterMultiplier(row, col) == 4) bgcolor = "blueviolet"; else if (wordMultiplier(row, col) == 2) bgcolor = "palevioletred"; else if (wordMultiplier(row, col) == 3) bgcolor = "firebrick"; else if (wordMultiplier(row, col) == 4) bgcolor = "goldenrod"; ss << "<td height=" << tdHeight << " width=" << tdWidth << " bgcolor=\"" << bgcolor << "\" " << centerAlign << ">"; if (m_letters[row][col] != QUACKLE_NULL_MARK) { const int fontSize = static_cast<int>(tileSize * 5/9); if (QUACKLE_ALPHABET_PARAMETERS->isBlankLetter(m_letters[row][col])) { const int blankFontSize = static_cast<int>(fontSize * 0.8); ss << "<table style=\"border: 1pt; border-style: dashed\"><tr><td width=" << tdWidth * 0.8 << " height=" << tdHeight * 0.8 << " bgcolor=\"" << bgcolor << "\" " << centerAlign << ">"; ss << "<span style=\"font-size: " << blankFontSize << "px\">"; ss << QUACKLE_ALPHABET_PARAMETERS->userVisible(QUACKLE_ALPHABET_PARAMETERS->clearBlankness(m_letters[row][col])); ss << "</span>"; ss << "</td></tr></table>"; } else { const int idealValueFontSize = static_cast<int>(tileSize * 2/9); const int minimumValueFontSize = 7; const int valueFontSize = minimumValueFontSize > idealValueFontSize? minimumValueFontSize : idealValueFontSize; ss << "<span style=\"font-size: " << fontSize << "px\">"; ss << QUACKLE_ALPHABET_PARAMETERS->userVisible(m_letters[row][col]); ss << "</span>"; ss << "<span style=\"font-size: " << valueFontSize << "px\">"; ss << QUACKLE_ALPHABET_PARAMETERS->score(m_letters[row][col]); ss << "</span>"; } } else { ss << " "; } ss << "</td>\n"; } ss << "</tr>\n"; } ss << "</table>\n"; return ss.str(); }
UVString Board::toString() const { UVOStringStream ss; ss << " "; for (int col = 0; col < m_width; ++col) ss << (UVChar)(MARK_UV('A') + col) << " "; ss << MARK_UV('\n') << " "; for (int col = 0; col < m_width; ++col) ss << "--"; ss << MARK_UV('\n'); for (int row = 0; row < m_height; row++) { if ((row + 1) < 10) ss << ' ' << row + 1 << '|'; else ss << row + 1 << '|'; for (int col = 0; col < m_width; col++) { if (m_letters[row][col] != QUACKLE_NULL_MARK) { ss << QUACKLE_ALPHABET_PARAMETERS->userVisible(m_letters[row][col]); } else { if (letterMultiplier(row, col) == 2) ss << "'"; else if (letterMultiplier(row, col) == 3) ss << '"'; else if (letterMultiplier(row, col) == 4) ss << '^'; else if (wordMultiplier(row, col) == 2) ss << '-'; else if (wordMultiplier(row, col) == 3) ss << '='; else if (wordMultiplier(row, col) == 4) ss << '~'; else ss << ' '; } if (col < width() - 1) ss << ' '; } ss << '|' << MARK_UV('\n'); } ss << " "; for (int col = 0; col < m_width; ++col) ss << "--"; return ss.str(); }
void Reporter::reportPosition(const GamePosition &position, ComputerPlayer *computerPlayer, UVString *report) { UVOStringStream s; UVOStringStream titleStream; if (!position.gameOver()) titleStream << position.currentPlayer().name() << MARK_UV(": Turn ") << position.turnNumber() << MARK_UV('\n'); const Quackle::PlayerList players(position.endgameAdjustedScores()); for (PlayerList::const_iterator it = players.begin(); it != players.end(); ++it) { s.width(3); s << right << ((*it) == position.currentPlayer()? MARK_UV("->") : MARK_UV(" ")); s << MARK_UV(' '); s.width(24); s << left << (*it).name() << MARK_UV(' '); s.width(9); s << (*it).rack().toString() << MARK_UV(' '); s.width(4); s << (*it).score(); s << MARK_UV('\n'); } if (computerPlayer && !position.gameOver()) { computerPlayer->setPosition(position); if (position.committedMove().isAMove()) computerPlayer->considerMove(position.committedMove()); const unsigned int movesToShow = 10; MoveList moves = computerPlayer->moves(movesToShow); int ourMoveIndex = 0; int i = 1; for (Quackle::MoveList::const_iterator it = moves.begin(); it != moves.end(); ++it, ++i) { if ((*it) == position.committedMove()) { ourMoveIndex = i; break; } } bool isUrp = false; if (position.committedMove().isAMove()) { // our move not in list if (ourMoveIndex == 0) { if (moves.size() == movesToShow) moves.pop_back(); isUrp = true; ourMoveIndex = movesToShow; moves.push_back(position.committedMove()); } } int highestScore = 0; double highestEquity = 0; unsigned int widestPositionString = 0; unsigned int widestMove = 0; bool hasWinPercentages = false; const Quackle::MoveList::const_iterator end(moves.end()); for (Quackle::MoveList::const_iterator it = moves.begin(); it != end; ++it) { if ((*it).prettyTiles().length() > widestMove) widestMove = (*it).prettyTiles().length(); if ((*it).positionString().length() > widestPositionString) widestPositionString = (*it).positionString().length(); if ((*it).win > 0) hasWinPercentages = true; if ((*it).equity > highestEquity) highestEquity = (*it).equity; if ((*it).score > highestScore) highestScore = (*it).score; } s << MARK_UV("--"); UVOStringStream headerStream; headerStream << computerPlayer->name(); headerStream << "'s choices (your play: "; if (isUrp) headerStream << "urp"; else headerStream << ourMoveIndex; headerStream << ")"; s.width(43); s << setfill(MARK_UV('-')); s << left << headerStream.str() << MARK_UV('\n'); s << setfill(MARK_UV(' ')); i = 1; for (Quackle::MoveList::const_iterator it = moves.begin(); it != end; ++it, ++i) { // column 2, the valuation. s.width(5); if ((*it).equity > (highestEquity - .01) && (*it).equity < (highestEquity + .01)) { s << MARK_UV("best"); } else { s << right << showpoint; s.precision(3); s << (highestEquity - (*it).equity); } s << (i == ourMoveIndex? MARK_UV("*") : MARK_UV(" ")); // column 3, the position string. s << left; s.width(widestPositionString); switch ((*it).action) { case Move::Place: s << (*it).positionString(); break; case Move::Exchange: s << MARK_UV("xch"); break; case Move::Pass: s << MARK_UV("pas"); break; case Move::UnusedTilesBonus: case Move::TimePenalty: case Move::Nonmove: break; } s << MARK_UV(" "); // column 4, the word s.width(widestMove); s << left << QUACKLE_ALPHABET_PARAMETERS->userVisible((*it).prettyTiles()) << MARK_UV(" "); // column 5, the score s.width(highestScore >= 100? 3 : (highestScore >= 10? 2 : 1)); s << left << (*it).score << MARK_UV(" "); // column 6, the win percentage if (hasWinPercentages) { s.precision(4); s.width(5); s << showpoint << ((*it).win * 100.0) << MARK_UV("% "); } // column 7, the leave s << (position.currentPlayer().rack() - (*it)).toString() << MARK_UV('\n'); } } if (position.gameOver()) { s << MARK_UV("\n Game over.\n\n"); } int j = 0; UVString wrappedTiles; LongLetterString unseenTiles = position.unseenBag().tiles(); for (Quackle::LongLetterString::const_iterator it = unseenTiles.begin(); it != unseenTiles.end(); ++it, ++j) { if (j >= 44) { wrappedTiles += MARK_UV('\n'); j = 0; } wrappedTiles += QUACKLE_ALPHABET_PARAMETERS->userVisible(*it); } s << MARK_UV("--"); s.width(43); s << setfill(MARK_UV('-')); s << MARK_UV("Tracking") << MARK_UV('\n'); s << wrappedTiles << MARK_UV(" ") << unseenTiles.size() << MARK_UV('\n'); UVString reportString = s.str(); UVString boardString = position.board().toString(); *report = titleStream.str(); // Ensure that the board ends with a newline. boardString += MARK_UV("\n"); // Put board and report side by side. UVString::const_iterator boardIt = boardString.begin(); UVString::const_iterator reportIt = reportString.begin(); UVString::const_iterator reportLineBeginning = reportString.begin(); UVString::const_iterator boardLineBeginning = boardString.begin(); const UVString::const_iterator reportEnd = reportString.end(); const UVString::const_iterator boardEnd = boardString.end(); while (true) { if (boardIt == boardEnd && reportIt == reportEnd) break; if (boardIt != boardEnd && (*boardIt) != MARK_UV('\n')) { ++boardIt; continue; } if (reportIt != reportEnd && (*reportIt) != MARK_UV('\n')) { ++reportIt; continue; } if (boardIt != boardEnd) { report->append(boardLineBeginning, boardIt); } if (reportIt != reportEnd) { report->append(MARK_UV(" ")); report->append(reportLineBeginning, reportIt); } boardLineBeginning = boardIt + 1; reportLineBeginning = reportIt + 1; if (boardIt != boardEnd) ++boardIt; if (reportIt != reportEnd) ++reportIt; report->append(MARK_UV("\n")); } }
void Reporter::reportGameStatistics(const Game &game, UVString *report) { (void) game; UVOStringStream s; *report = s.str(); }
void Reporter::reportHeader(const Game & /* game */, UVString *report) { UVOStringStream s; s << MARK_UV("Game Report\nGenerated by Quackle crossword game AI and analysis software\nhttp://quackle.org\n\n"); *report = s.str(); }
UVString Move::xml() const { UVString actionString; UVString rest; bool includeRest = false; bool includeTiles = false; bool includeScore = false; switch (action) { case Pass: actionString = MARK_UV("pass"); break; case Exchange: actionString = MARK_UV("exchange"); includeTiles = true; break; case Nonmove: actionString = MARK_UV("nonmove"); break; case TimePenalty: actionString = MARK_UV("timepenalty"); includeScore = true; break; case UnusedTilesBonus: actionString = MARK_UV("unusedtilesbonus"); includeTiles = true; includeScore = true; break; case Place: { actionString = MARK_UV("place"); UVOStringStream restStream; // adding row and column numbers I suppose is bloat //restStream << "position=\"" << positionString() << "\" startrow=\"" << startrow << "\" startcolumn=\"" << startcol << "\""; restStream << "position=\"" << positionString() << "\""; rest = restStream.str(); includeTiles = true; includeScore = true; includeRest = true; break; } } UVOStringStream xmlStream; xmlStream << "<move action=\"" << actionString << "\""; if (includeTiles) xmlStream << " tiles=\"" << QUACKLE_ALPHABET_PARAMETERS->userVisible(tiles()) << "\""; if (includeRest) xmlStream << " " << rest; if (includeScore) xmlStream << " score=\"" << score << "\""; xmlStream << " />"; return xmlStream.str(); }