Fun Golf

Products: Fun Golf
Date: 1983
Type: Program
Platform(s): TS 2068
Tags: Game

This program implements a top-down golf simulation for one or two players, spanning either a 9-hole or 18-hole course. Each hole is procedurally generated using RND to place fairways, rough, trees, bunkers, water hazards, and the green before computing par and yardage. Ball physics are handled with trigonometric calculations using COS and SIN against a clock-face direction system (0–12), with STEP scaling shots proportionally to hole yardage. Five user-defined graphics (UDGs A–E) are loaded from DATA at startup to represent terrain types and the ball. The program uses ATTR to read screen cell attributes for terrain detection, and ON ERR with RESET provides error recovery throughout.


Program Analysis

Program Structure

The program is organized into several well-separated subroutines and sections:

  • Lines 5000–5055: Initialization — UDG setup, course length, player count selection.
  • Lines 2005–2055: Hole generation subroutine (called via GO SUB 2000 — note line 2000 does not exist; execution falls through to 2005, a known technique).
  • Lines 5060–5225: Main game loop — stroke-by-stroke play for each player on each hole.
  • Lines 5230–5320: Scorecard display after each hole.
  • Lines 5400–5415: End-of-game prompt for replay.
  • Lines 7000–7040: Player input subroutine — direction and strength entry with validation.
  • Lines 7700–7715: Water hazard handling with penalty stroke.
  • Lines 8000–8020: UDG sprite data (5 characters, 8 bytes each).
  • Lines 9000–9020: Instructions display subroutine.
  • Lines 9900–9990: Error recovery and SAVE routine.

UDG Definitions

Five UDGs are defined at startup in lines 50055005 by READing from DATA lines 8000–8020 and POKEing into USR CHR$ I for I=65 to 69 (characters A–E). Their roles as used in PRINT statements are:

UDGEscapeRole
A (65)\aRough terrain
B (66)\bTrees
C (67)\cWater hazard
D (68)\dHole/flag
E (69)\eBall (flashes on-screen)

Hole Generation

The hole generation subroutine (lines 2005–2055) builds each hole procedurally using a sequence of PRINT AT loops:

  1. Line 2005: Fills the screen with UDG A (rough) using a loop of 176 iterations printing four characters at a time. The ON ERR GO TO 2005 guards against the scroll prompt at the bottom of the screen.
  2. Line 2010: Draws 3–6 tree clusters with meandering vertical paths using UDG B, sliced with ( TO 4+RND*8) string slicing for variable-width bands.
  3. Line 2015: Prints blank spaces in a grid pattern to represent the fairway (paper color creates the green attribute).
  4. Line 2020: Draws water hazards using UDG C with string slicing for width variation.
  5. Line 2025: Draws sand bunkers using blank spaces over multiple rows.
  6. Lines 2030–2035: Draws the green area and places the hole marker (UDG D).
  7. Lines 2040–2045: Sets ball starting position (BX, BY), determines par (3/4/5) and yardage via RND thresholds, then computes STEP as 28/YRD to scale shot distances.

Ball Physics and Movement

Direction is entered as a clock-face value (0–12). The constant V=PI/6 (line 5050) converts this to radians (each hour = 30°). Ball displacement per shot is calculated in lines 5115–5115:

  • P(P,1) = P(P,1) - ST*COS(D*V) — row movement (north-south)
  • P(P,2) = P(P,2) + ST*SIN(D*V) — column movement (east-west)

The effective shot distance is ST * STEP * 2, where STEP = 28/YRD, so longer holes yield proportionally shorter movement per unit of strength.

Terrain Detection via ATTR

After each shot, line 5150 reads the screen attribute at the new ball position with ATTR(P(P,1), P(P,2)) and stores it in P(P,3). Terrain types are identified by their attribute byte values:

ATTR valueTerrainEffect
36FairwayNormal shot distance
32Rough (UDG A)Distance reduced by 2–3×
4Trees (UDG B)Random direction bounce, distance ÷4
48Bunker60% chance of no movement
41WaterPenalty stroke, repositioned at water edge
100GreenNormal movement, reported as “ON THE GREEN”
97Hole (UDG D)Holed out — records score
39Two-ball overlapReplaced by other player’s terrain value

Player Data Array

Each player’s state is stored in row I of the 2D array P(PL,6) defined at line 5050:

IndexContents
P(I,1)Current ball row
P(I,2)Current ball column
P(I,3)Current terrain attribute
P(I,4)Cumulative course score vs par
P(I,5)Score for current hole vs par
P(I,6)Penalty stroke count for current hole

Status Bar Technique

Line 5010 constructs a reusable status bar string B$ using CHR$ 22 (AT), CHR$ 21 (PAPER), and CHR$ 0 to position output at the bottom of the screen, padded with 32 spaces to clear it. This avoids CLS and allows in-place message updates without disrupting the hole display.

Input Validation

Direction and strength inputs in lines 7020–7035 are validated for range (0–12 and 0–100 respectively). A strength of zero (IF NOT ST) returns the player to direction input, allowing shot correction. Values are rounded to two decimal places using INT(X*100+.5)/100, accommodating the program’s note that decimal inputs like 3.25 are valid.

Water Hazard Recovery

Line 7700 handles water landings. The loop at 7705–7710 scans leftward along the ball’s row until it finds a cell whose ATTR is not 41 (water), placing the ball at the water’s edge. A penalty stroke is added to P(P,6), and the terrain check resumes at line 5150.

Error Handling

ON ERR is used in three contexts: line 2005 catches scroll errors during screen fill, line 2042 catches runtime errors during hole play, and lines 9900–9930 form a recovery chain using ON ERR RESET, PAUSE, ON ERR GO TO, and ON ERR CONTINUE to attempt graceful recovery. The final line 9990 loops on SAVE "golf" LINE 5000 as a combined save-and-auto-run operation.

Notable Idioms

  • Boolean arithmetic for conditional assignment: PAR=3+(J>.5)+(J>=.8) and CL=9*(INKEY$="S")+18*(INKEY$="L").
  • String slicing for variable-width terrain bands: "\b\b\b\b\b\b\b\b\b"( TO 4+RND*8).
  • PAUSE 0 / INKEY$ loops (lines 7010, 9004, etc.) for keypress waiting without INPUT.
  • POKE 23658,8 in line 5001 enables CAPS SHIFT + symbol shift behavior, locking out unintended key modes during play.

Potential Anomalies

  • Line 5155 handles two balls occupying the same cell (ATTR 39) by substituting the other player’s terrain value — this works for two players but would fail for more.
  • The water hazard scan loop at 7710 uses NEXT I inside an IF statement to skip non-water cells, an unusual but valid Spectrum BASIC technique that continues the FOR loop conditionally.
  • The hole instructions text in line 9010 references “WATER HAZZARD” (misspelled as “hazzard” rather than “hazard”).
  • Line 5040 sets BY=0 always, so all players start at column 0 regardless of hole layout. Only the row BX is randomized.

Content

Related Products

Up to two golfers can enjoy a 9- or 18-hole trek around the green. You must hit the ball from...

Related Articles

Related Content

Image Gallery

Fun Golf

