home *** CD-ROM | disk | FTP | other *** search
- * This program plays a rudimentary game of TIC-TAC-TOE.
- *
- * Although the strategy is not elaborate, it illustrates
- * how pattern matching can be used to analyse board positions.
- *
- * The board is represented by a nine-character string. Each string
- * position may contain an "X" (player), "O" (program), or "." (vacant).
- *
- * The correspondence between character position and the board is:
- *
- * 0 | 1 | 2
- * ---------
- * 3 | 4 | 5
- * ---------
- * 6 | 7 | 8
- *
- *
- * From STRING AND LIST PROCESSING IN SNOBOL4 by Ralph E. Griswold,
- * by permission of the author.
- * ----------------------------------------------------------------
- *
- *
- * (c) Copyright 1985 - Catspaw, Incorporated
- *
- -TICTAC
- *********************************************************************
- * INITIALIZATION *
- *********************************************************************
- &TRIM = 1
- DEFINE("COL(C1,C2,C3)")
- DEFINE("DIAG(C1,C2,C3)")
- DEFINE("ROW(C1,C2,C3)")
- DEFINE("TWO(M)")
- UC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- LC = 'abcdefghijklmnopqrstuvwxyz'
- SKIP = NULL . OUTPUT
- ROW = LEN(3) . OUTPUT
- PRINT = SKIP ROW ROW ROW SKIP
- *********************************************************************
- * BOARD PATTERNS *
- *********************************************************************
- * Columns start at character positions 0, 1, and 2:
- C = TAB(0) | TAB(1) | TAB(2)
-
- * Rows start at character positions 0, 3, and 6:
- R = TAB(0) | TAB(3) | TAB(6)
-
- * Assign scanner position to M, then see if the next square is free:
- F = @M "."
-
- * Pattern to take a vacant square at position M:
- P = POS(*M) "."
-
- * Pattern to determine if the center square is free. Set M = 4 if so.
- CENTER = TAB(4) F
-
- * Pattern to see if any corner is free, set M = corner if so.
- CORNER = (TAB(0) | TAB(2) | TAB(6) | TAB(8)) F
-
- * SNOBOL4 can win if there are two O's and a free square in a line:
- WIN = TWO("O")
-
- * SNOBOL4 must block user if two X's and a free square in a line:
- BLOCK = TWO("X")
-
- * SNOBOL4 loses if row, column, or diagonal of 3 X's:
- LOSE = ROW("X","X","X") | COL("X","X","X") |
- + DIAG("X","X","X")
-
- * Block if necessary, else seize corner, else any take first free square:
- PLAY = BLOCK | CORNER | F
-
- *********************************************************************
- * INTRODUCTION *
- *********************************************************************
- OUTPUT = "This program plays TIC-TAC-TOE. Your mark is"
- + " X and you will play first."
- OUTPUT = "The board is numbered as follows:"
- "012345678" PRINT
- OUTPUT = "When it is your turn to play, type the number"
- + " of the square you wish to mark."
- OUTPUT = "For example, if you type '4', the result is:"
- "....X...." PRINT
- OUTPUT = "Any time it is your turn to play, you may"
- + " start a new game by typing 'N'"
- OUTPUT = "or end the session by typing 'Q'"
- *********************************************************************
- * GAME PLAY *
- *********************************************************************
- START OUTPUT = DUPL("-",10)
- OUTPUT = "NEW GAME"
- BOARD = DUPL(".",9)
-
- NEXT OUTPUT = "Your play"
- M = REPLACE(INPUT,LC,UC) :F(ABAND)
- IDENT(M,"N") :S(START)
- IDENT(M,"Q") :S(STOP)
- INTEGER(M) :F(ERROR)
-
- * Make move for user:
- BOARD P = "X" :F(ERROR)
-
- * Try to seize the center:
- BOARD CENTER :S(MINE)
-
- * Check if we lost:
- BOARD LOSE :S(LOSE)
-
- * Check if we won:
- BOARD WIN :S(WIN)
-
- * Neither. Select our next move:
- BOARD PLAY :F(TIE)
-
- * Make our move into position M.
- MINE BOARD P = "O"
- BOARD PRINT :(NEXT)
-
- LOSE OUTPUT = "You win" :(NEW)
-
- TIE OUTPUT = "Tie game" :(NEW)
-
- WIN BOARD P = "O"
- OUTPUT = "I win"
-
- NEW BOARD PRINT :(START)
- ABAND OUTPUT = 'Session abandoned' :(END)
- STOP OUTPUT = 'Session ended' :(END)
- ERROR OUTPUT = 'Erroneous move - try again' :(NEXT)
- *********************************************************************
- * FUNCTION DEFINITIONS *
- *********************************************************************
-
- * Function returns pattern to check for C1, C2, C3 adjacent in any column.
- COL COL = C C1 LEN(2) C2 LEN(2) C3 :(RETURN)
-
- * Function returns pattern to check for C1, C2, C3 adjacent in any diagonal.
- DIAG DIAG = TAB(0) C1 TAB(4) C2 TAB(8) C3 |
- + TAB(2) C1 TAB(4) C2 TAB(6) C3 :(RETURN)
-
- * Function returns pattern to check for C1, C2, C3 adjacent in any row.
- ROW ROW = R C1 C2 C3 :(RETURN)
-
- * Function returns pattern to check for two marks (M) and a vacant square:
- TWO TWO = ROW(F,M,M) | ROW(M,F,M) | ROW(M,M,F) |
- + COL(F,M,M) | COL(M,F,M) | COL(M,M,F) |
- + DIAG(F,M,M) | DIAG(M,F,M) | DIAG(M,M,F) :(RETURN)
- END
-