summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/wordgame/wordgame.cpp2
1 files changed, 1 insertions, 1 deletions
diff --git a/noncore/games/wordgame/wordgame.cpp b/noncore/games/wordgame/wordgame.cpp
index 52e2be2..8cf92ef 100644
--- a/noncore/games/wordgame/wordgame.cpp
+++ b/noncore/games/wordgame/wordgame.cpp
@@ -1,1518 +1,1518 @@
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 <opie2/oresource.h> 24#include <opie2/oresource.h>
25 25
26#include <qpe/global.h> 26#include <qpe/global.h>
27#include <qpe/config.h> 27#include <qpe/config.h>
28 28
29#include <qapplication.h> 29#include <qapplication.h>
30#include <qmessagebox.h> 30#include <qmessagebox.h>
31#include <qcombobox.h> 31#include <qcombobox.h>
32#include <qdir.h> 32#include <qdir.h>
33#include <qlineedit.h> 33#include <qlineedit.h>
34#include <qpushbutton.h> 34#include <qpushbutton.h>
35#include <qtextstream.h> 35#include <qtextstream.h>
36#include <qtimer.h> 36#include <qtimer.h>
37#include <qtoolbar.h> 37#include <qtoolbar.h>
38#include <qtoolbutton.h> 38#include <qtoolbutton.h>
39#include <qvbox.h> 39#include <qvbox.h>
40#include <qwidgetstack.h> 40#include <qwidgetstack.h>
41#include <qlayout.h> 41#include <qlayout.h>
42 42
43#include <stdlib.h> 43#include <stdlib.h>
44#include <unistd.h> 44#include <unistd.h>
45#include <pwd.h> 45#include <pwd.h>
46#include <sys/types.h> 46#include <sys/types.h>
47 47
48enum RuleEffects { 48enum RuleEffects {
49 Multiplier=15, 49 Multiplier=15,
50 MultiplyAll=64, 50 MultiplyAll=64,
51 Start=128 51 Start=128
52}; 52};
53 53
54static int tile_smallw = 16; 54static int tile_smallw = 16;
55static int tile_smallh = 16; 55static int tile_smallh = 16;
56static int tile_bigw = 22; 56static int tile_bigw = 22;
57static int tile_bigh = 22; 57static int tile_bigh = 22;
58static int tile_stweak = -2; 58static int tile_stweak = -2;
59static int tile_btweak = -1; 59static int tile_btweak = -1;
60 60
61static const int rack_tiles=7; 61static const int rack_tiles=7;
62 62
63const char* sampleWGR= 63const char* sampleWGR=
64 "wordgame_shapes\n" 64 "wordgame_shapes\n"
65 "15 15\n" 65 "15 15\n"
66 "400001040100004\n" 66 "400001040100004\n"
67 "030000000000030\n" 67 "030000000000030\n"
68 "002002000200200\n" 68 "002002000200200\n"
69 "000300020003000\n" 69 "000300020003000\n"
70 "000020000020000\n" 70 "000020000020000\n"
71 "102001000100201\n" 71 "102001000100201\n"
72 "000000202000000\n" 72 "000000202000000\n"
73 "400200050002004\n" 73 "400200050002004\n"
74 "000000202000000\n" 74 "000000202000000\n"
75 "102001000100201\n" 75 "102001000100201\n"
76 "000020000020000\n" 76 "000020000020000\n"
77 "000300020003000\n" 77 "000300020003000\n"
78 "002002000200200\n" 78 "002002000200200\n"
79 "030000000000030\n" 79 "030000000000030\n"
80 "400001040100004\n" 80 "400001040100004\n"
81 "1 2 3 66 67 194 100 0\n" 81 "1 2 3 66 67 194 100 0\n"
82 "1 j 8\n" 82 "1 j 8\n"
83 "1 q 7\n" 83 "1 q 7\n"
84 "1 x 6\n" 84 "1 x 6\n"
85 "1 z 6\n" 85 "1 z 6\n"
86 "1 w 4\n" 86 "1 w 4\n"
87 "1 k 4\n" 87 "1 k 4\n"
88 "1 v 3\n" 88 "1 v 3\n"
89 "1 f 3\n" 89 "1 f 3\n"
90 "2 y 3\n" 90 "2 y 3\n"
91 "2 h 2\n" 91 "2 h 2\n"
92 "2 b 2\n" 92 "2 b 2\n"
93 "2 m 2\n" 93 "2 m 2\n"
94 "3 p 2\n" 94 "3 p 2\n"
95 "3 g 2\n" 95 "3 g 2\n"
96 "3 u 2\n" 96 "3 u 2\n"
97 "4 d 2\n" 97 "4 d 2\n"
98 "4 c 2\n" 98 "4 c 2\n"
99 "5 l 1\n" 99 "5 l 1\n"
100 "5 o 1\n" 100 "5 o 1\n"
101 "7 t 1\n" 101 "7 t 1\n"
102 "7 n 1\n" 102 "7 n 1\n"
103 "7 a 1\n" 103 "7 a 1\n"
104 "7 r 1\n" 104 "7 r 1\n"
105 "8 s 1\n" 105 "8 s 1\n"
106 "8 i 1\n" 106 "8 i 1\n"
107 "11 e 1\n" 107 "11 e 1\n"
108 "0\n"; 108 "0\n";
109 109
110WordGame::WordGame( QWidget* parent, const char* name, WFlags fl ) : 110WordGame::WordGame( QWidget* parent, const char* name, WFlags fl ) :
111 QMainWindow(parent, name, fl) 111 QMainWindow(parent, name, fl)
112{ 112{
113 if ( qApp->desktop()->width() < 240 ) { 113 if ( qApp->desktop()->width() < 240 ) {
114 tile_smallw = 10; 114 tile_smallw = 10;
115 tile_smallh = 10; 115 tile_smallh = 10;
116 tile_bigw = 16; 116 tile_bigw = 16;
117 tile_bigh = 16; 117 tile_bigh = 16;
118 tile_stweak = 0; 118 tile_stweak = 0;
119 tile_btweak = 0; 119 tile_btweak = 0;
120 } 120 }
121 121
122 setIcon( Opie::Core::OResource::loadPixmap( "wordgame/WordGame" ) ); 122 setIcon( Opie::Core::OResource::loadPixmap( "wordgame/WordGame" ) );
123 setCaption( tr("Word Game") ); 123 setCaption( tr("Word Game") );
124 124
125 setToolBarsMovable( FALSE ); 125 setToolBarsMovable( FALSE );
126 vbox = new QVBox(this); 126 vbox = new QVBox(this);
127 127
128 setCentralWidget(vbox); 128 setCentralWidget(vbox);
129 toolbar = new QToolBar(this); 129 toolbar = new QToolBar(this);
130 addToolBar(toolbar, Bottom); 130 addToolBar(toolbar, Bottom);
131 bool useBigIcon = qApp->desktop()->size().width() > 330; 131 bool useBigIcon = qApp->desktop()->size().width() > 330;
132 reset = new QToolButton(Opie::Core::OResource::loadPixmap("back", Opie::Core::OResource::SmallIcon), 132 reset = new QToolButton(Opie::Core::OResource::loadPixmap("back", Opie::Core::OResource::SmallIcon),
133 tr("Back"), "", this, SLOT(resetTurn()), toolbar); 133 tr("Back"), "", this, SLOT(resetTurn()), toolbar);
134 reset->setUsesBigPixmap( useBigIcon ); 134 reset->setUsesBigPixmap( useBigIcon );
135 done = new QToolButton(Opie::Core::OResource::loadPixmap("done", Opie::Core::OResource::SmallIcon), 135 done = new QToolButton(Opie::Core::OResource::loadPixmap("done", Opie::Core::OResource::SmallIcon),
136 tr("Done"), "", this, SLOT(endTurn()), toolbar); 136 tr("Done"), "", this, SLOT(endTurn()), toolbar);
137 done->setUsesBigPixmap( useBigIcon ); 137 done->setUsesBigPixmap( useBigIcon );
138 scoreinfo = new ScoreInfo(toolbar); 138 scoreinfo = new ScoreInfo(toolbar);
139 scoreinfo->setFont(QFont("Helvetica",10)); 139 scoreinfo->setFont(QFont("Helvetica",10));
140 QToolButton *btn = new QToolButton(Opie::Core::OResource::loadPixmap("finish", Opie::Core::OResource::SmallIcon), 140 QToolButton *btn = new QToolButton(Opie::Core::OResource::loadPixmap("finish", Opie::Core::OResource::SmallIcon),
141 tr("Close"), "", this, SLOT(endGame()), toolbar); 141 tr("Close"), "", this, SLOT(endGame()), toolbar);
142 btn->setUsesBigPixmap( useBigIcon ); 142 btn->setUsesBigPixmap( useBigIcon );
143 toolbar->setStretchableWidget(scoreinfo); 143 toolbar->setStretchableWidget(scoreinfo);
144 144
145 cpu = 0; 145 cpu = 0;
146 board = 0; 146 board = 0;
147 bag = 0; 147 bag = 0;
148 racks = 0; 148 racks = 0;
149 149
150 aiheart = new QTimer(this); 150 aiheart = new QTimer(this);
151 connect(aiheart, SIGNAL(timeout()), this, SLOT(think())); 151 connect(aiheart, SIGNAL(timeout()), this, SLOT(think()));
152 152
153 readConfig(); 153 readConfig();
154} 154}
155 155
156WordGame::~WordGame() 156WordGame::~WordGame()
157{ 157{
158 writeConfig(); 158 writeConfig();
159} 159}
160 160
161void WordGame::writeConfig() 161void WordGame::writeConfig()
162{ 162{
163 Config cfg("WordGame"); 163 Config cfg("WordGame");
164 cfg.setGroup("Game"); 164 cfg.setGroup("Game");
165 cfg.writeEntry("NameList",namelist,';'); 165 cfg.writeEntry("NameList",namelist,';');
166 cfg.writeEntry("CurrentPlayer",gameover ? 0 : player+1); 166 cfg.writeEntry("CurrentPlayer",gameover ? 0 : player+1);
167 if ( !gameover ) { 167 if ( !gameover ) {
168 cfg.writeEntry("Rules",rules); 168 cfg.writeEntry("Rules",rules);
169 bag->writeConfig(cfg); 169 bag->writeConfig(cfg);
170 board->writeConfig(cfg); 170 board->writeConfig(cfg);
171 scoreinfo->writeConfig(cfg); 171 scoreinfo->writeConfig(cfg);
172 } 172 }
173 for (int p=0; p<nplayers; p++) { 173 for (int p=0; p<nplayers; p++) {
174 cfg.setGroup("Player"+QString::number(p+1)); 174 cfg.setGroup("Player"+QString::number(p+1));
175 if ( gameover ) cfg.clearGroup(); else rack(p)->writeConfig(cfg); 175 if ( gameover ) cfg.clearGroup(); else rack(p)->writeConfig(cfg);
176 } 176 }
177} 177}
178 178
179void WordGame::readConfig() 179void WordGame::readConfig()
180{ 180{
181 Config cfg("WordGame"); 181 Config cfg("WordGame");
182 cfg.setGroup("Game"); 182 cfg.setGroup("Game");
183 int currentplayer = cfg.readNumEntry("CurrentPlayer",0); 183 int currentplayer = cfg.readNumEntry("CurrentPlayer",0);
184 QStringList pnames = cfg.readListEntry("NameList",';'); 184 QStringList pnames = cfg.readListEntry("NameList",';');
185 if ( currentplayer ) { 185 if ( currentplayer ) {
186 gameover = FALSE; 186 gameover = FALSE;
187 rules = cfg.readEntry("Rules"); 187 rules = cfg.readEntry("Rules");
188 if ( rules.find("x-wordgamerules") >= 0 ) { 188 if ( rules.find("x-wordgamerules") >= 0 ) {
189 // rules files moved 189 // rules files moved
190 rules = "Sample.rules"; 190 rules = "Sample.rules";
191 } 191 }
192 if ( loadRules(rules) ) { 192 if ( loadRules(rules) ) {
193 startGame(pnames); 193 startGame(pnames);
194 bag->readConfig(cfg); 194 bag->readConfig(cfg);
195 board->readConfig(cfg); 195 board->readConfig(cfg);
196 scoreinfo->readConfig(cfg); 196 scoreinfo->readConfig(cfg);
197 for (int p=0; p<nplayers; p++) { 197 for (int p=0; p<nplayers; p++) {
198 cfg.setGroup("Player"+QString::number(p+1)); 198 cfg.setGroup("Player"+QString::number(p+1));
199 rack(p)->readConfig(cfg); 199 rack(p)->readConfig(cfg);
200 } 200 }
201 player=currentplayer-1; 201 player=currentplayer-1;
202 readyRack(player); 202 readyRack(player);
203 return; 203 return;
204 } 204 }
205 } 205 }
206 // fall-back 206 // fall-back
207 openGameSelector(pnames); 207 openGameSelector(pnames);
208} 208}
209 209
210void WordGame::openGameSelector(const QStringList& initnames) 210void WordGame::openGameSelector(const QStringList& initnames)
211{ 211{
212 toolbar->hide(); 212 toolbar->hide();
213 gameover = FALSE; 213 gameover = FALSE;
214 214
215 delete board; 215 delete board;
216 board = 0; 216 board = 0;
217 delete racks; 217 delete racks;
218 racks = 0; 218 racks = 0;
219 219
220 delete cpu; 220 delete cpu;
221 cpu = 0; 221 cpu = 0;
222 222
223 newgame = new NewGame(vbox); 223 newgame = new NewGame(vbox);
224 224
225 //Rules rules(this); 225 //Rules rules(this);
226 //connect(game.editrules, SIGNAL(clicked()), &rules, SLOT(editRules())); 226 //connect(game.editrules, SIGNAL(clicked()), &rules, SLOT(editRules()));
227 //connect(&rules, SIGNAL(rulesChanged()), &game, SLOT(updateRuleSets())); 227 //connect(&rules, SIGNAL(rulesChanged()), &game, SLOT(updateRuleSets()));
228 struct passwd* n = getpwuid(getuid()); 228 struct passwd* n = getpwuid(getuid());
229 QString playername = n ? n->pw_name : ""; 229 QString playername = n ? n->pw_name : "";
230 if ( playername.isEmpty() ) { 230 if ( playername.isEmpty() ) {
231 playername = "Player"; 231 playername = "Player";
232 } 232 }
233 newgame->player0->changeItem(playername,0); 233 newgame->player0->changeItem(playername,0);
234 newgame->player1->setCurrentItem(1); 234 newgame->player1->setCurrentItem(1);
235 newgame->updateRuleSets(); 235 newgame->updateRuleSets();
236 newgame->show(); 236 newgame->show();
237 237
238 connect(newgame->buttonOk, SIGNAL(clicked()), this, SLOT(startGame())); 238 connect(newgame->buttonOk, SIGNAL(clicked()), this, SLOT(startGame()));
239} 239}
240 240
241void WordGame::startGame() 241void WordGame::startGame()
242{ 242{
243 rules = newgame->ruleslist[newgame->rules->currentItem()]; 243 rules = newgame->ruleslist[newgame->rules->currentItem()];
244 if ( loadRules(rules) ) { 244 if ( loadRules(rules) ) {
245 QStringList names; 245 QStringList names;
246 names.append(newgame->player0->currentText()); 246 names.append(newgame->player0->currentText());
247 names.append(newgame->player1->currentText()); 247 names.append(newgame->player1->currentText());
248 names.append(newgame->player2->currentText()); 248 names.append(newgame->player2->currentText());
249 names.append(newgame->player3->currentText()); 249 names.append(newgame->player3->currentText());
250 names.append(newgame->player4->currentText()); 250 names.append(newgame->player4->currentText());
251 names.append(newgame->player5->currentText()); 251 names.append(newgame->player5->currentText());
252 delete newgame; 252 delete newgame;
253 startGame(names); 253 startGame(names);
254 } else { 254 } else {
255 // error... 255 // error...
256 delete newgame; 256 delete newgame;
257 close(); 257 close();
258 } 258 }
259} 259}
260 260
261void WordGame::startGame(const QStringList& playerlist) 261void WordGame::startGame(const QStringList& playerlist)
262{ 262{
263 toolbar->show(); 263 toolbar->show();
264 racks = new QWidgetStack(vbox); 264 racks = new QWidgetStack(vbox);
265 racks->setFixedHeight(TileItem::bigHeight()+2); 265 racks->setFixedHeight(TileItem::bigHeight()+2);
266 namelist.clear(); 266 namelist.clear();
267 nplayers=0; 267 nplayers=0;
268 for (QStringList::ConstIterator it=playerlist.begin(); it!=playerlist.end(); ++it) 268 for (QStringList::ConstIterator it=playerlist.begin(); it!=playerlist.end(); ++it)
269 addPlayer(*it); 269 addPlayer(*it);
270 scoreinfo->init(namelist); 270 scoreinfo->init(namelist);
271 271
272 if ( nplayers ) { 272 if ( nplayers ) {
273 player=0; 273 player=0;
274 readyRack(player); 274 readyRack(player);
275 } 275 }
276 276
277 board->show(); 277 board->show();
278 racks->show(); 278 racks->show();
279} 279}
280 280
281bool WordGame::loadRules(const QString &name) 281bool WordGame::loadRules(const QString &name)
282{ 282{
283 QString filename = Global::applicationFileName( "wordgame", name ); 283 QString filename = Global::applicationFileName( "wordgame", name );
284 QFile file( filename ); 284 QFile file( filename );
285 if ( !file.open( IO_ReadOnly ) ) 285 if ( !file.open( IO_ReadOnly ) )
286 return FALSE; 286 return FALSE;
287 287
288 QTextStream ts( &file ); 288 QTextStream ts( &file );
289 289
290 QString title = name; 290 QString title = name;
291 title.truncate( title.length() - 6 ); 291 title.truncate( title.length() - 6 );
292 //setCaption( title ); 292 //setCaption( title );
293 293
294 QString shapepixmap; 294 QString shapepixmap;
295 ts >> shapepixmap; 295 ts >> shapepixmap;
296 int htiles,vtiles; 296 int htiles,vtiles;
297 ts >> htiles >> vtiles; 297 ts >> htiles >> vtiles;
298 298
299 if ( htiles < 3 || vtiles < 3 ) 299 if ( htiles < 3 || vtiles < 3 )
300 return FALSE; 300 return FALSE;
301 301
302 QString rule_shapes; 302 QString rule_shapes;
303 for (int i=0; i<vtiles; i++) { 303 for (int i=0; i<vtiles; i++) {
304 QString line; 304 QString line;
305 ts >> line; 305 ts >> line;
306 rule_shapes += line; 306 rule_shapes += line;
307 } 307 }
308 static int rule_effects[12]; 308 static int rule_effects[12];
309 int re=0,e; 309 int re=0,e;
310 ts >> e; 310 ts >> e;
311 while ( e && re < 10 ) { 311 while ( e && re < 10 ) {
312 rule_effects[re] = e; 312 rule_effects[re] = e;
313 if ( re++ < 10 ) ts >> e; 313 if ( re++ < 10 ) ts >> e;
314 } 314 }
315 315
316 QImage shim = Opie::Core::OResource::loadImage("wordgame/wordgame_shapes"); 316 QImage shim = Opie::Core::OResource::loadImage("wordgame/wordgame_shapes");
317 shim = shim.smoothScale((re-1)*TileItem::smallWidth(),TileItem::smallHeight()); 317 shim = shim.smoothScale((re-1)*TileItem::smallWidth(),TileItem::smallHeight());
318 QPixmap bgshapes; 318 QPixmap bgshapes;
319 bgshapes.convertFromImage(shim); 319 bgshapes.convertFromImage(shim);
320 320
321 rule_effects[re++] = 100; // default bonus 321 rule_effects[re++] = 100; // default bonus
322 board = new Board(bgshapes, htiles, vtiles, vbox); 322 board = new Board(bgshapes, htiles, vtiles, vbox);
323 board->setRules(rule_shapes, rule_effects); 323 board->setRules(rule_shapes, rule_effects);
324 connect(board, SIGNAL(temporaryScore(int)), scoreinfo, SLOT(showTemporaryScore(int))); 324 connect(board, SIGNAL(temporaryScore(int)), scoreinfo, SLOT(showTemporaryScore(int)));
325 325
326 bag = new Bag; 326 bag = new Bag;
327 327
328 int count; 328 int count;
329 ts >> count; 329 ts >> count;
330 while ( count ) { 330 while ( count ) {
331 QString text; 331 QString text;
332 int value; 332 int value;
333 ts >> text >> value; 333 ts >> text >> value;
334 if ( text == "_" ) 334 if ( text == "_" )
335 text = ""; 335 text = "";
336 336
337 Tile t(text, value); 337 Tile t(text, value);
338 for (int n=count; n--; ) 338 for (int n=count; n--; )
339 bag->add(t); 339 bag->add(t);
340 340
341 ts >> count; 341 ts >> count;
342 } 342 }
343 343
344 return TRUE; 344 return TRUE;
345} 345}
346 346
347 347
348NewGame::NewGame(QWidget* parent) : 348NewGame::NewGame(QWidget* parent) :
349 NewGameBase(parent) 349 NewGameBase(parent)
350{ 350{
351} 351}
352 352
353void NewGame::updateRuleSets() 353void NewGame::updateRuleSets()
354{ 354{
355 rules->clear(); 355 rules->clear();
356 356
357 QString rulesDir = Global::applicationFileName( "wordgame", "" ); 357 QString rulesDir = Global::applicationFileName( "wordgame", "" );
358 QDir dir( rulesDir, "*.rules" ); 358 QDir dir( rulesDir, "*.rules" );
359 ruleslist = dir.entryList(); 359 ruleslist = dir.entryList();
360 if ( ruleslist.isEmpty() ) { 360 if ( ruleslist.isEmpty() ) {
361 // Provide a sample 361 // Provide a sample
362 QFile file( rulesDir + "Sample.rules" ); 362 QFile file( rulesDir + "Sample.rules" );
363 if ( file.open( IO_WriteOnly ) ) { 363 if ( file.open( IO_WriteOnly ) ) {
364 file.writeBlock( sampleWGR, strlen(sampleWGR) ); 364 file.writeBlock( sampleWGR, strlen(sampleWGR) );
365 file.close(); 365 file.close();
366 updateRuleSets(); 366 updateRuleSets();
367 } 367 }
368 return; 368 return;
369 } 369 }
370 int newest=0; 370 int newest=0;
371 int newest_age=INT_MAX; 371 int newest_age=INT_MAX;
372 QDateTime now = QDateTime::currentDateTime(); 372 QDateTime now = QDateTime::currentDateTime();
373 QStringList::Iterator it; 373 QStringList::Iterator it;
374 for ( it = ruleslist.begin(); it != ruleslist.end(); ++it ) { 374 for ( it = ruleslist.begin(); it != ruleslist.end(); ++it ) {
375 QFileInfo fi((*it)); 375 QFileInfo fi((*it));
376 int age = fi.lastModified().secsTo(now); 376 int age = fi.lastModified().secsTo(now);
377 QString name = *it; 377 QString name = *it;
378 name.truncate( name.length()-6 ); // remove extension 378 name.truncate( name.length()-6 ); // remove extension
379 rules->insertItem( name ); 379 rules->insertItem( name );
380 if ( age < newest_age ) { 380 if ( age < newest_age ) {
381 newest_age = age; 381 newest_age = age;
382 newest = rules->count()-1; 382 newest = rules->count()-1;
383 } 383 }
384 } 384 }
385 rules->setCurrentItem(newest); 385 rules->setCurrentItem(newest);
386} 386}
387 387
388Rules::Rules(QWidget* parent) : 388Rules::Rules(QWidget* parent) :
389 RulesBase(parent,0,TRUE) 389 RulesBase(parent,0,TRUE)
390{ 390{
391} 391}
392 392
393void Rules::editRules() 393void Rules::editRules()
394{ 394{
395 if ( exec() ) { 395 if ( exec() ) {
396 // ### create a new set of rules 396 // ### create a new set of rules
397 emit rulesChanged(); 397 emit rulesChanged();
398 } 398 }
399} 399}
400 400
401void Rules::deleteRuleSet() 401void Rules::deleteRuleSet()
402{ 402{
403 // ### delete existing rule set 403 // ### delete existing rule set
404 emit rulesChanged(); 404 emit rulesChanged();
405} 405}
406 406
407void WordGame::addPlayer(const QString& name) 407void WordGame::addPlayer(const QString& name)
408{ 408{
409 if ( !name.isEmpty() ) { 409 if ( !name.isEmpty() ) {
410 int colon = name.find(':'); 410 int colon = name.find(':');
411 int cpu = (colon >=0 && name.left(2) == "AI") ? name.mid(2,1).toInt() : 0; 411 int cpu = (colon >=0 && name.left(2) == "AI") ? name.mid(2,1).toInt() : 0;
412 addPlayer(name,cpu); 412 addPlayer(name,cpu);
413 } 413 }
414} 414}
415 415
416void WordGame::addPlayer(const QString& name, int cpu) 416void WordGame::addPlayer(const QString& name, int cpu)
417{ 417{
418 Rack* r = new Rack(rack_tiles,racks); 418 Rack* r = new Rack(rack_tiles,racks);
419 r->setPlayerName(name); 419 r->setPlayerName(name);
420 r->setComputerization(cpu); 420 r->setComputerization(cpu);
421 racks->addWidget(r, nplayers); 421 racks->addWidget(r, nplayers);
422 refillRack(nplayers); 422 refillRack(nplayers);
423 namelist.append(name); 423 namelist.append(name);
424 424
425 ++nplayers; 425 ++nplayers;
426} 426}
427 427
428void WordGame::nextPlayer() 428void WordGame::nextPlayer()
429{ 429{
430 if ( !refillRack(player) ) { 430 if ( !refillRack(player) ) {
431 endGame(); 431 endGame();
432 } else { 432 } else {
433 player = (player+1)%nplayers; 433 player = (player+1)%nplayers;
434 scoreinfo->setBoldOne(player); 434 scoreinfo->setBoldOne(player);
435 readyRack(player); 435 readyRack(player);
436 } 436 }
437} 437}
438 438
439bool WordGame::mayEndGame() 439bool WordGame::mayEndGame()
440{ 440{
441 int out=-1; 441 int out=-1;
442 int i; 442 int i;
443 for (i=0; i<nplayers; i++) 443 for (i=0; i<nplayers; i++)
444 if ( !rack(i)->count() ) 444 if ( !rack(i)->count() )
445 out = i; 445 out = i;
446 if ( out<0 ) { 446 if ( out<0 ) {
447 if ( QMessageBox::warning(this,tr("End game"), 447 if ( QMessageBox::warning(this,tr("End game"),
448 tr("Do you want to end the game early?"), 448 tr("Do you want to end the game early?"),
449 tr("Yes"), tr("No") )!=0 ) 449 tr("Yes"), tr("No") )!=0 )
450 { 450 {
451 return FALSE; 451 return FALSE;
452 } 452 }
453 } 453 }
454 return TRUE; 454 return TRUE;
455} 455}
456 456
457void WordGame::endGame() 457void WordGame::endGame()
458{ 458{
459 if ( gameover ) { 459 if ( gameover ) {
460 close(); 460 close();
461 return; 461 return;
462 } 462 }
463 463
464 if ( !mayEndGame() ) 464 if ( !mayEndGame() )
465 return; 465 return;
466 int out=-1; 466 int out=-1;
467 int totalleft=0; 467 int totalleft=0;
468 int i; 468 int i;
469 for (i=0; i<nplayers; i++) { 469 for (i=0; i<nplayers; i++) {
470 Rack* r = rack(i); 470 Rack* r = rack(i);
471 int c = r->count(); 471 int c = r->count();
472 if ( c ) { 472 if ( c ) {
473 int lose=0; 473 int lose=0;
474 for ( int j=0; j<c; j++ ) 474 for ( int j=0; j<c; j++ )
475 lose += r->tileRef(j)->value(); 475 lose += r->tileRef(j)->value();
476 totalleft += lose; 476 totalleft += lose;
477 scoreinfo->addScore(i,-lose); 477 scoreinfo->addScore(i,-lose);
478 } else { 478 } else {
479 out = i; 479 out = i;
480 } 480 }
481 } 481 }
482 int highest=0; 482 int highest=0;
483 int winner=0; 483 int winner=0;
484 for (i=0; i<nplayers; i++) { 484 for (i=0; i<nplayers; i++) {
485 int s = scoreinfo->playerScore(i); 485 int s = scoreinfo->playerScore(i);
486 if ( s > highest ) { 486 if ( s > highest ) {
487 highest = s; 487 highest = s;
488 winner = i; 488 winner = i;
489 } 489 }
490 } 490 }
491 if ( out >= 0 ) 491 if ( out >= 0 )
492 scoreinfo->addScore(out,totalleft); 492 scoreinfo->addScore(out,totalleft);
493 scoreinfo->setBoldOne(winner); 493 scoreinfo->setBoldOne(winner);
494 gameover = TRUE; 494 gameover = TRUE;
495 done->setEnabled(TRUE); 495 done->setEnabled(TRUE);
496 reset->setEnabled(FALSE); 496 reset->setEnabled(FALSE);
497} 497}
498 498
499void WordGame::endTurn() 499void WordGame::endTurn()
500{ 500{
501 if ( gameover ) { 501 if ( gameover ) {
502 openGameSelector(namelist); 502 openGameSelector(namelist);
503 } else { 503 } else {
504 if ( board->checkTurn() ) { 504 if ( board->checkTurn() ) {
505 if ( board->turnScore() >= 0 ) { 505 if ( board->turnScore() >= 0 ) {
506 scoreinfo->addScore(player,board->turnScore()); 506 scoreinfo->addScore(player,board->turnScore());
507 board->finalizeTurn(); 507 board->finalizeTurn();
508 } else { 508 } else {
509 QApplication::beep(); 509 QApplication::beep();
510 } 510 }
511 nextPlayer(); 511 nextPlayer();
512 } 512 }
513 } 513 }
514} 514}
515 515
516void WordGame::resetTurn() 516void WordGame::resetTurn()
517{ 517{
518 board->resetRack(); 518 board->resetRack();
519} 519}
520 520
521void WordGame::passTurn() 521void WordGame::passTurn()
522{ 522{
523 // ######## trade? 523 // ######## trade?
524 nextPlayer(); 524 nextPlayer();
525} 525}
526 526
527bool WordGame::refillRack(int i) 527bool WordGame::refillRack(int i)
528{ 528{
529 Rack* r = rack(i); 529 Rack* r = rack(i);
530 while ( !bag->isEmpty() && !r->isFull() ) { 530 while ( !bag->isEmpty() && !r->isFull() ) {
531 r->addTile(bag->takeRandom()); 531 r->addTile(bag->takeRandom());
532 } 532 }
533 return r->count() != 0; 533 return r->count() != 0;
534} 534}
535 535
536void WordGame::readyRack(int i) 536void WordGame::readyRack(int i)
537{ 537{
538 Rack* r = rack(i); 538 Rack* r = rack(i);
539 racks->raiseWidget(i); 539 racks->raiseWidget(i);
540 board->setCurrentRack(r); 540 board->setCurrentRack(r);
541 541
542 done->setEnabled( !r->computerized() ); 542 done->setEnabled( !r->computerized() );
543 reset->setEnabled( !r->computerized() ); 543 reset->setEnabled( !r->computerized() );
544 544
545 if ( r->computerized() ) { 545 if ( r->computerized() ) {
546 cpu = new ComputerPlayer(board, r); 546 cpu = new ComputerPlayer(board, r);
547 aiheart->start(0); 547 aiheart->start(0);
548 } 548 }
549} 549}
550 550
551Rack* WordGame::rack(int i) const 551Rack* WordGame::rack(int i) const
552{ 552{
553 return (Rack*)racks->widget(i); 553 return (Rack*)racks->widget(i);
554} 554}
555 555
556void WordGame::think() 556void WordGame::think()
557{ 557{
558 if ( !cpu->step() ) { 558 if ( !cpu->step() ) {
559 delete cpu; 559 delete cpu;
560 cpu = 0; 560 cpu = 0;
561 aiheart->stop(); 561 aiheart->stop();
562 if ( board->turnScore() < 0 ) 562 if ( board->turnScore() < 0 )
563 passTurn(); 563 passTurn();
564 else 564 else
565 endTurn(); 565 endTurn();
566 } 566 }
567} 567}
568 568
569ComputerPlayer::ComputerPlayer(Board* b, Rack* r) : 569ComputerPlayer::ComputerPlayer(Board* b, Rack* r) :
570 board(b), rack(r), best(new const Tile*[rack_tiles]), 570 board(b), rack(r), best(new const Tile*[rack_tiles]),
571 best_blankvalues(new Tile[rack_tiles]) 571 best_blankvalues(new Tile[rack_tiles])
572{ 572{
573 best_score = -1; 573 best_score = -1;
574 across=FALSE; 574 across=FALSE;
575 dict=0; 575 dict=0;
576} 576}
577 577
578ComputerPlayer::~ComputerPlayer() 578ComputerPlayer::~ComputerPlayer()
579{ 579{
580 delete [] best; 580 delete [] best;
581 delete [] best_blankvalues; 581 delete [] best_blankvalues;
582} 582}
583 583
584bool ComputerPlayer::step() 584bool ComputerPlayer::step()
585{ 585{
586 const QDawg::Node* root = dict ? Global::dawg("WordGame").root() 586 const QDawg::Node* root = dict ? Global::dawg("WordGame").root()
587 : Global::fixedDawg().root(); 587 : Global::fixedDawg().root();
588 QPoint d = across ? QPoint(1,0) : QPoint(0,1); 588 QPoint d = across ? QPoint(1,0) : QPoint(0,1);
589 const Tile* tiles[99]; // ### max board size 589 const Tile* tiles[99]; // ### max board size
590 uchar nletter[4095]; // QDawg only handles 0..4095 590 uchar nletter[4095]; // QDawg only handles 0..4095
591 memset(nletter,0,4096); 591 memset(nletter,0,4095);
592 for (int i=0; i<rack->count(); i++) { 592 for (int i=0; i<rack->count(); i++) {
593 const Tile* r = rack->tileRef(i); 593 const Tile* r = rack->tileRef(i);
594 if ( r->isBlank() ) 594 if ( r->isBlank() )
595 nletter[0]++; 595 nletter[0]++;
596 else 596 else
597 nletter[r->text()[0].unicode()]++; 597 nletter[r->text()[0].unicode()]++;
598 } 598 }
599 Tile blankvalues[99]; // ### max blanks 599 Tile blankvalues[99]; // ### max blanks
600 findBest(current, d, root, 0, nletter, tiles, 0, blankvalues, 0); 600 findBest(current, d, root, 0, nletter, tiles, 0, blankvalues, 0);
601 if ( ++current.rx() == board->xTiles() ) { 601 if ( ++current.rx() == board->xTiles() ) {
602 current.rx() = 0; 602 current.rx() = 0;
603 if ( ++current.ry() == board->yTiles() ) { 603 if ( ++current.ry() == board->yTiles() ) {
604 if ( across ) { 604 if ( across ) {
605 if ( dict == 1 ) { 605 if ( dict == 1 ) {
606 if ( best_score >= 0 ) { 606 if ( best_score >= 0 ) {
607 rack->arrangeTiles(best,best_n); 607 rack->arrangeTiles(best,best_n);
608 rack->setBlanks(best_blankvalues); 608 rack->setBlanks(best_blankvalues);
609 board->scoreTurn(best_start, best_n, best_dir); 609 board->scoreTurn(best_start, best_n, best_dir);
610 board->showTurn(); 610 board->showTurn();
611 } 611 }
612 return FALSE; 612 return FALSE;
613 } 613 }
614 dict++; 614 dict++;
615 across = FALSE; 615 across = FALSE;
616 current = QPoint(0,0); 616 current = QPoint(0,0);
617 } else { 617 } else {
618 across = TRUE; 618 across = TRUE;
619 current = QPoint(0,0); 619 current = QPoint(0,0);
620 } 620 }
621 } 621 }
622 } 622 }
623 return TRUE; 623 return TRUE;
624} 624}
625 625
626void ComputerPlayer::findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar* nletter, const Tile** tiles, int n, Tile* blankvalues, int blused) 626void ComputerPlayer::findBest(QPoint at, const QPoint& d, const QDawg::Node* node, ulong used, uchar* nletter, const Tile** tiles, int n, Tile* blankvalues, int blused)
627{ 627{
628 if ( !node ) 628 if ( !node )
629 return; 629 return;
630 QChar l = node->letter(); 630 QChar l = node->letter();
631 const Tile* cur = board->tile(at); 631 const Tile* cur = board->tile(at);
632 if ( cur ) { 632 if ( cur ) {
633 if ( cur->text()[0] == l ) { 633 if ( cur->text()[0] == l ) {
634 bool nextok = board->contains(at+d); 634 bool nextok = board->contains(at+d);
635 if ( node->isWord() && n && (!nextok || !board->tile(at+d)) ) 635 if ( node->isWord() && n && (!nextok || !board->tile(at+d)) )
636 noteChoice(tiles,n,d,blankvalues,blused); 636 noteChoice(tiles,n,d,blankvalues,blused);
637 if ( nextok ) 637 if ( nextok )
638 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused); 638 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused);
639 // #### text()[1]... 639 // #### text()[1]...
640 } 640 }
641 } else { 641 } else {
642 if ( nletter[l.unicode()] || nletter[0] ) { 642 if ( nletter[l.unicode()] || nletter[0] ) {
643 int rc = rack->count(); 643 int rc = rack->count();
644 ulong msk = 1; 644 ulong msk = 1;
645 for ( int x=0; x<rc; x++ ) { 645 for ( int x=0; x<rc; x++ ) {
646 if ( !(used&msk) ) { 646 if ( !(used&msk) ) {
647 const Tile* t = rack->tileRef(x); 647 const Tile* t = rack->tileRef(x);
648 if ( t->isBlank() || t->text() == l ) { // #### multi-char value()s 648 if ( t->isBlank() || t->text() == l ) { // #### multi-char value()s
649 bool nextok = board->contains(at+d); 649 bool nextok = board->contains(at+d);
650 tiles[n++] = t; 650 tiles[n++] = t;
651 if ( t->isBlank() ) 651 if ( t->isBlank() )
652 blankvalues[blused++] = Tile(l,0); 652 blankvalues[blused++] = Tile(l,0);
653 if ( node->isWord() && (!nextok || !board->tile(at+d)) ) 653 if ( node->isWord() && (!nextok || !board->tile(at+d)) )
654 noteChoice(tiles,n,d,blankvalues,blused); 654 noteChoice(tiles,n,d,blankvalues,blused);
655 used |= msk; // mark 655 used |= msk; // mark
656 nletter[t->text()[0].unicode()]--; 656 nletter[t->text()[0].unicode()]--;
657 if ( nextok ) 657 if ( nextok )
658 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused); 658 findBest(at+d, d, node->jump(), used, nletter, tiles, n, blankvalues, blused);
659 n--; 659 n--;
660 nletter[t->text()[0].unicode()]++; 660 nletter[t->text()[0].unicode()]++;
661 if ( t->isBlank() ) { 661 if ( t->isBlank() ) {
662 // keep looking 662 // keep looking
663 blused--; 663 blused--;
664 used &= ~msk; // unmark 664 used &= ~msk; // unmark
665 } else { 665 } else {
666 break; 666 break;
667 } 667 }
668 } 668 }
669 } 669 }
670 msk <<= 1; 670 msk <<= 1;
671 } 671 }
672 } 672 }
673 // #### text()[1]... 673 // #### text()[1]...
674 } 674 }
675 findBest(at, d, node->next(), used, nletter, tiles, n, blankvalues, blused); 675 findBest(at, d, node->next(), used, nletter, tiles, n, blankvalues, blused);
676} 676}
677 677
678void ComputerPlayer::noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused) 678void ComputerPlayer::noteChoice(const Tile** tiles, int n, const QPoint& d, const Tile* blankvalues, int blused)
679{ 679{
680 int s = board->score(current, tiles, n, blankvalues, d, TRUE, 0); 680 int s = board->score(current, tiles, n, blankvalues, d, TRUE, 0);
681/* 681/*
682if (s>0 || current==QPoint(5,1)){ 682if (s>0 || current==QPoint(5,1)){
683QString st; 683QString st;
684for ( int i=0; i<n; i++ ) 684for ( int i=0; i<n; i++ )
685 st += tiles[i]->text(); 685 st += tiles[i]->text();
686odebug << "" << current.x() << "," << current.y() << ": " << st.latin1() << " (" << n << ") for " << s << "" << oendl; 686odebug << "" << current.x() << "," << current.y() << ": " << st.latin1() << " (" << n << ") for " << s << "" << oendl;
687} 687}
688*/ 688*/
689 if ( s > best_score ) { 689 if ( s > best_score ) {
690 int i; 690 int i;
691 for ( i=0; i<n; i++ ) 691 for ( i=0; i<n; i++ )
692 best[i] = tiles[i]; 692 best[i] = tiles[i];
693 for ( i=0; i<blused; i++ ) 693 for ( i=0; i<blused; i++ )
694 best_blankvalues[i] = blankvalues[i]; 694 best_blankvalues[i] = blankvalues[i];
695 best_n = n; 695 best_n = n;
696 best_blused = blused; 696 best_blused = blused;
697 best_score = s; 697 best_score = s;
698 best_dir = d; 698 best_dir = d;
699 best_start = current; 699 best_start = current;
700 } 700 }
701} 701}
702 702
703int TileItem::smallWidth() 703int TileItem::smallWidth()
704{ 704{
705 return tile_smallw; 705 return tile_smallw;
706} 706}
707 707
708int TileItem::smallHeight() 708int TileItem::smallHeight()
709{ 709{
710 return tile_smallh; 710 return tile_smallh;
711} 711}
712 712
713int TileItem::bigWidth() 713int TileItem::bigWidth()
714{ 714{
715 return tile_bigw; 715 return tile_bigw;
716} 716}
717 717
718int TileItem::bigHeight() 718int TileItem::bigHeight()
719{ 719{
720 return tile_bigh; 720 return tile_bigh;
721} 721}
722 722
723void TileItem::setState( State state ) 723void TileItem::setState( State state )
724{ 724{
725 hide(); 725 hide();
726 s = state; 726 s = state;
727 show(); // ### use update() in Qt 3.0 727 show(); // ### use update() in Qt 3.0
728} 728}
729 729
730void TileItem::setTile(const Tile& tile) 730void TileItem::setTile(const Tile& tile)
731{ 731{
732 hide(); 732 hide();
733 t = tile; 733 t = tile;
734 show(); // ### use update() in Qt 3.0 734 show(); // ### use update() in Qt 3.0
735} 735}
736 736
737void TileItem::setBig(bool b) 737void TileItem::setBig(bool b)
738{ 738{
739 big = b; 739 big = b;
740} 740}
741 741
742void TileItem::drawShape(QPainter& p) 742void TileItem::drawShape(QPainter& p)
743{ 743{
744 static QFont *value_font=0; 744 static QFont *value_font=0;
745 static QFont *big_font=0; 745 static QFont *big_font=0;
746 static QFont *small_font=0; 746 static QFont *small_font=0;
747 if ( !value_font ) { 747 if ( !value_font ) {
748 value_font = new QFont("helvetica",8); 748 value_font = new QFont("helvetica",8);
749 if ( TileItem::bigWidth() < 20 ) { 749 if ( TileItem::bigWidth() < 20 ) {
750 big_font = new QFont("helvetica",12); 750 big_font = new QFont("helvetica",12);
751 small_font = new QFont("helvetica",8); 751 small_font = new QFont("helvetica",8);
752 } else { 752 } else {
753 big_font = new QFont("smoothtimes",17); 753 big_font = new QFont("smoothtimes",17);
754 small_font = new QFont("smoothtimes",10); 754 small_font = new QFont("smoothtimes",10);
755 } 755 }
756 } 756 }
757 757
758 QRect area(x(),y(),width(),height()); 758 QRect area(x(),y(),width(),height());
759 p.setBrush(s == Floating ? yellow/*lightGray*/ : white); 759 p.setBrush(s == Floating ? yellow/*lightGray*/ : white);
760 p.drawRect(area); 760 p.drawRect(area);
761 if ( big ) { 761 if ( big ) {
762 p.setFont(*value_font); 762 p.setFont(*value_font);
763 QString n = QString::number(t.value()); 763 QString n = QString::number(t.value());
764 int w = p.fontMetrics().width('1'); 764 int w = p.fontMetrics().width('1');
765 int h = p.fontMetrics().height(); 765 int h = p.fontMetrics().height();
766 w *= n.length(); 766 w *= n.length();
767 QRect valuearea(x()+width()-w-1,y()+height()-h,w,h); 767 QRect valuearea(x()+width()-w-1,y()+height()-h,w,h);
768 p.drawText(valuearea,AlignCenter,n); 768 p.drawText(valuearea,AlignCenter,n);
769 p.setFont(*big_font); 769 p.setFont(*big_font);
770 area = QRect(x(),y()+tile_btweak,width()-4,height()-1); 770 area = QRect(x(),y()+tile_btweak,width()-4,height()-1);
771 } else { 771 } else {
772 p.setFont(*small_font); 772 p.setFont(*small_font);
773 area = QRect(x()+1+tile_stweak,y()+1,width(),height()-3); 773 area = QRect(x()+1+tile_stweak,y()+1,width(),height()-3);
774 } 774 }
775 if ( t.value() == 0 ) 775 if ( t.value() == 0 )
776 p.setPen(darkGray); 776 p.setPen(darkGray);
777 p.drawText(area,AlignCenter,t.text().upper()); 777 p.drawText(area,AlignCenter,t.text().upper());
778} 778}
779 779
780Board::Board(QPixmap bgshapes, int w, int h, QWidget* parent) : 780Board::Board(QPixmap bgshapes, int w, int h, QWidget* parent) :
781 QCanvasView(new QCanvas(bgshapes,w,h, TileItem::smallWidth(), TileItem::smallHeight()), 781 QCanvasView(new QCanvas(bgshapes,w,h, TileItem::smallWidth(), TileItem::smallHeight()),
782 parent) 782 parent)
783{ 783{
784 setFixedSize(w*TileItem::smallWidth(),h*TileItem::smallHeight()); 784 setFixedSize(w*TileItem::smallWidth(),h*TileItem::smallHeight());
785 grid = new TileItem*[w*h]; 785 grid = new TileItem*[w*h];
786 memset(grid,0,w*h*sizeof(TileItem*)); 786 memset(grid,0,w*h*sizeof(TileItem*));
787 setFrameStyle(0); 787 setFrameStyle(0);
788 setHScrollBarMode(AlwaysOff); 788 setHScrollBarMode(AlwaysOff);
789 setVScrollBarMode(AlwaysOff); 789 setVScrollBarMode(AlwaysOff);
790 current_rack = 0; 790 current_rack = 0;
791 shown_n = 0; 791 shown_n = 0;
792} 792}
793 793
794Board::~Board() 794Board::~Board()
795{ 795{
796 delete canvas(); 796 delete canvas();
797} 797}
798 798
799QSize Board::sizeHint() const 799QSize Board::sizeHint() const
800{ 800{
801 return QSize(canvas()->width(),canvas()->height()); 801 return QSize(canvas()->width(),canvas()->height());
802} 802}
803 803
804void Board::writeConfig(Config& cfg) 804void Board::writeConfig(Config& cfg)
805{ 805{
806 QStringList t; 806 QStringList t;
807 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically(); 807 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically();
808 for (int i=0; i<n; i++) 808 for (int i=0; i<n; i++)
809 t.append( grid[i] ? grid[i]->tile().key() : QString(".") ); 809 t.append( grid[i] ? grid[i]->tile().key() : QString(".") );
810 cfg.writeEntry("Board",t,';'); 810 cfg.writeEntry("Board",t,';');
811} 811}
812 812
813void Board::readConfig(Config& cfg) 813void Board::readConfig(Config& cfg)
814{ 814{
815 clear(); 815 clear();
816 QStringList t = cfg.readListEntry("Board",';'); 816 QStringList t = cfg.readListEntry("Board",';');
817 int i=0; 817 int i=0;
818 int h=canvas()->tilesHorizontally(); 818 int h=canvas()->tilesHorizontally();
819 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it) { 819 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it) {
820 if ( *it != "." ) { 820 if ( *it != "." ) {
821 QPoint p(i%h,i/h); 821 QPoint p(i%h,i/h);
822 setTile(p,Tile(*it)); 822 setTile(p,Tile(*it));
823 } 823 }
824 i++; 824 i++;
825 } 825 }
826 canvas()->update(); 826 canvas()->update();
827} 827}
828 828
829void Board::clear() 829void Board::clear()
830{ 830{
831 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically(); 831 int n=canvas()->tilesHorizontally()*canvas()->tilesVertically();
832 for (int i=0; i<n; i++) { 832 for (int i=0; i<n; i++) {
833 delete grid[i]; 833 delete grid[i];
834 grid[i]=0; 834 grid[i]=0;
835 } 835 }
836} 836}
837 837
838 838
839void Board::setCurrentRack(Rack* r) 839void Board::setCurrentRack(Rack* r)
840{ 840{
841 turn_score = -1; 841 turn_score = -1;
842 current_rack = r; 842 current_rack = r;
843} 843}
844 844
845void Board::resetRack() 845void Board::resetRack()
846{ 846{
847 unshowTurn(); 847 unshowTurn();
848 canvas()->update(); 848 canvas()->update();
849} 849}
850 850
851void Board::contentsMousePressEvent(QMouseEvent* e) 851void Board::contentsMousePressEvent(QMouseEvent* e)
852{ 852{
853 dragstart = e->pos(); 853 dragstart = e->pos();
854} 854}
855 855
856void Board::contentsMouseMoveEvent(QMouseEvent* e) 856void Board::contentsMouseMoveEvent(QMouseEvent* e)
857{ 857{
858 if ( current_rack && !current_rack->computerized() ) { 858 if ( current_rack && !current_rack->computerized() ) {
859 QPoint d = e->pos() - dragstart; 859 QPoint d = e->pos() - dragstart;
860 if ( d.x() <= 0 && d.y() <= 0 ) { 860 if ( d.x() <= 0 && d.y() <= 0 ) {
861 // None 861 // None
862 resetRack(); 862 resetRack();
863 } else { 863 } else {
864 int n; 864 int n;
865 QPoint start=boardPos(dragstart); 865 QPoint start=boardPos(dragstart);
866 QPoint end=boardPos(e->pos()); 866 QPoint end=boardPos(e->pos());
867 QPoint diff=end-start; 867 QPoint diff=end-start;
868 QPoint dir; 868 QPoint dir;
869 if ( d.x() > d.y() ) { 869 if ( d.x() > d.y() ) {
870 n = diff.x()+1; 870 n = diff.x()+1;
871 dir = QPoint(1,0); 871 dir = QPoint(1,0);
872 } else { 872 } else {
873 n = diff.y()+1; 873 n = diff.y()+1;
874 dir = QPoint(0,1); 874 dir = QPoint(0,1);
875 } 875 }
876 876
877 unshowTurn(); 877 unshowTurn();
878 878
879 // Subtract existing tiles from n 879 // Subtract existing tiles from n
880 QPoint t = start; 880 QPoint t = start;
881 for ( int i=n; i--; ) { 881 for ( int i=n; i--; ) {
882 if ( contains(t) && tile(t) ) 882 if ( contains(t) && tile(t) )
883 n--; 883 n--;
884 t += dir; 884 t += dir;
885 } 885 }
886 886
887 // Move start back to real start 887 // Move start back to real start
888 while (contains(start-dir) && tile(start-dir)) 888 while (contains(start-dir) && tile(start-dir))
889 start -= dir; 889 start -= dir;
890 890
891 scoreTurn(start, n, dir); 891 scoreTurn(start, n, dir);
892 showTurn(); 892 showTurn();
893 } 893 }
894 } 894 }
895} 895}
896 896
897void Board::finalizeTurn() 897void Board::finalizeTurn()
898{ 898{
899 int i=0; 899 int i=0;
900 QPoint at = shown_at; 900 QPoint at = shown_at;
901 while ( i<shown_n && contains(at) ) { 901 while ( i<shown_n && contains(at) ) {
902 if ( item(at) && item(at)->state() == TileItem::Floating ) { 902 if ( item(at) && item(at)->state() == TileItem::Floating ) {
903 current_rack->remove(item(at)->tile()); 903 current_rack->remove(item(at)->tile());
904 setTileState(at,TileItem::Firm); 904 setTileState(at,TileItem::Firm);
905 i++; 905 i++;
906 } 906 }
907 at += shown_step; 907 at += shown_step;
908 } 908 }
909 canvas()->update(); 909 canvas()->update();
910} 910}
911 911
912void Board::unshowTurn() 912void Board::unshowTurn()
913{ 913{
914 int i=0; 914 int i=0;
915 QPoint at = shown_at; 915 QPoint at = shown_at;
916 while ( i<shown_n && i<current_rack->count() && contains(at) ) { 916 while ( i<shown_n && i<current_rack->count() && contains(at) ) {
917 if ( item(at) && item(at)->state() == TileItem::Floating ) { 917 if ( item(at) && item(at)->state() == TileItem::Floating ) {
918 unsetTile(at); 918 unsetTile(at);
919 i++; 919 i++;
920 } 920 }
921 at += shown_step; 921 at += shown_step;
922 } 922 }
923} 923}
924 924
925void Board::showTurn() 925void Board::showTurn()
926{ 926{
927 unshowTurn(); 927 unshowTurn();
928 QPoint at = shown_at; 928 QPoint at = shown_at;
929 int i=0; 929 int i=0;
930 while ( i<shown_n && i<current_rack->count() && contains(at) ) { 930 while ( i<shown_n && i<current_rack->count() && contains(at) ) {
931 if ( !tile(at) ) { 931 if ( !tile(at) ) {
932 Tile t = current_rack->tile(i); 932 Tile t = current_rack->tile(i);
933 setTile(at,t); 933 setTile(at,t);
934 setTileState(at,TileItem::Floating); 934 setTileState(at,TileItem::Floating);
935 i++; 935 i++;
936 } 936 }
937 at += shown_step; 937 at += shown_step;
938 } 938 }
939 canvas()->update(); 939 canvas()->update();
940} 940}
941 941
942int Board::bonussedValue(const QPoint& at, int base, int& all_mult) const 942int Board::bonussedValue(const QPoint& at, int base, int& all_mult) const
943{ 943{
944 int rule = rule_shape[idx(at)]-'0'; 944 int rule = rule_shape[idx(at)]-'0';
945 int effect = rule_effect[rule]; 945 int effect = rule_effect[rule];
946 int mult = effect&Multiplier; 946 int mult = effect&Multiplier;
947 if ( effect & MultiplyAll ) { 947 if ( effect & MultiplyAll ) {
948 all_mult *= mult; 948 all_mult *= mult;
949 return base; 949 return base;
950 } else { 950 } else {
951 return base * mult; 951 return base * mult;
952 } 952 }
953} 953}
954 954
955bool Board::isStart(const QPoint& at) const 955bool Board::isStart(const QPoint& at) const
956{ 956{
957 int rule = rule_shape[idx(at)]-'0'; 957 int rule = rule_shape[idx(at)]-'0';
958 int effect = rule_effect[rule]; 958 int effect = rule_effect[rule];
959 return effect&Start; 959 return effect&Start;
960} 960}
961 961
962bool Board::checkTurn() 962bool Board::checkTurn()
963{ 963{
964 if ( current_rack->computerized() ) 964 if ( current_rack->computerized() )
965 return TRUE; // computer doesn't cheat, and has already set blanks. 965 return TRUE; // computer doesn't cheat, and has already set blanks.
966 966
967 QPoint at = shown_at; 967 QPoint at = shown_at;
968 int n = shown_n; 968 int n = shown_n;
969 QPoint d = shown_step; 969 QPoint d = shown_step;
970 const Tile* tiles[99]; 970 const Tile* tiles[99];
971 Tile blankvalues[99]; 971 Tile blankvalues[99];
972 if ( n > current_rack->count() ) 972 if ( n > current_rack->count() )
973 n = current_rack->count(); 973 n = current_rack->count();
974 974
975 QDialog check(this,0,TRUE); 975 QDialog check(this,0,TRUE);
976 (new QVBoxLayout(&check))->setAutoAdd(TRUE); 976 (new QVBoxLayout(&check))->setAutoAdd(TRUE);
977 977
978 QHBox mw(&check); 978 QHBox mw(&check);
979 new QLabel(tr("Blanks: "),&mw); 979 new QLabel(tr("Blanks: "),&mw);
980 980
981 int bl=0; 981 int bl=0;
982 QLineEdit* le[99]; 982 QLineEdit* le[99];
983 for (int i=0; i<n; i++) { 983 for (int i=0; i<n; i++) {
984 tiles[i] = current_rack->tileRef(i); 984 tiles[i] = current_rack->tileRef(i);
985 if ( tiles[i]->isBlank() ) { 985 if ( tiles[i]->isBlank() ) {
986 QLineEdit *l = new QLineEdit(&mw); 986 QLineEdit *l = new QLineEdit(&mw);
987 le[bl++] = l; 987 le[bl++] = l;
988 l->setMaxLength(1); 988 l->setMaxLength(1);
989 l->setFixedSize(l->minimumSizeHint()); 989 l->setFixedSize(l->minimumSizeHint());
990 } 990 }
991 } 991 }
992 992
993 QHBox btns(&check); 993 QHBox btns(&check);
994 connect(new QPushButton(tr("OK"),&btns), SIGNAL(clicked()), &check, SLOT(accept())); 994 connect(new QPushButton(tr("OK"),&btns), SIGNAL(clicked()), &check, SLOT(accept()));
995 connect(new QPushButton(tr("Cancel"),&btns), SIGNAL(clicked()), &check, SLOT(reject())); 995 connect(new QPushButton(tr("Cancel"),&btns), SIGNAL(clicked()), &check, SLOT(reject()));
996 996
997 if ( bl ) { 997 if ( bl ) {
998retry: 998retry:
999 if ( !check.exec() ) { 999 if ( !check.exec() ) {
1000 unshowTurn(); 1000 unshowTurn();
1001 canvas()->update(); 1001 canvas()->update();
1002 return FALSE; 1002 return FALSE;
1003 } 1003 }
1004 1004
1005 for (int b=0; b<bl; b++) { 1005 for (int b=0; b<bl; b++) {
1006 QString v = le[b]->text(); 1006 QString v = le[b]->text();
1007 blankvalues[b]=Tile(v,0); 1007 blankvalues[b]=Tile(v,0);
1008 if ( v.length() != 1 ) 1008 if ( v.length() != 1 )
1009 goto retry; 1009 goto retry;
1010 } 1010 }
1011 } 1011 }
1012 1012
1013 QStringList words; 1013 QStringList words;
1014 unshowTurn(); 1014 unshowTurn();
1015 turn_score = score(at,tiles,n,blankvalues,d,FALSE,&words); 1015 turn_score = score(at,tiles,n,blankvalues,d,FALSE,&words);
1016 showTurn(); 1016 showTurn();
1017 QStringList to_add; 1017 QStringList to_add;
1018 for (QStringList::Iterator it=words.begin(); it!=words.end(); ++it) { 1018 for (QStringList::Iterator it=words.begin(); it!=words.end(); ++it) {
1019 if ( !Global::fixedDawg().contains(*it) 1019 if ( !Global::fixedDawg().contains(*it)
1020 && !Global::dawg("WordGame").contains(*it) ) { 1020 && !Global::dawg("WordGame").contains(*it) ) {
1021 switch (QMessageBox::warning(this, tr("Unknown word"), 1021 switch (QMessageBox::warning(this, tr("Unknown word"),
1022 tr("<p>The word \"%1\" is not in the dictionary.").arg(*it), 1022 tr("<p>The word \"%1\" is not in the dictionary.").arg(*it),
1023 tr("Add"), tr("Ignore"), tr("Cancel"))) 1023 tr("Add"), tr("Ignore"), tr("Cancel")))
1024 { 1024 {
1025 case 0: 1025 case 0:
1026 // ####### add to wordgame dictionary 1026 // ####### add to wordgame dictionary
1027 to_add.append(*it); 1027 to_add.append(*it);
1028 break; 1028 break;
1029 case 1: 1029 case 1:
1030 break; 1030 break;
1031 case 2: 1031 case 2:
1032 unshowTurn(); 1032 unshowTurn();
1033 canvas()->update(); 1033 canvas()->update();
1034 return FALSE; 1034 return FALSE;
1035 } 1035 }
1036 } 1036 }
1037 } 1037 }
1038 if ( to_add.count() ) 1038 if ( to_add.count() )
1039 Global::addWords("WordGame",to_add); 1039 Global::addWords("WordGame",to_add);
1040 return TRUE; 1040 return TRUE;
1041} 1041}
1042 1042
1043void Board::scoreTurn(const QPoint& at, int n, const QPoint& d) 1043void Board::scoreTurn(const QPoint& at, int n, const QPoint& d)
1044{ 1044{
1045 unshowTurn(); 1045 unshowTurn();
1046 shown_at = at; 1046 shown_at = at;
1047 shown_n = n; 1047 shown_n = n;
1048 shown_step = d; 1048 shown_step = d;
1049 const Tile* tiles[99]; 1049 const Tile* tiles[99];
1050 if ( n > current_rack->count() ) 1050 if ( n > current_rack->count() )
1051 n = current_rack->count(); 1051 n = current_rack->count();
1052 for (int i=0; i<n; i++) 1052 for (int i=0; i<n; i++)
1053 tiles[i] = current_rack->tileRef(i); 1053 tiles[i] = current_rack->tileRef(i);
1054 turn_score = score(at,tiles,n,0,d,FALSE,0); 1054 turn_score = score(at,tiles,n,0,d,FALSE,0);
1055 emit temporaryScore(turn_score); 1055 emit temporaryScore(turn_score);
1056} 1056}
1057 1057
1058int Board::score(QPoint at, const Tile** tiles, int n, const Tile* blankvalue, const QPoint& d, bool checkdict, QStringList* words) const 1058int Board::score(QPoint at, const Tile** tiles, int n, const Tile* blankvalue, const QPoint& d, bool checkdict, QStringList* words) const
1059{ 1059{
1060 int total=0; 1060 int total=0;
1061 int totalsidetotal=0; 1061 int totalsidetotal=0;
1062 1062
1063 // words gets filled with words made 1063 // words gets filled with words made
1064 1064
1065 // mainword==0 -> 1065 // mainword==0 ->
1066 // Checks side words, but not main word 1066 // Checks side words, but not main word
1067 1067
1068 // -1 means words not in dict, or illegally positioned (eg. not connected) 1068 // -1 means words not in dict, or illegally positioned (eg. not connected)
1069 1069
1070 // text is assumed to fit on board. 1070 // text is assumed to fit on board.
1071 1071
1072 if ( words ) *words=QStringList(); 1072 if ( words ) *words=QStringList();
1073 1073
1074 QPoint otherd(d.y(), d.x()); 1074 QPoint otherd(d.y(), d.x());
1075 1075
1076 int all_mult = 1; 1076 int all_mult = 1;
1077 int bl=0; 1077 int bl=0;
1078 1078
1079 bool connected = FALSE; 1079 bool connected = FALSE;
1080 1080
1081 QString mainword=""; 1081 QString mainword="";
1082 1082
1083 if ( contains(at-d) && tile(at-d) ) { 1083 if ( contains(at-d) && tile(at-d) ) {
1084 return -1; // preceeding tiles 1084 return -1; // preceeding tiles
1085 } 1085 }
1086 1086
1087 const Tile* t; 1087 const Tile* t;
1088 for (int i=0; contains(at) && ((t=tile(at)) || i<n); ) { 1088 for (int i=0; contains(at) && ((t=tile(at)) || i<n); ) {
1089 if ( t ) { 1089 if ( t ) {
1090 if ( checkdict || words ) mainword += t->text(); 1090 if ( checkdict || words ) mainword += t->text();
1091 total += t->value(); 1091 total += t->value();
1092 connected = TRUE; 1092 connected = TRUE;
1093 } else { 1093 } else {
1094 QString sideword; 1094 QString sideword;
1095 QString tt; 1095 QString tt;
1096 if ( tiles[i]->isBlank() ) { 1096 if ( tiles[i]->isBlank() ) {
1097 if ( blankvalue ) 1097 if ( blankvalue )
1098 tt = blankvalue[bl++].text(); 1098 tt = blankvalue[bl++].text();
1099 } else { 1099 } else {
1100 tt = tiles[i]->text(); 1100 tt = tiles[i]->text();
1101 } 1101 }
1102 sideword=tt; 1102 sideword=tt;
1103 if ( checkdict || words ) mainword += tt; 1103 if ( checkdict || words ) mainword += tt;
1104 int side_mult = 1; 1104 int side_mult = 1;
1105 int tilevalue = bonussedValue(at,tiles[i]->value(),side_mult); 1105 int tilevalue = bonussedValue(at,tiles[i]->value(),side_mult);
1106 all_mult *= side_mult; 1106 all_mult *= side_mult;
1107 if ( !connected && isStart(at) ) 1107 if ( !connected && isStart(at) )
1108 connected = TRUE; 1108 connected = TRUE;
1109 total += tilevalue; 1109 total += tilevalue;
1110 int sidetotal = tilevalue; 1110 int sidetotal = tilevalue;
1111 { 1111 {
1112 QPoint side = at-otherd; 1112 QPoint side = at-otherd;
1113 1113
1114 while ( contains(side) && (t=tile(side)) ) { 1114 while ( contains(side) && (t=tile(side)) ) {
1115 sidetotal += t->value(); 1115 sidetotal += t->value();
1116 sideword.prepend(t->text()); 1116 sideword.prepend(t->text());
1117 side -= otherd; 1117 side -= otherd;
1118 } 1118 }
1119 } 1119 }
1120 { 1120 {
1121 QPoint side = at+otherd; 1121 QPoint side = at+otherd;
1122 while ( contains(side) && (t=tile(side)) ) { 1122 while ( contains(side) && (t=tile(side)) ) {
1123 sidetotal += t->value(); 1123 sidetotal += t->value();
1124 sideword.append(t->text()); 1124 sideword.append(t->text());
1125 side += otherd; 1125 side += otherd;
1126 } 1126 }
1127 } 1127 }
1128 if ( sideword.length() > 1 ) { 1128 if ( sideword.length() > 1 ) {
1129 if ( words ) 1129 if ( words )
1130 words->append(sideword); 1130 words->append(sideword);
1131 if ( checkdict && !Global::fixedDawg().contains(sideword) 1131 if ( checkdict && !Global::fixedDawg().contains(sideword)
1132 && !Global::dawg("WordGame").contains(sideword) ) 1132 && !Global::dawg("WordGame").contains(sideword) )
1133 return -1; 1133 return -1;
1134 totalsidetotal += sidetotal * side_mult; 1134 totalsidetotal += sidetotal * side_mult;
1135 connected = TRUE; 1135 connected = TRUE;
1136 } 1136 }
1137 i++; 1137 i++;
1138 } 1138 }
1139 at += d; 1139 at += d;
1140 } 1140 }
1141 1141
1142 if ( words ) 1142 if ( words )
1143 words->append(mainword); 1143 words->append(mainword);
1144 if ( checkdict && !Global::fixedDawg().contains(mainword) 1144 if ( checkdict && !Global::fixedDawg().contains(mainword)
1145 && !Global::dawg("WordGame").contains(mainword) ) 1145 && !Global::dawg("WordGame").contains(mainword) )
1146 return -1; 1146 return -1;
1147 1147
1148 if ( n == rack_tiles ) 1148 if ( n == rack_tiles )
1149 totalsidetotal += rack_tiles_bonus; 1149 totalsidetotal += rack_tiles_bonus;
1150 1150
1151 return connected ? totalsidetotal + total * all_mult : -1; 1151 return connected ? totalsidetotal + total * all_mult : -1;
1152} 1152}
1153 1153
1154QPoint Board::boardPos(const QPoint& p) const 1154QPoint Board::boardPos(const QPoint& p) const
1155{ 1155{
1156 return QPoint(p.x()/canvas()->tileWidth(), p.y()/canvas()->tileHeight()); 1156 return QPoint(p.x()/canvas()->tileWidth(), p.y()/canvas()->tileHeight());
1157} 1157}
1158 1158
1159void Board::contentsMouseReleaseEvent(QMouseEvent*) 1159void Board::contentsMouseReleaseEvent(QMouseEvent*)
1160{ 1160{
1161 if ( current_rack ) { 1161 if ( current_rack ) {
1162 } 1162 }
1163} 1163}
1164 1164
1165 1165
1166void Board::setRules(const QString& shapes, const int* effects) 1166void Board::setRules(const QString& shapes, const int* effects)
1167{ 1167{
1168 rule_shape=shapes; rule_effect=effects; 1168 rule_shape=shapes; rule_effect=effects;
1169 int i=0; 1169 int i=0;
1170 int maxre=0; 1170 int maxre=0;
1171 for (int y=0; y<yTiles(); y++) { 1171 for (int y=0; y<yTiles(); y++) {
1172 for (int x=0; x<xTiles(); x++) { 1172 for (int x=0; x<xTiles(); x++) {
1173 int re = shapes[i++]-'0'; 1173 int re = shapes[i++]-'0';
1174 if ( re > maxre ) maxre = re; 1174 if ( re > maxre ) maxre = re;
1175 canvas()->setTile(x,y,re); 1175 canvas()->setTile(x,y,re);
1176 } 1176 }
1177 } 1177 }
1178 rack_tiles_bonus=effects[maxre+1]; 1178 rack_tiles_bonus=effects[maxre+1];
1179} 1179}
1180 1180
1181void Board::unsetTile(const QPoint& p) 1181void Board::unsetTile(const QPoint& p)
1182{ 1182{
1183 delete item(p); 1183 delete item(p);
1184 grid[idx(p)] = 0; 1184 grid[idx(p)] = 0;
1185} 1185}
1186 1186
1187void Board::setTile(const QPoint& p, const Tile& t) 1187void Board::setTile(const QPoint& p, const Tile& t)
1188{ 1188{
1189 TileItem* it=item(p); 1189 TileItem* it=item(p);
1190 if ( !it ) { 1190 if ( !it ) {
1191 it = grid[idx(p)] = new TileItem(t,FALSE,canvas()); 1191 it = grid[idx(p)] = new TileItem(t,FALSE,canvas());
1192 it->move(p.x()*canvas()->tileWidth(), p.y()*canvas()->tileHeight()); 1192 it->move(p.x()*canvas()->tileWidth(), p.y()*canvas()->tileHeight());
1193 it->show(); 1193 it->show();
1194 } else { 1194 } else {
1195 it->setTile(t); 1195 it->setTile(t);
1196 } 1196 }
1197} 1197}
1198 1198
1199Rack::Rack(int ntiles, QWidget* parent) : QCanvasView( 1199Rack::Rack(int ntiles, QWidget* parent) : QCanvasView(
1200 new QCanvas(ntiles*TileItem::bigWidth(),TileItem::bigHeight()), 1200 new QCanvas(ntiles*TileItem::bigWidth(),TileItem::bigHeight()),
1201 parent), 1201 parent),
1202 item(ntiles) 1202 item(ntiles)
1203{ 1203{
1204 setLineWidth(1); 1204 setLineWidth(1);
1205 setFixedHeight(sizeHint().height()); 1205 setFixedHeight(sizeHint().height());
1206 n = 0; 1206 n = 0;
1207 for (int i=0; i<ntiles; i++) 1207 for (int i=0; i<ntiles; i++)
1208 item[i]=0; 1208 item[i]=0;
1209 setHScrollBarMode(AlwaysOff); 1209 setHScrollBarMode(AlwaysOff);
1210 setVScrollBarMode(AlwaysOff); 1210 setVScrollBarMode(AlwaysOff);
1211 canvas()->setBackgroundColor(gray); 1211 canvas()->setBackgroundColor(gray);
1212 dragging = 0; 1212 dragging = 0;
1213} 1213}
1214 1214
1215Rack::~Rack() 1215Rack::~Rack()
1216{ 1216{
1217 clear(); 1217 clear();
1218 delete canvas(); 1218 delete canvas();
1219} 1219}
1220 1220
1221QSize Rack::sizeHint() const 1221QSize Rack::sizeHint() const
1222{ 1222{
1223 return QSize(-1,TileItem::bigHeight()+2); 1223 return QSize(-1,TileItem::bigHeight()+2);
1224} 1224}
1225 1225
1226void Rack::clear() 1226void Rack::clear()
1227{ 1227{
1228 for (int i=0; i<n; i++) 1228 for (int i=0; i<n; i++)
1229 delete item[i]; 1229 delete item[i];
1230 n=0; 1230 n=0;
1231} 1231}
1232 1232
1233void Rack::writeConfig(Config& cfg) 1233void Rack::writeConfig(Config& cfg)
1234{ 1234{
1235 QStringList l; 1235 QStringList l;
1236 for (int i=0; i<n; i++) 1236 for (int i=0; i<n; i++)
1237 l.append(tile(i).key()); 1237 l.append(tile(i).key());
1238 cfg.writeEntry("Tiles",l,';'); 1238 cfg.writeEntry("Tiles",l,';');
1239} 1239}
1240 1240
1241void Rack::readConfig(Config& cfg) 1241void Rack::readConfig(Config& cfg)
1242{ 1242{
1243 clear(); 1243 clear();
1244 int x=0; 1244 int x=0;
1245 QStringList l = cfg.readListEntry("Tiles",';'); 1245 QStringList l = cfg.readListEntry("Tiles",';');
1246 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) { 1246 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) {
1247 TileItem *i = new TileItem(Tile(*it),TRUE,canvas()); 1247 TileItem *i = new TileItem(Tile(*it),TRUE,canvas());
1248 i->move(x++,0); 1248 i->move(x++,0);
1249 i->show(); 1249 i->show();
1250 item[n++] = i; 1250 item[n++] = i;
1251 } 1251 }
1252 layoutTiles(); 1252 layoutTiles();
1253} 1253}
1254 1254
1255static int cmp_tileitem(const void *a, const void *b) 1255static int cmp_tileitem(const void *a, const void *b)
1256{ 1256{
1257 const TileItem* ia = *(TileItem**)a; 1257 const TileItem* ia = *(TileItem**)a;
1258 const TileItem* ib = *(TileItem**)b; 1258 const TileItem* ib = *(TileItem**)b;
1259 return int(ia->x() - ib->x()); 1259 return int(ia->x() - ib->x());
1260} 1260}
1261 1261
1262void Rack::layoutTiles() 1262void Rack::layoutTiles()
1263{ 1263{
1264 int w = TileItem::bigWidth()+2; 1264 int w = TileItem::bigWidth()+2;
1265 1265
1266 if ( dragging ) dragging->moveBy(dragging_adj,0); 1266 if ( dragging ) dragging->moveBy(dragging_adj,0);
1267 qsort(item.data(), n, sizeof(TileItem*), cmp_tileitem); 1267 qsort(item.data(), n, sizeof(TileItem*), cmp_tileitem);
1268 if ( dragging ) dragging->moveBy(-dragging_adj,0); 1268 if ( dragging ) dragging->moveBy(-dragging_adj,0);
1269 1269
1270 for (int i=0; i<n ;i++) 1270 for (int i=0; i<n ;i++)
1271 if ( item[i] == dragging ) { 1271 if ( item[i] == dragging ) {
1272 item[i]->setZ(1); 1272 item[i]->setZ(1);
1273 } else { 1273 } else {
1274 item[i]->move(i*w, 0); 1274 item[i]->move(i*w, 0);
1275 item[i]->setZ(0); 1275 item[i]->setZ(0);
1276 } 1276 }
1277 canvas()->update(); 1277 canvas()->update();
1278} 1278}
1279 1279
1280void Rack::setBlanks(const Tile* bv) 1280void Rack::setBlanks(const Tile* bv)
1281{ 1281{
1282 for (int j=0; j<n; j++) { 1282 for (int j=0; j<n; j++) {
1283 Tile tt = item[j]->tile(); 1283 Tile tt = item[j]->tile();
1284 if ( tt.isBlank() ) { 1284 if ( tt.isBlank() ) {
1285 tt.setText(bv->text()); 1285 tt.setText(bv->text());
1286 item[j]->setTile(tt); 1286 item[j]->setTile(tt);
1287 bv++; 1287 bv++;
1288 } 1288 }
1289 } 1289 }
1290} 1290}
1291 1291
1292bool Rack::arrangeTiles(const Tile** s, int sn) 1292bool Rack::arrangeTiles(const Tile** s, int sn)
1293{ 1293{
1294 bool could = TRUE; 1294 bool could = TRUE;
1295 for (int j=0; j<n; j++) { 1295 for (int j=0; j<n; j++) {
1296 Tile tt = item[j]->tile(); 1296 Tile tt = item[j]->tile();
1297 int f=-1; 1297 int f=-1;
1298 for (int i=0; i<sn && f<0; i++) { 1298 for (int i=0; i<sn && f<0; i++) {
1299 if (s[i] && *s[i] == tt ) { 1299 if (s[i] && *s[i] == tt ) {
1300 s[i]=0; 1300 s[i]=0;
1301 f=i; 1301 f=i;
1302 } 1302 }
1303 } 1303 }
1304 if ( f >= 0 ) { 1304 if ( f >= 0 ) {
1305 item[j]->move(f-999,0); 1305 item[j]->move(f-999,0);
1306 } else { 1306 } else {
1307 could = FALSE; 1307 could = FALSE;
1308 } 1308 }
1309 } 1309 }
1310 layoutTiles(); 1310 layoutTiles();
1311 return could; 1311 return could;
1312} 1312}
1313 1313
1314void Rack::addTile(const Tile& t) 1314void Rack::addTile(const Tile& t)
1315{ 1315{
1316 TileItem *i = new TileItem(t,TRUE,canvas()); 1316 TileItem *i = new TileItem(t,TRUE,canvas());
1317 i->show(); 1317 i->show();
1318 item[n++] = i; 1318 item[n++] = i;
1319 layoutTiles(); 1319 layoutTiles();
1320} 1320}
1321 1321
1322void Rack::remove(Tile t) 1322void Rack::remove(Tile t)
1323{ 1323{
1324 for (int i=0; i<n ;i++) 1324 for (int i=0; i<n ;i++)
1325 if ( item[i]->tile() == t ) { 1325 if ( item[i]->tile() == t ) {
1326 remove(i); 1326 remove(i);
1327 return; 1327 return;
1328 } 1328 }
1329} 1329}
1330 1330
1331void Rack::remove(int i) 1331void Rack::remove(int i)
1332{ 1332{
1333 delete item[i]; 1333 delete item[i];
1334 n--; 1334 n--;
1335 for (;i<n;i++) 1335 for (;i<n;i++)
1336 item[i]=item[i+1]; 1336 item[i]=item[i+1];
1337 layoutTiles(); 1337 layoutTiles();
1338} 1338}
1339 1339
1340void Rack::resizeEvent(QResizeEvent* e) 1340void Rack::resizeEvent(QResizeEvent* e)
1341{ 1341{
1342 canvas()->resize(width()-frameWidth()*2,height()-frameWidth()*2); 1342 canvas()->resize(width()-frameWidth()*2,height()-frameWidth()*2);
1343 QCanvasView::resizeEvent(e); 1343 QCanvasView::resizeEvent(e);
1344} 1344}
1345 1345
1346void Rack::contentsMousePressEvent(QMouseEvent* e) 1346void Rack::contentsMousePressEvent(QMouseEvent* e)
1347{ 1347{
1348 if ( computerized() ) 1348 if ( computerized() )
1349 return; 1349 return;
1350 QCanvasItemList list = canvas()->collisions(e->pos()); 1350 QCanvasItemList list = canvas()->collisions(e->pos());
1351 if (list.count()) { 1351 if (list.count()) {
1352 dragging = list.first(); 1352 dragging = list.first();
1353 dragstart = e->pos()-QPoint(int(dragging->x()),int(dragging->y())); 1353 dragstart = e->pos()-QPoint(int(dragging->x()),int(dragging->y()));
1354 } else { 1354 } else {
1355 dragging = 0; 1355 dragging = 0;
1356 } 1356 }
1357} 1357}
1358 1358
1359void Rack::contentsMouseMoveEvent(QMouseEvent* e) 1359void Rack::contentsMouseMoveEvent(QMouseEvent* e)
1360{ 1360{
1361 if ( computerized() ) 1361 if ( computerized() )
1362 return; 1362 return;
1363 //int w = TileItem::bigWidth()+2; 1363 //int w = TileItem::bigWidth()+2;
1364 if ( dragging ) { 1364 if ( dragging ) {
1365 dragging_adj = TileItem::bigWidth()/2; 1365 dragging_adj = TileItem::bigWidth()/2;
1366 if ( dragging->x() > e->x()-dragstart.x() ) 1366 if ( dragging->x() > e->x()-dragstart.x() )
1367 dragging_adj = -dragging_adj; 1367 dragging_adj = -dragging_adj;
1368 dragging->move(e->x()-dragstart.x(),0); 1368 dragging->move(e->x()-dragstart.x(),0);
1369 layoutTiles(); 1369 layoutTiles();
1370 } 1370 }
1371} 1371}
1372 1372
1373void Rack::contentsMouseReleaseEvent(QMouseEvent* /*e*/) 1373void Rack::contentsMouseReleaseEvent(QMouseEvent* /*e*/)
1374{ 1374{
1375 if ( computerized() ) 1375 if ( computerized() )
1376 return; 1376 return;
1377 if ( dragging ) { 1377 if ( dragging ) {
1378 dragging=0; 1378 dragging=0;
1379 layoutTiles(); 1379 layoutTiles();
1380 } 1380 }
1381} 1381}
1382 1382
1383Tile::Tile(const QString& key) 1383Tile::Tile(const QString& key)
1384{ 1384{
1385 int a=key.find('@'); 1385 int a=key.find('@');
1386 txt = key.left(a); 1386 txt = key.left(a);
1387 val = key.mid(a+1).toInt(); 1387 val = key.mid(a+1).toInt();
1388 blank = txt.isEmpty(); 1388 blank = txt.isEmpty();
1389} 1389}
1390 1390
1391QString Tile::key() const 1391QString Tile::key() const
1392{ 1392{
1393 return txt+"@"+QString::number(val); 1393 return txt+"@"+QString::number(val);
1394} 1394}
1395 1395
1396Bag::Bag() 1396Bag::Bag()
1397{ 1397{
1398 tiles.setAutoDelete(TRUE); 1398 tiles.setAutoDelete(TRUE);
1399} 1399}
1400 1400
1401void Bag::writeConfig(Config& cfg) 1401void Bag::writeConfig(Config& cfg)
1402{ 1402{
1403 QStringList t; 1403 QStringList t;
1404 for (QListIterator<Tile> it(tiles); it; ++it) 1404 for (QListIterator<Tile> it(tiles); it; ++it)
1405 t.append((*it)->key()); 1405 t.append((*it)->key());
1406 cfg.writeEntry("Tiles",t,';'); 1406 cfg.writeEntry("Tiles",t,';');
1407} 1407}
1408 1408
1409void Bag::readConfig(Config& cfg) 1409void Bag::readConfig(Config& cfg)
1410{ 1410{
1411 tiles.clear(); 1411 tiles.clear();
1412 QStringList t = cfg.readListEntry("Tiles",';'); 1412 QStringList t = cfg.readListEntry("Tiles",';');
1413 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it ) 1413 for (QStringList::ConstIterator it=t.begin(); it!=t.end(); ++it )
1414 add(Tile(*it)); 1414 add(Tile(*it));
1415} 1415}
1416 1416
1417void Bag::add(const Tile& t) 1417void Bag::add(const Tile& t)
1418{ 1418{
1419 tiles.append(new Tile(t)); 1419 tiles.append(new Tile(t));
1420} 1420}
1421 1421
1422Tile Bag::takeRandom() 1422Tile Bag::takeRandom()
1423{ 1423{
1424 Tile* rp = tiles.take(random()%tiles.count()); 1424 Tile* rp = tiles.take(random()%tiles.count());
1425 Tile r=*rp; 1425 Tile r=*rp;
1426 return r; 1426 return r;
1427} 1427}
1428 1428
1429ScoreInfo::ScoreInfo( QWidget* parent, const char* name, WFlags fl ) : 1429ScoreInfo::ScoreInfo( QWidget* parent, const char* name, WFlags fl ) :
1430 QLabel("<P>",parent,name,fl) 1430 QLabel("<P>",parent,name,fl)
1431{ 1431{
1432 score=0; 1432 score=0;
1433 msgtimer = new QTimer(this); 1433 msgtimer = new QTimer(this);
1434 connect(msgtimer, SIGNAL(timeout()), this, SLOT(showScores())); 1434 connect(msgtimer, SIGNAL(timeout()), this, SLOT(showScores()));
1435 setBackgroundMode( PaletteButton ); 1435 setBackgroundMode( PaletteButton );
1436} 1436}
1437 1437
1438ScoreInfo::~ScoreInfo() 1438ScoreInfo::~ScoreInfo()
1439{ 1439{
1440 if ( score ) delete [] score; 1440 if ( score ) delete [] score;
1441} 1441}
1442 1442
1443void ScoreInfo::writeConfig(Config& cfg) 1443void ScoreInfo::writeConfig(Config& cfg)
1444{ 1444{
1445 QStringList l; 1445 QStringList l;
1446 for (int i=0; i<(int)names.count(); i++) 1446 for (int i=0; i<(int)names.count(); i++)
1447 l.append(QString::number(score[i])); 1447 l.append(QString::number(score[i]));
1448 cfg.writeEntry("Scores",l,';'); 1448 cfg.writeEntry("Scores",l,';');
1449} 1449}
1450 1450
1451void ScoreInfo::readConfig(Config& cfg) 1451void ScoreInfo::readConfig(Config& cfg)
1452{ 1452{
1453 QStringList l = cfg.readListEntry("Scores",';'); 1453 QStringList l = cfg.readListEntry("Scores",';');
1454 int i=0; 1454 int i=0;
1455 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it ) 1455 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it )
1456 score[i++]=(*it).toInt(); 1456 score[i++]=(*it).toInt();
1457 showScores(); 1457 showScores();
1458} 1458}
1459 1459
1460 1460
1461QSize ScoreInfo::sizeHint() const 1461QSize ScoreInfo::sizeHint() const
1462{ 1462{
1463 return QSize(QLabel::sizeHint().width(),fontMetrics().height()); 1463 return QSize(QLabel::sizeHint().width(),fontMetrics().height());
1464} 1464}
1465 1465
1466void ScoreInfo::init(const QStringList& namelist) 1466void ScoreInfo::init(const QStringList& namelist)
1467{ 1467{
1468 names = namelist; 1468 names = namelist;
1469 if ( score ) delete [] score; 1469 if ( score ) delete [] score;
1470 score = new int[names.count()]; 1470 score = new int[names.count()];
1471 memset(score,0,sizeof(int)*names.count()); 1471 memset(score,0,sizeof(int)*names.count());
1472 boldone = -1; 1472 boldone = -1;
1473 showScores(); 1473 showScores();
1474} 1474}
1475 1475
1476void ScoreInfo::addScore(int player, int change) 1476void ScoreInfo::addScore(int player, int change)
1477{ 1477{
1478 score[player] += change; 1478 score[player] += change;
1479 showScores(); 1479 showScores();
1480} 1480}
1481 1481
1482void ScoreInfo::setBoldOne(int b) 1482void ScoreInfo::setBoldOne(int b)
1483{ 1483{
1484 boldone=b; 1484 boldone=b;
1485 showScores(); 1485 showScores();
1486} 1486}
1487 1487
1488void ScoreInfo::showScores() 1488void ScoreInfo::showScores()
1489{ 1489{
1490 QString r="<p>"; 1490 QString r="<p>";
1491 int i=0; 1491 int i=0;
1492 //int spl=(names.count()+1)/2; // 2 lines 1492 //int spl=(names.count()+1)/2; // 2 lines
1493 for (QStringList::ConstIterator it=names.begin(); it!=names.end(); ) { 1493 for (QStringList::ConstIterator it=names.begin(); it!=names.end(); ) {
1494 if ( i==boldone ) r += "<b>"; 1494 if ( i==boldone ) r += "<b>";
1495 QString n = *it; 1495 QString n = *it;
1496 n.replace(QRegExp(":.*"),""); 1496 n.replace(QRegExp(":.*"),"");
1497 r += n; 1497 r += n;
1498 r += ":"; 1498 r += ":";
1499 r += QString::number(score[i]); 1499 r += QString::number(score[i]);
1500 if ( i==boldone ) r += "</b>"; 1500 if ( i==boldone ) r += "</b>";
1501 1501
1502 ++i; 1502 ++i;
1503 ++it; 1503 ++it;
1504 if ( it != names.end() ) 1504 if ( it != names.end() )
1505 r += " "; 1505 r += " ";
1506 } 1506 }
1507 setText(r); 1507 setText(r);
1508} 1508}
1509 1509
1510void ScoreInfo::showTemporaryScore(int amount) 1510void ScoreInfo::showTemporaryScore(int amount)
1511{ 1511{
1512 if ( amount < 0 ) 1512 if ( amount < 0 )
1513 setText(tr("<P>Invalid move")); 1513 setText(tr("<P>Invalid move"));
1514 else 1514 else
1515 setText(tr("<P>Score: ")+QString::number(amount)); 1515 setText(tr("<P>Score: ")+QString::number(amount));
1516 msgtimer->start(3000,TRUE); 1516 msgtimer->start(3000,TRUE);
1517} 1517}
1518 1518