effect5x3.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
effect5x3.cc
Go to the documentation of this file.
1 /* effect5x3.cc
2 */
3 #include "osl/progress/effect5x3.h"
4 #include "osl/progress/effect5x3Table.h"
5 #include "osl/pieceStand.h"
6 #include "osl/container/pieceMask.h"
7
8 osl::progress::
9 Effect5x3::Effect5x3(const NumEffectState& state)
10 {
11 area_progresses[BLACK]=makeProgressArea(WHITE, state, state.kingSquare(BLACK));
12 area_progresses[WHITE]=makeProgressArea(BLACK, state, state.kingSquare(WHITE));
13 stand_progresses[WHITE]=makeProgressStand(BLACK, state);
14 stand_progresses[BLACK]=makeProgressStand(WHITE, state);
15 progresses[BLACK]=area_progresses[BLACK]+stand_progresses[BLACK];
16 progresses[WHITE]=area_progresses[WHITE]+stand_progresses[WHITE];
17 }
18
19 int osl::progress::
20 Effect5x3::makeProgressAll(Player defense, const NumEffectState& state,
21 Square king)
22 {
23 return makeProgressArea(alt(defense), state, king)
24 + makeProgressStand(alt(defense), state);
25 }
26
27 int osl::progress::
28 Effect5x3::makeProgressArea(Player attack, const NumEffectState& state,
29 Square king)
30 {
31 const Square center = Centering5x3::adjustCenter(king);
32
33 const int min_x = center.x() - 2;
34 const int min_y = center.y() - 1;
35
36 // 利き
37 int sum_effect = 0;
38
39 for (int dx=0; dx<5; ++dx)
40 {
41 for (int dy=0; dy<3; ++dy)
42 {
43 const Square target(min_x+dx,min_y+dy);
44 sum_effect += state.countEffect(attack, target) *
45 Effect5x3_Table.getAttackEffect(attack,king,dx,dy);
46 }
47 }
48 return sum_effect / 2;
49 }
50
51 int osl::progress::
52 Effect5x3::makeProgressStand(Player attack, const NumEffectState& state)
53 {
54 // 持駒
55 int sum_pieces = 0;
56 sum_pieces += state.countPiecesOnStand<PAWN>(attack)*Effect5x3Table::StandPAWN;
57 sum_pieces += state.countPiecesOnStand<LANCE>(attack)*Effect5x3Table::StandLANCE;
58 sum_pieces += state.countPiecesOnStand<KNIGHT>(attack)*Effect5x3Table::StandKNIGHT;
59 sum_pieces += state.countPiecesOnStand<SILVER>(attack)*Effect5x3Table::StandSILVER;
60 sum_pieces += state.countPiecesOnStand<GOLD>(attack)*Effect5x3Table::StandGOLD;
61 sum_pieces += state.countPiecesOnStand<BISHOP>(attack)*Effect5x3Table::StandBISHOP;
62 sum_pieces += state.countPiecesOnStand<ROOK>(attack)*Effect5x3Table::StandROOK;
63 return sum_pieces;
64 }
65
66 void osl::progress::
67 Effect5x3::updateStand(int& old_stand, Move last_move)
68 {
69 if (last_move.isDrop()) {
70 const Ptype ptype = last_move.ptype();
71 old_stand -= Effect5x3_Table.piecesOnStand(ptype);
72 return;
73 }
74 const Ptype ptype = last_move.capturePtype();
75 if (ptype == PTYPE_EMPTY) {
76 return;
77 }
78 old_stand += Effect5x3_Table.piecesOnStand(unpromote(ptype));
79 }
80
81 void osl::progress::
82 Effect5x3::update(const NumEffectState& new_state, Move last_move)
83 {
84 const Player pl = last_move.player();
85 updateStand(stand_progresses[alt(pl)], last_move);
86
87 const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
88 BoardMask mb = new_state.changedEffects(BLACK), mw = new_state.changedEffects(WHITE);
89 bool king_move = last_move.ptype() == KING;
90 if ((king_move && new_state.turn() == BLACK) || mb.anyInRange(Board_Mask_Table5x3_Center.mask(kw)))
91 area_progresses[WHITE]=makeProgressArea(BLACK,new_state, kw);
92 if ((king_move && new_state.turn() == WHITE) || mw.anyInRange(Board_Mask_Table5x3_Center.mask(kb)))
93 area_progresses[BLACK]=makeProgressArea(WHITE,new_state, kb);
94
95 progresses[BLACK]=area_progresses[BLACK]+stand_progresses[BLACK];
96 progresses[WHITE]=area_progresses[WHITE]+stand_progresses[WHITE];
97 }
98
99 osl::progress::Effect5x3 osl::progress::
100 Effect5x3::expect(const NumEffectState&, Move move) const
101 {
102 Effect5x3 new_progress = *this;
103 if (move.capturePtype() != PTYPE_EMPTY) {
104 const Player alt_pl = alt(move.player());
105 int old = stand_progresses[alt_pl];
106 updateStand(new_progress.stand_progresses[alt_pl], move);
107 new_progress.progresses[alt_pl] += new_progress.stand_progresses[alt_pl] - old;
108 }
109 return new_progress;
110 }
111
112 /* ------------------------------------------------------------------------- */
113
114 osl::progress::
115 Effect5x3WithBonus::Effect5x3WithBonus(const NumEffectState& state) : Effect5x3(state)
116 {
117 progress_bonuses[BLACK]=makeProgressAreaBonus<WHITE>(state, state.kingSquare<BLACK>());
118 progress_bonuses[WHITE]=makeProgressAreaBonus<BLACK>(state, state.kingSquare<WHITE>());
119 effect_mask[BLACK] = makeEffectMask<BLACK>(state);
120 effect_mask[WHITE] = makeEffectMask<WHITE>(state);
121 updateProgressBonuses(state);
122 }
123
124 template <osl::Player Defense>
125 osl::container::PieceMask osl::progress::
126 Effect5x3WithBonus::makeEffectMask(const NumEffectState &state)
127 {
128 const Square king =
129 state.kingSquare<Defense>();
130 const Square center =
131 Centering5x3::adjustCenter(king);
132
133 const int min_x = center.x() - 2;
134 const int min_y = center.y() - 1;
135
136 PieceMask mask;
137 for (int dx = 0; dx < 5; ++dx)
138 {
139 for (int dy = 0; dy < 3; ++dy)
140 {
141 const Square target(min_x+dx, min_y+dy);
142 mask = mask | state.effectSetAt(target);
143 }
144 }
145 return mask;
146 }
147
148 inline
149 int osl::progress::
150 Effect5x3WithBonus::attackEffect3(const NumEffectState& state, Player attack, Square target)
151 {
152 const int a = state.countEffect(attack, target);
153 if (a <= 1)
154 return a;
155 if (state.countEffect(alt(attack), target) > 0
156 || state.pieceAt(target).isOnBoardByOwner(attack))
157 return 1;
158 return 2;
159 }
160
161 namespace osl
162 {
163 namespace
164 {
165 template <Player P>
166 int countPawnLanceKnight(const NumEffectState& state, Square target)
167 {
168 // effect is max 2, pawn and lance cannot have the effect
169 // to a position at the same time so this is OK
170 const Square d = target+DirectionPlayerTraits<D,P>::offset();
171 const Piece pd = state.pieceAt(d);
172
173 // pawn and lance
174 int count = 0;
175 if (pd.ptypeO() == newPtypeO(P,PAWN))
176 ++count;
177 else if (pd.ptypeO() == newPtypeO(P,LANCE))
178 ++count;
179 else if (pd.isEmpty())
180 {
181 if (state.hasLongEffectAt<LANCE>(P, target))
182 ++count;
183 }
184 else if (pd.isEdge())
185 return 0;
186
187 // knight
188 const Piece pdl = state.pieceAt(d+DirectionPlayerTraits<DL,P>::offset());
189 if (pdl.ptypeO() == newPtypeO(P,KNIGHT))
190 return count+1;
191 const Piece pdr = state.pieceAt(d+DirectionPlayerTraits<DR,P>::offset());
192 if (pdr.ptypeO() == newPtypeO(P,KNIGHT))
193 return count+1;
194 return count;
195 }
196 }
197 }
198
199 template <osl::Player Attack, bool AlwaysPromotable, bool AlwaysNotPromotable>
200 int osl::progress::
201 Effect5x3WithBonus::makeProgressAreaBonus(const NumEffectState& state, Square king,
202 Square center)
203 {
204 const int min_x = center.x() - 2;
205 const int min_y = center.y() - 1;
206
207 // 利き
208 int sum_effect = 0;
209
210 for (int dy = 0; dy < 3; ++dy)
211 {
212 const Square target(king.x(), min_y + dy);
213 int effect = attackEffect3(state, Attack, target) * 2;
214 if (effect > 0)
215 {
216 if (! AlwaysPromotable
217 && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
218 {
219 effect -= countPawnLanceKnight<Attack>(state, target);
220 assert(effect >= 0);
221 }
222 sum_effect += effect *
223 Effect5x3_Table.getAttackEffect(Attack, king, target.x() - min_x, dy) / 2;
224
225 }
226 }
227 for (int x = king.x() - 1; x >= min_x; --x)
228 {
229 int y_count = 0;
230 int sum = 0;
231 for (int dy = 0; dy < 3; ++dy)
232 {
233 const Square target(x, min_y + dy);
234 int effect = attackEffect3(state, Attack, target) * 2;
235 if (effect > 0)
236 {
237 if (! AlwaysPromotable
238 && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
239 {
240 if (king.x() - x > 1)
241 effect = 0;
242 else
243 effect -= countPawnLanceKnight<Attack>(state, target);
244 assert(effect >= 0);
245 }
246 sum += effect *
247 Effect5x3_Table.getAttackEffect(Attack, king, x - min_x, dy) / 2;
248 y_count++;
249 }
250 }
251 sum_effect += sum;
252 if (y_count == 3)
253 {
254 sum_effect += sum;
255 break;
256 }
257 }
258 for (int x = king.x() + 1; x < min_x + 5; ++x)
259 {
260 int y_count = 0;
261 int sum = 0;
262 for (int dy = 0; dy < 3; ++dy)
263 {
264 const Square target(x, min_y + dy);
265 int effect = attackEffect3(state, Attack, target) * 2;
266 if (effect > 0)
267 {
268 if (! AlwaysPromotable
269 && (AlwaysNotPromotable || !target.canPromote<Attack>()) )
270 {
271 if (x - king.x() > 1)
272 effect = 0;
273 else
274 effect -= countPawnLanceKnight<Attack>(state, target);
275 assert(effect >= 0);
276 }
277 sum += effect *
278 Effect5x3_Table.getAttackEffect(Attack, king, x - min_x, dy) / 2;
279 y_count++;
280 }
281 }
282 sum_effect += sum;
283 if (y_count == 3)
284 {
285 sum_effect += sum;
286 break;
287 }
288 }
289 return sum_effect / 2;
290 }
291
292 template <osl::Player Attack>
293 int osl::progress::
294 Effect5x3WithBonus::makeProgressAreaBonus(const NumEffectState& state,
295 Square king)
296 {
297 const Square center = Centering5x3::adjustCenter(king);
298
299 const bool always_promotable = center.squareForBlack<Attack>().y() <= 2;
300 if (always_promotable)
301 return makeProgressAreaBonus<Attack,true,false>(state, king, center);
302 const bool always_notpromotable = center.squareForBlack<Attack>().y() >= 5;
303 if (always_notpromotable)
304 return makeProgressAreaBonus<Attack,false,true>(state, king, center);
305 return makeProgressAreaBonus<Attack,false,false>(state, king, center);
306 }
307
308 void osl::progress::
309 Effect5x3WithBonus::update(const NumEffectState& new_state, Move last_move)
310 {
311 Effect5x3::update(new_state, last_move);
312
313 const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
314 BoardMask mask = new_state.changedEffects();
315 mask.set(last_move.to()); mask.set(last_move.from());
316
317 const bool update_black = mask.anyInRange(Board_Mask_Table5x3_Center.mask(kb));
318 const bool update_white = mask.anyInRange(Board_Mask_Table5x3_Center.mask(kw));
319
320 if (update_black)
321 {
322 progress_bonuses[BLACK]=makeProgressAreaBonus<WHITE>(new_state,kb);
323 effect_mask[BLACK] = makeEffectMask<BLACK>(new_state);
324 }
325 if (update_white)
326 {
327 progress_bonuses[WHITE]=makeProgressAreaBonus<BLACK>(new_state,kw);
328 effect_mask[WHITE] = makeEffectMask<WHITE>(new_state);
329 }
330 updateProgressBonuses(new_state, update_black, update_white);
331 }
332
333 osl::progress::Effect5x3WithBonus osl::progress::
334 Effect5x3WithBonus::expect(const NumEffectState&, Move move) const
335 {
336 Effect5x3WithBonus new_progress = *this;
337 if (move.capturePtype() != PTYPE_EMPTY) {
338 const Player alt_pl = alt(move.player());
339 int old = stand_progresses[playerToIndex(alt_pl)];
340 new_progress.updateStand(alt_pl, move);
341 new_progress.progresses[playerToIndex(alt_pl)] += new_progress.stand_progresses[playerToIndex(alt_pl)] - old;
342 }
343 return new_progress;
344 }
345
346 void osl::progress::
347 Effect5x3WithBonus::updateProgressBonuses(const NumEffectState& state, bool update_black, bool update_white)
348 {
349 if (update_black && progress_bonuses[BLACK] != 0)
350 {
351 const int pieces = countEffectPieces(state, WHITE);
352 progress_bonuses[BLACK] =
353 std::min(pieces * pieces * 4,
354 progress_bonuses[BLACK]);
355 }
356 if (update_white && progress_bonuses[WHITE] != 0)
357 {
358 const int pieces = countEffectPieces(state, BLACK);
359 progress_bonuses[WHITE] =
360 std::min(pieces * pieces * 4,
361 progress_bonuses[WHITE]);
362 }
363 }
364
365 int osl::progress::
366 Effect5x3WithBonus::countEffectPieces(const NumEffectState &state, Player attack) const
367 {
368 PieceMask mask = effect5x3Mask(alt(attack));
369 mask = mask & state.piecesOnBoard(attack);
370 return mask.countBit();
371 }
372
373 /* ------------------------------------------------------------------------- */
374 // ;;; Local Variables:
375 // ;;; mode:c++
376 // ;;; c-basic-offset:2
377 // ;;; End: