;; Clean up the memory (clear) ;; set the strategy (set-strategy lex) ;; prints the game board ;; sets goal to check for winner (defrule print-board ?g <- (goal print-board) (square 1 1 ?val1) (square 1 2 ?val2) (square 1 3 ?val3) (square 2 1 ?val4) (square 2 2 ?val5) (square 2 3 ?val6) (square 3 1 ?val7) (square 3 2 ?val8) (square 3 3 ?val9) => (printout t ?val1 " | " ?val2 " | " ?val3 crlf) (printout t "--------------------" crlf) (printout t ?val4 " | " ?val5 " | " ?val6 crlf) (printout t "--------------------" crlf) (printout t ?val7 " | " ?val8 " | " ?val9 crlf) (printout t crlf) (retract ?g) (assert (goal check-for-win))) ;; starts a game by asking for first move (defrule start-game ?g <- (goal start-game) => (printout t "Who should make the first move? (user or computer)" crlf) (retract ?g) (assert (goal print-board)) (assert-string (format nil "(next-move %s)" (readline)))) ;; reads a user's move - expect (defrule get-user-move ?g <- (goal get-move) ?n <- (next-move user) => (printout t "Please enter a move: (row column)" crlf) (retract ?n) (retract ?g) (assert-string (format nil "(move %s)" (readline))) (assert (goal handle-user-move))) ;; handles user selecting a square ;; sets next move for computer (defrule user-moves ?g <- (goal handle-user-move) ?m <- (move ?val1 ?val2) ?s <- (square ?val1 ?val2 _) => (printout t "User selects square " ?val1 " " ?val2 "." crlf) (retract ?g) (retract ?m) (retract ?s) (assert (square ?val1 ?val2 X)) (assert (goal print-board)) (assert (next-move computer))) ;; computer will take the top left corner as its first move (defrule first-move ?g <- (goal get-move) ?n <- (next-move computer) (not (square ?a ?a X)) ?s <- (square 1 1 _) => (retract ?g) (retract ?n) (retract ?s) (printout t "Computer selects square 1 1" crlf) (assert (square 1 1 O)) (assert (goal print-board)) (assert (next-move user))) ;; take center if it is available after user has moved (defrule take-center ?g <- (goal get-move) ?n <- (next-move computer) ?s <- (square 2 2 _) (square ?a ?a X) => (retract ?g) (retract ?n) (retract ?s) (printout t "Computer selects square 2 2" crlf) (assert (square 2 2 O)) (assert (goal print-board)) (assert (next-move user))) ;; take some open square if other rules dont take effect (defrule take-open ?g <- (goal get-move) ?n <- (next-move computer) ?s <- (square ?a ?b _) (square ?c ?c X) (not (square 2 2 _)) => (retract ?g) (retract ?n) (retract ?s) (printout t "Computer selects square " ?a " " ?b crlf) (assert (square ?a ?b O)) (assert (goal print-board)) (assert (next-move user))) ;; stop user from using the center/corner trap (defrule center-scorner-block ?g <- (goal get-move) ?n <- (next-move computer) (square 2 2 X) (square ?a&~2 ?a X) ?s <- (square ?b&~2 ?a _) => (retract ?g) (retract ?n) (retract ?s) (printout t "Computer selects square " ?b " " ?a crlf) (assert (square ?b ?a O)) (assert (goal print-board)) (assert (next-move user))) ;; stop user from using center/corner trap (defrule center-dcorner-block ?g <- (goal get-move) ?n <- (next-move computer) (square 2 2 X) (square ?a&~2 ?b&~?a&~2 X) ?s <- (square ?c&~2 ?c _) => (retract ?g) (retract ?n) (retract ?s) (printout t "Computer selects square " ?a " " ?a crlf) (assert (square ?a ?a O)) (assert (goal print-board)) (assert (next-move user))) ;; attempt to use the diagonal trap (defrule opp-ldiag-strat ?g <- (goal get-move) ?n <- (next-move computer) (square ?row&~2 ?col&~2 O) ?s <- (square ?col ?row _) => (printout t "Computer selects square " ?col " " ?row crlf) (retract ?g) (retract ?n) (retract ?s) (assert (square ?col ?row O)) (assert (goal print-board)) (assert (next-move user))) ;; attempt to use the diagonal trap (defrule opp-rdiag-strat ?g <- (goal get-move) ?n <- (next-move computer) (square ?row&~2 ?row O) ?s <- (square ?col&~?row&~2 ?col _) => (printout t "Computer selects square " ?col " " ?col crlf) (retract ?g) (retract ?n) (retract ?s) (assert (square ?col ?col O)) (assert (goal print-board)) (assert (next-move user))) ;; make a winning move on a row (defrule for-row-win ?g <- (goal get-move) ?n <- (next-move computer) (square ?row ?col1 O) (square ?row ?col2&~?col1 O) ?s <- (square ?row ?col3 _) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?row ?col3 O)) (printout t "Computer selects square " ?row " " ?col3 " for win" crlf) (assert (goal print-board)) (assert (next-move user))) ;; block user from winning by row ;; don't block if have a winning condition - not 100% effective (defrule row-block ?g <- (goal get-move) ?n <- (next-move computer) (square ?row ?col1 X) (square ?row ?col2&~?col1 X) ?s <- (square ?row ?col3 _) (not (and (square ?row2 ?col4 O) (square ?row2 ?col5&~?col4 O) (square ?row2 ?col6 _))) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?row ?col3 O)) (printout t "Computer blocks " ?row crlf) (assert (goal print-board)) (assert (next-move user))) ;; make a winning column move (defrule for-col-win ?g <- (goal get-move) ?n <- (next-move computer) (square ?row1 ?col O) (square ?row2&~?row1 ?col O) ?s <- (square ?row3 ?col _) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?row3 ?col O)) (printout t "Computer selects square " ?row3 " " ?col " for win" crlf) (assert (goal print-board)) (assert (next-move user))) ;; block user from making a winning column move ;; dont if can make a winning move - not 100% effective (defrule col-block ?g <- (goal get-move) ?n <- (next-move computer) (square ?row1 ?col X) (square ?row2&~?row1 ?col X) ?s <- (square ?row3 ?col _) (not (and (square ?row4 ?col2 O) (square ?row5&~?row4 ?col2 O) (square ?row6 ?col2 _))) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?row3 ?col O)) (printout t "Computer blocks column " ?col crlf) (assert (goal print-board)) (assert (next-move user))) ;; make a right diagonal winning move (defrule for-rdiag-win ?g <- (goal get-move) ?n <- (next-move computer) (square ?a ?a O) (square ?b&~?a ?b O) ?s <- (square ?c&~?b&~?a ?c _) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?c ?c O)) (printout t "Computer selects square " ?c " " ?c " for win" crlf) (assert (goal print-board)) (assert (next-move user))) ;; block a right diagonal winning move (defrule rdiag-block ?g <- (goal get-move) ?n <- (next-move computer) (square ?a ?a X) (square ?b&~?a ?b X) ?s <- (square ?c&~?b&~?a ?c _) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?c ?c O)) (printout t "Computer blocks diagonal at " ?c " " ?c crlf) (assert (goal print-board)) (assert (next-move user))) ;; make a left diagonal winning move in center (defrule for-ldiag-win-center ?g <- (goal get-move) ?n <- (next-move computer) (square ?a&~2 ?b&~?a&~2 O) ?s <- (square 2 2 _) (square ?b ?a O) => (retract ?g) (retract ?n) (retract ?s) (assert (square 2 2 O)) (printout t "Computer selects square 2 2 for win" crlf) (assert (goal print-board)) (assert (next-move user))) ;; block a left diagonal winning move in the center (defrule ldiag-center-block ?g <- (goal get-move) ?n <- (next-move computer) (square ?a&~2 ?b&~?a&~2 X) (square ?b ?a X) ?s <- (square 2 2 _) => (retract ?g) (retract ?n) (retract ?s) (assert (square 2 2 O)) (printout t "Computer blocks diagonal at 2 2" crlf) (assert (goal print-board)) (assert (next-move user))) ;; make a corner left diagonal winning move (defrule for-ldiag-win-corner ?g <- (goal get-move) ?n <- (next-move computer) (square ?a&~2 ?b&~?a&~2 O) (square 2 2 O) ?s <- (square ?b ?a _) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?b ?a O)) (printout t "Computer selects square " ?b " " ?a " for win" crlf) (assert (goal print-board)) (assert (next-move user))) ;; block a corner left diagonal winning move (defrule block-ldiag-corner ?g <- (goal get-move) ?n <- (next-move computer) (square ?a&~2 ?b&~?a&~2 X) (square 2 2 X) ?s <- (square ?b ?a _) => (retract ?g) (retract ?n) (retract ?s) (assert (square ?b ?a O)) (printout t "Computer blocks diagonal at " ?b " " ?a crlf) (assert (goal print-board)) (assert (next-move user))) ;; handle user entering a legal square that is already taken (defrule taken-square ?g <- (goal handle-user-move) ?m <- (move ?val1 ?val2) (square ?val1 ?val2 ?a) (not (square ?val1 ?val2 _)) => (printout t "Square " ?val1 " " ?val2 " has been taken" crlf) (retract ?g) (retract ?m) (assert (goal get-move)) (assert (next-move user))) ;; handle user entering an illegal square (defrule illegal-square ?g <- (goal handle-user-move) ?m <- (move ?val1 ?val2) (not (square ?val1 ?val2 ?)) => (printout t "Illegal Move" crlf) (retract ?g) (retract ?m) (assert (goal get-move)) (assert (next-move user))) ;; handle user entering quit at the enter move prompt (defrule quit-move ?g <- (goal handle-user-move) ?m <- (move quit) => (printout t "Quitting Game. Goodbye." crlf) (retract *) ) ;; handle user entering incorrectly at command (defrule illegal-move ?g <- (goal handle-user-move) ?m <- (move $?a) => (printout t "Illegal move. Type " crlf) (retract ?g) (retract ?m) (assert (goal get-move)) (assert (next-move user))) ;; no winning state (defrule no-win ?g <- (goal check-for-win) ?n <- (next-move $?a) (square ?c ?d _) => (retract ?g) (assert (goal get-move)) ) ;; a player has a row win (defrule row-win ?g <- (goal check-for-win) ?n <- (next-move $?a) (square ?row 1 ?player) (square ?row 2 ?player) (square ?row 3 ?player) (not (square ?row 1 _)) => (printout t "Player " ?player " wins! Another game?" crlf) (retract ?g) (retract ?n) (assert-string (format nil "(new-game %s)" (readline))) (assert (goal new-game))) ;; a player has a right diagonal win (defrule rdiag-win ?g <- (goal check-for-win) ?n <- (next-move $?a) (square 1 1 ?player) (square 2 2 ?player) (square 3 3 ?player) (not (square 1 1 _)) => (printout t "Player " ?player " wins! Another game?" crlf) (retract ?g) (retract ?n) (assert-string (format nil "(new-game %s)" (readline))) (assert (goal new-game))) ;; a player has a left diagonal win (defrule ldiag-win ?g <- (goal check-for-win) ?n <- (next-move $?a) (square 1 3 ?player) (square 2 2 ?player) (square 3 1 ?player) (not (square 1 3 _)) => (printout t "Player " ?player " wins! Another game?" crlf) (retract ?g) (retract ?n) (assert-string (format nil "(new-game %s)" (readline))) (assert (goal new-game))) ;; a player has a column win (defrule col-win ?g <- (goal check-for-win) ?n <- (next-move $?a) (square 1 ?col ?player) (square 2 ?col ?player) (square 3 ?col ?player) (not (square 1 ?col _)) => (printout t "Player " ?player " wins! Another game?" crlf) (retract ?g) (retract ?n) (assert-string (format nil "(new-game %s)" (readline))) (assert (goal new-game))) ;; tied game (defrule cat ?g <- (goal check-for-win) ?n <- (next-move $?) (not (square ?a ?b _)) => (printout t "Game Tied. Another game? (y or n)" crlf) (retract ?g) (retract ?n) (assert-string (format nil "(new-game %s)" (readline))) (assert (goal new-game))) ;; user wants to play again (defrule yes-new-game ?g <- (goal new-game) ?n <- (new-game y) => (retract ?g) (retract ?n) (assert (goal cleanup))) ;; cleanup the old board (defrule cleanup (goal cleanup) ?s <- (square $?a) => (retract ?s)) ;; create a blank board (defrule newboard ?g <- (goal cleanup) (not (square $?a)) => (assert (square 1 1 _)) (assert (square 1 2 _)) (assert (square 1 3 _)) (assert (square 2 1 _)) (assert (square 2 2 _)) (assert (square 2 3 _)) (assert (square 3 1 _)) (assert (square 3 2 _)) (assert (square 3 3 _)) (retract ?g) (assert (goal start-game))) ;; user doesn't want to play again (defrule no-new-game ?g <- (goal new-game) ?n <- (new-game n) => (retract ?g) (retract ?n) (printout t "Its been fun! Bye now!" crlf)) ;; setup goal to start (assert (goal cleanup)) ;; activate system (run)