Source Code (Use browser search to find items of interest.)
Class Index
kreversi'Board (./kdegames/kreversi/board.h:51)
class Board : public QWidget {
Q_OBJECT
public:
enum { READY = 1, THINKING = 2, HINT = 3};
Board(QWidget *parent = 0);
~Board();
void newGame();
int humanIs();
int computerIs();
void getScore(int&, int&);
void setStrength(int);
int getStrength();
void interrupt();
bool interrupted();
void doContinue();
void undo();
void hint();
// starts all: emits some signal, so it can't be called from
// constructor
void start();
// event stuff
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *);
void timerEvent(QTimerEvent *);
QSize sizeHint() const;
/// stuff for zooming
bool canZoomIn();
bool canZoomOut();
void zoomIn();
void zoomOut();
void setZoom(int);
int getZoom() const;
void switchSides();
int getState();
void setState(int);
void setAnimationSpeed(int);
int animationSpeed();
int getMoveNumber();
void loadChips(const char *);
QString chipsName();
void loadGame(KConfig *, bool noupdate = FALSE);
void saveGame(KConfig *);
bool canLoad(KConfig *);
public slots:
void setColor(const QColor &);
void setPixmap(QPixmap &);
protected slots:
void slotFieldClicked(int, int);
signals:
void signalFieldClicked(int, int);
void score();
void sizeChange();
void gameWon(int);
void statusChange(int);
void illegalMove();
void turn(int);
void strengthChanged(int);
private:
void gameEnded();
void computerMakeMove();
void updateBoard(bool force = FALSE);
void drawPiece(int row, int col, bool force = FALSE);
void drawOnePiece(int row, int col, int color);
void loadPixmaps();
void adjustSize();
void animateChanged(Move m);
void animateChangedRow(int row, int col, int dy, int dx);
void rotateChip(int row, int col);
bool isField(int row, int col);
void scaleOneChip(int i);
private:
QString chipname;
Engine e;
Game g;
int _status;
int _size;
int oldsizehint;
int _zoom;
int human;
int initTimerID, scaleTimerID;
bool nopaint;
QPixmap bg;
// the chips
QPixmap *chip[25];
QPixmap allchips;
int anim_speed;
};
kreversi'Board::Board() (./kdegames/kreversi/board.cpp:68)
Board::Board(QWidget *parent) : QWidget(parent) {
setAnimationSpeed(DEFAULT_ANIMATION_DELAY);
setUpdatesEnabled(FALSE);
// ensure that the first time adjustsize does
// pixmap loading
oldsizehint = -1;
for(int i = 0; i < CHIP_MAX; i++)
chip[i] = 0;
loadChips("chips.xpm");
nopaint = FALSE;
human = Score::BLACK;
_size = 32;
_zoom = 100;
setStrength(4);
connect(this, SIGNAL(signalFieldClicked(int, int)),
this, SLOT(slotFieldClicked(int, int)));
scaleTimerID = -1;
}
kreversi'Board::~Board() (./kdegames/kreversi/board.cpp:94)
Board::~Board() {
for(int i = 0; i < CHIP_MAX; i++)
if(chip[i])
delete chip[i];
}
kreversi'Board::start() (./kdegames/kreversi/board.cpp:100)
void Board::start() {
// make sure a signal is emitted
setStrength(e.GetStrength());
newGame();
adjustSize();
setUpdatesEnabled(TRUE);
}
kreversi'Board::loadChips() (./kdegames/kreversi/board.cpp:108)
void Board::loadChips(const char *filename) {
allchips.load(PICDATA(filename));
chipname = filename;
loadPixmaps();
}
kreversi'Board::chipsName() (./kdegames/kreversi/board.cpp:114)
QString Board::chipsName() {
return chipname;
}
kreversi'Board::getMoveNumber() (./kdegames/kreversi/board.cpp:119)
int Board::getMoveNumber() {
return g.GetMoveNumber();
}
// negative speed is allowed. if speed is negative,
// no animations are displayed
kreversi'Board::setAnimationSpeed() (./kdegames/kreversi/board.cpp:125)
void Board::setAnimationSpeed(int speed) {
if(speed <= 10)
anim_speed = speed;
}
kreversi'Board::animationSpeed() (./kdegames/kreversi/board.cpp:130)
int Board::animationSpeed() {
return anim_speed;
}
// ensure that signals at the beginning are emited if
// the parent has already setup it's connecions
kreversi'Board::timerEvent() (./kdegames/kreversi/board.cpp:136)
void Board::timerEvent(QTimerEvent *t) {
if(t->timerId() == initTimerID) {
killTimer(t->timerId());
initTimerID = -1;
}
// check if all chips are already scaled,
// if not scale them. If all chips are
// already scaled, kill the timer
if(t->timerId() == scaleTimerID) {
for(int i = 0; i < CHIP_MAX; i++)
if(chip[i] == 0) {
scaleOneChip(i);
return;
}
killTimer(t->timerId());
scaleTimerID = -1;
}
}
/// takes back on move
kreversi'Board::undo() (./kdegames/kreversi/board.cpp:160)
void Board::undo() {
if((getState() == READY) && (g.GetMoveNumber() != 0)) {
g.TakeBackMove();
g.TakeBackMove();
update();
}
}
/// interrupt thinking of game engine
kreversi'Board::interrupt() (./kdegames/kreversi/board.cpp:170)
void Board::interrupt() {
e.SetInterrupt(TRUE);
}
kreversi'Board::interrupted() (./kdegames/kreversi/board.cpp:174)
bool Board::interrupted() {
return ((g.GetWhoseTurn() == computerIs()) && (getState() == THINKING));
}
/// continues a move if it was prior interrupted
kreversi'Board::doContinue() (./kdegames/kreversi/board.cpp:180)
void Board::doContinue() {
if(interrupted())
computerMakeMove();
}
/// adjusts the size
kreversi'Board::adjustSize() (./kdegames/kreversi/board.cpp:187)
void Board::adjustSize() {
// do only resize if size has really change to avoid a flickering display
if(sizeHint().width() != oldsizehint) {
loadPixmaps();
resize(sizeHint());
emit sizeChange();
oldsizehint = sizeHint().width();
}
}
/// returns which color the human plays
kreversi'Board::humanIs() (./kdegames/kreversi/board.cpp:199)
int Board::humanIs() {
return human;
}
/// returns which color the computer plays
kreversi'Board::computerIs() (./kdegames/kreversi/board.cpp:205)
int Board::computerIs() {
if(human == Score::BLACK)
return Score::WHITE;
else
return Score::BLACK;
}
/// starts a new game
kreversi'Board::newGame() (./kdegames/kreversi/board.cpp:214)
void Board::newGame() {
// return;
g.Reset();
updateBoard(TRUE);
setState(READY);
emit turn(Score::BLACK);
// computer makes first move
if(human == Score::WHITE)
computerMakeMove();
}
/// handles mouse clicks
kreversi'Board::mousePressEvent() (./kdegames/kreversi/board.cpp:229)
void Board::mousePressEvent(QMouseEvent *e) {
if(getState() == READY) {
int px = (e->pos().x()-2) / ((_size *5 / 4) * _zoom / 100);
int py = (e->pos().y()-2) / ((_size *5 / 4) * _zoom / 100);
emit signalFieldClicked(py, px);
} else if(getState() == HINT)
setState(READY);
else
emit illegalMove();
}
/// handles piece settings
kreversi'Board::slotFieldClicked() (./kdegames/kreversi/board.cpp:242)
void Board::slotFieldClicked(int row, int col) {
if(getState() == READY) {
int color = g.GetWhoseTurn();
/// makes a human move
Move m(col + 1, row + 1, color);
if(g.MoveIsLegal(m)) {
// playSound("click.wav");
g.MakeMove(m);
animateChanged(m);
if(!g.MoveIsAtAllPossible()) {
updateBoard();
setState(READY);
gameEnded();
return;
}
updateBoard();
if(color != g.GetWhoseTurn())
computerMakeMove();
} else
emit illegalMove();
}
}
/// makes a computer move
kreversi'Board::computerMakeMove() (./kdegames/kreversi/board.cpp:271)
void Board::computerMakeMove() {
// check if the computer can move
int color = g.GetWhoseTurn();
int opponent = g.GetWhoseTurnOpponent();
emit turn(color);
if(g.MoveIsPossible(color)) {
setState(THINKING);
do {
Move m;
if(!g.MoveIsAtAllPossible()) {
setState(READY);
gameEnded();
return;
}
m = e.ComputeMove(g);
if(m.GetX() == -1) {
setState(READY);
return;
}
//playSound("click.wav");
g.MakeMove(m);
animateChanged(m);
updateBoard();
} while(!g.MoveIsPossible(opponent));
emit turn(opponent);
setState(READY);
if(!g.MoveIsAtAllPossible()) {
setState(READY);
gameEnded();
return;
}
}
}
/// returns the current score
kreversi'Board::getScore() (./kdegames/kreversi/board.cpp:313)
void Board::getScore(int &black, int &white) {
black = g.GetScore(Score::BLACK);
white = g.GetScore(Score::WHITE);
}
/// calculate final score
kreversi'Board::gameEnded() (./kdegames/kreversi/board.cpp:320)
void Board::gameEnded() {
int b, w;
getScore(b, w);
if(b > w)
emit gameWon(Score::BLACK);
else if(b < w)
emit gameWon(Score::WHITE);
else
emit gameWon(Score::NOBODY);
emit turn(Score::NOBODY);
}
kreversi'Board::switchSides() (./kdegames/kreversi/board.cpp:334)
void Board::switchSides() {
if(getState() == READY) {
if(human == Score::WHITE)
human = Score::BLACK;
else
human = Score::WHITE;
emit score();
computerMakeMove();
}
}
kreversi'Board::getState() (./kdegames/kreversi/board.cpp:346)
int Board::getState() {
return _status;
}
kreversi'Board::setState() (./kdegames/kreversi/board.cpp:350)
void Board::setState(int nstatus) {
_status = nstatus;
emit statusChange(_status);
}
kreversi'Board::setStrength() (./kdegames/kreversi/board.cpp:356)
void Board::setStrength(int st) {
if((st > 1) && (st <= 10)) {
e.SetStrength(st);
emit strengthChanged(e.GetStrength());
}
}
kreversi'Board::getStrength() (./kdegames/kreversi/board.cpp:364)
int Board::getStrength() {
return e.GetStrength();
}
kreversi'Board::hint() (./kdegames/kreversi/board.cpp:369)
void Board::hint() {
if(getState() == READY) {
setState(THINKING);
Move m = e.ComputeMove(g);
setState(HINT);
if(m.GetX() != -1) {
for(int flash = 0; (flash < 100) && (getState() != READY); flash++) {
if(flash & 1)
drawOnePiece(m.GetY() - 1, m.GetX() - 1, Score::NOBODY);
else
drawOnePiece(m.GetY() - 1, m.GetX() - 1, g.GetWhoseTurn());
// keep GUI alive while waiting
for(int dummy = 0; dummy < 5; dummy++) {
usleep(HINT_BLINKRATE/5);
qApp->processEvents();
}
}
drawOnePiece(m.GetY() - 1, m.GetX() - 1,
g.GetSquare(m.GetX(), m.GetY()));
}
setState(READY);
}
}
// ********************************************************
// ********************************************************
//
// functions related to drawing/painting
//
// ********************************************************
// ********************************************************
// flash all pieces which are turned
// NOTE: this code is white a hack. Should make it better
kreversi'Board::animateChanged() (./kdegames/kreversi/board.cpp:406)
void Board::animateChanged(Move m) {
if(animationSpeed() <= 0)
return;
// since now all chips are needed, ensure that all of them
// are loaded
for(int i = 0; i < CHIP_MAX; i++)
if(chip[i] == 0)
scaleOneChip(i);
// draw the new piece
drawOnePiece(m.GetY()-1, m.GetX()-1, m.GetPlayer());
soundSync();
for(int dx = -1; dx < 2; dx++)
for(int dy = -1; dy < 2; dy++)
if((dx != 0) || (dy != 0))
animateChangedRow(m.GetY()-1, m.GetX()-1, dy, dx);
}
kreversi'Board::isField() (./kdegames/kreversi/board.cpp:428)
bool Board::isField(int row, int col) {
return (bool)((row > -1) && (row < 8) && (col > -1) && (col < 8));
}
kreversi'Board::animateChangedRow() (./kdegames/kreversi/board.cpp:433)
void Board::animateChangedRow(int row, int col, int dy, int dx) {
row = row + dy;
col = col + dx;
while(isField(row, col)) {
if(g.wasTurned(col+1, row+1)) {
playSound("reversi-click.wav");
rotateChip(row, col);
soundSync();
} else
return;
col += dx;
row += dy;
}
}
// NOTE: this code is S**T
kreversi'Board::rotateChip() (./kdegames/kreversi/board.cpp:450)
void Board::rotateChip(int row, int col) {
// check which direction the chip has to be rotated
// if the new chip is white, the chip was black first,
// so lets begin at index 1, otherwise it was white
int color = g.GetSquare(col+1, row+1);
int from, end, delta;
if(color == Score::WHITE) {
from = CHIP_BLACK + 2;
end = CHIP_WHITE - 2;
delta = 1;
} else if(color == Score::BLACK) {
from = CHIP_WHITE -2;
end = CHIP_BLACK + 2;
delta = -1;
} else
return;
int px = (col * (_size / 4) + col * _size + 3) * _zoom / 100 + 2;
int py = (row * (_size / 4) + row * _size + 3) * _zoom / 100 + 2;
// copy the background of an empty square
drawOnePiece(row, col, Score::NOBODY);
QPixmap saveunder;
int p_width = (sizeHint().width())/8;
int p_height = (sizeHint().height())/8;
saveunder.resize(p_width, p_height);
bitBlt(&saveunder, 0, 0, this, p_width * col, p_height * row,
p_width, p_height, CopyROP);
for(int i = from; i != end; i += delta) {
// copy the piece over a copy of the saveunder, this will reduce flicker
QPixmap tmp = saveunder;
bitBlt(&tmp, px % p_width, py % p_height, chip[i], 0, 0,
chip[i]->width(), chip[i]->height(), CopyROP);
QPainter p;
p.begin(this);
p.drawPixmap(p_width * col, p_height * row, tmp);
//p.drawPixmap(p_width * col, p_height * row, saveunder);
//p.drawPixmap(px, py, *chip[i]);
p.flush();
p.end();
usleep(ANIMATION_DELAY * anim_speed);
}
QPainter p;
p.begin(this);
p.drawPixmap(p_width * col, p_height * row, saveunder);
p.flush();
p.end();
drawOnePiece(row, col, color);
}
kreversi'Board::canZoomIn() (./kdegames/kreversi/board.cpp:503)
bool Board::canZoomIn() {
return (bool)(width() < 640);
}
kreversi'Board::canZoomOut() (./kdegames/kreversi/board.cpp:508)
bool Board::canZoomOut() {
return (bool)(width() > 200);
}
kreversi'Board::setZoom() (./kdegames/kreversi/board.cpp:513)
void Board::setZoom(int _new) {
if(((_new < _zoom) && canZoomOut()) ||
((_new > _zoom) && canZoomIn())) {
if(_new != _zoom) {
_zoom = _new;
adjustSize();
emit sizeChange();
}
}
}
kreversi'Board::getZoom() (./kdegames/kreversi/board.cpp:525)
int Board::getZoom() const {
return _zoom;
}
kreversi'Board::zoomIn() (./kdegames/kreversi/board.cpp:530)
void Board::zoomIn() {
setZoom(_zoom + 20);
}
kreversi'Board::zoomOut() (./kdegames/kreversi/board.cpp:535)
void Board::zoomOut() {
setZoom(_zoom - 20);
}
kreversi'Board::scaleOneChip() (./kdegames/kreversi/board.cpp:540)
void Board::scaleOneChip(int i) {
if((i >= 0) && (i < CHIP_MAX)) {
// free pixmap if any
if(chip[i] != 0)
delete chip[i];
int w = allchips.width()/5;
int h = allchips.height()/5;
// make new pixmap
chip[i] = new QPixmap;
chip[i]->resize(30, 30);
chip[i]->fill(); // thanks to Stephan Kulow
// easy to understand, isn't it :-)
bitBlt(chip[i], 0, 0, &allchips, (i % 5) * w + 10, (i / 5) * h + 10,
30, 30, CopyROP);
// scale to final size
chip[i]->setMask(chip[i]->createHeuristicMask());
QWMatrix wm;
wm.scale((float)(0.01 * _zoom * _size) / 30,
(float)(0.01 * _zoom * _size) / 30);
*chip[i] = chip[i]->xForm(wm);
}
}
kreversi'Board::loadPixmaps() (./kdegames/kreversi/board.cpp:568)
void Board::loadPixmaps() {
// the chips CHIP_BLACK and CHIP_WHITE
// are needed immidiatly, so scale them. All other chips
// are scaled in the background (timerEvent) to make the
// program react faster to size events
for(int i = 0; i < CHIP_MAX; i++)
if(chip[i] != 0) {
delete chip[i];
chip[i] = 0;
}
scaleOneChip(CHIP_WHITE);
scaleOneChip(CHIP_BLACK);
// scale background (if any)
if(bg.width() != 0) {
QWMatrix wm3;
wm3.scale((float)(sizeHint().width()-4)/8.0/bg.width(),
(float)(sizeHint().height()-4)/8.0/bg.height());
setBackgroundPixmap(bg.xForm(wm3));
}
// start the timer to begin scaling of pixmaps (if needed)
if(scaleTimerID == -1)
scaleTimerID = startTimer(0);
}
kreversi'Board::updateBoard() (./kdegames/kreversi/board.cpp:595)
void Board::updateBoard(bool force) {
for(int row = 0; row < 8; row++)
for(int col = 0; col < 8; col++)
drawPiece(row, col, force);
emit score();
}
kreversi'Board::drawOnePiece() (./kdegames/kreversi/board.cpp:604)
void Board::drawOnePiece(int row, int col, int color) {
int px = (col * (_size / 4) + col * _size + 3) * _zoom / 100 + 2;
int py = (row * (_size / 4) + row * _size + 3) * _zoom / 100 + 2;
// ensure that the chips are loaded
if((chip[CHIP_BLACK] == 0) || (chip[CHIP_WHITE] == 0))
loadPixmaps();
QPainter p;
p.begin(this);
if(color == Score::NOBODY) {
nopaint = TRUE;
repaint(px, py, chip[CHIP_BLACK]->width(), chip[CHIP_BLACK]->height());
nopaint = FALSE;
} else if(color == Score::BLACK)
p.drawPixmap(px, py, *chip[CHIP_BLACK]);
else if(color == Score::WHITE)
p.drawPixmap(px, py, *chip[CHIP_WHITE]);
p.flush();
p.end();
}
kreversi'Board::drawPiece() (./kdegames/kreversi/board.cpp:627)
void Board::drawPiece(int row, int col, bool force) {
if(g.squareModified(col+1, row+1) || force) {
int color = g.GetSquare(col + 1, row + 1);
drawOnePiece(row, col, color);
}
}
kreversi'Board::paintEvent() (./kdegames/kreversi/board.cpp:635)
void Board::paintEvent(QPaintEvent *) {
int i, w = sizeHint().width() - 2;
if(!nopaint) {
QPainter p;
p.begin(this);
p.setPen(QPen(QColor("black"), 2));
// draw vertical lines
for(i = 1; i < 8; i++) {
int x = (i*(5 * _size / 4)) * _zoom / 100 + 2;
p.drawLine(x, 0, x, w);
}
// draw horizontal lines
for(i = 1; i < 8; i++) {
int y = (i*(5 * _size / 4)) * _zoom / 100 + 2;
p.drawLine(0, y, w, y);
}
p.drawRect(1, 1, w+1, w+1);
p.end();
updateBoard(TRUE);
}
}
kreversi'Board::sizeHint() (./kdegames/kreversi/board.cpp:664)
QSize Board::sizeHint() const {
int w = (8 * (_size/4) + 8 * _size) * _zoom / 100;
return QSize(w+2, w+2);
}
kreversi'Board::setPixmap() (./kdegames/kreversi/board.cpp:669)
void Board::setPixmap(QPixmap &pm) {
bg = pm;
// scale background (if any)
if(bg.width() != 0) {
QWMatrix wm3;
wm3.scale((float)(sizeHint().width()-4)/8.0/bg.width(),
(float)(sizeHint().height()-4)/8.0/bg.height());
setBackgroundPixmap(bg.xForm(wm3));
}
}
kreversi'Board::setColor() (./kdegames/kreversi/board.cpp:680)
void Board::setColor(const QColor &c) {
setBackgroundColor(c);
bg.resize(0, 0);
}
// saves the game. Only one game at a time can be saved
kreversi'Board::saveGame() (./kdegames/kreversi/board.cpp:686)
void Board::saveGame(KConfig *config) {
interrupt(); // stop thinking
config->writeEntry("NumberOfMoves", g.GetMoveNumber());
int nmoves = g.GetMoveNumber();
config->writeEntry("State", getState());
for(int i = nmoves; i > 0; i--) {
Move m = g.GetLastMove();
g.TakeBackMove();
QString s, idx;
s.sprintf("%d %d %d", m.GetX(), m.GetY(), m.GetPlayer());
idx.sprintf("Move_%d", i);
config->writeEntry(idx, s);
}
// save whose turn it is
config->writeEntry("WhoseTurn", human);
// all moves must be redone
loadGame(config, TRUE);
doContinue(); // continue possible move
}
// loads the game. Only one game at a time can be saved
kreversi'Board::loadGame() (./kdegames/kreversi/board.cpp:709)
void Board::loadGame(KConfig *config, bool noupdate) {
interrupt(); // stop thinking
int nmoves = config->readNumEntry("NumberOfMoves", -1);
if(nmoves > 0) {
g.Reset();
int movenumber = 1;
while(nmoves--) {
// read one move
QString idx;
idx.sprintf("Move_%d", movenumber++);
QString s = config->readEntry(idx);
int x, y, pl;
sscanf(s.data(), "%d %d %d", &x, &y, &pl);
Move m(x, y, pl);
g.MakeMove(m);
}
if(noupdate)
return;
human = config->readNumEntry("WhoseTurn");
updateBoard(TRUE);
setState(config->readNumEntry("State"));
if(interrupted())
doContinue();
else {
emit turn(Score::BLACK);
// computer makes first move
if(human == Score::WHITE)
computerMakeMove();
}
}
}
kreversi'Board::canLoad() (./kdegames/kreversi/board.cpp:746)
bool Board::canLoad(KConfig *config) {
int nmoves = config->readNumEntry("NumberOfMoves", -1);
return (bool)(nmoves > 0);
}