TIC TAC TOE
THE PROGRAM EXPLAINED
Page 4

Go to:   P1    P2    P3

TIC TAC TOE PROGRAM
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."

LET'S BEGIN . . .
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.


SetUp










ORG 0
MOVLW 07
MOVWF 1Fh
BSF 03,5
CLRF 06
MOVLW 18h
MOVWF 05
BCF 03,5
CLRF 2F
CLRF 05
CLRF 06
GOTO Att
;This is the start of memory for the program.
;Disable the comparators
;File 1F is the CMCON file
;Go to Bank 1
;Make all port B output
;Load W with 0001 1000
;Make RA0,1,2,6,7 output and RA3, RA4 input
;Go to Bank 0 - the program memory area.
;Clear the button-press file
;Clear the output lines of PortA
;Blank the output
 

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






















Main

MainA



MainB



MainC


Main1


Main2


Main3


Main4


Main5


Main6








Main7


Main8


Main9


Main10


Main11


Main12








Main13


Main14


Main15


Main16


Main17


Main18



















Main19







Main20






Main21



Main22





MOVLW 05
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
GOTO Preload
BTFSS 05,4
GOTO Preload
GOTO Main






MOVLW 20h
MOVWF 22h
BTFSC 2F,0
GOTO MainB
BTFSS 05,3
CALL ButtonA
BTFSC 2F,1
GOTO MainC
BTFSS 05,4
CALL ButtonB
BTFSS 31h,0
GOTO Main1
BSF 06,5
BTFSS 31h,2
GOTO Main2
BSF 06,4
BTFSS 32h,0
GOTO Main3
BSF 06,3
BTFSS 32h,2
GOTO Main4
BSF 06,2
BTFSS 33h,0
GOTO Main5
BSF 06,1
BTFSS 33h,2
GOTO Main6
BSF 06,0
BSF 05,0
CALL Del1
BCF 05,0
CLRF 06
CALL Del1

BTFSS 34h,0
GOTO Main7
BSF 06,5
BTFSS 34h,2
GOTO Main8
BSF 06,4
BTFSS 35h,0
GOTO Main9
BSF 06,3
BTFSS 35h,2
GOTO Main10
BSF 06,2
BTFSS 36h,0
GOTO Main11
BSF 06,1
BTFSS 36h,2
GOTO Main12
BSF 06,0
BSF 05,2
CALL Del1
BCF 05,2
CLRF 06
CALL Del1

BTFSS 37h,0
GOTO Main13
BSF 06,5
BTFSS 37h,2
GOTO Main14
BSF 06,4
BTFSS 38h,0
GOTO Main15
BSF 06,3
BTFSS 38h,2
GOTO Main16
BSF 06,2
BTFSS 39h,0
GOTO Main17
BSF 06,1
BTFSS 39h,2
GOTO Main18
BSF 06,0
BSF 05,1
CALL Del1
BCF 05,1
CLRF 06
BTFSC 05,3
BCF 2F,0
BTFSC 05,4
BCF 2F,1
DECFSZ 22h,1
GOTO MainA






MOVLW 0A
MOVWF 23h
MOVLW 30h
MOVWF 04
BTFSS 00,0
GOTO Main20
BTFSS 00,2
GOTO Main20
MOVLW 08
MOVWF 00
GOTO Main

INCF 04,1
DECFSZ 23h,1
GOTO Main19


MOVLW 30h
MOVWF 04
BTFSC 00,3
GOTO Main22
INCF 04,1
GOTO Main21
MOVLW 05
MOVWF 00h
INCF 28h
INCF 28h
CALL Stale
GOTO Main

END
;Put cursor into "ready" file











;Make sure button "A" is released

;Make sure button "B" is released

;Go to Main


;Player Value = 01 = red
;Computer Value = 04 = green
;Cursor = 05

;Loops of Main for flashing cursor
;File to decrement
;ButtonA pressed first time?

;Test for ButtonA

;ButtonB pressed first time?

;Test for ButtonB







































































;Skip if ButtonA is still pressed
;Clear button-press flag
;Skip if ButtonB is still pressed
;Clear button-press flag



;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

;Ten loops of routine
;Loop file
;Start of files for board
;Load start into FSR
;Test bit0 of INDF

;Is bit2 = HIGH?

;File contains cursor. Put 08 into file to "hide"
;08 will be put into a file 30h to 39h
;Cursor has been hidden

;Increment pointer
;Decrement loop file



;Start of files for board
;Load start into FSR
;Look for "8" in a file

;Increment the pointer

;Put 5 in file looked at by FSR

;Increment the RANDOM NUMBER file




;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


















ButAA

ButA1






ButA2

ButA3







