This program implements the dice game Yahtzee for one to four players on a 15-row scorecard. Each player takes up to three throws per turn, choosing which of the five dice (labelled A–E) to re-roll by entering a string of letter choices. The scorecard layout is encoded in the single long string Z$ at line 110, sliced into 10-character fields for display. Scores are stored in a two-dimensional array P(PLYRS,15), where column 15 holds each player’s running total and columns 7–8 track the upper-section subtotal and bonus.
Program Analysis
Program Structure
The code is divided into clearly separated routines accessed via GOSUB:
- Lines 10–110 – Global constants and data: player-name string
T$, layout stringZ$, display offsetsP1,LE,P2,P3, bonus thresholdPLUS. - Lines 800–990 – Setup: player-count input, array initialisation, scorecard draw (
GOSUB 8000). - Lines 1000–2340 – Main game loop: throw loop (up to 3), option selection, scoring dispatch.
- Lines 3000–3160 – Score recording, player cycling, end-of-game winner display with a flashing loop.
- Lines 7010–7100 – Winner determination subroutine.
- Lines 8010–8120 – Screen draw subroutine (scorecard labels + player headers).
- Lines 9010–9110 – Dice-roll subroutine; only dice whose letter appears in
A$are re-rolled. - Lines 9210–9260 – Count-array builder (
DIM C(6), tally of each face value). - Lines 9310–9940 – Individual scoring subroutines: Yacht (5-of-a-kind, 50pts), 4-of-a-kind, Full House / High Straight, Big Straight, Little Straight, Choice (sum all), upper-section numbers.
- Lines 9950–9970 –
CLEAR/SAVE/RUNauto-restart block.
Scorecard Layout Encoding
The string Z$ at line 110 is exactly 150 characters long (15 rows × 10 characters each). The subroutine at line 8010 slices it with Z$(PS TO PF) using computed offsets and prints each slice at the corresponding screen row, providing the entire left-hand label column of the scorecard without any individual PRINT statements per row. The constant LE=10 controls field width.
Display Coordinate System
Column positions for each player’s scores are computed from three constants:
P1=1– base left marginP2=5– per-player column strideP3=12– right offset from left margin to score columns
The expression (PL-1)*P2+P1+P3 therefore yields column 13 for player 1, 18 for player 2, etc., giving a compact multi-column scorecard for up to four players.
Score Array Layout
| Index | Contents |
|---|---|
| 1–6 | Upper section (ones through sixes); initialised to -1 (unscored) |
| 7 | Upper subtotal (accumulates as entries are made) |
| 8 | Bonus flag (0 = not awarded, 50 = awarded) |
| 9–14 | Lower section categories (Choice, Full/High Straight, 4-of-a-kind, Little Straight, Big Straight, Yacht) |
| 15 | Grand total (running sum) |
Unscored cells are initialised to -1 so that a score of 0 (a valid outcome) is distinguishable from an empty slot. The guard at line 2060 (IF P(PL,OP)>=0 THEN GOTO 2010) prevents overwriting an already-scored category.
Option Numbering Offset
The user enters options 1–12. Because the score array reserves slots 7 and 8 for the subtotal and bonus (not directly selectable), line 2052 adjusts: IF OP>6 THEN LET OP=OP+2. This maps user choices 7–12 to array indices 9–14, skipping the internal slots cleanly.
Dice Re-roll Mechanic
Dice are labelled A–E via T$="ABCDE". The player types a string of letters for dice to keep (or re-roll — the logic at lines 9010–9070 re-rolls any die whose letter appears in A$). On the first throw, A$ is pre-set to "ABCDE" at line 1006 so all five dice are always rolled. Subsequent throws prompt the player to enter letters.
Scoring Subroutines
All scoring routines rely on the count array C(6) built by the subroutine at line 9210. The count array is declared with DIM C(6) inside the subroutine, which resets it to zero on each call — a neat initialisation trick. Key scoring logic:
- Yacht (line 9310): checks for any
C(N)=5; awards 50 points. - 4-of-a-kind (line 9410): checks
C(N)>=4, then sums all dice. - Little Straight (line 9510): calls
GOSUB 9800to count zero-valued slots (CT); awards sum of dice if exactly 4 distinct values present (CT=4 gaps in C means… see anomaly below). - Full House / High Straight (line 9610): awards 30 if
C(6)=0andCT=1(one face missing, no sixes — i.e. 1–5 straight or full house heuristic). - Big Straight (line 9710): awards 30 if
C(1)=0andCT=1(2–6 straight).
Notable Techniques
FAST/SLOW(lines 900, 990) bracket the array initialisation and screen setup for speed.- The winner-display loop (lines 3090–3160) uses two short
FOR…NEXTdelay loops and alternates the winner name with a blank to create a flashing effect withoutPAUSE. RANDat line 832 seeds the random number generator from the real-time clock, ensuring different dice sequences each game.- The
SAVE "1025%4"at line 9960 uses an inverse-video character in the filename as an auto-run flag.
Bugs and Anomalies
- Missing
GOSUB 7000: Line 3080 callsGOSUB 7000but the subroutine begins at line 7010. This is a standard technique of jumping past the first line of a subroutine via a non-existent entry point — here it works because there is no executable code at line 7000 itself and execution falls through to 7010. - Little Straight scoring: The subroutine at 9510 checks
CT=4(four empty slots in C), which would mean only two distinct values are present — the opposite of a straight. A genuine 1–2–3–4 straight would haveCT=2. This appears to be a logic error; the intended check was likelyCT=2. - Full House / High Straight conflation: Option 8 is labelled “FULL/HS” (Full House / High Straight) but the scoring subroutine only checks for a 1–5 straight (no sixes, one missing value). A genuine full house (e.g. three 2s and two 5s) would also give
CT=2, notCT=1, and would not be caught. - Grand total double-counting: The upper-section bonus (50 pts) is added to
P(PL,15)at line 2150, and each scored option also adds toP(PL,15)at line 3012. However, the upper subtotal (slot 7) is also added at line 3012 when the player nominates an upper-section option, meaning the upper-section points are counted twice in the grand total (once via slot 7 and once via slots 1–6). A$as keep-or-reroll ambiguity: Lines 1006 and 9040–9050 re-roll dice whose letters appear inA$, but the prompt at line 1010 says “CHOOSE” with no indication of whether the player should enter dice to keep or dice to re-roll.
Content
Source Code
10 LET T$="ABCDE"
20 DIM H(5)
70 LET P1=1
72 LET LE=10
80 LET P2=5
90 LET P3=12
100 LET PLUS=60
110 LET Z$="1 ONES---2 TWOS---3 THREES 4 FOURS--5 FIVES--6 SIXES--*SUB TOTAL**BONUS***7 CHOICE-8 FULL/HS9 4/KIND-10 LTL/ST-11 BIG/ST-12 YACHT--***TOTAL**"
800 CLS
802 PRINT AT 10,10;"YACHTZEE"
810 PRINT AT 12,1;"HOW MANY PLAYERS ? (1-4)"
820 INPUT PLYRS
830 IF PLYRS<1 OR PLYRS>4 THEN GOTO 800
832 RAND
840 CLS
900 FAST
902 LET NUMG=0
910 LET PL=1
920 DIM P(PLYRS,15)
930 FOR N=1 TO PLYRS
940 FOR M=1 TO 14
942 IF M=7 OR M=8 THEN GOTO 960
950 LET P(N,M)=-1
960 NEXT M
970 NEXT N
980 GOSUB 8000
990 SLOW
\n1000 LET TURN=0
\n1002 PRINT AT 18,1;"PLAYER ";PL
\n1006 LET A$="ABCDE"
\n1008 GOTO 1022
\n1010 PRINT AT 20,0;"CHOOSE"
\n1012 INPUT A$
\n1014 PRINT AT 20,0;" "
\n1020 IF A$="" THEN GOTO 2000
\n1022 PRINT AT 18,10;"THROW ";TURN+1
\n1030 GOSUB 9000
\n1040 LET TURN=TURN+1
\n1050 IF TURN<3 THEN GOTO 1010
\n2000 GOSUB 9200
\n2010 PRINT AT 20,0;"OPTION ?"
\n2012 PRINT AT 21,0;"(1-12)"
\n2020 INPUT OP
\n2030 PRINT AT 20,0;" "
\n2032 PRINT AT 21,0;" "
\n2050 IF OP<1 OR OP>12 THEN GOTO 2010
\n2052 IF OP>6 THEN LET OP=OP+2
\n2060 IF P(PL,OP)>=0 THEN GOTO 2010
\n2070 LET PTS=0
\n2080 LET FLAG=0
\n2090 IF OP>6 THEN GOTO 2200
\n2100 GOSUB 9900
\n2110 LET P(PL,7)=P(PL,7)+PTS
\n2112 PRINT AT 7,(PL-1)*P2+P1+P3;P(PL,7)
\n2120 IF P(PL,7)<PLUS THEN GOTO 3000
\n2122 IF P(PL,8)>0 THEN GOTO 3000
\n2130 LET P(PL,8)=50
\n2140 PRINT AT 8,(PL-1)*P2+P1+P3-1;"*50*"
\n2150 LET P(PL,15)=P(PL,15)+50
\n2200 IF OP<>9 THEN GOTO 2300
\n2210 FOR N=1 TO 5
\n2220 LET PTS=PTS+H(N)
\n2230 NEXT N
\n2240 GOTO 3000
\n2300 GOSUB 9200
\n2308 IF OP=10 THEN GOSUB 9500
\n2310 IF OP=11 THEN GOSUB 9400
\n2320 IF OP=12 THEN GOSUB 9600
\n2330 IF OP=13 THEN GOSUB 9700
\n2340 IF OP=14 THEN GOSUB 9300
\n3000 LET P(PL,OP)=PTS
\n3010 PRINT AT OP,(PL-1)*P2+P3+P1;PTS
\n3012 LET P(PL,15)=P(PL,15)+PTS
\n3014 PRINT AT 15,(PL-1)*P2+P1+P3;P(PL,15)
\n3020 LET PL=PL+1
\n3030 IF PL<(PLYRS+1) THEN GOTO 1000
\n3040 LET PL=1
\n3050 LET NUMG=NUMG+1
\n3060 IF NUMG<12 THEN GOTO 1000
\n3080 GOSUB 7000
\n3090 PRINT AT 18,8;WIN;" WINS "
\n3100 IF INKEY$<>"" THEN GOTO 800
\n3110 FOR N=1 TO 10
\n3120 NEXT N
\n3130 PRINT AT 18,8;" "
\n3140 FOR N=1 TO 3
\n3150 NEXT N
\n3160 GOTO 3090
\n7010 LET MAX=P(1,15)
\n7020 LET WIN=1
\n7030 IF PLYRS=1 THEN RETURN
\n7040 FOR N=2 TO PLYRS
\n7050 IF P(N,15)<=MAX THEN GOTO 7080
\n7060 LET MAX=P(N,15)
\n7070 LET WIN=N
\n7080 NEXT N
\n7100 RETURN
\n8010 FOR N=1 TO 15
\n8020 LET PS=(N-1)*LE+1
\n8030 LET PF=PS+LE-1
\n8040 PRINT AT N,1;Z$(PS TO PF)
\n8050 NEXT N
\n8060 FOR N=1 TO 5
\n8070 PRINT AT 20,(N-1)*3+10;T$(N)
\n8080 NEXT N
\n8090 FOR N=1 TO PLYRS
\n8100 PRINT AT 0,(N-1)*P2+P3;"*P";N;"*"
\n8110 NEXT N
\n8120 RETURN
\n9010 LET N1=LEN A$
\n9020 FOR N=1 TO N1
\n9030 FOR M=1 TO 5
\n9040 IF A$(N)<>T$(M) THEN GOTO 9060
\n9050 LET H(M)=INT (RND*6)+1
\n9060 NEXT M
\n9070 NEXT N
\n9080 FOR N=1 TO 5
\n9090 PRINT AT 21,(N-1)*3+10;H(N)
\n9100 NEXT N
\n9110 RETURN
\n9210 DIM C(6)
\n9230 FOR N=1 TO 5
\n9240 LET C(H(N))=C(H(N))+1
\n9250 NEXT N
\n9260 RETURN
\n9310 FOR N=1 TO 6
\n9320 IF C(N)=5 THEN LET PTS=50
\n9330 NEXT N
\n9340 RETURN
\n9410 FOR N=1 TO 6
\n9420 IF C(N)>=4 THEN LET FLAG=1
\n9440 NEXT N
\n9450 IF FLAG<>1 THEN RETURN
\n9460 FOR N=1 TO 5
\n9470 LET PTS=PTS+H(N)
\n9480 NEXT N
\n9490 RETURN
\n9510 GOSUB 9800
\n9520 IF CT<>4 THEN RETURN
\n9530 FOR N=1 TO 5
\n9540 LET PTS=PTS+H(N)
\n9550 NEXT N
\n9560 RETURN
\n9610 GOSUB 9800
\n9640 IF C(6)=0 AND CT=1 THEN LET PTS=30
\n9650 RETURN
\n9710 GOSUB 9800
\n9720 IF C(1)=0 AND CT=1 THEN LET PTS=30
\n9730 RETURN
\n9810 LET CT=0
\n9820 FOR N=1 TO 6
\n9830 IF C(N)=0 THEN LET CT=CT+1
\n9840 NEXT N
\n9850 RETURN
\n9910 FOR N=1 TO 5
\n9920 IF OP=H(N) THEN LET PTS=PTS+OP
\n9930 NEXT N
\n9940 RETURN
\n9950 CLEAR
\n9960 SAVE "1025%4"
\n9970 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
