Added ChessGameState, related classes and tests.
[tagua/yd.git] / tests / hlvariants / prototype / chess / gamestate.h
blob56109ddf0de67424c08f0542101bbfbd785061ee
1 #ifndef HLVARIANT__CHESS__GAMESTATE_H
2 #define HLVARIANT__CHESS__GAMESTATE_H
4 #include "../board.h"
5 #include "piece.h"
6 #include "move.h"
8 namespace HLVariant {
9 namespace Chess {
11 struct CastlingData {
12 bool wk : 1;
13 bool wq : 1;
14 bool bk : 1;
15 bool bq : 1;
17 CastlingData();
18 CastlingData(bool, bool, bool, bool);
19 bool operator==(const CastlingData& other) const;
22 template <typename _Board, typename _Move>
23 class GameState {
24 public:
25 typedef _Board Board;
26 typedef _Move Move;
27 typedef typename Board::Piece Piece;
28 private:
29 Board m_board;
30 CastlingData m_castling;
31 Point m_en_passant;
32 typename Piece::Color m_turn;
33 public:
34 GameState();
35 virtual ~GameState() { }
37 virtual Board& board();
38 virtual const Board& board() const;
40 virtual void setup();
42 virtual bool operator==(const GameState<Board, Move>& other) const;
44 virtual void move(const Move& m);
45 virtual void basicMove(const Move& m);
46 virtual void handleCastling(const Piece& piece, const Move& m);
47 virtual void captureOn(const Point& p);
49 virtual void switchTurn();
50 virtual typename Piece::Color turn() const;
53 // IMPLEMENTATION
55 template <typename Board, typename Move>
56 GameState<Board, Move>::GameState()
57 : m_board(Point(8, 8))
58 , m_en_passant(Point::invalid())
59 , m_turn(Piece::WHITE) { }
61 template <typename Board, typename Move>
62 Board& GameState<Board, Move>::board() { return m_board; }
64 template <typename Board, typename Move>
65 const Board& GameState<Board, Move>::board() const { return m_board; }
67 template <typename Board, typename Move>
68 void GameState<Board, Move>::setup() {
69 for (int c = 0; c < 2; c++) {
70 typename Piece::Color color = static_cast<typename Piece::Color>(c);
71 int row = color == Piece::WHITE ? m_board.size().y - 1: 0;
72 for (int i = 0; i < m_board.size().x; i++) {
73 m_board.set(Point(i, color == Piece::WHITE ? row - 1 : row + 1),
74 Piece(color, Piece::PAWN));
75 m_board.set(Point(0, row), Piece(color, Piece::ROOK));
76 m_board.set(Point(1, row), Piece(color, Piece::KNIGHT));
77 m_board.set(Point(2, row), Piece(color, Piece::BISHOP));
78 m_board.set(Point(3, row), Piece(color, Piece::QUEEN));
79 m_board.set(Point(4, row), Piece(color, Piece::KING));
80 m_board.set(Point(5, row), Piece(color, Piece::BISHOP));
81 m_board.set(Point(6, row), Piece(color, Piece::KNIGHT));
82 m_board.set(Point(7, row), Piece(color, Piece::ROOK));
87 template <typename Board, typename Move>
88 bool GameState<Board, Move>::operator==(const GameState<Board, Move>& other) const {
89 return m_board == other.m_board &&
90 m_castling == other.m_castling &&
91 m_en_passant == other.m_en_passant;
94 template <typename Board, typename Move>
95 void GameState<Board, Move>::captureOn(const Point& p) {
96 m_board.set(p, Piece());
99 template <typename Board, typename Move>
100 void GameState<Board, Move>::basicMove(const Move& m) {
101 if (m.from() != m.to()) {
102 m_board.set(m.to(), m_board.get(m.from()));
103 m_board.set(m.from(), Piece());
107 template <typename Board, typename Move>
108 void GameState<Board, Move>::handleCastling(const Piece& piece, const Move& m) {
109 if (m.kingSideCastling()) {
110 Point rookSquare = m.to() + Point(1,0);
111 Point rookDestination = m.from() + Point(1,0);
112 basicMove(Move(rookSquare, rookDestination));
115 else if (m.queenSideCastling()) {
116 Point rookSquare = m.to() - Point(2,0);
117 Point rookDestination = m.from() - Point(1,0);
118 basicMove(Move(rookSquare, rookDestination));
121 typename Piece::Type type = piece.type();
122 typename Piece::Color color = piece.color();
124 if (type == Piece::KING) {
125 if (color == Piece::WHITE) {
126 m_castling.wk = false;
127 m_castling.wq = false;
129 else {
130 m_castling.bk = false;
131 m_castling.bq = false;
135 if (m.from() == Point(0,0) || m.to() == Point(0,0))
136 m_castling.bq = false;
137 else if (m.from() == Point(7,0) || m.to() == Point(7,0))
138 m_castling.bk = false;
139 else if (m.from() == Point(0,7) || m.to() == Point(0,7))
140 m_castling.wq = false;
141 else if (m.from() == Point(7,7) || m.to() == Point(7,7))
142 m_castling.wk = false;
145 template <typename Board, typename Move>
146 void GameState<Board, Move>::switchTurn() {
147 m_turn = Piece::oppositeColor(m_turn);
150 template <typename Board, typename Move>
151 void GameState<Board, Move>::move(const Move& m) {
152 Piece piece = m_board.get(m.from());
153 if (piece == Piece()) return;
155 captureOn(m.captureSquare());
156 basicMove(m);
158 m_en_passant = m.enPassantTrigger();
160 typename Piece::Type promotion_type =
161 static_cast<typename Piece::Type>(m.promoteTo());
162 if (promotion_type != Piece::INVALID_TYPE) {
163 m_board.set(m.to(), Piece(piece.color(), promotion_type));
166 handleCastling(piece, m);
167 switchTurn();
170 template <typename Board, typename Move>
171 typename Board::Piece::Color GameState<Board, Move>::turn() const {
172 return m_turn;
175 } // namespace Chess
176 } // namespace HLVariant
178 #endif // HLVARIANT__CHESS__GAMESTATE_H