8 set server "freechess.org"
24 font create font_offers -family courier -size 12 -weight bold
27 set offers_minelo 1000
28 set offers_maxelo 2500
32 variable isGuestLogin 0
33 array set profileVars {}
34 array set findopponent {}
49 global ::fics::sockChan
52 if {[
winfo exists $w]} {
57 if {[
winfo exists .fics]} {
63 set ::fics::showPass 0
67 ttk::labelframe $w.f -text "Login"
68 ttk::labelframe $w.conf -text $::tr(CCDlgCGeneraloptions)
69 ttk::frame $w.fbuttons
71 ttk::label $w.f.lLogin -text [
::tr "CCDlgLoginName"]
72 ttk::entry $w.f.login -width 20 -textvariable ::fics::login
73 ttk::label $w.f.lPwd -text [
::tr "CCDlgPassword"]
74 ttk::entry $w.f.passwd -width 20 -textvariable ::fics::password -show *
75 ttk::checkbutton $w.f.showPass -text [
::tr "CCDlgShowPassword"] -variable ::fics::showPass -command {
76 if {$::fics::showPass} {
77 .ficsConfig.f.passwd configure -show {}
79 .ficsConfig.f.passwd configure -show *
83 ttk::button $w.fbuttons.connect -text [
::tr "FICSConnect"] -state disabled -command {
84 ::fics::connect [.ficsConfig.f.login get] [.ficsConfig.f.passwd get]
87 ttk::button $w.fbuttons.guest -text [
::tr FICSGuest] -state disabled -command {
88 ::fics::connect "guest" ""
91 ttk::button $w.fbuttons.cancel -text [
::tr "Cancel"] -command { destroy .ficsConfig }
94 grid $w.f.lLogin -column 0 -row $row -sticky w -padx "0 5"
95 grid $w.f.login -column 1 -row $row -sticky w
97 grid $w.f.lPwd -column 0 -row $row -sticky w -padx "0 5"
98 grid $w.f.passwd -column 1 -row $row -sticky w
100 grid $w.f.showPass -column 1 -row $row -sticky w
102 pack $w.f -side top -anchor w -fill x
103 pack $w.conf -side top -anchor w -pady "10 0"
106 ttk::checkbutton $w.conf.cbvars -text [
::tr "FICSdefaultuservars"] -variable ::fics::usedefaultvars
107 grid $w.conf.cbvars -column 0 -row $row -sticky w -columnspan 2
111 ttk::checkbutton $w.conf.premove -text [
::tr "FICSpremove"] -variable ::fics::premoveEnabled
112 grid $w.conf.premove -column 0 -row $row -sticky w -columnspan 2
116 ttk::checkbutton $w.conf.cbts -text "Time seal" -variable ::fics::use_timeseal -onvalue 1 -offvalue 0
117 grid $w.conf.cbts -column 0 -row $row -sticky w
119 ttk::entry $w.conf.eExec -textvariable ::fics::timeseal_exec
120 ttk::button $w.conf.bExec -text "..." -command { set ::fics::timeseal_exec [tk_getOpenFile] }
121 grid $w.conf.eExec -column 0 -row $row -columnspan 2 -sticky we -padx "20 10"
122 grid $w.conf.bExec -column 2 -row $row -sticky w
124 ttk::label $w.conf.lFICS_ip -text [
::tr "FICSServerAddress"]
125 ttk::entry $w.conf.ipserver -width 16 -textvariable ::fics::server_ip -state readonly
126 ttk::button $w.conf.bRefresh -text [
::tr "FICSRefresh"] -command ::fics::getIP
127 ttk::label $w.conf.lFICS_port -text [
::tr "FICSServerPort"]
128 ttk::entry $w.conf.portserver -width 6 -textvariable ::fics::port_fics
129 ttk::label $w.conf.ltsport -text [
::tr "FICSTimesealPort"]
130 ttk::entry $w.conf.portts -width 6 -textvariable ::fics::port_timeseal
132 grid $w.conf.lFICS_ip -column 0 -row $row -sticky w -padx "0 5"
133 grid $w.conf.ipserver -column 1 -row $row -sticky w -padx "0 10"
134 grid $w.conf.bRefresh -column 2 -row $row -sticky w
136 grid $w.conf.lFICS_port -column 0 -row $row -sticky w -padx "0 5"
137 grid $w.conf.portserver -column 1 -row $row -sticky w
139 grid $w.conf.ltsport -column 0 -row $row -sticky w -padx "0 5"
140 grid $w.conf.portts -column 1 -row $row -sticky w
143 pack $w.fbuttons -side top -anchor e
144 packdlgbuttons $w.fbuttons.cancel $w.fbuttons.connect $w.fbuttons.guest
146 bind $w <Escape> "$w.fbuttons.cancel invoke"
147 bind $w <F1> { helpWindow FICSLogin}
150 if { $::fics::server_ip == "0.0.0.0" } {
154 $w.fbuttons.connect configure -state normal
155 $w.fbuttons.guest configure -state normal
162 set b .ficsConfig.conf.bRefresh
163 $b configure -state disabled
166 if { [
catch {
set sockChan [socket -async $::fics::server $::fics::port_fics]} err]} {
167 tk_messageBox -icon error -type ok -title "Unable to contact $::fics::server" -message $err -parent .ficsConfig.f
174 while { $i <= $timeOut } {
177 if { [
catch {
set peer [
fconfigure $sockChan -peername]} err]} {
178 if {$i == $timeOut} {
179 tk_messageBox -icon error -type ok -title "Unable to contact $::fics::server" -message $err -parent .ficsConfig.f
188 set ::fics::server_ip [
lindex $peer 0]
190 $b configure -state normal
195 proc setProfileVars { login } {
196 global ::fics::profileVars
197 if { ! [
info exists profileVars(initTime_$login)] } {
200 set ::fics::findopponent(initTime) $profileVars(initTime_$login)
201 set ::fics::findopponent(incTime) $profileVars(incTime_$login)
202 set ::fics::findopponent(rated) $profileVars(rated_$login)
203 set ::fics::findopponent(color) $profileVars(color_$login)
204 set ::fics::findopponent(limitrating) $profileVars(limitrating_$login)
205 set ::fics::findopponent(rating1) $profileVars(rating1_$login)
206 set ::fics::findopponent(rating2) $profileVars(rating2_$login)
207 set ::fics::findopponent(manual) $profileVars(manual_$login)
208 set ::fics::findopponent(formula) $profileVars(formula_$login)
213 proc syncProfileVars { login } {
214 global ::fics::profileVars
215 variable isGuestLogin
220 set profileVars(initTime_$login) $::fics::findopponent(initTime)
221 set profileVars(incTime_$login) $::fics::findopponent(incTime)
222 set profileVars(rated_$login) $::fics::findopponent(rated)
223 set profileVars(color_$login) $::fics::findopponent(color)
224 set profileVars(limitrating_$login) $::fics::findopponent(limitrating)
225 set profileVars(rating1_$login) $::fics::findopponent(rating1)
226 set profileVars(rating2_$login) $::fics::findopponent(rating2)
227 set profileVars(manual_$login) $::fics::findopponent(manual)
228 set profileVars(formula_$login) $::fics::findopponent(formula)
235 if { [
sc_pos side] == "white" } {
set side 2}
241 proc connect { login passwd } {
242 global ::fics::sockchan ::fics::seeklist ::fics::width ::fics::height ::fics::off
243 variable isGuestLogin
246 set ::fics::reallogin $login
249 if {$login != "guest"} {
250 set ::fics::password $passwd
256 set isGuestLogin [
string match -nocase "guest" $login]
261 if {$::fics::use_timeseal} {
262 if {![
file executable $::fics::timeseal_exec]} {
263 tk_messageBox -title "Error" -icon error -type ok -message "Timeseal exec error : $::fics::timeseal_exec"
270 ::setTitle $w "Free Internet Chess Server $::fics::reallogin"
271 grid [ttk::panedwindow $w.f -orient vertical] -sticky news
272 grid rowconfigure $w 0 -weight 1
273 grid columnconfigure $w 0 -weight 1
275 ttk::notebook $w.f.top
276 ttk::frame $w.f.top.fconsole
277 ttk::frame $w.f.top.fconsole.f1
278 ttk::frame $w.f.top.fconsole.f2
280 ttk::frame $w.f.top.foffers
281 $w.f.top add $w.f.top.fconsole -sticky nsew -text [
::tr "FICSConsole"]
282 $w.f.top add $w.f.top.foffers -sticky nsew -text [
::tr "FICSOffers"]
284 grid $w.f.top.fconsole.f1 -sticky news
285 grid $w.f.top.fconsole.f2 -sticky news
286 grid rowconfigure $w.f.top.fconsole 0 -weight 1
287 grid columnconfigure $w.f.top.fconsole 0 -weight 1
288 ttk::frame $w.f.bottom
290 $w.f add $w.f.top -weight 1
291 $w.f add $w.f.bottom -weight 0
293 ttk::frame $w.f.bottom.left
294 ttk::frame $w.f.bottom.right
295 grid $w.f.bottom.left $w.f.bottom.right -sticky news
298 canvas $w.f.top.foffers.c -background white -width $width -height $height -relief solid
299 grid $w.f.top.foffers.c
300 bind $w.f.top.foffers <Configure> { ::fics::configureCanvas}
302 ttk::scrollbar $w.f.top.fconsole.f1.ysc -command { .fics.f.top.fconsole.f1.console yview }
303 text $w.f.top.fconsole.f1.console -bg $::fics::consolebg -fg $::fics::consolefg -height $::fics::consoleheight -width $::fics::consolewidth \
304 -font font_Fixed -wrap word -yscrollcommand "$w.f.top.fconsole.f1.ysc set"
305 grid $w.f.top.fconsole.f1.console $w.f.top.fconsole.f1.ysc -sticky news
306 grid rowconfigure $w.f.top.fconsole.f1 0 -weight 1
307 grid columnconfigure $w.f.top.fconsole.f1 0 -weight 1
310 $w.f.top.fconsole.f1.console tag configure seeking -foreground $::fics::colseeking
311 $w.f.top.fconsole.f1.console tag configure game -foreground $::fics::colgame
312 $w.f.top.fconsole.f1.console tag configure gameresult -foreground $::fics::colgameresult
313 $w.f.top.fconsole.f1.console tag configure ficspercent -foreground $::fics::colficspercent
314 $w.f.top.fconsole.f1.console tag configure ficshelpnext -foreground $::fics::colficshelpnext -underline 1
316 ttk::entry $w.f.top.fconsole.f2.cmd -width 32
317 ttk::button $w.f.top.fconsole.f2.send -text [
::tr "FICSSend"] -command ::fics::cmd
318 bind $w.f.top.fconsole.f2.cmd <Return> { ::fics::cmd }
319 bind $w.f.top.fconsole.f2.cmd <Up> { ::fics::cmdHistory up ; break }
320 bind $w.f.top.fconsole.f2.cmd <Down> { ::fics::cmdHistory down ; break }
321 bind $w.f.top.fconsole.f2.cmd <Left> " [
bind TEntry <Left>] ; break "
322 bind $w.f.top.fconsole.f2.cmd <Right> " [
bind TEntry <Right>] ; break "
323 grid $w.f.top.fconsole.f2.cmd $w.f.top.fconsole.f2.send -sticky news
324 grid columnconfigure $w.f.top.fconsole.f2 0 -weight 1
331 ttk::checkbutton $w.f.bottom.right.silence -image FICSsilence -variable ::fics::silence -onvalue 0 -offvalue 1 -command {
332 ::fics::writechan "set gin $::fics::silence" "echo"
333 ::fics::writechan "set seek $::fics::silence" "echo"
334 ::fics::writechan "set silence $::fics::silence" "echo"
335 ::fics::writechan "set chanoff [expr ! $::fics::silence ]" "echo"
337 ::utils::tooltip::Set $w.f.bottom.right.silence "[
::tr FICSSilence]\n(set gin 0\nset seek 0\nset silence 0\nset chanoff 1)"
338 set ::fics::silence 1
340 set ::fics::graphon 0
342 ttk::button $w.f.bottom.right.findopp -image FICSsearch -command { ::fics::findOpponent }
344 grid $w.f.bottom.right.findopp -column 0 -row $row -sticky ew -pady 2
345 ttk::button $w.f.bottom.right.relay -image FICSrelayedgames -compound image -command { ::fics::writechan "tell relay listgames"}
347 grid $w.f.bottom.right.relay -column 1 -row $row -sticky ew -pady 2
348 ttk::button $w.f.bottom.right.games -image FICSusers -compound image -command { ::fics::writechan "games /bsu"}
350 grid $w.f.bottom.right.games -column 2 -row $row -sticky ew -pady 2
351 ttk::button $w.f.bottom.right.uno -image FICSunobserve -compound image -command { ::fics::writechan "unobserve"}
353 grid $w.f.bottom.right.uno -column 3 -row $row -sticky ew -pady 2
354 ttk::button $w.f.bottom.right.profile -image FICSprofile -compound image -command { ::fics::writechan "finger" ; ::fics::writechan "history" }
356 grid $w.f.bottom.right.profile -column 4 -row $row -sticky ew -pady 2
360 ttk::button $w.f.bottom.right.draw -image FICSdraw -command { ::fics::writechan "draw"}
362 ttk::button $w.f.bottom.right.resign -image FICSresign -command { ::fics::writechan "resign"}
364 grid $w.f.bottom.right.draw -column 0 -row $row -sticky ew -pady 2
365 grid $w.f.bottom.right.resign -column 1 -row $row -sticky ew -pady 2
366 ttk::button $w.f.bottom.right.abort -image FICSabort -command { ::fics::writechan "abort" }
368 grid $w.f.bottom.right.abort -column 2 -row $row -sticky ew -pady 2
369 grid $w.f.bottom.right.silence -column 4 -row $row -sticky w
372 ttk::button $w.f.bottom.right.takeback -image FICStakeback1 -command { ::fics::writechan "takeback"}
374 ttk::button $w.f.bottom.right.takeback2 -image FICStakeback2 -command { ::fics::writechan "takeback 2"}
377 grid $w.f.bottom.right.takeback -column 0 -row $row -sticky ew -pady 2
378 grid $w.f.bottom.right.takeback2 -column 1 -row $row -sticky ew -pady 2
381 ttk::button $w.f.bottom.right.cancel -image FICSexit -command { ::fics::close }
383 grid $w.f.bottom.right.cancel -column 0 -columnspan 3 -row $row -sticky ew -pady 2
385 bind $w.f.top <<NotebookTabChanged>> { ::fics::tabchanged ; break }
386 bind $w <Destroy> { catch ::fics::close }
388 bind $w <F1> { helpWindow FICS}
389 bind $w.f.top.fconsole.f1.console <FocusIn> "focus $w.f.top.fconsole.f2.cmd"
390 bind $w.f.top.fconsole.f1.console <Configure> { .fics.f.top.fconsole.f1.console yview moveto 1 }
391 bind $w.f.top.fconsole.f1.console <ButtonPress-1> { ::fics::consoleClick %x %y %W }
397 set x [
winfo reqwidth $w]
398 set y [
winfo reqheight $w]
407 if {$::fics::use_timeseal} {
409 if { [
catch {
set timeseal_pid [
exec $::fics::timeseal_exec $::fics::server_ip $::fics::port_fics -p $::fics::port_timeseal &]}] } {
410 set ::fics::use_timeseal 0
411 set port $::fics::port_fics
415 set server "localhost"
416 set port $::fics::port_timeseal
419 set server $::fics::server
420 set port $::fics::port_fics
425 if { [
catch {
set sockchan [socket $server $port]}] } {
426 tk_messageBox -title "Error" -icon error -type ok -message "Network error\nCan't connect to $server $port" -parent .fics
432 fconfigure $sockchan -blocking 0 -buffering line -translation auto
433 fileevent $sockchan readable ::fics::readchan
440 set l [.fics.f.top.fconsole.f2.cmd get]
441 .fics.f.top.fconsole.f2.cmd delete 0 end
447 if {[
string trim $l] == ""} {
return}
449 lappend ::fics::history $l
450 set ::fics::history_pos [
llength $::fics::history]
455 proc cmdHistory { action } {
456 set t .fics.f.top.fconsole.f2.cmd
458 if {$action == "up" && $::fics::history_pos > 0} {
459 incr ::fics::history_pos -1
461 $t insert end [
lindex $::fics::history $::fics::history_pos]
463 if {$action == "down" && $::fics::history_pos < [
expr [
llength $::fics::history] -1] } {
464 incr ::fics::history_pos
466 $t insert end [
lindex $::fics::history $::fics::history_pos]
472 proc findOpponent {} {
474 if {[
winfo exists $w]} {
479 wm title $w [
::tr "FICSFindOpponent"]
482 pack $w.f -side top -anchor w -fill x
483 ttk::label $w.f.linit -text [
::tr "FICSInitialTime"]
484 ttk::spinbox $w.f.sbTime1 -background white -width 3 -textvariable ::fics::findopponent(initTime) -from 0 -to 120 -increment 1 -validate all -validatecommand { regexp {^[0-9]+$} %P }
485 ttk::label $w.f.linc -text [
::tr "FICSIncrement"]
486 ttk::spinbox $w.f.sbTime2 -background white -width 3 -textvariable ::fics::findopponent(incTime) -from 0 -to 120 -increment 1 -validate all -validatecommand { regexp {^[0-9]+$} %P }
487 grid $w.f.linit -column 0 -row 0 -sticky w
488 grid $w.f.sbTime1 -column 1 -row 0 -sticky w -pady "0 2"
489 grid $w.f.linc -column 0 -row 1 -sticky w
490 grid $w.f.sbTime2 -column 1 -row 1 -sticky w
492 ttk::checkbutton $w.f.cbrated -text [
::tr "FICSRatedGame"] -onvalue "rated" -offvalue "unrated" -variable ::fics::findopponent(rated)
493 grid $w.f.cbrated -column 0 -row 2 -columnspan 2 -sticky ew
495 ttk::labelframe $w.f.color -text [
::tr "FICSColour"]
496 grid $w.f.color -column 0 -row 3 -columnspan 2 -sticky ew
497 ttk::radiobutton $w.f.rb1 -text [
::tr "FICSAutoColour"] -value "" -variable ::fics::findopponent(color)
498 ttk::radiobutton $w.f.rb2 -text [
::tr "White"] -value "white" -variable ::fics::findopponent(color)
499 ttk::radiobutton $w.f.rb3 -text [
::tr "Black"] -value "black" -variable ::fics::findopponent(color)
500 pack $w.f.rb1 $w.f.rb2 $w.f.rb3 -side top -anchor w -in $w.f.color
502 ttk::checkbutton $w.f.cblimitrating -text [
::tr "RatingRange"] -variable ::fics::findopponent(limitrating)
503 ttk::spinbox $w.f.sbrating1 -background white -width 4 -textvariable ::fics::findopponent(rating1) -from 1000 -to 3000 -increment 50 -validate all -validatecommand { regexp {^[0-9]+$} %P }
504 ttk::spinbox $w.f.sbrating2 -background white -width 4 -textvariable ::fics::findopponent(rating2) -from 1000 -to 3000 -increment 50 -validate all -validatecommand { regexp {^[0-9]+$} %P }
505 grid $w.f.cblimitrating -column 0 -row 5 -columnspan 2 -sticky ew
506 grid $w.f.sbrating1 -column 0 -row 6 -sticky w
507 grid $w.f.sbrating2 -column 1 -row 6 -sticky w
509 ttk::checkbutton $w.f.cbmanual -text [
::tr "FICSManualConfirm"] -onvalue "manual" -offvalue "auto" -variable ::fics::findopponent(manual)
510 grid $w.f.cbmanual -column 0 -row 7 -columnspan 2 -sticky ew
511 ttk::checkbutton $w.f.cbformula -text [
::tr "FICSFilterFormula"] -onvalue "formula" -offvalue "" -variable ::fics::findopponent(formula)
512 grid $w.f.cbformula -column 0 -row 8 -columnspan 2 -sticky ew
514 ttk::button $w.seek -text [
::tr "FICSIssueSeek"] -command {
515 ::fics::syncProfileVars $::fics::login
518 if {$::fics::findopponent(limitrating) } {
519 set range "$::fics::findopponent(rating1)-$::fics::findopponent(rating2)"
521 set cmd "seek $::fics::findopponent(initTime) $::fics::findopponent(incTime) $::fics::findopponent(rated) \
522 $::fics::findopponent(color) $::fics::findopponent(manual) $::fics::findopponent(formula) $range"
523 ::fics::writechan $cmd
526 ttk::button $w.cancel -text [
::tr "Cancel"] -command "destroy $w"
527 bind $w <F1> { helpWindow FICSfindOpp}
537 if {[
eof $::fics::sockchan]} {
538 fileevent $::fics::sockchan readable {}
539 tk_messageBox -title "FICS" -icon error -type ok -message "Network error reading channel"
546 set line [read $::fics::sockchan]
547 foreach l [
split $line "\n"] {
551 set line [
gets $::fics::sockchan]
552 set line [
string map {"\a" ""} $line]
563 proc parseSoughtLine { l } {
564 global ::fics::offers_minelo ::fics::offers_maxelo ::fics::offers_mintime ::fics::offers_maxtime
567 if {[
string match "fics% *" $l]} {
568 set l [
string range $l 6 end]
571 if { [
catch {
if {[
llength $l] < 8} {
return 0}}] } {
return 0}
575 set ga(game) [
lindex $l 0]
576 if { ! [
string is integer $ga(game)] } {
return 0}
577 set tmp [
lindex $l 1]
578 if { [
scan $tmp "%d" ga(elo)] != 1} {
set ga(elo) $offers_minelo}
579 if { $ga(elo) < $offers_minelo } {
set ga(elo) $offers_minelo}
580 set ga(name) [
lindex $l 2]
582 set tmp [
lindex $l 3]
583 if { [
scan $tmp "%d" ga(time_init)] != 1} {
set ga(time_init) $offers_maxtime}
584 set tmp [
lindex $l 4]
585 if { [
scan $tmp "%d" ga(time_inc)] != 1} {
set ga(time_inc) 0}
587 set ga(rated) [
lindex $l 5]
588 if {$ga(rated) != "rated" && $ga(rated) != "unrated"} {
return 0}
590 set ga(type) [
lindex $l 6]
591 if { $ga(type) != "untimed" && $ga(type) != "blitz" && $ga(type) != "standard" && $ga(type) != "lightning" } {
595 if { [
lindex $l 7] == "\[white\]" || [
lindex $l 7] == "\[black\]" } {
596 set ga(color) [
lindex $l 7]
599 set ga(rating_range) [
lindex $l [
expr 7 + $offset]]
600 if { [
catch {
set ga(start) [
lindex $l [
expr 8 + $offset]]}] } {
604 lappend ::fics::soughtlist [
array get ga]
610 proc readparse {line} {
612 variable isGuestLogin
614 if {$line == "" || $line == "fics% "} {
return}
616 if { $::fics::sought } {
617 if {[
string match "* ad* displayed." $line]} {
628 if {[
string match "login: " $line]} {
630 if { $isGuestLogin} {
635 if {[
string match "password: " $line]} {
640 if {[
string match "<sc>*" $line]} {
641 set ::fics::seeklist {}
644 if {[
string match "<s>*" $line]} {
648 if {[
string match "<sr>*" $line]} {
653 if {[
string match "<12>*" $line]} {
660 if {[
string match "Creating: *" $line]} {
669 set idx1 [
string first "(" $line]
670 set white [
string trim [
string range $line 10 [
expr $idx1 -1]]]
671 set idx2 [
string first ")" $line]
672 set whiteElo [
string trim [
string range $line [
expr $idx1 +1] [
expr $idx2 -1]]]
674 set idx1 [
expr $idx2 +1]
675 set idx2 [
string first "(" $line $idx1]
676 set black [
string trim [
string range $line $idx1 [
expr $idx2 -1]]]
678 set idx1 [
expr $idx2 +1]
679 set idx2 [
string first ")" $line $idx1]
680 set blackElo [
string trim [
string range $line $idx1 [
expr $idx2 -1]]]
682 if { $whiteElo == "++++"} {
set whiteElo 0}
683 if { $blackElo == "++++"} {
set blackElo 0}
686 sc_game tags set -whiteElo $whiteElo
688 sc_game tags set -blackElo $blackElo
690 sc_game tags set -site "FICS freechess.org"
691 sc_game tags set -event "FICS played [
lrange $line 5 6] game"
692 sc_game tags set -extra [list "Timecontrol \"[
lindex $line 7]+[
lindex $line 8]\""]
695 if { [
string match -nocase $white $::fics::reallogin] } {
::board::flip .main.board}
697 if { [
string match -nocase $black $::fics::reallogin] } {
::board::flip .main.board}
700 set ::fics::rated [
string equal [
lindex $line 5] "rated"]
704 set ::fics::showabortreq 1
705 set ::fics::showadjournreq 1
706 set ::fics::showdrawreq 1
707 set ::fics::showtakebackreq 1
711 if {[
string match "\{Game *" $line]} {
712 set num [
lindex [
lindex $line 0] 1]
713 set res [
lindex $line end]
714 set comment [
lrange [
lindex $line 0] 2 end]
715 set n [
string first {)} $comment]
717 set comment [
string range $comment $n+2 end]
720 if {$num == $::fics::observedGame} {
721 if {[
string match "1/2*" $res]} {
722 tk_messageBox -title [
::tr "Result"] -icon info -type ok -message "Draw\n$comment"
724 tk_messageBox -title [
::tr "Result"] -icon info -type ok -message "$res\n$comment"
727 set ::fics::playing 0
728 set ::fics::observedGame -1
736 if { [
string match "You are now observing game*" $line] } {
737 scan $line "You are now observing game %d." ::fics::observedGame
741 if {[
string match "*Starting FICS session*" $line]} {
744 writechan "set interface Scid/$::scidVersion ([tk windowingsystem]; $::tcl_platform(os) $::tcl_platform(machine); rv:$::scidVersionDate) Tcl/Tk [
info patchlevel]"
752 if { $::fics::usedefaultvars } {
763 if { $::fics::waitForRating == "wait" } {
764 if {[
catch {
set val [
lindex $line 0]}]} {
767 if {[
lindex $line 0] == "Standard"} {
768 set ::fics::waitForRating [
lindex $line 1]
774 if { $::fics::waitForMoves != "" } {
779 set line [
string trim $line]
782 if {[
catch {
llength $line} err]} {
783 puts "Exception $err llength $line"
787 if {[
llength $line] == 5 && [
scan $line "%d. %s (%d:%d) %s (%d:%d)" t1 m1 t2 t3 m2 t4 t5] != 7} {
790 if {[
llength $line] == 3 && [
scan $line "%d. %s (%d:%d)" t1 m1 t2 t3] != 4} {
804 if {[
sc_pos fen] == $::fics::waitForMoves } {
805 set ::fics::waitForMoves ""
809 if {[
string match "Challenge:*" $line]} {
810 set ans [
tk_dialog .challenge [
::tr "FICSChallenge"] $line "" 0 [
::tr "FICSAccept"] [
::tr "FICSDecline"]]
823 if {[
string match "* would like to abort the game;*" $line] && $::fics::showabortreq} {
824 set ans [
tk_messageBox -title [
::tr "Abort"] -icon question -type yesnocancel -message "$line\nDo you accept ?"]
828 cancel {
set ::fics::showabortreq 0}
833 if {[
string match "* would like to take back *" $line] && $::fics::showtakebackreq} {
834 set ans [
tk_messageBox -title "Abort" -icon question -type yesnocancel -message "$line\nDo you accept ?"]
838 cancel {
set ::fics::showtakebackreq 0}
843 if {[
string match "*offers you a draw*" $line] && $::fics::showdrawreq} {
844 set ans [
tk_messageBox -title "Abort" -icon question -type yesnocancel -message "$line\nDo you accept ?"]
848 cancel {
set ::fics::showdrawreq 0}
853 if {[
string match "*would like to adjourn the game*" $line] && $::fics::showadjournreq} {
854 set ans [
tk_messageBox -title "Abort" -icon question -type yesnocancel -message "$line\nDo you accept ?"]
858 cancel {
set ::fics::showadjournreq 0}
863 if {[
string match "Logging you in as*" $line]} {
864 set line [
string map {"\"" "" ";" ""} $line]
865 set ::fics::reallogin [
lindex $line 4]
866 ::setTitle .fics "Free Internet Chess Server $::fics::reallogin"
868 if {[
string match "Press return to enter the server as*" $line]} {
876 proc setState { state } {
879 foreach elt [
winfo children $w.f.bottom.right] {
880 if { $elt != "$w.f.bottom.right.cancel" } {
881 $elt configure -state $state
885 foreach elt [list $w.f.top.fconsole.f2.send $w.f.top.fconsole.f2.cmd] {
886 $elt configure -state $state
889 if {$state == "normal" } {
890 $w.f.top add $w.f.top.foffers
892 $w.f.top hide $w.f.top.foffers
898 proc updateConsole {line} {
899 set t .fics.f.top.fconsole.f1.console
901 if { [
string match "* seeking *" $line] } {
902 $t insert end "$line\n" seeking
903 }
elseif { [
string match "\{Game *\}" $line] } {
904 $t insert end "$line\n" game
905 }
elseif { [
string match "\{Game *\} *" $line] } {
906 $t insert end "$line\n" gameresult
907 }
elseif { [
string match "fics% *" $line] } {
908 $t insert end "$line\n" ficspercent
909 }
elseif { $line == "Type \[next\] to see next page." } {
910 $t insert end "Click or type \[next\] to see next page.\n" ficshelpnext
912 $t insert end "$line\n"
915 set pos [
lindex [ .fics.f.top.fconsole.f1.ysc get] 1]
924 proc removeSeek {line} {
925 global ::fics::seeklist
928 if { $l == "<sr>" } {continue}
931 for {
set i 0} {$i < [
llength $seeklist]} {
incr i} {
932 array set a [
lindex $seeklist $i]
933 if {$a(index) == $l} {
934 set seeklist [
lreplace $seeklist $i $i]
940 if { $::fics::graphon } {
941 for {
set idx 0} { $idx < [
llength $::fics::soughtlist]} {
incr idx} {
942 array set g [
lindex $::fics::soughtlist $idx]
945 .fics.f.top.foffers.c delete game_$idx
956 proc parseStyle12 {line} {
957 set color [
lindex $line 9]
958 set gameNumber [
lindex $line 16]
959 set white [
lindex $line 17]
960 set black [
lindex $line 18]
961 set relation [
lindex $line 19]
962 set initialTime [
lindex $line 20]
963 set increment [
lindex $line 21]
964 set whiteMaterial [
lindex $line 22]
965 set blackMaterial [
lindex $line 23]
966 set whiteRemainingTime [
lindex $line 24]
967 set blackRemainingTime [
lindex $line 25]
968 set moveNumber [
lindex $line 26]
969 set verbose_move [
lindex $line 27]
970 set moveTime [
lindex $line 28]
971 set moveSan [
lindex $line 29]
973 set ::fics::playing $relation
974 set ::fics::observedGame $gameNumber
987 for {
set i 1} {$i <=8} {
incr i} {
988 set l [
lindex $line $i]
991 for {
set col 0} { $col < 8 } {
incr col} {
992 set c [
string index $l $col]
1004 if {$count != 0} {
set fen "$fen$count"}
1005 if {$i != 8} {
set fen "$fen/"}
1008 set fen "$fen [
string tolower $color]"
1009 set f [
lindex $line 10]
1012 if { $f == "-1" || $verbose_move == "none"} {
1017 set fl [
string index $conv $f]
1018 if {$color == "W"} {
1019 if { [
string index [
lindex $line 4] [
expr $f - 1]] == "P" || [
string index [
lindex $line 4] [
expr $f + 1]] == "P" } {
1020 set enpassant "${fl}6"
1023 if { [
string index [
lindex $line 5] [
expr $f - 1]] == "p" || [
string index [
lindex $line 5] [
expr $f + 1]] == "p" } {
1024 set enpassant "${fl}3"
1030 if {[
lindex $line 11] == "1"} {
set castle "${castle}K"}
1031 if {[
lindex $line 12] == "1"} {
set castle "${castle}Q"}
1032 if {[
lindex $line 13] == "1"} {
set castle "${castle}k"}
1033 if {[
lindex $line 14] == "1"} {
set castle "${castle}q"}
1034 if {$castle == ""} {
set castle "-"}
1036 set fen "$fen $castle $enpassant [
lindex $line 15] $moveNumber"
1039 if {$moveSan != "none" && $::fics::playing != -1} {
1041 if { ([
sc_pos side] == "white" && $color == "B") || ([
sc_pos side] == "black" && $color == "W") } {
1045 if { [
catch {
sc_move addSan $moveSan} err] } {
1048 if { $::fics::playing == 1 } {
1052 if { [
scan $moveTime "(%d:%d)" t1 t2] == 2} {
1056 if { $::novag::connected } {
1058 if { [
string index $m 1] == "/" } {
set m [
string range $m 2 end]}
1059 set m [
string map { "-" "" "=" "" } $m]
1067 if {$fen != [
sc_pos fen]} {
1074 set ::fics::waitForRating "wait"
1076 vwaitTimed ::fics::waitForRating 2000 "nowarn"
1077 if {$::fics::waitForRating == "wait"} {
set ::fics::waitForRating "0"}
1078 sc_game tags set -white $white
1079 sc_game tags set -whiteElo $::fics::waitForRating
1081 set ::fics::waitForRating "wait"
1083 vwaitTimed ::fics::waitForRating 2000 "nowarn"
1084 if {$::fics::waitForRating == "wait"} {
set ::fics::waitForRating "0"}
1085 sc_game tags set -black $black
1086 sc_game tags set -blackElo $::fics::waitForRating
1088 set ::fics::waitForRating ""
1090 sc_game tags set -site "FICS freechess.org"
1091 sc_game tags set -event "FICS observed game"
1092 sc_game tags set -extra [list "Timecontrol \"$initialTime+$increment\""]
1097 set ::fics::waitForMoves $fen
1098 vwaitTimed ::fics::waitForMoves 2000 "nowarn"
1099 set ::fics::waitForMoves ""
1102 if {$fen != [
sc_pos fen]} {
1111 proc parseSeek {line} {
1112 array set seekelt {}
1113 set seekelt(index) [
lindex $line 1]
1114 foreach m [
split $line] {
1115 if {[
string match "w=*" $m]} {
set seekelt(name_from) [
string range $m 2 end] continue}
1116 if {[
string match "ti=*" $m]} {
set seekelt(titles) [
string range $m 3 end] continue}
1117 if {[
string match "rt=*" $m]} {
set seekelt(rating) [
string range $m 3 end] continue}
1118 if {[
string match "t=*" $m]} {
set seekelt(time) [
string range $m 2 end] continue}
1119 if {[
string match "i=*" $m]} {
set seekelt(increment) [
string range $m 2 end] continue}
1120 if {[
string match "r=*" $m]} {
set seekelt(rated) [
string range $m 2 end] continue}
1121 if {[
string match "tp=*" $m]} {
set seekelt(type) [
string range $m 3 end] continue}
1122 if {[
string match "c=*" $m]} {
set seekelt(color) [
string range $m 2 end] continue}
1123 if {[
string match "rr=*" $m]} {
set seekelt(rating_range) [
string range $m 3 end] continue}
1124 if {[
string match "a=*" $m]} {
set seekelt(automatic) [
string range $m 2 end] continue}
1125 if {[
string match "f=*" $m]} {
set seekelt(formula_checked) [
string range $m 2 end] continue}
1127 lappend ::fics::seeklist [
array get seekelt]
1132 proc updateOffers { } {
1133 set ::fics::sought 1
1134 set ::fics::soughtlist {}
1137 after 3000 ::fics::updateOffers
1142 proc configureCanvas {} {
1143 set w .fics.f.top.foffers
1144 set ::fics::height [
winfo height $w]
1145 set ::fics::width [
winfo width $w]
1146 $w.c configure -width $::fics::width -height $::fics::height
1152 proc displayOffers { } {
1153 global ::fics::width ::fics::height ::fics::off \
1154 ::fics::offers_minelo ::fics::offers_maxelo ::fics::offers_mintime ::fics::offers_maxtime
1155 after cancel ::fics::updateOffers
1157 set w .fics.f.top.foffers
1162 foreach id [ $w.c find all] { $w.c delete $id}
1165 set y_unit [
expr $height / 32.0]
1166 for {
set i 0} {$i < 32} {
incr i} {
1167 set y [
expr $height - $i * $y_unit]
1168 $w.c create line 0 $y $width $y -fill "light gray"
1172 set x1_tick [
expr $width - $off]
1173 set x_text [
expr $width - 2]
1174 foreach elo [list 5 10 15 20 25 30] {
1175 set y [
expr $height - $elo * $y_unit]
1176 $w.c create line $x1_tick $y $width $y -fill black
1177 $w.c create text $x_text $y -fill black -anchor se -text [
expr $elo * 100]
1181 set x_unit [
expr ($width - 3 * $off) / 60.0]
1182 set y2_tick [
expr $height - $off]
1183 foreach t [list 2 5 10 15 30 60] {
1184 set x [
expr $t * $x_unit + $off]
1185 $w.c create line $x $height $x 0 -fill "light gray"
1186 $w.c create line $x $height $x $y2_tick -fill black
1187 $w.c create text [
expr $x + 2] $height -fill black -anchor sw -text "${t}m"
1190 foreach g $::fics::soughtlist {
1194 set tt [
expr $l(time_init) + $l(time_inc) * 2 / 3]
1195 if { $tt > $offers_maxtime } {
1196 set tt $offers_maxtime
1200 if { [
string match "*(C)" $l(name)] } {
1204 if { [
string match "Guest*" $l(name)] } {
1208 set x [
expr $tt * $x_unit + $off]
1209 set y [
expr $height - ($l(elo) / 100.0) * $y_unit]
1211 if { $l(rated) == "rated" } {
1214 set object "rectangle"
1216 $w.c create $object [
expr $x - $size] [
expr $y - $size] [
expr $x + $size] [
expr $y + $size] -tag game_$idx -fill $fillcolor
1218 $w.c bind game_$idx <Enter> "::fics::setOfferStatus $idx %x %y"
1219 $w.c bind game_$idx <Leave> "::fics::setOfferStatus -1 %x %y"
1220 $w.c bind game_$idx <ButtonPress> "::fics::getOffersGame $idx"
1228 proc getOffersGame { idx } {
1229 array set ga [
lindex $::fics::soughtlist $idx]
1235 proc setOfferStatus { idx x y } {
1236 global ::fics::height ::fics::width ::fics::off
1238 set w .fics.f.top.foffers
1240 set gl [
lindex $::fics::soughtlist $idx]
1241 if { $gl == "" } {
return}
1242 array set l [
lindex $::fics::soughtlist $idx]
1243 set m "$l(game) $l(name)($l(elo))\n$l(time_init)/$l(time_inc) $l(rated)\n$l(color) $l(start)"
1245 if {$y < [
expr $height / 2]} {
1251 if {$x < [
expr $width / 2]} {
1257 $w.c create text [
expr $x + $off] $y -tags status -text $m -font font_offers -anchor $anchor
1258 $w.c raise game_$idx
1269 set ::fics::observedGame $index
1274 proc writechan {line {echo "noecho"}} {
1275 after cancel ::fics::stayConnected
1276 if {[
eof $::fics::sockchan]} {
1277 tk_messageBox -title "FICS" -icon error -type ok -message "Network error writing channel"
1281 puts $::fics::sockchan $line
1282 if {$echo != "noecho"} {
1285 after 2700000 ::fics::stayConnected
1291 proc stayConnected {} {
1294 after 2700000 ::fics::stayConnected
1300 proc setPremove {sq1 sq2} {
1301 if { $::fics::premoveEnabled && $::fics::playing == -1 && $sq2 != -1 } {
1302 set ::fics::premoveSq1 $sq1
1303 set ::fics::premoveSq2 $sq2
1312 proc makePremove {} {
1313 if { $::fics::premoveEnabled && $::fics::playing == 1 && $::fics::premoveSq1 != -1 } {
1314 addMove $::fics::premoveSq1 $::fics::premoveSq2
1315 set ::fics::premoveSq1 -1
1321 proc playerCanMove {} {
1323 if { ! [
winfo exists .fics] } {
return 1}
1325 if { [
sc_game info white] == "puzzlebot" || [
sc_game info black] == "puzzlebot" } {
1329 if { $::fics::playing == 1 } {
return 1}
1331 if { $::fics::premoveEnabled && $::fics::playing == -1 } {
1332 .main.board.bd delete mark
1333 set ::fics::premoveSq1 -1
1342 proc consoleClick { x y win } {
1343 set idx [ $win index @$x,$y]
1344 if { [
scan $idx "%d.%d" l c] != 2 } {
1348 set elt [$win get $l.0 $l.end]
1350 if { $elt == "Click or type \[next\] to see next page." } {
1355 regsub -all {\s+} $elt " " elt
1356 set elt [
split $elt " "]
1359 if { [
llength $elt] > 4} {
1361 set game [
lindex $elt 0]
1362 set elow [
lindex $elt 1]
1363 set white [
lindex $elt 2]
1364 set elob [
lindex $elt 3]
1365 set black [
lindex $elt 4]
1367 if { [
scan $game "%d" tmp] != 1 || \
1368 ( [
scan $elow "%d" tmp] != 1 && $elow != "++++" ) || \
1369 ( [
scan $elob "%d" tmp] != 1 && $elob != "++++" ) } {
1376 if { [
llength $elt] == 5 && ! $found } {
1377 if { [
scan [
lindex $elt 0] ":%d" game] == 1 } {
1378 set white [
lindex $elt 1]
1379 set black [
lindex $elt 2]
1387 puts "$elt not a valid game"
1393 set ans [
tk_messageBox -title "Observe game" -icon question -type yesno \
1394 -message "[
::tr FICSObserveconfirm] $game\n$white ($elow) - $black ($elob) ?"]
1395 if { $ans == yes } {
1404 proc tabchanged {} {
1406 set w .fics.f.top.foffers
1408 if { [ $nb select] == $w } {
1410 set ::fics::graphon 1
1412 after cancel ::fics::updateOffers
1413 set ::fics::graphon 0
1419 proc close { {mode ""} } {
1422 bind .fics <Destroy> {}
1424 set ::fics::sought 0
1425 after cancel ::fics::updateOffers
1426 after cancel ::fics::stayConnected
1429 if {$mode != "error"} {
1433 set ::fics::playing 0
1434 set ::fics::observedGame -1
1435 ::close $::fics::sockchan
1436 if { ! $::windowsOS } {
catch {
exec -- kill -s INT [ $::fics::timeseal_pid]}}