|
|
|
//
|
|
|
|
// KBlackbox
|
|
|
|
//
|
|
|
|
// A simple game inspired by an emacs module
|
|
|
|
//
|
|
|
|
// File: kbbgame.cpp
|
|
|
|
//
|
|
|
|
// The implementation of the KBBGame widget
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqkeycode.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
|
|
|
|
#include <tdemessagebox.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdeapplication.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdeconfig.h>
|
|
|
|
#include <tdeglobal.h>
|
|
|
|
#include <tdemenubar.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <khelpmenu.h>
|
|
|
|
#include <tdeaction.h>
|
|
|
|
#include <kstdaction.h>
|
|
|
|
#include <kstatusbar.h>
|
|
|
|
#include <kstdgameaction.h>
|
|
|
|
|
|
|
|
#include "kbbgame.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "version.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
Names of pixmap files.
|
|
|
|
*/
|
|
|
|
|
|
|
|
const char *pFNames[NROFTYPES] = {
|
|
|
|
"white",
|
|
|
|
"gray",
|
|
|
|
"green",
|
|
|
|
"red",
|
|
|
|
"blue",
|
|
|
|
"cyan",
|
|
|
|
"brown",
|
|
|
|
"green2"
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Creates the KBBGame widget and sets saved options (if any).
|
|
|
|
*/
|
|
|
|
|
|
|
|
KBBGame::KBBGame()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
TQPixmap **pix = new TQPixmap * [NROFTYPES];
|
|
|
|
pix[0] = new TQPixmap();
|
|
|
|
*pix[0] = BarIcon( pFNames[0] );
|
|
|
|
if (!pix[0]->isNull()) {
|
|
|
|
kdDebug(12009) << "Pixmap \"" << pFNames[0] << "\" loaded." << endl;
|
|
|
|
for (i = 1; i < NROFTYPES; i++) {
|
|
|
|
pix[i] = new TQPixmap;
|
|
|
|
*pix[i] = BarIcon( pFNames[i] );
|
|
|
|
if (!pix[i]->isNull()) {
|
|
|
|
kdDebug(12009) << "Pixmap \"" << pFNames[i] << "\" loaded." << endl;
|
|
|
|
} else {
|
|
|
|
pix[i] = pix[i-1];
|
|
|
|
pix[i]->detach();
|
|
|
|
kdDebug(12009) << "Cannot find pixmap \"" << pFNames[i] << "\". Using previous one." << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
kdDebug(12009) << "Cannot find pixmap \"" << pFNames[0] << "\". Pixmaps will not be loaded." << endl;
|
|
|
|
delete pix[0];
|
|
|
|
delete pix;
|
|
|
|
pix = NULL;
|
|
|
|
}
|
|
|
|
gr = new KBBGraphic( pix, this, "KBBGraphic" );
|
|
|
|
|
|
|
|
statusBar()->insertItem(i18n("Score: 0000"), SSCORE);
|
|
|
|
statusBar()->insertItem(i18n("Placed: 00 / 00"), SBALLS);
|
|
|
|
statusBar()->insertItem(i18n("Run: yesno"), SRUN);
|
|
|
|
statusBar()->insertItem(i18n("Size: 00 x 00"), SSIZE);
|
|
|
|
|
|
|
|
initTDEAction();
|
|
|
|
|
|
|
|
connect( gr, TQT_SIGNAL(inputAt(int,int,int)),
|
|
|
|
this, TQT_SLOT(gotInputAt(int,int,int)) );
|
|
|
|
connect( this, TQT_SIGNAL(gameRuns(bool)),
|
|
|
|
gr, TQT_SLOT(setInputAccepted(bool)) );
|
|
|
|
connect( gr, TQT_SIGNAL(endMouseClicked()),
|
|
|
|
this, TQT_SLOT(gameFinished()) );
|
|
|
|
|
|
|
|
/*
|
|
|
|
TQToolTip::add( doneButton, i18n(
|
|
|
|
"Click here when you think you placed all the balls.") );
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Game initializations
|
|
|
|
*/
|
|
|
|
running = FALSE;
|
|
|
|
gameBoard = NULL;
|
|
|
|
|
|
|
|
TDEConfig *kConf;
|
|
|
|
int j;
|
|
|
|
kConf = kapp->config();
|
|
|
|
kConf->setGroup( "KBlackBox Setup" );
|
|
|
|
if (kConf->hasKey( "Balls" )) {
|
|
|
|
i = kConf->readNumEntry( "Balls" );
|
|
|
|
balls = i;
|
|
|
|
switch (i) {
|
|
|
|
case 4: ballsAction->setCurrentItem(0); break;
|
|
|
|
case 6: ballsAction->setCurrentItem(1); break;
|
|
|
|
case 8: ballsAction->setCurrentItem(2); break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
balls = 4;
|
|
|
|
ballsAction->setCurrentItem(0);
|
|
|
|
}
|
|
|
|
if ((kConf->hasKey( "Width" )) &&
|
|
|
|
(kConf->hasKey( "Balls" ))) {
|
|
|
|
i = kConf->readNumEntry( "Width" );
|
|
|
|
j = kConf->readNumEntry( "Height" );
|
|
|
|
gr->setSize( i+4, j+4 ); // +4 is the space for "lasers" and an edge...
|
|
|
|
gameBoard = new RectOnArray( gr->numC(), gr->numR() );
|
|
|
|
switch (i) {
|
|
|
|
case 8: sizeAction->setCurrentItem(0); break;
|
|
|
|
case 10: sizeAction->setCurrentItem(1); break;
|
|
|
|
case 12: sizeAction->setCurrentItem(2); break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gr->setSize( 8+4, 8+4 ); // +4 is the space for "lasers" and an edge...
|
|
|
|
gameBoard = new RectOnArray( gr->numC(), gr->numR() );
|
|
|
|
sizeAction->setCurrentItem(0);
|
|
|
|
}
|
|
|
|
if (kConf->hasKey( "tutorial" )) {
|
|
|
|
tutorial = (bool) kConf->readNumEntry( "tutorial" );
|
|
|
|
} else tutorial = FALSE;
|
|
|
|
tutorialAction->setChecked(tutorial);
|
|
|
|
|
|
|
|
setCentralWidget( gr );
|
|
|
|
|
|
|
|
setScore( 0 );
|
|
|
|
ballsPlaced = 0;
|
|
|
|
|
|
|
|
updateStats();
|
|
|
|
|
|
|
|
newGame();
|
|
|
|
setMinSize();
|
|
|
|
|
|
|
|
setupGUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Saves the options and destroys the KBBGame widget.
|
|
|
|
*/
|
|
|
|
|
|
|
|
KBBGame::~KBBGame()
|
|
|
|
{
|
|
|
|
TDEConfig *kConf;
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
kConf = kapp->config();
|
|
|
|
kConf->setGroup( "KBlackBox Setup" );
|
|
|
|
kConf->writeEntry( "Balls", balls );
|
|
|
|
kConf->writeEntry( "Width", gr->numC() - 4);
|
|
|
|
kConf->writeEntry( "Height", gr->numR() - 4);
|
|
|
|
kConf->writeEntry( "tutorial", (int) tutorial );
|
|
|
|
|
|
|
|
delete gameBoard;
|
|
|
|
// All the rest has "this" for parent so it doesn't need to be deleted.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Resizes yourself to fit the contents perfectly, from menu.
|
|
|
|
*/
|
|
|
|
void KBBGame::gameResize()
|
|
|
|
{
|
|
|
|
resize( gr->wHint(), gr->hHint() + menuBar()->height() + statusBar()->height() +
|
|
|
|
toolBar()->height() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KBBGame::setMinSize()
|
|
|
|
{
|
|
|
|
setMinimumSize( gr->wHint(), gr->hHint() + menuBar()->height() + statusBar()->height() +
|
|
|
|
toolBar()->height() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Settings of various options.
|
|
|
|
*/
|
|
|
|
void KBBGame::slotSize()
|
|
|
|
{
|
|
|
|
int i = sizeAction->currentItem();
|
|
|
|
bool ok = false;
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
ok = setSize( 8, 8 );
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ok = setSize( 10, 10 );
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ok = setSize( 12, 12 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
switch(gr->numR() - 4) {
|
|
|
|
case 8:
|
|
|
|
sizeAction->setCurrentItem(0); break;
|
|
|
|
case 10:
|
|
|
|
sizeAction->setCurrentItem(1); break;
|
|
|
|
case 12:
|
|
|
|
sizeAction->setCurrentItem(2); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KBBGame::slotBalls()
|
|
|
|
{
|
|
|
|
int i = ballsAction->currentItem();
|
|
|
|
bool ok = false;
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
ok = setBalls( 4 );
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ok = setBalls( 6 );
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ok = setBalls( 8 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ok) {
|
|
|
|
switch (balls) {
|
|
|
|
case 4:
|
|
|
|
ballsAction->setCurrentItem(0); break;
|
|
|
|
case 6:
|
|
|
|
ballsAction->setCurrentItem(1); break;
|
|
|
|
case 8:
|
|
|
|
ballsAction->setCurrentItem(2); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KBBGame::tutorialSwitch()
|
|
|
|
{
|
|
|
|
tutorial = !tutorial;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Creates a new game.
|
|
|
|
*/
|
|
|
|
void KBBGame::newGame()
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
if (running) {
|
|
|
|
bool cancel;
|
|
|
|
cancel = KMessageBox::warningContinueCancel(0,
|
|
|
|
i18n("Do you really want to give up this game?"),TQString(),i18n("Give Up"))
|
|
|
|
== KMessageBox::Cancel;
|
|
|
|
if (cancel)
|
|
|
|
return;
|
|
|
|
|
|
|
|
abortGame();
|
|
|
|
}
|
|
|
|
|
|
|
|
gameBoard->fill( INNERBBT );
|
|
|
|
for (j = 0; j < (gr->numR()); j++) {
|
|
|
|
gameBoard->set( 0, j, OUTERBBT );
|
|
|
|
gameBoard->set( gr->numC()-1, j, OUTERBBT );
|
|
|
|
}
|
|
|
|
for (i = 0; i < (gr->numC()); i++) {
|
|
|
|
gameBoard->set( i, 0, OUTERBBT );
|
|
|
|
gameBoard->set( i, gr->numR()-1, OUTERBBT );
|
|
|
|
}
|
|
|
|
for (j = 2; j < (gr->numR()-2); j++) {
|
|
|
|
gameBoard->set( 1, j, LASERBBT );
|
|
|
|
gameBoard->set( gr->numC()-2, j, LASERBBT );
|
|
|
|
}
|
|
|
|
for (i = 2; i < (gr->numC()-2); i++) {
|
|
|
|
gameBoard->set( i, 1, LASERBBT );
|
|
|
|
gameBoard->set( i, gr->numR()-2, LASERBBT );
|
|
|
|
}
|
|
|
|
gameBoard->set( 1, 1, OUTERBBT );
|
|
|
|
gameBoard->set( 1, gr->numR()-2, OUTERBBT );
|
|
|
|
gameBoard->set( gr->numC()-2, 1, OUTERBBT );
|
|
|
|
gameBoard->set( gr->numC()-2, gr->numR()-2, OUTERBBT );
|
|
|
|
|
|
|
|
randomBalls( balls );
|
|
|
|
remap( gameBoard, gr->getGraphicBoard() );
|
|
|
|
gr->repaint( TRUE );
|
|
|
|
setScore( 0 );
|
|
|
|
detourCounter = -1;
|
|
|
|
ballsPlaced = 0;
|
|
|
|
running = TRUE;
|
|
|
|
updateStats();
|
|
|
|
emit gameRuns( running );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Ends the current game.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::gameFinished()
|
|
|
|
{
|
|
|
|
if (running) {
|
|
|
|
TQString s;
|
|
|
|
if (ballsPlaced == balls) {
|
|
|
|
getResults();
|
|
|
|
abortGame();
|
|
|
|
if (score <= (balls*3))
|
|
|
|
s = i18n("Your final score is: %1\n"
|
|
|
|
"You did really well!");
|
|
|
|
else
|
|
|
|
s = i18n("Your final score is: %1\n"
|
|
|
|
"I guess you need more practice.");
|
|
|
|
|
|
|
|
KMessageBox::information(this,
|
|
|
|
s.arg(TDEGlobal::locale()->formatNumber(score, 0)));
|
|
|
|
} else {
|
|
|
|
s = i18n( "You should place %1 balls!\n"
|
|
|
|
"You have placed %2.")
|
|
|
|
.arg(TDEGlobal::locale()->formatNumber(balls, 0))
|
|
|
|
.arg(TDEGlobal::locale()->formatNumber(ballsPlaced, 0));
|
|
|
|
|
|
|
|
KMessageBox::sorry(this, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Computes the final score and indicate errors.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::getResults()
|
|
|
|
{
|
|
|
|
int i, j, tgam, tgra;
|
|
|
|
RectOnArray *r = gr->getGraphicBoard();
|
|
|
|
for (j = 0; j < (gr->numR()); j++) {
|
|
|
|
for (i = 0; i < (gr->numC()); i++) {
|
|
|
|
tgam = gameBoard->get( i, j );
|
|
|
|
tgra = r->get( i, j );
|
|
|
|
if ((tgam == BALLBBT) && (tgra != TBALLBBG)) {
|
|
|
|
setScore( score+5 );
|
|
|
|
r->set( i, j, WBALLBBG );
|
|
|
|
gr->updateElement( i, j );
|
|
|
|
}
|
|
|
|
if ((tgam != BALLBBT) && (tgra == TBALLBBG)) {
|
|
|
|
r->set( i, j, FBALLBBG );
|
|
|
|
gr->updateElement( i, j );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Aborts the current game.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::abortGame()
|
|
|
|
{
|
|
|
|
if (running) {
|
|
|
|
running = FALSE;
|
|
|
|
ballsPlaced = 0;
|
|
|
|
updateStats();
|
|
|
|
gr->clearFocus();
|
|
|
|
emit gameRuns( running );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Gives the game up.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::giveUp()
|
|
|
|
{
|
|
|
|
if (running) {
|
|
|
|
bool stop;
|
|
|
|
stop = KMessageBox::warningContinueCancel(0,
|
|
|
|
i18n(
|
|
|
|
"Do you really want to give up this game?"),TQString(),i18n("Give Up"))
|
|
|
|
== KMessageBox::Continue;
|
|
|
|
|
|
|
|
if (stop) {
|
|
|
|
getResults();
|
|
|
|
abortGame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Displays game statistics.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::updateStats()
|
|
|
|
{
|
|
|
|
TQString tmp;
|
|
|
|
TQString s = i18n("Run: ");
|
|
|
|
if (running)
|
|
|
|
s += i18n("Yes");
|
|
|
|
else
|
|
|
|
s += i18n("No");
|
|
|
|
statusBar()->changeItem( s, SRUN );
|
|
|
|
s = i18n( "Size: " );
|
|
|
|
s += tmp.sprintf( "%2d x %2d",
|
|
|
|
gr->numC()-4, gr->numR()-4 );
|
|
|
|
statusBar()->changeItem( s, SSIZE );
|
|
|
|
s = i18n( "Placed: " );
|
|
|
|
s += tmp.sprintf( "%2d / %2d",
|
|
|
|
ballsPlaced, balls );
|
|
|
|
statusBar()->changeItem( s, SBALLS );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Sets the score value to n.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::setScore( int n )
|
|
|
|
{
|
|
|
|
score = n;
|
|
|
|
statusBar()->changeItem( i18n("Score: %1").arg(n), SSCORE );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Sets the size of the black box.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool KBBGame::setSize( int w, int h )
|
|
|
|
{
|
|
|
|
bool ok = FALSE;
|
|
|
|
if (((w+4) != gr->numC()) || ((h+4) != gr->numR())) {
|
|
|
|
if (running) {
|
|
|
|
ok = KMessageBox::warningContinueCancel(0,
|
|
|
|
i18n(
|
|
|
|
"This will be the end of the current game!"),TQString(),i18n("End Game"))
|
|
|
|
== KMessageBox::Continue;
|
|
|
|
|
|
|
|
} else ok = TRUE;
|
|
|
|
if (ok) {
|
|
|
|
gr->setSize( w+4, h+4 ); // +4 is the space for "lasers" and an edge...
|
|
|
|
setMinSize();
|
|
|
|
gameResize();
|
|
|
|
delete gameBoard;
|
|
|
|
gameBoard = new RectOnArray( gr->numC(), gr->numR() );
|
|
|
|
if (running) abortGame();
|
|
|
|
newGame();
|
|
|
|
// gr->repaint( TRUE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Sets the number of balls in the black box to n.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool KBBGame::setBalls( int n )
|
|
|
|
{
|
|
|
|
bool ok = FALSE;
|
|
|
|
if (balls != n) {
|
|
|
|
if (running) {
|
|
|
|
ok = KMessageBox::warningContinueCancel(0,
|
|
|
|
i18n("This will be the end of the current game!"),TQString(),i18n("End Game"))
|
|
|
|
== KMessageBox::Continue;
|
|
|
|
} else ok = TRUE;
|
|
|
|
if (ok) {
|
|
|
|
balls = n;
|
|
|
|
if (running) abortGame();
|
|
|
|
newGame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Puts n balls in the black box on random positions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::randomBalls( int n )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
random.setSeed(0);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
int x=0, y=0; // there is OUTERBBT...
|
|
|
|
while (gameBoard->get( x, y ) != INNERBBT ) {
|
|
|
|
x = 2 + random.getLong(gameBoard->width()-4);
|
|
|
|
y = 2 + random.getLong(gameBoard->height()-4);
|
|
|
|
}
|
|
|
|
gameBoard->set( x, y, BALLBBT );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This is, in fact, the whole game...
|
|
|
|
*/
|
|
|
|
|
|
|
|
int KBBGame::traceRay( int startX, int startY, int *endX, int *endY )
|
|
|
|
{
|
|
|
|
int type, x, y, d, refl;
|
|
|
|
int slx, scx, srx, sly, scy, sry;
|
|
|
|
bool directionChanged;
|
|
|
|
*endX = x = startX;
|
|
|
|
*endY = y = startY;
|
|
|
|
/*
|
|
|
|
Just to avoid compiler warnings
|
|
|
|
*/
|
|
|
|
type = slx = scx = srx = sly = scy = sry = 0;
|
|
|
|
/*
|
|
|
|
Get the initial direction d.
|
|
|
|
0 .. up, 1 .. right, 2 .. down, 3 .. left
|
|
|
|
(0,0) is the upper-left corner.
|
|
|
|
*/
|
|
|
|
if ((gameBoard->get( x, y-1 ) == INNERBBT) ||
|
|
|
|
(gameBoard->get( x, y-1 ) == BALLBBT)) { d = 0; }
|
|
|
|
else if ((gameBoard->get( x+1, y ) == INNERBBT) ||
|
|
|
|
(gameBoard->get( x+1, y ) == BALLBBT)) { d = 1; }
|
|
|
|
else if ((gameBoard->get( x, y+1 ) == INNERBBT) ||
|
|
|
|
(gameBoard->get( x, y+1 ) == BALLBBT)) { d = 2; }
|
|
|
|
else if ((gameBoard->get( x-1, y ) == INNERBBT) ||
|
|
|
|
(gameBoard->get( x-1, y ) == BALLBBT)) { d = 3; }
|
|
|
|
else return WRONGSTART;
|
|
|
|
/*
|
|
|
|
And now trace the ray.
|
|
|
|
*/
|
|
|
|
while (1) {
|
|
|
|
switch (d) {
|
|
|
|
case 0:
|
|
|
|
slx = -1; scx = 0; srx = 1;
|
|
|
|
sly = -1; scy = -1; sry = -1;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
slx = 1; scx = 1; srx = 1;
|
|
|
|
sly = -1; scy = 0; sry = 1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
slx = 1; scx = 0; srx = -1;
|
|
|
|
sly = 1; scy = 1; sry = 1;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
slx = -1; scx = -1; srx = -1;
|
|
|
|
sly = 1; scy = 0; sry = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
directionChanged = FALSE;
|
|
|
|
if (gameBoard->get( x+scx, y+scy ) == LASERBBT) {
|
|
|
|
type = DETOUR;
|
|
|
|
*endX = x+scx;
|
|
|
|
*endY = y+scy;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (gameBoard->get( x+scx, y+scy ) == BALLBBT) {
|
|
|
|
type = HIT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
refl = 0;
|
|
|
|
if (gameBoard->get( x+slx, y+sly ) == BALLBBT) {
|
|
|
|
type = REFLECTION;
|
|
|
|
if (gameBoard->get( x, y ) == LASERBBT) break;
|
|
|
|
directionChanged = TRUE;
|
|
|
|
refl += 1;
|
|
|
|
}
|
|
|
|
if (gameBoard->get( x+srx, y+sry ) == BALLBBT) {
|
|
|
|
type = REFLECTION;
|
|
|
|
if (gameBoard->get( x, y ) == LASERBBT) break;
|
|
|
|
directionChanged = TRUE;
|
|
|
|
refl +=2;
|
|
|
|
}
|
|
|
|
// turn to the right
|
|
|
|
if (refl == 1) d = (d + 1) % 4;
|
|
|
|
// turn to the left
|
|
|
|
if (refl == 2) if ((d -= 1) < 0) d += 4;
|
|
|
|
// turn back -- no need to trace again the same way
|
|
|
|
if (refl == 3) break;
|
|
|
|
if (!directionChanged) {
|
|
|
|
x += scx;
|
|
|
|
y += scy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Remaps the gameBoard to its graphic representation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::remap( RectOnArray *gam, RectOnArray *gra )
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
for (j = 0; j < (gam->height()); j++) {
|
|
|
|
for (i = 0; i < (gam->width()); i++) {
|
|
|
|
switch (gam->get( i,j )) {
|
|
|
|
case BALLBBT: if (tutorial) { gra->set( i,j, WBALLBBG ); break; }
|
|
|
|
case INNERBBT: gra->set( i,j, INNERBBG ); break;
|
|
|
|
case OUTERBBT: gra->set( i,j, OUTERBBG ); break;
|
|
|
|
case LASERBBT: gra->set( i,j, LASERBBG ); break;
|
|
|
|
default: gra->set( i,j, OUTERBBG );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Processes the user input.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void KBBGame::gotInputAt( int col, int row, int state )
|
|
|
|
{
|
|
|
|
RectOnArray *r = gr->getGraphicBoard();
|
|
|
|
int type = r->get( col, row );
|
|
|
|
int x, y;
|
|
|
|
int ex, ey;
|
|
|
|
int w = gameBoard->width() - 2;
|
|
|
|
int h = gameBoard->height() - 2;
|
|
|
|
|
|
|
|
if (state & TQt::LeftButton) {
|
|
|
|
switch (type) {
|
|
|
|
case WBALLBBG: // because of the tutorial mode
|
|
|
|
case INNERBBG:
|
|
|
|
r->set( col, row, TBALLBBG );
|
|
|
|
ballsPlaced++;
|
|
|
|
break;
|
|
|
|
case MARK1BBG:
|
|
|
|
r->set( col, row, INNERBBG );
|
|
|
|
break;
|
|
|
|
case TBALLBBG:
|
|
|
|
r->set( col, row, INNERBBG );
|
|
|
|
ballsPlaced--;
|
|
|
|
break;
|
|
|
|
case LASERBBG:
|
|
|
|
int endX, endY, result;
|
|
|
|
result = traceRay( col, row, &endX, &endY );
|
|
|
|
r->set( col, row, LFIREBBG );
|
|
|
|
//kdDebug << endX << " " << endY << endl;
|
|
|
|
if (col == 1) x = 0; else
|
|
|
|
if (col == w) x = w + 1;
|
|
|
|
else x = col;
|
|
|
|
|
|
|
|
if (row == 1) y = 0; else
|
|
|
|
if (row == h) y = h + 1;
|
|
|
|
else y = row;
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
case DETOUR:
|
|
|
|
r->set( endX, endY, LFIREBBG );
|
|
|
|
r->set( x, y, detourCounter );
|
|
|
|
if (endX == 1) ex = 0; else
|
|
|
|
if (endX == w) ex = w + 1;
|
|
|
|
else ex = endX;
|
|
|
|
if (endY == 1) ey = 0; else
|
|
|
|
if (endY == h) ey = h + 1;
|
|
|
|
else ey = endY;
|
|
|
|
r->set( ex, ey, detourCounter-- );
|
|
|
|
gr->updateElement( x, y );
|
|
|
|
gr->updateElement( ex, ey );
|
|
|
|
gr->updateElement( endX, endY );
|
|
|
|
setScore( score+2 );
|
|
|
|
break;
|
|
|
|
case REFLECTION:
|
|
|
|
r->set( x, y, RLASERBBG );
|
|
|
|
gr->updateElement( x, y );
|
|
|
|
setScore( score+1 );
|
|
|
|
break;
|
|
|
|
case HIT:
|
|
|
|
r->set( x, y, HLASERBBG );
|
|
|
|
gr->updateElement( x, y );
|
|
|
|
setScore( score+1 );
|
|
|
|
break;
|
|
|
|
case WRONGSTART:
|
|
|
|
kdDebug(12009) << "Wrong start?! It should't happen!!" << endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (state & TQt::RightButton) {
|
|
|
|
switch (type) {
|
|
|
|
case INNERBBG:
|
|
|
|
r->set( col, row, MARK1BBG );
|
|
|
|
break;
|
|
|
|
/*case MARK1BBG:
|
|
|
|
r->set( col, row, INNERBBG );
|
|
|
|
break;*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gr->updateElement( col, row );
|
|
|
|
updateStats();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KBBGame::initTDEAction()
|
|
|
|
{
|
|
|
|
// game
|
|
|
|
KStdGameAction::gameNew(this, TQT_SLOT(newGame()), actionCollection());
|
|
|
|
(void)new TDEAction( i18n("&Give Up"), SmallIcon("giveup"), 0, this, TQT_SLOT(giveUp()), actionCollection(), "game_giveup" );
|
|
|
|
(void)new TDEAction( i18n("&Done"), SmallIcon("done"), 0, this, TQT_SLOT(gameFinished()), actionCollection(), "game_done" );
|
|
|
|
(void)new TDEAction( i18n("&Resize"), 0, this, TQT_SLOT(slotResize()), actionCollection(), "game_resize" );
|
|
|
|
KStdGameAction::quit(this, TQT_SLOT(close()), actionCollection());
|
|
|
|
|
|
|
|
|
|
|
|
// settings
|
|
|
|
sizeAction = new TDESelectAction( i18n("&Size"), 0, this, TQT_SLOT(slotSize()), actionCollection(), "options_size");
|
|
|
|
TQStringList list;
|
|
|
|
list.append(i18n(" 8 x 8 "));
|
|
|
|
list.append(i18n(" 10 x 10 "));
|
|
|
|
list.append(i18n(" 12 x 12 "));
|
|
|
|
sizeAction->setItems(list);
|
|
|
|
|
|
|
|
ballsAction = new TDESelectAction( i18n("&Balls"), 0, this, TQT_SLOT(slotBalls()), actionCollection(), "options_balls");
|
|
|
|
list.clear();
|
|
|
|
list.append(i18n(" 4 "));
|
|
|
|
list.append(i18n(" 6 "));
|
|
|
|
list.append(i18n(" 8 "));
|
|
|
|
ballsAction->setItems(list);
|
|
|
|
tutorialAction = new TDEToggleAction( i18n("&Tutorial"), 0, this, TQT_SLOT(tutorialSwitch()), actionCollection(), "options_tutorial" );
|
|
|
|
// KStdAction::keyBindings(guiFactory(), TQT_SLOT(configureShortcuts()),
|
|
|
|
//actionCollection());
|
|
|
|
|
|
|
|
// keyboard only
|
|
|
|
(void)new TDEAction( i18n("Move Down"), TQt::Key_Down, gr, TQT_SLOT(slotDown()), actionCollection(), "move_down" );
|
|
|
|
(void)new TDEAction( i18n("Move Up"), TQt::Key_Up, gr, TQT_SLOT(slotUp()), actionCollection(), "move_up" );
|
|
|
|
(void)new TDEAction( i18n("Move Left"), TQt::Key_Left, gr, TQT_SLOT(slotLeft()), actionCollection(), "move_left" );
|
|
|
|
(void)new TDEAction( i18n("Move Right"), TQt::Key_Right, gr, TQT_SLOT(slotRight()), actionCollection(), "move_right" );
|
|
|
|
(void)new TDEAction( i18n("Trigger Action"), TQt::Key_Return, gr, TQT_SLOT(slotInput()), actionCollection(), "move_trigger" );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KBBGame::slotResize()
|
|
|
|
{
|
|
|
|
setMinSize();
|
|
|
|
gameResize();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kbbgame.moc"
|