TENAGLIA@mis.mcw.edu (Chris Tenaglia - 257-8765) (05/28/91)
Another holiday has passed, and with it came another icon game. This is Yahtzee, the poker dice game. I use ICON 8 under VMS 5.4-1, but I tried to avoid system specific stuff. I'll probably get flamed again for my screen management methods (I tried a little something different.) It's written for VT100,2XX,3XX,4XX and compatible terminals, since that's all I have at this site. Bye the way, this version allows for multiple players. I've played it several times with my daughter and it seems pretty solid. Game design involves many tricky decisions. The two in this implementation were.. o Not to repaint dice if the value stayed the same This is seen in procedure depict(). I use a list 'od' to remember former values. Then when choosen dice are shaken, the unshaken ones stay put. But, so do the ones that come up the same. Oh well. o To give the player the feel of the three shakes, I provide a prompt saying whose turn it is, and asking them to press <RETURN>. These lines can be found at the beginning of procedure play(name). I also ask them to press return after their turn is over in order to allow some time to read their scorecard and think about future strategy. So here's the code. Enjoy! Chris Tenaglia (System Manager) | Medical College of Wisconsin 8701 W. Watertown Plank Rd. | Milwaukee, WI 53226 (414)257-8765 | tenaglia@mis.mcw.edu, mcwmis!tenaglia # # YAHT.ICN 5/27/91 BY TENAGLIA # # YAHTZEE GAME # global players,slot,team,d,od,dice,round procedure main(param) paint() assign_players() every round := 1 to 13 do every play(!team) summarize() end # # DISPLAYS THE HEADER AND SEPARATOR LINE AT BEGINNING OF GAME # procedure paint() write(cls(),high(uhalf(" Y A H T Z E E "))) write(high(lhalf(" Y A H T Z E E "))) write(at(1,10),graf(repl("q",75))) end # # DISPLAYS THE FINAL SCORE OF ALL THE PLAYERS # procedure summarize() write(at(1,11),blink(high(inverse(chop("Final Score Summary"))))) every player := key(players) do { card := players[player] top := 0 ; every i := 1 to 6 do top +:= card[i] if top > 62 then top +:= 35 bottom := 0 ; every i := 7 to 13 do bottom +:= card[i] write("Player ",high(left(player,14))," Top = ",right(top,5), " Bottom = ",right(bottom,5), " Total = ",right(top+bottom,5)) } input("<press return>") end # # SETUP AND INITIALIZATION OF YAHTZEE ENVIRONMENT # procedure assign_players() n := 1 ; team := [] ; slot := [] ; d := list(6,"") ; od := list(5,0) &random := map(&clock,":","9") players := table("n/a") repeat { (player := input(("Name of player #" || n || ":"))) | stop("Game called off.") if player == "" then break n +:= 1 put(team,player) players[player] := list(13,"*") } if n = 1 then stop("Nobody wants to play!") put(slot,"Ones") ; put(slot,"Twos") ; put(slot,"Threes") put(slot,"Fours") ; put(slot,"Fives") ; put(slot,"Sixes") put(slot,"3oK") ; put(slot,"4oK") ; put(slot,"FullH") put(slot,"SmStr") ; put(slot,"LgStr") ; put(slot,"Yahtzee") put(slot,"Chance") d[1] := "lqqqqqkx xx ` xx xmqqqqqj" d[2] := "lqqqqqkx xx ` ` xx xmqqqqqj" d[3] := "lqqqqqkx` xx ` xx `xmqqqqqj" d[4] := "lqqqqqkx` `xx xx` `xmqqqqqj" d[5] := "lqqqqqkx` `xx ` xx` `xmqqqqqj" d[6] := "lqqqqqkx` ` `xx xx` ` `xmqqqqqj" end # # THIS ROUTINE LETS A PLAYER TAKE THEIR TURN # procedure play(name) writes(at(1,11),"It's ",high(name),"'s turn",chop()) writes(at(1,12),high(name)) ; input(", Please press <RETURN> to begin.") score(name) dice := [] ; every 1 to 5 do put(dice,?6) depict() shake := obtain("Shake which ones :") (shake === []) | (every dice[!shake] := ?6) depict() shake := obtain("(Last Chance) Shake which ones :") (shake === []) | (every dice[!shake] := ?6) depict() repeat { select := input(at(1,22) || clip("Tally to which category (1 -> 13) :")) numeric(select) | next (1 <= select <= 13) | next (players[name][select] == "*") | next break } tally(name,select) score(name) input(at(1,22) || clip("Press <RETURN>")) end # # THIS ROUTINE DRAWS THE DICE # procedure depict() every i := 1 to 5 do { if od[i] = dice[i] then next x := 1 writes(at(i*10+4,3),inverse(i)) # writes(at(i*10+4,9),inverse(dice[i])) every j := 4 to 8 do { writes(at(i*10,j),graf(d[dice[i]][x:x+7])) x +:= 7 } od[i] := dice[i] } end # # THIS ROUTINE LETS THE PLAYER DECIDE WHAT TO APPLY THE SHAKES TO # procedure tally(name,area) case integer(area) of { 1 : { # ones sum := 0 ; every unit := !dice do if unit = 1 then sum +:= 1 players[name][1] := sum } 2 : { # twos sum := 0 ; every unit := !dice do if unit = 2 then sum +:= 2 players[name][2] := sum } 3 : { # threes sum := 0 ; every unit := !dice do if unit = 3 then sum +:= 3 players[name][3] := sum } 4 : { # fours sum := 0 ; every unit := !dice do if unit = 4 then sum +:= 4 players[name][4] := sum } 5 : { # fives sum := 0 ; every unit := !dice do if unit = 5 then sum +:= 5 players[name][5] := sum } 6 : { # sixes sum := 0 ; every unit := !dice do if unit = 6 then sum +:= 6 players[name][6] := sum } 7 : { # 3 of a kind sum := 0 ; flag := 0 tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1 every piece := key(tmp) do if tmp[piece] >= 3 then flag := 1 if flag = 1 then every sum +:= !dice players[name][7] := sum } 8 : { # four of a kind sum := 0 ; flag := 0 tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1 every piece := key(tmp) do if tmp[piece] >= 4 then flag := 1 if flag = 1 then every sum +:= !dice players[name][8] := sum } 9 : { # full house sum := 0 ; flag := 0 tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1 every piece := key(tmp) do { if tmp[piece] = 3 then flag +:= 1 if tmp[piece] = 2 then flag +:= 1 } if flag = 2 then sum := 25 players[name][9] := sum } 10 : { # small straight sum := 0 ; flag := 0 hold := set() ; every insert(hold,!dice) tmp := sort(hold) if tmp[1]+1 = tmp[2] & tmp[2]+1 = tmp[3] & tmp[3]+1 = tmp[4] then flag := 1 if tmp[2]+1 = tmp[3] & tmp[3]+1 = tmp[4] & tmp[4]+1 = tmp[5] then flag := 1 if flag = 1 then sum := 30 players[name][10] := sum } 11 : { # large straight sum := 0 ; flag := 0 tmp := sort(dice) if tmp[1]+1 = tmp[2] & tmp[2]+1 = tmp[3] & tmp[3]+1 = tmp[4] & tmp[4]+1 = tmp[5] then flag := 1 if flag = 1 then sum := 40 players[name][11] := sum } 12 : { # yahtzee sum := 0 ; flag := 0 tmp := table(0) ; every unit := !dice do tmp[unit] +:= 1 every piece := key(tmp) do if tmp[piece] = 5 then flag := 1 if flag = 1 then sum := 50 players[name][12] := sum } 13 : { # chance sum := 0 ; every sum +:= !dice players[name][13] := sum } } end # # THIS ROUTINE OBTAINS A VALID SHAKER REQUEST # procedure obtain(prompt) repeat { writes(at(1,22),prompt) (line := read()) | next if match("q",map(line)) then stop("Game Quit") if trim(line) == "" then return [] units := parse(line,', \t') every unit := !units do (1 <= unit <= 5) | next break } return units end # # THIS ROUTINE PAINTS THE SCORECARD FOR A GIVEN PLAYER # procedure score(name) writes(at(1,11),chop(),at(25,11),under(),"Player = ",name," Round = ",under(round)) writes(at(10,12)," 1 : Ones = ",players[name][1]) writes(at(10,13)," 2 : Twos = ",players[name][2]) writes(at(10,14)," 3 : Threes = ",players[name][3]) writes(at(10,15)," 4 : Fours = ",players[name][4]) writes(at(10,16)," 5 : Fives = ",players[name][5]) writes(at(10,17)," 6 : Sixes = ",players[name][6]) writes(at(40,12)," 7 : 3oK = ",players[name][7]) writes(at(40,13)," 8 : 4oK = ",players[name][8]) writes(at(40,14)," 9 : FullH = ",players[name][9]) writes(at(40,15),"10 : SmStr = ",players[name][10]) writes(at(40,16),"11 : LgStr = ",players[name][11]) writes(at(40,17),"12 : Yahtzee = ",players[name][12]) writes(at(40,18),"13 : Chance = ",players[name][13]) st1 := 0 ; every i := 1 to 6 do st1 +:= numeric(players[name][i]) if st1 > 62 then bonus := 35 else bonus := 0 st2 := 0 ; every i := 7 to 13 do st2 +:= numeric(players[name][i]) writes(at(10,19),"Bonus = ",clip(bonus)) writes(at(10,20),"Subtotal = ",st1+bonus) writes(at(40,20),"Subtotal = ",st2) writes(at(37,21),"Grand Total = ",st1+st2+bonus) end # # VIDEO ROUTINE CLEARS SCREEN # procedure cls(str) /str := "" return "\e[2J\e[H" || str end # # VIDEO ROUTINE ERASES REST OF SCREEN # procedure chop(str) /str := "" return "\e[J" || str end # # VIDEO ROUTINE OUTPUTS UPPER HALF OF DOUBLE SIZE MESSAGES # procedure uhalf(str) /str := "" if str == "" then return "\e#3" return "\e#3" || str end # # VIDEO ROUTINE OUTPUTS BOTTOM HALF OF DOUBLE SIZE MESSAGES # procedure lhalf(str) /str := "" if str == "" then return "\e#4" return "\e#4" || str end # # VIDEO ROUTINE OUTPUTS STRING AND CLEARS TO EOL # procedure clip(str) /str := "" if str == "" then return "\e[K " return str ||:= "\e[K" end # # VIDEO ROUTINE OUTPUTS HIGHLIGHTED STRINGS # procedure high(str) /str := "" if str == "" then return "\e[1m" str := "\e[1m" || str if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m") then return str else return str || "\e[m" end # # VIDEO ROUTINE OUTPUTS INVERSE VIDEO STRINGS # procedure inverse(str) /str := "" if str == "" then return "\e[7m" str := "\e[7m" || str if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m") then return str else return str || "\e[m" end # # VIDEO ROUTINE OUTPUTS UNDERLINED STRINGS # procedure under(str) /str := "" if str == "" then return "\e[4m" str := "\e[4m" || str if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m") then return str else return str || "\e[m" end # # VIDEO ROUTINE OUTPUTS BLINKING STRINGS # procedure blink(str) /str := "" if str == "" then return "\e[5m" str := "\e[5m" || str if (str[-3:0] == "\e[m") | (str[-4:0] == "\e[0m") then return str else return str || "\e[m" end # # VIDEO ROUTINE SETS NORMAL VIDEO MODE # procedure norm(str) /str := "" if str == "" then return "\e[m" str := "\e[m" || str return str end # # VIDEO ROUTINE TURNS ON VT GRAPHICS CHARACTERS # procedure graf(str) /str := "" if str == "" then return "\e(0" str := "\e(0" || str if (str[-3:0] == "\e(B") then return str else return str || "\e(B" end # # VIDEO ROUTINE TURNS OFF VT GRAPHICS CHARACTERS # procedure nograf(str) /str := "" if str == "" then return "\e(B" str := "\e(B" || str return str end # # VIDEO ROUTINE SETS CURSOR TO GIVEN X,Y COORDINATES # procedure at(x,y) return "\e[" || y || ";" || x || "f" end # # PARSES A STRING INTO A LIST WITH RESPECT TO A GIVEN DELIMITER # procedure parse(line,delims) static chars chars := &cset -- delims tokens := [] line ? while tab(upto(chars)) do put(tokens,tab(many(chars))) return tokens end # # TAKE AN INPUT STRING VIA GIVEN PROMPT # procedure input(prompt) writes(prompt) return read() end # # DISCLAIMER # ######################################################################### # # # Copyright (c) 1991, Chris D. Tenaglia # 12p # # # # This software is intended for free and unrestricted distribution. # # I place only two conditions on its use: 1) That you clearly mark # # any additions or changes you make to the source code, and 2) that # # you do not delete this message therefrom. In order to protect # # myself from spurious litigation, it must also be stated here that, # # because this is free software, I, Chris tenaglia, make no claim # # about the applicability or fitness of this software for any # # purpose, and expressly disclaim any responsibility for any damages # # that might be incurred in conjunction with its use. # # # #########################################################################
goer@ellis.uchicago.edu (Richard L. Goerwitz) (05/29/91)
If anyone wants a Unix version of Chris Tenaglia's yahtzee game (will probably work for DOS, too), please let me know. If I get more than a few requests, I'll post it. -Richard -- -Richard L. Goerwitz goer%sophist@uchicago.bitnet goer@sophist.uchicago.edu rutgers!oddjob!gide!sophist!goer