3D NOUGHTS & CROSSES
--------------------
Add a new dimension to this popular game with this program for your 48K
Spectrum from Bill Welch of Herne Hill.


This is a game played on a cubical "board" containing 27 spaces, any one of
which can be filled with a nought or a cross. The board is represented on the
screen by three conventional noughts and crosses boards placed one above the
other. The levels are labelled A, B and C and the spaces on each level are
numbered from one to nine. The object of the game is not to make the first
row of three  that is too easy for the player who goes first  but to make
more complete rows than your opponent, the computer.

When the program is RUN, the computer asks you to choose a skill level, then
draws the board and asks if you want to go first. The computer plays the 'X'
and you play the 'O'. Any row of three will count, whether horizontal,
vertical or diagonal; some of them are hard to spot at first, but you'll soon
get the hang of it. There are 49 possible rows. Examples: A1, B1 and C1 make
a row, and so do A1, B5 and C9. If you change your mind halfway through
entering a move, press any obviously wrong key and you will be able to start
your entry again.

In between each move the computer checks through all the possible rows and
counts any completed ones by making an audible blip. The blip is higher for
the computer's rows than for yours, so you can listen to your progress.

The computer is hard to beat at first, especially at level three, but it can
be done, especially if you go first! Why not try to improve the computer's
game? You can see how its strategy is organised by reading the program notes
and you could, for example, change the order in which it checks for almost
complete rows by changing the order of the numbers 1-49 in the DATA
statements at lines 1060-1080.

Variables

To save on memory use, most of the variables are only temporary, and are used
for different purposes in different parts of the program. These are the
variables which have a single constant use:

a$       Contains the character of the key last pressed when an input
          was requested.
a()     - An array containing one element for each of the 27 spaces on
          the board.
b()      An array containing one element for each of the 49 possible
          rows of three.
level    The skill level which has been selected.
posn     The number of the element of a() corresponding
          to the move which has been selected by you or the computer.
go       The number of moves which have been made.
m        An indicator of whose turn it is to move.

Other variables used are: g, f, a, b, p, q, t and no.

Memory

As listed, this program will not run on a 16K machine  it uses more than
8,300 bytes. However, it could be compressed for a 16K machine by omitting
the REM statements and perhaps using some of the standard Sinclair memory
saving methods. For example, numbers can be referred to using the VAL
function; eg. PRINT AT VAL "22",VAL "2"; and so on. Again, some of the lines
can be run together with the use of colons.

Program notes

Line 5          Calls the instructions subroutine at line 9900.
Lines 20-70     Define the 'X' and 'O' graphics characters.
                This short routine, with the appropriate DATA
                statements, can be used to define any number
                of characters up to the maximum of 21.
Lines 80-90     Initialise the arrays a() and b(), and the move
                counter, and set the screen attributes for the game.
Line 95         POKE 23658,8 sets CAPS LOCK at capitals,
                which simplifies mug-trapping. POKE 23659,1
                allows you to PRINT AT line 22.
Lines 100-175   Set up the board.
Lines 180-198   Set who is to go first. Line 190 calls an INKEY$
                subroutine at line 9500 which stores
                the key pressed in a$, Note line 194; the effect
                of the commas after a PRINT AT statement is to
                blank out half a line per comma in the current
                PAPER colour. m is set to zero when it is the
                computer's move, and one when it is your move.
                If the computer is to go first, the program jumps
                to 1000.
