if 0 {[Richard Suchenwirth] 2003-11-23 - This game was marketed as "The a-Maze-ing Labyrinth" - here's my Tcl approximation to it. [http://mini.net/files/shiftmaze.jpg] The maze is a 7*7 grid of cards, 16 of which are fixed on the board, 34 are movable - 33 on the board, and one "off-board" card. You can insert this card at any place where an orange arrow is displayed, and shift the cards in that row or column by one position. Rotate the off-board card by right-clicking. '''WARNING:''' This is still under development - shifting cards works in the good case, but can easily go wrong on other mouse movements. Fixes welcome! [DKF]: Hmm. I've not encountered this game before; what's the winning condition(s)? [AK]: Each player has a colored token to move. Start locations for the tokens are in the four corners. Each player has a set of cards showing treasures (hide them from other the players). Some pieces of the board (fixed, and moveable) show the same treasures. Each player looks at the topmost treasure card he has, and whenever it is his turn he tries to shift the labyrinth so that his token can move from the current place to the treasure without hitting a wall. He can also move the token (even if the treasure is not hit). When a player was able place his token on a treasure the treasure card is made visible, and the player can work on getting to the next treasure in his set of cards. When a player has visited all treasures on his cards he has to shift the labyrinth so that he can get his token back to his start location. When he reaches the start location again, and is the first to do so, he wins. } ---- proc main {} { global g set g(size) 40 set side [expr $g(size)*9] pack [canvas .c -width $side -height [expr $g(size)*10] -bg purple] #------- fixed cards card .c L 2 1 1 card .c T 0 3 1 card .c T 0 5 1 card .c L 1 7 1 card .c T 1 1 3 card .c T 1 3 3 card .c T 0 5 3 card .c T 3 7 3 card .c T 1 1 5 card .c T 2 3 5 card .c T 3 5 5 card .c T 3 7 5 card .c L 3 1 7 card .c T 2 3 7 card .c T 2 5 7 card .c L 0 7 7 #--- arrows set y0 [expr $g(size)*0.7] set y1 [expr $g(size)*8] set y2 [expr $g(size)*8.3] foreach x {2.5 4.5 6.5} { set x0 [expr $x*$g(size)] foreach line [list [list $x0 $y0 $x0 $g(size)] \ [list $x0 $y2 $x0 $y1] [list $y0 $x0 $g(size) $x0]\ [list $y2 $x0 $y1 $x0]] { .c create line $line -arrow last -width 5 \ -fill orange -tag arrow } } #--- movable cards set cards [split [rep I 13][rep L 15][rep T 6] ""] set y 1 foreach row { {0 1 0 1 0 1 0} {1 1 1 1 1 1 1} {0 1 0 1 0 1 0} {1 1 1 1 1 1 1} {0 1 0 1 0 1 0} {1 1 1 1 1 1 1} {0 1 0 1 0 1 0} } { set x 1 foreach col $row { if $col { card .c [ldraw cards] [lpick {0 1 2 3}] $x $y } incr x } incr y } #--- the last card is off-board card .c $cards 0 4 9 mvcard movable .c mvcard } proc card {w shape rot x y {tag ""}} { global g $w create rect [expr {$x*$g(size)}] [expr {$y*$g(size)}] \ [expr {($x+1)*$g(size)}] [expr {($y+1)*$g(size)}] \ -fill brown -tag $tag switch -- $shape { I {set coo {0 0.3 1 0.3 1 0.7 0 0.7}} L {set coo {0.3 1 0.3 0.3 1 0.3 1 0.7 0.7 0.7 0.7 1}} T {set coo {0 .7 0 .3 .3 .3 .3 0 .7 0 .7 .3 1 .3 1 .7}} } set id [$w create poly $coo -fill beige -tag $tag] rotate $w $id $rot 0.5 0.5 $w scale $id 0 0 $g(size) $g(size) $w move $id [expr {$x*$g(size)}] [expr {$y*$g(size)}] } interp alias {} rep {} string repeat proc rotate {w tag rot xm ym} { set coords {} foreach {x y} [$w coords $tag] { set r [expr hypot($xm-$x,$ym-$y)] set a [expr atan2($ym-$y,$xm-$x)-$rot/2.*acos(-1)] set x2 [expr $xm+cos($a)*$r] set y2 [expr $ym+sin($a)*$r] lappend coords $x2 $y2 } $w coords $tag $coords } proc rotate2 {w tag rot} { foreach id [$w find withtag $tag] { if {[$w type $id]=="polygon"} {set poly $id; break} } foreach {x0 y0 x1 y1} [$w bbox $tag] break set xm [expr {($x1+$x0)/2.}] set ym [expr {($y1+$y0)/2.}] rotate $w $poly $rot $xm $ym } proc movable {w tag} { $w bind $tag <1> {set g(x) %x; set g(y) %y} $w bind $tag [list move %W $tag %x %y] $w bind $tag [list release %W $tag] set poly {} $w bind $tag <3> [list rotate2 $w $tag 3] } proc move {w tag x y} { global g $w move $tag [expr {$x-$g(x)}] [expr {$y-$g(y)}] array set g [list x $x y $y] } proc release {w tag} { global g #--- snap card in exact place foreach {x y - -} [$w bbox $tag] break set s2 [expr {$g(size)/2.}] set dx [expr -round($x-$s2)%$g(size)-$s2-1] set dy [expr -round($y-$s2)%$g(size)-$s2-1] $w move $tag $dx $dy #--- on arrow? foreach {x0 y0 x1 y1} [$w bbox $tag] break set ok 0 foreach item [$w find overlapping $x0 $y0 $x1 $y1] { if {[$w type $item] eq "line"} {incr ok; break} } if !$ok return set dir {0 0} if {$x0==-1} {set x1 [expr $g(size)*8+1]; set dir {1 0}} if {$x0==$g(size)*8-1} {set x0 -1; set dir {-1 0}} if {$y0==-1} {set y1 [expr $g(size)*8+1]; set dir {0 1}} if {$y0==$g(size)*8-1} {set y0 -1; set dir {0 -1}} if {$dir ne {0 0}} { foreach {dx dy} $dir break foreach item [$w find enclosed $x0 $y0 $x1 $y1] { if {[$w type $item] eq "line"} continue $w move $item [expr $dx*$g(size)] [expr $dy*$g(size)] } $w dtag $tag } #--- find out-shifted card switch -- $dir { {0 1} {set y0 [expr $g(size)*8-1]} {0 -1} {set y1 [expr $g(size)-1]} {1 0} {set x0 [expr $g(size)*8-1]} {-1 0} {set x1 [expr $g(size)-1]} } $w addtag $tag overlapping $x0 $y0 $x1 $y1 $w dtag arrow $tag movable $w $tag $w raise $tag } #--- General utilities: proc ldraw listVar { upvar 1 $listVar list set pos [expr {int(rand()*[llength $list])}] K [lindex $list $pos] [set list [lreplace $list $pos $pos]] } proc K {a b} {set a} proc lpick list {lindex $list [expr {int(rand()*[llength $list])}]} bind . {console show} main bind . {exec wish $argv0 &; exit}