1 /***************************************************************************
4 begin : Mer Oct 19 2005
5 copyright : (C) 2005 by Maurizio Monge
6 email : monge@linuz.sns.it
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
21 /* each move in the book will be stored in 24 bits */
22 struct PACKED ComprMove
24 unsigned int move
: 14;
25 unsigned int stat
: 10;
28 /* MoveMark and MoveStat are for the book creation */
29 struct PACKED MoveMark
46 MoveMark
& operator[](int i
) {
52 mv_oth
= (MoveMark
*)realloc(mv_oth
, oth_size
*sizeof(MoveMark
));
71 void insert(uint32_t m
, unsigned int w
)
73 for(int i
=0;i
<num
; i
++)
74 if((*this)[i
].move
== m
)
81 (*this)[num
].move
= m
;
82 (*this)[num
].stat
= w
;
87 static int sort_mv_marks(const void *a
, const void *b
)
89 return ((MoveMark
*)b
)->stat
- ((MoveMark
*)a
)->stat
;
94 for(int i
=0;i
<num
-1;i
++)
95 if(mv_oth
[i
].stat
> mv_first
.stat
)
96 SWITCH(mv_oth
[i
], mv_first
);
97 qsort(mv_oth
, num
-1, sizeof(MoveMark
), sort_mv_marks
);
101 typedef std::map
< HashKey
, MoveStat
> BkEntryMap
;
104 /* an entry in the book */
105 struct PACKED BookEntry
108 /* the offset you have to add to find the right branch of the binary tree */
110 /* the number of moves */
115 /* special flags for marking the leaf nodes or those with only 1 child */
116 #define NO_RIGHT ((uint32_t)-1)
117 #define LEAF ((uint32_t)-2)
119 /* the size of the entry in a book with x alternatives */
120 #define ENTRY_SIZE(x) (sizeof(BookEntry) + ((x)-1)*sizeof(ComprMove))
122 static uint32_t calc_book_range_size(BkEntryMap::iterator begin
, BkEntryMap::iterator end
)
125 for(;begin
!=end
;++begin
)
126 sz
+= ENTRY_SIZE(begin
->second
.num
);
130 static int write_book_range(FILE* f
, BkEntryMap::iterator begin
, BkEntryMap::iterator end
)
136 BkEntryMap::iterator mid
= begin
;
144 for(int i
=0;i
<num
/2;i
++)
147 const HashKey
& hk
= mid
->first
;
148 MoveStat
& m
= mid
->second
;
149 uint32_t besz
= ENTRY_SIZE(m
.num
);
150 uint32_t lsize
= calc_book_range_size(begin
, mid
);
151 BkEntryMap::iterator tmpit
= mid
;
156 b
.right_off
= lsize
? NO_RIGHT
: LEAF
;
159 b
.mv
[0].move
= m
[0].move
;
160 b
.mv
[0].stat
= m
[0].stat
;
161 fwrite(&b
, 1, sizeof(BookEntry
), f
);
163 for(int i
=1;i
<m
.num
;i
++)
165 ComprMove c
= { m
[i
].move
, m
[i
].stat
};
166 fwrite(&c
, 1, sizeof(ComprMove
), f
);
170 uint32_t truels
= write_book_range(f
, begin
, mid
);
172 fprintf(stderr
, "Error! %d %d\n", truels
, lsize
);
175 return besz
+ lsize
+ write_book_range(f
, mid
, end
);
178 void Engine::create_book(int argc
, char *argv
[])
182 FILE* f
= fopen(argv
[0],"r");
184 output("Error, could not open \"%s\" for reading.\n", argv
[0]);
189 output("(%d games processed)\n", n
);
191 for(int i
=mv_done_num
-1; i
>=0; i
--)
193 board
.undo_move(mv_done
[i
]);
195 if(i
>v_book_creation_max_depth
)
198 MoveStat
& ms
= b
[board
.hash
];
200 unsigned int weight
= 2;
202 weight
= board
.color_to_move
== BLACK
? 3 : 1;
203 else if(status
== _10
)
204 weight
= board
.color_to_move
== WHITE
? 3 : 1;
206 ms
.insert( board
.compress_move(mv_done
[i
]), weight
);
212 /* adjust the entries */
213 output("(preprocessing the tree)\n");
215 for(BkEntryMap::iterator it
= b
.begin(); it
!= b
.end(); )
217 MoveStat
& ms
= it
->second
;
219 /* discard moves played too few times in games */
220 if(ms
.tot
< (unsigned int)v_book_creation_min_games
)
227 /* remove very rare moves) */
228 for(int i
=0;i
<ms
.num
;i
++)
230 if(ms
[i
].stat
*1000 < ms
.tot
*v_book_creation_min_probability
)
232 ms
.tot
-= ms
[i
].stat
;
233 ms
[i
] = ms
[ms
.num
-1];
239 /* renormalize the alternatives up to 1024 */
241 for(int i
=0;i
<ms
.num
;i
++)
244 ms
[i
].stat
= ((prev_tot
+st
)*1024)/ms
.tot
245 - (prev_tot
*1024)/ms
.tot
;
249 /* sort them so the program will give a nicer output :) */
253 FILE *bf
= fopen("ratta.book","w");
254 output("(writing the book)\n");
255 uint32_t sz
= write_book_range(bf
, b
.begin(), b
.end());
256 printf("Book size is %u\n",sz
);
259 st_computer_color
= 0;
262 bool Engine::open_book(const char *f
)
266 // book_mmap = map_file( f, &book_size);
269 // output("Error, could not open and mmap the book file \"%s\".\n", f);
274 // output("Book file \"%s\" opened and mapped, good!\n", f);
278 FILE *file
= fopen(f
, "r");
281 output("Error, could not open and mmap the book file \"%s\" (%s).\n", f
, strerror(errno
));
286 fseek(file
, 0, SEEK_END
);
287 book_size
= ftell(file
);
288 fseek(file
, 0, SEEK_SET
);
289 book_mmap
= malloc(book_size
);
290 fread(book_mmap
, book_size
, 1, file
);
293 output("Book file \"%s\" opened and mapped, good!\n", f
);
298 void Engine::close_book()
301 // unmap_file(book_mmap, book_size);
307 bool Engine::probe_book(const HashKey
& h
, Move
* m
)
311 if(!book_mmap
|| mv_done_num
>50)
314 /* walk the in-memory mapped binary search tree */
317 BookEntry
*b
= (BookEntry
*)((long)book_mmap
+delta
);
319 /* book entry found */
322 /* print the (e4 64%, d4 36%)-like thinking line */
325 output("\t0\t0\t0\t0\t(");
326 for(unsigned int i
=0;i
<b
->num
;i
++)
329 Move m
= board
.uncompress_move(b
->mv
[i
].move
);
332 output("%s %.01f%%", move_to_alg(str
, &m
),
334 (b
->mv
[i
].stat
*100.0)/1024);
341 *m
= board
.uncompress_move(b
->mv
[0].move
);
346 for(unsigned int i
=0;i
<b
->num
;i
++)
351 *m
= board
.uncompress_move(b
->mv
[i
].move
);
356 /* this should never happen */
360 if(b
->right_off
== LEAF
)
366 if(b
->right_off
== 0)
370 delta
+= ENTRY_SIZE(b
->num
);
375 if(b
->right_off
== NO_RIGHT
)
379 delta
+= ENTRY_SIZE(b
->num
) + b
->right_off
;
382 if(delta
< 0 || delta
>= book_size
-16 )
384 output("Error! Damaged binary book!\n");
391 bool Engine::open_lines(const char *linef
)
393 FILE* f
= fopen(linef
,"r");
396 output("Error, could not open \"%s\" for reading.\n", linef
);
402 for(int i
=mv_done_num
-1; i
>=0; i
--)
404 board
.undo_move(mv_done
[i
]);
406 if(mv_done
[i
].val
> 0)
408 std::list
< Move
>& ml
= lines
[board
.hash
];
409 ml
.push_front(mv_done
[i
]);
412 output("Good move %s loaded! %lx\n",
413 move_to_alg(buf, &mv_done[i]), board.hash.check);
414 board.print_board();*/
419 output("Lines loaded from file \"%s\", good!\n", linef
);
423 void Engine::close_lines()
428 bool Engine::probe_lines(const HashKey
& h
, Move
* m
)
430 Lines::iterator it
= lines
.find( h
);
431 if( it
== lines
.end() )
433 //output("Not found! %lx\n", board.hash.check);
437 int r
= rand() % it
->second
.size();
438 std::list
< Move
>::iterator mit
= it
->second
.begin();
440 for(int i
=0;i
<r
;i
++) mit
++;