Add shogi-related traces in various places.
[tagua/yd.git] / src / hlvariant / shogi / legalitycheck.h
blob34fc699b82def2223bae038b335a554612d21a17
1 /*
2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@sns.it>
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.
9 */
11 #ifndef HLVARIANT__SHOGI__LEGALITYCHECK_H
12 #define HLVARIANT__SHOGI__LEGALITYCHECK_H
14 #include "interactiontype.h"
15 #include "turnpolicy.h"
17 namespace HLVariant {
18 namespace Shogi {
20 template <typename _GameState>
21 class LegalityCheck {
22 public:
23 typedef _GameState GameState;
24 typedef typename GameState::Board Board;
25 typedef typename Board::Piece Piece;
26 typedef typename GameState::Move Move;
27 private:
28 const GameState& m_state;
29 public:
30 LegalityCheck(const GameState& state);
31 virtual ~LegalityCheck();
33 virtual bool getMoveType(const Piece& piece, const Move& move) const;
34 bool legal(Move& move) const;
35 bool pseudolegal(Move& move) const;
37 virtual InteractionType movable(const TurnTest&, const Point& x) const;
38 virtual InteractionType droppable(const TurnTest&, int index) const;
41 // IMPLEMENTATION
43 template <typename GameState>
44 LegalityCheck<GameState>::LegalityCheck(const GameState& state)
45 : m_state(state) { }
47 template <typename GameState>
48 LegalityCheck<GameState>::~LegalityCheck() { }
50 template <typename GameState>
51 bool LegalityCheck<GameState>::getMoveType(const Piece& piece, const Move& move) const {
52 if (!move.valid())
53 return false;
55 if (move.from() == move.to())
56 return false;
58 if (m_state.board().get(move.to()).color() == piece.color())
59 return false;
60 Point delta = move.to() - move.from();
62 if (!piece.promoted()) {
63 switch (piece.type()) {
64 case Piece::KING:
65 return abs(delta.x) <= 1 && abs(delta.y) <= 1;
66 case Piece::GOLD:
67 return (delta.x == 0 && abs(delta.y) == 1)
68 || (delta.y == 0 && abs(delta.x) == 1)
69 || (delta.y == m_state.direction(piece.color()).y && abs(delta.x) <= 1);
70 case Piece::SILVER:
71 return (abs(delta.x) == abs(delta.y) && abs(delta.x) == 1)
72 || (delta.y == m_state.direction(piece.color()).y && abs(delta.x) <= 1);
73 case Piece::ROOK:
75 PathInfo path = m_state.board().path(move.from(), move.to());
76 return path.parallel() && path.clear();
78 case Piece::BISHOP:
80 PathInfo path = m_state.board().path(move.from(), move.to());
81 return path.diagonal() && path.clear();
83 case Piece::KNIGHT:
85 return abs(delta.x) == 1 && delta.y == m_state.direction(piece.color()).y * 2;
87 case Piece::LANCE:
89 PathInfo path = m_state.board().path(move.from(), move.to());
90 return delta.x == 0 &&
91 path.clear() &&
92 (delta.y * m_state.direction(piece.color()).y > 0);
94 case Piece::PAWN:
95 return delta == m_state.direction(piece.color());
96 default:
97 return false;
100 else {
101 switch (piece.type()) {
102 case Piece::SILVER:
103 case Piece::PAWN:
104 case Piece::LANCE:
105 case Piece::KNIGHT:
106 return (delta.x == 0 && abs(delta.y) == 1)
107 || (delta.y == 0 && abs(delta.x) == 1)
108 || (delta.y == m_state.direction(piece.color()).y && abs(delta.x) <= 1);
109 case Piece::ROOK:
111 if (abs(delta.x) <= 1 && abs(delta.y) <= 1) return true;
112 PathInfo path = m_state.board().path(move.from(), move.to());
113 return path.parallel() && path.clear();
115 case Piece::BISHOP:
117 if (abs(delta.x) <= 1 && abs(delta.y) <= 1) return true;
118 PathInfo path = m_state.board().path(move.from(), move.to());
119 return path.diagonal() && path.clear();
121 default:
122 return false;
127 template <typename GameState>
128 bool LegalityCheck<GameState>::pseudolegal(Move& move) const {
129 if (move.drop() == Piece() &&
130 move.pool() != -1 &&
131 move.index() != -1) {
132 move.setDrop(m_state.pools().pool(move.pool()).get(move.index()));
135 Piece dropped = move.drop();
136 if (dropped != Piece()) {
137 if (m_state.board().get(move.to()) != Piece())
138 return false;
140 // if (stuckPiece(dropped, m.to)) return false; // BROKEN
142 if (dropped.type() == Piece::PAWN) {
143 for (int i = 0; i < m_state.board().size().y; i++) {
144 Piece other = m_state.board().get(Point(move.to().x, i));
145 if (other.type() == Piece::PAWN &&
146 other.color() == m_state.turn() &&
147 !other.promoted())
148 return false;
152 return true;
154 else {
155 Piece piece = m_state.board().get(move.from());
156 if (piece != Piece() && getMoveType(piece, move)) {
157 if (!piece.promoted() &&
158 (m_state.promotionZone(piece.color(), move.to()) ||
159 m_state.promotionZone(piece.color(), move.from())))
160 move.setType(Move::PROMOTION);
161 return true;
163 else {
164 //std::cerr << "CANNOT MOVE: piece type cannot go there" << std::endl;
165 return false;
170 template <typename GameState>
171 bool LegalityCheck<GameState>::legal(Move& move) const {
172 if (!pseudolegal(move))
173 return false;
175 GameState tmp(m_state);
176 tmp.move(move);
178 // find king position
179 Point king_pos = tmp.board().find(Piece(m_state.turn(), Piece::KING));
180 if (!king_pos.valid())
181 return false;
183 // check if the king can be captured
184 for (int i = 0; i < m_state.board().size().x; i++) {
185 for (int j = 0; j < m_state.board().size().y; j++) {
186 Point p(i, j);
187 Piece piece = tmp.board().get(p);
188 LegalityCheck<GameState> check(tmp);
189 if (piece.color() == tmp.turn() && check.getMoveType(piece, Move(p, king_pos))) {
190 return false;
195 return true;
198 template <typename GameState>
199 InteractionType LegalityCheck<GameState>::movable(const TurnTest& test, const Point& p) const {
200 Piece piece = m_state.board().get(p);
201 if (piece == Piece() || !test(piece.color()))
202 return NoAction;
204 return piece.color() == m_state.turn() ? Moving : Premoving;
207 template <typename GameState>
208 InteractionType LegalityCheck<GameState>::droppable(const TurnTest& test, int index) const {
209 if (!test(index))
210 return NoAction;
212 typename Piece::Color c = static_cast<typename Piece::Color>(index);
213 return c == m_state.turn() ? Moving : Premoving;
216 } // namespace Shogi
217 } // namespace HLVariant
219 #endif // HLVARIANT__SHOGI__LEGALITYCHECK_H