summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/lexica/copyrights.txt1
-rw-r--r--game.cpp7
-rw-r--r--move.cpp19
-rw-r--r--move.h4
-rw-r--r--quacker/boarddisplay.cpp28
-rw-r--r--quacker/boarddisplay.h17
-rw-r--r--quacker/configpages.cpp4
-rw-r--r--quacker/configpages.h1
-rw-r--r--quacker/graphicalreporter.cpp1
-rw-r--r--quacker/letterbox.cpp9
-rw-r--r--quacker/lister.cpp2
-rw-r--r--quacker/quacker.cpp15
-rw-r--r--quacker/quackersettings.cpp2
-rw-r--r--quackleio/gcgio.cpp22
-rw-r--r--quackleio/util.cpp6
-rw-r--r--quackleio/util.h1
-rw-r--r--reporter.cpp1
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
diff --git a/game.cpp b/game.cpp
index 845e864..242556c 100644
--- a/game.cpp
+++ b/game.cpp
@@ -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;
diff --git a/move.cpp b/move.cpp
index eaaf8b6..7f77dc5 100644
--- a/move.cpp
+++ b/move.cpp
@@ -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;
diff --git a/move.h b/move.h
index f4d1827..e628b52 100644
--- a/move.h
+++ b/move.h
@@ -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;