progressEval.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
progressEval.cc
Go to the documentation of this file.
1 /* progressEval.cc
2 */
3 #include "osl/eval/progressEval.h"
4 #include "osl/container/pieceValues.h"
5 #include "osl/state/numEffectState.h"
6 #include "osl/effect_util/effectUtil.tcc"
7 #include "osl/oslConfig.h"
8 #include <boost/filesystem/operations.hpp>
9 #include <iostream>
10 #include <cstdio>
11
12 BOOST_STATIC_ASSERT((osl::eval::ProgressEval::ROUND_UP
13 & (osl::eval::ProgressEval::ROUND_UP-1))
14 == 0);
15 #ifndef MINIMAL
16 template <class Opening>
17 osl::CArray<int, osl::PTYPEO_SIZE> osl::eval::ProgressEvalGeneral<Opening>::capture_values;
18
19 template <class Opening>
20 int osl::eval::
21 ProgressEvalGeneral<Opening>::expect(const NumEffectState& state, Move move) const
22 {
23 if (move.isPass())
24 return value();
25 progress_t new_progress = current_progress.expect(state, move);
26 return composeValue(opening_eval.expect(state, move),
27 endgame_eval.expect(state, move),
28 progress16(), new_progress.progress16(BLACK),
29 new_progress.progress16(WHITE),
30 defense_effect.progress16(BLACK),
31 defense_effect.progress16(WHITE),
32 minor_piece_bonus.value(progress16(),
33 progress16bonus(BLACK),
34 progress16bonus(WHITE)),
35 progress_independent_bonus,
36 progress_dependent_bonus);
37 }
38
39 template <class Opening>
40 void osl::eval::
41 ProgressEvalGeneral<Opening>::setUpInternal(const char *filename_given)
42 {
43 // read weights if exists
44 std::string filename;
45 if (filename_given)
46 filename = filename_given;
47 else {
48 filename = OslConfig::home();
49 filename += "/data/progresseval.txt";
50 }
51 if (boost::filesystem::exists(filename.c_str())) {
52 if (OslConfig::verbose())
53 std::cerr << "loading " << filename << "\n";
54 CArray<int, AdjustableDimension> w;
55 FILE *fp = fopen(filename.c_str(), "r");
56 for (size_t i=0; i<w.size(); ++i) {
57 if (fscanf(fp, "%d", &w[i]) != 1) {
58 std::cerr << filename << " read failed " << i << "\n";
59 break;
60 }
61 }
62 fclose(fp);
63 resetWeights(&w[0]);
64 }
65
66 // others
67 for (int i=0; i<PTYPEO_SIZE; ++i) {
68 // 序盤を使用
69 const PtypeO ptypeo = static_cast<PtypeO>(i+PTYPEO_MIN);
70 capture_values[i] = composeValue(opening_eval_t::captureValue(ptypeo), 0,
71 Progress16(0), Progress16(0), Progress16(0),
72 Progress16(0), Progress16(0), 0, 0, 0);
73 }
74 }
75
76 template <class Opening>
77 void osl::eval::
78 ProgressEvalGeneral<Opening>::resetWeights(const int *w)
79 {
80 opening_eval_t::resetWeights(w);
81 endgame_eval_t::resetWeights(w+PTYPE_SIZE);
82 }
83
84 template <class Opening>
85 osl::eval::
86 ProgressEvalGeneral<Opening>::ProgressEvalGeneral(const NumEffectState& state)
87 : opening_eval(state), endgame_eval(state),
88 current_progress(state), defense_effect(state),
89 minor_piece_bonus(state), major_pieces(0),
90 cache(INVALID)
91 {
92 for (int i = PtypeTraits<ROOK>::indexMin;
93 i < PtypeTraits<ROOK>::indexLimit; ++i)
94 {
95 if (state.pieceOf(i).owner() == osl::BLACK)
96 ++major_pieces;
97 }
98 for (int i = PtypeTraits<BISHOP>::indexMin;
99 i < PtypeTraits<BISHOP>::indexLimit; ++i)
100 {
101 if (state.pieceOf(i).owner() == osl::BLACK)
102 ++major_pieces;
103 }
104 can_check_pieces.fill(0);
105 // knight and pawn are intentionally omitted
106 initializeCheckPiece<BLACK, ROOK>(state);
107 initializeCheckPiece<BLACK, BISHOP>(state);
108 initializeCheckPiece<BLACK, GOLD>(state);
109 initializeCheckPiece<BLACK, SILVER>(state);
110 initializeCheckPiece<BLACK, LANCE>(state);
111 initializeCheckPiece<WHITE, ROOK>(state);
112 initializeCheckPiece<WHITE, BISHOP>(state);
113 initializeCheckPiece<WHITE, GOLD>(state);
114 initializeCheckPiece<WHITE, SILVER>(state);
115 initializeCheckPiece<WHITE, LANCE>(state);
116 rook_mobility = calculateMobilityBonusRook(state);
117 bishop_mobility = calculateMobilityBonusBishop(state);
118 lance_mobility = calculateMobilityBonusLance(state);
119 progress_independent_bonus = calculateMobilityBonus();
120 progress_independent_bonus += calculateAttackRooks(state);
121 progress_independent_bonus += calculateSilverPenalty(state);
122 progress_independent_bonus += calculateGoldPenalty(state);
123 attack_bonus[BLACK] = calculateAttackBonusEach<WHITE>(state);
124 attack_bonus[WHITE] = calculateAttackBonusEach<BLACK>(state);
125 progress_dependent_bonus = attackBonusScale(attack_bonus[BLACK], WHITE);
126 progress_dependent_bonus += attackBonusScale(attack_bonus[WHITE], BLACK);
127 progress_dependent_bonus += calculatePinBonus(state);
128 progress_independent_bonus += calculateKnightCheck(state);
129 progress_independent_bonus += calculateRookRankBonus(state);
130 progress_independent_bonus += calculateEnterKingBonus<BLACK>(state);
131 progress_independent_bonus += calculateEnterKingBonus<WHITE>(state);
132 progress_independent_bonus += calculateMiddleKingBonus<BLACK>(state);
133 progress_independent_bonus += calculateMiddleKingBonus<WHITE>(state);
134 assert(initialized());
135 }
136
137 template <class Opening>
138 template<osl::Player P, osl::Ptype PTYPE>
139 void osl::eval::
140 ProgressEvalGeneral<Opening>::initializeCheckPiece(
141 const NumEffectState &state)
142 {
143 if (state.hasPieceOnStand<PTYPE>(P))
144 {
145 int count = state.countPiecesOnStand(P, PTYPE);
146 initializeCheckPieceDir<P, PTYPE, UL, LONG_UL>(state, count);
147 initializeCheckPieceDir<P, PTYPE, U, LONG_U>(state, count);
148 initializeCheckPieceDir<P, PTYPE, UR, LONG_UR>(state, count);
149 initializeCheckPieceDir<P, PTYPE, L, LONG_L>(state, count);
150 initializeCheckPieceDir<P, PTYPE, R, LONG_R>(state, count);
151 initializeCheckPieceDir<P, PTYPE, DL, LONG_DL>(state, count);
152 initializeCheckPieceDir<P, PTYPE, D, LONG_D>(state, count);
153 initializeCheckPieceDir<P, PTYPE, DR, LONG_DR>(state, count);
154 }
155 }
156
157 template <class Opening>
158 template<osl::Player P, osl::Ptype PTYPE, osl::Direction Dir, osl::Direction LongDir>
159 void osl::eval::
160 ProgressEvalGeneral<Opening>::initializeCheckPieceDir(
161 const NumEffectState &,
162 int count)
163 {
164 if (PtypeTraits<PTYPE>::moveMask & (DirectionTraits<Dir>::mask
165 | DirectionTraits<LongDir>::mask))
166 can_check_pieces[P][Dir] = count;
167 }
168
169 template <class Opening>
170 int osl::eval::
171 ProgressEvalGeneral<Opening>::calculateMobilityBonusRook(const NumEffectState& state)
172 {
173 using namespace osl::mobility;
174 int val=0;
175 for(int i=PtypeTraits<ROOK>::indexMin;
176 i<PtypeTraits<ROOK>::indexLimit;++i){
177 Piece p=state.pieceOf(i);
178 if(p.isOnBoardByOwner<BLACK>()){
179 int vc= RookMobility::countVerticalAll(BLACK,state,p);
180 int hc= RookMobility::countHorizontalAll(BLACK,state,p);
181 if(p.isPromoted()){
182 val+=MobilityTable::prookVertical[vc];
183 val+=MobilityTable::prookHorizontal[hc];
184 }
185 else{
186 val+=MobilityTable::rookVertical[vc];
187 val+=MobilityTable::rookHorizontal[hc];
188 }
189 }
190 else if(p.isOnBoardByOwner<WHITE>()){
191 int vc= RookMobility::countVerticalAll(WHITE,state,p);
192 int hc= RookMobility::countHorizontalAll(WHITE,state,p);
193 if(p.isPromoted()){
194 val-=MobilityTable::prookVertical[vc];
195 val-=MobilityTable::prookHorizontal[hc];
196 }
197 else{
198 val-=MobilityTable::rookVertical[vc];
199 val-=MobilityTable::rookHorizontal[hc];
200 }
201 }
202 }
203 return val;
204 }
205
206 template <class Opening>
207 int osl::eval::
208 ProgressEvalGeneral<Opening>::calculateMobilityBonusBishop(const NumEffectState& state)
209 {
210 using namespace osl::mobility;
211 int val=0;
212 for(int i=PtypeTraits<BISHOP>::indexMin;
213 i<PtypeTraits<BISHOP>::indexLimit;++i){
214 Piece p=state.pieceOf(i);
215 if(p.isOnBoardByOwner<BLACK>()){
216 int c= BishopMobility::countAll(BLACK,state,p);
217 if(p.isPromoted())
218 val+=MobilityTable::pbishop[c];
219 else
220 val+=MobilityTable::bishop[c];
221 }
222 else if(p.isOnBoardByOwner<WHITE>()){
223 int c= BishopMobility::countAll(WHITE,state,p);
224 if(p.isPromoted())
225 val-=MobilityTable::pbishop[c];
226 else
227 val-=MobilityTable::bishop[c];
228 }
229 }
230 return val;
231 }
232
233 template <class Opening>
234 int osl::eval::
235 ProgressEvalGeneral<Opening>::calculateMobilityBonusLance(const NumEffectState& state)
236 {
237 using namespace osl::mobility;
238 int val=0;
239 for(int i=PtypeTraits<LANCE>::indexMin;
240 i<PtypeTraits<LANCE>::indexLimit;++i){
241 Piece p=state.pieceOf(i);
242 if(p.isOnBoardByOwner<BLACK>() && !p.isPromoted()){
243 int c= LanceMobility::countAll(BLACK,state,p);
244 val+=MobilityTable::lance[c];
245 }
246 else if(p.isOnBoardByOwner<WHITE>() && !p.isPromoted()){
247 int c= LanceMobility::countAll(WHITE,state,p);
248 val-=MobilityTable::lance[c];
249 }
250 }
251 return val;
252 }
253
254 template <class Opening> inline
255 int osl::eval::
256 ProgressEvalGeneral<Opening>::calculateMobilityBonus() const
257 {
258 using namespace osl::mobility;
259 int val=rook_mobility + bishop_mobility + lance_mobility;
260 return val*128/100 * 12;
261 }
262
263 template <class Opening>
264 void osl::eval::
265 ProgressEvalGeneral<Opening>::update(
266 const NumEffectState& new_state, Move last_move)
267 {
268 if (last_move.isPass())
269 return;
270 const Ptype captured = last_move.capturePtype();
271 if (last_move.isDrop())
272 {
273 const Ptype ptype = last_move.ptype();
274 if (ptype == ROOK)
275 {
276 --can_check_pieces[playerToIndex(last_move.player())][U];
277 --can_check_pieces[playerToIndex(last_move.player())][D];
278 --can_check_pieces[playerToIndex(last_move.player())][L];
279 --can_check_pieces[playerToIndex(last_move.player())][R];
280 }
281 else if (ptype == BISHOP)
282 {
283 --can_check_pieces[playerToIndex(last_move.player())][UL];
284 --can_check_pieces[playerToIndex(last_move.player())][DL];
285 --can_check_pieces[playerToIndex(last_move.player())][UR];
286 --can_check_pieces[playerToIndex(last_move.player())][DR];
287 }
288 if (ptype == GOLD)
289 {
290 --can_check_pieces[playerToIndex(last_move.player())][U];
291 --can_check_pieces[playerToIndex(last_move.player())][D];
292 --can_check_pieces[playerToIndex(last_move.player())][L];
293 --can_check_pieces[playerToIndex(last_move.player())][R];
294 --can_check_pieces[playerToIndex(last_move.player())][UL];
295 --can_check_pieces[playerToIndex(last_move.player())][UR];
296 }
297 else if (ptype == SILVER)
298 {
299 --can_check_pieces[playerToIndex(last_move.player())][U];
300 --can_check_pieces[playerToIndex(last_move.player())][UL];
301 --can_check_pieces[playerToIndex(last_move.player())][DL];
302 --can_check_pieces[playerToIndex(last_move.player())][UR];
303 --can_check_pieces[playerToIndex(last_move.player())][DR];
304 }
305 if (ptype == LANCE)
306 {
307 --can_check_pieces[playerToIndex(last_move.player())][U];
308 }
309 }
310
311 if (captured != PTYPE_EMPTY)
312 {
313 const Ptype captured_base = unpromote(captured);
314 if (isMajor(captured_base))
315 {
316 if (last_move.player() == BLACK)
317 ++major_pieces;
318 else
319 --major_pieces;
320 }
321 if (captured_base == ROOK)
322 {
323 ++can_check_pieces[playerToIndex(last_move.player())][U];
324 ++can_check_pieces[playerToIndex(last_move.player())][D];
325 ++can_check_pieces[playerToIndex(last_move.player())][L];
326 ++can_check_pieces[playerToIndex(last_move.player())][R];
327 }
328 else if (captured_base == BISHOP)
329 {
330 ++can_check_pieces[playerToIndex(last_move.player())][UL];
331 ++can_check_pieces[playerToIndex(last_move.player())][DL];
332 ++can_check_pieces[playerToIndex(last_move.player())][UR];
333 ++can_check_pieces[playerToIndex(last_move.player())][DR];
334 }
335 if (captured_base == GOLD)
336 {
337 ++can_check_pieces[playerToIndex(last_move.player())][U];
338 ++can_check_pieces[playerToIndex(last_move.player())][D];
339 ++can_check_pieces[playerToIndex(last_move.player())][L];
340 ++can_check_pieces[playerToIndex(last_move.player())][R];
341 ++can_check_pieces[playerToIndex(last_move.player())][UL];
342 ++can_check_pieces[playerToIndex(last_move.player())][UR];
343 }
344 else if (captured_base == SILVER)
345 {
346 ++can_check_pieces[playerToIndex(last_move.player())][U];
347 ++can_check_pieces[playerToIndex(last_move.player())][UL];
348 ++can_check_pieces[playerToIndex(last_move.player())][DL];
349 ++can_check_pieces[playerToIndex(last_move.player())][UR];
350 ++can_check_pieces[playerToIndex(last_move.player())][DR];
351 }
352 if (captured_base == LANCE)
353 {
354 ++can_check_pieces[playerToIndex(last_move.player())][U];
355 }
356 }
357 opening_eval.update(new_state, last_move);
358 endgame_eval.update(new_state, last_move);
359 current_progress.update(new_state, last_move);
360 defense_effect.update(new_state, last_move);
361 minor_piece_bonus.update(new_state, last_move);
362
363 if (new_state.longEffectChanged<ROOK>())
364 rook_mobility = calculateMobilityBonusRook(new_state);
365 if (new_state.longEffectChanged<BISHOP>())
366 bishop_mobility = calculateMobilityBonusBishop(new_state);
367 if (new_state.longEffectChanged<LANCE>())
368 lance_mobility = calculateMobilityBonusLance(new_state);
369
370 progress_independent_bonus = calculateMobilityBonus();
371 progress_independent_bonus += calculateAttackRooks(new_state);
372 progress_independent_bonus += calculateSilverPenalty(new_state);
373 progress_independent_bonus += calculateGoldPenalty(new_state);
374
375 {
376 bool capture_or_drop = last_move.isDrop() || last_move.capturePtype() != PTYPE_EMPTY;
377 const Square kb = new_state.kingSquare<BLACK>(), kw = new_state.kingSquare<WHITE>();
378 BoardMask mask = new_state.changedEffects();
379 mask.set(last_move.from()); mask.set(last_move.to());
380 if ((capture_or_drop && new_state.turn() == BLACK)
381 || mask.anyInRange(Board_Mask_Table3x3.mask(kb)))
382 attack_bonus[BLACK] = calculateAttackBonusEach<WHITE>(new_state);
383 if ((capture_or_drop && new_state.turn() == WHITE)
384 || mask.anyInRange(Board_Mask_Table3x3.mask(kw)))
385 attack_bonus[WHITE] = calculateAttackBonusEach<BLACK>(new_state);
386 }
387 progress_dependent_bonus = attackBonusScale(attack_bonus[BLACK], WHITE);
388 progress_dependent_bonus += attackBonusScale(attack_bonus[WHITE], BLACK);
389 progress_dependent_bonus += calculatePinBonus(new_state);
390 progress_independent_bonus += calculateKnightCheck(new_state);
391 progress_independent_bonus += calculateRookRankBonus(new_state);
392 progress_independent_bonus += calculateEnterKingBonus<BLACK>(new_state);
393 progress_independent_bonus += calculateEnterKingBonus<WHITE>(new_state);
394 progress_independent_bonus += calculateMiddleKingBonus<BLACK>(new_state);
395 progress_independent_bonus += calculateMiddleKingBonus<WHITE>(new_state);
396 invalidateCache();
397 }
398
399 template <class Opening>
400 int osl::eval::
401 ProgressEvalGeneral<Opening>::calculatePinBonus(
402 const NumEffectState& state) const
403 {
404 const Piece black_king = state.kingPiece<BLACK>();
405 const Piece white_king = state.kingPiece<WHITE>();
406 int bonus = 0;
407 PieceMask white_mask = pin_mask[WHITE] = state.pin(WHITE);
408 PieceMask black_mask = pin_mask[BLACK] = state.pin(BLACK);
409 while (white_mask.any())
410 {
411 const Piece piece = state.pieceOf(white_mask.takeOneBit());
412 bonus -= endgame_eval.valueOf(
413 black_king, white_king,
414 piece) / 4;
415 }
416
417 while (black_mask.any())
418 {
419 const Piece piece = state.pieceOf(black_mask.takeOneBit());
420 bonus -= endgame_eval.valueOf(
421 black_king, white_king,
422 piece) / 4;
423 }
424
425 return bonus * progress16().value() / 16;
426 }
427
428 template <class Opening>
429 int osl::eval::
430 ProgressEvalGeneral<Opening>::calculateAttackRooks(
431 const NumEffectState& state) const
432 {
433 int rooks = 0;
434 for(int i = PtypeTraits<ROOK>::indexMin;
435 i < PtypeTraits<ROOK>::indexLimit; ++i)
436 {
437 const Piece rook = state.pieceOf(i);
438 if (rook.isOnBoard() && rook.square().canPromote(rook.owner()) &&
439 state.kingPiece(alt(rook.owner())).square().canPromote(rook.owner()))
440 {
441 if (rook.owner() == BLACK)
442 ++rooks;
443 else
444 --rooks;
445 }
446 }
447 if (rooks == 2)
448 return (PtypeEvalTraits<KNIGHT>::val + PtypeEvalTraits<PAWN>::val) * 16;
449 else if (rooks == -2)
450 return -(PtypeEvalTraits<KNIGHT>::val + PtypeEvalTraits<PAWN>::val) * 16;
451
452 return 0;
453 }
454
455 template <class Opening>
456 int osl::eval::
457 ProgressEvalGeneral<Opening>::calculateAttackBonus(
458 const NumEffectState& state) const
459 {
460 return attackBonusScale(calculateAttackBonusEach<BLACK>(state), BLACK) +
461 attackBonusScale(calculateAttackBonusEach<WHITE>(state), WHITE);
462 }
463
464 template <class Opening>
465 template <osl::Player Attack, osl::Direction Dir>
466 int osl::eval::
467 ProgressEvalGeneral<Opening>::calculateAttackBonusOne(
468 const NumEffectState& state) const
469 {
470 const Player defense = PlayerTraits<Attack>::opponent;
471 const Square king = state.kingSquare<defense>();
472
473 const Square target = king + DirectionPlayerTraits<Dir, defense>::offset();
474 int result = 0;
475
476 const Piece p = state.pieceAt(target);
477 if (! p.isEdge() && (Dir != UUR || Attack != BLACK || p.isOnBoard()))
478 {
479 int effect_diff = (state.countEffect(Attack, target) -
480 state.countEffect(PlayerTraits<Attack>::opponent, target));
481 if ((effect_diff >= 0 && p.isEmpty()) ||
482 (effect_diff >= 1 && !p.isEmpty() &&
483 p.owner() ==alt(Attack)))
484 {
485 if (Dir == UL || Dir == U || Dir == UR)
486 result = PtypeEvalTraits<PAWN>::val * 3 * 16;
487 else if (Dir == L || Dir == R)
488 result = (PtypeEvalTraits<PAWN>::val * 1 +
489 PtypeEvalTraits<PAWN>::val / 2) * 16;
490 else
491 result = PtypeEvalTraits<PAWN>::val * 1 * 16;
492
493 if ((effect_diff > 0 &&
494 (target.canPromote<Attack>() ||
495 state.hasEffectByPtype<GOLD>(Attack,target) ||
496 state.hasEffectByPtype<SILVER>(Attack,target) ||
497 state.hasEffectByPtype<ROOK>(Attack,target) ||
498 state.hasEffectByPtype<BISHOP>(Attack,target))) ||
499 (p.isEmpty() &&
500 can_check_pieces[Attack][Dir] > 0))
501 result += PtypeEvalTraits<PAWN>::val * 16;
502 }
503 }
504
505 if (Attack == BLACK)
506 return result;
507 else
508 return -result;
509 }
510
511 // P is attacking player
512 template <class Opening>
513 template <osl::Player P>
514 int osl::eval::
515 ProgressEvalGeneral<Opening>::calculateAttackBonusEach(
516 const NumEffectState& state) const
517 {
518 int result = 0;
519 result += calculateAttackBonusOne<P, UL>(state);
520 result += calculateAttackBonusOne<P, U>(state);
521 result += calculateAttackBonusOne<P, UR>(state);
522 result += calculateAttackBonusOne<P, L>(state);
523 result += calculateAttackBonusOne<P, R>(state);
524 result += calculateAttackBonusOne<P, DL>(state);
525 result += calculateAttackBonusOne<P, D>(state);
526 result += calculateAttackBonusOne<P, DR>(state);
527 return result;
528 }
529
530 template <class Opening>
531 int osl::eval::
532 ProgressEvalGeneral<Opening>::calculateSilverPenalty(
533 const NumEffectState &state) const
534 {
535 int result = 0;
536 const int bonus = PtypeEvalTraits<PAWN>::val / 4 * 16;
537 for (int i = PtypeTraits<SILVER>::indexMin;
538 i < PtypeTraits<SILVER>::indexLimit; ++i)
539 {
540 const Piece silver = state.pieceOf(i);
541 if (!silver.isOnBoard() || silver.isPromoted())
542 continue;
543
544 if (silver.square().y() >= 4 && silver.square().y() <= 6)
545 {
546 Square dl = Board_Table.nextSquare(silver.owner(),
547 silver.square(), DL);
548 Square dr = Board_Table.nextSquare(silver.owner(),
549 silver.square(), DR);
550 if ((!dl.isOnBoard() ||
551 state.pieceAt(dl).isOnBoardByOwner(silver.owner()) ||
552 state.hasEffectAt(alt(silver.owner()), dl)) &&
553 (!dr.isOnBoard() ||
554 state.pieceAt(dr).isOnBoardByOwner(silver.owner()) ||
555 state.hasEffectAt(alt(silver.owner()), dr)))
556 {
557 if (silver.owner() == BLACK)
558 result -= bonus;
559 else
560 result += bonus;
561 }
562 }
563
564 }
565 return result;
566 }
567
568 template <class Opening>
569 int osl::eval::
570 ProgressEvalGeneral<Opening>::calculateGoldPenalty(
571 const NumEffectState &state) const
572 {
573 int result = 0;
574 const int bonus = PtypeEvalTraits<PAWN>::val / 4 * 16;
575 for (int i = PtypeTraits<GOLD>::indexMin;
576 i < PtypeTraits<GOLD>::indexLimit; ++i)
577 {
578 const Piece gold = state.pieceOf(i);
579 if (!gold.isOnBoard())
580 continue;
581
582 if (gold.square().y() >= 4 && gold.square().y() <= 6)
583 {
584 Square d = Board_Table.nextSquare(gold.owner(),
585 gold.square(), D);
586 if ((state.pieceAt(d).isOnBoardByOwner(gold.owner()) ||
587 state.hasEffectAt(alt(gold.owner()), d)))
588 {
589 if (gold.owner() == BLACK)
590 result -= bonus;
591 else
592 result += bonus;
593 }
594 }
595
596 }
597 return result;
598 }
599
600 template <class Opening>
601 int osl::eval::
602 ProgressEvalGeneral<Opening>::calculateKnightCheck(
603 const NumEffectState& state) const
604 {
605 return calculateKnightCheckEach<BLACK>(state) +
606 calculateKnightCheckEach<WHITE>(state);
607 }
608
609 // P is attacking player
610 template <class Opening>
611 template <osl::Player P>
612 int osl::eval::
613 ProgressEvalGeneral<Opening>::calculateKnightCheckEach(
614 const NumEffectState& state) const
615 {
616 const int bonus = (P == BLACK ? 1 : -1) *
617 (PtypeEvalTraits<PAWN>::val * 3 + PtypeEvalTraits<PAWN>::val / 2) * 16;
618 const Square king = state.kingSquare<PlayerTraits<P>::opponent>();
619 const Square up = king +
620 DirectionPlayerTraits<U,PlayerTraits<P>::opponent>::offset();
621 if (!state.hasEffectAt<PlayerTraits<P>::opponent>(king)
622 && ! state.pieceAt(up).isEdge())
623 {
624 const Square ur =
625 up + DirectionPlayerTraits<UR,PlayerTraits<P>::opponent>::offset();
626 if (! state.pieceAt(ur).isEdge() &&
627 state.pieceAt(ur).isEmpty() &&
628 !state.hasEffectAt<PlayerTraits<P>::opponent>(ur) &&
629 (state.hasPieceOnStand<KNIGHT>(P) ||
630 state.hasEffectByPtype<KNIGHT>(P, ur)))
631 {
632 if (state.hasPieceOnStand<GOLD>(P))
633 return bonus;
634 else
635 return bonus / 2;
636 }
637
638 const Square ul =
639 up + DirectionPlayerTraits<UL,PlayerTraits<P>::opponent>::offset();
640 if (! state.pieceAt(ul).isEdge() &&
641 state.pieceAt(ul).isEmpty() &&
642 !state.hasEffectAt<PlayerTraits<P>::opponent>(ul) &&
643 (state.hasPieceOnStand<KNIGHT>(P) ||
644 state.hasEffectByPtype<KNIGHT>(P, ul)))
645 {
646 if (state.hasPieceOnStand<GOLD>(P))
647 return bonus;
648 else
649 return bonus / 2;
650 }
651 }
652 return 0;
653 }
654
655 // P is defense player
656 template <class Opening>
657 template <osl::Player P>
658 int osl::eval::
659 ProgressEvalGeneral<Opening>::calculateEnterKingBonus(
660 const NumEffectState& state) const
661 {
662 const Square king = state.kingSquare<P>();
663
664 if ((P == BLACK && king.y() > 4) ||
665 (P == WHITE && king.y() < 6))
666 {
667 return 0;
668 }
669
670 // If not the last rank, check one rank above
671 if ((P == BLACK && king.y() >= 2) ||
672 (P == WHITE && king.y() <= 8))
673 {
674 const int y = P == BLACK ? king.y() - 1 : king.y() + 1;
675 const int min_x = std::max(1, king.x() - 1);
676 const int max_x = std::min(9, king.x() + 1);
677 bool found_opening = false;
678 for (int x = min_x; x <= max_x; ++x)
679 {
680 Square pos(x, y);
681 Piece piece = state.pieceAt(pos);
682 if (piece.isEmpty())
683 {
684 if (!state.hasEffectAt<PlayerTraits<P>::opponent>(pos))
685 found_opening = true;
686 else if (state.countEffect(P, pos) <=
687 state.countEffect(alt(P), pos))
688 return 0;
689 }
690 else if (piece.owner() == alt(P))
691 {
692 return 0;
693 }
694 else if (piece.owner() == P)
695 {
696 if (state.countEffect(P, pos) <
697 state.countEffect(alt(P), pos))
698 return 0;
699 }
700 else
701 abort();
702 }
703 if (!found_opening)
704 return 0;
705 }
706
707 return PtypeEvalTraits<PAWN>::val * 16 * PlayerTraits<P>::offsetMul * 4;
708 }
709
710 // P is defense player
711 template <class Opening>
712 template <osl::Player P>
713 int osl::eval::
714 ProgressEvalGeneral<Opening>::calculateMiddleKingBonus(
715 const NumEffectState& state) const
716 {
717 const Square king = state.kingSquare<P>();
718
719 if ((P == BLACK && king.y() >= 6 && major_pieces == 4) ||
720 (P == WHITE && king.y() <= 4 && major_pieces == 0))
721 {
722 return PtypeEvalTraits<PAWN>::val * 2 * 16 * PlayerTraits<P>::offsetMul;
723 }
724 return 0;
725 }
726
727 template<class Opening>
728 int osl::eval::
729 ProgressEvalGeneral<Opening>::calculateRookRankBonus(
730 const NumEffectState& state) const
731 {
732 int bonus = 0;
733 for (int i = PtypeTraits<ROOK>::indexMin;
734 i < PtypeTraits<ROOK>::indexLimit; ++i)
735 {
736 const Piece rook = state.pieceOf(i);
737 const Player owner = rook.owner();
738 const int target_y = owner == BLACK ? 3 : 7;
739 const int inbetween_y = owner == BLACK ? 4 : 6;
740 if (rook.isOnBoard() && !rook.square().canPromote(owner))
741 {
742 const Piece rank5 = state.pieceAt(Square(rook.square().x(), 5));
743 const Piece rank4 = state.pieceAt(Square(rook.square().x(),
744 inbetween_y));
745 const Square rank3_pos(rook.square().x(), target_y);
746 if (state.hasEffectByPtype<SILVER>(
747 owner,
748 Square(rook.square().x(),
749 inbetween_y)) &&
750 !rank5.isOnBoardByOwner(alt(owner)) &&
751 !state.pieceAt(rank3_pos).isOnBoardByOwner(owner) &&
752 state.countEffect(alt(owner),
753 Square(rook.square().x(), target_y)) <= 1 &&
754 state.countEffect(owner,
755 Square(rook.square().x(), inbetween_y)) >=
756 state.countEffect(alt(owner),
757 Square(rook.square().x(), inbetween_y)))
758 {
759 if (rook.owner() == BLACK)
760 bonus += PtypeEvalTraits<PAWN>::val * 2 * 16;
761 else
762 bonus -= PtypeEvalTraits<PAWN>::val * 2 * 16;
763 }
764 else if (((rank5.isOnBoardByOwner(owner) &&
765 rank5.ptype() == PAWN &&
766 state.hasEffectByPiece(rook, rank5.square())) ||
767 (rank4.isOnBoardByOwner(owner) &&
768 rank4.ptype() == PAWN &&
769 state.hasEffectByPiece(rook, rank4.square()))) &&
770 !state.hasEffectAt(alt(owner),
771 rank3_pos) &&
772 state.countEffect(alt(owner),
773 Square(rook.square().x(),
774 inbetween_y)) <= 1)
775 {
776 if (rook.owner() == BLACK)
777 bonus += PtypeEvalTraits<PAWN>::val * 2 * 16;
778 else
779 bonus -= PtypeEvalTraits<PAWN>::val * 2 * 16;
780 }
781 else if (state.hasEffectByPiece(rook, rank3_pos) &&
782 !state.hasEffectAt(alt(owner), rank3_pos) &&
783 !state.isPawnMaskSet(owner, rook.square().x()))
784 {
785 if (rook.owner() == BLACK)
786 bonus += PtypeEvalTraits<PAWN>::val * 16;
787 else
788 bonus -= PtypeEvalTraits<PAWN>::val * 16;
789 }
790 }
791 }
792 return bonus;
793 }
794
795 template <class Opening>
796 void osl::eval::
797 ProgressEvalGeneral<Opening>::setValues(const SimpleState& state,
798 Progress16 progress16,
799 PieceValues& out)
800 {
801 PieceValues opening, endgame;
802 const NumEffectState nstate(state);
803 const progress_t progress(nstate);
804 const defense_t defense_effect(nstate);
805 const MinorPieceBonus minor_piece_bonus(state);
806 opening_eval_t::setValues(state, opening);
807 endgame_eval_t::setValues(state, endgame);
808 for (int i=0; i<Piece::SIZE; ++i)
809 {
810 out[i] = composeValue(opening[i] & (~1), endgame[i] & (~1), progress16,
811 progress.progress16(BLACK),
812 progress.progress16(WHITE),
813 defense_effect.progress16(BLACK),
814 defense_effect.progress16(WHITE),
815 minor_piece_bonus.value(progress16,
816 progress.progress16bonus(BLACK),
817 progress.progress16bonus(WHITE)), 0, 0);
818 }
819 }
820
821 template <class Opening>
822 void osl::eval::
823 ProgressEvalGeneral<Opening>::setValues(const SimpleState& state, PieceValues& out)
824 {
825 const NumEffectState nstate(state);
826 const progress_t progress(nstate);
827 setValues(state, progress.progress16(), out);
828 }
829
830 template <class Opening>
831 osl::eval::ProgressDebugInfo osl::eval::
832 ProgressEvalGeneral<Opening>::debugInfo(const NumEffectState& state) const
833 {
834 ProgressDebugInfo debug_info;
835 debug_info.eval = value();
836 debug_info.opening = openingValue();
837 debug_info.endgame = endgameValue();
838 debug_info.progress = current_progress.progress16().value();
839 debug_info.progress_bonus = attackDefenseBonus();
840 debug_info.progress_independent_bonus = progress_independent_bonus;
841 debug_info.progress_dependent_bonus = progress_dependent_bonus;
842 debug_info.minor_piece_bonus = minorPieceValue();
843
844 debug_info.black_danger = current_progress.progress16bonus(BLACK).value();
845 debug_info.white_danger = current_progress.progress16bonus(WHITE).value();
846 debug_info.black_defense = defense_effect.progress16(BLACK).value();
847 debug_info.white_defense = defense_effect.progress16(WHITE).value();
848
849 debug_info.mobility_bonus = calculateMobilityBonus();
850 debug_info.two_rook_bonus = calculateAttackRooks(state);
851 debug_info.knight_check_bonus = calculateKnightCheck(state);
852 debug_info.rook_rank_bonus = calculateRookRankBonus(state);
853 debug_info.enter_king_bonus = calculateEnterKingBonus<BLACK>(state) +
854 calculateEnterKingBonus<WHITE>(state);
855 debug_info.middle_king_bonus = calculateMiddleKingBonus<BLACK>(state) +
856 calculateMiddleKingBonus<WHITE>(state);
857 debug_info.silver_penalty = calculateSilverPenalty(state);
858 debug_info.gold_penalty = calculateGoldPenalty(state);
859
860 debug_info.king8_attack_bonus = calculateAttackBonus(state);
861 debug_info.pin_bonus = calculatePinBonus(state);
862
863 debug_info.minor_piece_bonus_info =
864 minor_piece_bonus.debugInfo(progress16(),
865 progress16bonus(BLACK),
866 progress16bonus(WHITE));
867
868 return debug_info;
869 }
870
871 namespace osl
872 {
873 namespace eval
874 {
875 template class ProgressEvalGeneral<progress_eval_opening_t>;
876 }
877 #ifndef DFPNSTATONE
878 template void
879 EffectUtil::findThreat<eval::ProgressEval>(const NumEffectState& state,
880 Square position,
881 PtypeO ptypeo,
882 PieceVector& out);
883 #endif
884 }
885
886 #endif
887 /* ------------------------------------------------------------------------- */
888 // ;;; Local Variables:
889 // ;;; mode:c++
890 // ;;; c-basic-offset:2
891 // ;;; coding:utf-8
892 // ;;; End: