diff --git a/.gitignore b/.gitignore
index ff7d583..da9cdbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ toruschess.kdevses
*.o
moc_*
qrc_*
+ui_*
diff --git a/media/board1_dark.png b/media/board1_dark.png
new file mode 100644
index 0000000..9578ad1
Binary files /dev/null and b/media/board1_dark.png differ
diff --git a/media/board1_white.png b/media/board1_white.png
new file mode 100644
index 0000000..ea03fa6
Binary files /dev/null and b/media/board1_white.png differ
diff --git a/media/board2_dark.png b/media/board2_dark.png
new file mode 100644
index 0000000..b7075e6
Binary files /dev/null and b/media/board2_dark.png differ
diff --git a/media/board2_white.png b/media/board2_white.png
new file mode 100644
index 0000000..42c8730
Binary files /dev/null and b/media/board2_white.png differ
diff --git a/src/ai.cpp b/src/ai.cpp
index c7aade9..fe61551 100644
--- a/src/ai.cpp
+++ b/src/ai.cpp
@@ -57,8 +57,22 @@ namespace toruschess {
}
return mx;
}
-
-
+
+ Move ai::getMove(Field &field, Player curp, int depth) {
+ int balance = 0;
+ for (int x = 0; x < 8; x++)
+ for (int y = 0; y < 8; y++) {
+ Pos p(x,y);
+ balance += field.player(p) * piece_value[field.piece(p)];
+ }
+
+ Move move;
+ minimax(field, balance, curp, depth, &move);
+
+ return move;
+ }
+
+
Move ai::getMove(const Game *game) {
Player curp = NOPLAYER;
switch (game->state()) {
@@ -73,16 +87,6 @@ namespace toruschess {
}
Field field = *game->field();
- int balance = 0;
- for (int x = 0; x < 8; x++)
- for (int y = 0; y < 8; y++) {
- Pos p(x,y);
- balance += field.player(p) * piece_value[field.piece(p)];
- }
-
- Move move;
- minimax(field, balance, curp, 2, &move);
-
- return move;
+ return getMove(field, curp, 2);
}
}
diff --git a/src/ai.h b/src/ai.h
index 42e473d..f0a058e 100644
--- a/src/ai.h
+++ b/src/ai.h
@@ -28,6 +28,7 @@
namespace toruschess {
class ai{
public:
+ static Move getMove(Field &field, Player curp, int depth);
static Move getMove(const Game *game);
};
}
diff --git a/src/field2d.cpp b/src/field2d.cpp
index 6fd83bc..0123b29 100644
--- a/src/field2d.cpp
+++ b/src/field2d.cpp
@@ -131,11 +131,9 @@ namespace toruschess {
for (int y = 0; y < 8; y++) {
bool marked = m_marked[x][y];
int place = m_game->field()->place(Pos(x, y));
- /* #D18B47 for dark, #FFCE9E for white */
- QBrush fieldBG = ((x+y) % 2 == 1) ? QBrush(QColor(0xD1, 0x8B, 0x47)) : QBrush(QColor(0xFF, 0xCE, 0x9E));
QRect prect(x * pieceWidth, y * pieceHeight, pieceWidth - 1, pieceHeight - 1);
- pt.fillRect(prect, fieldBG);
+ m_lib->paint_board(pt, (x+y) % 2 == 1, prect);
m_lib->paint(pt, place, prect);
if (marked) {
int r = qMax(1, (pieceWidth + pieceHeight) / 36);
diff --git a/src/field3d.cpp b/src/field3d.cpp
index 1da54bd..2c0bccd 100644
--- a/src/field3d.cpp
+++ b/src/field3d.cpp
@@ -169,11 +169,9 @@ namespace toruschess {
for (int y = 0; y < 8; y++) {
bool marked = m_marked[x][y];
int place = m_game->field()->place(Pos(x, y));
- /* #D18B47 for dark, #FFCE9E for white */
- QBrush fieldBG = ((x+y) % 2 == 1) ? QBrush(QColor(0xD1, 0x8B, 0x47)) : QBrush(QColor(0xFF, 0xCE, 0x9E));
QRect prect(x * pieceSize, y * pieceSize, pieceSize - 1, pieceSize - 1);
- pt.fillRect(prect, fieldBG);
+ m_lib->paint_board(pt, (x+y) % 2 == 1, prect);
m_lib->paint(pt, place, prect);
if (marked) {
int r = qMax(1, (pieceSize + pieceSize) / 36);
diff --git a/src/media.qrc b/src/media.qrc
index 0c94b0b..d27351a 100644
--- a/src/media.qrc
+++ b/src/media.qrc
@@ -13,5 +13,9 @@
../media/Chess_qdt45.svg
../media/Chess_kdt45.svg
../media/pawn.3ds
+ ../media/board1_dark.png
+ ../media/board1_white.png
+ ../media/board2_dark.png
+ ../media/board2_white.png
diff --git a/src/optiondlg.cpp b/src/optiondlg.cpp
new file mode 100644
index 0000000..00322c0
--- /dev/null
+++ b/src/optiondlg.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Stefan Bühler *
+ * stbuehler@web.de *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#include "optiondlg.h"
+#include
+
+namespace toruschess {
+
+ OptionDlg::OptionDlg(Game *game, QWidget *parent)
+ : QDialog(parent), m_game(game) {
+ m_curMode = m_game->gameMode();
+ m_curAIStrength = m_game->aiStrength();
+ setupUi(this);
+
+ m_bgMode = new QButtonGroup(this);
+ m_bgMode->addButton(rb_mode1, HUMAN_HUMAN);
+ m_bgMode->addButton(rb_mode2, HUMAN_COMPUTER);
+ m_bgMode->addButton(rb_mode3, COMPUTER_HUMAN);
+ m_bgMode->addButton(rb_mode4, COMPUTER_COMPUTER);
+
+ dlgReset();
+
+ connect(m_game, SIGNAL(changedMode(GameMode)), this, SLOT(gameChangedMode(GameMode)));
+ connect(m_game, SIGNAL(changedAIStrength(int)), this, SLOT(gameChangedAIStrength(int)));
+
+ connect(this, SIGNAL(accepted()), this, SLOT(dlgAccept()));
+ connect(this, SIGNAL(rejected()), this, SLOT(dlgReset()));
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ connect(buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), this, SLOT(dlgReset()));
+ }
+
+ void OptionDlg::gameChangedMode(GameMode mode) {
+ if (m_curMode != mode) {
+ if (m_bgMode->checkedId() == m_curMode) {
+ m_bgMode->button(mode)->setChecked(true);
+ }
+ m_curMode = mode;
+ }
+ }
+
+ void OptionDlg::gameChangedAIStrength(int aiStrength) {
+ if (m_curAIStrength != aiStrength) {
+ if (sb_aiStrength->value() == m_curAIStrength) {
+ sb_aiStrength->setValue(aiStrength);
+ }
+ m_curAIStrength = aiStrength;
+ }
+ }
+
+ void OptionDlg::dlgReset() {
+ sb_aiStrength->setValue(m_curAIStrength);
+ m_bgMode->button(m_curMode)->setChecked(true);
+ }
+
+ void OptionDlg::dlgAccept() {
+ m_curAIStrength = sb_aiStrength->value();
+ m_game->setAiStrength(m_curAIStrength);
+ m_curMode = (GameMode) m_bgMode->checkedId();
+ m_game->setGameMode(m_curMode);
+ }
+
+}
diff --git a/src/optiondlg.h b/src/optiondlg.h
new file mode 100644
index 0000000..642f3f8
--- /dev/null
+++ b/src/optiondlg.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Stefan Bühler *
+ * stbuehler@web.de *
+ * *
+ * 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., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef TORUSCHESSOPTIONDLG_H
+#define TORUSCHESSOPTIONDLG_H
+
+#include
+#include
+#include "ui_optiondlg.h"
+
+#include "toruschess.h"
+
+/**
+ @author Stefan Bühler
+*/
+namespace toruschess {
+ class OptionDlg : public QDialog, private Ui::OptionDlg {
+ Q_OBJECT
+ public:
+ OptionDlg(Game *game, QWidget *parent = 0);
+
+ private slots:
+ void gameChangedMode(GameMode mode);
+ void gameChangedAIStrength(int aiStrength);
+
+ void dlgReset();
+ void dlgAccept();
+
+ private:
+ Game *m_game;
+ GameMode m_curMode;
+ int m_curAIStrength;
+ QButtonGroup *m_bgMode;
+ };
+
+}
+
+#endif
diff --git a/src/optiondlg.ui b/src/optiondlg.ui
new file mode 100644
index 0000000..919d64a
--- /dev/null
+++ b/src/optiondlg.ui
@@ -0,0 +1,123 @@
+
+ OptionDlg
+
+
+ Qt::ApplicationModal
+
+
+
+ 0
+ 0
+ 373
+ 227
+
+
+
+ Options
+
+
+ -
+
+
+ Opponent
+
+
+
-
+
+
+ Human vs. Human
+
+
+
+ -
+
+
+ Human vs. Computer
+
+
+
+ -
+
+
+ Computer vs. Human
+
+
+
+ -
+
+
+ Computer vs. Computer
+
+
+
+ -
+
+
+ QLayout::SetMinimumSize
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Computer strength (recursion depth)
+
+
+ sb_aiStrength
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 2
+
+
+ 7
+
+
+
+
+
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset
+
+
+
+
+
+
+ rb_mode1
+ rb_mode2
+ rb_mode3
+ rb_mode4
+ sb_aiStrength
+
+
+
+
diff --git a/src/piecelibrary.cpp b/src/piecelibrary.cpp
index 3f73328..05a92be 100644
--- a/src/piecelibrary.cpp
+++ b/src/piecelibrary.cpp
@@ -133,6 +133,9 @@ typedef size_t (*Lib3dsIoWriteFunc)(void *self, const void *buffer, size_t size)
PieceLibrary::PieceLibrary(QObject *parent)
: QObject(parent), m_pieces(0), m_buffers(0) {
+ m_board = new QImage*[2];
+ m_board[0] = new QImage(":/media/board2_white.png");
+ m_board[1] = new QImage(":/media/board2_dark.png");
m_pawn = read_3ds(loadResource(":/media/pawn.3ds"));
setSize(45, 45);
}
@@ -141,6 +144,7 @@ typedef size_t (*Lib3dsIoWriteFunc)(void *self, const void *buffer, size_t size)
if (m_pawn) lib3ds_file_free(m_pawn);
delete [] m_pieces;
delete [] m_buffers;
+ delete [] m_board;
}
void PieceLibrary::setSize(int width, int height) {
@@ -179,6 +183,9 @@ typedef size_t (*Lib3dsIoWriteFunc)(void *self, const void *buffer, size_t size)
pt.drawImage(rect, *m_buffers[place-1]);
}
+ void PieceLibrary::paint_board(QPainter &pt, bool darkField, const QRect &rect) const {
+ pt.drawImage(rect, *m_board[darkField ? 1 : 0]);
+ }
void PieceLibrary::paint_pawn() {
glEnableClientState(GL_VERTEX_ARRAY);
diff --git a/src/piecelibrary.h b/src/piecelibrary.h
index b78e535..ff0ba8b 100644
--- a/src/piecelibrary.h
+++ b/src/piecelibrary.h
@@ -42,11 +42,13 @@ namespace toruschess {
void paint(QPainter &pt, int place) const;
void paint(QPainter &pt, int place, const QRect &rect) const;
+ void paint_board(QPainter &pt, bool darkField, const QRect &rect) const;
+
void paint_pawn();
private:
QSvgRenderer **m_pieces;
- QImage **m_buffers;
+ QImage **m_buffers, **m_board;
int m_width, m_height;
Lib3dsFile *m_pawn;
diff --git a/src/src.pro b/src/src.pro
index 649ccc0..d75dcd5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -4,7 +4,8 @@ SOURCES += main.cpp \
field2d.cpp \
piecelibrary.cpp \
field3d.cpp \
- ai.cpp
+ ai.cpp \
+ optiondlg.cpp
TEMPLATE = app
CONFIG += warn_on \
thread \
@@ -22,7 +23,8 @@ toruschess.h \
field2d.h \
piecelibrary.h \
field3d.h \
- ai.h
+ ai.h \
+ optiondlg.h
LIBS += -l3ds
@@ -30,3 +32,5 @@ QMAKE_CXXFLAGS_RELEASE += -g
CONFIG -= release
+FORMS += optiondlg.ui
+
diff --git a/src/testgame.cpp b/src/testgame.cpp
index 7edf560..55e3db8 100644
--- a/src/testgame.cpp
+++ b/src/testgame.cpp
@@ -25,6 +25,9 @@
#include
#include
+#include
+#include
+
#include "field2d.h"
#include "field3d.h"
@@ -32,89 +35,7 @@
namespace toruschess {
- TestPlace::TestPlace(QWidget *parent, const PieceLibrary *lib, const Field *field, const Pos &p)
- : QWidget(parent), m_field(field), m_lib(lib), m_pos(p), m_mark(false) {
- setMinimumSize(m_lib->minPieceSize());
- }
-
- QSize TestPlace::sizeHint() const {
- return m_lib->pieceSize();
- }
-
- void TestPlace::paintEvent(QPaintEvent *) {
- QPainter pt(this);
- int pl = m_field->place(m_pos);
- if ((m_pos.x() + m_pos.y()) % 2) {
- // #D18B47
- pt.fillRect(rect(), QBrush(QColor(0xD1, 0x8B, 0x47)));
- } else {
- // #FFCE9E
- pt.fillRect(rect(), QBrush(QColor(0xFF, 0xCE, 0x9E)));
- }
- m_lib->paint(pt, pl);
- if (m_mark) {
- int r = qMax(1, (rect().width() + rect().height()) / 36);
- pt.setBrush(pl != 0 ? Qt::green : Qt::white);
- pt.setPen(Qt::red);
- pt.drawEllipse(QPoint(rect().width() / 2, rect().height() / 2), r, r);
- }
- }
-
- TestField::TestField(QWidget *parent, PieceLibrary *lib, Game *game) : QWidget(parent), m_lib(lib), m_game(game) {
- QGridLayout *layout = new QGridLayout();
- for (int y = 0; y < 8; y++) {
- for (int x = 0; x < 8; x++) {
- m_places[x][y] = new TestPlace(this, m_lib, m_game->field(), Pos(x, y));
- layout->addWidget(m_places[x][y], y, x);
- }
- }
- layout->setSpacing(0);
- setLayout(layout);
- show();
- }
-
- void TestField::markMoves(const QList &moves) {
- foreach(Move m, m_marked) m_places[m.to().x()][m.to().y()]->hideMark();
- m_marked = moves;
- foreach(Move m, m_marked) m_places[m.to().x()][m.to().y()]->showMark();
- update();
- }
-
- void TestField::resizeEvent(QResizeEvent *event) {
- m_lib->setSize(event->size().width()/8, event->size().height()/8);
- }
-
- void TestField::mousePressEvent(QMouseEvent *event) {
- if (event->button() == Qt::LeftButton) {
- QList moves;
- int x = (event->x() * 8) / width();
- int y = (event->y() * 8) / height();
- if (x < 0 || x >= 8 || y < 0 || y >= 8) {
- markMoves(moves);
- } else {
- moves = m_game->field()->validMoves(Pos(x, y));
- markMoves(moves);
- }
- }
- }
-
- void TestField::mouseReleaseEvent(QMouseEvent *event) {
- if (event->button() == Qt::LeftButton) {
- if (m_marked.size() == 0) return;
- Pos from = m_marked[0].from();
- QList moves;
- markMoves(QList());
- int x = (event->x() * 8) / width();
- int y = (event->y() * 8) / height();
- if (x < 0 || x >= 8 || y < 0 || y >= 8) {
- return;
- }
- Move m(m_game->field(), from, Pos(x, y));
- m_game->move(m);
- }
- }
-
- TestGame::TestGame(QWidget *parent) : QMainWindow(parent), m_game(new Game()) {
+ TestGame::TestGame(QWidget *parent) : QMainWindow(parent), m_game(new Game()), m_optionDlg(new OptionDlg(m_game, this)) {
setWindowTitle("Torus Chess");
// PieceLibrary *lib = new PieceLibrary(this);
// setCentralWidget(new TestField(this, lib, m_game));
@@ -123,16 +44,34 @@ namespace toruschess {
connect(m_game, SIGNAL(updated()), this, SLOT(gameUpdated()));
connect(m_game, SIGNAL(changed(GameState)), this, SLOT(gameChanged(GameState)));
m_game->restart();
+
+ QMenuBar *menuBar = new QMenuBar(this);
+ QMenu *menuGame = menuBar->addMenu("Game");
+ menuGame->addAction("New Game", this, SLOT(menuRestart()));
+ menuGame->addAction("Options", this, SLOT(menuOptions()));
+ menuGame->addSeparator();
+ menuGame->addAction("Quit", this, SLOT(close()));
+ setMenuBar(menuBar);
+
}
void TestGame::gameUpdated() {
- if (m_game->state() == TURN_BLACK) {
+/* if (m_game->state() == TURN_BLACK) {
Move m = ai::getMove(m_game);
if (m.valid()) m_game->move(m);
- }
+ }*/
}
void TestGame::gameChanged(GameState state) {
statusBar()->showMessage(state2string(state));
}
+
+ void TestGame::menuRestart() {
+ m_game->restart();
+ }
+
+ void TestGame::menuOptions() {
+ m_optionDlg->exec();
+ }
+
}
diff --git a/src/testgame.h b/src/testgame.h
index e5deed6..5181966 100644
--- a/src/testgame.h
+++ b/src/testgame.h
@@ -28,53 +28,13 @@
#include "toruschess.h"
#include "piecelibrary.h"
+#include "optiondlg.h"
+
/**
@author Stefan Bühler
*/
namespace toruschess {
- class TestPlace : public QWidget {
- Q_OBJECT
- public:
- TestPlace(QWidget *parent, const PieceLibrary *lib, const Field *field, const Pos &p);
-
- const Pos& pos() const { return m_pos; }
- const Field* field() const { return m_field; }
-
- virtual QSize sizeHint() const;
-
- void showMark() { m_mark = true; update(); }
- void hideMark() { m_mark = false; update(); }
-
- protected:
- virtual void paintEvent(QPaintEvent *event);
-
- private:
- const Field *m_field;
- const PieceLibrary *m_lib;
- Pos m_pos;
- bool m_mark;
- };
-
- class TestField : public QWidget {
- Q_OBJECT
- public:
- TestField(QWidget *parent, PieceLibrary *lib, Game *m_game);
-
- void markMoves(const QList &moves);
-
- protected:
- virtual void resizeEvent(QResizeEvent *event);
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
-
- private:
- PieceLibrary *m_lib;
- Game *m_game;
- TestPlace* m_places[8][8];
- QList m_marked;
- };
-
class TestGame : public QMainWindow {
Q_OBJECT
public:
@@ -83,9 +43,13 @@ namespace toruschess {
private slots:
void gameUpdated();
void gameChanged(GameState state);
+
+ void menuRestart();
+ void menuOptions();
private:
Game *m_game;
+ OptionDlg *m_optionDlg;
};
}
diff --git a/src/toruschess.cpp b/src/toruschess.cpp
index 12d9199..a600989 100644
--- a/src/toruschess.cpp
+++ b/src/toruschess.cpp
@@ -18,9 +18,18 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "toruschess.h"
+#include "ai.h"
namespace toruschess {
+ static void init() {
+ static bool done = FALSE;
+ if (done) return;
+ done = TRUE;
+ qRegisterMetaType("Move");
+ qRegisterMetaType("Pos");
+ }
+
QString state2string(GameState state) {
switch (state) {
case TURN_WHITE: return "White's turn";
@@ -318,13 +327,16 @@ namespace toruschess {
}
Game::Game(QObject *parent)
- : QObject(parent), m_field(new Field()), m_state(TURN_WHITE) { }
+ : QObject(parent), m_field(new Field()), m_state(TURN_WHITE), m_gameMode(HUMAN_COMPUTER), m_aiStrength(2), m_aiThread(0) {
+ init();
+ }
Game::~Game() {
delete m_field;
}
bool Game::move(const Move &m) {
+ if (m_aiThread) return false;
if (!m.valid()) return false;
switch (m_state) {
case TURN_WHITE:
@@ -357,6 +369,7 @@ namespace toruschess {
}
}
}
+ checkAI();
emit moved(m);
emit changed(m_state);
emit updated();
@@ -368,6 +381,7 @@ namespace toruschess {
void Game::restart() {
m_state = TURN_WHITE;
m_field->reset();
+ checkAI();
emit changed(m_state);
emit started();
emit updated();
@@ -393,4 +407,81 @@ namespace toruschess {
}
return moves;
}
+
+ void Game::setGameMode(GameMode gm) {
+ m_gameMode = gm;
+ checkAI();
+ emit changedMode(m_gameMode);
+ }
+
+ void Game::setAiStrength(int s) {
+ m_aiStrength = qMin(7, qMax(2, s));
+ emit changedAIStrength(m_aiStrength);
+ }
+
+ void Game::checkAI() {
+ if (m_aiThread) {
+ switch (m_gameMode) {
+ case HUMAN_HUMAN:
+ m_ignoreAI = true;
+ break;
+ case HUMAN_COMPUTER:
+ if (m_state != TURN_BLACK) m_ignoreAI = true;
+ break;
+ case COMPUTER_HUMAN:
+ if (m_state != TURN_WHITE) m_ignoreAI = true;
+ break;
+ case COMPUTER_COMPUTER:
+ break;
+ }
+ } else {
+ Player curp = NOPLAYER;
+ switch (m_state) {
+ case TURN_WHITE:
+ curp = WHITE;
+ break;
+ case TURN_BLACK:
+ curp = BLACK;
+ break;
+ default:
+ return;
+ }
+ switch (m_gameMode) {
+ case HUMAN_HUMAN:
+ return;
+ case HUMAN_COMPUTER:
+ if (m_state != TURN_BLACK) return;
+ break;
+ case COMPUTER_HUMAN:
+ if (m_state != TURN_WHITE) return;
+ break;
+ case COMPUTER_COMPUTER:
+ break;
+ }
+ m_aiThread = new GameAIThread(*m_field, curp, m_aiStrength, this);
+ m_ignoreAI = false;
+ connect(m_aiThread, SIGNAL(aiFinished(Move)), this, SLOT(finishedAI(Move)));
+ m_aiThread->start();
+ }
+ }
+
+ void Game::finishedAI(Move m) {
+ m_aiThread->wait();
+ delete m_aiThread;
+ m_aiThread = 0;
+ if (!m_ignoreAI) {
+ move(m);
+ }
+ checkAI();
+ }
+
+ GameAIThread::GameAIThread(const Field &field, Player curp, int depth, QObject *parent)
+ : QThread(parent), m_field(field), m_curp(curp), m_depth(depth) {
+ }
+
+ void GameAIThread::run() {
+ Move m = ai::getMove(m_field, m_curp, m_depth);
+ emit aiFinished(m);
+ }
+
}
diff --git a/src/toruschess.h b/src/toruschess.h
index 23012d0..c74df18 100644
--- a/src/toruschess.h
+++ b/src/toruschess.h
@@ -22,6 +22,8 @@
#include
#include
+#include
+#include
/**
@author Stefan Bühler
@@ -31,10 +33,12 @@ namespace toruschess {
class Pos;
class Field;
class Game;
-
+ class GameAIThread;
+
typedef enum { BLACK = -1, NOPLAYER = 0, WHITE = 1 } Player;
typedef enum { NOPIECE = 0, PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5, KING = 6 } Piece;
typedef enum { TURN_WHITE, TURN_BLACK, WON_WHITE, WON_BLACK, DRAW } GameState;
+ typedef enum { HUMAN_HUMAN, HUMAN_COMPUTER, COMPUTER_HUMAN, COMPUTER_COMPUTER } GameMode;
inline Player place2player(int place) {
return (place < 0) ? BLACK : (place > 0) ? WHITE : NOPLAYER;
@@ -49,7 +53,7 @@ namespace toruschess {
class Pos {
public:
Pos() : m_x(0), m_y(0) { }
- Pos(int x, int y) : m_x(x % 8), m_y(y % 8) { }
+ Pos(int x, int y) : m_x(x & 7), m_y(y & 7) { }
int x() const { return m_x; }
int y() const { return m_y; }
@@ -132,19 +136,59 @@ namespace toruschess {
QList possibleMoves() const;
+ GameMode gameMode() const { return m_gameMode; }
+ void setGameMode(GameMode gm);
+
+ int aiStrength() const { return m_aiStrength; }
+ void setAiStrength(int s);
+
signals:
void moved(Move m);
void updated();
void undone(Move m);
void changed(GameState state);
void started();
-
+
+ void changedMode(GameMode mode);
+ void changedAIStrength(int aiStrength);
+
+ private slots:
+ void finishedAI(Move m);
+
private:
+
+ void checkAI();
+
Field *m_field;
GameState m_state;
-
+ GameMode m_gameMode;
+ int m_aiStrength;
+
QList m_moves;
+
+ GameAIThread *m_aiThread;
+ bool m_ignoreAI;
};
+
+ class GameAIThread : public QThread {
+ Q_OBJECT
+ public:
+ GameAIThread(const Field &field, Player curp, int depth, QObject *parent = 0);
+
+ void run();
+
+ signals:
+ void aiFinished(Move m);
+
+ private:
+ Field m_field;
+ Player m_curp;
+ int m_depth;
+ };
+
}
+Q_DECLARE_METATYPE(toruschess::Move)
+Q_DECLARE_METATYPE(toruschess::Pos)
+
#endif
diff --git a/toruschess.kdevelop b/toruschess.kdevelop
index e2f6c5e..38354f5 100644
--- a/toruschess.kdevelop
+++ b/toruschess.kdevelop
@@ -144,7 +144,7 @@
executable
- /home/stefan/studium/7. semester/fapra_vis/src/toruschess
+ /home/stefan/develop/toruschess
false
false
false
@@ -152,13 +152,13 @@
false
-
+
- /home/stefan/studium/7. semester/fapra_vis/src/toruschess/..
+ /home/stefan/develop/toruschess
-
+
@@ -213,7 +213,7 @@
0.1
2009
- /home/stefan/studium/7. semester/fapra_vis/src/toruschess
+ /home/stefan/develop/toruschess