This program plots a biorhythm chart, graphing the Physical (23-day), Sensitivity (28-day), and Intellectual (33-day) sinusoidal cycles for a given person and calendar month. The user inputs their birth date and the target month, and the program computes the elapsed days between those dates using a Julian-day-style integer accumulation routine at line 3000. Each cycle is drawn pixel-by-pixel using PLOT, with the sine argument converted from degrees to radians by multiplying by the constant 0.0174533. When a curve exceeds the screen boundaries (above row 18 or below row 158), the cycle identifier letter (“P”, “S”, or “I”) is printed at the top or bottom of the screen to indicate overflow. The calendar logic at lines 2082–2088 correctly handles month lengths including a basic leap-year check for February.
Program Analysis
Program Structure
The program is organized into well-separated functional blocks:
- Lines 105–210: Draw the chart grid — vertical lines every 8 pixels for each day, and a horizontal baseline at y=88.
- Lines 400–430: Print day-number labels along the x-axis.
- Lines 500–740: Plot the three biorhythm curves (Physical, Sensitivity, Intellectual) by calling the shared curve-drawing subroutine at line 1000.
- Line 999:
STOPto halt after display. - Lines 1000–1040: Generic sine-curve plotter; shared by all three cycles.
- Lines 2000–2095: Main input and setup subroutine — collects birth date, graph month, computes elapsed days, determines month length, and prints the chart header.
- Lines 2200–2420: Cycle-specific phase-calculation subroutines for Physical (23), Sensitivity (28), and Intellectual (33) cycles.
- Lines 3000–3400: Date-to-integer-day conversion routine, producing an absolute day count in
dt. - Lines 4000–4010:
SAVEblock, separated from the main program flow.
Date Arithmetic (Lines 3000–3400)
The date-to-day-number routine at line 3000 converts a calendar date into an absolute integer day count stored in dt. It computes years elapsed since 1901 (yt), counts leap years (lt), and uses a hard-coded cumulative day-of-year table via a chain of IF … GO TO statements for each month. The formula yt*365+306+lt+mt+d is applied, with an additional +1 added at line 3310 if the year being processed is itself a leap year. There is a subtlety: the caller decrements y by 1 before the call (LET y=y-1 at lines 2000 and 2020), and the subroutine increments it back at line 3300 (LET y=y+1) before the leap-year check at 3310, meaning January and February of a leap year are handled via the lt adjustment at line 3020 rather than the post-increment check.
Curve-Drawing Subroutine (Lines 1000–1040)
The single generic plotter at line 1000 iterates x from 0 to 8*days pixels. For each pixel column, it computes y=88+72*SIN(s*0.0174533), converting the accumulated angle s in degrees to radians using the approximation π/180 ≈ 0.0174533. The center baseline is y=88 and the amplitude is 72 pixels. The PAPER color is set by each caller before invoking the subroutine, coloring the ink of subsequent PLOTs. If the computed y-coordinate falls outside the visible plot area (above 158 or below 18), the cycle’s letter identifier is printed at the screen edge to signal overflow.
Phase Calculation Subroutines
Lines 2200–2420 each calculate the starting phase for one biorhythm cycle from the total elapsed days r (the difference between graph-month start and birth date). The integer quotient q is discarded; the remainder d gives the number of days into the current cycle. The angular increment per pixel a and starting angle s are then set in the calling block before the curve subroutine is invoked. The current phase day is also printed on the screen as a status line.
| Cycle | Period (days) | Subroutine | Color (PAPER) | Label |
|---|---|---|---|---|
| Physical | 23 | 2200 | 5 (Cyan) | P |
| Sensitivity | 28 | 2300 | (unchanged) | S |
| Intellectual | 33 | 2400 | 4 (Green) | I |
Month-Length Calculation (Lines 2082–2088)
After the user inputs the graph month number, days is initially set equal to the month number (LET days=m). Lines 2082–2088 then replace days with the actual number of days in that month. February gets 28 days by default, bumped to 29 if the year is divisible by 4. April, June, September, and November get 30 days. All other months (except already-handled February) get 31. Note that the leap-year test (years/4=INT(years/4)) is a simple divisibility-by-4 check and does not account for century years.
Key BASIC Idioms and Notable Techniques
- The shared curve subroutine at line 1000 is parameterized entirely through global variables (
a,s,a$,days), avoiding code duplication across the three cycles. - The delay loop
FOR t=1 TO 250: NEXT tat line 2040 provides a brief pause before clearing the screen on an input error, a common BASIC timing idiom. - The grid lines are drawn using
PLOT/DRAWwithin aFORloop stepping by 8 pixels, matching each screen column to one day. PAPERis used to change the color context for each curve, withPAPER 7restoring white at line 740 after all curves are drawn.- The month table at lines 3100–3210 uses explicit
GO TO 3300orGO TO 3400branches to handle months needing the post-increment leap adjustment separately from those that do not.
Bugs and Anomalies
- Line 2000 contains a typo in the prompt string:
"Your BIIRTHDAY (MM/DD/YY)?"— “BIRTHDAY” is misspelled with a double “I”. - Line 2100 contains a
REM *S/cycle*comment that appears to be a leftover stub; it is never reached by normal program flow (line 2095 returns before reaching it). - The leap-year test at line 2084 uses only divisibility by 4, not the full Gregorian rule (divisible by 100 and 400 exceptions), so years like 1900 would be incorrectly treated as leap years if entered.
- The
SENSITIVITYcurve subroutine at line 2300 does not set a PAPER color before plotting, so it inherits whatever color was last set (Cyan from the Physical curve). This may be intentional to distinguish it visually, but it is not explicit.
Content
Source Code
105 GO SUB 2000
110 FOR l=0 TO 8*days STEP 8
120 PLOT l,16: DRAW 0,144: NEXT l
200 PLOT 0,88
210 DRAW days*8,0
400 PRINT AT 11,0;"0": PRINT AT 11,5;"5"
410 FOR n=10 TO days STEP 5
420 PRINT AT 11,n-1;n
430 NEXT n
500 REM *p/curve*
510 PAPER 5: GO SUB 2200
520 LET a=360/(8*23): LET s=a*d*8: LET a$="P"
530 GO SUB 1000
600 REM *s/curve*
610 GO SUB 2300
620 LET a=360/(8*28): LET s=a*d*8: LET a$="S"
630 GO SUB 1000
700 REM *I/curve*
710 PAPER 4: GO SUB 2400
720 LET a=360/(8*33): LET s=a*d*8: LET a$="I"
730 GO SUB 1000
740 PAPER 7
999 STOP
1000 FOR x=0 TO 8*days
1005 LET y=88+72*SIN (s*.0174533)
1006 IF y>158 AND x/8=INT (x/8) THEN PRINT AT 2,x/8;a$
1007 IF y<18 AND x/8=INT (x/8) THEN PRINT AT 19,x/8;a$
1010 PLOT x,y
1020 LET s=s+a
1030 NEXT x
1040 RETURN
2000 INPUT "Your BIIRTHDAY (MM/DD/YY)?";m,d,y: LET y=y-1
2005 GO SUB 3000
2010 LET ds=dt
2020 INPUT "BIO-GRAPH month (MM/YY)?";m,y: LET d=1: LET days=m: LET month=m: LET years=y: LET y=y-1
2025 GO SUB 3000
2030 LET de=dt
2040 LET r=de-ds: IF r<0 THEN PRINT "OOPS!! Dates entered wrong!": FOR t=1 TO 250: NEXT t: CLS : GO TO 2000
2082 IF days=2 THEN LET days=28
2084 IF days=28 AND years/4=INT (years/4) THEN LET days=29
2087 IF days=4 OR days=6 OR days=9 OR days=11 THEN LET days=30: GO TO 2090
2088 IF days<>28 AND days<>29 THEN LET days=31
2090 INPUT "What is your FIRST NAME?";n$
2092 PRINT " B I O - G R A P H"
2093 PRINT "For: ";n$;" Month: ";month;"/";years
2095 RETURN
2100 REM *S/cycle*
2200 REM *P/cycle*
2210 LET q=INT (r/23): LET d=r-(q*23): PRINT AT 20,0;"Physical=";d
2220 RETURN
2300 REM
2310 LET q=INT (r/28): LET d=r-q*28: PRINT AT 20,16;"Sensitivity=";d
2320 RETURN
2400 REM
2410 LET q=INT (r/33): LET d=r-q*33: PRINT AT 21,8;"Intellectual=";d
2420 RETURN
3000 LET yt=y-1901
3010 LET lt=INT (yt/4)
3020 IF y/4=INT (y/4) AND m<3 THEN LET lt=lt+1
3100 IF m=1 THEN LET mt=0: GO TO 3400
3110 IF m=2 THEN LET mt=31: GO TO 3400
3120 IF m=3 THEN LET mt=59: GO TO 3300
3130 IF m=4 THEN LET mt=90: GO TO 3300
3140 IF m=5 THEN LET mt=120: GO TO 3300
3150 IF m=6 THEN LET mt=151: GO TO 3300
3160 IF m=7 THEN LET mt=181: GO TO 3300
3170 IF m=8 THEN LET mt=212: GO TO 3300
3180 IF m=9 THEN LET mt=243: GO TO 3300
3190 IF m=10 THEN LET mt=273: GO TO 3300
3200 IF m=11 THEN LET mt=304: GO TO 3300
3210 IF m=12 THEN LET mt=334
3300 LET dt=(yt*365+306)+lt+mt+d: LET y=y+1
3310 IF y/4=INT (y/4) THEN LET dt=dt+1
3330 RETURN
3400 LET dt=(yt*365+306)+lt+mt+d: RETURN
4000 SAVE "BIO-GRAPH"
4010 STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
