split piecelibrary, new Field2D
This commit is contained in:
parent
6f39c10d93
commit
b3abfc3538
131
src/field2d.cpp
Normal file
131
src/field2d.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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 "field2d.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QWheelEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace toruschess {
|
||||||
|
|
||||||
|
Field2D::Field2D(Game *game, QWidget *parent)
|
||||||
|
: QWidget(parent), m_lib(new PieceLibrary(this)), m_game(game), m_fieldWidth(360), m_fieldHeight(360), m_originX(23), m_originY(23) {
|
||||||
|
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) m_marked[x][y] = false;
|
||||||
|
m_lib->setSize(m_fieldWidth / 8, m_fieldHeight / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::markMoves(const QList<Move> &moves) {
|
||||||
|
foreach(Move m, m_markedMoves) m_marked[m.to().x()][m.to().y()] = false;
|
||||||
|
m_markedMoves = moves;
|
||||||
|
foreach(Move m, m_markedMoves) m_marked[m.to().x()][m.to().y()] = true;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize Field2D::sizeHint() const {
|
||||||
|
return QSize(17*m_fieldWidth/8, 17*m_fieldHeight/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::paintEvent(QPaintEvent *) {
|
||||||
|
QPainter pt(this);
|
||||||
|
int pieceWidth = m_fieldWidth / 8, pieceHeight = m_fieldHeight / 8;
|
||||||
|
int winWidth = width(), winHeight = height();
|
||||||
|
for (int x = 0; x < 8; x++)
|
||||||
|
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));
|
||||||
|
|
||||||
|
for (int px = m_originX - m_fieldWidth + x*pieceWidth; px < winWidth; px += m_fieldWidth)
|
||||||
|
for (int py = m_originY - m_fieldHeight + y*pieceHeight; py < winHeight; py += m_fieldHeight) {
|
||||||
|
QRect prect(px, py, pieceWidth - 1, pieceHeight - 1);
|
||||||
|
pt.fillRect(prect, fieldBG);
|
||||||
|
m_lib->paint(pt, place, prect);
|
||||||
|
if (marked) {
|
||||||
|
int r = qMax(1, (pieceWidth + pieceHeight) / 36);
|
||||||
|
pt.setBrush(place != 0 ? Qt::green : Qt::white);
|
||||||
|
pt.setPen(Qt::red);
|
||||||
|
pt.drawEllipse(QPoint(px + pieceWidth / 2, py + pieceHeight / 2), r, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::mousePressEvent(QMouseEvent *event) {
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
QList<Move> moves;
|
||||||
|
Pos p = findPos(event->x(), event->y());
|
||||||
|
moves = m_game->field()->validMoves(p);
|
||||||
|
markMoves(moves);
|
||||||
|
}
|
||||||
|
m_mouseLastX = event->x();
|
||||||
|
m_mouseLastY = event->y();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::mouseMoveEvent(QMouseEvent *event) {
|
||||||
|
if (event->buttons() & Qt::RightButton) {
|
||||||
|
m_originX += event->x() - m_mouseLastX;
|
||||||
|
m_originY += event->y() - m_mouseLastY;
|
||||||
|
checkSizes();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
m_mouseLastX = event->x();
|
||||||
|
m_mouseLastY = event->y();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::mouseReleaseEvent(QMouseEvent *event) {
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
if (m_markedMoves.size() == 0) return;
|
||||||
|
Pos from = m_markedMoves[0].from();
|
||||||
|
QList<Move> moves;
|
||||||
|
markMoves(QList<Move>());
|
||||||
|
Pos p = findPos(event->x(), event->y());
|
||||||
|
Move m(m_game->field(), from, p);
|
||||||
|
m_game->move(m);
|
||||||
|
}
|
||||||
|
m_mouseLastX = event->x();
|
||||||
|
m_mouseLastY = event->y();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::wheelEvent(QWheelEvent *event) {
|
||||||
|
double zoom = pow(1.2, event->delta() / 120);
|
||||||
|
int max = qMin(width(), height());
|
||||||
|
m_fieldWidth = qMax(120, qMin(max, (int) (m_fieldWidth * zoom))) & ~(0x7);
|
||||||
|
m_fieldHeight = qMax(120, qMin(max, (int) (m_fieldHeight * zoom))) & ~(0x7);
|
||||||
|
m_lib->setSize(m_fieldWidth / 8, m_fieldHeight / 8);
|
||||||
|
checkSizes();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field2D::checkSizes() {
|
||||||
|
m_originX = m_originX % m_fieldWidth;
|
||||||
|
m_originY = m_originY % m_fieldHeight;
|
||||||
|
if (m_originX < 0) m_originX += m_fieldWidth;
|
||||||
|
if (m_originY < 0) m_originY += m_fieldHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pos Field2D::findPos(int x, int y) {
|
||||||
|
return Pos(8 * ((x - m_originX) % m_fieldWidth) / m_fieldWidth, 8 * ((y - m_originY) % m_fieldHeight) / m_fieldHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
68
src/field2d.h
Normal file
68
src/field2d.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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 TORUSCHESSFIELD2D_H
|
||||||
|
#define TORUSCHESSFIELD2D_H
|
||||||
|
|
||||||
|
#include "toruschess.h"
|
||||||
|
#include "piecelibrary.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Stefan Bühler <stbuehler@web.de>
|
||||||
|
*/
|
||||||
|
namespace toruschess {
|
||||||
|
|
||||||
|
class Field2D : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Field2D(Game *game, QWidget *parent = 0);
|
||||||
|
|
||||||
|
void markMoves(const QList<Move> &moves);
|
||||||
|
|
||||||
|
virtual QSize sizeHint() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paintEvent(QPaintEvent *event);
|
||||||
|
virtual void mousePressEvent(QMouseEvent *event);
|
||||||
|
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent *event);
|
||||||
|
virtual void wheelEvent(QWheelEvent *event);
|
||||||
|
|
||||||
|
void checkSizes();
|
||||||
|
|
||||||
|
Pos findPos(int x, int y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PieceLibrary *m_lib;
|
||||||
|
Game *m_game;
|
||||||
|
bool m_marked[8][8];
|
||||||
|
QList<Move> m_markedMoves;
|
||||||
|
|
||||||
|
int m_fieldWidth, m_fieldHeight;
|
||||||
|
int m_originX, m_originY;
|
||||||
|
|
||||||
|
int m_mouseLastX, m_mouseLastY;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
72
src/piecelibrary.cpp
Normal file
72
src/piecelibrary.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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 "piecelibrary.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace toruschess {
|
||||||
|
|
||||||
|
PieceLibrary::PieceLibrary(QObject *parent)
|
||||||
|
: QObject(parent), m_pieces(0), m_buffers(0) {
|
||||||
|
setSize(45, 45);
|
||||||
|
}
|
||||||
|
|
||||||
|
PieceLibrary::~PieceLibrary() {
|
||||||
|
delete [] m_pieces;
|
||||||
|
delete [] m_buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PieceLibrary::setSize(int width, int height) {
|
||||||
|
m_width = qMax(10, width);
|
||||||
|
m_height = qMax(10, height);
|
||||||
|
if (m_buffers) {
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
delete m_buffers[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_pieces = new QSvgRenderer* [12];
|
||||||
|
m_buffers = new QImage* [12];
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
m_pieces[i] = new QSvgRenderer(QString(":/media/chess_%1.svg").arg(i+1), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
m_buffers[i] = new QImage(QSize(m_width, m_height), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
m_buffers[i]->fill(0x0);
|
||||||
|
QPainter p(m_buffers[i]);
|
||||||
|
m_pieces[i]->render(&p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PieceLibrary::paint(QPainter &pt, int place) const {
|
||||||
|
if (place == 0) return;
|
||||||
|
if (place < 0) place = 6 - place;
|
||||||
|
if (place <= 0 || place > 12) return;
|
||||||
|
pt.drawImage(0, 0, *m_buffers[place-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PieceLibrary::paint(QPainter &pt, int place, const QRect &rect) const {
|
||||||
|
if (place == 0) return;
|
||||||
|
if (place < 0) place = 6 - place;
|
||||||
|
if (place <= 0 || place > 12) return;
|
||||||
|
pt.drawImage(rect, *m_buffers[place-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
src/piecelibrary.h
Normal file
51
src/piecelibrary.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* 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 TORUSCHESSPIECELIBRARY_H
|
||||||
|
#define TORUSCHESSPIECELIBRARY_H
|
||||||
|
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
|
/**
|
||||||
|
@author Stefan Bühler <stbuehler@web.de>
|
||||||
|
*/
|
||||||
|
namespace toruschess {
|
||||||
|
|
||||||
|
class PieceLibrary : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PieceLibrary(QObject *parent);
|
||||||
|
virtual ~PieceLibrary();
|
||||||
|
|
||||||
|
QSize pieceSize() const { return QSize(m_width, m_height); }
|
||||||
|
QSize minPieceSize() const { return QSize(20, 20); }
|
||||||
|
void setSize(int width, int height);
|
||||||
|
|
||||||
|
void paint(QPainter &pt, int place) const;
|
||||||
|
void paint(QPainter &pt, int place, const QRect &rect) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSvgRenderer **m_pieces;
|
||||||
|
QImage **m_buffers;
|
||||||
|
int m_width, m_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,8 @@
|
|||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
testgame.cpp \
|
testgame.cpp \
|
||||||
toruschess.cpp
|
toruschess.cpp \
|
||||||
|
field2d.cpp \
|
||||||
|
piecelibrary.cpp
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
CONFIG += warn_on \
|
CONFIG += warn_on \
|
||||||
thread \
|
thread \
|
||||||
@ -14,6 +16,8 @@ RESOURCES += media.qrc
|
|||||||
QT += svg \
|
QT += svg \
|
||||||
opengl
|
opengl
|
||||||
HEADERS += testgame.h \
|
HEADERS += testgame.h \
|
||||||
toruschess.h
|
toruschess.h \
|
||||||
|
field2d.h \
|
||||||
|
piecelibrary.h
|
||||||
CONFIG -= release
|
CONFIG -= release
|
||||||
|
|
||||||
|
@ -20,51 +20,14 @@
|
|||||||
#include "testgame.h"
|
#include "testgame.h"
|
||||||
|
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QPainter>
|
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "field2d.h"
|
||||||
|
|
||||||
namespace toruschess {
|
namespace toruschess {
|
||||||
|
|
||||||
PieceLibrary::PieceLibrary(QObject *parent)
|
|
||||||
: QObject(parent), m_pieces(0), m_buffers(0) {
|
|
||||||
setSize(45, 45);
|
|
||||||
}
|
|
||||||
|
|
||||||
PieceLibrary::~PieceLibrary() {
|
|
||||||
delete [] m_pieces;
|
|
||||||
delete [] m_buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PieceLibrary::setSize(int width, int height) {
|
|
||||||
m_width = qMax(10, width);
|
|
||||||
m_height = qMax(10, height);
|
|
||||||
if (m_buffers) {
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
delete m_buffers[i];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_pieces = new QSvgRenderer* [12];
|
|
||||||
m_buffers = new QImage* [12];
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
m_pieces[i] = new QSvgRenderer(QString(":/media/chess_%1.svg").arg(i+1), this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
m_buffers[i] = new QImage(QSize(m_width, m_height), QImage::Format_ARGB32_Premultiplied);
|
|
||||||
m_buffers[i]->fill(0x0);
|
|
||||||
QPainter p(m_buffers[i]);
|
|
||||||
m_pieces[i]->render(&p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PieceLibrary::paint(QPainter &pt, int piece) const {
|
|
||||||
if (piece == 0) return;
|
|
||||||
if (piece < 0) piece = 6 - piece;
|
|
||||||
if (piece <= 0 || piece > 12) return;
|
|
||||||
pt.drawImage(0, 0, *m_buffers[piece-1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TestPlace::TestPlace(QWidget *parent, const PieceLibrary *lib, const Field *field, const Pos &p)
|
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) {
|
: QWidget(parent), m_field(field), m_lib(lib), m_pos(p), m_mark(false) {
|
||||||
setMinimumSize(m_lib->minPieceSize());
|
setMinimumSize(m_lib->minPieceSize());
|
||||||
@ -149,8 +112,9 @@ namespace toruschess {
|
|||||||
|
|
||||||
TestGame::TestGame(QWidget *parent) : QMainWindow(parent), m_game(new Game()) {
|
TestGame::TestGame(QWidget *parent) : QMainWindow(parent), m_game(new Game()) {
|
||||||
setWindowTitle("Torus Chess");
|
setWindowTitle("Torus Chess");
|
||||||
PieceLibrary *lib = new PieceLibrary(this);
|
// PieceLibrary *lib = new PieceLibrary(this);
|
||||||
setCentralWidget(new TestField(this, lib, m_game));
|
// setCentralWidget(new TestField(this, lib, m_game));
|
||||||
|
setCentralWidget(new Field2D(m_game, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,30 +26,13 @@
|
|||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
|
||||||
#include "toruschess.h"
|
#include "toruschess.h"
|
||||||
|
#include "piecelibrary.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@author Stefan Bühler <stbuehler@web.de>
|
@author Stefan Bühler <stbuehler@web.de>
|
||||||
*/
|
*/
|
||||||
namespace toruschess {
|
namespace toruschess {
|
||||||
|
|
||||||
class PieceLibrary : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
PieceLibrary(QObject *parent);
|
|
||||||
virtual ~PieceLibrary();
|
|
||||||
|
|
||||||
QSize pieceSize() const { return QSize(m_width, m_height); }
|
|
||||||
QSize minPieceSize() const { return QSize(20, 20); }
|
|
||||||
void setSize(int width, int height);
|
|
||||||
|
|
||||||
void paint(QPainter &pt, int piece) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSvgRenderer **m_pieces;
|
|
||||||
QImage **m_buffers;
|
|
||||||
int m_width, m_height;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TestPlace : public QWidget {
|
class TestPlace : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -21,6 +21,17 @@
|
|||||||
|
|
||||||
namespace toruschess {
|
namespace toruschess {
|
||||||
|
|
||||||
|
QString state2string(GameState state) {
|
||||||
|
switch (state) {
|
||||||
|
case TURN_WHITE: return "White's turn";
|
||||||
|
case TURN_BLACK: return "Black's turn";
|
||||||
|
case WON_WHITE: return "White is the winner";
|
||||||
|
case WON_BLACK: return "Black is the winner";
|
||||||
|
case DRAW: return "Draw game";
|
||||||
|
}
|
||||||
|
return "Invalid GameState";
|
||||||
|
}
|
||||||
|
|
||||||
Move::Move(const Field* field, const Pos &from, const Pos &to)
|
Move::Move(const Field* field, const Pos &from, const Pos &to)
|
||||||
: m_from(from), m_to(to), m_prevFrom(field->place(from)), m_prevTo(field->place(to)), m_player(field->player(from)) { }
|
: m_from(from), m_to(to), m_prevFrom(field->place(from)), m_prevTo(field->place(to)), m_player(field->player(from)) { }
|
||||||
|
|
||||||
@ -39,6 +50,10 @@ namespace toruschess {
|
|||||||
memcpy(m_places, start_field, sizeof(start_field));
|
memcpy(m_places, start_field, sizeof(start_field));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Field::reset() {
|
||||||
|
memcpy(m_places, start_field, sizeof(start_field));
|
||||||
|
}
|
||||||
|
|
||||||
void tryDirection(QList<Move> &moves, const Field *field, int thePlace, const Pos &from, int dx, int dy) {
|
void tryDirection(QList<Move> &moves, const Field *field, int thePlace, const Pos &from, int dx, int dy) {
|
||||||
for (int d = 1; d < 8; d++) {
|
for (int d = 1; d < 8; d++) {
|
||||||
Pos to = Pos(from.x() + d*dx, from.y() + d*dy);
|
Pos to = Pos(from.x() + d*dx, from.y() + d*dy);
|
||||||
@ -152,16 +167,12 @@ foundking:
|
|||||||
Field testField(*this);
|
Field testField(*this);
|
||||||
testField.place(from) = 0;
|
testField.place(from) = 0;
|
||||||
bool movedKing = (from == pking);
|
bool movedKing = (from == pking);
|
||||||
|
Player player = place2player(thePlace);
|
||||||
foreach(Move m, moves) {
|
foreach(Move m, moves) {
|
||||||
testField.place(m.to()) = thePlace;
|
testField.place(m.to()) = thePlace;
|
||||||
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) {
|
if (!testField.inCheck(player, movedKing ? m.to() : pking)) {
|
||||||
Pos curp(x, y);
|
resMoves.push_back(m);
|
||||||
if (0 > testField.place(curp) * thePlace && testField.simpleValidMoves(curp).contains(Move(&testField, curp, movedKing ? m.to() : pking))) {
|
|
||||||
goto invalidmove;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
resMoves.push_back(m);
|
|
||||||
invalidmove:
|
|
||||||
testField.place(m.to()) = m.prevTo();
|
testField.place(m.to()) = m.prevTo();
|
||||||
}
|
}
|
||||||
return resMoves;
|
return resMoves;
|
||||||
@ -185,11 +196,100 @@ invalidmove:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Field::inCheck(Player player, const Pos &pking) const {
|
||||||
|
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) {
|
||||||
|
Pos curp(x, y);
|
||||||
|
if (0 > place(curp) * player && simpleValidMoves(curp).contains(Move(this, curp, pking))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Field::inCheck(Player player) const {
|
||||||
|
/* find king */
|
||||||
|
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) {
|
||||||
|
Pos curp(x, y);
|
||||||
|
if (piece(curp) == KING && 0 < place(curp) * player) {
|
||||||
|
return inCheck(player, curp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; /* error, no king found */
|
||||||
|
}
|
||||||
|
|
||||||
Game::Game(QObject *parent)
|
Game::Game(QObject *parent)
|
||||||
: QObject(parent), m_field(new Field()) { }
|
: QObject(parent), m_field(new Field()), m_state(TURN_WHITE) { }
|
||||||
|
|
||||||
Game::~Game() {
|
Game::~Game() {
|
||||||
delete m_field;
|
delete m_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Game::move(const Move &m) {
|
||||||
|
switch (m_state) {
|
||||||
|
case TURN_WHITE:
|
||||||
|
if (m.player() != WHITE) return false;
|
||||||
|
break;
|
||||||
|
case TURN_BLACK:
|
||||||
|
if (m.player() != BLACK) return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (m_field->move(m)) {
|
||||||
|
m_moves.push_back(m);
|
||||||
|
if (m_state == TURN_WHITE) {
|
||||||
|
m_state = TURN_BLACK;
|
||||||
|
if (possibleMoves().empty()) {
|
||||||
|
if (m_field->inCheck(BLACK)) {
|
||||||
|
m_state = WON_WHITE;
|
||||||
|
} else {
|
||||||
|
m_state = DRAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_state = TURN_WHITE;
|
||||||
|
if (possibleMoves().empty()) {
|
||||||
|
if (m_field->inCheck(WHITE)) {
|
||||||
|
m_state = WON_BLACK;
|
||||||
|
} else {
|
||||||
|
m_state = DRAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit moved(m);
|
||||||
|
emit changed(m_state);
|
||||||
|
emit updated();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::restart() {
|
||||||
|
m_state = TURN_WHITE;
|
||||||
|
m_field->reset();
|
||||||
|
emit changed(m_state);
|
||||||
|
emit started();
|
||||||
|
emit updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Move> Game::possibleMoves() const {
|
||||||
|
Player player = NOPLAYER;
|
||||||
|
switch (m_state) {
|
||||||
|
case TURN_WHITE:
|
||||||
|
player = WHITE;
|
||||||
|
break;
|
||||||
|
case TURN_BLACK:
|
||||||
|
player = BLACK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return QList<Move>();
|
||||||
|
}
|
||||||
|
QList<Move> moves;
|
||||||
|
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) {
|
||||||
|
Pos curp(x, y);
|
||||||
|
if (0 < m_field->place(curp) * player)
|
||||||
|
moves += m_field->validMoves(curp);
|
||||||
|
}
|
||||||
|
return moves;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,21 @@ namespace toruschess {
|
|||||||
|
|
||||||
typedef enum { BLACK = -1, NOPLAYER = 0, WHITE = 1 } Player;
|
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 { 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;
|
||||||
|
|
||||||
|
inline Player place2player(int place) {
|
||||||
|
return (place < 0) ? BLACK : (place > 0) ? WHITE : NOPLAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Piece place2piece(int place) {
|
||||||
|
return (Piece) qAbs(place);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString state2string(GameState state);
|
||||||
|
|
||||||
class Pos {
|
class Pos {
|
||||||
public:
|
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 % 8), m_y(y % 8) { }
|
||||||
|
|
||||||
int x() const { return m_x; }
|
int x() const { return m_x; }
|
||||||
@ -78,11 +90,10 @@ namespace toruschess {
|
|||||||
public:
|
public:
|
||||||
Field();
|
Field();
|
||||||
|
|
||||||
Player player(const Pos &p) const {
|
void reset();
|
||||||
int pl = place(p);
|
|
||||||
return (pl < 0) ? BLACK : (pl > 0) ? WHITE : NOPLAYER;
|
Player player(const Pos &p) const { return place2player(place(p)); }
|
||||||
}
|
Piece piece(const Pos &p) const { return place2piece(place(p)); }
|
||||||
Piece piece(const Pos &p) const { return (Piece) qAbs(place(p)); }
|
|
||||||
int place(const Pos &p) const { return m_places[p.y()][p.x()]; }
|
int place(const Pos &p) const { return m_places[p.y()][p.x()]; }
|
||||||
int& place(const Pos &p) { return m_places[p.y()][p.x()]; }
|
int& place(const Pos &p) { return m_places[p.y()][p.x()]; }
|
||||||
|
|
||||||
@ -91,6 +102,9 @@ namespace toruschess {
|
|||||||
bool move(const Move &m);
|
bool move(const Move &m);
|
||||||
bool undo(const Move &m);
|
bool undo(const Move &m);
|
||||||
|
|
||||||
|
bool inCheck(Player player, const Pos &pking) const;
|
||||||
|
bool inCheck(Player player) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<Move> simpleValidMoves(const Pos &from) const;
|
QList<Move> simpleValidMoves(const Pos &from) const;
|
||||||
|
|
||||||
@ -104,11 +118,26 @@ namespace toruschess {
|
|||||||
virtual ~Game();
|
virtual ~Game();
|
||||||
|
|
||||||
const Field* field() const { return m_field; }
|
const Field* field() const { return m_field; }
|
||||||
|
GameState state() const { return m_state; }
|
||||||
|
QList<Move> moves() const { return m_moves; }
|
||||||
|
|
||||||
bool move(const Move &m) { return m_field->move(m); }
|
bool move(const Move &m);
|
||||||
|
void restart();
|
||||||
|
|
||||||
|
QList<Move> possibleMoves() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void moved(Move m);
|
||||||
|
void updated();
|
||||||
|
void undone(Move m);
|
||||||
|
void changed(GameState state);
|
||||||
|
void started();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Field *m_field;
|
Field *m_field;
|
||||||
|
GameState m_state;
|
||||||
|
|
||||||
|
QList<Move> m_moves;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user