[Keith Vetter] 2003-10-31 : here's an addictive little arcade type game similar to [Gem Game] (in fact I reused most of its code) based on a applet at [http://www.gamehouse.com/affiliates/template.jsp?AID=1406]. The object of the games is to collapse the rising blocks to get as many points as possible. You click on a colored block and if it has three or more neighbors of the same color, they explode and the blocks above collapse down. But as your exploding blocks, new lines of blocks are being added. I'm not quite done with the code, a few final touches are needed and perhaps people here might have some suggestions. Two things in particular come to mind: 1) a better visual indicator of how much time before a new row appears, and 2) some sort of end of level bonus probably based either on height or number of blocks, along with some cute visual display. It's a fun little game, enjoy. ---- [KPV] 2003-11-04 : puts some finishing touches on this game: end of round bonuses, new levels, and better visual for the new line. ---- [male] 2003-11-21: First, when the game is over, and I want to restart, to start a new game, then the "game over" in the screen won't disappear and every click inside the screen won't cause collapse/slide actions. Second, toggling the pause button won't everytime cause a pause. The First problem is change inside the source. ---- [HJG] when pause is activated during LevelOverAnimation, it gets reset when the next level starts ---- The "pocket edition" is at [Collapse (iPaq)] :-) ---- ##+############################################################### # # Collapse # http://www.gamehouse.com/affiliates/template.jsp?AID=1406 # by Keith Vetter -- October 2003 # # KPV Oct 30, 2003 - Initial revision starting with gemgame code # KPV Nov 04, 2003 - EOR bonus, new row count down display, new levels # male Nov 21, 2003 - Game Over canvas items with tags, delete # in NewGame # # TODO: # bombs package require Tk 8.4 array set S {title "Collapse" version 1.0 cols 12 rows 15 cell 27 delay 10 mute 0 numSteps 4 level 1 ticks 13} set S(rowsX) [expr {$S(rows) - 1}] array set LEVEL { 1 {srows 4 tiles 3 newRow 5000 lines 25} 2 {srows 5 tiles 3 newRow 4000 lines 30} 3 {srows 7 tiles 3 newRow 2000 lines 30} 4 {srows 7 tiles 3 newRow 1000 lines 30} 5 {srows 8 tiles 3 newRow 1000 lines 35} 6 {srows 9 tiles 3 newRow 1000 lines 40} 7 {srows 10 tiles 3 newRow 1000 lines 45} 8 {srows 3 tiles 3 newRow 700 lines 20} 9 {srows 4 tiles 3 newRow 700 lines 25} 10 {srows 5 tiles 3 newRow 700 lines 25} 11 {srows 4 tiles 4 newRow 4000 lines 25} } proc DoDisplay {} { global S wm title . $S(title) set w [expr {$S(cell) * $S(cols) + 5}] set h [expr {$S(cell) * $S(rows) + 5}] CompressImages option add *Label.background black frame .ctrl -relief ridge -bd 2 -bg black canvas .c -relief ridge -bg black -height $h -width $w \ -highlightthickness 0 -bd 2 -relief raised canvas .cc -relief ridge -bg black -height [expr {5 + $S(cell)}] -width $w \ -highlightthickness 0 -bd 2 -relief raised label .score -text Score: -fg white .score configure -font "[font actual [.score cget -font]] -weight bold" option add *font [.score cget -font] label .vscore -textvariable S(score) -fg yellow label .vscore2 -textvariable S(score2) -fg yellow label .level -text Level: -fg white label .vlevel -textvariable S(level) -fg yellow label .lines -text "Lines Left:" -fg white label .vlines -textvariable S(lines) -fg yellow button .new -text "New Game" -command NewGame set levels {} foreach a [lsort -integer [array names ::LEVEL]] { lappend levels "Level $a" } eval tk_optionMenu .optlvl S(strlvl) $levels .optlvl config -highlightthickness 0 trace variable ::S(strlvl) w Tracer checkbutton .mute -text Mute -variable S(mute) -relief raised -anchor w checkbutton .pause -text Pause -variable S(pause) \ -command {Pause 0} -relief raised -anchor w button .about -text About -command About pack .ctrl -side left -fill y -ipady 5 -ipadx 5 pack .c -side top -fill both -expand 1 pack .cc -side top -fill both -expand 1 grid .score -in .ctrl -sticky ew -row 1 grid .vscore -in .ctrl -sticky ew grid .vscore2 -in .ctrl -sticky ew grid .level -in .ctrl -sticky ew grid .vlevel -in .ctrl -sticky ew grid .lines -in .ctrl -sticky ew grid .vlines -in .ctrl -sticky ew grid rowconfigure .ctrl 20 -minsize 10 grid .new -in .ctrl -sticky ew -row 25 -pady 1 grid .optlvl -in .ctrl -sticky ew -pady 1 grid .mute -in .ctrl -sticky ew -pady 1 grid .pause -in .ctrl -sticky ew -pady 1 grid rowconfigure .ctrl 50 -weight 1 grid .about -in .ctrl -row 100 -sticky ew -pady 5 bind all {console show} bind .c

{Pause 1} bind .c

{Pause 1} bind .c [list StartStop 0] bind .c {set S(tcnt) 0} focus .c for {set row 0} {$row < $S(rows)} {incr row} { for {set col 0} {$col < $S(cols)} {incr col} { .c create image [GetXY $row $col] -tag [list c$row,$col cell] .c bind "c$row,$col" [list DoClick $row $col] } } for {set col 0} {$col < $S(cols)} {incr col} { .cc create image [GetXY 0 $col] -tag [list c$col cell] } } proc CompressImages {} { image create photo ::img::img(0) ;# Blank image foreach id {1 2 3 4} { ;# Each image we have foreach a {2 3 4} { ;# We need narrower images image create photo ::img::img($id,$a) if {$a == 4} continue ::img::img($id,$a) copy ::img::img($id) -subsample $a $a } } } proc Tracer {var1 var2 op} { ;# Handles level optionMenu if {$var2 == "strlvl"} { scan $::S(strlvl) "Level %d" level if {$level == $::S(level)} return set ::S(level) $level NewGame } } proc NewGame {} { array set ::S {score 0 state 0 score2 "" best 0} catch {eval .c delete gameOver;} StartLevel Banner "CLICK TO START" WaitClick } proc StartLevel {} { global S B BB LEVEL StartStop 0 array set S {busy 0 needRow 0 pause 0} if {! [info exists LEVEL($S(level))]} { ;# Above set levels set lvl [expr {$S(level) % 10}] if {$lvl == 0} {set lvl 10} array set S $LEVEL($lvl) set S(tiles) 4 ;# Always use 4 tiles } else { array set S $LEVEL($S(level)) set S(strlvl) "Level $S(level)" } set S(newRowX) [expr {$S(newRow) / $S(ticks)}] ;# Tick mark interval .c delete banner .c itemconfig cell -image {} array unset B set row1 [expr {$S(rowsX) - 4}] for {set row -1} {$row < $S(rows)} {incr row} { for {set col -1} {$col <= $S(cols)} {incr col} { if {$row < 0 || $row == $S(rows) || $col < 0 || $col == $S(cols)} { set B($row,$col) -1 } else { set B($row,$col) 0 } } } for {set col 0} {$col < $S(cols)} {incr col} { set BB($col) 0 } DrawBoard for {set i 0} {$i < $S(srows)} {incr i} { UpRow } } proc DrawBoard {} { global S B for {set row 0} {$row < $S(rows)} {incr row} { for {set col 0} {$col < $S(cols)} {incr col} { .c itemconfig "c$row,$col" -image ::img::img($B($row,$col)) } } } proc DrawBoard2 {} { ;# The new row board global S BB for {set col 0} {$col < $S(cols)} {incr col} { .cc itemconfig c$col -image ::img::img($BB($col)) } } proc GetXY {r c} { global S set x [expr {5 + $c * $S(cell) + $S(cell)/2}] set y [expr {5 + $r * $S(cell) + $S(cell)/2}] return [list $x $y] } proc DoClick {row col} { ;# Handles mouse clicks global S if {$S(state) == 0} { Banner "" StartStop 1 set S(state) 1 if {$row == -1} return } if {$S(state) != 1} return if {$S(busy)} return set S(busy) 1 Explode $row $col set S(busy) 0 if {$S(needRow)} NewRow } proc Explode {r c} { set cells [FindNeighbors $r $c] ;# Find who should explode if {$cells == {}} return if {! $::S(mute)} {catch { snd_ok play }} # Update our score set cnt [llength $cells] set n [expr {$cnt * $cnt}] incr ::S(score) $n set ::S(score2) "" ;# Show special scores if {$cnt > 3} {set ::S(score2) "($n)"} ExplodeCells $cells ;# Do the explosion affect CollapseCells ;# Move cells down CompactCells ;# Move cells inward if {[IsEmpty]} { incr ::S(score) 1000 Banner "1000 POINT BONUS" after 1000 [list Banner ""] } } proc FindNeighbors {row col} { ;# Find all triplets and up global S B # We'll do a flood fill (bfs) to find connected components set q [list $row $col] ;# Our BFS queue set qhead 0 ;# Head of the queue array unset neighbors ;# Whose in our neighborhood set neighbors($row,$col) 1 ;# We're in our own neighborhood set type $B($row,$col) ;# Type of our neighborhood set cnt 1 while {[llength $q] > $qhead} { ;# While stuff in the queue foreach {r c} [lrange $q $qhead [incr qhead]] break incr qhead foreach {dr dc} {-1 0 1 0 0 -1 0 1} { ;# Look n,s,e & w set r1 [expr {$r + $dr}] set c1 [expr {$c + $dc}] if {[info exists neighbors($r1,$c1)]} continue ;# Already seen if {$B($r1,$c1) != $type} continue ;# Wrong type set neighbors($r1,$c1) 1 ;# Another neighbor lappend q $r1 $c1 ;# Add to our BFS incr cnt } } if {$cnt < 3} {return {}} return [array names neighbors] } proc ExplodeCells {cells} { foreach stage {2 3 4} { foreach who $cells { .c itemconfig c$who -image ::img::img($::B($who),$stage) if {$stage == 4} {set ::B($who) 0} } update after [expr {$::S(delay)}] } } proc CollapseCells {} { global B S while {1} { ;# Stop when nothing slides set sliders {} for {set col 0} {$col < $S(cols)} {incr col} { set collapse 0 for {set row $S(rowsX)} {$row >= 0} {incr row -1} { if {$B($row,$col) == -1} break if {$B($row,$col) == 0} { set collapse 1 } elseif {$collapse} { lappend sliders $row $col y } } } if {$sliders == {}} break SlideCells $sliders } } proc CompactCells {} { global B S array set ::BB [array get B] set ROW $S(rowsX) set COL [expr {int($S(cols) / 2)}] while {1} { ;# Stop when nothing slides set sliders {} # Check the slide to the right columns set cols {} for {set col 0} {$col < $COL} {incr col} { if {$B($ROW,$col) <= 0} { foreach c $cols { for {set row $ROW} {$row >= 0} {incr row -1} { if {$B($row,$c) <= 0} break lappend sliders $row $c x } } set cols {} } else { lappend cols $col } } # Check the slide to the left columns set cols {} for {set col [expr {$S(cols) - 1}]} {$col >= $COL} {incr col -1} { if {$B($ROW,$col) <= 0} { foreach c $cols { for {set row $ROW} {$row >= 0} {incr row -1} { if {$B($row,$c) <= 0} break lappend sliders $row $c xx } } set cols {} } else { lappend cols $col } } if {$sliders == {}} break SlideCells $sliders } } ##+########################################################################## # # SlideCells -- move a set of cells one unit in a specified direction. # # Tricky part is NOT losing the correct binding for cell X,Y. Thus we # first blank the real image and replace it with a temporary one which # we slide. DrawBoard will put the correct image back in place. # proc SlideCells {cells} { foreach {r c dir} $cells { .c itemconfig c$r,$c -image {} set M($r,$c) $::B($r,$c) set ::B($r,$c) 0 .c create image [GetXY $r $c] -image ::img::img($M($r,$c)) \ -tag slider$dir } .c raise banner set dx [expr {double($::S(cell)) / $::S(numSteps)}] set dy [expr {double($::S(cell)) / $::S(numSteps)}] for {set step 0} {$step < $::S(numSteps)} {incr step} { .c move slidery 0 $dy .c move slideryy 0 -$dy .c move sliderx $dx 0 .c move sliderxx -$dx 0 update after $::S(delay) } foreach {r c dir} $cells { ;# Update board data if {$dir == "y"} { set ::B([expr {$r+1}],$c) $M($r,$c) } elseif {$dir == "yy"} { set ::B([expr {$r-1}],$c) $M($r,$c) } elseif {$dir == "x"} { set ::B($r,[expr {$c+1}]) $M($r,$c) } elseif {$dir == "xx"} { set ::B($r,[expr {$c-1}]) $M($r,$c) } } DrawBoard .c delete slidery slideryy sliderx sliderxx } proc NewRow {} { global S B StartStop 0 if {$S(busy)} { ;# Busy handling mouse click set S(needRow) 1 ;# ...so set flag and leave return } set S(busy) 1 incr S(lines) -1 if {$S(lines) == 0} { ;# Is the level over yet??? return [LevelOver] } # Check for game over for {set col 0} {$col < $S(cols)} {incr col} { if {$B(0,$col) > 0} { return [GameOver] } } UpRow StartStop 1 set S(needRow) 0 set S(busy) 0 } ##+########################################################################## # # UpRow -- Scrolls the screen up one row and adds in another row # proc UpRow {} { global B S BB for {set col 0} {$col < $S(cols)} {incr col} { if {$BB($col) == 0} {set BB($col) [expr {1 + int(rand() * $S(tiles))}]} } set sliders {} for {set row 1} {$row < $S(rows)} {incr row} { for {set col 0} {$col < $S(cols)} {incr col} { if {$B($row,$col) == -1} continue lappend sliders $row $col yy } } for {set col 0} {$col < $S(cols)} {incr col} { set n $BB($col) if {$n == 0} {set n [expr {1 + int(rand() * $S(tiles))}]} set B($S(rows),$col) $n set BB($col) 0 lappend sliders $S(rows) $col yy } SlideCells $sliders for {set col 0} {$col < $S(cols)} {incr col} { set B($S(rows),$col) -1 } } proc IsEmpty {} { for {set row $::S(rowsX)} {$row >= 0} {incr row -1} { for {set col 0} {$col < $::S(cols)} {incr col} { if {$::B($row,$col) > 0} {return 0} } } return 1 } proc About {} { set msg "$::S(title) v$::S(version)\nby Keith Vetter, October 2003\n" append msg "Based on a program by GameHouse\n\n" append msg "The object of the game is to collapse the rising blocks\n" append msg "to get as many points as possible.\n\n" append msg "Score points by clicking on a colored block that has\n" append msg "three or more neighbors of the same color. Blocks above\n" append msg "the resulting explosion will collapse on the blocks\n" append msg "below. The more blocks exploded the higher your score.\n\n" append msg "As you play, new lines of blocks will appear. When \n" append msg "\"Lines Left\" reaches zero, the level is over and the\n" append msg "next level will start.\n" tk_messageBox -message $msg } proc GameOver {{txt "Game Over"}} { set ::S(state) 2 StartStop 0 .c create rect 0 0 [winfo width .c] [winfo height .c] \ -fill white -stipple gray25 -tag gameOver .c create text [GetXY 4 5] -text $txt -font {Helvetica 28 bold} \ -fill white -tag gameOver } proc StartStop {onoff} { foreach aid [after info] {after cancel $aid} .cc itemconfig cell -image {} if {! $onoff} return set ::S(tcnt) $::S(ticks) after $::S(newRowX) ticker } proc ticker {} { global S BB incr S(tcnt) -1 set col [expr {$S(ticks) - 1 - $S(tcnt)}] set BB($col) [expr {1 + int(rand() * $S(tiles))}] DrawBoard2 if {$S(tcnt) <= 0} { NewRow } else { after $S(newRowX) ticker } } proc LevelOver {} { global S B set S(state) 3 ;# Level over state StartStop 0 Banner "LEVEL COMPLETE" update after 3000 LevelOverAnimation incr S(level) StartLevel set S(state) 1 StartStop 1 } proc LevelOverAnimation {} { global S B Banner "" for {set row 0} {$row < $S(rows)} {incr row} { set bonus [expr {100 + $row*10}] incr S(score) $bonus Banner "$bonus POINT BONUS" for {set col 0} {$col < $S(cols)} {incr col} { if {$B($row,$col) > 0} break set B($row,$col) 4 DrawBoard update after [expr {$S(delay)}] } if {$B($row,$col) > 0} break } after 2000 } ##+########################################################################## # # WaitClick -- waits for a click to begin # proc WaitClick {} { set w [winfo width .c] set h [winfo height .c] .c create rect -10 -10 $w $h -tag scrim -fill black .c lower scrim .c raise banner .c bind banner {DoClick -1 -1} .c bind scrim {DoClick -1 -1} } proc Banner {msg} { global S .c delete banner scrim if {$msg == ""} return set x [expr {[winfo width .c] / 2}] .c create rect [expr {$x - 100}] 100 [expr {$x + 100}] 200 \ -tag banner -width 5 -fill black -outline gold .c create text $x 175 -tag banner -font {Helvetica 12 bold} \ -text $msg -anchor c -fill white for {set i 0} {$i < 6} {incr i} { set xx [expr {$x - (2.5-$i)*$S(cell)}] set yy [expr {120 + rand()*$S(cell)}] set who [expr {1 + int(rand() * $S(tiles))}] .c create image $xx $yy -image ::img::img($who) -tag banner } } proc Pause {byBinding} { global S if {$byBinding} { ;# Button toggles for us set S(pause) [expr {! $S(pause)}] } if {$S(pause) == 1} { ;# Pause on if {$S(state) != 1} return ;# Not in play mode foreach aid [after info] {after cancel $aid} .c create rect 0 0 [winfo width .c] [winfo height .c] \ -fill black -tag pause .c create text [GetXY 4 5] -font {Helvetica 28 bold} \ -fill white -tag pause -text "PAUSED" -justify center .c create text [GetXY 6 5] -font {Helvetica 12 bold} \ -fill white -tag pause -text "Press p to continue" -justify center } else { ;# Pause off .c delete pause after $::S(newRowX) ticker } } proc DoSounds {} { proc snd_ok {play} {} ;# Stub if {[catch {package require base64}]} return if {[catch {package require snack}]} return set s(ok) {UklGRkACAABXQVZFZm10IBAAAAABAAEAESsAABErAAABAAgAZGF0YRwCAACAgId0Z HZbU5aMj7/MsIZ6UX6nWIiITWiIRUGUlZesvrGCiKiKTl96Fit3YF5emrGHqcqhlJuAdWxgW 01EbWSHubW1uJ2MkqGPYFVSamtvgHmEh5ybraWLkHp5Xm5oWGRvb3WSlYqMi4+JhY6Ac25xd Xp5jYR/hoODdIN8e356goCHgoqGgIV/g35/d3N2eHZ6gIOIgouHioaNioGAfHpycHp2dH2Hi ouNiYiKhIF9enZzd3l+dX2BgYKIjoaJhIJ/fX6AfHl8fICAgICEgISFhYF/gH+AfIJ/gH6Af X6AfICAfYB+gn2DfoGAgIOAgYB8e3x9gIKChYCDgIN/g32Afn+BgIF+gH+BgIOAgX2CfYGAg IB/gH9/fIB/gICBgH+Df4KAgIB9gHuBfYKAgoCAhICDgIN+gH+Af4CAgIGAg4CFgIOAgICAg H9/f32AfoF/gn+BgICAf4B/gICAgICAgIKAgYCAgH+AfYB8f4CAgoGBgIKBgHt0cnqEi4yIh oKHioOBeoF+gHRvbW10eYSHhoyMmI+PhIF5dm9tbW92fICJjpKRkY6JhHx5b2xlbnWAhYeOj pSQkIiAe3R1cnNzdnx/gomLj4yJhICAfHp3d3d6fYKDhoKGgIeAhX1/eXt9foCAg4GCg4CDf YF6gHmAfYCBgIR/h4CEf4B9fn98gHuEfYV/g4CAgn6Fe4R6gn1/gHuDe4V+g4CAgn8=} regsub -all {\s} $s(ok) {} sdata ;# Bug in base64 package sound snd_ok snd_ok data [::base64::decode $sdata] } image create photo ::img::img(-1) image create photo ::img::img(0) image create photo ::img::img(1) -data { R0lGODdhGwAcANUAABwaKSopKi4nGAocdQYdswUhzw0jjRcgTDBr+HCX+iGX+2aG+156+hx58E5s +CZQ+BQ68gQo7K3p+5bV+5rF+nCr/JKs+D2p/BMy2RkYFyRBsCVC2T1b8hdT0j5Y0Yme90JVr1Rs 0qG5+BRPlh80bjI2TBc9kP////////////////////////////////////////////////////// /////////////////////////////////////////////ywAAAAAGwAcAAAG/0AAICAEBIQCgEAA EAACAkBAABAAAgJAIDAAEoRDYrFAKBAKhgNAACggEooFo+FAIB6PxwMIEQ6HkQPAgJBIJpSK5ZJY MBAIxOPxgDyIEIKAkJA0IMCIUIiJFIbDIQQCKQAIFUqkUCgQCIQCAVgQDoER4RBSEBAulUiBUCgQ gAXhsBApRAqRSAQCKQAIiUqEUCAQiUNgRDiEFDIERSJSKBQwwIJQiClEMBFMJBKBRCCYDGGRwAwL mAIGg4lgIphIJAKJQCCQAoCgSECEQIxQGMFAMECIcCh8PAoCzWIBxAiHGMgGCBEOiZDHAxMgLBQQ DAazEW6GD+ED8ng8HhwOJv+jWSwgGMxms9k8II8HBPgQDjkcB2Ij0CwYj81ms3lshkIgRzgUOhib jGbBeGw2m8fm8Xg8iA6Ow+FwMBYbgYaxeGw2nI3wQQQ6hEMHY7HoZDQMB4ez8Xg4HA6HyHAAGUJh IuEBaBwOjofj4XA4Do7DMRwOEx8PQONwcDwejofDcTgcjiFjwVgwFh+LJwPiODgejocTAjqEDAZj wVgwFozF4mPxCDRCB8cT4giFQIZQuGAsFoyFpRICgBwOB4fj4DgcjiFjwVgsFowFwyIKZTRAh3A4 ZDAYwIVwOEyIRB7AyMFwOBgMhjCRSHw+H4vFYhGJKBQLKHPwOIAMoXCxWCQzEonEp/KpVCwV0cdB ygBKJqBHOCQWQ8QRKSPIZASATCYDyAAEGYAgA8gAMoAMQAAQZABBADs=} image create photo ::img::img(2) -data { R0lGODdhGwAcANUAABkYFyopKhwaKS4nGFYnEasSB8oLBWkoKvE0I/hmWPhXTPVTO/VFOuw5MOgj EtkZD6gZH+QpH/CnldnHtveXjfGYcfeFdfh4b/dsZmwHBVsXE+x3Wa0mD+AqLk8ZKaU2HvVMRJ8t LqA4M6JKR/x+hPaKh+mdnf////////////////////////////////////////////////////// /////////////////////////////////////////////ywAAAAAGwAcAAAG/0BAABAACAYCgGAg GAgCgkBAEBAEBIGBYDAIEAqGgqFgKBiABeGwYCgYDAbDYSAQFBCJREKhWDAYDQQCAXQIh47H4wEJ HCKSiYRSsVwwCcWC0UAgIhGi4/EAZBiTCyIScUSIjsfD8Xg4Ho/Hw/EAZBaSBtAgFBYMBUPhYXgY HoaH4fF4PACZBSUiLAgLhoKwIHwYgA/h8KHJNCoPg8FQKBQehUfhASESHQ9ApmFxGAwFYWEIIQ4d D4fDockgNg9DQQiJPCCPiNDheAAjDocjEokAMoiEw2B4QCIPTuQRiTgckYgjEnF0EBFNBpFwGCAP DjAiHAo7RCGCgfBkEAqHgf/z6HwiHUQH0UEgEB0EooNogBqDDELheDiEnUYH2BAOEQ1EA9FgJBqa TEMRcYQiIsRwKGQwGIwGA4RhADIIRSQS6TRGDUYDyBAOiQwFhuHJMECIiKjRIIIYQJBwyAAxFBfQ INNYNDoNEYMxHAoVQwZIQQJpNA1GoyNqMEbDIUgxBDEYCpLCkwE2hMIRAwQCKUAgkAKkAIFAIIai pBhoOsMRYwQECYcKkGLIYDASJYVHg2gwGg3GcDgcghiMhoKi0GgQjU6jwWCAgAzhkNhoNBAKkwKQ 6SAQwIZQyGgAGcJhg9FoNBgXCsijiSAiiEYDBAIpFIpEIgHECIcXSqkxGDxCEB1Eo8EAgRSJRCIh vFwuFlLJoogAAJ4CxwGMCIfDRqSD6CAiCEQEEgAAAAMBQAAACAAAwUAAGAAEA8AAIAAMAIAgADs=} image create photo ::img::img(3) -data { R0lGODdhGwAcANUAACopKi4nGBwaKTZ4LhyoBSG4BSCcBzNqLyaIFVP8E337T4z8Olz3NT71FDXo DT9FMC3YCZb8aOX7kbz9birICSF0EFLrFsj8VyRDFUXYGRxtDh04DljoNkjHLFHYMGroSlfKMWrZ UWXKTDQyNEaYMk6LRxkYF0CHNUa4Lf////////////////////////////////////////////// /////////////////////////////////////////////ywAAAAAGwAcAAAG/0AAICAICAKCAEAA CAgCgoAgIAgIAoKAACAADAiFQqFAIBQIBgKBUCAQCoVCgXAABACIhEKxWCyADGBCKGw0HA2gQzh0 IAQPSEQyiUQUigUjkUgkGg0ikQKoWCQLBwQCpAiHRCEEAoE4HJBAxTJxFAgGgsFgMAAJQmGhUKBQ IBAIJFCxRBxCg2E4JBQKhQKFQoFAHJBAxXGBDIcFArAgHBYoFAoE4oBgKg5FhkAgEoEU4ZACgTgc EIzGsoAUCIWCsEAcAiFCocPhwFQaCkehUChQKBAKhDIcQhwORwOCqVgWEEqhAKQIhUCIcAhxOByO RsOBqVgWGUqBQqFQMkNHBv/oEA4bjYYDU7EwLECKUJiBZCAZh8PRcAAbQmHCsqlwGBkKpUPJZDIZ jsPBcTQ4wwaD4cBUOAwPpUPpUDIeR8bBcTCEjAajkWBYMBUOI9MBUjoUTybDsXAsDU6D0WA0GAwG B1PxcDwdSqfTyXgyHAuDw+AAGcKhwoOpeDieTqfT8Xg8HA6HMxwOFRzMwcPxADtCocfD4XA4QIZw KFQoPpgKKOQBdToijyfE4Qw/Q4VQofhgDh6OBwQCgTweDofzYXyECqIi8sFUPB+gRzj0cDgMDoPB +DAYCgZDEflgBh4OhyPkcDgfDuPDUDAYCgaDwYhEPpgDCMgRCj8fBQOoEA5GIwpgRDj0jAQkDufD +HwYH8UHqBAOiREFpxQwAU5AlHAI7AiHoA5KiBKiTgCBKWASmEwBk8AkMJkEJoEpYBIEBCaBKWAK AgA7} image create photo ::img::img(4) -data { R0lGODdhGwAcAMQAACspKzQyNExISbi4t8q7x6qpq6qnlOnp6fv8+tnY1mVnZtTZ8srJyXmId/Lp 1Ih6iLPEzHZ3dbbItLa6zDhRUYp8dHN6jZuZlB8bKCsoFf///////////////////////ywAAAAA GwAcAAAF/yAgjkAgBkBAjgEZiIIwEMNQDEMxFEVRgIM4DkURAIFxgIg4goc4IuOBHAiSJIGygIg4 kiJ4iOOBHAjCBM2BIEeSJEzCMAyTMEmSLKCzHAeSAM+BHNAwFEMxFMMwDBDDMElygAfiANGBJMRQ DMVQDMMwSATBMEmyHMcCBtGBJMNQDMMgDQMxEBDDMEySHEgiRAeIJOAgisRAMBDIiGKSJMlxJEJ0 IAkxTBIBMdAoJkySJOBxIIkQHUgiDRIBMqKYMGAiistxHEgiRAeSQATBMAw0juAhjgeSUJWYMAzE MGAiigt4iKOIIIcQHcjBMEzCJEmSkCJyIAiCJKAQHUeSMMkMkyTJcRwHciAHiIjjIUQHsiQMAyVJ Ah7iCCLiKB5CdBwOwzBJkhzHcZDkeAjRcSwJmDBMkhzHgRwgIo7kQUXHkTAMkyTLcSAHSY6HEB1H koBMwiTJcRwHiIgjiRxClBxJwjBJchxHWY6HUB3HkjBgIh7HcYCIOJLiQVnJcSRJkhzHUZbkIUTg IY4kiIgjSR5ClCDgIYogIo5kKSZCYBymaY7HBQCCUICDOIoEMzCQREASARVNAAAABmQAkAFABgJA JmZiJmaiGAIAOw==} DoDisplay DoSounds NewGame ---- [http://tclerswiki.googlepages.com/TCL_wiki_Collapse_Game.PNG ] ---- [Category Games] | [Tcl/Tk Games] | [Category Application]