Check in Bonanza Feliz 0.0
[bonanza.git] / utility.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 #include <limits.h>
7 #include "shogi.h"
8
9
10 int
11 ini_game( tree_t * restrict ptree, const min_posi_t *pmin_posi, int flag,
12           const char *str_name1, const char *str_name2 )
13 {
14   bitboard_t bb;
15   int piece;
16   int sq, iret;
17
18   if ( flag & flag_history )
19     {
20       iret = open_history( str_name1, str_name2 );
21       if ( iret < 0 ) { return iret; }
22     }
23
24   if ( ! ( flag & flag_nofmargin ) )
25     {
26       fmg_misc      = FMG_MISC;
27       fmg_cap       = FMG_CAP;
28       fmg_drop      = FMG_DROP;
29       fmg_mt        = FMG_MT;
30       fmg_misc_king = FMG_MISC_KING;
31       fmg_cap_king  = FMG_CAP_KING;
32     }
33
34   memcpy( ptree->posi.asquare, pmin_posi->asquare, nsquare );
35   ptree->move_last[0]  = ptree->amove;
36   ptree->nsuc_check[0] = 0;
37   ptree->nsuc_check[1] = 0;
38   root_nrep            = 0;
39   root_turn            = pmin_posi->turn_to_move;
40   HAND_B               = pmin_posi->hand_black;
41   HAND_W               = pmin_posi->hand_white;
42   MATERIAL             = 0;
43
44   BBIni( BB_BOCCUPY );
45   BBIni( BB_BPAWN );
46   BBIni( BB_BLANCE );
47   BBIni( BB_BKNIGHT );
48   BBIni( BB_BSILVER );
49   BBIni( BB_BGOLD );
50   BBIni( BB_BBISHOP );
51   BBIni( BB_BROOK );
52   BBIni( BB_BPRO_PAWN );
53   BBIni( BB_BPRO_LANCE );
54   BBIni( BB_BPRO_KNIGHT );
55   BBIni( BB_BPRO_SILVER );
56   BBIni( BB_BHORSE );
57   BBIni( BB_BDRAGON );
58   BBIni( BB_BTGOLD );
59   BBIni( BB_WOCCUPY );
60   BBIni( BB_WPAWN );
61   BBIni( BB_WLANCE );
62   BBIni( BB_WKNIGHT );
63   BBIni( BB_WSILVER );
64   BBIni( BB_WGOLD );
65   BBIni( BB_WBISHOP );
66   BBIni( BB_WROOK );
67   BBIni( BB_WPRO_PAWN );
68   BBIni( BB_WPRO_LANCE );
69   BBIni( BB_WPRO_KNIGHT );
70   BBIni( BB_WPRO_SILVER );
71   BBIni( BB_WHORSE );
72   BBIni( BB_WDRAGON );
73   BBIni( BB_WTGOLD );
74   BBIni( OCCUPIED_FILE );
75   BBIni( OCCUPIED_DIAG1 );
76   BBIni( OCCUPIED_DIAG2 );
77
78   for ( sq = 0; sq < nsquare; sq++ ) {
79     piece = BOARD[sq];
80     if ( piece > 0 ) {
81       Xor( sq, BB_BOCCUPY );
82       XorFile( sq, OCCUPIED_FILE );
83       XorDiag1( sq, OCCUPIED_DIAG1 );
84       XorDiag2( sq, OCCUPIED_DIAG2 );
85       switch ( piece )
86         {
87         case pawn:        Xor( sq, BB_BPAWN );        break;
88         case lance:       Xor( sq, BB_BLANCE );       break;
89         case knight:      Xor( sq, BB_BKNIGHT );      break;
90         case silver:      Xor( sq, BB_BSILVER );      break;
91         case rook:        Xor( sq, BB_BROOK );        break;
92         case bishop:      Xor( sq, BB_BBISHOP );      break;
93         case king:        SQ_BKING = (char)sq;        break;
94         case dragon:      Xor( sq, BB_BDRAGON );      break;
95         case horse:       Xor( sq, BB_BHORSE );       break;
96         case gold:        Xor( sq, BB_BGOLD );        break;
97         case pro_pawn:    Xor( sq, BB_BPRO_PAWN );    break;
98         case pro_lance:   Xor( sq, BB_BPRO_LANCE );   break;
99         case pro_knight:  Xor( sq, BB_BPRO_KNIGHT );  break;
100         case pro_silver:  Xor( sq, BB_BPRO_SILVER );  break;
101         }
102     }
103     else if ( piece < 0 ) {
104       Xor( sq, BB_WOCCUPY );
105       XorFile( sq, OCCUPIED_FILE );
106       XorDiag1( sq, OCCUPIED_DIAG1 );
107       XorDiag2( sq, OCCUPIED_DIAG2 );
108       switch ( - piece )
109         {
110         case pawn:        Xor( sq, BB_WPAWN );        break;
111         case lance:       Xor( sq, BB_WLANCE );       break;
112         case knight:      Xor( sq, BB_WKNIGHT );      break;
113         case silver:      Xor( sq, BB_WSILVER );      break;
114         case rook:        Xor( sq, BB_WROOK );        break;
115         case bishop:      Xor( sq, BB_WBISHOP );      break;
116         case king:        SQ_WKING = (char)sq;        break;
117         case dragon:      Xor( sq, BB_WDRAGON );      break;
118         case horse:       Xor( sq, BB_WHORSE );       break;
119         case gold:        Xor( sq, BB_WGOLD );        break;
120         case pro_pawn:    Xor( sq, BB_WPRO_PAWN );    break;
121         case pro_lance:   Xor( sq, BB_WPRO_LANCE );   break;
122         case pro_knight:  Xor( sq, BB_WPRO_KNIGHT );  break;
123         case pro_silver:  Xor( sq, BB_WPRO_SILVER );  break;
124         }
125     }
126   }
127
128   BBOr( BB_BTGOLD, BB_BPRO_PAWN,   BB_BGOLD );
129   BBOr( BB_BTGOLD, BB_BPRO_LANCE,  BB_BTGOLD );
130   BBOr( BB_BTGOLD, BB_BPRO_KNIGHT, BB_BTGOLD );
131   BBOr( BB_BTGOLD, BB_BPRO_SILVER, BB_BTGOLD );
132   BBOr( BB_B_HDK,  BB_BHORSE,      BB_BDRAGON );
133   BBOr( BB_B_HDK,  BB_BKING,       BB_B_HDK );
134   BBOr( BB_B_BH,   BB_BBISHOP,     BB_BHORSE );
135   BBOr( BB_B_RD,   BB_BROOK,       BB_BDRAGON );
136
137   BBOr( BB_WTGOLD, BB_WPRO_PAWN,   BB_WGOLD );
138   BBOr( BB_WTGOLD, BB_WPRO_LANCE,  BB_WTGOLD );
139   BBOr( BB_WTGOLD, BB_WPRO_KNIGHT, BB_WTGOLD );
140   BBOr( BB_WTGOLD, BB_WPRO_SILVER, BB_WTGOLD );
141   BBOr( BB_W_HDK,  BB_WHORSE,      BB_WDRAGON );
142   BBOr( BB_W_HDK,  BB_WKING,       BB_W_HDK );
143   BBOr( BB_W_BH,   BB_WBISHOP,     BB_WHORSE );
144   BBOr( BB_W_RD,   BB_WROOK,       BB_WDRAGON );
145
146   BB_BPAWN_ATK.p[0]  = ( BB_BPAWN.p[0] <<  9 ) & 0x7ffffffU;
147   BB_BPAWN_ATK.p[0] |= ( BB_BPAWN.p[1] >> 18 ) & 0x00001ffU;
148   BB_BPAWN_ATK.p[1]  = ( BB_BPAWN.p[1] <<  9 ) & 0x7ffffffU;
149   BB_BPAWN_ATK.p[1] |= ( BB_BPAWN.p[2] >> 18 ) & 0x00001ffU;
150   BB_BPAWN_ATK.p[2]  = ( BB_BPAWN.p[2] <<  9 ) & 0x7ffffffU;
151
152   BB_WPAWN_ATK.p[2]  = ( BB_WPAWN.p[2] >>  9 );
153   BB_WPAWN_ATK.p[2] |= ( BB_WPAWN.p[1] << 18 ) & 0x7fc0000U;
154   BB_WPAWN_ATK.p[1]  = ( BB_WPAWN.p[1] >>  9 );
155   BB_WPAWN_ATK.p[1] |= ( BB_WPAWN.p[0] << 18 ) & 0x7fc0000U;
156   BB_WPAWN_ATK.p[0]  = ( BB_WPAWN.p[0] >>  9 );
157
158   MATERIAL = eval_material( ptree );
159   HASH_KEY = hash_func( ptree );
160
161   memset( ptree->hist_good,       0, sizeof(ptree->hist_good) );
162   memset( ptree->hist_tried,      0, sizeof(ptree->hist_tried) );
163   memset( hash_rejections_parent, 0, sizeof(hash_rejections_parent) );
164   memset( hash_rejections,        0, sizeof(hash_rejections) );
165
166   game_status &= ( flag_quiet | flag_reverse | flag_narrow_book
167                    | flag_time_extendable | flag_learning
168                    | flag_nobeep | flag_nostress | flag_nopeek
169                    | flag_noponder | flag_noprompt );
170
171   sec_b_total     = 0;
172   sec_w_total     = 0;
173   sec_elapsed     = 0;
174   last_root_value = 0;
175   n_nobook_move   = 0;
176   last_pv.depth   = 0;
177   last_pv.length  = 0;
178   last_pv.a[0]    = 0;
179   last_pv.a[1]    = 0;
180
181   if ( InCheck( root_turn ) )
182     {
183       ptree->nsuc_check[1] = 1U;
184       if ( is_mate( ptree, 1 ) ) { game_status |= flag_mated; }
185     }
186
187   BBOr( bb, BB_BPAWN, BB_WPAWN );
188   BBOr( bb, bb, BB_BPRO_PAWN );
189   BBOr( bb, bb, BB_WPRO_PAWN );
190   npawn_box  = npawn_max;
191   npawn_box -= PopuCount( bb );
192   npawn_box -= (int)I2HandPawn(HAND_B);
193   npawn_box -= (int)I2HandPawn(HAND_W);
194
195   BBOr( bb, BB_BLANCE, BB_WLANCE );
196   BBOr( bb, bb, BB_BPRO_LANCE );
197   BBOr( bb, bb, BB_WPRO_LANCE );
198   nlance_box  = nlance_max;
199   nlance_box -= PopuCount( bb );
200   nlance_box -= (int)I2HandLance(HAND_B);
201   nlance_box -= (int)I2HandLance(HAND_W);
202   
203   BBOr( bb, BB_BKNIGHT, BB_WKNIGHT );
204   BBOr( bb, bb, BB_BPRO_KNIGHT );
205   BBOr( bb, bb, BB_WPRO_KNIGHT );
206   nknight_box  = nknight_max;
207   nknight_box -= PopuCount( bb );
208   nknight_box -= (int)I2HandKnight(HAND_B);
209   nknight_box -= (int)I2HandKnight(HAND_W);
210
211   BBOr( bb, BB_BSILVER, BB_WSILVER );
212   BBOr( bb, bb, BB_BPRO_SILVER );
213   BBOr( bb, bb, BB_WPRO_SILVER );
214   nsilver_box  = nsilver_max;
215   nsilver_box -= PopuCount( bb );
216   nsilver_box -= (int)I2HandSilver(HAND_B);
217   nsilver_box -= (int)I2HandSilver(HAND_W);
218
219   BBOr( bb, BB_BGOLD, BB_WGOLD );
220   ngold_box  = ngold_max;
221   ngold_box -= PopuCount( bb );
222   ngold_box -= (int)I2HandGold(HAND_B);
223   ngold_box -= (int)I2HandGold(HAND_W);
224
225   BBOr( bb, BB_BBISHOP, BB_WBISHOP );
226   BBOr( bb, bb, BB_BHORSE );
227   BBOr( bb, bb, BB_WHORSE );
228   nbishop_box  = nbishop_max;
229   nbishop_box -= PopuCount( bb );
230   nbishop_box -= (int)I2HandBishop(HAND_B);
231   nbishop_box -= (int)I2HandBishop(HAND_W);
232
233   BBOr( bb, BB_BROOK, BB_WROOK );
234   BBOr( bb, bb, BB_BDRAGON );
235   BBOr( bb, bb, BB_WDRAGON );
236   nrook_box  = nrook_max;
237   nrook_box -= PopuCount( bb );
238   nrook_box -= (int)I2HandRook(HAND_B);
239   nrook_box -= (int)I2HandRook(HAND_W);
240
241   iret = exam_tree( ptree );
242   if ( iret < 0 )
243     {
244       ini_game( ptree, &min_posi_no_handicap, 0, NULL, NULL );
245       return iret;
246     }
247
248   return 1;
249 }
250
251
252 int
253 gen_legal_moves( tree_t * restrict ptree, unsigned int *p0 )
254 {
255   unsigned int *p1;
256   int i, j, n;
257
258   p1 = GenCaptures( root_turn, p0 );
259   p1 = GenNoCaptures( root_turn, p1 );
260   p1 = GenCapNoProEx2( root_turn, p1 );
261   p1 = GenNoCapNoProEx2( root_turn, p1 );
262   p1 = GenDrop( root_turn, p1 );
263   n  = (int)( p1 - p0 );
264
265   for ( i = 0; i < n; i++ )
266     {
267       MakeMove( root_turn, p0[i], 1 );
268       if ( InCheck( root_turn ) )
269         {
270           UnMakeMove( root_turn, p0[i], 1 );
271           p0[i] = 0;
272           continue;
273         }
274       if ( InCheck(Flip(root_turn)) )
275         {
276           ptree->nsuc_check[2] = (unsigned char)( ptree->nsuc_check[0] + 1U );
277           if ( ptree->nsuc_check[2] >= 6U
278                && ( detect_repetition( ptree, 2, Flip(root_turn), 3 )
279                     == perpetual_check ) )
280             {
281               UnMakeMove( root_turn, p0[i], 1 );
282               p0[i] = 0;
283               continue;
284             }
285         }
286       UnMakeMove( root_turn, p0[i], 1 );
287     }
288
289   for ( i = 0; i < n; )
290     {
291       if ( ! p0[i] )
292         {
293           for ( j = i+1; j < n; j++ ) { p0[j-1] = p0[j]; }
294           n -= 1;
295         }
296       else { i++; }
297     }
298   
299   return n;
300 }
301
302
303 /*
304   - detection of perpetual check is omitted.
305   - weak moves are omitted.
306 */
307 int
308 is_mate( tree_t * restrict ptree, int ply )
309 {
310   int iret = 0;
311
312   assert( InCheck(root_turn) );
313
314   ptree->move_last[ply] = GenEvasion( root_turn, ptree->move_last[ply-1] );
315   if ( ptree->move_last[ply] == ptree->move_last[ply-1] ) { iret = 1; }
316
317   return iret;
318 }
319
320
321 int
322 is_hand_eq_supe( unsigned int u, unsigned int uref )
323 {
324 #if 1
325 /* aggressive superior correspondences are applied, that is:
326  *   pawn  <= lance, silver, gold, rook
327  *   lance <= rook.
328  */
329   int nsupe;
330
331   if ( IsHandKnight(u) < IsHandKnight(uref)
332        || IsHandSilver(u) < IsHandSilver(uref)
333        || IsHandGold(u)   < IsHandGold(uref)
334        || IsHandBishop(u) < IsHandBishop(uref)
335        || IsHandRook(u)   < IsHandRook(uref) ) { return 0; }
336
337   nsupe  = (int)I2HandRook(u)  - (int)I2HandRook(uref);
338   nsupe += (int)I2HandLance(u) - (int)I2HandLance(uref);
339   if ( nsupe < 0 ) { return 0; }
340
341   nsupe += (int)I2HandSilver(u) - (int)I2HandSilver(uref);
342   nsupe += (int)I2HandGold(u)   - (int)I2HandGold(uref);
343   nsupe += (int)I2HandPawn(u)   - (int)I2HandPawn(uref);
344   if ( nsupe < 0 ) { return 0; }
345
346   return 1;
347 #else
348   if ( IsHandPawn(u) >= IsHandPawn(uref)
349        && IsHandLance(u)  >= IsHandLance(uref)
350        && IsHandKnight(u) >= IsHandKnight(uref)
351        && IsHandSilver(u) >= IsHandSilver(uref)
352        && IsHandGold(u)   >= IsHandGold(uref)
353        && IsHandBishop(u) >= IsHandBishop(uref)
354        && IsHandRook(u)   >= IsHandRook(uref) ) { return 1; }
355   
356   return 0;
357 #endif
358 }
359
360
361 /* weak moves are omitted. */
362 int
363 detect_repetition( tree_t * restrict ptree, int ply, int turn, int nth )
364 {
365   const unsigned int *p;
366   unsigned int hand1, hand2;
367   int n, i, imin, counter, irep, ncheck;
368
369   ncheck = (int)ptree->nsuc_check[ply];
370   n      = root_nrep + ply - 1;
371
372   /*if ( ncheck >= 6 )*/
373   if ( ncheck >= nth * 2 )
374     {
375       /* imin = n - ncheck*2; */
376       imin = n - ncheck*2 + 1;
377       if ( imin < 0 ) { imin = 0; }
378
379       ptree->move_last[ply] = GenEvasion( turn, ptree->move_last[ply-1] );
380       for ( p = ptree->move_last[ply-1]; p < ptree->move_last[ply]; p++ )
381         {
382           MakeMove( turn, *p, ply );
383
384           /* for ( i = n-1, counter = 0; i >= imin; i -= 2 ) */
385           for ( i = n-3, counter = 0; i >= imin; i -= 2 )
386             {
387               if ( ptree->rep_board_list[i] == HASH_KEY
388                    && ptree->rep_hand_list[i] == HAND_B
389                    && ++counter == nth )
390                    /* && ncheck*2 - 1 >= n - i )*/
391                 {
392                   UnMakeMove( turn, *p, ply );
393                   move_evasion_pchk = *p;
394                   return perpetual_check;
395                 }
396             }
397           UnMakeMove( turn, *p, ply );
398         }
399     }
400
401   irep = no_rep;
402   for ( i = n-4, counter = 0; i >= 0; i-- )
403     {
404       if ( ptree->rep_board_list[i] == HASH_KEY )
405         {
406           hand1 = HAND_B;
407           hand2 = ptree->rep_hand_list[i];
408
409           if ( (n-i) & 1 )
410             {
411               if ( irep == no_rep )
412                 {
413                   if ( turn )
414                     {
415                       if ( is_hand_eq_supe( hand2, hand1 ) )
416                         {
417                           irep = white_superi_rep;
418                         }
419                     }
420                   else if ( is_hand_eq_supe( hand1, hand2 ) )
421                     {
422                       irep = black_superi_rep;
423                     }
424                 }
425             }
426           else if ( hand1 == hand2 )
427             {
428               if ( ++counter == nth )
429                 {
430                   if ( (ncheck-1)*2 >= n - i ) { return perpetual_check; }
431                   else                         { return four_fold_rep; }
432                 }
433             }
434           else if ( irep == no_rep )
435             {
436               if ( is_hand_eq_supe( hand1, hand2 ) )
437                 {
438                   irep = black_superi_rep;
439                 }
440               else if ( is_hand_eq_supe( hand2, hand1 ) )
441                 {
442                   irep = white_superi_rep;
443                 }
444             }
445         }
446     }
447
448   return irep;
449 }
450
451
452 int
453 com_turn_start( tree_t * restrict ptree, int flag )
454 {
455   const char *str_move;
456   unsigned int move, sec_total;
457   int iret, is_resign, value, ply;
458
459   if ( ! ( flag & flag_from_ponder ) )
460     {
461       assert( ! ( game_status & mask_game_end ) );
462       
463       time_start = time_turn_start;
464       
465       game_status |=  flag_thinking;
466       iret         = iterate( ptree, flag );
467       game_status &= ~flag_thinking;
468       if ( iret < 0 ) { return iret; }
469     }
470   if ( game_status & flag_suspend ) { return 1; }
471
472   move     = last_pv.a[1];
473   value    = root_turn ? -last_root_value : last_root_value;
474   str_move = str_CSA_move( move );
475
476   if ( value < -resign_threshold && last_pv.type != pv_fail_high )
477     {
478 #if defined(DEKUNOBOU)
479       if ( dek_ngame )
480         {
481           dek_lost += 1;
482           Out( "Bonanza lost against Dekunobou\n" );
483         }
484 #endif
485       is_resign = 1;
486     }
487   else {
488     is_resign = 0;
489
490 #if defined(DEKUNOBOU)
491     if ( dek_ngame && ! is_resign
492          && value > ( MT_CAP_DRAGON * 3 ) / 2
493          && value > resign_threshold
494          && value != score_inferior )
495       {
496         is_resign = 1;
497         dek_win  += 1;
498         Out( "Bonanza won against Dekunobou.\n" );
499       }
500     if ( dek_ngame && ! is_resign && value == -score_draw )
501       {
502         iret = make_move_root( ptree, move, ( flag_rep | flag_nomake_move ) );
503         if ( iret < 0 )
504           {
505             Out( "%s\n\n", str_move );
506             return iret;
507           }
508         else if ( iret == 2 )
509           {
510             is_resign = 1;
511             Out( "The game with Dekunobou is drawn.\n" );
512           }
513       }
514     if ( dek_ngame && ! is_resign && record_game.moves > 255 )
515       {
516         is_resign = 1;
517         Out( "The game with Dekunobou is interrupted...\n" );
518       }
519 #endif
520   }
521
522 #if defined(DBG_EASY)
523   if ( easy_move && easy_move != move )
524     {
525       out_warning( "EASY MOVE DITECTION FAILED." );
526     }
527 #endif
528
529   /* send urgent outputs */
530   if ( is_resign )
531     {
532 #if defined(CSA_LAN)
533       if ( sckt_csa != SCKT_NULL )
534         {
535           iret = sckt_out( sckt_csa, "%%TORYO\n" );
536           if ( iret < 0 ) { return iret; }
537         }
538 #endif
539       OutCsaShogi( "resign\n" );
540       OutDek( "%%TORYO\n" );
541     }
542   else {
543 #if defined(CSA_LAN)
544     if ( sckt_csa != SCKT_NULL )
545       {
546         iret = sckt_out( sckt_csa, "%c%s\n", ach_turn[root_turn], str_move );
547         if ( iret < 0 ) { return iret; }
548       }
549 #endif
550
551     OutCsaShogi( "move%s\n", str_move );
552     OutDek( "%c%s\n", ach_turn[root_turn], str_move );
553   }
554   OutBeep();
555
556   /* learning and stuff */;
557   ply = record_game.moves;
558   if ( ply < HASH_REG_HIST_LEN )
559     {
560       history_book_learn[ply].data             &= ~( (1U<<31) | 0xffffU );
561       history_book_learn[ply].data             |= (unsigned int)(value+32768);
562       history_book_learn[ply].move_responsible  = move;
563       history_book_learn[ply].key_responsible   = (unsigned int)HASH_KEY;
564       history_book_learn[ply].hand_responsible  = (unsigned int)HAND_B;
565     }
566
567   iret = hash_learn( ptree, move, value, iteration_depth - 1 );
568   if ( iret < 0 ) { return iret; }
569
570   /* show search result and make a move */
571   if ( is_resign )
572     {
573       show_prompt();
574       game_status |= flag_resigned;
575       renovate_time( root_turn );
576       out_CSA( ptree, &record_game, MOVE_RESIGN );
577       sec_total = root_turn ? sec_w_total : sec_b_total;
578       str_move  = "resign";
579     }
580   else {
581     show_prompt();
582     iret = make_move_root( ptree, move,
583                            ( flag_rep | flag_time | flag_history
584                              | flag_rejections ) );
585     if ( iret < 0 )
586       {
587         Out( "%s\n\n", str_move );
588         return iret;
589       }
590     sec_total = root_turn ? sec_b_total : sec_w_total;
591   }
592
593   OutCsaShogi( "info tt %03u:%02u\n", sec_total / 60U, sec_total % 60U );
594   Out( "%s '(%d%s) %03u:%02u/%03u:%02u  elapsed: b%u, w%u\n",
595        str_move, value,
596        ( last_pv.type == pv_fail_high ) ? "!" : "",
597        sec_elapsed / 60U, sec_elapsed % 60U,
598        sec_total   / 60U, sec_total   % 60U,
599        sec_b_total, sec_w_total );
600  
601   if ( ! is_resign )
602     {
603 #if ! defined(NO_STDOUT)
604       iret = out_board( ptree, stdout, move, 0 );
605       if ( iret < 0 ) { return iret; }
606 #endif
607     }
608   
609   return 1;
610 }
611
612
613 #if defined(MNJ_LAN)
614 int mnj_reset_tbl( int sd, unsigned int seed )
615 {
616   double average, deviation, d;
617   unsigned int u;
618   int i, j;
619
620   if ( clear_trans_table() < 0 ) { return -1; }
621   ehash_clear();
622
623   if ( sd <= 0 )
624     {
625       for ( i = 0; i < MNJ_MASK + 1; i++ ) { mnj_tbl[i] = 0; }
626       return 1;
627     }
628
629   ini_rand( seed );
630
631   for( i = 0; i < MNJ_MASK + 1; i++ )
632     {
633       d = -6.0;
634
635       for ( j = 0; j < 12; j++ ) { d += (double)rand32() / (double)UINT_MAX; }
636       mnj_tbl[i] = (short)( (double)sd * d );
637     }
638
639   average = 0.0;
640   for ( i = 0; i < MNJ_MASK + 1; i++ ) { average += (double)mnj_tbl[i]; }
641   average /= (double)( MNJ_MASK + 1 );
642
643   deviation = 0.0;
644   for ( i = 0; i < MNJ_MASK + 1; i++ )
645     {
646       d = (double)mnj_tbl[i] - average;
647       deviation += d * d;
648     }
649   deviation = sqrt( deviation / (double)( MNJ_MASK + 1 ) );
650
651   if ( get_elapsed( &u ) < 0 ) { return -1; }
652   ini_rand( u );
653
654   Out( "\nThe normal distribution N(0,sd^2) is generated.\n" );
655   Out( "  actual average:            % .3f\n", average );
656   Out( "  actual standard deviation: % .3f\n", deviation );
657   Out( "rand seed = %x\n", u );
658
659   return 1;
660 }
661 #endif
662
663
664 void *
665 memory_alloc( size_t nbytes )
666 {
667 #if defined(_WIN32)
668   void *p = VirtualAlloc( NULL, nbytes, MEM_COMMIT, PAGE_READWRITE );
669   if ( p == NULL ) { str_error = "VirturlAlloc() faild"; }
670 #else
671   void *p = malloc( nbytes );
672   if ( p == NULL ) { str_error = "malloc() faild"; }
673 #endif
674   return p;
675 }
676
677
678 int
679 memory_free( void *p )
680 {
681 #if defined(_WIN32)
682   if ( VirtualFree( p, 0, MEM_RELEASE ) ) { return 1; }
683   str_error = "VirtualFree() faild";
684   return -2;
685 #else
686   free( p );
687   return 1;
688 #endif
689 }