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