When Richard posted a little Pachisi game here, it reminded me that I had this dusty piece of code sitting on the shelf.
Because it predates Tcl 8.0, it doesn't use bindtags or namespaces. I've updated it to use Tcl's random number generator, but found it necessary to add post-sampling using a different congruence in order to avoid patterns in the numbers.
KBK 6 October 2000
I've made quite a few constructive changes to this program , but haven't updated the widget below.
You'll find the new game (tkyahtzee) at http://tkgames.sf.net
stevenaaus, jan, 2006.
Wow, what are the odds? I pasted this into a console, played the game, and immediately got a yatzee. Well, ok, it actually took two rolls rather than one. Maybe I should buy a lottery ticket today :-)
(time passes)
Hmmm. Must be a bug. I've gotten three yahtzee's with 4's and one with 2's in the same game. Sure wish that happened when I played for real...
Still, it's a nice little game. Amazing how much you can do with just a few lines of tcl.
-- Bryan Oakley 6 October 2000
There was a problem with seeding the pseudo-random number generator. I hope it's fixed now.
KBK 6 October 2000
Jeff Smith 2021-02-24 : Below is an online demo using CloudTk. This demo runs "A little Yahtzee game" in an Alpine Linux Docker Container. It is a 27.4MB image which is made up of Alpine Linux + tclkit + A-little-Yahtzee-game.kit + libx11 + libxft + fontconfig + ttf-linux-libertine. It is run under a user account in the Container. The Container is restrictive with permissions for "Other" removed for "execute" and "read" for certain directories.
#!/bin/sh # the next line restarts using tclsh \ exec wish "$0" "$@" ### Yahtzee, downloaded from www.tcl.tk, ### package require Tk set data(version) 1.2.4 set data(name) TkYahtzee set data(date) 26/10/2008 set data(web) http://tkgames.sf.net set rcfile "~/.tkyahtzeerc" # Table defining the score card. # The table is a list of lists. The elements of the sublists are: # 0 - Title of the row. If missing, the row is blank. # 1 - Name of a global variable holding the score for this row. # 2 - Value of the row. # 3 - Procedure that scores the row. If missing, the player cannot # mouse on the row to enter a score. set scorecard { {{1's} count1 {Sum of 1's} {count 1}} {{2's} count2 {Sum of 2's} {count 2}} {{3's} count3 {Sum of 3's} {count 3}} {{4's} count4 {Sum of 4's} {count 4}} {{5's} count5 {Sum of 5's} {count 5}} {{6's} count6 {Sum of 6's} {count 6}} {} {{Subtotal} subtotal {Add 1's ... 6's}} {{Bonus if >= 63} bonus {35 points}} {} {{3 of a kind} kind3 {Sum of dice} {kind 3}} {{4 of a kind} kind4 {Sum of dice} {kind 4}} {{Full house} fullhouse {25 points} fullhouse} {{Sm. straight} smstraight {30 points} smstraight} {{Lg. straight} lgstraight {40 points} lgstraight} {{Yahtzee} yahtzee {50 points} yahtzee} {{Chance} chance {Sum of dice} chance} {} {{Extra Yahtzees} extra {100 points each}} {} {{Grand total} total {Add lines 7-16}} } # Initialize random number generator proc random_init { seed } { global rand expr { srand($seed) } for {set i 0} {$i < 100} {incr i} { set rand($i) [expr { rand() }] } set rand(x) [expr { int( 233280. * rand()) }] return } # Pull a random integer in a given range. Use sampling driven by # a second PRNG to try to increase the number of planes on which # N consecutive random numbers fall. proc randint { range } { global rand if ![info exists rand] { random_init 0 } set rand(x) [expr { ( 9301 * $rand(x) + 49297 ) % 233280}] set ind [expr { $rand(x) * 100 / 233280 }] set newrand $rand($ind) set rand($ind) [expr { rand() }] return [expr { int( $range * $newrand ) }] } ### Each die has it's own canvas # Make a die. $w is the canvas, $n is the die number proc die {w n} { global dieActive dieBackGround global dieSelected canvas $w -width 50 -height 50 -relief flat -borderwidth 2 -background $dieBackGround bind $w <Enter> "dieEnter $w $n" bind $w <Leave> "dieLeave $w $n" bind $w <Button-1> "diePressInit $w $n" bind $w <ButtonRelease-1> "diePress $w $n" set dieActive($n) 1 set dieSelected($n) 0 return $w } # Dice change colors as they roll. This is the table of colors they take on. # (colors were prev: \#ff5f5f , \#bfbfbf (skyblue,skyblue3)) # lavenderblush3 mistyrose3 \#bfbfbf set dieBackGround lavenderblush3 set dieColor(0) skyblue set dieColor(1) skyblue3 set dieColor(2) skyblue set dieColor(3) skyblue3 set dieColor(4) skyblue set dieColor(5) $dieBackGround # Roll die whose canvas is $w, whose die number is $n, and which # has bounced $times times proc dieRoll {w n {times 0}} { global dieSelected dieColor dieValue if { !$dieSelected($n) } return if {$times == 0} { catch {unset dieValue($n)} } $w configure -background $dieColor($times) $w delete all set v [expr { [randint 6] + 1 }] if {$v % 2} { $w create oval 20 20 30 30 -fill black } if {$v >= 2} { $w create oval 5 5 15 15 -fill black $w create oval 35 35 45 45 -fill black } if {$v >= 4} { $w create oval 5 35 15 45 -fill black $w create oval 35 5 45 15 -fill black } if {$v >= 6} { $w create oval 5 20 15 30 -fill black $w create oval 35 20 45 30 -fill black } incr times if {$times > 5} { set dieValue($n) $v } else { after [expr { 50 * $times + [randint 150] }] dieRoll $w $n $times } } # Mouse into a die proc dieEnter {w n} { global dieCurrent set dieCurrent $w } # Mouse out of a die proc dieLeave {w n} { global dieCurrent set dieCurrent {} } # Button down in a die proc diePressInit {w n} { # S.A. $w configure -relief sunken } proc diePress {w n} { global dieCurrent dieSelected dieActive dieNumPressed roll dieBackGround # S.A. $w configure -relief raised if {!$dieActive($n) || $roll == 3} return if { [string match $w $dieCurrent] } { set dieSelected($n) [expr { !$dieSelected($n) }] if {$dieSelected($n)} { incr dieNumPressed .action configure -state normal $w configure -background tan ;# lightgreen } else { incr dieNumPressed -1 if {$dieNumPressed == 0} {.action configure -state disabled} $w configure -background $dieBackGround } } } # Is a die active? -- that is, is it listening to mouse clicks? proc dieActive {n v} { global dieActive set dieActive($n) $v } # Is a die selected for reroll? proc dieSelected {n v} { global dieSelected set dieSelected($n) $v } # Wait for a die to settle down proc dieWait {n} { global dieValue if { ![info exists dieValue($n)] } { vwait dieValue($n) } } # Make an initial die roll proc initroll {} { global scoreActive dieNumPressed roll dieBackGround set scoreActive 0 set dieNumPressed 0 for {set n 1} {$n <= 5} {incr n} { dieActive $n 0 dieSelected $n 1 .dice.d$n delete all .dice.d$n configure -background $dieBackGround } .action configure -text "R o l l 1" -command {set roll 1 ; doroll} -state normal -padx 60 } # Make a die roll. $roll is 1, 2, or 3 proc doroll {} { global scoreActive dieSelected dieNumPressed roll set scoreActive 0 .action configure -state disabled for {set n 1} {$n <= 5} {incr n} { dieRoll .dice.d$n $n 0 } for {set n 1} {$n <= 5} {incr n} { dieWait $n } if {$roll < 3} { for {set n 1} {$n <= 5} {incr n} { dieActive $n 1 dieSelected $n 0 } set dieNumPressed 0 .action configure -text "R o l l [expr $roll + 1]" -command "incr roll ; doroll" } else { .action configure -text "S c o r e" -state disabled } set scoreActive 1 } # Display the score card proc scorecard w { global scorecard tcl_patchLevel frame $w -relief flat -borderwidth 2 ;# raised, no pad - S.A. if {[string match 8.5* $tcl_patchLevel]} { grid columnconfigure $w 0 -weight 1 -pad 18 grid columnconfigure $w 1 -weight 1 -pad 22 grid columnconfigure $w 2 -weight 1 -pad 10 # grid rowconfigure $w all -minsize 2 ... makes no diff S.A. } else { grid columnconfigure $w 1 -weight 1 grid columnconfigure $w 2 -weight 1 } set i 0 set RELIEF groove ;# S.A. set FONT {8x13} foreach line $scorecard { if {[llength $line] == 0} { frame $w.sep$i -relief flat -height 1 -background yellow grid $w.sep$i - - - -sticky ew } else { incr i set title [lindex $line 0] set vname [lindex $line 1] set desc [lindex $line 2] set pname [lindex $line 3] # label $w.n$i -text $i -relief $RELIEF -font $FONT -borderwidth 2 -anchor w label $w.t$i -text $title -relief $RELIEF -font $FONT -borderwidth 2 -anchor w label $w.d$i -text $desc -relief $RELIEF -font $FONT -borderwidth 2 -anchor w label $w.s$i -relief $RELIEF -font $FONT -borderwidth 2 -anchor e \ -width 3 -textvariable score($vname) bind $w.s$i <Enter> [list scoreEnter %W $i $pname $vname] bind $w.s$i <Leave> [list scoreLeave %W $i $pname $vname] bind $w.s$i <Button-1> [list scoreDown %W $i $pname $vname] bind $w.s$i <ButtonRelease-1> [list scoreUp %W $i $pname $vname] # grid $w.n$i $w.t$i $w.d$i $w.s$i -sticky ew grid $w.t$i $w.d$i $w.s$i -sticky ew } } return $w } # Enter a cell on the score card proc scoreEnter {w line pname vname} { global scoreActive score tempScore tempBG scoreCurrentWin set scoreCurrentWin $w set tempBG [$w cget -background] if {$scoreActive == 0} return if { [string compare $score($vname) {}] } return # \#ffff7f was the orig color S.A. $w configure -textvariable tempScore -background yellow3 ;#rosybrown, yellow3, khaki diceCount set tempScore [eval $pname] } # Leave a cell in the score card proc scoreLeave {w line pname vname} { global scoreActive global score global tempBG global scoreCurrentWin set scoreCurrentWin {} if {$scoreActive == 0} return if { [string compare $score($vname) {}] } return $w configure -textvariable score($vname) -background $tempBG catch {unset tempScore} } # Button press on a cell in the score card proc scoreDown {w line pname vname} { global scoreActive global score if {$scoreActive == 0} return if { [string compare $score($vname) {}] } return } # Button release on a cell in the score card -- score the roll. proc scoreUp {w line pname vname} { global scoreActive global score global scoreCurrentWin global tempScore global tempBG global linesUsed if {$scoreActive == 0} return if { ![info exists tempScore] } return if { [string compare $score($vname) {}] } return if { [string compare $w $scoreCurrentWin] } return $w configure -textvariable score($vname) -background $tempBG set score($vname) [eval $pname 1] unset tempScore if {[incr linesUsed] >= 13} { endGame } else { initroll } } # Count the number of 1's, 2's, etc... rolled proc diceCount {} { global dieValue global dieCount global dieTotal set dieTotal 0 for {set d 1} {$d <= 6} {incr d} { set dieCount($d) 0 } for {set n 1} {$n <= 5} {incr n} { incr dieCount($dieValue($n)) incr dieTotal $dieValue($n) } } # Score up 1's, 2's etc. proc count {d {done 0}} { global dieCount global score set c [expr { $dieCount($d)*$d }] if {$done} { incr score(subtotal) $c incr score(total) $c incr score(difference) [expr { $c-3*$d }] if {$score(subtotal) >= 63 && $score(bonus) == 0} { set score(bonus) 35 incr score(total) 35 } checkXtra } return $c } # Score 3-of-a-kind, 4-of-a-kind proc kind {need {done 0}} { global score global dieCount global dieTotal set rv 0 for {set d 1} {$d <= 6} {incr d} { if {$dieCount($d) >= $need} { set rv $dieTotal } } if {$done} { incr score(total) $rv checkXtra } return $rv } # Score full house proc fullhouse {{done 0}} { global dieCount global score for {set n 1} {$n <= 5} {incr n} { set have($n) 0 } for {set d 1} {$d <= 6} {incr d} { set have($dieCount($d)) 1 } if {$have(5) || ($have(2) && $have(3))} { set rv 25 } else { set rv 0 } if {$done} { incr score(total) $rv checkXtra } return $rv } # Score chance proc chance {{done 0}} { global score global dieTotal if {$done} { incr score(total) $dieTotal checkXtra } return $dieTotal } # Score small-straight proc smstraight {{done 0}} { global dieCount global score set rv 0 if {$dieCount(3) && $dieCount(4)} { if {$dieCount(1) && $dieCount(2) \ || $dieCount(2) && $dieCount(5) \ || $dieCount(5) && $dieCount(6)} { set rv 30 } } set x [isyahtzee] if {$x \ && [string compare $score(count$x) {}] \ && [string match $score(yahtzee) 50]} { set rv 30 } if { $done } { incr score(total) $rv checkXtra } return $rv } # Score large-straight proc lgstraight {{done 0}} { global dieCount global score set rv 0 if {$dieCount(2) && $dieCount(3) && $dieCount(4) && $dieCount(5)} { if {$dieCount(1) || $dieCount(6)} { set rv 40 } } set x [isyahtzee] if {$x \ && [string compare $score(count$x) {}] \ && [string match $score(yahtzee) 50]} { set rv 40 } if { $done } { incr score(total) $rv checkXtra } return $rv } # Score yahtzee proc yahtzee {{done 0}} { global score if { [isyahtzee] } { set rv 50 } else { set rv 0 } if {$done} { incr score(total) $rv } return $rv } # Check for an extra yahtzee proc checkXtra {} { global score if {[string match $score(yahtzee) 50] && [isyahtzee]} { incr score(extra) 100 incr score(total) 100 } } # Check if this roll is a yahtzee proc isyahtzee {} { global dieCount for {set d 1} {$d <= 6} {incr d} { if {$dieCount($d) == 5} { return $d } } return 0 } proc endGame {} { global score rcfile env highscores username tcl_platform set highscores {} ### read in file if it exists if {[file readable $rcfile ]} { set fid [open $rcfile r] while {![eof $fid]} { gets $fid line if {[string is integer [lindex $line 0]] && "$line" != ""} { lappend highscores $line } } close $fid } if {[lindex [lindex $highscores end] 0] < $score(total) \ || [llength $highscores] < 14 } { ### new high score # get a name if {![info exists username]} { if { $tcl_platform(platform) == "unix" } { set username $env(USER) } else { set username $env(USERNAME) } } set username [getName $username] destroy .name # sort them and keep only best 15 set newentry "[format "%3i" $score(total)] [format "%-15s" $username] [clock format [clock seconds] -format %d/%m/%y]" lappend highscores $newentry set highscores [lrange [lsort -integer -index 0 -decreasing $highscores] 0 13] ### write highscores set fid [open $rcfile w] foreach line $highscores { puts $fid "$line" } close $fid showScores $newentry } .action configure -text "N e w G a m e" -command newGame -padx 31 -state normal } proc getName {default} { global result initSubWindow .name "High Score" 1 message .name.msg -text "Please enter a name" -aspect 1000 entry .name.entry -textvariable name .name.entry delete 0 end .name.entry insert 0 $default .name.entry icursor end raise .name focus .name.entry update bind .name.entry <Return> {set result $name} button .name.button -text ok -command {set result $name} -pady .7 -activebackground lightgoldenrodyellow pack .name.msg .name.entry -side top -fill x pack .name.entry -pady 5 -padx 10 pack .name.button -side bottom center .name wm deiconify .name update tkwait variable result return [string range $result 0 14] } proc initSubWindow {w title transient} { # Initilaises a toplevel window offscreen and withdrawn # (to allow the user to pack it before centering and being drawn) # I tried to use bind <FocusIn|Enter> to raise the window, # but using "grab" stops this command taking effect. # Additionally, using grab is the only way I know of to disable menus catch {destroy $w} toplevel $w wm title $w $title wm withdraw $w wm geometry $w +2000+2000 if {$transient} { wm transient $w . bind . <FocusIn> "raise $w ; focus -force $w" } wm protocol $w WM_DELETE_WINDOW "closeSubWindow $w" } proc grabSubWindow {w} { # There is an obscure bug in the grab code that means grab shouldn't be used till window # is drawn, so put grab here global data if { $data(platform) == "unix"} { grab set $w } } proc closeSubWindow {w} { bind . <FocusIn> "" grab release $w destroy $w } proc closeDialog {w {cmd ""}} { closeSubWindow $w .c configure -state normal if { $cmd != "" } { uplevel #0 $cmd } } proc center {win} { # Center window $win on the screen set w [winfo reqwidth $win] set h [winfo reqheight $win] set parent [winfo parent $win] if {"$parent" == "" } { set sh [winfo screenheight $win] set sw [winfo screenwidth $win] set reqX [expr {($sw-$w)/2}] set reqY [expr {($sh-$h)/2}] } else { scan [wm geometry $parent] "%dx%d+%d+%d" a b c d set reqX [expr $c + ($a-$w)/2] set reqY [expr $d + ($b-$h)/2] } if {$reqX < 0} {set reqX 0} if {$reqY < 0} {set reqY 0} wm geometry $win +$reqX+$reqY update idletasks return; } proc newGame {} { global scorecard global score global linesUsed initroll set linesUsed 0 foreach line $scorecard { set vname [lindex $line 1] set score($vname) {} } set score(subtotal) 0 set score(difference) 0 set score(total) 0 set score(bonus) 0 set score(extra) 0 set scoreCurrentWin {} } proc showScores {{newentry {}}} { global rcfile tcl_platform initSubWindow .scores "High Scores" 1 text .scores.t -relief groove -spacing1 3 -back grey80 -height 15 .scores.t tag configure center -justify center .scores.t tag configure hilight -background gainsboro -justify center .scores.t insert end "High Scores\n" center if {[file readable $rcfile]} { set fid [open $rcfile r] while {![eof $fid]} { gets $fid line if {$line != {} && $line == $newentry} { .scores.t insert end "$line\n" hilight } else { .scores.t insert end "$line\n" center } } close $fid } button .scores.b -text ok -command {closeSubWindow .scores} -pady .7 -activebackground lightgoldenrodyellow # gates is a piece of shit if { $tcl_platform(platform) != "unix" } { .scores.t configure -font {courier 9} .scores.b configure -font {Arial 9} -padx 15 -pady .5 } pack .scores.t -padx 5 -pady 2 pack .scores.b -side bottom # centre the help window before enabling update scan [wm geometry .] "%dx%d+%d+%d" e f g h set x [expr $g+30] set y [expr $h+60] wm geometry .scores "250x305+$x+$y" wm state .scores normal update } proc initHelp {} { global help data tcl_patchLevel # basically each help text ("k") is just a list of {text format text format ....} # where format is the text "tag" that determines any special formatting foreach {i j k} { 0 TkYahtzee { {Yahtzee is game played with 5 dice. You roll them - up to 3 times - trying to get patterns which match the entries in the score card. After the first roll, only unwanted dies are rolled a second and third time, trying to get the best score. You must then select one entry to score against before starting the next round. The game is over and a score tallied after all the entries are full. A bonus of 35 points is gained if the upper score card sub-total is 63 or greater. Extra Yahtzees score a 100 point Bonus (though this is not official rules).} {} \n\n {} } 1 Changes { {1.2.4 Bug with destroying the highscore window - fixed. 07/10/08. Help menu up/down key bindings 26/11/08} indent \n\n {} {1.2.3 Restructured 'help' and 'about' widgets, adding a 'changes' widget 10/11/07} indent \n\n {} {1.2.2 Changed around a few colours, and the fonts for wish8.5, 22/07/07} indent \n\n {} {1.2.1 Added a high score widget, overhauled buttons, added menus, removed message widget , fixed up win fonts, added help dialogs, removed the 1,2,...17 column from the scorecard 18/01/06} indent \n\n {} {1.01 Moved button close to dice, sanity checked the colour scheme 14/11/05} indent \n\n {} {- Downloaded Kevin's yahtzee from www.tcl.tk} indent } 2 About {} } { set help($i) "" set help(title,$i) "$j" set help(text,$i) "$k" } # end foreach set help(text,2) [list "$data(name) $data(version) ($data(date)) copyright Steven A. Released under the GPL v2. Available at $data(web).\n\n" {} "Based on: Yahtzee, downloaded from www.tcl.tk, written by Kevin Kenny.\n\n" {} "Tcl Version $tcl_patchLevel.\n" {} ] } proc showHelp {{topic 0}} { global p help data set w .help if { [winfo exists $w] } { showHelpTopic $w $topic wm deiconify $w raise $w focus $w return } initSubWindow $w "$data(name) - Help" 0 pack [listbox $w.l -activestyle none -selectmode single -font $data(font_default) -width 12] \ -expand 0 -fill y -side left -anchor nw bind $w.l <<ListboxSelect>> "showHelpTopic $w" pack [text $w.t -width 30 -height 25 -yscrollcommand "$w.s set" \ -wrap word -font $data(font_default) -padx 5 -pady 8] \ -expand 1 -fill both -side left -anchor nw $w.t tag configure "title" -font $data(font_large) -justify center $w.t tag configure "indent" -lmargin2 15 $w.t tag configure "indent2" -lmargin1 8 -lmargin2 20 $w.t tag configure "italic" -font "[font actual [$w.t cget -font]] -slant italic" $w.t tag configure "link" -font "[font actual [$w.t cget -font]] -underline 1" \ -foreground blue $w.t tag bind link <Enter> "%W configure -cursor hand2" $w.t tag bind link <Leave> "%W configure -cursor {}" pack [scrollbar $w.s -command "$w.t yview"] -fill y -side left -anchor ne # populate list, show index topic foreach x [lsort [array names help -regexp {^[0-9]+$}]] { $w.l insert end $help(title,$x) $w.t tag bind goto$x <Button-1> "showHelpTopic $w $x" } bind $w <KeyPress-q> "destroy $w" # there's a minor unresolved issue with wish8.5 and focus bind $w <KeyPress-Up> "$w.t yview scroll -1 unit" bind $w <KeyPress-Down> "$w.t yview scroll +1 unit" bind $w <KeyPress-Prior> "$w.t yview scroll -1 page" bind $w <KeyPress-Next> "$w.t yview scroll +1 page" focus $w update center $w wm deiconify $w showHelpTopic $w $topic $w.t configure -state disabled } proc showHelpTopic {w {topic {}}} { global help # show a specific help topic in the window # $w is toplevel, $w.t is the text frame if { $topic != {}} { $w.l selection clear 0 end $w.l selection set $topic $w.l activate $topic } $w.t configure -state normal $w.t delete 1.0 end set helpFile [$w.l curselection] $w.t insert end $help(title,$helpFile) title $w.t image create end -image ::img::logo -align center -padx 20 $w.t insert end "\n\n" foreach {text tags} $help(text,$helpFile) { $w.t insert end $text $tags } $w.t configure -state disabled } proc exitYahtzee {} { exit } ######## # main # ######## ### init menus . configure -menu [menu .m -tearoff 0] .m add cascade -label "Game" -underline 0 -menu [menu .m.g -tearoff 0] .m.g add command -label "New Game" -underline 0 -command newGame .m.g add command -label "High Scores" -underline 0 -command showScores .m.g add command -label "Quit" -underline 1 -command exitYahtzee # .m add cascade -label "Options" -underline 0 -menu [menu .m.o -tearoff 0] # .m.o add command -label "Background Colour" -underline 0 -command showColor .m add cascade -label "Help" -underline 0 -menu [menu .m.help -tearoff 0] .m.help add command -label "Help" -command showHelp -underline 0 .m.help add command -label "Changes" -command {showHelp 1} -underline 0 .m.help add command -label "About" -command {showHelp 2} -underline 0 # used by new help widgets set data(font_default) {Arial -16} set data(font_medium) {Arial -18} set data(font_large) {Arial -20} ### make the user interface catch {wm title . "$data(name) $data(version)"} catch {wm minsize . 300 500} grid columnconfigure . 0 -weight 1 grid columnconfigure . 2 -weight 1 grid [scorecard .score] - - - set FONT {8x13bold} grid [frame .padding] - - - -sticky ew -pady 3 ;# padding S.A. ### init button & labels grid [label .dummy -text {} -padx 16 ] \ [button .action -text {} -padx 60 -pady 5 ] \ [label .diff -textvariable score(difference) -padx 16] \ if { $tcl_platform(platform) == "unix" } { .action configure -font {Arial 20} } else { .action configure -font {Arial 10} } # [button .button -image im1 -fg "lightslategray" -borderwidth 1 -padx 5 -pady 5 -activeforeground lightslategray -activebackground grey82 ] ### init dice grid [frame .dice] - - - -sticky ew -pady 10 for {set n 1} {$n <= 5} {incr n} { grid columnconfigure .dice $n -weight 1 grid [die .dice.d$n $n] -row 1 -column $n } # set window state and prime the random number generator set dieCurrent {} set scoreCurrentWin {} random_init [clock seconds] image create photo ::img::logo -data { R0lGODlhQABAAOf/AAABAAgLBw0PDBIUERgZFxsdGh4gHiIkISYoJSssKi4w LTI0MTY3NTg6OD0+PEFCQEVGRElLSElKU05MT0xOS0tPUUtRSFBOUk1RU1BS T1BRWVNRVVZQWk5aP1FZRFRVU1JYT1VYSldVWVZYVVRXZVRZW1dYYVpYXFdc U1pXZlVdWVhcalphTF1aalpeYF5cYF1kOFxeW11gUl5eZ19hXl1jWmJfY2Nh ZWJkYV9jcWVicmJmaGRlbmZoZWtlb2lnamVrYWZqeGpraWxpeW9pdGtsdWxu a2trgG9tcWpth2p5UG9xbm1xdHBxenN1cnhyfXZ0eHZzgnZ3dXh6d3x6fnl5 jnd7iXx+e3x8hn56lnuAgoB+gn+BfoCAioOBhYKEgX+DkX+CnYSAnISGg4OD mISFjn+GmoiGioaIhYeJhoaGm4SHooaLjYmLiH2Qj42Lj4uNio2JmoOPnIyO i42JpYuLoYmNnIyNloiMp4uQkoWRno6QjZKQlJCSj42RoJKOq5CQppOQoI2R rIuTp5KUkZKTnZSWk5aSr5OYm42ZppWVq5CYrJeZloufnpaZqJiXrpmbmJuY qZqapJidoJudmZqasJ6coJyem5SgrZ2fnJ2cs5ygsJilpaCftqGjoKOfsKGh q5uoqKSmo6Slr6iktaOntpyssqmnq6amvKWqraiqp6ustamtvKqvsa6rvK2v rKysw7GzsK6ywbSwwbKyvLGxx7Wzt7S2s7S1v7O3x7e5trm2x7e4wrq4vLm7 uL25y7u8xry+u7q+zcC+wr/Bvr+/1sLEwcDFyMbDx8PEzsXHxMjE1sfJxsXK zcjJ08vJzcvNys3PzNDN0svQ0s7P2dHN39DSz9LU0dXT19XR49TW09TU39LX 2dbY1dnW29zV4dXa3Nnb19rc2d3a39vd2tze293f3N7g3d/h3tzi5OLg5ODi 3+Lk4ebj6OTm4+Ln6ubo5efp5unr5+rs6evu6u7s8O3v7O3y9fDy7/L18fXz 9/b49PT5/Pn79/z++////yH5BAEKAP8ALAAAAABAAEAAAAj+AP8JHEiwoMGD CBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIC1yMhWqkRtHlUJirPUtW7Vl xWqVwrSpk6aUKh1WgqWunz9+/vDVG/ctWS5XnSopEsRUUM6Dj3Z5u6fPn1V9 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 ADs=} initHelp newGame bind . <F1> showHelp bind . <KeyPress-q> {destroy . ; exit 0} bind . <KeyPress-i> {wm iconify .} ####### # end # #######