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