This program draws 25 randomly placed straight lines on screen using Bresenham’s line-drawing algorithm implemented entirely in BASIC. Starting from a random point, it repeatedly selects a new random destination within a 62×42 pixel area and calls the subroutine at line 1000 to plot each line pixel by pixel. The subroutine correctly handles all octants by choosing the major axis (the longer dimension) as the driving axis and using an integer accumulator variable S to decide when to step along the minor axis. The REM statements scattered throughout appear to serve as inline documentation for intermediate values rather than functional code.
Program Analysis
Program Structure
The program is divided into two parts: a short main loop (lines 10–70) and a line-drawing subroutine (lines 1000–1260). Lines 1270–1290 handle saving and re-running the program.
- Lines 10–20: Initialise the starting point (
A,B) with random coordinates. - Lines 25–70: Loop 25 times, each iteration picking a random endpoint (
C,D), calling the line-draw subroutine, then advancing the current position to the endpoint. - Lines 1000–1260: Bresenham’s line-drawing subroutine, plotting from (
A,B) to (C,D).
Coordinate Space
Random coordinates are constrained to a 62×42 pixel region: A and C are in the range 1–62 and B and D in the range 1–42. This keeps all points within the displayable screen area without risk of out-of-bounds PLOT errors.
Bresenham’s Line Algorithm
The subroutine at line 1000 is a faithful BASIC implementation of Bresenham’s integer line algorithm. Key variables are:
| Variable | Role |
|---|---|
U | Horizontal delta (C−A) |
V | Vertical delta (D−B) |
D1X, D1Y | Diagonal step direction (both axes) |
D2X, D2Y | Primary-axis step direction (one axis only) |
M | Length of the major (driving) axis |
N | Length of the minor axis |
S | Bresenham error accumulator, initialised to INT(M/2) |
L | Loop counter, 0 to M inclusive |
The algorithm determines which axis is longer (lines 1060–1120) and sets the step vectors accordingly so that it always iterates along the major axis. At each step, N is added to the accumulator S; when S reaches or exceeds M, M is subtracted and a diagonal step (D1X, D1Y) is taken; otherwise only the primary-axis step (D2X, D2Y) is used. This correctly handles all eight octants.
Notable Techniques
- SGN for direction:
SGN UandSGN Vextract ±1 or 0 cleanly without any IF/THEN branching, keeping the step-vector setup compact. - Error accumulator initialisation: Setting
S = INT(M/2)before the loop centres the error term, producing a more visually symmetric line than initialising to 0. - Connected line segments: After each subroutine call,
AandBare updated toCandD(lines 50–60), so successive lines form a continuous polyline rather than isolated segments. - REM as commentary: Several REM statements (e.g. lines 1005, 1015, 1035) appear immediately after variable assignments to document what each variable represents, a common documentation practice in BASIC of this era.
Bugs and Anomalies
- Subroutine modifies caller variables: The subroutine uses
AandBas its working plot position, overwriting the caller’s start-point values during the drawing loop. The main loop relies on this side-effect by reading the final values ofAandBat lines 50–60 — however, because the loop always runs from 0 toMinclusive and ends exactly at (C,D), the final values ofAandBafter the RETURN will equal the originalCandD, so the behaviour is correct if fragile. - Line 1270 CLEAR: This line is unreachable during normal execution (the RETURN at 1260 sends control back to the main loop, which ends at line 70 with no fall-through). It would only execute if the main loop somehow fell through, suggesting it may be a remnant of development.
Content
Source Code
10 LET A=INT (RND*62)+1
20 LET B=INT (RND*42)+1
25 FOR P=1 TO 25
30 LET C=INT (RND*62)+1
40 LET D=INT (RND*42)+1
45 GOSUB 1000
50 LET A=C
60 LET B=D
70 NEXT P
1000 LET U=C-A
1005 REM U
1010 LET V=D-B
1015 REM V
1020 LET D1X=SGN U
1030 LET D1Y=SGN V
1035 REM (D1X,D1Y)
1040 LET D2X=SGN U
1050 LET D2Y=0
1055 REM (D2X,D2Y)
1060 LET M=ABS U
1070 LET N=ABS V
1080 IF M>N THEN GOTO 1130
1090 LET D2X=0
1100 LET D2Y=SGN V
1105 REM (D2X,D2Y)
1110 LET M=ABS V
1120 LET N=ABS U
1130 REM
1140 LET S=INT (M/2)
1145 REM
1150 FOR L=0 TO M
1160 PLOT A,B
1170 LET S=S+N
1180 IF S<M THEN GOTO 1230
1190 LET S=S-M
1200 LET A=A+D1X
1210 LET B=B+D1Y
1215 REM
1220 GOTO 1250
1230 LET A=A+D2X
1240 LET B=B+D2Y
1245 REM
1250 NEXT L
1260 RETURN
1270 CLEAR
1280 SAVE "1030%4"
1290 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
