This program is a US federal income tax planning tool that compares projected 1982 and 1983 tax liabilities side by side. It collects income items (wages, dividends, interest, business income, and up to 13 categories), calculates adjusted gross income, itemized deductions (including the medical expense floor at 3% of AGI for 1982 and 5% for 1983), zero bracket amounts, exemptions, and taxable income, then looks up the computed tax using bracket tables stored in parallel arrays. Three filing statuses are supported: single, married filing jointly, and married filing separately. Data for both tax years is held simultaneously in the arrays S() and T(), and results can be printed to a ZX printer using the COPY command triggered by pressing “Z” at review screens.
Program Analysis
Program Structure
The program is organized into clearly labeled subroutine blocks separated by REM lines and STOP guards. Control flows through a main menu at line 500 that dispatches on a single keypress to five functions.
- Lines 1–195: Constants and string initialization
- Line 240 / 1000–1060: Description loader (populates
D$()) - Lines 500–690: Main menu loop
- Lines 2000–2310: Data clear submenu
- Lines 3000–3280: 1982 value entry
- Lines 3500–3785: 1983 value entry
- Lines 4000–4070: Tape save
- Lines 5000–5490: 1982 tax table loader and bracket calculation
- Lines 5500–5900: 1983 tax table loader and bracket calculation
- Lines 6000–6897: Results display with optional hardcopy
- Lines 6900–7299: 1982 tax bracket data (single and married)
- Lines 7400–7639: 1983 tax bracket data (single and married)
- Lines 9500–9560: Right-justify number display subroutine
Data Storage
All 26 tax line items for 1982 are stored in the numeric array S(26) and for 1983 in T(26). Line descriptions are stored in the string array D$(26,18) (26 entries, 18 characters wide). The tax bracket tables are loaded at runtime into three parallel arrays: bracket floor values (A()/D()), base tax amounts (B()/E()), and marginal rates (C()/F()).
Tax Calculation Logic
The bracket lookup at lines 5420–5470 (1982) and 5810–5870 (1983) scans the bracket floor array until the taxable income falls below the next bracket, then backs up one step and applies the formula: base_tax + (taxable_income − bracket_floor) × rate / 100, rounded to the nearest dollar using INT(...+.5).
Medical expense deduction logic differs between years: 1982 uses a 3% AGI floor (line 3104) and also incorporates a medical insurance premium half-deduction capped at $150; 1983 uses a 5% AGI floor (line 3604) with no insurance premium split, reflecting actual tax law changes between the two years.
Line 3185 applies a special rule: if only charitable contributions are entered among deductions (medical, taxes, interest, and miscellaneous all zero), the contribution amount is divided by 4. Line 3192 then collapses the entire deduction total to just that contribution value. The 1983 equivalent at lines 3685–3692 handles this similarly.
Filing Status Handling
Filing status is stored in the variable S (1=single, 2=married, 3=married filing separately). After the zero bracket amount is assigned for status 3 (line 3210/3710), status is immediately reset to 1 (line 3215/3715) so that the single-filer tax bracket table is used for married filing separately — which matches IRS rules of the era.
Notable Techniques
- The
PAUSE 4E4idiom (approximately 40,000 frame pause) combined withINKEY$is used throughout the menu system to wait for a keypress without blocking execution indefinitely. - The right-justify subroutine at line
9500usesSTR$andLENto position values at a fixed columnCby computingTAB(C - LEN J$ + 1), giving the results screen a column-aligned appearance. - The
COPYcommand is offered at both results screens (lines6056and6894) by testing for keypress “Z”, sending the screen contents to a ZX printer. - Income credits at
D$(13)are forced negative byLET S(13)=-1*S(13)(line3035) so they reduce the running income total correctly when summed. - The bracket data subroutine at line
6900is called once per bracket entry via aFORloop (lines 5070–5080), causing each pass to overwrite all array entries — effectively the loop only needs one iteration since the subroutine sets all values unconditionally. The loop is harmless but redundant.
Bugs and Anomalies
- Line
1027misspells “PARTNERSHIP” as “PARTNERSJIP” — a data entry error that will appear on-screen and in printouts. - Line
7611setsD(12)=27278for the 1983 married bracket floor, which is clearly wrong (it should be approximately 85,600 by analogy with the 1982 table and actual 1983 rates). The corresponding base taxE(12)=27278coincidentally matches the bracket floor value, suggesting a copy-paste error. - At line
3192, the code setsS(2)(dividends) rather thanS(20)(total deductions), which appears to be a typographical error where a zero was dropped — this would corrupt the dividends entry rather than setting total deductions. - The variable
Sserves double duty as both the filing status integer and the index into theS()income array. After status is used to setS(21)and then reassigned to 1 for married-separate filers, subsequent code usingSas a numeric index could produce unexpected results if not carefully tracked. - The
FORloop callingGO SUB 6900at lines 5070–5080 iteratesBtimes (12 or 13), but the subroutine unconditionally sets all array elements on every call. Only one call is necessary; the repetition wastes time but does not cause incorrect results. - Line
3106applies the medical insurance premium amountIonly when the net medical deduction would otherwise be zero or negative, butIholds a halved, capped value from lines 3058–3060 rather than the full premium — this matches the 1982 half-premium rule but the logic flow is non-obvious.
Content
Source Code
1 REM TAX ***PLANER***
2 REM ...COPYRIGHT..1982.....
3 REM ...BY..H.GESCHWIND.....
100 REM ***INITIALIZE***
110 DIM D$(26,18)
120 DIM S(26)
130 DIM T(26)
135 LET M$="PRESS ANY KEY TO CONTINUE"
140 LET P$="ENTER"
150 LET X$="--------------------------------"
160 LET Y$=" 1982"
170 LET Z$=" 1983"
180 LET V$="INCOME"
190 LET W$="DEDUCTIONS"
195 LET H$="---->"
200 LET S=0
210 LET M=0
220 LET N=0
225 LET F$=" ENTER FILING STATUS:-->1 FOR SINGLE,-->2 FOR MARRIED,-->3 FORMARRIED FILING SEPARATELY"
240 GO SUB 1000
499 REM ***MENU***
500 PRINT AT 3,6;" TAX PLANNER"
510 PRINT AT 6,4;"-->PRESS DESIRED FUNCTION"
520 PRINT AT 8,6;"1. ENTER VALUES"
525 PRINT AT 9,6;"2. REVIEW RESULTS"
530 PRINT AT 10,6;"3. CLEAR DATA"
570 PRINT AT 11,6;"4. SAVE DATA"
580 PRINT AT 12,6;"5. ENTER 1983 VALUES ONLY"
590 PAUSE 4E4
600 LET K$=INKEY$
610 IF K$<"1" OR K$>"5" THEN GO TO 690
620 IF K$="1" THEN GO TO 3000
622 IF K$="2" THEN GO TO 6000
624 IF K$="3" THEN GO TO 2000
626 IF K$="4" THEN GO TO 4000
627 IF K$="5" THEN GO TO 3500
690 GO TO 500
998 STOP
999 REM ***DESCRIPTIONS***
1000 CLS
1005 PRINT AT 21,5;"LOADING DESCRIPTIONS"
1020 LET D$(1)="SALARIES, WAGES"
1021 LET D$(2)="DIVIDENDS"
1022 LET D$(3)="INTEREST INCOME"
1023 LET D$(4)="NET BUS. INCOME"
1024 LET D$(5)="OTHER GAINS/LOSSES"
1025 LET D$(7)="PENSIONS,ANNUITIES"
1026 LET D$(8)="RENTS, ROYALTIES"
1027 LET D$(9)="PARTNERSJIP INC."
1028 LET D$(10)="TRUST/ESTATE INC."
1029 LET D$(11)="CHAPTER""S""CORP."
1030 LET D$(12)="OTHER INCOME"
1031 LET D$(13)="INCOME CREDITS(*)"
1032 LET D$(14)="ADJ. GROSS INCOME"
1034 LET D$(15)="MEDICAL EXPENSES"
1035 LET D$(16)="TAXES"
1036 LET D$(17)="CONTRIBUTIONS"
1037 LET D$(18)="INTEREST EXPENSES"
1038 LET D$(19)="CASUALTY LOSS,MISC."
1039 LET D$(20)="TOTAL DEDUCTIONS"
1040 LET D$(21)="ZERO BRACKET"
1041 LET D$(22)="NET DEDUCTIONS"
1042 LET D$(23)="INC.BEF.EXEMPTIONS"
1043 LET D$(24)="EXEMPTIONS"
1044 LET D$(25)="TAXABLE INCOME"
1045 LET D$(26)="INCOME TAX"
1050 CLS
1060 RETURN
1998 STOP
1999 REM ***CLEAR***
2000 CLS
2010 PRINT AT 6,4;"-->PRESS DESIRED FUNCTION"
2020 PRINT AT 8,6;"1. DELETE 1982 VALUES"
2030 PRINT AT 9,6;"2. DELETE 1983 VALUES"
2050 PAUSE 4E4
2060 LET K$=INKEY$
2070 IF K$<"1" OR K$>"2" THEN GO TO 2090
2072 IF K$="1" THEN GO TO 2100
2074 IF K$="2" THEN GO TO 2300
2090 GO TO 2010
2100 DIM S(26)
2101 LET S=0
2105 CLS
2110 GO TO 500
2300 DIM T(26)
2301 LET S=0
2305 CLS
2310 GO TO 500
2999 REM ***82 VALUES***
3000 CLS
3001 LET M=0
3002 LET N=0
3003 LET I=0
3005 PRINT F$
3006 INPUT S
3007 IF S<1 OR S>3 THEN GO TO 3005
3008 CLS
3010 FOR I=1 TO 13
3015 PRINT AT 10,(31-LEN V$)/2;V$
3016 PRINT X$
3020 PRINT P$
3025 PRINT D$(I)+" FOR "+Y$
3030 INPUT S(I)
3035 IF S(13) THEN LET S(13)=-1*S(13)
3036 PRINT H$; S(I)
3037 PAUSE 180
3038 CLS
3039 LET M=M+S(I)
3040 NEXT I
3041 LET S(14)=M
3042 LET M=0
3050 PRINT AT 10,(31-LEN W$)/2;W$
3051 PRINT X$
3052 PRINT P$+" FULL AMOUNT OF MEDICAL INSURANCE PREMIUMS"
3053 INPUT I
3054 PRINT H$;I
3055 PAUSE 180
3056 CLS
3058 LET I=I/2
3060 IF I>150 THEN LET I=150
3062 PRINT AT 10,(31-LEN W$)/2;W$
3064 PRINT X$
3066 PRINT P$
3068 PRINT D$(15)+" FOR "+Y$
3102 INPUT N
3103 PRINT H$;N
3104 LET M=INT (3/100*S(14)+.5)
3105 LET S(15)=N-M
3106 IF S(15)<=0 THEN LET S(15)=0+I
3107 LET M=0
3108 LET N=0
3109 CLS
3110 FOR I=16 TO 19
3111 PRINT AT 10,(31-LEN W$)/2;W$
3112 PRINT X$
3120 PRINT P$
3125 PRINT D$(I)+" FOR "+Y$
3130 INPUT S(I)
3140 PRINT H$;S(I)
3150 PAUSE 180
3160 CLS
3170 LET M=M+S(I)
3180 NEXT I
3185 IF S(15) AND S(16)=0 AND S(18)=0 AND S(19)=0 THEN LET S(17)=S(17)/4
3190 LET S(20)=M+S(15)
3192 IF S(15)=0 AND S(16)=0 AND S(18)=0 AND S(19)=0 THEN LET S(2)=S(17)
3195 LET M=0
3200 IF S=1 THEN LET S(21)=2300
3205 IF S=2 THEN LET S(21)=3400
3210 IF S=3 THEN LET S(21)=1700
3215 IF S=3 THEN LET S=1
3220 LET S(22)=S(20)-S(21)
3225 IF S(22)<=0 THEN LET S(22)=0
3230 LET S(23)=S(14)-S(22)
3240 PRINT "ENTER NUMBER OF EXEMPTIONS"
3250 INPUT M
3255 IF M<1 THEN LET M=1
3260 LET S(24)=M*1000
3265 LET M=0
3270 LET S(25)=S(23)-S(24)
3275 CLS
3280 GO SUB 5000
3499 REM ***83 VALUES***
3500 CLS
3501 LET M=0
3502 LET N=0
3503 LET I=0
3505 PRINT F$
3506 INPUT S
3507 IF S<1 OR S>3 THEN GO TO 3505
3508 CLS
3510 FOR I=1 TO 13
3515 PRINT AT 10,(31-LEN V$)/2;V$
3516 PRINT X$
3520 PRINT P$
3525 PRINT D$(I)+" FOR "+Z$
3538 INPUT T(I)
3539 IF T(13) THEN LET T(13)=-1*T(13)
3540 PRINT H$;T(I)
3550 PAUSE 180
3560 CLS
3570 LET N=N+T(I)
3580 NEXT I
3590 LET T(14)=N
3595 LET N=0
3596 PRINT AT 10,(31-LEN W$)/2;W$
3597 PRINT X$
3598 PRINT P$
3599 PRINT D$(15)+" FOR "+Z$
3602 INPUT N
3603 PRINT H$;N
3604 LET M=INT (5/100*T(14)+.5)
3605 LET T(15)=N-M
3606 IF T(15)<=0 THEN LET T(15)=0
3607 LET M=0
3608 LET N=0
3609 CLS
3610 FOR I=16 TO 19
3611 PRINT AT 10,(31-LEN W$)/2;W$
3612 PRINT X$
3620 PRINT P$
3625 PRINT D$(I)+" FOR "+Z$
3630 INPUT T(I)
3640 PRINT H$;T(I)
3650 PAUSE 180
3660 CLS
3670 LET N=N+T(I)
3680 NEXT I
3685 IF T(15)=0 AND T(16)=0 AND T(18)=0 AND T(19)=0 THEN LET T(17)=T(17)/4
3690 LET T(20)=N+T(15)
3692 IF T(15)=0 AND T(16)=0 AND T(18)=0 AND T(19)=0 THEN LET T(20)=T(17)
3695 LET N=0
3700 IF S=1 THEN LET T(21)=2300
3705 IF S=2 THEN LET T(21)=3400
3710 IF S=3 THEN LET T(21)=1700
3715 IF S=3 THEN LET S=1
3717 LET M=0
3718 LET N=0
3720 LET T(22)=T(20)-T(21)
3725 IF T(22)<=0 THEN LET T(22)=0
3730 LET T(23)=T(14)-T(22)
3740 PRINT "ENTER NUMBER OF EXEMPTIONS"
3750 INPUT M
3755 IF M<1 THEN LET M=1
3760 LET T(24)=M*1000
3765 LET M=0
3770 LET T(25)=T(23)-T(24)
3780 GO SUB 5500
3785 GO TO 500
3990 STOP
3999 REM ***SAVE***
4000 CLS
4020 PRINT AT 8,7;"PREPARE RECORDER"
4030 PRINT AT 10,3;M$
4040 PAUSE 4E4
4050 CLS
4060 SAVE "TAX PLANNER"
4070 GO TO 500
4999 REM ***82 TABLE***
5000 CLS
5010 IF S=1 THEN LET B=13
5011 IF S=2 THEN LET B=12
5040 DIM A(B)
5050 DIM B(B)
5060 DIM C(B)
5065 PRINT AT 21,0;"LOADING TAX TABLE"
5070 FOR I=1 TO B
5075 GO SUB 6900
5080 NEXT I
5350 GO TO 5399
5361 STOP
5399 REM ***82 CALC***
5400 LET S(26)=0
5420 IF S(25)<A(1) THEN RETURN
5430 FOR E=2 TO B
5440 IF S(25)<A(E) THEN GO TO 5460
5450 NEXT E
5460 LET E=E-1
5470 LET S(26)=INT ((B(E)+(S(25)-A(E))*C(E)/100)+.5)
5480 LET B=0
5490 RETURN
5491 STOP
5500 CLS
5510 REM ***83 TABLE***
5535 LET B=13
5540 DIM D(B)
5550 DIM E(B)
5560 DIM F(B)
5565 PRINT AT 21,0;"LOADING TAX TABLE"
5570 FOR I=1 TO B
5580 GO SUB 7400
5690 NEXT I
5770 GO TO 5800
5771 STOP
5799 REM ***83 CALC***
5800 LET T(26)=0
5810 IF T(25)<D(1) THEN RETURN
5820 FOR E=2 TO B
5830 IF T(25)<D(E) THEN GO TO 5860
5840 NEXT E
5860 LET E=E-1
5870 LET T(26)=INT ((E(E)+(T(25)-D(E))*F(E)/100)+.5)
5890 LET B=0
5895 CLS
5900 GO TO 500
5999 REM ***PRINT RESULTS***
6000 CLS
6010 PRINT V$;TAB 20;Y$;TAB 27;Z$
6015 PRINT X$
6020 FOR I=1 TO 13
6022 PRINT D$(I);
6024 LET V=S(I)
6026 LET C=24
6028 GO SUB 9500
6030 LET V=T(I)
6032 LET C=31
6034 GO SUB 9500
6035 NEXT I
6040 PRINT X$
6042 PRINT D$(14);
6044 LET V=S(14)
6046 LET C=24
6048 GO SUB 9500
6050 LET V=T(14)
6051 LET C=31
6052 GO SUB 9500
6053 PRINT AT 21,0;M$
6055 IF INKEY$="" THEN GO TO 6055
6056 IF INKEY$="Z" THEN COPY
6059 CLS
6060 PRINT W$;TAB 20;Y$;TAB 27;Z$
6062 PRINT X$
6064 FOR I=15 TO 19
6066 PRINT D$(I);
6068 LET V=S(I)
6070 LET C=24
6072 GO SUB 9500
6074 LET V=T(I)
6076 LET C=31
6078 GO SUB 9500
6080 NEXT I
6100 PRINT X$
6110 FOR I=20 TO 26
6120 PRINT D$(I);
6130 LET V=S(I)
6140 LET C=24
6150 GO SUB 9500
6160 LET V=T(I)
6170 LET C=31
6180 GO SUB 9500
6185 PRINT X$
6200 NEXT I
6890 PRINT AT 21,3;M$
6892 IF INKEY$="" THEN GO TO 6892
6894 IF INKEY$="Z" THEN COPY
6896 CLS
6897 GO TO 500
6900 REM ***82 TAX***
6910 IF S=1 THEN GO TO 7000
6920 IF S=2 THEN GO TO 7200
6925 RETURN
7000 LET A(1)=2500
7001 LET A(2)=3400
7002 LET A(3)=4400
7003 LET A(4)=6500
7004 LET A(5)=8500
7005 LET A(6)=10800
7006 LET A(7)=12900
7007 LET A(8)=15000
7008 LET A(9)=18200
7009 LET A(10)=23500
7010 LET A(11)=28800
7011 LET A(12)=34100
7012 LET A(13)=41500
7013 LET B(1)=0
7014 LET B(2)=132
7015 LET B(3)=272
7016 LET B(4)=608
7017 LET B(5)=948
7018 LET B(6)=1385
7019 LET B(7)=1847
7020 LET B(8)=2330
7021 LET B(9)=3194
7022 LET B(10)=4837
7023 LET B(11)=6692
7024 LET B(12)=8812
7025 LET B(13)=12068
7026 LET C(1)=12
7027 LET C(2)=14
7028 LET C(3)=16
7029 LET C(4)=17
7030 LET C(5)=19
7031 LET C(6)=22
7032 LET C(7)=23
7033 LET C(8)=27
7034 LET C(9)=31
7035 LET C(10)=35
7036 LET C(11)=40
7037 LET C(12)=44
7038 LET C(13)=50
7199 RETURN
7200 LET A(1)=3400
7201 LET A(2)=5500
7202 LET A(3)=7600
7203 LET A(4)=11900
7204 LET A(5)=16000
7205 LET A(6)=20200
7206 LET A(7)=24600
7207 LET A(8)=29900
7208 LET A(9)=35200
7209 LET A(10)=45800
7210 LET A(11)=60000
7212 LET A(12)=85600
7213 LET B(1)=0
7214 LET B(2)=252
7215 LET B(3)=546
7216 LET B(4)=1234
7217 LET B(5)=2013
7218 LET B(6)=2937
7219 LET B(7)=4037
7220 LET B(8)=5574
7221 LET B(9)=7323
7222 LET B(10)=11457
7223 LET B(11)=17705
7224 LET B(12)=30249
7225 LET C(1)=12
7226 LET C(2)=14
7227 LET C(3)=16
7228 LET C(4)=19
7229 LET C(5)=22
7230 LET C(6)=25
7231 LET C(7)=29
7232 LET C(8)=33
7233 LET C(9)=39
7234 LET C(10)=44
7235 LET C(11)=49
7236 LET C(12)=50
7299 RETURN
7400 REM 83 TAX
7410 IF S=1 THEN GO SUB 7500
7420 IF S=2 THEN GO SUB 7600
7425 RETURN
7500 LET D(1)=2300
7501 LET D(2)=3400
7502 LET D(3)=4400
7503 LET D(4)=8500
7504 LET D(5)=10800
7505 LET D(6)=12900
7506 LET D(7)=15000
7507 LET D(8)=18200
7508 LET D(9)=23500
7509 LET D(10)=28800
7510 LET D(11)=34100
7511 LET D(12)=41500
7512 LET D(13)=55300
7513 LET E(1)=0
7514 LET E(2)=121
7515 LET E(3)=251
7516 LET E(4)=866
7517 LET E(5)=1257
7518 LET E(6)=1656
7519 LET E(7)=2097
7520 LET E(8)=2865
7521 LET E(9)=4349
7522 LET E(10)=6045
7523 LET E(11)=7953
7524 LET E(12)=10913
7525 LET E(13)=17123
7527 LET F(1)=11
7528 LET F(2)=13
7529 LET F(3)=15
7530 LET F(4)=17
7531 LET F(5)=19
7532 LET F(6)=21
7533 LET F(7)=24
7534 LET F(8)=28
7535 LET F(9)=32
7536 LET F(10)=36
7537 LET F(11)=40
7538 LET F(12)=45
7539 LET F(13)=50
7598 RETURN
7600 LET D(1)=3400
7601 LET D(2)=5500
7602 LET D(3)=7600
7603 LET D(4)=11900
7604 LET D(5)=16000
7605 LET D(6)=20200
7606 LET D(7)=24600
7607 LET D(8)=29900
7608 LET D(9)=35200
7609 LET D(10)=45800
7610 LET D(11)=60000
7611 LET D(12)=27278
7612 LET D(13)=109400
7613 LET E(1)=0
7614 LET E(2)=231
7615 LET E(3)=504
7616 LET E(4)=1149
7617 LET E(5)=1846
7618 LET E(6)=2644
7619 LET E(7)=3656
7620 LET E(8)=5034
7621 LET E(9)=6624
7622 LET E(10)=10334
7623 LET E(11)=16014
7624 LET E(12)=27278
7625 LET E(13)=38702
7626 LET F(1)=11
7627 LET F(2)=13
7628 LET F(3)=15
7629 LET F(4)=17
7630 LET F(5)=19
7631 LET F(6)=23
7632 LET F(7)=26
7633 LET F(8)=30
7634 LET F(9)=35
7635 LET F(10)=40
7636 LET F(11)=44
7637 LET F(12)=48
7638 LET F(13)=50
7639 RETURN
7999 STOP
9500 REM ***JUSTIFY***
9510 LET XL=INT (ABS V+.005)*SGN V
9540 LET J$=STR$ XL
9550 PRINT TAB (C-LEN J$+1);J$;
9560 RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
