minorPiece.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
minorPiece.cc
Go to the documentation of this file.
1 #include "osl/eval/ml/minorPiece.h"
2 #include "osl/effect_util/additionalEffect.h"
3 #include <iostream>
4 using osl::MultiInt;
5
6 void osl::eval::ml::PawnDropX::setUp(const Weights &weights)
7 {
8 for (size_t i = 0; i < ONE_DIM; ++i)
9 {
10 for (int s=0; s<NStages; ++s)
11 PawnDropBoth::x_table[i][s] = weights.value(i+ONE_DIM*s);
12 }
13 }
14
15 osl::misc::CArray<osl::MultiInt, 9>
16 osl::eval::ml::PawnDropBoth::attack_table;
17 osl::misc::CArray<osl::MultiInt, 9>
18 osl::eval::ml::PawnDropBoth::defense_table;
19 osl::misc::CArray<osl::MultiInt, 81>
20 osl::eval::ml::PawnDropBoth::attack_y_table;
21 osl::misc::CArray<osl::MultiInt, 81>
22 osl::eval::ml::PawnDropBoth::defense_y_table;
23 osl::misc::CArray<osl::MultiInt, 90>
24 osl::eval::ml::PawnDropBoth::x_table;
25 osl::misc::CArray<osl::MultiInt, 18>
26 osl::eval::ml::PawnDropBoth::stand_table;
27 osl::misc::CArray<osl::MultiInt, 90>
28 osl::eval::ml::PawnDropBoth::x_stand_table;
29 osl::misc::CArray<osl::MultiInt, 162>
30 osl::eval::ml::PawnDropBoth::y_stand_table;
31 osl::misc::CArray<osl::MultiInt, 10>
32 osl::eval::ml::PawnDropBoth::drop_non_drop_table;
33 osl::misc::CArray<osl::MultiInt, 36>
34 osl::eval::ml::PawnDropBoth::state_king_relative_table;
35 osl::CArray<osl::MultiInt, 1>
36 osl::eval::ml::SilverAdvance26::table;
37
38 void osl::eval::ml::PawnDrop::setUp(const Weights &weights,int stage)
39 {
40 for (int i = 0; i < ONE_DIM; ++i)
41 {
42 PawnDropBoth::defense_table[i][stage] = weights.value(i);
43 PawnDropBoth::attack_table[i][stage] = weights.value(i + ONE_DIM);
44 }
45 }
46
47 void osl::eval::ml::PawnDropY::setUp(const Weights &weights,int stage)
48 {
49 for (int i = 0; i < ONE_DIM; ++i)
50 {
51 PawnDropBoth::attack_y_table[i][stage] = weights.value(i);
52 PawnDropBoth::defense_y_table[i][stage] = weights.value(i + ONE_DIM);
53 }
54 }
55
56 void osl::eval::ml::PawnDropPawnStand::setUp(const Weights &weights)
57 {
58 for (int i = 0; i < ONE_DIM; ++i)
59 {
60 for (int s=0; s<NStages; ++s)
61 PawnDropBoth::stand_table[i][s] = weights.value(i + ONE_DIM*s);
62 }
63 }
64
65 void osl::eval::ml::PawnDropPawnStandX::setUp(const Weights &weights)
66 {
67 for (int i = 0; i < ONE_DIM; ++i)
68 {
69 for (int s=0; s<NStages; ++s)
70 PawnDropBoth::x_stand_table[i][s] = weights.value(i + ONE_DIM*s);
71 }
72 }
73 void osl::eval::ml::PawnDropPawnStandY::setUp(const Weights &weights)
74 {
75 for (int i = 0; i < ONE_DIM; ++i)
76 {
77 for (int s=0; s<NStages; ++s)
78 PawnDropBoth::y_stand_table[i][s] = weights.value(i + ONE_DIM*s);
79 }
80 }
81
82 void osl::eval::ml::PawnDropNonDrop::setUp(const Weights &weights)
83 {
84 for (int i = 0; i < ONE_DIM; ++i)
85 {
86 for (int s=0; s<NStages; ++s)
87 PawnDropBoth::drop_non_drop_table[i][s] = weights.value(i + ONE_DIM*s);
88 }
89 }
90
91 void osl::eval::ml::PawnStateKingRelative::setUp(const Weights &weights)
92 {
93 for (int i = 0; i < ONE_DIM; ++i)
94 {
95 for (int s=0; s<NStages; ++s)
96 PawnDropBoth::state_king_relative_table[i][s] = weights.value(i + ONE_DIM*s);
97 }
98 }
99
100 osl::MultiInt osl::eval::ml::PawnDropBoth::eval(
101 const NumEffectState &state)
102 {
103 osl::MultiInt result;
104 CArray<Square, 2> kings = {{state.kingSquare<BLACK>(),
105 state.kingSquare<WHITE>()}};
106 CArray<Piece, 2> king_piece = {{state.kingPiece<BLACK>(),
107 state.kingPiece<WHITE>()}};
108 CArray<bool, 2> has_pawn = {{state.hasPieceOnStand<PAWN>(BLACK),
109 state.hasPieceOnStand<PAWN>(WHITE)}};
110 for (int x = 1; x <= 9; ++x)
111 {
112 const bool black_on_board = state.isPawnMaskSet<BLACK>(x);
113 const bool white_on_board = state.isPawnMaskSet<WHITE>(x);
114 if (!black_on_board)
115 {
116 const int attack_index = index(kings[WHITE], x);
117 const int defense_index = index(kings[BLACK], x);
118 const int attack_index_x =
119 indexX<true>(king_piece[WHITE], x);
120 const int defense_index_x =
121 indexX<false>(king_piece[BLACK], x);
122 const int attack_index_y = indexY<WHITE>(king_piece[WHITE], x);
123 const int defense_index_y = indexY<BLACK>(king_piece[BLACK], x);
124 result += value(attack_index, defense_index,
125 attack_index_y, defense_index_y,
126 attack_index_x, defense_index_x);
127 if (has_pawn[BLACK])
128 {
129 result += standValue(attack_index, defense_index,
130 attack_index_y, defense_index_y,
131 attack_index_x, defense_index_x);
132 }
133 }
134 if (!white_on_board)
135 {
136 const int attack_index = index(kings[BLACK], x);
137 const int defense_index = index(kings[WHITE], x);
138 const int attack_index_x =
139 indexX<true>(king_piece[BLACK], x);
140 const int defense_index_x =
141 indexX<false>(king_piece[WHITE], x);
142 const int attack_index_y = indexY<BLACK>(king_piece[BLACK], x);
143 const int defense_index_y = indexY<WHITE>(king_piece[WHITE], x);
144 result -= value(attack_index, defense_index,
145 attack_index_y, defense_index_y,
146 attack_index_x, defense_index_x);
147 if (has_pawn[WHITE])
148 {
149 result -= standValue(attack_index, defense_index,
150 attack_index_y, defense_index_y,
151 attack_index_x, defense_index_x);
152 }
153 }
154 const int index_x = (x > 5 ? 10 - x : x);
155 if (black_on_board && white_on_board)
156 {
157 result +=
158 state_king_relative_table[std::abs(kings[BLACK].x() - x) +
159 BOTH_ON_BOARD * 9];
160 result -=
161 state_king_relative_table[std::abs(kings[WHITE].x() - x) +
162 BOTH_ON_BOARD * 9];
163 }
164 else if (black_on_board && !white_on_board)
165 {
166 result += drop_non_drop_table[index_x - 1];
167 result -= drop_non_drop_table[index_x - 1 + 5];
168 result +=
169 state_king_relative_table[std::abs(kings[BLACK].x() - x) +
170 SELF_ON_BOARD * 9];
171 result -=
172 state_king_relative_table[std::abs(kings[WHITE].x() - x) +
173 OPP_ON_BOARD * 9];
174 }
175 else if (!black_on_board && white_on_board)
176 {
177 result += drop_non_drop_table[index_x - 1 + 5];
178 result -= drop_non_drop_table[index_x - 1];
179 result +=
180 state_king_relative_table[std::abs(kings[BLACK].x() - x) +
181 OPP_ON_BOARD * 9];
182 result -=
183 state_king_relative_table[std::abs(kings[WHITE].x() - x) +
184 SELF_ON_BOARD * 9];
185 }
186 else
187 {
188 result +=
189 state_king_relative_table[std::abs(kings[BLACK].x() - x) +
190 BOTH_ON_STAND * 9];
191 result -=
192 state_king_relative_table[std::abs(kings[WHITE].x() - x) +
193 BOTH_ON_STAND * 9];
194 }
195 }
196 return result;
197 }
198
199
200
201 osl::MultiInt osl::eval::ml::NoPawnOnStand::weight;
202
203 void osl::eval::ml::
204 NoPawnOnStand::setUp(const Weights &weights,int stage)
205 {
206 weight[stage] = weights.value(0);
207 }
208
209
210
211 osl::misc::CArray<osl::MultiInt, 9> osl::eval::ml::PawnAdvance::table;
212
213 void osl::eval::ml::
214 PawnAdvance::setUp(const Weights &weights,int stage)
215 {
216 for (size_t i = 0; i < weights.dimension(); ++i) {
217 table[i][stage] = weights.value(i);
218 }
219 }
220
221 osl::MultiInt osl::eval::ml::PawnAdvance::eval(
222 const NumEffectState &state)
223 {
224 MultiInt result;
225 for (int i = PtypeTraits<PAWN>::indexMin;
226 i < PtypeTraits<PAWN>::indexLimit; ++i)
227 {
228 const Piece pawn = state.pieceOf(i);
229 if (pawn.isOnBoard() && !pawn.isPromoted() &&
230 cantAdvance(state, pawn))
231 {
232 if (pawn.owner() == BLACK)
233 result += table[index(BLACK, pawn.square())];
234 else
235 result -= table[index(WHITE, pawn.square())];
236 }
237 }
238 return result;
239 }
240
241 template <osl::Player P> inline
242 void osl::eval::ml::
243 PawnAdvanceAll::adjust(int index, MultiInt& values)
244 {
245 if(P==BLACK)
246 values += PawnAdvance::table[index];
247 else
248 values -= PawnAdvance::table[index];
249 }
250
251 template <osl::Player P>
252 void osl::eval::ml::
253 PawnAdvanceAll::evalWithUpdateBang(const osl::state::NumEffectState &state,
254 osl::Move moved, MultiInt& values)
255 {
256 assert(moved.player() == P);
257 if (moved.ptype() == PAWN)
258 {
259 if (cantAdvance(state, moved.ptypeO(), moved.to()))
260 {
261 adjust<P>(index(P, moved.to()), values);
262 return;
263 }
264 }
265 const Player Opponent = PlayerTraits<P>::opponent;
266 Ptype captured = moved.capturePtype();
267 if (captured == PAWN)
268 {
269 if (cantAdvance(state, moved.capturePtypeO(), moved.to()))
270 adjust<P>(index(Opponent, moved.to()), values);
271 }
272 else if (captured != PTYPE_EMPTY)
273 {
274 const Piece piece = state.pieceAt(
275 moved.to() + DirectionPlayerTraits<D, Opponent>::offset());
276 if (piece.isPlayerPtype(Opponent,PAWN))
277 adjust<P>(index(Opponent, piece.square()), values);
278 }
279 if (!moved.isDrop())
280 {
281 const Piece piece = state.pieceAt(
282 moved.from() + DirectionPlayerTraits<D, P>::offset());
283 if (piece.isPlayerPtype(P,PAWN))
284 adjust<Opponent>(index(P, piece.square()), values);
285 }
286 {
287 const Piece piece = state.pieceAt(
288 moved.to()+DirectionPlayerTraits<D,P>::offset());
289 if (piece.isPlayerPtype(P,PAWN))
290 adjust<P>(index(P, piece.square()), values);
291 }
292 }
293
294
295
296 osl::misc::CArray<osl::MultiInt, 153>
297 osl::eval::ml::SilverFeatures::head_table;
298 osl::misc::CArray<osl::MultiInt, 9>
299 osl::eval::ml::SilverFeatures::retreat_table;
300
301 void osl::eval::ml::
302 SilverHeadPawnKingRelative::setUp(const Weights &weights)
303 {
304 for (size_t i = 0; i < ONE_DIM; ++i)
305 {
306 for (int s=0; s<NStages; ++s)
307 head_table[i][s] = weights.value(i + ONE_DIM*s);
308 }
309 }
310
311 osl::MultiInt osl::eval::ml::
312 SilverFeatures::eval(const NumEffectState &state)
313 {
314 MultiInt result;
315 CArray<Square, 2> kings = {{state.kingSquare<BLACK>(),
316 state.kingSquare<WHITE>()}};
317 for (int i = PtypeTraits<SILVER>::indexMin;
318 i < PtypeTraits<SILVER>::indexLimit; ++i)
319 {
320 const Piece silver = state.pieceOf(i);
321 if (!silver.isOnBoard() || silver.isPromoted()) continue;
322 if (silver.owner()==BLACK){
323 result += evalOne<BLACK>(state, silver, kings);
324 }
325 else{
326 result -= evalOne<WHITE>(state, silver, kings);
327 }
328 }
329 return result;
330 }
331
332 template<osl::Player P>
333 inline
334 bool osl::eval::ml::
335 SilverFeatures::canRetreat(const osl::state::NumEffectState &state,
336 const osl::Piece silver)
337 {
338 assert(silver.isOnBoard() && !silver.isPromoted());
339 assert(silver.owner()==P);
340 if ((P == BLACK && silver.square().y() != 9) ||
341 (P == WHITE && silver.square().y() != 1))
342 {
343 Square dl = silver.square()+DirectionPlayerTraits<DL,P>::offset();
344 Piece pdl = state.pieceAt(dl);
345 if (!pdl.canMoveOn<P>() ||
346 state.hasEffectAt(alt(P), dl))
347 {
348 Square dr = silver.square()+DirectionPlayerTraits<DR,P>::offset();
349 Piece pdr = state.pieceAt(dr);
350 if (!pdr.canMoveOn<P>() ||
351 state.hasEffectAt(alt(P), dr))
352 {
353 return false;
354 }
355 }
356 }
357 return true;
358 }
359
360 void osl::eval::ml::
361 SilverRetreat::setUp(const Weights &weights, int stage)
362 {
363 for (size_t i = 0; i < weights.dimension(); ++i) {
364 retreat_table[i][stage] = weights.value(i);
365 }
366 }
367
368
369 osl::misc::CArray<osl::MultiInt, 153>
370 osl::eval::ml::GoldFeatures::knight_table;
371 osl::misc::CArray<osl::MultiInt, 9>
372 osl::eval::ml::GoldFeatures::retreat_table;
373 osl::misc::CArray<osl::MultiInt, 14>
374 osl::eval::ml::GoldFeatures::side_table;
375
376 void osl::eval::ml::
377 GoldKnightKingRelative::setUp(const Weights &weights)
378 {
379 for (size_t i = 0; i < ONE_DIM; ++i)
380 {
381 for (int s=0; s<NStages; ++s)
382 knight_table[i][s] = weights.value(i + ONE_DIM*s);
383 }
384 }
385
386 void osl::eval::ml::
387 GoldSideMove::setUp(const Weights &weights)
388 {
389 for (size_t i = 0; i < ONE_DIM; ++i)
390 {
391 for (int s=0; s<NStages; ++s)
392 side_table[i][s] = weights.value(i + ONE_DIM*s);
393 }
394 }
395
396 osl::MultiInt osl::eval::ml::
397 GoldFeatures::eval(const NumEffectState &state)
398 {
399 MultiInt result;
400 CArray<Square, 2> kings = {{state.kingSquare<BLACK>(),
401 state.kingSquare<WHITE>()}};
402 for (int i = PtypeTraits<GOLD>::indexMin;
403 i < PtypeTraits<GOLD>::indexLimit; ++i)
404 {
405 const Piece gold = state.pieceOf(i);
406 if (!gold.isOnBoard())
407 continue;
408 if (gold.owner() == BLACK)
409 {
410 result += evalOne<BLACK>(state, gold, kings);
411 }
412 else
413 {
414 result -= evalOne<WHITE>(state, gold, kings);
415 }
416 }
417 return result;
418 }
419
420 template<osl::Player P>
421 inline
422 bool osl::eval::ml::
423 GoldFeatures::canRetreat(const osl::state::NumEffectState &state,
424 const osl::Piece gold)
425 {
426 assert(gold.isOnBoard());
427 assert(P==gold.owner());
428
429 if ((P == BLACK && gold.square().y() != 9) ||
430 (P == WHITE && gold.square().y() != 1))
431 {
432 Square d = gold.square()+DirectionPlayerTraits<D,P>::offset();
433 if ((state.pieceAt(d).isOnBoardByOwner(P) ||
434 state.hasEffectAt(alt(P), d)))
435 {
436 return false;
437 }
438 }
439 return true;
440 }
441
442 void osl::eval::ml::
443 GoldRetreat::setUp(const Weights &weights,int stage)
444 {
445 for (size_t i = 0; i < weights.dimension(); ++i) {
446 retreat_table[i][stage] = weights.value(i);
447 }
448 }
449
450
451
452 osl::misc::CArray<MultiInt, 9> osl::eval::ml::KnightAdvance::table;
453
454 template<osl::Player P>
455 inline
456 bool osl::eval::ml::
457 KnightAdvance::cantAdvance(const osl::state::NumEffectState &state,
458 const osl::Piece knight)
459 {
460 // knight が敵陣一段目にいないと仮定
461 // もしいる場合はSquare(1,1)のUURが駒台に衝突
462 assert(P==knight.owner());
463 Square uul = knight.square()+DirectionPlayerTraits<UUL,P>::offset();
464 const Piece puul = state.pieceAt(uul);
465 if (!puul.canMoveOn<P>())
466 {
467 Square uur = knight.square()+DirectionPlayerTraits<UUR,P>::offset();
468 const Piece puur = state.pieceAt(uur);
469 if (!puur.canMoveOn<P>())
470 return true;
471 }
472 return false;
473 }
474
475 void osl::eval::ml::
476 KnightAdvance::setUp(const Weights &weights,int stage)
477 {
478 for (size_t i = 0; i < weights.dimension(); ++i) {
479 table[i][stage] = weights.value(i);
480 }
481 }
482
483 MultiInt osl::eval::ml::KnightAdvance::eval(
484 const NumEffectState &state)
485 {
486 MultiInt result;
487 for (int i = PtypeTraits<KNIGHT>::indexMin;
488 i < PtypeTraits<KNIGHT>::indexLimit; ++i)
489 {
490 const Piece knight = state.pieceOf(i);
491 if (!knight.isOnBoard() || knight.isPromoted()) continue;
492 if (knight.owner() == BLACK){
493 if(cantAdvance<BLACK>(state,knight))
494 result += table[index(BLACK, knight.square())];
495 }
496 else if(cantAdvance<WHITE>(state,knight)){
497 result -= table[index(WHITE, knight.square())];
498 }
499 }
500 return result;
501 }
502
503
504 MultiInt osl::eval::ml::AllGold::weight;
505
506 void osl::eval::ml::
507 AllGold::setUp(const Weights &weights,int stage)
508 {
509 weight[stage] = weights.value(0);
510 }
511
512
513
514 osl::misc::CArray<MultiInt, 144> osl::eval::ml::PtypeY::table;
515
516 void osl::eval::ml::
517 PtypeY::setUp(const Weights &weights,int stage)
518 {
519 for (size_t i = 0; i < weights.dimension(); ++i)
520 {
521 table[i][stage] = weights.value(i);
522 }
523 }
524
525 MultiInt osl::eval::ml::PtypeY::eval(const NumEffectState &state)
526 {
527 MultiInt result;
528 for (int i = 0; i < Piece::SIZE; ++i)
529 {
530 const Piece p = state.pieceOf(i);
531 if (!p.isOnBoard())
532 continue;
533 if (p.owner() == BLACK)
534 result += table[index(BLACK,p.ptype(),p.square())];
535 else
536 result -= table[index(WHITE,p.ptype(),p.square())];
537 }
538 return result;
539 }
540
541 template<osl::Player P>
542 MultiInt osl::eval::ml::
543 PtypeY::evalWithUpdate(const NumEffectState &, Move moved,
544 MultiInt const& last_value)
545 {
546 MultiInt result(last_value);
547
548 if (!moved.isDrop())
549 {
550 if (P == BLACK)
551 result -= table[index(BLACK, moved.oldPtype(), moved.from())];
552 else
553 result += table[index(WHITE, moved.oldPtype(), moved.from())];
554 }
555 Ptype captured = moved.capturePtype();
556 if (captured != PTYPE_EMPTY)
557 {
558 const MultiInt weight =
559 table[index(alt(P), captured, moved.to())];
560 if (P == BLACK)
561 result += weight;
562 else
563 result -= weight;
564 }
565 {
566 if (P == BLACK)
567 result += table[index(BLACK, moved.ptype(), moved.to())];
568 else
569 result -= table[index(WHITE, moved.ptype(), moved.to())];
570 }
571
572 return result;
573 }
574
575
576 osl::misc::CArray<MultiInt, 80> osl::eval::ml::PtypeX::table;
577
578 void osl::eval::ml::
579 PtypeX::setUp(const Weights &weights,int stage)
580 {
581 for (size_t i = 0; i < weights.dimension(); ++i)
582 {
583 table[i][stage] = weights.value(i);
584 }
585 }
586
587 MultiInt osl::eval::ml::PtypeX::eval(const NumEffectState &state)
588 {
589 MultiInt result;
590 for (int i = 0; i < Piece::SIZE; ++i)
591 {
592 const Piece p = state.pieceOf(i);
593 if (!p.isOnBoard())
594 continue;
595 if (p.owner() == BLACK)
596 result += table[index(BLACK,p.ptype(),p.square())];
597 else
598 result -= table[index(WHITE,p.ptype(),p.square())];
599 }
600 return result;
601 }
602
603 template<osl::Player P>
604 MultiInt osl::eval::ml::
605 PtypeX::evalWithUpdate(const NumEffectState &, Move moved,
606 MultiInt const& last_value)
607 {
608 MultiInt result(last_value);
609
610 if (!moved.isDrop())
611 {
612 if (P == BLACK)
613 result -= table[index(BLACK, moved.oldPtype(), moved.from())];
614 else
615 result += table[index(WHITE, moved.oldPtype(), moved.from())];
616 Ptype captured = moved.capturePtype();
617 if (captured != PTYPE_EMPTY)
618 {
619 if (P == BLACK)
620 result += table[index(WHITE, captured, moved.to())];
621 else
622 result -= table[index(BLACK, captured, moved.to())];
623 }
624 }
625 if (P == BLACK)
626 result += table[index(BLACK, moved.ptype(), moved.to())];
627 else
628 result -= table[index(WHITE, moved.ptype(), moved.to())];
629 return result;
630 }
631
632
633 MultiInt osl::eval::ml::KnightCheck::weight;
634 osl::misc::CArray<MultiInt, 9> osl::eval::ml::KnightCheck::y_table;
635
636 void osl::eval::ml::KnightCheck::setUp(const Weights &weights,int stage)
637 {
638 KnightCheck::weight[stage] = weights.value(0);
639 }
640
641 void osl::eval::ml::
642 KnightCheckY::setUp(const Weights &weights)
643 {
644 for (size_t i = 0; i < ONE_DIM; ++i)
645 {
646 for (int s=0; s<NStages; ++s)
647 KnightCheck::y_table[i][s] = weights.value(i + ONE_DIM*s);
648 }
649 }
650
651 MultiInt osl::eval::ml::
652 KnightCheck::eval(const NumEffectState &state)
653 {
654 MultiInt result;
655 if (canCheck<BLACK>(state))
656 {
657 const int index_y = indexY<BLACK>(state.kingSquare<BLACK>().y());
658 result += value(index_y);
659 }
660 if (canCheck<WHITE>(state))
661 {
662 const int index_y = indexY<WHITE>(state.kingSquare<WHITE>().y());
663 result -= value(index_y);
664 }
665 return result;
666 }
667
668 osl::misc::CArray<MultiInt, 1024> osl::eval::ml::PawnPtypeOPtypeO::table;
669 osl::misc::CArray<MultiInt, 9216> osl::eval::ml::PawnPtypeOPtypeO::y_table;
670
671 void osl::eval::ml::
672 PawnPtypeOPtypeO::setUp(const Weights &weights)
673 {
674 for (size_t i = 0; i < ONE_DIM; ++i)
675 {
676 for (int s=0; s<NStages; ++s)
677 table[i][s] = weights.value(i + ONE_DIM*s);
678 }
679 }
680
681 void osl::eval::ml::
682 PawnPtypeOPtypeOY::setUp(const Weights &weights)
683 {
684 for (size_t i = 0; i < ONE_DIM; ++i)
685 {
686 for (int s=0; s<NStages; ++s)
687 PawnPtypeOPtypeO::y_table[i][s] = weights.value(i + ONE_DIM*s);
688 }
689 }
690
691 MultiInt osl::eval::ml::
692 PawnPtypeOPtypeO::eval(const NumEffectState &state)
693 {
694 MultiInt result;
695 for (int i = PtypeTraits<PAWN>::indexMin;
696 i < PtypeTraits<PAWN>::indexLimit; ++i)
697 {
698 Piece pawn = state.pieceOf(i);
699 if (pawn.isOnBoard() && !pawn.isPromoted())
700 {
701 const Square up = Board_Table.nextSquare(pawn.owner(),
702 pawn.square(), U);
703 const Square up_up = Board_Table.nextSquare(pawn.owner(),
704 up, U);
705 PtypeO up_p =
706 (up.isOnBoard() ? state.pieceAt(up).ptypeO() : PTYPEO_EDGE);
707 PtypeO up_up_p =
708 (up_up.isOnBoard() ? state.pieceAt(up_up).ptypeO() : PTYPEO_EDGE);
709 const int idx = index(pawn.owner(), up_p, up_up_p);
710 const int idx_y = indexY(pawn.owner(), up_p, up_up_p,
711 pawn.square().y());
712 if (pawn.owner() == BLACK)
713 result += table[idx] + y_table[idx_y];
714 else
715 result -= table[idx] + y_table[idx_y];
716 }
717 }
718 return result;
719 }
720
721 template<osl::Player P>
722 MultiInt
723 #if (defined __GNUC__ && ! defined __clang__)
724 __attribute__((__flatten__))
725 #endif
726 osl::eval::ml::
727 PawnPtypeOPtypeO::evalWithUpdate(const NumEffectState &state, Move moved,
728 const CArray2d<int, 2, 9> &pawns,
729 const MultiInt &last_value)
730 {
731 assert(moved.player()==P);
732 MultiInt result(last_value);
733 if (!moved.isDrop())
734 {
735 if (moved.oldPtype() == PAWN)
736 {
737 const Square up_up = moved.to() + DirectionPlayerTraits<U,P>::offset();
738 const PtypeO up_up_p =
739 (up_up.isOnBoard() ? state.pieceAt(up_up).ptypeO() : PTYPEO_EDGE);
740 const int i = index(P, moved.capturePtypeOSafe(), up_up_p);
741 const int i_y = indexY(P, moved.capturePtypeOSafe(),
742 up_up_p, moved.from().y());
743 if (P == BLACK)
744 result -= table[i]+y_table[i_y];
745 else
746 result += table[i]+y_table[i_y];
747 }
748 if (pawns[BLACK][moved.from().x() - 1] != 0)
749 {
750 if (pawns[BLACK][moved.from().x() - 1] ==
751 moved.from().y() + 1)
752 {
753 const Square up_up = moved.from() + DirectionPlayerTraits<U,BLACK>::offset();
754 const PtypeO up_up_p =
755 (up_up.isOnBoard() ? (up_up == moved.to() ? moved.capturePtypeOSafe() :
756 state.pieceAt(up_up).ptypeO()) :
757 PTYPEO_EDGE);
758 const int i = index(BLACK, moved.oldPtypeO(), up_up_p);
759 const int i_y = indexY(BLACK, moved.oldPtypeO(), up_up_p,
760 moved.from().y() + 1);
761 result -= table[i]+y_table[i_y];
762 if (up_up != moved.to())
763 {
764 const int new_i = index(BLACK, PTYPEO_EMPTY, up_up_p);
765 const int new_i_y = indexY(BLACK, PTYPEO_EMPTY, up_up_p,
766 moved.from().y() + 1);
767 result += table[new_i]+y_table[new_i_y];
768 }
769 }
770 if (pawns[BLACK][moved.from().x() - 1] ==
771 moved.from().y() + 2)
772 {
773 const Square up = moved.from() + DirectionPlayerTraits<D,BLACK>::offset();
774 const PtypeO up_p =
775 (up.isOnBoard() ? (up == moved.to() ? moved.capturePtypeOSafe() :
776 state.pieceAt(up).ptypeO()) : PTYPEO_EDGE);
777 const int i = index(BLACK, up_p, moved.oldPtypeO());
778 const int i_y = indexY(BLACK, up_p, moved.oldPtypeO(),
779 moved.from().y() + 2);
780 result -= table[i]+y_table[i_y];
781 if (moved.to() != up)
782 {
783 const int new_i = index(BLACK, up_p, PTYPEO_EMPTY);
784 const int new_i_y = indexY(BLACK, up_p, PTYPEO_EMPTY,
785 moved.from().y() + 2);
786 result += table[new_i]+y_table[new_i_y];
787 }
788 }
789 }
790 if (pawns[WHITE][moved.from().x() - 1] != 0)
791 {
792 if (pawns[WHITE][moved.from().x() - 1] ==
793 moved.from().y() - 1)
794 {
795 const Square up_up = moved.from() + DirectionPlayerTraits<U,WHITE>::offset();
796 const PtypeO up_up_p =
797 (up_up.isOnBoard() ? (up_up == moved.to() ? moved.capturePtypeOSafe() :
798 state.pieceAt(up_up).ptypeO()) :
799 PTYPEO_EDGE);
800 const int i = index(WHITE, moved.oldPtypeO(), up_up_p);
801 const int i_y = indexY(WHITE, moved.oldPtypeO(), up_up_p,
802 moved.from().y() - 1);
803 result += table[i]+y_table[i_y];
804 if (moved.to() != up_up)
805 {
806 const int new_i = index(WHITE, PTYPEO_EMPTY, up_up_p);
807 const int new_i_y = indexY(WHITE, PTYPEO_EMPTY, up_up_p,
808 moved.from().y() - 1);
809 result -= table[new_i]+y_table[new_i_y];
810 }
811 }
812 if (pawns[WHITE][moved.from().x() - 1] ==
813 moved.from().y() - 2)
814 {
815 const Square up = moved.from() + DirectionPlayerTraits<D,WHITE>::offset();
816 const PtypeO up_p =
817 (up.isOnBoard() ? (up == moved.to() ? moved.capturePtypeOSafe() :
818 state.pieceAt(up).ptypeO()) : PTYPEO_EDGE);
819 const int i = index(WHITE, up_p, moved.oldPtypeO());
820 const int i_y = indexY(WHITE, up_p, moved.oldPtypeO(),
821 moved.from().y() - 2);
822 result += table[i]+y_table[i_y];
823 if (moved.to() != up)
824 {
825 const int new_i = index(WHITE, up_p, PTYPEO_EMPTY);
826 const int new_i_y = indexY(WHITE, up_p, PTYPEO_EMPTY,
827 moved.from().y() - 2);
828 result -= table[new_i]+y_table[new_i_y];
829 }
830 }
831 }
832 }
833 Ptype captured = moved.capturePtype();
834 if (captured == PAWN)
835 {
836 const Square up = moved.to() + DirectionPlayerTraits<D,P>::offset();
837 const Square up_up = up + DirectionPlayerTraits<D,P>::offset();
838 const PtypeO up_p =
839 (up.isOnBoard() ? (up == moved.from() ? moved.oldPtypeO() :
840 state.pieceAt(up).ptypeO()) : PTYPEO_EDGE);
841 const PtypeO up_up_p =
842 (up_up.isOnBoard() ? (up_up == moved.from() ? moved.oldPtypeO() :
843 state.pieceAt(up_up).ptypeO()) : PTYPEO_EDGE);
844 const int i = index(alt(P), up_p, up_up_p);
845 const int i_y = indexY(alt(P), up_p, up_up_p,
846 moved.to().y());
847 if (P == BLACK)
848 {
849 result += table[i]+y_table[i_y];
850 }
851 else
852 {
853 result -= table[i]+y_table[i_y];
854 }
855 }
856 if (moved.ptype() == PAWN)
857 {
858 const Square up = moved.to() + DirectionPlayerTraits<U,P>::offset();
859 const Square up_up = up + DirectionPlayerTraits<U,P>::offset();
860 const PtypeO up_p =
861 (up.isOnBoard() ? (up == moved.from() ? moved.oldPtypeO() :
862 state.pieceAt(up).ptypeO()) : PTYPEO_EDGE);
863 const PtypeO up_up_p =
864 (up_up.isOnBoard() ? (up_up == moved.from() ? moved.oldPtypeO() :
865 state.pieceAt(up_up).ptypeO()) : PTYPEO_EDGE);
866 const int i = index(P, up_p, up_up_p);
867 const int i_y = indexY(P, up_p, up_up_p, moved.to().y());
868 if (P == BLACK)
869 {
870 result += table[i]+y_table[i_y];
871 }
872 else
873 {
874 result -= table[i]+y_table[i_y];
875 }
876 }
877 if (pawns[BLACK][moved.to().x() - 1] != 0)
878 {
879 if (pawns[BLACK][moved.to().x() - 1] ==
880 moved.to().y() + 1)
881 {
882 const Square up_up = moved.to() + DirectionPlayerTraits<U,BLACK>::offset();
883 const PtypeO up_up_p =
884 (up_up.isOnBoard() ? state.pieceAt(up_up).ptypeO() :
885 PTYPEO_EDGE);
886 const int i = index(BLACK, moved.ptypeO(), up_up_p);
887 const int i_y = indexY(BLACK, moved.ptypeO(), up_up_p,
888 moved.to().y() + 1);
889 result += table[i]+y_table[i_y];
890 if (moved.isDrop() || moved.from() != up_up)
891 {
892 const int old_i = index(BLACK, moved.capturePtypeOSafe(), up_up_p);
893 const int old_i_y = indexY(BLACK, moved.capturePtypeOSafe(),
894 up_up_p, moved.to().y() + 1);
895 result -= table[old_i]+y_table[old_i_y];
896 }
897 }
898 if (pawns[BLACK][moved.to().x() - 1] ==
899 moved.to().y() + 2)
900 {
901 const Square up = moved.to() + DirectionPlayerTraits<D,BLACK>::offset();
902 const PtypeO up_p =
903 (up.isOnBoard() ? state.pieceAt(up).ptypeO() : PTYPEO_EDGE);
904 const int i = index(BLACK, up_p, moved.ptypeO());
905 const int i_y = indexY(BLACK, up_p, moved.ptypeO(), moved.to().y() + 2);
906 result += table[i]+y_table[i_y];
907 if (moved.isDrop() || up != moved.from())
908 {
909 const int old_i = index(BLACK, up_p, moved.capturePtypeOSafe());
910 const int old_i_y = indexY(BLACK, up_p, moved.capturePtypeOSafe(),
911 moved.to().y() + 2);
912 result -= table[old_i]+y_table[old_i_y];
913 }
914 }
915 }
916 if (pawns[WHITE][moved.to().x() - 1] != 0)
917 {
918 if (pawns[WHITE][moved.to().x() - 1] ==
919 moved.to().y() - 1)
920 {
921 const Square up_up = moved.to() + DirectionPlayerTraits<U,WHITE>::offset();
922 const PtypeO up_up_p =
923 (up_up.isOnBoard() ? state.pieceAt(up_up).ptypeO() :
924 PTYPEO_EDGE);
925 const int i = index(WHITE, moved.ptypeO(), up_up_p);
926 const int i_y = indexY(WHITE, moved.ptypeO(), up_up_p,
927 moved.to().y() - 1);
928 result -= table[i]+y_table[i_y];
929 if (up_up != moved.from())
930 {
931 const int old_i = index(WHITE, moved.capturePtypeOSafe(), up_up_p);
932 const int old_i_y = indexY(WHITE, moved.capturePtypeOSafe(), up_up_p,
933 moved.to().y() - 1);
934 result += table[old_i]+y_table[old_i_y];
935 }
936 }
937 if (pawns[WHITE][moved.to().x() - 1] ==
938 moved.to().y() - 2)
939 {
940 const Square up = moved.to() + DirectionPlayerTraits<D,WHITE>::offset();
941 const PtypeO up_p =
942 (up.isOnBoard() ? state.pieceAt(up).ptypeO() : PTYPEO_EDGE);
943 const int i = index(WHITE, up_p, moved.ptypeO());
944 const int i_y = indexY(WHITE, up_p, moved.ptypeO(), moved.to().y() - 2);
945 result -= table[i]+y_table[i_y];
946 if (moved.isDrop() || up != moved.from())
947 {
948 const int old_i = index(WHITE, up_p, moved.capturePtypeOSafe());
949 const int old_i_y = indexY(WHITE, up_p, moved.capturePtypeOSafe(),
950 moved.to().y() - 2);
951 result += table[old_i]+y_table[old_i_y];
952 }
953 }
954 }
955 return result;
956 }
957
958
959
960 osl::misc::CArray<MultiInt, 9> osl::eval::ml::PromotedMinorPieces::table;
961 osl::misc::CArray<MultiInt, 162> osl::eval::ml::PromotedMinorPieces::y_table;
962
963 void osl::eval::ml::
964 PromotedMinorPieces::setUp(const Weights &weights)
965 {
966 for (size_t i = 0; i < ONE_DIM; ++i)
967 {
968 for (int s=0; s<NStages; ++s)
969 table[i][s] = weights.value(i + ONE_DIM*s);
970 }
971 }
972
973 void osl::eval::ml::
974 PromotedMinorPiecesY::setUp(const Weights &weights)
975 {
976 for (size_t i = 0; i < ONE_DIM; ++i)
977 {
978 for (int s=0; s<NStages; ++s)
979 PromotedMinorPieces::y_table[i][s] = weights.value(i + ONE_DIM*s);
980 }
981 }
982
983 template <int Sign>
984 inline void osl::eval::ml::
985 PromotedMinorPieces::adjust(int index, int index_attack, int index_defense,
986 MultiInt &result)
987 {
988 if(Sign>0)
989 result+= table[index] + y_table[index_attack] + y_table[index_defense];
990 else
991 result-= table[index] + y_table[index_attack] + y_table[index_defense];
992 }
993 template <osl::Player P>
994 void osl::eval::ml::
995 PromotedMinorPieces::evalOne(const NumEffectState &state,
996 const PieceMask promoted,
997 MultiInt &result)
998 {
999 PieceMask attack = promoted & state.piecesOnBoard(P);
1000 const Square king = state.kingSquare<PlayerTraits<P>::opponent>();
1001 const Square self_king = state.kingSquare<P>();
1002 int min_left = -10;
1003 int min_right = 10;
1004 while (attack.any())
1005 {
1006 const Piece p = state.pieceOf(attack.takeOneBit());
1007 const int x_diff = (P == BLACK ? p.square().x() - king.x() :
1008 king.x() - p.square().x());
1009 if (x_diff <= 0)
1010 {
1011 if (x_diff > min_left)
1012 {
1013 if (min_left != -10)
1014 {
1015 if (P == BLACK)
1016 adjust<1>(-min_left, indexY<true, P>(king, -min_left),
1017 indexY<false, P>(self_king, -min_left), result);
1018 else
1019 adjust<-1>(-min_left, indexY<true, P>(king, -min_left),
1020 indexY<false, P>(self_king, -min_left), result);
1021 }
1022 min_left = x_diff;
1023 }
1024 else
1025 {
1026 if (P == BLACK)
1027 adjust<1>(-x_diff, indexY<true, P>(king, -x_diff),
1028 indexY<false, P>(self_king, -x_diff),
1029 result);
1030 else
1031 adjust<-1>(-x_diff, indexY<true, P>(king, -x_diff),
1032 indexY<false, P>(self_king, -x_diff),
1033 result);
1034 }
1035 }
1036 if (x_diff >= 0)
1037 {
1038 if (x_diff < min_right)
1039 {
1040 if (min_right != 10)
1041 {
1042 if (P == BLACK)
1043 adjust<1>(min_right, indexY<true, P>(king, min_right),
1044 indexY<false, P>(self_king, min_right),
1045 result);
1046 else
1047 adjust<-1>(min_right, indexY<true, P>(king, min_right),
1048 indexY<false, P>(self_king, min_right),
1049 result);
1050 }
1051 min_right = x_diff;
1052 }
1053 else if (x_diff != 0)
1054 {
1055 if (P == BLACK)
1056 adjust<1>(x_diff, indexY<true, P>(king, x_diff),
1057 indexY<false, P>(self_king, x_diff),
1058 result);
1059 else
1060 adjust<-1>(x_diff, indexY<true, P>(king, x_diff),
1061 indexY<false, P>(self_king, x_diff),
1062 result);
1063 }
1064 }
1065 }
1066 }
1067
1068 MultiInt osl::eval::ml::
1069 PromotedMinorPieces::eval(const NumEffectState &state)
1070 {
1071 MultiInt result;
1072 PieceMask promoted_pieces = state.promotedPieces();
1073 promoted_pieces.clearBit<ROOK>();
1074 promoted_pieces.clearBit<BISHOP>();
1075 if (promoted_pieces.none())
1076 return result;
1077
1078 evalOne<BLACK>(state, promoted_pieces, result);
1079 evalOne<WHITE>(state, promoted_pieces, result);
1080 return result;
1081 }
1082
1083 MultiInt osl::eval::ml::
1084 PromotedMinorPieces::evalWithUpdate(const NumEffectState &state,
1085 Move moved,
1086 const MultiInt &last_values)
1087 {
1088 Ptype captured = moved.capturePtype();
1089 if (moved.ptype() == KING ||
1090 (isPromoted(moved.ptype()) && !isMajor(moved.ptype())) ||
1091 (captured != PTYPE_EMPTY && isPromoted(captured) &&
1092 !isMajor(captured)))
1093 return eval(state);
1094
1095 return last_values;
1096 }
1097
1098
1099 osl::misc::CArray<MultiInt, 64> osl::eval::ml::NonPawnAttacked::table;
1100 osl::misc::CArray<MultiInt, 19584> osl::eval::ml::NonPawnAttacked::king_table;
1101
1102 void osl::eval::ml::NonPawnAttacked::setUp(const Weights &weights)
1103 {
1104 for (size_t i = 0; i < ONE_DIM; ++i)
1105 {
1106 for (int s=0; s<NStages; ++s)
1107 table[i][s] = weights.value(i + ONE_DIM*s);
1108 }
1109 }
1110
1111 void osl::eval::ml::NonPawnAttackedKingRelative::setUp(
1112 const Weights &weights)
1113 {
1114 for (size_t i = 0; i < ONE_DIM; ++i)
1115 {
1116 for (int s=0; s<NStages; ++s)
1117 NonPawnAttacked::king_table[i][s] = weights.value(i + ONE_DIM*s);
1118 }
1119 for(int x_diff=0;x_diff<9;x_diff++)
1120 for(int y_diff= -8;y_diff<=8;y_diff++)
1121 for(int has_support=0;has_support<2;has_support++)
1122 for(int same_turn=0;same_turn<2;same_turn++)
1123 for(int ptype=0;ptype<PTYPE_SIZE;ptype++){
1124 int index=((ptype + (same_turn ? 0 : PTYPE_SIZE) +
1125 (has_support ? 0 : PTYPE_SIZE*2))* 9 + x_diff) * 17 +
1126 y_diff + 8;
1127 int index0=ptype + (same_turn ? 0 : PTYPE_SIZE) +
1128 (has_support ? 0 : PTYPE_SIZE * 2);
1129 NonPawnAttacked::king_table[index] += NonPawnAttacked::table[index0];
1130 }
1131 }
1132
1133 template <int Sign>
1134 void osl::eval::ml::
1135 NonPawnAttacked::adjust(int black_turn_king_attack,
1136 int black_turn_king_defense,
1137 int white_turn_king_attack,
1138 int white_turn_king_defense,
1139 MultiIntPair &result)
1140 {
1141 if(Sign>0){
1142 result[BLACK] += king_table[black_turn_king_attack] +
1143 king_table[black_turn_king_defense];
1144 result[WHITE] += king_table[white_turn_king_attack] +
1145 king_table[white_turn_king_defense];
1146 }
1147 else{
1148 result[BLACK] -= king_table[black_turn_king_attack] +
1149 king_table[black_turn_king_defense];
1150 result[WHITE] -= king_table[white_turn_king_attack] +
1151 king_table[white_turn_king_defense];
1152 }
1153 }
1154
1155 void osl::eval::ml::
1156 NonPawnAttacked::eval(const NumEffectState &state, MultiIntPair& result)
1157 {
1158 result = MultiIntPair();
1159 CArray<Square, 2> kings = {{state.kingSquare<BLACK>(),
1160 state.kingSquare<WHITE>()}};
1161 PieceMask black_attacked = state.effectedMask(WHITE) & state.piecesOnBoard(BLACK);
1162 black_attacked.reset(KingTraits<BLACK>::index);
1163 mask_t black_ppawn = state.promotedPieces().getMask<PAWN>() & black_attacked.selectBit<PAWN>();
1164 black_attacked.clearBit<PAWN>();
1165 black_attacked.orMask(PtypeFuns<PAWN>::indexNum, black_ppawn);
1166 PieceMask black_with_support = state.effectedMask(BLACK) & black_attacked;
1167 PieceMask black_without_support = (~state.effectedMask(BLACK)) & black_attacked;
1168 while (black_with_support.any())
1169 {
1170 const Piece piece = state.pieceOf(black_with_support.takeOneBit());
1171 const int index_king_black_turn_attack =
1172 indexK<true>(kings[WHITE], true, true, piece);
1173 const int index_king_white_turn_attack =
1174 indexK<true>(kings[WHITE], false, true, piece);
1175 const int index_king_black_turn_defense =
1176 indexK<false>(kings[BLACK], true, true, piece);
1177 const int index_king_white_turn_defense =
1178 indexK<false>(kings[BLACK], false, true, piece);
1179 adjust<1>(index_king_black_turn_attack, index_king_black_turn_defense,
1180 index_king_white_turn_attack, index_king_white_turn_defense,
1181 result);
1182 }
1183 while (black_without_support.any())
1184 {
1185 const Piece piece = state.pieceOf(black_without_support.takeOneBit());
1186 const int index_king_black_turn_attack =
1187 indexK<true>(kings[WHITE], true, false, piece);
1188 const int index_king_white_turn_attack =
1189 indexK<true>(kings[WHITE], false, false, piece);
1190 const int index_king_black_turn_defense =
1191 indexK<false>(kings[BLACK], true, false, piece);
1192 const int index_king_white_turn_defense =
1193 indexK<false>(kings[BLACK], false, false, piece);
1194 adjust<1>(index_king_black_turn_attack, index_king_black_turn_defense,
1195 index_king_white_turn_attack, index_king_white_turn_defense,
1196 result);
1197 }
1198
1199 PieceMask white_attacked = state.effectedMask(BLACK) & state.piecesOnBoard(WHITE);
1200 white_attacked.reset(KingTraits<WHITE>::index);
1201 mask_t white_ppawn = state.promotedPieces().getMask<PAWN>() & white_attacked.selectBit<PAWN>();
1202 white_attacked.clearBit<PAWN>();
1203 white_attacked.orMask(PtypeFuns<PAWN>::indexNum, white_ppawn);
1204 PieceMask white_with_support = state.effectedMask(WHITE) & white_attacked;
1205 PieceMask white_without_support = (~state.effectedMask(WHITE)) & white_attacked;
1206 while (white_with_support.any())
1207 {
1208 const Piece piece = state.pieceOf(white_with_support.takeOneBit());
1209 const int index_king_black_turn_attack =
1210 indexK<true>(kings[BLACK], false, true, piece);
1211 const int index_king_white_turn_attack =
1212 indexK<true>(kings[BLACK], true, true, piece);
1213 const int index_king_black_turn_defense =
1214 indexK<false>(kings[WHITE], false, true, piece);
1215 const int index_king_white_turn_defense =
1216 indexK<false>(kings[WHITE], true, true, piece);
1217 adjust<-1>(index_king_black_turn_attack, index_king_black_turn_defense,
1218 index_king_white_turn_attack, index_king_white_turn_defense,
1219 result);
1220 }
1221 while (white_without_support.any())
1222 {
1223 const Piece piece = state.pieceOf(white_without_support.takeOneBit());
1224 const int index_king_black_turn_attack =
1225 indexK<true>(kings[BLACK], false, false, piece);
1226 const int index_king_white_turn_attack =
1227 indexK<true>(kings[BLACK], true, false, piece);
1228 const int index_king_black_turn_defense =
1229 indexK<false>(kings[WHITE], false, false, piece);
1230 const int index_king_white_turn_defense =
1231 indexK<false>(kings[WHITE], true, false, piece);
1232 adjust<-1>(index_king_black_turn_attack, index_king_black_turn_defense,
1233 index_king_white_turn_attack, index_king_white_turn_defense,
1234 result);
1235 }
1236 }
1237
1238 template<osl::Player P>
1239 void osl::eval::ml::
1240 NonPawnAttacked::evalWithUpdateBang(
1241 const NumEffectState &state,
1242 Move moved,
1243 const CArray<PieceMask, 2> &effected,
1244 MultiIntPair &result)
1245 {
1246 if (moved.ptype() == KING)
1247 {
1248 eval(state, result);
1249 return;
1250 }
1251
1252 CArray<PieceMask, 2> effected_mask = effected;
1253 effected_mask[0].clearBit<KING>();
1254 effected_mask[1].clearBit<KING>();
1255 CArray<PieceMask, 2> new_mask = {{
1256 state.effectedMask(BLACK),
1257 state.effectedMask(WHITE)
1258 }};
1259
1260 mask_t black_ppawn =
1261 new_mask[0].selectBit<PAWN>() & state.promotedPieces().template getMask<PAWN>();
1262 mask_t white_ppawn =
1263 new_mask[1].template selectBit<PAWN>() & state.promotedPieces().template getMask<PAWN>();
1264 new_mask[0].clearBit<PAWN>();
1265 new_mask[1].clearBit<PAWN>();
1266 new_mask[0].orMask(PtypeFuns<PAWN>::indexNum, black_ppawn);
1267 new_mask[1].orMask(PtypeFuns<PAWN>::indexNum, white_ppawn);
1268 new_mask[0].clearBit<KING>();
1269 new_mask[1].clearBit<KING>();
1270 CArray<Square, 2> kings = {{ state.kingSquare<BLACK>(),
1271 state.kingSquare<WHITE>() }};
1272 const Piece p = state.pieceAt(moved.to());
1273 assert(p.owner()==P);
1274 if (!moved.isDrop())
1275 {
1276 if (effected_mask[alt(P)].test(p.number()))
1277 {
1278 const bool has_support = effected_mask[P].test(p.number());
1279 const int index_king_black_turn_attack =
1280 indexK<true>(kings[alt(P)], BLACK == P,
1281 has_support, moved.from(), P, moved.oldPtype());
1282 const int index_king_white_turn_attack =
1283 indexK<true>(kings[alt(P)], WHITE == P,
1284 has_support, moved.from(), P, moved.oldPtype());
1285 const int index_king_black_turn_defense =
1286 indexK<false>(kings[P], BLACK == P,
1287 has_support, moved.from(), P, moved.oldPtype());
1288 const int index_king_white_turn_defense =
1289 indexK<false>(kings[P], WHITE == P,
1290 has_support, moved.from(), P, moved.oldPtype());
1291 if (P == BLACK)
1292 adjust<-1>(index_king_black_turn_attack, index_king_black_turn_defense,
1293 index_king_white_turn_attack, index_king_white_turn_defense,
1294 result);
1295 else
1296 adjust<1>(index_king_black_turn_attack, index_king_black_turn_defense,
1297 index_king_white_turn_attack, index_king_white_turn_defense,
1298 result);
1299 }
1300 }
1301 if (new_mask[alt(P)].test(p.number()))
1302 {
1303 const bool has_support = new_mask[P].test(p.number());
1304 const int index_king_black_turn_attack =
1305 indexK<true>(kings[alt(P)], BLACK == P,
1306 has_support, p);
1307 const int index_king_white_turn_attack =
1308 indexK<true>(kings[alt(P)], WHITE == P,
1309 has_support, p);
1310 const int index_king_black_turn_defense =
1311 indexK<false>(kings[P], BLACK == P,
1312 has_support, p);
1313 const int index_king_white_turn_defense =
1314 indexK<false>(kings[P], WHITE == P,
1315 has_support, p);
1316 if (P == BLACK)
1317 adjust<1>(index_king_black_turn_attack, index_king_black_turn_defense,
1318 index_king_white_turn_attack, index_king_white_turn_defense,
1319 result);
1320 else
1321 adjust<-1>(index_king_black_turn_attack, index_king_black_turn_defense,
1322 index_king_white_turn_attack, index_king_white_turn_defense,
1323 result);
1324 }
1325 const Ptype captured = moved.capturePtype();
1326 if (captured != PTYPE_EMPTY && captured != PAWN)
1327 {
1328 PieceMask captured_mask =
1329 effected_mask[P] & (~state.piecesOnBoard(BLACK)) &
1330 (~state.piecesOnBoard(WHITE));
1331
1332 const bool has_support = effected_mask[alt(P)].test(captured_mask.takeOneBit());
1333 const int index_king_black_turn_attack =
1334 indexK<true>(kings[P], WHITE == P,
1335 has_support, moved.to(), alt(P), captured);
1336 const int index_king_white_turn_attack =
1337 indexK<true>(kings[P], BLACK == P,
1338 has_support, moved.to(), alt(P), captured);
1339 const int index_king_black_turn_defense =
1340 indexK<false>(kings[alt(P)], WHITE == P,
1341 has_support, moved.to(), alt(P), captured);
1342 const int index_king_white_turn_defense =
1343 indexK<false>(kings[alt(P)], BLACK == P,
1344 has_support, moved.to(), alt(P), captured);
1345 if (P == BLACK)
1346 adjust<1>(index_king_black_turn_attack, index_king_black_turn_defense,
1347 index_king_white_turn_attack, index_king_white_turn_defense,
1348 result);
1349 else
1350 adjust<-1>(index_king_black_turn_attack, index_king_black_turn_defense,
1351 index_king_white_turn_attack, index_king_white_turn_defense,
1352 result);
1353 }
1354
1355 updateEffectChanged<BLACK>(state, effected_mask, new_mask, p.number(),
1356 result);
1357 updateEffectChanged<WHITE>(state, effected_mask, new_mask, p.number(),
1358 result);
1359 }
1360
1361
1362 osl::misc::CArray<MultiInt, 9> osl::eval::ml::KnightHead::table;
1363 osl::misc::CArray<MultiInt, 144> osl::eval::ml::KnightHead::opp_table;
1364
1365 void osl::eval::ml::
1366 KnightHead::setUp(const Weights &weights)
1367 {
1368 for (size_t i = 0; i < ONE_DIM; ++i)
1369 {
1370 for (int s=0; s<NStages; ++s)
1371 table[i][s] = weights.value(i + ONE_DIM*s);
1372 }
1373 }
1374
1375 void osl::eval::ml::
1376 KnightHeadOppPiecePawnOnStand::setUp(const Weights &weights)
1377 {
1378 for (size_t i = 0; i < ONE_DIM; ++i)
1379 {
1380 for (int s=0; s<NStages; ++s)
1381 KnightHead::opp_table[i][s] = weights.value(i + ONE_DIM*s);
1382 }
1383 }
1384
1385 MultiInt osl::eval::ml::
1386 KnightHead::eval(const NumEffectState &state)
1387 {
1388 MultiInt result;
1389 for (int i = PtypeTraits<KNIGHT>::indexMin;
1390 i < PtypeTraits<KNIGHT>::indexLimit;
1391 ++i)
1392 {
1393 const Piece knight = state.pieceOf(i);
1394 if (knight.isOnBoard() && !knight.isPromoted())
1395 {
1396 const Square up = Board_Table.nextSquare(knight.owner(),
1397 knight.square(), U);
1398 const Piece up_piece = state.pieceAt(up);
1399 if ((up_piece.isEmpty() && state.hasPieceOnStand<PAWN>(alt(knight.owner())) &&
1400 !state.isPawnMaskSet(alt(knight.owner()), knight.square().x()) &&
1401 state.countEffect(knight.owner(), up) <=
1402 state.countEffect(alt(knight.owner()), up)) ||
1403 (state.hasEffectByPtypeStrict<PAWN>(alt(knight.owner()), up) &&
1404 (up_piece.isEmpty() || up_piece.owner() == knight.owner()) &&
1405 state.countEffect(knight.owner(), up) <
1406 state.countEffect(alt(knight.owner()), up)))
1407 {
1408 const int y = knight.square().y();
1409 if (knight.owner() == BLACK)
1410 {
1411 result += table[y - 1];
1412 }
1413 else
1414 {
1415 result -= table[9 - y];
1416 }
1417 }
1418 else if (up_piece.isPiece() && up_piece.owner() != knight.owner() &&
1419 state.hasPieceOnStand<PAWN>(up_piece.owner()))
1420 {
1421 const int y = (knight.owner() == BLACK ? knight.square().y() :
1422 10 - knight.square().y());
1423 const int index = up_piece.ptype() * 9 + y - 1;
1424 if (knight.owner() == BLACK)
1425 {
1426 result += opp_table[index];
1427 }
1428 else
1429 {
1430 result -= opp_table[index];
1431 }
1432 }
1433 }
1434 }
1435 return result;
1436 }
1437
1438
1439 osl::misc::CArray<MultiInt, 1024> osl::eval::ml::NonPawnAttackedPtype::table;
1440
1441 void osl::eval::ml::
1442 NonPawnAttackedPtype::setUp(const Weights &weights)
1443 {
1444 for (size_t i = 0; i < ONE_DIM; ++i)
1445 {
1446 for (int s=0; s<NStages; ++s)
1447 table[i][s] = weights.value(i + ONE_DIM*s);
1448 }
1449 }
1450
1451 void osl::eval::ml::
1452 NonPawnAttackedPtype::eval(const NumEffectState &state,
1453 CArray<PieceMask, 40> &attacked_mask,
1454 MultiIntPair &result)
1455 {
1456 result = MultiIntPair();
1457 PieceMask black_attacked = state.effectedMask(WHITE) & state.piecesOnBoard(BLACK);
1458 black_attacked.reset(KingTraits<BLACK>::index);
1459 mask_t black_ppawn = state.promotedPieces().getMask<PAWN>() & black_attacked.selectBit<PAWN>();
1460 black_attacked.clearBit<PAWN>();
1461 black_attacked.orMask(PtypeFuns<PAWN>::indexNum, black_ppawn);
1462 while (black_attacked.any())
1463 {
1464 const Piece piece = state.pieceOf(black_attacked.takeOneBit());
1465 const bool with_support = state.effectedMask(BLACK).test(piece.number());
1466 PieceMask attacking =
1467 state.effectSetAt(piece.square()) & state.piecesOnBoard(WHITE);
1468 attacked_mask[piece.number()] = attacking;
1469
1470 while (attacking.any())
1471 {
1472 const Piece attack = state.pieceOf(attacking.takeOneBit());
1473 const int index_black_turn = index(true, with_support,
1474 piece.ptype(), attack.ptype());
1475 const int index_white_turn = index(false, with_support,
1476 piece.ptype(), attack.ptype());
1477 adjust<1>(index_black_turn, index_white_turn, result);
1478 }
1479 }
1480 PieceMask white_attacked = state.effectedMask(BLACK) & state.piecesOnBoard(WHITE);
1481 white_attacked.reset(KingTraits<WHITE>::index);
1482 mask_t white_ppawn = state.promotedPieces().getMask<PAWN>() & white_attacked.selectBit<PAWN>();
1483 white_attacked.clearBit<PAWN>();
1484 white_attacked.orMask(PtypeFuns<PAWN>::indexNum, white_ppawn);
1485 while (white_attacked.any())
1486 {
1487 const Piece piece = state.pieceOf(white_attacked.takeOneBit());
1488 const bool with_support = state.effectedMask(WHITE).test(piece.number());
1489 PieceMask attacking =
1490 state.effectSetAt(piece.square()) & state.piecesOnBoard(BLACK);
1491 attacked_mask[piece.number()] = attacking;
1492 while (attacking.any())
1493 {
1494 const Piece attack = state.pieceOf(attacking.takeOneBit());
1495 const int index_black_turn = index(false, with_support,
1496 piece.ptype(), attack.ptype());
1497 const int index_white_turn = index(true, with_support,
1498 piece.ptype(), attack.ptype());
1499 adjust<-1>(index_black_turn, index_white_turn, result);
1500 }
1501 }
1502 }
1503
1504 template<osl::Player P>
1505 void osl::eval::ml::
1506 NonPawnAttackedPtype::evalWithUpdateBang(
1507 const NumEffectState &state,
1508 Move moved,
1509 const CArray<PieceMask, 2> &effected,
1510 CArray<PieceMask, 40> &attacked_mask,
1511 MultiIntPair &result)
1512 {
1513 CArray<PieceMask, 2> effected_mask = effected;
1514 effected_mask[0].clearBit<KING>();
1515 effected_mask[1].clearBit<KING>();
1516 CArray<PieceMask, 2> new_mask = {{
1517 state.effectedMask(BLACK),
1518 state.effectedMask(WHITE)
1519 }};
1520 mask_t black_ppawn =
1521 new_mask[0].selectBit<PAWN>() & state.promotedPieces().template getMask<PAWN>();
1522 mask_t white_ppawn =
1523 new_mask[1].selectBit<PAWN>() & state.promotedPieces().template getMask<PAWN>();
1524 new_mask[0].clearBit<PAWN>();
1525 new_mask[1].clearBit<PAWN>();
1526 new_mask[0].orMask(PtypeFuns<PAWN>::indexNum, black_ppawn);
1527 new_mask[1].orMask(PtypeFuns<PAWN>::indexNum, white_ppawn);
1528 new_mask[0].clearBit<KING>();
1529 new_mask[1].clearBit<KING>();
1530 const Piece p = state.pieceAt(moved.to());
1531 assert(p.owner()==P);
1532 assert(moved.player()==P);
1533 const Ptype captured = moved.capturePtype();
1534 int captured_number = -1;
1535 if (captured != PTYPE_EMPTY && captured != PAWN)
1536 {
1537 PieceMask captured_mask =
1538 effected_mask[P] & (~state.piecesOnBoard(BLACK)) &
1539 (~state.piecesOnBoard(WHITE));
1540 captured_number = captured_mask.takeOneBit();
1541 }
1542 if (!moved.isDrop() && moved.oldPtype() != PAWN)
1543 {
1544 if (effected_mask[alt(P)].test(p.number()))
1545 {
1546 const bool has_support = effected_mask[P].test(p.number());
1547 PieceMask attacking = attacked_mask[p.number()];
1548 if (captured_number != -1)
1549 {
1550 if (attacking.test(captured_number))
1551 {
1552 if (P == BLACK)
1553 {
1554 evalOnePiece<false>(P, moved.oldPtype(), captured,
1555 has_support, result);
1556 }
1557 else
1558 {
1559 evalOnePiece<true>(P, moved.oldPtype(), captured,
1560 has_support, result);
1561 }
1562 attacking.reset(captured_number);
1563 }
1564 }
1565 while (attacking.any())
1566 {
1567 const Piece attack = state.pieceOf(attacking.takeOneBit());
1568 if (P == BLACK)
1569 {
1570 evalOnePiece<false>(P, moved.oldPtype(), attack.ptype(),
1571 has_support, result);
1572 }
1573 else
1574 {
1575 evalOnePiece<true>(P, moved.oldPtype(), attack.ptype(),
1576 has_support, result);
1577 }
1578 }
1579 }
1580 }
1581 if (new_mask[alt(P)].test(p.number()))
1582 {
1583 const bool has_support = new_mask[P].test(p.number());
1584 PieceMask attacking =
1585 state.effectSetAt(moved.to()) & state.piecesOnBoard(alt(P));
1586 attacked_mask[p.number()] = attacking;
1587 while (attacking.any())
1588 {
1589 const Piece attack = state.pieceOf(attacking.takeOneBit());
1590 if (P == BLACK)
1591 {
1592 evalOnePiece<true>(P, p.ptype(), attack.ptype(),
1593 has_support, result);
1594 }
1595 else
1596 {
1597 evalOnePiece<false>(P, p.ptype(), attack.ptype(),
1598 has_support, result);
1599 }
1600 }
1601 }
1602 if (captured_number != -1)
1603 {
1604 const bool has_support = effected_mask[alt(P)].test(captured_number);
1605 PieceMask attacking = attacked_mask[captured_number];
1606 if (attacking.test(p.number()))
1607 {
1608 if (P == BLACK)
1609 {
1610 evalOnePiece<true>(alt(P), captured, moved.oldPtype(),
1611 has_support, result);
1612 }
1613 else
1614 {
1615 evalOnePiece<false>(alt(P), captured, moved.oldPtype(),
1616 has_support, result);
1617 }
1618 attacking.reset(p.number());
1619 }
1620 while (attacking.any())
1621 {
1622 const Piece attack = state.pieceOf(attacking.takeOneBit());
1623 if (P == BLACK)
1624 {
1625 evalOnePiece<true>(alt(P), captured, attack.ptype(),
1626 has_support, result);
1627 }
1628 else
1629 {
1630 evalOnePiece<false>(alt(P), captured, attack.ptype(),
1631 has_support, result);
1632 }
1633 }
1634 }
1635 updateChanged<BLACK>(state, p, moved, captured_number,
1636 effected_mask, new_mask, attacked_mask, result);
1637 updateChanged<WHITE>(state, p, moved, captured_number,
1638 effected_mask, new_mask, attacked_mask, result);
1639 }
1640
1641 osl::CArray<osl::MultiInt, 512*512>
1642 osl::eval::ml::NonPawnAttackedPtypePair::table;
1643 void osl::eval::ml::NonPawnAttackedPtypePair::setUp(const Weights &weights)
1644 {
1645 for (int i = 0; i < ONE_DIM; ++i)
1646 {
1647 for (int s=0; s<NStages; ++s)
1648 table[i][s] = weights.value(i + ONE_DIM*s);
1649 }
1650 for (int i=0; i<PTYPE_SIZE*2*PTYPE_SIZE; ++i)
1651 for (int j=i+1; j<PTYPE_SIZE*2*PTYPE_SIZE; ++j) {
1652 table[index2(j,i)] = table[index2(i,j)];
1653 }
1654 }
1655 template <osl::Player Owner>
1656 osl::MultiInt osl::eval::ml::NonPawnAttackedPtypePair::
1657 evalOne(const NumEffectState &state)
1658 {
1659 MultiInt result;
1660 PieceMask attacked = state.effectedMask(alt(Owner)) & state.piecesOnBoard(Owner);
1661 attacked.reset(state.kingPiece<Owner>().number());
1662 mask_t ppawn = state.promotedPieces().getMask<PAWN>() & attacked.selectBit<PAWN>();
1663 attacked.clearBit<PAWN>();
1664 attacked.orMask(PtypeFuns<PAWN>::indexNum, ppawn);
1665 PieceVector pieces;
1666 while (attacked.any())
1667 {
1668 const Piece piece = state.pieceOf(attacked.takeOneBit());
1669 pieces.push_back(piece);
1670 }
1671 for (size_t i=0; i+1<pieces.size(); ++i) {
1672 const int i0 = index1(state, pieces[i]);
1673 for (size_t j=i+1; j<pieces.size(); ++j) {
1674 const int i1 = index1(state, pieces[j]);
1675 if (Owner == BLACK)
1676 result += table[index2(i0, i1)];
1677 else
1678 result -= table[index2(i0, i1)];
1679 }
1680 }
1681 return result;
1682 }
1683
1684 osl::MultiInt osl::eval::ml::NonPawnAttackedPtypePair::
1685 eval(const NumEffectState &state)
1686 {
1687 return evalOne<BLACK>(state) + evalOne<WHITE>(state);
1688 }
1689
1690
1691 osl::misc::CArray<MultiInt, 160>
1692 osl::eval::ml::PtypeCount::table;
1693 osl::misc::CArray<MultiInt, 2240>
1694 osl::eval::ml::PtypeCount::xy_table;
1695 osl::misc::CArray<MultiInt, 2240>
1696 osl::eval::ml::PtypeCount::xy_attack_table;
1697 osl::misc::CArray<MultiInt, 2240>
1698 osl::eval::ml::PtypeCount::xy_table_diff;
1699 osl::misc::CArray<MultiInt, 2240>
1700 osl::eval::ml::PtypeCount::xy_attack_table_diff;
1701 void osl::eval::ml::PtypeCount::setUp(const Weights &weights)
1702 {
1703 for (size_t i = 0; i < ONE_DIM; ++i)
1704 {
1705 for (int s=0; s<NStages; ++s)
1706 table[i][s] = weights.value(i + ONE_DIM*s);
1707 }
1708 }
1709
1710 void osl::eval::ml::PtypeCountXY::setUp(const Weights &weights)
1711 {
1712 for (size_t i = 0; i < ONE_DIM; ++i)
1713 {
1714 for (int s=0; s<NStages; ++s)
1715 PtypeCount::xy_table[i][s] = weights.value(i + ONE_DIM*s);
1716 }
1717 for(int i=PTYPE_BASIC_MIN;i<=PTYPE_MAX;i++){
1718 Ptype ptype=static_cast<Ptype>(i);
1719 int indexMin=Ptype_Table.getIndexMin(ptype);
1720 int size=Ptype_Table.getIndexLimit(ptype)-indexMin;
1721 for(int x=0;x<5;x++){
1722 for(int j=0;j<size;j++){
1723 for(int k=0;k<160;k+=40){
1724 PtypeCount::xy_table[(indexMin+j+k)*5+x]+=PtypeCount::table[indexMin+j+k];
1725 }
1726 }
1727 }
1728 }
1729 for(int i=PTYPE_BASIC_MIN;i<=PTYPE_MAX;i++){
1730 Ptype ptype=static_cast<Ptype>(i);
1731 int indexMin=Ptype_Table.getIndexMin(ptype);
1732 int size=Ptype_Table.getIndexLimit(ptype)-indexMin;
1733 for(int x=0;x<5;x++){
1734 for(int k=0;k<160;k+=40)
1735 PtypeCount::xy_table_diff[(indexMin+k)*5+x]=PtypeCount::xy_table[(indexMin+k)*5+x];
1736 for(int j=1;j<size;j++){
1737 for(int k=0;k<160;k+=40)
1738 PtypeCount::xy_table_diff[(indexMin+k+j)*5+x]=PtypeCount::xy_table[(indexMin+k+j)*5+x]-PtypeCount::xy_table[(indexMin+k+j-1)*5+x];
1739 }
1740 }
1741 for(int y=0;y<9;y++){
1742 for(int k=0;k<160;k+=40)
1743 PtypeCount::xy_table_diff[800+(indexMin+k)*9+y]=PtypeCount::xy_table[800+(indexMin+k)*9+y];
1744 for(int j=1;j<size;j++){
1745 for(int k=0;k<160;k+=40)
1746 PtypeCount::xy_table_diff[800+(indexMin+k+j)*9+y]=PtypeCount::xy_table[800+(indexMin+k+j)*9+y]-PtypeCount::xy_table[800+(indexMin+k+j-1)*9+y];
1747 }
1748 }
1749 }
1750 }
1751
1752 void osl::eval::ml::PtypeCountXYAttack::setUp(const Weights &weights)
1753 {
1754 for (size_t i = 0; i < ONE_DIM; ++i)
1755 {
1756 for (int s=0; s<NStages; ++s)
1757 PtypeCount::xy_attack_table[i][s] = weights.value(i + ONE_DIM*s);
1758 }
1759 for(int i=PTYPE_BASIC_MIN;i<=PTYPE_MAX;i++){
1760 Ptype ptype=static_cast<Ptype>(i);
1761 int indexMin=Ptype_Table.getIndexMin(ptype);
1762 int size=Ptype_Table.getIndexLimit(ptype)-indexMin;
1763 for(int x=0;x<5;x++){
1764 for(int k=0;k<160;k+=40)
1765 PtypeCount::xy_attack_table_diff[(indexMin+k)*5+x]=PtypeCount::xy_attack_table[(indexMin+k)*5+x];
1766 for(int j=1;j<size;j++){
1767 for(int k=0;k<160;k+=40)
1768 PtypeCount::xy_attack_table_diff[(indexMin+k+j)*5+x]=PtypeCount::xy_attack_table[(indexMin+k+j)*5+x]-PtypeCount::xy_attack_table[(indexMin+k+j-1)*5+x];
1769 }
1770 }
1771 for(int y=0;y<9;y++){
1772 for(int k=0;k<160;k+=40)
1773 PtypeCount::xy_attack_table_diff[800+(indexMin+k)*9+y]=PtypeCount::xy_attack_table[800+(indexMin+k)*9+y];
1774 for(int j=1;j<size;j++){
1775 for(int k=0;k<160;k+=40)
1776 PtypeCount::xy_attack_table_diff[800+(indexMin+k+j)*9+y]=PtypeCount::xy_attack_table[800+(indexMin+k+j)*9+y]-PtypeCount::xy_attack_table[800+(indexMin+k+j-1)*9+y];
1777 }
1778 }
1779 }
1780 }
1781
1782 template<osl::Player P,osl::Ptype T>
1783 MultiInt osl::eval::ml::PtypeCount::
1784 evalPlayerPtype(const osl::CArray2d<int, 2, osl::PTYPE_SIZE> &ptype_count,
1785 const osl::CArray2d<int, 2, osl::PTYPE_SIZE> &ptype_board_count,
1786 const osl::CArray<int,2> &kings_x,
1787 const osl::CArray<int,2> &kings_y)
1788 {
1789 MultiInt out;
1790 int i=PlayerTraits<P>::index;
1791 int j=static_cast<int>(T);
1792 if (ptype_count[i][j] != 0)
1793 {
1794 const int index_x = indexCountX<T>(ptype_count[i][j], kings_x[i]);
1795 const int index_y = indexCountY<T>(ptype_count[i][j], kings_y[i]);
1796 const int index_x_attack =
1797 indexCountX<T>(ptype_count[i][j], kings_x[1-i]);
1798 const int index_y_attack =
1799 indexCountY<T>(ptype_count[i][j], kings_y[1-i]);
1800 if (P == BLACK)
1801 {
1802 out += xy_table[index_x] + xy_table[index_y];
1803 out += xy_attack_table[index_x_attack] +
1804 xy_attack_table[index_y_attack];
1805 }
1806 else
1807 {
1808 out -= (xy_table[index_x] + xy_table[index_y]);
1809 out -= (xy_attack_table[index_x_attack] +
1810 xy_attack_table[index_y_attack]);
1811 }
1812 if (ptype_board_count[i][j] != 0)
1813 {
1814 const int index_x =
1815 indexBoardCountX<T>(ptype_board_count[i][j], kings_x[i]);
1816 const int index_y =
1817 indexBoardCountY<T>(ptype_board_count[i][j], kings_y[i]);
1818 const int index_x_attack =
1819 indexBoardCountX<T>(ptype_board_count[i][j], kings_x[(i + 1) & 1]);
1820 const int index_y_attack =
1821 indexBoardCountY<T>(ptype_board_count[i][j], kings_y[(i + 1) & 1]);
1822 if (P == BLACK)
1823 {
1824 out += xy_table[index_x] + xy_table[index_y];
1825 out += xy_attack_table[index_x_attack] +
1826 xy_attack_table[index_y_attack];
1827 }
1828 else
1829 {
1830 out -= (xy_table[index_x] + xy_table[index_y]);
1831 out -= (xy_attack_table[index_x_attack] +
1832 xy_attack_table[index_y_attack]);
1833 }
1834 }
1835 }
1836 return out;
1837 }
1838
1839 void
1840 #if (defined __GNUC__ && ! defined __clang__)
1841 __attribute__((__flatten__))
1842 #endif
1843 osl::eval::ml::PtypeCount::eval(
1844 const NumEffectState &state,
1845 const CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
1846 const CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
1847 MultiInt &out)
1848 {
1849 out.clear();
1850 CArray<int, 2> kings_x = {{ state.kingSquare<BLACK>().x(),
1851 state.kingSquare<WHITE>().x() }};
1852 CArray<int, 2> kings_y = {{ state.kingSquare<BLACK>().y(),
1853 10 - state.kingSquare<WHITE>().y() }};
1854 if (kings_x[0] > 5)
1855 kings_x[0] = 10 - kings_x[0];
1856 if (kings_x[1] > 5)
1857 kings_x[1] = 10 - kings_x[1];
1858 out =
1859 evalPlayerPtype<BLACK,PPAWN>(ptype_count,ptype_board_count,kings_x,kings_y)+
1860 evalPlayerPtype<BLACK,PLANCE>(ptype_count,ptype_board_count,kings_x,kings_y)+
1861 evalPlayerPtype<BLACK,PKNIGHT>(ptype_count,ptype_board_count,kings_x,kings_y)+
1862 evalPlayerPtype<BLACK,PSILVER>(ptype_count,ptype_board_count,kings_x,kings_y)+
1863 evalPlayerPtype<BLACK,PBISHOP>(ptype_count,ptype_board_count,kings_x,kings_y)+
1864 evalPlayerPtype<BLACK,PROOK>(ptype_count,ptype_board_count,kings_x,kings_y)+
1865 evalPlayerPtype<BLACK,GOLD>(ptype_count,ptype_board_count,kings_x,kings_y)+
1866 evalPlayerPtype<BLACK,PAWN>(ptype_count,ptype_board_count,kings_x,kings_y)+
1867 evalPlayerPtype<BLACK,LANCE>(ptype_count,ptype_board_count,kings_x,kings_y)+
1868 evalPlayerPtype<BLACK,KNIGHT>(ptype_count,ptype_board_count,kings_x,kings_y)+
1869 evalPlayerPtype<BLACK,SILVER>(ptype_count,ptype_board_count,kings_x,kings_y)+
1870 evalPlayerPtype<BLACK,BISHOP>(ptype_count,ptype_board_count,kings_x,kings_y)+
1871 evalPlayerPtype<BLACK,ROOK>(ptype_count,ptype_board_count,kings_x,kings_y)+
1872 evalPlayerPtype<WHITE,PPAWN>(ptype_count,ptype_board_count,kings_x,kings_y)+
1873 evalPlayerPtype<WHITE,PLANCE>(ptype_count,ptype_board_count,kings_x,kings_y)+
1874 evalPlayerPtype<WHITE,PKNIGHT>(ptype_count,ptype_board_count,kings_x,kings_y)+
1875 evalPlayerPtype<WHITE,PSILVER>(ptype_count,ptype_board_count,kings_x,kings_y)+
1876 evalPlayerPtype<WHITE,PBISHOP>(ptype_count,ptype_board_count,kings_x,kings_y)+
1877 evalPlayerPtype<WHITE,PROOK>(ptype_count,ptype_board_count,kings_x,kings_y)+
1878 evalPlayerPtype<WHITE,GOLD>(ptype_count,ptype_board_count,kings_x,kings_y)+
1879 evalPlayerPtype<WHITE,PAWN>(ptype_count,ptype_board_count,kings_x,kings_y)+
1880 evalPlayerPtype<WHITE,LANCE>(ptype_count,ptype_board_count,kings_x,kings_y)+
1881 evalPlayerPtype<WHITE,KNIGHT>(ptype_count,ptype_board_count,kings_x,kings_y)+
1882 evalPlayerPtype<WHITE,SILVER>(ptype_count,ptype_board_count,kings_x,kings_y)+
1883 evalPlayerPtype<WHITE,BISHOP>(ptype_count,ptype_board_count,kings_x,kings_y)+
1884 evalPlayerPtype<WHITE,ROOK>(ptype_count,ptype_board_count,kings_x,kings_y);
1885 }
1886
1887 template<osl::Player P>
1888 void osl::eval::ml::PtypeCount::evalWithUpdateBang(
1889 const NumEffectState &state,
1890 Move last_move,
1891 CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
1892 CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
1893 MultiInt &last_value_and_out,
1894 unsigned int &ptypeo_mask)
1895 {
1896 assert(last_move.player()==P);
1897 const Player altP=PlayerTraits<P>::opponent;
1898 CArray<int, 2> kings_x = {{ state.kingSquare<BLACK>().x(),
1899 state.kingSquare<WHITE>().x() }};
1900 CArray<int, 2> kings_y = {{ state.kingSquare<BLACK>().y(),
1901 10 - state.kingSquare<WHITE>().y() }};
1902 if (kings_x[0] > 5)
1903 kings_x[0] = 10 - kings_x[0];
1904 if (kings_x[1] > 5)
1905 kings_x[1] = 10 - kings_x[1];
1906
1907 if (last_move.ptype() == KING)
1908 {
1909 const Ptype capturedPtype = last_move.capturePtype();
1910 if (capturedPtype != PTYPE_EMPTY)
1911 {
1912 const PtypeO capturedPtypeO = last_move.capturePtypeO();
1913 if(--ptype_count[altP][capturedPtype]==0)
1914 ptypeo_mask &= ~(1<<(last_move.capturePtypeO()-PTYPEO_MIN));
1915 --ptype_board_count[altP][capturedPtype];
1916 const Ptype base_captured = unpromote(capturedPtype);
1917 ++ptype_count[P][base_captured];
1918 ptypeo_mask |= (1<<(captured(capturedPtypeO)-PTYPEO_MIN));
1919 }
1920 eval(state, ptype_count, ptype_board_count, last_value_and_out);
1921 return;
1922 }
1923
1924 MultiInt sum;
1925 if (last_move.isDrop())
1926 {
1927 const int count = ++ptype_board_count[P][last_move.ptype()];
1928 sum = valueBoardAll(last_move.ptype(),count,kings_x[P],kings_y[P],kings_x[altP],kings_y[altP]);
1929 }
1930 else{
1931 Ptype capturedPtype = last_move.capturePtype();
1932 if (capturedPtype != PTYPE_EMPTY)
1933 {
1934 const int count = --ptype_count[altP][capturedPtype];
1935 if(count==0)
1936 ptypeo_mask &= ~(1<<(last_move.capturePtypeO()-PTYPEO_MIN));
1937 const int board_count = --ptype_board_count[altP][capturedPtype];
1938 const Ptype base_captured = unpromote(capturedPtype);
1939 const int c_count = ++ptype_count[P][base_captured];
1940 ptypeo_mask |= 1<<(captured(last_move.capturePtypeO())-PTYPEO_MIN);
1941 sum=valueAll(capturedPtype,count+1,kings_x[altP],kings_y[altP],kings_x[P],kings_y[P])+
1942 valueBoardAll(capturedPtype,board_count+1,kings_x[altP],kings_y[altP],kings_x[P],kings_y[P])+
1943 valueAll(base_captured,c_count,kings_x[P],kings_y[P],kings_x[altP],kings_y[altP]);
1944 }
1945 if (last_move.isPromotion())
1946 {
1947 const Ptype old_ptype = last_move.oldPtype();
1948 const Ptype new_ptype = last_move.ptype();
1949 const int base_count = --ptype_count[P][old_ptype];
1950 const int base_board_count = --ptype_board_count[P][old_ptype];
1951 const int count = ++ptype_count[P][new_ptype];
1952 const int board_count = ++ptype_board_count[P][new_ptype];
1953 if(base_count==0)
1954 ptypeo_mask &= ~(1<<(last_move.oldPtypeO()-PTYPEO_MIN));
1955 ptypeo_mask |= (1<<(last_move.ptypeO()-PTYPEO_MIN));
1956 sum+=valueAll(new_ptype,count,kings_x[P],kings_y[P],kings_x[altP],kings_y[altP])+
1957 valueBoardAll(new_ptype,board_count,kings_x[P],kings_y[P],kings_x[altP],kings_y[altP])-
1958 valueAll(old_ptype,base_count+1,kings_x[P],kings_y[P],kings_x[altP],kings_y[altP])-
1959 valueBoardAll(old_ptype,base_board_count+1,kings_x[P],kings_y[P],kings_x[altP],kings_y[altP]);
1960 }
1961 }
1962 if(P==BLACK) last_value_and_out+= sum;
1963 else last_value_and_out-= sum;
1964 }
1965
1966 void osl::eval::ml::
1967 LanceEffectPieceKingRelative::setUp(const Weights &weights)
1968 {
1969 for (size_t i = 0; i < ONE_DIM; ++i)
1970 {
1971 for (int s=0; s<NStages; ++s)
1972 table[i][s] = weights.value(i + ONE_DIM*s);
1973 }
1974 }
1975
1976 osl::misc::CArray<MultiInt, 9792>
1977 osl::eval::ml::LanceEffectPieceKingRelative::table;
1978
1979 MultiInt osl::eval::ml::
1980 LanceEffectPieceKingRelative::eval(const NumEffectState &state)
1981 {
1982 MultiInt result;
1983 for (int i = PtypeTraits<LANCE>::indexMin;
1984 i < PtypeTraits<LANCE>::indexLimit;
1985 ++i)
1986 {
1987 const Piece lance = state.pieceOf(i);
1988 if (lance.isOnBoard() && !lance.isPromoted())
1989 {
1990 const Square self_king = state.kingSquare(lance.owner());
1991 const Square opp_king = state.kingSquare(alt(lance.owner()));
1992 Square p = state.mobilityOf(lance.owner() == BLACK ? U : D,
1993 lance.number());
1994 if (!p.isOnBoard())
1995 {
1996 const int index1 = 0 + 0 + (PTYPEO_EDGE - PTYPEO_MIN) * 17 * 9;
1997 const int index2 = 0 + 0 + (PTYPEO_EDGE - PTYPEO_MIN) * 17 * 9 + 4896;
1998 if (lance.owner() == BLACK)
1999 {
2000 result += table[index1];
2001 result += table[index2];
2002 }
2003 else
2004 {
2005 result -= table[index1];
2006 result -= table[index2];
2007 }
2008 }
2009 else
2010 {
2011 const int index1 = index(lance.owner(), p, opp_king,
2012 state.pieceAt(p).ptypeO(), true);
2013 const int index2 = index(lance.owner(), p, self_king,
2014 state.pieceAt(p).ptypeO(), false);
2015 if (lance.owner() == BLACK)
2016 {
2017 result += table[index1];
2018 result += table[index2];
2019 }
2020 else
2021 {
2022 result -= table[index1];
2023 result -= table[index2];
2024 }
2025 }
2026 }
2027 }
2028 return result;
2029 }
2030
2031 osl::misc::CArray<MultiInt, 1440>
2032 osl::eval::ml::PtypeYPawnY::table;
2033
2034 void osl::eval::ml::PtypeYPawnY::setUp(const Weights &weights)
2035 {
2036 for (size_t i = 0; i < ONE_DIM; ++i)
2037 {
2038 for (int s = 0; s < NStages; ++s)
2039 {
2040 table[i][s] = weights.value(i + ONE_DIM*s);
2041 }
2042 }
2043 }
2044
2045 osl::MultiInt osl::eval::ml::
2046 PtypeYPawnY::eval(const NumEffectState &state,
2047 const CArray2d<int, 2, 9> &pawns)
2048 {
2049 MultiInt result;
2050 for (int i = 0; i < Piece::SIZE; ++i)
2051 {
2052 const Piece piece = state.pieceOf(i);
2053 // only skip pawn, not ppawns
2054 if (piece.ptype() == PAWN)
2055 continue;
2056 if (!piece.isOnBoard())
2057 continue;
2058
2059 const int idx = index(piece.owner(), piece.ptype(), piece.square().y(),
2060 pawns[piece.owner()][piece.square().x() - 1]);
2061 if (piece.owner() == BLACK)
2062 {
2063 result += table[idx];
2064 }
2065 else
2066 {
2067 result -= table[idx];
2068 }
2069 }
2070
2071 return result;
2072 }
2073
2074 template<osl::Player P>
2075 void osl::eval::ml::
2076 PtypeYPawnY::evalWithUpdateBang(const NumEffectState &state,
2077 Move moved,
2078 const CArray2d<int, 2, 9> &pawns,
2079 MultiInt& last_value)
2080 {
2081 Ptype captured = moved.capturePtype();
2082 assert(P==moved.player());
2083
2084 if (moved.oldPtype() == PAWN)
2085 {
2086 const int x = moved.to().x();
2087 const int old_pawn_y = (moved.isDrop() ? 0 : moved.from().y());
2088 const int new_pawn_y = pawns[P][moved.to().x() - 1];
2089 for (int y = 1; y <= 9; ++y)
2090 {
2091 const Piece p = state.pieceAt(Square(x, y));
2092 if (y == moved.to().y())
2093 {
2094 if (p.ptype() == PPAWN)
2095 {
2096 const int idx_new = index(P, p.ptype(), y, new_pawn_y);
2097 if (P == BLACK)
2098 {
2099 last_value += table[idx_new];
2100 }
2101 else
2102 {
2103 last_value -= table[idx_new];
2104 }
2105 }
2106 }
2107 else if (!p.isEmpty() && p.owner() == P)
2108 {
2109 const int idx_old = index(P, p.ptype(), y, old_pawn_y);
2110 const int idx_new = index(P, p.ptype(), y, new_pawn_y);
2111 if (P == BLACK)
2112 {
2113 last_value -= table[idx_old];
2114 last_value += table[idx_new];
2115 }
2116 else
2117 {
2118 last_value += table[idx_old];
2119 last_value -= table[idx_new];
2120 }
2121 }
2122 }
2123 }
2124 else
2125 {
2126 if (!moved.isDrop())
2127 {
2128 const int pawn_y = pawns[P][moved.from().x() - 1];
2129 const int idx = index(P, moved.oldPtype(), moved.from().y(),
2130 pawn_y);
2131 if (P == BLACK)
2132 {
2133 last_value -= table[idx];
2134 }
2135 else
2136 {
2137 last_value += table[idx];
2138 }
2139 }
2140 {
2141 const int pawn_y = pawns[P][moved.to().x() - 1];
2142 const int idx = index(P, moved.ptype(), moved.to().y(),
2143 pawn_y);
2144 if (P == BLACK)
2145 {
2146 last_value += table[idx];
2147 }
2148 else
2149 {
2150 last_value -= table[idx];
2151 }
2152 }
2153 }
2154
2155 if (captured != PTYPE_EMPTY)
2156 {
2157 if (captured == PAWN)
2158 {
2159 const int old_pawn_y = moved.to().y();
2160 const int new_pawn_y = 0;
2161 const int x = moved.to().x();
2162 for (int y = 1; y <= 9; ++y)
2163 {
2164 const Piece p = state.pieceAt(Square(x, y));
2165 if (!p.isEmpty() && p.owner() == alt(P))
2166 {
2167 const int idx_old = index(alt(P), p.ptype(), y,
2168 old_pawn_y);
2169 const int idx_new = index(alt(P), p.ptype(), y,
2170 new_pawn_y);
2171 if (P == BLACK)
2172 {
2173 last_value += table[idx_old];
2174 last_value -= table[idx_new];
2175 }
2176 else
2177 {
2178 last_value -= table[idx_old];
2179 last_value += table[idx_new];
2180 }
2181 }
2182 }
2183 }
2184 else
2185 {
2186 const int pawn_y = pawns[alt(P)][moved.to().x() - 1];
2187 const int idx = index(alt(P), captured, moved.to().y(),
2188 pawn_y);
2189 if (P == BLACK)
2190 {
2191 last_value += table[idx];
2192 }
2193 else
2194 {
2195 last_value -= table[idx];
2196 }
2197 }
2198 }
2199 }
2200
2201 osl::misc::CArray<osl::MultiInt, 1215>
2202 osl::eval::ml::GoldAndSilverNearKing::table;
2203 osl::misc::CArray<osl::MultiInt, 9720>
2204 osl::eval::ml::GoldAndSilverNearKing::combination_table;
2205
2206 void osl::eval::ml::
2207 GoldAndSilverNearKing::setUp(const Weights &weights)
2208 {
2209 for (size_t i = 0; i < ONE_DIM; ++i)
2210 {
2211 for (int s=0; s<NStages; ++s)
2212 table[i][s] = weights.value(i + ONE_DIM*s);
2213 }
2214 }
2215
2216 void osl::eval::ml::
2217 GoldAndSilverNearKingCombination::setUp(const Weights &weights)
2218 {
2219 for (size_t i = 0; i < ONE_DIM; ++i)
2220 {
2221 for (int s=0; s<NStages; ++s)
2222 GoldAndSilverNearKing::combination_table[i][s] =
2223 weights.value(i + ONE_DIM*s);
2224 }
2225 }
2226
2227 template <osl::Player P>
2228 osl::MultiInt osl::eval::ml::
2229 GoldAndSilverNearKing::evalOne(const NumEffectState &state,
2230 const CArray2d<int, 2, 3> &gs_count)
2231 {
2232 MultiInt result;
2233 int total = 0;
2234 const Square king = state.kingSquare<P>();
2235 for (size_t i = 0; i < gs_count.size2(); ++i)
2236 {
2237 total += gs_count[P][i];
2238 if (total != 0)
2239 {
2240 result += table[index<P>(king, i, total)];
2241 }
2242 }
2243 result += combination_table[
2244 indexCombination<P>(king, gs_count[P][0],
2245 gs_count[P][1], gs_count[P][2])];
2246 return P == BLACK ? result : -result;
2247 }
2248
2249 osl::MultiInt osl::eval::ml::
2250 GoldAndSilverNearKing::eval(const NumEffectState &state,
2251 const CArray2d<int, 2, 3> &gs_count)
2252 {
2253 return evalOne<BLACK>(state, gs_count) + evalOne<WHITE>(state, gs_count);
2254 }
2255
2256
2257 osl::misc::CArray<osl::MultiInt, 8192>
2258 osl::eval::ml::PtypeCombination::table;
2259
2260 void osl::eval::ml::
2261 PtypeCombination::setUp(const Weights &weights)
2262 {
2263 static CArray<MultiInt, 8192> orig_table;
2264 for (size_t i = 0; i < ONE_DIM; ++i)
2265 {
2266 for (int s = 0; s < NStages; ++s)
2267 {
2268 orig_table[i][s] = weights.value(i + ONE_DIM*s);
2269 }
2270 }
2271 for(int i=0;i<8192;i++){
2272 int pawn=(i>>12)&1;
2273 int ppawn=(i>>6)&1;
2274 int lance=(i>>11)&1;
2275 int plance=(i>>5)&1;
2276 int knight=(i>>10)&1;
2277 int pknight=(i>>4)&1;
2278 int silver=(i>>9)&1;
2279 int psilver=(i>>3)&1;
2280 int bishop=(i>>8)&1;
2281 int pbishop=(i>>2)&1;
2282 int rook=(i>>7)&1;
2283 int prook=(i>>1)&1;
2284 int gold=(i>>0)&1;
2285 int newIndex=ppawn|(plance<<1)|(pknight<<2)|(psilver<<3)|(pbishop<<4)|
2286 (prook<<5)|(gold<<6)|(pawn<<7)|(lance<<8)|(knight<<9)|(silver<<10)|
2287 (bishop<<11)|(rook<<12);
2288 table[newIndex]=orig_table[i];
2289 }
2290 }
2291
2292 osl::MultiInt osl::eval::ml::
2293 PtypeCombination::eval(unsigned int ptypeo_mask)
2294 {
2295 return evalOne<BLACK>(ptypeo_mask) + evalOne<WHITE>(ptypeo_mask);
2296 }
2297
2298
2299 osl::CArray<osl::MultiInt, 5*2>
2300 osl::eval::ml::SilverFork::table;
2301 inline
2302 std::pair<int,int> osl::eval::ml::
2303 SilverFork::matchRook(const NumEffectState& state, Piece rook,
2304 const CArray<bool,2>& has_silver,
2305 Square& silver_drop)
2306 {
2307 const Square sq = rook.square();
2308 if (rook.isPromoted() || sq.isPieceStand())
2309 return std::make_pair(0,0);
2310 const Player owner = rook.owner();
2311 if (! has_silver[alt(owner)] || ! sq.canPromote(alt(owner)))
2312 return std::make_pair(0,0);
2313 const CArray<Offset,2> offset = {{
2314 Board_Table.getOffset(owner, UL), Board_Table.getOffset(owner, UR)
2315 }};
2316 for (size_t i=0; i<offset.size(); ++i) {
2317 const Square next = sq+offset[i], next2 = next+offset[i];
2318 if (! state.pieceAt(next).isEmpty() || state.hasEffectAt(owner, next))
2319 continue;
2320 const Piece p = state.pieceAt(next2);
2321 if (! p.isOnBoardByOwner(owner))
2322 continue;
2323 silver_drop = next;
2324 if (p.ptype() == ROOK)
2325 return std::make_pair(playerToMul(owner), 0);
2326 if (p.ptype() == GOLD)
2327 return std::make_pair(playerToMul(owner), state.hasEffectAt(owner, next2) ? 1 : 2);
2328 }
2329 return std::make_pair(0,0);
2330 }
2331 inline
2332 std::pair<int,int> osl::eval::ml::
2333 SilverFork::matchGold(const NumEffectState& state, Piece gold,
2334 const CArray<bool,2>& has_silver, Square& silver_drop)
2335 {
2336 const Square sq = gold.square();
2337 if (sq.isPieceStand())
2338 return std::make_pair(0,0);
2339 const Player owner = gold.owner();
2340 if (! has_silver[alt(owner)] || ! sq.canPromote(alt(owner)))
2341 return std::make_pair(0,0);
2342 const CArray<Offset,2> offset = {{
2343 Board_Table.getOffset(BLACK, L), Board_Table.getOffset(BLACK, R)
2344 }};
2345 const bool guarded = state.hasEffectAt(owner, sq);
2346 for (size_t i=0; i<offset.size(); ++i) {
2347 const Square next = sq+offset[i], next2 = next+offset[i];
2348 const Piece np = state.pieceAt(next);
2349 if (np.isEdge())
2350 continue;
2351 const Square next_down = next + Board_Table.getOffset(owner, D);
2352 if (! state.pieceAt(next_down).isEmpty() || state.hasEffectAt(owner, next_down))
2353 continue;
2354 const Piece p = state.pieceAt(next2);
2355 if (! p.isOnBoardByOwner(owner))
2356 continue;
2357 if (p.ptype() == ROOK || p.ptype() == GOLD) {
2358 silver_drop = next_down;
2359 const bool recaputure = guarded
2360 || (p.ptype() == GOLD && state.hasEffectAt(owner, next2))
2361 || (np.canMoveOn(owner) && ! state.hasEffectAt(alt(owner), next));
2362 return std::make_pair(playerToMul(owner), 3 + recaputure);
2363 }
2364 }
2365 return std::make_pair(0,0);
2366 }
2367
2368 osl::MultiIntPair osl::eval::ml::
2369 SilverFork::eval(const NumEffectState& state, CArray<std::pair<Square,int>,2>& silver_drop)
2370 {
2371 silver_drop.fill(std::make_pair(Square(),0));
2372 MultiIntPair result; // by turn
2373 const CArray<bool,2> has_silver = {{
2374 state.hasPieceOnStand<SILVER>(BLACK),
2375 state.hasPieceOnStand<SILVER>(WHITE),
2376 }};
2377 if (! has_silver[BLACK] && ! has_silver[WHITE])
2378 return result;
2379 Square drop;
2380 for (int i = PtypeTraits<ROOK>::indexMin;
2381 i < PtypeTraits<ROOK>::indexLimit; ++i)
2382 {
2383 const Piece rook = state.pieceOf(i);
2384 std::pair<int,int> match = matchRook(state, rook, has_silver, drop);
2385 if (match.first) {
2386 const MultiInt value_attack = table[match.second*2];
2387 const Player attack = (match.first > 0) ? WHITE : BLACK;
2388 if (-value_attack[0] > silver_drop[attack].second) {
2389 silver_drop[attack].second = -value_attack[0];
2390 silver_drop[attack].first = drop;
2391 }
2392 if (match.first > 0) // owner is black
2393 {
2394 result[BLACK] += table[match.second*2+1];
2395 result[WHITE] += value_attack;
2396 }
2397 else if (match.first < 0) // owner is white
2398 {
2399 result[BLACK] -= value_attack;
2400 result[WHITE] -= table[match.second*2+1];
2401 }
2402 }
2403 }
2404
2405 for (int i = PtypeTraits<GOLD>::indexMin;
2406 i < PtypeTraits<GOLD>::indexLimit; ++i)
2407 {
2408 const Piece gold = state.pieceOf(i);
2409 std::pair<int,int> match = matchGold(state, gold, has_silver, drop);
2410 if (match.first) {
2411 const MultiInt value_attack = table[match.second*2];
2412 const Player attack = (match.first > 0) ? WHITE : BLACK;
2413 if (-value_attack[0] > silver_drop[attack].second) {
2414 silver_drop[attack].second = -value_attack[0];
2415 silver_drop[attack].first = drop;
2416 }
2417 if (match.first > 0)
2418 {
2419 result[BLACK] += table[match.second*2+1];
2420 result[WHITE] += value_attack;
2421 }
2422 else if (match.first < 0)
2423 {
2424 result[BLACK] -= value_attack;
2425 result[WHITE] -= table[match.second*2+1];
2426 }
2427 }
2428 }
2429 return result;
2430 }
2431
2432 void osl::eval::ml::SilverFork::setUp(const Weights &weights)
2433 {
2434 for (int i = 0; i < ONE_DIM; ++i)
2435 {
2436 for (int s=0; s<NStages; ++s)
2437 table[i][s] = weights.value(i + ONE_DIM*s);
2438 }
2439 }
2440
2441 osl::CArray<osl::MultiInt, 256*2*2>
2442 osl::eval::ml::BishopRookFork::table;
2443 void osl::eval::ml::BishopRookFork::setUp(const Weights &weights)
2444 {
2445 for (int i = 0; i < ONE_DIM; ++i)
2446 {
2447 for (int s=0; s<NStages; ++s)
2448 table[i][s] = weights.value(i + ONE_DIM*s);
2449 }
2450 for (int i=0; i<PTYPE_SIZE; ++i)
2451 for (int j=i+1; j<PTYPE_SIZE; ++j)
2452 {
2453 table[bishopIndex((Ptype)j,(Ptype)i)*2] = table[bishopIndex((Ptype)i,(Ptype)j)*2];
2454 table[bishopIndex((Ptype)j,(Ptype)i)*2+1] = table[bishopIndex((Ptype)i,(Ptype)j)*2+1];
2455 table[rookIndex((Ptype)j,(Ptype)i)*2] = table[rookIndex((Ptype)i,(Ptype)j)*2];
2456 table[rookIndex((Ptype)j,(Ptype)i)*2+1] = table[rookIndex((Ptype)i,(Ptype)j)*2+1];
2457 }
2458 }
2459 inline
2460 const osl::Square osl::eval::ml::BishopRookFork::
2461 findDropInLine(const NumEffectState& state, Player defense,
2462 const Square a, const Square b, Piece king)
2463 {
2464 Offset offset = Board_Table.getShortOffset(Offset32(b,a));
2465 Square drop_position;
2466 Square sq=a+offset;
2467 for (Piece p=state.pieceAt(sq); p.isEmpty(); sq+=offset, p=state.pieceAt(sq))
2468 {
2469 if (! drop_position.isPieceStand())
2470 continue;
2471 if (! state.hasEffectAt(defense, sq)
2472 || (state.hasEffectAt(alt(defense), sq)
2473 && ! state.hasEffectNotBy(defense, king, sq)))
2474 drop_position = sq;
2475 }
2476 return (sq == b) ? drop_position : Square();
2477 }
2478 inline
2479 bool osl::eval::ml::BishopRookFork::
2480 testCenter(const NumEffectState& state, Player defense,
2481 const Square a, const Square b, Piece king,
2482 Square center, bool maybe_empty)
2483 {
2484 const Piece p = state.pieceAt(center);
2485 if (! p.isEmpty()
2486 || (state.hasEffectAt(defense, center)
2487 && (! state.hasEffectAt(alt(defense), center)
2488 || state.hasEffectNotBy(defense, king, center))))
2489 return false;
2490 return state.isEmptyBetween(center, a, !maybe_empty)
2491 && state.isEmptyBetween(center, b, !maybe_empty);
2492 }
2493
2494 const osl::Square osl::eval::ml::
2495 BishopRookFork::isBishopForkSquare(const NumEffectState& state, Player defense,
2496 const Square a, const Square b,
2497 bool maybe_empty)
2498 {
2499 const Piece king = state.kingPiece(defense);
2500 const int cx = b.x() - a.x(), cy = b.y() - a.y();
2501 if ((cx + cy) % 2)
2502 return Square();
2503 const int p = (cx+cy)/2, q = (cx-cy)/2;
2504 if (p == 0 || q == 0)
2505 return findDropInLine(state, defense, a, b, king);
2506
2507 const CArray<Square,2> centers = {{
2508 b + Offset(-p,-p), b + Offset(-q,q)
2509 }};
2510
2511 for (size_t i=0; i<centers.size(); ++i) {
2512 if (! centers[i].isOnBoardRegion())
2513 continue;
2514 if (testCenter(state, defense, a, b, king, centers[i], maybe_empty))
2515 return centers[i];
2516 }
2517 return Square();
2518 }
2519
2520 inline
2521 const osl::Square osl::eval::ml::
2522 BishopRookFork::isRookForkSquare(const NumEffectState& state, Player defense,
2523 const Square a, const Square b)
2524 {
2525 const Piece king = state.kingPiece(defense);
2526 const CArray<Square,2> centers = {{
2527 Square(a.x(), b.y()), Square(b.x(), a.y())
2528 }};
2529 if (centers[0] == a || centers[0] == b)
2530 return findDropInLine(state, defense, a, b, king);
2531 for (size_t i=0; i<centers.size(); ++i)
2532 {
2533 assert(centers[i].isOnBoardRegion());
2534 if (testCenter(state, defense, a, b, king, centers[i]))
2535 return centers[i];
2536 }
2537 return Square();
2538 }
2539
2540 template <osl::Player Defense>
2541 osl::MultiIntPair osl::eval::ml::
2542 BishopRookFork::evalOne(const NumEffectState &state, const PieceVector& target,
2543 std::pair<Square,int>& bishop_drop,
2544 std::pair<Square,int>& rook_drop)
2545 {
2546 MultiIntPair result;
2547 for (size_t i=0; i<target.size(); ++i)
2548 {
2549 const Piece pi = target[i];
2550 assert(pi.isOnBoardByOwner(Defense));
2551 for (size_t j=i+1; j<target.size(); ++j)
2552 {
2553 const Piece pj = target[j];
2554 assert(pj.isOnBoardByOwner(Defense));
2555 if (state.hasPieceOnStand<BISHOP>(alt(Defense)))
2556 {
2557 const Square center
2558 = isBishopForkSquare(state, Defense, pi.square(), pj.square());
2559 if (! center.isPieceStand()) {
2560 const int index = bishopIndex(pi.ptype(), pj.ptype())*2;
2561 const MultiInt value_attack = table[index];
2562 if (-value_attack[0] > bishop_drop.second) { // negative value is better for attacker
2563 bishop_drop.second = -value_attack[0];
2564 bishop_drop.first = center;
2565 }
2566 if (Defense == BLACK)
2567 {
2568 result[BLACK] += table[index+1];
2569 result[WHITE] += value_attack;
2570 }
2571 else
2572 {
2573 result[BLACK] -= value_attack;
2574 result[WHITE] -= table[index+1];
2575 }
2576 }
2577 }
2578 if (state.hasPieceOnStand<ROOK>(alt(Defense)))
2579 {
2580 const Square center
2581 = isRookForkSquare(state, Defense, pi.square(), pj.square());
2582 if (! center.isPieceStand()) {
2583 const int index = rookIndex(pi.ptype(), pj.ptype())*2;
2584 const MultiInt value_attack = table[index];
2585 if (-value_attack[0] > rook_drop.second) { // negative value is better for attacker
2586 rook_drop.second = -value_attack[0];
2587 rook_drop.first = center;
2588 }
2589 if (Defense == BLACK)
2590 {
2591 result[BLACK] += table[index+1];
2592 result[WHITE] += value_attack;
2593 }
2594 else
2595 {
2596 result[BLACK] -= value_attack;
2597 result[WHITE] -= table[index+1];
2598 }
2599 }
2600 }
2601 }
2602 }
2603 assert(bishop_drop.second == 0 || ! bishop_drop.first.isPieceStand());
2604 return result;
2605 }
2606
2607 osl::MultiIntPair osl::eval::ml::
2608 BishopRookFork::eval(const NumEffectState &state,
2609 CArray<std::pair<Square,int>,2>& bishop_drop,
2610 CArray<std::pair<Square,int>,2>& rook_drop)
2611 {
2612 bishop_drop.fill(std::make_pair(Square(),0));
2613 rook_drop.fill(std::make_pair(Square(),0));
2614 MultiIntPair result;
2615 const CArray<bool,2> has_bishop = {{
2616 state.hasPieceOnStand<BISHOP>(BLACK),
2617 state.hasPieceOnStand<BISHOP>(WHITE),
2618 }};
2619 const CArray<bool,2> has_rook = {{
2620 state.hasPieceOnStand<ROOK>(BLACK),
2621 state.hasPieceOnStand<ROOK>(WHITE),
2622 }};
2623 if (has_bishop[BLACK] + has_bishop[WHITE]
2624 + has_rook[BLACK] + has_rook[WHITE] == 0)
2625 return result;
2626 PieceMask notcovered = ~state.effectedMask(BLACK);
2627 notcovered &= ~state.effectedMask(WHITE);
2628 notcovered.clearBit<PAWN>();
2629 notcovered.setBit<KING>();
2630 if (has_bishop[WHITE] + has_rook[WHITE]) {
2631 PieceVector pieces;
2632 PieceMask target = notcovered & state.piecesOnBoard(BLACK);
2633 while (target.any())
2634 pieces.push_back(state.pieceOf(target.takeOneBit()));
2635 result += evalOne<BLACK>(state, pieces, bishop_drop[WHITE], rook_drop[WHITE]);
2636 }
2637 if (has_bishop[BLACK] + has_rook[BLACK]) {
2638 PieceVector pieces;
2639 PieceMask target = notcovered & state.piecesOnBoard(WHITE);
2640 while (target.any())
2641 pieces.push_back(state.pieceOf(target.takeOneBit()));
2642 result += evalOne<WHITE>(state, pieces, bishop_drop[BLACK], rook_drop[BLACK]);
2643 }
2644 return result;
2645 }
2646
2647
2648
2649 osl::CArray<osl::MultiInt, 256*2*2>
2650 osl::eval::ml::KnightFork::table;
2651 void osl::eval::ml::KnightFork::setUp(const Weights &weights)
2652 {
2653 for (int i = 0; i < ONE_DIM; ++i)
2654 {
2655 for (int s=0; s<NStages; ++s)
2656 table[i][s] = weights.value(i + ONE_DIM*s);
2657 }
2658 for (int i=0; i<PTYPE_SIZE; ++i)
2659 for (int j=i+1; j<PTYPE_SIZE; ++j) {
2660 table[index((Ptype)j,(Ptype)i)*2] = table[index((Ptype)i,(Ptype)j)*2];
2661 table[index((Ptype)j,(Ptype)i)*2+1] = table[index((Ptype)i,(Ptype)j)*2+1];
2662 table[(index((Ptype)j,(Ptype)i)+DROP_DIM)*2] = table[(index((Ptype)i,(Ptype)j)+DROP_DIM)*2];
2663 table[(index((Ptype)j,(Ptype)i)+DROP_DIM)*2+1] = table[(index((Ptype)i,(Ptype)j)+DROP_DIM)*2+1];
2664 }
2665 }
2666
2667 template <osl::Player Defense>
2668 osl::MultiIntPair osl::eval::ml::
2669 KnightFork::evalOne(const NumEffectState &state, bool has_knight,
2670 BoardMask& knight_fork_squares,
2671 std::pair<Square,int>& knight_drop)
2672 {
2673 knight_fork_squares.clear();
2674 const int z = playerToIndex(Defense);
2675 const int y_min = 3-z*2, y_max = 9-z*2;
2676 CArray<PieceVector,10> pieces;
2677 {
2678 PieceMask target = state.piecesOnBoard(Defense);
2679 target.clearBit<PAWN>();
2680 target.clearBit<LANCE>();
2681 target.clearBit<KNIGHT>();
2682 while (target.any()) {
2683 const Piece p = state.pieceOf(target.takeOneBit());
2684 const int y = p.square().y();
2685 pieces[y].push_back(p);
2686 }
2687 }
2688 MultiIntPair result;
2689 for (int y=y_min; y<=y_max; ++y){
2690 if (pieces[y].size() < 2)
2691 continue;
2692 const int y_drop = y - playerToMul(Defense)*2;
2693 for (size_t i=0; i<pieces[y].size(); ++i)
2694 {
2695 const Piece pi = pieces[y][i];
2696 assert(pi.isOnBoardByOwner(Defense));
2697 assert(pi.square().y() == y);
2698 const int xi = pi.square().x();
2699 for (size_t j=i+1; j<pieces[y].size(); ++j)
2700 {
2701 const Piece pj = pieces[y][j];
2702 assert(pj.isOnBoardByOwner(Defense));
2703 assert(pj.square().y() == y);
2704 const int xj = pj.square().x();
2705 if (abs(xi -xj) != 2)
2706 continue;
2707 const Square drop = Square((xi+xj)/2, y_drop);
2708 knight_fork_squares.set(drop);
2709 if (! state[drop].isEmpty() || state.hasEffectAt(Defense, drop))
2710 continue;
2711 int found = index(pi.ptype(), pj.ptype());
2712 if (! has_knight)
2713 found += DROP_DIM;
2714 found *= 2;
2715 const MultiInt value_attack = table[found];
2716 if (Defense == BLACK)
2717 {
2718 result[BLACK] += table[found+1];
2719 result[WHITE] += value_attack;
2720 }
2721 else
2722 {
2723 result[BLACK] -= value_attack;
2724 result[WHITE] -= table[found+1];
2725 }
2726 if (has_knight && -value_attack[0] > knight_drop.second) {
2727 knight_drop.second = -value_attack[0];
2728 knight_drop.first = Square((pi.square().x()+pj.square().x())/2, y_drop);
2729 }
2730 }
2731 }
2732 }
2733 return result;
2734 }
2735
2736 osl::MultiIntPair osl::eval::ml::
2737 KnightFork::eval(const NumEffectState &state,
2738 CArray<BoardMask,2>& knight_fork_squares,
2739 CArray<std::pair<Square,int>,2>& knight_drop)
2740 {
2741 knight_drop.fill(std::make_pair(Square(),0));
2742 MultiIntPair result;
2743 const CArray<bool,2> has_knight = {{
2744 state.hasPieceOnStand<KNIGHT>(BLACK),
2745 state.hasPieceOnStand<KNIGHT>(WHITE),
2746 }};
2747
2748 const CArray<bool,2> may_have_knight = {{
2749 has_knight[BLACK]
2750 || (state.effectedMask(BLACK).selectBit<KNIGHT>()
2751 & ~state.effectedMask(WHITE).selectBit<KNIGHT>()
2752 & state.piecesOnBoard(WHITE).getMask(PtypeFuns<KNIGHT>::indexNum)).any(),
2753 has_knight[WHITE]
2754 || (state.effectedMask(WHITE).selectBit<KNIGHT>()
2755 & ~state.effectedMask(BLACK).selectBit<KNIGHT>()
2756 & state.piecesOnBoard(BLACK).getMask(PtypeFuns<KNIGHT>::indexNum)).any(),
2757 }};
2758 if (has_knight[BLACK] + has_knight[WHITE]
2759 + may_have_knight[BLACK] + may_have_knight[WHITE] == 0) {
2760 knight_fork_squares[BLACK].invalidate();
2761 knight_fork_squares[WHITE].invalidate();
2762 return result;
2763 }
2764 {
2765 const Player Defense = BLACK;
2766 if (has_knight[alt(Defense)] + may_have_knight[alt(Defense)] > 0)
2767 result += evalOne<Defense>(state, has_knight[alt(Defense)],
2768 knight_fork_squares[alt(Defense)],
2769 knight_drop[alt(Defense)]);
2770 else
2771 knight_fork_squares[alt(Defense)].invalidate();
2772 }
2773 {
2774 const Player Defense = WHITE;
2775 if (has_knight[alt(Defense)] + may_have_knight[alt(Defense)] > 0)
2776 result += evalOne<Defense>(state, has_knight[alt(Defense)],
2777 knight_fork_squares[alt(Defense)],
2778 knight_drop[alt(Defense)]);
2779 else
2780 knight_fork_squares[alt(Defense)].invalidate();
2781 }
2782 return result;
2783 }
2784
2785 template <osl::Player P, osl::Player Defense>
2786 void osl::eval::ml::
2787 KnightFork::updateSquares(const NumEffectState& state, Move moved,
2788 BoardMask& knight_fork_squares)
2789 {
2790 assert(! knight_fork_squares.isInvalid());
2791 const Square to = moved.to();
2792 if (P != Defense) {
2793 if (! moved.isCapture())
2794 return;
2795 if ((Defense == BLACK && to.y() >= 3)
2796 || (Defense == WHITE && to.y() <= 7)) {
2797 knight_fork_squares.reset(to.neighbor<Defense,UUL>());
2798 knight_fork_squares.reset(to.neighbor<Defense,UUR>());
2799 }
2800 return;
2801 }
2802 if (! moved.isDrop()) {
2803 if ((P == BLACK && moved.from().y() >= 3)
2804 || (P == WHITE && moved.from().y() <= 7)) {
2805 knight_fork_squares.reset(moved.from().neighbor<P,UUL>());
2806 knight_fork_squares.reset(moved.from().neighbor<P,UUR>());
2807 }
2808 }
2809 if (! isTarget(moved.ptype())
2810 || (P == BLACK && to.y() < 3) || (P == WHITE && to.y() > 7))
2811 return;
2812 if (to.x() <= 7)
2813 {
2814 const Square l = to.neighbor<BLACK,L>(), l2 = l.neighbor<BLACK,L>();
2815 if (state[l2].isOnBoardByOwner<P>()) {
2816 knight_fork_squares.set(l.neighbor<P,U>().template neighbor<P,U>());
2817 }
2818 }
2819 if (to.x() >= 3)
2820 {
2821 const Square r = to.neighbor<BLACK,R>(), r2 = r.neighbor<BLACK,R>();
2822 if (state[r2].isOnBoardByOwner<P>()){
2823 knight_fork_squares.set(r.neighbor<P,U>().template neighbor<P,U>());
2824 }
2825 }
2826 }
2827
2828 template <osl::Player Defense>
2829 osl::MultiIntPair osl::eval::ml::
2830 KnightFork::accumulate(const NumEffectState& state,
2831 bool has_knight,
2832 const BoardMask& knight_fork_squares,
2833 std::pair<Square,int>& knight_drop)
2834 {
2835 MultiIntPair result;
2836 BoardMask mask = knight_fork_squares;
2837 while (mask.any()) {
2838 Square sq = mask.takeOneBit();
2839 if (! state[sq].isEmpty() || state.hasEffectAt(Defense, sq))
2840 continue;
2841 const Piece pi = state[sq.back<Defense,UUL>()];
2842 const Piece pj = state[sq.back<Defense,UUR>()];
2843 if (! pi.isOnBoardByOwner<Defense>() || ! pj.isOnBoardByOwner<Defense>())
2844 std::cerr << state << Defense << ' ' << pi << ' ' << pj << "\n";
2845 assert(pi.isOnBoardByOwner<Defense>());
2846 assert(pj.isOnBoardByOwner<Defense>());
2847 int found = index(pi.ptype(), pj.ptype());
2848 if (! has_knight)
2849 found += DROP_DIM;
2850 found *= 2;
2851 const MultiInt value_attack = table[found];
2852 if (Defense == BLACK)
2853 {
2854 result[BLACK] += table[found+1];
2855 result[WHITE] += value_attack;
2856 }
2857 else
2858 {
2859 result[BLACK] -= value_attack;
2860 result[WHITE] -= table[found+1];
2861 }
2862 if (has_knight && -value_attack[0] > knight_drop.second) {
2863 knight_drop.second = -value_attack[0];
2864 knight_drop.first = sq;
2865 }
2866 }
2867 return result;
2868 }
2869
2870 template <osl::Player P>
2871 osl::MultiIntPair osl::eval::ml::
2872 KnightFork::evalWithUpdate(const NumEffectState &state, Move moved,
2873 CArray<BoardMask,2>& knight_fork_squares,
2874 CArray<std::pair<Square,int>,2>& knight_drop)
2875 {
2876 knight_drop.fill(std::make_pair(Square(),0));
2877 MultiIntPair result;
2878 const CArray<bool,2> has_knight = {{
2879 state.hasPieceOnStand<KNIGHT>(BLACK),
2880 state.hasPieceOnStand<KNIGHT>(WHITE),
2881 }};
2882 const CArray<bool,2> may_have_knight = {{
2883 has_knight[BLACK]
2884 || (state.effectedMask(BLACK).selectBit<KNIGHT>()
2885 & ~state.effectedMask(WHITE).selectBit<KNIGHT>()
2886 & state.piecesOnBoard(WHITE).getMask(PtypeFuns<KNIGHT>::indexNum)).any(),
2887 has_knight[WHITE]
2888 || (state.effectedMask(WHITE).selectBit<KNIGHT>()
2889 & ~state.effectedMask(BLACK).selectBit<KNIGHT>()
2890 & state.piecesOnBoard(BLACK).getMask(PtypeFuns<KNIGHT>::indexNum)).any(),
2891 }};
2892 if (has_knight[BLACK] + has_knight[WHITE]
2893 + may_have_knight[BLACK] + may_have_knight[WHITE] == 0) {
2894 knight_fork_squares[BLACK].invalidate();
2895 knight_fork_squares[WHITE].invalidate();
2896 return result;
2897 }
2898 {
2899 const Player Defense = BLACK;
2900 if (has_knight[alt(Defense)] + may_have_knight[alt(Defense)] > 0) {
2901 if (knight_fork_squares[alt(Defense)].isInvalid())
2902 result += evalOne<Defense>(state, has_knight[alt(Defense)],
2903 knight_fork_squares[alt(Defense)],
2904 knight_drop[alt(Defense)]);
2905 else {
2906 updateSquares<P,Defense>(state, moved, knight_fork_squares[alt(Defense)]);
2907 result += accumulate<Defense>(state, has_knight[alt(Defense)],
2908 knight_fork_squares[alt(Defense)],
2909 knight_drop[alt(Defense)]);
2910 }
2911 }
2912 else
2913 knight_fork_squares[alt(Defense)].invalidate();
2914 }
2915 {
2916 const Player Defense = WHITE;
2917 if (has_knight[alt(Defense)] + may_have_knight[alt(Defense)] > 0) {
2918 if (knight_fork_squares[alt(Defense)].isInvalid())
2919 result += evalOne<Defense>(state, has_knight[alt(Defense)],
2920 knight_fork_squares[alt(Defense)],
2921 knight_drop[alt(Defense)]);
2922 else {
2923 updateSquares<P,Defense>(state, moved, knight_fork_squares[alt(Defense)]);
2924 result += accumulate<Defense>(state, has_knight[alt(Defense)],
2925 knight_fork_squares[alt(Defense)],
2926 knight_drop[alt(Defense)]);
2927 }
2928 }
2929 else
2930 knight_fork_squares[alt(Defense)].invalidate();
2931 }
2932 return result;
2933 }
2934
2935
2936 void osl::eval::ml::SilverAdvance26::setUp(const Weights &weights)
2937 {
2938 for (size_t i = 0; i < ONE_DIM; ++i)
2939 {
2940 for (int s=0; s<NStages; ++s)
2941 table[i][s] = weights.value(i + ONE_DIM*s);
2942 }
2943 }
2944 osl::MultiInt osl::eval::ml::
2945 SilverAdvance26::eval(const NumEffectState &state)
2946 {
2947 const CArray<std::pair<Square,Ptype>,5> pattern = {{
2948 std::make_pair( Square(2,6), SILVER ),
2949 std::make_pair( Square(1,5), PAWN ),
2950 std::make_pair( Square(3,7), KNIGHT ),
2951 std::make_pair( Square(2,5), PAWN ),
2952 std::make_pair( Square(3,6), PAWN ),
2953 }};
2954 MultiInt sum;
2955 bool match = state.kingSquare(BLACK).x() >= 5;
2956 if (match) {
2957 for (size_t i=0; i<pattern.size(); ++i) {
2958 const Piece p = state.pieceAt(pattern[i].first);
2959 if (p.ptype() != pattern[i].second || p.owner() != BLACK) {
2960 match = false;
2961 break;
2962 }
2963 }
2964 if (match)
2965 sum += table[0];
2966 }
2967 match = state.kingSquare(WHITE).x() <= 5;
2968 if (match) {
2969 for (size_t i=0; i<pattern.size(); ++i) {
2970 const Piece p = state.pieceAt(pattern[i].first.rotate180());
2971 if (p.ptype() != pattern[i].second || p.owner() != WHITE) {
2972 match = false;
2973 break;
2974 }
2975 }
2976 if (match)
2977 sum += -table[0];
2978 }
2979 return sum;
2980 }
2981
2982
2983
2984 osl::CArray<osl::MultiInt, osl::PTYPE_SIZE>
2985 osl::eval::ml::Promotion37::table;
2986 void osl::eval::ml::Promotion37::setUp(const Weights &weights)
2987 {
2988 for (size_t i = 0; i < ONE_DIM; ++i)
2989 {
2990 for (int s=0; s<NStages; ++s)
2991 table[i][s] = weights.value(i + ONE_DIM*s);
2992 }
2993 }
2994
2995 template <osl::Player P>
2996 osl::MultiInt osl::eval::ml::
2997 Promotion37::evalOne(const NumEffectState &state, int rank)
2998 {
2999 CArray<int,PTYPE_SIZE> count = {{ 0 }};
3000 for (int x=1; x<=9; ++x) {
3001 const Square target(x, rank);
3002 if (! state[target].isEmpty())
3003 continue;
3004 int a = state.countEffect(P, target);
3005 const int d = state.countEffect(alt(P), target);
3006 if (a > 0 && a == d)
3007 a += AdditionalEffect::hasEffect(state, target, P);
3008 if (a < d)
3009 continue;
3010 const Ptype ptype = state.findCheapAttack(P, target).ptype();
3011 if (isPiece(ptype) && ! isPromoted(ptype))
3012 count[ptype]++;
3013 }
3014 MultiInt ret;
3015 for (int p=PTYPE_BASIC_MIN; p<=PTYPE_MAX; ++p) {
3016 if (count[p] > 0)
3017 ret += table[p]*playerToMul(P);
3018 if (count[p] > 1)
3019 ret += table[p-8]*(playerToMul(P)*(count[p]-1));
3020 }
3021 return ret;
3022 }
3023
3024 osl::MultiInt osl::eval::ml::
3025 Promotion37::eval(const NumEffectState &state)
3026 {
3027 return evalOne<BLACK>(state, 3) + evalOne<WHITE>(state, 7);
3028 }
3029
3030 template <osl::Player P>
3031 osl::MultiInt osl::eval::ml::
3032 Promotion37::evalWithUpdate(const NumEffectState& state, Move moved,
3033 MultiInt const& last_value)
3034 {
3035 if (moved.isPass())
3036 return last_value;
3037 // todo changedEffects
3038 return eval(state);
3039 }
3040
3041
3042 namespace osl
3043 {
3044 namespace eval
3045 {
3046 namespace ml
3047 {
3048 template void PawnAdvanceAll::
3049 evalWithUpdateBang<BLACK>(const NumEffectState &, Move,MultiInt&);
3050 template void PawnAdvanceAll::
3051 evalWithUpdateBang<WHITE>(const NumEffectState &, Move,MultiInt&);
3052 template MultiInt PtypeY::
3053 evalWithUpdate<BLACK>(const NumEffectState &, Move, MultiInt const&);
3054 template MultiInt PtypeY::
3055 evalWithUpdate<WHITE>(const NumEffectState &, Move, MultiInt const&);
3056 template MultiInt PtypeX::
3057 evalWithUpdate<BLACK>(const NumEffectState &, Move, MultiInt const&);
3058 template MultiInt PtypeX::
3059 evalWithUpdate<WHITE>(const NumEffectState &, Move, MultiInt const&);
3060 template MultiInt PawnPtypeOPtypeO::
3061 evalWithUpdate<BLACK>(const NumEffectState &, Move, const CArray2d<int, 2, 9> &, MultiInt const&);
3062 template MultiInt PawnPtypeOPtypeO::
3063 evalWithUpdate<WHITE>(const NumEffectState &, Move, const CArray2d<int, 2, 9> &, MultiInt const&);
3064
3065 template void osl::eval::ml::NonPawnAttacked::
3066 evalWithUpdateBang<BLACK>(const NumEffectState &state,
3067 Move moved,
3068 const CArray<PieceMask, 2> &effected,
3069 MultiIntPair &result);
3070 template void osl::eval::ml::NonPawnAttacked::
3071 evalWithUpdateBang<WHITE>(const NumEffectState &state,
3072 Move moved,
3073 const CArray<PieceMask, 2> &effected,
3074 MultiIntPair &result);
3075 template void osl::eval::ml::NonPawnAttackedPtype::
3076 evalWithUpdateBang<BLACK>(
3077 const NumEffectState &state,
3078 Move moved,
3079 const CArray<PieceMask, 2> &effected,
3080 CArray<PieceMask, 40> &attacked_mask,
3081 MultiIntPair &result);
3082 template void osl::eval::ml::NonPawnAttackedPtype::
3083 evalWithUpdateBang<WHITE>(
3084 const NumEffectState &state,
3085 Move moved,
3086 const CArray<PieceMask, 2> &effected,
3087 CArray<PieceMask, 40> &attacked_mask,
3088 MultiIntPair &result);
3089 template void osl::eval::ml::PtypeYPawnY::
3090 evalWithUpdateBang<BLACK>(const NumEffectState &state,
3091 Move moved,
3092 const CArray2d<int, 2, 9> &pawns,
3093 MultiInt& last_value);
3094 template void osl::eval::ml::PtypeYPawnY::
3095 evalWithUpdateBang<WHITE>(const NumEffectState &state,
3096 Move moved,
3097 const CArray2d<int, 2, 9> &pawns,
3098 MultiInt& last_value);
3099 template void PtypeCount::
3100 evalWithUpdateBang<BLACK>(const NumEffectState &state,Move last_move,
3101 CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
3102 CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
3103 MultiInt &last_value_and_out,
3104 unsigned int &ptypeo_mask);
3105 template void PtypeCount::
3106 evalWithUpdateBang<WHITE>(const NumEffectState &state,Move last_move,
3107 CArray2d<int, 2, PTYPE_SIZE> &ptype_count,
3108 CArray2d<int, 2, PTYPE_SIZE> &ptype_board_count,
3109 MultiInt &last_value_and_out,
3110 unsigned int &ptypeo_mask);
3111
3112 template MultiIntPair KnightFork::
3113 evalWithUpdate<BLACK>(const NumEffectState&, Move, CArray<BoardMask,2>&,
3114 CArray<std::pair<Square,int>,2>&);
3115 template MultiIntPair KnightFork::
3116 evalWithUpdate<WHITE>(const NumEffectState&, Move, CArray<BoardMask,2>&,
3117 CArray<std::pair<Square,int>,2>&);
3118 }
3119 }
3120 }
3121 // ;;; Local Variables:
3122 // ;;; mode:c++
3123 // ;;; c-basic-offset:2
3124 // ;;; End: