2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2007 Maurizio Monge <maurizio.monge@kdemail.net>
4 (c) 2007 Yann Dirson <ydirson@altern.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
12 #ifndef HLVARIANT__TORISHOGI__LEGALITYCHECK_H
13 #define HLVARIANT__TORISHOGI__LEGALITYCHECK_H
15 #include "interactiontype.h"
16 #include "../shogi/legalitycheck.h"
21 template <typename _GameState
>
22 class LegalityCheck
: public Shogi::LegalityCheck
<_GameState
> {
23 typedef Shogi::LegalityCheck
<_GameState
> Base
;
25 typedef _GameState GameState
;
26 typedef typename
GameState::Board Board
;
27 typedef typename
Board::Piece Piece
;
28 typedef typename
GameState::Move Move
;
30 LegalityCheck(const GameState
& state
);
32 virtual bool getMoveType(const Piece
& piece
, const Move
& move
) const;
33 bool legal(Move
& move
) const;
34 bool pseudolegal(Move
& move
) const;
36 virtual bool stuckPiece(const Piece
& piece
, const Point
& p
) const;
41 template <typename GameState
>
42 LegalityCheck
<GameState
>::LegalityCheck(const GameState
& state
)
45 template <typename GameState
>
46 bool LegalityCheck
<GameState
>::getMoveType(const Piece
& piece
, const Move
& move
) const {
50 if (move
.from() == move
.to())
53 if (Base::m_state
.board().get(move
.to()).color() == piece
.color())
55 Point delta
= move
.to() - move
.from();
57 if (!piece
.promoted()) {
58 switch (piece
.type()) {
60 return abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1;
62 return (abs(delta
.x
) == 1 && abs(delta
.y
) <= 1)
63 || (delta
.x
== 0 && delta
.y
== Base::m_state
.direction(piece
.color()).y
);
65 return (abs(delta
.y
) == 1 && abs(delta
.x
) <= 1);
67 return (delta
.x
== 0 && delta
.y
== 2 * Base::m_state
.direction(piece
.color()).y
)
68 || (abs(delta
.x
) == 1 && delta
.y
== -Base::m_state
.direction(piece
.color()).y
);
71 return delta
== Base::m_state
.direction(piece
.color());
73 case Piece::RIGHT_QUAIL
:
75 if (delta
.x
== 1 && delta
.y
== -Base::m_state
.direction(piece
.color()).y
)
77 PathInfo path
= Base::m_state
.board().path(move
.from(), move
.to());
78 return ((path
.parallel() && delta
.y
* Base::m_state
.direction(piece
.color()).y
> 0) ||
79 (path
.diagonal() && delta
.y
* Base::m_state
.direction(piece
.color()).y
< 0
80 && delta
.x
< 0)) && path
.clear();
82 case Piece::LEFT_QUAIL
:
84 if (delta
.x
== -1 && delta
.y
== -Base::m_state
.direction(piece
.color()).y
)
86 PathInfo path
= Base::m_state
.board().path(move
.from(), move
.to());
87 return ((path
.parallel() && delta
.y
* Base::m_state
.direction(piece
.color()).y
> 0) ||
88 (path
.diagonal() && delta
.y
* Base::m_state
.direction(piece
.color()).y
< 0
89 && delta
.x
> 0)) && path
.clear();
97 switch (piece
.type()) {
98 case Piece::SWALLOW
: // Goose
99 return (delta
.x
== 0 && delta
.y
== -2 * Base::m_state
.direction(piece
.color()).y
)
100 || (abs(delta
.x
) == 2 && delta
.y
== 2 * Base::m_state
.direction(piece
.color()).y
);
102 case Piece::FALCON
: // Eagle
104 if (abs(delta
.x
) <= 1 && abs(delta
.y
) <= 1)
106 PathInfo path
= Base::m_state
.board().path(move
.from(), move
.to());
107 return ((path
.parallel() && delta
.y
* Base::m_state
.direction(piece
.color()).y
< 0) ||
108 (path
.diagonal() && delta
.y
* Base::m_state
.direction(piece
.color()).y
> 0) ||
109 (path
.diagonal() && delta
.y
* Base::m_state
.direction(piece
.color()).y
== -2)) &&
118 template <typename GameState
>
119 bool LegalityCheck
<GameState
>::pseudolegal(Move
& move
) const {
120 if (move
.drop() == Piece() &&
122 move
.index() != -1) {
123 move
.setDrop(Base::m_state
.pools().pool(move
.pool()).get(move
.index()));
126 Piece dropped
= move
.drop();
127 if (dropped
!= Piece()) {
128 if (Base::m_state
.board().get(move
.to()) != Piece())
131 if (stuckPiece(dropped
, move
.to()))
134 if (dropped
.type() == Piece::SWALLOW
) {
135 int otherswallows
= 0;
136 for (int i
= 0; i
< Base::m_state
.board().size().y
; i
++) {
137 Piece other
= Base::m_state
.board().get(Point(move
.to().x
, i
));
138 if (other
.type() == Piece::SWALLOW
&&
139 other
.color() == Base::m_state
.turn() &&
142 if (otherswallows
>= 2)
151 Piece piece
= Base::m_state
.board().get(move
.from());
152 if (piece
!= Piece() && getMoveType(piece
, move
)) {
153 if (Base::m_state
.canPromote(piece
) &&
154 (Base::m_state
.promotionZone(piece
.color(), move
.to()) ||
155 Base::m_state
.promotionZone(piece
.color(), move
.from())))
156 move
.setType(Move::PROMOTION
);
160 //std::cerr << "CANNOT MOVE: piece type cannot go there";
167 template <typename GameState
>
168 bool LegalityCheck
<GameState
>::legal(Move
& move
) const {
169 if (!pseudolegal(move
))
172 GameState
tmp(Base::m_state
);
175 // find king and prince positions
176 Point king_pos
= tmp
.board().find(Piece(Base::m_state
.turn(), Piece::PHOENIX
));
178 if (!king_pos
.valid())
181 // check if the king can be captured
182 if (Base::canBeCaptured(tmp
, king_pos
))
188 template <typename GameState
>
189 bool LegalityCheck
<GameState
>::stuckPiece(const Piece
& piece
, const Point
& p
) const {
190 if (piece
.type() == Piece::SWALLOW
) {
191 return p
.y
== Base::m_state
.startingRank(Piece::oppositeColor(piece
.color()));
198 } // namespace ToriShogi
199 } // namespace HLVariant
201 #endif // HLVARIANT__TORISHOGI__LEGALITYCHECK_H