;; The first three lines of this file were inserted by DrRacket. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-advanced-reader.ss" "lang")((modname |pset10 vfinal|) (read-case-sensitive #t) (teachpacks ((lib "draw.ss" "teachpack" "htdp") (lib "gui.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ((lib "draw.ss" "teachpack" "htdp") (lib "gui.ss" "teachpack" "htdp"))))) ;Problem Set 10 ;Paul Schmitz ;Jon Schouvieller ;John McCall ;CSci 1301 ;Dec 2010 ;;The Extra Stuff Included;; ;structures: used for defining events ;recursive functions: used for almost everything, all the battles and moving and picking up items uses recursion of some kind ;drawings: quite a few drawings and the map is updated with everymove ;memory updates: used set! to change many variables, including Health, the list of items, and event-status' ;randomness: used for dealing damage ;; ============== These are the two predefined functions ==================== ;; You don't need to understand their code, only the contract and the purpose ;; =========================================================================== ;; ===================== You may skip to the sample code below ================ ;; get-choice: string, list of strings -> integer ;; the function displays a simple menu form with the given message ;; and a drop-down menu with the list of choices. The menu ;; initially displays "Make a choice". Once a different item is chosen, ;; that item is returned. ;; When a "Close" button is pressed, the form disappears. (define (get-choice message list-of-choices) (local ( (define the-choices (make-choice (cons "Make a choice" list-of-choices))) (define w (create-window (list (list (make-message message)) (list the-choices) (list (make-button "Close" (lambda (e) (hide-window w))))))) (define (process-result n) (cond [(> n 200) (hide-window w)] ;; timeout after 200 sec [(= (choice-index the-choices) 0) (and (sleep-for-a-while 1) (process-result (+ n 1)))] [else true]) ) ) (cond [(process-result 0) (list-ref list-of-choices (- (choice-index the-choices) 1))]))) ;; get-answer: string number -> string ;; The function displays a simple text input with a question ;; and returns the answer typed in by the user ;; The second parameter (time-delay) is the number of seconds ;; the function waits after the typing of the first character ;; before it returns the answer. If the user takes longer ;; than that, a partial answer may be returned ;; 5 sec delay is reasonable for a one-word answer (define (get-answer question time-delay) (local ((define the-answer (make-text question)) (define w (create-window (list (list the-answer) (list (make-button "Accept" (lambda (e) (hide-window w))))))) (define (process-result n) (cond [(> n 200) (hide-window w)] ;; timeout after 200 sec [(string=? (text-contents the-answer) "") (and (sleep-for-a-while 1) (process-result (+ n 1)))] [else true] ;; the user starts typing ))) (cond [(process-result 0) (cond [(sleep-for-a-while time-delay) (text-contents the-answer)]) ]) )) ;; =========================== do not change anything above this line ============= ;; NOTE: The language is Advanced Student. Teachpacks: gui.ss, draw.ss ;; =========================== Your work goes here: =============================== ;; This is an example of one round of the accummulation stage of a game. ;; Your game will have multiple rounds. ;; the first list of choices: ;(define weapon-choices (list "frying pan" "light saber")) ;; calling "get-choice" to get the user's choice, adding the choice to ;; the list of weapons. weapon-list is the new list ;(define weapon-list (cons ; (get-choice "Choose your weapon" weapon-choices) ; empty)) ;(sleep-for-a-while 2) ;; calling a get-answer function to let the user type in their name ;; 5 is the number of seconds you expect the user to spend on typing ;; the answer (from the fisrt character to the last one). ;; Too short times may result in the program getting a partial answer ;; Feel free to adjust this time as needed ;(define character-name (get-answer "What's your name?" 5)) (define standard-delay 2) ;PLAYER/MONSTER STATS (define player-hp 100) ;;player-death ;;to inform a player that they have died (define (player-death null) (begin (give-message "You have died. GAME OVER" standard-delay) (stop) ) ) ;;change-player-hp: number -> number ;;used to change the player-hp variable (define (change-player-hp amount) (begin (set! player-hp (- player-hp amount)) (give-status-message (string-append "Your Health is " (number->string player-hp)) standard-delay) (cond [(>= 0 player-hp) (player-death null)] [else true]) ) ) (define boss-hp 200) ;;boss-death ;;to inform player of the bosses death (define (boss-death null) (begin (give-message "The Beholder has been triumphed over! The Exit Lies Ahead.") ) ) ;;change-boss-hp: amount -> number ;;to change the boss' hp (define (change-boss-hp amount) (begin (set! boss-hp (- boss-hp amount)) (give-monster-message (string-append "Boss Health: " (number->string boss-hp)) standard-delay) (cond [(>= 0 boss-hp) (boss-death null)] [else true] ) ) ) (define monster-hp 0) ;;change-monster-hp: number -> number ;;to change a monster's hp (define (change-monster-hp amount) (begin (set! monster-hp (- monster-hp amount)) (give-monster-message (string-append "Enemy Health: " (number->string monster-hp)) standard-delay) ) ) ;MAP ;this structure represents a 2D map. (define-struct map-position (x-posn y-posn)) ;this function converts a map-position to a posn structure (define (map-position-to-posn input-map-position) (make-posn (+ 15 (* 30 (map-position-x-posn input-map-position))) (- 115 (* -30 (map-position-y-posn input-map-position))) ) ) ;this is the list of choices for the movement function. (define movement-choices (list "up" "right" "down" "left")) ;this is the direction that the player is currently moving. (define current-movement "starting value for current-movement") ;map-position=? : map-position map-position -> boolean ;checks whether two map positions are equal (define (map-position=? pos1 pos2) (and (= (map-position-x-posn pos1) (map-position-x-posn pos2)) (= (map-position-y-posn pos1) (map-position-y-posn pos2)) ) ) ;this is the starting position for the character. (define character-position (make-map-position 0 0)) ;this is the list of valid positions on the map. (define valid-positions (list (make-map-position 0 0) (make-map-position 1 0) (make-map-position 2 0) (make-map-position 3 0) (make-map-position 4 0) (make-map-position 4 1) (make-map-position 5 1) (make-map-position 6 1) (make-map-position 6 0) (make-map-position 7 0) (make-map-position 8 0) (make-map-position 9 0) (make-map-position 1 1) (make-map-position 1 2) (make-map-position 1 3) (make-map-position 1 4) (make-map-position 0 4) (make-map-position 0 5) (make-map-position 0 6) (make-map-position 0 7) (make-map-position 0 8) (make-map-position 1 6) (make-map-position 2 6) (make-map-position 3 6) (make-map-position 1 8) (make-map-position 2 8) (make-map-position 2 9) (make-map-position 2 3) (make-map-position 3 3) (make-map-position 4 3) (make-map-position 5 3) (make-map-position 6 3) (make-map-position 7 3) (make-map-position 7 2) (make-map-position 8 2) (make-map-position 5 2) (make-map-position 9 1) (make-map-position 9 2) (make-map-position 9 3) (make-map-position 9 4) (make-map-position 9 5) (make-map-position 9 6) (make-map-position 9 7) (make-map-position 9 8) (make-map-position 9 9) (make-map-position 2 3) (make-map-position 5 4) (make-map-position 5 5) (make-map-position 6 5) (make-map-position 6 6) (make-map-position 6 7) (make-map-position 6 8) (make-map-position 6 9) (make-map-position 7 9) (make-map-position 3 5) (make-map-position 4 5) (make-map-position 8 4) (make-map-position 8 5) (make-map-position 7 7) (make-map-position 8 7) (make-map-position 3 2) )) ;DRAWING THE MAP (start 301 401) ;(draw-solid-rect (make-posn 0 100) 300 300 'black) ;(draw-solid-line (make-posn 0 100) (make-posn 0 400)) ;;draw-vertical-lines: posn1 posn2 -> boolean ;;To draw the vertical lines of the map (define (draw-vertical-lines posn1 posn2) (cond [(= (posn-x posn1) 300) (draw-solid-line posn1 posn2)] [else (and (draw-solid-line posn1 posn2) (draw-vertical-lines (make-posn (+ (posn-x posn1) 30) (posn-y posn1)) (make-posn (+ (posn-x posn2) 30) (posn-y posn2)) ) )] ) ) ;;draw-hoizontal-lines: posn1 posn2 -> boolean ;;To draw the horizontal lines of the map (define (draw-horizontal-lines posn1 posn2) (cond [(= (posn-y posn1) 400) (draw-solid-line posn1 posn2)] [else (and (draw-solid-line posn1 posn2) (draw-horizontal-lines (make-posn (posn-x posn1) (+ (posn-y posn1) 30)) (make-posn (posn-x posn2) (+ (posn-y posn2) 30)) ) )] ) ) ;;used to draw the map (define draw-map (and (draw-vertical-lines (make-posn 0 100) (make-posn 0 400)) (draw-horizontal-lines (make-posn 0 100) (make-posn 300 100)) ) ) ;contract: draw-character-abs : posn color -> void ;this function draws a picture of the player character at the given position ;and uses the given color. ;definition: (define (draw-character-abs inputposn color) (local ((define posn (make-posn (- (posn-x inputposn) 14) (- (posn-y inputposn) 14)))) (begin (draw-solid-rect posn 29 29 'white) (draw-solid-disk (make-posn (+ (posn-x posn) 14) (+ (posn-y posn) 8)) 5 color) (draw-solid-rect (make-posn (+ (posn-x posn) 13) (+ (posn-y posn) 12)) 4 9 color) (draw-solid-line (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 7) (+ (posn-y posn) 20)) color) (draw-solid-line (make-posn (+ (posn-x posn) 11) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 6) (+ (posn-y posn) 20)) color) (draw-solid-line (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 22) (+ (posn-y posn) 20)) color) (draw-solid-line (make-posn (+ (posn-x posn) 18) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 23) (+ (posn-y posn) 20)) color) (draw-solid-line (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 21)) (make-posn (+ (posn-x posn) 11) (+ (posn-y posn) 27)) color) (draw-solid-line (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 21)) (make-posn (+ (posn-x posn) 18) (+ (posn-y posn) 27)) color) ) ) ) ;contract: draw-character : posn -> void ;this is a particular case of draw-character-abs which uses the color blue. ;this is necessary because the game was already setup to work with ;draw-character as a function taking a single parameter. ;definition: (define (draw-character posn) (draw-character-abs posn 'blue) ) ;contract: clear-character : posn -> true ;this function clears the image of the player character at the given position. ;definition: (define (clear-character inputposn) (local ((define posn (make-posn (- (posn-x inputposn) 14) (- (posn-y inputposn) 14)))) (draw-solid-rect posn 29 29 'white) )) ;;draw-treasure: posn -> boolean ;;draws an icon showing a treasure (define (draw-treasure posn) (and (draw-solid-rect posn 18 18 'brown) (draw-solid-rect (make-posn (+ (posn-x posn) 7.5) (posn-y posn)) 5 5 'yellow) ) ) ;;clear-treasure: posn -> boolean ;;to clear the treasure icon (define (clear-treasure posn) (clear-solid-rect posn 20 20) ) ;contract: draw-monster1 : posn color -> void ;this function draws an image of a monster standing on two legs at the givin ;position using the given color. ;definition: (define (draw-monster1 inputposn color) (local ((define posn (make-posn (- (posn-x inputposn) 14) (- (posn-y inputposn) 14)))) (begin ;clearing the background (draw-solid-rect posn 29 29 'white) ;head and torso (draw-solid-rect (make-posn (+ (posn-x posn) 11) (+ (posn-y posn) 5)) 8 9 color) (draw-solid-rect (make-posn (+ (posn-x posn) 13) (+ (posn-y posn) 12)) 4 9 color) ;horns (draw-solid-line (make-posn (+ (posn-x posn) 13) (+ (posn-y posn) 5)) (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 2)) color) (draw-solid-line (make-posn (+ (posn-x posn) 16) (+ (posn-y posn) 5)) (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 2)) color) ;face (draw-solid-line (make-posn (+ (posn-x posn) 13) (+ (posn-y posn) 8)) (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 7)) 'white) (draw-solid-line (make-posn (+ (posn-x posn) 13) (+ (posn-y posn) 9)) (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 8)) 'white) (draw-solid-line (make-posn (+ (posn-x posn) 16) (+ (posn-y posn) 8)) (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 7)) 'white) (draw-solid-line (make-posn (+ (posn-x posn) 16) (+ (posn-y posn) 9)) (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 8)) 'white) ;arms (draw-solid-line (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 7) (+ (posn-y posn) 20)) color) (draw-solid-line (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 22) (+ (posn-y posn) 20)) color) ;legs (draw-solid-line (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 21)) (make-posn (+ (posn-x posn) 11) (+ (posn-y posn) 27)) color) (draw-solid-line (make-posn (+ (posn-x posn) 17) (+ (posn-y posn) 21)) (make-posn (+ (posn-x posn) 18) (+ (posn-y posn) 27)) color) ) )) ;contract: draw-monster2 : posn color -> void ;this function draws an image of a monster standing on four legs at the givin ;position using the given color. ;definition: (define (draw-monster2 inputposn color) (local ((define posn (make-posn (- (posn-x inputposn) 14) (- (posn-y inputposn) 14)))) (begin ;clearing the background (draw-solid-rect posn 29 29 'white) ;body (draw-solid-rect (make-posn (+ (posn-x posn) 10) (+ (posn-y posn) 15)) 15 8 color) ;head (draw-solid-rect (make-posn (+ (posn-x posn) 9) (+ (posn-y posn) 6)) 5 14 color) (draw-solid-rect (make-posn (+ (posn-x posn) 6) (+ (posn-y posn) 8)) 4 3 color) (draw-solid-rect (make-posn (+ (posn-x posn) 4) (+ (posn-y posn) 9)) 2 2 color) (draw-solid-rect (make-posn (+ (posn-x posn) 5) (+ (posn-y posn) 13)) 6 2 color) ;eye (draw-solid-line (make-posn (+ (posn-x posn) 11) (+ (posn-y posn) 8)) (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 7)) 'white) (draw-solid-line (make-posn (+ (posn-x posn) 11) (+ (posn-y posn) 9)) (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 8)) 'white) ;limbs (draw-solid-line (make-posn (+ (posn-x posn) 10) (+ (posn-y posn) 23)) (make-posn (+ (posn-x posn) 9) (+ (posn-y posn) 27)) color) (draw-solid-line (make-posn (+ (posn-x posn) 14) (+ (posn-y posn) 23)) (make-posn (+ (posn-x posn) 13) (+ (posn-y posn) 27)) color) (draw-solid-line (make-posn (+ (posn-x posn) 20) (+ (posn-y posn) 23)) (make-posn (+ (posn-x posn) 21) (+ (posn-y posn) 27)) color) (draw-solid-line (make-posn (+ (posn-x posn) 24) (+ (posn-y posn) 23)) (make-posn (+ (posn-x posn) 25) (+ (posn-y posn) 27)) color) ) )) ;contract: draw-monster3 : posn color -> void ;this function draws an image of a monster standing on two legs with wings and ;a tail at the givin position using the given color. ;definition: (define (draw-monster3 inputposn color) (local ((define posn (make-posn (- (posn-x inputposn) 14) (- (posn-y inputposn) 14)))) (begin ;body (draw-monster2 inputposn color) ;wings (draw-solid-line (make-posn (+ (posn-x posn) 15) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 18) (+ (posn-y posn) 4)) color) (draw-solid-line (make-posn (+ (posn-x posn) 16) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 19) (+ (posn-y posn) 4)) color) (draw-solid-line (make-posn (+ (posn-x posn) 19) (+ (posn-y posn) 5)) (make-posn (+ (posn-x posn) 27) (+ (posn-y posn) 3)) color) (draw-solid-line (make-posn (+ (posn-x posn) 26) (+ (posn-y posn) 4)) (make-posn (+ (posn-x posn) 23) (+ (posn-y posn) 12)) color) (draw-solid-line (make-posn (+ (posn-x posn) 23) (+ (posn-y posn) 12)) (make-posn (+ (posn-x posn) 16) (+ (posn-y posn) 15)) color) ;tail (draw-solid-line (make-posn (+ (posn-x posn) 25) (+ (posn-y posn) 15)) (make-posn (+ (posn-x posn) 27) (+ (posn-y posn) 20)) color) (draw-solid-line (make-posn (+ (posn-x posn) 25) (+ (posn-y posn) 16)) (make-posn (+ (posn-x posn) 27) (+ (posn-y posn) 21)) color) (draw-solid-line (make-posn (+ (posn-x posn) 25) (+ (posn-y posn) 17)) (make-posn (+ (posn-x posn) 27) (+ (posn-y posn) 22)) color) (draw-solid-line (make-posn (+ (posn-x posn) 27) (+ (posn-y posn) 22)) (make-posn (+ (posn-x posn) 27) (+ (posn-y posn) 25)) color) ) )) ;;draw-exit: posn -> boolean ;;to draw a door for the exit (define (draw-exit posn) (and (draw-solid-disk (make-posn (+ (posn-x posn) 10) (posn-y posn)) 9 'brown) (draw-circle (make-posn (+ (posn-x posn) 10) (posn-y posn)) 10 'black) (draw-solid-rect posn 20 20 'brown) (draw-solid-line (make-posn (posn-x posn) (- (posn-y posn) 2)) (make-posn (posn-x posn) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 3) (- (posn-y posn) 5)) (make-posn (+ (posn-x posn) 3) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 6) (- (posn-y posn) 9)) (make-posn (+ (posn-x posn) 6) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 9) (- (posn-y posn) 10)) (make-posn (+ (posn-x posn) 9) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 12) (- (posn-y posn) 9)) (make-posn (+ (posn-x posn) 12) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 15) (- (posn-y posn) 7)) (make-posn (+ (posn-x posn) 15) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 18) (- (posn-y posn) 5)) (make-posn (+ (posn-x posn) 18) (+ (posn-y posn) 19))) (draw-solid-line (make-posn (+ (posn-x posn) 20) (- (posn-y posn) 2)) (make-posn (+ (posn-x posn) 20) (+ (posn-y posn) 19))) ) ) ;;These are helper functions for the draw-monster(x) functions ;;Used because the draw-map-objects functions only takes one parameter (define (draw-monster1-black posn) (draw-monster1 posn 'black)) (define (draw-monster1-brown posn) (draw-monster1 posn 'brown)) (define (draw-monster2-green posn) (draw-monster2 posn 'green)) (define (draw-monster2-red posn) (draw-monster2 posn 'red)) (define (draw-monster3-purple posn) (draw-monster3 posn 'purple)) ;contract: clear-monster : posn -> true ;this function clears the image of a monster at the given position. ;definition: (define (clear-monster inputposn) (local ((define posn (make-posn (- (posn-x inputposn) 14) (- (posn-y inputposn) 14)))) (draw-solid-rect posn 29 29 'white) )) ;ITEMS ;this structure represents an item in the game. it consists of a data number and a name which is a string. the data number is used for calculations. the name is used for display in lists that the player chooses from. (define-struct item (number name)) ;Global Variables ;this is the item currently being used by the player for a particular event. (define item-weilded "starting value for item-weilded") ;the list of items owned by player. (define items-owned (list (make-item 0 "Sword") )) ;Functions ;this function takes a list of items and makes it into a list of strings which are the names of the items. this is used to modify the list of items-owned for use by the get-choice function. (define (item-list-to-string list-of-items) (map item-name list-of-items) ) ;this function is kind of the reverse of item-list-to-string except it works for one item. given an item name, it returns the corresponding item structure. (define (string-to-item input-name) (first (filter (lambda (x) (string=? (item-name x) input-name)) items-owned)) ) ;this function takes an item and adds it to the list of items owned. (define (give-item input-item) (set! items-owned (cons input-item items-owned)) ) ;tests: ;EVENTS ;this structure is used to match events and their corresponding positions on the map. ;encounter is a function that runs different hings like text. ;position is the map position of the event. ;status is a global variable that represents that status of the event. ;type is a tag used to match an event with it's picture. (define-struct event (encounter position status type)) ;this function takes an event-encounter and runs it (define (encounter-executor input-encounter) (input-encounter null) ) ;this function runs an event function if that event function's position matches character-position (define (event-checker null) (local ((define encounters-at-player-location (map event-encounter (filter (lambda (x) (map-position=? (event-position x) character-position)) event-list))) (define (recursive-function input-list) (cond [(empty? input-list) empty] [else (begin (encounter-executor (first input-list)) (recursive-function (rest input-list)) )] ))) (recursive-function encounters-at-player-location) ) ) ;this function displays a message and prompts the player choose from among their owned items. the choice is stored in item-weilded. (define (pick-an-item message) (set! item-weilded (string-to-item (get-choice message (item-list-to-string items-owned)))) ) ;the following are encounter definitions ;they execute a series of commands based on event-status ;Monsters ;Slime Monster (define (slime-monster-encounter null) (begin (cond [(<= player-hp 0) true] [(= 0 (event-status slime-monster)) (begin (set! monster-hp 20) (set-event-status! slime-monster 1) (slime-monster-encounter null))] [(= 1 (event-status slime-monster)) (cond [(<= monster-hp 0) (begin (give-message "The slime monster has been killed!" standard-delay) (set-event-status! slime-monster 2) (slime-monster-encounter null))] [else (begin (give-message "You see a green slime monster." standard-delay) (pick-an-item "Which item will you use?") (cond [(= 2 (item-number item-weilded)) (begin (give-message "The slime monster attacks!" standard-delay) (change-player-hp (+ 3 (random 3))) (give-message "You attacked with a torch" standard-delay) (give-message "The slime monster catches fire." standard-delay) (change-monster-hp (+ 10 (random 10))) (slime-monster-encounter null) )] [(= 0 (item-number item-weilded)) (begin (give-message "The slime reforms itself around your sword." standard-delay) (change-monster-hp (random 4)) (give-message "The slime monster attacks!" standard-delay) (change-player-hp (+ 10 (random 11))) (slime-monster-encounter null) )] [else (begin (give-message "There was no effect! The slime monster attacks!" standard-delay) (change-player-hp (+ 3 (random 3))) (slime-monster-encounter null) )] ) )])] [(= 2 (event-status slime-monster)) (begin (give-message "There is green slime residue on the floor." standard-delay) )] ) ) ) ;Skeleton (define (skeleton-encounter null) (begin (cond [(= 0 (event-status skeleton)) (begin (set! monster-hp 50) (set-event-status! skeleton 1) (skeleton-encounter null) )] [(<= player-hp 0) true] [(= 1 (event-status skeleton)) (cond [(<= monster-hp 0) (begin (give-message "The skeleton has been killed!" standard-delay) (set-event-status! skeleton 2) (skeleton-encounter null) )] [else (begin (give-message "You see a skeleton." standard-delay) (pick-an-item "Which item will you use?") (cond [(= 0 (item-number item-weilded)) (begin (give-message "The Skeleton attacks!" standard-delay) (change-player-hp (random 5)) (give-message "You slash at the skeleton with your sword." standard-delay) (change-monster-hp (+ 8 (random 12))) (set-event-status! skeleton 1) (skeleton-encounter null) )] [else (begin (give-message "There was no effect! Skeleton attaks!" standard-delay) (change-player-hp (+ 5 (random 5))) (skeleton-encounter null) )] ))] )] [(= 2 (event-status skeleton)) (begin (give-message "You see a pile of bones on the floor." standard-delay) )] )) ) ;;Riddle Master (define (riddle-master-encounter null) (begin (cond [(<= player-hp 0) true] [(= 0 (event-status riddle-master)) (begin (give-message "A Riddle Maser confronts you" standard-delay) (give-message "Answer my Riddles, or Else." standard-delay) (cond [(string=? (get-answer "I go up a chimney down, but I can't go down a chimney up. What am I?" 5) "umbrella") (begin (give-message "Correct!" standard-delay) (set-event-status! riddle-master 1) (riddle-master-encounter null) )] [else (begin (give-message "Wrong Answer! Take this!" standard-delay) (change-player-hp (+ 3 (random 3))) (riddle-master-encounter null) )] ) )] [(= 1 (event-status riddle-master)) (begin (give-message "Not bad, but can you answer this one" standard-delay) (cond [(string=? (get-answer "What Month has 28 Days?" 5) "all of them") (begin (give-message "Right Again!" standard-delay) (set-event-status! riddle-master 2) (riddle-master-encounter null) )] [else (begin (give-message "Wrong Answer! Take this!" standard-delay) (change-player-hp (+ 3 (random 3))) (riddle-master-encounter null) )] ) )] [(= 2 (event-status riddle-master)) (begin (give-message "This next one is the hardest of all!" standard-delay) (cond [(string=? (get-answer "What do I have in my pocket?" 5) "the one ring") (begin (give-message "ARGH! Your intellect is too much for me!" standard-delay) (set-event-status! riddle-master 3) (riddle-master-encounter null) )] [else (begin (give-message "Wrong Answer! Take this!" standard-delay) (change-player-hp (+ 3 (random 3))) (riddle-master-encounter null) )] ) )] [(= 3 (event-status riddle-master)) (begin (give-message "The Riddle Master is Weeping to himself" standard-delay))] ) ) ) ;Mimic (enemy that looks like a treasure chest) (define (mimic-encounter null) (begin (cond [(= 0 (event-status mimic)) (begin (set! monster-hp 60) (set-event-status! mimic 1) (mimic-encounter null) )] [(<= player-hp 0) true] [(= 1 (event-status mimic)) (cond [(<= monster-hp 0) (begin (give-message "The Mimic has been killed!" standard-delay) (set-event-status! mimic 2) (mimic-encounter null) )] [else (begin (give-message "The treasure chest was actually a Mimic!" standard-delay) (pick-an-item "Which item will you use?") (cond [(= 0 (item-number item-weilded)) (begin (give-message "You slash at the Mimic with your sword." standard-delay) (change-monster-hp (+ (random 10) 10)) (give-message "The Mimic strikes back!" standard-delay) (change-player-hp (+ 2 (random 5))) (mimic-encounter null) )] [else (begin (give-message "There was no effect! Mimic attaks!" standard-delay) (change-player-hp (+ 10 (random 5))) (mimic-encounter null) )] ))])] [(= 2 (event-status mimic)) (begin (give-message "You see an empty treasure chest." standard-delay) )] )) ) ;Gryphon (define (gryphon-encounter null) (begin (cond [(<= player-hp 0) true] [(= 0 (event-status gryphon)) (begin (set! monster-hp 50) (set-event-status! gryphon 1) (gryphon-encounter null) )] [(= 1 (event-status gryphon)) (cond [(<= monster-hp 0) (begin (give-message "The Gryphon has been killed!" standard-delay) (set-event-status! gryphon 2) (gryphon-encounter null) )] [else (begin (give-message "A Gyrphon blocks your path" standard-delay) (pick-an-item "Which item will you use?") (cond [(= 3 (item-number item-weilded)) (begin (give-message "The Gyrphon swoops down and attacks" standard-delay) (change-player-hp (+ 4 (random 8))) (give-message "You loose an arrow at the Gryphon" standard-delay) (change-monster-hp (+ 15 (random 30))) (gryphon-encounter null) )] [else (begin (give-message "The Gryphon attaks!" standard-delay) (change-player-hp (+ 5 (random 10))) (give-message "You attack the Gryphon" standard-delay) (change-monster-hp (+ 2 (random 8))) (gryphon-encounter null) )] ))])] [(= 2 (event-status gryphon)) (begin (give-message "Bloodied feathers are strewn about the room." standard-delay) )] )) ) ;Beholder (boss) (define (beholder-encounter null) (begin (cond [(<= player-hp 0) true] [(= 0 (event-status beholder)) (begin (give-message "I have awaited your coming" standard-delay) (give-message "What is Man? A Miserable little pile of secrets" standard-delay) (give-message "But enough talk. Have at You!!" standard-delay) (set-event-status! beholder 1) (beholder-encounter null) )] [(= 1 (event-status beholder)) (begin (give-message "The Beholder is Staring you down" standard-delay) (pick-an-item "Which item will you use?") (cond [(<= boss-hp 0) (begin (set-event-status! beholder 2) (beholder-encounter null) )] [(= 4 (item-number item-weilded)) (begin (give-message "The Mysterious Rune glows brightly" standard-delay) (give-message "You fire a bolt of magic!" standard-delay) (change-boss-hp (+ (random 20) 30)) (give-message "The Beholder attacks" standard-delay) (change-player-hp (+ (random 15) 8)) (beholder-encounter null) )] [else (begin (give-message "You attack the Beholder" standard-delay) (change-boss-hp (+ (random 5) 10)) (give-message "The Beholder counter-strikes" standard-delay) (change-player-hp (+ 10 (random 20))) (beholder-encounter null) )] ))] [(= 2 (event-status beholder)) (begin (give-message "You have bested me. You May Pass" standard-delay) )] )) ) ;Treasure ;Potion (define (treasure-encounter1 null) (begin (cond [(= 0 (event-status potion)) (begin (give-message "You found a potion" standard-delay) (set-event-status! potion 1) (set! items-owned (cons (make-item 1 "Potion") items-owned)) (treasure-encounter1 null) )] [(= 1 (event-status potion)) (begin (empty-encounter null) )] ) ) ) ;Torch (define (treasure-encounter2 null) (begin (cond [(= 0 (event-status torch)) (begin (give-message "You found a torch" standard-delay) (set-event-status! torch 1) (set! items-owned (cons (make-item 2 "Torch") items-owned)) (treasure-encounter2 null) )] [(= 1 (event-status torch)) (begin (empty-encounter null) )] ) ) ) ;Bow&Arrow (define (treasure-encounter3 null) (begin (cond [(= 0 (event-status bow)) (begin (give-message "You found a bow and arrow." standard-delay) (set-event-status! bow 1) (set! items-owned (cons (make-item 3 "Bow") items-owned)) (treasure-encounter3 null) )] [(= 1 (event-status bow)) (begin (empty-encounter null) )] ) ) ) ;Mysterious Rune (temporary name) (define (treasure-encounter4 null) (begin (cond [(= 0 (event-status rune)) (begin (give-message "You have discovered a Mysterious Rune." standard-delay) (set-event-status! rune 1) (set! items-owned (cons (make-item 4 "Rune") items-owned)) (treasure-encounter4 null) )] [(= 1 (event-status rune)) (begin (empty-encounter null) )] ) ) ) ;;victory (define (exit-reached null) (begin (cond [(= 0 (event-status victory)) (begin (give-message "Congratulations!" standard-delay) (give-message "After countless battles you" standard-delay) (give-message "have finally reached the exit" standard-delay) (set-event-status! victory 1) (exit-reached null))] [(= 1 (event-status victory)) (give-message "YOU WIN!!" standard-delay)] ) ) ) ;these are all event definitions ;monster event definitions (define slime-monster (make-event slime-monster-encounter (make-map-position 6 9) 0 'monster2-green)) (define skeleton (make-event skeleton-encounter (make-map-position 5 3) 0 'monster1-black)) (define riddle-master (make-event riddle-master-encounter (make-map-position 4 0) 0 'monster1-brown)) (define beholder (make-event beholder-encounter (make-map-position 9 8) 0 'monster2-red)) (define gryphon (make-event gryphon-encounter (make-map-position 0 6) 0 'monster3-purple)) (define mimic (make-event mimic-encounter (make-map-position 8 4) 0 'treasure)) ;treasure event definitions (define potion (make-event treasure-encounter1 (make-map-position 2 9) 0 'treasure)) (define torch (make-event treasure-encounter2 (make-map-position 8 5) 0 'treasure)) (define bow (make-event treasure-encounter3 (make-map-position 3 2) 0 'treasure)) (define rune (make-event treasure-encounter4 (make-map-position 7 9) 0 'treasure)) ;;victory event (define victory (make-event exit-reached (make-map-position 9 9) 0 'exit)) ;empty encounter (define (empty-encounter null) (begin (give-message "There is nothing here." standard-delay)) ) ;list of all events (define event-list (list slime-monster skeleton riddle-master beholder gryphon potion torch victory bow mimic rune )) ;the purpose of this function is to automatically create a "blank" event (consisting of empty-encounter) at each position that doesn't already have an event according to event-list. when this function is called, event-list is updated to include a blank event at each empty position. (define (fill-map-with-empty-events null) (local ( ;this is a list of all map positions that already have events according to event-list. (define map-positions-with-events (map event-position event-list)) ;is-empty-position?: map-position -> boolean ;this function checks to see if a given map position is empty by comparing it to map-positions-with-events. (define (is-empty-position? x) (local ((define (recursive-function input-list) (cond [(empty? input-list) true] [(map-position=? (first input-list) x) false] [else (recursive-function (rest input-list))] ) ) ) (recursive-function map-positions-with-events) ) ) ;this is a list of all positions that don't have events. (define list-of-empty-positions (filter is-empty-position? valid-positions)) ;empty-event-maker: posn -> list of (empty) events ;this function takes a list of map-positions and makes a list of empty events at those positions (define (empty-event-maker input-list) (cond [(empty? input-list) empty] [else (cons (make-event empty-encounter (first input-list) 0 'empty) (empty-event-maker (rest input-list)) )] ) ) ) (set! event-list (append (empty-event-maker list-of-empty-positions) event-list)) )) ;treasure-posn-converter: posn -> posn ;this function converts a posn to an offset posn so that the treasure is drawn correctly. (define (treasure-posn-converter input-posn) (make-posn (- (posn-x input-posn) 9) (- (posn-y input-posn) 9)) ) ;list-of-all-positions-maker: x-max y-max -> list of positions ;this makes a list of all positions. (define (list-of-all-positions-maker x-max y-max) (local ((define (inner-recursion y-max) (cond [(> 0 y-max) empty] [else (cons (make-map-position x-max y-max) (inner-recursion (- y-max 1)))] ) )) (cond [(> 0 x-max) empty] [else (append (inner-recursion y-max) (list-of-all-positions-maker (- x-max 1) y-max))] ) ) ) ;test: ;is-invalid-position?: map-position -> boolean ;this function is used by filter to filter a list so it contains only invalid positions (define (is-invalid-position? x) (local ((define (recursive-function input-list) (cond [(empty? input-list) true] [(map-position=? (first input-list) x) false] [else (recursive-function (rest input-list))] ) ) ) (recursive-function valid-positions) ) ) ;test: ;(filter is-invalid-position? (list-of-all-positions-maker 9 9)) ;draw-walls: posn -> boolean ;this fucntion draws walls (define (draw-walls input-position) (draw-solid-rect (make-posn (- (posn-x input-position) 14) (- (posn-y input-position) 14)) 29 29 'gray) ) ;this function draws all the objects that current exist on the map (define draw-map-objects (begin (map draw-monster1-black (map map-position-to-posn (map event-position (filter (lambda (x) (symbol=? (event-type x) 'monster1-black)) event-list)))) (map draw-monster1-brown (map map-position-to-posn (map event-position (filter (lambda (x) (symbol=? (event-type x) 'monster1-brown)) event-list)))) (map draw-monster2-green (map map-position-to-posn (map event-position (filter (lambda (x) (symbol=? (event-type x) 'monster2-green)) event-list)))) (map draw-monster2-red (map map-position-to-posn (map event-position (filter (lambda (x) (symbol=? (event-type x) 'monster2-red)) event-list)))) (map draw-monster3-purple (map map-position-to-posn (map event-position (filter (lambda (x) (symbol=? (event-type x) 'monster3-purple)) event-list)))) (map draw-treasure (map treasure-posn-converter (map map-position-to-posn (map event-position (filter (lambda (x) (symbol=? (event-type x) 'treasure)) event-list))))) (draw-exit (make-posn 275 380)) (map draw-walls (map map-position-to-posn (filter is-invalid-position? (list-of-all-positions-maker 9 9)))) ) ) ;MOVEMENT ;move-function : map-position -> ? ;purpose: asks the user to move and updates the position (define (move-function null) (begin draw-map-objects show-hp (set! current-movement (get-choice "Where do you want to go?" (list "up" "right" "down" "left"))) (clear-character (map-position-to-posn character-position)) (cond [(string=? current-movement "right") (set-map-position-x-posn! character-position (+ (map-position-x-posn character-position) 1))] [(string=? current-movement "left") (set-map-position-x-posn! character-position (- (map-position-x-posn character-position) 1))] [(string=? current-movement "up") (set-map-position-y-posn! character-position (- (map-position-y-posn character-position) 1))] [(string=? current-movement "down") (set-map-position-y-posn! character-position (+ (map-position-y-posn character-position) 1))] ) (move-validator null) (draw-character (map-position-to-posn character-position)) (event-checker null) ) ) ;move-validator : map-position -> ? ;purpose: checks the character position against a given list of valid map positions. moves the character back if they are out of bounds. (define (move-validator null) (local ((define (recursive-function input-list) (cond [(empty? input-list) (begin (give-message "You can't move out of bounds" 0) (cond [(string=? current-movement "up") (set-map-position-y-posn! character-position (+ (map-position-y-posn character-position) 1))] [(string=? current-movement "down") (set-map-position-y-posn! character-position (- (map-position-y-posn character-position) 1))] [(string=? current-movement "left") (set-map-position-x-posn! character-position (+ (map-position-x-posn character-position) 1))] [(string=? current-movement "right") (set-map-position-x-posn! character-position (- (map-position-x-posn character-position) 1))] ))] [(map-position=? character-position (first input-list)) true] [else (recursive-function (rest input-list))] ))) (recursive-function valid-positions) ) ) ;tests: ;movement-repeater ;calls move-function with sleep-for-a-while indefinitely until something special happens. (define (movement-repeater pause) (cond [(<= player-hp 0) true] [(= 1 (event-status victory)) true] [else (begin (move-function character-position) (sleep-for-a-while pause) (movement-repeater pause) ) ] ) ) ;tests: ;MESSAGES ;this variable holds the message currently being displayed. (define current-message "starting value for current-message") (define current-status-message "starting value for current-status-message") (define current-monster-message "starting value for current-monster-message") ;this function displays the given message. (define (give-message message pause-time) (begin (clear-solid-string (make-posn 20 20) current-message) (set! current-message message) (draw-solid-string (make-posn 20 20) message) (sleep-for-a-while pause-time) ) ) ;this function displays the given message as a status. (define (give-status-message message pause-time) (begin (clear-solid-string (make-posn 3 97) current-status-message) (set! current-status-message message) (draw-solid-string (make-posn 3 97) message) (sleep-for-a-while pause-time) ) ) ;this function displays the given message as a status. (define (give-monster-message message pause-time) (begin (clear-solid-string (make-posn 190 97) current-monster-message) (set! current-monster-message message) (draw-solid-string (make-posn 190 97) current-monster-message) (sleep-for-a-while pause-time) ) ) (define show-hp (give-status-message (string-append "Your health is " (number->string player-hp)) 0)) ;start of the game ;drawing the canvas draw-map (draw-character (map-position-to-posn character-position)) ;this fills all otherwise empty map spaces with blank events (fill-map-with-empty-events null) ;this basically runs the game indefinitely (movement-repeater 0)