summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/wordgame/wordgame.cpp4
1 files changed, 2 insertions, 2 deletions
diff --git a/noncore/games/wordgame/wordgame.cpp b/noncore/games/wordgame/wordgame.cpp
index 16d37b3..d3160f4 100644
--- a/noncore/games/wordgame/wordgame.cpp
+++ b/noncore/games/wordgame/wordgame.cpp
@@ -1,1085 +1,1085 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21 21
22#include "wordgame.h" 22#include "wordgame.h"
23 23
24#include <qpe/applnk.h> 24#include <qpe/applnk.h>
25#include <qpe/global.h> 25#include <qpe/global.h>
26#include <qpe/filemanager.h> 26#include <qpe/filemanager.h>
27#include <qpe/resource.h> 27#include <qpe/resource.h>
28#include <qpe/config.h> 28#include <qpe/config.h>
29 29
30#include <qapplication.h> 30#include <qapplication.h>
31#include <qmessagebox.h> 31#include <qmessagebox.h>
32#include <qcombobox.h> 32#include <qcombobox.h>
33#include <qdatetime.h> 33#include <qdatetime.h>
34#include <qfileinfo.h> 34#include <qfileinfo.h>
35#include <qfile.h> 35#include <qfile.h>
36#include <qdir.h> 36#include <qdir.h>
37#include <qiconset.h> 37#include <qiconset.h>
38#include <qlabel.h> 38#include <qlabel.h>
39#include <qlineedit.h> 39#include <qlineedit.h>
40#include <qpushbutton.h> 40#include <qpushbutton.h>
41#include <qtextstream.h> 41#include <qtextstream.h>
42#include <qtimer.h> 42#include <qtimer.h>
43#include <qpe/qpetoolbar.h> 43#include <qpe/qpetoolbar.h>
44#include <qtoolbutton.h> 44#include <qtoolbutton.h>
45#include <qvbox.h> 45#include <qvbox.h>
46#include <qwidgetstack.h> 46#include <qwidgetstack.h>
47#include <qpainter.h> 47#include <qpainter.h>
48#include <qlayout.h> 48#include <qlayout.h>
49#include <qregexp.h> 49#include <qregexp.h>
50 50
51#include <stdlib.h> 51#include <stdlib.h>
52#include <unistd.h> 52#include <unistd.h>
53#include <pwd.h> 53#include <pwd.h>
54#include <sys/types.h> 54#include <sys/types.h>
55 55
56enum RuleEffects { 56enum RuleEffects {
57 Multiplier=15, 57 Multiplier=15,
58 MultiplyAll=64, 58 MultiplyAll=64,
59 Start=128 59 Start=128
60}; 60};
61 61
62static int tile_smallw = 16; 62static int tile_smallw = 16;
63static int tile_smallh = 16; 63static int tile_smallh = 16;
64static int tile_bigw = 22; 64static int tile_bigw = 22;
65static int tile_bigh = 22; 65static int tile_bigh = 22;
66static int tile_stweak = -2; 66static int tile_stweak = -2;
67static int tile_btweak = -1; 67static int tile_btweak = -1;
68 68
69static const int rack_tiles=7; 69static const int rack_tiles=7;
70 70
71const char* sampleWGR= 71const char* sampleWGR=
72 "wordgame_shapes\n" 72 "wordgame_shapes\n"
73 "15 15\n" 73 "15 15\n"
74 "400001040100004\n" 74 "400001040100004\n"
75 "030000000000030\n" 75 "030000000000030\n"
76 "002002000200200\n" 76 "002002000200200\n"
77 "000300020003000\n" 77 "000300020003000\n"
78 "000020000020000\n" 78 "000020000020000\n"
79 "102001000100201\n" 79 "102001000100201\n"
80 "000000202000000\n" 80 "000000202000000\n"
81 "400200050002004\n" 81 "400200050002004\n"
82 "000000202000000\n" 82 "000000202000000\n"
83 "102001000100201\n" 83 "102001000100201\n"
84 "000020000020000\n" 84 "000020000020000\n"
85 "000300020003000\n" 85 "000300020003000\n"
86 "002002000200200\n" 86 "002002000200200\n"
87 "030000000000030\n" 87 "030000000000030\n"
88 "400001040100004\n" 88 "400001040100004\n"
89 "1 2 3 66 67 194 100 0\n" 89 "1 2 3 66 67 194 100 0\n"
90 "1 j 8\n" 90 "1 j 8\n"
91 "1 q 7\n" 91 "1 q 7\n"
92 "1 x 6\n" 92 "1 x 6\n"
93 "1 z 6\n" 93 "1 z 6\n"
94 "1 w 4\n" 94 "1 w 4\n"
95 "1 k 4\n" 95 "1 k 4\n"
96 "1 v 3\n" 96 "1 v 3\n"
97 "1 f 3\n" 97 "1 f 3\n"
98 "2 y 3\n" 98 "2 y 3\n"
99 "2 h 2\n" 99 "2 h 2\n"
100 "2 b 2\n" 100 "2 b 2\n"
101 "2 m 2\n" 101 "2 m 2\n"
102 "3 p 2\n" 102 "3 p 2\n"
103 "3 g 2\n" 103 "3 g 2\n"
104 "3 u 2\n" 104 "3 u 2\n"
105 "4 d 2\n" 105 "4 d 2\n"
106 "4 c 2\n" 106 "4 c 2\n"
107 "5 l 1\n" 107 "5 l 1\n"
108 "5 o 1\n" 108 "5 o 1\n"
109 "7 t 1\n" 109 "7 t 1\n"
110 "7 n 1\n" 110 "7 n 1\n"
111 "7 a 1\n" 111 "7 a 1\n"
112 "7 r 1\n" 112 "7 r 1\n"
113 "8 s 1\n" 113 "8 s 1\n"
114 "8 i 1\n" 114 "8 i 1\n"
115 "11 e 1\n" 115 "11 e 1\n"
116 "0\n"; 116 "0\n";
117 117
118WordGame::WordGame( QWidget* parent, const char* name, WFlags fl ) : 118WordGame::WordGame( QWidget* parent, const char* name, WFlags fl ) :
119 QMainWindow(parent, name, fl) 119 QMainWindow(parent, name, fl)
120{ 120{
121 if ( qApp->desktop()->width() < 240 ) { 121 if ( qApp->desktop()->width() < 240 ) {
122 tile_smallw = 10; 122 tile_smallw = 10;
123 tile_smallh = 10; 123 tile_smallh = 10;
124 tile_bigw = 16; 124 tile_bigw = 16;
125 tile_bigh = 16; 125 tile_bigh = 16;
126 tile_stweak = 0; 126 tile_stweak = 0;
127 tile_btweak = 0; 127 tile_btweak = 0;
128 } 128 }
129 129
130 setIcon( Resource::loadPixmap( "wordgame" ) ); 130 setIcon( Resource::loadPixmap( "wordgame/WordGame.png" ) );
131 setCaption( tr("Word Game") ); 131 setCaption( tr("Word Game") );
132 132
133 setToolBarsMovable( FALSE ); 133 setToolBarsMovable( FALSE );
134 vbox = new QVBox(this); 134 vbox = new QVBox(this);
135 135
136 setCentralWidget(vbox); 136 setCentralWidget(vbox);
137 toolbar = new QPEToolBar(this); 137 toolbar = new QPEToolBar(this);
138 addToolBar(toolbar, Bottom); 138 addToolBar(toolbar, Bottom);
139 reset = new QToolButton(Resource::loadPixmap("back"), tr("Back"), "", this, SLOT(resetTurn()), toolbar); 139 reset = new QToolButton(Resource::loadPixmap("back"), tr("Back"), "", this, SLOT(resetTurn()), toolbar);
140 done = new QToolButton(Resource::loadPixmap("done"), tr("Done"), "", this, SLOT(endTurn()), toolbar); 140 done = new QToolButton(Resource::loadPixmap("done"), tr("Done"), "", this, SLOT(endTurn()), toolbar);
141 scoreinfo = new ScoreInfo(toolbar); 141 scoreinfo = new ScoreInfo(toolbar);
142 scoreinfo->setFont(QFont("Helvetica",10)); 142 scoreinfo->setFont(QFont("Helvetica",10));
143 new QToolButton(Resource::loadPixmap("finish"), tr("Close"), "", this, SLOT(endGame()), toolbar); 143 new QToolButton(Resource::loadPixmap("finish"), tr("Close"), "", this, SLOT(endGame()), toolbar);
144 toolbar->setStretchableWidget(scoreinfo); 144 toolbar->setStretchableWidget(scoreinfo);
145 145
146 cpu = 0; 146 cpu = 0;
147 board = 0; 147 board = 0;
148 bag = 0; 148 bag = 0;
149 racks = 0; 149 racks = 0;
150 150
151 aiheart = new QTimer(this); 151 aiheart = new QTimer(this);
152 connect(aiheart, SIGNAL(timeout()), this, SLOT(think())); 152 connect(aiheart, SIGNAL(timeout()), this, SLOT(think()));
153 153
154 readConfig(); 154 readConfig();
155} 155}
156 156
157WordGame::~WordGame() 157WordGame::~WordGame()
158{ 158{
159 writeConfig(); 159 writeConfig();
160} 160}
161 161
162void WordGame::writeConfig() 162void WordGame::writeConfig()
163{ 163{
164 Config cfg("WordGame"); 164 Config cfg("WordGame");
165 cfg.setGroup("Game"); 165 cfg.setGroup("Game");
166 cfg.writeEntry("NameList",namelist,';'); 166 cfg.writeEntry("NameList",namelist,';');
167 cfg.writeEntry("CurrentPlayer",gameover ? 0 : player+1); 167 cfg.writeEntry("CurrentPlayer",gameover ? 0 : player+1);
168 if ( !gameover ) { 168 if ( !gameover ) {
169 cfg.writeEntry("Rules",rules); 169 cfg.writeEntry("Rules",rules);
170 bag->writeConfig(cfg); 170 bag->writeConfig(cfg);
171 board->writeConfig(cfg); 171 board->writeConfig(cfg);
172 scoreinfo->writeConfig(cfg); 172 scoreinfo->writeConfig(cfg);
173 } 173 }
174 for (int p=0; p<nplayers; p++) { 174 for (int p=0; p<nplayers; p++) {
175 cfg.setGroup("Player"+QString::number(p+1)); 175 cfg.setGroup("Player"+QString::number(p+1));
176 if ( gameover ) cfg.clearGroup(); else rack(p)->writeConfig(cfg); 176 if ( gameover ) cfg.clearGroup(); else rack(p)->writeConfig(cfg);
177 } 177 }
178} 178}
179 179
180void WordGame::readConfig() 180void WordGame::readConfig()
181{ 181{
182 Config cfg("WordGame"); 182 Config cfg("WordGame");
183 cfg.setGroup("Game"); 183 cfg.setGroup("Game");
184 int currentplayer = cfg.readNumEntry("CurrentPlayer",0); 184 int currentplayer = cfg.readNumEntry("CurrentPlayer",0);
185 QStringList pnames = cfg.readListEntry("NameList",';'); 185 QStringList pnames = cfg.readListEntry("NameList",';');
186 if ( currentplayer ) { 186 if ( currentplayer ) {
187 gameover = FALSE; 187 gameover = FALSE;
188 rules = cfg.readEntry("Rules"); 188 rules = cfg.readEntry("Rules");
189 if ( rules.find("x-wordgamerules") >= 0 ) { 189 if ( rules.find("x-wordgamerules") >= 0 ) {
190 // rules files moved 190 // rules files moved
191 rules = "Sample.rules"; 191 rules = "Sample.rules";
192 } 192 }
193 if ( loadRules(rules) ) { 193 if ( loadRules(rules) ) {
194 startGame(pnames); 194 startGame(pnames);
195 bag->readConfig(cfg); 195 bag->readConfig(cfg);
196 board->readConfig(cfg); 196 board->readConfig(cfg);
197 scoreinfo->readConfig(cfg); 197 scoreinfo->readConfig(cfg);
198 for (int p=0; p<nplayers; p++) { 198 for (int p=0; p<nplayers; p++) {
199 cfg.setGroup("Player"+QString::number(p+1)); 199 cfg.setGroup("Player"+QString::number(p+1));
200 rack(p)->readConfig(cfg); 200 rack(p)->readConfig(cfg);
201 } 201 }
202 player=currentplayer-1; 202 player=currentplayer-1;
203 readyRack(player); 203 readyRack(player);
204 return; 204 return;
205 } 205 }
206 } 206 }
207 // fall-back 207 // fall-back
208 openGameSelector(pnames); 208 openGameSelector(pnames);
209} 209}
210 210
211void WordGame::openGameSelector(const QStringList& initnames) 211void WordGame::openGameSelector(const QStringList& initnames)
212{ 212{
213 toolbar->hide(); 213 toolbar->hide();
214 gameover = FALSE; 214 gameover = FALSE;
215 215
216 delete board; 216 delete board;
217 board = 0; 217 board = 0;
218 delete racks; 218 delete racks;
219 racks = 0; 219 racks = 0;
220 220
221 delete cpu; 221 delete cpu;
222 cpu = 0; 222 cpu = 0;
223 223
224 newgame = new NewGame(vbox); 224 newgame = new NewGame(vbox);
225 225
226 //Rules rules(this); 226 //Rules rules(this);
227 //connect(game.editrules, SIGNAL(clicked()), &rules, SLOT(editRules())); 227 //connect(game.editrules, SIGNAL(clicked()), &rules, SLOT(editRules()));
228 //connect(&rules, SIGNAL(rulesChanged()), &game, SLOT(updateRuleSets())); 228 //connect(&rules, SIGNAL(rulesChanged()), &game, SLOT(updateRuleSets()));
229 struct passwd* n = getpwuid(getuid()); 229 struct passwd* n = getpwuid(getuid());
230 QString playername = n ? n->pw_name : ""; 230 QString playername = n ? n->pw_name : "";
231 if ( playername.isEmpty() ) { 231 if ( playername.isEmpty() ) {
232 playername = "Player"; 232 playername = "Player";
233 } 233 }
234 newgame->player0->changeItem(playername,0); 234 newgame->player0->changeItem(playername,0);
235 newgame->player1->setCurrentItem(1); 235 newgame->player1->setCurrentItem(1);
236 newgame->updateRuleSets(); 236 newgame->updateRuleSets();
237 newgame->show(); 237 newgame->show();
238 238
239 connect(newgame->buttonOk, SIGNAL(clicked()), this, SLOT(startGame())); 239 connect(newgame->buttonOk, SIGNAL(clicked()), this, SLOT(startGame()));
240} 240}
241 241
242void WordGame::startGame() 242void WordGame::startGame()
243{ 243{
244 rules = newgame->ruleslist[newgame->rules->currentItem()]; 244 rules = newgame->ruleslist[newgame->rules->currentItem()];
245 if ( loadRules(rules) ) { 245 if ( loadRules(rules) ) {
246 QStringList names; 246 QStringList names;
247 names.append(newgame->player0->currentText()); 247 names.append(newgame->player0->currentText());
248 names.append(newgame->player1->currentText()); 248 names.append(newgame->player1->currentText());
249 names.append(newgame->player2->currentText()); 249 names.append(newgame->player2->currentText());
250 names.append(newgame->player3->currentText()); 250 names.append(newgame->player3->currentText());
251 names.append(newgame->player4->currentText()); 251 names.append(newgame->player4->currentText());
252 names.append(newgame->player5->currentText()); 252 names.append(newgame->player5->currentText());
253 delete newgame; 253 delete newgame;
254 startGame(names); 254 startGame(names);
255 } else { 255 } else {
256 // error... 256 // error...
257 delete newgame; 257 delete newgame;
258 close(); 258 close();
259 } 259 }
260} 260}
261 261
262void WordGame::startGame(const QStringList& playerlist) 262void WordGame::startGame(const QStringList& playerlist)
263{ 263{
264 toolbar->show(); 264 toolbar->show();
265 racks = new QWidgetStack(vbox); 265 racks = new QWidgetStack(vbox);
266 racks->setFixedHeight(TileItem::bigHeight()+2); 266 racks->setFixedHeight(TileItem::bigHeight()+2);
267 namelist.clear(); 267 namelist.clear();
268 nplayers=0; 268 nplayers=0;
269 for (QStringList::ConstIterator it=playerlist.begin(); it!=playerlist.end(); ++it) 269 for (QStringList::ConstIterator it=playerlist.begin(); it!=playerlist.end(); ++it)
270 addPlayer(*it); 270 addPlayer(*it);
271 scoreinfo->init(namelist); 271 scoreinfo->init(namelist);
272 272
273 if ( nplayers ) { 273 if ( nplayers ) {
274 player=0; 274 player=0;
275 readyRack(player); 275 readyRack(player);
276 } 276 }
277 277
278 board->show(); 278 board->show();
279 racks->show(); 279 racks->show();
280} 280}
281 281
282bool WordGame::loadRules(const QString &name) 282bool WordGame::loadRules(const QString &name)
283{ 283{
284 QString filename = Global::applicationFileName( "wordgame", name ); 284 QString filename = Global::applicationFileName( "wordgame", name );
285 QFile file( filename ); 285 QFile file( filename );
286 if ( !file.open( IO_ReadOnly ) ) 286 if ( !file.open( IO_ReadOnly ) )
287 return FALSE; 287 return FALSE;
288 288
289 QTextStream ts( &file ); 289 QTextStream ts( &file );
290 290
291 QString title = name; 291 QString title = name;
292 title.truncate( title.length() - 6 ); 292 title.truncate( title.length() - 6 );
293 setCaption( title ); 293 setCaption( title );
294 294
295 QString shapepixmap; 295 QString shapepixmap;
296 ts >> shapepixmap; 296 ts >> shapepixmap;
297 int htiles,vtiles; 297 int htiles,vtiles;
298 ts >> htiles >> vtiles; 298 ts >> htiles >> vtiles;
299 299
300 if ( htiles < 3 || vtiles < 3 ) 300 if ( htiles < 3 || vtiles < 3 )
301 return FALSE; 301 return FALSE;
302 302
303 QString rule_shapes; 303 QString rule_shapes;
304 for (int i=0; i<vtiles; i++) { 304 for (int i=0; i<vtiles; i++) {
305 QString line; 305 QString line;
306 ts >> line; 306 ts >> line;
307 rule_shapes += line; 307 rule_shapes += line;
308 } 308 }
309 static int rule_effects[12]; 309 static int rule_effects[12];
310 int re=0,e; 310 int re=0,e;
311 ts >> e; 311 ts >> e;
312 while ( e && re < 10 ) { 312 while ( e && re < 10 ) {
313 rule_effects[re] = e; 313 rule_effects[re] = e;
314 if ( re++ < 10 ) ts >> e; 314 if ( re++ < 10 ) ts >> e;
315 } 315 }
316 316
317 QImage shim = Resource::loadImage(shapepixmap); 317 QImage shim = Resource::loadImage("wordgame/wordgame_shapes.xpm");
318 shim = shim.smoothScale((re-1)*TileItem::smallWidth(),TileItem::smallHeight()); 318 shim = shim.smoothScale((re-1)*TileItem::smallWidth(),TileItem::smallHeight());
319 QPixmap bgshapes; 319 QPixmap bgshapes;
320 bgshapes.convertFromImage(shim); 320 bgshapes.convertFromImage(shim);
321 321
322 rule_effects[re++] = 100; // default bonus 322 rule_effects[re++] = 100; // default bonus
323 board = new Board(bgshapes, htiles, vtiles, vbox); 323 board = new Board(bgshapes, htiles, vtiles, vbox);
324 board->setRules(rule_shapes, rule_effects); 324 board->setRules(rule_shapes, rule_effects);
325 connect(board, SIGNAL(temporaryScore(int)), scoreinfo, SLOT(showTemporaryScore(int))); 325 connect(board, SIGNAL(temporaryScore(int)), scoreinfo, SLOT(showTemporaryScore(int)));
326 326
327 bag = new Bag; 327 bag = new Bag;
328 328
329 int count; 329 int count;
330 ts >> count; 330 ts >> count;
331 while ( count ) { 331 while ( count ) {
332 QString text; 332 QString text;
333 int value; 333 int value;
334 ts >> text >> value; 334 ts >> text >> value;
335 if ( text == "_" ) 335 if ( text == "_" )
336 text = ""; 336 text = "";
337 337
338 Tile t(text, value); 338 Tile t(text, value);
339 for (int n=count; n--; ) 339 for (int n=count; n--; )
340 bag->add(t); 340 bag->add(t);
341 341
342 ts >> count; 342 ts >> count;
343 } 343 }
344 344
345 return TRUE; 345 return TRUE;
346} 346}
347 347
348 348
349NewGame::NewGame(QWidget* parent) : 349NewGame::NewGame(QWidget* parent) :
350 NewGameBase(parent) 350 NewGameBase(parent)
351{ 351{
352} 352}
353 353
354void NewGame::updateRuleSets() 354void NewGame::updateRuleSets()
355{ 355{
356 rules->clear(); 356 rules->clear();
357 357
358 QString rulesDir = Global::applicationFileName( "wordgame", "" ); 358 QString rulesDir = Global::applicationFileName( "wordgame", "" );
359 QDir dir( rulesDir, "*.rules" ); 359 QDir dir( rulesDir, "*.rules" );
360 ruleslist = dir.entryList(); 360 ruleslist = dir.entryList();
361 if ( ruleslist.isEmpty() ) { 361 if ( ruleslist.isEmpty() ) {
362 // Provide a sample 362 // Provide a sample
363 QFile file( rulesDir + "Sample.rules" ); 363 QFile file( rulesDir + "Sample.rules" );
364 if ( file.open( IO_WriteOnly ) ) { 364 if ( file.open( IO_WriteOnly ) ) {
365 file.writeBlock( sampleWGR, strlen(sampleWGR) ); 365 file.writeBlock( sampleWGR, strlen(sampleWGR) );
366 file.close(); 366 file.close();
367 updateRuleSets(); 367 updateRuleSets();
368 } 368 }
369 return; 369 return;
370 } 370 }
371 int newest=0; 371 int newest=0;
372 int newest_age=INT_MAX; 372 int newest_age=INT_MAX;
373 QDateTime now = QDateTime::currentDateTime(); 373 QDateTime now = QDateTime::currentDateTime();
374 QStringList::Iterator it; 374 QStringList::Iterator it;
375 for ( it = ruleslist.begin(); it != ruleslist.end(); ++it ) { 375 for ( it = ruleslist.begin(); it != ruleslist.end(); ++it ) {
376 QFileInfo fi((*it)); 376 QFileInfo fi((*it));
377 int age = fi.lastModified().secsTo(now); 377 int age = fi.lastModified().secsTo(now);
378 QString name = *it; 378 QString name = *it;
379 name.truncate( name.length()-6 ); // remove extension 379 name.truncate( name.length()-6 ); // remove extension
380 rules->insertItem( name ); 380 rules->insertItem( name );
381 if ( age < newest_age ) { 381 if ( age < newest_age ) {
382 newest_age = age; 382 newest_age = age;
383 newest = rules->count()-1; 383 newest = rules->count()-1;
384 } 384 }
385 } 385 }
386 rules->setCurrentItem(newest); 386 rules->setCurrentItem(newest);
387} 387}
388 388
389Rules::Rules(QWidget* parent) : 389Rules::Rules(QWidget* parent) :
390 RulesBase(parent,0,TRUE) 390 RulesBase(parent,0,TRUE)
391{ 391{
392} 392}
393 393
394void Rules::editRules() 394void Rules::editRules()
395{ 395{
396 if ( exec() ) { 396 if ( exec() ) {
397 // ### create a new set of rules 397 // ### create a new set of rules
398 emit rulesChanged(); 398 emit rulesChanged();
399 } 399 }
400} 400}
401 401
402void Rules::deleteRuleSet() 402void Rules::deleteRuleSet()
403{ 403{
404 // ### delete existing rule set 404 // ### delete existing rule set
405 emit rulesChanged(); 405 emit rulesChanged();
406} 406}
407 407
408void WordGame::addPlayer(const QString& name) 408void WordGame::addPlayer(const QString& name)
409{ 409{
410 if ( !name.isEmpty() ) { 410 if ( !name.isEmpty() ) {
411 int colon = name.find(':'); 411 int colon = name.find(':');
412 int cpu = (colon >=0 && name.left(2) == "AI") ? name.mid(2,1).toInt() : 0; 412 int cpu = (colon >=0 && name.left(2) == "AI") ? name.mid(2,1).toInt() : 0;
413 addPlayer(name,cpu); 413 addPlayer(name,cpu);
414 } 414 }
415} 415}
416 416
417void WordGame::addPlayer(const QString& name, int cpu) 417void WordGame::addPlayer(const QString& name, int cpu)
418{ 418{
419 Rack* r = new Rack(rack_tiles,racks); 419 Rack* r = new Rack(rack_tiles,racks);
420 r->setPlayerName(name); 420 r->setPlayerName(name);
421 r->setComputerization(cpu); 421 r->setComputerization(cpu);
422 racks->addWidget(r, nplayers); 422 racks->addWidget(r, nplayers);
423 refillRack(nplayers); 423 refillRack(nplayers);
424 namelist.append(name); 424 namelist.append(name);
425 425
426 ++nplayers; 426 ++nplayers;
427} 427}
428 428
429void WordGame::nextPlayer() 429void WordGame::nextPlayer()
430{ 430{
431 if ( !refillRack(player) ) { 431 if ( !refillRack(player) ) {
432 endGame(); 432 endGame();
433 } else { 433 } else {
434 player = (player+1)%nplayers; 434 player = (player+1)%nplayers;
435 scoreinfo->setBoldOne(player); 435 scoreinfo->setBoldOne(player);
436 readyRack(player); 436 readyRack(player);
437 } 437 }
438} 438}
439 439
440bool WordGame::mayEndGame() 440bool WordGame::mayEndGame()
441{ 441{
442 int out=-1; 442 int out=-1;
443 int i; 443 int i;
444 for (i=0; i<nplayers; i++) 444 for (i=0; i<nplayers; i++)
445 if ( !rack(i)->count() ) 445 if ( !rack(i)->count() )
446 out = i; 446 out = i;
447 if ( out<0 ) { 447 if ( out<0 ) {
448 if ( QMessageBox::warning(this,tr("End game"), 448 if ( QMessageBox::warning(this,tr("End game"),
449 tr("Do you want to end the game early?"), 449 tr("Do you want to end the game early?"),
450 tr("Yes"), tr("No") )!=0 ) 450 tr("Yes"), tr("No") )!=0 )
451 { 451 {
452 return FALSE; 452 return FALSE;
453 } 453 }
454 } 454 }
455 return TRUE; 455 return TRUE;
456} 456}
457 457
458void WordGame::endGame() 458void WordGame::endGame()
459{ 459{
460 if ( gameover ) { 460 if ( gameover ) {
461 close(); 461 close();
462 return; 462 return;
463 } 463 }
464 464
465 if ( !mayEndGame() ) 465 if ( !mayEndGame() )
466 return; 466 return;
467 int out=-1; 467 int out=-1;
468 int totalleft=0; 468 int totalleft=0;
469 int i; 469 int i;
470 for (i=0; i<nplayers; i++) { 470 for (i=0; i<nplayers; i++) {
471 Rack* r = rack(i); 471 Rack* r = rack(i);
472 int c = r->count(); 472 int c = r->count();
473 if ( c ) { 473 if ( c ) {
474 int lose=0; 474 int lose=0;
475 for ( int j=0; j<c; j++ ) 475 for ( int j=0; j<c; j++ )
476 lose += r->tileRef(j)->value(); 476 lose += r->tileRef(j)->value();
477 totalleft += lose; 477 totalleft += lose;
478 scoreinfo->addScore(i,-lose); 478 scoreinfo->addScore(i,-lose);
479 } else { 479 } else {
480 out = i; 480 out = i;
481 } 481 }
482 } 482 }
483 int highest=0; 483 int highest=0;
484 int winner=0; 484 int winner=0;
485 for (i=0; i<nplayers; i++) { 485 for (i=0; i<nplayers; i++) {
486 int s = scoreinfo->playerScore(i); 486 int s = scoreinfo->playerScore(i);
487 if ( s > highest ) { 487 if ( s > highest ) {
488 highest = s; 488 highest = s;
489 winner = i; 489 winner = i;
490 } 490 }
491 } 491 }
492 if ( out >= 0 ) 492 if ( out >= 0 )
493 scoreinfo->addScore(out,totalleft); 493 scoreinfo->addScore(out,totalleft);
494 scoreinfo->setBoldOne(winner); 494 scoreinfo->setBoldOne(winner);
495 gameover = TRUE; 495 gameover = TRUE;
496 done->setEnabled(TRUE); 496 done->setEnabled(TRUE);
497 reset->setEnabled(FALSE); 497 reset->setEnabled(FALSE);
498} 498}
499 499
500void WordGame::endTurn() 500void WordGame::endTurn()
501{ 501{
502 if ( gameover ) { 502 if ( gameover ) {
503 openGameSelector(namelist); 503 openGameSelector(namelist);
504 } else { 504 } else {
505 if ( board->checkTurn() ) { 505 if ( board->checkTurn() ) {
506 if ( board->turnScore() >= 0 ) { 506 if ( board->turnScore() >= 0 ) {
507 scoreinfo->addScore(player,board->turnScore()); 507 scoreinfo->addScore(player,board->turnScore());
508 board->finalizeTurn(); 508 board->finalizeTurn();
509 } else { 509 } else {
510 QApplication::beep(); 510 QApplication::beep();
511 } 511 }
512 nextPlayer(); 512 nextPlayer();
513 } 513 }
514 } 514 }
515} 515}
516 516
517void WordGame::resetTurn() 517void WordGame::resetTurn()
518{ 518{
519 board->resetRack(); 519 board->resetRack();
520} 520}
521 521
522void WordGame::passTurn() 522void WordGame::passTurn()
523{ 523{
524 // ######## trade? 524 // ######## trade?
525 nextPlayer(); 525 nextPlayer();
526} 526}
527 527
528bool WordGame::refillRack(int i) 528bool WordGame::refillRack(int i)
529{ 529{
530 Rack* r = rack(i); 530 Rack* r = rack(i);
531 while ( !bag->isEmpty() && !r->isFull() ) { 531 while ( !bag->isEmpty() && !r->isFull() ) {
532 r->addTile(bag->takeRandom()); 532 r->addTile(bag->takeRandom());
533 } 533 }
534 return r->count() != 0; 534 return r->count() != 0;
535} 535}
536 536
537void WordGame::readyRack(int i) 537void WordGame::readyRack(int i)
538{ 538{
539 Rack* r = rack(i); 539 Rack* r = rack(i);
540 racks->raiseWidget(i); 540 racks->raiseWidget(i);
541 board->setCurrentRack(r); 541 board->setCurrentRack(r);
542 542
543 done->setEnabled( !r->computerized() ); 543 done->setEnabled( !r->computerized() );
544 reset->setEnabled( !r->computerized() ); 544 reset->setEnabled( !r->computerized() );
545 545
546 if ( r->computerized() ) { 546 if ( r->computerized() ) {
547 cpu = new ComputerPlayer(board, r); 547 cpu = new ComputerPlayer(board, r);
548 aiheart->start(0); 548 aiheart->start(0);
549 } 549 }
550} 550}
551 551
552Rack* WordGame::rack(int i) const 552Rack* WordGame::rack(int i) const
553{ 553{
554 return (Rack*)racks->widget(i); 554 return (Rack*)racks->widget(i);
555} 555}
556 556
557void WordGame::think() 557void WordGame::think()
558{ 558{
559 if ( !cpu->step() ) { 559 if ( !cpu->step() ) {
560 delete cpu; 560 delete cpu;
561 cpu = 0; 561 cpu = 0;
562 aiheart->stop(); 562 aiheart->stop();
563 if ( board->turnScore() < 0 ) 563 if ( board->turnScore() < 0 )
564 passTurn(); 564 passTurn();
565 else 565 else
566 endTurn(); 566 endTurn();
567 } 567 }
568} 568}
569 569
570ComputerPlayer::ComputerPlayer(Board* b, Rack* r) : 570ComputerPlayer::ComputerPlayer(Board* b, Rack* r) :
571 board(b), rack(r), best(new const Tile*[rack_tiles]), 571 board(b), rack(r), best(new const Tile*[rack_tiles]),
572 best_blankvalues(new Tile[rack_tiles]) 572 best_blankvalues(new Tile[rack_tiles])
573{ 573{
574 best_score = -1; 574 best_score = -1;
575 across=FALSE; 575 across=FALSE;
576 dict=0; 576 dict=0;
577} 577}
578 578
579ComputerPlayer::~ComputerPlayer() 579ComputerPlayer::~ComputerPlayer()
580{ 580{
581 delete [] best; 581 delete [] best;
582 delete [] best_blankvalues; 582 delete [] best_blankvalues;
583} 583}
584 584
585bool ComputerPlayer::step() 585bool ComputerPlayer::step()
586{ 586{
587 const QDawg::Node* root = dict ? Global::dawg("WordGame").root() 587 const QDawg::Node* root = dict ? Global::dawg("WordGame").root()
588 : Global::fixedDawg().root(); 588 : Global::fixedDawg().root();
589 QPoint d = across ? QPoint(1,0) : QPoint(0,1); 589 QPoint d = across ? QPoint(1,0) : QPoint(0,1);
590 const Tile* tiles[99]; // ### max board size 590 const Tile* tiles[99]; // ### max board size
591 uchar nletter[4095]; // QDawg only handles 0..4095 591 uchar nletter[4095]; // QDawg only handles 0..4095
592 memset(nletter,0,4096); 592 memset(nletter,0,4096);
593 for (int i=0; i<rack->count(); i++) { 593 for (int i=0; i<rack->count(); i++) {
594 const Tile* r = rack->tileRef(i); 594 const Tile* r = rack->tileRef(i);
595 if ( r->isBlank() ) 595 if ( r->isBlank() )
596 nletter[0]++; 596 nletter[0]++;
597 else 597 else
598 nletter[r->text()[0].unicode()]++; 598 nletter[r->text()[0].unicode()]++;
599 } 599 }
600 Tile blankvalues[99]; // ### max blanks 600 Tile blankvalues[99]; // ### max blanks
601 findBest(current, d, root, 0, nletter, tiles, 0, blankvalues, 0); 601 findBest(current, d, root, 0, nletter, tiles, 0, blankvalues, 0);
602 if ( ++current.rx() == board->xTiles() ) { 602 if ( ++current.rx() == board->xTiles() ) {
603 current.rx() = 0; 603 current.rx() = 0;
604 if ( ++current.ry() == board->yTiles() ) { 604 if ( ++current.ry() == board->yTiles() ) {
605 if ( across ) { 605 if ( across ) {
606 if ( dict == 1 ) { 606 if ( dict == 1 ) {
607 if ( best_score >= 0 ) { 607 if ( best_score >= 0 ) {
608 rack->arrangeTiles(best,best_n); 608 rack->arrangeTiles(best,best_n);
609 rack->setBlanks(best_blankvalues); 609 rack->setBlanks(best_blankvalues);
610 board->scoreTurn(best_start, best_n, best_dir); 610 board->scoreTurn(best_start, best_n, best_dir);
611 board->showTurn(); 611 board->showTurn();
612 } 612 }
613 return FALSE; 613 return FALSE;
614 } 614 }
615 dict++; 615 dict++;
616 across = FALSE; 616 across = FALSE;
617 current = QPoint(0,0); 617 current = QPoint(0,0);
618 } else { 618 } else {
619 across = TRUE; 619 across = TRUE;
620 current = QPoint(0,0); 620 current = QPoint(0,0);
621 } 621 }
622 } 622 }
623 } 623 }
624 return TRUE; 624 return TRUE;
625} 625}
626 626
627void ComputerPlayer::findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar* nletter, const Tile** tiles, int n, Tile* blankvalues, int blused) 627void ComputerPlayer::findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar* nletter, const Tile** tiles, int n, Tile* blankvalues, int blused)
628{ 628{
629 if ( !node ) 629 if ( !node )
630 return; 630 return;
631 QChar l = node->letter(); 631 QChar l = node->letter();
632 const Tile* cur = board->tile(at); 632 const Tile* cur = board->tile(at);
633 if ( cur ) { 633 if ( cur ) {
634 if ( cur->text()[0] == l ) { 634 if ( cur->text()[0] == l ) {
635 bool nextok = board->contains(at+d); 635 bool nextok = board->contains(at+d);
636 if ( node->isWord() && n && (!nextok || !board->tile(at+d)) ) 636 if ( node->isWord() && n && (!nextok || !board->tile(at+d)) )
637 noteChoice(tiles,n,d,blankvalues,blused); 637 noteChoice(tiles,n,d,blankvalues,blused);
638 if ( nextok ) 638 if ( nextok )
639 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused); 639 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused);
640 // #### text()[1]... 640 // #### text()[1]...
641 } 641 }
642 } else { 642 } else {
643 if ( nletter[l.unicode()] || nletter[0] ) { 643 if ( nletter[l.unicode()] || nletter[0] ) {
644 int rc = rack->count(); 644 int rc = rack->count();
645 ulong msk = 1; 645 ulong msk = 1;
646 for ( int x=0; x<rc; x++ ) { 646 for ( int x=0; x<rc; x++ ) {
647 if ( !(used&msk) ) { 647 if ( !(used&msk) ) {
648 const Tile* t = rack->tileRef(x); 648 const Tile* t = rack->tileRef(x);
649 if ( t->isBlank() || t->text() == l ) { // #### multi-char value()s 649 if ( t->isBlank() || t->text() == l ) { // #### multi-char value()s
650 bool nextok = board->contains(at+d); 650 bool nextok = board->contains(at+d);
651 tiles[n++] = t; 651 tiles[n++] = t;
652 if ( t->isBlank() ) 652 if ( t->isBlank() )
653 blankvalues[blused++] = Tile(l,0); 653 blankvalues[blused++] = Tile(l,0);
654 if ( node->isWord() && (!nextok || !board->tile(at+d)) ) 654 if ( node->isWord() && (!nextok || !board->tile(at+d)) )
655 noteChoice(tiles,n,d,blankvalues,blused); 655 noteChoice(tiles,n,d,blankvalues,blused);
656 used |= msk; // mark 656 used |= msk; // mark
657 nletter[t->text()[0].unicode()]--; 657 nletter[t->text()[0].unicode()]--;
658 if ( nextok ) 658 if ( nextok )
659 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused); 659 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused);
660 n--; 660 n--;
661 nletter[t->text()[0].unicode()]++; 661 nletter[t->text()[0].unicode()]++;
662 if ( t->isBlank() ) { 662 if ( t->isBlank() ) {
663 // keep looking 663 // keep looking
664 blused--; 664 blused--;
665 used &= ~msk; // unmark 665 used &= ~msk; // unmark
666 } else { 666 } else {
667 break; 667 break;
668 } 668 }
669 } 669 }
670 } 670 }
671 msk <<= 1; 671 msk <<= 1;
672 } 672 }
673 } 673 }
674 // #### text()[1]... 674 // #### text()[1]...
675 } 675 }
676 findBest(at, d, node->next(), used, nletter, tiles, n, blankvalues, blused); 676 findBest(at, d, node->next(), used, nletter, tiles, n, blankvalues, blused);
677} 677}
678 678
679void ComputerPlayer::noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused) 679void ComputerPlayer::noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused)
680{ 680{
681 int s = board->score(current, tiles, n, blankvalues, d, TRUE, 0); 681 int s = board->score(current, tiles, n, blankvalues, d, TRUE, 0);
682/* 682/*
683if (s>0 || current==QPoint(5,1)){ 683if (s>0 || current==QPoint(5,1)){
684QString st; 684QString st;
685for ( int i=0; i<n; i++ ) 685for ( int i=0; i<n; i++ )
686 st += tiles[i]->text(); 686 st += tiles[i]->text();
687qDebug("%d,%d: %s (%d) for %d",current.x(),current.y(),st.latin1(),n,s); 687qDebug("%d,%d: %s (%d) for %d",current.x(),current.y(),st.latin1(),n,s);
688} 688}
689*/ 689*/
690 if ( s > best_score ) { 690 if ( s > best_score ) {
691 int i; 691 int i;
692 for ( i=0; i<n; i++ ) 692 for ( i=0; i<n; i++ )
693 best[i] = tiles[i]; 693 best[i] = tiles[i];
694 for ( i=0; i<blused; i++ ) 694 for ( i=0; i<blused; i++ )
695 best_blankvalues[i] = blankvalues[i]; 695 best_blankvalues[i] = blankvalues[i];
696 best_n = n; 696 best_n = n;
697 best_blused = blused; 697 best_blused = blused;
698 best_score = s; 698 best_score = s;
699 best_dir = d; 699 best_dir = d;
700 best_start = current; 700 best_start = current;
701 } 701 }
702} 702}
703 703
704int TileItem::smallWidth() 704int TileItem::smallWidth()
705{ 705{
706 return tile_smallw; 706 return tile_smallw;
707} 707}
708 708
709int TileItem::smallHeight() 709int TileItem::smallHeight()
710{ 710{
711 return tile_smallh; 711 return tile_smallh;
712} 712}
713 713
714int TileItem::bigWidth() 714int TileItem::bigWidth()
715{ 715{
716 return tile_bigw; 716 return tile_bigw;
717} 717}
718 718
719int TileItem::bigHeight() 719int TileItem::bigHeight()
720{ 720{
721 return tile_bigh; 721 return tile_bigh;
722} 722}
723 723
724void TileItem::setState( State state ) 724void TileItem::setState( State state )
725{ 725{
726 hide(); 726 hide();
727 s = state; 727 s = state;
728 show(); // ### use update() in Qt 3.0 728 show(); // ### use update() in Qt 3.0
729} 729}
730 730
731void TileItem::setTile(const Tile& tile) 731void TileItem::setTile(const Tile& tile)
732{ 732{
733 hide(); 733 hide();
734 t = tile; 734 t = tile;
735 show(); // ### use update() in Qt 3.0 735 show(); // ### use update() in Qt 3.0
736} 736}
737 737
738void TileItem::setBig(bool b) 738void TileItem::setBig(bool b)
739{ 739{
740 big = b; 740 big = b;
741} 741}
742 742
743void TileItem::drawShape(QPainter& p) 743void TileItem::drawShape(QPainter& p)
744{ 744{
745 static QFont *value_font=0; 745 static QFont *value_font=0;
746 static QFont *big_font=0; 746 static QFont *big_font=0;
747 static QFont *small_font=0; 747 static QFont *small_font=0;
748 if ( !value_font ) { 748 if ( !value_font ) {
749 value_font = new QFont("helvetica",8); 749 value_font = new QFont("helvetica",8);
750 if ( TileItem::bigWidth() < 20 ) { 750 if ( TileItem::bigWidth() < 20 ) {
751 big_font = new QFont("helvetica",12); 751 big_font = new QFont("helvetica",12);
752 small_font = new QFont("helvetica",8); 752 small_font = new QFont("helvetica",8);
753 } else { 753 } else {
754 big_font = new QFont("smoothtimes",17); 754 big_font = new QFont("smoothtimes",17);
755 small_font = new QFont("smoothtimes",10); 755 small_font = new QFont("smoothtimes",10);
756 } 756 }
757 } 757 }
758 758
759 QRect area(x(),y(),width(),height()); 759 QRect area(x(),y(),width(),height());
760 p.setBrush(s == Floating ? yellow/*lightGray*/ : white); 760 p.setBrush(s == Floating ? yellow/*lightGray*/ : white);
761 p.drawRect(area); 761 p.drawRect(area);
762 if ( big ) { 762 if ( big ) {
763 p.setFont(*value_font); 763 p.setFont(*value_font);
764 QString n = QString::number(t.value()); 764 QString n = QString::number(t.value());
765 int w = p.fontMetrics().width('1'); 765 int w = p.fontMetrics().width('1');
766 int h = p.fontMetrics().height(); 766 int h = p.fontMetrics().height();
767 w *= n.length(); 767 w *= n.length();
768 QRect valuearea(x()+width()-w-1,y()+height()-h,w,h); 768 QRect valuearea(x()+width()-w-1,y()+height()-h,w,h);
769 p.drawText(valuearea,AlignCenter,n); 769 p.drawText(valuearea,AlignCenter,n);
770 p.setFont(*big_font); 770 p.setFont(*big_font);
771 area = QRect(x(),y()+tile_btweak,width()-4,height()-1); 771 area = QRect(x(),y()+tile_btweak,width()-4,height()-1);
772 } else { 772 } else {
773 p.setFont(*small_font); 773 p.setFont(*small_font);
774 area = QRect(x()+1+tile_stweak,y()+1,width(),height()-3); 774 area = QRect(x()+1+tile_stweak,y()+1,width(),height()-3);
775 } 775 }
776 if ( t.value() == 0 ) 776 if ( t.value() == 0 )
777 p.setPen(darkGray); 777 p.setPen(darkGray);
778 p.drawText(area,AlignCenter,t.text().upper()); 778 p.drawText(area,AlignCenter,t.text().upper());
779} 779}
780 780
781Board::Board(QPixmap bgshapes, int w, int h, QWidget* parent) : 781Board::Board(QPixmap bgshapes, int w, int h, QWidget* parent) :
782 QCanvasView(new QCanvas(bgshapes,w,h, TileItem::smallWidth(), TileItem::smallHeight()), 782 QCanvasView(new QCanvas(bgshapes,w,h, TileItem::smallWidth(), TileItem::smallHeight()),
783 parent) 783 parent)
784{ 784{
785 setFixedSize(w*TileItem::smallWidth(),h*TileItem::smallHeight()); 785 setFixedSize(w*TileItem::smallWidth(),h*TileItem::smallHeight());
786 grid = new TileItem*[w*h]; 786 grid = new TileItem*[w*h];
787 memset(grid,0,w*h*sizeof(TileItem*)); 787 memset(grid,0,w*h*sizeof(TileItem*));
788 setFrameStyle(0); 788 setFrameStyle(0);
789 setHScrollBarMode(AlwaysOff); 789 setHScrollBarMode(AlwaysOff);
790 setVScrollBarMode(AlwaysOff); 790 setVScrollBarMode(AlwaysOff);
791 current_rack = 0; 791 current_rack = 0;
792 shown_n = 0; 792 shown_n = 0;
793} 793}
794 794
795Board::~Board() 795Board::~Board()
796{ 796{
797 delete canvas(); 797 delete canvas();
798} 798}
799 799
800QSize Board::sizeHint() const 800QSize Board::sizeHint() const
801{ 801{
802 return QSize(canvas()->width(),canvas()->height()); 802 return QSize(canvas()->width(),canvas()->height());
803} 803}
804 804
805void Board::writeConfig(Config& cfg) 805void Board::writeConfig(Config& cfg)
806{ 806{
807 QStringList t; 807 QStringList t;
808 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically(); 808 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically();
809 for (int i=0; i<n; i++) 809 for (int i=0; i<n; i++)
810 t.append( grid[i] ? grid[i]->tile().key() : QString(".") ); 810 t.append( grid[i] ? grid[i]->tile().key() : QString(".") );
811 cfg.writeEntry("Board",t,';'); 811 cfg.writeEntry("Board",t,';');
812} 812}
813 813
814void Board::readConfig(Config& cfg) 814void Board::readConfig(Config& cfg)
815{ 815{
816 clear(); 816 clear();
817 QStringList t = cfg.readListEntry("Board",';'); 817 QStringList t = cfg.readListEntry("Board",';');
818 int i=0; 818 int i=0;
819 int h=canvas()->tilesHorizontally(); 819 int h=canvas()->tilesHorizontally();
820 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it) { 820 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it) {
821 if ( *it != "." ) { 821 if ( *it != "." ) {
822 QPoint p(i%h,i/h); 822 QPoint p(i%h,i/h);
823 setTile(p,Tile(*it)); 823 setTile(p,Tile(*it));
824 } 824 }
825 i++; 825 i++;
826 } 826 }
827 canvas()->update(); 827 canvas()->update();
828} 828}
829 829
830void Board::clear() 830void Board::clear()
831{ 831{
832 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically(); 832 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically();
833 for (int i=0; i<n; i++) { 833 for (int i=0; i<n; i++) {
834 delete grid[i]; 834 delete grid[i];
835 grid[i]=0; 835 grid[i]=0;
836 } 836 }
837} 837}
838 838
839 839
840void Board::setCurrentRack(Rack* r) 840void Board::setCurrentRack(Rack* r)
841{ 841{
842 turn_score = -1; 842 turn_score = -1;
843 current_rack = r; 843 current_rack = r;
844} 844}
845 845
846void Board::resetRack() 846void Board::resetRack()
847{ 847{
848 unshowTurn(); 848 unshowTurn();
849 canvas()->update(); 849 canvas()->update();
850} 850}
851 851
852void Board::contentsMousePressEvent(QMouseEvent* e) 852void Board::contentsMousePressEvent(QMouseEvent* e)
853{ 853{
854 dragstart = e->pos(); 854 dragstart = e->pos();
855} 855}
856 856
857void Board::contentsMouseMoveEvent(QMouseEvent* e) 857void Board::contentsMouseMoveEvent(QMouseEvent* e)
858{ 858{
859 if ( current_rack && !current_rack->computerized() ) { 859 if ( current_rack && !current_rack->computerized() ) {
860 QPoint d = e->pos() - dragstart; 860 QPoint d = e->pos() - dragstart;
861 if ( d.x() <= 0 && d.y() <= 0 ) { 861 if ( d.x() <= 0 && d.y() <= 0 ) {
862 // None 862 // None
863 resetRack(); 863 resetRack();
864 } else { 864 } else {
865 int n; 865 int n;
866 QPoint start=boardPos(dragstart); 866 QPoint start=boardPos(dragstart);
867 QPoint end=boardPos(e->pos()); 867 QPoint end=boardPos(e->pos());
868 QPoint diff=end-start; 868 QPoint diff=end-start;
869 QPoint dir; 869 QPoint dir;
870 if ( d.x() > d.y() ) { 870 if ( d.x() > d.y() ) {
871 n = diff.x()+1; 871 n = diff.x()+1;
872 dir = QPoint(1,0); 872 dir = QPoint(1,0);
873 } else { 873 } else {
874 n = diff.y()+1; 874 n = diff.y()+1;
875 dir = QPoint(0,1); 875 dir = QPoint(0,1);
876 } 876 }
877 877
878 unshowTurn(); 878 unshowTurn();
879 879
880 // Subtract existing tiles from n 880 // Subtract existing tiles from n
881 QPoint t = start; 881 QPoint t = start;
882 for ( int i=n; i--; ) { 882 for ( int i=n; i--; ) {
883 if ( contains(t) && tile(t) ) 883 if ( contains(t) && tile(t) )
884 n--; 884 n--;
885 t += dir; 885 t += dir;
886 } 886 }
887 887
888 // Move start back to real start 888 // Move start back to real start
889 while (contains(start-dir) && tile(start-dir)) 889 while (contains(start-dir) && tile(start-dir))
890 start -= dir; 890 start -= dir;
891 891
892 scoreTurn(start, n, dir); 892 scoreTurn(start, n, dir);
893 showTurn(); 893 showTurn();
894 } 894 }
895 } 895 }
896} 896}
897 897
898void Board::finalizeTurn() 898void Board::finalizeTurn()
899{ 899{
900 int i=0; 900 int i=0;
901 QPoint at = shown_at; 901 QPoint at = shown_at;
902 while ( i<shown_n && contains(at) ) { 902 while ( i<shown_n && contains(at) ) {
903 if ( item(at) && item(at)->state() == TileItem::Floating ) { 903 if ( item(at) && item(at)->state() == TileItem::Floating ) {
904 current_rack->remove(item(at)->tile()); 904 current_rack->remove(item(at)->tile());
905 setTileState(at,TileItem::Firm); 905 setTileState(at,TileItem::Firm);
906 i++; 906 i++;
907 } 907 }
908 at += shown_step; 908 at += shown_step;
909 } 909 }
910 canvas()->update(); 910 canvas()->update();
911} 911}
912 912
913void Board::unshowTurn() 913void Board::unshowTurn()
914{ 914{
915 int i=0; 915 int i=0;
916 QPoint at = shown_at; 916 QPoint at = shown_at;
917 while ( i<shown_n && i<current_rack->count() && contains(at) ) { 917 while ( i<shown_n && i<current_rack->count() && contains(at) ) {
918 if ( item(at) && item(at)->state() == TileItem::Floating ) { 918 if ( item(at) && item(at)->state() == TileItem::Floating ) {
919 unsetTile(at); 919 unsetTile(at);
920 i++; 920 i++;
921 } 921 }
922 at += shown_step; 922 at += shown_step;
923 } 923 }
924} 924}
925 925
926void Board::showTurn() 926void Board::showTurn()
927{ 927{
928 unshowTurn(); 928 unshowTurn();
929 QPoint at = shown_at; 929 QPoint at = shown_at;
930 int i=0; 930 int i=0;
931 while ( i<shown_n && i<current_rack->count() && contains(at) ) { 931 while ( i<shown_n && i<current_rack->count() && contains(at) ) {
932 if ( !tile(at) ) { 932 if ( !tile(at) ) {
933 Tile t = current_rack->tile(i); 933 Tile t = current_rack->tile(i);
934 setTile(at,t); 934 setTile(at,t);
935 setTileState(at,TileItem::Floating); 935 setTileState(at,TileItem::Floating);
936 i++; 936 i++;
937 } 937 }
938 at += shown_step; 938 at += shown_step;
939 } 939 }
940 canvas()->update(); 940 canvas()->update();
941} 941}
942 942
943int Board::bonussedValue(const QPoint& at, int base, int& all_mult) const 943int Board::bonussedValue(const QPoint& at, int base, int& all_mult) const
944{ 944{
945 int rule = rule_shape[idx(at)]-'0'; 945 int rule = rule_shape[idx(at)]-'0';
946 int effect = rule_effect[rule]; 946 int effect = rule_effect[rule];
947 int mult = effect&Multiplier; 947 int mult = effect&Multiplier;
948 if ( effect & MultiplyAll ) { 948 if ( effect & MultiplyAll ) {
949 all_mult *= mult; 949 all_mult *= mult;
950 return base; 950 return base;
951 } else { 951 } else {
952 return base * mult; 952 return base * mult;
953 } 953 }
954} 954}
955 955
956bool Board::isStart(const QPoint& at) const 956bool Board::isStart(const QPoint& at) const
957{ 957{
958 int rule = rule_shape[idx(at)]-'0'; 958 int rule = rule_shape[idx(at)]-'0';
959 int effect = rule_effect[rule]; 959 int effect = rule_effect[rule];
960 return effect&Start; 960 return effect&Start;
961} 961}
962 962
963bool Board::checkTurn() 963bool Board::checkTurn()
964{ 964{
965 if ( current_rack->computerized() ) 965 if ( current_rack->computerized() )
966 return TRUE; // computer doesn't cheat, and has already set blanks. 966 return TRUE; // computer doesn't cheat, and has already set blanks.
967 967
968 QPoint at = shown_at; 968 QPoint at = shown_at;
969 int n = shown_n; 969 int n = shown_n;
970 QPoint d = shown_step; 970 QPoint d = shown_step;
971 const Tile* tiles[99]; 971 const Tile* tiles[99];
972 Tile blankvalues[99]; 972 Tile blankvalues[99];
973 if ( n > current_rack->count() ) 973 if ( n > current_rack->count() )
974 n = current_rack->count(); 974 n = current_rack->count();
975 975
976 QDialog check(this,0,TRUE); 976 QDialog check(this,0,TRUE);
977 (new QVBoxLayout(&check))->setAutoAdd(TRUE); 977 (new QVBoxLayout(&check))->setAutoAdd(TRUE);
978 978
979 QHBox mw(&check); 979 QHBox mw(&check);
980 new QLabel(tr("Blanks: "),&mw); 980 new QLabel(tr("Blanks: "),&mw);
981 981
982 int bl=0; 982 int bl=0;
983 QLineEdit* le[99]; 983 QLineEdit* le[99];
984 for (int i=0; i<n; i++) { 984 for (int i=0; i<n; i++) {
985 tiles[i] = current_rack->tileRef(i); 985 tiles[i] = current_rack->tileRef(i);
986 if ( tiles[i]->isBlank() ) { 986 if ( tiles[i]->isBlank() ) {
987 QLineEdit *l = new QLineEdit(&mw); 987 QLineEdit *l = new QLineEdit(&mw);
988 le[bl++] = l; 988 le[bl++] = l;
989 l->setMaxLength(1); 989 l->setMaxLength(1);
990 l->setFixedSize(l->minimumSizeHint()); 990 l->setFixedSize(l->minimumSizeHint());
991 } 991 }
992 } 992 }
993 993
994 QHBox btns(&check); 994 QHBox btns(&check);
995 connect(new QPushButton(tr("OK"),&btns), SIGNAL(clicked()), &check, SLOT(accept())); 995 connect(new QPushButton(tr("OK"),&btns), SIGNAL(clicked()), &check, SLOT(accept()));
996 connect(new QPushButton(tr("Cancel"),&btns), SIGNAL(clicked()), &check, SLOT(reject())); 996 connect(new QPushButton(tr("Cancel"),&btns), SIGNAL(clicked()), &check, SLOT(reject()));
997 997
998 if ( bl ) { 998 if ( bl ) {
999retry: 999retry:
1000 if ( !check.exec() ) { 1000 if ( !check.exec() ) {
1001 unshowTurn(); 1001 unshowTurn();
1002 canvas()->update(); 1002 canvas()->update();
1003 return FALSE; 1003 return FALSE;
1004 } 1004 }
1005 1005
1006 for (int b=0; b<bl; b++) { 1006 for (int b=0; b<bl; b++) {
1007 QString v = le[b]->text(); 1007 QString v = le[b]->text();
1008 blankvalues[b]=Tile(v,0); 1008 blankvalues[b]=Tile(v,0);
1009 if ( v.length() != 1 ) 1009 if ( v.length() != 1 )
1010 goto retry; 1010 goto retry;
1011 } 1011 }
1012 } 1012 }
1013 1013
1014 QStringList words; 1014 QStringList words;
1015 unshowTurn(); 1015 unshowTurn();
1016 turn_score = score(at,tiles,n,blankvalues,d,FALSE,&words); 1016 turn_score = score(at,tiles,n,blankvalues,d,FALSE,&words);
1017 showTurn(); 1017 showTurn();
1018 QStringList to_add; 1018 QStringList to_add;
1019 for (QStringList::Iterator it=words.begin(); it!=words.end(); ++it) { 1019 for (QStringList::Iterator it=words.begin(); it!=words.end(); ++it) {
1020 if ( !Global::fixedDawg().contains(*it) 1020 if ( !Global::fixedDawg().contains(*it)
1021 && !Global::dawg("WordGame").contains(*it) ) { 1021 && !Global::dawg("WordGame").contains(*it) ) {
1022 switch (QMessageBox::warning(this, tr("Unknown word"), 1022 switch (QMessageBox::warning(this, tr("Unknown word"),
1023 tr("<p>The word \"%1\" is not in the dictionary.").arg(*it), 1023 tr("<p>The word \"%1\" is not in the dictionary.").arg(*it),
1024 tr("Add"), tr("Ignore"), tr("Cancel"))) 1024 tr("Add"), tr("Ignore"), tr("Cancel")))
1025 { 1025 {
1026 case 0: 1026 case 0:
1027 // ####### add to wordgame dictionary 1027 // ####### add to wordgame dictionary
1028 to_add.append(*it); 1028 to_add.append(*it);
1029 break; 1029 break;
1030 case 1: 1030 case 1:
1031 break; 1031 break;
1032 case 2: 1032 case 2:
1033 unshowTurn(); 1033 unshowTurn();
1034 canvas()->update(); 1034 canvas()->update();
1035 return FALSE; 1035 return FALSE;
1036 } 1036 }
1037 } 1037 }
1038 } 1038 }
1039 if ( to_add.count() ) 1039 if ( to_add.count() )
1040 Global::addWords("WordGame",to_add); 1040 Global::addWords("WordGame",to_add);
1041 return TRUE; 1041 return TRUE;
1042} 1042}
1043 1043
1044void Board::scoreTurn(const QPoint& at, int n, const QPoint& d) 1044void Board::scoreTurn(const QPoint& at, int n, const QPoint& d)
1045{ 1045{
1046 unshowTurn(); 1046 unshowTurn();
1047 shown_at = at; 1047 shown_at = at;
1048 shown_n = n; 1048 shown_n = n;
1049 shown_step = d; 1049 shown_step = d;
1050 const Tile* tiles[99]; 1050 const Tile* tiles[99];
1051 if ( n > current_rack->count() ) 1051 if ( n > current_rack->count() )
1052 n = current_rack->count(); 1052 n = current_rack->count();
1053 for (int i=0; i<n; i++) 1053 for (int i=0; i<n; i++)
1054 tiles[i] = current_rack->tileRef(i); 1054 tiles[i] = current_rack->tileRef(i);
1055 turn_score = score(at,tiles,n,0,d,FALSE,0); 1055 turn_score = score(at,tiles,n,0,d,FALSE,0);
1056 emit temporaryScore(turn_score); 1056 emit temporaryScore(turn_score);
1057} 1057}
1058 1058
1059int Board::score(QPoint at, const Tile** tiles, int n, const Tile* blankvalue, const QPoint& d, bool checkdict, QStringList* words) const 1059int Board::score(QPoint at, const Tile** tiles, int n, const Tile* blankvalue, const QPoint& d, bool checkdict, QStringList* words) const
1060{ 1060{
1061 int total=0; 1061 int total=0;
1062 int totalsidetotal=0; 1062 int totalsidetotal=0;
1063 1063
1064 // words gets filled with words made 1064 // words gets filled with words made
1065 1065
1066 // mainword==0 -> 1066 // mainword==0 ->
1067 // Checks side words, but not main word 1067 // Checks side words, but not main word
1068 1068
1069 // -1 means words not in dict, or illegally positioned (eg. not connected) 1069 // -1 means words not in dict, or illegally positioned (eg. not connected)
1070 1070
1071 // text is assumed to fit on board. 1071 // text is assumed to fit on board.
1072 1072
1073 if ( words ) *words=QStringList(); 1073 if ( words ) *words=QStringList();
1074 1074
1075 QPoint otherd(d.y(), d.x()); 1075 QPoint otherd(d.y(), d.x());
1076 1076
1077 int all_mult = 1; 1077 int all_mult = 1;
1078 int bl=0; 1078 int bl=0;
1079 1079
1080 bool connected = FALSE; 1080 bool connected = FALSE;
1081 1081
1082 QString mainword=""; 1082 QString mainword="";
1083 1083
1084 if ( contains(at-d) && tile(at-d) ) { 1084 if ( contains(at-d) && tile(at-d) ) {
1085 return -1; // preceeding tiles 1085 return -1; // preceeding tiles