See Also: part 1, part 2, with part 3 and part 4 coming (and maybe more).
These types of posts are probably my favorite. Someone posts something with a coding challenge, and folks start submitting their ideas, and I get to play collector and just repost without doing any work… (Well, except I am submitting ideas as well, this time.)
This all kicked off when Michael Pittsley shared a contest he found in a 1984 issue of UnderColor magazine that challenged BASIC programmers to draw a specific spiral pattern:

Michael tackled it with this code:
10 ' SPIRAL THING
20 '
30 XL=3:YT=0:XR=252:YB=188:PX=3
40 PMODE 4,1
50 PCLS
60 SCREEN 1,1
65 LINE (XL,YB) - (XR-PX,YB),PSET
200 ' RIGHT
210 XR=XR-PX
220 LINE - (XR,YB),PSET
300 ' UP
306 YT=YT+PX
307 IF YT=96 THEN 600
310 LINE - (XR,YT), PSET
400 ' LEFT
410 XL=XL+PX
420 LINE - (XL,YT),PSET
500 ' DOWN
510 YB=YB-PX
520 LINE - (XL,YB),PSET
550 GOTO 200
600 GOTO 600
A nicely formatted and documented (with REMmarks) example of the power BASIC. He was even aware that LINE does not need both a start and end point each time you use it. If you just do “LINE-(x,y),PSET” it will draw from the last point to the new coordinates. This greatly reduces the amount of parsing BASIC has to do versus if you wrote the program always having a pair of start/end points.
Let’s modify it with some timing stuff.
10 ' SPIRAL THING
20 '
25 TIMER=0
30 XL=3:YT=0:XR=252:YB=188:PX=3
40 PMODE 4,1
50 PCLS
60 SCREEN 1,1
65 LINE (XL,YB) - (XR-PX,YB),PSET
200 ' RIGHT
210 XR=XR-PX
220 LINE - (XR,YB),PSET
300 ' UP
306 YT=YT+PX
307 IF YT=96 THEN 600
310 LINE - (XR,YT), PSET
400 ' LEFT
410 XL=XL+PX
420 LINE - (XL,YT),PSET
500 ' DOWN
510 YB=YB-PX
520 LINE - (XL,YB),PSET
550 GOTO 200
600 PRINT TIMER/60
Running it reports 3.16666667 seconds at the end, so really close to the time my version using DRAW got. AND, that is with REMs and spaces and multiple lines to parse. Let’s see what tricks we can do to speed it up by removing spaces, REMs, and packing lines together:
25 TIMER=0:XL=3:YT=0:XR=252:YB=188:PX=3::PMODE4,1:PCLS:SCREEN1,1:LINE(XL,YB)-(XR-PX,YB),PSET
200 XR=XR-PX:LINE-(XR,YB),PSET:YT=YT+PX:IFYT=96THEN600
310 LINE-(XR,YT),PSET:XL=XL+PX:LINE-(XL,YT),PSET:YB=YB-PX:LINE-(XL,YB),PSET:GOTO200
600 PRINT TIMER/60
This drops it down to 3.03333334! Parsing LINE may be faster than parsing a DRAW string. Also, longer line numbers take longer to parse, so we could RENUM0,0,1:
0 TIMER=0:XL=3:YT=0:XR=252:YB=188:PX=3:PMODE4,1:PCLS:SCREEN1,1:LINE(XL,YB)-(XR-PX,YB),PSET
1 XR=XR-PX:LINE-(XR,YB),PSET:YT=YT+PX:IFYT=96THEN3
2 LINE-(XR,YT),PSET:XL=XL+PX:LINE-(XL,YT),PSET:YB=YB-PX:LINE-(XL,YB),PSET:GOTO1
3 PRINTTIMER/60
However, this did not seem to make any consistent measurable difference.
A further optimization could be done by changing the 2-letter variables to 1-letter. But, beyond that, it would take adjusting the logic to find more improvements. Parsing integers is slow, such as “IF YT=96” as is parsing line numbers (thus, lines 1, 2 and 3 should be faster to “GOTO 1” than 100, 200, 300 and “GOTO 100”).
And, one question:: Michael started in from the corner of the screen. Here is a screen shot done in the Xroar emulator with artifact colors turned off so we can see the actual lines better:

