This program calculates and plots biorhythm cycles — physical (23-day), mental (28-day), and emotional (33-day) — as sine waves on a graphics display. The user enters their date of birth and today’s date; the program computes the number of elapsed days using a simplified Julian-style formula (365.25 days per year, 30.35 days per month). Each cycle is drawn using PLOT with INK color-coding: INK 1 (blue) for physical, INK 2 (red) for mental, and INK 4 (green) for emotional. The horizontal scale is adjusted per cycle using the expression `(35-28+u)` so that each wave spans the same screen width regardless of its period. A tick-mark axis is drawn at y=10 with vertical markers at intervals of B (which is uninitialized, defaulting to 0, making every column a tick — a likely bug).
Program Analysis
Program Structure
The program is organized into a small number of logical phases:
- Setup (lines 5–8): REM header, RESTORE, random BORDER color, title display.
- Input (lines 10–20): Collects date of birth (day, month, year) and current date (month, year — notably, no current day is requested).
- Elapsed-day calculation (line 30): Computes
t, the number of days since birth. - Axis drawing (lines 800–830): Draws a horizontal baseline and tick marks, then labels it.
- Curve plotting (lines 900–1040): Loops over the three biorhythm periods, reads each from DATA, and plots a sine wave in the appropriate INK color.
- Repeat prompt (line 1050): Asks the user to run again, branching to line 1 (non-existent) which restarts the program from the top via the well-known GO TO 0/1 technique.
Elapsed-Day Calculation
Line 30 computes the total elapsed days as:
t = INT(((e-c)*365.25) + (d-b)*30.35) - a
where c/e are birth/current year, b/d are birth/current month, and a is the birth day. This is a simplified but reasonably accurate approximation — 365.25 accounts for leap years and 30.35 is an average month length. The current day is never entered, so the result is only accurate to within about a month.
Biorhythm Plotting Technique
Lines 900–1030 loop over the three cycle lengths (23, 28, 33 days) stored in DATA at line 1040. For each period u:
lis the current phase angle:2*PI*(t MOD u)/ucomputed without MOD usingt - INT(t/u)*u.kis a scaling factor:2*PI*(33-u)*0.03, used to normalize the horizontal step so all three waves occupy similar screen width.- The PLOT x-coordinate is
(a-l)*(35-28+u), which maps the angular progress onto the pixel range for that cycle. - The y-coordinate is
90 + SIN(a)*60, centering the wave at pixel row 90 with amplitude 60.
INK color selection uses a compact Boolean expression: INK ((1 AND u=23)+(2 AND u=28)+(4 AND u=33)). In Sinclair BASIC, AND with a true condition returns the left-hand value and 0 otherwise, so exactly one term is non-zero per iteration.
Axis Drawing Bug
Lines 810–815 draw tick marks at intervals of B pixels along the baseline. However, B is never assigned a value anywhere in the program. In Sinclair BASIC, an uninitialized numeric variable defaults to 0. Since INT(r/0) would cause a division-by-zero error, and the condition r = INT(r/B)*B with B=0 evaluates as r = 0 (since 0*anything=0), only the single tick at r=0 is drawn rather than the intended regular grid. The variable should likely be a constant such as 10 or 32 to produce evenly spaced markers.
Variable Reuse
The variable a is used for three distinct purposes: birth day (line 10), loop variable in the sine plotting loop (line 1000), and the user’s response string a$ at line 1050. Similarly, u serves as both the tick-mark inner loop counter (line 815) and the biorhythm period variable (lines 905–1020). This reuse is typical of space-conscious BASIC programming but can make the code harder to follow.
Notable Techniques
- The
GO TO 1on the last line targets a non-existent line, causing the interpreter to restart execution from the first available line — an intentional restart idiom. - Using
RESTOREat line 6 ensures the DATA pointer is reset if the program is re-run without a full restart. - The
BORDER RND*8at line 7 picks a random border color on each run as a cosmetic flourish. - Prompted INPUT with a string literal prefix (e.g.,
INPUT "Day ";a) provides inline labeling without separate PRINT statements.
Data Summary
| Cycle | Period (days) | INK color | Display color |
|---|---|---|---|
| Physical | 23 | 1 | Blue |
| Mental | 28 | 2 | Red |
| Emotional | 33 | 4 | Green |
Content
Image Gallery
Source Code
5 REM biorhythms by J. Clark from SINCLAIR USER ANNUAL-83
6 RESTORE
7 BORDER RND*8
8 PRINT AT 0,0;" BIORHYTHMS "
10 INPUT "Enter Date of Birth (numerical)","Day ";a;" Month ";b;" Year ";c
20 INPUT "Enter Date Now (numerical)","Month ";d;" Year ";e
25 CLS
30 LET t=INT (((e-c)*365.25)+(d-b)*30.35)-a
800 FOR r=0 TO 255
810 PLOT r,10
815 IF r=INT (r/B)*B THEN FOR u=10 TO 20: PLOT r,u: NEXT u
820 NEXT r
830 PRINT AT 21,0;"1st 10th 20th 30th"
840 PRINT AT 0,0; INK 1;"physical "; INK 2;"mental "; INK 4;"emotional"
900 FOR r=1 TO 3
905 READ u
910 LET l=2*PI*(t-(INT (t/u)*u))/u
920 LET k=2*PI*(33-u)*.03
1000 FOR a=l TO k+l+(2*PI) STEP .1
1010 PLOT INK ((1 AND u=23)+(2 AND u=28)+(4 AND u=33));(a-l)*(35-28+u),90+SIN a*60
1020 NEXT a
1030 NEXT r
1040 DATA 23,28,33
1050 INPUT "Again (y/n)? ";a$: IF a$(1)="y" OR a$(1)="Y" THEN GO TO 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.