|
|
|
/*
|
|
|
|
* ksame 0.4 - simple Game
|
|
|
|
* Copyright (C) 1997,1998 Marcus Kreutzberger
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqbitmap.h>
|
|
|
|
#include <tqimage.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "StoneWidget.moc"
|
|
|
|
|
|
|
|
|
|
|
|
struct StoneSlice {
|
|
|
|
TQPixmap stone;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
StoneWidget::StoneWidget( TQWidget *parent, int x, int y )
|
|
|
|
: TQWidget(parent,"StoneWidget"), stonefield(x,y)
|
|
|
|
{
|
|
|
|
setBackgroundPixmap(TQPixmap(locate("wallpaper", "Time-For-Lunch-2.jpg")));
|
|
|
|
TQPixmap stonemap(locate("appdata", "stones.png"));
|
|
|
|
|
|
|
|
assert(!stonemap.isNull());
|
|
|
|
|
|
|
|
slice=0;
|
|
|
|
maxslices=30;
|
|
|
|
maxcolors=4;
|
|
|
|
|
|
|
|
sizex=x;
|
|
|
|
sizey=y;
|
|
|
|
|
|
|
|
stone_width=stonemap.width()/(maxslices+1);
|
|
|
|
stone_height=stonemap.height()/maxcolors;
|
|
|
|
|
|
|
|
map = new StoneSlice*[maxcolors];
|
|
|
|
TQBitmap mask;
|
|
|
|
for (int c = 0; c < maxcolors; c++) {
|
|
|
|
map[c] = new StoneSlice[maxslices];
|
|
|
|
|
|
|
|
for (int s = 0; s < maxslices; s++) {
|
|
|
|
map[c][s].stone.resize(stone_width, stone_height);
|
|
|
|
assert(!map[c][s].stone.isNull());
|
|
|
|
bitBlt(&map[c][s].stone, 0, 0,
|
|
|
|
&stonemap, stone_width * s,
|
|
|
|
c*stone_height,
|
|
|
|
stone_width,stone_height,CopyROP,false);
|
|
|
|
TQImage im = map[c][s].stone.convertToImage();
|
|
|
|
mask = im.createHeuristicMask();
|
|
|
|
map[c][s].stone.setMask(mask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
field_height=stone_height*sizey;
|
|
|
|
field_width=stone_width*sizex;
|
|
|
|
|
|
|
|
setMouseTracking(true);
|
|
|
|
|
|
|
|
// TQColor c(115,115,115);
|
|
|
|
// setBackgroundColor(c);
|
|
|
|
|
|
|
|
// emit s_sizechanged();
|
|
|
|
startTimer( 100 );
|
|
|
|
history.setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
StoneWidget::~StoneWidget() {
|
|
|
|
for (int c = 0; c < maxcolors; c++) {
|
|
|
|
delete [] map[c];
|
|
|
|
}
|
|
|
|
delete [] map;
|
|
|
|
|
|
|
|
setMouseTracking(false);
|
|
|
|
killTimers();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
StoneWidget::board() {
|
|
|
|
return stonefield.getBoard();
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
StoneWidget::score() {
|
|
|
|
return stonefield.getScore();
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
StoneWidget::count(int color) {
|
|
|
|
return stonefield.count(color);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
StoneWidget::marked() {
|
|
|
|
return stonefield.getMarked();
|
|
|
|
}
|
|
|
|
|
|
|
|
QSize
|
|
|
|
StoneWidget::size() {
|
|
|
|
return TQSize(sizex,sizey);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
StoneWidget::colors() {
|
|
|
|
return stonefield.getColors();
|
|
|
|
}
|
|
|
|
|
|
|
|
QSize
|
|
|
|
StoneWidget::sizeHint () const {
|
|
|
|
return TQSize(field_width,field_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::newGame(unsigned int board,int colors) {
|
|
|
|
stonefield.newGame(board,colors);
|
|
|
|
history.clear();
|
|
|
|
modified= false;
|
|
|
|
emit s_newgame();
|
|
|
|
emit s_colors(stonefield.getColors());
|
|
|
|
emit s_board(stonefield.getBoard());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::reset() {
|
|
|
|
stonefield.reset();
|
|
|
|
history.clear();
|
|
|
|
emit s_newgame();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::unmark() {
|
|
|
|
stonefield.unmark();
|
|
|
|
emit s_marked(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StoneWidget::undoPossible() const {
|
|
|
|
if (stonefield.isGameover()) return false;
|
|
|
|
return stonefield.undoPossible();
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
StoneWidget::undo(int count) {
|
|
|
|
if (stonefield.isGameover()) return 0;
|
|
|
|
|
|
|
|
int ret_val=stonefield.undo(count);
|
|
|
|
|
|
|
|
TQPoint p=mapFromGlobal(cursor().pos());
|
|
|
|
int x=p.x();
|
|
|
|
int y=p.y();
|
|
|
|
if (x<0||y<0||x>=field_width||y>=field_height) {
|
|
|
|
emit s_score(stonefield.getMarked());
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
int marked=stonefield.mark(x/stone_width,y/stone_height);
|
|
|
|
emit s_marked(marked);
|
|
|
|
slice=0;
|
|
|
|
emit s_score(stonefield.getScore());
|
|
|
|
modified= (stonefield.getScore()>0);
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StoneWidget::isGameover() {
|
|
|
|
return stonefield.isGameover();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StoneWidget::hasBonus() {
|
|
|
|
return stonefield.gotBonus(); // don't ask me why the names differ... ;-| [hlm]
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StoneWidget::isOriginalBoard() {
|
|
|
|
return !modified;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoneWidget::readProperties(KConfig *conf) {
|
|
|
|
Q_ASSERT(conf);
|
|
|
|
|
|
|
|
history.clear();
|
|
|
|
|
|
|
|
if (!conf->hasKey("Board")||
|
|
|
|
!conf->hasKey("Colors")||
|
|
|
|
!conf->hasKey("Stones")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
newGame(conf->readNumEntry("Board"),conf->readNumEntry("Colors"));
|
|
|
|
|
|
|
|
TQStrList list;
|
|
|
|
conf->readListEntry("Stones",list);
|
|
|
|
|
|
|
|
for (const char *item=list.first();item;item=list.next()) {
|
|
|
|
int x=-1,y=-1;
|
|
|
|
if (sscanf(item,"%02X%02X",&x,&y)!=2) break;
|
|
|
|
history.append(new TQPoint(x,y));
|
|
|
|
stonefield.remove(x,y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::saveProperties(KConfig *conf) {
|
|
|
|
Q_ASSERT(conf);
|
|
|
|
|
|
|
|
TQStrList list(true);
|
|
|
|
TQString tmp;
|
|
|
|
|
|
|
|
for (TQPoint *item=history.first();item;item=history.next()) {
|
|
|
|
tmp.sprintf("%02X%02X",item->x(),item->y());
|
|
|
|
list.append(tmp.ascii());
|
|
|
|
}
|
|
|
|
|
|
|
|
conf->writeEntry("Stones",list);
|
|
|
|
conf->writeEntry("Board",stonefield.getBoard());
|
|
|
|
conf->writeEntry("Colors",stonefield.getColors());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::timerEvent( TQTimerEvent * ) {
|
|
|
|
TQPoint p=mapFromGlobal(cursor().pos());
|
|
|
|
int x=p.x();
|
|
|
|
int y=p.y();
|
|
|
|
if (x<0||y<0||x>=field_width||y>=field_height)
|
|
|
|
stonefield.unmark();
|
|
|
|
slice=(slice+1)%maxslices;
|
|
|
|
paintEvent(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::paintEvent( TQPaintEvent *e ) {
|
|
|
|
|
|
|
|
Stone *stone=stonefield.getField();
|
|
|
|
|
|
|
|
for (int y=0;y<sizey;y++) {
|
|
|
|
int cy = y * stone_height;
|
|
|
|
|
|
|
|
for (int x=0;x<sizex;x++) {
|
|
|
|
int cx = stone_width * x;
|
|
|
|
|
|
|
|
bool redraw=stone->marked||stone->changed;
|
|
|
|
|
|
|
|
if (!redraw&&e) {
|
|
|
|
TQRect r(cx,cy,stone_width,stone_height);
|
|
|
|
redraw=r.intersects(e->rect());
|
|
|
|
}
|
|
|
|
if (redraw) {
|
|
|
|
stone->changed=false;
|
|
|
|
if (stone->color) {
|
|
|
|
|
|
|
|
int tslice = stone->marked?slice:0;
|
|
|
|
bitBlt(this,cx,cy,
|
|
|
|
&map[stone->color-1][tslice].stone,
|
|
|
|
0, 0,
|
|
|
|
stone_width,stone_height,CopyROP,FALSE);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
erase(cx, cy, stone_width, stone_height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stone++; // naechster Stein.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::mousePressEvent ( TQMouseEvent *e) {
|
|
|
|
|
|
|
|
if (stonefield.isGameover()) return;
|
|
|
|
|
|
|
|
int x=e->pos().x();
|
|
|
|
int y=e->pos().y();
|
|
|
|
if (x<0||y<0||x>=field_width||y>=field_height) return;
|
|
|
|
|
|
|
|
int sx=x/stone_width;
|
|
|
|
int sy=y/stone_height;
|
|
|
|
|
|
|
|
if (stonefield.remove(sx, sy)) {
|
|
|
|
history.append(new TQPoint(sx, sy));
|
|
|
|
|
|
|
|
emit s_remove(sx, sy);
|
|
|
|
|
|
|
|
stonefield.mark(sx,sy);
|
|
|
|
emit s_marked(stonefield.getMarked());
|
|
|
|
modified= true;
|
|
|
|
|
|
|
|
emit s_score(stonefield.getScore());
|
|
|
|
if (stonefield.isGameover()) emit s_gameover();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StoneWidget::mouseMoveEvent ( TQMouseEvent *e)
|
|
|
|
{
|
|
|
|
if (stonefield.isGameover()) {
|
|
|
|
stonefield.unmark();
|
|
|
|
emit s_marked(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x=e->pos().x();
|
|
|
|
int y=e->pos().y();
|
|
|
|
if (x<0||y<0||x>=field_width||y>=field_height) return;
|
|
|
|
|
|
|
|
int marked=stonefield.mark(x/stone_width,y/stone_height);
|
|
|
|
if (marked>=0) {
|
|
|
|
emit s_marked(marked);
|
|
|
|
slice=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|