(define-module (gib-gab-gob rps) #:use-module (gib-gab-gob actors) #:use-module (ice-9 match) #:use-module (goblins) #:use-module (goblins actor-lib methods) #:use-module (goblins actor-lib sealers) #:use-module (goblins ocapn captp) #:use-module (goblins ocapn ids) #:use-module (goblins ocapn netlayer testuds) #:export (make-host make-client)) ;; ;; Helper to use testuds netlayer ;; (define (new-testuds-netlayer) (define tmp "/tmp/netlayers") (unless (access? tmp X_OK) (mkdir tmp)) (spawn ^testuds-netlayer tmp)) ;; ;; Host logic ;; (define (make-host ^game-controller) (with-vat (spawn-vat) (define lobby (spawn ^game-lobby ^game-controller)) (define mycapn (spawn-mycapn (new-testuds-netlayer))) (define lobby-sref ($ mycapn 'register lobby 'testuds)) (format #t "Connect to: ~a\n" (ocapn-id->string lobby-sref)))) (define (^game-lobby bcom ^game-controller) (define pick (pick-rps)) (methods [(register-opponent name peer sealed-pick) (format #t "Hey there, ~a! You sent me your pick of rock-paper-scissors; now I will send mine.\n" name) (on (<- (<- peer 'pick->unsealer pick) sealed-pick) (lambda (peer-pick) (define won? (rps-winner pick peer-pick)) (format #t "Opponent ~a has picked ~a (do I win? ~a). Time to be a controller.\n" name peer-pick won?) (bcom (^game-controller bcom won? peer))))])) ;; ;; Client logic ;; (define (make-client ^game-controller user-name addr) (pk user-name) (pk addr) (pk ^game-controller) (with-vat (spawn-vat) (define mycapn (spawn-mycapn (new-testuds-netlayer))) (define lobby-sref (string->ocapn-id addr)) (define lobby ($ mycapn 'enliven lobby-sref)) (define client-picker (spawn ^client-picker lobby ^game-controller)) (on (<- lobby 'register-opponent user-name client-picker ($ client-picker 'get-sealed-pick)) (lambda (_) (format #t "~a finished the game.\n" user-name))))) (define (^client-picker bcom lobby ^game-controller) (define-values (seal-pick unseal-pick my-pick?) (spawn-sealer-triplet)) (define pick (pick-rps)) (methods [(get-sealed-pick) ($ seal-pick pick)] [(pick->unsealer peer-pick) (define won? (rps-winner pick peer-pick)) (format #t "Peer picked ~a... a bold choice (do I win? ~a), I will become a controller and send my unsealer.\n" peer-pick won?) ;; We make the assumption that lobby is to become a controller. (bcom (^game-controller bcom won? lobby)) unseal-pick])) ;; ;; Standard rock paper scissors logic follows! ;; (define rock-paper-scissors (list 'rock 'paper 'scissors)) (define (pick-rps) (list-ref rock-paper-scissors (random (length rock-paper-scissors)))) (define (rps-winner a b) (if (and (memq a rock-paper-scissors) (memq b rock-paper-scissors)) (match (list a b) [(x x) 'tie] [('rock 'scissors) #t] [('rock 'paper) #f] [('scissors 'paper) #t] [(x y) (not (rps-winner y x))]) (error "Unexpected item in the shooting area" a b)))