1
2 // sort.cpp
3
4 // includes
5
6 #include "attack.h"
7 #include "board.h"
8 #include "colour.h"
9 #include "list.h"
10 #include "move.h"
11 #include "move_check.h"
12 #include "move_evasion.h"
13 #include "move_gen.h"
14 #include "move_legal.h"
15 #include "piece.h"
16 #include "search.h"
17 #include "see.h"
18 #include "sort.h"
19 #include "util.h"
20 #include "value.h"
21
22 // constants
23
24 static const int KillerNb = 2;
25
26 static const int HistorySize = 12 * 64 * 64;
27 static const int HistoryMax = 16384;
28
29 static const int TransScore = +32766;
30 static const int GoodScore = +4000;
31 static const int KillerScore = +4;
32 static const int HistoryScore = -24000;
33 static const int BadScore = -28000;
34
35 static const int CODE_SIZE = 256;
36
37 // macros
38
39 #define HISTORY_INC(depth) ((depth)*(depth))
40
41 // types
42
43 enum gen_t {
44 GEN_ERROR,
45 GEN_LEGAL_EVASION,
46 GEN_TRANS,
47 GEN_GOOD_CAPTURE,
48 GEN_BAD_CAPTURE,
49 GEN_KILLER,
50 GEN_QUIET,
51 GEN_EVASION_QS,
52 GEN_CAPTURE_QS,
53 GEN_CHECK_QS,
54 GEN_END
55 };
56
57 enum test_t {
58 TEST_ERROR,
59 TEST_NONE,
60 TEST_LEGAL,
61 TEST_TRANS_KILLER,
62 TEST_GOOD_CAPTURE,
63 TEST_BAD_CAPTURE,
64 TEST_KILLER,
65 TEST_QUIET,
66 TEST_CAPTURE_QS,
67 TEST_CHECK_QS
68 };
69
70 // variables
71
72 static int PosLegalEvasion;
73 static int PosSEE;
74
75 static int PosEvasionQS;
76 static int PosCheckQS;
77 static int PosCaptureQS;
78
79 static int Code[CODE_SIZE];
80
81 static uint16 Killer[HeightMax][KillerNb];
82
83 static fail_high_stats_t FailHighStats[HistorySize];
84 static uint16 History[HistorySize];
85 static uint16 HistHit[HistorySize];
86 static uint16 HistTot[HistorySize];
87
88 // prototypes
89
90 // static void note_captures (list_t * list, const board_t * board);
91 static void note_quiet_moves (list_t * list, const board_t * board);
92 static void note_moves_simple (list_t * list, const board_t * board);
93 static void note_mvv_lva (list_t * list, const board_t * board);
94
95 static int move_value (int move, const board_t * board, int height, int trans_killer);
96 static int capture_value (int move, const board_t * board);
97 static int quiet_move_value (int move, const board_t * board);
98 static int move_value_simple (int move, const board_t * board);
99
100 static int history_prob (int move, const board_t * board);
101
102 static bool capture_is_good (int move, const board_t * board);
103
104 static int mvv_lva (int move, const board_t * board);
105
106 static int history_index (int move, const board_t * board);
107
108 // functions
109
110 // sort_init()
111
sort_init()112 void sort_init() {
113
114 int i, height;
115 int pos;
116
117 // killer
118
119 for (height = 0; height < HeightMax; height++) {
120 for (i = 0; i < KillerNb; i++) Killer[height][i] = MoveNone;
121 }
122
123 // history
124
125 for (i = 0; i < HistorySize; i++) History[i] = 0;
126
127 for (i = 0; i < HistorySize; i++) {
128 HistHit[i] = 1;
129 HistTot[i] = 1;
130 FailHighStats[i].success = 1;
131 FailHighStats[i].tried = 1;
132 }
133
134 // Code[]
135
136 for (pos = 0; pos < CODE_SIZE; pos++) Code[pos] = GEN_ERROR;
137
138 pos = 0;
139
140 // main search
141
142 PosLegalEvasion = pos;
143 Code[pos++] = GEN_LEGAL_EVASION;
144 Code[pos++] = GEN_END;
145
146 PosSEE = pos;
147 Code[pos++] = GEN_TRANS;
148 Code[pos++] = GEN_GOOD_CAPTURE;
149 Code[pos++] = GEN_KILLER;
150 Code[pos++] = GEN_QUIET;
151 Code[pos++] = GEN_BAD_CAPTURE;
152 Code[pos++] = GEN_END;
153
154 // quiescence search
155
156 PosEvasionQS = pos;
157 Code[pos++] = GEN_EVASION_QS;
158 Code[pos++] = GEN_END;
159
160 PosCheckQS = pos;
161 Code[pos++] = GEN_CAPTURE_QS;
162 Code[pos++] = GEN_CHECK_QS;
163 Code[pos++] = GEN_END;
164
165 PosCaptureQS = pos;
166 Code[pos++] = GEN_CAPTURE_QS;
167 Code[pos++] = GEN_END;
168
169 ASSERT(pos<CODE_SIZE);
170 }
171
172 // sort_init()
173
sort_init(sort_t * sort,board_t * board,const attack_t * attack,int depth,int height,int trans_killer)174 void sort_init(sort_t * sort, board_t * board, const attack_t * attack, int depth, int height, int trans_killer) {
175
176 ASSERT(sort!=NULL);
177 ASSERT(board!=NULL);
178 ASSERT(attack!=NULL);
179 ASSERT(depth_is_ok(depth));
180 ASSERT(height_is_ok(height));
181 ASSERT(trans_killer==MoveNone||move_is_ok(trans_killer));
182
183 sort->board = board;
184 sort->attack = attack;
185
186 sort->depth = depth;
187 sort->height = height;
188
189 sort->trans_killer = trans_killer;
190 sort->killer_1 = Killer[sort->height][0];
191 sort->killer_2 = Killer[sort->height][1];
192 if (sort->height > 2){
193 sort->killer_3 = Killer[sort->height-2][0];
194 sort->killer_4 = Killer[sort->height-2][1];
195 }
196 else{
197 sort->killer_3 = MoveNone;
198 sort->killer_4 = MoveNone;
199 }
200
201 if (ATTACK_IN_CHECK(sort->attack)) {
202
203 gen_legal_evasions(sort->list,sort->board,sort->attack);
204 note_moves(sort->list,sort->board,sort->height,sort->trans_killer);
205 list_sort(sort->list);
206
207 sort->gen = PosLegalEvasion + 1;
208 sort->test = TEST_NONE;
209
210 } else { // not in check
211
212 LIST_CLEAR(sort->list);
213 sort->gen = PosSEE;
214 }
215
216 sort->pos = 0;
217 }
218
219 // sort_next()
220
sort_next(sort_t * sort)221 int sort_next(sort_t * sort) {
222
223 int move;
224 int gen;
225
226 ASSERT(sort!=NULL);
227
228 while (true) {
229
230 while (sort->pos < LIST_SIZE(sort->list)) {
231
232 // next move
233
234 move = LIST_MOVE(sort->list,sort->pos);
235 sort->value = 16384; // default score
236 sort->pos++;
237
238 ASSERT(move!=MoveNone);
239
240 // test
241
242 if (false) {
243
244 } else if (sort->test == TEST_NONE) {
245
246 // no-op
247
248 } else if (sort->test == TEST_TRANS_KILLER) {
249
250 if (!move_is_pseudo(move,sort->board)) continue;
251 if (!pseudo_is_legal(move,sort->board)) continue;
252
253 } else if (sort->test == TEST_GOOD_CAPTURE) {
254
255 ASSERT(move_is_tactical(move,sort->board));
256
257 if (move == sort->trans_killer) continue;
258
259 if (!capture_is_good(move,sort->board)) {
260 LIST_ADD(sort->bad,move);
261 continue;
262 }
263
264 if (!pseudo_is_legal(move,sort->board)) continue;
265
266 } else if (sort->test == TEST_BAD_CAPTURE) {
267
268 ASSERT(move_is_tactical(move,sort->board));
269 ASSERT(!capture_is_good(move,sort->board));
270
271 ASSERT(move!=sort->trans_killer);
272 if (!pseudo_is_legal(move,sort->board)) continue;
273
274 } else if (sort->test == TEST_KILLER) {
275
276 if (move == sort->trans_killer) continue;
277 if (!quiet_is_pseudo(move,sort->board)) continue;
278 if (!pseudo_is_legal(move,sort->board)) continue;
279
280 ASSERT(!move_is_tactical(move,sort->board));
281
282 } else if (sort->test == TEST_QUIET) {
283
284 ASSERT(!move_is_tactical(move,sort->board));
285
286 if (move == sort->trans_killer) continue;
287 if (move == sort->killer_1) continue;
288 if (move == sort->killer_2) continue;
289 if (move == sort->killer_3) continue;
290 if (move == sort->killer_4) continue;
291 if (!pseudo_is_legal(move,sort->board)) continue;
292
293 sort->value = history_prob(move,sort->board);
294
295 } else {
296
297 ASSERT(false);
298
299 return MoveNone;
300 }
301
302 ASSERT(pseudo_is_legal(move,sort->board));
303
304 return move;
305 }
306
307 // next stage
308
309 gen = Code[sort->gen++];
310
311 if (false) {
312
313 } else if (gen == GEN_TRANS) {
314
315 LIST_CLEAR(sort->list);
316 if (sort->trans_killer != MoveNone) LIST_ADD(sort->list,sort->trans_killer);
317
318 sort->test = TEST_TRANS_KILLER;
319
320 } else if (gen == GEN_GOOD_CAPTURE) {
321
322 gen_captures(sort->list,sort->board);
323 note_mvv_lva(sort->list,sort->board);
324 list_sort(sort->list);
325
326 LIST_CLEAR(sort->bad);
327
328 sort->test = TEST_GOOD_CAPTURE;
329
330 } else if (gen == GEN_BAD_CAPTURE) {
331
332 list_copy(sort->list,sort->bad);
333
334 sort->test = TEST_BAD_CAPTURE;
335
336 } else if (gen == GEN_KILLER) {
337
338 LIST_CLEAR(sort->list);
339 if (sort->killer_1 != MoveNone) LIST_ADD(sort->list,sort->killer_1);
340 if (sort->killer_2 != MoveNone) LIST_ADD(sort->list,sort->killer_2);
341 if (sort->killer_3 != MoveNone) LIST_ADD(sort->list,sort->killer_3);
342 if (sort->killer_4 != MoveNone) LIST_ADD(sort->list,sort->killer_4);
343
344 sort->test = TEST_KILLER;
345
346 } else if (gen == GEN_QUIET) {
347
348 gen_quiet_moves(sort->list,sort->board);
349 note_quiet_moves(sort->list,sort->board);
350 list_sort(sort->list);
351
352 sort->test = TEST_QUIET;
353
354 } else {
355
356 ASSERT(gen==GEN_END);
357
358 return MoveNone;
359 }
360
361 sort->pos = 0;
362 }
363 }
364
365 // sort_init_qs()
366
sort_init_qs(sort_t * sort,board_t * board,const attack_t * attack,bool check)367 void sort_init_qs(sort_t * sort, board_t * board, const attack_t * attack, bool check) {
368
369 ASSERT(sort!=NULL);
370 ASSERT(board!=NULL);
371 ASSERT(attack!=NULL);
372 ASSERT(check==true||check==false);
373
374 sort->board = board;
375 sort->attack = attack;
376
377 if (ATTACK_IN_CHECK(sort->attack)) {
378 sort->gen = PosEvasionQS;
379 } else if (check) {
380 sort->gen = PosCheckQS;
381 } else {
382 sort->gen = PosCaptureQS;
383 }
384
385 LIST_CLEAR(sort->list);
386 sort->pos = 0;
387 }
388
389 // sort_next_qs()
390
sort_next_qs(sort_t * sort)391 int sort_next_qs(sort_t * sort) {
392
393 int move;
394 int gen;
395
396 ASSERT(sort!=NULL);
397
398 while (true) {
399
400 while (sort->pos < LIST_SIZE(sort->list)) {
401
402 // next move
403
404 move = LIST_MOVE(sort->list,sort->pos);
405 sort->pos++;
406
407 ASSERT(move!=MoveNone);
408
409 // test
410
411 if (false) {
412
413 } else if (sort->test == TEST_LEGAL) {
414
415 if (!pseudo_is_legal(move,sort->board)) continue;
416
417 } else if (sort->test == TEST_CAPTURE_QS) {
418
419 ASSERT(move_is_tactical(move,sort->board));
420
421 if (!capture_is_good(move,sort->board)) continue;
422 if (!pseudo_is_legal(move,sort->board)) continue;
423
424 } else if (sort->test == TEST_CHECK_QS) {
425
426 ASSERT(!move_is_tactical(move,sort->board));
427 ASSERT(move_is_check(move,sort->board));
428
429 if (see_move(move,sort->board) < 0) continue;
430 if (!pseudo_is_legal(move,sort->board)) continue;
431
432 } else {
433
434 ASSERT(false);
435
436 return MoveNone;
437 }
438
439 ASSERT(pseudo_is_legal(move,sort->board));
440
441 return move;
442 }
443
444 // next stage
445
446 gen = Code[sort->gen++];
447
448 if (false) {
449
450 } else if (gen == GEN_EVASION_QS) {
451
452 gen_pseudo_evasions(sort->list,sort->board,sort->attack);
453 note_moves_simple(sort->list,sort->board);
454 list_sort(sort->list);
455
456 sort->test = TEST_LEGAL;
457
458 } else if (gen == GEN_CAPTURE_QS) {
459
460 gen_captures(sort->list,sort->board);
461 note_mvv_lva(sort->list,sort->board);
462 list_sort(sort->list);
463
464 sort->test = TEST_CAPTURE_QS;
465
466 } else if (gen == GEN_CHECK_QS) {
467
468 gen_quiet_checks(sort->list,sort->board);
469
470 sort->test = TEST_CHECK_QS;
471
472 } else {
473
474 ASSERT(gen==GEN_END);
475
476 return MoveNone;
477 }
478
479 sort->pos = 0;
480 }
481 }
482
483 // good_move()
484
good_move(int move,const board_t * board,int depth,int height)485 void good_move(int move, const board_t * board, int depth, int height) {
486
487 int index;
488 int i;
489
490 ASSERT(move_is_ok(move));
491 ASSERT(board!=NULL);
492 ASSERT(depth_is_ok(depth));
493 ASSERT(height_is_ok(height));
494
495
496 if (move_is_tactical(move,board)) return;
497
498 // killer
499
500 if (Killer[height][0] != move) {
501 Killer[height][1] = Killer[height][0];
502 Killer[height][0] = move;
503 }
504
505 ASSERT(Killer[height][0]==move);
506 ASSERT(Killer[height][1]!=move);
507
508 // history
509
510 index = history_index(move,board);
511
512 History[index] += HISTORY_INC(depth);
513
514 if (History[index] >= HistoryMax) {
515 for (i = 0; i < HistorySize; i++) {
516 History[i] = (History[i] + 1) / 2;
517 }
518 }
519 }
520
521 // history_good()
522
history_good(int move,const board_t * board)523 void history_good(int move, const board_t * board) {
524
525 int index;
526
527 ASSERT(move_is_ok(move));
528 ASSERT(board!=NULL);
529
530 if (move_is_tactical(move,board)) return;
531
532 // history
533
534 index = history_index(move,board);
535
536 HistHit[index]++;
537 HistTot[index]++;
538
539 if (HistTot[index] >= HistoryMax) {
540 HistHit[index] = (HistHit[index] + 1) / 2;
541 HistTot[index] = (HistTot[index] + 1) / 2;
542 }
543
544 ASSERT(HistHit[index]<=HistTot[index]);
545 ASSERT(HistTot[index]<HistoryMax);
546 }
547
548 // history_bad()
549
history_bad(int move,const board_t * board)550 void history_bad(int move, const board_t * board) {
551
552 int index;
553
554 ASSERT(move_is_ok(move));
555 ASSERT(board!=NULL);
556
557 if (move_is_tactical(move,board)) return;
558
559 // history
560
561 index = history_index(move,board);
562
563 HistTot[index]++;
564
565 if (HistTot[index] >= HistoryMax) {
566 HistHit[index] = (HistHit[index] + 1) / 2;
567 HistTot[index] = (HistTot[index] + 1) / 2;
568 }
569
570 ASSERT(HistHit[index]<=HistTot[index]);
571 ASSERT(HistTot[index]<HistoryMax);
572 }
573
574 // history_very_bad()
575
history_very_bad(int move,const board_t * board)576 void history_very_bad(int move, const board_t * board) {
577
578 int index;
579
580 ASSERT(move_is_ok(move));
581 ASSERT(board!=NULL);
582
583 //if (move_is_tactical(move,board)) return;
584
585 // history
586
587 index = PIECE_TO_12(board->square[MOVE_TO(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move));
588
589 HistTot[index] += 100;
590
591 if (HistTot[index] >= HistoryMax) {
592 HistHit[index] = (HistHit[index] + 1) / 2;
593 HistTot[index] = (HistTot[index] + 1) / 2;
594 }
595
596 ASSERT(HistHit[index]<=HistTot[index]);
597 ASSERT(HistTot[index]<HistoryMax);
598 }
599
600 // history_tried()
601
history_tried(int move,const board_t * board)602 void history_tried(int move, const board_t * board) {
603
604 int index;
605
606 ASSERT(move_is_ok(move));
607 ASSERT(board!=NULL);
608
609 if (move_is_tactical(move,board)) return;
610
611 // history
612
613 index = history_index(move,board);
614
615 FailHighStats[index].tried++;
616 }
617
618 // history_success()
619
history_success(int move,const board_t * board)620 void history_success(int move, const board_t * board) {
621
622 int index;
623
624 ASSERT(move_is_ok(move));
625 ASSERT(board!=NULL);
626
627 if (move_is_tactical(move,board)) return;
628
629 // history
630
631 index = history_index(move,board);
632
633 FailHighStats[index].success++;
634 }
635
history_reduction(int move,const board_t * board)636 bool history_reduction(int move, const board_t * board) {
637
638 int index;
639
640 ASSERT(move_is_ok(move));
641 ASSERT(board!=NULL);
642
643 // history
644
645 index = history_index(move,board);
646
647 if(FailHighStats[index].success > FailHighStats[index].tried / 8)
648 return false;
649 return true;
650 }
651
652 // note_moves()
653
note_moves(list_t * list,const board_t * board,int height,int trans_killer)654 void note_moves(list_t * list, const board_t * board, int height, int trans_killer) {
655
656 int size;
657 int i, move;
658
659 ASSERT(list_is_ok(list));
660 ASSERT(board!=NULL);
661 ASSERT(height_is_ok(height));
662 ASSERT(trans_killer==MoveNone||move_is_ok(trans_killer));
663
664 size = LIST_SIZE(list);
665
666 if (size >= 2) {
667 for (i = 0; i < size; i++) {
668 move = LIST_MOVE(list,i);
669 list->value[i] = move_value(move,board,height,trans_killer);
670 }
671 }
672 }
673
674 // note_captures()
675
676 // static void note_captures(list_t * list, const board_t * board) {
677 //
678 // int size;
679 // int i, move;
680 //
681 // ASSERT(list_is_ok(list));
682 // ASSERT(board!=NULL);
683 //
684 // size = LIST_SIZE(list);
685 //
686 // if (size >= 2) {
687 // for (i = 0; i < size; i++) {
688 // move = LIST_MOVE(list,i);
689 // list->value[i] = capture_value(move,board);
690 // }
691 // }
692 // }
693
694 // note_quiet_moves()
695
note_quiet_moves(list_t * list,const board_t * board)696 static void note_quiet_moves(list_t * list, const board_t * board) {
697
698 int size;
699 int i, move;
700
701 ASSERT(list_is_ok(list));
702 ASSERT(board!=NULL);
703
704 size = LIST_SIZE(list);
705
706 if (size >= 2) {
707 for (i = 0; i < size; i++) {
708 move = LIST_MOVE(list,i);
709 list->value[i] = quiet_move_value(move,board);
710 }
711 }
712 }
713
714 // note_moves_simple()
715
note_moves_simple(list_t * list,const board_t * board)716 static void note_moves_simple(list_t * list, const board_t * board) {
717
718 int size;
719 int i, move;
720
721 ASSERT(list_is_ok(list));
722 ASSERT(board!=NULL);
723
724 size = LIST_SIZE(list);
725
726 if (size >= 2) {
727 for (i = 0; i < size; i++) {
728 move = LIST_MOVE(list,i);
729 list->value[i] = move_value_simple(move,board);
730 }
731 }
732 }
733
734 // note_mvv_lva()
735
note_mvv_lva(list_t * list,const board_t * board)736 static void note_mvv_lva(list_t * list, const board_t * board) {
737
738 int size;
739 int i, move;
740
741 ASSERT(list_is_ok(list));
742 ASSERT(board!=NULL);
743
744 size = LIST_SIZE(list);
745
746 if (size >= 2) {
747 for (i = 0; i < size; i++) {
748 move = LIST_MOVE(list,i);
749 list->value[i] = mvv_lva(move,board);
750 }
751 }
752 }
753
754 // move_value()
755
move_value(int move,const board_t * board,int height,int trans_killer)756 static int move_value(int move, const board_t * board, int height, int trans_killer) {
757
758 int value;
759
760 ASSERT(move_is_ok(move));
761 ASSERT(board!=NULL);
762 ASSERT(height_is_ok(height));
763 ASSERT(trans_killer==MoveNone||move_is_ok(trans_killer));
764
765 if (false) {
766 } else if (move == trans_killer) { // transposition table killer
767 value = TransScore;
768 } else if (move_is_tactical(move,board)) { // capture or promote
769 value = capture_value(move,board);
770 } else if (move == Killer[height][0]) { // killer 1
771 value = KillerScore;
772 } else if (move == Killer[height][1]) { // killer 2
773 value = KillerScore - 2;
774 } else if (height > 2 && move == Killer[height-2][0]) { // killer 3
775 value = KillerScore - 1;
776 } else if (height > 2 && move == Killer[height-2][1]) { // killer 4
777 value = KillerScore - 3;
778 } else { // quiet move
779 value = quiet_move_value(move,board);
780 }
781
782 return value;
783 }
784
785 // capture_value()
786
capture_value(int move,const board_t * board)787 static int capture_value(int move, const board_t * board) {
788
789 int value;
790
791 ASSERT(move_is_ok(move));
792 ASSERT(board!=NULL);
793
794 ASSERT(move_is_tactical(move,board));
795
796 value = mvv_lva(move,board);
797
798 if (capture_is_good(move,board)) {
799 value += GoodScore;
800 } else {
801 value += BadScore;
802 }
803
804 ASSERT(value>=-30000&&value<=+30000);
805
806 return value;
807 }
808
809 // quiet_move_value()
810
quiet_move_value(int move,const board_t * board)811 static int quiet_move_value(int move, const board_t * board) {
812
813 int value;
814 int index;
815
816 ASSERT(move_is_ok(move));
817 ASSERT(board!=NULL);
818
819 ASSERT(!move_is_tactical(move,board));
820
821 index = history_index(move,board);
822
823 value = HistoryScore + History[index];
824 ASSERT(value>=HistoryScore&&value<=KillerScore-4);
825
826 return value;
827 }
828
829 // move_value_simple()
830
move_value_simple(int move,const board_t * board)831 static int move_value_simple(int move, const board_t * board) {
832
833 int value;
834
835 ASSERT(move_is_ok(move));
836 ASSERT(board!=NULL);
837
838 value = HistoryScore;
839 if (move_is_tactical(move,board)) value = mvv_lva(move,board);
840
841 return value;
842 }
843
844 // history_prob()
845
history_prob(int move,const board_t * board)846 static int history_prob(int move, const board_t * board) {
847
848 int value;
849 int index;
850
851 ASSERT(move_is_ok(move));
852 ASSERT(board!=NULL);
853
854 ASSERT(!move_is_tactical(move,board));
855
856 index = history_index(move,board);
857
858 ASSERT(HistHit[index]<=HistTot[index]);
859 ASSERT(HistTot[index]<HistoryMax);
860
861 value = (HistHit[index] * 16384) / HistTot[index];
862 ASSERT(value>=0&&value<=16384);
863
864 return value;
865 }
866
867 // capture_is_good()
868
capture_is_good(int move,const board_t * board)869 static bool capture_is_good(int move, const board_t * board) {
870
871 int piece, capture;
872
873 ASSERT(move_is_ok(move));
874 ASSERT(board!=NULL);
875
876 ASSERT(move_is_tactical(move,board));
877
878 // special cases
879
880 if (MOVE_IS_EN_PASSANT(move)) return true;
881 if (move_is_under_promote(move)) return false; // REMOVE ME?
882
883 // captures and queen promotes
884
885 capture = board->square[MOVE_TO(move)];
886
887 if (capture != Empty) {
888
889 // capture
890
891 ASSERT(move_is_capture(move,board));
892
893 if (MOVE_IS_PROMOTE(move)) return true; // promote-capture
894
895 piece = board->square[MOVE_FROM(move)];
896 if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true;
897 }
898
899 return see_move(move,board) >= 0;
900 }
901
902 // mvv_lva()
903
mvv_lva(int move,const board_t * board)904 static int mvv_lva(int move, const board_t * board) {
905
906 int piece, capture, promote;
907 int value;
908
909 ASSERT(move_is_ok(move));
910 ASSERT(board!=NULL);
911
912 ASSERT(move_is_tactical(move,board));
913
914 if (MOVE_IS_EN_PASSANT(move)) { // en-passant capture
915
916 value = 5; // PxP
917
918 } else if ((capture = board->square[MOVE_TO(move)]) != Empty) { // normal capture
919
920 piece = board->square[MOVE_FROM(move)];
921
922 value = PIECE_ORDER(capture) * 6 - PIECE_ORDER(piece) + 5;
923 ASSERT(value>=0&&value<30);
924
925 } else { // promote
926
927 ASSERT(MOVE_IS_PROMOTE(move));
928
929 promote = move_promote(move);
930
931 value = PIECE_ORDER(promote) - 5;
932 ASSERT(value>=-4&&value<0);
933 }
934
935 ASSERT(value>=-4&&value<+30);
936
937 return value;
938 }
939
940 // history_index()
941
history_index(int move,const board_t * board)942 static int history_index(int move, const board_t * board) {
943
944 int index;
945
946 ASSERT(move_is_ok(move));
947 ASSERT(board!=NULL);
948
949 ASSERT(!move_is_tactical(move,board));
950
951 index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * 64 + SQUARE_TO_64(MOVE_FROM(move)) * 64 + SQUARE_TO_64(MOVE_TO(move));
952
953 ASSERT(index>=0&&index<HistorySize);
954
955 return index;
956 }
957
958 // end of sort.cpp
959
960