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
\n1000 LET U=C-A
\n1005 REM U
\n1010 LET V=D-B
\n1015 REM V
\n1020 LET D1X=SGN U
\n1030 LET D1Y=SGN V
\n1035 REM (D1X,D1Y)
\n1040 LET D2X=SGN U
\n1050 LET D2Y=0
\n1055 REM (D2X,D2Y)
\n1060 LET M=ABS U
\n1070 LET N=ABS V
\n1080 IF M>N THEN GOTO 1130
\n1090 LET D2X=0
\n1100 LET D2Y=SGN V
\n1105 REM (D2X,D2Y)
\n1110 LET M=ABS V
\n1120 LET N=ABS U
\n1130 REM
\n1140 LET S=INT (M/2)
\n1145 REM
\n1150 FOR L=0 TO M
\n1160 PLOT A,B
\n1170 LET S=S+N
\n1180 IF S<M THEN GOTO 1230
\n1190 LET S=S-M
\n1200 LET A=A+D1X
\n1210 LET B=B+D1Y
\n1215 REM
\n1220 GOTO 1250
\n1230 LET A=A+D2X
\n1240 LET B=B+D2Y
\n1245 REM
\n1250 NEXT L
\n1260 RETURN
\n1270 CLEAR
\n1280 SAVE "1030%4"
\n1290 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
