Inspired by some of the title screens on early TRS-80 Color Computer games, tonight I wrote this:

```
10 ' ATTRACT.BAS
20 A=1024:B=A+23:C=1535:D=C-23:Z=143
30 AD=1:BD=1:CD=-1:DD=-1
40 CLS 0:PRINT @268,"ATTRACT!";
50 POKE A,Z:POKE B,Z:POKE C,Z:POKE D,Z
60 Z=Z+16:IF Z>255 THEN Z=143
70 A=A+AD
80 IF A=1055 THEN AD=32
90 IF A=1535 THEN AD=-1
100 IF A=1504 THEN AD=-32
110 IF A=1024 THEN AD=1
120 '
130 B=B+BD
140 IF B=1055 THEN BD=32
150 IF B=1535 THEN BD=-1
160 IF B=1504 THEN BD=-32
170 IF B=1024 THEN BD=1
180 '
190 C=C+CD
200 IF C=1055 THEN CD=32
210 IF C=1535 THEN CD=-1
220 IF C=1504 THEN CD=-32
230 IF C=1024 THEN CD=1
240 '
250 D=D+DD
260 IF D=1055 THEN DD=32
270 IF D=1535 THEN DD=-1
280 IF D=1504 THEN DD=-32
290 IF D=1024 THEN DD=1
300 GOTO 50
```

It produces color changing blocks that chase around the screen:

It works by assigning screen POKE memory locations to the four moving blocks. A (1024) is the top left corner, and C (1535) is the bottom right. I then made B halfway between A and C, and D halfway between C and A. See? (I initially started with them in each of the four corners, but since the screen is 32 wide and 16 tall, the pattern did not look very good.)

I assign Z as the graphical block I will be POKEing on to the screen, using 143 (the first solid color block).

20 A=1024:B=A+23:C=1535:D=C-23:Z=143

I then assign four directional (delta) variables for each position — AD is the direction A should move (1 to add one and move it right, -1 to subtract one and move it left, 32 to move it down, or -32 to move it up). A and B are not he top row so they start with deltas of 1 (right). C and D are on the bottom row, so they start with deltas of -1 (left).

30 AD=1:BD=1:CD=-1:DD=-1

I clear the screen to black and print a message in the center of the screen.

40 CLS 0:PRINT @268,"ATTRACT!";

Next, I use POKE to place the graphic block (Z) on to locations A, B, C and D.

50 POKE A,Z:POKE B,Z:POKE C,Z:POKE D,Z

To change the color to the next color block, I add 16 to Z. If it’s larger than 255, I reset it back to the 143 value of the first block. (Solid blocks are 16 apart in the character set).

60 Z=Z+16:IF Z>255 THEN Z=143

Then I just do A=A+AD to get the new position (and the same for B, C and D), then check to see if the new location is one of the four corners, and adjust the delta (movement) variable accordingly.

70 A=A+AD 80 IF A=1055 THEN AD=32 90 IF A=1535 THEN AD=-1 100 IF A=1504 THEN AD=-32 110 IF A=1024 THEN AD=1

This is duplicated for B, C and D, then back to the top to do it all over…

120 ' 130 B=B+BD 140 IF B=1055 THEN BD=32 150 IF B=1535 THEN BD=-1 160 IF B=1504 THEN BD=-32 170 IF B=1024 THEN BD=1 180 ' 190 C=C+CD 200 IF C=1055 THEN CD=32 210 IF C=1535 THEN CD=-1 220 IF C=1504 THEN CD=-32 230 IF C=1024 THEN CD=1 240 ' 250 D=D+DD 260 IF D=1055 THEN DD=32 270 IF D=1535 THEN DD=-1 280 IF D=1504 THEN DD=-32 290 IF D=1024 THEN DD=1 300 GOTO 50

It works!

But it seems to go very, very slowly.

And it’s quite large.

I wonder if you might want to try to make the smallest version that does the same thing (even if it’s slower), and the fastest version (even if it’s larger).

## Some Size-Reducing Ideas

For example, to make is small, perhaps using a multidimensional array of POKE locations, like DIM L(3) (it is base zero, so 0-3 would be the elements). That would let all the positions be POKEd in a loop like:

L(0)=1024:L(1)=1024+23:L(2)=1535:L(3)=1535-23 FOR I=0 TO 3:POKE L(I),Z:NEXT

For movement, there could be a location delta array like DIM LD(3) that could have the direction each location is meant to be heading.

LD(0)=1:LD(1)=1:LD(2)=-1:LD(3)=-1

To move each location, code like this could be used:

FOR I=0 TO 3:L(I)=L(I)+LD(I):NEXT

Then, perhaps the screen corners could be in an array, such as DIM C(3), and another corresponding array of delta directions could be used like DIM D(3) set up like this:

CL(0)=1024:CD(0)=1 CL(1)=1055:CD(1)=32 CL(2)=1535:CD(2)=-1 CL(3)=1504:CD(3)=-32

Then, you could check for each block being in a corner and adjust it’s delta using the array as a lookup table:

FOR L=0 TO 3 ' Check each Location FOR C=0 TO 3 ' Check each Corner IF L(L)=CL(C) THEN LD(L)=CD(L) NEXT NEXT

And instead of hard-coding all these values, maybe they could be read in via READ/DATA statements.

That might make it smaller, but probably slower.

I’ll share three iterations of this program, each one making it smaller than the previous. Then, if we aren’t bored by then, we can look at ways to make it faster.

As always, leave your thoughts in the comments. I bet you know a better way to do this.

Until next time…