Source Code

    0 REM Spectrum "GOLF" 
    5 GO TO 5000
 2005 BORDER 4: PAPER 4: CLS : PAPER 7: FOR I=1 TO 176: PRINT "\a\a\a\a";: ON ERR GO TO 2005: NEXT I
 2010 FOR I=1 TO 3+RND*3: LET K=4+RND*17: FOR L=0 TO 20: LET K=K-2+RND*4: PRINT AT L,K*(K<=31);"\b\b\b\b\b\b\b\b\b"( TO 4+RND*8): NEXT L: NEXT I
 2015 FOR I=1 TO 29 STEP 2: LET J=5+RND*5: FOR L=J TO 11+RND*4: PRINT AT L,I;"  ": NEXT L: NEXT I
 2020 LET I=5+10*RND: LET J=10+10*RND: FOR L=I TO I+2+RND*2: LET J=J-2+RND*4: PRINT AT L,J;"\c\c\c\c\c\c"( TO 6+RND*3): NEXT L
 2025 FOR I=1 TO 2+RND*2: LET J=5+RND*10: LET K=21+RND*6: FOR L=J TO J+1+RND*2: LET K=K-1+RND*2: PRINT AT L,K;"     "( TO 3+RND*2): NEXT L: NEXT I
 2030 LET J=INT (4+RND*14): FOR I=J-2 TO J+2: PRINT AT I,25+RND*2;"     ": NEXT I
 2035 PRINT AT J,27+RND*3;"\d "
 2040 LET BX=5+RND*8: LET BY=0
 2042 ON ERR GO TO 9900
 2045 LET J=RND: LET PAR=3+(J>.5)+(J>=.8): LET YRD=(170+INT (RND*100))*(PAR=3)+(275+INT (RND*175))*(PAR=4)+(450+INT (RND*125))*(PAR=5): LET STEP=28/YRD
 2050 PRINT AT 1,1;"Hole  ";H;TAB 10;AT 2,1;"Par   ";PAR;TAB 10;AT 3,1;"Yards ";YRD
 2055 RETURN 
 5000 ON ERR GO TO 9900
 5001 BORDER 6: PAPER 6: BRIGHT 0: OVER 0: FLASH 0: INK 0: CLS : RANDOMIZE : POKE 23658,8: RESTORE 
 5005 FOR I=65 TO 69: FOR J=0 TO 7: READ X: POKE USR CHR$ I+J,X: NEXT J: NEXT I
 5010 LET B$=CHR$ 22+CHR$ 21+CHR$ 0: LET B$=B$+"                                "+B$
 5015 PRINT '''''''''"   Do you need instructions?"''TAB 10;"""Y"" OR ""N"""
 5020 IF INKEY$="Y" THEN GO SUB 9000: GO TO 5030
 5025 IF INKEY$<>"N" THEN GO TO 5020
 5030 CLS : PRINT '''''''"What length of course would you";TAB 10;"like to play?"''TAB 7;"""S""  Short 9 hole."''TAB 7;"""L""  Long 18 hole."
 5035 LET CL=9*(INKEY$="S")+18*(INKEY$="L"): IF NOT CL THEN GO TO 5035
 5040 CLS : PRINT '''''"WELCOME TO THE TS INTERNATIONAL"''TAB 5;CL;" HOLE GOLF COURSE."'''TAB 7;"How many players?";''TAB 10;"""1"" OR ""2"""
 5045 LET PL=1*(INKEY$="1")+2*(INKEY$="2"): IF NOT PL THEN GO TO 5045
 5050 DIM P(PL,6): LET V=PI/6
 5055 FOR H=1 TO CL: GO SUB 2000
 5060 FOR I=1 TO PL: LET P(I,1)=BX: LET P(I,2)=BY: LET P(I,3)=1: LET P(I,6)=0: NEXT I
 5065 LET HO=0: FOR S=1 TO 99: FOR P=1 TO PL
 5070 IF P(P,3)=97 THEN GO TO 5215
 5075 GO SUB 7000: LET ST=ST*STEP*2: LET P$=" "
 5080 IF P(P,3)=32 THEN LET ST=ST/(2+RND*2): LET P$="\a"
 5085 IF P(P,3)=4 THEN LET P$="\b": IF RND>.6 THEN PRINT B$;"YOUR BALL REBOUNDS FROM A TREE.": LET D=RND*12: LET ST=ST/4: PAUSE 150
 5090 IF P(P,3)=48 THEN LET P$=" ": IF RND>.6 THEN PRINT B$;"MISS HIT! You remain in bunker.": LET ST=0: PAUSE 150
 5095 IF P(P,3)=36 THEN LET P$=" "
 5100 IF P(P,3)=100 THEN LET P$=" "
 5105 IF P(P,3)=1 THEN LET P$="T"
 5110 PRINT AT P(P,1),P(P,2);P$
 5115 LET P(P,1)=P(P,1)-ST*COS (D*V): LET P(P,2)=P(P,2)+ST*SIN (D*V)
 5120 IF P(P,1)>=0 AND P(P,1)<=20 AND P(P,2)>=0 AND P(P,2)<=31 THEN GO TO 5150
 5125 PRINT B$;"OUT OF BOUNDS... PENALTY STROKE": PAUSE 150: LET P(P,6)=P(P,6)+1
 5130 IF P(P,1)<0 THEN LET P(P,1)=0
 5135 IF P(P,1)>20 THEN LET P(P,1)=20
 5140 IF P(P,2)<0 THEN LET P(P,2)=0
 5145 IF P(P,2)>31 THEN LET P(P,2)=31
 5150 LET P(P,3)=ATTR (P(P,1),P(P,2))
 5155 IF P(P,3)=39 THEN LET P(P,3)=P(1+(P=1),3)
 5160 IF P(P,3)=41 THEN GO TO 7700
 5165 IF P(P,3)=97 THEN GO TO 5205
 5170 PRINT B$;
 5175 IF P(P,3)=36 THEN PRINT "ON THE FAIRWAY"
 5180 IF P(P,3)=32 THEN PRINT "IN THE ROUGH"
 5185 IF P(P,3)=4 THEN PRINT "IN THE TREES..."
 5190 IF P(P,3)=48 THEN PRINT "IN A BUNKER."
 5195 IF P(P,3)=100 THEN PRINT "ON THE GREEN."
 5200 PRINT AT P(P,1),P(P,2);"\e": PAUSE 150: PRINT AT P(P,1),P(P,2);"\e": GO TO 5215
 5205 LET P(P,5)=S+P(P,6)-PAR: LET P(P,4)=P(P,4)+P(P,5): LET HO=HO+1
 5210 PRINT B$;"Player ";P;" Holed out in ";S+P(P,6): IF S+P(P,6)=1 THEN FOR I=1 TO 30: BEEP .08,10+RND*20: NEXT I: PRINT B$;"YOU BUY THE DRINKS AT THE 19th."
 5215 PAUSE 200: NEXT P
 5220 IF HO=PL THEN GO TO 5230
 5225 NEXT S: REM RESET  R&R SOFTWARE
 5230 BORDER 4: PAPER 5: CLS : PRINT " SCORE    TS 2000 GOLF     CARD "
 5235 PRINT 'TAB 9+1*(CL=9);CL;" HOLE COURSE"
 5240 PRINT '"Hole - ";H;"  Par - ";PAR;"  Yards - ";YRD
 5245 PRINT '"PLAYER";TAB 10;"HOLE";TAB 20;"COURSE": PRINT "\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''"
 5250 FOR I=1 TO PL: PRINT '"   ";I;TAB 7;
 5255 IF NOT P(I,5) THEN PRINT "  On";: GO TO 5275
 5260 PRINT ABS P(I,5);
 5265 IF P(I,5)<0 THEN PRINT " Under";
 5270 IF P(I,5)>0 THEN PRINT " Over";
 5275 PRINT " Par";TAB 19;
 5280 IF NOT P(I,4) THEN PRINT " On";: GO TO 5300
 5285 PRINT ABS P(I,4);
 5290 IF P(I,4)<0 THEN PRINT " Under";
 5295 IF P(I,4)>0 THEN PRINT " Over";
 5300 PRINT " Par": NEXT I
 5305 IF H=CL THEN GO TO 5400
 5310 PRINT B$;" PRESS ENTER TO START NEXT HOLE "
 5315 IF INKEY$<>CHR$ 13 THEN GO TO 5315
 5320 NEXT H: REM RESET  R&R SOFTWARE
 5400 PRINT AT 16,2;"Would you like another game?";AT 18,11;"""Y"" OR ""N"""
 5405 IF INKEY$="Y" THEN RUN 5000
 5410 IF INKEY$="N" THEN PRINT AT 20,7;"Thanks for playing": STOP 
 5415 GO TO 5405
 7000 PRINT B$;"  Player ";P;" Press ENTER to play"
 7005 PRINT AT P(P,1),P(P,2);"\e"
 7010 IF INKEY$<>CHR$ 13 THEN GO TO 7010
 7015 PRINT AT P(P,1),P(P,2);"\e"
 7020 PRINT B$;"Direction? 0-12": INPUT D: IF D<0 OR D>12 THEN PRINT B$;"INVALID Direction MUST be 0-12": PAUSE 150: GO TO 7020
 7025 LET D=INT (D*100+.5)/100
 7030 PRINT B$;"Direction= ";D;" Strength? 0-100": INPUT ST: IF NOT ST THEN GO TO 7020
 7035 IF ST<0 OR ST>100 THEN PRINT B$;"INVALID Strength MUST be 0-100": PAUSE 150: GO TO 7030
 7040 LET ST=INT (ST*100+.5)/100: PRINT B$;"Direction= ";D;" Strength= ";ST: PAUSE 100: RETURN 
 7700 PRINT B$;"LANDED IN WATER. Penalty Stroke"
 7705 FOR I=INT (P(P,2)) TO 0 STEP -1
 7710 IF ATTR (P(P,1),I)=41 THEN NEXT I
 7715 LET P(P,2)=I: LET P(P,6)=P(P,6)+1: PAUSE 150: GO TO 5150
 8000 DATA 0,0,4,0,0,64,0,0
 8005 DATA 255,247,227,213,247,227,213,247
 8010 DATA 0,96,144,9,102,144,9,6
 8015 DATA 12,60,12,4,4,30,37,30
 8020 DATA 0,28,62,62,62,28,0,0
 9000 BORDER 7: PAPER 7: CLS : LET T$="      TS 2000  PRO-AM GOLF      ": PRINT T$''"   A GAME FOR 1 OR 2 PLAYERS"
 9001 PRINT '" You may play a 9 hole course ORa full 18 hole course. Each holeis generated at RANDOM so no twogames are the same."
 9002 PRINT '" When its your turn to play yourball will be set flashing. When ready for move,Press the ENTER  key. You must now enter a value (0-12, As on a Clock) to select your DIRECTION. Now give a valuefor STRENGTH of shot (1-100), anentry of ZERO will return you tothe direction input.    Decimal inputs ie. 3.25 are allowed."
 9003 PRINT B$;"Hit ENTER for more instructions."
 9004 IF INKEY$<>CHR$ 13 THEN GO TO 9004
 9010 CLS : PRINT T$''"The GREEN =      FAIRWAY =        ROUGH = \a\a\a  BUNKER =    ","WATER HAZZARD = \c\c\c  TREES = \b","  The HOLE = \d   The BALL = \e"
 9011 PRINT '"When playing from the ROUGH yourball will not move as far as it will on the FAIRWAY. If you landin a bunker you may not get out first shot.   When in the TREES the ball MAY bounce off in any  direction.  Land in the WATER orgo OUT OF BOUNDS and you incur  ONE penalty stroke."
 9012 PRINT '"   I hope you enjoy your game  "''"Press ENTER to start round OR   ""P"" to see instructions again."
 9014 IF INKEY$="P" THEN GO TO 9000
 9015 IF INKEY$<>CHR$ 13 THEN GO TO 9014
 9020 RETURN 
 9900 ON ERR RESET 
 9910 PAUSE 100
 9920 ON ERR GO TO 9900
 9930 ON ERR CONTINUE 
 9990 SAVE "golf" LINE 5000: GO TO 9990

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top