Lines 200-350   Ask for your move, and mug-trap the results
                (again returned in a$). An acceptable move is
                turned into a number from one to 27 and stored
                in the variable, posn, for use later when
                displaying the move on the screen The corresponding
                element of array a() is checked to see if it is empty;
                if it is, a four is inserted. (Four is used for human's
                moves, and one for the computer's moves.) The program
                then jumps to line 8000.
Lines 1000-7910 These are used for the computer's moves.
Line 1005       Lets you know that the computer is working out
                its move. After each stage of working, if the computer
                has not found an acceptable move it will add an extra
                full stop after "I'M THINKING ..." so that you can see
                how hard it has had to think!
Lines 1010-1025 If the centre space is empty, the computer will always
                choose to go there. The centre space corresponds to
                element 14 in array a(). Once a move has been chosen,
                the computer always jumps to line 8000. If the centre
                space has already been filled, the computer will move
                on to line 1030.
Line 1030       At skill level one, the computer skips the rest
                of its strategy and jumps to a routine at line 7000
                which generates a random move. Lines 1060-1080 Contain DATA
                which tells the computer the order in which
                it is to scan array b() for the next steps in its strategy.
Line 1105       At skill level two, the computer skips the next two steps
                of its strategy.
Lines 1110-1135 Each element of array b() contains the sum of
                the numbers held in three elements of array a()
                corresponding to a row of three spaces on the
                board. For example. a(1) plus a(2) plus a(3)
                corresponds to the state of the row from the
                top far left of the board (space A1) to the top
                far right (space A3). This total is stored in one
                of the elements of array b(). In this section of
                the program, the computer checks through array b()
                looking for the number '8', which represents a row
                on the board containing two 'O's and an empty space.
                If thecomputer finds such a row, it jumps to a routine
                at line 7500 which will identify the empty space so
                that the computer can put an 'X' there to block your row.
Lines 1140-1175 If you are not in a position to complete a row next move,
                the computer checks through array b() again, this time
                looking for the number '2'. This corresponds to a row on
                the board containing two Xs and a blank space. If such a
                row is found, the computer again jumps to line 7500 so
                that it can identify the empty space and complete a row
                of Xs.
Lines 1180-2010 Failing these, the computer looks for a row containing
                two blank spaces and one X. If it finds one, it will
                insert another X, threatening to complete a row on its
                next move.
Lines 2015-2055 If the computer can find none of these possibilities,
                it will check array a() in the order
                given in the DATA statement in line 2055 to
                see if any of the centre face or corner spaces
                are empty. It will make its move in the first one
                it finds. Plenty of space is left between lines
                2055 and 7000 to insert more checks if you
                want to elaborate on the computer's strategy.
Lines 7000-7030 Generate a random move in any empty space
                on the board.
Lines 7500-7800 Contain a routine used by the computer to find
                which of the spaces, in a line it has identified in
                one of its scans of array b(), is empty. On exiting
                from this routine, the temporary variable - a -
                indicates the appropriate empty element in array a().
Line 7900       Puts the computer's move into array a() and also into
                the variable - posn - for later use when displaying the move.
Lines 8000-8080 Find the correct screen address for the selected move
                and print an 'X' or 'O' as appropriate. The 'O' is a
                Graphics A and the 'X' is a Graphics B. The selected
                move is also displayed at the bottom of the screen.
Lines 8500-8745 Scan through array a() in all the combinations of three
                elements which correspond to a row of three on the board.
                In each case the sum of the three elements is stored in an
                element of array b() by means of a subroutine at line 9600.
                The temporary vartable - a - is given the value 9600 to
                shorten the repeated calls to this subroutine.
Lines 8750-8770 Increase the move counter by one and check
                for the end of the game.
Line 8810       Blanks out the message line at the bottom of the screen.
Line 8820       If m is one, it becomes zero; if zero, it becomes one.
                This indicates whether it is your move or the computer's.
                This neat line was borrowed from J.A. Enness's program,
                Squareology, in ZX Computing, Summer 1982.
Line 8830       Jumps to line 1000 if it is the computer's move next,
                or line 200 if it is your move next.
Lines 9000-9050 When the game is over, this routine counts the completed
                rows of Os and Xs by scanning array b().
Lines 9200-9480 Display the final score and suitable messages, with
                jubilant or otherwise sound effects.
                (Room for improvement here, if you're interested.)
                You are asked if you want to play again. After the POKEs
                in line 95, if you break into direct command mode without
                POKE 23659,2 (line 9460) you will get a very strange
                screen display!
Lines 9500-9540 Contain an INKEY$ subroutine which waits for a key
                to be pressed, and stores the result in a$ for return.
Lines 9600-9640 Contain the subroutine used by the section of the program
                starting at line 8500. After each move, it stores the
                state of each possible row of three in an element of
                array b(). It gives a low blip when it finds a row of Os,
                and a higher one when it finds a row of Xs. It keeps quiet
                about mixed or empty lines.
Lines 9900-9995 Contain the subroutine which displays the instructions
                and sets the skill level.