12 set analysis(logMax) 5000
    18 set analysis(log_stdout) 0
    21 set analysisBookSlot 1
    22 set useAnalysisBookName ""
    37 set isBatchOpeningMoves 12
    40 set markTacticalExercises 0
    43 set isShortAnnotation 0
    44 set addScoreToShortAnnotations 0
    53 proc resetEngine {n} {
    55     set analysis(pipe$n) ""
    56 set analysis(seen$n) 0
    57 set analysis(seenEval$n) 0
    58 set analysis(score$n) 0
    59 set analysis(prevscore$n) 0
    60 set analysis(scoremate$n) 0
    61 set analysis(prevscoremate$n) 0
    62 set analysis(prevmoves$n) ""
    63 set analysis(nodes$n) 0
    64 set analysis(depth$n) 0
    65 set analysis(prev_depth$n) 0
    66 set analysis(time$n) 0
    67 set analysis(moves$n) ""
    68 set analysis(seldepth$n) 0
    69     set analysis(currmove$n) ""
    70 set analysis(currmovenumber$n) 0
    71 set analysis(hashfull$n) 0
    73     set analysis(tbhits$n) 0
    74     set analysis(sbhits$n) 0
    75     set analysis(cpuload$n) 0
    76     set analysis(movelist$n) {}
    77 set analysis(nonStdStart$n) 0
    78 set analysis(has_analyze$n) 0
    79 set analysis(has_setboard$n) 0
    80 set analysis(send_sigint$n) 0
    81 set analysis(wants_usermove$n) 0
    82 set analysis(isCrafty$n) 0
    83 set analysis(wholeSeconds$n) 0
    84 set analysis(analyzeMode$n) 0
    85 set analysis(invertScore$n) 1
    86 set analysis(automove$n) 0
    87     set analysis(automoveThinking$n) 0
    88     set analysis(automoveTime$n) 4000
    89     set analysis(lastClicks$n) 0
    90     set analysis(after$n) ""
    91     set analysis(log$n) ""
    92 set analysis(logCount$n) 0
    93 set analysis(wbEngineDetected$n) 0
    94 set analysis(multiPV$n) {}
    95 set analysis(multiPVraw$n) {}
    98 set analysis(uciOptions$n) {}
   100 set analysis(multiPVCount$n) 1
   101 set analysis(uciok$n) 0
   102 set analysis(name$n) ""
   103 set analysis(processInput$n) 0
   104 set analysis(waitForBestMove$n) 0
   105     set analysis(waitForReadyOk$n) 0
   106     set analysis(onUciOk$n) ""
   107     set analysis(movesDisplay$n) 1
   108 set analysis(lastHistory$n) {}
   109 set analysis(maxmovenumber$n) 0
   110 set analysis(lockEngine$n) 0
   111 set analysis(fen$n) {}
   118 set annotateModeButtonValue 0 
   120 set annotateMoves all
   121 set annotateBlunders blundersonly
   128 proc calculateNodes {{n}} {
   129     set len [
string length $n]
   133         set shortn [
string range $n 0 [
expr {$len - 4}]]
   143 proc resetAnalysis {{n 1}} {
   145     set analysis(score$n) 0
   146     set analysis(scoremate$n) 0
   147     set analysis(nodes$n) 0
   148     set analysis(prev_depth$n) 0
   149     set analysis(depth$n) 0
   150     set analysis(time$n) 0
   151     set analysis(moves$n) ""
   152     set analysis(multiPV$n) {}
   153     set analysis(multiPVraw$n) {}
   154     set analysis(lastHistory$n) {}
   155     set analysis(maxmovenumber$n) 0
   158 namespace eval enginelist {}
   167 proc engine {arglist} {
   169     array set newEngine {}
   170     foreach {attr value} $arglist {
   171         set newEngine($attr) $value
   174 if {! [
info exists newEngine(Name)]} { 
return  0}
   175     if {! [
info exists newEngine(Cmd)]} { 
return  0}
   176     if {! [
info exists newEngine(Dir)]} { 
return  0}
   178 if {! [
info exists newEngine(Args)]} { 
set newEngine(Args) ""}
   179     if {! [
info exists newEngine(Elo)]} { 
set newEngine(Elo) 0}
   180     if {! [
info exists newEngine(Time)]} { 
set newEngine(Time) 0}
   181     if {! [
info exists newEngine(URL)]} { 
set newEngine(URL) ""}
   183 if {! [
info exists newEngine(UCI)]} { 
set newEngine(UCI) 0}
   184     if {! [
info exists newEngine(UCIoptions)]} { 
set newEngine(UCIoptions) ""}
   186     lappend engines(list) [list $newEngine(Name) $newEngine(Cmd) \
   187             $newEngine(Args) $newEngine(Dir) \
   188             $newEngine(Elo) $newEngine(Time) \
   189             $newEngine(URL) $newEngine(UCI) $newEngine(UCIoptions)]
   196 proc ::enginelist::read {} {
   203 proc ::enginelist::write {} {
   204     global engines ::uci::newOptions
   209 catch {
file rename -force $enginesFile $enginesBackupFile}
   210     if {[
catch {open $enginesFile w} f]} {
   211         catch {
file rename $enginesBackupFile $enginesFile}
   215     puts $f "\# Analysis engines list file for Scid $::scidVersion with UCI support"
   217     foreach e $engines(list) {
   218         set name [
lindex $e 0]
   219         set cmd [
lindex $e 1]
   220         set args [
lindex $e 2]
   221         set dir [
lindex $e 3]
   222         set elo [
lindex $e 4]
   223         set time [
lindex $e 5]
   224         set url [
lindex $e 6]
   225         set uci [
lindex $e 7]
   226         set opt [
lindex $e 8]
   228             puts $f "  Name [list $name]"
   229             puts $f "  Cmd  [list $cmd]"
   230             puts $f "  Args [list $args]"
   231             puts $f "  Dir  [list $dir]"
   232             puts $f "  Elo  [list $elo]"
   233             puts $f "  Time [list $time]"
   234             puts $f "  URL  [list $url]"
   235             puts $f "  UCI [list $uci]"
   236             puts $f "  UCIoptions [list $opt]"
   247 if {[
llength $engines(list)] == 0} {
   249 set scidlet "scidlet"
   250     set phalanx "phalanx-scid"
   252     if { $::windowsOS } {
   253         set scidlet "scidlet.exe"
   254         set phalanx "phalanx-scid.exe"
   255         set togaII "TogaII.exe"
   257     set scidEngPaths [list $::scidExeDir [
file join $::scidExeDir "engines"] [
file join $::scidShareDir "engines"] \
   258             [ 
file join $::scidUserDir "engines"]  [ 
file join /usr local share scid engines] \
   259             [ 
file join /usr local bin] [ 
file join  /usr bin] [ 
file join /usr local games] [ 
file join /usr games] \
   260             [
file join $::scidExeDir "engines" "phalanx-scid"] [
file join $::scidExeDir "engines" "togaII1.2.1a" "src"]]
   263 set scidEngCmds [list $phalanx $togaII $scidlet]
   264     set scidEngNames [list "Phalanx-Scid" "Toga II" "Scidlet"]
   265     array set parentDirs "
   266     $phalanx { phalanx-scid Phalanx-XXII }
   267     $togaII  { togaII1.2.1a toga togaII [ 
file join togaII1.2.1a src] }
   271     set isUCI [list 0 1 0]
   274 foreach cmd $scidEngCmds name $scidEngNames uci $isUCI {
   276         foreach path $scidEngPaths {
   277             set c [ 
file join $path $cmd]
   278             if { [
file executable $c] && ! [ 
file isdirectory $c] } {
   287                 foreach parent $parentDirs($cmd) {
   288                     set c [ 
file join $path $parent $cmd]
   289                     if { [
file executable $c] && ! [ 
file isdirectory $c] } {
   301             if { $leave } { break}
   309 proc ::enginelist::date {time} {
   310     return [
clock format $time -format "%a %b %d %Y %H:%M"]
   318 proc ::enginelist::sort {{type ""}} {
   322         set type $engines(sort)
   324         set engines(sort) $type
   328             set engines(list) [lsort -dictionary -index 0 $engines(list)]
   331             set engines(list) [lsort -integer -decreasing -index 4 $engines(list)]
   334             set engines(list) [lsort -integer -decreasing -index 5 $engines(list)]
   341     if {! [
winfo exists $w]} { 
return}
   345     foreach engine $engines(list) {
   347         set name [
lindex $engine 0]
   348         set elo [
lindex $engine 4]
   349         set time [
lindex $engine 5]
   350         set uci [
lindex $engine 7]
   352         set text [
format "%2u. %-21s " $count $name]
   354         if {$elo > 0} { 
set eloText [
format "%4u" $elo]}
   357         if {$time > 0} { 
set timeText "   $date"}
   358         append text $timeText
   364 $w.title configure -state normal
   365     foreach i {Name Elo Time} {
   366         $w.title tag configure $i -foreground {}
   368     $w.title tag configure $engines(sort) -foreground red
   369     $w.title configure -state disabled
   377 proc ::enginelist::choose {} {
   380     if {[
winfo exists $w]} {
   385     ttk::label $w.flabel -text $::tr(EngineList:) -font font_Bold -anchor center
   386     pack $w.flabel -side top -fill x
   387     pack [ttk::frame $w.buttons] -side bottom -fill x
   390 text $w.title -width 55 -height 1 -font font_Fixed -relief flat \
   391             -cursor top_left_arrow
   392     $w.title insert end "    "
   393     $w.title insert end $::tr(EngineName) Name
   394     for {
set i [
string length $::tr(EngineName)]} {$i < 21} { 
incr i} {
   395         $w.title insert end " "
   397     $w.title insert end "  "
   398     $w.title insert end $::tr(EngineElo) Elo
   399     for {
set i [
string length $::tr(EngineElo)]} {$i < 4} { 
incr i} {
   400         $w.title insert end " "
   402     $w.title insert end "  "
   403     $w.title insert end $::tr(EngineTime) Time
   404     foreach i {Name Elo Time} {
   405         $w.title tag bind $i <Any-Enter> \
   406                 "$w.title tag configure $i -background yellow"
   407         $w.title tag bind $i <Any-Leave> \
   408                 "$w.title tag configure $i -background {}"
   409         $w.title tag bind $i <1> [list ::enginelist::sort $i]
   411     $w.title configure -state disabled
   412     pack $w.title -side top -fill x
   416     pack [ttk::frame $f] -side top -expand yes -fill both
   417     listbox $f.list -height 10 -width 55  -selectmode browse \
   418             -background white -setgrid 1 \
   419             -yscrollcommand "$f.ybar set" -font font_Fixed -exportselection 0
   420     bind $f.list <Double-ButtonRelease-1> "$w.buttons.ok invoke; break"
   421     ttk::scrollbar $f.ybar -command "$f.list yview"
   422     pack $f.ybar -side right -fill y
   423     pack $f.list -side top -fill both -expand yes
   424     $f.list selection set 0
   427     dialogbutton $f.add -text $::tr(EngineNew...) -command {::enginelist::edit -1}
   428     dialogbutton $f.edit -text $::tr(EngineEdit...) -command {
   429         ::enginelist::edit [lindex [.enginelist.list.list curselection] 0]
   431     dialogbutton $f.delete -text $::tr(Delete...) -command {
   432         ::enginelist::delete [lindex [.enginelist.list.list curselection] 0]
   434     ttk::label $f.sep -text "   "
   436         set engines(selection) [lindex [.enginelist.list.list curselection] 0]
   440         set engines(selection) ""
   444     pack $f.add $f.edit $f.delete -side left -padx 1
   449     wm protocol $w WM_DELETE_WINDOW "destroy $w"
   450     bind $w <F1> { helpWindow Analysis List }
   451     bind $w <Escape> "destroy $w"
   452     bind $w.list.list <Return> "$w.buttons.ok invoke; break"
   453     set engines(selection) ""
   456     return $engines(selection)
   465 proc ::enginelist::setTime {index {time -1}} {
   467     set e [
lindex $engines(list) $index]
   468     if {$time < 0} { 
set time [
clock seconds]}
   469     set e [
lreplace $e 5 5 $time]
   470     set engines(list) [
lreplace $engines(list) $index $index $e]
   473 trace variable engines(newElo) w [list ::utils::validate::Integer [
sc_info limit elo] 0]
   478 proc ::enginelist::delete {index} {
   480     if {$index == ""  ||  $index < 0} { 
return}
   481     set e [
lindex $engines(list) $index]
   482     set msg "Name: [
lindex $e 0]\n"
   483     append msg "Command: [
lindex $e 1]\n\n"
   484     append msg "Do you really want to remove this engine from the list?"
   485     set answer [
tk_messageBox -title Scid -icon question -type yesno \
   487     if {$answer == "yes"} {
   488         set engines(list) [
lreplace $engines(list) $index $index]
   498 proc ::enginelist::edit {index} {
   500     if {$index == ""} { 
return}
   502     if {$index >= 0  ||  $index >= [
llength $engines(list)]} {
   503         set e [
lindex $engines(list) $index]
   505         set e [list "" "" "" . 0 0 "" 1]
   508     set engines(newIndex) $index
   509     set engines(newName) [
lindex $e 0]
   510     set engines(newCmd) [
lindex $e 1]
   511     set engines(newArgs) [
lindex $e 2]
   512     set engines(newDir) [
lindex $e 3]
   513     set engines(newElo) [
lindex $e 4]
   514     set engines(newTime) [
lindex $e 5]
   515     set engines(newURL) [
lindex $e 6]
   516     set engines(newUCI) [
lindex $e 7]
   517     set engines(newUCIoptions) [
lindex $e 8]
   519     set engines(newDate) $::tr(None)
   520     if {$engines(newTime) > 0 } {
   528     set f [ttk::frame $w.f]
   529     pack $f -side top -fill x -expand yes
   531     foreach i {Name Cmd Args Dir URL} {
   532         ttk::label $f.l$i -text $i
   533         if {[
info exists ::tr(Engine$i)]} {
   534             $f.l$i configure -text $::tr(Engine$i)
   536         ttk::entry $f.e$i -textvariable engines(new$i) -width 40
   538         grid $f.l$i -row $row -column 0 -sticky w
   539         grid $f.e$i -row $row -column 1 -sticky we
   543             ttk::button $f.b$i -text "..." -command {
   546                         {"Applications" {".bat" ".exe"} }
   549                     set fName [tk_getOpenFile -initialdir $engines(newDir) \
   550                         -title "Scid: [tr ToolsAnalysis]" -filetypes $ftype]
   552                     set fName [tk_getOpenFile -initialdir $engines(newDir) \
   553                         -title "Scid: [tr ToolsAnalysis]"]
   556                     set engines(newCmd) $fName
   557                     # Set the directory from the executable path if possible:
   558                     set engines(newDir) [file dirname $fName]
   559                     if {$engines(newDir) == ""} [ set engines(newDir) .]
   562             grid $f.b$i -row $row -column 2 -sticky we
   566             ttk::button $f.current -text " . " -command {
   567                 set engines(newDir) .
   569             ttk::button $f.user -text "~/.scid" -command {
   570                 set engines(newDir) $scidUserDir
   573                 $f.user configure -text "scid.exe dir"
   575             grid $f.current -row $row -column 2 -sticky we
   576             grid $f.user -row $row -column 3 -sticky we
   580             ttk::button $f.bURL -text [
tr FileOpen] -command {
   581                 if {$engines(newURL) != ""} { openURL $engines(newURL) }
   583             grid $f.bURL -row $row -column 2 -sticky we
   589     grid columnconfigure $f 1 -weight 1
   591     ttk::checkbutton $f.cbUci -text UCI -variable engines(newUCI) -style Bold.TCheckbutton
   592     ttk::button $f.bConfigUCI -text $::tr(ConfigureUCIengine) -command {
   593         ::uci::uciConfig 2 [ toAbsPath $engines(newCmd) ] $engines(newArgs) \
   594                 [ toAbsPath $engines(newDir) ] $engines(newUCIoptions)
   597 $f.lName configure -font font_Bold
   598     $f.lCmd configure -font font_Bold
   599     $f.lDir configure -font font_Bold
   602     ttk::label $f.lElo -text $::tr(EngineElo)
   603     ttk::entry $f.eElo -textvariable engines(newElo) -justify right -width 5
   605     grid $f.lElo -row $row -column 0 -sticky w
   606     grid $f.eElo -row $row -column 1 -sticky w
   608     grid $f.cbUci -row $row -column 0 -sticky w
   609     grid $f.bConfigUCI -row $row -column 1 -sticky w
   612     ttk::label $f.lTime -text $::tr(EngineTime)
   613     ttk::label $f.eTime -textvariable engines(newDate) -anchor w -width 1
   614     grid $f.lTime -row $row -column 0 -sticky w
   615     grid $f.eTime -row $row -column 1 -sticky we
   616     ttk::button $f.clearTime -text $::tr(Clear) -command {
   617         set engines(newTime) 0
   618         set engines(newDate) $::tr(None)
   620     ttk::button $f.nowTime -text $::tr(Update) -command {
   621         set engines(newTime) [clock seconds]
   622         set engines(newDate) [::enginelist::date $engines(newTime)]
   624     grid $f.clearTime -row $row -column 2 -sticky we
   625     grid $f.nowTime -row $row -column 3 -sticky we
   628     set f [ttk::frame $w.buttons]
   629     ttk::button $f.ok -text OK -command {
   630         if {[string trim $engines(newName)] == ""  ||
   631             [string trim $engines(newCmd)] == ""  ||
   632             [string trim $engines(newDir)] == ""} {
   633             tk_messageBox -title Scid -icon info \
   634                     -message "The Name, Command and Directory fields must not be empty."
   636             set newEntry [list $engines(newName) $engines(newCmd) \
   637                     $engines(newArgs) $engines(newDir) \
   638                     $engines(newElo) $engines(newTime) \
   639                     $engines(newURL) $engines(newUCI) $::uci::newOptions ]
   640             if {$engines(newIndex) < 0} {
   641                 lappend engines(list) $newEntry
   643                 set engines(list) [lreplace $engines(list) \
   644                         $engines(newIndex) $engines(newIndex) $newEntry]
   653     ttk::button $f.cancel -text $::tr(Cancel) -command "destroy $w; raise .enginelist; focus .enginelist"
   654     pack $f -side bottom -fill x
   655     pack $f.cancel $f.ok -side right -padx 2 -pady 2
   656     ttk::label $f.required -font font_Small -text $::tr(EngineRequired)
   657     pack $f.required -side left
   659     bind $w <Return> "$f.ok invoke"
   660     bind $w <Escape> "destroy $w; raise .enginelist; focus .enginelist"
   661     bind $w <F1> { helpWindow Analysis List }
   670     global autoplayDelay autoplayMode annotateMode analysis
   675 if { $autoplayMode == 0 } {
   681 if { $annotateMode } {
   685     if { $::initialAnalysis } {
   693 set ::wentOutOfBook 0
   703 } 
elseif { [
sc_pos isAt end] || ($annotateMode && $::isBatchOpening && ([
sc_pos moveNumber] > $::isBatchOpeningMoves)) } {
   711 if { $annotateMode && $::isBatch } {
   715             if { $gameNo != 0 } {
   721 if { $gameNo < $::batchEnd } {
   728 set ::wentOutOfBook 0
   732 set ::initialAnalysis 1
   748     } 
elseif { $annotateMode && $::isAnnotateVar } {
   754         while { $emptyVar } {
   759 if { [
sc_pos isAt vend] } {
   763                 set lastVar [
sc_var count]
   768 if { $lastVar > 0 } {
   782                     set ::atStartOfLine 1
   798 after $autoplayDelay autoplay
   801 proc startAutoplay { } {
   806 proc setAnnotateModeButtonValue { value } {
   808    .analysisWin1.b1.annotate configure -image tb_annotate
   809    .analysisWin1.b1.annotate state !pressed
   811    .analysisWin1.b1.annotate configure -image tb_annotate_on
   812    .analysisWin1.b1.annotate state pressed
   814     set ::annotateModeButtonValue $value
   817 proc cancelAutoplay {} {
   821     after cancel autoplay
   826 proc configAnnotation {n} {
   827     global autoplayDelay tempdelay blunderThreshold annotateModeButtonValue
   829     set w .configAnnotation
   832 if { [
winfo exists $w] } {
   838     if { ! $annotateModeButtonValue } {
   846 if { ! $annotateModeButtonValue } {
   851     trace variable blunderThreshold w {::utils::validate::Regexp {^[0-9]*\.?[0-9]*$}}
   853     set tempdelay [
expr {int($autoplayDelay / 1000.0)}]
   857     set f [ttk::frame $w.f]
   860     ttk::labelframe $f.analyse -text $::tr(GameReview)
   861     ttk::label $f.analyse.label -text $::tr(AnnotateTime)
   862     ttk::spinbox $f.analyse.spDelay -background white -width 4 -textvariable tempdelay -from 1 -to 999 -increment 1 \
   863         -validate key -validatecommand { return [string is digit %S] }
   864     ttk::radiobutton  $f.analyse.allmoves     -text $::tr(AnnotateAllMoves)     -variable annotateBlunders -value allmoves
   865     ttk::radiobutton  $f.analyse.blundersonly -text $::tr(AnnotateBlundersOnly) -variable annotateBlunders -value blundersonly
   866     ttk::frame $f.analyse.blunderbox
   867     ttk::label $f.analyse.blunderbox.label -text $::tr(BlundersThreshold:)
   868     ttk::spinbox $f.analyse.blunderbox.spBlunder -background white -width 4 -textvariable blunderThreshold \
   869             -from 0.1 -to 3.0 -increment 0.1
   870     ttk::checkbutton $f.analyse.cbBook  -text $::tr(UseBook) -variable ::useAnalysisBook
   873 set bookPath $::scidBooksDir
   874     set bookList [  lsort -dictionary [ glob -nocomplain -directory $bookPath *.bin]]
   877 if { [
llength $bookList] == 0 } {
   878         set ::useAnalysisBook 0
   879         $f.analyse.cbBook configure -state disabled
   885     foreach file  $bookList {
   886         lappend tmp [ 
file tail $file]
   887         if {$::book::lastBook == [ 
file tail $file] } {
   892     ttk::combobox $f.analyse.comboBooks -width 12 -values $tmp
   893     catch { $f.analyse.comboBooks current $idx}
   894     pack $f.analyse.comboBooks -side bottom -anchor w -padx 20
   895     pack $f.analyse.cbBook -side bottom -anchor w
   896     pack $f.analyse.blunderbox.label -side left -padx { 20 0 }
   897     pack $f.analyse.blunderbox.spBlunder -side left -anchor w
   898     pack $f.analyse.blunderbox -side bottom -anchor w
   899     pack $f.analyse.blundersonly -side bottom -anchor w
   900     pack $f.analyse.allmoves  -side bottom -anchor w
   901     pack $f.analyse.label -side left -anchor w
   902     pack $f.analyse.spDelay -side right -anchor e
   903     bind $w <Escape> { .configAnnotation.f.buttons.cancel invoke }
   904     bind $w <Return> { .configAnnotation.f.buttons.ok invoke }
   906     ttk::labelframe   $f.av -text $::tr(AnnotateWhich)
   907     ttk::radiobutton  $f.av.all     -text $::tr(AnnotateAll)   -variable annotateMoves -value all
   908     ttk::radiobutton  $f.av.white   -text $::tr(AnnotateWhite) -variable annotateMoves -value white
   909     ttk::radiobutton  $f.av.black   -text $::tr(AnnotateBlack) -variable annotateMoves -value black
   910     pack $f.av.all $f.av.white $f.av.black -side top -fill x -anchor w
   912     ttk::labelframe   $f.comment -text $::tr(Comments)
   913     ttk::checkbutton  $f.comment.cbAnnotateVar      -text $::tr(AnnotateVariations)         -variable ::isAnnotateVar
   914     ttk::checkbutton  $f.comment.cbShortAnnotation  -text $::tr(ShortAnnotations)           -variable ::isShortAnnotation
   915     ttk::checkbutton  $f.comment.cbAddScore         -text $::tr(AddScoreToShortAnnotations) -variable ::addScoreToShortAnnotations
   916     ttk::checkbutton  $f.comment.cbAddAnnotatorTag  -text $::tr(addAnnotatorTag)            -variable ::addAnnotatorTag
   918 ttk::checkbutton  $f.comment.scoreAll -text $::tr(ScoreAllMoves) -variable scoreAllMoves
   919     ttk::checkbutton  $f.comment.cbMarkTactics -text $::tr(MarkTacticalExercises) -variable ::markTacticalExercises
   920     if {! $::analysis(uci1)} {
   921         set ::markTacticalExercises 0
   922         $f.comment.cbMarkTactics configure -state disabled
   925     pack $f.comment.scoreAll $f.comment.cbAnnotateVar $f.comment.cbShortAnnotation $f.comment.cbAddScore \
   926    $f.comment.cbAddAnnotatorTag $f.comment.cbMarkTactics -fill x -anchor w
   929     ttk::frame $f.buttons
   930     grid $f.analyse -row 0 -column 0 -pady { 0 10 } -sticky nswe -padx { 0 10 }
   931     grid $f.comment -row 0 -column 1 -pady { 0 10 } -sticky nswe -padx { 10 0 }
   932     grid $f.av -row 1 -column 0 -pady { 10 0 } -sticky nswe -padx { 0 10 }
   933     grid $f.batch -row 1 -column 1 -pady { 10 0 } -sticky nswe -padx { 10 0 }
   934     grid $f.buttons -row 2 -column 1 -sticky we
   936     set to [
sc_base numGames $::curr_db]
   937     if {$to <1} { 
set to 1}
   938     ttk::checkbutton $f.batch.cbBatch -text $::tr(AnnotateSeveralGames) -variable ::isBatch
   939     ttk::spinbox $f.batch.spBatchEnd -background white -width 8 -textvariable ::batchEnd \
   940             -from 1 -to $to -increment 1 -validate all -validatecommand { regexp {^[0-9]+$} %P }
   941     ttk::checkbutton $f.batch.cbBatchOpening -text $::tr(FindOpeningErrors) -variable ::isBatchOpening
   942     ttk::spinbox $f.batch.spBatchOpening -background white -width 2 -textvariable ::isBatchOpeningMoves \
   943             -from 10 -to 20 -increment 1 -validate all -validatecommand { regexp {^[0-9]+$} %P }
   944     ttk::label $f.batch.lBatchOpening -text $::tr(moves)
   945     pack $f.batch.cbBatch -side top -anchor w -pady { 0 0 }
   946     pack $f.batch.spBatchEnd -side top -padx 20 -anchor w
   947     pack $f.batch.cbBatchOpening -side top -anchor w
   948     pack $f.batch.spBatchOpening -side left -anchor w -padx { 20 4 }
   949     pack $f.batch.lBatchOpening  -side left
   952     ttk::button $f.buttons.cancel -text $::tr(Cancel) -command {
   953         destroy .configAnnotation
   954         setAnnotateModeButtonValue 0
   955    .analysisWin1.b1.annotate configure -image tb_annotate
   956    .analysisWin1.b1.annotate state !pressed
   958     ttk::button $f.buttons.ok -text "OK" -command {
   959         set ::useAnalysisBookName [.configAnnotation.f.analyse.comboBooks get]
   960         set ::book::lastBook $::useAnalysisBookName
   962         # tactical positions is selected, must be in multipv mode
   963         if {$::markTacticalExercises} {
   964             if { $::analysis(multiPVCount1) < 2} {
   965                 # TODO: Why not put it at the (apparent) minimum of 2?
   967                 set ::analysis(multiPVCount1) 4
   972         if {$tempdelay < 0.1} { set tempdelay 0.1 }
   973         set autoplayDelay [expr {int($tempdelay * 1000)}]
   974         destroy .configAnnotation
   976         setAnnotateModeButtonValue 1
   977    .analysisWin1.b1.annotate configure -image tb_annotate_on
   978         # Tell the analysis mode that we want an initial assessment of the
   979         # position. So: no comments yet, please!
   980         set ::initialAnalysis 1
   981         # And start the time slicer
   984     pack $f.buttons.cancel $f.buttons.ok -side right -padx 5 -pady 5
   985     focus $f.analyse.spDelay
   986     bind $w <Destroy> { focus . }
   992 proc bookAnnotation { {n 1} } {
   995     if {$::annotateMode && $::useAnalysisBook} {
   998         set bn [ 
file join $::scidBooksDir $::useAnalysisBookName]
   999         sc_book load $bn $::analysisBookSlot
  1001         set bookmoves [
sc_book moves $::analysisBookSlot]
  1002         while {[
string length $bookmoves] != 0 && ![
sc_pos isAt vend]} {
  1005             set prevbookmoves $bookmoves
  1006             set bookmoves [
sc_book moves $::analysisBookSlot]
  1008         sc_book close $::analysisBookSlot
  1009         set ::wentOutOfBook 1
  1011         set verboseMoveOutOfBook " $::tr(MoveOutOfBook)"
  1012         set verboseLastBookMove " $::tr(LastBookMove)"
  1015         if { [ 
string match -nocase "*[
sc_game info previousMoveNT]*" $prevbookmoves] != 1 } {
  1016             if {$prevbookmoves != ""} {
  1019                 sc_pos setComment "[
sc_pos getComment]$verboseMoveOutOfBook"
  1023 set theCatch [
catch {
sc_move back 1}]
  1025             sc_pos setComment "[
sc_pos getComment]$verboseLastBookMove"
  1028         if { ! $theCatch } {
  1032         set analysis(prevscore$n)     $analysis(score$n)
  1033         set analysis(prevmoves$n)     $analysis(moves$n)
  1034         set analysis(prevscoremate$n) $analysis(scoremate$n)
  1035         set analysis(prevdepth$n)     $analysis(depth$n)
  1042 proc markExercise { prevscore score nag} {
  1046     if {!$::markTacticalExercises} { 
return 0}
  1050 if {! $::analysis(uci1)} { 
return 0}
  1052     set deltamove [
expr {$score - $prevscore}]
  1054 if { [
expr abs($deltamove)] < $::informant("+/-") } { 
return 0}
  1056 if { [
expr $prevscore * $score] >= 0} {
  1057         if { [
expr abs($prevscore)] > $::informant("++-") } { 
return 0}
  1058         if { [
expr abs($prevscore)] > $::informant("+-") && [
expr abs($score)] < [
expr 2 * abs($prevscore)]} { 
return 0}
  1062 if { [
llength $::analysis(multiPV1)] < 2 } {
  1063         puts "error, not enough PV"
  1066     set sc2 [
lindex [ 
lindex $::analysis(multiPV1) 1] 1]
  1067     if { [
expr abs( $score - $sc2 )] < 1.5 } { 
return 0}
  1071 if { [
expr $score * $sc2] > 0.0 && [
expr abs($score)] > $::informant("+-") && [
expr abs($sc2)] > $::informant("+-") } {
  1076 if {[
sc_pos side] == "white" && $score < [
expr 0.0 - $::informant("+/-")] } { 
return 0}
  1077     if {[
sc_pos side] == "black" && $score > $::informant("+/-") } { 
return 0}
  1080 set pv [ 
lindex [ 
lindex $::analysis(multiPV1) 0] 2]
  1081     set bm0 [
lindex $pv 0]
  1082     foreach depth {1 2 3} {
  1083         set res [ 
sc_pos analyze -time 1000 -hashkb 32 -pawnkb 1 -searchdepth $depth]
  1084         set bm$depth [
lindex $res 1]
  1086     if { $bm0 == $bm1 && $bm0 == $bm2 && $bm0 == $bm3 } {
  1092 set timer {1 2 5 10 50 100 200 1000}
  1094     for {
set t 0} {$t < [
llength $timer]} { 
incr t} {
  1095         set res [
sc_pos analyze -time [
lindex $timer $t] -hashkb 1 -pawnkb 1 -mindepth 0]
  1096         set move_analyze [
lindex $res 1]
  1097         lappend movelist $move_analyze
  1102 for {
set t [
expr [
llength $timer] -1]} {$t >= 0} { 
incr t -1} {
  1103         if { [
lindex $movelist $t] != $bm0 } {
  1108     set difficulty [
expr $t +2]
  1112     sc_pos setComment "****D${difficulty} [
format %.1f $prevscore]->[
format %.1f $score] [
sc_pos getComment]"
  1120 proc addAnnotation { {n 1} } {
  1121     global analysis annotateMoves annotateBlunders annotateMode blunderThreshold scoreAllMoves autoplayDelay
  1127 if { $::initialAnalysis } {
  1128         set ::initialAnalysis 0
  1130         if { $::isBatchOpening && ([
sc_pos moveNumber] < $::isBatchOpeningMoves ) } {
  1133         if { $::addAnnotatorTag } {
  1134             appendAnnotator "$analysis(name1) ([
expr {$autoplayDelay / 1000}] sec)"
  1137         set analysis(prevscore$n)     $analysis(score$n)
  1138         set analysis(prevmoves$n)     $analysis(moves$n)
  1139         set analysis(prevscoremate$n) $analysis(scoremate$n)
  1140         set analysis(prevdepth$n)     $analysis(depth$n)
  1150 set skipEngineLine $::atStartOfLine
  1151     set ::atStartOfLine 0
  1158 if { ! $::wentOutOfBook && $::useAnalysisBook } {
  1171 set moves $analysis(moves$n)
  1173 set moves [regsub -all {\. *} $moves {.}]
  1177 set prevmoves $analysis(prevmoves$n)
  1179 set prevmoves [regsub -all {\. *} $prevmoves {.}]
  1181     set gamemove  [
sc_game info previousMoveNT]
  1185 if { [
expr { [string index $gamemove end] == "#" }] } {
  1186         set analysis(prevscore$n)     $analysis(score$n)
  1187         set analysis(prevmoves$n)     $analysis(moves$n)
  1188         set analysis(prevscoremate$n) $analysis(scoremate$n)
  1189         set analysis(prevdepth$n)     $analysis(depth$n)
  1195 set addClosingLine 0
  1196     if {  [
sc_pos isAt vend] } {
  1197         set addClosingLine 1
  1206 set bestMovePlayed 0
  1207     set bestMoveIsMate 0
  1208     if { $prevmoves != "" } {
  1216         set bestmove [
lindex $prevmoves 0]
  1219         set bestmove [
sc_game info previousMoveNT]
  1222         if { $bestmove == $gamemove } {
  1223             set bestMovePlayed 1
  1228 set bestMoveIsMate [
expr { [string index $bestmove end] == "#" }]
  1234 set skipEngineLine [
expr {$skipEngineLine + $bestMovePlayed}]
  1239 set score $analysis(score$n)
  1243 set prevscore $analysis(prevscore$n)
  1250 if { $bestMovePlayed } {
  1251         set prevscore $score
  1259 set deltamove [
expr {$prevscore - $score}]
  1262 set gameIsLost [
expr {$prevscore < (0.0 - $::informant("++-"))}]
  1266 if { $tomove == "white" } {
  1267         set deltamove [
expr {0.0 - $deltamove}]
  1268         set gameIsLost [
expr {$prevscore > $::informant("++-")}]
  1278     if { $deltamove > $blunderThreshold } {
  1280     } 
elseif { $deltamove > 0 } {
  1284     set absdeltamove [
expr { abs($deltamove) }]
  1286     set exerciseMarked 0
  1290 set engine_name  [
string map {"-" " " "+" " "} $analysis(name$n)]
  1294 if { $analysis(scoremate$n) != 0 } {
  1295         set text [
format "%d:M%d" $analysis(depth$n) $analysis(scoremate$n)]
  1297         set text [
format "%d:%+.2f" $analysis(depth$n) $score]
  1301 if { $analysis(prevscoremate$n) != 0 } {
  1302         set prevtext [
format "%d:M%d" $analysis(prevdepth$n) $analysis(prevscoremate$n)]
  1304         set prevtext [
format "%d:%+.2f" $analysis(prevdepth$n) $prevscore]
  1310 if { ( $annotateMoves == "white"  &&  $tomove == "white" ||
  1311            $annotateMoves == "black"  &&  $tomove == "black"   ) && ! $addClosingLine } {
  1312         set analysis(prevscore$n)     $analysis(score$n)
  1313         set analysis(prevmoves$n)     $analysis(moves$n)
  1314         set analysis(prevscoremate$n) $analysis(scoremate$n)
  1315         set analysis(prevdepth$n)     $analysis(depth$n)
  1319 if { $scoreAllMoves } {
  1332 if {  (  $annotateBlunders == "blundersonly"
  1333           && ($isBlunder > 1 || ($isBlunder > 0 && [
expr abs($score)] >= 327.0))
  1335        || ($annotateBlunders == "allmoves") } {
  1336         if { $isBlunder > 0 } {
  1339 if {       $absdeltamove > $::informant("??") } {
  1340                 set exerciseMarked [ 
markExercise $prevscore $score "??"]
  1341             } 
elseif { $absdeltamove > $::informant("?")  } {
  1342                 set exerciseMarked [ 
markExercise $prevscore $score "?"]
  1343             } 
elseif { $absdeltamove > $::informant("?!") } {
  1346         } 
elseif { $absdeltamove > $::informant("!?") } {
  1352 if { ! $::isShortAnnotation } {
  1353             sc_pos setComment "[
sc_pos getComment] $engine_name: $text"
  1354         } 
elseif { $::addScoreToShortAnnotations || $scoreAllMoves } {
  1364 if { $skipEngineLine == 0 } {
  1366             if { $annotateBlunders == "blundersonly" } {
  1369 if { [
string first "D" "[
sc_pos getNags]"] == -1 } {
  1373             if { $prevmoves != ""} {
  1378 if { ! $bestMoveIsMate } {
  1379                     if { ! $::isShortAnnotation || $::addScoreToShortAnnotations } {
  1380                         sc_pos setComment "$prevtext"
  1386 if { $analysis(prevscoremate$n) == 0 } {
  1394         if { $isBlunder == 0 && $absdeltamove > $::informant("!?") } {
  1397         if { $scoreAllMoves } { 
  1404     if { $addClosingLine } {
  1408         if { $analysis(scoremate$n) == 0 } {
  1409             if { ! $::isShortAnnotation || $::addScoreToShortAnnotations } {
  1410                 sc_pos setComment "$text"
  1414         if { $analysis(scoremate$n) == 0 } {
  1422     set analysis(prevscore$n)     $analysis(score$n)
  1423     set analysis(prevmoves$n)     $analysis(moves$n)
  1424     set analysis(prevscoremate$n) $analysis(scoremate$n)
  1425     set analysis(prevdepth$n)     $analysis(depth$n)
  1431 array set ana_informantList { 0 "+=" 1 "+/-" 2 "+-" 3 "++-" }
  1433 array set ana_nagList  { 0 "=" 1 "+=" 2 "+/-" 3 "+-" 4 "+--" 5 "=" 6 "=+" 7 "-/+" 8 "-+" 9 "--+" }
  1437 proc scoreToNag {score} {
  1438     global ana_informantList ana_nagList
  1440 set tmp [
expr { abs( $score ) }]
  1441     for { 
set i 0} { $i < 4 } { 
incr i} {
  1442         if { $tmp < $::informant("$ana_informantList($i)") } {
  1447 if { $score < 0.0 } {
  1448         set i [
expr {$i + 5}]
  1450     return $ana_nagList($i)
  1455 proc appendAnnotator { s } {
  1457 set extra [
sc_game tags get "Extra"]
  1464 foreach line $extra {
  1465         if { $annot == 1 } {
  1466             lappend nExtra "Annotator \"$line, $s\"\n"
  1468         } 
elseif { $other != "" } {
  1469             lappend nExtra "$other \"$line\"\n"
  1471         } 
elseif {[
string match "Annotator" $line]} {
  1479 if { $annot == 0 } {
  1480         lappend nExtra "Annotator \"$s\"\n"
  1483 sc_game tags set -extra $nExtra
  1488 proc pushAnalysisData { { lastVar } { n 1 } } {
  1490     lappend ::stack [list $analysis(prevscore$n) $analysis(prevscoremate$n) $analysis(prevdepth$n) \
  1491                           $analysis(score$n)     $analysis(scoremate$n)     $analysis(depth$n) \
  1492                           $analysis(prevmoves$n) $analysis(moves$n) $lastVar]
  1497 proc popAnalysisData { { n 1 } } {
  1500 if {[
llength $::stack] == 0} {
  1501         set analysis(prevscore$n) 0
  1502         set analysis(prevscoremate$n) 0
  1503         set analysis(prevdepth$n) 0
  1504         set analysis(score$n) 0
  1505         set analysis(scoremate$n) 0
  1506         set analysis(depth$n) 0
  1507         set analysis(prevmoves$n) ""
  1508         set analysis(moves$n) ""
  1512     set tmp [
lindex $::stack end]
  1513     set analysis(prevscore$n) [
lindex $tmp 0]
  1514     set analysis(prevscoremate$n) [
lindex $tmp 1]
  1515     set analysis(prevdepth$n) [
lindex $tmp 2]
  1516     set analysis(score$n) [
lindex $tmp 3]
  1517     set analysis(scoremate$n) [
lindex $tmp 4]
  1518     set analysis(depth$n) [
lindex $tmp 5]
  1519     set analysis(prevmoves$n) [
lindex $tmp 6]
  1520     set analysis(moves$n) [
lindex $tmp 7]
  1521     set lastVar [
lindex $tmp 8]
  1522     set ::stack [
lreplace $::stack end end]
  1529 proc addAnalysisVariation {{n 1}} {
  1532     if {! [
winfo exists .analysisWin$n]} { 
return}
  1535 if {[
sc_pos isAt vstart]  &&  [
sc_pos isAt vend]} { 
return}
  1539 set addAtEnd [
sc_pos isAt vend]
  1541     set moves $analysis(moves$n)
  1542     if {$analysis(uci$n)} {
  1543         set tmp_moves [ 
lindex [ 
lindex $analysis(multiPV$n) 0] 2]
  1544         set text [
format "\[%s\] %d:%s" $analysis(name$n) $analysis(depth$n) [
scoreToMate $analysis(score$n) $tmp_moves $n]]
  1546         set text [
format "\[%s\] %d:%+.2f" $analysis(name$n) $analysis(depth$n) $analysis(score$n)]
  1551 set lastMove [
sc_game info previousMoveUCI]
  1578 proc addAllVariations {{n 1}} {
  1581     if {! [
winfo exists .analysisWin$n]} { 
return}
  1584 if {[
sc_pos isAt vstart]  &&  [
sc_pos isAt vend]} { 
return}
  1588 set addAtEnd [
sc_pos isAt vend]
  1590     foreach i $analysis(multiPVraw$n) j $analysis(multiPV$n) {
  1591         set moves [
lindex $i 2]
  1593         set tmp_moves [ 
lindex $j 2]
  1594         set text [
format "\[%s\] %d:%s" $analysis(name$n) [
lindex $i 0] [
scoreToMate [
lindex $i 1] $tmp_moves $n]]
  1598 set lastMove [
sc_game info previousMoveUCI]
  1626 proc makeAnalysisMove {{n 1} {comment ""}} {
  1627     regexp {[^[:alpha:]]*(.*?)( .*|$)} $::analysis(moves$n) -> move
  1628     if {![
info exists move]} { 
return 0}
  1630     if { $::analysis(uci$n) } {
  1636     if {$comment != ""} {
  1637         set tmp [
sc_pos getComment]
  1638         if {$tmp != ""} { 
lappend tmp " - "}
  1639         sc_pos setComment "$tmp$comment"
  1651 proc destroyAnalysisWin {{n 1}} {
  1653     global windowsOS analysis annotateMode
  1657     if { $n == 1 && $annotateMode } {
  1662 if {$analysis(after$n) != ""} {
  1663         after cancel $analysis(after$n)
  1667 if {$analysis(pipe$n) == ""} {
  1668         set ::analysisWin$n 0
  1673 if {(!$windowsOS)  &&  $analysis(send_sigint$n)} {
  1674         catch {
exec -- kill -s INT [
pid $analysis(pipe$n)]}
  1679 if {$analysis(uci$n)} {
  1686     catch { 
flush $analysis(pipe$n)}
  1695 catch {
close $analysis(pipe$n)}
  1697     if {$analysis(log$n) != ""} {
  1698         catch {
close $analysis(log$n)}
  1699         set analysis(log$n) ""
  1702     set ::analysisWin$n 0
  1708 proc sendToEngine {n text} {
  1711     catch {
puts $::analysis(pipe$n) $text}
  1719 proc sendMoveToEngine {n move} {
  1722 set move [
string tolower $move]
  1723     if {$::analysis(uci$n)} {
  1727         if {$::analysis(wants_usermove$n)} {
  1738 proc logEngine {n text} {
  1742 if {$::analysis(log_stdout)} {
  1746     if { [ 
info exists ::analysis(log$n)] && $::analysis(log$n) != ""} {
  1747         puts $::analysis(log$n) $text
  1748         catch { 
flush $::analysis(log$n)}
  1751 incr analysis(logCount$n)
  1752         if {$analysis(logCount$n) >= $analysis(logMax)} {
  1753             puts $::analysis(log$n) \
  1754                     "NOTE  : Log file size limit reached; closing log file."
  1755             catch {
close $analysis(log$n)}
  1756             set analysis(log$n) ""
  1764 proc logEngineNote {n text} {
  1774 proc makeAnalysisWin { {n 1} {index -1} {autostart 1}} {
  1775     global analysisWin$n font_Analysis analysisCommand analysis annotateModeButtonValue
  1777     set w ".analysisWin$n"
  1778     if {[
winfo exists $w]} {
  1789         if { $index == "" ||  $index < 0 } { 
return}
  1795 set index [
expr {$n - 1}]
  1798     set n_engines [
llength $::engines(list)]
  1799     if { $index >= $n_engines} {
  1800         if { $n_engines > 0 } {
  1801             tk_messageBox -message "Invalid Engine Number: [
expr $index +1]"
  1810         set annotateModeButtonValue 0
  1813     set engineData [
lindex $::engines(list) $index]
  1814     set analysisName [
lindex $engineData 0]
  1815     set analysisCommand [ 
toAbsPath [
lindex $engineData 1]]
  1816     set analysisArgs [
lindex $engineData 2]
  1817     set analysisDir [ 
toAbsPath [
lindex $engineData 3]]
  1818     set analysis(uci$n) [ 
lindex $engineData 7]
  1822     if {$analysisDir != "."} {
  1824         catch {
cd $analysisDir}
  1828 set open_err [
catch {
set analysis(pipe$n) [open "| [list $analysisCommand] $analysisArgs" "r+"]}]
  1831 if {$oldpwd != ""} { 
catch {
cd $oldpwd}}
  1834         tk_messageBox -title "Scid: error starting analysis" \
  1835                 -icon warning -type ok \
  1836                 -message "Unable to start the program:\n$analysisCommand"
  1842 set analysis(log$n) ""
  1843     if {$analysis(logMax) > 0} {
  1844         if {! [
catch {open [
file join $::scidLogDir "engine$n.log"] w} log]} {
  1845             set analysis(log$n) $log
  1846             logEngine $n "Scid-Engine communication log file"
  1848             logEngine $n "Command: $analysisCommand"
  1849             logEngine $n "Date: [
clock format [
clock seconds]]"
  1851             logEngine $n "This file was automatically generated by Scid."
  1852             logEngine $n "It is rewritten every time an engine is started in Scid."
  1857     set analysis(name$n) $analysisName
  1860 fconfigure $analysis(pipe$n) -buffering line -blocking 0
  1872     bind $w <F1> { helpWindow Analysis }
  1875     $w.bd configure -relief solid -borderwidth 1
  1876     set analysis(showBoard$n) 0
  1877     set analysis(showEngineInfo$n) 0
  1880     pack $w.b1 -side bottom -fill x
  1881     ttk::button $w.b1.automove -image tb_training  -command "toggleAutomove $n"
  1884     ttk::button $w.b1.lockengine -image tb_lockengine -command "toggleLockEngine $n"
  1886     .analysisWin$n.b1.lockengine configure -state disabled
  1888     ttk::button $w.b1.line -image tb_addvar -command "addAnalysisVariation $n"
  1891     ttk::button $w.b1.alllines -image tb_addallvars -command "addAllVariations $n"
  1894     ttk::button $w.b1.move -image tb_addmove -command "makeAnalysisMove $n"
  1897     ttk::spinbox $w.b1.multipv -from 1 -to 8 -increment 1 -textvariable analysis(multiPVCount$n) -state disabled -width 2 \
  1898             -command "changePVSize $n"
  1902 ttk::button $w.b1.bStartStop -image tb_eng_on -command "toggleEngineAnalysis $n"
  1906         set ::finishGameMode 0
  1907         ttk::button $w.b1.bFinishGame -image tb_finish_off -command "toggleFinishGame $n"
  1910     ttk::button $w.b1.showboard -image tb_coords -command "toggleAnalysisBoard $n"
  1913     ttk::button $w.b1.showinfo -image tb_engineinfo -command "toggleEngineInfo $n"
  1917         ttk::button $w.b1.annotate -image tb_annotate -command "configAnnotation $n"
  1920     ttk::button $w.b1.priority -image tb_cpu_hi -command "setAnalysisPriority $w $n"
  1923     ttk::button $w.b1.update -image tb_update -command "if {$analysis(uci$n)} {sendToEngine $n .}"
  1926     ttk::button $w.b1.help -image tb_help -command { helpWindow Analysis }
  1929     pack $w.b1.bStartStop $w.b1.lockengine $w.b1.move $w.b1.line -side left
  1930     if {$analysis(uci$n)} {
  1931    pack $w.b1.alllines -side left
  1934         pack $w.b1.multipv $w.b1.annotate $w.b1.automove $w.b1.bFinishGame -side left
  1936         pack $w.b1.multipv $w.b1.automove -side left
  1938     pack $w.b1.help $w.b1.priority $w.b1.showboard -side right
  1939     if {! $analysis(uci$n)} {
  1940    pack $w.b1.update -side right
  1942    pack $w.b1.showinfo -side right
  1944     if {$analysis(uci$n)} {
  1945         text $w.text -width 60 -height 1 -fg black -bg white -font font_Bold -wrap word -setgrid 1
  1947         text $w.text -width 60 -height 4 -fg black -bg white -font font_Fixed -wrap word -setgrid 1
  1950     text $w.hist.text -width 60 -height 8 -fg black -bg white -font font_Fixed \
  1951             -wrap word -setgrid 1 -yscrollcommand "$w.hist.ybar set"
  1952     $w.hist.text tag configure indent -lmargin2 [font measure font_Fixed "xxxxxxxxxxxx"]
  1953     ttk::scrollbar $w.hist.ybar -command "$w.hist.text yview" -takefocus 0
  1954     pack $w.text -side top -fill both
  1955     pack $w.hist -side top -expand 1 -fill both
  1956     pack $w.hist.ybar -side right -fill y
  1957     pack $w.hist.text -side left -expand 1 -fill both
  1959     bind $w.hist.text <ButtonPress-$::MB3> "toggleMovesDisplay $n"
  1960     $w.text tag configure blue -foreground blue
  1961     $w.text tag configure bold -font font_Bold
  1962     $w.text tag configure small -font font_Small
  1963     $w.hist.text tag configure blue -foreground blue -lmargin2 [font measure font_Fixed "xxxxxxxxxxxx"]
  1964     $w.hist.text tag configure gray -foreground gray
  1965     if {$autostart != 0} {
  1966     $w.text insert end "Please wait a few seconds for engine initialisation (with some engines, you will not see any analysis \
  1967             until the board changes. So if you see this message, try changing the board \
  1968             by moving backward or forward or making a new move.)" small
  1970     $w.text configure -state disabled
  1971     bind $w <Destroy> "if {\[string equal $w %W\]} { destroyAnalysisWin $n }"
  1972     bind $w <Escape> "focus .; destroy $w"
  1973     bind $w <Key-a> "$w.b1.bStartStop invoke"
  1977     set analysis(onUciOk$n) "onUciOk $n $w.b1.multipv $autostart [list [ 
lindex $engineData 8]]"
  1978     if {$analysis(uci$n)} {
  1979         fileevent $analysis(pipe$n) readable "::uci::processAnalysisInput $n"
  1981         fileevent $analysis(pipe$n) readable "processAnalysisInput $n"
  1983     after 1000 "checkAnalysisStarted $n"
  1987 if { !$analysis(uci$n) && $autostart != 0 } {
  1998 proc onUciOk {{n} {multiPv_spin} {autostart} {uci_options}} {
  1999     foreach opt $::analysis(uciOptions$n) {
  2000         if { [
lindex $opt 0] == "MultiPV" } {
  2001             set min [
lindex $opt 1]
  2002             set max [
lindex $opt 2]
  2003             $multiPv_spin configure -from $min -to $max -state normal
  2017 proc toggleMovesDisplay { {n 1} } {
  2018     set ::analysis(movesDisplay$n) [
expr 1 - $::analysis(movesDisplay$n)]
  2019     set h .analysisWin$n.hist.text
  2020     $h configure -state normal
  2022     $h configure -state disabled
  2029 proc changePVSize { n } {
  2031     if { $analysis(multiPVCount$n) < [
llength $analysis(multiPV$n)] } {
  2032         set analysis(multiPV$n) {}
  2033         set analysis(multiPVraw$n) {}
  2035     set h .analysisWin$n.hist.text
  2036     if {[
winfo exists $h] && $analysis(multiPVCount$n) == 1} {
  2037         $h configure -state normal
  2039         $h configure -state disabled
  2040         set analysis(lastHistory$n) {}
  2042     if { ! $analysis(uci$n) } { 
return}
  2045 if {$analysis(analyzeMode$n)} {
  2047         set analysis(waitForReadyOk$n) 1
  2049         set dont_stuck [ after 60000 "set ::analysis(waitForReadyOk$n) 0"]
  2050         vwait analysis(waitForReadyOk$n)
  2051         after cancel $dont_stuck
  2052         sendToEngine $n "setoption name MultiPV value $analysis(multiPVCount$n)"
  2055         sendToEngine $n "setoption name MultiPV value $analysis(multiPVCount$n)"
  2063 proc setAnalysisPriority {w n} {
  2067 if {$analysis(pipe$n) == ""} { 
return}
  2068     set pidlist [
pid $analysis(pipe$n)]
  2069     if {[
llength $pidlist] < 1} { 
return}
  2070     set pid [
lindex $pidlist 0]
  2073 set priority "normal"
  2074     if {[
lindex [$w.b1.priority configure -image] end] eq "tb_cpu_hi"} { 
set priority "idle"}
  2075     catch {
sc_info priority $pid $priority}
  2078 if {[
catch {
sc_info priority $pid} newpriority]} { 
return}
  2079     if {$newpriority > 0} {
  2080         $w.b1.priority configure -image tb_cpu
  2081         $w.b1.priority state pressed
  2083         $w.b1.priority configure -image tb_cpu_hi
  2084         $w.b1.priority state !pressed
  2093 proc checkAnalysisStarted {n} {
  2095     if {$analysis(seen$n)} { 
return}
  2104     logEngineNote $n {Quiet engine (still no output); sending it initial commands.}
  2106     if {$analysis(uci$n)} {
  2111         set analysis(seen$n) 1
  2127 proc initialAnalysisStart {n} {
  2132     if { $analysis(processInput$n) == 0 } {
  2133         after 500 initialAnalysisStart $n
  2136     set cl [
clock clicks -milliseconds]
  2137     if {[
expr $cl - $analysis(processInput$n)] < 1000} {
  2138         after 200 initialAnalysisStart $n
  2141     after 200 startEngineAnalysis $n 1
  2148 proc processAnalysisInput {{n 1}} {
  2152 set line [
gets $analysis(pipe$n)]
  2155 set analysis(processInput$n) [
clock clicks -milliseconds]
  2161     if {! $analysis(seen$n)} {
  2162         set analysis(seen$n) 1
  2164 logEngineNote $n {First line from engine seen; sending it initial commands now.}
  2174 if {! [
string compare [
string range $line 0 6] "feature"]} {
  2175         if {[
string match "*analyze=1*" $line]} { 
set analysis(has_analyze$n) 1}
  2176         if {[
string match "*setboard=1*" $line]} { 
set analysis(has_setboard$n) 1}
  2177         if {[
string match "*usermove=1*" $line]} { 
set analysis(wants_usermove$n) 1}
  2178         if {[
string match "*sigint=1*" $line]} { 
set analysis(send_sigint$n) 1}
  2179         if {[
string match "*myname=*" $line] } {
  2181             if { [regexp "myname=\"(\[^\"\]*)\"" $line dummy name]} {
  2183                     catch {
::setTitle .analysisWin$n "Analysis: $name"}
  2185                     catch {
::setTitle .analysisWin$n "Analysis $n: $name"}
  2195 if {! [
string compare [
string range $line 0 5] "Crafty"]} {
  2196         logEngineNote $n {Seen "Crafty"; assuming analyze and setboard commands.}
  2198         if {[
scan $line "Crafty v%d.%d" major minor] == 2  &&  $major >= 18} {
  2199             logEngineNote $n {Crafty version is >= 18.0; assuming scores are from White perspective.}
  2200             set analysis(invertScore$n) 0
  2207         set analysis(isCrafty$n) 1
  2208         set analysis(has_setboard$n) 1
  2209         set analysis(has_analyze$n) 1
  2215 set res [
scan $line "%d%c %d %d %s %\[^\n\]\n" \
  2216             temp_depth dummy temp_score \
  2217             temp_time temp_nodes temp_moves]
  2219         if {$analysis(invertScore$n)  && (![
string compare [
sc_pos side] "black"])} {
  2220             set temp_score [
expr { 0.0 - $temp_score }]
  2222         set analysis(depth$n) $temp_depth
  2223         set analysis(score$n) $temp_score
  2225 set analysis(score$n) [
expr {double($analysis(score$n)) / 100.0}]
  2227         set analysis(time$n) $temp_time
  2231 if {! $analysis(wholeSeconds$n)} {
  2232             set analysis(time$n) [
expr {double($analysis(time$n)) / 100.0}]
  2237         if {! $analysis(seenEval$n)} {
  2240 set analysis(seenEval$n) 1
  2248 if {! [
string compare [
string range $line 0 6] "stat01:"]} {
  2249         if {[
scan $line "%s %d %s %d" \
  2250                     dummy temp_time temp_nodes temp_depth] == 4} {
  2251             set analysis(depth$n) $temp_depth
  2252             set analysis(time$n) $temp_time
  2255 if {! $analysis(wholeSeconds$n)} {
  2256                 set analysis(time$n) [
expr {double($analysis(time$n)) / 100.0}]
  2271 if { !$analysis(wbEngineDetected$n) } {
  2279 proc checkEngineIsAlive { {n 1} } {
  2282     if {$analysis(pipe$n) == ""} { 
return 0}
  2284     if {[
eof $analysis(pipe$n)]} {
  2285         fileevent $analysis(pipe$n) readable {}
  2287         if {[
catch {
close $analysis(pipe$n)} standard_error] != 0} {
  2289             if {"CHILDSTATUS" == [
lindex $errorCode 0]} {
  2290                 set exit_status [
lindex $errorCode 2]
  2293         set analysis(pipe$n) ""
  2294         if { $exit_status != 0 } {
  2295             logEngineNote $n {Engine terminated with exit code $exit_status: "\"$standard_error\""}
  2296             tk_messageBox -type ok -icon info -parent . -title "Scid" \
  2297                           -message "The analysis engine terminated with exit code $exit_status: \"$standard_error\""
  2299             logEngineNote $n {Engine terminated without exit code: "\"$standard_error\""}
  2300             tk_messageBox -type ok -icon info -parent . -title "Scid" \
  2301                           -message "The analysis engine terminated without exit code: \"$standard_error\""
  2303         catch {
destroy .analysisWin$n}
  2314 proc formatAnalysisMoves {text} {
  2317 if {[
strIsPrefix ". " $text]} { 
set text [
string range $text 2 end]}
  2318     if {[
strIsPrefix "t " $text]} { 
set text [
string range $text 2 end]}
  2319     if {[
strIsPrefix "t- " $text]} { 
set text [
string range $text 3 end]}
  2320     if {[
strIsPrefix "t+ " $text]} { 
set text [
string range $text 3 end]}
  2323 set text [
string trim $text]
  2326 regsub -all "H " $text " " text
  2329 regsub "<HT>" $text "{HT}" text
  2334 set finishGameMode 0
  2339 proc toggleFinishGame { { n 1 } } {
  2341    set b ".analysisWin$n.b1.bFinishGame"
  2342    if { $::annotateModeButtonValue || $::autoplayMode } { 
return}
  2343    if { ! $analysis(uci$n) } {
  2344        if { !$analysis(analyzeMode$n) || ! [
sc_pos isAt vend] } { 
return}
  2346        if {!$::finishGameMode} {
  2347            set ::finishGameMode 1
  2348            $b configure -image tb_finish_on
  2349            after $::autoplayDelay autoplayFinishGame
  2351            set ::finishGameMode 0
  2352            $b configure -image tb_finish_off
  2353            after cancel autoplayFinishGame
  2360 if {! [
info exists ::finishGameEng1] } { 
set ::finishGameEng1 1}
  2361    if {! [
info exists ::finishGameEng2] } { 
set ::finishGameEng2 1}
  2362    if {! [
info exists ::finishGameCmd1] } { 
set ::finishGameCmd1 "movetime"}
  2363    if {! [
info exists ::finishGameCmdVal1] } { 
set ::finishGameCmdVal1 5}
  2364    if {! [
info exists ::finishGameCmd2] } { 
set ::finishGameCmd2 "movetime"}
  2365    if {! [
info exists ::finishGameCmdVal2] } { 
set ::finishGameCmdVal2 5}
  2366    if {! [
info exists ::finishGameAnnotate] } { 
set ::finishGameAnnotate 1}
  2367    if {! [
info exists ::finishGameAnnotateShort] } { 
set ::finishGameAnnotateShort 1}
  2378    if {$::finishGameMode} {
  2379        set ::finishGameMode 0
  2381        set analysis(waitForReadyOk1) 0
  2382        set analysis(waitForBestMove1) 0
  2384        set analysis(waitForReadyOk2) 0
  2385        set analysis(waitForBestMove2) 0
  2386        $b configure -image tb_finish_off
  2387        grab release .analysisWin$n
  2388        .analysisWin$n.b1.bStartStop configure -state normal
  2389        .analysisWin$n.b1.move configure -state normal
  2390        .analysisWin$n.b1.line configure -state normal
  2391        .analysisWin$n.b1.alllines configure -state normal
  2392        .analysisWin$n.b1.annotate configure -state normal
  2393        .analysisWin$n.b1.automove configure -state normal
  2397    set w .configFinishGame
  2402    ttk::labelframe $w.wh_f -text "$::tr(White)" -padding 5
  2403    grid $w.wh_f -column 0 -row 0 -columnspan 2 -sticky we -pady 8
  2404    ttk::label $w.wh_f.p -image wk$::board::_size(.main.board)
  2405    grid $w.wh_f.p -column 0 -row 0 -rowspan 3
  2406    ttk::radiobutton $w.wh_f.e1 -text $analysis(name1) -variable ::finishGameEng1 -value 1
  2407    if {[
winfo exists .analysisWin2] && $analysis(uci2) } {
  2408        ttk::radiobutton $w.wh_f.e2 -text $analysis(name2) -variable ::finishGameEng1 -value 2
  2410        set ::finishGameEng1 1
  2411        ttk::radiobutton $w.wh_f.e2 -text $::tr(StartEngine) -variable ::finishGameEng1 -value 2 -state disabled
  2413    grid $w.wh_f.e1 -column 1 -row 0 -columnspan 3 -sticky w
  2414    grid $w.wh_f.e2 -column 1 -row 1 -columnspan 3 -sticky w
  2415    ttk::spinbox $w.wh_f.cv -width 4 -textvariable ::finishGameCmdVal1 -from 1 -to 999
  2416    ttk::radiobutton $w.wh_f.c1 -text $::tr(seconds) -variable ::finishGameCmd1 -value "movetime"
  2417    ttk::radiobutton $w.wh_f.c2 -text $::tr(FixedDepth) -variable ::finishGameCmd1 -value "depth"
  2418    grid $w.wh_f.cv -column 1 -row 2 -sticky w
  2419    grid $w.wh_f.c1 -column 2 -row 2 -sticky w
  2420    grid $w.wh_f.c2 -column 3 -row 2 -sticky w
  2421    grid columnconfigure $w.wh_f 2 -weight 1
  2423    ttk::labelframe $w.bk_f -text "$::tr(Black)" -padding 5
  2424    grid $w.bk_f -column 0 -row 1 -columnspan 2 -sticky we -pady 8
  2425    ttk::label $w.bk_f.p -image bk$::board::_size(.main.board)
  2426    grid $w.bk_f.p -column 0 -row 0 -rowspan 3
  2427    ttk::radiobutton $w.bk_f.e1 -text $analysis(name1) -variable ::finishGameEng2 -value 1
  2428    if {[
winfo exists .analysisWin2] && $analysis(uci2) } {
  2429        ttk::radiobutton $w.bk_f.e2 -text $analysis(name2) -variable ::finishGameEng2 -value 2
  2431        set ::finishGameEng2 1
  2432        ttk::radiobutton $w.bk_f.e2 -text $::tr(StartEngine) -variable ::finishGameEng2 -value 2 -state disabled
  2434    grid $w.bk_f.e1 -column 1 -row 0 -columnspan 3 -sticky w
  2435    grid $w.bk_f.e2 -column 1 -row 1 -columnspan 3 -sticky w
  2436    ttk::spinbox $w.bk_f.cv -width 4 -textvariable ::finishGameCmdVal2 -from 1 -to 999
  2437    ttk::radiobutton $w.bk_f.c1 -text $::tr(seconds) -variable ::finishGameCmd2 -value "movetime"
  2438    ttk::radiobutton $w.bk_f.c2 -text $::tr(FixedDepth) -variable ::finishGameCmd2 -value "depth"
  2439    grid $w.bk_f.cv -column 1 -row 2 -sticky w
  2440    grid $w.bk_f.c1 -column 2 -row 2 -sticky w
  2441    grid $w.bk_f.c2 -column 3 -row 2 -sticky w
  2442    grid columnconfigure $w.bk_f 2 -weight 1
  2444    ttk::checkbutton $w.annotate -text $::tr(Annotate) -variable ::finishGameAnnotate
  2445    grid $w.annotate -column 0 -row 2 -sticky w -padx 5 -pady 8
  2446    ttk::checkbutton $w.annotateShort -text $::tr(ShortAnnotations) -variable ::finishGameAnnotateShort
  2447    grid $w.annotateShort -column 1 -row 2 -sticky w -padx 5 -pady 8
  2449    ttk::frame $w.fbuttons
  2450    ttk::button $w.fbuttons.cancel -text $::tr(Cancel) -command { destroy .configFinishGame }
  2451    ttk::button $w.fbuttons.ok -text "OK" -command {
  2452        if {$::finishGameEng1 == $::finishGameEng2} {
  2453            set ::finishGameMode 1
  2455            set ::finishGameMode 2
  2457        set tmp [sc_pos getComment]
  2458        sc_pos setComment "$tmp $::tr(FinishGame) $::tr(White): $analysis(name$::finishGameEng1) $::tr(Black): $analysis(name$::finishGameEng2)"
  2459        destroy .configFinishGame
  2461    packbuttons right $w.fbuttons.cancel $w.fbuttons.ok
  2462    grid $w.fbuttons -row 3 -column 1 -columnspan 2 -sticky we
  2463    focus $w.fbuttons.ok
  2464    bind $w <Escape> { .configFinishGame.cancel invoke }
  2465    bind $w <Return> { .configFinishGame.ok invoke }
  2466    bind $w <Destroy> { focus .analysisWin1 }
  2467    ::tk::PlaceWindow $w widget .analysisWin1
  2469    bind $w <ButtonPress> {
  2470        set w .configFinishGame
  2471        if {%x < 0 || %x > [winfo width $w] || %y < 0 || %y > [winfo height $w] } { ::tk::PlaceWindow $w pointer }
  2474    if {!$::finishGameMode} { 
return}
  2476    set gocmd(1) "go $::finishGameCmd1 $::finishGameCmdVal1"
  2477    set gocmd(2) "go $::finishGameCmd2 $::finishGameCmdVal2"
  2478    if {$::finishGameCmd1 == "movetime" } { 
append gocmd(1) "000"}
  2479    if {$::finishGameCmd2 == "movetime" } { 
append gocmd(2) "000"}
  2480    if {[
sc_pos side] == "white"} {
  2482        set current_engine $::finishGameEng1
  2485        set current_engine $::finishGameEng2
  2490    $b configure -image tb_finish_on
  2491    .analysisWin$n.b1.bStartStop configure -state disabled
  2492    .analysisWin$n.b1.move configure -state disabled
  2493    .analysisWin$n.b1.line configure -state disabled
  2494    .analysisWin$n.b1.alllines configure -state disabled
  2495    .analysisWin$n.b1.annotate configure -state disabled
  2496    .analysisWin$n.b1.automove configure -state disabled
  2499    while { [
string index [
sc_game info previousMove] end] != "#"} {
  2500        set analysis(waitForReadyOk$current_engine) 1
  2502        vwait analysis(waitForReadyOk$current_engine)
  2503        if {!$::finishGameMode} { break}
  2506        set analysis(fen$current_engine) [
sc_pos fen]
  2507        set analysis(maxmovenumber$current_engine) 0
  2508        set analysis(waitForBestMove$current_engine) 1
  2509        vwait analysis(waitForBestMove$current_engine)
  2510        if {!$::finishGameMode} { break}
  2513        if {$::finishGameAnnotate} {
  2514            set moves [ 
lindex [ 
lindex $analysis(multiPV$current_engine) 0] 2]
  2515            if {$::finishGameAnnotateShort} {
  2516                set text [
format "%d:%+.2f" \
  2517                    $analysis(depth$current_engine) \
  2518                    $analysis(score$current_engine)]
  2521                set text [
format "%d:%+.2f" \
  2522                    $analysis(depth$current_engine) \
  2523                    $analysis(score$current_engine)]
  2526                set moves $analysis(moves$current_engine)
  2537        if {$current_cmd > 2} { 
set current_cmd 1}
  2538        if {$::finishGameMode == 2} {
  2540            if {$current_engine > 2 } { 
set current_engine 1}
  2548 proc autoplayFinishGame { {n 1} } {
  2549     if {!$::finishGameMode || ![
winfo exists .analysisWin$n]} {
return}
  2550     .analysisWin$n.b1.move invoke
  2551     if { [
string index [
sc_game info previousMove] end] == "#"} {
  2555     after $::autoplayDelay autoplayFinishGame
  2561 proc startEngineAnalysis { {n 1} {force 0} } {
  2564     if { !$analysis(analyzeMode$n) } {
  2565         set b ".analysisWin$n.b1.bStartStop"
  2568         $b configure -image tb_eng_off
  2571 .analysisWin$n.b1.lockengine configure -state normal
  2578 proc stopEngineAnalysis { {n 1} } {
  2581     if { $analysis(analyzeMode$n) } {
  2582         set b ".analysisWin$n.b1.bStartStop"
  2585         $b configure -image tb_eng_on
  2588 set analysis(lockEngine$n) 1
  2590         .analysisWin$n.b1.lockengine configure -state disabled
  2597 proc toggleEngineAnalysis { { n 1 } { force 0 } } {
  2601         if { ($::annotateMode || $::finishGameMode) && ! $force } {
  2606     if {$analysis(analyzeMode$n)} {
  2616 proc startAnalyzeMode {{n 1} {force 0}} {
  2620 if {$analysis(analyzeMode$n) && ! $force } { 
return}
  2621     set analysis(analyzeMode$n) 1
  2622     if { $analysis(uci$n) } {
  2625         if {$analysis(has_setboard$n)} {
  2628         if { $analysis(has_analyze$n) } {
  2638 proc stopAnalyzeMode { {n 1} } {
  2640     if {! $analysis(analyzeMode$n)} { 
return}
  2641     set analysis(analyzeMode$n) 0
  2642     if { $analysis(uci$n) } {
  2643         if {$analysis(after$n) != ""} {
  2644             after cancel $analysis(after$n)
  2645             set analysis(after$n) ""
  2648         set analysis(waitForReadyOk$n) 1
  2653     set analysis(fen$n) {}
  2659 proc toggleLockEngine {n} {
  2661     if { $analysis(lockEngine$n) } {
  2662    set analysis(lockEngine$n) 0
  2664    set analysis(lockEngine$n) 1
  2666     if { $analysis(lockEngine$n) } {
  2668         set analysis(lockN$n) [
sc_pos moveNumber]
  2669         set analysis(lockSide$n) [
sc_pos side]
  2670    .analysisWin$n.b1.lockengine state pressed
  2673    .analysisWin$n.b1.lockengine state !pressed
  2675     set w ".analysisWin$n"
  2676     $w.b1.move configure -state $state
  2677     $w.b1.line configure -state $state
  2678     if {$analysis(uci$n)} {
  2679         $w.b1.multipv configure -state $state
  2681     $w.b1.alllines configure -state $state
  2682     $w.b1.automove configure -state $state
  2684         $w.b1.annotate configure -state $state
  2685         $w.b1.bFinishGame configure -state $state
  2693 proc updateAnalysisText {{n 1}} {
  2697     if {$analysis(currmovenumber$n) > $analysis(maxmovenumber$n) } {
  2698         set analysis(maxmovenumber$n) $analysis(currmovenumber$n)
  2700     if {$analysis(time$n) > 0.0} {
  2701         set nps [
expr {round($analysis(nodes$n) / $analysis(time$n))}]
  2703     set score $analysis(score$n)
  2705     set t .analysisWin$n.text
  2706     set h .analysisWin$n.hist.text
  2708     $t configure -state normal
  2711     if { $analysis(uci$n) } {
  2712         if { [
expr abs($score)] >= 327.0 } {
  2713             if { [
catch { 
set tmp [
format "M%d " $analysis(scoremate$n)]}] } {
  2714                 set tmp [
format "%+.1f " $score]
  2717             set tmp [
format "%+.1f " $score]
  2721         $t insert end "[
tr Depth]: "
  2722         if {$analysis(showEngineInfo$n) && $analysis(seldepth$n) != 0} {
  2723             $t insert end [ 
format "%2u/%u " $analysis(depth$n) $analysis(seldepth$n)] small
  2725             $t insert end [ 
format "%2u " $analysis(depth$n)] small
  2727         $t insert end "[
tr Nodes]: "
  2728         $t insert end [ 
format "%6uK (%u kn/s) " $analysis(nodes$n) $nps] small
  2729         $t insert end "[
tr Time]: "
  2730         $t insert end [ 
format "%6.2f s" $analysis(time$n)] small
  2731         if {$analysis(showEngineInfo$n)} {
  2732             $t insert end "\n" small
  2733             $t insert end "[
tr Current]: "
  2734             $t insert end [ 
format "%s (%s/%s) " [
::trans $analysis(currmove$n)] $analysis(currmovenumber$n) $analysis(maxmovenumber$n)] small
  2735             $t insert end "TB Hits: "
  2736             $t insert end [ 
format "%u " $analysis(tbhits$n)] small
  2737             $t insert end "Nps: "
  2738             $t insert end [ 
format "%u n/s " $analysis(nps$n)] small
  2739             $t insert end "Hash Full: "
  2740             set hashfull [
expr {round($analysis(hashfull$n) / 10)}]
  2741             $t insert end [ 
format "%u%% " $hashfull] small
  2742             $t insert end "CPU Load: "
  2743             set cpuload [
expr {round($analysis(cpuload$n) / 10)}]
  2744             $t insert end [ 
format "%u%% " $cpuload] small
  2749         set newStr [
format "Depth:   %6u      Nodes: %6uK (%u kn/s)\n" $analysis(depth$n) $analysis(nodes$n) $nps]
  2750         append newStr [
format "Score: %+8.2f      Time: %9.2f seconds\n" $score $analysis(time$n)]
  2751         $t insert 1.0 $newStr small
  2755     if {$analysis(automove$n)} {
  2756         if {$analysis(automoveThinking$n)} {
  2757             set moves "   Thinking..... "
  2759             set moves "   Your move..... "
  2762         if { ! $analysis(uci$n) } {
  2763             $t insert end $moves blue
  2765         $t configure -state disabled
  2770     if {! $::analysis(movesDisplay$n)}  {
  2771         $h configure -state normal
  2773         $h insert end "     $::tr(ClickHereToSeeMoves)\n" blue
  2775         $h configure -state disabled
  2779     if { $analysis(uci$n) } {
  2780         set moves [ 
lindex [ 
lindex $analysis(multiPV$n) 0] 2]
  2782         set moves $analysis(moves$n)
  2785     $h configure -state normal
  2787     if { $analysis(depth$n) < $analysis(prev_depth$n)  || $analysis(prev_depth$n) == 0 } {
  2793 if { $analysis(uci$n) } {
  2794         if {$cleared} { 
set analysis(multiPV$n) {} 
set analysis(multiPVraw$n) {}}
  2795         if {$analysis(multiPVCount$n) == 1} {
  2797             if {$newhst != $analysis(lastHistory$n) && $moves != ""} {
  2798                 $h insert end [
format "%s (%.2f)\n" $newhst $analysis(time$n)] indent
  2800                 set analysis(lastHistory$n) $newhst
  2805 set pv [
lindex $analysis(multiPV$n) 0]
  2807                 catch { 
set newStr [
format "%2d %s " [
lindex $pv 0] [
scoreToMate $score [
lindex $pv 2] $n]]}
  2809                 $h insert end "1 " gray
  2811                 $h insert end $newStr blue
  2814                 foreach pv $analysis(multiPV$n) {
  2815                     if {$lineNumber == 1} { 
incr lineNumber continue}
  2816                     $h insert end "$lineNumber " gray
  2817                     set score [
scoreToMate [
lindex $pv 1] [
lindex $pv 2] $n]
  2818                     $h insert end [
format "%2d %s %s (%.2f)\n" [
lindex $pv 0] $score [
addMoveNumbers $n [
::trans [
lindex $pv 2]]] [
lindex $pv 4]] indent
  2826 $h insert end [
format "%2d %+5.2f %s (%.2f)\n" $analysis(depth$n) $score [
::trans $moves] $analysis(time$n)] indent
  2830     $h configure -state disabled
  2831     set analysis(prev_depth$n) $analysis(depth$n)
  2832     if { ! $analysis(uci$n) } {
  2833         $t insert end [
::trans $moves] blue
  2836 $t configure -state disabled
  2844 proc scoreToMate { score pv n } {
  2846     if {$::analysis(lockEngine$n)} {
  2847         return [
format "%+5.2f" $score]
  2850     if { [
string index $pv end] == "#" || [
string index $pv end] == "+" && [
string index $pv end-1] == "+"} {
  2851         set plies [
llength $pv]
  2853         set mate [
expr $plies / 2 + 1]
  2856         if {[
expr $plies % 2] == 0 && [
sc_pos side] == "white" || [
expr $plies % 2] == 1 && [
sc_pos side] == "black"} {
  2859         if {[
sc_pos side] == "white" } {
  2860             if { $sign == "" } {
  2861                 set mate [
expr $plies / 2 + 1]
  2863                 set mate [
expr $plies / 2]
  2866             if { $sign == "" } {
  2867                 set mate [
expr $plies / 2]
  2869                 set mate [
expr $plies / 2 + 1]
  2873         set ret "M$sign$mate"
  2875         set ret [
format "%+5.2f" $score]
  2884 proc addMoveNumbers { e pv } {
  2887     if { $analysis(lockEngine$e) } {
  2888       set n $analysis(lockN$e)
  2889       set turn $analysis(lockSide$e)
  2891       set n [
sc_pos moveNumber]
  2895     if {$::pgn::moveNumberSpaces} {
  2903     if {$turn == "black"} {
  2904         set ret "$n.$spc... [
lindex $pv 0] "
  2908     for {
set i $start} {$i < [
llength $pv]} {
incr i} {
  2909         set m [
lindex $pv $i]
  2910         if { [
expr $i % 2] == 0 && $start == 0 || [
expr $i % 2] == 1 && $start == 1 } {
  2911             append ret "$n.$spc$m "
  2923 proc toggleAnalysisBoard {n} {
  2925     if { $analysis(showBoard$n) } {
  2926         set analysis(showBoard$n) 0
  2927         pack forget .analysisWin$n.bd
  2929    .analysisWin$n.b1.showboard state !pressed
  2931         bind .analysisWin$n <Configure> ""
  2932         set analysis(showBoard$n) 1
  2933         pack .analysisWin$n.bd -side right -before .analysisWin$n.b1 -padx 4 -pady 4 -anchor n
  2935         .analysisWin$n.hist.text configure -setgrid 0
  2936         .analysisWin$n.text configure -setgrid 0
  2937         set x [
winfo reqwidth .analysisWin$n]
  2938         set y [
winfo reqheight .analysisWin$n]
  2939         wm geometry .analysisWin$n ${x}x${y}
  2940         .analysisWin$n.hist.text configure -setgrid 1
  2941         .analysisWin$n.text configure -setgrid 1
  2942    .analysisWin$n.b1.showboard state pressed
  2949 proc toggleEngineInfo {n} {
  2951     if { $analysis(showEngineInfo$n) } {
  2952    set analysis(showEngineInfo$n) 0
  2953         .analysisWin$n.text configure -height 1
  2954    .analysisWin$n.b1.showinfo state !pressed
  2956    set analysis(showEngineInfo$n) 1
  2957         .analysisWin$n.text configure -height 2
  2958    .analysisWin$n.b1.showinfo state pressed
  2970 proc updateAnalysisBoard {n moves} {
  2973 if {! $analysis(showBoard$n)} { 
return}
  2975     set bd .analysisWin$n.bd
  2993 proc sendFENtoEngineUCI {engine_n  {delay 0}} {
  2995     set analysis(after$engine_n) ""
  2997     if {$analysis(waitForReadyOk$engine_n) } {
  2999 if {$delay > 250} { 
return}
  3003         set cmd "set ::analysis(after$engine_n) "
  3004         append cmd { [ } " after $delay sendFENtoEngineUCI $engine_n $delay " { ] }
  3005         set analysis(after$engine_n) [
eval [list after idle $cmd]]
  3007         sendToEngine $engine_n "position fen $analysis(fen$engine_n)"
  3017 proc updateAnalysis {{n 1}} {
  3019     if {$analysis(pipe$n) == ""} { 
return}
  3021 if {! $analysis(seen$n)} { 
return}
  3023 if { ! $analysis(analyzeMode$n) } { 
return}
  3025 if { $analysis(lockEngine$n) } { 
return}
  3027     if { $analysis(uci$n) } {
  3028         if {$analysis(after$n) == "" } {
  3029             if { $analysis(fen$n) != "" } { 
sendToEngine $n "stop"}
  3030             set analysis(waitForReadyOk$n) 1
  3032             set analysis(after$n) [after idle "sendFENtoEngineUCI $n"]
  3034         set analysis(fen$n) [
sc_pos fen]
  3035         set analysis(maxmovenumber$n) 0
  3036         set analysis(movelist$n) [
sc_game moves coord list]
  3037         set analysis(nonStdStart$n) [
sc_game startBoard]
  3041         global analysisWin windowsOS
  3046 if {[
catch {
set clicks [
clock clicks -milliseconds]}]} {
  3047             set clicks [
clock clicks]
  3049         set diff [
expr {$clicks - $analysis(lastClicks$n)}]
  3050         if {$diff < 300  &&  $diff >= 0} {
  3051             if {$analysis(after$n) == ""} {
  3052                 set analysis(after$n) [after 300 updateAnalysis $n]
  3056         set analysis(lastClicks$n) $clicks
  3057         set analysis(after$n) ""
  3058         after cancel updateAnalysis $n
  3060         set old_movelist $analysis(movelist$n)
  3061         set movelist [
sc_game moves coord list]
  3062         set analysis(movelist$n) $movelist
  3063         set nonStdStart [
sc_game startBoard]
  3064         set old_nonStdStart $analysis(nonStdStart$n)
  3065         set analysis(nonStdStart$n) $nonStdStart
  3068 if {$analysis(has_analyze$n)} {
  3083 if {$analysis(has_setboard$n)} {
  3095                 set analysis(moves$n) "  Sorry, this game has a non-standard start position."
  3103             set oldlen [
llength $old_movelist]
  3104             set newlen [
llength $movelist]
  3113 if {($newlen == $oldlen + 1) && ($old_movelist == [
lrange $movelist 0 [
expr {$oldlen - 1}]])} {
  3116             } 
elseif {($newlen + 1 == $oldlen) && ($movelist == [
lrange $old_movelist 0 [
expr {$newlen - 1}]])} {
  3121             } 
elseif {$newlen == $oldlen  &&  $old_movelist == $movelist} {
  3128 for {
set i 0} {$i < $oldlen} {
incr i} {
  3131                 foreach m $movelist {
  3148 if {(!$windowsOS)  &&  $analysis(send_sigint$n)} {
  3149                 catch {
exec -- kill -s INT [
pid $analysis(pipe$n)]}
  3153             if { $nonStdStart && ! $analysis(has_setboard$n) } {
  3154                 set analysis(moves$n) "  Sorry, this game has a non-standard start position."
  3158             if {$analysis(has_setboard$n)} {
  3161                 foreach m $movelist {
  3180 trace variable temptime w {::utils::validate::Regexp {^[0-9]*\.?[0-9]*$}}
  3182 proc setAutomoveTime {{n 1}} {
  3183     global analysis temptime dialogResult
  3185     set temptime [
expr {$analysis(automoveTime$n) / 1000.0}]
  3193     ttk::label $w.f.label -text "Set the engine thinking time per move in seconds:"
  3194     pack $w.f.label -side top -pady 5 -padx 5
  3195     ttk::entry $w.f.entry -background white -width 10 -textvariable temptime
  3196     pack $w.f.entry -side top -pady 5
  3197     bind $w.f.entry <Escape> { .apdialog.buttons.cancel invoke }
  3198     bind $w.f.entry <Return> { .apdialog.buttons.ok invoke }
  3203     set b [ttk::frame $w.buttons]
  3204     pack $b -side top -fill x
  3205     ttk::button $b.cancel -text $::tr(Cancel) -command {
  3207         catch {grab release .apdialog}
  3210         set dialogResult Cancel
  3212     ttk::button $b.ok -text "OK" -command {
  3213         catch {grab release .apdialog}
  3214         if {$temptime < 0.1} { set temptime 0.1 }
  3215         set analysis(automoveTime$tempn) [expr {int($temptime * 1000)} ]
  3217         catch {grab release .apdialog}
  3222     pack $b.cancel $b.ok -side right -padx 5 -pady 5
  3225     catch {grab .apdialog}
  3226     tkwait window .apdialog
  3227     if {$dialogResult != "OK"} {
  3233 proc toggleAutomove {{n 1}} {
  3235     .analysisWin1.b1.automove state !pressed
  3236     if { $analysis(automove$n) } {
  3237    set analysis(automove$n) 0
  3240         set analysis(automove$n) 0
  3244         set analysis(automove$n) 1
  3245    .analysisWin1.b1.automove state pressed
  3250 proc cancelAutomove {{n 1}} {
  3252     set analysis(automove$n) 0
  3253     after cancel "automove $n"
  3254     after cancel "automove_go $n"
  3257 proc automove {{n 1}} {
  3258     global analysis autoplayDelay
  3259     if {! $analysis(automove$n)} { 
return}
  3260     after cancel "automove $n"
  3261     set analysis(automoveThinking$n) 1
  3262     after $analysis(automoveTime$n) "automove_go $n"
  3265 proc automove_go {{n 1}} {
  3267     if {$analysis(automove$n)} {
  3269             set analysis(autoMoveThinking$n) 0
  3271             after cancel "automove $n"
  3274             after 1000 "automove $n"
  3282 proc sc_move_add { moves n } {
  3283     if { $::analysis(uci$n) } {
  3286         return [ 
catch { 
sc_move addSan $moves}]
  3292 proc toAbsPath { path } {
  3294     if {[
string index $new 0] == "." } {
  3295         set scidInstallDir [
file dirname [
info nameofexecutable]]
  3296         set new [ 
string replace $new 0 0  $scidInstallDir]