Use Validator in chess MoveSerializer.
[tagua/yd.git] / src / variants / chess / validator.cpp
blob9fe368d6929a311540bd4cbbfd47baa19a561fb3
1 #include "validator.h"
2 #include <memory>
3 #include <core/behaviour.h>
4 #include <core/board.h>
5 #include <core/move.h>
6 #include <core/state.h>
7 #include <core/type.h>
8 #include "colors.h"
9 #include "types.h"
11 namespace Chess {
13 Validator::Validator() : m_delegator(this) { }
15 bool Validator::pseudolegal(const IState* state, Move& move) const {
16 if (!state->board()->valid(move.src())) return false;
17 if (!state->board()->valid(move.dst())) return false;
19 Piece piece = state->board()->get(move.src());
20 if (piece == Piece()) return false;
22 const IBehaviour* behaviour = state->behaviour();
23 if (!behaviour) return false;
25 const IColor* thisTurn = piece.color();
26 const IColor* otherTurn = behaviour->opponent(thisTurn);
28 if (piece != Piece() && state->turn() == thisTurn) {
29 Piece target = state->board()->get(move.dst());
30 if (target.color() == piece.color())
31 return false;
32 if (!piece.type()->canMove(piece, target, move, state))
33 return false;
35 // TODO: check promotion type
37 if (move.type() == "king_side_castling") {
38 if (m_delegator->attacks(state, otherTurn, move.src()) ||
39 m_delegator->attacks(state, otherTurn, move.src() + Point(1, 0), piece))
40 return false;
42 if (move.type() == "queen_side_castling") {
43 if (m_delegator->attacks(state, otherTurn, move.src()) ||
44 m_delegator->attacks(state, otherTurn, move.src() + Point(-1, 0), piece))
45 return false;
48 return true;
50 else {
51 return false;
55 bool Validator::legal(const IState* state, Move& move) const {
56 // if (!move.type().isEmpty()) return true;
58 if (!m_delegator->pseudolegal(state, move))
59 return false;
61 const IBehaviour* behaviour = state->behaviour();
62 if (!behaviour) return false;
64 const IColor* turn = m_delegator->mover(state, move);
66 std::auto_ptr<IState> tmp(state->clone());
67 tmp->move(move);
69 Point kingPos = tmp->board()->find(Piece(turn, King::self()));
71 if (kingPos == Point::invalid())
72 return false;
74 if (m_delegator->attacks(tmp.get(), behaviour->opponent(turn), kingPos))
75 return false;
77 return true;
80 bool Validator::attacks(const IState* state, const IColor* player,
81 const Point& square, const Piece& target_) const {
82 Piece target;
83 if (target_ != Piece())
84 target = target_;
85 else
86 target = state->board()->get(square);
88 for (int i = 0; i < state->board()->size().x; i++) {
89 for (int j = 0; j < state->board()->size().y; j++) {
90 Point p(i, j);
91 Piece piece = state->board()->get(p);
92 Move move(p, square);
93 if (piece != Piece() &&
94 piece.color() == player &&
95 piece.type()->canMove(piece, target, move, state))
96 return true;
99 return false;
102 const IColor* Validator::mover(const IState* state, const Move& move) const {
103 return state->board()->get(move.src()).color();
106 void Validator::setDelegator(IValidator* delegator) {
107 m_delegator = delegator;