Version 0 of Flow Colors

Updated 2014-04-24 03:20:13 by kpv

Keith Vetter 2014-04-23 : I recently came across the simple yet addictive puzzle game Flow Colors , and I decided it would be fun to write my own version of the game.

The object of Flow Colors is lay pipes to connect all pairs of colors. A level is solved when all the colors are paired and the entire board is filled. Flow Colors is based on a game by Mohammed el-Madhoun (see [L1 ]).

##+##########################################################################
#
# flowColors.tcl -- plays game Flow Colors
# http://moh97.us/flow/
# by Keith Vetter April 2014
#

package require Tk
package require tooltip

set S(state) play
set S(stage) 1
set S(level) 1
set S(solved) {}
set S(margin) 75
set S(sz) 90
set S(radius,factor) .35
set S(lwidth,factor) .30
set S(stageButton,size) 4
set S(fade,params) {20 20}
set S(hints,canDo) 0
set S(hints,used) 0
set S(shiftStage,params) {100 10}
set S(darken,0) 30
set S(darken,1) 70
if {$tcl_platform(os) eq "Darwin"} {
    set S(rcFile) [file join $::env(HOME) Library Preference flowColors.rc]
} elseif {$tcl_platform(os) eq "windows"} {
    set S(rcFile) [file join $::env(HOME) flowColors.rc]
} else {
    set S(rcFile) [file join $::env(HOME) .flowColorsrc]
}
array set SOLUTIONS {}

set CLR(bg) black
set CLR(fg) white
set CLR(txt) red
set CLR(dialog,bg) bisque
set CLR(dialog,fg) black
set CLR(dialog,txt) gray20
set CLR(dialog,button)  [::tk::Darken $CLR(dialog,bg) 50]
set CLR(dialog,button) bisque4
set CLR(dialog,highlight) pink
set CLR(star) darkgoldenrod
set CLR(stageButton,off) white
set CLR(stageButton,on) red

catch {font delete myDialogFont}
catch {font delete myDisplayFont}
font create myDialogFont {*}[font actual {Helvetica 14 bold}]
font create myDisplayFont {*}[font actual {Helvetica 18 bold}]
font create myDisplayFontBig {*}[font actual {Helvetica 32 bold}]
font create myDisplayFontTitle {*}[font actual {Helvetica 56 bold}]

