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

**Updates:**

**2023-02-06**– William Astle pointed out that Color BASIC*does*have ELSE. Not sure why I thought it didn’t — I never had a machine with plain Color BASIC. Striked out!

In the first installment, I shared a brief history of the game **Lights Out** using “extensive” research from the Wikipedia page and some YouTube videos.

This time, let’s look begin implementing the game in BASIC. My first goal is to write something generic enough that it could be easily ported to other systems. I specifically have VIC-20 in mind, since it was my first home computer.

After this is achieved, maybe we can see how much we could optimize and enhance it specifically for the CoCo (or VIC).

In **Rick Adams**‘ CoCo 3 version, he uses what appears to be the high-resolution 320×200 16-color graphics screen. It uses a joystick to move around and select squares.

It is quite nice, and reminds me of how his Shanghai game was controlled. (Rick wrote the official Color Computer version, sold on a ROM-Pak cartridge by Radio Shack.)

For my version, I’ll only use the text screen, and the keyboard to select squares.

## Representing the Grid of Lights

Since the game is played on a 5×5 grid, a simple (and obvious) way to represent that grid of lights might be to use a two-dimensioned array. Something like this:

DIM L(4,4)

That may look wrong for a 5×5 grid, but on Color BASIC, dimensions start at 0. DIM X(4) gives entries X(0), X(1), X(2), X(3) and X(4). For DIM L(4,4) we get:

+---+---+---+---+---+---+

| . | 0 | 1 | 2 | 3 | 4 |

+---+---+---+---+---+---+

| 0 | . | . | . | . | . |

+---+---+---+---+---+---+

| 1 | . | . | . | . | . |

+---+---+---+---+---+---+

| 2 | . | . | . | . | . |

+---+---+---+---+---+---+

| 3 | . | . | . | . | . |

+---+---+---+---+---+---+

| 4 | . | . | . | . | . |

+---+---+---+---+---+---+

If I were to do L(0,0)=123, the top left square would be 123:

+---+---+---+---+---+---+

| . | 0 | 1 | 2 | 3 | 4 |

+---+---+---+---+---+---+

| 0 |123| . | . | . | . |

+---+---+---+---+---+---+

| 1 | . | . | . | . | . |

+---+---+---+---+---+---+

| 2 | . | . | . | . | . |

+---+---+---+---+---+---+

| 3 | . | . | . | . | . |

+---+---+---+---+---+---+

| 4 | . | . | . | . | . |

+---+---+---+---+---+---+

Then if I did L(3,2)=456:

+---+---+---+---+---+---+

| . | 0 | 1 | 2 | 3 | 4 |

+---+---+---+---+---+---+

| 0 |123| . | . | . | . |

+---+---+---+---+---+---+

| 1 | . | . | . | . | . |

+---+---+---+---+---+---+

| 2 | . | . | . |456| . |

+---+---+---+---+---+---+

| 3 | . | . | . | . | . |

+---+---+---+---+---+---+

| 4 | . | . | . | . | . |

+---+---+---+---+---+---+

## Toggling a Grid Value

By having a two-dimensional 5×5 array like that, I can represent the 25 squares of the Lights Out game. If I made it so a value of 0 was “off” and a value of “1” was on, I could toggle the value of a square using some simple logic like this:

IF L(X,Y)=1 THEN L(X,Y)=0 ELSE IF L(X,Y)=0 THEN L(X,Y)=1

Or, since I know I am only going to be putting a 0 or 1 there, I could simplify:

IF L(X,Y)=1 THEN L(X,Y)=0 ELSE L(X,Y)=1

That’s a bit clunky, and requires a BASIC that has the **ELSE** keyword. ~~While the CoCo got ELSE with Extended BASIC, it was not present on the original Color BASIC.~~ (Thanks, William A.!) My Commodore VIC-20 does not have it. To avoid using ELSE, it could be written like this:

100 IF L(X,Y)=1 THEN L(X,Y)=0:GOTO 120

110 L(X,Y)=1

120 ...program continues...

That “GOTO 120” to skip the next line is very important, else the first line would set it to 0, then the next line would set it back to 1. See? Clunky.

Since our goal is simply to toggle a square from on to off, or from off to on, the value is not important. It could be any two values, such as -57 and +123, using that code.

BUT, we can do better. We can make use of the BASIC mathematical **NOT** keyword. **NOT** is available in 1980 Color BASIC and even on the VIC-20.

**NOT** can be used on a number to flip it back and forth between two values:

PRINT NOT 0

-1

PRINT NOT -1

0

If we made 0 mean OFF, and -1 mean ON, we could toggle them back and forth by using NOT.

100 IF L(X,Y)=NOT L(X,Y)

That looks much simpler. And, as an added bonus, when you compare things in BASIC, the result is either -1 for TRUE, or 0 for FALSE. This is what the **IF** keyword is expecting. For example:

IF -1 THEN PRINT "THIS IS TRUE"

IF 0 THEN PRINT "YOU WON'T SEE THIS"

That will print “THIS IS TRUE”.

This would allow printing something quite easily based on the variable. We could use a FOR/NEXT loop for each row of the grid, and a second FOR/NEXT loop for each column in that row. A simple check could be done to decide if an “X” or “Y” should be printed for that grid element.

1000 REM SHOW GRID

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

Since 0 represents FALSE (light is on), and since BASIC variables are initialized to 0, running that program should present a grid of all lights off (represented by a dot):

.....

.....

.....

.....

.....

If we set some of those array elements to -1 (FALSE, off), like this:

10 L(0,0)=-1

20 L(1,1)=-1

30 L(2,2)=-1

40 L(3,3)=-1

50 L(4,4)=-1

…then running it would show something like this:

X....

.X...

..X..

...X.

....X

This gives us a very simple “show grid” subroutine.

## Selecting a Square to Toggle

If we go really, really old school, we could use INPUT and ask the user to tell us which square to toggle by using X and Y coordinates.

2000 REM INPUT SQUARE

2010 INPUT "X (0-4)";X

2020 INPUT "Y (0-4)";Y

Or, both variables could be asked for at the same time using “INPUT X,Y” like this:

2000 REM INPUT SQUARE

2010 INPUT "X,Y (0-4,0-4)";X,Y

To make sure typing a number larger than the array size (like 5), or smaller (like -5), does not crash the program, we should add some error checking:

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

Do you remember when we were learning BASIC like this? I promise, we’ll make it less remedial later.

## Toggling that Square

Once we know the X and Y for a square inside the array, we can toggle that square as shown earlier:

L(X,Y)=NOT L(X,Y)

If the square value was 0, it will become -1. If it was -1, it will become zero. NOT does the work for us.

But, the way Lights Out works is it not only toggles that square, but the ones above, below, left and right of it (if there is a square there). Our toggle routine should do all that for us — and it should also know when there is not a square above, below, left or right of it:

3000 REM TOGGLE SQUARES

3010 L(X,Y)=NOT L(X,Y)

3020 IF X>0 THEN L(X-1,Y)=NOT L(X-1,Y)

3030 IF X<4 THEN L(X+1,Y)=NOT L(X+1,Y)

3040 IF Y>0 THEN L(X,Y-1)=NOT L(X,Y-1)

3050 IF Y<4 THEN L(X,Y+1)=NOT L(X,Y+1)

Let’s walk through that…

**Line 3010**– toggles the selected square.**Line 3020**– if the selected square’s column (X) is greater than 0 (1-4), there will be a square to the left. Toggle that square (X-1).**Line 3030**– if the selected square’s column (X) is less than 4 (0-3), there will be a square to the right. Toggle that square (X+1).**Line 3040**– if the selected square’s row (Y) is greater than 0 (1-4), there will be a square above it. Toggle that square (Y-1).**Line 3050**– if the selected square’s row (Y) is less than 4 (0-3), there will be a square below it. Toggle that square (Y+1).

## Putting it all together…

By adding a “RETURN” at the end of those three blocks of code, we can make them subroutines and call them using GOSUB. We now have the basic framework for a Lights Out game!

10 REM SHOW GRID

20 GOSUB 1000

30 REM INPUT SQUARE

40 GOSUB 2000

50 REM TOGGLE SQUARES

60 GOSUB 3000

70 REM REPEAT

80 GOTO 10

1000 REM SHOW GRID

1010 FOR Y=0 TO 4

1020 FOR X=0 TO 4

1030 IF L(X,Y) THEN PRINT ".";:GOTO 1050

1040 PRINT "X";

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)

3020 IF X>0 THEN L(X-1,Y)=NOT L(X-1,Y)

3030 IF X<4 THEN L(X+1,Y)=NOT L(X+1,Y)

3040 IF Y>0 THEN L(X,Y-1)=NOT L(X,Y-1)

3050 IF Y<4 THEN L(X,Y+1)=NOT L(X,Y+1)

3060 RETURN

BUT, since variables initialize as 0, and see means FALSE (off), there would be no lights on at the start of this game. The game would initialize to “already won” ;-) There would need to be some kind of initializing routine that sets some or all of the squares “on” at the start of the game.

But even with that, this would still be an un-win-able game – there is no code that checks to see if all the lights have been turned off.

Let’s add that in the next installment…

William AstleOne correction: ELSE was present in Color Basic. Other Basics don’t have it, but the Coco always did.

Allen HuffmanPost authorReally? Maybe it was the MC-10 I was thinking about? I remember writing an adventure game in 1984, and not using ELSE because it needed to run on other levels of CoCo.

I’ll update it and blame it on Commodore BASIC not having it. :)

Johann KlasekYou could still use 1 and toggling is also easy nearly as fast with L(X,Y)=1-L(X,Y).

With 0 and 1 the display routine could be simplified to PRINT D$(L(X,Y) where D$(0)=”.” and D$(1)=”X”. But you can still use -1 and add the ABS function around D$() in above PRINT.

Allen HuffmanPost authorOh, man. I didn’t even think about something like that. 1-1 becomes 0. 1-0 becomes 1… That would feel much better, and I am guessing subtracting one is probably smaller and less COu time than doing the NOT.