--- title: "Biorhythm" id: 71330 type: "computer_media" slug: "biorhythm-2" url: "http://localhost/computer_media/biorhythm-2/" markdown_url: "http://localhost/computer_media/biorhythm-2.md" published_at: "2026-09-02T06:58:16+00:00" modified_at: "2026-09-02T06:58:16+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/biorhythms.png" excerpt: "Enter two dates and watch three sine-wave biorhythm cycles — Physical, Emotional, and Intellectual — plotted simultaneously across a full-width graph." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Entertainment" slug: "entertainment" taxonomy: "genre" url: "http://localhost/type/entertainment/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Biorhythm%20(198x)(-)(TS2068)(US)(Program).zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/biorhythms.png" media_type_tags: "Entertainment" --- # Biorhythm This program calculates and displays biorhythm charts for three cycles — Physical (23 days), Emotional (28 days), and Intellectual (33 days) — based on a user-supplied date of birth and today’s date. Date validation at line 1000 checks string length, delimiter placement, and digit validity before converting the DD.MM.YY input into a day-count using month-length data encoded in the string `m$` as ASCII offset values (e.g., `CODE m$(m)-20` yields the number of days in month `m`). Leap year correction is applied when the year is divisible by 4 and the accumulated day count has passed February. The chart is plotted using PLOT and SIN with a scaling factor of 20 pixels amplitude, and month boundaries are marked by vertical tick lines driven by the same `m$` encoding used during date parsing. *** ### Program Structure The program is divided into four logical sections: 1. **Lines 10–90:** Setup, color attributes, and input loop for birth date and today’s date. 2. **Lines 100–340:** Cycle calculation and chart rendering including sine-wave plotting and month-boundary markers. 3. **Lines 1000–1550:** Subroutine that validates a date string and converts it to an absolute day number stored in `n`. 4. **Line 2000–2010:** Error handler that sets flag `x=1` and prints a flashing “INVALID DATE” message. ### The m$ Encoding Trick The string `m$="303232332323"` at line 20 encodes month lengths in a compact form. Each character’s ASCII code minus 20 yields the number of days in that month: `'3'` = 51−20 = 31, `'0'` = 48−20 = 28, `'2'` = 50−20 = 30. This avoids a DATA statement or array, and the same string is reused both in the date-to-day conversion (lines 1090–1530) and in the month-boundary tick-mark loop (lines 300–330). ### Date Validation Subroutine (Lines 1000–1550) The subroutine performs several layered checks before attempting numeric conversion: - Exact length of 8 characters (line 1010). - Dots at positions 3 and 6 (line 1020). - Digit characters at positions 1–2, 4–5, and 7–8 via a loop stepping by 3 (lines 1030–1050). - Non-zero day, month, and year, and month ≤ 12 (line 1070). An anomaly exists at line 1090: it calculates the days in month `m` into `n` (including leap-day adjustment for February), but this value is immediately overwritten by `LET n=0` at line 1500 without being used. The intent was likely to validate that the day number does not exceed the month length, but that check was never implemented — so invalid days such as 31 in April pass silently. ### Day-Count Calculation Lines 1500–1550 sum month lengths for all months before `m`, add a leap-year correction if the accumulated count has passed day 59 (end of February), then add the day-of-month and an approximation of prior complete years using `INT (365.25*(y-1))`. This gives a relative Julian-style day number sufficient for computing the difference between two dates. The two-digit year `y` means dates in different centuries are not distinguished, though this is typical for the era. ### Biorhythm Calculation and Plotting Line 130 derives cycle periods: `b(1)=23`, `b(2)=28`, `b(3)=33`, matching Physical, Emotional, and Intellectual cycles. Line 140 computes `c(j)`, the phase offset (days into the current cycle). The sine wave is plotted at line 230: `PLOT INK j; k, SIN((k + 2*c(j)) * PI / b(j)) * 20 + ((4-j)*48-28)` The factor `2*c(j)` in the argument shifts the curve horizontally so the chart’s left edge represents the current date. Each cycle is drawn in a different INK color (1=blue, 2=red, 3=green) and centered on its own horizontal baseline at vertical positions 20, 68, and 116 pixels respectively. ### Month Boundary Markers (Lines 300–330) A second pass over all 256 x-coordinates draws short vertical tick marks at month boundaries. Variable `d` accumulates 0.5 per pixel column and is compared against `CODE m$(m)-20` (days in month `m`). When the threshold is exceeded, `d` resets and `m` advances. Note that `d` is also used as the day-of-month variable in the date parsing subroutine (line 1060), so if the chart section is reached, `d` retains whatever value was left from parsing. This is benign because `d` is effectively initialized to a small value before the comparison matters, but it is a variable reuse that could cause confusion. ### Notable Techniques and Anomalies - The typo “Pleasr” (missing ‘e’) in the PRINT statement at line 30 is a cosmetic bug in the original listing. - Error handling uses a flag variable `x` rather than structured error trapping, with GO TO 2000 used as a shared error exit from multiple validation points. - The `DIM n$(3,12)` at line 100 allocates fixed-length strings; “Physical” (8 chars), “Emotional” (9), and “Intellectual” (12) are padded to 12 by the DIM, so labels display correctly without manual padding. - Line 1090 computes a value into `n` that is immediately discarded by line 1500’s `LET n=0`, representing an incomplete validation or refactoring artifact. ## Source Code ``` 10 INK 2:BORDER 6:PAPER 6:BRIGHT 1:CLS 20 LET m$="303232332323" 30 PRINT TAB 11;"BIORHYTHM"'''''"Pleasr enter dates in the form:"''' TAB 11;"DD.MM.YY" 40 INPUT "Enter your date of birth ";d$ 50 GO SUB 1000:IF x THEN GO TO 40 60 LET b=n:LET b$=d$ 70 INPUT "Enter today's date ";d$ 80 GO SUB 1000:IF x THEN GO TO 70 90 LET n=n-b:IF n<0 THEN GO SUB 2000:GO TO 70 100 DIM n$(3,12):LET n$(1)="Physical":LET n$(2)="Emotional":LET n$(3)="Intellectual" 110 DIM b(3):DIM c(3) 120 FOR j=1 TO 3 130 LET b(j)=18+5*j 140 LET c(j)=n-b(j)* INT (n/b(j)) 150 NEXT j 200 CLS :PRINT TAB 11;"BIOCHART"''"D.O.B.:";b$;"Today:";d$ 210 INK 7:FOR j=1 TO 3:PLOT 0,j*48-28:DRAW 255,0:PRINT INK j; AT j*6-2,2;n$(j):NEXT j 220 FOR j=1 TO 3:FOR k=0 TO 255 230 PLOT INK j;k, SIN ((k+(2*c(j)))* PI/b(j))*20+((4-j)*48-28) 240 NEXT k:NEXT j 300 FOR j=0 TO 255 310 LET d=d+.5 320 IF d> CODE m$(m)-20 THEN LET d=.5:FOR k=1 TO 3:PLOT j,k*48-30:DRAW 0,5:NEXT k:LET m=m+1:IF m>12 THEN LET m=1 330 NEXT j 340 STOP 1000 LET x=0:PRINT AT 15,10;" ":REM 12 spaces 1010 IF LEN d$ <>8 THEN GO TO 2000 1020 IF d$(3) <>"." OR d$(6) <>"." THEN GO TO 2000 1030 FOR j=1 TO 7 STEP 3 1040 IF d$(j)<"0" OR d$(j)>"9" OR d$(j+1)<"0" OR d$(j+1)>"9" THEN GO TO 2000 1050 NEXT j 1060 LET y= VAL d$(7 TO ):LET m= VAL d$(4 TO 5):LET d= VAL d$( TO 2) 1070 IF y=0 OR d=0 OR m=0 OR m>12 THEN GO TO 2000 1080 LET l=0:IF y/4= INT y/4 THEN LET l=1 1090 LET n= CODE m$(m)-20+(m=2 AND l=1) 1500 LET n=0 1510 FOR j=1 TO m-1 1520 LET n=n+ CODE m$(j)-20 1530 NEXT j 1540 IF l=1 AND n>59 THEN LET n=n+1 1550 LET n=n+d+ INT (365.25*(y-1)):RETURN 2000 LET x=1 2010 PRINT INK 2; FLASH 1; AT 15,10;"\{16}\{2}INVALID DATE":RETURN 9000 SAVE "BIORHYTHMS" LINE 0 ```