(define-module (gib-gab-gob game) #:use-module (goblins) #:use-module (goblins vat) #:use-module (goblins actor-lib methods) #:use-module (goblins actor-lib sealers) #:use-module (goblins actor-lib selfish-spawn) #:use-module (ice-9 match) #:use-module (ice-9 rdelim) #:export (^ggg-controller)) ;; Actual Tic Tac Toe game (define ggg-size 3) ;; tic tac toe with more than 3x3 grid? (define (^ggg-controller bcom initiator? peer) (define mark (if initiator? "x" "o")) (define peer-mark (if initiator? "o" "x")) (define board (selfish-spawn ^peer-board)) (define my-turn? (not initiator?)) (methods ;; The peer is telling us about the turn it took. [(peer-turn! coords) (if (not my-turn?) (begin ($ board 'choose! coords peer-mark) (set! my-turn? (not my-turn?))) (error "It's my turn!"))] ;; TODO: This needs to go somewhere else so the peer can't move for us! [(my-turn! coords) (if my-turn? (begin ($ board 'choose! coords mark) (set! my-turn? (not my-turn?))) (error "It's not my turn."))])) ;; Board logic (define (^peer-board bcom self) ;; Define the array with unspecified values, then fill (define arr (make-array *unspecified* ggg-size ggg-size)) (array-map! arr (lambda () (spawn ^mark))) (methods ;; Switch coords for clarity [(ref coords) (match coords ((x y) (array-ref arr y x)))] [(chosen? coords) (not (not ($ ($ self 'ref coords) 'get)))] [(choose! coords mark-char) (let* ((mark ($ self 'ref coords)) (char ($ mark 'get))) (if char (error "coords already chosen:" coords) (begin ($ mark 'choose! mark-char) ($ self 'display))))] [(display) (define (print-mark mark) (let ((mark ($ mark 'get))) (or mark " "))) ;; this is .. probably messy? (array-slice-for-each-in-order 1 (lambda (x) (map (lambda (i) (format #t "[~a]" (print-mark i))) (array->list x)) (format #t "\n")) arr)])) ;; Do we need to use SRFI 158, or newra library, to do this? ;; [(get-winner) ???] (define* (^mark bcom #:optional [mark #f]) (methods [(get) mark] [(choose! mark-char) (if mark (error "this mark is already chosen") (bcom (^mark bcom mark-char)))]))