--- title: "D&D Track" id: 57362 type: "computer_media" slug: "dd-track" url: "http://localhost/computer_media/dd-track/" markdown_url: "http://localhost/computer_media/dd-track.md" published_at: "2024-10-04T08:55:21+00:00" modified_at: "2026-04-03T07:58:32+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/09/210_DDT.png" excerpt: "A full RPG combat tracker handling hit points, troll regeneration, wound binding, healing, and an arbitrary dice roller — all managed through a compact menu-driven interface." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Tony Willing" slug: "tony-willing" taxonomy: "indiv" url: "http://localhost/indiv/tony-willing/" genre: - name: "Dungeons & Dragons" slug: "dungeons-dragons" taxonomy: "genre" url: "http://localhost/type/dungeons-dragons/" - name: "Hobby" slug: "hobby" taxonomy: "genre" url: "http://localhost/type/hobby/" media_contents: - id: 56735 title: "Timex Sinclair Public Domain Library Tape 1004" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1004/" media_type: "Program" programmers: - name: "Tony Willing" slug: "tony-willing" taxonomy: "indiv" url: "http://localhost/indiv/tony-willing/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/09/210_DDT.png" media_type_tags: "Dungeons & Dragons, Hobby" --- # D&D Track TRACK is a combat-tracking utility for tabletop role-playing games, designed to manage hit points and status effects for multiple creatures simultaneously. It stores data in five parallel arrays (A through E) covering current HP, maximum HP, regeneration rate, regeneration delay, and bind status for up to Q creatures. The program implements D&D-style rules including troll regeneration (10 HP/round), general per-round regeneration, wound bleeding for creatures at negative HP, and a “bind wounds” mechanic that freezes HP loss. A dice-roller sub-mode accepts any die size and roll count, displaying results before returning to the main menu. *** ## Program Analysis ### Program Structure The program is organized as a menu-driven application with a central dispatch at line `200` and subroutines branching out to labeled REM blocks. Execution begins at line `100` and jumps to the initialization section at line `210`. After setup, control falls to line `130` (which is a missing line — a deliberate technique to fall through to `140`). The main menu loop lives at lines `140`–`200`, and each menu option jumps to a dedicated REM-labeled section. ### Menu Dispatch Technique Line `200` uses a compact arithmetic dispatch idiom common in Sinclair BASIC: ``` GOTO (360 AND J=1)+(590 AND J=2)+(1140 AND J=3)+... ``` Because boolean expressions evaluate to 1 (true) or 0 (false), multiplying the target line number by the condition and summing them produces exactly one non-zero addend, acting as a computed GOTO. This avoids a cascade of IF/GOTO statements and is a well-known space-saving technique on memory-constrained systems. ### Data Arrays Five parallel arrays are dimensioned at lines `220`–`224`, all of size `Q` (number of creatures): | Array | Purpose | | --- | --- | | `A()` | Current hit points (0 = dropped/dead) | | `B()` | Maximum (base) hit points, used as heal ceiling | | `C()` | Regeneration amount per round (10 = troll) | | `D()` | Round number when slow regeneration next fires | | `E()` | Bind/bleed state (1 = bleeding, 10 = bound) | ### Game Mechanics Implementation The regeneration/round loop (lines `690`–`870`) encodes several layered rules: - **Bleeding:** If `A(F) < 0` and `E(F)` is not 10 (bound), the creature loses 1 HP per round. The first negative round sets `E(F)=1` as a bleed flag. - **Fast regeneration (trolls):** If `C(F)=10` and current HP is below maximum, a 3-HP-per-round slow-regen schedule via `D(F)` fires every 4 rounds (line `790`: `D(F)=Z+3`). There is an apparent bug here — troll fast regen (`C(F)=10`) actually routes to the slow-regen path at line `780` because the condition `C(F)<10` is false, so trolls only regenerate 3 HP every 4 rounds rather than 10 HP/round. - **Other regeneration:** Creatures with `0 < C(F) < 10` heal `C(F)` HP every round (line `850`). - **Bind wounds:** Setting `E(F)=10` (option 5, line `1350`) prevents both bleeding and regeneration checks. ### Healing Special Case At line `1210`, entering `N=1000` as the cure amount is treated as a “full heal” sentinel, restoring `A(F)` to `B(F)` (maximum HP). Any other value is added directly. This avoids a dedicated “full heal” menu option at the cost of an undocumented magic number. ### Regeneration Base Reset When the Regenerate option (J=4) is chosen, lines `900`–`904` iterate through all creatures and reset `B(F)=A(F)`, making the current HP the new maximum before assigning regeneration rates. This means a creature’s heal ceiling is recalculated from its current (possibly damaged) state at the time regeneration is registered, not from its original full HP. ### Display Layout The status display (lines `370`–`580`) prints creature numbers and HP in a grid across the screen, with 4-character column spacing (`H=H+4`) and 3-row vertical spacing. It handles up to 7 columns (H wraps at 28) before moving down. If more than 42 display rows’ worth of creatures are shown, a “CONTINUE PRINTOUT?” prompt appears via the subroutine at line `510`. ### Dice Roller Lines `1380`–`1520` implement a general-purpose dice roller. The user inputs the die size `F` and number of rolls `G`; the result is `INT(F*RND)+1` for each roll. A `PAUSE 4E4` (approximately 27 minutes on a 50 Hz machine, effectively waiting for a keypress via key-interrupt or the user pressing a key) holds the display before looping back. Entering 0 for die size exits to the status display. ### Utility Subroutine The subroutine at line `1530` clears rows 20 and 21 by printing 31 spaces at each position, providing a clean input area before prompting. It is called before most input prompts throughout the program. ### Notable Anomalies - Line `350` jumps to `GOTO 130`, which does not exist. This is a deliberate fall-through technique — execution continues at the next defined line, which is `140` (the main menu). - The round counter `Z` is incremented inside the Damage routine (line `600`) rather than in a dedicated end-of-round handler, meaning rounds advance only when damage is applied. - Line `1600` (`STOP`) is unreachable dead code, as is the commented-out `RAND USR 14336` at line `1610`, suggesting a machine-code helper was once planned or used in an earlier version. - The `PAUSE 4E4` at line `1495` is effectively an indefinite pause on most hardware configurations; the program relies on the user pressing a key or waiting out the timer. ## Source Code ``` 0 REM TRACK ****D £ D TRACK**** BY JIM LANE MODIFIED FOR %T%I%M%E%X/ SINCLAIR BY ANTHONY WILLING (4/1984) ******************* 70 REM 80 CLS 100 LET R=0 110 LET Z=1 120 GOTO 210 140 REM ** CONTROL ** 150 PRINT AT 19,1;"########BEGINNING OF ROUND ";Z;"########" 160 PRINT AT 20,1;"%1=STATUS %2=DAMAGE %3=HEAL %4=REG. %5=BIND %6=DROP %7= RAND " 170 INPUT J 180 IF J=0 THEN STOP 190 IF J>7 THEN GOTO 170 200 GOTO (360 AND J=1)+(590 AND J=2)+(1140 AND J=3)+(880 AND J=4)+(1320 AND J=5)+(1240 AND J=6)+(1380 AND J=7) 210 REM ** BEGIN ** 215 PRINT AT 0,0;"HOW MANY CREATURES TO TRACK?" 217 INPUT Q 220 DIM A(Q) 221 DIM B(Q) 222 DIM C(Q) 223 DIM D(Q) 224 DIM E(Q) 230 CLS 240 PRINT AT 20,1;"MONSTER NUMBER?" 250 INPUT F 260 IF F=0 THEN GOTO 290 270 LET A(F)=1 280 GOTO 230 290 FOR F=1 TO Q 300 IF A(F)=0 THEN GOTO 340 310 PRINT AT 20,1;"HIT POINTS FOR ";F 320 INPUT H 330 LET A(F)=H 335 LET B(F)=H 340 NEXT F 350 GOTO 130 360 REM ** DISPLAY STATUS ** 370 CLS 380 LET G=1 390 LET H=0 400 FOR F=1 TO Q 410 IF A(F)=0 THEN GOTO 490 420 IF G>42 THEN GOSUB 510 430 PRINT AT G-1,H;F 440 PRINT AT G,H;A(F) 450 LET H=H+4 460 IF H<28 THEN GOTO 490 470 LET H=1 480 LET G=G+3 490 NEXT F 500 GOTO 580 510 PRINT AT 21,1;"CONTINUE PRINTOUT?" 520 INPUT A$ 530 IF A$="N" THEN GOTO 580 540 LET G=3 550 LET H=1 560 CLS 570 RETURN 580 GOTO 140 590 GOSUB 1530 595 REM ** DAMAGE ** 600 LET Z=Z+1 610 PRINT AT 21,1;"CHARACTER THAT TOOK DAMAGE? " 620 INPUT F 630 IF F=0 THEN GOTO 680 640 PRINT AT 21,1;"AMOUNT OF DAMAGE? " 650 INPUT J 660 LET A(F)=A(F)-J 670 GOTO 610 680 REM ** REGENERATE/ROUND ** 690 FOR F=1 TO Q 700 IF A(F)>=0 THEN LET E(F)=0 710 IF A(F)>=0 THEN GOTO 770 720 IF E(F)=10 THEN GOTO 770 730 IF E(F)=0 THEN GOTO 760 740 LET A(F)=A(F)-1 750 GOTO 770 760 LET E(F)=1 770 IF (C(F)=0 OR A(F)=B(F)) THEN GOTO 830 780 IF (C(F)<10) AND (A(F)Z THEN GOTO 830 810 LET A(F)=A(F)+3 820 IF A(F)>B(F) THEN LET A(F)=B(F) 830 NEXT F 840 GOTO 360 850 LET A(F)=A(F)+C(F) 860 IF A(F)>B(F) THEN LET A(F)=B(F) 870 GOTO 830 880 REM ** REGENERATE ** 890 LET R=1 900 FOR F=1 TO Q 902 LET B(F)=A(F) 904 NEXT F 910 REM ** TROLLS ** 920 GOSUB 1530 930 PRINT AT 20,1;"FIRST TROLL NUMBER?" 940 INPUT K 950 IF K=0 THEN GOTO 1040 960 PRINT AT 20,1;"LAST TROLL NUMBER? " 970 INPUT L 980 IF K>L THEN GOTO 1030 990 IF A(K)<1 THEN GOTO 1010 1000 LET C(K)=10 1010 LET K=K+1 1020 GOTO 980 1030 GOTO 930 1040 REM ** OTHER REGENERATE ** 1050 GOSUB 1530 1060 PRINT AT 20,1;"OTHER REGENERATING CREATURE?" 1070 INPUT F 1080 IF F=0 THEN GOTO 1130 1090 PRINT AT 20,1;"REGENERATION PER ROUND? " 1100 INPUT M 1110 LET C(F)=M 1120 GOTO 1060 1130 GOTO 360 1140 REM ** HEAL ** 1150 GOSUB 1530 1160 PRINT AT 20,1;"CHARACTER THAT WAS HEALED?" 1170 INPUT F 1180 IF F=0 THEN GOTO 1230 1190 PRINT AT 20,1;"AMOUNT OF CURE? " 1200 INPUT N 1210 IF N=1000 THEN LET A(F)=B(F) 1212 IF N<>1000 THEN LET A(F)=A(F)+N 1220 GOTO 1160 1230 GOTO 360 1240 REM ** DROP CHARACTERS ** 1250 GOSUB 1530 1260 PRINT AT 20,1;"CHARACTER TO DROP FROM STATUS?" 1270 INPUT F 1280 IF F=0 THEN GOTO 1310 1290 LET A(F)=0 1295 LET B(F)=0 1300 GOTO 1260 1310 GOTO 360 1320 REM ** BIND ** 1330 PRINT AT 20,1;"CHARACTER NUMBER BOUND?" 1332 INPUT F 1340 IF F=0 THEN GOTO 1370 1350 LET E(F)=10 1360 GOTO 1330 1370 GOTO 360 1380 REM ** RANDOM ROLLS ** 1390 CLS 1400 PRINT "WHAT SIDED DICE?" 1410 INPUT F 1420 IF F=0 THEN GOTO 1510 1430 PRINT "NUMBER OF TIMES?" 1440 INPUT G 1445 CLS 1450 FOR H=1 TO G 1470 LET K=INT (F*RND)+1 1480 PRINT K 1490 NEXT H 1492 PRINT "(PRESS %E%N%T%E%R TO GO ON)" 1495 PAUSE 4E4 1500 GOTO 1390 1510 CLS 1520 GOTO 360 1530 PRINT AT 20,1;" " 1540 PRINT AT 21,1;" " 1570 RETURN 1600 STOP 1610 REM RAND USR 14336 1620 REM SAVE "TRACK.B1" 1625 SAVE "1021%0" 1630 RUN ```