UnderColor’s spiral challenge from 1984 – part 1

See Also: part 1, part 2, with part 3 and part 4 coming (and maybe more).

And now back to CoCo …

– Michael Pittsley posted in the TRS-80 Color Computer (CoCo) group on Facebook:

Many of us have our CoCos and have memories or how good we once were writing basic programs on it. Including myself. I found this article in the first UnderColor magazine. It was a contest to see who could write an ECB program that created a spiral. — Write an Extended Basic program that draws a spiral figure on graphics screen 0 on PMODE 4. The figure, when done should look like the picture. Use any combination of Basic commands, but no assembly language. The winner will be the person whose program executes in the shortest possible time. (Entries that simply list a series of LINE commands will be disqualified). I took a stab at it and realized how much I had forgotten about basic, so this was fun for me. I put my results as the first comment. Feel free to try your hand at it, post a screen shot and the time it took to complete.

– Michael Pittsley

This caught my attention.

UnderColor magazine (1984-1985) was one I never saw, though the name sounds familiar so I may have at least read a reference to it, or seen an ad for it somewhere. You can find the issues preserved here:

Search – TRS-80 Color Computer Archive

The article in question appeared in the first issue, which you can read here:

UNDERCOLOR Vol1 No 1 Dec 10, 1984

The article, by Bill Barden, presented a contest to see who could write a program in BASIC (no assembly allowed) that would generate a spiral as demonstrated by this graphic:

The winner would be the program that could do this in the least amount of time.

I have discussed drawing spirals on the CoCo in the past, but not like this. I also wrote about spirals for a text mode attract screen, but not like this.

So now let’s spiral like this.

LINE versus DRAW

The most obvious approach would be to use the LINE command. It takes a set of X and Y coordinates and draws a line between them, like this:

LINE (0,0)-(255,191),PSET

However, with what I know about BASIC these days (and wish I knew back then), that is alot of parsing of numbers and characters and such. That makes it slower than it might need to be.

One shortcut is that LINE remembers where it left off, so you can start a new line just by specifying the destination:

LINE-(127,0),PSET

Doing this trick should speed up a spiral program, since you only need to give the starting point once, then you can just “draw to the next spot” from then on out.

But I did not attempt this. Instead, I thought about DRAW.

The DRAW command is very powerful, and does allow you to draw to specific coordinates. You can do a “blank” draw just to move the starting point, like this:

DRAW"BM0,191"

That will do a Blank Move to (0,191), which is the lower left corner of the screen and the location where the spiral is supposed to start.

You can then do things like…

DRAW"R10"

…and that will draw a line 10 pixels to the right. (Well, the coordinates are scaled, I think, so it is 10 pixels on a PMODE 4 screen, but at other lower resolutions, that number of pixels will be scaled down.)

How can we spiral like that? One way would be to build a string and append it:

X=100
X$=STR$(X)
DRAW"R"+X$

That works, but all that parsing and creating strings and such would certainly be slower than using a built-in feature of DRAW which lets you use a variable inside the quotes! You just put “=” before the variable name, and a “;” after it.

X=100
DRAW"R=X;"

That will draw to the right however many pixels X is set to!

Could this be faster than line?

Here is what I came up with:

0 'SPIRAL1.BAS
10 TIMER=0
20 PMODE4,1:PCLS:SCREEN1,1
30 W=255:H=191:DRAW"BM0,191"
40 DRAW"R=W;"
50 DRAW"U=H;L=W;"
60 H=H-3:W=W-3
70 DRAW"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

This sets a TIMER variable at the start, draws the spiral, then reads the value of the TIMER again. When you press any key, the program exits and prints the time (TIMER/60) it took to run the main code.

Here is what I get:

And pressing a key shows me:

3.03333334

Three seconds.

I expect I can optimize my program to speed it up. In the meantime, what can you come up with? Is there a faster way?

Let’s play!

5 thoughts on “UnderColor’s spiral challenge from 1984 – part 1

  1. Paul Fiscarelli

    Hello Allen – I sent you a DM on FB, but I don’t think you’ve seen it yet. What you have posted above is not exactly an accurate reproduction of what is being asked in the challenge question. You are using an offset decrease of 3 in each of your iterations, which produces a gap of only 2-pixels in both height and width. The challenge is indicating a gap of 3-pixels between lines, which requires an offset decrease of 4 in each iteration. This is further evident in the challenge’s diagram of the spiral, which indicates a line-length of 188-pixels for the line on the far left-hand side of the screen. If you perform a screen grab in XRoar (pixel perfect geometry of 640×480 window and 512×384 screen resolution), you will find your code generates a line length of 189 pixels (scale the 512×384 in half).

    If you change the offset decrease in your code to 4 instead of 3, you will achieve a render time of roughly 2.43 seconds. This is due to the fact that you are rendering about 23% fewer lines with the DRAW statement.

    You can reduce this time even further if you were to use only a single offset variable for drawing both the horizontal and vertical lines, and by adding a separate width to the horizontal lines with a value of 64 = (256w – 192v). This method will shave roughly 0.10 seconds off your render time, down to approximately 2.33 seconds.

    10 TIMER=0
    20 PMODE4,1:PCLS:SCREEN1,1
    30 OF=191:DRAW”BM0,191″
    40 DRAW”R=OF;R64″
    50 DRAW”U=OF;L=OF;L64;”
    60 OF=OF-4
    70 DRAW”D=OF;R=OF;R64;”
    80 OF=OF-4
    90 IF OF>0 THEN 50
    100 TM=TIMER
    110 IF INKEY$=”” THEN 110
    120 PRINT TM/60

    As an additional optimization step, you can replace the IF/THEN boundary check with a FOR/NEXT loop, to shave another 0.05 seconds from your render time – getting it down to roughly 2.28 seconds.

    10 TIMER=0
    20 PMODE4,1:PCLS:SCREEN1,1
    30 OF=191:DRAW”BM0,191″
    40 DRAW”R=OF;R64″
    50 FOR N=0 TO 23
    60 DRAW”U=OF;L=OF;L64;”
    70 OF=OF-4
    80 DRAW”D=OF;R=OF;R64;”
    90 OF=OF-4
    100 NEXT
    110 TM=TIMER
    120 IF INKEY$=”” THEN 120
    130 PRINT TM/60

    There are probably some other optimizations that can be done here – but it’s a start. Oh, I also tested these examples with VCC 2.1.9.2-pre2. I’m sure there will be slight variations in timing with the different emulators, and probably even with different versions of VCC.

    Reply
    1. Allen Huffman Post author

      Sounds like you are volunteering to be included in part 4 ;) As you will see in part 2, we have two patterns at play that are different so one (or both) is definitely wrong ;)

      Permission to include your code and details?

      Reply
    2. Allen Huffman Post author

      And FB wants a separate app to chat mobile which I don’t have installed on my phone or tablet, so I don’t see any messages to my personal account. But I can see them if you message my Sub-Etha page.

      Reply
      1. Paul Fiscarelli

        Understood. I no longer post in public groups on FB, otherwise I would I followed up in the comments on the original post.

        Reply

Leave a Reply to Allen HuffmanCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.