3 #include <core/behaviour.h>
4 #include <core/board.h>
6 #include <core/poolcollection.h>
8 #include <core/state.h>
15 Validator::Validator() : m_delegator(this) { }
17 bool Validator::pseudolegal(const IState
* state
, Move
& move
) const {
18 // add drop information to move, if missing
19 if (move
.drop() == Piece() &&
20 move
.pool() && move
.index() != -1) {
21 move
.setDrop(state
->pools()->pool(move
.pool())->get(move
.index()));
24 Piece dropped
= move
.drop();
25 if (dropped
== Piece()) {
26 if (!state
->board()->valid(move
.src())) return false;
27 if (!state
->board()->valid(move
.dst())) return false;
29 const Piece
* piece
= state
->board()->get(move
.src());
30 if (piece
== NULL
|| *piece
== Piece()) return false;
32 const IBehaviour
* behaviour
= state
->behaviour();
33 if (!behaviour
) return false;
35 const IColor
* thisTurn
= piece
->color();
36 if (state
->turn() != thisTurn
) return false;
38 const Piece
* target
= state
->board()->get(move
.dst());
39 if (target
->color() == piece
->color())
41 if (!piece
->type()->canMove(*piece
, *target
, move
, state
))
45 if (move
.type() == "promotion") {
46 const IType
* promotionType
= move
.promotion();
47 if (promotionType
!= Queen::self() &&
48 promotionType
!= Bishop::self() &&
49 promotionType
!= Rook::self() &&
50 promotionType
!= Knight::self()) return false;
54 // dropping on a valid square
55 if (!state
->board()->valid(move
.dst()))
58 // cannot drop on occupied squares
59 if (state
->board()->get(move
.dst()) != NULL
&&
60 *state
->board()->get(move
.dst()) != Piece())
63 // cannot drop on a place where piece would be stuck
64 if (stuckPiece(state
, dropped
, move
.dst()))
67 // cannot drop a pawn in a column with already a pawn of same color
68 if (dropped
.type() == Pawn::self()) {
69 for (int i
= 0; i
< state
->board()->size().y
; i
++) {
70 const Piece
* other
= state
->board()->get(Point(move
.dst().x
, i
));
71 if (other
->type() == Pawn::self() &&
72 other
->color() == state
->turn() &&
73 !other
->get("promoted").toBool())
82 bool Validator::legal(const IState
* state
, Move
& move
) const {
83 // do not check a move more than once
84 if (!move
.type().isEmpty()) return true;
86 if (!m_delegator
->pseudolegal(state
, move
))
89 const IBehaviour
* behaviour
= state
->behaviour();
90 if (!behaviour
) return false;
92 const IColor
* turn
= m_delegator
->mover(state
, move
);
94 IState
* tmp(state
->clone());
97 Point kingPos
= tmp
->board()->find(Piece(turn
, King::self()));
99 if (kingPos
== Point::invalid())
102 if (m_delegator
->attacks(tmp
, behaviour
->opponent(turn
), kingPos
))
105 // set move type as normal, if not already set
106 if (move
.type().isEmpty()) move
.setType("normal");
110 // FIXME: move this logic into Piece classes ?
111 bool Validator::stuckPiece(const IState
* state
,
112 const Piece
& piece
, const Point
& p
) const {
113 const IBehaviour
* behaviour
= state
->behaviour();
115 if (piece
.type() == Pawn::self() || piece
.type() == Lance::self()) {
116 return p
.y
== state
->rank(0, behaviour
->opponent(piece
.color()));
118 else if (piece
.type() == Knight::self()) {
119 int rank
= state
->rank(0, behaviour
->opponent(piece
.color()));
120 return p
.y
== rank
|| p
.y
== rank
- behaviour
->direction(piece
.color()).y
;
127 bool Validator::attacks(const IState
* state
, const IColor
* player
,
128 const Point
& square
, const Piece
& target_
) const {
130 if (target_
!= Piece())
133 target
= state
->board()->get(square
);
135 for (int i
= 0; i
< state
->board()->size().x
; i
++) {
136 for (int j
= 0; j
< state
->board()->size().y
; j
++) {
138 const Piece
* piece
= state
->board()->get(p
);
139 Move
move(p
, square
);
142 piece
->color() == player
&&
143 piece
->type()->canMove(*piece
, *target
, move
, state
))
150 const IColor
* Validator::mover(const IState
* state
, const Move
& move
) const {
151 return state
->board()->get(move
.src())->color();
154 void Validator::setDelegator(IValidator
* delegator
) {
155 m_delegator
= delegator
;