1 /*
2  * noughtsandcrossesplugin.cpp - Psi plugin to play noughts and crosses
3  * Copyright (C) 2006  Kevin Smith
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * You can also redistribute and/or modify this program under the
11  * terms of the Psi License, specified in the accompanied COPYING
12  * file, as published by the Psi Project; either dated January 1st,
13  * 2005, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 
26 #include <QtCore>
27 #include <QDebug>
28 
29 #include "psiplugin.h"
30 #include "eventfilter.h"
31 #include "stanzasender.h"
32 #include "stanzasendinghost.h"
33 
34 #include "tictac.h"
35 
36 class NoughtsAndCrossesPlugin : public QObject, public PsiPlugin, public EventFilter, public StanzaSender
37 {
38 	Q_OBJECT
39 	Q_INTERFACES(PsiPlugin EventFilter StanzaSender)
40 
41 public:
42 	NoughtsAndCrossesPlugin();
43 
44 	virtual QString name() const;
45 	virtual QString shortName() const;
46 	virtual QString version() const;
47 	virtual QWidget* options() const;
48 	virtual bool enable();
49 	virtual bool disable();
50 
51 	virtual void setStanzaSendingHost(StanzaSendingHost *host);
52 
53     virtual bool processEvent(int account, const QDomElement& e);
54 	virtual bool processMessage(int account, const QString& fromJid, const QString& body, const QString& subject);
55 
56 private slots:
57 	void stopGame();
58 	void myTurn(int space);
59 	void theirTurn(int space);
60 	void gameOver(TicTacGameBoard::State state);
61 
62 private:
63 	void startGame(QString jid, int size, bool meFirst, int account);
64 
65 
66 
67 	TicTacToe* game;
68 	QString playingWith;
69 	int account_;
70 	bool enabled_;
71 	StanzaSendingHost* stanzaSender_;
72 };
73 
74 Q_EXPORT_PLUGIN(NoughtsAndCrossesPlugin);
75 
NoughtsAndCrossesPlugin()76 NoughtsAndCrossesPlugin::NoughtsAndCrossesPlugin()
77 {
78 	game = NULL;
79 	enabled_ = false;
80 	stanzaSender_ = 0;
81 }
82 
name() const83 QString NoughtsAndCrossesPlugin::name() const
84 {
85 	return "NoughtsAndCrosses Plugin";
86 }
87 
shortName() const88 QString NoughtsAndCrossesPlugin::shortName() const
89 {
90 	return "noughtsandcrosses";
91 }
92 
version() const93 QString NoughtsAndCrossesPlugin::version() const
94 {
95 	return "0.1";
96 }
97 
options() const98 QWidget* NoughtsAndCrossesPlugin::options() const
99 {
100 	return 0;
101 }
102 
enable()103 bool NoughtsAndCrossesPlugin::enable()
104 {
105 	if (stanzaSender_) {
106 		enabled_ = true;
107 	}
108 	return enabled_;
109 }
110 
disable()111 bool NoughtsAndCrossesPlugin::disable()
112 {
113 	stopGame();
114 	enabled_ = false;
115 	return true;
116 }
117 
setStanzaSendingHost(StanzaSendingHost * host)118 void NoughtsAndCrossesPlugin::setStanzaSendingHost(StanzaSendingHost *host)
119 {
120 	stanzaSender_ = host;
121 }
122 
123 
processEvent(int account,const QDomElement & e)124 bool NoughtsAndCrossesPlugin::processEvent(int account, const QDomElement& e)
125 {
126 	Q_UNUSED(account);
127 	Q_UNUSED(e);
128 	return false;
129 }
130 
processMessage(int account,const QString & fromJid,const QString & message,const QString & subject)131 bool NoughtsAndCrossesPlugin::processMessage(int account, const QString& fromJid, const QString& message, const QString& subject)
132 {
133 	// FIXME(mck)
134 	QString fromDisplay = fromJid;
135 
136 	Q_UNUSED(subject);
137 
138 	if (!enabled_) {
139 		return false;
140 	}
141 
142 	QString reply;
143 	qDebug("naughtsandcrosses message");
144 	if (!message.startsWith("noughtsandcrosses"))
145 		return false;
146 	qDebug("message for us in noughtsandcrosses");
147 	if (game && fromJid != playingWith)
148 	{
149 		reply=QString("<message to=\"%1\" type=\"chat\"><body>already playing with %2, sorry</body></message>").arg(fromJid).arg(playingWith);
150 		stanzaSender_->sendStanza(account, reply);
151 		return true;
152 	}
153 	QString command = QString(message);
154 	command.remove(0,18);
155 	qDebug() << (qPrintable(QString("noughtsandcrosses command string %1").arg(command)));
156 	if (command == QString("start"))
157 	{
158 		if (game)
159 			return true;
160 		qWarning(qPrintable(QString("Received message '%1', launching nac with %2").arg(message).arg(fromDisplay)));
161 		QString reply;
162 		reply=QString("<message to=\"%1\" type=\"chat\"><body>noughtsandcrosses starting</body></message>").arg(fromJid);
163 		stanzaSender_->sendStanza(account, reply);
164 		startGame(fromJid, 3, false, account);
165 	}
166 	else if (command == QString("starting"))
167 	{
168 		if (game)
169 			return true;
170 		qWarning(qPrintable(QString("Received message '%1', launching nac with %2").arg(message).arg(fromDisplay)));
171 		QString reply;
172 		reply=QString("<message to=\"%1\" type=\"chat\"><body>starting noughts and crosses, I go first :)</body></message>").arg(fromJid);
173 		stanzaSender_->sendStanza(account, reply);
174 		startGame(fromJid, 3, true, account);
175 	}
176 	else if (!game)
177 	{
178 		return true;
179 	}
180 	else if (command.startsWith("move"))
181 	{
182 		command.remove(0,5);
183 
184 		int space=command.toInt();
185 		qDebug() << (qPrintable(QString("noughtsandcrosses move to space %1").arg(space)));
186 		theirTurn(space);
187 	}
188 	return true;
189 }
190 
startGame(QString jid,int size,bool meFirst,int account)191 void NoughtsAndCrossesPlugin::startGame(QString jid, int size, bool meFirst, int account)
192 {
193 	game = new TicTacToe( meFirst, size );
194 	game->setCaption(QString("Noughts and Crosses with %1").arg(jid));
195 	playingWith=jid;
196     game->show();
197 	account_=account;
198 	connect(game, SIGNAL(closing()), this, SLOT(stopGame()));
199 	connect(game, SIGNAL(myMove(int)), this, SLOT(myTurn(int)));
200 	connect(game, SIGNAL(gameOverSignal(TicTacGameBoard::State)), this, SLOT(gameOver(TicTacGameBoard::State)));
201 }
202 
stopGame()203 void NoughtsAndCrossesPlugin::stopGame()
204 {
205 	delete game;
206 	game=NULL;
207 }
208 
gameOver(TicTacGameBoard::State state)209 void NoughtsAndCrossesPlugin::gameOver(TicTacGameBoard::State state)
210 {
211 	QString reply;
212 	QString winner;
213 	switch (state)
214 	{
215 		case TicTacGameBoard::HumanWon:
216 			winner="I";
217 			break;
218 		case TicTacGameBoard::ComputerWon:
219 			winner="You";
220 			break;
221 		case TicTacGameBoard::NobodyWon:
222 			winner="It was a draw, no-one";
223 			break;
224 		default:
225 			winner="ERROR!!!";
226 	}
227 	reply=QString("<message to=\"%1\" type=\"chat\"><body>%2 won. Good game.</body></message>").arg(playingWith).arg(winner);
228 	stanzaSender_->sendStanza(account_, reply);
229 }
230 
myTurn(int space)231 void NoughtsAndCrossesPlugin::myTurn(int space)
232 {
233 	qDebug() << (qPrintable(QString("my turn: %1").arg(space)));
234 	if (!game)
235 		return;
236 	QString reply;
237 	reply=QString("<message to=\"%1\" type=\"chat\"><body>noughtsandcrosses move %2</body></message>").arg(playingWith).arg(space);
238 	stanzaSender_->sendStanza(account_, reply);
239 }
240 
theirTurn(int space)241 void NoughtsAndCrossesPlugin::theirTurn(int space)
242 {
243 	qDebug() << (qPrintable(QString("their turn: %1").arg(space)));
244 	if (!game)
245 		return;
246 	game->theirMove(space);
247 }
248 
249 
250 #include "noughtsandcrossesplugin.moc"
251