2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2007 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
11 #ifndef HLVARIANT__SHOGI__LEGALITYCHECK_H
12 #define HLVARIANT__SHOGI__LEGALITYCHECK_H
14 #include "interactiontype.h"
15 #include "turnpolicy.h"
20 template <typename _GameState
>
23 typedef _GameState GameState
;
24 typedef typename
GameState::Board Board
;
25 typedef typename
Board::Piece Piece
;
26 typedef typename
GameState::Move Move
;
28 const GameState
& m_state
;
30 virtual bool stuckPiece(const Piece
& piece
, const Point
& p
) const;
32 LegalityCheck(const GameState
& state
);
33 virtual ~LegalityCheck();
35 virtual bool getMoveType(const Piece
& piece
, const Move
& move
) const;
36 bool legal(Move
& move
) const;
37 bool pseudolegal(Move
& move
) const;
38 bool canBeCaptured(const GameState
& state
, const Point
& point
) const;
40 virtual InteractionType
movable(const TurnTest
&, const Point
& x
) const;
41 virtual InteractionType
droppable(const TurnTest
&, int index
) const;
46 template <typename GameState
>
47 LegalityCheck
<GameState
>::LegalityCheck(const GameState
& state
)
50 template <typename GameState
>
51 LegalityCheck
<GameState
>::~LegalityCheck() { }
53 template <typename GameState
>
54 bool LegalityCheck
<GameState
>::getMoveType(const Piece
& piece
, const Move
& move
) const {
58 if (move
.from() == move
.to())
61 if (m_state
.board().get(move
.to()).color() == piece
.color())
63 Point delta
= move
.to() - move
.from();
65 if (!piece
.promoted()) {
66 switch (piece
.type()) {
68 return abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1;
70 return (delta
.x
== 0 && abs(delta
.y
) == 1)
71 || (delta
.y
== 0 && abs(delta
.x
) == 1)
72 || (delta
.y
== m_state
.direction(piece
.color()).y
&& abs(delta
.x
) <= 1);
74 return (abs(delta
.x
) == abs(delta
.y
) && abs(delta
.x
) == 1)
75 || (delta
.y
== m_state
.direction(piece
.color()).y
&& abs(delta
.x
) <= 1);
78 PathInfo path
= m_state
.board().path(move
.from(), move
.to());
79 return path
.parallel() && path
.clear();
83 PathInfo path
= m_state
.board().path(move
.from(), move
.to());
84 return path
.diagonal() && path
.clear();
88 return abs(delta
.x
) == 1 && delta
.y
== m_state
.direction(piece
.color()).y
* 2;
92 PathInfo path
= m_state
.board().path(move
.from(), move
.to());
93 return delta
.x
== 0 &&
95 (delta
.y
* m_state
.direction(piece
.color()).y
> 0);
98 return delta
== m_state
.direction(piece
.color());
100 case Piece::DRUNKEN_ELEPHANT
:
101 return (abs(delta
.x
) == 1 && abs(delta
.y
) <= 1)
102 || (delta
.x
== 0 && delta
.y
== m_state
.direction(piece
.color()).y
);
108 switch (piece
.type()) {
113 return (delta
.x
== 0 && abs(delta
.y
) == 1)
114 || (delta
.y
== 0 && abs(delta
.x
) == 1)
115 || (delta
.y
== m_state
.direction(piece
.color()).y
&& abs(delta
.x
) <= 1);
118 if (abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1) return true;
119 PathInfo path
= m_state
.board().path(move
.from(), move
.to());
120 return path
.parallel() && path
.clear();
124 if (abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1) return true;
125 PathInfo path
= m_state
.board().path(move
.from(), move
.to());
126 return path
.diagonal() && path
.clear();
129 case Piece::DRUNKEN_ELEPHANT
: // Crown Prince
130 return abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1;
138 template <typename GameState
>
139 bool LegalityCheck
<GameState
>::pseudolegal(Move
& move
) const {
140 if (move
.drop() == Piece() &&
142 move
.index() != -1) {
143 move
.setDrop(m_state
.pools().pool(move
.pool()).get(move
.index()));
146 Piece dropped
= move
.drop();
147 if (dropped
!= Piece()) {
148 if (m_state
.board().get(move
.to()) != Piece())
151 if (stuckPiece(dropped
, move
.to()))
154 if (dropped
.type() == Piece::PAWN
) {
155 for (int i
= 0; i
< m_state
.board().size().y
; i
++) {
156 Piece other
= m_state
.board().get(Point(move
.to().x
, i
));
157 if (other
.type() == Piece::PAWN
&&
158 other
.color() == m_state
.turn() &&
167 Piece piece
= m_state
.board().get(move
.from());
168 if (piece
!= Piece() && getMoveType(piece
, move
)) {
169 if (m_state
.canPromote(piece
) &&
170 (m_state
.promotionZone(piece
.color(), move
.to()) ||
171 m_state
.promotionZone(piece
.color(), move
.from())))
172 move
.setType(Move::PROMOTION
);
176 //std::cerr << "CANNOT MOVE: piece type cannot go there";
183 template <typename GameState
>
184 bool LegalityCheck
<GameState
>::canBeCaptured(const GameState
& state
, const Point
& point
) const {
185 for (int i
= 0; i
< m_state
.board().size().x
; i
++) {
186 for (int j
= 0; j
< m_state
.board().size().y
; j
++) {
188 Piece piece
= state
.board().get(p
);
189 LegalityCheck
<GameState
> check(state
);
190 if (piece
.color() == state
.turn() && check
.getMoveType(piece
, Move(p
, point
))) {
191 std::cerr
<< state
.board().get(point
).name() << " can be captured";
199 template <typename GameState
>
200 bool LegalityCheck
<GameState
>::legal(Move
& move
) const {
201 if (!pseudolegal(move
))
204 GameState
tmp(m_state
);
207 // find king position
208 Point king_pos
= tmp
.board().find(Piece(m_state
.turn(), Piece::KING
));
209 if (!king_pos
.valid())
212 // check if the king can be captured
213 if (canBeCaptured(tmp
, king_pos
))
219 template <typename GameState
>
220 bool LegalityCheck
<GameState
>::stuckPiece(const Piece
& piece
, const Point
& p
) const {
221 if (piece
.type() == Piece::PAWN
|| piece
.type() == Piece::LANCE
) {
222 return p
.y
== m_state
.startingRank(Piece::oppositeColor(piece
.color()));
224 else if (piece
.type() == Piece::KNIGHT
) {
225 int rank
= m_state
.startingRank(Piece::oppositeColor(piece
.color()));
226 return p
.y
== rank
|| p
.y
== rank
- m_state
.direction(piece
.color()).y
;
233 template <typename GameState
>
234 InteractionType LegalityCheck
<GameState
>::movable(const TurnTest
& test
, const Point
& p
) const {
235 Piece piece
= m_state
.board().get(p
);
236 if (piece
== Piece() || !test(piece
.color()))
239 return piece
.color() == m_state
.turn() ? Moving
: Premoving
;
242 template <typename GameState
>
243 InteractionType LegalityCheck
<GameState
>::droppable(const TurnTest
& test
, int index
) const {
247 typename
Piece::Color c
= static_cast<typename
Piece::Color
>(index
);
248 return c
== m_state
.turn() ? Moving
: Premoving
;
252 } // namespace HLVariant
254 #endif // HLVARIANT__SHOGI__LEGALITYCHECK_H