array set BOARDS {
    1,1 {6 blue 0 1 5 0 cyan 4 2 1 4 darkorange 0 0 4 0 green 0 2 2 2 red 5 2 0 5 yellow 3 2 0 4}
    1,2 {6 blue 0 2 3 5 cyan 3 3 4 4 darkorange 0 1 4 5 green 0 5 2 5 red 2 3 4 1 yellow 2 2 4 2}
    1,3 {6 blue 1 4 4 4 darkorange 1 3 4 2 green 2 5 3 2 red 0 0 1 5 yellow 2 3 4 1}
    1,4 {6 blue 1 4 4 4 darkorange 4 3 5 2 green 1 1 4 2 yellow 2 3 5 3}
    1,5 {6 blue 0 1 3 2 darkorange 1 1 4 3 green 1 3 5 5 yellow 0 2 1 4}
    1,6 {6 blue 0 0 5 4 darkorange 3 4 4 1 green 2 0 2 4 yellow 2 3 4 4}
    1,7 {6 blue 3 2 5 0 cyan 3 4 4 2 darkorange 1 1 3 5 green 0 5 2 5 red 0 3 2 4 yellow 1 3 3 3}
    1,8 {6 blue 0 2 2 3 darkorange 1 1 3 2 green 1 2 4 4 red 2 5 4 0 yellow 0 3 1 5}
    1,9 {6 blue 0 4 4 4 darkorange 2 2 5 1 green 0 5 3 3 red 1 2 4 1 yellow 3 2 5 2}
    1,10 {6 blue 4 1 4 5 cyan 1 2 1 5 darkorange 2 0 5 5 green 0 1 0 5 red 0 0 2 5 yellow 3 1 3 5}
    1,11 {6 blue 1 1 2 5 darkorange 1 2 1 4 green 3 5 4 0 red 1 5 3 4 yellow 4 1 4 4}
    1,12 {6 blue 0 1 3 3 darkorange 1 1 2 3 green 0 2 5 1 yellow 1 2 5 0}
    1,13 {6 blue 0 2 2 0 darkorange 4 1 5 0 green 1 1 4 4 red 1 2 2 5 yellow 1 4 4 0}
    1,14 {6 blue 1 4 5 5 darkorange 0 4 4 5 green 1 2 5 1 red 3 3 5 3 yellow 5 0 5 2}
    1,15 {6 blue 1 0 2 1 cyan 2 4 5 1 darkorange 4 3 5 2 green 2 3 4 4 red 2 0 5 0 yellow 0 0 5 3}
    1,16 {6 blue 0 3 5 0 cyan 0 2 1 0 darkorange 2 4 4 4 green 2 3 3 1 red 3 3 4 1 yellow 1 4 4 0}
    1,17 {6 blue 1 3 5 4 cyan 2 1 3 2 darkorange 2 4 4 4 green 2 3 4 0 red 0 5 1 1 yellow 0 1 4 2}
    1,18 {6 blue 4 2 4 4 darkorange 0 5 5 0 green 1 1 5 2 red 2 1 2 3 yellow 1 5 5 3}
    1,19 {6 blue 0 5 2 2 darkorange 0 1 3 4 green 0 0 2 4 red 1 5 2 3 yellow 4 1 4 4}
    1,20 {6 blue 3 3 4 1 darkorange 0 0 5 3 green 2 4 3 2 yellow 3 4 4 3}
    1,21 {6 blue 0 0 1 1 cyan 0 4 5 0 darkorange 0 3 2 3 green 0 5 5 1 red 0 1 2 1 yellow 2 0 3 3}
    1,22 {6 blue 0 0 4 3 darkorange 2 0 4 2 green 2 1 3 2 red 0 5 4 0 yellow 1 0 3 3}
    1,23 {6 blue 0 5 5 5 darkorange 1 5 4 5 green 2 2 2 4 yellow 2 5 3 2}
    1,24 {6 blue 3 2 4 1 cyan 0 5 5 5 darkorange 1 0 1 3 green 0 0 1 2 red 0 2 4 3 yellow 3 1 4 4}
    1,25 {6 blue 2 3 2 5 cyan 2 2 3 4 darkorange 0 2 0 5 green 0 1 5 0 red 1 5 5 1 yellow 3 3 4 4}
    1,26 {6 blue 3 3 5 0 darkorange 2 3 3 0 green 1 0 4 3 red 0 0 5 3 yellow 4 2 5 1}
    1,27 {6 blue 2 4 5 4 darkorange 0 0 4 1 green 1 5 5 3 red 1 4 4 4 yellow 1 0 5 2}
    1,28 {6 blue 4 1 4 4 darkorange 1 1 5 0 green 0 0 2 3 yellow 0 1 5 1}
    1,29 {6 blue 1 0 3 5 cyan 4 5 5 3 darkorange 1 3 4 4 green 2 3 3 0 red 1 1 2 0 yellow 1 2 4 1}
    1,30 {6 blue 1 1 4 5 darkorange 3 1 5 0 green 1 3 4 4 red 1 0 3 5 yellow 2 1 4 1}
    2,1 {7 blue 0 6 6 5 cyan 3 4 6 6 darkorange 1 5 2 1 green 3 3 4 2 red 1 6 5 4 yellow 4 4 5 5}
    2,2 {7 blue 1 3 1 5 cyan 3 2 4 5 darkorange 1 2 5 2 green 2 2 3 5 magenta 0 1 6 2 red 0 2 6 3 yellow 3 3 4 4}
    2,3 {7 blue 4 0 6 6 brown 3 0 5 1 cyan 0 0 1 6 darkorange 2 3 4 5 green 2 4 3 6 magenta 2 0 2 2 red 3 2 4 6 yellow 1 0 2 6}
    2,4 {7 blue 4 4 5 1 darkorange 4 2 5 4 green 1 0 6 0 red 5 0 5 5 yellow 2 2 3 4}
    2,5 {7 blue 0 1 3 4 cyan 0 0 6 1 darkorange 3 1 6 6 green 1 5 4 4 red 2 1 4 2 yellow 0 2 2 3}
    2,6 {7 blue 1 1 3 0 cyan 2 5 4 6 darkorange 0 5 2 2 green 0 6 1 5 magenta 3 5 4 1 red 4 0 5 6 yellow 1 4 4 2}
    2,7 {7 blue 3 1 3 3 darkorange 2 0 4 2 green 1 0 2 1 red 1 1 1 5 yellow 4 1 4 5}
    2,8 {7 blue 4 3 4 6 cyan 0 6 1 1 darkorange 1 6 5 1 green 0 4 6 5 magenta 5 3 6 6 red 3 3 3 6 yellow 3 2 5 2}
    2,9 {7 blue 2 4 2 6 cyan 1 1 4 6 darkorange 0 5 1 0 green 1 2 4 5 red 0 6 3 6 yellow 3 1 5 5}
    2,10 {7 blue 2 4 6 4 cyan 0 1 6 0 darkorange 1 1 6 2 green 5 2 6 5 red 3 3 5 5 yellow 4 3 6 3}
    2,11 {7 blue 1 0 2 3 cyan 1 2 3 3 darkorange 3 1 5 4 green 5 1 5 3 magenta 1 1 4 0 red 1 5 5 5 yellow 3 4 5 0}
    2,12 {7 blue 5 5 6 2 cyan 3 0 6 0 darkorange 2 2 6 6 green 2 0 2 3 magenta 3 1 6 1 red 1 5 2 1 yellow 3 6 4 3}
    2,13 {7 blue 1 2 1 4 cyan 2 4 3 3 darkorange 0 6 3 6 green 4 0 5 6 red 1 1 1 5 yellow 0 5 4 6}
    2,14 {7 blue 3 2 4 1 brown 1 2 5 1 cyan 1 4 6 0 darkorange 1 1 3 1 green 2 2 4 3 magenta 1 5 6 6 red 1 3 2 6 yellow 4 5 6 3}
    2,15 {7 blue 0 2 3 1 darkorange 0 1 1 0 green 1 2 3 3 red 1 1 1 4 yellow 1 5 5 1}
    2,16 {7 blue 3 3 4 5 darkorange 3 2 5 5 green 4 6 5 1 red 5 2 5 6 yellow 6 0 6 2}
    2,17 {7 blue 2 1 3 4 cyan 4 1 6 2 darkorange 3 1 3 5 green 5 1 5 6 magenta 1 1 2 4 red 0 6 4 5 yellow 3 2 5 5}
    2,18 {7 blue 2 5 5 3 cyan 4 6 6 6 darkorange 4 5 6 5 green 1 1 5 2 magenta 3 6 5 0 red 2 6 5 1 yellow 1 5 2 2}
    2,19 {7 blue 4 6 6 6 cyan 1 5 4 5 darkorange 5 5 6 2 green 3 5 4 3 red 3 6 6 1 yellow 0 3 6 0}
    2,20 {7 blue 2 1 3 3 darkorange 1 3 4 1 green 0 0 0 2 red 0 3 1 2 yellow 2 4 3 1}
    2,21 {7 blue 0 0 1 4 cyan 3 0 6 0 darkorange 0 4 2 3 green 1 0 3 3 red 1 5 5 2 yellow 2 0 3 1}
    2,22 {7 blue 1 4 3 2 cyan 4 5 5 1 darkorange 4 6 6 0 green 1 2 2 0 magenta 1 5 5 0 red 0 0 1 3 yellow 5 2 5 5}
    2,23 {7 blue 4 5 6 5 cyan 0 6 4 3 darkorange 1 6 3 3 green 0 0 4 4 red 0 4 5 3 yellow 3 4 6 6}
    2,24 {7 blue 5 4 6 6 cyan 1 5 5 6 darkorange 0 6 2 0 green 1 6 4 1 red 6 0 6 3 yellow 3 3 4 6}
    2,25 {7 blue 2 1 6 5 cyan 4 1 6 4 darkorange 3 1 5 5 green 0 0 6 3 red 0 1 1 5 yellow 0 6 1 1}
    2,26 {7 blue 0 2 6 0 darkorange 1 5 4 5 green 0 1 4 1 red 2 2 5 3 yellow 5 0 5 5}
    2,27 {7 blue 0 3 6 6 darkorange 2 1 3 3 green 1 5 4 5 red 0 4 3 1 yellow 1 4 2 2}
    2,28 {7 blue 0 5 6 1 cyan 4 0 5 5 darkorange 4 1 6 0 green 0 2 3 4 magenta 0 0 1 3 red 1 5 3 3 yellow 1 0 2 3}
    2,29 {7 blue 2 2 2 4 cyan 3 1 4 4 darkorange 5 3 6 6 green 4 3 5 0 red 2 1 4 5 yellow 5 1 5 4}
    2,30 {7 blue 0 5 3 6 cyan 1 5 3 4 darkorange 0 0 4 0 green 0 2 0 4 magenta 1 2 2 4 red 4 1 5 5 yellow 1 0 4 2}
    3,1 {8 blue 3 4 5 4 cyan 1 4 2 7 darkorange 3 3 4 4 green 1 6 2 4 red 0 4 7 1 yellow 1 7 2 5}
    3,2 {8 blue 0 1 5 5 cyan 0 2 7 3 darkorange 1 6 7 1 green 3 3 5 0 red 0 0 7 0 yellow 3 0 3 2}
    3,3 {8 blue 2 2 5 7 cyan 4 4 6 1 darkorange 5 3 7 6 green 4 7 7 7 red 0 1 4 3 yellow 1 3 1 6}
    3,4 {8 blue 5 7 6 3 cyan 1 6 3 6 darkorange 4 7 5 2 green 1 7 3 1 magenta 2 3 3 7 red 4 4 6 2 yellow 0 0 6 7}
    3,5 {8 blue 0 7 4 5 cyan 3 3 6 1 darkorange 7 2 7 7 green 0 6 4 1 red 1 3 3 1 yellow 3 6 7 1}
    3,6 {8 blue 0 7 4 6 cyan 6 2 7 6 darkorange 1 4 4 7 green 6 1 7 7 magenta 1 0 5 4 red 0 0 5 7 yellow 2 0 7 1}
    3,7 {8 blue 3 1 4 4 darkorange 1 0 2 4 green 2 2 4 1 red 3 6 6 1 yellow 0 7 1 5}
    3,8 {8 blue 5 2 5 7 cyan 0 5 6 4 darkorange 0 6 2 1 green 0 7 5 1 magenta 5 3 6 1 red 5 4 7 7 yellow 4 4 6 7}
    3,9 {8 blue 1 1 4 0 cyan 4 5 5 1 darkorange 2 2 3 0 green 1 2 4 3 red 3 5 5 0 yellow 1 6 6 6}
    3,10 {8 blue 0 7 4 6 cyan 0 3 0 5 darkorange 1 7 4 2 green 1 1 1 4 red 4 4 7 0 yellow 3 1 6 7}
    3,11 {8 blue 7 1 7 3 cyan 1 6 3 6 darkorange 4 3 5 6 green 0 5 2 4 magenta 0 6 7 0 red 5 3 6 6 yellow 3 3 4 1}
    3,12 {8 blue 2 4 2 6 cyan 1 4 6 6 darkorange 4 7 5 5 green 1 6 3 1 red 0 1 7 4 yellow 0 6 5 2}
    3,13 {8 blue 6 4 6 6 cyan 3 6 5 2 darkorange 0 0 5 6 green 2 5 4 4 red 0 7 3 7 yellow 2 3 6 0}
    3,14 {8 blue 1 4 3 3 cyan 4 7 5 2 darkorange 7 0 7 5 green 5 3 7 7 red 2 5 4 6 yellow 0 2 7 6}
    3,15 {8 blue 2 5 6 2 cyan 6 5 6 7 darkorange 4 4 5 7 green 0 1 7 3 red 3 6 7 7 yellow 2 4 4 3}
    3,16 {8 blue 3 4 6 3 cyan 2 4 6 2 darkorange 1 4 4 0 green 0 0 0 7 magenta 0 6 6 6 red 3 2 5 2 yellow 4 4 5 0}
    3,17 {8 blue 0 0 7 6 brown 3 1 3 4 cyan 4 0 5 4 darkorange 3 0 4 6 green 5 6 7 4 magenta 2 1 5 5 red 4 4 6 1 yellow 5 3 6 2}
    3,18 {8 blue 1 0 2 2 brown 3 5 4 2 cyan 0 0 2 0 darkorange 0 4 5 4 green 2 7 7 7 magenta 4 3 5 2 purple 3 0 3 6 red 1 5 1 7 yellow 1 6 2 5}
    3,19 {8 blue 3 4 4 6 brown 1 1 2 6 cyan 0 1 3 2 darkorange 0 6 2 4 green 6 1 6 6 magenta 3 3 4 0 red 1 4 2 1 yellow 4 5 5 6}
    3,20 {8 blue 5 5 6 3 brown 6 2 7 4 cyan 4 7 7 5 darkorange 0 2 6 1 green 3 0 7 3 magenta 1 4 1 6 purple 0 5 2 7 red 0 4 3 7 yellow 1 1 3 5}
    3,21 {8 blue 0 7 4 7 brown 0 5 7 1 cyan 4 5 6 6 darkorange 0 6 2 6 green 2 1 7 5 magenta 5 3 7 2 red 3 3 6 1 yellow 4 1 7 3}
    3,22 {8 blue 0 6 2 2 cyan 1 2 6 1 darkorange 0 4 1 5 green 2 3 6 6 red 1 6 3 4 yellow 4 5 7 1}
    3,23 {8 blue 1 2 2 6 cyan 0 7 1 4 darkorange 1 3 6 6 green 0 0 6 4 magenta 1 5 7 3 red 5 4 6 1 yellow 4 1 6 5}
    3,24 {8 blue 4 6 5 5 cyan 1 2 2 3 darkorange 0 2 1 1 green 0 1 7 0 magenta 3 3 5 6 red 2 5 4 5 yellow 3 1 7 1}
    3,25 {8 blue 1 4 6 6 cyan 0 3 7 6 darkorange 3 1 7 0 green 5 3 6 0 magenta 0 0 2 1 red 1 3 7 2 yellow 1 1 4 3}
    3,26 {8 blue 0 0 2 2 brown 2 5 4 4 cyan 1 1 3 1 darkorange 1 3 7 0 green 3 2 5 5 magenta 4 2 5 4 red 5 0 5 6 yellow 1 0 5 2}
    3,27 {8 blue 3 5 6 2 cyan 2 7 6 5 darkorange 1 7 7 3 green 3 4 5 2 magenta 1 1 6 3 red 6 7 7 4 yellow 5 5 6 4}
    3,28 {8 blue 1 7 7 3 cyan 3 6 7 4 darkorange 1 3 7 7 green 3 3 5 1 magenta 1 2 3 1 red 4 1 5 4 yellow 2 5 6 1}
    3,29 {8 blue 0 3 3 7 cyan 1 6 6 6 darkorange 2 3 6 5 green 1 1 3 5 red 2 1 5 2 yellow 3 1 6 4}
    3,30 {8 blue 4 3 6 1 cyan 1 6 3 6 darkorange 0 4 0 6 green 2 2 4 2 magenta 0 5 3 5 red 1 4 6 3 yellow 5 5 6 2}
    4,1 {9 blue 1 3 2 7 brown 5 7 7 1 cyan 1 2 2 3 darkorange 2 4 2 6 green 4 1 4 3 magenta 3 7 5 1 purple 5 8 6 1 red 1 1 4 4 yellow 5 0 6 2}
    4,2 {9 blue 0 0 3 7 brown 0 7 3 0 cyan 4 7 7 5 darkorange 5 1 7 1 green 4 3 8 3 magenta 3 5 5 5 red 3 3 7 2 yellow 5 4 8 2}
    4,3 {9 blue 0 2 1 0 cyan 3 1 7 1 darkorange 4 4 6 4 green 6 3 7 6 magenta 2 5 4 0 red 7 5 8 8 yellow 3 0 3 8}
    4,4 {9 blue 4 8 8 8 cyan 0 8 6 4 darkorange 0 1 1 3 green 1 8 3 4 magenta 5 8 7 8 red 3 8 4 4 yellow 0 0 3 7}
    4,5 {9 blue 1 7 6 5 brown 2 5 6 4 cyan 6 7 7 2 darkorange 1 0 7 1 green 0 0 3 3 magenta 2 0 6 8 red 5 3 7 7 yellow 1 4 3 6}
    4,6 {9 blue 3 5 6 4 brown 6 5 8 6 cyan 4 4 7 4 darkorange 3 4 7 0 green 8 0 8 4 magenta 3 6 6 0 purple 1 5 6 7 red 4 6 7 7 white 5 0 8 7 yellow 1 1 1 4}
    4,7 {9 blue 2 7 5 7 brown 6 7 8 8 cyan 2 3 6 3 darkorange 4 2 6 6 green 2 1 6 4 magenta 0 6 7 8 purple 1 7 5 6 red 1 2 3 1 white 0 4 5 2 yellow 0 0 8 0}
    4,8 {9 blue 0 0 1 8 brown 5 2 6 4 cyan 2 3 8 8 darkorange 2 8 3 5 green 1 0 7 4 magenta 1 5 1 7 red 4 7 6 7 yellow 6 2 6 6}
    4,9 {9 blue 0 0 3 8 brown 0 1 2 8 cyan 2 7 6 2 darkorange 0 3 3 3 green 1 7 4 5 magenta 2 6 4 6 red 6 7 7 4 yellow 1 1 6 6}
    4,10 {9 blue 7 6 8 8 cyan 5 1 8 5 darkorange 7 5 7 8 green 6 1 6 8 magenta 2 6 5 6 red 2 2 6 6 yellow 4 3 7 1}
    4,11 {9 blue 4 2 5 3 brown 4 0 8 0 cyan 1 1 2 5 darkorange 1 4 7 7 green 7 2 8 5 magenta 4 4 8 4 purple 3 0 5 1 red 1 2 6 5 yellow 0 0 4 3}
    4,12 {9 blue 4 8 5 6 brown 2 0 7 7 cyan 1 1 1 4 darkorange 1 6 2 1 green 5 2 5 5 magenta 3 2 8 4 red 1 7 3 3 yellow 6 2 7 6}
    4,13 {9 blue 3 4 5 7 brown 3 2 4 4 cyan 5 5 7 6 darkorange 4 5 7 7 green 1 7 7 1 magenta 4 2 6 4 red 5 4 8 3 yellow 2 2 2 7}
    4,14 {9 blue 6 4 6 6 brown 1 1 2 7 cyan 6 1 8 0 darkorange 1 4 7 0 green 5 7 6 3 magenta 2 6 3 4 purple 2 1 3 3 red 1 3 4 5 yellow 4 8 6 2}
    4,15 {9 blue 2 7 4 2 cyan 0 0 4 3 darkorange 1 0 1 7 green 5 3 6 1 magenta 4 6 6 6 red 3 2 3 4 yellow 2 0 4 0}
    4,16 {9 blue 2 2 2 5 brown 0 7 6 7 cyan 7 1 8 8 darkorange 0 6 3 1 green 0 8 5 6 magenta 6 3 7 2 purple 4 6 5 1 red 0 4 6 4 yellow 1 6 3 2}
    4,17 {9 blue 1 3 4 6 cyan 4 7 7 0 darkorange 3 3 6 6 green 4 8 8 0 red 1 4 1 6 yellow 1 7 4 5}
    4,18 {9 blue 1 4 7 1 brown 4 3 7 3 cyan 0 8 8 8 darkorange 6 5 8 7 green 4 4 7 6 magenta 5 5 5 7 purple 2 6 3 3 red 1 6 7 2 yellow 4 5 8 6}
    4,19 {9 blue 1 6 5 7 brown 1 4 1 7 cyan 4 7 8 8 darkorange 5 1 7 5 green 0 7 4 5 magenta 1 3 4 1 purple 2 4 6 2 red 3 3 7 6 yellow 3 4 4 6}
    4,20 {9 blue 1 1 6 3 brown 3 8 4 4 cyan 1 7 6 8 darkorange 3 0 6 5 green 3 1 3 6 magenta 5 6 8 8 purple 5 7 7 8 red 0 5 2 4 yellow 0 4 6 2}
    4,21 {9 blue 3 6 5 3 cyan 4 2 7 2 darkorange 1 1 6 5 green 3 2 7 8 magenta 2 6 6 8 red 5 2 6 6 yellow 5 5 7 7}
    4,22 {9 blue 5 1 7 2 brown 0 5 0 8 cyan 3 6 7 7 darkorange 0 4 6 4 green 4 7 5 2 magenta 1 4 2 1 purple 2 2 4 4 red 2 6 5 8 yellow 2 8 6 2}
    4,23 {9 blue 4 0 8 0 brown 1 5 4 6 cyan 1 8 7 7 darkorange 1 4 2 1 green 2 6 8 7 magenta 1 6 3 8 purple 5 2 6 6 red 3 3 6 7 yellow 2 4 6 4}
    4,24 {9 blue 1 1 4 3 brown 1 4 4 7 cyan 4 4 7 6 darkorange 0 2 6 8 green 1 3 5 8 magenta 1 2 6 2 red 2 3 7 7 yellow 2 4 5 7}
    4,25 {9 blue 2 7 6 3 brown 1 4 2 6 cyan 0 0 8 0 darkorange 4 7 6 4 green 0 1 6 8 magenta 0 8 4 3 red 1 5 6 6 yellow 0 2 6 7}
    4,26 {9 blue 7 4 8 0 brown 1 7 5 2 cyan 2 7 5 6 darkorange 7 6 7 8 green 0 4 3 5 magenta 4 0 7 3 purple 4 4 8 8 red 1 4 2 1 yellow 2 2 6 6}
    4,27 {9 blue 3 5 4 3 brown 0 2 8 1 cyan 0 3 6 4 darkorange 1 5 7 6 green 3 3 6 6 magenta 5 1 7 1 red 1 4 7 3 yellow 0 1 3 0}
    4,28 {9 blue 2 6 8 4 cyan 3 6 7 4 darkorange 2 4 7 6 green 1 1 7 3 magenta 6 6 7 5 red 5 0 7 1 yellow 1 4 2 7}
    4,29 {9 blue 4 1 4 5 brown 4 2 4 4 cyan 0 0 3 7 darkorange 1 0 1 4 green 5 7 7 3 magenta 1 7 8 1 red 4 7 5 5 yellow 2 7 6 2}
    4,30 {9 blue 1 1 8 0 brown 2 0 7 3 cyan 0 7 3 3 darkorange 4 7 7 7 green 0 8 4 1 magenta 5 4 7 6 purple 7 8 8 5 red 0 6 2 3 yellow 6 6 6 8}
    5,1 {9 blue 0 6 3 6 cyan 4 6 6 7 darkorange 0 0 3 5 green 0 7 5 3 magenta 7 7 8 6 red 2 1 2 3 yellow 0 8 8 7}
    5,2 {9 blue 0 0 0 8 brown 7 6 7 8 cyan 2 5 5 3 darkorange 2 0 4 0 green 5 0 8 8 magenta 4 4 5 2 red 1 0 4 5 yellow 5 1 6 6}
    5,3 {9 blue 0 5 4 5 brown 3 2 7 2 cyan 7 8 8 0 darkorange 0 0 0 4 green 0 6 6 8 magenta 2 3 8 8 purple 3 3 6 4 red 0 8 5 8 yellow 0 7 5 7}
    5,4 {9 blue 0 8 8 1 cyan 8 2 8 8 darkorange 0 5 8 0 green 2 3 5 3 red 5 4 6 3 yellow 2 2 2 4}
    5,5 {9 blue 0 0 0 6 cyan 5 6 8 8 darkorange 0 8 6 6 green 0 5 6 1 red 7 3 7 6 yellow 4 5 8 0}
    5,6 {9 blue 0 0 4 0 brown 6 2 7 6 cyan 4 2 5 6 darkorange 0 2 0 7 green 0 1 3 6 magenta 5 2 5 5 purple 4 1 7 5 red 2 3 7 7 white 0 8 5 0 yellow 1 7 2 2}
    5,7 {9 blue 0 7 3 7 brown 5 2 5 7 cyan 1 5 4 5 darkorange 0 6 4 7 green 0 8 1 4 magenta 7 1 7 5 purple 0 0 0 5 red 4 0 7 8 yellow 1 0 2 0}
    5,8 {9 blue 0 0 0 7 brown 7 4 7 8 cyan 3 2 4 8 darkorange 0 8 3 8 green 1 7 8 0 magenta 5 3 7 3 purple 7 2 8 8 red 3 1 5 2 yellow 2 1 3 3}
    5,9 {9 blue 0 1 0 8 brown 8 0 8 8 cyan 6 1 6 6 darkorange 0 0 1 7 green 3 7 4 1 magenta 7 1 7 6 purple 1 8 7 8 red 5 1 7 7 yellow 2 7 7 0}
    5,10 {9 blue 0 7 3 3 cyan 3 7 7 1 darkorange 0 8 8 8 green 1 7 3 4 red 2 7 8 7 yellow 0 0 5 0}
    5,11 {9 blue 7 8 8 0 brown 5 4 5 7 cyan 0 3 5 8 darkorange 8 1 8 8 green 3 2 6 8 magenta 1 3 1 7 purple 2 3 5 3 red 2 2 6 0 white 2 4 2 7 yellow 1 1 6 1}
    5,12 {9 blue 0 7 8 0 brown 7 2 7 4 cyan 3 2 3 8 darkorange 0 8 2 8 green 1 7 5 7 magenta 4 2 7 5 red 2 2 2 7 yellow 6 7 8 4}
    5,13 {9 blue 1 2 1 8 brown 6 4 7 4 cyan 4 4 8 8 darkorange 0 8 8 7 green 0 0 8 0 magenta 5 4 5 7 purple 3 3 3 8 red 4 3 7 3 yellow 2 8 7 2}
    5,14 {9 blue 0 1 6 2 brown 3 6 6 4 cyan 2 7 4 6 darkorange 0 0 7 2 green 0 3 0 8 magenta 4 5 6 5 purple 3 7 8 7 red 0 2 5 2 white 8 2 8 6 yellow 1 3 8 8}
    5,15 {9 blue 0 8 5 8 cyan 5 7 7 8 darkorange 2 0 2 7 green 3 0 8 8 magenta 6 3 6 8 red 4 4 4 7 yellow 3 7 7 1}
    5,16 {9 blue 0 2 0 5 brown 5 1 6 6 cyan 3 2 3 5 darkorange 1 0 4 1 green 0 6 5 6 magenta 2 0 7 6 purple 5 2 5 5 red 2 2 2 5 white 8 2 8 5 yellow 0 8 8 6}
    5,17 {9 blue 0 0 7 8 brown 8 0 8 8 cyan 2 2 5 2 darkorange 5 7 6 1 green 0 8 6 8 magenta 6 2 6 7 red 2 5 5 5 yellow 1 2 5 6}
    5,18 {9 blue 0 1 5 1 brown 6 1 6 8 cyan 1 7 2 4 darkorange 0 2 5 8 green 0 0 8 8 magenta 3 4 3 6 purple 7 1 7 8 red 0 8 4 8 yellow 0 3 0 7}
    5,19 {9 blue 0 7 4 1 brown 4 6 4 8 cyan 2 7 3 4 darkorange 0 1 8 0 green 0 8 4 4 magenta 4 3 8 3 purple 6 2 8 2 red 2 2 8 1 yellow 1 7 3 3}
    5,20 {9 blue 0 1 2 1 brown 3 2 4 5 cyan 1 8 2 8 darkorange 0 0 8 8 green 0 2 2 2 magenta 3 5 3 8 purple 5 2 5 7 red 1 4 4 2 white 7 3 7 8 yellow 0 8 3 3}
    5,21 {9 blue 0 4 3 4 darkorange 0 1 0 2 green 1 2 4 2 red 7 7 8 2 yellow 0 0 8 3}
    5,22 {9 blue 0 1 7 1 brown 6 3 6 5 cyan 4 2 5 2 darkorange 0 0 3 3 green 0 8 3 2 magenta 5 3 5 5 red 2 3 2 7 yellow 1 3 8 8}
    5,23 {9 blue 0 0 2 8 brown 7 1 7 5 cyan 6 1 8 7 darkorange 0 8 2 7 green 1 2 1 8 magenta 5 8 8 8 red 4 8 5 1 yellow 4 6 7 6}
    5,24 {9 blue 4 3 6 3 brown 3 8 8 0 cyan 2 1 2 8 darkorange 4 2 6 2 green 5 1 5 5 magenta 3 7 7 0 red 1 6 3 6 yellow 0 0 0 8}
    5,25 {9 blue 1 1 5 0 brown 3 3 5 2 cyan 1 3 7 7 darkorange 0 0 4 4 green 2 1 5 1 magenta 2 3 7 0 red 7 1 7 6 yellow 0 3 8 0}
    5,26 {9 blue 0 0 7 1 cyan 2 5 2 6 darkorange 0 1 6 1 green 0 2 1 4 magenta 0 4 8 0 red 2 4 6 4 yellow 0 3 6 3}
    5,27 {9 blue 1 1 5 1 cyan 2 5 7 5 darkorange 0 1 8 5 green 2 2 2 4 magenta 1 5 7 7 red 1 2 2 6 yellow 1 4 4 3}
    5,28 {9 blue 1 0 7 0 brown 5 8 8 8 cyan 0 7 3 4 darkorange 0 0 0 6 green 1 6 8 0 magenta 0 8 4 4 red 2 6 5 3 yellow 2 2 6 3}
    5,29 {9 blue 0 1 8 2 brown 1 7 8 3 cyan 5 5 7 5 darkorange 0 0 7 0 green 4 2 4 4 magenta 5 6 7 6 red 4 5 5 4 yellow 3 5 8 8}
    5,30 {9 blue 1 1 1 3 brown 6 2 8 2 cyan 3 0 3 5 darkorange 2 2 8 8 green 1 4 6 3 magenta 4 0 5 3 red 2 3 4 3 yellow 5 4 5 6}
}
################################################################
proc DoDisplay {} {
    wm title . "Flow Colors"
    set sz [expr {2*$::S(margin) + $::S(sz) * 6}]
    set ::S(X0) [expr {$sz/2}]
    canvas .c -width $sz -height $sz -bd 0 -highlightthickness 0 -bg $::CLR(bg)
    pack .c -side top -fill both -expand 1

    bind .c <Configure> {Recenter %W %h %w}
    bind .c <1> {DoButton down %x %y}
    bind .c <B1-Motion> {DoButton move %x %y}
    bind .c <ButtonRelease-1> {DoButton up %x %y}
    if {[file exists ~/misc/tcl/console.tcl]} {
        uplevel #0 source ~/misc/tcl/console.tcl
        bind all <F12> {console show}
    }
}
proc DrawConstants {} {
    global S CLR B
    .c create rect -$::S(X0) -$::S(X0) $::S(X0) $::S(X0) -tag border -fill {} \
        -outline white -width 5
    set top [lindex [Cell2XY 0 0] 0 1]
    set y [expr {(-$::S(X0) + $top) / 2}]
    set x [expr {abs($y)}]
    .c create text 0 $y -text "Flow Colors" -font myDisplayFontTitle \
        -anchor c -fill red
    set star [MakeStar $x $y [expr {$top - $y - 5}]]
    .c create poly $star -fill $CLR(star) -outline $CLR(star) -tag solvedStar

    lassign [lindex [Cell2XY $::B(N) 0] 0] xLeft y
    lassign [lindex [Cell2XY $::B(N) $::B(N)] 0] xRight
    incr y 5
    .c create text $xLeft $y -font myDisplayFont -fill $::CLR(txt) \
        -anchor nw -tag level,txt

    # Navigation buttons
    .c create image -60 $y -image ::img::left -anchor n -tag prev
    .c create image 0 $y -image ::img::undo -anchor n -tag undo
    .c create image 60 $y -image ::img::right -anchor n -tag next

    # Help
    .c create image $xRight $y -image ::img::help -anchor ne -tag help
    CanvasButtonBinding .c help "" "" Help
    ::tooltip::tooltip .c -items help "Help"
    .c create image [expr {$xRight-48-5}] $y -image ::img::up -anchor ne -tag up
}    
proc DrawBoard {stage level} {
    global B S L BOARDS

    set S(stage) $stage
    set S(level) $level
    set S(level,txt) "Stage $stage\nLevel $level"
    set S(stages) [llength [array names BOARDS *,30]]

    unset -nocomplain B
    set boardSpec [lassign $BOARDS($stage,$level) N]
    ComputeSizes $N
    set B(N) $N
    set B(xy0) [expr {round(-$N/2. * $S(sz))}]
    set B(almost) 0

    .c delete all
    DrawConstants
    
    for {set row 0} {$row < $N} {incr row} {
        for {set col 0} {$col < $N} {incr col} {
            lassign [Cell2XY $row $col] xy
            .c create rect $xy -tag cell_${row},$col -fill $::CLR(bg) \
                -outline $::CLR(fg)
            set B($row,$col) {}
        }
    }

    # Draw all the nodes
    unset -nocomplain L
    foreach {clr row1 col1 row2 col2} $boardSpec {
        lassign [Cell2XY $row1 $col1] . xy1
        lassign [Cell2XY $row2 $col2] . xy2
        set id1 [.c create oval $xy1 -fill $clr -outline $clr -tag node]
        set id2 [.c create oval $xy2 -fill $clr -outline $clr -tag node]
        set B($row1,$col1) [list node $clr]
        set B($row2,$col2) [list node $clr]
        set L(path,$clr) {}
        set L(delete,$clr) {}
        set L(done,$clr) 0
        .c bind $id1 <Shift-Double-Button-3> [list DoHint $clr]
        .c bind $id2 <Shift-Double-Button-3> [list DoHint $clr]
    }

    # Level indicator
    .c itemconfig level,txt -text $S(level,txt) -anchor nw
    # Button bindings and tooltips
    CanvasButtonBinding .c prev "" "" {PlayAgain -1}
    CanvasButtonBinding .c undo "" "" {PlayAgain 0}
    CanvasButtonBinding .c next "" "" {PlayAgain 1}
    ::tooltip::tooltip .c -items prev "Previous puzzle"
    ::tooltip::tooltip .c -items undo "Restart puzzle"
    ::tooltip::tooltip .c -items next "Next puzzle"

    # Choose level button
    CanvasButtonBinding .c up "" "" ShowPickPuzzlePage
    ::tooltip::tooltip .c -items up "Choose level"

    .c itemconfig solvedStar \
        -state [expr {[HasBeenSolved $S(stage) $S(level)] ? "" : "hidden"}]
}
proc DrawPickPuzzlePage {} {
    global S B CLR
    set N 6
    ComputeSizes $N
    set B(N) $N
    set B(xy0) [expr {round(-$N/2. * $S(sz))}]

    .c delete all
    DrawConstants
    .c itemconfig solvedStar -state hidden
    for {set row 0} {$row < 5} {incr row} {
        for {set col 0} {$col < $N} {incr col} {
            for {set stage 1} {$stage <= $S(stages)} {incr stage} {
                set num [expr {1 + $row*$N + $col}]
                set fauxCol [expr {$col + ($stage - $S(stage))*$N}]
                set txt_tag "pick$stage,$num"
                lassign [Cell2XY [expr {$row+0}] $fauxCol] . xy x y
                set box_tag [.c create oval $xy -fill black -outline white \
                                 -width 2 -tag [list oval stage stage,$stage]]
                if {[HasBeenSolved $stage $num]} {
                    set star [MakeStar $x $y [expr {$S(radius) - 1}]]
                    .c create poly $star -fill $CLR(star) -outline $CLR(star) \
                        -tag [list star stage stage,$stage $txt_tag]
                }
                incr x 1 ; incr y 2
                .c create text $x $y -text $num -fill white \
                    -font "Helvetica 32 bold" \
                    -tag [list txt stage stage,$stage $txt_tag]
                CanvasButtonBinding .c $txt_tag $box_tag \
                    $::CLR(dialog,highlight) [list PlayChosenPuzzle $num]
            }
        }
    }
    .c itemconfig stage -state hidden
    .c itemconfig stage,$S(stage) -state {}
    
    # Stage and Help
    set N [lindex $::BOARDS($S(stage),1) 0]
    set range "\n([expr {$S(stage)*30-29}]-[expr {$S(stage)*30}])"
    .c itemconfig level,txt -text "$N x $N$range" -anchor w

    # Navigation buttons
    .c delete undo
    CanvasButtonBinding .c prev "" "" {ShiftStage -1}
    CanvasButtonBinding .c next "" "" {ShiftStage 1}
    ::tooltip::tooltip .c -items prev "Previous stage"
    ::tooltip::tooltip .c -items next "Next stage"
    StageButtons $S(stage)

    .c delete up
}
proc HasBeenSolved {stage level} {
    return [expr {[lsearch $::S(solved) $stage,$level] > -1}]
}
proc StageButtons {which} {
    if {[.c find withtag stageButton] eq ""} {
        lassign [.c bbox prev] . . x0 .
        lassign [.c bbox next] x1 y0 . y1
        set gap [expr {($x1 - $x0)/double($::S(stages))}]
        set y [expr {($y0 + $y1) / 2}]
        for {set stage 1} {$stage <= $::S(stages)} {incr stage} {
            set x [expr {$x0 - $gap/2 + $stage * $gap}]
            set xy [Box $x $y $::S(stageButton,size)]
            .c create oval $xy -tag [list stageButton stageButton,$stage] \
                -width 1
        }
    }
    .c itemconfig stageButton -fill $::CLR(stageButton,off) \
        -outline $::CLR(stageButton,off)
    .c itemconfig stageButton,$which -fill $::CLR(stageButton,on) \
        -outline $::CLR(stageButton,on)
}
proc ShiftStage {dir} {
    global S

    if {$dir < 0 && $S(stage) == 1} return
    if {$dir > 0 && $S(stage) == $S(stages)} return
    set nextStage [expr {$S(stage) + $dir}]
    set N [lindex $::BOARDS($nextStage,1) 0]
    set range "\n([expr {$nextStage*30-29}]-[expr {$nextStage*30}])"
    .c itemconfig level,txt -text "$N x $N$range"
    .c itemconfig stage,$nextStage -state {}
    StageButtons $nextStage

    lassign [.c bbox stage,$S(stage)] x0
    lassign [.c bbox stage,$nextStage] x1
    lassign $S(shiftStage,params) steps delay
    set delta [expr {($x0 - $x1) / double($steps)}]
    AnimateMove stage $delta 0 0
    MyWait
    
    .c itemconfig stage,$S(stage) -state hidden
    set S(stage) $nextStage
}
proc AnimateMove {tag xDelta yDelta step} {
    lassign $::S(shiftStage,params) steps delay
    .c move $tag $xDelta $yDelta
    
    incr step
    if {$step < $steps} {
        after $delay [list AnimateMove $tag $xDelta $yDelta $step]
    } else {
        set ::S(wait) 1
    }
}


