[Keith Vetter] : 2006-09-06 : My daughter recently played this game for the first time and wanted to play it some more and I thought it would be fun to write this game. Here it is. [http://mini.net/files/ChineseCheckers.jpg] For a good description of how to play the game, see [http://en.wikipedia.org/wiki/Chinese_Checkers]. ---- ##+########################################################################## # # Chinese Checkers # by Keith Vetter, September 6, 2006 # package require Tk image create photo ::img::b(1) -data { R0lGODlhJwAnALMAANnZ2QeEBxeMFy+XL0ekR1msWWm0aXm8eYnFiZjMmKnTqbjcuMfjx9fr1+j0 6Pr7+iH5BAEAAAAALAAAAAAnACcAAAT/EMhJaQghCAGDlBDISaulIQghxIBjQCFlCAECOWmtIQgB h5xUChFCgEBOWmUQYwxI5KRjjCFECBDISWkQYgxCCCxyFkIIGWMMIWCAQE4qgxCDkFKgkVOWUggh YwwBRQgQyDmDGIOQYuCRcxpTCiFkjAGFCBDIOYUYpBRzEIIoJYTQOceYUggkYwwhAgRygiAGKeYc lGBSSqmUEDrHmAILIWMMEQIEUgYxCCkHJaXgklKplNA5xhQCCRlDiBAAACAMOEgxJym1GGNswaVU SugcYwohA44hQgAABDFIMfAgpRhrrTXGloIqIXSMKYWQMQQUIQAQxCDloKTgYs451xpb/0upBBE6 xhRCxhgiBAiAGISYg9JizcH3nGuMraUSQgcaUwghYwgRQBBwkGIOUos1956DrjW2lkoInWMKLISM MUQIQQxSoDlJLdacc641BtlaKiV0jimFEDikCCGIQYo5ScHFWnOutcbYWgqmhM4xphAyxhAwyDFI MQeptRhsUjK21lIJoXOgMYWQMYYIQYwBSTEHJbUYY40xyNhaSiWEzjGlQELGGEIEMQYpBh6UlFqL McbWWlCplBA6xpRCyIBjCBGCGKSYgxBMSsEl51JKJYTQMQaWQsgYQ4QQxCCQFHNQSkrBJaVSKiWE zjEGFkLIGEOEEMQgkBRzDkoJKjlVSv8JoXOMKbAQQsYYIoQgxoCkFHMOQjDJKRFC5xxjSoGEjDGE CCGIMSQsxpyDEEIpQSTlOceYUgghA44hRAggiDEIKdCYcw5EcqJzzjGmFEIgGWMMEQIAQYwBCSnF GAOPnNQYU0ohhAw4hhAhABCCGINAUooxxsAjJTRSllIIIWOMIWCQAIAgxhiEkAILNHLSUgohhIwx 4BAiBAAACEGMAQchBBYpjZmTEELGGHAIEUKAQMogxBgDEilhkbNAIucYYwghQoBAThCEGGMMSOSk FA4phRAhQCDnDELAISUkclI45BRChACBnDQEIQQcctI6hRAhBAjkpDIEIQQcclIqhAg2IUAgJ60h BCEEHHJOIYQIIQQI5KRVhhACFHJSCYOUEMhJa4VBziAEpRDISaulMMhJAwRyUhoBADs=} set S(sz) [image width ::img::b(1)] array set S {title "Chinese Checkers" pad 10 padx 2} array set G {turn 1 okay 0 ended 0 n,players 6 players {1 2 3 4 5 6}} array set COLORS {bg \#006600 ctrl,bg black ctrl,fg white oval gray50 txt deepskyblue} array set C {1 green 2 yellow 3 blue 4 purple 5 red 6 cyan} proc DoDisplay {} { global S COLORS P wm title . $S(title) GetCorners set w [expr {40 + 2*[lindex $P(2) 0]}] ;# Size based off of board/piece set h [expr {40 + 2*[lindex $P(6) 1]}] frame .ctrl -bd 0 -padx 5 -pady 5 -bg $COLORS(ctrl,bg) pack .ctrl -side right -fill both -ipady 5 MakeCtrlArea DoMenus canvas .c -width $w -height $h -bd 0 -highlightthickness 0 -bg $COLORS(bg) bind .c {ReCenter %W %h %w} pack .c -side top -fill both -expand 1 bind all exit bind all [list console show] } proc DoMenus {} { option add *Menu.tearOff 0 menu .menu . config -menu .menu menu .menu.game .menu add cascade -label "Game" -menu .menu.game -underline 0 .menu.game add command -label "New Game" -command NewGame set m .menu.game.players menu $m .menu.game add cascade -label "Players" -menu $m -underline 0 foreach n {2 4 6} { $m add radio -label "$n Players" \ -variable G(n,players) \ -value $n \ -underline 0 \ -command NewGame } .menu.game add separator .menu.game add command -label "Exit" -command exit menu .menu.help .menu add cascade -label "Help" -menu .menu.help -underline 0 .menu.help add command -label "Help" -command Help -state disabled .menu.help add command -label "About" -command About } proc MakeCtrlArea {} { global S G C COLORS eval destroy [winfo child .ctrl] label .ctrl.title -text Turn -font {Times 42 bold underline} \ -bg $COLORS(ctrl,bg) -fg $COLORS(ctrl,fg) canvas .ctrl.c -bg black -bd 0 -highlightthickness 0 -width 180 grid .ctrl.title -sticky ew -row 1 -pady {0 10} grid .ctrl.c -sticky news -row 2 grid rowconfigure .ctrl 2 -weight 1 .ctrl.c delete all set y [expr {20 + $::S(sz)/2}] foreach who $G(players) { .ctrl.c create image 130 $y -image ::img::b($who) -anchor c .ctrl.c create line 20 $y 100 $y -width 10 -tag [list arrow arrow$who] \ -fill $COLORS(ctrl,bg) -arrow last -arrowshape {16 24 11} \ -capstyle round incr y [expr {20 + $::S(sz)}] } } proc GetCorners {} { global P set P(outer) {} foreach {who cells} { 0 {-9 -1 -9 1} 1 {-5 3 -4 6} 2 {-5 13 -4 14} 3 {-1 9 1 9} 4 {4 14 5 13} 5 {4 6 5 3} 6 {9 1 9 -1} 7 {5 -3 4 -6} 8 {4 -14 5 -13} 9 {1 -9 -1 -9} 10 {-5 -13 -4 -14} 11 {-4 -6 -5 -3} } { foreach {x y} [eval Midpoint $cells] break set x1 [expr {$x * 1.02}] ;# Looks better a bit bigger set y1 [expr {$y * 1.02}] set P($who) [list $x $y] lappend P(outer) $x1 $y1 } set P(-1) $P(11) } proc ShadedText {w xy fg bg args} { foreach {x y} $xy break set cbg [ $w cget -bg ] eval [list $w create text $x $y -fill $bg] $args eval [list $w create text [expr {$x-2}] [expr {$y-2}] -fill $cbg] $args eval [list $w create text [expr {$x-3}] [expr {$y-3}] -fill $fg] $args } proc About {} { set msg "$::S(title)\n\nby Keith Vetter\nSeptember 2006\n" tk_messageBox -title "About $::S(title)" -message $msg } proc NewGame {} { global G if {$G(n,players) == 2} {set a {{1 4} {2 5} {6 3}}} if {$G(n,players) == 4} {set a {{1 3 5} {2 4 6}}} if {$G(n,players) == 6} {set a {{1 2 3 4 5 6}}} set G(players) [lindex $a [expr {int(rand()*[llength $a])}]] InitBoard $G(players) Redraw set G(turn) 0 set G(ended) 0 MakeCtrlArea NextTurn } proc NextTurn {} { global G if {[Victory]} { set G(ended) 1 return } set n [lsearch $G(players) $G(turn)] if {[incr n] >= [llength $G(players)]} {set n 0} set G(turn) [lindex $G(players) $n] .ctrl.c itemconfig arrow -fill $::COLORS(ctrl,bg) .ctrl.c itemconfig arrow$G(turn) -fill $::COLORS(ctrl,fg) } proc Victory {} { global B V G S if {$G(turn) == 0} {return 0} foreach cell $V($G(turn)) { foreach {row col} $cell break set team [lindex $B($row,$col) 0] if {$team != $G(turn)} { return 0 } } .c create text 0 -40 -anchor s -text " Wins! " -font {Times 42 bold} \ -tag victory -fill red foreach {x0 y0 x1 y1} [.c bbox victory] break .c create image 0 $y0 -tag victory -image ::img::b($G(turn)) -anchor s .c create rect $x0 [expr {$y0 - $S(sz) - 2*$S(pad)}] $x1 $y1 \ -fill black -outline red -width 5 .c raise victory return 1 } ##+########################################################################## # # Recenter -- keeps 0,0 at the center of the canvas during resizing # proc ReCenter {W h w} { ;# Called by configure event set h2 [expr {$h / 2}] set w2 [expr {$w / 2}] $W config -scrollregion [list -$w2 -$h2 $w2 $h2] } proc InitBoard {whom} { global B V unset -nocomplain B unset -nocomplain V array set cnts {0 -1 1 -1 2 -1 3 -1 4 -1 5 -1 6 -1} array set opposites {0 0 1 4 2 5 3 6 4 1 5 2 6 3} for {set row -8} {$row < 5} {incr row} { ;# Up triangle set width [expr {(8 + $row)}] for {set col [expr {-$width}]} {$col <= $width} {incr col 2} { set who 0 if {$row <= -5} {set who 1} if {$row > 0 && $row + $col >= 10} { set who 3} if {$row > 0 && $row - $col >= 10} { set who 5} lappend V($opposites($who)) [list $row $col] if {[lsearch $whom $who] == -1} { set who 0} set B($row,$col) [list $who [incr cnts($who)]] } } for {set row 8} {$row > -5} {incr row -1} { ;# Down triangle set width [expr {(8 - $row)}] for {set col [expr {-$width}]} {$col <= $width} {incr col 2} { set who 0 if {$row >= 5} {set who 4} if {$row < 0 && -$row + $col >= 10} { set who 2} if {$row < 0 && -$row - $col >= 10} { set who 6} lappend V($opposites($who)) [list $row $col] if {[lsearch $whom $who] == -1} { set who 0} set B($row,$col) [list $who [incr cnts($who)]] } } } proc Redraw {} { global S B P COLORS .c delete all .c create poly $P(outer) -fill white -outline black -width 9 ShadedText .c [Cell2XY -9.25 -2.5] $COLORS(txt) black -text "Chinese" \ -font {Times 42 bold} -anchor ne ShadedText .c [Cell2XY -9.25 2] $COLORS(txt) black -text "Checkers" \ -font {Times 42 bold} -anchor nw AllHomes foreach arr [lsort -dictionary [array names B]] { foreach {row col} [split $arr ","] break Redraw1 $row $col } .c raise c .c raise txt } proc Redraw1 {row col} { global C B S COLORS set xy [Cell2XY $row $col] set xy2 [eval MakeBox $xy [expr {$S(sz)+2}]] .c create oval $xy2 -tag [list o o$row,$col] -fill {} -outline $COLORS(oval) -width 2 foreach {team id} $B($row,$col) break if {$team > 0} { .c create image $xy -image ::img::b($team) -tag [list c c$team,$id] .c bind c$team,$id [list BDown $team $id %x %y] .c bind c$team,$id [list BMove $team $id %x %y] .c bind c$team,$id [list BUp $team $id %x %y] } #.c create text $xy -text "$row,$col" -tag txt } proc Cell2XY {row col} { global S set x [expr {($S(pad) + $S(sz)) * $col/2}] set y [expr {($S(padx) + $S(sz)) * $row}] return [list $x $y] } proc XY2Cell {x y} { global S set sign [expr {$x < 0 ? -1 : 1}] set row [expr {round($y / double($S(padx) + $S(sz)))}] set col [expr {($x / ($S(pad) + $S(sz)))}] if {$row & 1} { ;# Odd row set col [expr {int($col)*2 + $sign}] } else { ;# Even row set col [expr {2*int((2*$col+$sign)/2)}] } return [list $row $col] } proc Midpoint {r1 c1 r2 c2} { foreach {x1 y1} [Cell2XY $r1 $c1] {x2 y2} [Cell2XY $r2 $c2] break return [list [expr {($x1+$x2)/2}] [expr {($y1+$y2)/2}]] } proc MakeBox {x y diam} { set r [expr {$diam/2}] return [list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]] } proc AllHomes {} { for {set who 1} {$who <= 6} {incr who} { set n [expr {($who-1)*2 - 1}] ;# Starting corner set xy [concat $::P($n) $::P([incr n]) $::P([incr n])] .c create poly $xy -tag home -fill $::C($who) } } proc BDown {team id x y} { ;# Button down global S G B set G(okay) 0 ;# Assume bad if {$G(ended)} return if {$team != $G(turn)} return set G(okay) 1 set xx [.c canvasx $x] set yy [.c canvasy $y] foreach {row col} [XY2Cell $xx $yy] break set G(from) "$row,$col" set G(moves) [LegalMoves $row $col] HighlightMany $G(moves) - - .c raise c$team,$id } proc BMove {team id x y} { if {! $::G(okay)} return set xx [.c canvasx $x] set yy [.c canvasy $y] .c coords c$team,$id $xx $yy foreach {row col} [XY2Cell $xx $yy] break HighlightMany $::G(moves) $row $col } proc BUp {team id x y} { global G B if {! $G(okay)} return Unhighlight foreach {row col} [XY2Cell [.c canvasx $x] [.c canvasy $y]] break if {[lsearch $G(moves) [list $row $col]] != -1} { ;# Legal move set done 1 set B($row,$col) $B($G(from)) ;# Move into new spot set B($G(from)) [list 0 x] ;# Mark old spot empty .c coords c$team,$id [Cell2XY $row $col] NextTurn } else { foreach {row col} [split $G(from) ","] break .c coords c$team,$id [Cell2XY $row $col] } } ##+########################################################################## # # LegalMoves -- returns a list of all positions piece can move to. # recursive calling to handle multiple jumps # proc LegalMoves {row col {onlyJumps 0} {moves {}}} { foreach dir {0 1 2 3 4 5} { foreach {r c} [DoMove $row $col $dir 1] break set team [GetTeam $r $c] if {$team == 0} { ;# Immediate neighbor empty if {! $onlyJumps} { lappend moves [list $r $c] } } elseif {$team != -1} { ;# See if we can jump neighbor foreach {r c} [DoMove $row $col $dir 2] break if {[lsearch $moves [list $r $c]] != -1} continue ;# Already visited if {[GetTeam $r $c] == 0} { ;# Yes, we can jump lappend moves [list $r $c] set moves [LegalMoves $r $c 1 $moves] ;# See about more jumps } } } return $moves } ##+########################################################################## # # DoMove -- return position moved FAR places in direction DIR # proc DoMove {row col dir far} { array set DIRS {0 {0 2} 1 {1 1} 2 {1 -1} 3 {0 -2} 4 {-1 -1} 5 {-1 1}} foreach {dr dc} $DIRS($dir) break set row [expr {$row + $far * $dr}] set col [expr {$col + $far * $dc}] return [list $row $col] } ##+########################################################################## # # GetCell -- returns who's in a given cell, handling off board positions # proc GetCell {row col} { if {! [info exists ::B($row,$col)]} { return -1} return $::B($row,$col) } proc GetTeam {row col} { return [lindex [GetCell $row $col] 0] } proc HighlightMany {who row col} { Unhighlight foreach item $who { foreach {r c} $item break Highlight $r $c [expr {($r == $row && $c == $col) ? 2 : 1}] } } proc Highlight {row col how} { .c itemconfig o$row,$col -width [expr {$how == 1 ? 3 : 6}] -outline red } proc Unhighlight {} { .c itemconfig o -width 2 -outline $::COLORS(oval) } image create photo ::img::b(2) -data { R0lGODlhJwAnALMAANnZ2YSEB4yMF5iXL6SkR6ysWbS0aby8ecTFiczMmNPTqdzcuOTjx+zr1/T0 6Pz7+iH5BAEAAAAALAAAAAAnACcAAAT/EMhJaQghCAGDlBDISaulIQghxIBjQCFlCAECOWmtIQgB h5xUChFCgEBOWmUQYwxI5KRjjCFECBDISWkQYgxCCCxyFkIIGWMMIWCAQE4qgxCDkFKgkVOWUggh YwwBRQgQyDmDGIOQYuCRcxpTCiFkjAGFCBDIOYUYpBRzEIIoJYTQOceYUggkYwwhAgRygiAGKeYc lGBSSqmUEDrHmAILIWMMEQIEUgYxCCkHJaXgklKplNA5xhQCCRlDiBAAACAMOEgxJym1GGNswaVU SugcYwohA44hQgAABDFIMfAgpRhrrTXGloIqIXSMKYWQMQQUIQAQxCDloKTgYs451xpb/0upBBE6 xhRCxhgiBAiAGISYg9JizcH3nGuMraUSQgcaUwghYwgRQBBwkGIOUos1956DrjW2lkoInWMKLISM MUQIQQxSoDlJLdacc641BtlaKiV0jimFEDikCCGIQYo5ScHFWnOutcbYWgqmhM4xphAyxhAwyDFI MQeptRhsUjK21lIJoXOgMYWQMYYIQYwBSTEHJbUYY40xyNhaSiWEzjGlQELGGEIEMQYpBh6UlFqL McbWWlCplBA6xpRCyIBjCBGCGKSYgxBMSsEl51JKJYTQMQaWQsgYQ4QQxCCQFHNQSkrBJaVSKiWE zjEGFkLIGEOEEMQgkBRzDkoJKjlVSv8JoXOMKbAQQsYYIoQgxoCkFHMOQjDJKRFC5xxjSoGEjDGE CCGIMSQsxpyDEEIpQSTlOceYUgghA44hRAggiDEIKdCYcw5EcqJzzjGmFEIgGWMMEQIAQYwBCSnF GAOPnNQYU0ohhAw4hhAhABCCGINAUooxxsAjJTRSllIIIWOMIWCQAIAgxhiEkAILNHLSUgohhIwx 4BAiBAAACEGMAQchBBYpjZmTEELGGHAIEUKAQMogxBgDEilhkbNAIucYYwghQoBAThCEGGMMSOSk FA4phRAhQCDnDELAISUkclI45BRChACBnDQEIQQcctI6hRAhBAjkpDIEIQQcclIqhAg2IUAgJ60h BCEEHHJOIYQIIQQI5KRVhhACFHJSCYOUEMhJa4VBziAEpRDISaulMMhJAwRyUhoBADs=} image create photo ::img::b(3) -data { R0lGODlhJwAnALMAANnZ2QcHhBcXjCcnlDc3nEdIpFlZrGlotHl5vImJxJiYzKam0re22s7O5+jo 9Pr6/CH5BAEAAAAALAAAAAAnACcAAAT/EMhJaQghCAGDlBDISaulIQghxIBjQCFlCAECOWmtIQgx BiRykjGGECEECOSkVQYxBiEEFjkJIWQMIUKAQE5KgxCDkFKgkdOUUgghYwgBAwRyUhmEGKQYA4+c 0hhTCiFjCChCgEDOGcQgpJgDkZzzHGNKIWQMKESAQM4pBCnGHJQSTEqllBBC5xhTICFjCBEgkBME MYg5CCUF1VprKZUSQucYaAohY4gQIJAyiEGKQUmtBZmUaymVEDrHFFgIGUKEAAAAYUBSzEFqLdZa awyytZRKCJ1jSiFwDBECACCIQcyBKK3VWnOttcYWXColdI4xhZAhoAgBgCBIMSipBVlz/8651hpj aymYEjrHlELGECFAAMQg5aCkWGsOvudca42xpVJC8BxTCiFDiACCgIOYg9Jizbn3HHStNcaWSgmh Y6AphIwhQgiCFAMPUou1Bp2UrTXGllIJIXiMKYWMIUIIgsBiDlKLtdaccw221hhbSiWEzjGwFDKG CCEMUsyBKC3GYJNTMsaWSgmhA48phYwhQhCDFGgOSmox2OSUjK2lUkLoQGNKIWMIEcQgBZqDklqL sdZaY5CxtZRKCZ1jTIGFjCFECIIUcxBMSa0FmZxsraVSSugcaEwpZAwRQhCEwGIOSkqtBZmUay2l UkLoHGhKIWQMEUIQg8BiDkJJKbjkXP9KqZQQOsdAUwohY4gQghgEFmMOQilBJadMKSGEzjEGlkLG ECKEIAYhsJhzEEopJaVgkhIhdI4xpRACxxAiBBDEIKUYeA5CCCY5E0IInWNMKbAQMoYIAYAgBoGk GHPOgUhOes4xxpRCCBxDiBAACEEMQmAx5pxzIJISHimNMaUQMsYQMEgAQBBjEFKKgQYeOakxppRC CBlwCBECAACEIMaAhJQCjZTnzFlKIYQMOIQIIUAgZRBiDEJKKQUaOQ0sUhJCxhBChACBnCAIMQYh BBY5qSSEjDGEEDAECOScQYgxBiGEwCInJFKOMYQQIUAgJw1BCDHGgEROCoeUQogQAgRBclIZghAC DjkpFUKEECCQk9YQghACDjmnEEKEEAIEctIqQwgBCjmphEFKCOSktcIgZxCCUgjkpNVSGOSkAQI5 KY0AOw==} image create photo ::img::b(4) -data { R0lGODlhJwAnALMAANnZ2YQHhIwXjJQnlJw3nKRIpKxZrLRotLx5vMSJxMyYzNKm0tq22ufO5/To 9Pz6/CH5BAEAAAAALAAAAAAnACcAAAT/EMhJaQghCAGDlBDISaulIQghxIBjQCFlCAECOWmtIQgx BiRykjGGECEECOSkVQYxBiEEFjkJIWQMIUKAQE5KgxCDkFKgkdOUUgghYwgBAwRyUhmEGKQYA4+c 0hhTCiFjCChCgEDOGcQgpJgDkZzzHGNKIWQMKESAQM4pBCnGHJQSTEqllBBC5xhTICFjCBEgkBME MYg5CCUF1VprKZUSQucYaAohY4gQIJAyiEGKQUmtBZmUaymVEDrHFFgIGUKEAAAAYUBSzEFqLdZa awyytZRKCJ1jSiFwDBECACCIQcyBKK3VWnOttcYWXColdI4xhZAhoAgBgCBIMSipBVlz/8651hpj aymYEjrHlELGECFAAMQg5aCkWGsOvudca42xpVJC8BxTCiFDiACCgIOYg9Jizbn3HHStNcaWSgmh Y6AphIwhQgiCFAMPUou1Bp2UrTXGllIJIXiMKYWMIUIIgsBiDlKLtdaccw221hhbSiWEzjGwFDKG CCEMUsyBKC3GYJNTMsaWSgmhA48phYwhQhCDFGgOSmox2OSUjK2lUkLoQGNKIWMIEcQgBZqDklqL sdZaY5CxtZRKCZ1jTIGFjCFECIIUcxBMSa0FmZxsraVSSugcaEwpZAwRQhCEwGIOSkqtBZmUay2l UkLoHGhKIWQMEUIQg8BiDkJJKbjkXP9KqZQQOsdAUwohY4gQghgEFmMOQilBJadMKSGEzjEGlkLG ECKEIAYhsJhzEEopJaVgkhIhdI4xpRACxxAiBBDEIKUYeA5CCCY5E0IInWNMKbAQMoYIAYAgBoGk GHPOgUhOes4xxpRCCBxDiBAACEEMQmAx5pxzIJISHimNMaUQMsYQMEgAQBBjEFKKgQYeOakxppRC CBlwCBECAACEIMaAhJQCjZTnzFlKIYQMOIQIIUAgZRBiDEJKKQUaOQ0sUhJCxhBChACBnCAIMQYh BBY5qSSEjDGEEDAECOScQYgxBiGEwCInJFKOMYQQIUAgJw1BCDHGgEROCoeUQogQAgRBclIZghAC DjkpFUKEECCQk9YQghACDjmnEEKEEAIEctIqQwgBCjmphEFKCOSktcIgZxCCUgjkpNVSGOSkAQI5 KY0AOw==} image create photo ::img::b(5) -data { R0lGODlhJwAnALMAANnZ2YQHB4wXF5QnJ5w3N6RIR6xZWbRoabx5ecSJicyYmNKmptq2t+TIx/To 6Pz6+iH5BAEAAAAALAAAAAAnACcAAAT/EMhJaQghCAGDlBDISaulIQghxIBjQCFlCAECOWmtIQgx BiRykjGGECEECOSkVQYxBiEEFjkJIWQMIUKAQE5KgxCDkFKgkdOUUgghYwgBAwRyUhmEGKQYA4+c 0hhTCiFjCChCgEDOGcQgpJgDkZzzHGNKIWQMKESAQM4pBCnGHJQSTEqllBBC5xhTICFjCBEgkBME MYg5CCUF1VprKZUSQucYaAohY4gQIJAyiEGKQUmtBZmUaymVEDrHFFgIGUKEAAAAYUBSzEFqLdZa awyytZRKCJ1jSiFwDBECACCIQcyBKK3VWnOttcYWXColdI4xhZAhoAgBgCBIMSipBVmD/07K1hhb S6WEDjymFDKGCAEAMSApByXFWnPvOQebZGyplNA5phRIyBAigCAGMQfBtFhz7j3nXGsMsqVSQugY UwgZcIgQgiDFHKQWg61BJ2VrjbGlVEIIHmNKIWOIEIIgsJiD1GKtQSdla42xpVRCCJ5jSiFjiBDC ILCYg9JirLXmWoOtMcaWSgmhcwwshYwhQhCDFHMgSmox2OSUjK2lUkLoQGNKIWMIEcQgBZqDklqL sdZaY5CxtZRKCZ1jTIGFjCFECIIUcxBMSa0FmZxsraVSSugcaEwpZAwRQhCEwGIOSkqtBZmUay2l UkLoHGhKIWQMEUIQg8BiDkJJKbjkXP9KqZQQOsdAUwohY4gQghgEFmMOQilBJadMKSGEzjEGlkLG ECKEIAYhsJhzEEopJaVgkhIhdI4xpRACxxAiBBDEIKUYeA5CCCY5E0IInWNMKbAQMoYIAYAgBoGk GHPOgUhOes4xxpRCCBxDiBAACEEMQmAx5pxzIJISHimNMaUQMsYQMEgAQBBjEFKKgQYeOakxppRC CBlwCBECAACEIMaAhJQCjZTnzFlKIYQMOIQIIUAgZRBiDEJKKQUaOQ0sUhJCxhBChACBnCAIMQYh BBY5qSSEjDGEEDAECOScQYgxBiGEwCInJFKOMYQQIUAgJw1BCDHGgEROCoeUQogQAgRBclIZghAC DjkpFUKEECCQk9YQghACDjmnEEKEEAIEctIqQwgBCjmphEFKCOSktcIgZxCCUgjkpNVSGOSkAQI5 KY0AOw==} image create photo ::img::b(6) -data { R0lGODlhJwAnALMAANnZ2QeEhBeMjC+XmEekpFmsrGm0tHm8vInFxJrMzKrU1Ljc3Mfj5Nfr7Oj0 9Pr7/CH5BAEAAAAALAAAAAAnACcAAAT/EMhJaQghCAGDlBDISaulIQghxIBjQCFlCAECOWmtIQgB h5xUChFCgEBOWmUQcEgJiZxwyClECBDISWkQYoxBCCxyFkIIHFIKESCQk8ogxBikFGjklKUUQsYY Q0ARAgRyziDGGKQYeOScxpRCyBhjQCECBHJOIQYpxRyEIEoJIXTOMaYUAoccQgQI5ARBjFHMOSjB pJRKKSF0jjEFFjLGGCIECKQMYgxSDkpJwSWXUikldI4xBRIyxhAiBAAACHAMUsxJSi3GGINrKZUS OseYQggcUoQAAAhCFnMgSoqx1lpjbCkFE0LHmFLIGEMIGAIAQQxSDkpqQeacc62xtVRK/wiiY0wh ZIwhQgAQiDGIOSgt1tyDz7nG2FIqIXQMNIWQMYYQAQQx4CjmILVYc+85B1tjS6mE0DmmFEjGGEOE EMQgxcCT1GLNOedaYwwupVJC55hSCBlwDBFCEIMUc5KCi7XmXGuNsaUUTAmdY0whZIwhYJBjkGIO Smox2KRkbC2lEkLnQGMKIWMMEYIYA5JiDkpqMcYaY5CxpZRKCJ1jSoGEjDGECGIMUgw8KCW1FmOM rbWgUikhdIwphZABxxAiBDFIMQchmJSCS06lVEoIoWMMLIWQMYYIIYgxICnmoJSgknOmlBA6x5gC CRljDBFCEGMQWMw5KKUElZwpJYTOMf+mFEjIGGOIEIIYg8BSzDkIwSSnRAidc4wpBRIyxhAihCDG GJAUY85BCKGUIJLynGNMKYSMAccQIgQQxBiEFGjMOQciOdE55xhTCiGQjDGGCAGAIMaAg5RijIFH TmqMKaUQMgYcQ4gQAAhBjDEgKcUYY+CREhopSymEwCGlCCEAAIKYAxJSCjRy0lIKIQQOKYUIAQAA QhBwyEEILFIaMychBA4phQghQCBlEGKMMQghBBY5CyRSwiGlECIECOQEQQg4pIRETirhkFMIEQIE cs4gBBxyDkjkhENOKYQIAQI5aQhCCDjkpHUKIUIIEMhJZQhCCDjkpFQIEUKAQE5aQwgvQgg45JxC CBFCCBDISasMIQQo5KQSBikhkJPWCoOcQQhKIZCTVkthkJMGCOSkNAIAOw==} ################################################################ InitBoard $G(players) DoDisplay NewGame return ---- [Category Games]