/*
* C++ Implementation: aiplayer
*
* Description:
*
*
* Author: Hendrik Hochstetter <hochsthk@studi.informatik.uni-stuttgart.de>, (C) 2008
*
* Copyright: See COPYING file that comes with this distribution
*
*/
#include "aiplayer.h"
#include "aibrain.h"
#include <transfer.hpp>
#include <cheppcl.h>
#include <login.h>
#include <messages.h>
#include <msgerr.h>
#include <msgusr.h>
#include <msgcon.h>
#include <msgconv.h>
#include <msgame.h>
#include <msggmgt.h>
#include <msgchat.h>
#include <stdio.h>
#include <QtCore/QThread>
#include <QtCore/QTimer>
#include <QtCore/QString>
#include <QtCore/QChar>
#include <QtCore/QDebug>
#include <QtCore/QMetaType>
#include <QtCore/QObject>
/**
* @brief Cheppcl-objekt kommt aus eventloop zurück.
**/
void AiPlayer::clientFinished ()
{
qDebug () << this << "Done.";
delete timer;
if (cheppcl)
{
delete cheppcl;
}
if (aiBrain)
{
delete aiBrain;
}
exit (0);
};
/**
* @brief zum schluss noch ein signal mit dem spielnamen emitten
* @details damit das signal finished einem bestimmten thread zugeordnet werden kann
* wird zusätzlich das signal returning (QString) emittet, das zusätzlich als parameter
* en spielnamen übergibt.
**/
void AiPlayer::finishing ()
{
emit returning (game);
};
void AiPlayer::wakeUp ()
{
if (aiStatus & KeepAlive)
{
if (serverConnection > 3)
{
qDebug () << this << "seem to have lost server connection. exiting.";
emit returning (game);
}
// in der rechenphase irgendeine anfrage an den server schicken, damit
// der weiß, dass die ki noch da ist.
serverConnection ++;
emit send (new CheppHi ("",""));
}
qDebug () << this << game << "alive";
};
AiPlayer::AiPlayer (QObject *parent, AiSettings settings, QString game, QChar colour)
: QThread (parent),
aiSettings (settings),
game (game),
colour (colour),
aiBrain (0)
{
//qRegisterMetaType<zug> ("zug");
serverConnection = 0;
timer = new QTimer ();
connect (timer, SIGNAL (timeout ()), this, SLOT (wakeUp ()));
timer -> start (45000);
connect (this, SIGNAL (finished ()), this, SLOT (finishing ()));
};
void AiPlayer::receive (const CheppResponse *rspns)
{
//qDebug () << "AiPlayer::receive ()" << "incoming CheppResponse." << rspns << rspns -> text ();
// { solange noch nicht mit server verbunden war interessiert uns nur ob eine verbindung hergestellt werden konnte.
if (!(aiStatus & Connected))
{
aiStatus = aiStatus & (~Trying);
if (dynamic_cast<const CheppConnectionResponse*> (rspns))
{
aiStatus = NotConnected;
if (dynamic_cast<const CheppOpenSuccess*> (rspns))
{
aiStatus = aiStatus | Connected;
qDebug () << "AiPlayer::receive ()" << "successfully connected.";
emit send (new CheppLogin (aiSettings.username, aiSettings.password));
}
else
{
qDebug () << "AiPlayer::receive ()" << "connection failed. " << "exiting.";
}
}
else
{
// nicht (mehr) im status "Connected" und doch was geschickt bekommen außer CheppConnectionResponse-
// subklasse: hier läuft was schief.
qDebug () << "AiPlayer::receive ()" << "strange server bla.";
cheppcl -> exit (0);
}
}
// }
//
//
// { Verbindung aufrecht erhalten in der rechenphase
else if (aiStatus & KeepAlive)
{
if (dynamic_cast<const CheppSyntaxResponse*> (rspns))
{
if (rspns -> text () == "3 Syntax error in\nhi\n ")
{
serverConnection = 0;
}
}
// }}
}
// }
//
// { server verbindung steht bereits...
//
else
{
aiStatus = aiStatus & (~Trying);
//
// {{ user management respones
//
if (dynamic_cast<const CheppUsermgtResponse*> (rspns))
{
// {{{ login response
if (dynamic_cast<const CheppLoginResponse*> (rspns))
{
if (dynamic_cast<const CheppLoginSuccess*> (rspns))
{
aiStatus = aiStatus | LoggedIn;
qDebug () << "AiPlayer::receive ()" << "successfully logged in.";
emit send (new CheppJoin (game));
}
else if (dynamic_cast<const CheppLoginFail*> (rspns) ||
dynamic_cast<const CheppLoginULimit*> (rspns))
{
aiStatus = NotConnected;
//qDebug () << "AiPlayer::receive ()" << "could not log in" << rspns -> text ();
}
}
// }}}
// {{{ Logout response
else if (dynamic_cast<const CheppLogoutResponse*> (rspns))
{
if (dynamic_cast<const CheppLogoutSuccess*> (rspns))
{
//qDebug () << "AiPlayer::receive ()" << "successfully logged out.";
}
}
// }}}
}
// }}
// {{ Game responses
else if (dynamic_cast<const CheppGameResponse*> (rspns))
{
// {{{ pieces response - aktuelle aufstellung der figuren
if (dynamic_cast<const CheppPiecesResponse*> (rspns))
{
if (dynamic_cast<const CheppPieces*> (rspns))
{
//qDebug () << "AiPlayer::receive ()" << "received pieces.";
pieces = dynamic_cast<const CheppPieces*> (rspns) -> pieces;
position = positionOfPieces (pieces);
//#define PLAYERDEBUG
#ifdef PLAYERDEBUG
foreach (Field f, position.keys ())
{
qDebug () << stringOfField (f) << stringOfPiece (position [f]);
}
#endif
emit send (new CheppMovesQuery ());
}
}
// }}}
// {{{ Moves response - liste moeglicher zuege
else if (dynamic_cast<const CheppMovesResponse*> (rspns))
{
if (dynamic_cast<const CheppMoves*> (rspns))
{
moves = dynamic_cast<const CheppMoves*> (rspns) -> moves;
qDebug () << "AiPlayer::receive ()" << "received list of moves." << moves.size ();
int lastMove = lastMoveOfMovesAndPieces (moves, pieces);
Colour colour = colourOfMovesAndPieces (moves, pieces);
aiBrain = new AiBrain (this, position, lastMove, colour, aiSettings);
connect (aiBrain, SIGNAL (send (const CheppCommand*)), this, SIGNAL (send (const CheppCommand*)));
connect (aiBrain, SIGNAL (moveCalculated ()), this, SLOT (moveCalculated ()));
aiBrain -> gamename = game;
aiBrain -> movesFromServer = moves;
aiBrain -> start (QThread::HighestPriority);
// wir gehen in rechenphase ein, serververbindung aufrecht erhalten.
aiStatus = aiStatus | KeepAlive;
}
}
// }}}
else if (dynamic_cast<const CheppDoResponse*> (rspns))
{
// {{{ Do - war ziehen erfolgreich?
if (dynamic_cast<const CheppDone*> (rspns))
{
qDebug () << "Move successfully done. Exiting.";
emit send (new CheppLogout);
}
else if (dynamic_cast<const CheppDoFailed*> (rspns))
{
qWarning () << "Move has been rejected by the server!";
emit send (new CheppLogout);
}
// cheppcl -> terminate ();
// cheppcl -> wait (10);
cheppcl -> exit (0);
// }}}
}
}
// }}
// {{ Connection responses
//
else if (dynamic_cast<const CheppConnectionResponse*> (rspns))
{
if (dynamic_cast<const CheppCloseResponse*> (rspns))
{
if (dynamic_cast<const CheppCloseNotification*> (rspns))
{
qDebug () << "AiPlayer::receive ()" << "connection closed";
cheppcl -> exit (0);
}
}
else // login responses sollten nur ankommen wenn nicht eingeloggt.
{
//qDebug () << "AiPlayer::receive ()" << "we shouldn't have ended up here o.O";
cheppcl -> exit (0);
}
}
// }}
//
// {{ GameMgt Responses
//
else if (dynamic_cast<const CheppGamemgtResponse*> (rspns))
{
// {{{ GameInfo responses
if (dynamic_cast<const CheppGameInfoResponse*> (rspns))
{
if (dynamic_cast<const CheppGameInfo*> (rspns))
{
qDebug () << "AiPlayer::receive ()" << "received game info.";
}
else if (dynamic_cast<const CheppGameInfoFail*> (rspns))
{
qDebug () << "AiPlayer::receive ()" << "error: game info:" << rspns -> text ();
}
}
// }}}
// {{{ GameInfo Responses
else if (dynamic_cast<const CheppGameInfoResponse*> (rspns))
{
}
// }}}
// {{{ Join Responses
else if (dynamic_cast<const CheppJoinResponse*> (rspns))
{
// erfolgreich spiel beigetreten. spieldaten abfragen.
if (dynamic_cast<const CheppJoinSuccess*> (rspns))
{
// wenn schon als player im spiel position abfragen, sonst playen
if (dynamic_cast<const CheppJoinSuccess*> (rspns) -> farben.contains (colour))
{
emit send (new CheppPiecesQuery ());
}
else
{
emit send (new CheppPlay (colour));
}
}
else if (dynamic_cast<const CheppJoinFail*> (rspns))
{
cheppcl -> exit (0);
}
}
// }}}
// {{{ Play Responses
else if (dynamic_cast<const CheppPlayResponse*> (rspns))
{
// erfolgreich als player beigetreten -> stellung abfragen.
if (dynamic_cast<const CheppPlaySuccess*> (rspns))
{
qDebug () << "AiPlayer::receive ()" << "now playing.";
emit send (new CheppPiecesQuery ());
}
else if (dynamic_cast<const CheppPlayFail*> (rspns))
{
qDebug () << "AiPlayer::receive ()" << "Could not take color." << rspns -> text();
cheppcl -> exit (0);
}
}
// }}}
}
// }}
}
// }
delete rspns;
//qDebug () << "AiPlayer::receive (). done";
};
void AiPlayer::moveCalculated ()
{
qDebug () << "AiPlayer::moveCalculated ()" << stringOfZug (aiBrain -> result);
printf ("use calculated move?\n");
char answer = ' ';
while (answer != 'y' && answer != 'n')
{
answer = getchar ();
}
if (answer == 'y')
{
emit send (new CheppDo (aiBrain -> result));
}
aiBrain -> exit (0);
aiStatus = aiStatus & (~KeepAlive);
};
void AiPlayer::run ()
{
qDebug () << this << "Starting Cheppcl thread.";
cheppcl = new Cheppcl (aiSettings.server, aiSettings.port, 0);
connect (this, SIGNAL (send (const CheppCommand *)), cheppcl, SLOT (send (const CheppCommand *)));
connect (cheppcl, SIGNAL (recv (const CheppResponse *)), this, SLOT (receive (const CheppResponse *)));
connect (cheppcl, SIGNAL (finished ()), this, SLOT (clientFinished ()));
aiStatus = Trying;
cheppcl -> start ();
qDebug () << this << "Entering run mode.";
exec ();
};