proc DoButton {action x y} {
    global L B
    if {$::S(state) ne "play"} return
    lassign [XY2Cell [.c canvasy $y] [.c canvasx $x]] row col
    if {$row < 0 || $row >= $B(N) || $col < 0 || $col >= $B(N)} return
    lassign $B($row,$col) what clr
    
    if {$action eq "down"} {
        if {$what eq ""} return

        if {$what eq "node"} {
            # Starting from a node
            set L(delete,$clr) $L(path,$clr)
            set L(path,$clr) [list [list $row $col]]
            set L(done,$clr) 0
            set L(clr) $clr
            array unset L stolen,*
            ShowPath $L(clr)
        } else {
            # Starting from the middle of a path
            set L(clr) $clr
            array unset L stolen,*
            AdjustPath $row $col $L(clr)
            ShowPath $L(clr)
        }
        return
    }
    if {! [info exists L(clr)]} return
    
    if {$action eq "move" && $L(clr) ne ""} {
        lassign [lindex $L(path,$L(clr)) end] lastRow lastCol
        set drow [expr {abs($row - $lastRow)}]
        set dcol [expr {abs($col - $lastCol)}]
        if {! (($drow == 1 && $dcol == 0) || ($drow == 0 && $dcol == 1))} return
        
        set stolen [StealCell $row $col $L(clr)]
        if {$stolen eq "node"} return
        AdjustPath $row $col $L(clr)
        if {$stolen eq "endNode"} {
            set L(done,$clr) 1
        }
        ShowPath $L(clr)
        if {$stolen eq "endNode"} {             ;# Is path complete?
            set L(clr) ""
        }
        CheckUnsteal
        return
    }

    if {$action eq "up"} {
        unset L(clr)

        if {$what ne "node"} return
        CheckVictory
    }
}
# Handles toClr's pipe wanting to move to row,col
# which may cause another pipe to be truncated
proc StealCell {row col toClr} {
    global L B

    lassign $B($row,$col) who oldClr
    if {$who eq ""} {return empty}
    set n [lsearch -exact $L(path,$oldClr) [list $row $col]]
    if {$oldClr eq $toClr} {
        if {$who ne "node"} { return self }
        if {$n == -1} { return endNode }
        return startNode
    }
    if {$who eq "node"} {return node}

    # Here when truncating oldClr's path
    set n [lsearch -exact $L(path,$oldClr) [list $row $col]]
    if {$n == -1} {
        tk_messageBox -icon error \
            -message "B and L messed up for $row $col $toClr"
        return
    }
    # Remember then truncate clr's pipe
    #set L(stolen,$row,$col) [list $oldClr $L(path,$oldClr)]
    lappend L(stolen,$oldClr) [list $row $col $L(done,$oldClr) $L(path,$oldClr)]
    set L(delete,$oldClr) [lrange $L(path,$oldClr) $n end]
    set L(path,$oldClr) [lrange $L(path,$oldClr) 0 $n-1]
    set L(done,$oldClr) 0
    ShowPath $oldClr
    return steal
}
proc CheckUnsteal {} {
    global L B
    foreach arr [array names L stolen,*] {
        set clr [lindex [split $arr ","] 1]
        # NB. ordering is very important: search from end of old path
        # backwards, then if found we can ignore everything closer to beginning
        for {set idx 0} {$idx < [llength $L($arr)]} {incr idx} {
            set steal [lindex $L($arr) $idx]
            lassign $steal row col done oldPath
            if {$B($row,$col) ne ""} continue
            set L(path,$clr) $oldPath
            set L(delete,$clr) ""
            set L(done,$clr) $done
            set L($arr) [lrange $L($arr) 0 $idx-1]
            ShowPath $clr
            break
        }
    }
}
# Adds row, col to clr's path, truncating path if it intersects itself
proc AdjustPath {row col clr} {
    global L

    set L(delete,$clr) {}
    set n [lsearch -exact $L(path,$clr) [list $row $col]]
    if {$n + 1 == [llength $L(path,$clr)]} return
    if {$n > -1} {
        set L(delete,$clr) [lrange $L(path,$clr) $n+1 end]
        set L(path,$clr) [lrange $L(path,$clr) 0 $n]
    } else {
        lappend L(path,$clr) [list $row $col]
    }
}

