summaryrefslogtreecommitdiff
authorerik <erik>2007-01-19 01:10:09 (UTC)
committer erik <erik>2007-01-19 01:10:09 (UTC)
commit2b45dc71e79a3eb7d4e8553273c9bc4f4282d50a (patch) (unidiff)
tree5f1b129bf6864ad8c47054471a0c4a34badeeebe
parentca67251af3f46d685afac8dc6bfe452799c2546e (diff)
downloadopie-2b45dc71e79a3eb7d4e8553273c9bc4f4282d50a.zip
opie-2b45dc71e79a3eb7d4e8553273c9bc4f4282d50a.tar.gz
opie-2b45dc71e79a3eb7d4e8553273c9bc4f4282d50a.tar.bz2
BUG: There are only 4095 items in the buffer that is zero'd out using 4096.
FIX: Fix the number used in memset.
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
@@ -207,769 +207,769 @@ void WordGame::readConfig()
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);