# 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 GAME6 GOSUB 600010 REM INITIALIZE GRID20 GOSUB 400030 REM SHOW GRID40 GOSUB 100047 IF LO=0 THEN PRINT "YOU WON!":END48 PRINT "LIGHTS ON:";LO50 REM INPUT SQUARE60 GOSUB 200070 REM TOGGLE SQUARES80 GOSUB 300090 REM REPEAT100 GOTO 301000 REM SHOW GRID1005 PRINT "GAME NUMBER:";GN1010 FOR Y=0 TO 41020 FOR X=0 TO 41030 IF L(X,Y) THEN PRINT "X";:GOTO 10501040 PRINT ".";1050 NEXT1060 PRINT1070 NEXT1080 PRINT1090 RETURN2000 REM INPUT SQUARE2010 INPUT "X,Y (0-4,0-4)";X,Y2020 IF X<0 OR X>4 OR Y<0 OR Y>4 THEN 20102030 RETURN3000 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 RETURN4000 REM INITIALIZE GRID4010 PRINT "INITIALIZING..."4020 FOR A=1 TO 104030 Y=RND(5)-14040 X=RND(5)-14050 GOSUB 30004060 NEXT4070 RETURN6000 REM SELECT GAME6010 PRINT "PLAY SPECIFIC GAME # (Y/N)?"6020 S=S+1:A\$=INKEY\$:IF A\$="" THEN 60206030 IF A\$="Y" THEN 60606040 IF A\$="N" THEN A=RND(-S)6045 GN=RND(65535):A=RND(-GN)6046 GOTO 60906050 GOTO 60206060 INPUT "PLAY GAME (1-65535)";GN6070 IF GN<1 OR GN>65535 THEN 60606080 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 GRID15 MV=020 GOSUB 4000`

…and increment it after every move:

`90 REM REPEAT95 MV=MV+1100 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 GRID1005 PRINT "GAME NUMBER:";GN1010 FOR Y=0 TO 41020 FOR X=0 TO 41030 IF L(X,Y) THEN PRINT "X";:GOTO 10501040 PRINT ".";1050 NEXT1060 PRINT1070 NEXT1080 PRINT "MOVES:";MV;"LIGHTS ON:";LO1090 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 200200 REM GAME WON220 PRINT "YOU WON IN";MV;"MOVES."230 INPUT "PLAY AGAIN (Y/N)";Q\$240 IF Q\$="Y" THEN 5250 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 SQUARE2010 INPUT "X,Y (0-4,0-4 OR -1,-1)";X,Y2015 IF X=-1 THEN IF Y=-1 THEN 2302020 IF X<0 OR X>4 OR Y<0 OR Y>4 THEN 20102030 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 GRID1005 PRINT "GAME NUMBER:";GN1006 PRINT "   12345"1010 FOR Y=0 TO 41015 PRINT Y+1;1020 FOR X=0 TO 41030 IF L(X,Y) THEN PRINT "X";:GOTO 10501040 PRINT ".";1050 NEXT1060 PRINT1070 NEXT1080 PRINT "MOVES:";MV;"LIGHTS ON:";LO1090 RETURN`

…and…

`2000 REM INPUT SQUARE2010 INPUT "X,Y (1-5,1-5 OR 0,0)";X,Y2015 IF X=0 THEN IF Y=0 THEN 2302020 IF X<1 OR X>5 OR Y<1 OR Y>5 THEN 20102025 X=X-1:Y=Y-12030 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.