; ; ; ; ; ;;;; ; ; ; ; ; ;;;; ; ;;;; ; ; ; ;;; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ;;;; ; ;;;;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ;; ; ; ;;;;; ; ; ; ; ; ; ; ; #| THE GAME ------------------------------------------------------- One player, the dealer, picks a digit. When (a given number of) N other players, the guessers, have told the dealer that they are ready, the guessing may begin. Each guesser may make one guess at a time and request an immediate response from the dealer. The response is either "correct" or "incorrect". When a guesser picks the correct number, the dealer also tells all other guessers that the game is over. ------------------------------------------------------- |# (define DIGITS '(0 1 2 3 4 5 6 7 8 9)) ;; A Digit is a member of DIGITS. ;; QUESTIONS: ;; --------------------------------------------------------------- ;; Which information must reside in/is created in the server? ;; the secret digit -- has to be a constant throughout the game ;; the winner and all the guessers ;; are all guessers signed up? has the game started yet? ;; --------------------------------------------------------------- ;; Which information must reside in/is created in the clients? ;; the (current) guess ;; whether they won or lost the game ;; --------------------------------------------------------------- ;; Which information must flow from a client to the server? ;; the guess ;; Which information must flow from the server to a specific ;; client? ;; whether the guess was correct/incorrect (right or wrong) ;; that the client is a loser ;; that the game has started ;; --------------------------------------------------------------- ;; WHEN does information flow from the server to the clients ;; and vice versa? ;; cient to server: press a digit key ;; server to client: ;; -- the game has started (all N guessers have registered) ;; -- right or wrong after a guess arrives ;; -- loser message: when the correct digit has been guessed, ;; everyone but the winner ;; --------------------------------------------------------------- ;; What is a good data representation for the messages from the ;; clients to the server? ;; Client2Server is Digit. ;; What is a good data representation for the messages from the ;; server to the clients? ;; Server2Client is one of: ;; -- 'go ;; -- Boolean (true means your guess was correct) ;; -- 'stop ;; --------------------------------------------------------------- ;; Which events should the server react to? ;; How about the client(s)? ;; on-new another guesser showed up, the server must remember ;; must count, may have to start the game, ... ;; on-msg a guesser sent in a digit ;; when there aren't enough guessers, ignore ;; when there are, check and react ;; when the game is over, ignore ;; on-disc removed at Calyton's request ;; on-key a new guess, if it is a digit ;; on-receive when a 'go or an answer comes in ;; to-draw render the current state for the player ;; stop-when when you have been picked as winner or loser ;; --------------------------------------------------------------- ;; Which parts of the server's state of information changes over ;; time and needs to be tracked in its state? ;; What is a good data representation? ;; constant: the secret digit and the number of guessers that play ;; changing: the guessers (their number) ;; N : natural number ;; s : Digit ;; the guessers : [List-of IWorld] ;; --------------------------------------------------------------- ;; Which parts of each client's state of information changes over ;; time and how does it change? ;; What is a good data representation? ;; constant: ;; changing: wait until 'go, I am now a guesser ;; the current guess ;; true: I am no longer a guesser, I am a winner ;; false: current guess was wrong ;; 'stop : I am no longer a guesser, I am a loser. ;; The GuesserState is one of: ;; -- 'waiting ;; -- 'going ;; -- Digit ;; -- false xor (list Digit false) ;; -- true (you're the winner) ;; -- 'loser ;; -------------------------------------------------------------- (require 2htdp/universe) (require 2htdp/image) ; ; ; ; ; ; ; ;;; ; ;;;; ;; ; ; ;; ; ; ;;;; ;; ;; ; ; ;; ; ; ;; ;; ; ;; ;; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;;; ;;;; ;;; ;; ;;;; ;; ; ;;;; ;;; ;; ; ; ; ; ;; ---------------------- DESIGN ---------------------- ;; each world wants to send out the current guess ;; the universe will respond to each guess with true/false ;; ;; A Server2Guesser message is one of: ;; -- 'go % the server accepts guesses ;; -- 'stop % someone (else) guessed the digit ;; -- true % you guessed the correct digit ;; -- false % your guess was incorrect ;; ;; A Guesser2Server message is Digit ;; ;; Digit is in DIGITS ;; ------------------------------------------------------- ;; Digit Boolean -> '() | GuessState | GuessState ... ;; create universe and let two worlds guess (define (main x debug?) (launch-many-worlds (server 2 x debug?) ;; two communicating worlds: (world "carl" LOCALHOST) (world "sam" LOCALHOST))) ; ; ; ; ;; ;; ; ; ; ; ; ; ; ;;; ;; ;;;; ;; ;;; ; ;;; ; ; ; ; ; ; ;; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ;;;; ;;;;; ;;;;; ;;; ;; ; ; ; ; (define BASE (empty-scene 200 200)) ;; GuessState is one of: ;; DATA INTERPRETATION ;; -- 'waiting no guess yet ;; -- 'going ready to accept guesses ;; -- Digit the most recent guess ;; -- (list Digit false) the most recent guess was wrong ;; -- true you're the winner ;; -- 'loser someone else won ;; GuessPackage is (make-package Digit Digit) ;; interpretation: (make-package d d); d is the guess ;; constraint: the two digits are always the same ;; see create-guess-package ;; String String -> GuessState ;; launch a world named n that enables a player to guess a digit ;; once enough other worlds have signed up (define (world n ip) (big-bang false [to-draw render] [on-key guessing] [on-receive did-i-guess] [stop-when loser? render-result] [register ip] [name n])) ;; WISHLIST ;; GuessState KeyEvent -> GuessPackage or GuessState ;; if it is a digit, send it off to the server ;; when the 'waiting period is over (check-expect (guessing 'waiting 5) 'waiting) (check-expect (guessing 'going 5) (make-package 5 5)) (check-expect (guessing 5 8) (make-package 8 8)) (check-expect (guessing (list 5 false) 8) (make-package 8 8)) (check-expect (guessing (list 5 false) "a") (list 5 false)) (check-expect (guessing true 8) true) (check-expect (guessing 'loser 8) 'loser) (check-expect (guessing 'going "a") 'going) (define (guessing w ke) w) ;; GuessState Server2Guesser -> GuessState ;; receive message and set state appropriately (check-expect (did-i-guess 'waiting 'go) 'going) (check-expect (did-i-guess 'going 'stop) 'loser) (check-expect (did-i-guess 5 'stop) 'loser) (check-expect (did-i-guess 5 false) (list 5 false)) (check-expect (did-i-guess 5 true) true) (define (did-i-guess w msg) w) ;; Digit -> GuessPackage ;; create a guess package from a single digit (check-expect (create-guess-package 5) (make-package 5 5)) (check-expect (create-guess-package 0) (make-package 0 0)) (define (create-guess-package d) (make-package d d)) ;; GuessState -> Image ;; render an world state (define (render w) empty-image) ;; GuessState -> Image ;; render the final state of the world ;; NOTE: w is either true or 'loser (define (render-result w) empty-image) ;; GuessState -> Boolean ;; is this a final state? (check-expect (loser? 'loser) true) (check-expect (loser? true) true) (check-expect (loser? (list 5 false)) false) (check-expect (loser? 5) false) (check-expect (loser? 'going) false) (check-expect (loser? 'waiting) false) (define (loser? w) false) ; ; ; ; ; ; ; ; ;; ;; ;; ;; ;;; ;;; ;;; ;;;; ;; ;;; ;;;; ;;;; ; ; ; ;; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; ; ; ; ;;;;;; ; ;;;; ;;;;;; ; ; ; ; ; ; ; ; ; ; ; ; ; ;; ; ; ; ;; ; ; ; ; ; ;; ; ;;; ;; ;;;;; ;; ;;;;; ;;;;; ;;;;; ;;;;; ; ; ; ; ;; ServerState is [List-of IWorld] ;; interpretation: the worlds signed up so far (define u1 (list iworld1)) (define u2 (list iworld1 iworld2)) ;; GuessBundle is ;; (make-bundle ServerState [List-of GMail] '()) ;; GMail is (make-mail IWorld Server2Guesser) ;; Nat Digit Boolean -> SeverState ;; launch server with secret digit s to be guessed when (define (server n s debug?) ;; ------------------------------------------------------------ ;; see HtDP/2e section 19.2 on expressive power to see why ;; the handlers are defined inside of server with a local ;; http://www.ccs.neu.edu/home/matthias/HtDP2e/part_three.html ;; ------------------------------------------------------------ (local (;; ServerState IWorld -> GuessBundle ;; add a world to the universe until n (define (sign-up u iw) (local ((define v (cons iw u)) (define k (length v))) (cond [(< k n) (send-nothing v)] [(= k n) (go v)] [(> k n) (send-nothing u)]))) ;; ServerState IWorld Guesser2Server -> GuessBundle ;; take care of a message (define (check-and-respond u iw g) (if (= (length u) n) (create-response u iw g s) (send-nothing u)))) ;; --- IN --- (universe '() [state debug?] [on-new sign-up] [on-msg check-and-respond]))) ;; SeverState -> GuessBundle ;; create a bundle from the state w/o ;; sending messages or dropping worlds (check-expect (send-nothing u2) (make-bundle u2 '() '())) (define (send-nothing v) (make-bundle v '() '())) ;; WISHLIST ;; ServerState -> GuessBundle ;; let everyone know that the game is ready to go (check-expect (go u1) (make-bundle u1 (list (make-mail iworld1 'go)) '())) (check-expect (go u2) (make-bundle u2 (list (make-mail iworld1 'go) (make-mail iworld2 'go)) '())) (define (go v) (send-nothing v)) ;; ServerState IWorld Digit Digit -> GuessBundle ;; formulate a response to iw on whether g = s ;; and all others when g is really equal to s (check-expect (create-response u1 iworld1 5 6) (make-bundle u1 (list (make-mail iworld1 false)) '())) (check-expect (create-response u1 iworld1 5 5) (make-bundle u1 (list (make-mail iworld1 true)) '())) (check-expect (create-response u2 iworld2 5 7) (make-bundle u2 (list (make-mail iworld2 false)) '())) (check-expect (create-response u2 iworld2 5 5) (make-bundle u2 (list (make-mail iworld1 'stop) (make-mail iworld2 true)) '())) (define (create-response u iw g s) (send-nothing u))