# PUZZLE.GUI -- A simple number re-ordering puzzle, kinda like the one my # Dad would make me play on long car trips to shut me up.... # # History: 4/23/94 - written # 4/25/94 - Added timer and move counter labels reset-server appInitialize puzzle Puzzle { Puzzle*objects:\ toplevel Paned puzzle\ puzzle Form tForm\ tForm Label timerLabel\ tForm Toggle pauseButton\ tForm Label movesLabel\ \ puzzle Form pForm\ pForm Command pos11\ pForm Command pos12\ pForm Command pos13\ pForm Command pos14\ pForm Command pos15\ pForm Command pos21\ pForm Command pos22\ pForm Command pos23\ pForm Command pos24\ pForm Command pos25\ pForm Command pos31\ pForm Command pos32\ pForm Command pos33\ pForm Command pos34\ pForm Command pos35\ pForm Command pos41\ pForm Command pos42\ pForm Command pos43\ pForm Command pos44\ pForm Command pos45\ pForm Command pos51\ pForm Command pos52\ pForm Command pos53\ pForm Command pos54\ pForm Command pos55\ pForm Label lab11\ pForm Label lab12\ pForm Label lab13\ pForm Label lab14\ pForm Label lab15\ pForm Label lab21\ pForm Label lab22\ pForm Label lab23\ pForm Label lab24\ pForm Label lab25\ pForm Label lab31\ pForm Label lab32\ pForm Label lab33\ pForm Label lab34\ pForm Label lab35\ pForm Label lab41\ pForm Label lab42\ pForm Label lab43\ pForm Label lab44\ pForm Label lab45\ pForm Label lab51\ pForm Label lab52\ pForm Label lab53\ pForm Label lab54\ pForm Label lab55\ \ puzzle Form pCmd\ pCmd Command newButton\ pCmd Command quitButton *puzzle.title: IRAF GUI Puzzle Demo *tForm*background: bisque3 *tForm*showGrip: false *tForm*resizeable: false *tForm*Label.background: black *tForm*Label.foreground: red *tForm*Label.shadowWidth: 0 *tForm*Label.borderWidth: 0 *tForm*Command.background: grey80 *tForm*Toggle.background: grey80 *pForm*background: bisque3 *pForm*showGrip: false *pForm*resizeable: false *pForm*Command.background: grey80 *pCmd*background: bisque3 *pCmd*Command.background: grey80 *pCmd*resizeable: false *timerLabel.label: 0000 *timerLabel.height: 30 *timerLabel*font: *times-bold-r*24* *pauseButton.label: Pause *pauseButton.height: 30 *pauseButton.fromHoriz: timerLabel *pauseButton.horizDistance: 10 *pauseButton*font: *times-bold-r*18* *movesLabel.label: 0000 *movesLabel.height: 30 *movesLabel*font: *times-bold-r*24* *movesLabel.fromHoriz: pauseButton *movesLabel.horizDistance: 10 *pForm*width: 50 *pForm*height: 50 *pForm*horizDistance: 0 *pForm*vertDistance: 0 *pForm*Label.background: bisque3 *pForm*Label.shadowWidth: 0 *pForm*Label.borderWidth: 0 *pForm*font: *times-bold-r*24* *lab12.fromHoriz: lab11 *lab13.fromHoriz: lab12 *lab14.fromHoriz: lab13 *lab15.fromHoriz: lab14 *lab11.vertDistance: 2 *lab12.vertDistance: 2 *lab13.vertDistance: 2 *lab14.vertDistance: 2 *lab15.vertDistance: 2 *lab21.fromVert: lab11 *lab21.horizDistance: 1 *lab22.fromVert: lab12 *lab22.fromHoriz: lab21 *lab23.fromVert: lab13 *lab23.fromHoriz: lab22 *lab24.fromVert: lab14 *lab24.fromHoriz: lab23 *lab25.fromVert: lab15 *lab25.fromHoriz: lab24 *lab31.fromVert: lab21 *lab31.horizDistance: 1 *lab32.fromHoriz: lab31 *lab32.fromVert: lab22 *lab33.fromVert: lab23 *lab33.fromHoriz: lab32 *lab34.fromVert: lab24 *lab34.fromHoriz: lab33 *lab35.fromVert: lab25 *lab35.fromHoriz: lab34 *lab41.fromVert: lab31 *lab41.horizDistance: 1 *lab42.fromHoriz: lab41 *lab42.fromVert: lab32 *lab43.fromVert: lab33 *lab43.fromHoriz: lab42 *lab44.fromVert: lab34 *lab44.fromHoriz: lab43 *lab45.fromVert: lab35 *lab45.fromHoriz: lab44 *lab51.fromVert: lab41 *lab51.horizDistance: 1 *lab52.fromHoriz: lab51 *lab52.fromVert: lab42 *lab53.fromVert: lab43 *lab53.fromHoriz: lab52 *lab54.fromVert: lab44 *lab54.fromHoriz: lab53 *lab55.fromVert: lab45 *lab55.fromHoriz: lab54 *pos12.fromHoriz: pos11 *pos13.fromHoriz: pos12 *pos14.fromHoriz: pos13 *pos15.fromHoriz: pos14 *pos11.vertDistance: 2 *pos12.vertDistance: 2 *pos13.vertDistance: 2 *pos14.vertDistance: 2 *pos15.vertDistance: 2 *pos21.fromVert: pos11 *pos21.horizDistance: 1 *pos22.fromVert: pos12 *pos22.fromHoriz: pos21 *pos23.fromVert: pos13 *pos23.fromHoriz: pos22 *pos24.fromVert: pos14 *pos24.fromHoriz: pos23 *pos25.fromVert: pos15 *pos25.fromHoriz: pos24 *pos31.fromVert: pos21 *pos31.horizDistance: 1 *pos32.fromHoriz: pos31 *pos32.fromVert: pos22 *pos33.fromVert: pos23 *pos33.fromHoriz: pos32 *pos34.fromVert: pos24 *pos34.fromHoriz: pos33 *pos35.fromVert: pos25 *pos35.fromHoriz: pos34 *pos41.fromVert: pos31 *pos41.horizDistance: 1 *pos42.fromHoriz: pos41 *pos42.fromVert: pos32 *pos43.fromVert: pos33 *pos43.fromHoriz: pos42 *pos44.fromVert: pos34 *pos44.fromHoriz: pos43 *pos45.fromVert: pos35 *pos45.fromHoriz: pos44 *pos51.fromVert: pos41 *pos51.horizDistance: 1 *pos52.fromHoriz: pos51 *pos52.fromVert: pos42 *pos53.fromVert: pos43 *pos53.fromHoriz: pos52 *pos54.fromVert: pos44 *pos54.fromHoriz: pos53 *pos55.fromVert: pos45 *pos55.fromHoriz: pos54 *pCmd*Command.height: 30 *pCmd*Command.width: 50 *pCmd*Command.vertDistance: 12 *pCmd*Command*font: *times-bold-r*18* *newButton.label: New Game *quitButton.fromHoriz: newButton *quitButton.vertDistance: 5 *quitButton.label: Quit } # Crank 'er up... createObjects createBitmap irafLogo 32 36 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xd8, 0x06, 0x00, 0x00, 0x98, 0xf5, 0x03, 0x00, 0xdb, 0xed, 0x01, 0xc0, 0xdb, 0x6e, 0x00, 0xf8, 0xdb, 0xde, 0x00, 0xf8, 0xfb, 0xde, 0x00, 0xe0, 0x7b, 0xbe, 0x00, 0x80, 0x39, 0x6e, 0x00, 0x00, 0x3c, 0x6e, 0x00, 0x00, 0xfc, 0xde, 0x00, 0x00, 0xfc, 0xde, 0x00, 0x00, 0xdc, 0xdc, 0x01, 0x00, 0x1e, 0xf8, 0x01, 0x00, 0x1e, 0xf0, 0x03, 0x00, 0x1e, 0xc0, 0x03, 0x00, 0x1e, 0xc0, 0x07, 0x00, 0x0e, 0x80, 0x07, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} activate # Should be a better way to randomize the start. set space [ expr ( [pid] % 23 ) ] set random "17 8 13 19 22 21 12 18 15 9 23 5 3 20 6 4 1 7 24 10 14 16 2 11" set timerId 0 set time 0 # Quit the game. proc Quit args { global timerId if {[send pauseButton get state] == 0} { deleteTimedCallback $timerId } send client gkey q deactivate unmap } ; send quitButton addCallback Quit # Initialize the game board. proc Init args { global space random time timerId set timerId 0 set time 0 set k $space set ispace [ expr ($space / 5 + 1) ] set jspace [ expr ($space % 5 + 1) ] for { set i 1 } { $i<=5 } { incr i } { for { set j 1 } { $j<=5 } { incr j } { set val [lindex $random $k] if {[expr [expr $i == $ispace] && [expr $j == $jspace]]} { send pForm unmanage pos$i$j } else { send pos$i$j "set label $val" set k [ expr ($k == 23) ? 0 : [expr $k+1] ] } } } } ; send server postActivateCallback Init Init # Define the game buttons and positions. set buttons { pos11 pos12 pos13 pos14 pos15 pos21 pos22 pos23 pos24 pos25 pos31 pos32 pos33 pos34 pos35 pos41 pos42 pos43 pos44 pos45 pos51 pos52 pos53 pos54 pos55 } set indx 0 for { set i 1 } { $i<=5 } { incr i } { for { set j 1 } { $j<=5 } { incr j } { set bpos(pos$i$j) "$i $j $indx" incr indx send lab$i$j "set bitmap irafLogo" } } # Take action when hitting a button. proc Move { widget args } { global space buttons bpos # If we've paused the game then don't move anything. if {[send pauseButton get state] == 1} { return } # Get the position of the empty space. set ispace [ expr ($space / 5 + 1) ] set jspace [ expr ($space % 5 + 1) ] # Get the position of the current widget. set i [ lindex $bpos($widget) 0] set j [ lindex $bpos($widget) 1] # Now see if the current widget is next to the empty space, but not on # a corner. set xdiff [expr abs ([expr $ispace-$i])] set ydiff [expr abs ([expr $jspace-$j])] if { ! [expr [expr $xdiff == 1] && [expr $ydiff == 1]]} { if {[expr [expr $xdiff < 2] && [expr $ydiff < 2]]} { # Manage the empty space. manage_space $space # Set space label to current label. set lab [send $widget get label] send [lindex $buttons $space] "set label $lab" # Unmanage current space. unmanage_space [lindex $bpos($widget) 2] set space [lindex $bpos($widget) 2] # Update the number of times we've made a move. update_nmoves } } } ; foreach item $buttons { send $item addCallback Move } # Start a new game. proc new_game args { global space time nmoves timerId # If we've paused the game then don't do anything. if {[send pauseButton get state] == 1} { return } manage_space $space new_space Init set nmoves -1 ; update_nmoves set time 0 deleteTimedCallback $timerId send timerLabel set label 0000 set timerId [postTimedCallback timer 1000] } ; send newButton addCallback new_game # Get a new empty space. proc new_space args { global space random set space [lindex $random [ expr ($space >= 23) ? 0 : $space ] ] if {$space == 24} { set space 5 } } # Show a puzzle piece. proc manage_space { space args } { set ispace [ expr ($space / 5 + 1) ] set jspace [ expr ($space % 5 + 1) ] send pForm manage pos$ispace$jspace } # Remove a puzzle piece. proc unmanage_space { space args } { set ispace [ expr ($space / 5 + 1) ] set jspace [ expr ($space % 5 + 1) ] send pForm unmanage pos$ispace$jspace } # Install a timer so we can keep score of our best times. proc timer args { global timerId time send timerLabel set label [ format "%04d" $time ] incr time set timerId [postTimedCallback timer 1000] }; set timerId [postTimedCallback timer 1000] # Count the number of times we move a piece. set nmoves 0 proc update_nmoves args { global nmoves incr nmoves send movesLabel set label [ format "%04d" $nmoves ] } # Define a 'pause' command in case the boss walks in... proc pause_toggle args { global timerId if {[send pauseButton get state] == 0} { set timerId [postTimedCallback timer 1000] } else { deleteTimedCallback $timerId } } ; send pauseButton addCallback pause_toggle