diff options
author | Jason Katz-Brown <jason@airbnb.com> | 2013-08-25 02:17:13 -0700 |
---|---|---|
committer | Jason Katz-Brown <jason@airbnb.com> | 2013-08-25 02:17:13 -0700 |
commit | 9306cb60c32082c5403931de0823a9fd5daa196c (patch) | |
tree | ca1b6eb695fdf3f0c2294e92416b272164bae642 /quacker/newgame.cpp | |
parent | 8fb2c681cecc01b46b0f4ba02d5cc177c4747b1c (diff) |
Initial git commit.
Diffstat (limited to 'quacker/newgame.cpp')
-rw-r--r-- | quacker/newgame.cpp | 425 |
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); +} + |