Intro edit
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 [1].HJG 2015-06-18: That link expired, last archived version: [2]Also: http://www.senscritique.com/jeuvideo/Flow_Colors/10749199/actualites
Program edit
##+########################################################################## # # flowColors.tcl -- plays game Flow Colors # http://moh97.us/flow/ # by Keith Vetter April 2014 # package require Tk package require Img 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(platform) 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 {$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 [list $::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
Comments edit
ak - 2014-04-24 19:09:21Oh yes on the addictive. Have this on my pad. Running the pipes with the fingers is very natural. Lost quite some time on it. Having it for Tcl is really nice. Thanks, Keith.HJG 2014-04-24 - Nice program, but I encountered some problems:
- Tcl 8.5 complains about the image-format kpv added 'package require Img
- when running the program the second time, it fails to load/source the savefile .flowColorsrc from a directory with spaces (as in 'C:/Dokumente und Einstellungen/...') MG added list around the dir to hopefully fix this
- $tcl_platform(os) returns on WinXP with "Windows NT", so the default filename for linux is used MG Changed to tcl_platform(platform)
- also: sometimes, when connecting the last pipe from A->B the level does not end. But it works when doing it B->A. I haven't found a clear testcase for this yet...