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
== 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()) != Piece())
62 // cannot drop on a place where piece would be stuck
63 if (stuckPiece(state
, dropped
, move
.dst()))
66 // cannot drop a pawn in a column with already a pawn of same color
67 if (dropped
.type() == Pawn::self()) {
68 for (int i
= 0; i
< state
->board()->size().y
; i
++) {
69 const Piece other
= state
->board()->get(Point(move
.dst().x
, i
));
70 if (other
.type() == Pawn::self() &&
71 other
.color() == state
->turn() &&
72 !other
.get("promoted").toBool())
81 bool Validator::legal(const IState
* state
, Move
& move
) const {
82 // do not check a move more than once
83 if (!move
.type().isEmpty()) return true;
85 if (!m_delegator
->pseudolegal(state
, move
))
88 const IBehaviour
* behaviour
= state
->behaviour();
89 if (!behaviour
) return false;
91 const IColor
* turn
= m_delegator
->mover(state
, move
);
93 std::auto_ptr
<IState
> tmp(state
->clone());
96 Point kingPos
= tmp
->board()->find(Piece(turn
, King::self()));
98 if (kingPos
== Point::invalid())
101 if (m_delegator
->attacks(tmp
.get(), behaviour
->opponent(turn
), kingPos
))
104 // set move type as normal, if not already set
105 if (move
.type().isEmpty()) move
.setType("normal");
109 // FIXME: move this logic into Piece classes ?
110 bool Validator::stuckPiece(const IState
* state
,
111 const Piece
& piece
, const Point
& p
) const {
112 const IBehaviour
* behaviour
= state
->behaviour();
114 if (piece
.type() == Pawn::self() || piece
.type() == Lance::self()) {
115 return p
.y
== state
->rank(0, behaviour
->opponent(piece
.color()));
117 else if (piece
.type() == Knight::self()) {
118 int rank
= state
->rank(0, behaviour
->opponent(piece
.color()));
119 return p
.y
== rank
|| p
.y
== rank
- behaviour
->direction(piece
.color()).y
;
126 bool Validator::attacks(const IState
* state
, const IColor
* player
,
127 const Point
& square
, const Piece
& target_
) const {
129 if (target_
!= Piece())
132 target
= state
->board()->get(square
);
134 for (int i
= 0; i
< state
->board()->size().x
; i
++) {
135 for (int j
= 0; j
< state
->board()->size().y
; j
++) {
137 const Piece piece
= state
->board()->get(p
);
138 Move
move(p
, square
);
139 if (piece
!= Piece() &&
140 piece
.color() == player
&&
141 piece
.type()->canMove(piece
, target
, move
, state
))
148 const IColor
* Validator::mover(const IState
* state
, const Move
& move
) const {
149 return state
->board()->get(move
.src()).color();
152 void Validator::setDelegator(IValidator
* delegator
) {
153 m_delegator
= delegator
;