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,701 +1,701 @@
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 }