This means this version is drawing a few lines less than the version I made. I need to go back and re-read the article and see if I got the details wrong, or if Michael is just keeping the 3-pixel border more consistent. I like the 3-pixel padding, but perhaps the first line to the right on the bottom should have gone further (3 pixel padding) and then at the top left a bit more (3 pixel padding).
Meanwhile, in response to Michael Pittsley‘s post. Andrew Ayers took the version I did and modifies it to work on the CoCo 3. The original contest was a few years before the CoCo 3 even existed, but one would imagine if the article had appeared later it might have had a contest for fastest CoCo 1/2 version, and fastest CoCo 3 version:
A couple more slightly improved CoCo 3 versions of Allen’s code above:
– Andres Ayers
…
Both of these take longer to run than the original Allen posted, even with the high-speed poke…at least, running on XRoar Online (no idea about real hardware).
CoCo 3 RGB b/w 320×192:
5 POKE65497,0
10 TIMER=0
20 HSCREEN2:PALETTE0,0:PALETTE1,63:HCOLOR1
30 W=320:H=191:HDRAW"BM0,191"
40 HDRAW"R=W;"
50 HDRAW"U=H;L=W;"
60 H=H-3:W=W-3
70 HDRAW"D=H;R=W;"
80 H=H-3:W=W-3
90 IF H>0 THEN 50
100 TM=TIMER
110 IF INKEY$="" THEN 110
120 PRINT TM/60
130 POKE65496,0
CoCo 3 RGB b/w 640×192:
5 POKE65497,0
10 TIMER=0
20 HSCREEN4:PALETTE0,0:PALETTE1,63:HCOLOR1
30 W=640:H=191:HDRAW"BM0,191"
40 HDRAW"R=W;"
50 HDRAW"U=H;L=W;"
60 H=H-3:W=W-3
70 HDRAW"D=H;R=W;"
80 H=H-3:W=W-3
90 IF H>0 THEN 50
100 TM=TIMER
110 IF INKEY$="" THEN 110
120 PRINT TM/60
130 POKE65496,0
It has been so long since I worked in BASIC on the CoCo 3 that I had forgotten about HDRAW and such being there. And, as expected, it takes longer to draw 320 or 640 pixel lines than it would to draw the 256 pixel lines on the CoCo 1/2 PMODE 4 display.
This does make me wonder how it would compare if limited to the same 256×192 resolution of PMODE 4. I expect the overhead of banking in and out the CoCo 3 high resolution graphics screens will add some extra time, and likely working with a screen with more than just 1-bit color (on/off pixels) is more memory to plot through.
Anyone want to work on that experiment?
Make it faster!
Revisiting my version from part 1, I changed the screen to PCLS1 (to make it white) and set COLOR 0 (to make the drawing black) so it would look like the printout in the magazine. This looks nice, but now we cannot tell how close to the original border of the image my results are:

I also see that because of the 256×191, the very last line does not appear to have a 3 pixel padding. Maybe we can look at the math later.
I simply took my version and combined lines and removed any spaces:
0 'SPIRAL2.BAS
5 FORA=1TO1000:NEXT
10 TIMER=0:PMODE4,1:PCLS1:SCREEN1,1:COLOR0:W=255:H=191:DRAW"BM0,191R=W;"
50 DRAW"U=H;L=W;":H=H-3:W=W-3:DRAW"D=H;R=W;":H=H-3:W=W-3:IFH>0THEN50
100 TM=TIMER
110 IF INKEY$="" THEN 110
120 PRINT TM/60
I could also do the “RENUM0,0,1” trick, but all of this only gets me to 3.016666667 seconds.
NOTE: I put a FOR/NEXT at the start so when I type “RUN” I have a moment to release the ENTER key before the timing starts. If you hit a key during the drawing, BASIC tries to handle that key and it will slow down the program. Run it and pound on the keyboard while it is drawing and you can see it slow down quite a bit (I got 3.7 seconds doing that).
But I digress…
Let’s collect some more examples, and see what other methods folks come up with. Now I want to get the same logic, just DRAW versus LINE to draw the lines, and see which one is faster.
To be continued…