Biorhythms

Developer(s): Jim Clark
Type: Program
Platform(s): TS 2068

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:

  1. Setup (lines 5–8): REM header, RESTORE, random BORDER color, title display.
  2. Input (lines 10–20): Collects date of birth (day, month, year) and current date (month, year — notably, no current day is requested).
  3. Elapsed-day calculation (line 30): Computes t, the number of days since birth.
  4. Axis drawing (lines 800–830): Draws a horizontal baseline and tick marks, then labels it.
  5. 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.
  6. 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:

  • l is the current phase angle: 2*PI*(t MOD u)/u computed without MOD using t - INT(t/u)*u.
  • k is 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 1 on the last line targets a non-existent line, causing the interpreter to restart execution from the first available line — an intentional restart idiom.
  • Using RESTORE at line 6 ensures the DATA pointer is reset if the program is re-run without a full restart.
  • The BORDER RND*8 at 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

CyclePeriod (days)INK colorDisplay color
Physical231Blue
Mental282Red
Emotional334Green

Content

Related Products

Related Articles

Related 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.

Scroll to Top