/* Yo Emacs, this -*- C++ -*- Copyright (C) 1999-2001 Jens Hoefkens jens@hoefkens.com 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. $Id$ */ #include "kbgng.moc" #include "kbgng.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Constructor */ KBgEngineNg::KBgEngineNg(QWidget *parent, QString *name, QPopupMenu *pmenu) : KBgEngine(parent, name, pmenu) { // get a new game initGame(); // create actions and menus QString label[MaxTypes]; label[Local ] = i18n("Local Games"); label[NetServer] = i18n("Offer Network Games"); label[NetClient] = i18n("Join Network Games"); QStringList list; for (int i = 0; i < MaxTypes; i++) list.append(label[i]); _gameSelect = new KSelectAction(i18n("&Types"), 0, this, SLOT(setGame()), this); _gameSelect->setItems(list); _gameSelect->plug(menu); menu->insertSeparator(); _connectAction = new KAction(i18n("&Names..."), 0, this, SLOT(changeName()), this); _connectAction->plug(menu); // Restore last settings readConfig(); // initialize to local games _player[0] = _player[1] = 0; _currGame = None; _gameSelect->setCurrentItem(Local); setGame(); } /* * Switch the local game type. This is called by the menu... * * TODO: lots of work and testing needed... */ void KBgEngineNg::setGame() { // shutdown old game switch (_currGame) { case Local: // nothing to do... break; case NetServer: _game->stopServerConnection(); break; case NetClient: _game->disconnect(); break; default: // ignore break; } // reset the game and delete the players delete _game; initGame(); emit infoText("
"); // initialize a new game bool ret = false; QString label, port_s, host_s; Q_UINT16 port; switch (_currGame = _gameSelect->currentItem()) { case Local: _game->addPlayer(createPlayer(0, _name[0])); _game->addPlayer(createPlayer(1, _name[1])); break; case NetServer: label = i18n("Type the port number on which you want to listen to " "connections.\nThe number should be between 1024 and " "65535."); port_s.setNum(_port); do { port_s = KLineEditDlg::getText(label, port_s, &ret, (QWidget *)parent()); if (!ret) return; port = port_s.toUShort(&ret); } while (port_s.isEmpty() && !ret); if (_game->offerConnections(port)) emit infoText(i18n("Now waiting for incoming connections on port %1."). arg(_port = port)); else emit infoText(i18n("Failed to offer connections on port %1.").arg(port)); _game->addPlayer(createPlayer(0, _name[0])); break; case NetClient: label = i18n("Type the name of the server you want to connect to:"); host_s = _host; do { host_s = KLineEditDlg::getText(label, host_s, &ret, (QWidget *)parent()); if (!ret) return; } while (host_s.isEmpty()); label = i18n("Type the port number on %1 you want to connect to.\nThe " "number should be between 1024 and 65535.").arg(host_s); port_s.setNum(_port); do { port_s = KLineEditDlg::getText(label, port_s, &ret, (QWidget *)parent()); if (!ret) return; port = port_s.toUShort(&ret); } while (port_s.isEmpty() && !ret); /* * Hi Martin: another thing you night want to try is to move this to the * place marked by (about 10 lines further down. If you do that, the * players are created properly on the server, but a total of three players * is created on the client. */ _game->addPlayer(createPlayer(0, _name[0])); if (_game->connectToServer(host_s, port)) emit infoText(i18n("Now connected to %1:%2.").arg(_host = host_s). arg(_port = port)); else emit infoText(i18n("Failed to connect to %1:%2.").arg(_host = host_s). arg(_port = port)); // break; default: kdDebug(true, PROG_COOKIE) << "setGame parameter invalid: " << _currGame << endl; _currGame = None; return; } // we are still having problems with player creation... // FIXME - which status _game->setGameStatus(KGame::End); } void KBgEngineNg::slotPlayerJoinedGame(KPlayer *p) { emit infoText(i18n("Player %1 (%2) has joined the game.").arg(p->name()).arg(p->id())); cerr << i18n("Player %1 (%2) has joined the game.").arg(p->name()).arg(p->id()).latin1() << endl; } void KBgEngineNg::slotCreatePlayer(KPlayer *&p, int rtti, int io, bool v, KGame *g) { Q_UNUSED(rtti) Q_UNUSED(g) Q_UNUSED(io) emit infoText(i18n("creating player. virtual=%1").arg(v)); p = createPlayer(1); } void KBgEngineNg::slotClientConnected(Q_UINT32) { cerr << "client has joint the game..." << endl; } void KBgEngineNg::slotClientDisconnected(Q_UINT32, bool) { cerr << "KBgEngineNg::slotClientDisconnected" << endl; } // == start and init games ===================================================== /* * Start a new game. ... */ void KBgEngineNg::newGame() { // TODO cerr << "games are not yet working..." << endl; } /* * Finish the last move - called by the timer and directly by the used */ void KBgEngineNg::done() { // empty } /* * Undo the last move */ void KBgEngineNg::undo() { // TODO } /* * Redo the last move */ void KBgEngineNg::redo() { // TODO } /* * Take the move string and make the changes on the working copy * of the state. */ void KBgEngineNg::handleMove(QString *s) { Q_UNUSED(s) // TODO } /* * Roll random dice for the player whose turn it is */ void KBgEngineNg::roll() { // empty } /* * If possible, roll random dice for player w */ void KBgEngineNg::rollDice(const int w) { Q_UNUSED(w) // empty } /* * Double the cube for the player that can double - asks player */ void KBgEngineNg::cube() { // TODO } /* * Double the cube for player w */ void KBgEngineNg::doubleCube(const int) { cube(); } /* * Put the engine specific details in the setup dialog */ void KBgEngineNg::getSetupPages(KDialogBase *) { // FIXME: do nothing... } /* * Called when the setup dialog is positively closed */ void KBgEngineNg::setupOk() { // FIXME: do nothing... } void KBgEngineNg::setupDefault() { // FIXME: do nothing... } void KBgEngineNg::setupCancel() { // FIXME: do nothing... } // == various slots & functions ================================================ /* * Check with the user if we should really quit in the middle of a * game. */ bool KBgEngineNg::queryClose() { return true; } /* * Quitting is fine at any time */ bool KBgEngineNg::queryExit() { return true; } /* * Load the last known sane state of the board */ void KBgEngineNg::load() { // TODO } /* * Store if cmd is allowed or not */ void KBgEngineNg::setAllowed(int cmd, bool f) { switch (cmd) { case Roll: rollingAllowed = f; return; case Undo: undoPossible = f; return; case Cube: doublePossible = f; return; case Done: donePossible = f; return; } } // ******************************************************************************** // ******************************************************************************** // DONE // ******************************************************************************** // ******************************************************************************** /* * Destructor. */ KBgEngineNg::~KBgEngineNg() { saveConfig(); delete _game; } /* * Restore settings */ void KBgEngineNg::readConfig() { KConfig* config = kapp->config(); config->setGroup("next generation engine"); _port = config->readNumEntry("port", PROG_COOKIE); _host = config->readEntry("host", "localhost"); _name[0] = config->readEntry("name_0", i18n("one")); _name[1] = config->readEntry("name_1", i18n("two")); } /* * Save the engine specific settings */ void KBgEngineNg::saveConfig() { KConfig* config = kapp->config(); config->setGroup("next generation engine"); config->writeEntry("port", _port); config->writeEntry("host", _host); config->writeEntry("name_0", _name[0]); config->writeEntry("name_1", _name[1]); } /* * Read the users input from the command line and send it to all * players. Although the message gets the Cmd ID, it is currently * handled as a regular text message. */ void KBgEngineNg::handleCommand(const QString& text) { QByteArray msg; QTextStream ts(msg, IO_WriteOnly); ts << text; if (!_game->sendMessage(msg, KBgGame::Cmd)) kdDebug(true, PROG_COOKIE) << "couldn't send message: " << text.latin1() << endl; } /* * Return a random integer between 1 and 6. Use the KGame random * number generator. */ int KBgEngineNg::getRandom() { return 1+_game->random()->getLong(6); } /* * A player propert has changed - check if we care */ void KBgEngineNg::slotPropertyChanged(KGamePropertyBase *p, KPlayer *me) { int player = (me->id() == _player[1]->id()); switch (p->id()) { case KGamePropertyBase::IdName: emit infoText(i18n("Player %1 has changed the name to %2.") .arg(_name[player]).arg(me->name())); _name[player] = me->name(); break; default: kdDebug(true, PROG_COOKIE) << "KBgPlayer (" << me << ") property change (" << p->id() << ") ignored" << endl; break; } } /* * A game property has changed */ void KBgEngineNg::slotPropertyChanged(KGamePropertyBase *p, KGame *me) { Q_UNUSED(me) switch (p->id()) { default: kdDebug(true, PROG_COOKIE) << "Change in GameProperty " << p->id() << " has been ignored." << endl; break; } } /* * Change the names of all local players */ void KBgEngineNg::changeName() { bool ok = false; QString name; for (int i = 0; i < 2; i++) { name = QString::null; while (!_player[i]->isVirtual() && name.isEmpty()) { if (i == 0) name = KLineEditDlg::getText(i18n("Type the name of the first player:"), _name[i], &ok, (QWidget *)parent()); else name = KLineEditDlg::getText(i18n("Type the name of the second player:"), _name[i], &ok, (QWidget *)parent()); if (!ok) return; _player[i]->setName(name); } } } /* * Receive data sent via KBgGame::sendMessage(...) */ void KBgEngineNg::slotNetworkData(int msgid, const QByteArray &msg, Q_UINT32 r, Q_UINT32 s) { Q_UNUSED(r); Q_UNUSED(s); switch (msgid) { case KBgGame::Cmd: emit infoText(msg); emit infoText(i18n("Players are %1 and %2").arg(_player[0]->name()) .arg(_player[1]->name())); break; default: kdDebug(true, PROG_COOKIE) << "Ignored message ID: " << msgid << endl; break; } } /* * Create the i-th player */ KBgPlayer * KBgEngineNg::createPlayer(int i, QString name) { KBgPlayer *p = new KBgPlayer(); if (!name.isNull()) p->setName(name); p->findProperty(KGamePropertyBase::IdName)->setEmittingSignal(true); connect(p, SIGNAL(signalPropertyChanged(KGamePropertyBase *, KPlayer *)), this, SLOT(slotPropertyChanged(KGamePropertyBase *, KPlayer *))); return (_player[i] = p); } /* * Create and connect the game object */ void KBgEngineNg::initGame() { _game = new KBgGame(PROG_COOKIE); _game->random()->setSeed(getpid()*time(NULL)); connect(_game, SIGNAL(signalPlayerJoinedGame(KPlayer *)), this, SLOT(slotPlayerJoinedGame(KPlayer *))); connect(_game, SIGNAL(signalCreatePlayer(KPlayer *&, int, int, bool, KGame *)), this, SLOT(slotCreatePlayer(KPlayer *&, int, int, bool, KGame *))); connect(_game, SIGNAL(signalClientConnected(Q_UINT32)), this, SLOT(slotClientConnected(Q_UINT32))); connect(_game, SIGNAL(signalClientDisconnected(Q_UINT32, bool)), this, SLOT(slotClientDisconnected(Q_UINT32, bool))); connect(_game, SIGNAL(signalPropertyChanged(KGamePropertyBase *, KGame *)), this, SLOT(slotPropertyChanged(KGamePropertyBase *, KGame *))); connect(_game, SIGNAL(signalNetworkData(int,const QByteArray &, Q_UINT32, Q_UINT32)), this, SLOT(slotNetworkData(int,const QByteArray &, Q_UINT32, Q_UINT32))); } // EOF