My Project
escape_.tcc
Go to the documentation of this file.
1#ifndef OSL_GENERATE_ESCAPE_MOVES_TCC
2#define OSL_GENERATE_ESCAPE_MOVES_TCC
3
4#include "osl/move_generator/escape_.h"
5#include "osl/move_generator/capture_.h"
6#include "osl/move_generator/move_action.h"
7
8namespace osl
9{
10 namespace move_generator
11 {
12 namespace escape
13 {
14 /**
15 * Tの駒をtoに打つ手を生成する.
16 * 生成できたらtrueを返す.
17 */
18 template<Player P,class Action,Ptype Type>
19 bool generateDrop(const NumEffectState& state,Square to,Action& action){
20 if(state.template hasPieceOnStand<Type>(P)){
21 if((Type!=PAWN || !state.isPawnMaskSet(P,to.x())) &&
22 PtypePlayerTraits<Type,P>::canDropTo(to)){
23 action.dropMove(to,Type,P);
24 return true;
25 }
26 }
27 return false;
28 }
29 /*
30 * 駒をtoに打つ手を生成する.
31 * CheapOnlyの時は最も価値の低い駒を打つ手のみ生成する.
32 */
33 template<Player P,class Action,bool CheapOnly>
34 void generateDropAll(const NumEffectState& state,Square to,Action& action)
35 {
36 bool gen = generateDrop<P,Action,PAWN>(state,to,action); if (CheapOnly && gen) return;
37 gen = generateDrop<P,Action,LANCE>(state,to,action); if (CheapOnly && gen) return;
38 gen = generateDrop<P,Action,KNIGHT>(state,to,action); if (CheapOnly && gen) return;
39 gen = generateDrop<P,Action,SILVER>(state,to,action); if (CheapOnly && gen) return;
40 gen = generateDrop<P,Action,GOLD>(state,to,action); if (CheapOnly && gen) return;
41 gen = generateDrop<P,Action,BISHOP>(state,to,action); if (CheapOnly && gen) return;
42 generateDrop<P,Action,ROOK>(state,to,action);
43 }
44
45 /**
46 * 安い駒でposへ移動する手を生成する.
47 * 自殺手も生成している.
48 * TODO: あんまりなif文 PAWN,LANCE mask, それ以外maskでOK
49 */
50 template<Player P,class Action,bool CheapOnly>
51 void
52 blockByMoveOne(const NumEffectState& state, Square pos, Action &action)
53 {
54 const PieceMask pieces = state.effectSetAt(pos) & state.piecesOnBoard(P);
55 int offset = 0;
56 mask_t m = pieces.selectBit<PAWN>();
57 if (m.none()) {
58 m = pieces.selectBit<LANCE>();
59 offset = PtypeFuns<LANCE>::indexNum*32;
60 if (m.none()) {
61 m = pieces.selectBit<KNIGHT>();
62 offset = PtypeFuns<KNIGHT>::indexNum*32;
63 if (m.none()) {
64 m = pieces.selectBit<SILVER>();
65 offset = PtypeFuns<SILVER>::indexNum*32;
66 if (m.none()) {
67 m = pieces.selectBit<GOLD>();
68 offset = PtypeFuns<GOLD>::indexNum*32;
69 if (m.none()) {
70 m = pieces.selectBit<BISHOP>();
71 offset = PtypeFuns<BISHOP>::indexNum*32;
72 if (m.none()) {
73 m = pieces.selectBit<ROOK>();
74 offset = PtypeFuns<ROOK>::indexNum*32;
75 if (m.none())
76 return;
77 }
78 }
79 }
80 }
81 }
82 }
83 const Piece p = state.pieceOf(m.takeOneBit() + offset);
84 PieceOnBoard<Action>::template generatePiece<P>(state,p,pos,Piece::EMPTY(),action);
85 }
86 } // end of namespace escape
87 using escape::generateDropAll;
88 using escape::blockByMoveOne;
89
90 /**
91 * Square toにある玉以外の駒にfromにある駒から王手がかかっている時に,長い利きの途中に入る手を
92 * 生成する(合駒,駒移動).
93 * pが動く手は生成しない
94 * CheapOnlyの時は
95 * TODO: 自殺手も生成してしまう
96 * 短い利きの時にもこちらに入ってしまう
97 */
98 template<class Action>
99 template<Player P,bool CheapOnly>
100 void Escape<Action>::
101 generateBlocking(const NumEffectState& state,Piece p,Square to,Square from,Action &action)
102 {
103 assert(from.isOnBoard());
104 Offset offset=Board_Table.getShortOffset(Offset32(from,to));
105 assert(!offset.zero());
106 for(Square pos=to+offset;pos!=from;pos+=offset){
107 assert(state.pieceAt(pos).isEmpty());
108 if (! CheapOnly) {
109 Capture<Action>::template escapeByCapture<P>(state,pos,p,action);
110 // 駒を置いて
111 generateDropAll<P,Action,false>(state,pos,action);
112 }
113 else {
114 // 駒を動かして
115 const int e = state.countEffect(P, pos);
116 if (e >= 2)
117 blockByMoveOne<P,Action,CheapOnly>(state, pos, action);
118 // 駒を置いて
119 if (e)
120 generateDropAll<P,Action,true>(state,pos,action);
121 }
122 }
123 }
124 /**
125 * 玉pにfromにある駒から王手がかかっている時に,長い利きの途中に入る手を
126 * 生成する(合駒,駒移動).
127 * 短い利きの時にもこちらに入ってしまう
128 */
129 template<class Action>
130 template<Player P,bool CheapOnly>
131 void Escape<Action>::
132 generateBlockingKing(const NumEffectState& state,Piece p,Square from,Action &action)
133 {
134 Square to=p.square();
135 Offset offset=Board_Table.getShortOffset(Offset32(from,to));
136 assert(!offset.zero());
137 for(Square pos=to+offset;pos!=from;pos+=offset){
138 assert(state.pieceAt(pos).isEmpty());
139 Capture<Action>::template escapeByCapture<P>(state,pos,p,action);
140 // 駒を置いて
141 generateDropAll<P,Action,CheapOnly>(state,pos,action);
142 }
143 }
144 template<class Action>
145 template<Player P,Ptype Type,bool CheapOnly>
146 void Escape<Action>::
147 generateMovesBy(const NumEffectState& state,Piece p,Piece const attacker,Action& action)
148 {
149 if(attacker==Piece::EMPTY()){
150 /** escape only */
151 generateEscape<P,Type>(state,p,action);
152 }
153 else if(Type == KING){
154#ifndef NDEBUG
155 {
156 Piece attack_by_position;
157 state.template findCheckPiece<P>(attack_by_position);
158 assert(attacker == attack_by_position);
159 }
160#endif
161 Square attackFrom=attacker.square();
162
163 generateCaptureKing<P>( state, p, attackFrom, action );
164 /** escape */
165 generateEscape<P,Type>( state,p,action);
166 /** 合い駒 */
167 generateBlockingKing<P,CheapOnly>(state,p,attackFrom,action);
168 }
169 else{
170 Square attackFrom=attacker.square();
171 generateCapture<P>( state, p, attackFrom, action );
172 /** escape */
173 generateEscape<P,Type>( state,p,action);
174 /** 合い駒 */
175 generateBlocking<P,CheapOnly>(state,p,p.square(),attackFrom,action);
176 }
177 }
178
179 template<class Action>
180 template<Player P,bool CheapOnly>
181 void Escape<Action>::
182 generateKingEscape(const NumEffectState& state,Action& action){
183 Piece kingPiece=state.pieceOf(KingTraits<P>::index);
184 Piece attacker;
185#ifndef NDEBUG
186 const bool is_attacked=
187#endif
188 state.template findCheckPiece<P>(attacker);
189 assert(is_attacked); // 相手からの利きがないのに呼ぶな
190 generateMovesBy<P,KING,CheapOnly>(state,kingPiece,attacker,action);
191 }
192
193 template<class Action>
194 template<Player P,Ptype TYPE,bool CheapOnly>
195 void Escape<Action>::
196 generateMovesBy(const NumEffectState& state,Piece p,Action& action)
197 {
198 Square target=p.square();
199 Piece attacker;
200#ifndef NDEBUG
201 const bool is_attacked=
202#endif
203 state.template hasEffectAt<alt(P)>(target,attacker);
204 assert(is_attacked); // 相手からの利きがないのに呼ぶな
205 generateMovesBy<P,TYPE,CheapOnly>(state,p,attacker,action);
206 }
207
208 template<class Action>
209 template<Player P,bool CheapOnly>
210 void Escape<Action>::
211 generateMoves(const NumEffectState& state,Piece piece,Piece attacker,Action& action)
212 {
213 switch(piece.ptype()){
214 case PAWN: generateMovesBy<P,PAWN,CheapOnly>(state,piece,attacker,action); break;
215 case LANCE: generateMovesBy<P,LANCE,CheapOnly>(state,piece,attacker,action); break;
216 case KNIGHT: generateMovesBy<P,KNIGHT,CheapOnly>(state,piece,attacker,action); break;
217 case SILVER: generateMovesBy<P,SILVER,CheapOnly>(state,piece,attacker,action); break;
218 case PPAWN: generateMovesBy<P,PPAWN,CheapOnly>(state,piece,attacker,action); break;
219 case PLANCE: generateMovesBy<P,PLANCE,CheapOnly>(state,piece,attacker,action); break;
220 case PKNIGHT: generateMovesBy<P,PKNIGHT,CheapOnly>(state,piece,attacker,action); break;
221 case PSILVER: generateMovesBy<P,PSILVER,CheapOnly>(state,piece,attacker,action); break;
222 case GOLD: generateMovesBy<P,GOLD,CheapOnly>(state,piece,attacker,action); break;
223 case BISHOP: generateMovesBy<P,BISHOP,CheapOnly>(state,piece,attacker,action); break;
224 case PBISHOP: generateMovesBy<P,PBISHOP,CheapOnly>(state,piece,attacker,action); break;
225 case ROOK: generateMovesBy<P,ROOK,CheapOnly>(state,piece,attacker,action); break;
226 case PROOK: generateMovesBy<P,PROOK,CheapOnly>(state,piece,attacker,action); break;
227 case KING: generateMovesBy<P,KING,CheapOnly>(state,piece,attacker,action); break;
228 default: assert(0);
229
230 }
231 }
232 template<class Action>
233 template<Player P,bool shouldPromote,bool CheapOnly>
234 void Escape<Action>::
235 generate(const NumEffectState& state,Piece piece,Action& action)
236 {
237 assert(piece.owner() == P);
238 Square target=piece.square();
239 Piece attacker;
240 state.template hasEffectAt<alt(P)>(target,attacker);
241 generateMoves<P,CheapOnly>(state,piece,attacker,action);
242 }
243 } // namespace move_generator
244
245} // namespace osl
246
247#endif // OSL_GENERATE_ESCAPE_MOVES_TCC
248// ;;; Local Variables:
249// ;;; mode:c++
250// ;;; c-basic-offset:2
251// ;;; End:
252