# draws path for clr, deleting everything in L(delete,...) and
# drawing L(path,...)
proc ShowPath {clr} {
    global L S B

    # Stuff to be deleted
    foreach cell $L(delete,$clr) {
        lassign $cell row col
        if {[lindex $B($row,$col) 0] ne "node"} {
            set B($row,$col) ""
        }
        .c itemconfig cell_${row},$col -fill $::CLR(bg)
    }
    set L(delete,$clr) {}
    
    set xy {}
    foreach cell $L(path,$clr) {
        lassign $cell row col
        if {[lindex $B($row,$col) 0] ne "node"} {
            set B($row,$col) [list path $clr]
        }
        lassign [Cell2XY $row $col] . . x y
        lappend xy $x $y

        set bgClr [::tk::Darken $clr $S(darken,$L(done,$clr))]
        .c itemconfig cell_${row},$col -fill $bgClr
    }
    if {[llength $L(path,$clr)] < 2} {
        .c delete path,$clr
        return
    }
    if {[.c find withtag path,$clr] eq ""} {
        .c create line $xy -tag path,$clr -fill $clr \
            -width $S(lwidth) -capstyle round
        .c raise node
    } else {
        .c coords path,$clr $xy
    }
}
proc DoHint {clr} {
    global L S SOLUTIONS

    if {! $S(hints,canDo)} {
        MyDialog "Turn on hints on\nthe help dialog" ok {destroy .dialog}
        return
    }
        
    if {![info exists SOLUTIONS($S(stage),$S(level))]} {
        MyDialog "No hints available\nfor this level" ok {destroy .dialog}
        return
    }
    incr S(hints,used)
    set hintPath [GetHintPath $clr]
    set L(delete,$clr) $L(path,$clr)
    set L(path,$clr) {}
    ShowPath $clr
    set L(path,$clr) $hintPath
    set L(done,$clr) 1
    foreach cell $hintPath {
        lassign $cell row col
        StealCell $row $col $clr
    }
    ShowPath $clr
    CheckVictory
}
proc GetHintPath {clr} {
    global S BOARDS SOLUTIONS
    array set DIRS {w {0 -1} e {0 1} n {-1 0} s {1 0}}

    set me "$S(stage),$S(level)"
    set idx [lsearch $BOARDS($me) $clr]
    lassign [lrange $BOARDS($me) $idx+1 $idx+4] row0 col0 row1 col1
    set steps [dict get $SOLUTIONS($me) $clr]

    # The saved path may be from either end, build up both
    set path0 [list [list $row0 $col0]]
    set path1 [list [list $row1 $col1]]
    set lastStep ""

    # steps is: e3nws5  and count could be 2 digits, hence regsub
    foreach step [regsub -all {[nsew]} $steps " \& "] {
        set cnt 1
        if {[string is integer $step]} {
            set cnt [expr {$step - 1}]
            set step $lastStep
        }
        while {[incr cnt -1] >= 0} {
            lassign $DIRS($step) drow dcol
            set row [expr {[lindex $path0 end 0] + $drow}]
            set col [expr {[lindex $path0 end 1] + $dcol}]
            lappend path0 [list $row $col]
            set row [expr {[lindex $path1 end 0] + $drow}]
            set col [expr {[lindex $path1 end 1] + $dcol}]
            lappend path1 [list $row $col]
        }
        set lastStep $step
    }
    # Determine which path is correct
    if {[lindex $path0 end] eq [list $row1 $col1]} {
        return $path0
    }
    return $path1
}
# Determine size of a cell which determines the size of everything else
proc ComputeSizes {N} {
    global S

    set w [expr {max([winfo width .c], [winfo reqwidth .c])}]
    set w [expr {$w - 2*$S(margin)}]
    set S(sz) [expr {$w/$N}]
    set S(sz2) [expr {$S(sz)/2}]
    set S(radius) [expr {$S(sz) * $S(radius,factor)}]
    set S(lwidth) [expr {$S(sz) * $S(lwidth,factor)}]
}
proc CheckVictory {} {
    global L B

    foreach arr [array names L path,*] {
        if {[llength $L($arr)] < 2} return
        lassign $arr . clr
        lassign [lindex $L($arr) 0] row col
        if {[lindex $B($row,$col) 0] ne "node"} return
        lassign [lindex $L($arr) end] row col
        if {[lindex $B($row,$col) 0] ne "node"} return
    }

    # Every cell must be used
    for {set row 0} {$row < $B(N)} {incr row} {
        for {set col 0} {$col < $B(N)} {incr col} {
            if {$B($row,$col) eq ""} {
                AlmostVictory
                return
            }
        }
    }
    Victory
    return 1
}
proc AlmostVictory {} {
    if {$::B(almost)} return
    set ::B(almost) 1
    MyDialog "Almost done!\nNow fill all the cells" "skip ahead" {PlayAgain 1} \
        "keep playing" {destroy .dialog}
}
proc Victory {} {
    global S SOLUTIONS
    
    .c itemconfig solvedStar -state ""
    set me "$S(stage),$S(level)"
    if {$S(hints,used) > 0} {
        set hintText "\nwith a hint"
    } else {
        set hintText ""
        if {! [HasBeenSolved $S(stage) $S(level)]} {
            #set SOLUTIONS($me) [CompactPaths]
            set S(solved) [lsort -dictionary -unique [concat $me $S(solved)]]
            WriteRC
        }
    }
    if {$me eq [lindex [lsort -dictionary [array names ::BOARDS]] end]} {
        MyDialog "You finished the\nlast level!$hintText" \
            "restart" {PlayAgain 1} "play again" {PlayAgain 0}
    } else {
        MyDialog "Finished!$hintText" "next level" {PlayAgain 1} \
            "play again" {PlayAgain 0}
    }
}
proc CompactPaths {} {
    array set DIRS {1,0 s -1,0 n 0,1 e 0,-1 w}
    set allPaths {}
    foreach arr [array names ::L path,*] {
        set thisPath [lindex [split $arr ","] 1]
        append thisPath " "
        set row0 -1
        foreach cell $::L($arr) {
            lassign $cell row1 col1
            if {$row0 > -1} {
                set drow [expr {$row1 - $row0}]
                set dcol [expr {$col1 - $col0}]
                append thisPath $DIRS($drow,$dcol)
            }
            lassign [list $row1 $col1] row0 col0
        }
        lappend allPaths $thisPath
    }
    return [join $allPaths " "]
}
proc MakeStar {x y delta} {
    set pi [expr {acos(-1)}]

    # Compute distance to inner corner
    #set x1 [expr {$delta * cos(54 * $pi/180)}]  ;# Unit vector to inner point
    set y1 [expr {sin(54 * $pi/180)}]
    set y2 [expr {$delta * sin(18 * $pi/180)}]  ;# Y value to match
    set delta2 [expr {$y2 / $y1}]

    # Now get all coordinates of the 5 outer and 5 inner points
    for {set i 0} {$i < 10} {incr i} {
        set d [expr {($i % 2) == 0 ? $delta : $delta2}]
        set theta [expr {(90 + 36 * $i) * $pi / 180}]
        set x1 [expr {$x + $d * cos($theta)}]
        set y1 [expr {$y - $d * sin($theta)}]

        lappend coords $x1 $y1
    }
    return $coords
 }

