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]