Skip to content

Instantly share code, notes, and snippets.

@fictorial
Created October 10, 2012 16:37
Show Gist options
  • Save fictorial/3866754 to your computer and use it in GitHub Desktop.
Save fictorial/3866754 to your computer and use it in GitHub Desktop.
YAHTZEE.BAS
'--------------------------
' Yahtzee Version 1.1
' Brian Hammond
' Finished: June 25, 1995
' Coded in: MS-QBasic 7.1
'--------------------------
'Initial Setup-------------------------------------------------------------
'make arrays static by usage of a MetaCommand (needs the comment)
'$STATIC
'default variable type DEF is an integer INT (DEFINT)
DEFINT A-Z
'Constants------------------------------------------------------------------
CONST white = 15
CONST black = 0: CONST blue = 1
CONST green = 2: CONST cyan = 3
CONST purple = 5: CONST red = 4
CONST brown = 6: CONST gray = 7
CONST skyblue = 9: CONST yellow = 14
CONST lrepeat = 8 '# logo inner rectangles
CONST maxcol = 80 'max width of screen
CONST str3 = 25 'full house score
CONST str1 = 30 'four straight
CONST str2 = 40 'five straight
'Global Variables-----------------------------------------------------------
DIM SHARED newgame AS STRING * 2
DIM SHARED player1 AS STRING * 10
DIM SHARED player2 AS STRING * 10
DIM SHARED player3 AS STRING * 10
DIM SHARED player4 AS STRING * 10
DIM SHARED changes$
DIM SHARED numplayers
DIM SHARED lplacement
DIM SHARED x1, y1, x2, y2
DIM SHARED player, category
DIM SHARED die1, die2, die3, die4, die5
DIM SHARED roll.number
DIM SHARED one.counter, two.counter
DIM SHARED three.counter, four.counter
DIM SHARED five.counter, six.counter
DIM SHARED scores(1 TO 4, 1 TO 16)
DIM SHARED turn
DIM SHARED quit.counter
DIM SHARED yah.score
'Procedures/Functions------------------------------------------------------
DECLARE SUB blank (linenum)
DECLARE SUB board ()
DECLARE SUB center (row%, text$)
DECLARE SUB check.dice ()
DECLARE SUB graphic ()
DECLARE SUB intro ()
DECLARE SUB logo (lplacement, x1, y1, x2, y2)
DECLARE SUB place.score (turn)
DECLARE SUB play.game ()
DECLARE SUB player.turn (turn)
DECLARE SUB show.winner ()
DECLARE SUB update.score (turn, category)
DECLARE SUB user.input (numplayers, player1$, player2$, player3$, player4$)
DECLARE SUB yahtzee.scored ()
DECLARE FUNCTION roll% (n)
DECLARE FUNCTION certain$ (really.quit$)
'Module-Level Code---------------------------------------------------------
Main:
'screen mode set to VGA
CLS : SCREEN 12
'if any other error, display message
ON ERROR GOTO handler
'red fill-screen
CALL intro
'main loop - ends when user doesn't enter "Y" to continue a newgame
DO
CALL graphic
CALL user.input(numplayers%, player1$, player2$, player3$, player4$)
CALL board: CALL logo(lplacement, x1, 6, 625, 78)
'initialize scores array to equal 999 for every player's category scores.
'if it was not initialized to a value other than 0 (i.e. left alone) then
'the method to figure out if a player has scored in a certain category
'before reassigning a value to that category would be too difficult. A check
'to see if the value still = 999 is all that is needed now.
FOR q = 1 TO 4
FOR r = 1 TO 13
scores(q, r) = 999
NEXT
NEXT
FOR i = 1 TO 4
'allow for multiple yahtzees to be scored in any category. To disable the
'999 check, assign yahtzee another value, like 0.
scores(i, 12) = 0
NEXT
'indicate player's turn and start game
'set up a counter to quit when there are no more categories to score into.
quit.counter = numplayers * 13
turn = 1: CALL player.turn(turn): CALL play.game
'asks player if they want to play a new game
CLS : COLOR white: center 10, "ENTER=NO Y=YES"
COLOR skyblue: center 11, STRING$(15, CHR$(205))
COLOR gray: LOCATE 13, 32: INPUT "Play another? ", newgame$
newgame$ = UCASE$(newgame$)
IF INSTR(newgame$, "Y") THEN
ERASE scores: CLS : COLOR white
ELSE
COLOR white: CLS : EXIT DO
END IF
'reset variables if playing a newgame without program termination
roll.number = 0
LOOP
END
'Subroutines for Module Level----------------------------------------------
handler:
CLS
FOR j = 1 TO 3
FOR i = 1 TO 7
COLOR i
center 11, "ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸"
center 12, "³ Sorry but Yahtzee has run into a problem on this computer... ³"
center 13, "ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;"
NEXT
NEXT
SLEEP 2&
RESUME 100
'end of module-based code
'return to operating system (DOS)
100 CLS
'--------------------------------------------------------------------------
'
' Blanks out the passed line number.
'
'--------------------------------------------------------------------------
SUB blank (linenum)
LOCATE linenum, 1: PRINT SPACE$(78)
END SUB
'--------------------------------------------------------------------------
'
' Draws the yahtzee board.
'
'--------------------------------------------------------------------------
SUB board
'The following section labels the scoring categories. There are 13 of them.
CLS
COLOR cyan
LOCATE 9, 3: PRINT "1. Ones: "
LOCATE 10, 3: PRINT "2. Twos: "
LOCATE 11, 3: PRINT "3. Threes: "
LOCATE 12, 3: PRINT "4. Fours: "
LOCATE 13, 3: PRINT "5. Fives: "
LOCATE 14, 3: PRINT "6. Sixes: "
LOCATE 19, 3: PRINT "7. Three of a kind: "
LOCATE 20, 3: PRINT "8. Four of a kind: "
LOCATE 21, 3: PRINT "9. Full House: "
LOCATE 22, 3: PRINT "10. Four Straight: "
LOCATE 23, 3: PRINT "11. Five Straight: "
LOCATE 24, 3: PRINT "12. Yahtzee: "
LOCATE 25, 3: PRINT "13. Potpourri: "
'sum (1-6) labels
COLOR red: LOCATE 15, 3: PRINT "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
COLOR skyblue: LOCATE 16, 3: PRINT "Bonus 35 points if sum of fields 1-6 > 63"
COLOR cyan: LOCATE 17, 3: PRINT CHR$(228)
COLOR cyan: LOCATE 17, 4: PRINT "(1-6):"
COLOR red: LOCATE 18, 3: PRINT "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
'The following draws the dice holders
COLOR skyblue
LOCATE 8, 60: PRINT "The Dice"
COLOR cyan
column = 43
FOR x = 1 TO 5
column = column + 6
LOCATE 10, column: PRINT "ÕÍÍ͸"
LOCATE 11, column: PRINT "³ ³"
LOCATE 12, column: PRINT "³ÍÍͳ"
LOCATE 13, column: PRINT "³ ³"
LOCATE 14, column: PRINT "ÔÍÍ;"
NEXT
'The following draws the A-E labels for each die
character = 64 'ascii value of one less than "A"
column.ii = 45 'location across the screen
COLOR brown 'brown labels
FOR y = 1 TO 5 'a-e = 5
column.ii = column.ii + 6
character = character + 1
LOCATE 11, column.ii: PRINT CHR$(character)
NEXT
'The following draws the labels and names of those playing
COLOR white: LOCATE 2, 2: PRINT "PLAYER 1: "
COLOR green: LOCATE 3, 2: PRINT player1$
COLOR cyan: LOCATE 5, 2: PRINT "SCORE: "
x1% = 105
lplacement = 43
IF numplayers > 1 THEN
COLOR white: LOCATE 2, 15: PRINT "PLAYER 2: "
COLOR red: LOCATE 3, 15: PRINT player2$
COLOR cyan: LOCATE 5, 15: PRINT "SCORE: "
x1% = 205
lplacement = 50
END IF
IF numplayers > 2 THEN
COLOR white: LOCATE 2, 27: PRINT "PLAYER 3: "
COLOR brown: LOCATE 3, 27: PRINT player3$
COLOR cyan: LOCATE 5, 27: PRINT "SCORE: "
x1% = 305
lplacement = 57
END IF
IF numplayers > 3 THEN
COLOR white: LOCATE 2, 40: PRINT "PLAYER 4: "
COLOR yellow: LOCATE 3, 40: PRINT player4$
COLOR cyan: LOCATE 5, 40: PRINT "SCORE: "
x1% = 405
lplacement = 62
END IF
'prints dashes in category score positions so that the users can
'see which categories they can score into
FOR i = 9 TO 14
FOR j = 26 TO 38 STEP 4: LOCATE i, j + 1: PRINT "-": NEXT
NEXT
'sums (1-6)
FOR k = 26 TO 38 STEP 4: LOCATE 17, k + 1: PRINT "-": NEXT
'lower half of categories
FOR l = 19 TO 25
FOR m = 26 TO 38 STEP 4: LOCATE l, m + 1: PRINT "-": NEXT
NEXT
'individual scoring category labels for each player
COLOR 10: LOCATE 7, 31: PRINT "Player"
COLOR skyblue: LOCATE 7, 3: PRINT "Scoring Categories"
COLOR red: LOCATE 24, 50: PRINT "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
COLOR green: LOCATE 8, 27: PRINT "1"
LOCATE 8, 31: PRINT "2"
LOCATE 8, 35: PRINT "3"
LOCATE 8, 39: PRINT "4"
COLOR white
'The following case structure blacks out the labels of those not
'playing. If left alone, these labels would remain behind the logo.
SELECT CASE numplayers
CASE IS = 1
LINE (102, 2)-(397, 80), 0, BF
CASE IS = 2
LINE (202, 2)-(397, 80), 0, BF
CASE IS = 3
LINE (302, 2)-(397, 80), 0, BF
CASE IS = 4
'nothing needed for 4 players
END SELECT
'middle screen separator
LINE (365, 90)-(365, 400), cyan, B
LINE (367, 90)-(367, 400), red, B
LINE (369, 90)-(369, 400), cyan, B
'player info separator from game area
LINE (1, 83)-(630, 83), gray, B
'bottom screen separator top
LINE (1, 412)-(630, 412), gray, B
'bottom screen separator bottom
LINE (1, 470)-(630, 470), gray, B
'the player turn indicator
LOCATE 23, 50: COLOR gray: PRINT "Player Turn: "
'print initial total scores of those playing
COLOR white
LOCATE 5, 8: PRINT scores(1, 15)
IF numplayers > 1 THEN : LOCATE 5, 21: PRINT scores(2, 15)
IF numplayers > 2 THEN : LOCATE 5, 33: PRINT scores(3, 15)
IF numplayers > 3 THEN : LOCATE 5, 46: PRINT scores(4, 15)
END SUB
'--------------------------------------------------------------------------
'
' Centers a string and prints it given the row it will be placed on
' by the row% (integer) parameter
'
'--------------------------------------------------------------------------
SUB center (row%, text$)
col = maxcol \ 2
LOCATE row, col - (LEN(text$) / 2 + .5)
PRINT text$;
END SUB
'--------------------------------------------------------------------------
'
' Asks the user if they are sure they want to quit all player's games
'
'--------------------------------------------------------------------------
FUNCTION certain$ (really.quit$)
blank (28)
LOCATE 25, 50: PRINT " "
COLOR white: LOCATE 28, 30: PRINT "Do you really want to quit? "
COLOR white: LOCATE 28, 58: INPUT "", really.quit$
blank (28)
certain$ = really.quit$
END FUNCTION
'--------------------------------------------------------------------------
'
' Accumulates counters for each possible value based on the current value
' of the five dice. Rolling 1 5 5 6 4 would give the 1 counter a value of
' 1, the 5 counter a value of 2, the six counter a value of 1, etc.
'
'--------------------------------------------------------------------------
SUB check.dice
'$STATIC
DIM dice(5) AS INTEGER
dice(1) = die1: dice(2) = die2: dice(3) = die3: dice(4) = die4: dice(5) = die5
FOR i = 1 TO 5
SELECT CASE dice(i)
CASE IS = 1
one.counter = one.counter + 1
CASE IS = 2
two.counter = two.counter + 1
CASE IS = 3
three.counter = three.counter + 1
CASE IS = 4
four.counter = four.counter + 1
CASE IS = 5
five.counter = five.counter + 1
CASE IS = 6
six.counter = six.counter + 1
END SELECT
NEXT
'done with temp array so reinitialize its indices to zero
ERASE dice
END SUB
'--------------------------------------------------------------------------
'
' Draws a rotating square on screen the name input screen (sub users)
'
'--------------------------------------------------------------------------
SUB graphic
Move$ = "D75 L65" 'move cursor w/o drawing anything
Object1$ = "R100 D100 L100 U100" 'a square defined
DRAW "B X" + VARPTR$(Move$) 'move cursor again
DRAW "C6 X" + VARPTR$(Object1$) 'frame defined square in color ('C')
'brown ('6')
DRAW "TA10 X" + VARPTR$(Object1$) 'rotate ('TA') # degrees ('10-60')
DRAW "TA20 X" + VARPTR$(Object1$) 'and draw the new object pointed to
DRAW "TA30 X" + VARPTR$(Object1$) 'by the string pointer 'VARPTR$'
DRAW "TA40 X" + VARPTR$(Object1$)
DRAW "TA50 X" + VARPTR$(Object1$)
DRAW "TA60 X" + VARPTR$(Object1$)
END SUB
'--------------------------------------------------------------------------
'
' This procedure sets up the random sequence of red rectangles for a
' "fill" effect using GET and PUT
'
'--------------------------------------------------------------------------
SUB intro
'initialize the array to hold 500 integer values
DIM box%(1 TO 500)
'set up the 3x3 pixel rectangle values
a1% = 1: a2% = 3: b1% = 1: b2% = 3
'draw a rectangle using these values
LINE (a1, b1)-(a2, b2), red, BF
'take a picture of values in array
GET (a1, b1)-(a2, b2), box%
'loop takes values from get and puts them onto the screen somewhere between
'pixels 1 and 629 across and 1 and 469 down. The screen resolution this is
'made for is 640 x 480 pixels. However, the entire screen can't be used since
'the rectangles cannot be displayed with a portion of it off the screen and
'a portion on. Since, the length is only 3 pixels, this problem doesn't come
'about.
DO: LOCATE 13, 38: PRINT "Yahtzee"
LOCATE 14, 35: PRINT "Brian Hammond"
COLOR gray: LOCATE 17, 29: PRINT "Press any key to continue": COLOR white
PUT (a1, b1), box%, AND
a1 = RND * 629: b1 = RND * 469
PUT (a1, b1), box%
LOOP WHILE INKEY$ = "": CLS
END SUB
'--------------------------------------------------------------------------
'
' This procedure draws the Yahtzee logo on the board. The passed parameters
' of lrepeat, x1, x2, y1, y2, and lplacement determine the location of the
' logo based on the number of players. lrepeat = 8.
'
'--------------------------------------------------------------------------
SUB logo (lplacement, x1, y1, x2, y2)
FOR i = 1 TO lrepeat
'give the inner rectangles random colors (+ 1 to guard fom black)
rect.color = INT(RND * 15) + 1
'draw the rectangles
LINE (x1, y1)-(x2, y2), rect.color, B
'move coordinates so next rectangle is inside the previous one
x1 = x1 + 5: y1 = y1 + 5: x2 = x2 - 5: y2 = y2 - 5
NEXT
'reset original top,bottom, right coords.
y1 = 6: x2 = 625: y2 = 78
COLOR 15: LOCATE 3, lplacement%: PRINT "YAHTZEE"
END SUB
'--------------------------------------------------------------------------
'
' Prompts user for category to score into and based on counter values
' returned by check.dice, allows/disallows credit for the category. The
' players category score, total score, and sum score (if category < 7)
' are updated. Counters are reset @ the end of this sub.
'
' Refer to the main module for an explanation on the use of 999.
'
'--------------------------------------------------------------------------
SUB place.score (turn)
'prompt user for category to score into - label 10 used for errors,
'as in the user entered an invalid category and must repeat entry.
10
DO
blank (28): LOCATE 25, 50: PRINT " "
COLOR white: LOCATE 28, 30: INPUT "Score into which category? ", where$
LOOP UNTIL VAL(where$) > 0 AND VAL(where$) <= 13
where = VAL(where$)
SELECT CASE where
'****************************************************************************
' 1-6 = ones .. sixes
'****************************************************************************
CASE IS = 1
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
temp.counter = one.counter: whichlowcat = 1: GOSUB lowcat
CASE IS = 2
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
temp.counter = two.counter: whichlowcat = 2: GOSUB lowcat
CASE IS = 3
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
temp.counter = three.counter: whichlowcat = 3: GOSUB lowcat
CASE IS = 4
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
temp.counter = four.counter: whichlowcat = 4: GOSUB lowcat
CASE IS = 5
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
temp.counter = five.counter: whichlowcat = 5: GOSUB lowcat
CASE IS = 6
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
temp.counter = six.counter: whichlowcat = 6: GOSUB lowcat
'****************************************************************************
' 7 = three of a kind
'****************************************************************************
CASE IS = 7
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
IF one.counter > 2 OR two.counter > 2 OR three.counter > 2 OR four.counter > 2 OR five.counter > 2 OR six.counter > 2 THEN
scores(turn, 7) = (one.counter * 1) + (two.counter * 2) + (three.counter * 3) + (four.counter * 4) + (five.counter * 5) + (six.counter * 6)
ELSE
scores(turn, 7) = 0
END IF
CALL update.score(turn, 7)
'****************************************************************************
' 8 = four of a kind
'****************************************************************************
CASE IS = 8
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
IF one.counter > 3 OR two.counter > 3 OR three.counter > 3 OR four.counter > 3 OR five.counter > 3 OR six.counter > 3 THEN
scores(turn, 8) = (one.counter * 1) + (two.counter * 2) + (three.counter * 3) + (four.counter * 4) + (five.counter * 5) + (six.counter * 6)
ELSE
scores(turn, 8) = 0
END IF
CALL update.score(turn, 8)
'****************************************************************************
' 9 = full house
'****************************************************************************
CASE IS = 9
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
'the checks for the pairs of a full house
IF one.counter = 2 THEN pair = 1
IF two.counter = 2 THEN pair = 1
IF three.counter = 2 THEN pair = 1
IF four.counter = 2 THEN pair = 1
IF five.counter = 2 THEN pair = 1
IF six.counter = 2 THEN pair = 1
'check for the three of a kind in a full house
IF one.counter = 3 THEN triple = 1
IF two.counter = 3 THEN triple = 1
IF three.counter = 3 THEN triple = 1
IF four.counter = 3 THEN triple = 1
IF five.counter = 3 THEN triple = 1
IF six.counter = 3 THEN triple = 1
IF pair = 1 AND triple = 1 THEN
scores(turn, 9) = str3
ELSE
scores(turn, 9) = 0
END IF
CALL update.score(turn, 9)
'****************************************************************************
' 10 = four straight
'****************************************************************************
CASE IS = 10
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
'1234 check
IF one.counter > 0 AND two.counter > 0 AND three.counter > 0 AND four.counter > 0 THEN
scores(turn, 10) = str1
'2345 check
ELSEIF two.counter > 0 AND three.counter > 0 AND four.counter > 0 AND five.counter > 0 THEN
scores(turn, 10) = str1
'3456 check
ELSEIF three.counter > 0 AND four.counter > 0 AND five.counter > 0 AND six.counter > 0 THEN
scores(turn, 10) = str1
ELSE
scores(turn, 10) = 0
END IF
CALL update.score(turn, 10)
'****************************************************************************
' 11 = five straight
'****************************************************************************
CASE IS = 11
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
'12345 check
IF one.counter > 0 AND two.counter > 0 AND three.counter > 0 AND four.counter > 0 AND five.counter > 0 THEN
scores(turn, 11) = str2
'23456
ELSEIF two.counter > 0 AND three.counter > 0 AND four.counter > 0 AND five.counter > 0 AND six.counter > 0 THEN
scores(turn, 11) = str2
ELSE
scores(turn, 11) = 0
END IF
CALL update.score(turn, 11)
'****************************************************************************
' 12 = yahtzee
'****************************************************************************
CASE IS = 12
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
IF one.counter > 4 OR two.counter > 4 OR three.counter > 4 OR four.counter > 4 OR five.counter > 4 OR six.counter > 4 THEN
scores(turn, 16) = scores(turn, 16) + 1
IF scores(turn, 16) > 0 THEN
yah.score = 50
ELSEIF scores(turn, 16) > 1 THEN
yah.score = 100
END IF
CALL yahtzee.scored
ELSE
scores(turn, 12) = 0
END IF
CALL update.score(turn, 12)
'****************************************************************************
' 13 = potpourri
'****************************************************************************
CASE IS = 13
GOSUB errorcheck: IF duplicate = 1 THEN GOTO 10
GOSUB check.yahtzee
scores(turn, 13) = die1 + die2 + die3 + die4 + die5 + die6
CALL update.score(turn, 13)
END SELECT
'****************************************************************************
' end of category case
'****************************************************************************
'go to next player
turn = turn + 1
IF numplayers = 1 THEN turn = 1
IF numplayers = 2 AND turn > 2 THEN turn = 1
IF numplayers = 3 AND turn > 3 THEN turn = 1
IF turn > 4 THEN turn = 1
CALL player.turn(turn)
'reset counters for next roll
one.counter = 0: two.counter = 0: three.counter = 0
four.counter = 0: five.counter = 0: six.counter = 0
CALL blank(28)
'this counter quits the game and calls sub winner when there are no more
'places to place a score, i.e. the game is over
quit.counter = quit.counter - 1
IF quit.counter <= 0 THEN changes$ = "Q": CALL show.winner
'exit since following subroutines are called specifically from above and
'would be called and extra time if exit sub wasn't here.
EXIT SUB
'checks to see if player is trying to overwrite an old score. If messaging
'is on, and the player is overwriting, display a message and then ask for a
'new category to score into. If messaging is off, just return control to
'input.
errorcheck:
IF where = 12 THEN
'initialized to zero, if not zero now... don't score there
IF scores(turn, 12) <> 0 THEN
duplicate = 1
GOTO 75
ELSE
duplicate = 0
GOTO 75
END IF
ELSEIF scores(turn, where) = 999 THEN
duplicate = 0
ELSE
duplicate = 1
END IF
75 RETURN
'runs the scoring for categories 1-6
lowcat:
scores(turn, whichlowcat) = temp.counter * whichlowcat
CALL update.score(turn, whichlowcat)
RETURN
'checks to see if a yahtzee is being scored.
check.yahtzee:
IF one.counter > 4 OR two.counter > 4 OR three.counter > 4 OR four.counter > 4 OR five.counter > 4 OR six.counter > 4 THEN
IF scores(turn, 12) = 0 THEN GOTO 90
scores(turn, 16) = scores(turn, 16) + 1
CALL yahtzee.scored
END IF
90 RETURN
END SUB
'--------------------------------------------------------------------------
'
' This is the main loop which handles user input on what action
' is to be taken. Valid input includes:
'
' 1. Any combination of A,B,C,D,E to roll those dice
' 2. Q to quit
' 3. ENTER to score the roll
'
'--------------------------------------------------------------------------
SUB play.game
DO
20 'label to return to when roll # > 3
IF quit.counter <= 0 THEN EXIT SUB
'increment roll number after each loop
roll.number = roll.number + 1
'Roll Handler -------------------------------------------------------------
'Each player's 1st roll is automatically taken rolling all 5 dice
IF roll.number = 1 THEN
die1 = roll(n): die2 = roll(n)
die3 = roll(n): die4 = roll(n): die5 = roll(n)
GOSUB display.dice: GOTO 20
END IF
'--------------------------------------------------------------------------
'The 2 extra rerolls handler
IF roll.number > 1 AND roll.number <= 3 THEN
COLOR white: LOCATE 25, 50: LINE INPUT "Changes? "; changes$
changes$ = LEFT$(UCASE$(changes$), 5)
'if any of the following letters are found in what the user entered,
'then set a flag for the die in question as 1, i.e. roll that die
IF INSTR(changes$, "A") THEN a = 1 ELSE a = 0
IF INSTR(changes$, "B") THEN B = 1 ELSE B = 0
IF INSTR(changes$, "C") THEN c = 1 ELSE c = 0
IF INSTR(changes$, "D") THEN d = 1 ELSE d = 0
IF INSTR(changes$, "E") THEN e = 1 ELSE e = 0
'the following determines which dice to roll and calls the function
'roll(die) to roll them.
IF a = 1 THEN die1 = roll(n)
IF B = 1 THEN die2 = roll(n)
IF c = 1 THEN die3 = roll(n)
IF d = 1 THEN die4 = roll(n)
IF e = 1 THEN die5 = roll(n)
'If changes$ = a blank, as in enter was hit, the player wants to score roll
IF changes$ = "" THEN
GOSUB display.dice: CALL check.dice: CALL place.score(turn)
roll.number = 0: GOTO 20
END IF
'if "Q" was entered, user(s) wants to quit all player's games
'ask for certainty, then quit or return here if not quitting
IF INSTR(changes$, "Q") THEN
really.quit$ = certain$(really.quit$)
really.quit$ = UCASE$(really.quit$)
IF INSTR(really.quit$, "Y") THEN EXIT DO
IF roll.number > 1 THEN roll.number = roll.number - 1
LOCATE 25, 59: PRINT " ": GOTO 20
END IF
'clear last changes$ value entered
LOCATE 25, 59: PRINT " "
'the following tells user what went wrong with what they entered for changes
'note: checks to see if messaging is enabled first.
IF INSTR(changes$, "A") = 0 AND INSTR(changes$, "B") = 0 AND INSTR(changes$, "C") = 0 AND INSTR(changes$, "D") = 0 AND INSTR(changes$, "E") = 0 AND INSTR(changes$, "Q") = 0 THEN
roll.number = roll.number - 1
GOTO 20
END IF
'end of if roll.number > 1 and < 3
GOSUB display.dice
END IF
'--------------------------------------------------------------------------
'If Player has used up both additional rolls, jump to score the current dice
'values
IF roll.number > 3 THEN
CALL check.dice
CALL place.score(turn)
roll.number = 0: GOTO 20
END IF
LOOP
'skip subroutine being called upon exiting loop
EXIT SUB
'subroutine: display dice values returned by function roll
display.dice:
COLOR white:
LOCATE 13, 50: PRINT die1
LOCATE 13, 56: PRINT die2
LOCATE 13, 62: PRINT die3
LOCATE 13, 68: PRINT die4
LOCATE 13, 74: PRINT die5
RETURN
END SUB
'--------------------------------------------------------------------------
'
' Shows users who goes by 1) a blue box around the player's name on top
' 2) the name near the CHANGES? prompt
' 3) the column header of category scores of
' the player's turn in yellow
'
'--------------------------------------------------------------------------
SUB player.turn (turn)
'first indicator
SELECT CASE turn
CASE IS = 1
SELECT CASE numplayers
CASE IS = 1
LINE (2, 2)-(97, 80), skyblue, B 'frame 1
CASE IS = 2
LINE (102, 2)-(197, 80), black, B 'erase 2
LINE (2, 2)-(97, 80), skyblue, B 'frame 1
CASE IS = 3
LINE (202, 2)-(297, 80), black, B 'erase 3
LINE (2, 2)-(97, 80), skyblue, B 'frame 1
CASE IS = 4
LINE (302, 2)-(397, 80), black, B 'erase 4
LINE (2, 2)-(97, 80), skyblue, B 'frame 1
END SELECT
CASE IS = 2
LINE (2, 2)-(97, 80), black, B 'erase 1
LINE (102, 2)-(197, 80), skyblue, B
CASE IS = 3
LINE (2, 2)-(97, 80), black, B 'erase 1
LINE (102, 2)-(197, 80), black, B 'erase 2
LINE (202, 2)-(297, 80), skyblue, B
CASE IS = 4
LINE (2, 2)-(97, 80), black, B 'erase 1
LINE (102, 2)-(197, 80), black, B 'erase 2
LINE (202, 2)-(297, 80), black, B 'erase 3
LINE (302, 2)-(397, 80), skyblue, B
END SELECT
'second indicator
COLOR white
SELECT CASE turn
CASE IS = 1
x$ = SPACE$(10): LOCATE 23, 63: PRINT x$
LOCATE 23, 63: PRINT player1$
CASE IS = 2
x$ = SPACE$(10): LOCATE 23, 63: PRINT x$
LOCATE 23, 63: PRINT player2$
CASE IS = 3
x$ = SPACE$(10): LOCATE 23, 63: PRINT x$
LOCATE 23, 63: PRINT player3$
CASE IS = 4
x$ = SPACE$(10): LOCATE 23, 63: PRINT x$
LOCATE 23, 63: PRINT player4$
END SELECT
'third indicator
IF turn = 1 THEN
COLOR yellow: LOCATE 8, 27: PRINT "1"
ELSE
COLOR green: LOCATE 8, 27: PRINT "1"
END IF
IF turn = 2 THEN
COLOR yellow: LOCATE 8, 31: PRINT "2"
ELSE
COLOR green: LOCATE 8, 31: PRINT "2"
END IF
IF turn = 3 THEN
COLOR yellow: LOCATE 8, 35: PRINT "3"
ELSE
COLOR green: LOCATE 8, 35: PRINT "3"
END IF
IF turn = 4 THEN
COLOR yellow: LOCATE 8, 39: PRINT "4"
ELSE
COLOR green: LOCATE 8, 39: PRINT "4"
END IF
END SUB
'--------------------------------------------------------------------------
'
' This function rolls a dice returning the value rolled.
'
'--------------------------------------------------------------------------
FUNCTION roll (n)
'roll die and give the function a return value
RANDOMIZE TIMER: die = INT(RND * 6) + 1: roll = die
END FUNCTION
'--------------------------------------------------------------------------
'
' Shows users who winner is based on total score. If only one player,
' this tells that player the game is over. called if no user quits
' before the end of the game.
'
'--------------------------------------------------------------------------
SUB show.winner
'erase player turn... goes back to player 1 when game is over.
LOCATE 23, 63: PRINT " "
'make category player highlight green
COLOR green: LOCATE 8, 27: PRINT "1"
'erase all boxes on top
LINE (2, 2)-(97, 80), black, B 'erase 1
IF numplayers > 1 THEN
LINE (102, 2)-(197, 80), black, B 'erase 2
END IF
IF numplayers > 2 THEN
LINE (202, 2)-(297, 80), black, B 'erase 3
END IF
IF numplayers > 3 THEN
LINE (302, 2)-(397, 80), black, B 'erase 4
END IF
extent = 68: x$ = SPACE$(1): r = 2
FOR j = 1 TO 33
COLOR yellow: LOCATE 28, extent: PRINT "GAME OVER!"
LOCATE 28, extent + 10: PRINT " "
extent = extent - 1: r = r + 1
NEXT
SLEEP 2&
IF numplayers > 1 THEN
COLOR white: center 28, "The winner is... ": SLEEP 2&
IF scores(1, 15) < scores(2, 15) THEN
IF scores(2, 15) > scores(3, 15) THEN
IF scores(2, 15) > scores(4, 15) THEN
winner$ = player2$
END IF
ELSEIF scores(2, 15) < scores(3, 15) THEN
IF scores(3, 15) > scores(4, 15) THEN
winner$ = player3$
ELSEIF scores(3, 15) < scores(4, 15) THEN
winner$ = player4$
END IF
END IF
ELSEIF scores(1, 15) > scores(2, 15) THEN
IF scores(1, 15) > scores(3, 15) THEN
IF scores(1, 15) > scores(4, 15) THEN
winner$ = player1$
END IF
END IF
ELSE
winner$ = "No one wins because you all played so poorly."
END IF
FOR i = 1 TO 50: FOR j = 1 TO 9: COLOR j: LOCATE 28, 48: PRINT winner$: NEXT: NEXT
DO: LOOP UNTIL INKEY$ <> ""
END IF
END SUB
'--------------------------------------------------------------------------
'
' Takes as parameters player # and category and updates the category score
' after accessing the correct position in the 4-D "scores" array.
' row.score = row position of each category
' column.score = column position of category based on which player
' total.column = total score column position based on player
' total.score = score displayed at the top of the screen
'
'--------------------------------------------------------------------------
SUB update.score (turn, category)
'this case determines which row the score will be displayed on, based on
'which category is being updated
IF category < 7 THEN row.score = category + 8 ELSE row.score = category + 12
'this case determines which column the score to be updated will be displayed
'in based on which player's turn it currently is.
SELECT CASE turn
CASE IS = 1
column.score = 26
CASE IS = 2
column.score = 30
CASE IS = 3
column.score = 34
CASE IS = 4
column.score = 38
END SELECT
'update sum (1-6) if necc.
IF category < 7 THEN
FOR k = 1 TO 6
IF scores(turn, k) <> 999 THEN
sum = sum + scores(turn, k)
END IF
NEXT
scores(turn, 14) = sum
END IF
'bonus for a sum (1-6) greater than 63
IF scores(turn, 14) > 63 THEN
total.score = total.score + 35
END IF
'check for yahtzees to be added in to the total score
IF scores(turn, 16) > 0 AND scores(turn, 12) = 0 THEN
scores(turn, 12) = scores(turn, 12) + 50
ELSEIF scores(turn, 16) > 1 THEN
scores(turn, 12) = (scores(turn, 16) * 100) - 50
END IF
'show the yahtzee category if something was scored there
IF scores(turn, 12) <> 0 THEN
IF scores(turn, 12) > 99 THEN column.score = column.score - 1
COLOR white: LOCATE 24, column.score - 1: PRINT scores(turn, 12)
IF scores(turn, 12) > 99 THEN column.score = column.score + 1
END IF
'always update the total score (top [1-6] + bottom [7-13])
FOR i = 7 TO 13:
IF scores(turn, i) <> 999 THEN
total.score = total.score + scores(turn, i)
END IF
NEXT
'total score = top sum + bottom sum or rather [scores(turn,14) + total.score]
scores(turn, 15) = total.score + scores(turn, 14)
'print updated category score
IF scores(turn, category) > 9 THEN column.score = column.score - 1
COLOR white: LOCATE row.score, column.score: PRINT scores(turn, category)
IF scores(turn, category) > 9 THEN column.score = column.score + 1
'print sum if necc.
IF scores(turn, 14) > 9 THEN column.score = column.score - 1
IF scores(turn, 14) > 99 THEN column.score = column.score - 1
IF category < 7 THEN : LOCATE 17, column.score: PRINT scores(turn, 14)
IF scores(turn, 14) > 9 THEN column.score = column.score + 1
IF scores(turn, 14) > 99 THEN column.score = column.score + 1
'print total.scores of those playing
LOCATE 5, 8: PRINT scores(1, 15)
IF numplayers > 1 THEN : LOCATE 5, 21: PRINT scores(2, 15)
IF numplayers > 2 THEN : LOCATE 5, 33: PRINT scores(3, 15)
IF numplayers > 3 THEN : LOCATE 5, 46: PRINT scores(4, 15)
'reset temps for next usage
sum = 0: total.score = 0
'flash logo to show score has been updated
x1 = numplayers * 100 + 5: x2 = 625: y1 = 6: y2 = 78
CALL logo(lplacement, x1, y1, x2, y2)
END SUB
'--------------------------------------------------------------------------
'
' This procedure asks the user(s) how many people are playing, and then
' asks each player for their name.
'
'--------------------------------------------------------------------------
SUB user.input (numplayers%, player1$, player2$, player3$, player4$)
'number playing
DO
LOCATE 5, 24: INPUT "How many players (1 to 4)"; num$
LOOP UNTIL VAL(num$) >= 1 AND VAL(num$) <= 4
numplayers = VAL(num$)
COLOR black: LOCATE 5, 24: PRINT " "
'names
COLOR green
LOCATE 5, 24
LINE INPUT "Name of Player 1 <Player 1>: "; player1$
IF player1$ = "" THEN
player1$ = "Player 1"
ELSE
player1$ = LEFT$(player1$, 9)
END IF
COLOR red
IF numplayers > 1 THEN
LOCATE 7, 24
LINE INPUT "Name of Player 2 <Player 2>: "; player2$
IF player2$ = "" THEN
player2$ = "Player 2"
ELSE
player2$ = LEFT$(player2$, 10)
END IF
END IF
COLOR brown
IF numplayers > 2 THEN
LOCATE 9, 24
LINE INPUT "Name of Player 3 <Player 3>: "; player3$
IF player3$ = "" THEN
player3$ = "Player 3"
ELSE
player3$ = LEFT$(player3$, 10)
END IF
END IF
COLOR yellow
IF numplayers > 3 THEN
LOCATE 11, 24
LINE INPUT "Name of Player 4 <Player 4>: "; player4$
IF player4$ = "" THEN
player4$ = "Player 4"
ELSE
player4$ = LEFT$(player4$, 10)
END IF
END IF
'make all user names uppercase
player1$ = UCASE$(player1$)
player2$ = UCASE$(player2$)
player3$ = UCASE$(player3$)
player4$ = UCASE$(player4$)
'reset color to white
COLOR white
END SUB
'--------------------------------------------------------------------------
'
' Flashes Yahtzee! whenever a player gets a yahtzee.
'
'--------------------------------------------------------------------------
SUB yahtzee.scored
blank (28): x$ = SPACE$(1): r = 3: extent = 67
FOR h = 1 TO 10
FOR i = 1 TO extent
COLOR r: LOCATE 28, i + 1: PRINT "Yahtzee!"
LOCATE 28, i: PRINT x$
NEXT
r = r + 1: extent = extent - 9
NEXT
SLEEP 2&
END SUB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment