Category Archives: CoCo

Tandy/Radio Shack TRS-80 Color Computer (CoCo)

TRON arcade game clones for the CoCo

My all-time favorite arcade game was TRON, probably due to its connection with the Disney movie. I do not know if I played it much when it first came out, but during the time I lived in Broaddus, Texas (1985-1986 era) the local cafe had a TRON machine. I would walk home from school, stop in to get a .25 iced tea, and play TRON. I do not know how good I was at it, but I remember playing past enough levels that the game seemed to repeat and slow down.

Since then, I have only encountered TRON a few times. After moving to Des Moines, Iowa in 1995, I found a TRON in an arcade at our local Adventureland amusement park. I recall playing it there, but the joystick or spinner was in pretty bad shape.

I remember attending an arcade auction and a TRON game came up, but I stopped bidding at $250. I really wish I hadn’t, since years later, a TRON machine was for sale locally … for $1500.

My real interest in TRON came when a local bar-arcade opened and had a machine. I would stop by on my way home from work most days and play until I beat my previous score. Eventually, I had one “perfect” game where I got the score all the way up to where it would flip back over to 0 … and died on purpose. I was concerned that if I rolled the game back to 0, I wouldn’t get to enter my initials ;-)

My TRON high score from 2014.

This earned me a place on Up-Down’s wall of fame.

My TRON high score, immortalized in an instant photo.

To the best of my knowledge, that photo is still there, though the TRON machine died not too long after. They did get a TRON back a few times, but they all had issues — spinners that didn’t work, joystick that wouldn’t go in all directions, sound didn’t work, messed up screen, etc. I am very glad I got to play on a “good” machine all those times.

TRON-less.

Recently, I came across a video for a CoCo game called ElecTRON. I had forgotten about this TRON clone!

Then, I accidentally came across another CoCo game called KRON, which was another clone of TRON.

I now recall seeing both of these “back in the day” (and I likely had a “borrowed” copy of both of them at some point), but neither was a very good home version of TRON. It’s hard to replicate a game that needs a spinner and flight stick with a trigger ;-)

I just thought I’d share my TRON story, so there it is.

You can play these games online here:

Have fun! But probably not…

Steve Bjork’s TRS-80 Model 1 days

Steven Robert Bork (SRB Software) was such an iconic name in the Tandy/Radio Shack TRS-80 Color Computer community. Seeing his name on title screens of games etched it into my memory more than any other game author I can recall.

Recently, Roger Taylor spent over $6700 to acquire some of Bjorks software source code (disks and printouts) from an auction house. He has been discovering some interesting things, such as internal development tools Steve used as well as unfinished and unreleased programs. The archive goes back to Steve’s TRS-80 Model 1 days in the late 1970s.

One year before Steve wrote Popcorn for the CoCo, he had Space Ball for the Model 1:

I had also heard mentions of some multi-voice software music program he wrote. This was Soft Music:

I do not know how to use it, but when I figure it out, I will make a longer video of it. There appears to be several disks of songs available on a TRS-80 archive site, but I do not know how to get them in to the emulator yet.

There is also a Space Balls 2 which seems to be the same except for a countdown before the next ball drops.

Still a mystery is Galactic Fighter (not to be confused with a completely different game by that name released for the CoCo in 1984 by a different author). In a 2007 interview, Bjork described his Galatic Fighter game as similar to Galaxian, but predating it by three months. I see Galaxian listed as a September/November 1979 game, but I do not know when it was released in the USA. Wikipedia says Galaxian was the highest grossing game of 1980. I did manage to find this screenshot:

Roger Taylor has disks for this game, but is still working on safely getting them preserved and, hopefully, in a form that can run in an emulator.

Also during my research were two BASIC programs by Bjork – Perpetual Calendar and Bio-Rhythm. These appeared in a cassette tape collection called People’s Software./

Here is a link to the source of Perpetual Calendar that is supposed to be runnable in a web emulator, but I could not figure out how to start it:

https://willus.com/trs80/?-a+1+-p+10272+-f+1

And here is Bio-Rhythm on the same emulator site:

https://willus.com/trs80/?-a+1+-p+1226+-f+1

I do not know the date these were published, and do not see a date in the source listing. There may be a date in one of the other programs in the collection that might give us a clue.

Steve also created PEN BASIC, a program that added commands to the TRS-80 Model 1 for using a light pen device. I have heard him mention that he worked on a light pen, but never knew anything about it. Here is an ad mentioning it:

I also found a magazine article that goes in to details on the commands that PEN BASIC provides, and discusses how to use it.

And there is more to still be located… I see references to other things he created in the TRS-80 Model 1 days that I have yet to go searching for.

But one thing I have discovered is that Steve was known outside the pages of Color Computer magazines such as Rainbow. I find him referenced in articles in magazines of the day I had heard of (such as K-Power) and plenty I had never heard of (such as Softline and Today). There are some interviews, quotes, and a number of game reviews that mention his name as the author.

I now have a list of questions I wish I could ask Steve. When we were hanging out in Southern California, the subject of CoCo stuff would inevitably come up from time to time, but I wish I had dug deeper and learned more about some of his other works.

To be continued…

Steve Bjork’s Zaxxon, but updated for CoCo 3?

Roger Taylor continues to make discoveries…

https://www.patreon.com/posts/100701156?utm_campaign=postshare_fan

SPECULATIVE UPDATE: Zaxxon ran on the PMODE 4 2-color screen, and used artifact colors. Those did not display on the CoCo 3’s RGB CM-8 monitor. Perhaps this was just a way to make a CM-8 compatible version of the game? Though, changing the title screen and adding the logo (as well as updating the font) does make it appear it was more than just that.

Unreleased CoCo 3 update to the 1983 CoCo Zaxxon???

My VIC-20 Factory TNT for CoCo?

Insert “my first computer was a Commodore VIC-20” story here.

TL:DNR – I figured out how I might port one of my old VIC-20 games to the CoCo so it actually looks like the VIC-20 game ;-)

The VIC-20 has a 22×23 text screen. The CoCo has a 32×16 text screen. At the time, going from a width of 22 characters to 32 seemed like a huge upgrade. After all, you could scroll up and down to get more lines, but you couldn’t scroll left and right to get more columns.

I knew there was no way I could port any of my old character-based VIC-20 games to the CoCo without altering the screen layouts. Games that were written to use the 22×23 display, such as my Sky-Ape-Er, could not be replicated on the CoCo’s 32×16 text screen with 100% size accuracy.

VIC-20 Sky-Ape Er, screen 1.

Without reprogrammable characters, anything on the CoCo’s text screen would look far less graphical. Each text blog could either be a letter/number/punctuation character, or a 2×2 block of one color plus black.

Even if I did try to use these blocky characters to port any of my VIC-20 games, they would not be accurate since the width and height were different. I would have to redesign them to fit the CoCo screen:

Above, you can see I tried to get the “spirit” of the game on the screen, but there are less steps for each level, and 10 more horizontal spaces on each level, so the gameplay would be quite different. (To get to the top takes 12 jumps on the VIC, but only 8 on the CoCo version.)

With 32×16 there is simply no way I could accurately recreate a 22×23 game.

At least, not in text mode.

I knew the CoCo’s 32 column screen was equivalent to the 256 pixel width hi-res screen, and it would be larger than whatever the VIC’s 22 column screen was. Therefore, I figured the VIC’s 23 row screen must be larger than the CoCo’s 16 row screen.

When I started revisiting my VIC-20 programs, I remember that each screen character was 8×8. That made the 22 columns represent 176 pixels (22*8), and the 23 rows represented 184 (23*8). 176×184 is smaller than the CoCo’s 256×192 screen! I had always thought the CoCo’s text characters were 8×8, but that was just the data used to draw them. There were a few extra lines between each row that I had never considered.

On the CoCo, 32 columns at 8 pixels each is 256 — that is what I would expect. But when it came to rows, if each character were 8 pixels high, that would only be 96 pixels tall (16*8)! I had never bothered to “math” this. The 192 horizontal resolution meant that each of the 16 rows was 12 pixels tall! That means the CoCo text font was really more like 8×12.

This led me to experimenting with the VIC-20 font data. I could display a full VIC-20 display of 176×184 with room to spare on the CoCo’s 256×192 screen. I wrote about this in an earlier article and made this example showing the 22×23 VIC-20 character set drawn on the CoCo screen:

VIC-20 20×32 screen displaying PETSCII on a CoCo

The VIC-20 did not have a graphics mode, and did everything by putting characters on the text screen. You were able to reprogram what those characters looked like. You could do some pretty neat things just by PRINTing or POKEing to the text screen.

This is how I made my Factory TNT game. I drew the screen like this…

Factory TNT for the VIC-20

…then remapped the characters to be my graphics:

VIC-20 Factory TNT.

I wanted to accurately represent that screen on a CoCo, I would have to do it using the CoCo’s hi-res 256×192 graphics screen. I could bring over all the actual character data and recreate it accurately, though the aspect ratio would be off a bit… It might look like this:

CoCo Factory TNT concept

Missing is the “MEN:” and “SCORE:” text labels on the top line. Those font characters would have to be brought over, as well. The VIC would let you remap A, B, C, D, etc. to be different characters, and if you used inverse video (or something like that) while in this “reprogrammed character mode”, they would show up as normal uppercase letters on the screen.

This was just a quick experiment, but perhaps I can also bring over just the VIC-20 font letters needed for “MEN:” and “LIVES:”. Maybe I’d want the whole alphabet so I could add a title screen or instructions. Factory TNT 2024, perhaps?

To be continued… Maybe.

(Okay. Definitely. I have already started working on a multi-part article series about this endeavor.)

Super Pitfall … 2???

After the passing of Steve Bjork, his personal possessions ended up in an estate sale. Among them were some fantastic Disney collectables (Steve worked at Disneyland in the 1970s), and a bunch of CoCo stuff.

After the estate sale, much of this ended up at an auction. Roger Taylor spent over $6700 to acquire and preserve a huge bundle of Steve Bjork diskettes and source code printouts. To support him in this endeavor, I am now backing Roger’s Patreon with a $50/month “hardcore supporter” level. If you would like to help out, consider chipping in, even at a $5/month level, to help offset these investments.

Yesterday, Roger shared some photos of the source code printouts that had been kept in a storage box:

https://www.patreon.com/posts/here-we-go-100273449

There are listings from pre-CoCo TRS-80 Model I/III software, as well as highly recognizable CoCo programs such as Clowns & Balloons, Mega-Bug, Micro Painter, Rampage, Bash as well as something called Marty Goodman Game which was written in 30 days. This would be released as Marty’s Nightmare for the 1990 Atlanta CoCoFest (the first time I ever met Steve in person).

One of the more curious things in the printout collection is a listing for Super Pitfall 2, which does not exist. It seems Super Pitfall was only released for the original Nintendo Entertainment System (NES), the Color Computer 3, and a Japanese machine called a PC-88. The Wikipedia page has this comment:

Activision initially was going distribute Sunsoft‘s Atlantis no Nazo in the United States in a rebranded form as a sequel to Super Pitfall on the Super Nintendo Entertainment System. This release did not happen.

https://en.wikipedia.org/wiki/Super_Pitfall

YouTube does have a few videos of a game called Super Pitfall 2, described as a prototype and unreleased:

If this Atlantis no Nazo game, which was only released in Japan, was going to be converted to be Super Pitfall 2 for the USA audience, was Activision also going to have a CoCo 3 version done? This seems unlikely, but the source code clearly says “Super Pitfall 2” and also has that text on its title screen! It also shows that Steve worked on this game from 11/11/1987 to 4/6/1988.

Super Pitfall 2 source code listing, from the collection of Roger Taylor.

I do have a theory. Mine Rescue was a game very similar to Super Pitfall that Steve released in 1989. I cannot find the game in the Color Computer Archive (most likely since Steve was still active in the CoCo community and protecting his copyright), but the manual is there:

https://colorcomputerarchive.com/repo/Documents/Manuals/Games/Mine%20Rescue%20(SRB%20Software).pdf

It was very similar to Super Pitfall. (photos from L. Curtis Boyle’s site)

This was much like Steve’s game Bash was very similar to Arkanoid. (photos from L. Curtis Boyle’s site)

Steve had a library of routines he would use in various games. You could see how the scrolling perspective of his port of Zaxxon might have been re-used for one of the levels in his Ghana Bwana game (photos from L. Curtis Boyle’s site):

I am wondering if this “Super Pitfall 2” might have been the code that was later released as Mine Rescue. But, at the moment in time that printout was noted with “4/6/88”, both the source code and the embedded text for the title screen read “Super Pitfall 2”.

I am looking forward to following Roger Taylor’s exploration of this archive of Steve Bjork material. I wonder what other things will be discovered…

Until then, stop by Roger’s Patreon and please consider supporting him at whatever level you can justify.

Let’s write Lights Out in BASIC – part 7

See also: part 1, part 2, part 3, part 4, part 5, part 6 and part 7.

Code cleanup in aisle 4.

Let me begin this installment by presenting the current Lights Out code with some renumbering done and a few minor improvements.

0 REM LITESOUT-P7.BAS

10 REM SETUP
20 DIM L(9,9)

100 REM START NEW GAME
110 GOSUB 5000
120 REM INITIALIZE GRID
130 MV=0
140 GOSUB 4000
150 REM SHOW GRID
160 GOSUB 1000
170 REM CHECK FOR WIN
180 IF LO=0 THEN 300
190 REM INPUT SQUARE
200 GOSUB 2000
210 REM TOGGLE SQUARES
220 GOSUB 3000
230 REM REPEAT
240 MV=MV+1
250 GOTO 150

300 REM GAME WON
310 PRINT "YOU WON IN";MV;"MOVES."
320 INPUT "PLAY AGAIN (Y/N)";Q$
330 IF Q$="Y" THEN 100
340 PRINT "GAME OVER"
350 END

1000 REM SHOW GRID
1010 PRINT "GAME NUMBER:";GN
1020 PRINT " ";
1030 FOR A=1 TO GS
1040 PRINT RIGHT$(STR$(A),2);
1050 NEXT:PRINT
1060 FOR Y=0 TO GS-1
1070 PRINT RIGHT$(STR$(Y+1),2);" ";
1080 FOR X=0 TO GS-1
1090 IF L(X,Y) THEN PRINT "X ";:GOTO 1110
1100 PRINT ". ";
1110 NEXT
1120 PRINT
1130 NEXT
1140 PRINT "MOVES:";MV;"LIGHTS ON:";LO
1150 RETURN

2000 REM INPUT SQUARE
2010 S$=MID$(STR$(GS),2):PRINT "X,Y (1-";S$;",1-";S$;" OR 0,0)";
2020 INPUT X,Y
2030 IF X=0 THEN IF Y=0 THEN 320
2040 IF X<1 OR X>GS OR Y<1 OR Y>GS THEN 2010
2050 X=X-1:Y=Y-1
2060 RETURN

3000 REM TOGGLE SQUARES
3010 L(X,Y)=NOT L(X,Y):LO=LO-(L(X,Y)*2+1)
3020 IF X>0 THEN L(X-1,Y)=NOT L(X-1,Y):LO=LO-(L(X-1,Y)*2+1)
3030 IF X<GS-1 THEN L(X+1,Y)=NOT L(X+1,Y):LO=LO-(L(X+1,Y)*2+1)
3040 IF Y>0 THEN L(X,Y-1)=NOT L(X,Y-1):LO=LO-(L(X,Y-1)*2+1)
3050 IF Y<GS-1 THEN L(X,Y+1)=NOT L(X,Y+1):LO=LO-(L(X,Y+1)*2+1)
3060 RETURN

4000 REM INITIALIZE GRID
4010 INPUT "GRID SIZE (3-10, ENTER=5)";GS
4020 IF GS=0 THEN GS=5
4030 IF GS<3 OR GS>10 THEN 4010
4040 PRINT "INITIALIZING..."
4050 FOR A=1 TO 10*GS
4060 Y=RND(GS)-1
4070 X=RND(GS)-1
4080 GOSUB 3000
4090 NEXT
4100 RETURN

5000 REM SELECT GAME
5010 PRINT "PLAY SPECIFIC GAME # (Y/N)?"
5020 S=S+1:A$=INKEY$:IF A$="" THEN 5020
5030 IF A$="Y" THEN 5070
5040 IF A$="N" THEN A=RND(-S)
5050 GN=RND(65535):A=RND(-GN)
5060 GOTO 5100
5070 INPUT "PLAY GAME (1-65535)";GN
5080 IF GN<1 OR GN>65535 THEN 5060
5090 A=RND(-GN)
5100 RETURN

As I tested this version, I noticed my random grid generator was not very good–at least on a large 10×10 grid. It really needed to do more random light toggling for larger grids. This change would go in this line – maybe just doing a “grid size * X”, like “10*GS” or something. I am still trying things, but for now I made it do more random toggles the larger the grid size is (line 4050).

I also made it so the default grid size was 5 (line 4010).

And I fixed some output where it printed a numeric variable. In Color BASIC, there is an extra space printed before and after printing a number:

PRINT "*";42;"*"
* 42 *

And, technically, it’s not a space before a number — it’s a place for the sign (none if positive, “-” if negative):

PRINT "*";-42;"*"
*-42 *

Since I knew I was only printing a positive number, I just got rid of that leading space, and the one after it. I did this by converting the number to a string using STR$. That will convert it to a string with the first space (a place for the sign) but no space after it:

PRINT "*";STR$(42);"*"
* 42*

Then all I needed to do was trim off that leading space. In the old days, I would have done this by getting the length of the string using LEN$ and then using RIGHT$ to get just the character(s) after that leading space:

N=42
N$=STR$(N)
L=LEN(N$)
PRINT RIGHT$(N$,L-1)

But in recent years, someone commented on this site (I believe) about how you could use MID$ without a size and just specify the starting position in a string, and it would return everything from that position to the end:

N=42
PRINT MID$(STR$(N),2)

Nice! “Wish I knew then what I know now…”

But I digress…

We now have a fairly “feature complete” version of Lights Out that runs in very basic BASIC — it doesn’t even make use of ELSE.

Before I move on to making this look a lot nicer on a CoCo, I thought it might be fun to port it to a VIC-20. I made use of the wonderful CBM prg Studio Windows-based tool that can build BASIC or assembly programs for all kinds of Commodore machines. I just pasted in my source, and then found a few minor things I would need to change to run on the VIC-20’s CBM BASIC.

The first thing I did after pasting the code in to the editor was to convert it all to lowercase. That seems to be how that BASIC works, as SHIFT characters turn in to PETSCII graphics characters.

Now I would be able to build the program.

It would build right away, but not run on the VIC yet until I fix two things that are different between Color BASIC and CBM BASIC:

  • A$=INKEY$ must be changed to GET A$
  • RND(x) must be changed to INT(RND(1)*X)-1 (Doing the random seed using RND(-X) works the same way on the VIC, and could be left alone.)
CoCo:
5020 S=S+1:A$=INKEY$:IF A$="" THEN 5020

VIC:
5020 S=S+1:GET A$:IF A$="" THEN 5020

CoCo:
4060 Y=RND(GS)-1

VIC:
4060 Y=INT(RND(1)*GS)

CoCo:
4070 X=RND(GS)-1

VIC:
4070 X=INT(RND(1)*GS)

After that, I tried to RUN it and ran in to a problem with INPUT:

From testing, it seems that long prompts on INPUT cause issues, possibly related to how the VIC’s full screen editor works. I sent a tweet to 8-Bit Show and Tell to see what he knew, and did a simple workaround by breaking up the prompt and the input on separate screen lines:

4000 rem initialize grid
4010 print "grid size (3-10, enter=5)":input gs

I thought I might have the same issue with the “select square” input, but that prompt does not overlap to the next line so it worked… or so I thought. With the default grid size of 5×5, the prompt looked like:

X,Y (0-5,0-5 OR 0,0)?(space)
*(cursor here)

That seemed to work just fine, but when I did a grid of 10×10, it made the prompt longer, wrapping the “?” of INPUT to the next line:

X,Y (0-10,0-10 OR 0,0)
? *(cursor here)

So I needed to fix that, too. I had already had to break that one up in to a PRINT and an INPUT since I was printing variables in the prompt, so I just took the semicolon off from the end of the PRINT:

2000 rem input square
2010 s$=mid$(str$(gs),2):print "x,y (1-";s$;",1-";s$;" or 0,0)"
2020 input x,y

Now I had what appeared to be a working version of the game for VIC-20. BUT, it would need some work to reformat the prompts to fit on a 22-column screen, versus the 32- column CoCo screen. For anyone who wants to work on that, here is the VIC-20 version with the lines in bold that have changes from the CoCo version:

0 rem litesout-p7.bas

10 rem setup
20 dim l(9,9)

100 rem start new game
110 gosub 5000
120 rem initialize grid
130 mv=0
140 gosub 4000
150 rem show grid
160 gosub 1000
170 rem check for win
180 if lo=0 then 300
190 rem input square
200 gosub 2000
210 rem toggle squares
220 gosub 3000
230 rem repeat
240 mv=mv+1
250 goto 150

300 rem game won
310 print "you won in";mv;"moves."
320 input "play again (y/n)";q$
330 if q$="y" then 100
340 print "game over"
350 end

1000 rem show grid
1010 print "game number:";gn
1020 print " ";
1030 for a=1 to gs
1040 print right$(str$(a),2);
1050 next:print
1060 for y=0 to gs-1
1070 print right$(str$(y+1),2);" ";
1080 for x=0 to gs-1
1090 if l(x,y) then print "x ";:goto 1110
1100 print ". ";
1110 next
1120 print
1130 next
1140 print "moves:";mv;"lights on:";lo
1150 return

2000 rem input square
2010 s$=mid$(str$(gs),2):print "x,y (1-";s$;",1-";s$;" or 0,0)"
2020 input x,y
2030 if x=0 then if y=0 then 320
2040 if x<1 or x>gs or y<1 or y>gs then 2010
2050 x=x-1:y=y-1
2060 return

3000 rem toggle squares
3010 l(x,y)=not l(x,y):lo=lo-(l(x,y)*2+1)
3020 if x>0 then l(x-1,y)=not l(x-1,y):lo=lo-(l(x-1,y)*2+1)
3030 if x<gs-1 then l(x+1,y)=not l(x+1,y):lo=lo-(l(x+1,y)*2+1)
3040 if y>0 then l(x,y-1)=not l(x,y-1):lo=lo-(l(x,y-1)*2+1)
3050 if y<gs-1 then l(x,y+1)=not l(x,y+1):lo=lo-(l(x,y+1)*2+1)
3060 return

4000 rem initialize grid
4010 print "grid size (3-10, enter=5)":input gs
4020 if gs=0 then gs=5
4030 if gs<3 or gs>10 then 4010
4040 print "initializing..."
4050 for a=1 to 10*gs
4060 y=int(rnd(1)*gs)
4070 x=int(rnd(1)*gs)
4080 gosub 3000
4090 next
4100 return

5000 rem select game
5010 print "play specific game # (y/n)?"
5020 rem s=s+1:a$=inkey$:if a$="" then 5020
5021 s=s+1:get a$:if a$="" then 5020
5030 if a$="y" then 5070
5040 if a$="n" then a=rnd(-s)
5050 gn=rnd(65535):a=rnd(-gn)
5051 rem gn=int(rnd(1)*65535)-1:a=rnd(-gn)
5060 goto 5100
5070 input "play game (1-65535)";gn
5080 if gn<1 or gn>65535 then 5060
5090 a=rnd(-gn)
5100 return

The more I look at this code, the more optimizations I want to make to it.

But for now, that is a version for CoCo, and a version for Commodore. It should be easy to port to other flavors of BASIC. Let me know if you port it to something.

Now that I know how to write the game, the next goal will be to make it look a lot better on the CoCo (and maybe VIC-20 as well, if I feel ambitious).

But I think I need a brake from Lights Out for a bit…

Until then…

Let’s write Lights Out in BASIC – part 6

See also: part 1, part 2, part 3, part 4, part 5, part 6 and part 7.

At this point, we have a nicely functional BASIC version of Lights Out. Some of its features include:

  • 5×5 grid of lights.
  • Random games.
  • Allows replaying a specific game.
  • Counts moves for scoring.
  • Ability to quite a game in progress.
  • Slightly less sucky user interface than the original version.

But we still have more to do!

Bigger grid, please

One of the enhancements I mentioned in the previous installment was the ability to specify larger (or smaller, I suppose), grid sizes. We know that the official Lights Out games from Tiger Electronics in the 1990s used a 5×5 and 6×6 grid. Others have since created variations, such as one that operates around a cube (maybe we write that version some day). Let’s start there…

For this simple version, we’ll just arbitrarily pick a maximum grid size of 10×10. This should still fit easily on the CoCo’s 32×16 text screen. For fun, we could also allow a grid size smaller than 5×5 to be chosen. Since the spiritual predecessor of Lights Out was a 1970s game that featured a 3×3 grid, I’ll use that size as the minimum.

The changes needed should be fairly minor. When starting a game, the user will be prompted for the grid size.

It seems we could allow rectangular grids (5×3, 10×5, etc.), but for now we’ll just stick to square grids where both sides are the same size. The array for the grid just needs to be large enough to hold the largest sized grid.

Wrong DIMension

An oversight I made when starting this program was not adding a DIM statement to specify the maximum size of the two-dimensional grid array! The current version really needs a line that contains this at the very top:

DIM L(4,4)

Reminder: DIM is base-0, so it starts counting entries at 0. A DIM X(4) gives entries X(0), X(1), X(2), X(3) and X(4).

The program only works because Color BASIC allows array entries 0-10 before the DIM is needed. You can do A(10)=42 without needing to DIM A(10) first. (I find it weird that Microsoft chose to default to 11 array entries. I bet whoever coded that was thinking “1-10” rather than “0-10”.)

To enhance the program to support up to a 10×10 grid, we’ll allocate an array that large.

4 DIM L(9,9)

Next we need to ask the user what size grid they want. This can be added to the “initialize grid” subroutine:

4000 REM INITIALIZE GRID
4005 INPUT "GRID SIZE (3-10)";GS
4006 IF GS<3 OR GS>10 THEN 4005
...

After that, any place that is currently hard coded to 4 will need to be changed to use the grid size variable. If the user types in 10 (for a 10×10), the array will be using 0-9. We must pay attention to that and know that a 10 grid is actually 0-9.

This is also a good time to clean up the printing of the grid a bit. Here is the full program with the latest changes in bold:

4 DIM L(9,9)
5 REM SELECT GAME
6 GOSUB 6000
10 REM INITIALIZE GRID
15 MV=0
20 GOSUB 4000
30 REM SHOW GRID
40 GOSUB 1000
47 IF LO=0 THEN 200
50 REM INPUT SQUARE
60 GOSUB 2000
70 REM TOGGLE SQUARES
80 GOSUB 3000
90 REM REPEAT
95 MV=MV+1
100 GOTO 30

200 REM GAME WON
220 PRINT "YOU WON IN";MV;"MOVES."
230 INPUT "PLAY AGAIN (Y/N)";Q$
240 IF Q$="Y" THEN 5
250 PRINT "GAME OVER"
260 END

1000 REM SHOW GRID
1005 PRINT "GAME NUMBER:";GN
1006 PRINT " ";
1007 FOR A=1 TO GS
1008 PRINT RIGHT$(STR$(A),2);
1009 NEXT:PRINT
1010 FOR Y=0 TO GS-1
1015 PRINT RIGHT$(STR$(Y+1),2);" ";
1020 FOR X=0 TO GS-1
1030 IF L(X,Y) THEN PRINT "X ";:GOTO 1050
1040 PRINT ". ";
1050 NEXT
1060 PRINT
1070 NEXT
1080 PRINT "MOVES:";MV;"LIGHTS ON:";LO
1090 RETURN

2000 REM INPUT SQUARE
2010 PRINT "X,Y (1-";GS;",1-";GS;" OR 0,0)";
2011 INPUT X,Y
2015 IF X=0 THEN IF Y=0 THEN 230
2020 IF X<1 OR X>GS OR Y<1 OR Y>GS THEN 2010
2025 X=X-1:Y=Y-1
2030 RETURN

3000 REM TOGGLE SQUARES
3010 L(X,Y)=NOT L(X,Y):LO=LO-(L(X,Y)*2+1)
3020 IF X>0 THEN L(X-1,Y)=NOT L(X-1,Y):LO=LO-(L(X-1,Y)*2+1)
3030 IF X<GS-1 THEN L(X+1,Y)=NOT L(X+1,Y):LO=LO-(L(X+1,Y)*2+1)
3040 IF Y>0 THEN L(X,Y-1)=NOT L(X,Y-1):LO=LO-(L(X,Y-1)*2+1)
3050 IF Y<GS-1 THEN L(X,Y+1)=NOT L(X,Y+1):LO=LO-(L(X,Y+1)*2+1)
3060 RETURN

4000 REM INITIALIZE GRID
4005 INPUT "GRID SIZE (3-10)";GS
4006 IF GS<3 OR GS>10 THEN 4005
4010 PRINT "INITIALIZING..."
4020 FOR A=1 TO 10
4030 Y=RND(GS)-1
4040 X=RND(GS)-1
4050 GOSUB 3000
4060 NEXT
4070 RETURN

6000 REM SELECT GAME
6010 PRINT "PLAY SPECIFIC GAME # (Y/N)?"
6020 S=S+1:A$=INKEY$:IF A$="" THEN 6020
6030 IF A$="Y" THEN 6060
6040 IF A$="N" THEN A=RND(-S)
6045 GN=RND(65535):A=RND(-GN)
6046 GOTO 6090
6050 GOTO 6020
6060 INPUT "PLAY GAME (1-65535)";GN
6070 IF GN<1 OR GN>65535 THEN 6060
6080 A=RND(-GN)
6090 RETURN

This version will display the grid with nicely (?) formatted headers for the columns and rows, and less nicely formatted prompts for what values are allowed.

There is still so much work to do to make the user interface nicer to look at and interact with.

To be continued…

Let’s write Lights Out in BASIC – part 5

See also: part 1, part 2, part 3, part 4, part 5, part 6 and part 7.

As we begin this part, let’s look at the BASIC Lights Out code as it stands currently:

5 REM SELECT GAME
6 GOSUB 6000
10 REM INITIALIZE GRID
20 GOSUB 4000
30 REM SHOW GRID
40 GOSUB 1000
47 IF LO=0 THEN PRINT "YOU WON!":END
48 PRINT "LIGHTS ON:";LO
50 REM INPUT SQUARE
60 GOSUB 2000
70 REM TOGGLE SQUARES
80 GOSUB 3000
90 REM REPEAT
100 GOTO 30

1000 REM SHOW GRID
1005 PRINT "GAME NUMBER:";GN
1010 FOR Y=0 TO 4
1020 FOR X=0 TO 4
1030 IF L(X,Y) THEN PRINT "X";:GOTO 1050
1040 PRINT ".";
1050 NEXT
1060 PRINT
1070 NEXT
1080 PRINT
1090 RETURN

2000 REM INPUT SQUARE
2010 INPUT "X,Y (0-4,0-4)";X,Y
2020 IF X<0 OR X>4 OR Y<0 OR Y>4 THEN 2010
2030 RETURN

3000 REM TOGGLE SQUARES
3010 L(X,Y)=NOT L(X,Y):LO=LO-(L(X,Y)*2+1)
3020 IF X>0 THEN L(X-1,Y)=NOT L(X-1,Y):LO=LO-(L(X-1,Y)*2+1)
3030 IF X<4 THEN L(X+1,Y)=NOT L(X+1,Y):LO=LO-(L(X+1,Y)*2+1)
3040 IF Y>0 THEN L(X,Y-1)=NOT L(X,Y-1):LO=LO-(L(X,Y-1)*2+1)
3050 IF Y<4 THEN L(X,Y+1)=NOT L(X,Y+1):LO=LO-(L(X,Y+1)*2+1)
3060 RETURN

4000 REM INITIALIZE GRID
4010 PRINT "INITIALIZING..."
4020 FOR A=1 TO 10
4030 Y=RND(5)-1
4040 X=RND(5)-1
4050 GOSUB 3000
4060 NEXT
4070 RETURN

6000 REM SELECT GAME
6010 PRINT "PLAY SPECIFIC GAME # (Y/N)?"
6020 S=S+1:A$=INKEY$:IF A$="" THEN 6020
6030 IF A$="Y" THEN 6060
6040 IF A$="N" THEN A=RND(-S)
6045 GN=RND(65535):A=RND(-GN)
6046 GOTO 6090
6050 GOTO 6020
6060 INPUT "PLAY GAME (1-65535)";GN
6070 IF GN<1 OR GN>65535 THEN 6060
6080 A=RND(-GN)
6090 RETURN

There are quite a few more things that could (and probably need to) be done:

  • The number of moves taken should be counted and displayed.
  • If the game is won, it just ENDs in line 47. It could ask the player if they want to play again.
  • There is no way to quit a game in progress other than hitting the break key.
  • The user interface (typing in coordinates such as “0,2”) is user-hostile. At the very least, we could label the rows/columns to show which values to type. Perhaps even labeling them “A B C D E …” across, and “1 2 3 4 5” vertically, similar to how chess boards are done.
  • Options for grids larger than 5×5 could be implemented with very little change in the code.

Once the game is “code complete“, there is also be some cleanup and renumbering that should be done. (Having those odd line numbers like 47 bugs me.)

Score (Counting Moves)

The current code only knows that you won the game (the game ends) or you are still playing. If one person plays game number 16809 and solves it in 80 moves, and another person plays the same game and solves it in 10 moves, they are both treated to the same ending – the game exits.

Let’s add a move counter. We’ll reset it at the start of a game…

10 REM INITIALIZE GRID
15 MV=0
20 GOSUB 4000

…and increment it after every move:

90 REM REPEAT
95 MV=MV+1
100 GOTO 30

We should also display the move count each time the grid is display. This is a good time to also move the “number of lights on” in to the display grid routine, too.

48 PRINT "LIGHTS ON:";LO (removed)

1000 REM SHOW GRID
1005 PRINT "GAME NUMBER:";GN
1010 FOR Y=0 TO 4
1020 FOR X=0 TO 4
1030 IF L(X,Y) THEN PRINT "X";:GOTO 1050
1040 PRINT ".";
1050 NEXT
1060 PRINT
1070 NEXT
1080 PRINT "MOVES:";MV;"LIGHTS ON:";LO
1090 RETURN

This now gives us a display of our game number (which was already there), the number of moves made so far (new), and the current count of how many lights are on (already there).

DONE: The number of moves taken should be counted and displayed.

Game Over

The next thing I want to add is a game over screen. When the game is on, this screen should display how many moves it took. It could then prompt the user to see if they want to play agan.

It could be as simple as this:

47 IF LO=0 THEN 200

200 REM GAME WON
220 PRINT "YOU WON IN";MV;"MOVES."
230 INPUT "PLAY AGAIN (Y/N)";Q$
240 IF Q$="Y" THEN 5
250 PRINT "GAME OVER"
260 END

DONE: If the game is won, it just ENDs in line 47. It could ask the player if they want to play again.

I give up!

The user should also be able to quit. Currently, the awful “type in an X,Y coordinate” thing is yucky, but we could make typing “-1,-1” end the game. (We will fix the user interface later.)

2000 REM INPUT SQUARE
2010 INPUT "X,Y (0-4,0-4 OR -1,-1)";X,Y
2015 IF X=-1 THEN IF Y=-1 THEN 230

2020 IF X<0 OR X>4 OR Y<0 OR Y>4 THEN 2010
2030 RETURN

This is so yucky, but the goal here is to get the code fully functional. We can make it nice later.

DONE: There is no way to quit a game in progress other than hitting the break key.

The user interface sucks!

Okay, this one will take more work, but a quick enhancement might be to just print the columns and rows so the player knows what to type. Also, humans like counting from one instead of zero (base-1 humans) so typing in things to match the base-0 arrays is not very human friendly. We can fix both things here.

1000 REM SHOW GRID
1005 PRINT "GAME NUMBER:";GN
1006 PRINT " 12345"
1010 FOR Y=0 TO 4
1015 PRINT Y+1;
1020 FOR X=0 TO 4
1030 IF L(X,Y) THEN PRINT "X";:GOTO 1050
1040 PRINT ".";
1050 NEXT
1060 PRINT
1070 NEXT
1080 PRINT "MOVES:";MV;"LIGHTS ON:";LO
1090 RETURN

…and…

2000 REM INPUT SQUARE
2010 INPUT "X,Y (1-5,1-5 OR 0,0)";X,Y
2015 IF X=0 THEN IF Y=0 THEN 230
2020 IF X<1 OR X>5 OR Y<1 OR Y>5 THEN 2010
2025 X=X-1:Y=Y-1
2030 RETURN

Now the user will see numbers above the grid, and to the left of the grid, and be able to enter them using 1-5 rather than 0-4. I made 0,0 exit as well to save the use from having to type the minus signs.

But, this interface still sucks. After we get the “text and typing” version done, we can do one that is more modern and uses the arrow keys to cursor around and select squares.

DONE: The user interface (typing in coordinates such as “0,2”) is user-hostile.

Bigger grid, please

Hey, let’s just get the basic game working first, then we can worry about “Deluxe Lights Out.”

DEFERRED: Options for grids larger than 5×5 could be implemented with very little change in the code.

To be continued…

Steve Bjork’s haunted house life…

Though us CoCo folks knew Steve Bjork from Zaxxon and other games he wrote, in his later years he was very active in the haunted house industry.

He was part of Haunt Hackers which made haunted house electroincs. His partner, Steve Koci, passed away in recent years, and with Bjork’s passing, the website went aware.

Here is the last image of the Haunt Hackers website that the Intennet Archive has a copy of:

Haunt Hackers (archive.org)

He also did a home haunt display called Scary Lane. Here is his home haunt website from the archive:

Scary Lane (archive.org)

More to come…

Keywords: Steven Robert Bjork, Whittier California.

Let’s write Lights Out in BASIC – part 4

See also: part 1, part 2, part 3, part 4, part 5, part 6 and part 7.

Where where we?

Oh, right. Light Out, in very basic BASIC.

If Lights Out always started with the same lights on, once you figured out how to win, you could repeat those steps and win every time. This reminds me of a wooden golf tee game I was given as a child. (If you have ever eaten at a Cracker Barrel restaurant, you probably have seen this — they have/had one on every table.)

I never learned how to win that game intentionally, but sometimes I would get lucky. This made visits to Cracker Barrel sometimes frustrating. The game had a listing of rankings based on how many pegs you had left at the end of the game. I was often an “EG-NO-RA-MOOSE.” :)

But then the iPhone happened in 2007, and a year later there was an App Store and you could play games on the phone! I found a peg game app and decided to learn and memorize the steps that win the game. I took screen shots of every step so I could consult them later. Here is one of those tiny 320×480 screen shots taken in 2008 on my original 2007 iPhone:

While I no longer remember those steps, I did for awhile, and visits to the Cracker Barrel were never the same. I was the peg game master! But soon it become boring and not worth playing since I knew how to win it every time.

Oh well. At least the collard greens and fried okra were still great.

Side Note: During research for this article, I found that Cracker Barrel has a blog post with the history of the peg game, as well as all the steps to solve it.

Blog post on the steps that solve the peg game every time.

But I digress…

“Random” game variations

The current program has an initializing routine which turns random lights on. But does it really?

As I wrote in an earlier article about RND, RND is not really random. On my CoCo, each time I turn it on, I can print some random numbers. Each time I power cycle and try it again, I will get those same “random” numbers. Here is an example of the first eight random numbers between 1 and 50 on the CoCo:

You get these same random numbers every time you power up the CoCo.

Any programmer that writes something that relies on RND to generate levels or patterns should be aware that it will make the same level or pattern each time the program runs from a fresh power up. BUT, in Color BASIC, you can seed the random number generator to change that pattern. It works by passing in a negative value to RND. When you do that, it seeds the number generator to a specific and repeatable sequence for that seed value.

If you run this code on a CoCo, you will see it print the same set of eight random numbers ten times:

10 FOR A=1 TO 10
20 B=RND(-42)
30 FOR B=1 TO 8
40 PRINT RND(50);:
50 NEXT
60 PRINT
70 NEXT

This means that if I powered up my computer and ran this Lights Out program, I would get the same pattern the next time I powered up and ran the program.

This is probably not a problem that really needs to be solved, but since there is a simple solution, it makes for a good excuse to discuss it.

Seeding the random number generator

In Extended Color BASIC, there is a TIMER function that starts at 0 on power up, then increments every 60th of a second until it rolls over and starts again from 0. Since the amount of time between power up, typing in “CLOAD” or whatever, and “RUN” will vary, using that value makes for a simple seed:

A=RND(-TIMER)

Just doing something like that at the start of the program should be enough to reduce chances that the patterns are not the same each time the game is played from a fresh start.

BUT, Color BASIC does not have TIMER. It would need a different approach to creating that number. If the program has a title/splash screen, it might sit in a loop waiting for the user to press a key to start. Something like that could be used to create a seed number:

PRINT "PRESS ANY KEY TO BEGIN:"
xx S=S+1:IF INKEY$="" THEN xx
A=RND(-S)

It is not perfect since if the user types RUN and quickly hits a key, there is a good potential that the program would be using one of only a few seeds based on the low numbers that the counter got to. But, hey, better than nothing… And that’s something.

We could also keep incrementing that S variable inside the main program loop. If the user chose to play again (our program does not offer that feature, yet), the value could be used to create more random patterns. This is probably overkill, but it would be simple to add.

Predictable randomness could be a feature…

I recall some game that came with Microsoft Windows (maybe a Solitaire, or perhaps Minesweeper) that had a spot where you entered a “game number” or something. This let you replay a specific game. I did not realize it at the time, but this was probably just seeding a random number generator so the order of the cards or the mines (whatever game it was) would be the same for those that wanted to try again.

Update: I was close! It was apparently FreeCell for Windows 95. I asked BING’s AI and it told me:

I believe the game you are referring to is FreeCell. FreeCell is a solitaire card game that was first introduced in Windows 95. It is a popular game that allows players to replay specific games by entering a “game number” 1If you’re interested in playing FreeCell, you can download it from the Microsoft Store 1.

I hope this helps!

– BING AI

Thank you, large language model.

But I digress…

The game could try to randomize, but could also allow the user to pick a “game number” that would be repeatable. That could be a fun feature, since players could use it to practice different strategies.

It could be as simple as something like this (for Extended Color BASIC which has the TIMER function):

xx INPUT "PLAY GAME (1-65535, 0=RND)";S
IF S<0 OR S>65535 THEN xx
IF S=0 THEN S=TIMER
A=RND(-S)

Or if TIMER was not available, it could prompt the user then sit in a loop counting and use the count value as the seed. This is not a great approach, but might work…

PRINT "PLAY SPECIFIC GAME # (Y/N)?"
xx S=S+1:A$=INKEY$:IF A$="" THEN xx
IF A$="Y" THEN yy
IF A$="N" THEN A=RND(-S):GOTO zz
GOTO xx
yy INPUT "PLAY GAME (1-65535)";S
IF S<1 OR S>65535 THEN yy
A=RND(-S)
zz RETURN

I decided to add it to the program as a subroutine that can be called before the main game loop:

6000 REM SELECT GAME
6010 PRINT "PLAY SPECIFIC GAME # (Y/N)?"
6020 S=S+1:A$=INKEY$:IF A$="" THEN 6020
6030 IF A$="Y" THEN 6060
6040 IF A$="N" THEN A=RND(-S):GOTO 6090
6050 GOTO 6020
6060 INPUT "PLAY GAME (1-65535)";S
6070 IF S<1 OR S>65535 THEN 6060
6080 A=RND(-S)
6090 RETURN

I could just call this before the game begins:

5 REM SELECT GAME
6 GOSUB 6000

10 REM INITIALIZE GRID
20 GOSUB 4000
30 REM SHOW GRID
40 GOSUB 1000
47 IF LO=0 THEN PRINT "YOU WON!":END
48 PRINT "LIGHTS ON:";LO
50 REM INPUT SQUARE
60 GOSUB 2000
70 REM TOGGLE SQUARES
80 GOSUB 3000
90 REM REPEAT
100 GOTO 30

This would be simple enough to allow the user to replay a specific game. Here is a screen shot showing two instances of the XRoar emulator running the program, and generating the same pattern by using the same random seed:

This still is not 100% what we might want. While it does allow the user to request a specific game over and over, if they choose a random game, there is no way to get back to that game — it was chosen randomly.

To do that, we’d pick a random number for the “game number”, then use that as the seed value and display it as part of the game (so the user knows which number to use next time). We would still need to do some initial random seeding at the start so the game did not choose the same pattern of game numbers.

Here is a modification to the “select game” routine with some variable changes (GN for game number):

6000 REM SELECT GAME
6010 PRINT "PLAY SPECIFIC GAME # (Y/N)?"
6020 S=S+1:A$=INKEY$:IF A$="" THEN 6020
6030 IF A$="Y" THEN 6060
6040 IF A$="N" THEN A=RND(-S)
6045 GN=RND(65535):A=RND(-GN)
6046 GOTO 6090
6050 GOTO 6020
6060 INPUT "PLAY GAME (1-65535)";GN
6070 IF GN<1 OR GN>65535 THEN 6060
6080 A=RND(-GN)
6090 RETURN

Then, we could print the game number before it prints the grid each time:

1000 REM SHOW GRID
1005 PRINT "GAME NUMBER:";GN
1010 FOR Y=0 TO 4
1020 FOR X=0 TO 4
1030 IF L(X,Y) THEN PRINT "X";:GOTO 1050
1040 PRINT ".";
1050 NEXT
1060 PRINT
1070 NEXT
1080 PRINT
1090 RETURN

Now I can have the program generate a “random” game for me, and use that game number later to get the same puzzle.

At this point, we have a fairly playable (though ugly) version of a 5×5 Lights Out game.

There are a few more “nice to haves” we can add, so we’ll do those in the next installment.

Until then…