ButA4
ButA5






ButA6







BSF 2F,0
BTFSS 2F,3
GOTO ButAA
BCF 2F,3
BCF 05,6
BCF 05,7
MOVLW 05
MOVWF 30h
CLRF 31h
CLRF 32h
CLRF 33h
CLRF 34h
CLRF 35h
CLRF 36h
CLRF 37h
CLRF 38h
CLRF 39h
CLRF 3Ah
RETURN
MOVLW 30h
MOVWF 04
BTFSC 00,3
GOTO ButA3
BTFSS 00,0
GOTO ButA2
BTFSS 00,2
GOTO ButA2
GOTO ButA3
INCF 04
GOTO ButA1
MOVLW 3Ah
XORWF 04,0
BTFSS 03,2
GOTO ButA4
CLRF 3Ah
MOVLW 05
MOVWF 30h
RETURN
CLRF 00
INCF 04,1
MOVLW 3A
XORWF 04,0
BTFSS 03,2
GOTO ButA6
MOVLW 30h
MOVWF 04
MOVLW 00
XORWF 00,0
BTFSS 03,2
GOTO ButA5
MOVLW 05
MOVWF 00
RETURN
;Set button-press flag
;Is Win-LED/stalemate bit=1?




;Put cursor into "ready" file












;Start of "board"
;Start FSR at file 30h
;Look for "8"
;Found cursor
;Look for first part of "05"
;Cursor not found
;Look for second part of "05"

;Found cursor


;Has cursor reached end of "board?"

;Test the zero flag
;not at end of board
;reached end of board

;Return cursor to start

;Clear the cursor


;If cursor has reached end of board,
; return it to file 30h


;Return cursor to start

;Is board location empty?
;Test zero flag
;Not empty
;Empty location
;Show cursor in new location
 

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




ButB1







ButB2




ButB3




BSF 2F,1
MOVLW 09
MOVWF 23h
MOVLW 31h
MOVWF 04
MOVLW 05
XORWF 00,0
BTFSC 03,2
GOTO ButB2
MOVLW 08
XORWF 00,0
BTFSS 03,2
GOTO ButB3
MOVLW 01
MOVWF 00
MOVLW 05
MOVWF 30h
GOTO PWin
INCF 04,1
DECFSZ 23h
GOTO ButB1
GOTO PWin
 
;Set button-press flag

;Decrementing file
;Start of "board"
;FSR starts at file 31h

;Is the file looked at by FSR=5?
;Test zero flag
;Found
;Not found try "08" = flashing cursor
;Is the file looked at by FSR=8?

;Not found
;Cursor found
;Make file = 1 = red

;Put cursor into "hide" file

;Increment the pointer


;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.





PWin





PWin1





PWin2





PWin3





PWin4





PWin5





PWin6





PWin7





PWin8



PWin21







BTFSS 31h,0
GOTO PWin1
BTFSS 32h,0
GOTO PWin1
BTFSC 33h,0
GOTO PWin21
BTFSS 34h,0
GOTO PWin2
BTFSS 35h,0
GOTO PWin2
BTFSC 36h,0
GOTO PWin21
BTFSS 37h,0
GOTO PWin3
BTFSS 38h,0
GOTO PWin3
BTFSC 39h,0
GOTO PWin21
BTFSS 31h,0
GOTO PWin4
BTFSS 34h,0
GOTO PWin4
BTFSC 37h,0
GOTO PWin21
BTFSS 32h,0
GOTO PWin5
BTFSS 35h,0
GOTO PWin5
BTFSC 38h,0
GOTO PWin21
BTFSS 33h,0
GOTO PWin6
BTFSS 36h,0
GOTO PWin6
BTFSC 39h,0
GOTO PWin21
BTFSS 31h,0
GOTO PWin7
BTFSS 35h,0
GOTO PWin7
BTFSC 39h,0
GOTO PWin21
BTFSS 33h,0
GOTO PWin8
BTFSS 35h,0
GOTO PWin8
BTFSC 37h,0
GOTO PWin21
CALL Stale
BTFSS 2F,3
GOTO CWin
RETURN
BSF 05,6
BSF 2F,3
RETURN
 
;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"




















































;Player WINS!
;Set the Win-LED/stalemate bit

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

CWin1


CWin2












CWin3





CWin4










CWin5


MOVLW 0FFh
MOVWF 25h
CLRF 27h
MOVLW 03
MOVWF 26h
INCF 25h,1
MOVF 25h,0
CALL Table1
XORLW 0FFh
BTFSC 03,2
GOTO Stop
MOVF 25h,0
CALL Table1
MOVWF 04
BTFSC 00,0
DECF 27h,1
BTFSC 00,2
INCF 27h,1
DECFSZ 26h,1
GOTO CWin2
MOVLW 02
XORWF 27h,0
BTFSS 03,2
GOTO CWin1
MOVF 25h,0
CALL Table1
MOVWF 04
MOVF 00,1
BTFSS 03,2
GOTO CWin5
MOVLW 04
MOVWF 00
BSF 05,7
BSF 2F,3
RETURN
DECF 25h,1
GOTO CWin4
;The value will be incremented to 00!
;Table jump file
;Clear the Computer counter

;Fetch 3 table values in a loop.
;Increment the table-jump file
;Copy jump file into W
;Get first table value
;Look for end-of-table
;Test zero flag
;End of table found - no result obtained
;Copy jump file into W again
;Call table again as previous value was lost via XORLW
;Move table value into FSR
;Look for unwanted player piece
;Dec. computer counter so count cannot be recognised
;Look at bit2 of file 31h (first table value)
;Increment the Computer counter
;Decrement the 3 table-values counter
;Loop for next piece
;See if 2 computer pieces are found


;2 computer pieces not found
;2 Computer pieces found. Put 25h into W
;Locate table value
;Put W into FSR
;Move value in file in and out to see if it is zero
;Test zero flag
;Not zero
;Square is zero. Load computer piece

;Computer WINS!
;Set the Win-LED/stalemate bit
 

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

Stop1


Stop2


Stop2A










Stop3

Stop4





Stop5







Stop6

MOVLW 0FFh
MOVWF 25h
CLRF 27h
MOVLW 04
MOVWF 26h
DECFSZ 26h,1
GOTO Stop2A
GOTO Stop4
INCF 25h,1
MOVF 25h,0
CALL Table1
MOVWF 04
BTFSC 00,7
GOTO Corner
BTFSC 00,2
GOTO Stop3
BTFSC 00,0
INCF 27h,1
GOTO Stop2
BSF 27h,7
GOTO Stop2
BTFSC 27h,7
GOTO Stop1
BTFSS 27h,1
GOTO Stop1
DECF 25h,1
DECF 25h,1
MOVF 25h,0
CALL Table1
MOVWF 04
BTFSC 00,0
GOTO Stop6
MOVLW 04
MOVWF 00
RETURN
INCF 25h,1
GOTO Stop5
;The value will be incremented to 00!
;Table jump file
;Clear the "player" counter
;This will be decremented to 3!
;Fetch 3 table-values in a loop.


;3 values have been processed
;Increment the table-jump file
;Copy jump file into W
;Get first table value
;Move table value into FSR
;Look for end-of-table
;End of table found - no result obtained
;Look at bit2 of file 31h for computer piece
;Computer piece found
;Look at bit0 of file 31h (first table value)
;Increment the "player" counter

;Set bit 7 of "player" counter

;Is computer in the row?

;Is counter=2?

;Two player files found! Go back to start of the 3 files.
;Take table-jump value up-table
;Start of the three files. Move Jump value into W
;Look at value of first of three files.
;Put jump value into FSR
;Test for player
;Not empty
;Empty so put 04 into file looked at by FSR


;Increment the pointer

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



Corner1
MOVLW 09
MOVWF 25h
MOVLW 30h
MOVWF 04
INCF 04,1
MOVLW 00
XORWF 00,0
BTFSS 03,2
GOTO Center
DECFSZ 25h,1
GOTO Corner1
MOVLW 07
ANDWF 28h,1 
INCF 28h,1
MOVF 28h,0
CALL Table2
MOVWF 04
MOVLW 04
MOVWF 00
RETURN

;The loop file
;This will be incremented before starting routine
;The pointer file
;Look at first board location
;Put 00 into W
;Is location empty?
;Test the zero flag
;Location is not empty
;File is zero. Decrement the loop file
;Loop again
;Board is empty. Put masking value (7) into W
;AND 07 with random number file. Result in 28h
;File will be 1 to 8
;Put value in file 28 into W
;Fetch random corner from table
;Put random corner into FSR

;Put computer piece onto board
 

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
BTFSS 03,2
GOTO Fork
MOVLW 04
MOVWF 35h
RETURN
;Move 35h in and out of file to see if it is zero
;Test zero flag


;Put computer into center square

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





ForkA



ForkB

BTFSS 35h,2
GOTO Look4
BTFSS 31h,0
GOTO ForkA
BTFSC 39h,0
GOTO ForkB
BTFSS 33h,0
GOTO Divide
BTFSS 37h,0
GOTO Divide
MOVLW 07
ANDWF 28h,1
INCF 28h,1
MOVF 28h,0
CALL Table3
MOVWF 04
MOVF 00,1
BTFSS 03,2
GOTO ForkB
MOVLW 04
MOVWF 00
RETURN
;Is computer in centre square?
;Not computer piece
;Computer in centre. Is player in first square?
;Player not in first square
;Player in first square. Is player in last square?
;Player in last square




;Get a random value. Put masking value (7) into W
;AND 07 with random number file. Result in file
;File will be 1 to 8
;Put value in file 28 into W
;Fetch random side from table
;Put random side into FSR
;Move side value in and out of file to see if it is zero

;Side not empty

;Put computer piece onto board

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
GOTO Look4
BTFSC 31h,2
GOTO Look4
BTFSC 32h,0
GOTO Look4
BTFSC 32h,2
GOTO Look4
BTFSC 33h,0
GOTO
Look4
BTFSC 33h,2
GOTO Look4
BTFSC 34h,0
GOTO Look4
BTFSC 34h,2
GOTO Look4
BTFSS 35h,2
GOTO Look4
BTFSS 36h,0
GOTO Look4
BTFSC 37h,0
GOTO Look4
BTFSC 37h,2
GOTO Look4
BTFSS 38h,0
GOTO Look4
BTFSC 39h,0
GOTO Look4
BTFSC 39h,2
GOTO Look4
MOVLW 04
MOVWF 39h
RETURN
;Test for player in first square

;Test for computer in first square

;Test for player in second square

;Test for computer in second square

;Test for player in third square

;Test for computer in third square

;Test for player in fourth square

;Test for computer in fourth square

;Look for computer in centre square

;Test for player in sixth square

;Test for player in seventh square

;Test for computer in seventh square

;Test for player in eighth square

;Test for player in ninth square

;Look for computer in last location


;Put computer piece into last location
 

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

Look4A


Look4B










Look4L
Look4C







Look4G








Look4H

MOVLW 0FFh
MOVWF 25h
CLRF 27h
MOVLW 03
MOVWF 26h
INCF 25h,1
MOVF 25h,0
CALL Table1
MOVWF 04
BTFSC 00,7
GOTO Random
BTFSC 00,2
GOTO Look4L
BTFSS 00,0
GOTO Look4C
INCF 27h,1
INCF 27h,1
DECFSZ 26h,1
GOTO Look4B
MOVLW 01
XORWF 27h,1
BTFSS 03,2
GOTO Look4A
DECF 25h,1
DECF 25h,1
MOVF 25h,0
CALL Table1
MOVWF 04
MOVF 00,1
BTFSS 03,2
GOTO Look4H
MOVLW 04
MOVWF 00
RETURN
INCF 25h,1
INCF 25h,1
GOTO Look4G
;The value will be incremented to 00!
;Table jump file
;Clear the Look counter

;Fetch 3 table values in a loop.
;Increment the table-jump file
;Copy jump file into W
;Get first table value
;Move table value into FSR
;Look for end-of-table
;End of table found - no result obtained
;Look for computer

;Look for player

;Prevent row being accessed
;Increment the Look counter (If=1, Computer only once)
;Decrement the 3 table-values counter




;Computer nil or more than once
;Computer only once. Find start of row

;Move 25h into W

;Move table value into pointer
;Move file in and out to see it is zero
;Test zero flag

;Square is empty
;Put computer piece into empty square


;Place computer piece only in corner!


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

Random1
MOVLW 03
ANDWF 28h,1
INCF 28h,1
MOVF 28h,0
CALL Table5
MOVWF 04
BTFSC 00,7
RETURN
MOVF 00,1
BTFSS 03,2
GOTO Random1
MOVLW 04
MOVWF 00
RETURN
;Put masking value (3) into W
;AND 03 with random number file. Result in file
;File will be 1 to 4 on first pass.
;Put value into W
;Fetch random location from table
;Put random location into FSR
;Test for end-of-table

;Move value in and out of file to see if it is zero
;Test the zero-bit
;location not empty

;Put computer piece onto board
 

STALEMATE
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





Stale1
BTFSC 05,6
RETURN
MOVLW 09
MOVWF 25h
MOVLW 31h
MOVWF 04
MOVLW 05
XORWF 00,0
BTFSC 03,2
RETURN
BTFSC 00,3
RETURN
MOVLW 00
XORWF 00,0
BTFSC 03,2
RETURN
INCF 04,1
DECFSZ 25h,1
GOTO Stale1
BSF 05,6
BSF 05,7
BSF 2F,3
RETURN
;Check Player-WINS! bit


;Decrementing file

;Start of files into FSR



;Square has cursor
;Test for "hidden" cursor



;Test zero flag
;Square is empty
;Square is full. Increment the pointer




;Set the Win-LED/stalemate bit