All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
effect5x3.cc
Go to the documentation of this file.
1 /* effect5x3.cc
2  */
5 #include "osl/pieceStand.h"
7 
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 
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 
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 
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 
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 
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>
126 Effect5x3WithBonus::makeEffectMask(const NumEffectState &state)
127 {
128  const Square king =
129  state.kingSquare<Defense>();
130  const Square center =
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 {
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 
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: