You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/kbackgammon/engines/nextgen/kbgng.cpp

623 lines
13 KiB

/* 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 <kapplication.h>
#include <kmessagebox.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <tqlayout.h>
#include <kiconloader.h>
#include <kstdaction.h>
#include <tqbuttongroup.h>
#include <tqcheckbox.h>
#include <kconfig.h>
#include <klocale.h>
#include <kmainwindow.h>
#include <klineeditdlg.h>
#include <krandomsequence.h>
#include <tqstringlist.h>
#include <tqcstring.h>
#include <tqtextstream.h>
#include <version.h>
#include <iostream>
/*
* Constructor
*/
KBgEngineNg::KBgEngineNg(TQWidget *tqparent, TQString *name, TQPopupMenu *pmenu)
: KBgEngine(tqparent, name, pmenu)
{
// get a new game
initGame();
// create actions and menus
TQString label[MaxTypes];
label[Local ] = i18n("Local Games");
label[NetServer] = i18n("Offer Network Games");
label[NetClient] = i18n("Join Network Games");
TQStringList list;
for (int i = 0; i < MaxTypes; i++)
list.append(label[i]);
_gameSelect = new KSelectAction(i18n("&Types"), 0, this, TQT_SLOT(setGame()), this);
_gameSelect->setItems(list);
_gameSelect->plug(menu);
menu->insertSeparator();
_connectAction = new KAction(i18n("&Names..."), 0, this, TQT_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("<br/>");
// initialize a new game
bool ret = false;
TQString label, port_s, host_s;
TQ_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, (TQWidget *)tqparent());
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.").tqarg(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, (TQWidget *)tqparent());
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.").tqarg(host_s);
port_s.setNum(_port);
do {
port_s = KLineEditDlg::getText(label, port_s, &ret, (TQWidget *)tqparent());
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 <HERE> (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.").tqarg(_host = host_s).
arg(_port = port));
else
emit infoText(i18n("Failed to connect to %1:%2.").tqarg(_host = host_s).
arg(_port = port));
// <HERE>
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->setGametqStatus(KGame::End);
}
void KBgEngineNg::slotPlayerJoinedGame(KPlayer *p)
{
emit infoText(i18n("Player %1 (%2) has joined the game.").tqarg(p->name()).tqarg(p->id()));
cerr << i18n("Player %1 (%2) has joined the game.").tqarg(p->name()).tqarg(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").tqarg(v));
p = createPlayer(1);
}
void KBgEngineNg::slotClientConnected(TQ_UINT32)
{
cerr << "client has joint the game..." << endl;
}
void KBgEngineNg::slotClientDisconnected(TQ_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(TQString *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 TQString& text)
{
TQByteArray msg;
TQTextStream 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.")
.tqarg(_name[player]).tqarg(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;
TQString name;
for (int i = 0; i < 2; i++) {
name = TQString();
while (!_player[i]->isVirtual() && name.isEmpty()) {
if (i == 0)
name = KLineEditDlg::getText(i18n("Type the name of the first player:"),
_name[i], &ok, (TQWidget *)tqparent());
else
name = KLineEditDlg::getText(i18n("Type the name of the second player:"),
_name[i], &ok, (TQWidget *)tqparent());
if (!ok) return;
_player[i]->setName(name);
}
}
}
/*
* Receive data sent via KBgGame::sendMessage(...)
*/
void KBgEngineNg::slotNetworkData(int msgid, const TQByteArray &msg, TQ_UINT32 r, TQ_UINT32 s)
{
Q_UNUSED(r);
Q_UNUSED(s);
switch (msgid) {
case KBgGame::Cmd:
emit infoText(msg);
emit infoText(i18n("Players are %1 and %2").tqarg(_player[0]->name())
.tqarg(_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, TQString name)
{
KBgPlayer *p = new KBgPlayer();
if (!name.isNull())
p->setName(name);
p->findProperty(KGamePropertyBase::IdName)->setEmittingSignal(true);
connect(p, TQT_SIGNAL(signalPropertyChanged(KGamePropertyBase *, KPlayer *)),
this, TQT_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, TQT_SIGNAL(signalPlayerJoinedGame(KPlayer *)),
this, TQT_SLOT(slotPlayerJoinedGame(KPlayer *)));
connect(_game, TQT_SIGNAL(signalCreatePlayer(KPlayer *&, int, int, bool, KGame *)),
this, TQT_SLOT(slotCreatePlayer(KPlayer *&, int, int, bool, KGame *)));
connect(_game, TQT_SIGNAL(signalClientConnected(TQ_UINT32)),
this, TQT_SLOT(slotClientConnected(TQ_UINT32)));
connect(_game, TQT_SIGNAL(signalClientDisconnected(TQ_UINT32, bool)),
this, TQT_SLOT(slotClientDisconnected(TQ_UINT32, bool)));
connect(_game, TQT_SIGNAL(signalPropertyChanged(KGamePropertyBase *, KGame *)),
this, TQT_SLOT(slotPropertyChanged(KGamePropertyBase *, KGame *)));
connect(_game, TQT_SIGNAL(signalNetworkData(int,const TQByteArray &, TQ_UINT32, TQ_UINT32)),
this, TQT_SLOT(slotNetworkData(int,const TQByteArray &, TQ_UINT32, TQ_UINT32)));
}
// EOF