00001
00002 #include <qimage.h>
00003 #include <qlayout.h>
00004 #include <qmenubar.h>
00005 #include <qtoolbar.h>
00006 #include <qpe/config.h>
00007 #include <qwhatsthis.h>
00008 #include <qtoolbutton.h>
00009 #include <qmessagebox.h>
00010 #include <qapplication.h>
00011
00012 #include "kcheckers.h"
00013 #include "echeckers.h"
00014 #include "rcheckers.h"
00015
00016 #include "pics/logo.xpm"
00017 #include "pics/undo.xpm"
00018 #include "pics/exit.xpm"
00019 #include "pics/help.xpm"
00020 #include "pics/wood1.xpm"
00021 #include "pics/wood2.xpm"
00022 #include "pics/wood3.xpm"
00023 #include "pics/green1.xpm"
00024 #include "pics/green2.xpm"
00025 #include "pics/green3.xpm"
00026 #include "pics/marble1.xpm"
00027 #include "pics/marble2.xpm"
00028 #include "pics/marble3.xpm"
00029 #include "pics/biglogo.xpm"
00030 #include "pics/man_black.xpm"
00031 #include "pics/man_white.xpm"
00032 #include "pics/king_black.xpm"
00033 #include "pics/king_white.xpm"
00034 #include "pics/contexthelp.xpm"
00035
00036
00037 QString KCheckers::enNumeration="1 2 3 4 5 6 7 8 9 1011121314151617181920212223242526272829303132";
00038 QString KCheckers::ruNumeration="B8D8F8H8A7C7E7G7B6D6F6H6A5C5E5G5B4D4F4H4A3C3E3G3B2D2F2H2A1C1E1G1";
00039
00040 const int KCheckers::t[]={6,7,8,9,11,12,13,14,17,18,19,20,22,23,
00041 24,25,28,29,30,31,33,34,35,36,39,40,41,42,44,45,46,47};
00042
00043
00044 KCheckers::KCheckers(QWidget *p, const char* n, WFlags )
00045 :QMainWindow(p,n,WStyle_DialogBorder)
00046 {
00047 setCaption(tr("KCheckers") );
00048 setIcon(QPixmap(biglogo_xpm));
00049
00050 setToolBarsMovable(false);
00051
00052
00053
00054 gameMenu=new QPopupMenu;
00055 CHECK_PTR(gameMenu);
00056
00057 gameMenu->insertItem(QPixmap(logo_xpm),tr("&New"),this,SLOT(newGame()),CTRL+Key_N);
00058 gameMenu->insertSeparator();
00059 undoID=gameMenu->insertItem(QPixmap(undo_xpm),tr("&Undo Move"),this,SLOT(undoMove()),CTRL+Key_Z);
00060 gameMenu->insertSeparator();
00061 gameMenu->insertItem(QPixmap(exit_xpm),tr("&Quit"),qApp,SLOT(closeAllWindows()),CTRL+Key_Q);
00062
00063 skillMenu=new QPopupMenu;
00064 CHECK_PTR(skillMenu);
00065
00066 skillMenu->insertItem(tr("&Beginner"),this,SLOT(setSkillBeginner()),CTRL+Key_1,BEGINNER);
00067 skillMenu->insertItem(tr("&Novice"), this,SLOT(setSkillNovice()), CTRL+Key_2,NOVICE);
00068 skillMenu->insertItem(tr("&Average"), this,SLOT(setSkillAverage()), CTRL+Key_3,AVERAGE);
00069 skillMenu->insertItem(tr("&Good"), this,SLOT(setSkillGood()), CTRL+Key_4,GOOD);
00070 skillMenu->insertItem(tr("&Expert"), this,SLOT(setSkillExpert()), CTRL+Key_5,EXPERT);
00071 skillMenu->insertItem(tr("&Master"), this,SLOT(setSkillMaster()), CTRL+Key_6,MASTER);
00072
00073 optionsMenu=new QPopupMenu;
00074 CHECK_PTR(optionsMenu);
00075
00076 numID=optionsMenu->insertItem(tr("&Show Numeration"),this,SLOT(showNumeration()));
00077 optionsMenu->insertSeparator();
00078 optionsMenu->insertItem(tr("&English Rules"),this,SLOT(setRulesEnglish()),0,ENGLISH);
00079 optionsMenu->insertItem(tr("&Russian Rules"),this,SLOT(setRulesRussian()),0,RUSSIAN);
00080 optionsMenu->insertSeparator();
00081 optionsMenu->insertItem(tr("&Green Board"), this,SLOT(setPatternGreen()), 0,GREEN);
00082 optionsMenu->insertItem(tr("&Marble Board"),this,SLOT(setPatternMarble()),0,MARBLE);
00083 optionsMenu->insertItem(tr("&Wooden Board"),this,SLOT(setPatternWooden()),0,WOODEN);
00084
00085 QPopupMenu* helpMenu=new QPopupMenu;
00086 CHECK_PTR(helpMenu);
00087
00088 helpMenu->insertItem(QPixmap(contexthelp_xpm),tr("What's This"),this,SLOT(whatsThis()),SHIFT+Key_F1);
00089 helpMenu->insertItem(QPixmap(help_xpm),tr("&Rules of Play"),this,SLOT(help()),Key_F1);
00090 helpMenu->insertSeparator();
00091 helpMenu->insertItem(QPixmap(logo_xpm),tr("&About KCheckers"),this,SLOT(about()));
00092 helpMenu->insertItem(tr("About &Qt"),this,SLOT(aboutQt()));
00093
00094 QToolBar* menuToolBar=new QToolBar(this);
00095 CHECK_PTR(menuToolBar);
00096 QMenuBar* menuBar=new QMenuBar(menuToolBar);
00097 CHECK_PTR(menuBar);
00098
00099 menuBar->insertItem(tr("&Game"), gameMenu);
00100 menuBar->insertItem(tr("&Skill"), skillMenu);
00101 menuBar->insertItem(tr("&Options"),optionsMenu);
00102 menuBar->insertItem(tr("&Help"), helpMenu);
00103
00104
00105
00106 readConfig();
00107
00108 skillMenu->setItemChecked(skill,true);
00109 optionsMenu->setItemChecked(rules,true);
00110 optionsMenu->setItemChecked(numID,false);
00111
00112
00113
00114 QToolBar* emptyToolBar=new QToolBar(this);
00115 emptyToolBar->setHorizontalStretchable(true);
00116
00117 QToolBar* toolBar=new QToolBar(this);
00118 CHECK_PTR(toolBar);
00119
00120 QSize buttonSize(24,24);
00121
00122 QToolButton* gameButton=new QToolButton(QPixmap(logo_xpm),tr(" New Game ") ,"",this,SLOT(newGame()),toolBar);
00123 CHECK_PTR(gameButton);
00124 gameButton->setMinimumSize(buttonSize);
00125
00126 undoButton=new QToolButton(QPixmap(undo_xpm),tr(" Undo Move "),"",this,SLOT(undoMove()),toolBar);
00127 CHECK_PTR(undoButton);
00128 undoButton->setMinimumSize(buttonSize);
00129
00130 QToolButton* helpButton=new QToolButton(QPixmap(help_xpm),tr(" Rules of Play "),"",this,SLOT(help()),toolBar);
00131 CHECK_PTR(helpButton);
00132 helpButton->setMinimumSize(buttonSize);
00133
00134
00135
00136 imageMan1=new QImage(man_black_xpm); CHECK_PTR(imageMan1);
00137 imageMan2=new QImage(man_white_xpm); CHECK_PTR(imageMan2);
00138 imageKing1=new QImage(king_black_xpm); CHECK_PTR(imageKing1);
00139 imageKing2=new QImage(king_white_xpm); CHECK_PTR(imageKing2);
00140
00141 imageWood1=new QImage(wood1_xpm); CHECK_PTR(imageWood1);
00142 imageWood2=new QImage(wood2_xpm); CHECK_PTR(imageWood2);
00143 imageWood3=new QImage(wood3_xpm); CHECK_PTR(imageWood3);
00144 imageGreen1=new QImage(green1_xpm); CHECK_PTR(imageGreen1);
00145 imageGreen2=new QImage(green2_xpm); CHECK_PTR(imageGreen2);
00146 imageGreen3=new QImage(green3_xpm); CHECK_PTR(imageGreen3);
00147 imageMarble1=new QImage(marble1_xpm); CHECK_PTR(imageMarble1);
00148 imageMarble2=new QImage(marble2_xpm); CHECK_PTR(imageMarble2);
00149 imageMarble3=new QImage(marble3_xpm); CHECK_PTR(imageMarble3);
00150
00151 QWidget* centralWidget=new QWidget(this);
00152 setCentralWidget(centralWidget);
00153
00154 QFrame* frame=new QFrame(centralWidget);
00155 CHECK_PTR(frame);
00156 frame->setFrameStyle(QFrame::Box|QFrame::Plain);
00157 frame->setFixedSize(SIZE*8+2,SIZE*8+2);
00158
00159 statusLabel = new QLabel(centralWidget);
00160 statusLabel->setAlignment(Qt::AlignHCenter);
00161
00162 QVBoxLayout* vlayout=new QVBoxLayout(centralWidget);
00163
00164 vlayout->addStretch();
00165 vlayout->addWidget(frame);
00166 vlayout->addStretch();
00167 vlayout->addWidget(statusLabel);
00168 vlayout->addStretch();
00169
00170 for(int i=0;i<64;i++)
00171 {
00172 field[i]=new Field(frame,i);
00173 CHECK_PTR(field[i]);
00174 }
00175
00176 QGridLayout* grid=new QGridLayout(frame,8,8,1,0);
00177 CHECK_PTR(grid);
00178
00179 for(int i=0;i<4;i++)
00180 {
00181 for(int k=0;k<4;k++)
00182 {
00183 grid->addWidget(field[i*8+k+32],i*2, k*2 );
00184 grid->addWidget(field[i*8+k ],i*2, k*2+1);
00185 grid->addWidget(field[i*8+k+4 ],i*2+1,k*2 );
00186 grid->addWidget(field[i*8+k+36],i*2+1,k*2+1);
00187 }
00188 }
00189
00190 for(int i=0;i<32;i++)
00191 connect(field[i],SIGNAL(click(int)),this,SLOT(click(int)));
00192
00193 selected=false;
00194
00195 setPattern(pattern);
00196
00197 QWhatsThis::add(frame,"A checkers board");
00198
00199 userFirst=false;
00200
00201 game=NULL;
00202 newGame();
00203 }
00204
00205
00206 void KCheckers::readConfig()
00207 {
00208 Config config("KCheckers");
00209 config.setGroup("KCheckers");
00210 QString entry;
00211
00212 entry=config.readEntry("skill","novice");
00213 if(entry=="beginner") skill=BEGINNER;
00214 else if(entry=="average") skill=AVERAGE;
00215 else if(entry=="good") skill=GOOD;
00216 else if(entry=="expert") skill=EXPERT;
00217 else if(entry=="master") skill=MASTER;
00218 else skill=NOVICE;
00219
00220 entry=config.readEntry("rules","english");
00221 if(entry=="russian") rules=RUSSIAN;
00222 else rules=ENGLISH;
00223
00224 entry=config.readEntry("theme","wooden");
00225 if(entry=="green") pattern=GREEN;
00226 else if(entry=="marble") pattern=MARBLE;
00227 else pattern=WOODEN;
00228 }
00229
00230
00231 void KCheckers::closeEvent(QCloseEvent* event)
00232 {
00233 Config config("KCheckers");
00234 config.setGroup("KCheckers");
00235 QString entry;
00236
00237 if(skill==BEGINNER) entry="beginner";
00238 if(skill==NOVICE) entry="novice";
00239 if(skill==AVERAGE) entry="average";
00240 if(skill==GOOD) entry="good";
00241 if(skill==EXPERT) entry="expert";
00242 if(skill==MASTER) entry="master";
00243 config.writeEntry("skill",entry);
00244
00245 if(rules==ENGLISH) entry="english";
00246 if(rules==RUSSIAN) entry="russian";
00247 config.writeEntry("rules",entry);
00248
00249 if(pattern==GREEN) entry="green";
00250 if(pattern==MARBLE) entry="marble";
00251 if(pattern==WOODEN) entry="wooden";
00252 config.writeEntry("theme",entry);
00253
00254 event->accept();
00255 }
00256
00257
00258 void KCheckers::setSkill(int set)
00259 {
00260 skillMenu->setItemChecked(skill,false);
00261
00262 skill=set;
00263 skillMenu->setItemChecked(skill,true);
00264
00265 game->setLevel(skill);
00266 }
00267
00268
00269 void KCheckers::setRules(int set)
00270 {
00271 optionsMenu->setItemChecked(rules,false);
00272
00273 rules=set;
00274 optionsMenu->setItemChecked(rules,true);
00275
00276 colorChange();
00277 newGame();
00278 }
00279
00280
00281 void KCheckers::setPattern(int set)
00282 {
00283 optionsMenu->setItemChecked(pattern,false);
00284
00285 pattern=set;
00286 optionsMenu->setItemChecked(pattern,true);
00287
00288 switch(pattern)
00289 {
00290 case GREEN:
00291 imagePat1=imageGreen1;
00292 imagePat2=imageGreen2;
00293 imageFrame=imageGreen3;
00294 break;
00295 case MARBLE:
00296 imagePat1=imageMarble1;
00297 imagePat2=imageMarble2;
00298 imageFrame=imageMarble3;
00299 break;
00300 case WOODEN:
00301 imagePat1=imageWood1;
00302 imagePat2=imageWood2;
00303 imageFrame=imageWood3;
00304 }
00305
00306 for(int i=0; i<32;i++) field[i]->setPattern(imagePat2);
00307 for(int i=32;i<64;i++) field[i]->setPattern(imagePat1);
00308
00309 if(selected) field[from]->setFrame(imageFrame);
00310 }
00311
00312
00313 void KCheckers::showNumeration()
00314 {
00315 if(optionsMenu->isItemChecked(numID))
00316 {
00317 optionsMenu->setItemChecked(numID,false);
00318 for(int i=0;i<32;i++) field[i]->setLabel("");
00319 }
00320 else
00321 {
00322 optionsMenu->setItemChecked(numID,true);
00323 drawNumeration();
00324 }
00325 }
00326
00327
00328 void KCheckers::drawNumeration()
00329 {
00330 if(rules==ENGLISH)
00331 {
00332 if(userFirst)
00333 for(int i=0;i<32;i++)
00334 field[i]->setLabel(enNumeration.mid(i*2,2));
00335 else
00336 for(int i=0;i<32;i++)
00337 field[i]->setLabel(enNumeration.mid(62-i*2,2));
00338 }
00339 else
00340 {
00341 if(userFirst)
00342 for(int i=0;i<32;i++)
00343 field[i]->setLabel(ruNumeration.mid(i*2,2));
00344 else
00345 for(int i=0;i<32;i++)
00346 field[i]->setLabel(ruNumeration.mid(62-i*2,2));
00347 }
00348 }
00349
00350
00351 void KCheckers::drawBoard(int i)
00352 {
00353 switch(game->board[t[i]])
00354 {
00355 case MAN1:
00356 field[i]->setPicture(imageMan1);
00357 break;
00358 case MAN2:
00359 field[i]->setPicture(imageMan2);
00360 break;
00361 case KING1:
00362 field[i]->setPicture(imageKing1);
00363 break;
00364 case KING2:
00365 field[i]->setPicture(imageKing2);
00366 break;
00367 default:
00368 field[i]->setPicture(NULL);
00369 }
00370 }
00371
00372
00373 void KCheckers::help()
00374 {
00375 QMessageBox::information(this,"Rules of Play",
00376 "In the beginning of game you have\n"
00377 "12 checkers (men).\n"
00378 "The men move forward only.\n"
00379 "The men can capture:\n"
00380 "- by jumping forward only (english\n"
00381 " rules);\n"
00382 "- by jumping forward or backward\n"
00383 " (russian rules).\n"
00384 "A man which reaches the far side of\n"
00385 "the board becomes a king.\n"
00386 "The kings move forward or\n"
00387 "backward:\n"
00388 "- to one square only (english rules);\n"
00389 "- to any number of squares (russian\n"
00390 " rules).\n"
00391 "The kings capture by jumping\n"
00392 "forward or backward.\n"
00393 "Whenever a player is able to make a\n"
00394 "capture he must do so.",
00395 QMessageBox::Ok|QMessageBox::Default);
00396 }
00397
00398
00399 void KCheckers::about()
00400 {
00401 QMessageBox::about(this,"About KCheckers",
00402 "KCheckers, a board game. Ver 0.3\n"
00403 "(C) 2002, A. Peredri <andi@ukr.net>\n\n"
00404 "http://kcheckers.tuxfamily.org\n\n"
00405 "Contributors:\n"
00406 "S. Rosen <srosen@erols.com>\n\n"
00407 "Qtopia version: S.Prud'homme\n"
00408 "<prudhomme@laposte.net>\n\n"
00409 "This program is distributed under the\n"
00410 "terms of the GNU General Public\n"
00411 "License.");
00412 }
00413
00414
00415 void KCheckers::aboutQt()
00416 {
00417 QMessageBox::aboutQt(this);
00418 }
00419
00420
00421 void KCheckers::newGame()
00422 {
00423 if(game) delete game;
00424
00425 switch(rules)
00426 {
00427 case ENGLISH:
00428 game=new ECheckers(skill);
00429 CHECK_PTR(game);
00430 break;
00431
00432 case RUSSIAN:
00433 game=new RCheckers(skill);
00434 CHECK_PTR(game);
00435 }
00436
00437 unselect();
00438 gameOver=false;
00439
00440 gameMenu->setItemEnabled(undoID,false);
00441 undoButton->setEnabled(false);
00442
00443 colorChange();
00444
00445 for(int i=0;i<32;i++) drawBoard(i);
00446 if(optionsMenu->isItemChecked(numID)) drawNumeration();
00447
00448 if(!userFirst) compGo();
00449
00450 statusLabel->setText(tr("Go!"));
00451 }
00452
00453
00454
00455
00456 void KCheckers::undoMove()
00457 {
00458 for(int i=0;i<32;i++)
00459 {
00460 game->board[t[i]]=undoBoard[i];
00461 drawBoard(i);
00462 }
00463
00464 unselect();
00465 gameOver=false;
00466
00467 gameMenu->setItemEnabled(undoID,false);
00468 undoButton->setEnabled(false);
00469
00470 statusLabel->setText(tr("Go!"));
00471 }
00472
00473
00474 void KCheckers::colorChange()
00475 {
00476 userFirst=!userFirst;
00477
00478 QImage* image;
00479 image=imageMan1;
00480 imageMan1=imageMan2;
00481 imageMan2=image;
00482 image=imageKing1;
00483 imageKing1=imageKing2;
00484 imageKing2=image;
00485 }
00486
00487
00488 void KCheckers::unselect()
00489 {
00490 if(selected) field[from]->setFrame(NULL);
00491 selected=false;
00492 }
00493
00494
00495 void KCheckers::click(int fieldNumber)
00496 {
00497 if(gameOver) return;
00498 switch(game->board[t[fieldNumber]])
00499 {
00500 case MAN1:
00501 case KING1:
00502
00503 if(!selected)
00504 {
00505 from=fieldNumber;
00506 selected=true;
00507 field[fieldNumber]->setFrame(imageFrame);
00508 return;
00509 }
00510
00511 else
00512 {
00513 field[from]->setFrame(NULL);
00514 from=fieldNumber;
00515 field[fieldNumber]->setFrame(imageFrame);
00516 return;
00517 }
00518 case FREE:
00519 if(!selected) return;
00520
00521 if(!userGo(fieldNumber)) return;
00522
00523 unselect();
00524
00525 if(!(game->checkMove2() || game->checkCapture2()))
00526 {
00527 gameOver=true;
00528 statusLabel->setText(tr("Congratulation! You have won!"));
00529 return;
00530 }
00531
00532 statusLabel->setText(tr("Please wait..."));
00533 qApp->processEvents();
00534
00535 compGo();
00536 if(!(game->checkMove1() || game->checkCapture1()))
00537 {
00538 gameOver=true;
00539 statusLabel->setText(tr("You have lost. Game over."));
00540 return;
00541 }
00542 statusLabel->setText(tr("Go!"));
00543 }
00544 }
00545
00546
00547 void KCheckers::compGo()
00548 {
00549 int save[32];
00550 for(int i=0;i<32;i++) save[i]=game->board[t[i]];
00551
00552 game->go2();
00553
00554 for(int i=0;i<32;i++)
00555 {
00556 if(game->board[t[i]]==save[i]) continue;
00557 drawBoard(i);
00558 }
00559 }
00560
00561
00562 bool KCheckers::userGo(int to)
00563 {
00564 int save[32];
00565 for(int i=0;i<32;i++) save[i]=game->board[t[i]];
00566
00567 if(!game->go1(t[from],t[to]))
00568 {
00569 statusLabel->setText(tr("Incorrect course."));
00570 return false;
00571 }
00572
00573 for(int i=0;i<32;i++) undoBoard[i]=save[i];
00574 gameMenu->setItemEnabled(undoID,true);
00575 undoButton->setEnabled(true);
00576
00577 for(int i=0;i<32;i++)
00578 {
00579 if(game->board[t[i]]==save[i]) continue;
00580 drawBoard(i);
00581 }
00582
00583 return true;
00584 }
00585
00586