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.