proc ShowPickPuzzlePage {} {
    set ::S(state) pick
    FadeOut all
    DrawPickPuzzlePage
    FadeIn all
}
proc PlayChosenPuzzle {level} {
    set ::S(level) $level
    PlayAgain 0
}
proc PlayAgain {delta} {
    global S BOARDS
    destroy .dialog
    FadeOut all
    set S(state) play
    set S(hints,used) 0

    set S(level) [expr {max(1,$S(level)+$delta)}]
    if {! [info exists BOARDS($S(stage),$S(level))]} {
        incr S(stage) $delta
        set S(level) [expr {$delta > 0 ? 1 : 30}]
    }
    if {! [info exists BOARDS($S(stage),$S(level))]} {
        set S(stage) 1
        set S(level) 1
    }
    WriteRC
    DrawBoard $S(stage) $S(level)
    FadeIn all
}
proc MyDialog {txt args} {
    set C .dialog
    destroy $C
    
    set w [expr {50 + max(150,[MeasureText $txt])}]
    set x [expr {$w/2}]
    set bg purple4
    canvas $C -width $w -height 170 -bd 0 -highlightthickness 0 \
        -bg $::CLR(dialog,bg)
    place $C -anchor c -relx .5 -rely .5

    $C delete all
    $C create text $x 20 -text $txt -fill $::CLR(dialog,txt) \
        -font myDialogFont -anchor n

    foreach {txt command} $args {
        set y [expr {[lindex [$C bbox all] 3] + 15}]
        set id [$C create text $x $y -text $txt -fill $::CLR(dialog,txt) \
                    -font myDialogFont -anchor n]
        lassign [$C bbox $id] . y0 . y1
        set id1 [$C create rect \
                     25 [expr {$y0-5}] [expr {$w-25}] [expr {$y1+5}] \
                     -fill $::CLR(dialog,button) -outline $::CLR(dialog,fg) \
                     -width 2]
        $C raise $id
        CanvasButtonBinding $C $id $id1 $::CLR(dialog,highlight) $command
    }
    lassign [$C bbox all] . . x1 y1
    incr y1 20
    $C config -height $y1

    set id [$C create rect 0 0 $w $y1 -fill $::CLR(dialog,bg) \
                -outline $::CLR(dialog,fg) -width 5]
    $C lower $id
    update idletasks
    grab $C
}
proc MeasureText {txt} {
    set longest 0
    foreach line [split $txt \n] {
        set longest [expr {max($longest,[font measure myDialogFont $line])}]
    }
    return $longest
}


