100 REM BASIC Month 6: The Mandelbaum Set 110 REM http://reddit.com/r/RetroBattlestations 120 REM written by FozzTexx 130 REM "You think you're better than me?" 140 OPTION BASE 0 150 DIM GD(4):DIM SZ(2):DIM RZ(2) 160 DIM CM(9):DIM NT(9):DIM NM(9):DIM OM(9) 200 REM === Initialize variables and constants 210 PI = 3.14159265359:DIM PT(128) 220 GD(0) = 33:GD(1) = 138:GD(2) = 200 230 CM(0) = 1:CM(1) = 0:CM(2) = 0 240 CM(3) = 0:CM(4) = 1:CM(5) = 0 250 CM(6) = 0:CM(7) = 0:CM(8) = 1 260 GW = GD(2) * GD(2) / GD(1) 270 TH = GD(2) + 5:GOSUB 2630:TH = TH + SZ(1):GOSUB 2630:TH = TH + SZ(1) 280 RZ(0) = 1100:RZ(1) = 850:REM Width & height of page 285 PC = 8:CP = 1:REM Number of pens 290 SX = (RZ(0) - RZ(0) * 0.05) / GW:SY = (RZ(1) - RZ(1) * 0.07) / TH 300 SK = SX:IF SY < SK THEN SK = SY 310 PRINT "IN;SP1;VS10;" 320 REM "What in holy hell?" 330 X = -GW / 2:Y = -GD(2) / 2:GOSUB 2030:REM Translate 340 X = SK:Y = SK:GOSUB 2230:REM Scale 350 X = RZ(0) / 2:Y = RZ(1) / 2:GOSUB 2030:REM Translate 360 GOSUB 2820 370 RESTORE 380 GOSUB 2630:GOSUB 2720 390 GOSUB 2630 400 X = (GW - SZ(0)) * SK:Y = (GD(2) + SZ(1) + 5) * SK 410 GOSUB 2030:GOSUB 2720:GOSUB 2920 420 GOSUB 2630 430 GX = GD(1) / 2:GY = GD(2) / 2:GB = GY - GX:OO = GD(2) * GD(2) / GD(1) - GD(1) 440 GOSUB 4510 500 REM "Step aside, string bean." 510 X = -RZ(0) / 2:Y = -RZ(1) / 2:GOSUB 2030:REM Translate 520 A = PI / 2:GOSUB 2130:REM Rotate 530 X = GD(1) / GD(2):Y = X:GOSUB 2230:REM Scale 540 X = RZ(0) / 2 + (GW / 2 - GD(1) / 2) * SK:Y = RZ(1) / 2:GOSUB 2030:REM Translate 550 GOSUB 4510 560 IF HT > 1 THEN GOTO 510 570 GOSUB 4610 580 PRINT "SP0;PA";RZ(0);RZ(1);";" 999 QUIT 1000 REM === Update current transformation matrix 1010 REM - Input: 3x3 matrix in 1D array NT 1020 REM - Updates 3x3 Matrix in 1D array CM 1030 FOR R = 0 TO 2 1040 FOR C = 0 TO 2 1050 NM(R * 3 + C) = 0 1060 FOR K = 0 TO 2 1070 NM(R * 3 + C) = NM(R * 3 + C) + NT(R * 3 + K) * CM(K * 3 + C) 1080 NEXT K 1090 NEXT C 1100 NEXT R 1110 FOR K = 0 TO 3 * 3 - 1 1120 CM(K) = NM(K) 1130 NEXT K 1140 RETURN 2000 REM === Translate - move origin 2010 REM - Input: X, Y 2020 REM - Updates current transformation matrix in CM 2030 NT(0) = 1:NT(1) = 0:NT(2) = X 2040 NT(3) = 0:NT(4) = 1:NT(5) = Y 2050 NT(6) = 0:NT(7) = 0:NT(8) = 1 2060 GOSUB 1030 2070 RETURN 2100 REM === Rotate - rotate drawing space 2110 REM - Input: Angle in radians in A 2120 REM - Updates current transformation matrix in CM 2130 NT(0) = COS(A):NT(1) = -SIN(A):NT(2) = 0 2140 NT(3) = -NT(1):NT(4) = NT(0):NT(5) = 0 2150 NT(6) = 0:NT(7) = 0:NT(8) = 1 2160 GOSUB 1030 2170 RETURN 2200 REM === Scale - modify unit lengths of drawing 2210 REM - Input: X, Y 2220 REM - Updates current transformation matrix in CM 2230 NT(0) = X:NT(1) = 0:NT(2) = 0 2240 NT(3) = 0:NT(4) = Y:NT(5) = 0 2250 NT(6) = 0:NT(7) = 0:NT(8) = 1 2260 GOSUB 1030 2270 RETURN 2300 REM === Transform single point using current transformation matrix 2310 REM - Input: X, Y 2320 REM - Returns transformed point in X and Y 2330 NT(0) = X:NT(1) = Y:NT(2) = 1 2340 FOR R = 0 TO 2 2350 NM(R) = 0 2360 FOR K = 0 TO 2 2370 NM(R) = NM(R) + NT(K) * CM(R * 3 + K) 2380 NEXT K 2390 NEXT R 2400 X = NM(0):Y = NM(1) 2410 RETURN 2500 REM == Transform single point and convert to int and scale to plotter units 2510 GOSUB 2330 2520 X = INT(X) * 10:Y = (RZ(1) - INT(Y)) * 10 2530 RETURN 2600 REM === Load object from DATA 2610 REM - Reads the next object from DATA and leaves size in array SZ 2620 REM and paths in array PT 2630 ZI = 0:READ ZX:SZ(0) = ZX:READ ZY:SZ(1) = ZY 2640 READ ZC:PT(ZI) = ZC:ZI = ZI + 1 2650 IF ZC = 0 THEN RETURN 2660 FOR ZJ = 1 TO ZC:READ ZX:READ ZY 2670 PT(ZI) = ZX:ZI = ZI + 1:PT(ZI) = ZY:ZI = ZI + 1 2680 NEXT ZJ 2690 GOTO 2640 2700 REM === Draw path 2710 REM - Input: paths to draw in array PT 2720 ZI = 0 2730 ZC = PT(ZI):ZI = ZI + 1:IF ZC = 0 THEN RETURN 2740 X = PT(ZI):ZI = ZI + 1:Y = PT(ZI):ZI = ZI + 1 2745 GOSUB 2510:LX = X:LY = Y:FP = 0 2750 FOR ZJ = 1 TO ZC - 1 2760 X = PT(ZI):ZI = ZI + 1:Y = PT(ZI):ZI = ZI + 1 2770 GOSUB 2510 2771 IF FP = 0 AND (LX <> X OR LY <> Y) THEN PRINT "PA";LX;LY;";PD;":FP = 1 2775 IF LX <> X OR LY <> Y THEN PRINT "PA";X;Y;";" 2776 LX = X:LY = Y 2780 NEXT ZJ 2785 IF FP = 1 THEN PRINT "PU;" 2790 GOTO 2730 2800 REM == Save current transformation matrix 2810 REM Copies array CM to array OM 2820 FOR I = 0 TO 8 2830 OM(I) = CM(I) 2840 NEXT I 2850 RETURN 2900 REM == Restore transformation matrix 2910 REM Copies array OM to array CM 2920 FOR I = 0 TO 8:CM(I) = OM(I) 2930 NEXT I 2940 RETURN 3000 REM Mandelbaum arc 3010 REM - Input: Arc center at CX,CY; Start/end radians in SA,EA 3020 REM "If you want to live in a butcher shop, I'm gonna treat you like a piece of meat." 3030 IF (EA < SA) THEN EA = EA + 2 * PI 3040 NW = SZ(0):NH = SZ(1):NS = GD(0) / NW:SH = NH * NS 3050 RO = GD(1) / 2:RI = RO - GD(0) 3060 AL = (EA - SA) * GD(1) / 2:SG = INT(AL / SH) 3070 GA = (EA - SA) / SG 3080 GC = COS(2 * PI - GA):GS = SIN(2 * PI - GA):ZC = COS(0):ZS = SIN(0) 3090 F1 = CX + RI * GC:G1 = CY + RI * GS 3100 F2 = CX + RO * GC:G2 = CY + RO * GS 3110 F3 = CX + RI * ZC:G3 = CY + RI * ZS 3120 F4 = CX + RO * ZC:G4 = CY + RO * ZS 3130 D1 = F3 - F1:D2 = G3 - G1:D3 = F4 - F2:D4 = G4 - G2 3140 L1 = SQR(D1 * D1 + D2 * D2):L2 = SQR(D3 * D3 + D4 * D4) 3150 GOSUB 2820 3160 X = CX:Y = CY:GOSUB 2330:AX = X:AY = Y 3170 REM Walk through PT and draw 3180 FOR SN = 0 TO SG - 1 3190 GOSUB 2920 3200 X = -AX:Y = -AY:GOSUB 2030:REM Translate 3210 A = 2 * PI - (SA + SN * GA):GOSUB 2130:REM Rotate 3220 X = AX:Y = AY:GOSUB 2030:REM Translate 3230 ZI = 0 3240 ZC = PT(ZI):ZI = ZI + 1:IF ZC = 0 THEN GOTO 3360 3250 X = PT(ZI) * NS:ZI = ZI + 1 3260 Y = PT(ZI) * NS * (L1 - 1 + (L2 - L1 - 1) * (X / GD(0))) / L2:ZI = ZI + 1 3270 X = X + CX + RI:Y = Y + CY 3275 GOSUB 2510:LX = X:LY = Y:FP = 0 3280 FOR ZJ = 1 TO ZC - 1 3290 X = PT(ZI) * NS:ZI = ZI + 1 3300 Y = PT(ZI) * NS * (L1 - 1 + (L2 - L1 - 1) * (X / GD(0))) / L2:ZI = ZI + 1 3310 X = X + CX + RI:Y = Y + CY 3320 GOSUB 2510 3321 IF FP = 0 AND (LX <> X OR LY <> Y) THEN PRINT "PA";LX;LY;";PD;":FP = 1 3325 IF LX <> X OR LY <> Y THEN PRINT "PA";X;Y;";" 3326 LX = X:LY = Y 3340 NEXT ZJ 3345 IF FP = 1 THEN PRINT "PU;" 3350 GOTO 3240 3360 NEXT SN 3370 GOSUB 2920 3380 RETURN 4000 REM Mandelbaum line 4010 REM - Input: Start and end diagonal corners in X1,Y1 and X2,Y2 4020 REM "Wrong attitude, you're not bringing that trash into my house." 4030 NW = SZ(0):NH = SZ(1) + 1 4040 XD = X2 - X1:YD = Y2 - Y1 4050 IF XD > 0 AND YD < 0 THEN A = 0:WD = XD:HT = YD 4060 IF XD < 0 AND YD < 0 THEN A = 1.5 * PI:HT = XD:WD = YD 4070 IF XD < 0 AND YD > 0 THEN A = PI:WD = XD:HT = YD 4080 IF XD > 0 AND YD > 0 THEN A = 0.5 * PI:HT = XD:WD = YD 4090 WD = ABS(WD):HT = ABS(HT) 4100 NS = WD / NW:SH = INT(NH * NS) 4110 SG = INT((HT + SH - 1) / SH):SH = HT / SG 4120 SX = GD(0) / NW:SY = SH / NH 4130 GOSUB 2820 4140 AX = X1:AY = Y1:X = X1:Y = Y1:GOSUB 2330:OX = X:OY = Y 4150 X = X2:Y = Y2:GOSUB 2330:XD = X - OX:YD = Y - OY 4160 X = 0:Y = 0:GOSUB 2330 4170 X = -X:Y = -Y:GOSUB 2030:REM Translate 4180 GOSUB 2130:REM Rotate 4190 X = SX:Y = SY 4200 IF (XD < 0 AND YD < 0) OR (XD > 0 AND YD > 0) THEN Y = SX:X = SY 4210 GOSUB 2230:REM Scale 4220 X = OX:Y = OY:GOSUB 2030:REM Translate 4230 REM Walk through PT and draw 4240 FOR SN = 0 TO SG - 1 4250 ZI = 0 4260 ZC = PT(ZI):ZI = ZI + 1:IF ZC = 0 THEN GOTO 4360 4270 X = PT(ZI):ZI = ZI + 1 4280 Y = PT(ZI) * (SH - 1) / SH - SN * (SH / SY):ZI = ZI + 1 4285 GOSUB 2510:LX = X:LY = Y:FP = 0 4290 FOR ZJ = 1 TO ZC - 1 4300 X = PT(ZI):ZI = ZI + 1 4310 Y = PT(ZI) * (SH - 1) / SH - SN * (SH / SY):ZI = ZI + 1 4320 GOSUB 2510 4321 IF FP = 0 AND (LX <> X OR LY <> Y) THEN PRINT "PA";LX;LY;";PD;":FP = 1 4325 IF LX <> X OR LY <> Y THEN PRINT "PA";X;Y;";" 4330 LX = X:LY = Y 4340 NEXT ZJ 4345 IF FP = 1 THEN PRINT "PU;" 4350 GOTO 4260 4360 NEXT SN 4370 GOSUB 2920 4380 REM Return height to decide if it's time to stop 4390 X = AX:Y = AY + SH:GOSUB 2330 4400 HT = SQR((X - OX) * (X - OX) + (Y - OY) * (Y - OY)) 4410 RETURN 4500 REM === G 4510 CP = CP + 1:IF CP > PC THEN CP = 1 4520 PRINT "SP";CP;";" 4530 CX = GX:CY = GY - GB:SA = 0:EA = PI:GOSUB 3030 4540 X1 = GD(0):Y1 = GY - GB:X2 = 0:Y2 = GY + GB:GOSUB 4030 4550 CX = GX:CY = GY + GB:SA = PI:EA = 0:GOSUB 3030 4560 X1 = GD(1):Y1 = GY + GB:X2 = GX:Y2 = GY + GB - GD(0):GOSUB 4030 4570 RETURN 4600 REM === O 4610 CX = GX + OO:CY = GY - GB:SA = 0:EA = PI:GOSUB 3030 4620 X1 = GD(0) + OO:Y1 = GY - GB:X2 = OO:Y2 = GY + GB:GOSUB 4030 4630 CX = GX + OO:CY = GY + GB:SA = PI:EA = 0:GOSUB 3030 4640 X1 = GD(1) - GD(0) + OO:Y1 = GY + GB:X2 = GD(1) + OO:Y2 = GY - GB:GOSUB 4030 4650 RETURN 9000 REM "All aboard the pain train." 9010 DATA 39,16,15,3,-16,0,-16,0,-13,3,-13,3,-3,0,-3,0,0,10,0,10,-3,6,-3 9020 DATA 6,-13,10,-13,10,-16,6,-16,3,-16,11,16,-16,12,-16,12,-13,16,-13 9030 DATA 16,0,19,0,19,-13,23,-13,23,-16,19,-16,16,-16,5,25,-16,27,-16 9040 DATA 27,-13,25,-13,25,-16,19,36,-9,33,-10,32,-11,34,-13,36,-12,39 9050 DATA -12,34,-16,30,-14,29,-11,32,-7,35,-6,36,-5,34,-3,32,-4,29,-4 9060 DATA 34,0,38,-1,39,-5,36,-9,0 9070 DATA 53,16,15,23,-13,23,-16,20,-16,16,-16,13,-16,13,-13,16,-13,16 9080 DATA -3,13,-3,13,0,23,0,23,-3,20,-3,20,-13,23,-13,18,53,-13,53,-16 9090 DATA 46,-16,43,-16,43,-13,43,-10,43,-6,43,-3,43,0,53,0,53,-3,46,-3 9100 DATA 46,-6,51,-6,51,-10,46,-10,46,-13,53,-13,11,10,-16,7,-16,3,-16 9110 DATA 0,-16,0,-13,3,-13,3,0,7,0,7,-13,10,-13,10,-16,14,37,-16,33,-9 9120 DATA 29,-16,26,-16,26,0,29,0,29,-10,32,-4,34,-4,37,-10,37,0,40,0,40 9130 DATA -16,37,-16,0 9140 DATA 52,8,5,0,0,0,-8,3,-4,5,-8,5,0,3,10,0,8,-8,6,0,2,7,-4,9,-4,4,11 9150 DATA 0,11,-8,15,0,15,-8,6,18,-8,16,-8,16,0,18,0,20,-4,18,-8,2,23,-4 9160 DATA 21,-4,4,25,-8,21,-8,21,0,25,0,3,31,0,26,0,26,-8,12,32,-4,35,-4 9170 DATA 36,-5,36,-7,35,-8,32,-8,32,0,35,0,35,0,36,-1,36,-3,35,-4,3,41 9180 DATA 0,39,-8,37,0,2,38,-4,40,-4,6,42,-8,42,-1,44,0,45,0,47,-1,47,-8 9190 DATA 5,48,0,48,-8,50,-4,52,-8,52,0,0