summaryrefslogtreecommitdiffstats
path: root/eight/orc.rkt
diff options
context:
space:
mode:
authorrsiddharth <s@ricketyspace.net>2020-07-03 15:49:09 -0400
committerrsiddharth <s@ricketyspace.net>2020-07-03 15:49:09 -0400
commit9d23e66fe8332abc7a1bbd9022f3e58e1133b3fb (patch)
tree5bf435cd979dcb785624d43c75f379ae684f97e3 /eight/orc.rkt
parent0f072be231d0bd875d1c87ff127834e60979263a (diff)
name directories like the realm repo.
Diffstat (limited to 'eight/orc.rkt')
-rw-r--r--eight/orc.rkt943
1 files changed, 0 insertions, 943 deletions
diff --git a/eight/orc.rkt b/eight/orc.rkt
deleted file mode 100644
index f00d587..0000000
--- a/eight/orc.rkt
+++ /dev/null
@@ -1,943 +0,0 @@
-#lang racket
-
-#|
-
- From github.com/racket/realm
-
- With some trivial changes.
-
- Commit: 973041cb6a5c696b99b79a
-|#
-
-#|
- The Orc game
- -------------
-
- The Orc game is a turn-based battle game between monsters and the player.
-
- The player encounters a room full of monsters of all kinds, including
- orcs, hydras, hydrars, slimes, and brigands. They are ready to attack. It is
- the player's task to get rid of the monsters.
-
- When the game starts up, it is the player's turn, meaning she is given
- permission to attack a (randomly chosen number) of times. The player uses
- nine keys to play
- -- With the four arrow keys the player navigates among the twelve monsters.
- -- With "s", "f", "h", and "m"
- -- the player can 's'tab a specific monster,
- -- the player may 'f'lail at several monsters;
- -- the player may 'h'eal herself.
- -- the player may 'm'asturbate for a change.
- -- the player may 'b'lock to gain armor.
- When the player runs out of attacks, all live monsters attack the player.
- After that, it is the player's turn again.
-
- Just in case, the player can end a turn prematurely with "e".
-
- Play
- ----
-
- Run and evaluate
- (start-game)
- This will pop up a window that displays the player's vitals, the orcs and
- their basic state, and the game instructions.
-|#
-
-
-(require 2htdp/image 2htdp/universe)
-
-;
-;
-;
-; ;;; ;;; ;;; ;; ;;
-; ; ; ; ; ; ;
-; ; ; ;; ;;; ;;; ; ; ; ;;;; ;; ;;; ; ;;; ;
-; ; ; ;; ;; ;; ; ; ; ; ; ;; ; ; ;;
-; ; ; ; ; ; ; ; ; ; ; ; ; ;
-; ; ; ; ; ; ; ; ; ; ; ; ; ;
-; ; ; ; ; ; ; ; ; ; ; ; ; ; ;;
-; ;;; ;;;;; ;;;; ; ; ;;;; ;;;;; ;;;;; ;;; ;;
-;
-;
-;
-;
-
-;; The OrcWorld as Data:
-(struct orc-world (player lom attack# target) #:transparent #:mutable)
-;; A OrcWorld is a (orc-world Player [listof Monster] Nat Nat)
-;; The third field of the world refers to the number of attacks left.
-;; The fourth field refers to the position of the next attack target.
-
-(struct player (health agility strength armor) #:transparent #:mutable)
-;; A Player is a (player Nat Nat Nat Nat)
-;; The player's fields correspond to hit points, strength, agility, armor.
-
-(struct monster (image [health #:mutable]) #:transparent)
-(struct orc monster (club) #:transparent)
-(struct hydra monster () #:transparent)
-(struct hydrar monster () #:transparent)
-(struct slime monster (sliminess) #:transparent)
-(struct brigand monster () #:transparent)
-;; A Monster is a (monster Image Nat)
-;; (moster i h) is a monster at position i in the list with health h
-;; Each monster is equipped with the index number,
-;; which is used to identify the current target.
-;;
-;; An Orc is an (orc Nat Nat Nat)
-;; A Slime is a (slime Nat Nat Nat)
-;; A Brigrand is a (brigand Nat Nat)
-;; A Hydra is a (hydra Nat Nat)
-;; A Hydrar is a (hydrar Nat Nat)
-;;
-;; The four monster types all inherit the id and health fields from monster.
-;; Two have additional attributes:
-;; -- (orc i h c) means the orc's club has strength c
-;; -- (slime i h a) means the slime can reduce the player's agility by a
-
-;; -----------------------------------------------------------------------------
-;; THE CONSTANTS IN THE WORLD
-
-;; player attributes
-(define MAX-HEALTH 35)
-(define MAX-AGILITY 35)
-(define MAX-STRENGTH 35)
-(define MAX-ARMOR 35)
-
-;; depending on other player attributes,
-;; the game picks the number of attacks, flailing and stabbing damage
-(define ATTACKS# 4)
-(define STAB-DAMAGE 2)
-(define FLAIL-DAMAGE 3)
-(define MASTURBATE-DAMAGE 5)
-(define HEALING 8)
-(define BLOCK 8)
-
-;; monster attributes
-(define MONSTER# 12)
-(define PER-ROW 4)
-(unless (zero? (remainder MONSTER# PER-ROW))
- (error 'constraint "PER-ROW must divide MONSTER# evenly into rows"))
-
-(define MONSTER-HEALTH0 9)
-(define CLUB-STRENGTH 8)
-(define SLIMINESS 5)
-
-(define HEALTH-DAMAGE -2)
-(define AGILITY-DAMAGE -3)
-(define STRENGTH-DAMAGE -4)
-
-;; string constants
-(define STRENGTH "strength")
-(define AGILITY "agility")
-(define HEALTH "health")
-(define ARMOR "armor")
-(define LOSE "YOU LOSE")
-(define WIN "YOU WIN")
-(define DEAD "DEAD")
-(define REMAINING "Remaining attacks ")
-(define INSTRUCTIONS-2 "Select a monster using the arrow keys")
-(define INSTRUCTIONS-1
- (string-append "Press S to stab a monster | Press F to Flail wildly "
- "| Press H to Heal | Press M to Masturbate"))
-
-;; graphical constants
-(define HEALTH-BAR-HEIGHT 12)
-(define HEALTH-BAR-WIDTH 50)
-
-;; compute constants for image frames
-(define ORC (bitmap "graphics/orc.png"))
-(define HYDRA (bitmap "graphics/hydra.png"))
-(define HYDRAR (bitmap "graphics/hydrar.png"))
-(define SLIME (bitmap "graphics/slime.bmp"))
-(define BRIGAND (bitmap "graphics/brigand.bmp"))
-
-(define PIC-LIST (list ORC HYDRA HYDRAR SLIME BRIGAND))
-(define w (apply max (map image-width PIC-LIST)))
-(define h (apply max (map image-height PIC-LIST)))
-
-;; images: player, monsters, constant texts
-(define PLAYER-IMAGE (bitmap "graphics/player.bmp"))
-
-(define FRAME (rectangle w h 'outline 'white))
-(define TARGET (circle (- (/ w 2) 2) 'outline 'blue))
-
-(define ORC-IMAGE (overlay ORC FRAME))
-(define HYDRA-IMAGE (overlay HYDRA FRAME))
-(define HYDRAR-IMAGE (overlay HYDRAR FRAME))
-(define SLIME-IMAGE (overlay SLIME FRAME))
-(define BRIGAND-IMAGE (overlay BRIGAND FRAME))
-
-(define V-SPACER (rectangle 0 10 "solid" "white"))
-(define H-SPACER (rectangle 10 0 "solid" "white"))
-
-;; fonts & texts & colors
-(define AGILITY-COLOR "blue")
-(define HEALTH-COLOR "crimson")
-(define STRENGTH-COLOR "forest green")
-(define ARMOR-COLOR "goldenrod")
-(define MONSTER-COLOR "crimson")
-(define MESSAGE-COLOR "black")
-(define ATTACK-COLOR "crimson")
-
-(define HEALTH-SIZE (- HEALTH-BAR-HEIGHT 4))
-(define DEAD-TEXT-SIZE (- HEALTH-BAR-HEIGHT 2))
-(define INSTRUCTION-TEXT-SIZE 16)
-(define MESSAGES-SIZE 40)
-
-(define INSTRUCTION-TEXT
- (above
- (text INSTRUCTIONS-2 (- INSTRUCTION-TEXT-SIZE 2) "blue")
- (text INSTRUCTIONS-1 (- INSTRUCTION-TEXT-SIZE 4) "blue")))
-
-(define DEAD-TEXT (text DEAD DEAD-TEXT-SIZE "crimson"))
-
-;
-;
-;
-; ;;; ;;; ;
-; ;; ;;
-; ;; ;; ;;;; ;;; ;; ;;
-; ; ; ; ; ; ; ;; ;
-; ; ; ; ;;;;; ; ; ;
-; ; ; ; ; ; ; ;
-; ; ; ; ;; ; ; ;
-; ;;; ;;; ;;; ;; ;;;;; ;;; ;;;
-;
-;
-;
-;
-
-;; Start the game
-(define (start-game)
- (big-bang (initialize-orc-world)
- (on-key player-acts-on-monsters)
- (to-draw render-orc-battle)
- (stop-when end-of-orc-battle? render-the-end)))
-
-;; -> OrcWorld
-;; creates an orc-world ready for battling orcs
-(define (initialize-orc-world)
- (define player0 (initialize-player))
- (define lom0 (initialize-monsters))
- (orc-world player0 lom0 (random-number-of-attacks player0) 0))
-
-;; OrcWorld Key-Event -> OrcWorld
-;; act on key events by the player, if the player has attacks left
-(define (player-acts-on-monsters w k)
- (cond
- [(zero? (orc-world-attack# w)) w]
-
- [(key=? "s" k) (stab w)]
- [(key=? "h" k) (heal w)]
- [(key=? "f" k) (flail w)]
- [(key=? "m" k) (masturbate w)]
- [(key=? "b" k) (block w)]
-
- [(key=? "right" k) (move-target w +1)]
- [(key=? "left" k) (move-target w -1)]
- [(key=? "down" k) (move-target w (+ PER-ROW))]
- [(key=? "up" k) (move-target w (- PER-ROW))]
-
- [(key=? "e" k) (end-turn w)]
-;; [(key=? "n" k) (initialize-orc-world)]
-
- [else w])
- (give-monster-turn-if-attack#=0 w)
- w)
-
-;; OrcWorld -> Image
-;; renders the orc world
-(define (render-orc-battle w)
- (render-orc-world w (orc-world-target w) (instructions w)))
-
-;; OrcWorld -> Boolean
-;; is the battle over? i.e., the player lost or all monsters are dead
-(define (end-of-orc-battle? w)
- (or (win? w) (lose? w)))
-
-;; OrcWorld -> Image
-;; render the final orc world
-(define (render-the-end w)
- (render-orc-world w #f (message (if (lose? w) LOSE WIN))))
-
-;; -----------------------------------------------------------------------------
-
-;; WORLD MANAGEMENT
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;
-;
-;
-; ;;;;; ;
-; ; ;
-; ; ;; ;; ;;; ;;;;;
-; ; ;; ; ; ;
-; ; ; ; ; ;
-; ; ; ; ; ;
-; ; ; ; ; ; ;
-; ;;;;; ;;; ;;; ;;;;; ;;;
-;
-;
-;
-;
-
-;; -> Player
-;; create a player with maximal capabilities
-(define (initialize-player)
- (player MAX-HEALTH MAX-AGILITY MAX-STRENGTH 0))
-
-;; -> [Listof Monster]
-;; create a list of random monsters of length MONSTER-NUM,
-(define (initialize-monsters)
- ;; Nat -> Monster
- ;; makes a random monster
- (define (create-monster _)
- (define health (random+ MONSTER-HEALTH0))
- (case (random 4)
- [(0) (orc ORC-IMAGE health (random+ CLUB-STRENGTH))]
- [(1) (hydra HYDRA-IMAGE health)]
- [(2) (hydrar HYDRAR-IMAGE health)]
- [(3) (slime SLIME-IMAGE health (random+ SLIMINESS))]
- [(4) (brigand BRIGAND-IMAGE health)]
- [else (error "can't happen")]))
- (build-list MONSTER# create-monster))
-
-;; Player -> Nat
-;; compute a feasible number of attacks the player may execute
-(define (random-number-of-attacks p)
- (random-quotient (player-agility p)
- ATTACKS#))
-
-;
-;
-;
-; ;;; ;;; ;;;;;;
-; ; ; ; ; ;
-; ; ; ;;;; ;;; ;;; ; ; ;;; ;;; ;;;; ;; ;; ;;;;; ;;;;;
-; ; ; ; ; ; ; ;;; ; ; ; ; ;; ; ; ; ;
-; ;;; ;;;;;; ; ; ; ; ; ; ;;;;;; ; ; ; ;;;;
-; ; ; ; ; ; ; ; ; ; ; ; ; ;
-; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ;
-; ;;; ;; ;;;;; ; ;;;;;; ;; ;;;;; ;;; ;;; ;;; ;;;;;
-; ;
-; ;;;
-;
-;
-
-;; -----------------------------------------------------------------------------
-;; player actions
-
-;; OrcWorld Nat -> Void
-;; Effect: reduces the target by a given amount
-;; > (move-target
-;; (orc-world (player 5 5 5) (list (monster 0 2) (monster 1 3)) 1 0)
-;; 1)
-;; (orc-world (player 5 5 5) (list (monster 0 2) (monster 1 3)) 1 1)
-(define (move-target w n)
- (set-orc-world-target! w (modulo (+ n (orc-world-target w)) MONSTER#)))
-
-;; OrcWorld -> Void
-;; Effect: ends the player's turn by setting the number of attacks to 0
-(define (end-turn w)
- (set-orc-world-attack#! w 0))
-
-;; OrcWorld -> Void
-;; Effect: reduces the number of remaining attacks for this turn
-;; and increases the player's health level
-(define (heal w)
- (decrease-attack# w)
- (player-health+ (orc-world-player w) HEALING))
-
-;; OrcWorld -> Void
-(define (block w)
- (decrease-attack# w)
- (player-armor+ (orc-world-player w) BLOCK))
-
-;; OrcWorld -> Void
-;; Effect: reduces a targeted monster's health
-(define (stab w)
- (decrease-attack# w)
- (define target (current-target w))
- (define damage
- (random-quotient (player-strength (orc-world-player w))
- STAB-DAMAGE))
- (damage-monster target damage))
-
-;; OrcWorld -> Void
-;; Effect: damages a random number of live monsters,
-;; determined by strength of the player
-;; starting with the currently targeted monster
-(define (flail w)
- (decrease-attack# w)
- (define target (current-target w))
- (define alive (filter monster-alive? (orc-world-lom w)))
- (define pick#
- (min
- (random-quotient (player-strength (orc-world-player w))
- FLAIL-DAMAGE)
- (length alive)))
- (define getem (cons target (take alive pick#)))
- (for-each (lambda (m) (damage-monster m 1)) getem))
-
-;; OrcWorld -> Void
-
-;; Effect: reduces player agility by x and 2x damages a random number
-;; of live monsters
-(define (masturbate w)
- (decrease-attack# w)
- (define alive (filter monster-alive? (orc-world-lom w)))
- (define x (random-quotient (player-strength (orc-world-player w))
- MASTURBATE-DAMAGE))
- (define pick# (min x (length alive)))
- (define getem (take alive pick#))
- (player-agility+ (orc-world-player w) (- x))
- (for-each (lambda (m) (damage-monster m (* 2 x))) getem))
-
-;; OrcWorld -> Void
-;; Effect: decrease number of remaining attacks
-(define (decrease-attack# w)
- (set-orc-world-attack#! w (sub1 (orc-world-attack# w))))
-
-;; Monster Nat -> Void
-;; Effect: reduces the hit-strength of a monster
-(define (damage-monster m delta)
- (set-monster-health! m (interval- (monster-health m) delta)))
-
-;; World -> Monster
-(define (current-target w)
- (list-ref (orc-world-lom w) (orc-world-target w)))
-
-;; -----------------------------------------------------------------------------
-;; monster action
-
-;; OrcWorld -> Void
-;; if it is the monsters turn, they attack
-;; > (orc-world (player 4 4 4) empty 3 3)
-;; (orc-world (player 4 4 4) empty 3 3)
-(define (give-monster-turn-if-attack#=0 w)
- (when (zero? (orc-world-attack# w))
- (define player (orc-world-player w))
- (all-monsters-attack-player player (orc-world-lom w))
- (set-orc-world-attack#! w (random-number-of-attacks player))))
-
-;; Player [Listof Monster] -> Void
-;; Each monster attacks the player
-(define (all-monsters-attack-player player lom)
- ;; Monster -> Void
- (define (one-monster-attacks-player monster)
- (define armor (player-armor player))
- (define block (cond
- [(zero? armor) 0]
- [else (random+ armor)]))
- ;; block buffers the damage
- (define (damage d)
- (+ d block))
- ;; reduce player's armor by block
- (player-armor+ player (* -1 block))
- (cond
- [(orc? monster)
- (player-health+ player (damage (random- (orc-club monster))))]
- [(hydra? monster)
- (player-health+ player (damage (random- (monster-health monster))))]
- [(hydrar? monster)
- (player-health+ player (random- (monster-health monster)))]
- [(slime? monster)
- (player-health+ player (damage -1))
- (player-agility+ player (damage (random- (slime-sliminess monster))))]
- [(brigand? monster)
- (case (random 3)
- [(0) (player-health+ player (damage HEALTH-DAMAGE))]
- [(1) (player-agility+ player (damage AGILITY-DAMAGE))]
- [(2) (player-strength+ player (damage STRENGTH-DAMAGE))])]))
- ;; -- IN --
- (for-each one-monster-attacks-player (filter monster-alive? lom)))
-
-;; -----------------------------------------------------------------------------
-;; actions on player
-
-;; [Player -> Nat] [Player Nat -> Void] Nat -> Player Nat -> Void
-;; effect: change player's selector attribute by adding delta, but max out
-(define (player-update! setter selector max-value)
- (lambda (player delta)
- (setter player
- (interval+ (selector player) delta max-value))))
-
-;; Player Nat -> Void
-(define player-health+
- (player-update! set-player-health! player-health MAX-HEALTH))
-
-;; Player Nat -> Void
-(define player-agility+
- (player-update! set-player-agility! player-agility MAX-AGILITY))
-
-;; Player Nat -> Void
-(define player-strength+
- (player-update! set-player-strength! player-strength MAX-STRENGTH))
-
-;; Player Nat -> Void
-(define player-armor+
- (player-update! set-player-armor! player-armor MAX-ARMOR))
-
-;
-;
-;
-; ;;;;; ;; ;
-; ; ; ;
-; ; ; ;;;; ;; ;; ;;; ; ;;;; ;; ;;; ;;; ;; ;; ;;; ;;
-; ; ; ; ; ;; ; ; ;; ; ; ;; ; ;; ; ; ;;
-; ;;;; ;;;;;; ; ; ; ; ;;;;;; ; ; ; ; ; ;
-; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
-; ; ; ; ; ; ; ;; ; ; ; ; ; ; ;;
-; ;;; ; ;;;;; ;;; ;;; ;;; ;; ;;;;; ;;;;; ;;;;; ;;; ;;; ;;; ;
-; ;
-; ;;;;
-;
-;
-
-;; OrcWorld Boolean Image -> Image
-;; draws all the monsters and the player, then adds message
-(define (render-orc-world w with-target additional-text)
- (define i-player (render-player (orc-world-player w)))
- (define i-monster (render-monsters (orc-world-lom w) with-target))
- (above V-SPACER
- (beside H-SPACER
- i-player
- H-SPACER H-SPACER H-SPACER
- (above i-monster
- V-SPACER V-SPACER V-SPACER
- additional-text)
- H-SPACER)
- V-SPACER))
-
-;; Player -> Image
-;; render player with three status bars
-(define (render-player p)
- (above/align
- "left"
- (status-bar (player-strength p) MAX-STRENGTH STRENGTH-COLOR STRENGTH)
- V-SPACER
- (status-bar (player-agility p) MAX-AGILITY AGILITY-COLOR AGILITY)
- V-SPACER
- (status-bar (player-health p) MAX-HEALTH HEALTH-COLOR HEALTH)
- V-SPACER
- (status-bar (player-armor p) MAX-ARMOR ARMOR-COLOR ARMOR)
- V-SPACER V-SPACER V-SPACER
- PLAYER-IMAGE))
-
-;; Nat Nat Color String -> Image
-;; creates a labeled rectangle of width/max proportions
-;; assume: (<= width max)
-(define (status-bar v-current v-max color label)
- (define w (* (/ v-current v-max) HEALTH-BAR-WIDTH))
- (define f (rectangle w HEALTH-BAR-HEIGHT 'solid color))
- (define b (rectangle HEALTH-BAR-WIDTH HEALTH-BAR-HEIGHT 'outline color))
- (define bar (overlay/align 'left 'top f b))
- (beside bar H-SPACER (text label HEALTH-SIZE color)))
-
-;; String -> Image
-(define (message str)
- (text str MESSAGES-SIZE MESSAGE-COLOR))
-
-;; OrcWorld -> Image
-(define (instructions w)
- (define na (number->string (orc-world-attack# w)))
- (define ra (string-append REMAINING na))
- (above (text ra INSTRUCTION-TEXT-SIZE ATTACK-COLOR) INSTRUCTION-TEXT))
-
-;; [Listof Monster] [Opt Nat] -> Image
-;; add all monsters on lom, including status bar
-;; label the target unless it isn't called for
-(define (render-monsters lom with-target)
- ;; the currently targeted monster (if needed)
- (define target
- (if (number? with-target)
- (list-ref lom with-target)
- 'a-silly-symbol-that-cannot-be-eq-to-an-orc))
-
- ;; Monster -> Image
- (define (render-one-monster m)
- (define image
- (if (eq? m target)
- (overlay TARGET (monster-image m))
- (monster-image m)))
- (define health (monster-health m))
- (define health-bar
- (if (= health 0)
- (overlay DEAD-TEXT (status-bar 0 1 'white ""))
- (status-bar health MONSTER-HEALTH0 MONSTER-COLOR "")))
- (above health-bar image))
-
- (arrange (map render-one-monster lom)))
-
-;; [Listof Image] -> Image
-;; break a list of images into rows of PER-ROW
-(define (arrange lom)
- (cond
- [(empty? lom) empty-image]
- [else (define row-image (apply beside (take lom PER-ROW)))
- (above row-image (arrange (drop lom PER-ROW)))]))
-
-
-;
-;
-;
-; ;;;;;; ;; ;;;
-; ; ; ; ; ;
-; ; ; ;; ;; ;;; ; ;
-; ;;; ;; ; ; ;; ;
-; ; ; ; ; ; ; ;
-; ; ; ; ; ; ;
-; ; ; ; ; ; ;;
-; ;;;;;; ;;; ;;; ;;; ;; ;;
-;
-;
-;
-;
-
-;; OrcWorld -> Boolean
-;; Has the player won?
-;; > (orc-world (player 1 1 1) (list (monster 0 0)) 0 0)
-;; #t
-(define (win? w)
- (all-dead? (orc-world-lom w)))
-
-;; OrcWorld -> Boolean
-;; Has the player lost?
-;; > (lose? (orc-world (player 0 2 2) empty 0 0))
-;; #t
-(define (lose? w)
- (player-dead? (orc-world-player w)))
-
-;; Player -> Boolean
-;; Is the player dead?
-;; > (orc-world (player 1 0 1) empty 0 0)
-;; #t
-(define (player-dead? p)
- (or (= (player-health p) 0)
- (= (player-agility p) 0)
- (= (player-strength p) 0)))
-
-;; [Listof Monster] -> Boolean
-;; Are all the monsters in the list dead?s
-;; > (all-dead? (orc-world (player 5 5 5) (list (monster 1 0)) 0 1))
-;; #t
-(define (all-dead? lom)
- (not (ormap monster-alive? lom)))
-
-;; Monster -> Boolean
-;; Is the monster alive?
-(define (monster-alive? m)
- (> (monster-health m) 0))
-
-
-;
-;
-;
-; ;;
-; ;
-; ; ; ;; ;; ;; ;; ;;;;;
-; ; ; ; ; ; ; ; ;
-; ; ; ; ; ;; ;;;;
-; ;;; ; ; ;; ;
-; ; ; ; ;; ; ; ; ;
-; ;;; ;;; ;; ;; ;; ;; ;;;;;
-;
-;
-;
-;
-
-;; Nat Nat -> Nat
-;; a random number between 1 and the (quotient x y)
-(define (random-quotient x y)
- (define div (quotient x y))
- (if (> 0 div) 0 (random+ (add1 div))))
-
-;; Nat -> Nat
-;; (random+ n) creates a random number in [1,n]
-(define (random+ n)
- (add1 (random n)))
-
-;; Nat -> Nat
-;; (random+ n) creates a random number in [-n,-1]
-(define (random- n)
- (- (add1 (random n))))
-
-;; Nat Nat [Nat] -> Nat
-;; subtract n from m but stay in [0,max-value]
-(define (interval- n m (max-value 100))
- (min (max 0 (- n m)) max-value))
-
-;; Nat Nat [Nat] -> Nat
-;; subtract n from m but stay in [0,max-value]
-(define (interval+ n m (max-value 100))
- (interval- n (- m) max-value))
-
-;
-;
-;
-; ;;;;;;
-; ; ; ;
-; ; ;;;; ;;;;; ;;;;; ;;;;;
-; ; ; ; ; ; ; ; ;
-; ; ;;;;;; ;;;; ; ;;;;
-; ; ; ; ; ;
-; ; ; ; ; ; ; ; ;
-; ;;; ;;;;; ;;;;; ;;; ;;;;;
-;
-;
-;
-;
-
-(module+ test
-
- (require rackunit rackunit/text-ui)
-
- ;; Test structs
- (define WORLD0 (orc-world (initialize-player) empty 0 0))
- (define WORLD1 (struct-copy orc-world (initialize-orc-world) [attack# 5]))
- (define (WORLD2) (struct-copy orc-world (initialize-orc-world) [attack# 0]))
- ;; these are random worlds
- (define AN-ORC (orc 'image 0 5))
- (define A-SLIME (slime 'image 1 6))
- (define A-HYDRA (hydra 'image 2))
- (define A-BRIGAND (brigand 'image 3))
-
- ;; testing move-target
-
- (check-equal? (let ([w (orc-world 'dummy 'dummy 'dummy 0)])
- (move-target w +1)
- w)
- (orc-world 'dummy 'dummy 'dummy 1))
- (check-equal? (let ([w (orc-world 'dummy 'dummy 'dummy 0)])
- (move-target w -1)
- w)
- (orc-world 'dummy 'dummy 'dummy (- MONSTER# 1)))
- (check-equal? (let ([w (orc-world 'dummy 'dummy 'dummy 0)])
- (move-target w (- PER-ROW))
- w)
- (orc-world 'dummy 'dummy 'dummy (- MONSTER# PER-ROW)))
- (check-equal? (let ([w (orc-world 'dummy 'dummy 'dummy 1)])
- (move-target w (+ PER-ROW))
- w)
- (orc-world 'dummy 'dummy 'dummy (+ PER-ROW 1)))
- (check-equal? (begin
- (move-target WORLD1 0)
- WORLD1)
- WORLD1)
- (check-equal? (let ()
- (define w (struct-copy orc-world WORLD1))
- (move-target w 4)
- w)
- (struct-copy orc-world WORLD1 [target (+ 4 (orc-world-target WORLD1))]))
- (check-equal? (current-target WORLD1)
- (first (orc-world-lom WORLD1)))
-
- ;; testing basic player manipulations
-
- (check-equal? (let ([p (player 1 0 0 0)])
- (player-health+ p 5)
- p)
- (player 6 0 0 0))
- (check-equal? (let ([p (player 0 1 0 0)])
- (player-agility+ p 5)
- p)
- (player 0 6 0 0))
-
- (check-equal? (let ([p (player 0 0 1 0)])
- (player-strength+ p 5)
- p)
- (player 0 0 6 0))
-
- (check-equal? (let ([p (player 5 5 5 0)])
- (all-monsters-attack-player p (list (orc 'image 1 1)))
- p)
- (player 4 5 5 0))
-
- (check-equal? (let ([p (player 5 5 5 0)])
- (all-monsters-attack-player p (list (hydra 'image 1)))
- p)
- (player 4 5 5 0))
-
- (check-equal? (let ([p (player 5 5 5 0)])
- (all-monsters-attack-player p (list (slime 'image 1 1)))
- p)
- (player 4 4 5 0))
-
- (check member
- (let ([p (player 5 5 5 0)])
- (all-monsters-attack-player p (list (brigand 'image 1)))
- p)
- (list (player 3 5 5 0)
- (player 5 2 5 0)
- (player 5 5 1 0)))
-
- ;; Properties
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;; Property:
- ;; the output will always be in [1, (/ X Y)]
- (define (prop:rand-frac-range i)
- (test-begin
- (for ([i (in-range i)])
- (define x (random 4294967087))
- (define y (random 4294967087))
- (check-true (<= 1 (random-quotient x y) (add1 (/ x y)))))))
-
- ;; Property:
- ;; The number of the monsters in the list is equal to
- ;; MONSTER-NUM
- (define (prop:monster-init-length i)
- (test-begin
- (for ([i (in-range i)])
- (check-true (= MONSTER#
- (length (initialize-monsters)))))))
-
- ;; Property:
- ;; the player will have less points in at least one of its
- ;; fields
- (define (prop:monster-attack-player-dec i)
- (test-begin
- (for ([i (in-range i)])
- (define pl (player MAX-HEALTH MAX-AGILITY MAX-STRENGTH 0))
- (define mon (first (initialize-monsters)))
- (begin
- (all-monsters-attack-player pl (list mon))
- (check-true (or (< (player-health pl) MAX-HEALTH)
- (< (player-agility pl) MAX-AGILITY)
- (< (player-strength pl) MAX-STRENGTH)))))))
-
- ;; Property:
- ;; If there are monster, then the player will
- ;; have less points in at least one of its fields
- (define (prop:monsters-attack-player-dec i)
- (test-begin
- (for ([i (in-range i)])
- (define pl (player MAX-HEALTH MAX-AGILITY MAX-STRENGTH 0))
- (define monsters (initialize-monsters))
- (define wor (orc-world pl monsters 0 0))
- (begin
- (all-monsters-attack-player pl monsters)
- (check-true (or (< (player-health pl) MAX-HEALTH)
- (< (player-agility pl) MAX-AGILITY)
- (< (player-strength pl) MAX-STRENGTH)))))))
-
- ;; Property: The health of the targeted monster, m,
- ;; is less than what it was. and
- ;; [(sub1 (monster-health m)),
- ;; (- (monster-health m)
- ;; (/ (player-strength (orc-world-player w)) 2))]
- (define (prop:stab!-health i)
- (test-begin
- (for ([i (in-range i)])
- (begin (define mon (first(initialize-monsters)))
- (define ht (monster-health mon))
- (define pl (random-player))
- (define w (orc-world pl (list mon) 2 0))
- (stab w)
- (check-true (> ht (monster-health (first (orc-world-lom w)))))))))
-
- ;; random-player: -> Player
- ;; creates a random player
- (define (random-player)
- (player (add1 (random MAX-HEALTH))
- (add1 (random MAX-AGILITY))
- (add1 (random MAX-STRENGTH))
- 0))
-
- ;; testing initializers
- (prop:monster-init-length 1000)
- (check-true (monster? (first (initialize-monsters))))
- (check-true (> 10 (monster-health (first (initialize-monsters)))))
- (check-equal? (length (initialize-monsters)) MONSTER#)
- (check-equal? (length (orc-world-lom WORLD1)) MONSTER#)
- (check-true (>= (let ([p (initialize-player)])
- (player-health p))
- (let ([p (initialize-player)])
- (all-monsters-attack-player p (list AN-ORC))
- (player-health p))))
- (check-true (> (player-health (initialize-player))
- (let ([p (initialize-player)])
- (all-monsters-attack-player p (list A-HYDRA))
- (player-health p))))
- (check-true (< (let ([p (initialize-player)])
- (all-monsters-attack-player p (list A-SLIME))
- (player-agility p))
- (let ([p (initialize-player)])
- (player-agility p))))
- (check-true (let ([p (initialize-player)])
- (all-monsters-attack-player p (list A-BRIGAND))
- (or (= (player-health p)
- (- (player-health (initialize-player)) 2))
- (= (player-agility p)
- (- (player-agility (initialize-player)) 3))
- (= (player-strength p)
- (- (player-strength (initialize-player)) 4)))))
- (check-equal? (length (orc-world-lom WORLD1)) MONSTER#)
- (check-equal? (orc-world-player WORLD1) (orc-world-player WORLD1))
-
- ;; testing the-monster's attacks
-
- (prop:monster-attack-player-dec 1000)
- (prop:monsters-attack-player-dec 1000)
- (check-true (or (> (player-health (orc-world-player (WORLD2)))
- (player-health (orc-world-player
- (let ([w (WORLD2)])
- (all-monsters-attack-player (orc-world-player w) (orc-world-lom w))
- w))))
- (> (player-strength (orc-world-player (WORLD2)))
- (player-strength (orc-world-player
- (let ([w (WORLD2)])
- (all-monsters-attack-player (orc-world-player w) (orc-world-lom w))
- w))))
- (> (player-agility (orc-world-player (WORLD2)))
- (player-agility (orc-world-player
- (let ([w (WORLD2)])
- (all-monsters-attack-player (orc-world-player w) (orc-world-lom w))
- w))))))
-
- ;; testing the player's actions
-
- (prop:stab!-health 1000)
- (test-begin (define o (orc 'image 0 5))
- (damage-monster o 5)
- (check-equal? o (orc 'image 0 5)))
- (test-begin (define o (orc 'image 0 5))
- (damage-monster o 0)
- (check-equal? o (orc 'image 0 5)))
- (check-equal? (player-health (orc-world-player
- (let ()
- (define w (struct-copy orc-world WORLD1))
- (heal w)
- w)))
- (min MAX-HEALTH
- (+ 8 (player-health (orc-world-player WORLD1)))))
-
- (check-equal? (length (orc-world-lom
- (let ()
- (define w (struct-copy orc-world WORLD1))
- (stab w)
- w)))
- MONSTER#)
-
- ;; testing game predicates
-
- (check-false (lose? WORLD0))
- (check-true (lose? (orc-world (player 0 30 30 0) empty 0 0)))
- (check-true (all-dead? (list (orc 'image 0 0) (hydra 'image 0))))
- (check-true (all-dead? (list AN-ORC)))
- (check-true (win? (orc-world (initialize-player) (list (orc 'image 0 0)) 0 0)))
- (check-true (win? (orc-world (initialize-player) (list AN-ORC) 0 0)))
- (check-true (end-of-orc-battle? (orc-world (initialize-player) (list (orc 'image 0 0)) 0 0)))
- (check-true (end-of-orc-battle? (orc-world (initialize-player) (list AN-ORC) 0 0)))
- (check-true (end-of-orc-battle? (orc-world (player 0 30 30 0) empty 0 0)))
- (check-true (player-dead? (player 0 2 5 0)))
- (check-false (player-dead? (initialize-player)))
- (check-false (not (monster-alive? A-HYDRA)))
- (check-true (monster-alive? (monster 'image 1)))
- (check-false (monster-alive? (orc 'image 0 0)))
-
- ;; testing utilities
-
- (prop:rand-frac-range 1000)
-
- "all tests run")