summaryrefslogtreecommitdiff
path: root/quacker/newgame.cpp
diff options
context:
space:
mode:
authorJason Katz-Brown <jason@airbnb.com>2013-08-25 02:17:13 -0700
committerJason Katz-Brown <jason@airbnb.com>2013-08-25 02:17:13 -0700
commit9306cb60c32082c5403931de0823a9fd5daa196c (patch)
treeca1b6eb695fdf3f0c2294e92416b272164bae642 /quacker/newgame.cpp
parent8fb2c681cecc01b46b0f4ba02d5cc177c4747b1c (diff)
Initial git commit.
Diffstat (limited to 'quacker/newgame.cpp')
-rw-r--r--quacker/newgame.cpp425
1 files changed, 425 insertions, 0 deletions
diff --git a/quacker/newgame.cpp b/quacker/newgame.cpp
new file mode 100644
index 0000000..97ef15d
--- /dev/null
+++ b/quacker/newgame.cpp
@@ -0,0 +1,425 @@
+/*
+ * Quackle -- Crossword game artificial intelligence and analysis tool
+ * Copyright (C) 2005-2006 Jason Katz-Brown and John O'Laughlin.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <iostream>
+
+#include <QtGui>
+
+#include <computerplayer.h>
+#include <datamanager.h>
+#include <quackleio/util.h>
+
+#include "newgame.h"
+#include "customqsettings.h"
+
+NewGameDialog::NewGameDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_tabs = new QTabWidget;
+
+ m_playerTab = new PlayerTab;
+ m_tabs->addTab(m_playerTab, tr("&Players"));
+
+ QPushButton *okButton = new QPushButton(tr("&OK"));
+ QPushButton *cancelButton = new QPushButton(tr("&Cancel"));
+
+ connect(okButton, SIGNAL(clicked()), this, SLOT(done()));
+ connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
+
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ buttonLayout->addStretch(1);
+ buttonLayout->addWidget(okButton);
+ buttonLayout->addWidget(cancelButton);
+
+ QVBoxLayout *topLayout = new QVBoxLayout;
+ topLayout->addWidget(m_tabs);
+ topLayout->addLayout(buttonLayout);
+ setLayout(topLayout);
+
+ loadSettings();
+
+ setWindowTitle(tr("New Game - Quackle"));
+ okButton->setDefault(true);
+}
+
+Quackle::PlayerList NewGameDialog::players() const
+{
+ return m_playerTab->players();
+}
+
+void NewGameDialog::done()
+{
+ saveSettings();
+ accept();
+}
+
+void NewGameDialog::saveSettings()
+{
+ m_playerTab->saveSettings();
+}
+
+void NewGameDialog::loadSettings()
+{
+}
+
+/////////////
+
+PlayerTab::PlayerTab(QWidget *parent)
+ : QWidget(parent), m_changingEditorManually(false)
+{
+ m_addPlayerButton = new QPushButton(tr("&Add New Player"));
+ m_removePlayerButton = new QPushButton(tr("&Remove Player"));
+
+ connect(m_addPlayerButton, SIGNAL(clicked()), this, SLOT(addPlayer()));
+ connect(m_removePlayerButton, SIGNAL(clicked()), this, SLOT(removePlayer()));
+
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ buttonLayout->addWidget(m_addPlayerButton);
+ buttonLayout->addWidget(m_removePlayerButton);
+
+ m_playersTreeWidget = new QTreeWidget;
+
+ // probably too confusing to be able to select multiple players at oncet?
+ // all functionality for it is implemented wrt removing multiple players at oncet
+ //m_playersTreeWidget->setSelectionMode(QTreeWidget::ExtendedSelection);
+
+ connect(m_playersTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()));
+ QStringList headers;
+ headers << tr("Name") << tr("Controller");
+ m_playersTreeWidget->setHeaderLabels(headers);
+
+ m_editGroup = new QGroupBox(tr("Player &Information"));
+ QHBoxLayout *editLayout = new QHBoxLayout(m_editGroup);
+
+ m_nameEdit = new QLineEdit;
+ connect(m_nameEdit, SIGNAL(textEdited(const QString &)), this, SLOT(playerEdited()));
+ editLayout->addWidget(m_nameEdit);
+
+ m_playerType = new QComboBox;
+
+ QStringList playerTypes(tr("Human"));
+ playerTypes.push_back(tr("Human With Unknown Racks"));
+ for (Quackle::PlayerList::const_reverse_iterator it = QUACKLE_COMPUTER_PLAYERS.rbegin(); it != QUACKLE_COMPUTER_PLAYERS.rend(); ++it)
+ {
+ if ((*it).computerPlayer()->isUserVisible())
+ playerTypes.push_back(QuackleIO::Util::uvStringToQString((*it).name()));
+ }
+ m_playerType->addItems(playerTypes);
+
+ connect(m_playerType, SIGNAL(activated(const QString &)), this, SLOT(playerEdited()));
+ editLayout->addWidget(m_playerType);
+
+ QVBoxLayout *topLayout = new QVBoxLayout;
+ topLayout->addWidget(m_playersTreeWidget);
+ topLayout->addWidget(m_editGroup);
+ topLayout->addStretch();
+ topLayout->addLayout(buttonLayout);
+
+ setLayout(topLayout);
+
+ QTimer::singleShot(0, this, SLOT(populatePlayers()));
+}
+
+void PlayerTab::saveSettings()
+{
+ CustomQSettings settings;
+
+ QList<QVariant> playerIds;
+
+ QList<Quackle::Player> playerList(m_playerMap.keys());
+
+ for (QList<Quackle::Player>::iterator it = playerList.begin(); it != playerList.end(); ++it)
+ {
+ playerIds.push_back((*it).id());
+ settings.setValue(QString("quackle/newgame/players/%1").arg((*it).id()), QuackleIO::Util::uvStringToQString((*it).storeInformationToString()));
+ }
+
+ settings.setValue("quackle/newgame/playerIds", playerIds);
+
+ // this is a workaround for one item lists getting saved oddly
+ if (playerIds.size() == 1)
+ settings.setValue("quackle/newgame/playerId", playerIds.front().toInt());
+ else
+ settings.setValue("quackle/newgame/playerId", -1);
+}
+
+void PlayerTab::populatePlayers()
+{
+ CustomQSettings settings;
+
+ // this is a workaround for one item lists getting saved oddly
+ int playerId = settings.value("quackle/newgame/playerId", -1).toInt();
+
+ QList<QVariant> playerIds;
+ if (playerId >= 0)
+ playerIds.push_back(QVariant(playerId));
+ else
+ playerIds = settings.value("quackle/newgame/playerIds", QList<QVariant>()).toList();
+
+ for (QList<QVariant>::iterator it = playerIds.begin(); it != playerIds.end(); ++it)
+ {
+ int id = (*it).toInt();
+
+ QString infoString = settings.value(QString("quackle/newgame/players/%1").arg(id)).toString();
+ if (infoString.isNull())
+ continue;
+
+ Quackle::Player player(Quackle::Player::makePlayerFromString(QuackleIO::Util::qstringToString(infoString)));
+ if (!player.computerPlayer())
+ {
+ // this is required if the computer id in the settings is no longer
+ // offered by Quackle
+ player.setComputerPlayer(defaultComputerPlayer());
+ }
+ addPlayer(player);
+ }
+
+ if (m_playerMap.empty())
+ {
+ // one computer
+ Quackle::Player newPlayer(QuackleIO::Util::qstringToString(tr("Quackle")), Quackle::Player::ComputerPlayerType, 0);
+ newPlayer.setComputerPlayer(defaultComputerPlayer());
+ addPlayer(newPlayer);
+
+ // and a human
+ addPlayer();
+ }
+
+ selectionChanged();
+}
+
+Quackle::PlayerList PlayerTab::players() const
+{
+ // this is all silly to do but oh well
+ QList<Quackle::Player> playerList(m_playerMap.keys());
+ Quackle::PlayerList ret;
+
+ for (QList<Quackle::Player>::const_iterator it = playerList.begin(); it != playerList.end(); ++it)
+ {
+ ret.push_back(*it);
+
+ if (ret.back().name().empty())
+ ret.back().setName(QuackleIO::Util::qstringToString(tr("No Name")));
+
+ QStringList splitName = QuackleIO::Util::uvStringToQString(ret.back().name()).split(QRegExp("\\s+"));
+ ret.back().setAbbreviatedName(QuackleIO::Util::qstringToString(splitName.join("_")));
+ }
+
+ return ret;
+}
+
+void PlayerTab::addPlayer(const Quackle::Player &player)
+{
+ QTreeWidgetItem *item = new QTreeWidgetItem(m_playersTreeWidget);
+ m_playerMap.insert(player, item);
+ setItem(item, player);
+
+ m_playersTreeWidget->clearSelection();
+ m_playersTreeWidget->setItemSelected(item, true);
+}
+
+Quackle::ComputerPlayer *PlayerTab::defaultComputerPlayer() const
+{
+ for (Quackle::PlayerList::const_reverse_iterator it = QUACKLE_COMPUTER_PLAYERS.rbegin(); it != QUACKLE_COMPUTER_PLAYERS.rend(); ++it)
+ if ((*it).computerPlayer()->isUserVisible() && !(*it).computerPlayer()->isSlow())
+ return (*it).computerPlayer();
+
+ return QUACKLE_COMPUTER_PLAYERS.back().computerPlayer();
+}
+
+void PlayerTab::setItem(QTreeWidgetItem *item, const Quackle::Player &player)
+{
+ item->setText(PlayerName, QuackleIO::Util::uvStringToQString(player.name()));
+ item->setText(PlayerType, stringForPlayer(player));
+}
+
+void PlayerTab::addPlayer()
+{
+ QString name(tr("New Player %1"));
+ QString unusedName;
+ int unusedId;
+
+ for (int i = 1; ; ++i)
+ {
+ unusedName = name.arg(i);
+ UVString nameString = QuackleIO::Util::qstringToString(unusedName);
+
+ bool found = false;
+ for (QMap<Quackle::Player, QTreeWidgetItem *>::iterator it = m_playerMap.begin(); it != m_playerMap.end(); ++it)
+ {
+ if (it.key().name() == nameString)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ break;
+ }
+
+ for (unusedId = 0; ; ++unusedId)
+ {
+ bool found = false;
+ for (QMap<Quackle::Player, QTreeWidgetItem *>::iterator it = m_playerMap.begin(); it != m_playerMap.end(); ++it)
+ {
+ if (it.key().id() == unusedId)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ break;
+ }
+
+ Quackle::Player player(QuackleIO::Util::qstringToString(unusedName), Quackle::Player::HumanPlayerType, unusedId);
+ addPlayer(player);
+}
+
+void PlayerTab::removePlayer()
+{
+ QList<QTreeWidgetItem *> items = m_playersTreeWidget->selectedItems();
+ for (QList<QTreeWidgetItem *>::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ delete *it;
+
+ QList<Quackle::Player> correspondingPlayers(m_playerMap.keys(*it));
+
+ if (correspondingPlayers.size() > 0)
+ m_playerMap.remove(correspondingPlayers.front());
+ }
+
+ selectionChanged();
+}
+
+void PlayerTab::playerEdited()
+{
+ if (m_changingEditorManually || !hasSelection())
+ return;
+
+ Quackle::Player lastPlayer(getLastPlayer());
+ if (lastPlayer.id() < 0)
+ return;
+
+ lastPlayer.setName(QuackleIO::Util::qstringToString(m_nameEdit->text()));
+ updatePlayerFromString(m_playerType->currentText(), lastPlayer);
+
+ // please excuse the HORRIBLE use of QMap here
+ QTreeWidgetItem *item = m_playerMap.value(lastPlayer);
+ m_playerMap.remove(lastPlayer);
+ m_playerMap.insert(lastPlayer, item);
+
+ setItem(item, lastPlayer);
+}
+
+void PlayerTab::selectionChanged()
+{
+ bool hasSel = hasSelection();
+ m_removePlayerButton->setEnabled(hasSel);
+ m_editGroup->setEnabled(hasSel);
+
+ if (!hasSel)
+ return;
+
+ Quackle::Player lastPlayer(getLastPlayer());
+
+ if (lastPlayer.id() < 0)
+ {
+ UVcout << "last player id < 0" << endl;
+ return;
+ }
+
+ m_changingEditorManually = true;
+
+ m_nameEdit->setText(QuackleIO::Util::uvStringToQString(lastPlayer.name()));
+ m_playerType->setCurrentIndex(m_playerType->findText(stringForPlayer(lastPlayer)));
+
+ m_changingEditorManually = false;
+}
+
+bool PlayerTab::hasSelection()
+{
+ return !m_playersTreeWidget->selectedItems().empty();
+}
+
+Quackle::Player PlayerTab::getLastPlayer()
+{
+ QTreeWidgetItem *lastItem = m_playersTreeWidget->selectedItems().back();
+ Quackle::Player lastPlayer;
+ for (QMap<Quackle::Player, QTreeWidgetItem *>::iterator it = m_playerMap.begin(); it != m_playerMap.end(); ++it)
+ if (it.value() == lastItem)
+ return it.key();
+
+ // urp!
+ return Quackle::Player();
+}
+
+QString PlayerTab::stringForPlayer(const Quackle::Player &player)
+{
+ switch (player.type())
+ {
+ case Quackle::Player::HumanPlayerType:
+ {
+ if (player.racksAreKnown())
+ return tr("Human");
+ else
+ return tr("Human With Unknown Racks");
+ }
+
+ case Quackle::Player::ComputerPlayerType:
+ if (player.computerPlayer())
+ return QuackleIO::Util::uvStringToQString(player.computerPlayer()->name());
+
+ default:
+ return tr("Unknown Player");
+ }
+}
+
+void PlayerTab::updatePlayerFromString(const QString &typeString, Quackle::Player &player)
+{
+ if (typeString == tr("Human"))
+ {
+ player.setType(Quackle::Player::HumanPlayerType);
+ player.setRacksAreKnown(true);
+ player.setComputerPlayer(0);
+ return;
+ }
+
+ if (typeString == tr("Human With Unknown Racks"))
+ {
+ player.setType(Quackle::Player::HumanPlayerType);
+ player.setRacksAreKnown(false);
+ player.setComputerPlayer(0);
+ return;
+ }
+
+ player.setType(Quackle::Player::ComputerPlayerType);
+
+ bool found = false;
+ const Quackle::Player &modelPlayer = QUACKLE_COMPUTER_PLAYERS.playerForName(QuackleIO::Util::qstringToString(typeString), found);
+
+ if (found)
+ player.setComputerPlayer(modelPlayer.computerPlayer());
+ else
+ player.setComputerPlayer(0);
+}
+