diff options
-rw-r--r-- | data/lexica/copyrights.txt | 1 | ||||
-rw-r--r-- | game.cpp | 7 | ||||
-rw-r--r-- | move.cpp | 19 | ||||
-rw-r--r-- | move.h | 4 | ||||
-rw-r--r-- | quacker/boarddisplay.cpp | 28 | ||||
-rw-r--r-- | quacker/boarddisplay.h | 17 | ||||
-rw-r--r-- | quacker/configpages.cpp | 4 | ||||
-rw-r--r-- | quacker/configpages.h | 1 | ||||
-rw-r--r-- | quacker/graphicalreporter.cpp | 1 | ||||
-rw-r--r-- | quacker/letterbox.cpp | 9 | ||||
-rw-r--r-- | quacker/lister.cpp | 2 | ||||
-rw-r--r-- | quacker/quacker.cpp | 15 | ||||
-rw-r--r-- | quacker/quackersettings.cpp | 2 | ||||
-rw-r--r-- | quackleio/gcgio.cpp | 22 | ||||
-rw-r--r-- | quackleio/util.cpp | 6 | ||||
-rw-r--r-- | quackleio/util.h | 1 | ||||
-rw-r--r-- | reporter.cpp | 1 |
17 files changed, 122 insertions, 18 deletions
diff --git a/data/lexica/copyrights.txt b/data/lexica/copyrights.txt index 63edec3..980b9ae 100644 --- a/data/lexica/copyrights.txt +++ b/data/lexica/copyrights.txt @@ -1,3 +1,4 @@ eea8dfe5:Collins Scrabble™ Words 2012, ©HarperCollins Publishers Ltd 2015 48dea2c8:Collins Scrabble™ Words 2015, ©HarperCollins Publishers Ltd 2015 0109ce12:Official Tournament and Club Word List 2014 Edition (OTCWL2014) Copyright © 2014 Hasbro, Inc. Published under license with Merriam-Webster, Incorporated. +d5aeccff:ODS7 @@ -357,6 +357,11 @@ int GamePosition::validateMove(const Move &move) const } break; + case Move::BlindExchange: + if (!exchangeAllowed()) + ret |= TooLateExchange; + break; + case Move::UnusedTilesBonus: case Move::TimePenalty: ret = InvalidAction; @@ -783,7 +788,7 @@ bool GamePosition::incrementTurn() } } - if ((m_moveMade.action == Move::Place && m_moveMade.effectiveScore() == 0) || m_moveMade.action == Move::Exchange || m_moveMade.action == Move::Pass) + if ((m_moveMade.action == Move::Place && m_moveMade.effectiveScore() == 0) || m_moveMade.action == Move::Exchange || m_moveMade.action == Move::BlindExchange || m_moveMade.action == Move::Pass) ++m_scorelessTurnsInARow; else m_scorelessTurnsInARow = 0; @@ -48,6 +48,10 @@ bool operator==(const Move &move1, const Move &move2) ret = (Quackle::String::alphabetize(move1.tiles()) == Quackle::String::alphabetize(move2.tiles())); break; + case Quackle::Move::BlindExchange: + ret = (move1.tiles().length() == move2.tiles().length()); + break; + case Quackle::Move::Pass: case Quackle::Move::Nonmove: case Quackle::Move::TimePenalty: @@ -124,6 +128,7 @@ UVString Move::xml() const break; case Exchange: + case BlindExchange: actionString = MARK_UV("exchange"); includeTiles = true; break; @@ -180,10 +185,12 @@ 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); + if (action == Quackle::Move::Pass) + ss << "- "; + else if (action == Quackle::Move::Exchange) + ss << "-" << QUACKLE_ALPHABET_PARAMETERS->userVisible(m_tiles); + else if (action == Quackle::Move::BlindExchange) + ss << "-" << m_tiles.length(); else if (action == Quackle::Move::Nonmove) ss << "nonmove"; else if (action == Quackle::Move::TimePenalty) @@ -290,11 +297,11 @@ Move Move::createChallengedPhoney(int zeroIndexedRow, int zeroIndexedColumn, boo return move; } -Move Move::createExchangeMove(LetterString tilesToExchange) +Move Move::createExchangeMove(LetterString tilesToExchange, bool isBlind) { Move move; - move.action = Move::Exchange; + move.action = isBlind ? Move::BlindExchange : Move::Exchange; move.setTiles(tilesToExchange); move.score = 0; @@ -43,7 +43,7 @@ namespace Quackle class Move { public: - enum Action { Place = 0, Exchange, Pass, UnusedTilesBonus, TimePenalty, Nonmove }; + enum Action { Place = 0, Exchange, BlindExchange, Pass, UnusedTilesBonus, TimePenalty, Nonmove }; // creates a pass move with 0 equity; // tiles is "", score and equity are zero @@ -124,7 +124,7 @@ public: static Move createChallengedPhoney(UVString placeString, LetterString word); static Move createChallengedPhoney(int zeroIndexedRow, int zeroIndexedColumn, bool horizontal, LetterString word); - static Move createExchangeMove(LetterString tilesToExchange); + static Move createExchangeMove(LetterString tilesToExchange, bool isBlind); static Move createUnusedTilesBonus(LetterString unusedTiles, int bonus); static Move createTimePenalty(int penalty); static Move createPassMove(); diff --git a/quacker/boarddisplay.cpp b/quacker/boarddisplay.cpp index 9dd49da..85b551b 100644 --- a/quacker/boarddisplay.cpp +++ b/quacker/boarddisplay.cpp @@ -32,8 +32,9 @@ BoardWithQuickEntry::BoardWithQuickEntry(QWidget *parent) m_vlayout = new QVBoxLayout(this); Geometry::setupInnerLayout(m_vlayout); - m_lineEdit = new QLineEdit; + m_lineEdit = new QLineEditWithShiftReturn; connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(quickEditReturnPressed())); + connect(m_lineEdit, SIGNAL(shiftReturnPressed()), this, SLOT(quickEditShiftReturnPressed())); QLabel *placeLabel = new QLabel(tr("Move: '<position> <word>' or 'exchange <tiles|number>'")); placeLabel->setBuddy(m_lineEdit); @@ -96,6 +97,13 @@ void BoardWithQuickEntry::quickEditReturnPressed() m_lineEdit->clear(); } +void BoardWithQuickEntry::quickEditShiftReturnPressed() +{ + quickEditReturnPressed(); + performCommit(); + m_lineEdit->setFocus(); +} + void BoardWithQuickEntry::plusFive() { m_localCandidateMove.setScoreAddition(m_localCandidateMove.scoreAddition() + 5); @@ -170,7 +178,7 @@ void BoardWithQuickEntry::processCommand(const QString &command) if (isPass) move = Quackle::Move::createPassMove(); else - move = Quackle::Move::createExchangeMove(encodedLetters); + move = Quackle::Move::createExchangeMove(encodedLetters, isIntConvertable); } else { @@ -217,3 +225,19 @@ void TextBoard::positionChanged(const Quackle::GamePosition &position) //m_textEdit->setHtml(QString("<html><font size=\"+4\"><pre>%1</pre></font></html>").arg(QuackleIO::Util::uvStringToQString(position.boardAfterMoveMade().toString()))); m_textEdit->setPlainText(QString("%1").arg(QuackleIO::Util::uvStringToQString(position.boardAfterMoveMade().toString()))); } + +/////////// + +void QLineEditWithShiftReturn::keyPressEvent(QKeyEvent * e) +{ + if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) + { + if (e->modifiers() & Qt::ShiftModifier) + { + emit shiftReturnPressed(); + return; + } + } + QLineEdit::keyPressEvent(e); +} + diff --git a/quacker/boarddisplay.h b/quacker/boarddisplay.h index 35ebcb7..fbb71c1 100644 --- a/quacker/boarddisplay.h +++ b/quacker/boarddisplay.h @@ -22,8 +22,10 @@ #include <move.h> #include "view.h" +#include <QLineEdit> class QLineEdit; +class QLineEditWithShiftReturn; class QPushButton; class QTextEdit; class QVBoxLayout; @@ -49,6 +51,7 @@ protected slots: private slots: void quickEditReturnPressed(); + void quickEditShiftReturnPressed(); void plusFive(); void performCommit(); void reset(); @@ -60,7 +63,7 @@ protected: QVBoxLayout *m_vlayout; private: - QLineEdit *m_lineEdit; + QLineEditWithShiftReturn *m_lineEdit; QPushButton *m_commitButton; Quackle::Move m_localCandidateMove; }; @@ -79,4 +82,16 @@ private: QTextEdit *m_textEdit; }; +class QLineEditWithShiftReturn : public QLineEdit +{ +Q_OBJECT + +signals: + void shiftReturnPressed(); + +public: + virtual void keyPressEvent(QKeyEvent * e); +}; + + #endif diff --git a/quacker/configpages.cpp b/quacker/configpages.cpp index c246797..ee807fd 100644 --- a/quacker/configpages.cpp +++ b/quacker/configpages.cpp @@ -96,10 +96,12 @@ InterfacePage::InterfacePage(QWidget *parent) QGroupBox *miscellanyGroup = new QGroupBox(tr("Miscellany")); m_vowelFirstCheck = new QCheckBox(tr("&Vowel-first alphabetizing")); m_octothorpCheck = new QCheckBox(tr("&Octothorp British words")); + m_scoreInvalidAsZero = new QCheckBox(tr("&Score 0 for plays with illegal words")); QGridLayout *miscellanyLayout = new QGridLayout; miscellanyLayout->addWidget(m_vowelFirstCheck, 0, 0); miscellanyLayout->addWidget(m_octothorpCheck, 1, 0); + miscellanyLayout->addWidget(m_scoreInvalidAsZero, 2, 0); miscellanyGroup->setLayout(miscellanyLayout); QVBoxLayout *mainLayout = new QVBoxLayout; @@ -116,6 +118,7 @@ void InterfacePage::readConfig() m_verboseLabelsCheck->setChecked(QuackerSettings::self()->verboseLabels); m_scoreLabelsCheck->setChecked(QuackerSettings::self()->scoreLabels); m_octothorpCheck->setChecked(QuackleIO::UtilSettings::self()->octothorpBritish); + m_scoreInvalidAsZero->setChecked(QuackleIO::UtilSettings::self()->scoreInvalidAsZero); } void InterfacePage::writeConfig() @@ -125,5 +128,6 @@ void InterfacePage::writeConfig() QuackerSettings::self()->verboseLabels = m_verboseLabelsCheck->isChecked(); QuackerSettings::self()->scoreLabels = m_scoreLabelsCheck->isChecked(); QuackleIO::UtilSettings::self()->octothorpBritish = m_octothorpCheck->isChecked(); + QuackleIO::UtilSettings::self()->scoreInvalidAsZero = m_scoreInvalidAsZero->isChecked(); } diff --git a/quacker/configpages.h b/quacker/configpages.h index 6d02ec0..6b61375 100644 --- a/quacker/configpages.h +++ b/quacker/configpages.h @@ -52,6 +52,7 @@ private: QCheckBox *m_verboseLabelsCheck; QCheckBox *m_scoreLabelsCheck; QCheckBox *m_octothorpCheck; + QCheckBox *m_scoreInvalidAsZero; QComboBox *m_britishColoringCombo; }; diff --git a/quacker/graphicalreporter.cpp b/quacker/graphicalreporter.cpp index 2fb0842..a7ca9f5 100644 --- a/quacker/graphicalreporter.cpp +++ b/quacker/graphicalreporter.cpp @@ -192,6 +192,7 @@ void GraphicalReporter::reportPosition(const Quackle::GamePosition &position, Qu } case Quackle::Move::Exchange: + case Quackle::Move::BlindExchange: default: item = QuackleIO::Util::moveToDetailedString(*it); break; diff --git a/quacker/letterbox.cpp b/quacker/letterbox.cpp index 399b73a..04213d7 100644 --- a/quacker/letterbox.cpp +++ b/quacker/letterbox.cpp @@ -232,6 +232,7 @@ void Letterbox::loadFile() QTextStream stream(&file); QString line; + stream.setCodec(QTextCodec::codecForName("UTF-8")); m_initializationChuu = true; @@ -517,6 +518,7 @@ void Letterbox::outputResults() } QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); if (m_numberIterator < m_clueResults.count()) stream << "\" Resume: " << m_numberIterator << "\n"; @@ -553,6 +555,7 @@ void Letterbox::outputResults() } QTextStream stream(&missesFile); + stream.setCodec(QTextCodec::codecForName("UTF-8")); for (ClueResultList::iterator it = m_clueResults.begin(); it != m_clueResults.end(); ++it) { @@ -918,6 +921,7 @@ void Letterbox::print() setModified(wasModified); QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); stream << printer.html() << "\n"; file.close(); @@ -948,6 +952,7 @@ void Letterbox::printStudy() jumpTo(m_clueResults.size() - 1); QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); stream << generateStudySheet(m_answers.begin(), m_answers.end()) << "\n"; file.close(); @@ -1169,7 +1174,9 @@ void HTMLRepresentation::setHTML(const QString &text, ContentType type) QString HTMLRepresentation::html() { - return m_html; + return QString("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>") + + m_html + + QString("</body></html>"); } void HTMLRepresentation::setWords(ClueResultList::ConstIterator start, ClueResultList::ConstIterator end, bool revers) diff --git a/quacker/lister.cpp b/quacker/lister.cpp index be3e335..08e2405 100644 --- a/quacker/lister.cpp +++ b/quacker/lister.cpp @@ -233,6 +233,7 @@ void ListerDialog::openFile() if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); QString line; while (!stream.atEnd()) { @@ -430,6 +431,7 @@ QString ListerDialog::writeList(bool alphagrams) } QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); QMap<QString, Dict::WordList> map(anagramMap()); diff --git a/quacker/quacker.cpp b/quacker/quacker.cpp index 6b5becb..ffe6531 100644 --- a/quacker/quacker.cpp +++ b/quacker/quacker.cpp @@ -297,6 +297,7 @@ void TopLevel::setCandidateMove(const Quackle::Move &move) if (!m_game->hasPositions() || (move.action == Quackle::Move::Place && move.tiles().empty())) return; + bool playHasIllegalWords = false; Quackle::Move prettiedMove(move); m_game->currentPosition().ensureMoveTilesDoNotIncludePlayThru(prettiedMove); m_game->currentPosition().ensureMovePrettiness(prettiedMove); @@ -367,6 +368,8 @@ void TopLevel::setCandidateMove(const Quackle::Move &move) { prettiedMove.setIsChallengedPhoney(true); } + else + playHasIllegalWords = true; } validityFlags ^= Quackle::GamePosition::UnacceptableWord; @@ -384,13 +387,18 @@ void TopLevel::setCandidateMove(const Quackle::Move &move) if (!carryOn) return; - m_game->currentPosition().scoreMove(prettiedMove); + if (playHasIllegalWords && QuackleIO::UtilSettings::self()->scoreInvalidAsZero) + prettiedMove.score = 0; + else + m_game->currentPosition().scoreMove(prettiedMove); m_game->currentPosition().addAndSetMoveMade(prettiedMove); switchToTab(ChoicesTabIndex); ensureUpToDateSimulatorMoveList(); } - if (!m_game->currentPosition().currentPlayer().racksAreKnown() && !m_game->currentPosition().currentPlayer().rack().contains(prettiedMove.usedTiles())) + if (!m_game->currentPosition().currentPlayer().racksAreKnown() && + !m_game->currentPosition().currentPlayer().rack().contains(prettiedMove.usedTiles()) && + prettiedMove.action != Quackle::Move::BlindExchange) { m_game->currentPosition().setCurrentPlayerRack(Quackle::Rack(prettiedMove.usedTiles())); } @@ -1319,6 +1327,7 @@ void TopLevel::reportAs(Quackle::ComputerPlayer *player) Quackle::ComputerPlayer *clone = player->clone(); QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); QuackleIO::StreamingReporter::reportGame(*m_game, clone, stream); delete clone; } @@ -2077,6 +2086,7 @@ void TopLevel::writeAsciiToFile(const QString &text, const QString &filename) } QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); stream << text << "\n"; file.close(); @@ -2102,6 +2112,7 @@ void TopLevel::print() } QTextStream stream(&file); + stream.setCodec(QTextCodec::codecForName("UTF-8")); //stream << printer.html() << "\n"; file.close(); diff --git a/quacker/quackersettings.cpp b/quacker/quackersettings.cpp index 1889848..510e43a 100644 --- a/quacker/quackersettings.cpp +++ b/quacker/quackersettings.cpp @@ -45,6 +45,7 @@ void QuackerSettings::readSettings() scoreLabels = settings.value("quackle/settings/score-labels", scoreLabels).toBool(); QuackleIO::UtilSettings::self()->vowelFirst = settings.value("quackle/settings/vowel-first", QuackleIO::UtilSettings::self()->vowelFirst).toBool(); QuackleIO::UtilSettings::self()->octothorpBritish = settings.value("quackle/settings/octothorp-british", QuackleIO::UtilSettings::self()->octothorpBritish).toBool(); + QuackleIO::UtilSettings::self()->scoreInvalidAsZero = settings.value("quackle/settings/score-invalid-as-zero", QuackleIO::UtilSettings::self()->scoreInvalidAsZero).toBool(); m_letterboxSettings.readSettings(); } @@ -57,6 +58,7 @@ void QuackerSettings::writeSettings() settings.setValue("quackle/settings/score-labels", scoreLabels); settings.setValue("quackle/settings/vowel-first", QuackleIO::UtilSettings::self()->vowelFirst); settings.setValue("quackle/settings/octothorp-british", QuackleIO::UtilSettings::self()->octothorpBritish); + settings.setValue("quackle/settings/score-invalid-as-zero", QuackleIO::UtilSettings::self()->scoreInvalidAsZero); m_letterboxSettings.writeSettings(); } diff --git a/quackleio/gcgio.cpp b/quackleio/gcgio.cpp index 30fac0f..8f8112f 100644 --- a/quackleio/gcgio.cpp +++ b/quackleio/gcgio.cpp @@ -61,6 +61,7 @@ Quackle::Game *GCGIO::read(QTextStream &stream, int flags) bool gameStarted = false; QString line; + stream.setCodec(QTextCodec::codecForName("ISO-8859-1")); while (!stream.atEnd()) { line = stream.readLine(); @@ -129,6 +130,11 @@ Quackle::Game *GCGIO::read(QTextStream &stream, int flags) incompleteRack = Util::encode(rackString); hasIncompleteRack = true; } + else if (line.startsWith("#character-encoding")) + { + QString encoding{line.right(line.length() - 20).trimmed()}; + stream.setCodec(QTextCodec::codecForName(encoding.toAscii())); + } } else if (line.startsWith(">")) { @@ -180,10 +186,21 @@ Quackle::Game *GCGIO::read(QTextStream &stream, int flags) else if (firstMoveBite.startsWith("-")) { const QString exchangedLetters = firstMoveBite.right(firstMoveBite.length() - 1); - if (exchangedLetters.isEmpty()) + bool isLetterCount = false; + uint letterCount = exchangedLetters.toUInt(&isLetterCount); + + if (exchangedLetters.isEmpty() || (isLetterCount && letterCount == 0)) move = Quackle::Move::createPassMove(); + else if (isLetterCount) + { + Quackle::LetterString encodedLetters; + + for (uint i = 0; i < letterCount; ++i) + encodedLetters.push_back(QUACKLE_BLANK_MARK); + move = Quackle::Move::createExchangeMove(encodedLetters, true); + } else - move = Quackle::Move::createExchangeMove(Util::encode(exchangedLetters)); + move = Quackle::Move::createExchangeMove(Util::encode(exchangedLetters), false); } else if (firstMoveBite.startsWith("(time)")) { @@ -311,6 +328,7 @@ bool GCGIO::canRead(QTextStream &stream) const void GCGIO::write(const Quackle::Game &game, QTextStream &stream) { Quackle::PlayerList players = game.players(); + stream.setCodec(QTextCodec::codecForName("ISO-8859-1")); for (Quackle::PlayerList::iterator it = players.begin(); it != players.end(); ++it) { stream << "#player" << (*it).id() + 1 << " " << Util::uvStringToQString((*it).abbreviatedName()) << " " << Util::uvStringToQString((*it).name()) << endl; diff --git a/quackleio/util.cpp b/quackleio/util.cpp index 817edac..901c65e 100644 --- a/quackleio/util.cpp +++ b/quackleio/util.cpp @@ -34,7 +34,7 @@ UtilSettings *UtilSettings::self() } UtilSettings::UtilSettings() - : octothorpBritish(true), vowelFirst(false) + : octothorpBritish(true), vowelFirst(false), scoreInvalidAsZero(false) { m_self = this; } @@ -55,6 +55,10 @@ QString Util::moveToDetailedString(const Quackle::Move &move) ret = QObject::tr("Exch. %1").arg(prettyTiles); break; + case Quackle::Move::BlindExchange: + ret = QObject::tr("Exch. %1").arg(move.tiles().length()); + break; + case Quackle::Move::UnusedTilesBonus: ret = QObject::tr("2*(%1)").arg(letterStringToQString(Util::alphagram(move.usedTiles()))); break; diff --git a/quackleio/util.h b/quackleio/util.h index 10a57a2..62545bb 100644 --- a/quackleio/util.h +++ b/quackleio/util.h @@ -42,6 +42,7 @@ public: bool octothorpBritish; bool vowelFirst; + bool scoreInvalidAsZero; private: static UtilSettings *m_self; diff --git a/reporter.cpp b/reporter.cpp index c844afa..7054763 100644 --- a/reporter.cpp +++ b/reporter.cpp @@ -156,6 +156,7 @@ void Reporter::reportPosition(const GamePosition &position, ComputerPlayer *comp break; case Move::Exchange: + case Move::BlindExchange: s << MARK_UV("xch"); break; |