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