You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
br-parser-tools/collects/tests/mzscheme/ttt/tic-func.ss

120 lines
3.6 KiB
Scheme

;; --------------------------------------------------------------------------
;; tic-func.ss
;; This program plays through all possibilities of a tic-tac-toe
;; game, given the first move of a player. It only prints how many
;; states are being processed and how many states are terminal at
;; each stage of the game. But it is constructed so that it can
;; print how to get to a winning terminal state.
;; It relies on list-library.ss.
;; representations of fields, states, and collections of states
(define null '())
(define-structure (entry x y who))
(define entry-field
(lambda (an-entry)
(list (entry-x an-entry) (entry-y an-entry))))
;(define-type state (listof (structure:entry num num (union 'x 'o)))
;(define-type states (listof state))
(define PLAYER 'x)
(define OPPONENT 'o)
(define tic-tac-toe
(lambda (x y)
(tic (list (list (make-entry x y PLAYER))))))
(define make-move
(lambda (other-move p/o tag)
(lambda (states)
(printf "~s: processing ~s states of length ~s ~n"
tag (length states) (length (car states)))
(let ((t (print&remove-terminals states)))
(printf "terminal states removed: ~s~n"
(- (length states) (length t)))
(if (null? t)
(void)
(other-move (apply append (map p/o t))))))))
(define tic (make-move (lambda (x) (tac x)) (lambda (x) (opponent x)) 'tic))
(define tac (make-move (lambda (x) (tic x)) (lambda (x) (player x)) 'tac))
(define make-players
(local ((define rest-of-fields
(lambda (used-fields)
(set-minus ALL-FIELDS used-fields))))
(lambda (player/opponent)
(lambda (astate)
(map (lambda (counter-move)
(let ((counter-x (car counter-move))
(counter-y (cadr counter-move)))
(cons (make-entry counter-x counter-y player/opponent)
astate)))
(rest-of-fields (map entry-field astate)))))))
(define player (make-players PLAYER))
(define opponent (make-players OPPONENT))
(define terminal?
(local ((define filter-p/o
(lambda (p/o astate)
(map entry-field
(filter (lambda (x) (eq? (entry-who x) p/o)) astate)))))
(lambda (astate)
(and (>= (length astate) 5)
(let ((PLAYERf (filter-p/o PLAYER astate))
(OPPONENTf (filter-p/o OPPONENT astate)))
(or
(= (length astate) 9)
(ormap (lambda (ts) (subset? ts PLAYERf)) TERMINAL-STATES)
(ormap (lambda (ts) (subset? ts OPPONENTf)) TERMINAL-STATES)))))))
(define print&remove-terminals
(local (
(define print-state1
(lambda (x)
(display x)
(newline)))
(define print-state2
(lambda (astate)
(cond
((null? astate) (printf "------------~n"))
(else (print-state (cdr astate))
(let ((x (car astate)))
(printf " ~s @ (~s,~s) ~n"
(entry-who x) (entry-x x) (entry-y x)))))))
(define print-state
(lambda (x)
;(display ".")
(void))))
(collect null (lambda (_ astate rest)
(if (terminal? astate)
(begin (print-state astate) rest)
(cons astate rest))))))
;; fields
(define T
(lambda (alof)
(cond
((null? alof) null)
(else (cons (list (cadr (car alof)) (car (car alof)))
(T (cdr alof)))))))
(define row1 (list (list 1 1) (list 1 2) (list 1 3)))
(define row2 (list (list 2 1) (list 2 2) (list 2 3)))
(define row3 (list (list 3 1) (list 3 2) (list 3 3)))
(define col1 (list (list 1 1) (list 2 1) (list 3 1)))
(define col2 (list (list 1 2) (list 2 2) (list 3 2)))
(define col3 (list (list 1 3) (list 2 3) (list 3 3)))
(define posd (list (list 1 1) (list 2 2) (list 3 3)))
(define negd (list (list 1 3) (list 2 2) (list 3 1)))
(define TERMINAL-STATES (list row1 row2 row3 col1 col2 col3 posd negd))
(define ALL-FIELDS (append row1 row2 row3))