Page 4
The Tic Tac Toe program needs to be explained in a number of different ways. It’s really a highly sophisticated program, but if you read our explanations, you will be able to see how it has been put together.
The operation and performance of each instruction needs to be known. This is called your “home-work.” You need to “read” each of the instructions and know what they are “saying.” These details have already been covered in our PIC Programming Course, and you should read this course or at least read the INSTRUCTION SET before starting on this part of the Tic Tac Toe program.
The Instruction Set for the PIC16F84A is identical to the PIC16F628.
The next thing that needs to be explained is the overall operation of each routine. That’s what we have done in this section.
You also need to know why the programmer chose each instruction, as well as the “hidden” elements of the routines such as the value of the “Computer Piece” and “Player Piece.”
The micro starts at address location 000. To get it to start at this location, ORG 00 is the first instruction. It is really a “pseudo” instruction. It does not tell the micro to do anything, it tells the assembler to place the next instruction (MOVLW 07) at address 000. ORG 00 does not appear in the final .hex listing - it has already done its job.
MOVLW 07 disables the comparators in the PIC16F628. This makes the PIC16F628 very similar to a PIC16F84A as have produced a program to show how to migrate from an ‘F84A to a ‘628
The only differences between the two micro’s (for the moment) are: internal 4MHz oscillator and 3 extra in/out lines. This means the Tic Tac Toe project does not need external oscillator components and 3 more lines of PortA are available (RA5, RA6 and RA7 - of which we have used RA6 and RA7).
The remaining instructions in SetUp, determine the in/out situation for each of the lines of port A and B (via the TRIS registers - the registers that are directly below - figuratively speaking - PortA and PortB and can be found as file 05 and file 06 - but in Bank 1), clear the flag file (2F) and clear the output lines in files 05 and 06 - these files are in bank 0 - the bank where your program is placed.
The last instruction in SetUp sends the micro to Attract Mode. We deal with Attract mode on another page.
ORG 0 ;This is the start of memory for the program. SetUp MOVLW 07 ;Disable the comparators MOVWF 1Fh ;File 1F is the CMCON file BSF 03,5 ;Go to Bank 1 CLRF 06 ;Make all port B output MOVLW 18h ;Load W with 0001 1000 MOVWF 05 ;Make RA0,1,2,6,7 output and RA3, RA4 input BCF 03,5 ;Go to Bank 0 - the program memory area. CLRF 2F ;Clear the button-press file CLRF 05 ;Clear the output lines of PortA CLRF 06 ;Blank the output GOTO Att
Att sub-routine calls a Delay routine that contains an instruction to go to Preload when either button is pressed.
The program below shows Preload sub-routine. Preload puts “5” into file 30h and clears the 9 files for the display. Read below for the purpose of files 30h and 3Ah. The following diagram shows the board-files and the two “hidden” files:
Tic Tac Toe files for the “board”
When either button is pressed during Attract Mode, the micro goes to Tic Tac Toe section of the program. The loop routine for Tic Tac Toe is Main. It is accessed via Preload sub-routine.
The effect you will see on the Tic Tac Toe project is this: The display goes blank. When button “A” is pressed, a flashing orange cursor starts at the top left square. Each time button “A” is pressed, it increments across each row until it reaches the bottom right-hand square. It then disappears and starts at the top left square.
When button “B” is pressed, the flashing cursor is turned into a red “Player” piece. The micro then executes a number of sub-routines and produces a green “Computer” piece on the display.
Main is a loop routine similar to a RASTER on a TV. It takes information from 9 files (31h, 32h, 33h, 34h, 35h, 36h, 37h, 38h, and 39h) and displays it by showing the top row, middle row and bottom row. This is repeated at a rapid rate so that all rows appear to be illuminated at the same time. This is called SCANNING or MULTIPLEXING.
The cursor actually starts in file 30h. This file is not displayed and thus the cursor is “hidden.” At the end of the display it is transferred to file 3A and thus it is removed from the display. The program returns the cursor to file 30h.
Main is not an “intelligent” routine. It’s a simple “display” routine. It simply shows whatever is contained in the 9 display files.
A file can contain one of four values.
If it contains the value 01, bit0 is set and this represents the player. When bit0 is set, the red element of a LED will be illuminated, via Main sub-routine. We will see in a moment, how this is done.
If it contains the value 04, bit2 is set and this represents the computer. When bit2 is set, the green element of a LED will be illuminated, via Main sub-routine.
If it contains the value 05, bits 0and 2 are set and this represents the cursor. The LED will display “orange.”
If it contains the value 08, bit3 is set and this represents the “hidden cursor.”
On page 2 of this project, the activation of the display is explained. The six elements of the three top LEDs are taken to 6 lines of port B and when the corresponding “sinking” transistor is turned on, the LEDs will illuminate.
A table for the 64 combinations is also included and this shows how the different patterns are produced.
The display routine in Main uses bits 0 and 2 of the first three files to turn on the red and green emitters in top 3 LEDs. The sinking transistor is turned on and the top row is displayed. This is repeated with the middle and bottom rows.
To make the cursor flash, the program needs to know where it is located. When the cursor is visible on the display, it has the value 05. This represents the red and green crystals in a LED. The program turns on the top, middle and bottom rows for 20h loops (thirty-two loops)
After 20h loops, the micro goes to Main 19 where it executes ten loops, looking for 05, by testing bits 0 and 2. When 05 is found, it puts 08 into the file and returns to Main. If 05 is not found, the micro looks for 08. When 08 is found, it puts 05 in the file and returns to Main. This produces a flashing cursor with an equal on/off ratio. The cursor value is also changed, even when it is hidden in file 30h.
Preload MOVLW 05 ;Put cursor into "ready" file MOVWF 30h CLRF 31h CLRF 32h CLRF 33h CLRF 34h CLRF 35h CLRF 36h CLRF 37h CLRF 38h CLRF 39h CLRF 3Ah BTFSS 05,3 ;Make sure button "A" is released GOTO Preload BTFSS 05,4 ;Make sure button "B" is released GOTO Preload GOTO Main ;Go to Main ;Player Value = 01 = red ;Computer Value = 04 = green ;Cursor = 05 Main MOVLW 20h ;Loops of Main for flashing cursor MOVWF 22h ;File to decrement MainA BTFSC 2F,0 ;ButtonA pressed first time? GOTO MainB BTFSS 05,3 ;Test for ButtonA CALL ButtonA MainB BTFSC 2F,1 ;ButtonB pressed first time? GOTO MainC BTFSS 05,4 ;Test for ButtonB CALL ButtonB MainC BTFSS 31h,0 GOTO Main1 BSF 06,5 Main1 BTFSS 31h,2 GOTO Main2 BSF 06,4 Main2 BTFSS 32h,0 GOTO Main3 BSF 06,3 Main3 BTFSS 32h,2 GOTO Main4 BSF 06,2 Main4 BTFSS 33h,0 GOTO Main5 BSF 06,1 Main5 BTFSS 33h,2 GOTO Main6 BSF 06,0 Main6 BSF 05,0 CALL Del1 BCF 05,0 CLRF 06 CALL Del1 BTFSS 34h,0 GOTO Main7 BSF 06,5 Main7 BTFSS 34h,2 GOTO Main8 BSF 06,4 Main8 BTFSS 35h,0 GOTO Main9 BSF 06,3 Main9 BTFSS 35h,2 GOTO Main10 BSF 06,2 Main10 BTFSS 36h,0 GOTO Main11 BSF 06,1 Main11 BTFSS 36h,2 GOTO Main12 BSF 06,0 Main12 BSF 05,2 CALL Del1 BCF 05,2 CLRF 06 CALL Del1 BTFSS 37h,0 GOTO Main13 BSF 06,5 Main13 BTFSS 37h,2 GOTO Main14 BSF 06,4 Main14 BTFSS 38h,0 GOTO Main15 BSF 06,3 Main15 BTFSS 38h,2 GOTO Main16 BSF 06,2 Main16 BTFSS 39h,0 GOTO Main17 BSF 06,1 Main17 BTFSS 39h,2 GOTO Main18 BSF 06,0 Main18 BSF 05,1 CALL Del1 BCF 05,1 CLRF 06 BTFSC 05,3 ;Skip if ButtonA is still pressed BCF 2F,0 ;Clear button-press flag BTFSC 05,4 ;Skip if ButtonB is still pressed BCF 2F,1 ;Clear button-press flag DECFSZ 22h,1 GOTO MainA ;The following section hides and shows cursor ;If cursor is showing, it hides cursor ;If cursor is hidden, it shows cursor ;Cursor changes from 05 to 08 to 05 etc MOVLW 0A ;Ten loops of routine MOVWF 23h ;Loop file MOVLW 30h ;Start of files for board MOVWF 04 ;Load start into FSR Main19 BTFSS 00,0 ;Test bit0 of INDF GOTO Main20 BTFSS 00,2 ;Is bit2 = HIGH? GOTO Main20 MOVLW 08 ;File contains cursor. Put 08 into file to "hide" MOVWF 00 ;08 will be put into a file 30h to 39h GOTO Main ;Cursor has been hidden Main20 INCF 04,1 ;Increment pointer DECFSZ 23h,1 ;Decrement loop file GOTO Main19 MOVLW 30h ;Start of files for board MOVWF 04 ;Load start into FSR Main21 BTFSC 00,3 ;Look for "8" in a file GOTO Main22 INCF 04,1 ;Increment the pointer GOTO Main21 Main22 MOVLW 05 ;Put 5 in file looked at by FSR MOVWF 00h INCF 28h ;Increment the RANDOM NUMBER file INCF 28h CALL **Stale** GOTO Main END ;Tells assembler end of program
During the execution of Main, the micro is looking for Button “A” or “B.”
If button “A” (Move) is pressed, the player has the first move on the board. If button “B” is pressed, the computer has the first move.
If button A is pressed, the micro goes to ButtonA routine. The button-press flag is set so the routine is only accessed ONCE for each press of the button. If a button-press flag is not included, the micro will increment the cursor and return to Main. If the button is still pressed, the micro will advance the cursor one more location. This will continue until the button is released. We only want one advancement.
If the “Win LED” bit is set, the display is cleared for a new game. If the bit is not set, the micro looks for the cursor. The cursor can be 08 or 05. To test for 08, the program tests bit 3 in files 30h to 39h.
The program assumes (correctly), that the cursor will be found. Consequently, there is no decrementing loop. The program looks at these files via a feature called INDIRECT ADDRESSING.
The first file is loaded into FSR - the File Select Register. The micro then looks at file 00. This is not a normal file. It is called the INDIRECT FILE. It always contains the data of the file looked at by FSR. In our case, looking at file 00 will be looking at file 30h. You can carry out all the tests and operations on file 30h, via file 00.
By incrementing FSR, we look at file 31h. This is done until the cursor is found.
When the cursor is found, the program tests to see if it has passed the end of the board (file 3Ah).
At ButA3, the working register (W) is loaded with 3A and compared with FSR. If it has reached file 3A, the zero flag (bit 2) in file 03 will be SET. The micro will advance down the program and clear file 3A. File 30h will be loaded with 05 and the micro will return to Main.
If the cursor has not reached the end of the board, the file containing the cursor is cleared via indirect addressing mode and the next file is tested at ButA6. If it is empty, it is loaded with 05. If it is not empty, the FSR file incremented and tested. The micro then returns to Main.
ButtonA BSF 2F,0 ;Set button-press flag BTFSS 2F,3 ;Is Win-LED/stalemate bit=1? GOTO ButAA BCF 2F,3 BCF 05,6 BCF 05,7 MOVLW 05 ;Put cursor into "ready" file MOVWF 30h CLRF 31h CLRF 32h CLRF 33h CLRF 34h CLRF 35h CLRF 36h CLRF 37h CLRF 38h CLRF 39h CLRF 3Ah RETURN ButAA MOVLW 30h ;Start of "board" MOVWF 04 ;Start FSR at file 30h ButA1 BTFSC 00,3 ;Look for "8" GOTO ButA3 ;Found cursor BTFSS 00,0 ;Look for first part of "05" GOTO ButA2 ;Cursor not found BTFSS 00,2 ;Look for second part of "05" GOTO ButA2 GOTO ButA3 ;Found cursor ButA2 INCF 04 GOTO ButA1 ButA3 MOVLW 3Ah ;Has cursor reached end of "board?" XORWF 04,0 BTFSS 03,2 ;Test the zero flag GOTO ButA4 ;not at end of board CLRF 3Ah ;reached end of board MOVLW 05 MOVWF 30h ;Return cursor to start RETURN ButA4 CLRF 00 ;Clear the cursor ButA5 INCF 04,1 MOVLW 3A XORWF 04,0 ;If cursor has reached end of board, BTFSS 03,2 ; return it to file 30h GOTO ButA6 MOVLW 30h MOVWF 04 ;Return cursor to start ButA6 MOVLW 00 XORWF 00,0 ;Is board location empty? BTFSS 03,2 ;Test zero flag GOTO ButA5 ;Not empty MOVLW 05 ;Empty location MOVWF 00 ;Show cursor in new location RETURN
Button B (Play) converts a flashing cursor into a red “Player Piece.” It does this by creating 9 loops to look at files 31h to 39h. It looks at the files via Indirect Addressing. It firstly looks for the cursor with a value of 05, then 08. The program “looks into” file 00 ands “sees” the file we have placed in FSR (file 04).
If the cursor is found, the file00 is loaded with 01. The value 01 creates a red LED on the display. File 30h is then loaded with 05 to hide the cursor.
If the cursor is not found, the program assumes the player wants the computer to make the first move.
ButtonB BSF 2F,1 ;Set button-press flag MOVLW 09 MOVWF 23h ;Decrementing file MOVLW 31h ;Start of "board" MOVWF 04 ;FSR starts at file 31h ButB1 MOVLW 05 XORWF 00,0 ;Is the file looked at by FSR=5? BTFSC 03,2 ;Test zero flag GOTO ButB2 ;Found MOVLW 08 ;Not found try "08" = flashing cursor XORWF 00,0 ;Is the file looked at by FSR=8? BTFSS 03,2 GOTO ButB3 ;Not found ButB2 MOVLW 01 ;Cursor found MOVWF 00 ;Make file = 1 = red MOVLW 05 MOVWF 30h ;Put cursor into "hide" file GOTO PWin ButB3 INCF 04,1 ;Increment the pointer DECFSZ 23h GOTO ButB1 GOTO PWin ;ButtonB pushed for computer goes first
ButtonB converts the cursor into a player piece and exits with the cursor in file 30h. The micro then goes to PWin.
(PWin looks for all possibilities for PLAYER WIN by looking for a “1” in bit0 in three files.) The sub-routine contains all possible combinations of rows, columns and diagonals.
If bit0 is HIGH in three files in a row or column etc, the “Player Wins” LED is illuminated and the flag (2F,3) is SET.
If no “Player Win” is detected, a stalemate possibility is tested (CALL Stale). If the stalemate flag (2F,3) is not set, the micro goes to CWin.
;This sub-routine sees if "Player WINS" ;Check all possibilities for PLAYER WIN ;Looking for a HIGH in bit0 = 01 in three files ;This routine is in "Linear Programming Mode" PWin BTFSS 31h,0 GOTO PWin1 BTFSS 32h,0 GOTO PWin1 BTFSC 33h,0 GOTO PWin21 PWin1 BTFSS 34h,0 GOTO PWin2 BTFSS 35h,0 GOTO PWin2 BTFSC 36h,0 GOTO PWin21 PWin2 BTFSS 37h,0 GOTO PWin3 BTFSS 38h,0 GOTO PWin3 BTFSC 39h,0 GOTO PWin21 PWin3 BTFSS 31h,0 GOTO PWin4 BTFSS 34h,0 GOTO PWin4 BTFSC 37h,0 GOTO PWin21 PWin4 BTFSS 32h,0 GOTO PWin5 BTFSS 35h,0 GOTO PWin5 BTFSC 38h,0 GOTO PWin21 PWin5 BTFSS 33h,0 GOTO PWin6 BTFSS 36h,0 GOTO PWin6 BTFSC 39h,0 GOTO PWin21 PWin6 BTFSS 31h,0 GOTO PWin7 BTFSS 35h,0 GOTO PWin7 BTFSC 39h,0 GOTO PWin21 PWin7 BTFSS 33h,0 GOTO PWin8 BTFSS 35h,0 GOTO PWin8 BTFSC 37h,0 GOTO PWin21 PWin8 CALL Stale BTFSS 2F,3 GOTO **CWin** RETURN PWin21 BSF 05,6 ;Player WINS! BSF 2F,3 ;Set the Win-LED/stalemate bit RETURN
CWin checks for a Computer WIN. The program checks for all possibilities for “COMPUTER WIN”
The program looks for a HIGH in bit2 = 04 in 2 files. This routine is a “Algorithm.”
**CWin** MOVLW 0FFh ;The value will be incremented to 00! MOVWF 25h ;Table jump file CWin1 CLRF 27h ;Clear the Computer counter MOVLW 03 MOVWF 26h ;Fetch 3 table values in a loop. CWin2 INCF 25h,1 ;Increment the table-jump file MOVF 25h,0 ;Copy jump file into W CALL Table1 ;Get first table value XORLW 0FFh ;Look for end-of-table BTFSC 03,2 ;Test zero flag GOTO **Stop** ;End of table found - no result obtained MOVF 25h,0 ;Copy jump file into W again CALL Table1 ;Call table again as previous value was lost via XORLW MOVWF 04 ;Move table value into FSR BTFSC 00,0 ;Look for unwanted player piece DECF 27h,1 ;Dec. computer counter so count cannot be recognised BTFSC 00,2 ;Look at bit2 of file 31h (first table value) INCF 27h,1 ;Increment the Computer counter CWin3 DECFSZ 26h,1 ;Decrement the 3 table-values counter GOTO CWin2 ;Loop for next piece MOVLW 02 ;See if 2 computer pieces are found XORWF 27h,0 BTFSS 03,2 GOTO CWin1 ;2 computer pieces not found CWin4 MOVF 25h,0 ;2 Computer pieces found. Put 25h into W CALL Table1 ;Locate table value MOVWF 04 ;Put W into FSR MOVF 00,1 ;Move value in file in and out to see if it is zero BTFSS 03,2 ;Test zero flag GOTO CWin5 ;Not zero MOVLW 04 ;Square is zero. Load computer piece MOVWF 00 BSF 05,7 ;Computer WINS! BSF 2F,3 ;Set the Win-LED/stalemate bit RETURN CWin5 DECF 25h,1 GOTO CWin4
Stop sub-routine looks for a “stopper.” Any row or diagonal containing a “2” must be stopped.
i.e: look for two files in a row or diag with a value of 01. The sub-routine uses Table 1. It contains all the row and diagonals for the game. The sub-routine picks up 3 values at a time and sees if the answer is “2.”
The value “01” has been chosen for the player value so the values in a row can be added to get “3” for a “Player Win” or “2” for this sub-routine. That’s why the “Computer Value” has been chosen as “04.”
A very clever programming trick is to load a file with a value that is one more than the required value. This allows the program to decrement the file in a loop. You will notice the file gets decremented before it enters to loop during the first execution. That’s why the file must have a value “one higher” than required.
The end-of-table is detected by testing the highest bit. Since no values are higher than 80h, this method can be used.
If the sub-routine does not produce a result, the micro goes to the next sub-routine: Corner.
The program does not know if the player is in the first two locations, the last two or the end locations of a row or diagonal. It must go back to the beginning of the set-of-three in the table and check each location. That’s why the program must complete the 3 values in the table before adding the computer piece.
If you jump out of the program as soon as you get a result of “2,” you will not know where the player pieces are located and the program will not be able to locate the 3 files in the row.
If a computer piece is found, the player counter (file 27h) is incremented by 80h, by setting bit 7. This prevents the file becoming “02.”
The rest of the program is quite clear. The computer value is placed in the file by “Indirect Addressing.”
**Stop** MOVLW 0FFh ;The value will be incremented to 00! MOVWF 25h ;Table jump file Stop1 CLRF 27h ;Clear the "player" counter MOVLW 04 ;This will be decremented to 3! MOVWF 26h ;Fetch 3 table-values in a loop. Stop2 DECFSZ 26h,1 GOTO Stop2A GOTO Stop4 ;3 values have been processed Stop2A INCF 25h,1 ;Increment the table-jump file MOVF 25h,0 ;Copy jump file into W CALL Table1 ;Get first table value MOVWF 04 ;Move table value into FSR BTFSC 00,7 ;Look for end-of-table GOTO **Corner** ;End of table found - no result obtained BTFSC 00,2 ;Look at bit2 of file 31h for computer piece GOTO Stop3 ;Computer piece found BTFSC 00,0 ;Look at bit0 of file 31h (first table value) INCF 27h,1 ;Increment the "player" counter GOTO Stop2 Stop3 BSF 27h,7 ;Set bit 7 of "player" counter GOTO Stop2 Stop4 BTFSC 27h,7 ;Is computer in the row? GOTO Stop1 BTFSS 27h,1 ;Is counter=2? GOTO Stop1 DECF 25h,1 ;Two player files found! Go back to start of the 3 files. DECF 25h,1 ;Take table-jump value up-table Stop5 MOVF 25h,0 ;Start of the three files. Move Jump value into W CALL Table1 ;Look at value of first of three files. MOVWF 04 ;Put jump value into FSR BTFSC 00,0 ;Test for player GOTO Stop6 ;Not empty MOVLW 04 ;Empty so put 04 into file looked at by FSR MOVWF 00 RETURN Stop6 INCF 25h,1 ;Increment the pointer GOTO Stop5
See if all locations are empty. Place a computer piece in a random corner if first move.
If board is not empty, go to Center. This routine will be activated when the computer is required to make the first move.
**Corner** MOVLW 09 MOVWF 25h ;The loop file MOVLW 30h ;This will be incremented before starting routine MOVWF 04 ;The pointer file Corner1 INCF 04,1 ;Look at first board location MOVLW 00 ;Put 00 into W XORWF 00,0 ;Is location empty? BTFSS 03,2 ;Test the zero flag GOTO **Center** ;Location is not empty DECFSZ 25h,1 ;File is zero. Decrement the loop file GOTO Corner1 ;Loop again MOVLW 07 ;Board is empty. Put masking value (7) into W ANDWF 28h,1 ;AND 07 with random number file. Result in 28h INCF 28h,1 ;File will be 1 to 8 MOVF 28h,0 ;Put value in file 28 into W CALL Table2 ;Fetch random corner from table MOVWF 04 ;Put random corner into FSR MOVLW 04 MOVWF 00 ;Put computer piece onto board RETURN
The previous sub-routine (Corner) has determined the board is not empty. Center places “Computer Piece” in the center square (if it is empty). If the centre square is not empty, the micro goes to Fork.
**Center** MOVF 35h,1 ;Move 35h in and out of file to see if it is zero BTFSS 03,2 ;Test zero flag GOTO **Fork** MOVLW 04 MOVWF 35h ;Put computer into center square RETURN
Fork solves a “trick” situation where the player is forming a “fork.” If two player and one computer piece is found, and computer is in middle, computer plays a side square. The routine firstly determines if the computer is in the centre square. If the computer is not in the centre square, the micro goes to Look4 (look-for). If the player is not in location 39h, 33h or 37h, the micro goes to the next sub-routine: Divide.
If the player is in the first and last square, and the computer is in the centre, the computer plays a random side. If player is in the top-right and bottom-left, the computer plays a side.
This is the first sub-routine to have two branches. The first branch is Look4.
**Fork** BTFSS 35h,2 ;Is computer in centre square? GOTO **Look4** ;Not computer piece BTFSS 31h,0 ;Computer in centre. Is player in first square? GOTO ForkA ;Player not in first square BTFSC 39h,0 ;Player in first square. Is player in last square? GOTO ForkB ;Player in last square ForkA BTFSS 33h,0 GOTO **Divide** BTFSS 37h,0 GOTO **Divide** ForkB MOVLW 07 ;Get a random value. Put masking value (7) into W ANDWF 28h,1 ;AND 07 with random number file. Result in file INCF 28h,1 ;File will be 1 to 8 MOVF 28h,0 ;Put value in file 28 into W CALL Table3 ;Fetch random side from table MOVWF 04 ;Put random side into FSR MOVF 00,1 ;Move side value in and out of file to see if it is zero BTFSS 03,2 GOTO ForkB ;Side not empty MOVLW 04 MOVWF 00 ;Put computer piece onto board RETURN
Divide is another “trick” situation. If computer in centre and player on two adjoining sides, computer must go between player pieces.
**Divide** BTFSC 31h,0 ;Test for player in first square GOTO **Look4** BTFSC 31h,2 ;Test for computer in first square GOTO **Look4** BTFSC 32h,0 ;Test for player in second square GOTO **Look4** BTFSC 32h,2 ;Test for computer in second square GOTO **Look4** BTFSC 33h,0 ;Test for player in third square **GOTO** Look4 BTFSC 33h,2 ;Test for computer in third square GOTO **Look4** BTFSC 34h,0 ;Test for player in fourth square GOTO **Look4** BTFSC 34h,2 ;Test for computer in fourth square GOTO **Look4** BTFSS 35h,2 ;Look for computer in centre square GOTO Look4 BTFSS 36h,0 ;Test for player in sixth square GOTO **Look4** BTFSC 37h,0 ;Test for player in seventh square GOTO **Look4** BTFSC 37h,2 ;Test for computer in seventh square GOTO **Look4** BTFSS 38h,0 ;Test for player in eighth square GOTO **Look4** BTFSC 39h,0 ;Test for player in ninth square GOTO **Look4** BTFSC 39h,2 ;Look for computer in last location GOTO **Look4** MOVLW 04 MOVWF 39h ;Put computer piece into last location RETURN
Look for a row containing just a computer piece (04) and add another computer piece. If not, add a random computer piece. Table 1 is used again to get the files for each row, column and diagonal.
The program is looking for the value 04 in a single file, in row, column or diagonal. If the end-of-table is reached before a value is found, the micro goes to Random. At Look4C the program compares the counter (file27h) with 01 and if only one computer piece is found in a row etc, the beginning of the row is found by loading the “jump value” into W and calling Table1 at Look 4G. The file from the table is loaded into FSR and looked at to see if it is empty. If is is empty, 04 is loaded into the file via indirect addressing. If it is not empty, the “jump value” is increased twice so that only a corner is loaded with the computer piece.
**Look4** MOVLW 0FFh ;The value will be incremented to 00! MOVWF 25h ;Table jump file Look4A CLRF 27h ;Clear the Look counter MOVLW 03 MOVWF 26h ;Fetch 3 table values in a loop. Look4B INCF 25h,1 ;Increment the table-jump file MOVF 25h,0 ;Copy jump file into W CALL Table1 ;Get first table value MOVWF 04 ;Move table value into FSR BTFSC 00,7 ;Look for end-of-table GOTO **Random** ;End of table found - no result obtained BTFSC 00,2 ;Look for computer GOTO Look4L BTFSS 00,0 ;Look for player GOTO Look4C INCF 27h,1 ;Prevent row being accessed Look4L INCF 27h,1 ;Increment the Look counter (If=1, Computer only once) Look4C DECFSZ 26h,1 ;Decrement the 3 table-values counter GOTO Look4B MOVLW 01 XORWF 27h,1 BTFSS 03,2 GOTO Look4A ;Computer nil or more than once DECF 25h,1 ;Computer only once. Find start of row DECF 25h,1 Look4G MOVF 25h,0 ;Move 25h into W CALL Table1 MOVWF 04 ;Move table value into pointer MOVF 00,1 ;Move file in and out to see it is zero BTFSS 03,2 ;Test zero flag GOTO Look4H MOVLW 04 ;Square is empty MOVWF 00 ;Put computer piece into empty square RETURN Look4H INCF 25h,1 INCF 25h,1 ;Place computer piece only in corner! GOTO Look4G
Insert a random computer piece. Corners are first selected. The game must have a sub-routine that definitely places a piece on the board, just in case all the above routines do not find a result. This is the last routine for the “decision-making” section of the program. A random number is obtained from the Random Number file. This file is incremented every time the display cycles and will contain a different value due to the player pressing the buttons (for each “turn”), at a different time.
**Random** MOVLW 03 ;Put masking value (3) into W ANDWF 28h,1 ;AND 03 with random number file. Result in file Random1 INCF 28h,1 ;File will be 1 to 4 on first pass. MOVF 28h,0 ;Put value into W CALL Table5 ;Fetch random location from table MOVWF 04 ;Put random location into FSR BTFSC 00,7 ;Test for end-of-table RETURN MOVF 00,1 ;Move value in and out of file to see if it is zero BTFSS 03,2 ;Test the zero-bit GOTO Random1 ;location not empty MOVLW 04 MOVWF 00 ;Put computer piece onto board RETURN
Stalemate is CALLed from the Main routine.
The board is checked to see if any square is empty. If all are full, both LEDs are illuminated. The program creates 9 loops to check each square. It checks to see if the cursor is present by testing for 05 and 08. If so, the micro returns. It then checks to see if each square is full. If all squares are occupied, both LEDs are illuminated and the “Stalemate flag” is set.
Stale BTFSC 05,6 ;Check Player-WINS! bit RETURN MOVLW 09 MOVWF 25h ;Decrementing file MOVLW 31h MOVWF 04 ;Start of files into FSR Stale1 MOVLW 05 XORWF 00,0 BTFSC 03,2 RETURN ;Square has cursor BTFSC 00,3 ;Test for "hidden" cursor RETURN MOVLW 00 XORWF 00,0 BTFSC 03,2 ;Test zero flag RETURN ;Square is empty INCF 04,1 ;Square is full. Increment the pointer DECFSZ 25h,1 GOTO Stale1 BSF 05,6 BSF 05,7 BSF 2F,3 ;Set the Win-LED/stalemate bit RETURN
Quick Links
Legal Stuff
Social Media