proc Box {x y r} {
    return [list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]]
}
proc Cell2XY {row col} {
    global B S

    set x [expr {$B(xy0) + $col * $S(sz) + $S(sz2)}]
    set y [expr {$B(xy0) + $row * $S(sz) + $S(sz2)}]
    set box [Box $x $y $S(sz2)]
    set oval [Box $x $y $S(radius)]
    return [list $box $oval $x $y]
}
proc Test_Cell2XY {} {
    set x0 0
    for {set i 0} {$i < 7} {incr i} {
        lassign [Cell2XY $i $i] box oval x y
        set delta [expr {$x - $x0}]
        puts "$i : $x   $delta"
        set x0 $x
    }
}
proc XY2Cell {cx cy} {
    global B S
    set row [expr {int(($cx - $B(xy0)) / $S(sz))}]
    set col [expr {int(($cy - $B(xy0)) / $S(sz))}]
    return [list $row $col]
}
proc Recenter {W h w} {
    set h [expr {$h/2}]
    set w [expr {$w/2}]
    $W config -scrollregion [list -$w -$h $w $h]
}
proc FadeIn {tag} {
    FadeOut $tag fadein
}
proc FadeOut {tag {fadein fadeout}} {
    set ids [expr {$tag eq "all" ? [.c find all] : [.c find withtag $tag]}]
    set FADING [dict create]
    foreach id $ids {
        if {[.c itemcget $id -tag] eq "border"} continue
        set type [.c type $id]
        if {$type eq "image"} continue
        set gradient [Gradient [.c itemcget $id -fill] black]
        if {$fadein eq "fadein"} { set gradient [lreverse $gradient] }
        set fading [list fill $gradient]
        if {$type in {"oval" "rectangle" "polygon"}} {
            set gradient [Gradient [.c itemcget $id -outline] black]
            if {$fadein eq "fadein"} { set gradient [lreverse $gradient] }
            lappend fading outline $gradient
        }
        dict set FADING $id $fading
    }
    DoFade $FADING 0
    MyWait
}
proc DoFade {FADING step} {
    lassign $::S(fade,params) steps delay
    
    foreach id [dict keys $FADING] {
        foreach {what gradient} [dict get $FADING $id] {
            set clr [lindex $gradient $step]
            .c itemconfig $id -$what $clr
        }
    }
    incr step
    if {$step < $steps} {
        after $delay [list DoFade $FADING $step]
    } else {
        set ::S(wait) 1
    }
}
proc MyWait {} {
    destroy .grab
    label .grab ; place .grab -x -100 -y -100 ; grab .grab
    tkwait variable ::S(wait)
    destroy .grab
}
proc Gradient {fromColor toColor} {
    if {[info exists ::MEM($fromColor,$toColor)]} {
        return $::MEM($fromColor,$toColor)
    }
    set steps [lindex $::S(fade,params) 0]
    lassign [winfo rgb . $fromColor] r1 g1 b1
    lassign [winfo rgb . $toColor] r2 g2 b2
    
    set steps [expr {$steps <= 1 ? 1 : double($steps - 1)}]
    set gradient {}
    for {set step 0} {$step <= $steps} {incr step} {
        set r [expr {int(($r2 - $r1) * $step / $steps + $r1) * 255 / 65535}]
        set g [expr {int(($g2 - $g1) * $step / $steps + $g1) * 255 / 65535}]
        set b [expr {int(($b2 - $b1) * $step / $steps + $b1) * 255 / 65535}]
        lappend gradient [format "#%.2x%.2x%.2x" $r $g $b]
    }

    set ::MEM($fromColor,$toColor) $gradient
    return $gradient
}
proc CanvasButtonBinding {C text_tag box_tag highlight cmd} {
    global _CB
    set who "$C,$text_tag"
    set oldFill [expr {$box_tag ne "" ? [$C itemcget $box_tag -fill] : ""}]
    set oldOutline [expr {$box_tag ne "" ? [$C itemcget $box_tag -outline] : ""}]
    set _CB($who,data) [list "" $C $box_tag $highlight $oldOutline $oldFill $cmd]
    foreach tag [list $text_tag $box_tag] {
        if {$tag eq ""} continue
        foreach action {Button-1 ButtonRelease-1 Leave Enter} {
            $C bind $tag <$action> [list _CanvasButtonBinding $who $action]
        }
    }
}
proc _CanvasButtonBinding {who what} {
    global _CB

    lassign $_CB($who,data) state C box_tag highlight oldOutline oldFill cmd
    if {$what eq "Button-1"} {
        lset _CB($who,data) 0 "in"
        if {$box_tag ne ""} {$C itemconfig $box_tag -fill $highlight -outline $highlight}
    } elseif {$what eq "ButtonRelease-1"} {
        lset _CB($who,data) 0 ""
        if {$box_tag ne ""} {$C itemconfig $box_tag -fill $oldFill -outline $highlight}
        if {$state eq "in"} {uplevel #0 $cmd}
    } elseif {$what eq "Leave"} {
        if {$state ne ""} { lset _CB($who,data) 0 "out" }
        if {$box_tag ne ""} {$C itemconfig $box_tag -fill $oldFill -outline $oldOutline}
    } elseif {$what eq "Enter"} {
        if {$state ne ""} { lset _CB($who,data) 0 "in" }
        if {$box_tag ne ""} {
            if {$state eq ""} {
                $C itemconfig $box_tag -outline $highlight
            } else {
                $C itemconfig $box_tag -fill $highlight -outline $highlight
            }
        }
    }
}
proc Help {} {
    set msg "Flow Colors\nby Keith Vetter\n\n"
    append msg "The object of Flow Colors is\n"
    append msg "lay pipes to connect all pairs\n"
    append msg "of colors. A level is solved\n"
    append msg "when all the colors are paired\n"
    append msg "and the entire board is filled.\n\n"
    append msg "Flow Colors is based on a game\n"
    append msg "by Mohammed el-Madhoun\n"
    append msg "http://moh97.us/flow\n"
    if {[llength [array names ::SOLUTIONS]] > 0} {
        MyDialog  $msg "ok" {destroy .dialog} "hints" {HelpHint}
    } else {
        MyDialog  $msg "ok" {destroy .dialog}
    }
}
proc HelpHint {} {
    set ::S(hints,canDo) 1
    set msg "Flow Colors Hints\n\n"
    append msg "You can now get a hint by\n"
    append msg "holding down the shift key\n"
    append msg "and double right click on\n"
    append msg "any node.\n"
    MyDialog  $msg "ok" {destroy .dialog}
}
proc ReadRC {} {
    if {[file exists $::S(rcFile)]} {
        uplevel #0 source $::S(rcFile)
    }
    if {[info exists ::S(lastPuzzle)] && [llength $::S(lastPuzzle)] == 2} {
        lassign $::S(lastPuzzle) ::S(stage) ::S(level)
    }
}
proc WriteRC {} {
    global S SOLUTIONS
    catch { 
        set fout [open $S(rcFile) w]
        puts $fout "set ::S(lastPuzzle) {$S(stage) $S(level)}"
        puts $fout "set ::S(solved) {$S(solved)}"
        if {0} {
            puts $fout "array set SOLUTIONS {"
            foreach arr [lsort -dictionary [array names SOLUTIONS]] {
                puts $fout "   $arr {$SOLUTIONS($arr)}"
            }
            puts $fout "}"
        }
        close $fout
    }
}
################################################################
image create photo ::img::left -data {
    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
    AElFTkSuQmCC}
array set SOLUTIONS {
   1,1 {blue s5w green s2 darkorange n4 cyan s3w2 red e3n5 yellow en3e}
   1,2 {blue wn3w2 green s2 darkorange ws5e5n cyan se red n3e2s yellow n2}
   1,3 {red e5s yellow w2s2 blue s3 green s3w2n2w darkorange sw2n4e3}
   1,4 {yellow e2n5w2s2 blue n3 green wn3 darkorange nwn3w2s5e2}
   1,5 {yellow s2e2n blue e2s2w4n5e green ne2s5 darkorange s3e2}
   1,6 {yellow wsw3n2ene2 blue e5s5w green nw4s darkorange ene2}
   1,7 {blue n5e2s3 green s2 darkorange s2w4n4 cyan e2n red n2w yellow s2}
   1,8 {red s3w5n yellow e2s blue s2w2nwn3e2 green e2s3 darkorange ses}
   1,9 {red n3e yellow n2 blue s4 green s2e2n5 darkorange en2w3s5e}
   1,10 {blue w4 green e4 darkorange s3e5 cyan w3 red w4nwn yellow e4}
   1,11 {red w4n3e5s yellow e3 blue se4 green se5n2 darkorange e2}
   1,12 {yellow ne4n3w2 blue ws3e3 green e3s5w4 darkorange w2n}
   1,13 {red ene2s2 yellow ne2s2e3n2wn2 blue n2e2 green wn2w2n darkorange en}
   1,14 {red n2 yellow n5e3s2ws3 blue s4e green n4e darkorange n4w}
   1,15 {blue es green ses darkorange ne cyan n2en2e2s red s3 yellow e2n5w5}
   1,16 {blue e2s5w5 green wsw darkorange s2 cyan ne2 red e2n yellow n2ene3}
   1,17 {blue e2s4w green se3n3 darkorange s2 cyan nw red w3sw yellow ws3ese}
   1,18 {red e2 yellow e2n4 blue e2 green e3s2w3s2e darkorange w5s5}
   1,19 {red w2s yellow e3 blue w3s2 green s5e5n3w darkorange s3e3}
   1,20 {yellow en blue n2e2s green s2w2n4e4s darkorange e2n5w5}
   1,21 {blue se green e4n5 darkorange s2 cyan s4w4s red en2w yellow se3}
   1,22 {red s5w5n yellow e3s2 blue en4w4 green nw darkorange sese}
   1,23 {yellow e3n blue w5s5e5 green w2 darkorange w4n3e4}
   1,24 {blue en green ese darkorange sw3n cyan s5 red e2s3ws yellow sw4n2e}
   1,25 {blue w2 green ws5 darkorange w3 cyan s3e3n2w red n4e4 yellow se}
   1,26 {red e5s5w2 yellow en blue w2sws green en3w4 darkorange ne3}
   1,27 {red ws2es yellow s4e2 blue en3w green nwn4e3s darkorange n4w}
   1,28 {yellow e4n5w4 blue e3 green s2e3 darkorange e3s2w4s2}
   1,29 {blue ne5s3 green s2wsw2n2 darkorange es3 cyan sw2 red en yellow nen2}
   1,30 {red ne5s3 yellow ws2e blue sw2n3wnw green es3 darkorange e2n2w}
   2,1 {blue w6s6e5 green sw darkorange w4s cyan e2s3 red w3n2ene4n yellow nw}
   2,2 {blue e2 green nw3 magenta w2n6e darkorange ws4e cyan sw2nwn red e3n6w4 yellow es}
   2,3 {blue w6n2 green se2 magenta e2 darkorange w2n2 brown es2 red s2e4n cyan e6s yellow wnw5}
   2,4 {red n3ene4s4 yellow nw2 blue n2e2se green e6n6w6s darkorange w2n}
   2,5 {blue se3s2 green en3 darkorange s2ese4 cyan s6e red es2 yellow e4s5w3n3}
   2,6 {blue enwn2e2sw green sw magenta se4n2 darkorange sen3e2 cyan es2 red sw6n2 yellow e2n3}
   2,7 {red e4 yellow se4n blue e2 green ne6s2w5 darkorange s4e6n3w2sw2}
   2,8 {blue w3 green w5n6e4 magenta nw3 darkorange n3e5n cyan wsw4 red e3 yellow s2}
   2,9 {blue w2 green w3n3 darkorange ne5 cyan sws4e6n2 red sw3s2e3 yellow w4n2}
   2,10 {blue n4 green en6w4s5 darkorange s5e cyan ws6 red n2e2s4 yellow n2}
   2,11 {blue ne3s2 green w2 magenta sws2 darkorange se3s cyan s2e red n4 yellow se6n6w2s3}
   2,12 {blue sw3 green n2e6s2w3 magenta n3 darkorange s3e2ne2s2 cyan s3 red ne4 yellow ne3}
   2,13 {blue e2 green sw6n2 darkorange s3 cyan ws red ses2e2nen2 yellow wsw4n2wn3e5}
   2,14 {blue en green n2w magenta n3wn2 darkorange s2 brown nw2s5e red n2w3s cyan s4w2sw2 yellow e2n2}
   2,15 {red sws4e6n6w2s yellow s4w4 blue es2es2w3n green wn2 darkorange ws}
   2,16 {red ese3n yellow e2 blue e2s green n4w6s5e darkorange wnw3n3e4sw3s}
   2,17 {blue e2se green e2se3n magenta nw3 darkorange n3w5s3e cyan w2n2e red en4 yellow wnw2n}
   2,18 {blue w2s3 green n2wn2 magenta se4n3e2 darkorange s2 cyan s2 red n2w6s4es yellow ne3}
   2,19 {blue n2 green ne2 darkorange sw3 cyan sw3s3e2ne red n5e3ne2s3 yellow n6e3}
   2,20 {red w2s5e6n6w3 yellow ese2n2 blue nw2 green w2 darkorange e2s4w4n}
   2,21 {blue wnw3 green e2s2e darkorange es2w3s2e5n6w2 cyan s3 red s4w3 yellow es}
   2,22 {blue e4n3w2s green w2s magenta n2ene4n darkorange s2w6 cyan w4s red nw3 yellow e3}
   2,23 {blue n2 green s6e4n2 darkorange ne3n cyan wsw3s3e red w2n5e3 yellow n3w2}
   2,24 {blue se2 green sw4s2w darkorange n2e6 cyan wnw2sw3n2en2e4 red w3 yellow e3s}
   2,25 {blue en3w3nw2 green s6e3 darkorange ese3s cyan se3s red nw4 yellow e3se2n2}
   2,26 {red n3w yellow e2n2wn2e3s4e blue e6n6w4 green ws4e darkorange n3}
   2,27 {red e2s5w5n2 yellow s2e2n3 blue w6n6e3 green s3 darkorange n2w2s}
   2,28 {blue e5n6w green e2s3 magenta ese2 darkorange nen cyan w3n2w2s red se2n3 yellow se3}
   2,29 {blue e2 green se2n2e darkorange w3n cyan nw3 red ne4s3 yellow nwn4e6s5w2}
   2,30 {blue es3 green e2 magenta e2s darkorange es2e2s2e3s2w6n2 cyan s2w red se4 yellow s2e2s}
   3,1 {blue es2w green s5w3nwn3e2 darkorange se cyan w3s5ese5n5 red w4s7e yellow n2e2s}
   3,2 {blue n4w4n green sw3s darkorange ene4n5 cyan e5s7w4 red s2e4s3w3sws yellow e2}
   3,3 {blue e4s3e green n4w5sws2e4s3e2s darkorange w3s2e6 cyan s2w3 red ws4e3 yellow e3}
   3,4 {blue wsw3 green n3e6s magenta nw4 darkorange e3ne2 cyan w4s2e4 red wn2e3 yellow sw7n7}
   3,5 {blue s4w2 green w6s4e darkorange e5 cyan e6nw4nenw red n2e2 yellow wn2e2n3e2ne2swse}
   3,6 {blue n2w3n2e4 green nw4nw2s magenta es3e3s darkorange n3w3 cyan w4n red e2s3e3s2e2 yellow wn5}
   3,7 {red wnenes6wn3ws3wn2wnws2esw3n2es yellow w2s blue e3s green wn2ene2sw darkorange ne4s2}
   3,8 {blue n2w4sws green n2ene5n2 magenta sw2 darkorange sw5s cyan w5s7e4n red w2n2w yellow wn2w2}
   3,9 {blue enes2e2n5w4se green es3 darkorange ne2 cyan se4n2 red n3e2s7w7n2 yellow n5}
   3,10 {blue wswseswse green w2nw2se darkorange nes2wse2nesenen4 cyan w2 red n2w4s5 yellow sw6n4}
   3,11 {blue e2 green wsesw magenta es7w3nw4s darkorange eneses cyan s2 red e2se yellow esw2n5es3en3es3}
   3,12 {blue e2 green wnw3sws2 darkorange e2n cyan wsws2ws2e4se2nw red ws7e4 yellow e2nwne2senen3w}
   3,13 {blue e2 green wnwn2e3s darkorange s5ese2ne3 cyan n3w5s4es red n3 yellow se7n3w2nwnw}
   3,14 {blue sw2s2en green n2w4 darkorange e5 cyan wn4e2ne4s4 red nes2w2se2 yellow w2s6e6s}
   3,15 {blue wn5ene5s4w2n2 green ws7e3 darkorange se3 cyan e2 red w3nwnwn3ene3s2 yellow nen}
   3,16 {blue n3e green s7w2n7w5 magenta s6 darkorange n3e4 cyan w3s4e red s2 yellow s2e4n3}
   3,17 {blue e7s7w green enen magenta e4s3 darkorange n3w6s2 brown w3 red w3s2 cyan s3e3nen yellow ne}
   3,18 {blue e2s green s5 magenta sw darkorange s5 purple s4w6n4 brown ws2e4n3 red ne2s cyan ese2n3w3 yellow en}
   3,19 {blue s2w4s2e7n3w green w5 magenta sw3 darkorange es3w2nw brown ene3ses red wsw2 cyan ws3e2 yellow se}
   3,20 {blue ne2 green w3n4 magenta w2 darkorange w2s2es4 purple n2w2 brown n2e4s2w2s red wnw3n2e cyan e2n3 yellow es2e3}
   3,21 {blue s4 green e2n2wn2wn2w4s magenta sws darkorange s2 brown wn7e5 red nenen cyan wn2 yellow en5w2sws}
   3,22 {blue es7w5n5 green w3n4 darkorange nw cyan ws5 red s2e2n4 yellow wn7e3seses2}
   3,23 {blue w4n green w2sw2n7 magenta e2s6w4 darkorange nw2s3e5s3 cyan w3s red ne3 yellow n2w4}
   3,24 {blue wn4e2s3 green ws7 magenta s3e3n darkorange ses5e5n7w5 cyan es red s2 yellow s4}
   3,25 {blue e2s5 green w3s magenta e2s2w darkorange ene3n3w3 cyan en7w4 red se2s5w3 yellow w3n3e}
   3,26 {blue e2s2 green enene2s3ws magenta wnw darkorange e7n7w4s brown nen red se6n cyan s2 yellow s3ese}
   3,27 {blue wn4e4s green w2s2 magenta n2e3n3w5 darkorange nw7s7e3 cyan enen3 red e3n yellow ws}
   3,28 {blue nw7s7e3 green s2w2 magenta n2e darkorange n5wnw3 cyan e2n4 red en2e2s3 yellow e4n4}
   3,29 {blue w3s7e7n4 green e3nes3 darkorange es2es2 cyan n4en2ws red nenwnw yellow s3e2nes}
   3,30 {blue n5e2s3 green n2 magenta s3 darkorange es7w7n7e4 cyan s2 red e3n2w2n3 yellow w3s}
   4,1 {blue nw4 green e2 magenta e4n2e2 darkorange w2 purple s3w8n2e brown e6n2 red s2e3s cyan wn yellow e4n2e2n4w8s5}
   4,2 {blue e6ses2 green s4 magenta n2 darkorange s2 brown es8w4n2e2n4wnw5s2 red n4e cyan s3w2 yellow n3w3s2ws4e2}
   4,3 {blue ne2 green e2nw3ne3nwnwswnw2s3 magenta s4e2n6e2ne3sw2 darkorange s2 cyan s4 red w5ne2 yellow nene2ne5s3}
   4,4 {blue ws4e green w4s2 magenta s2 darkorange s4e2s2w4n7 cyan w6s6e2 red nw3s2w yellow s8e6n5e}
   4,5 {blue en2en3 green e2s3e magenta s6e8n2 darkorange es6 brown s3ws red w4n2 cyan nen5w5s2es2w2s3 yellow e2s2}
   4,6 {blue s2ws green e4 magenta nw5s4w darkorange e2n4e2 purple n5w2 brown s2e white en8w8s5 red wn3 cyan wn3e yellow e3}
   4,7 {blue n3 green n2e2ses5 magenta e2s7 darkorange ws4e5n2 purple ws4 brown s2e white s2e3n7w red en2 cyan s4 yellow s8}
   4,8 {blue e8s green e4s2w3s4e3 magenta w2 darkorange ne3 brown ese3n4w2sw4s red n2 cyan w8n6e3 yellow nw3sw}
   4,9 {blue s8e8n5 green w2s3 magenta s2 darkorange n3 brown es4e2n4e4s2 red e3n cyan s3w5s yellow w3sw2n6}
   4,10 {blue se2 green en2w2n4e8s6 magenta n3 darkorange wn6w6s2e3s4e cyan w5n3e red wn4w3 yellow e2n3}
   4,11 {blue se green e3s magenta w3n2e3n2 darkorange e3s6 purple es2 brown s4 red eseses3 cyan ne7s8w2n6w yellow nwnw2n2}
   4,12 {blue sw2 green w3 magenta w4n5e2 darkorange wsw4 brown n2e8s3wsw6s3e4se3n2ws red swsw3 cyan e3 yellow e4s}
   4,13 {blue n2w3 green n6e6 magenta s2e4n8w8s8e2n4 darkorange es2es brown wnw red ws3 cyan s2e yellow w5}
   4,14 {blue e2 green se4n2 magenta sw2 darkorange n2e6nenen3w4s purple se2 brown nw2sw3nw red w5n4e3s cyan en2 yellow s2e6n4}
   4,15 {blue w6s2e green w3s3enesenesen3wsw3 magenta s2 darkorange e7 cyan e8s8w2nen4w2sw2 red e2 yellow s2}
   4,16 {blue w3 green s7w2n2 magenta en darkorange wsw4s2 purple ne5 brown n6 red sen2w3sw2n6e4 cyan wse8 yellow e4n2}
   4,17 {blue ne5s3w2s green e8n4 darkorange nwsw5ne4n3w2n2w2sesws2enesen cyan s3w7 red w2 yellow sw2s2}
   4,18 {blue w3s6 green w2n3 magenta w2 darkorange n2w2 purple sw3 brown s3 red n5e3ne cyan s8 yellow w6n8e7s4w2}
   4,19 {blue s3w7n8e6s green es3w3s magenta w2s3 darkorange w4n2 purple n4e2 brown sw2nw red s3e3s cyan n4w yellow sw2n2}
   4,20 {blue e2s5 green swsws2w3n4 magenta s3e2 darkorange s2w5n5 purple wn2 brown n3w2s2wsws red sws cyan n2wn3 yellow n4w2n2e4}
   4,21 {blue n2e3 green sw8n5e2 magenta n6w8s2e6 darkorange wn2e3n3w6 cyan wn3e red sese3n yellow n2w2}
   4,22 {blue s2e green s2es2w8n4e2s magenta w3s darkorange w4s3e3s2es purple e2s2 brown w3 red n2wnw cyan s4e yellow nw3s6w2nw}
   4,23 {blue s4 green en4wnwn magenta eses darkorange ne3 purple wsw3n2 brown s3e red nw3n2w cyan nw8s3es5e5ne yellow w2s2es2e}
   4,24 {blue s3w2n6 green n5w5s magenta s5 darkorange w2s8e8n2 brown e3s3 red nw2n3w2n cyan s3e2 yellow e2s3e}
   4,25 {blue sw3s2ws green s8e7n2 magenta n4e5 darkorange en2e2 brown w2n red e3s4w2s cyan s8 yellow s7e5n}
   4,26 {blue e4n green w5n3e4 magenta s3e3 darkorange w2 purple w3n2w4n2e3 brown e3nen3e red w3s cyan en3 yellow e2n6w3s2w3}
   4,27 {blue swswn green wnen3w2sw magenta s2 darkorange e2s6w brown wn4en3en red wse2nese3n8w4s cyan s2ws4e2 yellow ws3}
   4,28 {blue e4n4w3n2e green sw3n2en5 magenta ne darkorange s3e3s2w cyan nwn6e5s3w2 red n5e2s7w yellow e3s}
   4,29 {blue nw4s green s2w4 magenta w2sw5s6e darkorange e4 brown e2 red w4s2ese6n4w cyan e8s3w yellow ws4w4}
   4,30 {blue n5en2 green s2w3s2w2s2es2w3n4 magenta es2e darkorange s3 purple sw3 brown wn7w2s2 red n2e3 cyan sw3s2w yellow n3w2s3}
   5,1 {blue s3 green s5w4 magenta w6ne7 darkorange s6en3e3n2w3ne4s3 cyan w4s2e5 red w2 yellow s8w}
   5,2 {blue e8 green w8n3 magenta se2n2 darkorange s2 brown e2 red e8s5wn4ws3wn cyan nw2n2esenesen yellow s2e4ne}
   5,3 {blue s4 green s6e2 magenta w2s6e7 darkorange e4 purple s4en brown s4 red s5 cyan w3n2wn4w4s7 yellow n5}
   5,4 {blue ne7n7 green s3 darkorange w5seswse2sw2se2sw2s2 cyan e6 red e4n6wswsesw2se2sw2 yellow ne2s}
   5,5 {blue esw5s6w2n7 green w4s6 darkorange w3n4e5n2 cyan n5w4s2e2 red w3 yellow e7n4w2}
   5,6 {blue s4 green s3e5 magenta w3 darkorange e5 purple s3e4 brown e4s white s3e8n8 red n5w4 cyan e4s yellow w5s}
   5,7 {blue s3 green s6w7n2e3nw2n2esen magenta e4 darkorange s4e purple e5 brown w5 red swnwsw6n4 cyan s3 yellow sen2w}
   5,8 {blue e7 green enwn6e7 magenta s2 darkorange s3 purple se6 brown w4 red swn3 cyan se2n2e3sw2s2wse4nw2ne2 yellow e2s}
   5,9 {blue e7 green e6n magenta w5 darkorange w2swnwswnwswn2 purple s6 brown e8 red n2w6 cyan e5 yellow wsw6s4}
   5,10 {blue n3e4 green w3ses3w4n5es4e2n darkorange n8 cyan s4w6 red w7n2e6n4e yellow s5}
   5,11 {blue ne8 green s3e6 magenta w4 darkorange w7 purple s3 brown n2es2en2es2 white e3 red n6e2s2 cyan e5s5 yellow s5}
   5,12 {blue w7s8 green w6n4e6 magenta e6s4w3n darkorange s2 brown e2 red e5 cyan e6 yellow swnw5s2e3}
   5,13 {blue w6 green s8 magenta w3 darkorange w6n8e7 purple w5 brown e3sw3 red s3 cyan e4s4 yellow n5e6}
   5,14 {blue s6e green e5 magenta s2 darkorange wswn8 purple s5 brown w2s3 white w4 red n5 cyan s3w3n5e4 yellow n7w5}
   5,15 {blue n5 green s5e8 magenta w5 darkorange n2w7s2 cyan w6n2e5 red e3 yellow n6es3en3e3sw2se3}
   5,16 {blue e3 green s5 magenta w5swn6 darkorange nes4 purple e3 brown w5n white w3 red nwswnws cyan senesen yellow e2nwnenwnenwnenwne}
   5,17 {blue w8n7 green s6 magenta w5 darkorange n6e6s5 brown e8 red s3 cyan s3 yellow n4w2s4wn4w}
   5,18 {blue s5 green s8e8 magenta e2 darkorange s5e6 purple w7 brown e7 red s4 cyan w4s3e4n2w3 yellow w4}
   5,19 {blue n3ene5 green s3w3s2e3sw3se3sw4n4 magenta s4 darkorange ws8 purple n2 brown e2 red n3en3 cyan ne3 yellow w4s2}
   5,20 {blue s2 green s2 magenta wn2w2sesw darkorange s8e8 purple e5 brown ws4ene6n2w3 white w5 red e2n3 cyan s yellow n3e5}
   5,21 {red w2ne7 yellow s6e8s2w5 blue s2e4nw3ne3nw4ne4nw4 green s3 darkorange s5e2n5w}
   5,22 {blue s7 green w6s3 magenta nese darkorange s8e5nesen2wnenw2nw2 brown wse2ne red swnw3 cyan s yellow e5s7}
   5,23 {blue s3e8n green w6 magenta s3 darkorange w7s2e6 brown w4 red wsw6 cyan e6s2 yellow sw6n4e6}
   5,24 {blue e3n2w3 green e4 magenta s4w7 darkorange w2s2e2 brown e8n5 red w6s2e6 cyan nwsw6 yellow w8}
   5,25 {blue ws4 green n3 magenta ne6n4w3 darkorange w2n4w2 brown e2s2w3 red w5 cyan e4s6 yellow e8n8w5}
   5,26 {blue s7e green s7e5n6w3 magenta e8n8w4 darkorange s6 cyan s4en4 red s4 yellow s6}
   5,27 {blue s4 green s4wse3nwnen3 magenta e2s6 darkorange ws8e5 cyan s5 red ne6s8w2n6 yellow ws3}
   5,28 {blue s6 green w5s7w magenta s3w2se5n4en4 darkorange e6 brown s3 red w3s3 cyan s3ws4wn4w yellow s4e}
   5,29 {blue s5es3 green n4e6s2w4s2 magenta s2 darkorange sen2wn6 brown n7e4 red e2s4w3n3 cyan s2 yellow e3s5}
   5,30 {blue e2 green e3s5w4 magenta w2s3wn4 darkorange w2n2e8s8 brown se5sw5 red e3s2w3 cyan esene3 yellow w2}
}
image create photo ::img::undo -data {
    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}
image create photo ::img::right -data {
    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
    JRQAAAAASUVORK5CYII=
}
image create photo ::img::help -data {
    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
}
image create photo ::img::up -data {
    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
    rkJggg==
}
################################################################

ReadRC
DoDisplay
DrawBoard $S(stage) $S(level)

return