How would I create a multiplayer (same screen, different windows) server in Racket ISL+ lambda with a thin server?

18 Views Asked by At

I am a bit frustrated and in need of some help. I am writing a turn based matching card flip game (Memory) with a multiplayer component and I am having a hard time knowing where to start for the server. The player code is as follows: (require 2htdp/image) (require 2htdp/universe)

;; Constants (define ESCN-LEN 600) (define ESCN-HEIGHT 400) (define ESCN-COLOR 'darkgreen) (define CARD-LEN 20) (define CARD-HEIGHT 40) (define CARD-COLOR 'black) (define TEXT-SIZE 36) (define TEXT-COLOR 'white) (define NON-TURN 'non-turn) (define PLAYER 1)

(define ESCN-BCKGRND (rectangle ESCN-LEN ESCN-HEIGHT 'solid ESCN-COLOR)) (define FLIP-INSTR (text "Press a corresponding number key to flip a card (i.e. 0 to flip the first card)." 16 'white)) (define TURN-INSTR (text "Press space to advance the turn to the next player." 16 'white)) (define ESCN2 (place-image FLIP-INSTR (/ ESCN-LEN 2) (* 0.8 ESCN-HEIGHT) ESCN-BCKGRND)) (define ESCN1 (place-image TURN-INSTR (/ ESCN-LEN 2) (* 0.86 ESCN-HEIGHT) ESCN2))

;; A card is a strucutre: ;; (make-card flipped? matched? color num) (define-struct card (flipped? matched? color num))

;; Sample cards (define CARD0 (make-card #f #f 'green 0)) (define CARD1 (make-card #f #f 'blue 0))

;; loc is a list of cards ;; Sample instances of list of cards (define INIT-LOC (list (make-card #f #f 'red 0) (make-card #f #f 'yellow 1) (make-card #f #f 'blue 2) (make-card #f #f 'yellow 3) (make-card #f #f 'pink 4) (make-card #f #f 'green 5) (make-card #f #f 'pink 6) (make-card #f #f 'red 7) (make-card #f #f 'blue 8) (make-card #f #f 'green 9))) (define INIT-LOC1 (list (make-card #t #t 'green 0) (make-card #t #t 'green 1) (make-card #f #t 'red 2) (make-card #f #t 'red 3) (make-card #f #t 'blue 4) (make-card #f #t 'blue 5) (make-card #f #t 'yellow 6) (make-card #f #t 'yellow 7) (make-card #f #t 'pink 8) (make-card #f #t 'pink 9)))

#| Template for functions on a card ;; card ... -> ... ;; Purpose: (define f-on-card a-card ...) ...)

;; Sample expressions for f-on-card

;; Tests using sample computations for f-on-card

;; Tests using sample values for f-on-card |#

;; A world is a structure, (make-world loc p-turn) ;; where loc is a list of cards, and p-turn is the current player turn (define-struct world (cards p-turn))

;; Sample worlds (define INIT-WORLD (make-world INIT-LOC 1)) ; p-turn starts at 1 so that player 1 can start the game (define INIT-WORLD1 (make-world INIT-LOC1 1))

;; world -> scene ;; to draw the given world in the empty-scene. (define (draw-world a-world) (local [;; card -> img ;; Purpose: to take a given card and draw it on the screen, face up if its flipped, and face down if not. (define (mk-card-img a-card) (if (not (card-flipped? a-card)) (overlay (text (number->string (card-num a-card)) TEXT-SIZE TEXT-COLOR) (rectangle CARD-LEN CARD-HEIGHT 'solid CARD-COLOR)) (rectangle CARD-LEN CARD-HEIGHT 'solid (card-color a-card))))

      ;; Sample expressions for mk-card-img
      (define CARD-IMG-0 (mk-card-img (list-ref (world-cards a-world) 0)))
      (define CARD-IMG-1 (mk-card-img (list-ref (world-cards a-world) 1)))
      (define CARD-IMG-2 (mk-card-img (list-ref (world-cards a-world) 2)))
      (define CARD-IMG-3 (mk-card-img (list-ref (world-cards a-world) 3)))
      (define CARD-IMG-4 (mk-card-img (list-ref (world-cards a-world) 4)))
      (define CARD-IMG-5 (mk-card-img (list-ref (world-cards a-world) 5)))
      (define CARD-IMG-6 (mk-card-img (list-ref (world-cards a-world) 6)))
      (define CARD-IMG-7 (mk-card-img (list-ref (world-cards a-world) 7)))
      (define CARD-IMG-8 (mk-card-img (list-ref (world-cards a-world) 8)))
      (define CARD-IMG-9 (mk-card-img (list-ref (world-cards a-world) 9)))

      (define ESCN (overlay
                    (above (beside CARD-IMG-0 CARD-IMG-1 CARD-IMG-2 CARD-IMG-3 CARD-IMG-4)
                           (beside CARD-IMG-5 CARD-IMG-6 CARD-IMG-7 CARD-IMG-8 CARD-IMG-9)) ESCN1))

      (define P-TURN-TEXT (text (string-append "current turn: player " (number->string (world-p-turn a-world))) 24 'white))
      
      ;; a-world -> scene
      ;; Purpose: to draw the given world in the empty scene.
      (define (draw-world a-world)
        (place-image P-TURN-TEXT
                     (/ ESCN-LEN 2)
                     (* 0.3 ESCN-HEIGHT)
                     ESCN))]
(draw-world a-world)))

; computer player, randomly pick 0 through 9. ; implement tests.

;; Key processing functions

;; world a-key -> world ;; Purpose: process a key event to return next world (define (process-key a-world a-key) (local [;; a-loc -> num ;; Purpose: to count the number of flipped cards in a-loc, excluding matched cards. (define (numof-cards-flipped a-loc) (if (empty? a-loc) 0 (if (and (card-flipped? (first a-loc)) (not (card-matched? (first a-loc)))) (+ 1 (numof-cards-flipped (rest a-loc))) (numof-cards-flipped (rest a-loc)))))

      ;; a-loc -> boolean
      ;; Purpose: to check if two cards are flipped in a-loc.
      (define (two-cards-flipped? a-loc)
        (= (numof-cards-flipped a-loc) 2))

      ;; a-card a-loc -> boolean
      ;; Purpose: to determine whether two cards are matched or not.
      (define (has-match? a-card a-loc)
        (ormap (λ (a-card1)
                 (and (not (= (card-num a-card) (card-num a-card1)))
                      (card-flipped? a-card)
                      (card-flipped? a-card1)
                      (equal? (card-color a-card)
                              (card-color a-card1))))
               a-loc))
      
      ;; a-card a-loc key-num down? -> a-card
      ;; Purpose: to update the flipped? and matched? values of a-card in a-loc, depending on whether we are flipping down or up.
      (define (update-flipped-card a-card a-loc key-num down?)
        (cond [down? ; flipping cards down
               (if (has-match? a-card a-loc)
                   (make-card #t #t (card-color a-card) (card-num a-card))
                   (make-card #f #f (card-color a-card) (card-num a-card)))]
              [else ; flipping a card up
               (if (= (card-num a-card) key-num)
                   (make-card #t #f (card-color a-card) (card-num a-card))
                   a-card)]))
      
      ;; a-loc key-num -> a-loc
      ;; Purpose: to flip a specific card in a-loc up.
      (define (flip-card-up a-loc key-num)
        (map (lambda (a-card) (update-flipped-card a-card a-loc key-num #f)) a-loc))

      ;; a-loc key-num -> a-loc
      ;; Purpose: to determine whether or not a card can be flipped, and flip it if so.
      (define (flip-card a-loc key-num)
        (if (two-cards-flipped? a-loc)
            a-loc
            (if (card-flipped? (list-ref a-loc key-num))
                a-loc
                (if (empty? a-loc)
                    '()
                    (flip-card-up a-loc key-num)))))

      ;; a-world -> boolean
      ;; Purpose: to determine whether it is the players turn or not.
      (define (is-player-turn? a-world)
        (= (world-p-turn a-world) PLAYER))

      ;; p-turn (num) -> p-turn (num)
      ;; Purpose: to cycle through the p-turns, 0 through 2.
      (define (increment-p-turn p-turn) ; ONLY INCREMENT IF THE TWO CARDS THE THE PLAYER FLIPPED ARE NOT MATCHED. ----------
        (if (= p-turn 2)
            0
            (add1 p-turn)))

      ;; a-loc -> a-loc
      ;; Purpose: to flip a-loc down.
      (define (flip-cards-down a-loc)
            (map (lambda (a-card) (update-flipped-card a-card a-loc 0 #t)) a-loc))

      ;; a-world -> a-world
      ;; Purpose: to advance the turn of one player to the next, flipping down the necessary cards, and incrementing the player turn.
      (define (advance-turn a-world)
        (make-world (flip-cards-down (world-cards a-world)) (increment-p-turn (world-p-turn a-world))))

      ;; world key -> world
      ;; Purpose: to process a key event to return a world
      (define (process-key a-world a-key)
        (cond [(key=? a-key "0")
               (make-world (flip-card (world-cards a-world) 0) (world-p-turn a-world))]
              [(key=? a-key "1")
               (make-world (flip-card (world-cards a-world) 1) (world-p-turn a-world))]
              [(key=? a-key "2")
               (make-world (flip-card (world-cards a-world) 2) (world-p-turn a-world))]
              [(key=? a-key "3")
               (make-world (flip-card (world-cards a-world) 3) (world-p-turn a-world))]
              [(key=? a-key "4")
               (make-world (flip-card (world-cards a-world) 4) (world-p-turn a-world))]
              [(key=? a-key "5")
               (make-world (flip-card (world-cards a-world) 5) (world-p-turn a-world))]
              [(key=? a-key "6")
               (make-world (flip-card (world-cards a-world) 6) (world-p-turn a-world))]
              [(key=? a-key "7")
               (make-world (flip-card (world-cards a-world) 7) (world-p-turn a-world))]
              [(key=? a-key "8")
               (make-world (flip-card (world-cards a-world) 8) (world-p-turn a-world))]
              [(key=? a-key "9")
               (make-world (flip-card (world-cards a-world) 9) (world-p-turn a-world))]
              [(key=? a-key " ")
               (advance-turn a-world)]
              [else a-world]))]
(if (is-player-turn? a-world)
    (process-key a-world a-key)
    a-world)))

;; world -> boolean ;; Purpose: to determine if the game is over or not. (define (game-over? a-world) (andmap (lambda (a-card) (card-flipped? a-card)) (world-cards a-world)))

(define (draw-final-world a-world) (place-image (text "Game Over D:" 80 'black) (/ ESCN-LEN 2) (/ ESCN-HEIGHT 2) (draw-world a-world)))

;; name -> world (define (run a-name) (big-bang INIT-WORLD (on-draw draw-world) (on-key process-key) (stop-when game-over? draw-final-world) ;(on-receive process-message) ;(register LOCALHOST) (name a-name)))

And the server code is: ;; Any -> universe ;; Purpose: Run the universe server (define (run-server a-z) (universe INIT-UNIV (on-new add-new-iworld) (on-msg process-message) (on-disconnect rm-iworld)))

Please let me know what I could/should do to get this working, I am not very good at the language. Anything helps.

I tried using Chatgpt to outline what I need for the server, but it went on and on with meaningless extra information which is not available in the Racket handbook nor our textboo. I could just really use some help.

0

There are 0 best solutions below