5 namespace eval opening {
9 set fenMovesEvalList {}
11 set allLinesHashList {}
16 set onlyFlaggedLines 0
22 set fenLastStatsUpdate 0
23 set cancelLoadRepertoire 0
25 set lastMainLoopFlipped [
sc_pos side]
34 set displayOpeningStats 1
41 global ::opening::playerBestMove ::opening::opBestMove ::opening::repColor
44 if { [
winfo exists $w] } {
focus $w
return}
45 if { [
winfo exists ".openingWin"] } {
focus ".openingWin"
return}
48 wm title $w $::tr(Repertoiretrainingconfiguration)
50 ttk::frame $w.f0 -relief groove
52 ttk::radiobutton $w.f0.rbRepColorW -value "w" -variable ::opening::repColor -text $::tr(white)
53 ttk::radiobutton $w.f0.rbRepColorB -value "b" -variable ::opening::repColor -text $::tr(black)
54 ttk::radiobutton $w.f0.rbRepColorWB -value "wb" -variable ::opening::repColor -text $::tr(both)
55 pack $w.f0.rbRepColorW $w.f0.rbRepColorB $w.f0.rbRepColorWB -side left -expand yes -fill both
58 ttk::checkbutton $w.f1.cbPlayerBestMove -text $::tr(PlayerBestMove) -variable ::opening::playerBestMove
59 ttk::checkbutton $w.f1.cbOpBestMove -text $::tr(OpponentBestMove) -variable ::opening::opBestMove
60 ttk::checkbutton $w.f1.cbOnlyFlaggedLines -text $::tr(OnlyFlaggedLines) -variable ::opening::onlyFlaggedLines
61 ttk::checkbutton $w.f1.cbResetStats -text $::tr(resetStats) -variable ::opening::resetStats
62 pack $w.f1.cbPlayerBestMove $w.f1.cbOpBestMove $w.f1.cbOnlyFlaggedLines $w.f1.cbResetStats -anchor w -side top
65 ttk::button $w.f2.ok -text $::tr(Continue) -command " destroy $w ; ::opening::openRep"
66 ttk::button $w.f2.cancel -text $::tr(Cancel) -command "focus .; destroy $w"
69 pack $w.f0 $w.f1 $w.f2 -side top -fill both
71 bind $w <F1> { helpWindow OpeningTrainer }
72 bind $w <Escape> "destroy $w"
74 bind $w <Configure> "recordWinSize $w"
80 global ::windows::switcher::base_types ::opening::repColor ::opening::repBase
82 if {$::opening::resetStats} {
83 set ::opening::listStats {}
89 set typeW [lsearch $base_types {Openings for White}]
90 set typeB [lsearch $base_types {Openings for Black}]
91 set typeWB [lsearch $base_types {Openings for either color}]
95 if {$type == $typeW && $repColor == "w" || $type == $typeB && $repColor == "b" || $type == $typeWB && $repColor == "wb"} {
101 if {$repBase == -1} {
102 tk_messageBox -title $::tr(Repertoirenotfound) -type ok -icon warning \
103 -message $::tr(Openfirstrepertoirewithtype)
108 if {$prevBase != $repBase} {
sc_base switch $repBase}
110 if {$prevBase != $repBase} {
116 if { $::opening::movesLoaded == 0 } {
117 tk_messageBox -title $::tr(Repertoirenotfound) -type ok -icon error -message $::tr(ZeroMovesLoaded)
120 if { ! [
sc_base inUse $prevBase] } {
127 sc_game tags set -event $::tr(Openingtrainer)
141 proc loadRep { name } {
142 global ::opening::repBase ::opening::fenMovesEvalList ::opening::allLinesFenList \
143 ::opening::allLinesHashList ::opening::hashList ::opening::onlyFlaggedLines \
144 ::opening::movesLoaded ::opening::cancelLoadRepertoire
147 set cancelLoadRepertoire 0
148 set allLinesFenList {}
149 set allLinesHashList {}
151 set ::curr_db [
sc_base current]
152 progressWindow "Scid" "$::tr(Loadingrepertoire)..." $::tr(Cancel) "::opening::sc_progressBar"
153 for {
set g 1} { $g <= [
sc_base numGames $::curr_db]} {
incr g} {
154 if {$cancelLoadRepertoire} { break}
155 if {$onlyFlaggedLines && ![
sc_base gameflag $::curr_db $g get W] && ![
sc_base gameflag $::curr_db $g get B]} {
158 set fenMovesEvalList {}
164 lappend allLinesFenList $fenMovesEvalList
165 set hashList [lsort -unique $hashList]
166 lappend allLinesHashList $hashList
174 proc sc_progressBar {} {
175 set ::opening::cancelLoadRepertoire 1
181 while {![
sc_pos isAt vend]} {
184 for {
set v 0} {$v<[
sc_var count]} {
incr v} {
197 while {![
sc_pos isAt vend]} {
200 for {
set v 0} {$v<[
sc_var count]} {
incr v} {
218 global ::opening::fenMovesEvalList ::opening::hashList ::opening::movesLoaded
224 set s [
split [
sc_pos fen]]
225 set fen "[
lindex $s 0] [
lindex $s 1] [
lindex $s 2] [
lindex $s 3]"
232 lappend hashList [
sc_pos hash]
235 for {
set i 0} { $i < [
llength $fenMovesEvalList]} {
incr i} {
236 set f [
lindex $fenMovesEvalList $i]
237 if {[
lindex $f 0] == $fen} {
set newFen $fen
set moves [
lindex $f 1]
set newIndex $i break}
242 if {! [
sc_pos isAt vend] } {
247 if {[lsearch $moves $m] == -1 } {
248 lappend moves $m $nag
251 set lmoves [lsearch -all $moves $m]
253 if {[
lindex $moves [
expr $i +1]] != $nag} {
254 puts "redundancy and incoherence $m $nag for $newFen"
260 for {
set v 0} {$v<[
sc_var count]} {
incr v} {
263 set m [
sc_game info previousMove]
264 if {[lsearch $moves $m] == -1 } {
265 lappend moves $m $nag
268 set lmoves [lsearch -all $moves $m]
270 if {[
lindex $moves [
expr $i +1]] != $nag} {
271 puts "var redundancy and incoherence $m $nag for $newFen"
279 if {$newIndex == -1} {
280 lappend fenMovesEvalList [list $fen $moves]
282 lset fenMovesEvalList $newIndex [list $fen $moves]
289 global ::opening::allLinesHashList ::opening::allLinesFenList tCM
291 after cancel ::opening::mainLoop
298 after 1000 ::opening::mainLoop
303 if {[
sc_pos fen] == $::opening::lastMainLoopFen && [
::board::isFlipped .main.board] == $::opening::lastMainLoopFlipped} {
304 after 1000 ::opening::mainLoop
309 set move_done [
sc_game info previousMove]
310 if { $move_done != "" } {
315 if { [
llength $cm] == 0 } {
318 after 1000 ::opening::mainLoop
323 set l [lsearch -all $cm $move_done]
325 if {[
llength $l] == 0} {
326 tk_messageBox -type ok -message $::tr(Movenotinrepertoire) -icon info
328 addStats -good 0 -dubious 0 -absent 1 -total 1
332 after 1000 ::opening::mainLoop
339 if {$::opening::playerBestMove} {
344 set nag [
lindex $cm [
expr $i+1]]
352 set answer [
tk_messageBox -icon question -title $::tr(OutOfOpening) -type yesno \
353 -message "$::tr(yourmoveisnotgood) ($nag) \n $::tr(DoYouWantContinue)"]
357 after 1000 ::opening::mainLoop
383 if {[
llength $cm] != 0} {
386 set ::opening::lastMainLoopFen [
sc_pos fen]
391 after 1000 ::opening::mainLoop
396 proc isGoodMove { n } {
397 if { [lsearch -exact $n "?"] != -1 || [lsearch -exact $n "?!"] != -1 || [lsearch -exact $n "??"] != -1} {
408 global ::opening::allLinesHashList ::opening::allLinesFenList ::opening::lastCMFen
412 if {$fen == $lastCMFen } {
return $lastCM}
417 for {
set i 0} {$i<[
llength $allLinesHashList]} {
incr i} {
418 set res [lsearch -sorted [
lindex $allLinesHashList $i] [
sc_pos hash]]
419 if {$res != -1} {
lappend linesFound $i}
423 set fen "[
lindex $s 0] [
lindex $s 1] [
lindex $s 2] [
lindex $s 3]"
424 foreach i $linesFound {
425 set line [
lindex $allLinesFenList $i]
427 if {[
lindex $f 0] == $fen} {
set cm [
concat $cm [
lindex $f 1]]}
441 set r [
expr int(rand()*[
llength $cm]/2)]
442 set m [
lindex $cm [
expr $r * 2]]
444 if {[
sc_pos moveNumber] == 1 && [
sc_pos side] == "white"} {
456 global ::opening::displayCM ::opening::displayCMValue ::opening::tCM ::opening::fenLastUpdate
459 if {[
winfo exists $w]} {
focus $w
return}
462 wm title $w $::tr(Openingtrainer)
465 ttk::frame $w.f2 -relief raised
468 ttk::checkbutton $w.f1.cbDisplayCM -text $::tr(DisplayCM) -variable ::opening::displayCM \
469 -command "set fenLastUpdate 0 ; ::opening::update_tCM 1"
470 ttk::checkbutton $w.f1.cbDisplayCMValue -text $::tr(DisplayCMValue) -variable ::opening::displayCMValue \
471 -command "set fenLastUpdate 0 ; ::opening::update_tCM 1"
472 ttk::label $w.f1.lCM -textvariable ::opening::tCM
473 pack $w.f1.cbDisplayCM $w.f1.cbDisplayCMValue -anchor w -side top
474 pack $w.f1.lCM -side top -anchor w -pady "0 3" -padx 20
476 ttk::checkbutton $w.f2.cbDisplayStats -text $::tr(DisplayOpeningStats) -variable ::opening::displayOpeningStats \
477 -command "::opening::updateStats 1"
478 ttk::label $w.f2.lStats1 -textvariable ::opening::lStats1 -width 4 -anchor center -background green
479 ttk::label $w.f2.lStats2 -textvariable ::opening::lStats2 -width 4 -anchor center -background yellow
480 ttk::label $w.f2.lStats3 -textvariable ::opening::lStats3 -width 4 -anchor center -background red
481 ttk::label $w.f2.lStats4 -textvariable ::opening::lStats4 -width 4 -anchor center -background white
483 ttk::label $w.f2.lStats1exp -text $::tr(NumberOfGoodMovesPlayed)
484 ttk::label $w.f2.lStats2exp -text $::tr(NumberOfDubiousMovesPlayed)
485 ttk::label $w.f2.lStats3exp -text $::tr(NumberOfMovesPlayedNotInRepertoire)
486 ttk::label $w.f2.lStats4exp -text $::tr(NumberOfTimesPositionEncountered)
488 grid $w.f2.cbDisplayStats -row 0 -column 0 -columnspan 2 -pady "3 0" -sticky w -padx 10
489 grid $w.f2.lStats4 -row 1 -column 0 -sticky w -padx 5
490 grid $w.f2.lStats1 -row 2 -column 0 -sticky w -padx 5
491 grid $w.f2.lStats2 -row 3 -column 0 -sticky w -padx 5
492 grid $w.f2.lStats3 -row 4 -column 0 -sticky w -padx 5
495 grid $w.f2.lStats4exp -row 1 -column 1 -sticky w -padx 5
496 grid $w.f2.lStats1exp -row 2 -column 1 -sticky w -padx 5
497 grid $w.f2.lStats2exp -row 3 -column 1 -sticky w -padx 5
498 grid $w.f2.lStats3exp -row 4 -column 1 -sticky w -padx 5 -pady "0 5"
500 ttk::button $w.f3.report -textvar ::tr(ShowReport) -command ::opening::report
501 ttk::button $w.f3.close -textvar ::tr(Abort) -command ::opening::endTraining
503 pack $w.f3.report $w.f3.close -side top -anchor center -fill x -pady "5 0"
504 pack $w.f1 $w.f2 $w.f3 -fill x
506 bind $w <F1> { helpWindow OpeningTrainer }
507 bind $w <Escape> "destroy $w"
509 bind $w <Configure> "recordWinSize $w"
515 proc endTraining {} {
516 after cancel ::opening::mainLoop
519 destroy ".openingWin"
524 proc update_tCM { { forceUpdate 0 } } {
525 global ::opening::displayCM ::opening::displayCMValue ::opening::tCM ::opening::fenLastUpdate
528 if {$fenLastUpdate == [
sc_pos fen] && ! $forceUpdate} {
return}
532 if { [
llength $cm] == 0 } {
533 .openingWin.f1.lCM configure -background LightCoral
534 set tCM $::tr(EndOfVar)
535 set fenLastUpdate [
sc_pos fen]
539 if { !$displayCM } {
set tCM ""
set fenLastUpdate 0
return}
541 .openingWin.f1.lCM configure -background linen
545 for {
set x 0} {$x<[
llength $cm]} {
set x [
expr $x+2]} {
546 set m [
lindex $cm $x]
548 if {[
string first $m $tmp] != -1} { continue}
550 set nlist [
lindex $cm [
expr $x+1]]
551 if {$nlist == 0} { continue}
552 if {$displayCMValue} {
558 if {[
expr $x % 3] == 2} {
append tmp "\n"}
561 set fenLastUpdate [
sc_pos fen]
569 if {[
catch {source $optionsFile}]} {
570 ::splash::add "Unable to find the options file: [
file tail $optionsFile]"
572 ::splash::add "Your options file \"[
file tail $optionsFile]\" was found and loaded."
580 if {[
catch {open $optrainerFile w} f]} {
583 puts $f "set ::opening::listStats { $::opening::listStats }"
593 set s [
split [
sc_pos fen]]
594 set fen "[
lindex $s 0] [
lindex $s 1] [
lindex $s 2] [
lindex $s 3]"
597 foreach l $::opening::listStats {
598 if {[
lindex $l 0] == $fen} {
614 proc addStats { args } {
620 for {
set i 0} {$i < [
llength $args]} {
incr i 2} {
621 if {[
lindex $args $i] == "-good"} {
set dx [
lindex $args [
expr $i + 1]] continue}
622 if {[
lindex $args $i] == "-dubious"} {
set dy [
lindex $args [
expr $i + 1]] continue}
623 if {[
lindex $args $i] == "-absent"} {
set dz [
lindex $args [
expr $i + 1]] continue}
624 if {[
lindex $args $i] == "-total"} {
set dt [
lindex $args [
expr $i + 1]] continue}
627 set s [
split [
sc_pos fen]]
628 set fen "[
lindex $s 0] [
lindex $s 1] [
lindex $s 2] [
lindex $s 3]"
631 foreach l $::opening::listStats {
632 if {[
lindex $l 0] == $fen} {
640 set lval [
lindex $l 1]
641 set ::opening::listStats [
lreplace $::opening::listStats $idx $idx [list $fen [list \
642 [
expr [
lindex $lval 0]+$dx] \
643 [
expr [
lindex $lval 1]+$dy] \
644 [
expr [
lindex $lval 2]+$dz] \
645 [
expr [
lindex $lval 3]+$dt]]]]
647 lappend ::opening::listStats [list $fen [list $dx $dy $dz $dt]]
654 proc addStatsPrev { args } {
655 if {[
sc_pos isAt vstart] } {
return}
656 if { ![
catch {
sc_move back}]} {
664 proc updateStats { {force 0} } {
665 global ::opening::fenLastStatsUpdate
668 if {$fenLastStatsUpdate == [
sc_pos fen] && !$force} {
return}
670 set fenLastStatsUpdate [
sc_pos fen]
672 if { $::opening::displayOpeningStats } {
674 set ::opening::lStats1 [
lindex $gs 0]
675 set ::opening::lStats2 [
lindex $gs 1]
676 set ::opening::lStats3 [
lindex $gs 2]
677 set ::opening::lStats4 [
lindex $gs 3]
679 set ::opening::lStats1 " "
680 set ::opening::lStats2 " "
681 set ::opening::lStats3 " "
682 set ::opening::lStats4 " "
689 global ::opening::listStats ::opening::allLinesFenList
690 set w ".openingWin.optrainerreport"
691 if {[
winfo exists $w]} {
focus $w
return}
694 wm title $w $::tr(Openingtrainer)
698 text $w.ft.text -height 10 -width 40 -wrap word -background white
703 ttk::button $w.fclose.close -textvar ::tr(Close) -command "destroy $w"
713 foreach line $allLinesFenList {
714 incr totalPos [
llength $line]
716 set fenLine [
lindex $pos 0]
719 foreach l $listStats {
720 if {$fenLine == [
lindex $l 0]} {
727 set stats [
lindex [
lindex $listStats $idx] 1]
728 if { $stats != "" } {
729 incr success [
lindex $stats 0]
730 incr dubMoves [
lindex $stats 1]
731 incr outOfRep [
lindex $stats 2]
732 incr posTotalPlayed [
lindex $stats 3]
739 $w.ft.text insert end "$::tr(PositionsInRepertoire) $totalPos\n"
740 $w.ft.text insert end "$::tr(PositionsNotPlayed) $posNotPlayed\n"
741 $w.ft.text insert end "$::tr(PositionsPlayed) [
expr $totalPos - $posNotPlayed]\n"
742 $w.ft.text insert end "$::tr(Success) $success\n"
743 $w.ft.text insert end "$::tr(DubiousMoves) $dubMoves\n"
744 $w.ft.text insert end "$::tr(OutOfRepertoire) $outOfRep\n"
746 $w.ft.text configure -state disabled
748 bind $w <F1> { helpWindow OpeningTrainer }
749 bind $w <Escape> "destroy $w"
751 bind $w <Configure> "recordWinSize $w"