summaryrefslogtreecommitdiff
authorimm <imm>2002-09-24 23:49:15 (UTC)
committer imm <imm>2002-09-24 23:49:15 (UTC)
commita390040768072b4b2b931ec0bcdaaa55daae0b4c (patch) (unidiff)
tree1938c484842f0c35e40dc406e719c0d86e07091c
parentc280cda4ece4a4aa60f4ef2c632d7a37ac08b258 (diff)
downloadopie-a390040768072b4b2b931ec0bcdaaa55daae0b4c.zip
opie-a390040768072b4b2b931ec0bcdaaa55daae0b4c.tar.gz
opie-a390040768072b4b2b931ec0bcdaaa55daae0b4c.tar.bz2
pics dir changed
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,1519 +1,1519 @@
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
1086 } 1086 }
1087 1087
1088 const Tile* t; 1088 const Tile* t;
1089 for (int i=0; contains(at) && ((t=tile(at)) || i<n); ) { 1089 for (int i=0; contains(at) && ((t=tile(at)) || i<n); ) {
1090 if ( t ) { 1090 if ( t ) {
1091 if ( checkdict || words ) mainword += t->text(); 1091 if ( checkdict || words ) mainword += t->text();
1092 total += t->value(); 1092 total += t->value();
1093 connected = TRUE; 1093 connected = TRUE;
1094 } else { 1094 } else {
1095 QString sideword; 1095 QString sideword;
1096 QString tt; 1096 QString tt;
1097 if ( tiles[i]->isBlank() ) { 1097 if ( tiles[i]->isBlank() ) {
1098 if ( blankvalue ) 1098 if ( blankvalue )
1099 tt = blankvalue[bl++].text(); 1099 tt = blankvalue[bl++].text();
1100 } else { 1100 } else {
1101 tt = tiles[i]->text(); 1101 tt = tiles[i]->text();
1102 } 1102 }
1103 sideword=tt; 1103 sideword=tt;
1104 if ( checkdict || words ) mainword += tt; 1104 if ( checkdict || words ) mainword += tt;
1105 int side_mult = 1; 1105 int side_mult = 1;
1106 int tilevalue = bonussedValue(at,tiles[i]->value(),side_mult); 1106 int tilevalue = bonussedValue(at,tiles[i]->value(),side_mult);
1107 all_mult *= side_mult; 1107 all_mult *= side_mult;
1108 if ( !connected && isStart(at) ) 1108 if ( !connected && isStart(at) )
1109 connected = TRUE; 1109 connected = TRUE;
1110 total += tilevalue; 1110 total += tilevalue;
1111 int sidetotal = tilevalue; 1111 int sidetotal = tilevalue;
1112 { 1112 {
1113 QPoint side = at-otherd; 1113 QPoint side = at-otherd;
1114 1114
1115 while ( contains(side) && (t=tile(side)) ) { 1115 while ( contains(side) && (t=tile(side)) ) {
1116 sidetotal += t->value(); 1116 sidetotal += t->value();
1117 sideword.prepend(t->text()); 1117 sideword.prepend(t->text());
1118 side -= otherd; 1118 side -= otherd;
1119 } 1119 }
1120 } 1120 }
1121 { 1121 {
1122 QPoint side = at+otherd; 1122 QPoint side = at+otherd;
1123 while ( contains(side) && (t=tile(side)) ) { 1123 while ( contains(side) && (t=tile(side)) ) {
1124 sidetotal += t->value(); 1124 sidetotal += t->value();
1125 sideword.append(t->text()); 1125 sideword.append(t->text());
1126 side += otherd; 1126 side += otherd;
1127 } 1127 }
1128 } 1128 }
1129 if ( sideword.length() > 1 ) { 1129 if ( sideword.length() > 1 ) {
1130 if ( words ) 1130 if ( words )
1131 words->append(sideword); 1131 words->append(sideword);
1132 if ( checkdict && !Global::fixedDawg().contains(sideword) 1132 if ( checkdict && !Global::fixedDawg().contains(sideword)
1133 && !Global::dawg("WordGame").contains(sideword) ) 1133 && !Global::dawg("WordGame").contains(sideword) )
1134 return -1; 1134 return -1;
1135 totalsidetotal += sidetotal * side_mult; 1135 totalsidetotal += sidetotal * side_mult;
1136 connected = TRUE; 1136 connected = TRUE;
1137 } 1137 }
1138 i++; 1138 i++;
1139 } 1139 }
1140 at += d; 1140 at += d;
1141 } 1141 }
1142 1142
1143 if ( words ) 1143 if ( words )
1144 words->append(mainword); 1144 words->append(mainword);
1145 if ( checkdict && !Global::fixedDawg().contains(mainword) 1145 if ( checkdict && !Global::fixedDawg().contains(mainword)
1146 && !Global::dawg("WordGame").contains(mainword) ) 1146 && !Global::dawg("WordGame").contains(mainword) )
1147 return -1; 1147 return -1;
1148 1148
1149 if ( n == rack_tiles ) 1149 if ( n == rack_tiles )
1150 totalsidetotal += rack_tiles_bonus; 1150 totalsidetotal += rack_tiles_bonus;
1151 1151
1152 return connected ? totalsidetotal + total * all_mult : -1; 1152 return connected ? totalsidetotal + total * all_mult : -1;
1153} 1153}
1154 1154
1155QPoint Board::boardPos(const QPoint& p) const 1155QPoint Board::boardPos(const QPoint& p) const
1156{ 1156{
1157 return QPoint(p.x()/canvas()->tileWidth(), p.y()/canvas()->tileHeight()); 1157 return QPoint(p.x()/canvas()->tileWidth(), p.y()/canvas()->tileHeight());
1158} 1158}
1159 1159
1160void Board::contentsMouseReleaseEvent(QMouseEvent*) 1160void Board::contentsMouseReleaseEvent(QMouseEvent*)
1161{ 1161{
1162 if ( current_rack ) { 1162 if ( current_rack ) {
1163 } 1163 }
1164} 1164}
1165 1165
1166 1166
1167void Board::setRules(const QString& shapes, const int* effects) 1167void Board::setRules(const QString& shapes, const int* effects)
1168{ 1168{
1169 rule_shape=shapes; rule_effect=effects; 1169 rule_shape=shapes; rule_effect=effects;
1170 int i=0; 1170 int i=0;
1171 int maxre=0; 1171 int maxre=0;
1172 for (int y=0; y<yTiles(); y++) { 1172 for (int y=0; y<yTiles(); y++) {
1173 for (int x=0; x<xTiles(); x++) { 1173 for (int x=0; x<xTiles(); x++) {
1174 int re = shapes[i++]-'0'; 1174 int re = shapes[i++]-'0';
1175 if ( re > maxre ) maxre = re; 1175 if ( re > maxre ) maxre = re;
1176 canvas()->setTile(x,y,re); 1176 canvas()->setTile(x,y,re);
1177 } 1177 }
1178 } 1178 }
1179 rack_tiles_bonus=effects[maxre+1]; 1179 rack_tiles_bonus=effects[maxre+1];
1180} 1180}
1181 1181
1182void Board::unsetTile(const QPoint& p) 1182void Board::unsetTile(const QPoint& p)
1183{ 1183{
1184 delete item(p); 1184 delete item(p);
1185 grid[idx(p)] = 0; 1185 grid[idx(p)] = 0;
1186} 1186}
1187 1187
1188void Board::setTile(const QPoint& p, const Tile& t) 1188void Board::setTile(const QPoint& p, const Tile& t)
1189{ 1189{
1190 TileItem* it=item(p); 1190 TileItem* it=item(p);
1191 if ( !it ) { 1191 if ( !it ) {
1192 it = grid[idx(p)] = new TileItem(t,FALSE,canvas()); 1192 it = grid[idx(p)] = new TileItem(t,FALSE,canvas());
1193 it->move(p.x()*canvas()->tileWidth(), p.y()*canvas()->tileHeight()); 1193 it->move(p.x()*canvas()->tileWidth(), p.y()*canvas()->tileHeight());
1194 it->show(); 1194 it->show();
1195 } else { 1195 } else {
1196 it->setTile(t); 1196 it->setTile(t);
1197 } 1197 }
1198} 1198}
1199 1199
1200Rack::Rack(int ntiles, QWidget* parent) : QCanvasView( 1200Rack::Rack(int ntiles, QWidget* parent) : QCanvasView(
1201 new QCanvas(ntiles*TileItem::bigWidth(),TileItem::bigHeight()), 1201 new QCanvas(ntiles*TileItem::bigWidth(),TileItem::bigHeight()),
1202 parent), 1202 parent),
1203 item(ntiles) 1203 item(ntiles)
1204{ 1204{
1205 setLineWidth(1); 1205 setLineWidth(1);
1206 setFixedHeight(sizeHint().height()); 1206 setFixedHeight(sizeHint().height());
1207 n = 0; 1207 n = 0;
1208 for (int i=0; i<ntiles; i++) 1208 for (int i=0; i<ntiles; i++)
1209 item[i]=0; 1209 item[i]=0;
1210 setHScrollBarMode(AlwaysOff); 1210 setHScrollBarMode(AlwaysOff);
1211 setVScrollBarMode(AlwaysOff); 1211 setVScrollBarMode(AlwaysOff);
1212 canvas()->setBackgroundColor(gray); 1212 canvas()->setBackgroundColor(gray);
1213 dragging = 0; 1213 dragging = 0;
1214} 1214}
1215 1215
1216Rack::~Rack() 1216Rack::~Rack()
1217{ 1217{
1218 clear(); 1218 clear();
1219 delete canvas(); 1219 delete canvas();
1220} 1220}
1221 1221
1222QSize Rack::sizeHint() const 1222QSize Rack::sizeHint() const
1223{ 1223{
1224 return QSize(-1,TileItem::bigHeight()+2); 1224 return QSize(-1,TileItem::bigHeight()+2);
1225} 1225}
1226 1226
1227void Rack::clear() 1227void Rack::clear()
1228{ 1228{
1229 for (int i=0; i<n; i++) 1229 for (int i=0; i<n; i++)
1230 delete item[i]; 1230 delete item[i];
1231 n=0; 1231 n=0;
1232} 1232}
1233 1233
1234void Rack::writeConfig(Config& cfg) 1234void Rack::writeConfig(Config& cfg)
1235{ 1235{
1236 QStringList l; 1236 QStringList l;
1237 for (int i=0; i<n; i++) 1237 for (int i=0; i<n; i++)
1238 l.append(tile(i).key()); 1238 l.append(tile(i).key());
1239 cfg.writeEntry("Tiles",l,';'); 1239 cfg.writeEntry("Tiles",l,';');
1240} 1240}
1241 1241
1242void Rack::readConfig(Config& cfg) 1242void Rack::readConfig(Config& cfg)
1243{ 1243{
1244 clear(); 1244 clear();
1245 int x=0; 1245 int x=0;
1246 QStringList l = cfg.readListEntry("Tiles",';'); 1246 QStringList l = cfg.readListEntry("Tiles",';');
1247 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) { 1247 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) {
1248 TileItem *i = new TileItem(Tile(*it),TRUE,canvas()); 1248 TileItem *i = new TileItem(Tile(*it),TRUE,canvas());
1249 i->move(x++,0); 1249 i->move(x++,0);
1250 i->show(); 1250 i->show();
1251 item[n++] = i; 1251 item[n++] = i;
1252 } 1252 }
1253 layoutTiles(); 1253 layoutTiles();
1254} 1254}
1255 1255
1256static int cmp_tileitem(const void *a, const void *b) 1256static int cmp_tileitem(const void *a, const void *b)
1257{ 1257{
1258 const TileItem* ia = *(TileItem**)a; 1258 const TileItem* ia = *(TileItem**)a;
1259 const TileItem* ib = *(TileItem**)b; 1259 const TileItem* ib = *(TileItem**)b;
1260 return int(ia->x() - ib->x()); 1260 return int(ia->x() - ib->x());
1261} 1261}
1262 1262
1263void Rack::layoutTiles() 1263void Rack::layoutTiles()
1264{ 1264{
1265 int w = TileItem::bigWidth()+2; 1265 int w = TileItem::bigWidth()+2;
1266 1266
1267 if ( dragging ) dragging->moveBy(dragging_adj,0); 1267 if ( dragging ) dragging->moveBy(dragging_adj,0);
1268 qsort(item.data(), n, sizeof(TileItem*), cmp_tileitem); 1268 qsort(item.data(), n, sizeof(TileItem*), cmp_tileitem);
1269 if ( dragging ) dragging->moveBy(-dragging_adj,0); 1269 if ( dragging ) dragging->moveBy(-dragging_adj,0);
1270 1270
1271 for (int i=0; i<n ;i++) 1271 for (int i=0; i<n ;i++)
1272 if ( item[i] == dragging ) { 1272 if ( item[i] == dragging ) {
1273 item[i]->setZ(1); 1273 item[i]->setZ(1);
1274 } else { 1274 } else {
1275 item[i]->move(i*w, 0); 1275 item[i]->move(i*w, 0);
1276 item[i]->setZ(0); 1276 item[i]->setZ(0);
1277 } 1277 }
1278 canvas()->update(); 1278 canvas()->update();
1279} 1279}
1280 1280
1281void Rack::setBlanks(const Tile* bv) 1281void Rack::setBlanks(const Tile* bv)
1282{ 1282{
1283 for (int j=0; j<n; j++) { 1283 for (int j=0; j<n; j++) {
1284 Tile tt = item[j]->tile(); 1284 Tile tt = item[j]->tile();
1285 if ( tt.isBlank() ) { 1285 if ( tt.isBlank() ) {
1286 tt.setText(bv->text()); 1286 tt.setText(bv->text());
1287 item[j]->setTile(tt); 1287 item[j]->setTile(tt);
1288 bv++; 1288 bv++;
1289 } 1289 }
1290 } 1290 }
1291} 1291}
1292 1292
1293bool Rack::arrangeTiles(const Tile** s, int sn) 1293bool Rack::arrangeTiles(const Tile** s, int sn)
1294{ 1294{
1295 bool could = TRUE; 1295 bool could = TRUE;
1296 for (int j=0; j<n; j++) { 1296 for (int j=0; j<n; j++) {
1297 Tile tt = item[j]->tile(); 1297 Tile tt = item[j]->tile();
1298 int f=-1; 1298 int f=-1;
1299 for (int i=0; i<sn && f<0; i++) { 1299 for (int i=0; i<sn && f<0; i++) {
1300 if (s[i] && *s[i] == tt ) { 1300 if (s[i] && *s[i] == tt ) {
1301 s[i]=0; 1301 s[i]=0;
1302 f=i; 1302 f=i;
1303 } 1303 }
1304 } 1304 }
1305 if ( f >= 0 ) { 1305 if ( f >= 0 ) {
1306 item[j]->move(f-999,0); 1306 item[j]->move(f-999,0);
1307 } else { 1307 } else {
1308 could = FALSE; 1308 could = FALSE;
1309 } 1309 }
1310 } 1310 }
1311 layoutTiles(); 1311 layoutTiles();
1312 return could; 1312 return could;
1313} 1313}
1314 1314
1315void Rack::addTile(const Tile& t) 1315void Rack::addTile(const Tile& t)
1316{ 1316{
1317 TileItem *i = new TileItem(t,TRUE,canvas()); 1317 TileItem *i = new TileItem(t,TRUE,canvas());
1318 i->show(); 1318 i->show();
1319 item[n++] = i; 1319 item[n++] = i;
1320 layoutTiles(); 1320 layoutTiles();
1321} 1321}
1322 1322
1323void Rack::remove(Tile t) 1323void Rack::remove(Tile t)
1324{ 1324{
1325 for (int i=0; i<n ;i++) 1325 for (int i=0; i<n ;i++)
1326 if ( item[i]->tile() == t ) { 1326 if ( item[i]->tile() == t ) {
1327 remove(i); 1327 remove(i);
1328 return; 1328 return;
1329 } 1329 }
1330} 1330}
1331 1331
1332void Rack::remove(int i) 1332void Rack::remove(int i)
1333{ 1333{
1334 delete item[i]; 1334 delete item[i];
1335 n--; 1335 n--;
1336 for (;i<n;i++) 1336 for (;i<n;i++)
1337 item[i]=item[i+1]; 1337 item[i]=item[i+1];
1338 layoutTiles(); 1338 layoutTiles();
1339} 1339}
1340 1340
1341void Rack::resizeEvent(QResizeEvent* e) 1341void Rack::resizeEvent(QResizeEvent* e)
1342{ 1342{
1343 canvas()->resize(width()-frameWidth()*2,height()-frameWidth()*2); 1343 canvas()->resize(width()-frameWidth()*2,height()-frameWidth()*2);
1344 QCanvasView::resizeEvent(e); 1344 QCanvasView::resizeEvent(e);
1345} 1345}
1346 1346
1347void Rack::contentsMousePressEvent(QMouseEvent* e) 1347void Rack::contentsMousePressEvent(QMouseEvent* e)
1348{ 1348{
1349 if ( computerized() ) 1349 if ( computerized() )
1350 return; 1350 return;
1351 QCanvasItemList list = canvas()->collisions(e->pos()); 1351 QCanvasItemList list = canvas()->collisions(e->pos());
1352 if (list.count()) { 1352 if (list.count()) {
1353 dragging = list.first(); 1353 dragging = list.first();
1354 dragstart = e->pos()-QPoint(int(dragging->x()),int(dragging->y())); 1354 dragstart = e->pos()-QPoint(int(dragging->x()),int(dragging->y()));
1355 } else { 1355 } else {
1356 dragging = 0; 1356 dragging = 0;
1357 } 1357 }
1358} 1358}
1359 1359
1360void Rack::contentsMouseMoveEvent(QMouseEvent* e) 1360void Rack::contentsMouseMoveEvent(QMouseEvent* e)
1361{ 1361{
1362 if ( computerized() ) 1362 if ( computerized() )
1363 return; 1363 return;
1364 //int w = TileItem::bigWidth()+2; 1364 //int w = TileItem::bigWidth()+2;
1365 if ( dragging ) { 1365 if ( dragging ) {
1366 dragging_adj = TileItem::bigWidth()/2; 1366 dragging_adj = TileItem::bigWidth()/2;
1367 if ( dragging->x() > e->x()-dragstart.x() ) 1367 if ( dragging->x() > e->x()-dragstart.x() )
1368 dragging_adj = -dragging_adj; 1368 dragging_adj = -dragging_adj;
1369 dragging->move(e->x()-dragstart.x(),0); 1369 dragging->move(e->x()-dragstart.x(),0);
1370 layoutTiles(); 1370 layoutTiles();
1371 } 1371 }
1372} 1372}
1373 1373
1374void Rack::contentsMouseReleaseEvent(QMouseEvent* e) 1374void Rack::contentsMouseReleaseEvent(QMouseEvent* e)
1375{ 1375{
1376 if ( computerized() ) 1376 if ( computerized() )
1377 return; 1377 return;
1378 if ( dragging ) { 1378 if ( dragging ) {
1379 dragging=0; 1379 dragging=0;
1380 layoutTiles(); 1380 layoutTiles();
1381 } 1381 }
1382} 1382}
1383 1383
1384Tile::Tile(const QString& key) 1384Tile::Tile(const QString& key)
1385{ 1385{
1386 int a=key.find('@'); 1386 int a=key.find('@');
1387 txt = key.left(a); 1387 txt = key.left(a);
1388 val = key.mid(a+1).toInt(); 1388 val = key.mid(a+1).toInt();
1389 blank = txt.isEmpty(); 1389 blank = txt.isEmpty();
1390} 1390}
1391 1391
1392QString Tile::key() const 1392QString Tile::key() const
1393{ 1393{
1394 return txt+"@"+QString::number(val); 1394 return txt+"@"+QString::number(val);
1395} 1395}
1396 1396
1397Bag::Bag() 1397Bag::Bag()
1398{ 1398{
1399 tiles.setAutoDelete(TRUE); 1399 tiles.setAutoDelete(TRUE);
1400} 1400}
1401 1401
1402void Bag::writeConfig(Config& cfg) 1402void Bag::writeConfig(Config& cfg)
1403{ 1403{
1404 QStringList t; 1404 QStringList t;
1405 for (QListIterator<Tile> it(tiles); it; ++it) 1405 for (QListIterator<Tile> it(tiles); it; ++it)
1406 t.append((*it)->key()); 1406 t.append((*it)->key());
1407 cfg.writeEntry("Tiles",t,';'); 1407 cfg.writeEntry("Tiles",t,';');
1408} 1408}
1409 1409
1410void Bag::readConfig(Config& cfg) 1410void Bag::readConfig(Config& cfg)
1411{ 1411{
1412 tiles.clear(); 1412 tiles.clear();
1413 QStringList t = cfg.readListEntry("Tiles",';'); 1413 QStringList t = cfg.readListEntry("Tiles",';');
1414 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it ) 1414 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it )
1415 add(Tile(*it)); 1415 add(Tile(*it));
1416} 1416}
1417 1417
1418void Bag::add(const Tile& t) 1418void Bag::add(const Tile& t)
1419{ 1419{
1420 tiles.append(new Tile(t)); 1420 tiles.append(new Tile(t));
1421} 1421}
1422 1422
1423Tile Bag::takeRandom() 1423Tile Bag::takeRandom()
1424{ 1424{
1425 Tile* rp = tiles.take(random()%tiles.count()); 1425 Tile* rp = tiles.take(random()%tiles.count());
1426 Tile r=*rp; 1426 Tile r=*rp;
1427 return r; 1427 return r;
1428} 1428}
1429 1429
1430ScoreInfo::ScoreInfo( QWidget* parent, const char* name, WFlags fl ) : 1430ScoreInfo::ScoreInfo( QWidget* parent, const char* name, WFlags fl ) :
1431 QLabel("<P>",parent,name,fl) 1431 QLabel("<P>",parent,name,fl)
1432{ 1432{
1433 score=0; 1433 score=0;
1434 msgtimer = new QTimer(this); 1434 msgtimer = new QTimer(this);
1435 connect(msgtimer, SIGNAL(timeout()), this, SLOT(showScores())); 1435 connect(msgtimer, SIGNAL(timeout()), this, SLOT(showScores()));
1436 setBackgroundMode( PaletteButton ); 1436 setBackgroundMode( PaletteButton );
1437} 1437}
1438 1438
1439ScoreInfo::~ScoreInfo() 1439ScoreInfo::~ScoreInfo()
1440{ 1440{
1441 if ( score ) delete [] score; 1441 if ( score ) delete [] score;
1442} 1442}
1443 1443
1444void ScoreInfo::writeConfig(Config& cfg) 1444void ScoreInfo::writeConfig(Config& cfg)
1445{ 1445{
1446 QStringList l; 1446 QStringList l;
1447 for (int i=0; i<(int)names.count(); i++) 1447 for (int i=0; i<(int)names.count(); i++)
1448 l.append(QString::number(score[i])); 1448 l.append(QString::number(score[i]));
1449 cfg.writeEntry("Scores",l,';'); 1449 cfg.writeEntry("Scores",l,';');
1450} 1450}
1451 1451
1452void ScoreInfo::readConfig(Config& cfg) 1452void ScoreInfo::readConfig(Config& cfg)
1453{ 1453{
1454 QStringList l = cfg.readListEntry("Scores",';'); 1454 QStringList l = cfg.readListEntry("Scores",';');
1455 int i=0; 1455 int i=0;
1456 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it ) 1456 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it )
1457 score[i++]=(*it).toInt(); 1457 score[i++]=(*it).toInt();
1458 showScores(); 1458 showScores();
1459} 1459}
1460 1460
1461 1461
1462QSize ScoreInfo::sizeHint() const 1462QSize ScoreInfo::sizeHint() const
1463{ 1463{
1464 return QSize(QLabel::sizeHint().width(),fontMetrics().height()); 1464 return QSize(QLabel::sizeHint().width(),fontMetrics().height());
1465} 1465}
1466 1466
1467void ScoreInfo::init(const QStringList& namelist) 1467void ScoreInfo::init(const QStringList& namelist)
1468{ 1468{
1469 names = namelist; 1469 names = namelist;
1470 if ( score ) delete [] score; 1470 if ( score ) delete [] score;
1471 score = new int[names.count()]; 1471 score = new int[names.count()];
1472 memset(score,0,sizeof(int)*names.count()); 1472 memset(score,0,sizeof(int)*names.count());
1473 boldone = -1; 1473 boldone = -1;
1474 showScores(); 1474 showScores();
1475} 1475}
1476 1476
1477void ScoreInfo::addScore(int player, int change) 1477void ScoreInfo::addScore(int player, int change)
1478{ 1478{
1479 score[player] += change; 1479 score[player] += change;
1480 showScores(); 1480 showScores();
1481} 1481}
1482 1482
1483void ScoreInfo::setBoldOne(int b) 1483void ScoreInfo::setBoldOne(int b)
1484{ 1484{
1485 boldone=b; 1485 boldone=b;
1486 showScores(); 1486 showScores();
1487} 1487}
1488 1488
1489void ScoreInfo::showScores() 1489void ScoreInfo::showScores()
1490{ 1490{
1491 QString r="<p>"; 1491 QString r="<p>";
1492 int i=0; 1492 int i=0;
1493 //int spl=(names.count()+1)/2; // 2 lines 1493 //int spl=(names.count()+1)/2; // 2 lines
1494 for (QStringList::ConstIterator it=names.begin(); it!=names.end(); ) { 1494 for (QStringList::ConstIterator it=names.begin(); it!=names.end(); ) {
1495 if ( i==boldone ) r += "<b>"; 1495 if ( i==boldone ) r += "<b>";
1496 QString n = *it; 1496 QString n = *it;
1497 n.replace(QRegExp(":.*"),""); 1497 n.replace(QRegExp(":.*"),"");
1498 r += n; 1498 r += n;
1499 r += ":"; 1499 r += ":";
1500 r += QString::number(score[i]); 1500 r += QString::number(score[i]);
1501 if ( i==boldone ) r += "</b>"; 1501 if ( i==boldone ) r += "</b>";
1502 1502
1503 ++i; 1503 ++i;
1504 ++it; 1504 ++it;
1505 if ( it != names.end() ) 1505 if ( it != names.end() )
1506 r += " "; 1506 r += " ";
1507 } 1507 }
1508 setText(r); 1508 setText(r);
1509} 1509}
1510 1510
1511void ScoreInfo::showTemporaryScore(int amount) 1511void ScoreInfo::showTemporaryScore(int amount)
1512{ 1512{
1513 if ( amount < 0 ) 1513 if ( amount < 0 )
1514 setText(tr("<P>Invalid move")); 1514 setText(tr("<P>Invalid move"));
1515 else 1515 else
1516 setText(tr("<P>Score: ")+QString::number(amount)); 1516 setText(tr("<P>Score: ")+QString::number(amount));
1517 msgtimer->start(3000,TRUE); 1517 msgtimer->start(3000,TRUE);
1518} 1518}
1519 1519