/*************************************************************************** * 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 TORUSCHESSTORUSCHESS_H #define TORUSCHESSTORUSCHESS_H #include #include #include #include /** @author Stefan Bühler */ namespace toruschess { /* Game logic * * "piece" and "player" are combined to "place": place = piece * player; */ 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; } inline Piece place2piece(int place) { return (Piece) qAbs(place); } QString state2string(GameState state); /* coords for a field on the board */ class Pos { public: Pos() : m_x(0), m_y(0) { } 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; } bool operator==(const Pos &other) const { return m_x == other.m_x && m_y == other.m_y; } private: int m_x, m_y; }; /* some basic information for one move: from and to, * which figure got moved, which (if any) got beaten */ class Move { public: Move(); Move(const Field* field, const Pos &from, const Pos &to); const Pos& from() const { return m_from; } const Pos& to() const { return m_to; } /** figure which gets moved */ int prevFrom() const { return m_prevFrom; } /** figure which gets beaten */ int prevTo() const { return m_prevTo; } /** which player is moving (player from prevFrom()) */ Player player() const { return m_player; } bool operator==(const Move &other) const { return m_from == other.m_from && m_to == other.m_to && m_prevFrom == other.m_prevFrom && m_prevTo == other.m_prevTo; /* player is included in m_prevFrom */ } bool valid() const { return m_prevFrom != 0; } private: Pos m_from,m_to; int m_prevFrom, m_prevTo; Player m_player; }; /** the raw field: only knows which figures is where */ class Field { public: Field(); void reset(); Player player(const Pos &p) const { return place2player(place(p)); } Piece piece(const Pos &p) const { return place2piece(place(p)); } 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()]; } /* all valid moves for a piece */ QList validMoves(const Pos &from) const; bool validMove(const Move &m) const; /* does not check for inCheck */ bool move(const Move &m); /* check if the move is valid */ bool undo(const Move &m); /* check if the undo is valid */ /* check if the king of a player at pos pking is in check */ bool inCheck(Player player, const Pos &pking) const; /* check if the king of a player is in check */ bool inCheck(Player player) const; void move_unchecked(const Move &m); void undo_unchecked(const Move &m); private: /* does not check for "in check" */ QList simpleValidMoves(const Pos &from) const; Pos m_wking, m_bking; int m_places[8][8]; }; /* contains a field plus addition information about the game state * such as which turn it is or who has won * also is responsible to do the ai moves, if activated */ class Game : public QObject { Q_OBJECT public: Game(QObject *parent = 0); virtual ~Game(); const Field* field() const { return m_field; } GameState state() const { return m_state; } QList moves() const { return m_moves; } /* only valid moves will be done */ bool move(const Move &m); /* restart the game */ void restart(); /* all valid moves for the current player */ 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; }; /* Calculate the ai move in another thread so the main thread (gui) isn't blocked */ 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