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
#!/bin/sh
# the next line restarts using tclsh \
exec wish "$0" "$@"
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 ) }]
}
# 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 #
. 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}
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.
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 ]
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
WO/Va5cOHDVnyXbNIqVJ0dOBh6Tay6dvn1Wr+PLlqzdvnrpefc7YQias7Nl/
qKilg9fOHlas+PTVo1d3HrY3DhiwaeaN1aOnf0i1U2crEzF4+/r10ye3Xr14
8/DdEiGAAAND6nhdVvlHFjV3aSIwuDCsHta5i+PRxYfMBoEECahAS4YTJB1X
1M4h+2DAAIJX8vaRtneasLpw2t7+MCCg4Ay2Z5XwhKwkDZ46TwwMJGBgC95a
usLhIfPEiNktKg7Y4Ik51HRSB0WYHHLIIokYRIcm2LQDzzinJCBAAlI8Yxpw
8MSjjRQECADFMOP48kw452jzCSASDVLJLMk8s8sndBBkRifAtIMOPOc8hoQX
yKjDDjx0wQMPPsP4cNwDe4SjjjrjOMkKixAdUkou0qRDIC+kKDKIQHKUgow8
T6IzDjLBKFPOk+7MQ2Q8+TCDBAEIHECFNeucE+U4s5gFUSe/cMNOmeokg0ok
Dd4hyS7qlLPmOoS5h8456tTj3nnPvPGAfFdg81044awjWxYNlaIJLN4YyeM5
4aCjzjX+uzxihhl+0OKekyiC+qST6sCjixQRWGILHwzYcAquUaKDzCakLlQK
K8KME+mT1JYzDjbIuIIHHqjoyus4n34nTzlvJGDAA20g0wsy0aiDzbVPOqNJ
GAoJU8os36jzjjzusRPqmqCCA440pAASCTbdhNNNwgmH42k48GCzxQEHGCCE
MfF8Vw6ooJ5zTSn0ImRvMemkZo+R8Rj5JMC7PrPiiVFSG6XC4KLDhwMJEGBD
fZR6i0043rhCxkFyAALLN1XhY088Eho5pHvqaKNNOT2SEggwvEIM5Xdcz9ML
Eq0JESSo3iS8azi0qGFQJaQk044+VCmN3zN82CCFJ9Hg6qT+NqvEYcvPxLyx
hSjacByONc8wY8sZb9gSjjlcq+ONw04CE0gSAz3SSS7f1OOWPonNE0/Kp1Aw
nw2W4Poz2nGAgo0xX0QmRC9PnueLLbG8osorJiKDDTZ5Y9OzOsdIcsRAisCy
TVVVBWWPPfOcRggDBRyggA0/h2uLH4FgYwkEIU5winvR9MKfJeifcooou98y
DDLQPBPNz8+AcrxAgOSSjlv+JK3Y6PYYhhAIQMAJZO9a6xiGJLowjC0gxwAf
GB82fIE+SGSCEoYgBB/48AY+7GEPfIDEKVRhC2L0whL3+4cidtEeejAPdNAT
TjiGcYYfSAESoFqdOqRhiSgMQzz+rnlDNK6hi1NkAn1I5IMhDNGHOWxwDm9o
gwc3CIYgDAQQvJBGrwwDOqFYSmXKsEUvPLWxqJVjGqPggS1O4QUbjGGMvRCF
JTIBCUrMYQo4sIEQvMAHOLQhimf4QiCp0IQhDGEggpiFNMLxDGyYwx6JgV6k
4OEmMoFqZtpAhiV0cIppTBAb0NCFJ+aIRClMgAEJcEAM+sDBP7YhkF5oAg9y
QJD8YeMalDjDsezDHaZRK3LeGoYq8pADSyjDSNg44REpwQhLvIECrknAARjw
Biim4QzX5EITdDCDguCBFs84BQMQ8AFLqKMd7RhdyuDBDoA5yRvIsIUc3+CD
OwzDXbr+UMUy0ceIPWzAAAc43R7ecM1rUgEJ3TQIHnAxDD4QUAFC8NSTVLUr
qEXDGKqwBCMIwQYedMEW0RjGKUjJiCVagg9QmMADJmCDKQz0lWM46A5WcJA6
7KKh8knAB6yhK2qxc1fW6MUp+KBBPpwBCVBgRC8ycQlLNLWZGyQEHM4ABSl8
4Q0EDeQWEKoChNSBFtKwxXh09jCzQWxQ6oDGK9oABz4wAhKGoOoMfnQGEDaT
EZSABCOmaAg+zOGaaDjDFnzgghIkhA6ymF/dpGAJVq2OV1ELhiVs4IAPXAGl
UuACF4SwAxvY4AY/8AERnvAELzBug37F6iup8IMPLOQ5WrT+hi1M9KlrUS4c
yBAFF8z1gCUsYQIspcIHMrCBE2xABBzQARB6AAQhCAGpUKACFbbwBSn84ASu
VUgYVgGNNVEKHdqAEq4+dQtLUAE5J/iBA+RDARswgAEZsMEIMDCQ5WZAAxzg
AA5w0AMjCOEGJ6AAQ2BruNv+bHXe6Ezd9kiFOjkgAuZK5QtGkAGFAKEDPZgA
BQTMEDGw4hlc8xbX3BOlW4xUg4Z4wwtE8IIXIIcBE9jABejLETGUYhiTi9Lk
PBUNMbYLG7E44hEJ8QYp+PcGD3AAcCdggRB0ZA11cIXvvOWwV/TACado1xoh
YQlK8GEMUoCCEH6w4gwA1wMfycL5Glb4MHWgoxdCAEAAPvAKdpS3qZfggxee
m8cRbEACEYCBSsSghk8M42fwsIVxCgCBM9xFjs2cgxSEkMcPcAC4Z8mCGCRh
i2eYIxggco0X2GE+jTpTCDaIgQgyAIIK/+UfWYgDKZ6hyXFOgBHq0IUluGyI
PdtABBeQAAtePZAjHOEOWbQEY9tlYi4zggox0MAFJkBsgxyhC5YYxjN4qo3O
WMITb0CCBkZQbYQMAQt86IUWwxHHvSIBBzJwcrkPogMddOEUyAhHec+wBA7I
QAnzVogJeFAGkZaBBygIeENM4AMoQMEHCoeICWwQ8Ypb/OIYz7jGN87xcgcE
ADs=}
initHelp
newGame
bind . <F1> showHelp
bind . <KeyPress-q> {destroy . ; exit 0}
bind . <KeyPress-i> {wm iconify .}
# end #
