Scid  4.6.5
book.tcl
Go to the documentation of this file.
1 ###
2 ### book.tcl: part of Scid.
3 ### Copyright (C) 2007 Pascal Georges
4 ###
5 ######################################################################
6 ### Book window
7 
8 namespace eval book {
9  set isOpen 0
10  set isReadonly 0
11  set bookList ""
12  set bookPath ""
13  set currentBook "" ; # book in form abc.bin
14  set currentTuningBook ""
15  set bookMoves ""
16  set cancelBookExport 0
17  set exportCount 0
18  set exportMax 3000
19  set hashList ""
20  set bookSlot 0
21  set bookTuningSlot 2
22  set oppMovesVisible 0
23 
24 
25  ################################################################################
26  # open a book, closing any previously opened one (called by annotation analysis)
27  # arg name : gm2600.bin for example
28  ################################################################################
29  proc scBookOpen { name slot } {
30  if {$slot == $::book::bookSlot} {
31  if {$::book::currentBook != ""} {
32  sc_book close $::book::bookSlot
33  }
34  set ::book::currentBook $name
35  }
36  if {$slot == $::book::bookTuningSlot} {
37  if {$::book::currentTuningBook != ""} {
38  sc_book close $::book::bookTuningSlot
39  }
40  set ::book::currentTuningBook $name
41  }
42 
43  set bn [ file join $::scidBooksDir $name]
44  set ::book::isReadonly [sc_book load $bn $slot]
45  }
46 
47  ################################################################################
48  # Return a move in book for position fen. If there is no move in book, returns ""
49  # Is used by engines, not book windows
50  ################################################################################
51  proc getMove { book fen slot} {
52  set tprob 0
53  ::book::scBookOpen $book $slot
54  set bookmoves [sc_book moves $slot]
55  if {[llength $bookmoves] == 0} {
56  return ""
57  }
58  set r [expr {(int (rand() * 100))}]
59  for {set i 0} {$i<[llength $bookmoves]} {incr i 2} {
60  set m [lindex $bookmoves $i]
61  set prob [string range [lindex $bookmoves [expr $i + 1]] 0 end-1]
62  incr tprob $prob
63  if { $tprob >= $r } {
64  break
65  }
66  }
67  sc_book close $slot
68  return $m
69  }
70 
71  ################################################################################
72  # Show moves leading to book positions
73  ################################################################################
74  proc togglePositionsDisplay {} {
75  global ::book::oppMovesVisible
76  if { $::book::oppMovesVisible == 0} {
77  set ::book::oppMovesVisible 1
78  pack .bookWin.f.text1 -expand yes -fill both
79  } else {
80  set ::book::oppMovesVisible 0
81  pack forget .bookWin.f.text1
82  }
83  }
84 
85  ################################################################################
86  # Open a window to select book and display book moves
87  # arg name : gm2600.bin for example
88  ################################################################################
89  proc open { {name ""} } {
90  global ::book::bookList ::book::bookPath ::book::currentBook ::book::isOpen ::book::lastBook
91 
92  set w .bookWin
93 
94  if {[winfo exists $w]} { return}
95 
96  set ::book::isOpen 1
97 
99  ::setTitle $w $::tr(Book)
100  wm resizable $w 0 1
101 
102  setWinLocation $w
103  bind $w <Configure> "recordWinSize $w"
104  bind $w <F1> { helpWindow Book }
105 
106  ttk::frame $w.f
107 
108  # load book names
109  if { $name == "" && $lastBook != "" } {
110  set name $lastBook
111  }
112  set bookPath $::scidBooksDir
113  set bookList [ lsort -dictionary [ glob -nocomplain -directory $bookPath *.bin]]
114 
115  # No book found
116  if { [llength $bookList] == 0 } {
117  tk_messageBox -title "Scid" -type ok -icon error -message "No books found. Check books directory"
118  set ::book::isOpen 0
119  set ::book::currentBook ""
120  destroy $w
122  return
123  }
124 
125  set i 0
126  set idx 0
127  set tmp {}
128  foreach file $bookList {
129  set f [ file tail $file]
130  lappend tmp $f
131  if {$name == $f} {
132  set idx $i
133  }
134  incr i
135  }
136  ttk::combobox $w.f.combo -width 12 -values $tmp
137 
138  catch { $w.f.combo current $idx}
139  pack $w.f.combo
140 
141  # text displaying book moves
142  frame $w.f.fscroll
143  autoscrollframe -bars y $w.f.fscroll text $w.f.text -wrap word -state disabled -width 12
144 
145  ttk::button $w.f.b -text $::tr(OtherBookMoves) -command { ::book::togglePositionsDisplay }
146  ::utils::tooltip::Set $w.f.b $::tr(OtherBookMovesTooltip)
147 
148  text $w.f.text1 -wrap word -state disabled -width 12
149 
150  pack $w.f.fscroll -expand yes -fill both
151  pack $w.f.b
152  pack $w.f.text1 -expand yes -fill both
153 
154  pack $w.f -expand 1 -fill both
155 
156  bind $w.f.combo <<ComboboxSelected>> ::book::bookSelect
157  bind $w <Destroy> "::book::closeMainBook ; ::docking::cleanup $w"
158  bind $w <Escape> { destroy .bookWin }
159  # we make a redundant check here, another one is done a few line above
160  if { [catch {bookSelect}] } {
161  tk_messageBox -title "Scid" -type ok -icon error -message "No books found. Check books directory"
162  set ::book::isOpen 0
163  set ::book::currentBook ""
164  destroy .bookWin
165  }
166  }
167  ################################################################################
168  #
169  ################################################################################
170  proc closeMainBook {} {
171  if { $::book::currentBook == "" } { return}
172  focus .
173  sc_book close $::book::bookSlot
174  set ::book::isOpen 0
175  set ::book::currentBook ""
176  }
177  ################################################################################
178  # updates book display when board changes
179  ################################################################################
180  proc refresh {} {
181  global ::book::bookMoves
182 
183  foreach t [.bookWin.f.text tag names] {
184  if { [string match "bookMove*" $t] } {
185  .bookWin.f.text tag delete $t
186  }
187  }
188  foreach t [.bookWin.f.text1 tag names] {
189  if { [string match "bookMove*" $t] } {
190  .bookWin.f.text1 tag delete $t
191  }
192  }
193  set bookMoves [sc_book moves $::book::bookSlot]
194  .bookWin.f.text configure -state normal
195  .bookWin.f.text delete 1.0 end
196  for {set i 0} {$i<[llength $bookMoves]} {incr i 2} {
197  set line [expr $i /2 +1]
198  set m ""
199  append m [::trans [lindex $bookMoves $i]] "\t" [lindex $bookMoves [expr $i + 1]] "\n"
200  .bookWin.f.text insert end $m
201  .bookWin.f.text tag add bookMove$line $line.0 $line.end
202  .bookWin.f.text tag bind bookMove$line <ButtonPress-1> "::book::makeBookMove [lindex $bookMoves $i]"
203  }
204  .bookWin.f.text configure -state disabled -height [expr [llength $bookMoves] / 2]
205 
206 
207  set oppBookMoves [sc_book positions $::book::bookSlot]
208  .bookWin.f.text1 configure -state normal
209  .bookWin.f.text1 delete 1.0 end
210  for {set i 0} {$i<[llength $oppBookMoves]} {incr i 1} {
211  set line [expr $i +1]
212  set m ""
213  append m [::trans [lindex $oppBookMoves $i]] "\n"
214  .bookWin.f.text1 insert end $m
215  .bookWin.f.text1 tag add bookMove$line $line.0 $line.end
216  .bookWin.f.text1 tag bind bookMove$line <ButtonPress-1> "::book::makeBookMove [lindex $oppBookMoves $i]"
217  }
218  .bookWin.f.text1 configure -state disabled -height [llength $oppBookMoves]
219  if { $::book::oppMovesVisible == 0 } {
220  pack forget .bookWin.f.text1
221  }
222  }
223  ################################################################################
224  #
225  ################################################################################
226  proc makeBookMove { move } {
227  addSanMove $move
228  }
229  ################################################################################
230  #
231  ################################################################################
232  proc bookSelect { { n "" } { v 0} } {
233  set ::book::lastBook [.bookWin.f.combo get]
234  scBookOpen [.bookWin.f.combo get] $::book::bookSlot
235  refresh
236  }
237  ################################################################################
238  #
239  ################################################################################
240  proc tuning { {name ""} } {
241  global ::book::bookList ::book::bookPath ::book::currentBook ::book::isOpen
242 
243  set w .bookTuningWin
244 
245  if {[winfo exists $w]} {
246  return
247  }
248 
250  ::setTitle $w $::tr(Book)
251  # wm resizable $w 0 0
252 
253  bind $w <F1> { helpWindow BookTuningWindow }
254  setWinLocation $w
255 
256  ttk::frame $w.fcombo
257  ttk::frame $w.f
258  # load book names
259  set bookPath $::scidBooksDir
260  set bookList [ lsort -dictionary [ glob -nocomplain -directory $bookPath *.bin]]
261 
262  # No book found
263  if { [llength $bookList] == 0 } {
264  tk_messageBox -title "Scid" -type ok -icon error -message "No books found. Check books directory"
265  set ::book::isOpen 0
266  set ::book::currentBook ""
267  destroy $w
269  return
270  }
271 
272  set i 0
273  set idx 0
274  set tmp {}
275  foreach file $bookList {
276  set f [ file tail $file]
277  lappend tmp $f
278  if {$name == $f} {
279  set idx $i
280  }
281  incr i
282  }
283 
284  ttk::combobox $w.fcombo.combo -width 12 -values $tmp
285  catch { $w.fcombo.combo current $idx}
286  pack $w.fcombo.combo -expand yes -fill x
287 
288  ttk::frame $w.fbutton
289 
290 
291  menubutton $w.fbutton.mbAdd -text $::tr(AddMove) -menu $w.fbutton.mbAdd.otherMoves
292  menu $w.fbutton.mbAdd.otherMoves
293 
294 
295  ttk::button $w.fbutton.bExport -text $::tr(Export) -command ::book::export
296  ttk::button $w.fbutton.bSave -text $::tr(Save) -command ::book::save
297 
298  pack $w.fbutton.mbAdd $w.fbutton.bExport $w.fbutton.bSave -side top -fill x -expand yes
299 
300 
301  pack $w.fcombo $w.f $w.fbutton -side top
302 
303  bind $w.fcombo.combo <<ComboboxSelected>> ::book::bookTuningSelect
304 
305  bind $w <Destroy> "::book::closeTuningBook ; ::docking::cleanup $w"
306  bind $w <Escape> { destroy .bookTuningWin }
307  bind $w <F1> { helpWindow BookTuning }
308 
310 
311  }
312  ################################################################################
313  #
314  ################################################################################
315  proc closeTuningBook {} {
316  if { $::book::currentTuningBook == "" } { return}
317  focus .
318  sc_book close $::book::bookTuningSlot
319  set ::book::currentTuningBook ""
320  }
321  ################################################################################
322  #
323  ################################################################################
324  proc bookTuningSelect { { n "" } { v 0} } {
325  set w .bookTuningWin
326  scBookOpen [.bookTuningWin.fcombo.combo get] $::book::bookTuningSlot
327  if { $::book::isReadonly > 0 } {
328  $w.fbutton.bSave configure -state disabled
329  } else {
330  $w.fbutton.bSave configure -state normal
331  }
333  }
334  ################################################################################
335  # add a move to displayed bookmoves
336  ################################################################################
337  proc addBookMove { move } {
338  global ::book::bookTuningMoves
339 
340  if { $::book::isReadonly > 0 } { return}
341 
342  set w .bookTuningWin
343  set children [winfo children $w.f]
344  set count [expr [llength $children] / 2]
345  ttk::label $w.f.m$count -text [::trans $move]
346  bind $w.f.m$count <ButtonPress-1> " ::book::makeBookMove $move"
347  spinbox $w.f.sp$count -from 0 -to 100 -width 3
348  $w.f.sp$count set 0
349  grid $w.f.m$count -row $count -column 0 -sticky w
350  grid $w.f.sp$count -row $count -column 1 -sticky w
351  $w.fbutton.mbAdd.otherMoves delete [::trans $move]
352  lappend ::book::bookTuningMoves $move
353  }
354  ################################################################################
355  # updates book display when board changes
356  ################################################################################
357  proc refreshTuning {} {
358 
359  if { $::book::isReadonly > 0 } { return}
360 
361  #unfortunately we need this as the moves on the widgets are translated
362  #and widgets have no clientdata in tcl/tk
363  global ::book::bookTuningMoves
364  set ::book::bookTuningMoves {}
365  set moves [sc_book moves $::book::bookTuningSlot]
366 
367  set w .bookTuningWin
368  bind $w <Destroy> "" ;# avoid the closing of the book
369  # erase previous children
370  set children [winfo children $w.f]
371  foreach c $children {
372  destroy $c
373  }
374 
375  set row 0
376  for {set i 0} {$i<[llength $moves]} {incr i 2} {
377  lappend ::book::bookTuningMoves [lindex $moves $i]
378  label $w.f.m$row -text [::trans [lindex $moves $i]]
379  bind $w.f.m$row <ButtonPress-1> " ::book::makeBookMove [lindex $moves $i] "
380  spinbox $w.f.sp$row -from 0 -to 100 -width 3
381  set pct [lindex $moves [expr $i+1]]
382  set value [string replace $pct end end ""]
383  $w.f.sp$row set $value
384  grid $w.f.m$row -row $row -column 0 -sticky w
385  grid $w.f.sp$row -row $row -column 1 -sticky w
386  incr row
387  }
388  # load legal moves
389  $w.fbutton.mbAdd.otherMoves delete 0 end
390  $w.fbutton.mbAdd.otherMoves add command -label $::tr(None)
391  set moveList [ sc_pos moves]
392  foreach move $moveList {
393  if { [ lsearch $moves $move] == -1 } {
394  $w.fbutton.mbAdd.otherMoves add command -label [::trans $move] -command "::book::addBookMove $move"
395  }
396  }
397  bind $w <Destroy> "::book::closeTuningBook ; ::docking::cleanup $w"
398  }
399  ################################################################################
400  # sends to book the list of moves and probabilities.
401  ################################################################################
402  proc save {} {
403  global ::book::bookTuningMoves
404  if { $::book::isReadonly > 0 } { return}
405 
406  set prob {}
407  set w .bookTuningWin
408  set children [winfo children $w.f]
409  set count [expr [llength $children] / 2]
410  for {set row 0} {$row < $count} {incr row} {
411  lappend prob [$w.f.sp$row get]
412  }
413  set tempfile [file join $::scidUserDir tempfile.[pid]]
414  sc_book movesupdate $::book::bookTuningMoves $prob $::book::bookTuningSlot $tempfile
415  file delete $tempfile
416  if { [ winfo exists .bookWin] } {
418  }
419  }
420  ################################################################################
421  #
422  ################################################################################
423  proc export {} {
426  progressWindow "Scid" "ExportingBook..." $::tr(Cancel) "::book::sc_progressBar"
427  set ::book::cancelBookExport 0
428  set ::book::exportCount 0
430  set ::book::hashList ""
432  if { $::book::exportCount >= $::book::exportMax } {
433  tk_messageBox -title "Scid" -type ok -icon info \
434  -message "$::tr(Movesloaded) $::book::exportCount\n$::tr(BookPartiallyLoaded)"
435  } else {
436  tk_messageBox -title "Scid" -type ok -icon info -message "$::tr(Movesloaded) $::book::exportCount"
437  }
438  updateBoard -pgn
439  }
440 
441  ################################################################################
442  #
443  ################################################################################
444  proc book2pgn { } {
445  global ::book::hashList
446 
447  if {$::book::cancelBookExport} { return}
448  if { $::book::exportCount >= $::book::exportMax } {
449  return
450  }
451  set hash [sc_pos hash]
452  if {[lsearch -sorted -integer -exact $hashList $hash] != -1} {
453  return
454  } else {
455  lappend hashList $hash
456  set hashList [lsort -integer -unique $hashList]
457  }
458 
459  updateBoard -pgn
460 
461  set bookMoves [sc_book moves $::book::bookTuningSlot]
462  incr ::book::exportCount
463  if {[expr $::book::exportCount % 50] == 0} {
464  updateProgressWindow $::book::exportCount $::book::exportMax
465  update
466  }
467  if {[llength $bookMoves] == 0} { return}
468 
469  for {set i 0} {$i<[llength $bookMoves]} {incr i 2} {
470  set move [lindex $bookMoves $i]
471  if {$i == 0} {
472  sc_move addSan $move
473  book2pgn
474  sc_move back
475  } else {
476  sc_var create
477  sc_move addSan $move
478  book2pgn
479  sc_var exit
480  }
481  }
482 
483  }
484  ################################################################################
485  # cancel book export
486  ################################################################################
487  proc sc_progressBar {} {
488  set ::book::cancelBookExport 1
489  }
490 }
491 ###
492 ### End of file: book.tcl
493 ###