Check in Bonanza Feliz 0.0
[bonanza.git] / hash.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stddef.h>
4 #include <assert.h>
5 #include "shogi.h"
6
7 static int eval_supe( unsigned int hand_current, unsigned int hand_hash,
8                       int turn_current, int turn_hash,
9                       int * restrict pvalue_hash, int * restrict ptype_hash );
10
11 int
12 ini_trans_table( void )
13 {
14   size_t size;
15   unsigned int ntrans_table;
16
17   ntrans_table = 1U << log2_ntrans_table;
18   size         = sizeof( trans_table_t ) * ntrans_table + 15U;
19   ptrans_table_orig = memory_alloc( size );
20   if ( ptrans_table_orig == NULL ) { return -1; }
21   ptrans_table = (trans_table_t *)( ((ptrdiff_t)ptrans_table_orig+15)
22                                     & ~(ptrdiff_t)15U );
23   hash_mask    = ntrans_table - 1;
24   Out( "Trans. Table Entries = %dK (%dMB)\n",
25        ( ntrans_table * 3U ) / 1024U, size / (1024U * 1024U ) );
26
27   return clear_trans_table();
28 }
29
30
31 #define Foo( PIECE, piece )  bb = BB_B ## PIECE;                    \
32                              while( BBToU(bb) ) {                   \
33                                sq = FirstOne( bb );                 \
34                                Xor( sq, bb );                       \
35                                key ^= ( b_ ## piece ## _rand )[sq]; \
36                              }                                      \
37                              bb = BB_W ## PIECE;                    \
38                              while( BBToU(bb) ) {                   \
39                                sq = FirstOne( bb );                 \
40                                Xor( sq, bb );                       \
41                                key ^= ( w_ ## piece ## _rand )[sq]; \
42                              }
43
44 uint64_t
45 hash_func( const tree_t * restrict ptree )
46 {
47   uint64_t key = 0;
48   bitboard_t bb;
49   int sq;
50
51   key ^= b_king_rand[SQ_BKING];
52   key ^= w_king_rand[SQ_WKING];
53
54   Foo( PAWN,       pawn );
55   Foo( LANCE,      lance );
56   Foo( KNIGHT,     knight );
57   Foo( SILVER,     silver );
58   Foo( GOLD,       gold );
59   Foo( BISHOP,     bishop );
60   Foo( ROOK,       rook );
61   Foo( PRO_PAWN,   pro_pawn );
62   Foo( PRO_LANCE,  pro_lance );
63   Foo( PRO_KNIGHT, pro_knight );
64   Foo( PRO_SILVER, pro_silver );
65   Foo( HORSE,      horse );
66   Foo( DRAGON,     dragon );
67
68   return key;
69 }
70
71 #undef Foo
72
73
74 /*
75        name    bits  shifts
76 word1  depth     8     56
77        value    16     40
78        move     19     21
79        hand     21      0
80 word2  key      57      7
81        turn      1      6
82        threat    1      5
83        type      2      3
84        age       3      0
85  */
86
87 void
88 hash_store( const tree_t * restrict ptree, int ply, int depth, int turn,
89             int value_type, int value, unsigned int move,
90             unsigned int state_node )
91 {
92   uint64_t word1, word2, hash_word1, hash_word2;
93   unsigned int index, slot;
94   int depth_hash, age_hash;
95
96 #if ! defined(MINIMUM)
97   if ( game_status & flag_learning ) { return; }
98 #endif
99   assert( depth <= 0xff );
100
101   if ( depth < 0 ) { depth = 0; }
102   if ( abs(value) > score_max_eval )
103     {
104       if ( abs(value) > score_mate1ply ) { return; }
105       if ( value > 0 ) { value += ply-1; }
106       else             { value -= ply-1; }
107 #if ! defined(MINIMUM)
108       if ( abs(value) > score_mate1ply )
109         {
110           out_warning( "A stored hash value is out of bounce!" );
111         }
112 #endif
113     }
114   word2 = ( ( HASH_KEY & ~(uint64_t)0x7fU )
115             | (uint64_t)( (turn<<6) | ( state_node & node_mate_threat )
116                           | (value_type<<3) | trans_table_age ) );
117   word1 = ( ( (uint64_t)( depth<<16 | (value+32768) ) << 40 )
118             | ( (uint64_t)( move & 0x7ffffU ) << 21 )
119             | HAND_B );
120
121   index = (unsigned int)HASH_KEY & hash_mask;
122   hash_word1 = ptrans_table[index].prefer.word1;
123   hash_word2 = ptrans_table[index].prefer.word2;
124   SignKey( hash_word2, hash_word1 );
125   age_hash   = (int)((unsigned int)(hash_word2    ) & 0x07U);
126   depth_hash = (int)((unsigned int)(hash_word1>>56) & 0xffU);
127
128   SignKey( word2, word1 );
129
130   if ( age_hash != trans_table_age || depth_hash <= depth )
131     {
132       ptrans_table[index].prefer.word1 = word1;
133       ptrans_table[index].prefer.word2 = word2;
134     }
135   else {
136     slot = (unsigned int)HASH_KEY >> 31;
137     ptrans_table[index].always[slot].word1 = word1;
138     ptrans_table[index].always[slot].word2 = word2;
139   }
140 }
141
142
143 void
144 hash_store_pv( const tree_t * restrict ptree, unsigned int move, int turn )
145 {
146   uint64_t key_turn_pv, word1, word2;
147   unsigned int index;
148
149   key_turn_pv = ( HASH_KEY & ~(uint64_t)0x7fU ) | (unsigned int)( turn << 6 );
150   index       = (unsigned int)HASH_KEY & hash_mask;
151
152   word1 = ptrans_table[index].prefer.word1;
153   word2 = ptrans_table[index].prefer.word2;
154   SignKey( word2, word1 );
155
156   if ( ( (unsigned int)word1 & 0x1fffffU ) == HAND_B
157        && ( word2 & ~(uint64_t)0x3fU ) == key_turn_pv )
158     {
159       if ( ( (unsigned int)(word1>>21) & 0x7ffffU ) != ( move & 0x7ffffU ) )
160         {
161           word1 &= ~((uint64_t)0x7ffffU << 21);
162           word1 |= (uint64_t)( move & 0x7ffffU ) << 21;
163           word2 &= ~((uint64_t)0x3U << 3);
164           SignKey( word2, word1 );
165           ptrans_table[index].prefer.word1 = word1;
166           ptrans_table[index].prefer.word2 = word2;
167         }
168     }
169   else {
170     unsigned int slot;
171
172     slot = (unsigned int)HASH_KEY >> 31;
173     word1 = ptrans_table[index].always[slot].word1;
174     word2 = ptrans_table[index].always[slot].word2;
175     SignKey( word2, word1 );
176     if ( ( (unsigned int)word1 & 0x1fffffU ) == HAND_B
177          && ( word2 & ~(uint64_t)0x3fU ) == key_turn_pv )
178       {
179         if ( ( (unsigned int)(word1>>21) & 0x7ffffU )
180              != ( move & 0x7ffffU ) )
181           {
182             word1 &= ~((uint64_t)0x7ffffU << 21);
183             word1 |= (uint64_t)( move & 0x7ffffU ) << 21;
184             word2 &= ~((uint64_t)0x3U << 3);
185             SignKey( word2, word1 );
186             ptrans_table[index].always[slot].word1 = word1;
187             ptrans_table[index].always[slot].word2 = word2;
188           }
189       }
190     else {
191       word1  = (uint64_t)32768U << 40;
192       word1 |= (uint64_t)( move & 0x7ffffU ) << 21;
193       word1 |= HAND_B;
194       word2  = key_turn_pv | trans_table_age;
195       SignKey( word2, word1 );
196       ptrans_table[index].prefer.word1 = word1;
197       ptrans_table[index].prefer.word2 = word2;
198     }
199   }
200 }
201
202
203 trans_entry_t
204 hash_learn_store( const tree_t * restrict ptree, int depth, int value,
205                   unsigned int move )
206 {
207   trans_entry_t ret;
208
209   assert( 0 <= depth && depth <= 0xff );
210
211   ret.word2 = ( (HASH_KEY&(~(uint64_t)0x7fU))
212                 | (uint64_t)( (root_turn<<6)
213                               | (value_exact<<3) | trans_table_age ) );
214   ret.word1 = ( ( (uint64_t)( depth<<16 | (value+32768) ) << 40 )
215                 | ( (uint64_t)( move & 0x7ffffU ) << 21 )
216                 | HAND_B );
217
218   return ret;
219 }
220
221
222 int
223 all_hash_learn_store( void )
224 {
225   uint64_t aword[2];
226   unsigned int u32key, unext, u, index;
227
228   if ( pf_hash == NULL ) { return 0; }
229
230   if ( fseek( pf_hash, sizeof(unsigned int), SEEK_SET ) == EOF
231        || fread( &unext, sizeof(unsigned int), 1, pf_hash ) != 1 )
232     {
233       str_error = str_io_error;
234       return -2;
235     }
236   if ( ++unext == 0x10000U ) { unext = 0x1U; }
237   if ( fseek( pf_hash, (long)( 20U * unext ), SEEK_SET ) == EOF )
238     {
239       str_error = str_io_error;
240       return -2;
241     }
242   for ( u = 0;; u++ )
243     {
244       if ( fread( &u32key, sizeof(unsigned int), 1, pf_hash ) != 1
245            || fread( aword, sizeof(uint64_t), 2, pf_hash ) != 2 )
246         {
247           str_error = str_io_error;
248           return -2;
249         }
250       index = u32key & hash_mask;
251       aword[1] |= (uint64_t)trans_table_age;
252       SignKey( aword[1], aword[0] );
253       ptrans_table[index].prefer.word1 = aword[0];
254       ptrans_table[index].prefer.word2 = aword[1];
255       if ( u == 0xfffeU ) { break; }
256       if ( ++unext == 0x10000U )
257         {
258           unext = 0x1U;
259           if ( fseek( pf_hash, 20, SEEK_SET ) == EOF )
260             {
261               str_error = str_io_error;
262               return -2;
263             }
264         }
265     }
266
267   return 1;
268 }
269
270
271 unsigned int
272 hash_probe( tree_t * restrict ptree, int ply, int depth_current,
273             int turn_current, int alpha, int beta, unsigned int state_node )
274 {
275   uint64_t word1, word2, key_current, key_hash;
276   unsigned int hand_hash, move_hash, move_infe, move_supe, slot, utemp;
277   unsigned int state_node_hash, index;
278   int null_depth, value_hash, ifrom;
279   int turn_hash, depth_hash, type_hash, is_superior;
280
281   ptree->ntrans_probe++;
282   move_supe   = 0;
283   move_infe   = 0;
284
285   if ( depth_current < 0 ) { depth_current = 0; }
286   null_depth  = NullDepth( depth_current );
287   if ( null_depth < PLY_INC ) { null_depth = 0; }
288
289   key_current = HASH_KEY & ~(uint64_t)0x7fU;
290
291   index = (unsigned int)HASH_KEY & hash_mask;
292   word1 = ptrans_table[index].prefer.word1;
293   word2 = ptrans_table[index].prefer.word2;
294   SignKey( word2, word1 );
295   key_hash = word2 & ~(uint64_t)0x7fU;
296
297   if ( key_hash == key_current ) {
298
299     ptree->ntrans_prefer_hit++;
300     
301     depth_hash  = (int)((unsigned int)(word1>>56) & 0x00ffU);
302     value_hash  = (int)((unsigned int)(word1>>40) & 0xffffU) - 32768;
303     move_hash   = (unsigned int)(word1>>21) & 0x7ffffU;
304     hand_hash   = (unsigned int)word1 & 0x1fffffU;
305     
306     utemp           = (unsigned int)word2;
307     state_node_hash = utemp & node_mate_threat;
308     turn_hash       = (int)((utemp>>6) & 0x1U);
309     type_hash       = (int)((utemp>>3) & 0x3U);
310     
311     if ( abs(value_hash) > score_max_eval )
312       {
313         if ( value_hash > 0 ) { value_hash -= ply-1; }
314         else                  { value_hash += ply-1; }
315 #if ! defined(MINIMUM)
316         if ( abs(value_hash) > score_mate1ply )
317           {
318             out_warning( "Hash value is out of bounce!!" );
319           }
320 #endif
321       }
322     
323     if ( move_hash )
324       {
325         move_hash |= turn_current ? Cap2Move( BOARD[I2To(move_hash)])
326                                   : Cap2Move(-BOARD[I2To(move_hash)]);
327       }
328
329     if ( turn_hash == turn_current && hand_hash == HAND_B ) {
330
331       assert( ! move_hash || is_move_valid( ptree, move_hash, turn_current ) );
332       ptree->amove_hash[ply] = move_hash;
333
334       if ( type_hash == value_lower
335            && value_hash >= beta
336            && ( depth_hash >= depth_current || value_hash > score_max_eval ) )
337         {
338           HASH_VALUE = value_hash;
339           ptree->ntrans_lower++;
340           return value_lower;
341         }
342
343       if ( type_hash == value_upper
344            && value_hash <= alpha
345            && ( depth_hash >= depth_current || value_hash < -score_max_eval ) )
346         {
347           HASH_VALUE = value_hash;
348           ptree->ntrans_upper++;
349           return value_upper;
350         }
351
352       if ( type_hash == value_exact
353            && ( depth_hash >= depth_current
354                 || abs(value_hash) > score_max_eval ) )
355         {
356           HASH_VALUE = value_hash;
357           ptree->ntrans_upper++;
358           return value_exact;
359         }
360
361       if ( ( type_hash & flag_value_low_exact )
362            && ! ptree->nsuc_check[ply]
363            && ! ptree->nsuc_check[ply-1]
364            && ( ( depth_current < 2*PLY_INC
365                   && beta+EFUTIL_MG1 <= value_hash )
366                 || ( depth_current < 3*PLY_INC
367                      && beta+EFUTIL_MG2 <= value_hash ) ) )
368         {
369           HASH_VALUE = beta;
370           ptree->ntrans_lower++;
371           return value_lower;
372         }
373
374       state_node |= state_node_hash;
375       
376       if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate; }
377
378       if ( ( type_hash & flag_value_up_exact )
379            && value_hash < beta
380            && null_depth <= depth_hash )
381         {
382           state_node &= ~node_do_null;
383         }
384
385     } else {
386
387       is_superior = eval_supe( HAND_B, hand_hash, turn_current, turn_hash,
388                                &value_hash, &type_hash );
389
390       if ( is_superior == 1 ) {
391
392         if ( turn_hash == turn_current ) { move_supe = move_hash; }
393
394         if ( type_hash & flag_value_low_exact )
395           {
396             if ( ! ptree->nsuc_check[ply]
397                  && ! ptree->nsuc_check[ply-1]
398                  && ( ( depth_current < 2*PLY_INC
399                         && beta+EFUTIL_MG1 <= value_hash )
400                       || ( depth_current < 3*PLY_INC
401                            && beta+EFUTIL_MG2 <= value_hash ) ) )
402               {
403                 HASH_VALUE = beta;
404                 ptree->ntrans_lower++;
405                 return value_lower;
406               }
407             
408             if ( beta <= value_hash
409                  && ( depth_current <= depth_hash
410                       || score_max_eval < value_hash
411                       || ( turn_current != turn_hash
412                            && depth_hash >= null_depth
413                            && ( state_node & node_do_null ) ) ) )
414               {
415                 HASH_VALUE = value_hash;
416                 ptree->ntrans_superior_hit++;
417                 return value_lower;
418               }
419           }
420
421       } else {
422
423         if ( turn_hash == turn_current ) { move_infe = move_hash; }
424
425         if ( is_superior == -1 ) {
426
427           state_node |= state_node_hash;
428
429           if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate; }
430
431           if ( type_hash & flag_value_up_exact )
432             {
433               if ( value_hash <= alpha
434                    && ( depth_current <= depth_hash
435                         || value_hash < -score_max_eval ) )
436                 {
437                   HASH_VALUE = value_hash;
438                   ptree->ntrans_inferior_hit++;
439                   return value_upper;
440                 }
441               if ( value_hash < beta && null_depth <= depth_hash )
442                 {
443                   state_node &= ~node_do_null;
444                 }
445             }
446         }
447       }
448     }
449   }
450   
451   slot  = (unsigned int)HASH_KEY >> 31;
452   word1 = ptrans_table[index].always[slot].word1;
453   word2 = ptrans_table[index].always[slot].word2;
454   
455   SignKey( word2, word1 );
456   key_hash = word2 & ~(uint64_t)0x7fU;
457   
458   if ( key_hash == key_current ) {
459
460     ptree->ntrans_always_hit++;
461
462     depth_hash  = (int)((unsigned int)(word1>>56) & 0x00ffU);
463     value_hash  = (int)((unsigned int)(word1>>40) & 0xffffU) - 32768;
464     move_hash   = (unsigned int)(word1>>21) & 0x7ffffU;
465     hand_hash   = (unsigned int)word1 & 0x1fffffU;
466     
467     utemp           = (unsigned int)word2;
468     state_node_hash = utemp & node_mate_threat;
469     turn_hash       = (int)((utemp>>6) & 0x1U);
470     type_hash       = (int)((utemp>>3) & 0x3U);
471     
472     if ( abs(value_hash) > score_max_eval )
473       {
474         if ( value_hash > 0 ) { value_hash -= ply-1; }
475         else                  { value_hash += ply-1; }
476 #if ! defined(MINIMUM)
477         if ( abs(value_hash) > score_mate1ply )
478           {
479             out_warning( "Hash value is out of bounce!!" );
480           }
481 #endif
482       }
483     
484     if ( move_hash )
485       {
486         move_hash |= turn_current ? Cap2Move( BOARD[I2To(move_hash)])
487                                   : Cap2Move(-BOARD[I2To(move_hash)]);
488       }
489
490     if ( turn_hash == turn_current && hand_hash == HAND_B ) {
491       
492       if ( ! ptree->amove_hash[ply] )
493         {
494           assert( ! move_hash
495                   || is_move_valid( ptree, move_hash, turn_current ) );
496           ptree->amove_hash[ply] = move_hash;
497         }
498
499       if ( type_hash == value_lower
500            && value_hash >= beta
501            && ( depth_hash >= depth_current || value_hash > score_max_eval ) )
502         {
503           HASH_VALUE = value_hash;
504           ptree->ntrans_lower++;
505           return value_lower;
506         }
507
508       if ( type_hash == value_upper
509            && value_hash <= alpha
510            && ( depth_hash >= depth_current || value_hash < -score_max_eval ) )
511         {
512           HASH_VALUE = value_hash;
513           ptree->ntrans_upper++;
514           return value_upper;
515         }
516
517       if ( type_hash == value_exact
518            && ( depth_hash >= depth_current
519                 || abs(value_hash) > score_max_eval ) )
520         {
521           HASH_VALUE = value_hash;
522           ptree->ntrans_upper++;
523           return value_exact;
524         }
525
526
527       if ( ( type_hash & flag_value_low_exact )
528            && ! ptree->nsuc_check[ply]
529            && ! ptree->nsuc_check[ply-1]
530            && ( ( depth_current < 2*PLY_INC
531                   && beta+EFUTIL_MG1 <= value_hash )
532                 || ( depth_current < 3*PLY_INC
533                      && beta+EFUTIL_MG2 <= value_hash ) ) )
534         {
535           HASH_VALUE = beta;
536           ptree->ntrans_lower++;
537           return value_lower;
538         }
539
540       state_node |= state_node_hash;
541
542       if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate; }
543       
544       if ( ( type_hash & flag_value_up_exact )
545            && value_hash < beta
546            && null_depth <= depth_hash )
547         {
548           state_node &= ~node_do_null;
549         }
550
551     } else {
552
553         is_superior = eval_supe( HAND_B, hand_hash, turn_current, turn_hash,
554                                  &value_hash, &type_hash );
555
556         if ( is_superior == 1 ) {
557
558           if ( ( turn_hash == turn_current ) && ! move_supe )
559             {
560               move_supe = move_hash;
561             }
562           
563           if ( type_hash & flag_value_low_exact )
564             {
565               if ( ! ptree->nsuc_check[ply]
566                    && ! ptree->nsuc_check[ply-1]
567                    && ( ( depth_current < 2*PLY_INC
568                           && beta+EFUTIL_MG1 <= value_hash )
569                         || ( depth_current < 3*PLY_INC
570                              && beta+EFUTIL_MG2 <= value_hash ) ) )
571                 {
572                   HASH_VALUE = beta;
573                   ptree->ntrans_lower++;
574                   return value_lower;
575                 }
576               
577               if ( value_hash >= beta
578                    && ( depth_hash >= depth_current
579                         || score_max_eval < value_hash
580                         || ( turn_current != turn_hash
581                              && depth_hash >= null_depth
582                              && ( state_node & node_do_null ) ) ) )
583                 {
584                   HASH_VALUE = value_hash;
585                   ptree->ntrans_superior_hit++;
586                   return value_lower;
587                 }
588             }
589
590         } else {
591
592           if ( ! move_infe && turn_hash == turn_current )
593             {
594               move_infe = move_hash;
595             }
596
597           if ( is_superior == -1 ) {
598
599             state_node |= state_node_hash;
600             
601             if ( value_hash <= score_max_eval ) { state_node &= ~node_do_mate;}
602
603             if ( type_hash & flag_value_up_exact )
604               {
605                 if ( value_hash <= alpha
606                      && ( depth_hash >= depth_current
607                           || value_hash < -score_max_eval ) )
608                   {
609                     HASH_VALUE = value_hash;
610                     ptree->ntrans_inferior_hit++;
611                     return value_upper;
612                   }
613                 if ( value_hash < beta && null_depth <= depth_hash )
614                   {
615                     state_node &= ~node_do_null;
616                   }
617               }
618           }
619         }
620     }
621   }
622   
623   if ( ! ptree->amove_hash[ply] )
624     {
625       if ( move_supe )
626         {
627           ifrom = (int)I2From(move_supe);
628           if ( ifrom >= nsquare )
629             {
630               unsigned int hand = turn_current ? HAND_W : HAND_B;
631               switch( From2Drop(ifrom) )
632                 {
633                 case pawn:
634                   if ( ! IsHandPawn(hand) ) {
635                     move_supe = To2Move(I2To(move_supe));
636                     if ( IsHandLance(hand) )
637                       {
638                         move_supe |= Drop2Move(lance);
639                       }
640                     else if ( IsHandSilver(hand))
641                       {
642                         move_supe |= Drop2Move(silver);
643                       }
644                     else if ( IsHandGold(hand) )
645                       {
646                         move_supe |= Drop2Move(gold);
647                       }
648                     else { move_supe |= Drop2Move(rook); }
649                   }
650                   break;
651                 
652                 case lance:
653                   if ( ! IsHandLance(hand) )
654                     {
655                       move_supe = To2Move(I2To(move_supe)) | Drop2Move(rook);
656                     }
657                   break;
658                 }
659             }
660
661           assert( is_move_valid( ptree, move_supe, turn_current ) );
662           ptree->amove_hash[ply] = move_supe;
663         }
664       else if ( move_infe )
665         {
666           ifrom = (int)I2From(move_infe);
667           if ( ifrom >= nsquare )
668             {
669               unsigned int hand = turn_current ? HAND_W : HAND_B;
670               switch( From2Drop(ifrom) )
671                 {
672                 case pawn:   if ( ! IsHandPawn(hand) )   { goto esc; } break;
673                 case lance:  if ( ! IsHandLance(hand) )  { goto esc; } break;
674                 case knight: if ( ! IsHandKnight(hand) ) { goto esc; } break;
675                 case silver: if ( ! IsHandSilver(hand) ) { goto esc; } break;
676                 case gold:   if ( ! IsHandGold(hand) )   { goto esc; } break;
677                 case bishop: if ( ! IsHandBishop(hand) ) { goto esc; } break;
678                 case rook:   if ( ! IsHandRook(hand) )   { goto esc; } break;
679                 }
680             }
681           assert( is_move_valid( ptree, move_infe, turn_current ) );
682           ptree->amove_hash[ply] = move_infe;
683         }
684     }
685   
686  esc:
687   return state_node;
688 }
689
690
691 int
692 hash_learn_on( void )
693 {
694   int iret = file_close( pf_hash );
695   if ( iret < 0 ) { return iret; }
696
697   pf_hash = file_open( str_hash, "rb+" );
698   if ( pf_hash == NULL ) { return -2; }
699
700   return 1;
701 }
702
703
704 int
705 hash_learn_off( void )
706 {
707   int iret = file_close( pf_hash );
708   if ( iret < 0 ) { return iret; }
709
710   pf_hash = NULL;
711
712   return 1;
713 }
714
715 #if !defined(MINIMUM)
716 int
717 hash_learn_create( void )
718 {
719   uint64_t au64[2];
720   unsigned int u;
721   int iret, i;
722
723   iret = hash_learn_off();
724   if ( iret < 0 ) { return iret; }
725
726   pf_hash = file_open( str_hash, "wb" );
727   if ( pf_hash == NULL ) { return -2; }
728
729   for ( i = 0; i < 5; i++ )
730     {
731       u = 0;
732       if ( fwrite( &u, sizeof(unsigned int), 1, pf_hash ) != 1 )
733         {
734           str_error = str_io_error;
735           return -2;
736         }
737     }
738
739   u = 0;
740   au64[0] = au64[1] = 0;
741   for ( i = 1; i < 0x10000; i++ )
742     if ( fwrite( &u, sizeof(unsigned int), 1, pf_hash ) != 1
743          || fwrite( au64, sizeof(uint64_t), 2, pf_hash ) != 2 )
744       {
745         str_error = str_io_error;
746         return -2;
747       }
748
749   return hash_learn_on();
750 }
751 #endif
752
753 int
754 hash_learn( const tree_t * restrict ptree, unsigned int move, int value,
755             int depth )
756 {
757   trans_entry_t trans_entry;
758   unsigned int unum, unext, u;
759   int pre_value, ply;
760
761   ply = record_game.moves;
762   if ( ply >= HASH_REG_HIST_LEN )    { return 1; }
763   if ( pf_hash == NULL )             { return 1; }
764   if ( abs(value) > score_max_eval ) { return 1; }
765   if ( ply < 2 )                     { return 1; }
766   if ( depth < 2 )                   { return 1; }
767
768   if ( history_book_learn[ply].key_probed == (unsigned int)HASH_KEY
769        && history_book_learn[ply].hand_probed == HAND_B
770        && history_book_learn[ply].move_probed == move ) { return 1; }
771
772   if ( history_book_learn[ply-2].key_responsible
773        != history_book_learn[ply-2].key_played ) { return 1; }
774   if ( history_book_learn[ply-2].hand_responsible
775        != history_book_learn[ply-2].hand_played ) { return 1; }
776   if ( history_book_learn[ply-2].move_responsible
777        != history_book_learn[ply-2].move_played ) { return 1; }
778
779   if ( ( history_book_learn[ply-2].key_probed
780          == history_book_learn[ply-2].key_played )
781        && ( history_book_learn[ply-2].hand_probed
782             == history_book_learn[ply-2].hand_played )
783        && ( history_book_learn[ply-2].move_probed
784             == history_book_learn[ply-2].move_played ) ) { return 1; }
785           
786   pre_value = (int)( history_book_learn[ply-2].data & 0xffffU ) - 32768;
787
788   if ( pre_value < value + HASH_REG_MINDIFF ) { return 1; }
789   if ( pre_value < -HASH_REG_THRESHOLD )      { return 1; }
790   if ( pre_value == score_inferior )          { return 1; }
791
792   Out( "save hash value of the position\n\n" );
793   if ( fseek( pf_hash, 0, SEEK_SET ) == EOF
794        || fread( &unum,  sizeof(unsigned int), 1, pf_hash ) != 1
795        || fread( &unext, sizeof(unsigned int), 1, pf_hash ) != 1 )
796     {
797       str_error = str_io_error;
798       return -2;
799     }
800   if ( ++unum  == 0x10000U ) { unum  = 0xffffU; }
801   if ( ++unext == 0x10000U ) { unext = 0x0001U; }
802
803   if ( fseek( pf_hash, 0, SEEK_SET ) == EOF
804        || fwrite( &unum,  sizeof(unsigned int), 1, pf_hash ) != 1
805        || fwrite( &unext, sizeof(unsigned int), 1, pf_hash ) != 1 )
806     {
807       str_error = str_io_error;
808       return -2;
809     }
810   trans_entry
811     = hash_learn_store( ptree, depth * PLY_INC + PLY_INC/2, value, move );
812   u = (unsigned int)HASH_KEY;
813   if ( fseek( pf_hash, (long)( 20 * unext ), SEEK_SET ) == EOF
814        || fwrite( &u, sizeof(unsigned int), 1, pf_hash ) != 1
815        || fwrite( &trans_entry.word1, sizeof(uint64_t), 1, pf_hash ) != 1
816        || fwrite( &trans_entry.word2, sizeof(uint64_t), 1, pf_hash ) != 1
817        || fflush( pf_hash ) == EOF )
818     {
819       str_error = str_io_error;
820       return -2;
821     }
822   
823   return 1;
824 }
825
826
827 static int
828 eval_supe( unsigned int hand_current, unsigned int hand_hash,
829            int turn_current, int turn_hash,
830            int * restrict pvalue_hash, int * restrict ptype_hash )
831 {
832   int is_superior;
833
834   if ( hand_current == hand_hash ) { is_superior = 0; }
835   else if ( is_hand_eq_supe( hand_current, hand_hash ) )
836     {
837       is_superior = turn_current ? -1 : 1;
838     }
839   else if ( is_hand_eq_supe( hand_hash, hand_current ) )
840     {
841       is_superior = turn_current ? 1 : -1;
842     }
843   else { return 0; }
844   
845   if ( turn_hash != turn_current )
846     {
847       if ( is_superior == -1 ) { is_superior = 0; }
848       else {
849         is_superior   = 1;
850         *pvalue_hash *= -1;
851         switch ( *ptype_hash )
852           {
853           case value_lower:  *ptype_hash=value_upper;  break;
854           case value_upper:  *ptype_hash=value_lower;  break;
855           }
856       }
857     }
858
859   return is_superior;
860 }
861
862
863 int
864 clear_trans_table( void )
865 {
866   unsigned int elapsed_start, elapsed_end;
867   int ntrans_table, i;
868
869   if ( get_elapsed( &elapsed_start ) < 0 ) { return -1; }
870
871   Out( "cleanning the transposition table ..." );
872   
873   trans_table_age = 1;
874   ntrans_table = 1 << log2_ntrans_table;
875   for ( i = 0; i < ntrans_table; i++ )
876     {
877       ptrans_table[i].prefer.word1    = 0;
878       ptrans_table[i].prefer.word2    = 0;
879       ptrans_table[i].always[0].word1 = 0;
880       ptrans_table[i].always[0].word2 = 0;
881       ptrans_table[i].always[1].word1 = 0;
882       ptrans_table[i].always[1].word2 = 0;
883     }
884
885   if ( get_elapsed( &elapsed_end ) < 0 ) { return -1; }
886   Out( " done (%ss)\n", str_time_symple( elapsed_end - elapsed_start ) );
887
888   return 1;
889 }
890
891
892 void
893 add_rejections_root( tree_t * restrict ptree, unsigned int move_made )
894 {
895   uint64_t hash_value;
896   unsigned int * restrict pmove;
897   unsigned int *pmove_last;
898   unsigned int hash_key, hand_ply_turn;
899   int tt;
900   unsigned char hash_parent;
901
902   tt = Flip( root_turn );
903   UnMakeMove( tt, move_made, 1 );
904   hash_parent = (unsigned char)(HASH_KEY >> 32);
905
906   pmove      = ptree->amove;
907   pmove_last = GenCaptures( tt, pmove );
908   pmove_last = GenNoCaptures( tt, pmove_last );
909   pmove_last = GenCapNoProEx2( tt, pmove_last );
910   pmove_last = GenNoCapNoProEx2( tt, pmove_last );
911   pmove_last = GenDrop( tt, pmove_last );
912
913   while ( pmove != pmove_last )
914     {
915       if ( *pmove != move_made )
916         {
917           MakeMove( tt, *pmove, 1 );
918           if ( ! InCheck( tt ) )
919             {
920               hash_key      = (unsigned int)HASH_KEY & REJEC_MASK;
921               hand_ply_turn = ( HAND_B << 6 ) | 2U | (unsigned int)tt;
922               hash_value    = ( ( HASH_KEY & ~(uint64_t)0x7ffffffU )
923                                 | (uint64_t)hand_ply_turn );
924               hash_rejections[hash_key].root   = hash_value;
925               hash_rejections_parent[hash_key] = hash_parent;
926             }      
927           UnMakeMove( tt, *pmove, 1 );
928         }
929       pmove++;
930     }
931
932   MakeMove( tt, move_made, 1 );
933 }
934
935
936 void
937 sub_rejections_root( tree_t * restrict ptree, unsigned int move_made )
938 {
939   unsigned int * restrict pmove;
940   unsigned int *pmove_last;
941   unsigned int hash_key;
942
943   pmove      = ptree->amove;
944   pmove_last = GenCaptures( root_turn, pmove );
945   pmove_last = GenNoCaptures( root_turn, pmove_last );
946   pmove_last = GenCapNoProEx2( root_turn, pmove_last );
947   pmove_last = GenNoCapNoProEx2( root_turn, pmove_last );
948   pmove_last = GenDrop( root_turn, pmove_last );
949
950   while ( pmove != pmove_last )
951     {
952       if ( *pmove != move_made )
953         {
954           MakeMove( root_turn, *pmove, 1 );
955           if ( ! InCheck( root_turn ) )
956             {
957               hash_key = (unsigned int)HASH_KEY & REJEC_MASK;
958
959               hash_rejections[hash_key].root   = 0;
960               hash_rejections_parent[hash_key] = 0;
961             }      
962           UnMakeMove( root_turn, *pmove, 1 );
963         }
964       pmove++;
965     }
966 }
967
968
969 void
970 add_rejections( tree_t * restrict ptree, int turn, int ply )
971 {
972   uint64_t hash_value;
973   unsigned int * restrict pmove;
974   unsigned int * restrict pmove_last;
975   unsigned int hash_key, hand_ply_turn;
976
977 #if ! defined(MINIMUM)
978   if ( game_status & flag_learning ) { return; }
979 #endif
980
981   pmove      = ptree->move_last[ply-1];
982   pmove_last = GenCaptures( turn, pmove );
983   pmove_last = GenNoCaptures( turn, pmove_last );
984   pmove_last = GenCapNoProEx2( turn, pmove_last );
985   pmove_last = GenNoCapNoProEx2( turn, pmove_last );
986   pmove_last = GenDrop( turn, pmove_last );
987
988   while ( pmove != pmove_last )
989     {
990       MakeMove( turn, *pmove, ply );
991       if ( ! InCheck( turn ) )
992         {
993           hash_key = (unsigned int)HASH_KEY & REJEC_MASK;
994           if ( ! (unsigned int)hash_rejections[hash_key].sibling )
995             {
996               hand_ply_turn = ( ( HAND_B << 6 ) | ( (unsigned int)ply << 1 )
997                                 | (unsigned int)turn );
998               hash_value    = ( ( HASH_KEY & ~(uint64_t)0x7ffffffU )
999                                 | (uint64_t)hand_ply_turn );
1000               hash_rejections[hash_key].sibling = hash_value;
1001 #if defined(TLP)
1002               tlp_rejections_slot[hash_key] = (unsigned short)
1003                 ( ptree->tlp_slot ^ (unsigned short)( hash_value >> 32 ) );
1004 #endif
1005             }
1006         }
1007       UnMakeMove( turn, *pmove, ply );
1008       pmove++;
1009     }
1010 }
1011
1012
1013 void
1014 sub_rejections( tree_t * restrict ptree, int turn, int ply )
1015 {
1016   uint64_t hash_value;
1017   unsigned int * restrict pmove;
1018   unsigned int * restrict pmove_last;
1019   unsigned int hash_key, hand_ply_turn;
1020
1021 #if ! defined(MINIMUM)
1022   if ( game_status & flag_learning ) { return; }
1023 #endif
1024
1025   pmove      = ptree->move_last[ply-1];
1026   pmove_last = GenCaptures( turn, pmove );
1027   pmove_last = GenNoCaptures( turn, pmove_last );
1028   pmove_last = GenCapNoProEx2( turn, pmove_last );
1029   pmove_last = GenNoCapNoProEx2( turn, pmove_last );
1030   pmove_last = GenDrop( turn, pmove_last );
1031
1032   while ( pmove != pmove_last )
1033     {
1034       MakeMove( turn, *pmove, ply );
1035       if ( ! InCheck( turn ) )
1036         {
1037           hash_key      = (unsigned int)HASH_KEY & REJEC_MASK;
1038           hand_ply_turn = ( ( HAND_B << 6 )
1039                             | ( (unsigned int)ply << 1 )
1040                             | (unsigned int)turn );
1041           hash_value    = ( ( HASH_KEY & ~(uint64_t)0x7ffffffU )
1042                             | (uint64_t)hand_ply_turn );
1043           
1044           if ( hash_rejections[hash_key].sibling == hash_value )
1045             {
1046               hash_rejections[hash_key].sibling = 0;
1047             }
1048         }
1049       UnMakeMove( turn, *pmove, ply );
1050       pmove++;
1051     }
1052 }
1053
1054
1055 int
1056 rejections_probe( tree_t * restrict ptree, int turn, int ply )
1057 {
1058   uint64_t value_turn, value_turn_current, value;
1059   unsigned int hand_hash, hand_current, key_current;
1060   int nrep, value_ply;
1061   unsigned char parent_hash, parent_current;
1062
1063   turn               = Flip(turn);
1064   hand_current       = HAND_B;
1065   key_current        = (unsigned int)HASH_KEY & REJEC_MASK;
1066   value_turn_current = ( HASH_KEY & ~(uint64_t)0x7ffffffU ) | (uint64_t)turn;
1067
1068   value = hash_rejections[key_current].root;
1069   value_turn = value & ~(uint64_t)0x7fffffeU;
1070   if ( value_turn == value_turn_current )
1071     {
1072       hand_hash = ( (unsigned int)value & 0x7ffffffU ) >> 6;
1073       if ( ( turn && is_hand_eq_supe( hand_current, hand_hash ) )
1074            || ( ! turn && is_hand_eq_supe( hand_hash, hand_current ) ) )
1075         {
1076           nrep = root_nrep + ply - 2;
1077           parent_current = (unsigned char)(ptree->rep_board_list[nrep] >> 32);
1078           parent_hash    = hash_rejections_parent[key_current];
1079           if ( parent_hash != parent_current ) { return 1; }
1080         }
1081     }
1082
1083   value = hash_rejections[key_current].sibling;
1084   value_ply = ( (int)value & 0x3eU ) >> 1;
1085   if ( value_ply + 2 < ply )
1086     {
1087       value_turn = value & ~(uint64_t)0x7fffffeU;
1088       if ( value_turn == value_turn_current )
1089         {
1090           hand_hash = ( (unsigned int)value & 0x7ffffffU ) >> 6;
1091           if ( ( turn && is_hand_eq_supe( hand_current, hand_hash ) )
1092                || ( ! turn && is_hand_eq_supe( hand_hash, hand_current ) ) )
1093             {
1094 #if defined(TLP)
1095               int slot_hash;
1096               slot_hash = (int)( tlp_rejections_slot[key_current]
1097                                  ^ (unsigned short)( value >> 32 ) );
1098               if ( tlp_is_descendant( ptree, slot_hash ) )
1099                 
1100 #endif
1101                 return 1;
1102             }
1103         }
1104     }
1105
1106   return 0;
1107 }