Skip to content

Instantly share code, notes, and snippets.

@tmountain
Created January 26, 2010 20:54
Show Gist options
  • Save tmountain/287215 to your computer and use it in GitHub Desktop.
Save tmountain/287215 to your computer and use it in GitHub Desktop.
(ns combat)
(defn roll
"roll the dice (roll 1 6) => 1d6, (roll 2 6) => 2d6"
[dice max]
(apply + (for [x (range dice)] (inc (rand-int max)))))
(defn weapon-dmg
"calculates a damage roll for the given weapon"
[weapon]
(let [dice (first (:dmg weapon))
max (second (:dmg weapon))
mod (or (:modifier weapon) 0)]
(+ (roll dice max) mod)))
(defn armor-class
"calculates the total AC for the given set of armor"
[armor]
(if (empty? armor)
0
; 10 is the base AC, so subtract the gear from that
(let [armor-vals (map #(:ac %1) armor)]
(- 10 (apply + armor-vals)))))
(defn dmg-reduction
"calculates the damage reduction from the current AC"
[armor-class]
(if (< armor-class 0)
(inc (rand-int (Math/abs armor-class)))
0))
(defn hit?
"returns true if an attack hits. false if it misses
When a monster attacks you, 1d20 is rolled. Rolling a target number
or lower results in a hit. In simple situations at low levels,
this target number is equal to:
10 + your AC + the monster's level
At higher levels and in funny circumstances, things become more complex.
If your AC is negative, the formula for the target number is:
10 + (a random number from -1 to your AC) + the monster's level."
[attacker-level defender-armor-class]
(let [ac (if (< defender-armor-class 0)
(+ attacker-level
(+ 10
(- (inc (rand-int (Math/abs defender-armor-class))))))
(+ attacker-level (+ 10 defender-armor-class)))
; If the final target number is so good that it would be
; less than or equal to zero, set it to 1.
real-ac (if (< ac 0)
1
ac)]
(if (< (roll 1 20) real-ac)
true
false)))
(defn dmg [attacker-level weapon armor]
"returns the damage for an attack
weapon should be a map representing the attacker's weapon
armor is a list of maps representing the defender's armor"
(let [ac (armor-class armor)
base-dmg (weapon-dmg weapon)
net-dmg (- base-dmg (dmg-reduction ac))]
(if (hit? attacker-level ac)
(if (< net-dmg 0)
1 ; if hit, minimum damage is one
net-dmg)
0)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment