001 (ns the-great-game.merchants.merchant-utils
002 "Useful functions for doing low-level things with merchants.")
003
004 (defn expected-price
005 "Find the price anticipated, given this `world`, by this `merchant` for
006 this `commodity` in this `city`. If no information, assume 1.
007 `merchant` should be passed as a map, `commodity` and `city` should be passed as keywords."
008 [merchant commodity city]
009 (or
010 (:price
011 (last
012 (sort-by
013 :date
014 (-> merchant :known-prices city commodity))))
015 1))
016
017 (defn burden
018 "The total weight of the current cargo carried by this `merchant` in this
019 `world`."
020 [merchant world]
021 (let [m (cond
022 (keyword? merchant)
023 (-> world :merchants merchant)
024 (map? merchant)
025 merchant)
026 cargo (:stock m)]
027 (reduce
028 +
029 0
030 (map
031 #(* (cargo %) (-> world :commodities % :weight))
032 (keys cargo)))))
033
034
035 (defn can-carry
036 "Return the number of units of this `commodity` which this `merchant`
037 can carry in this `world`, given their current burden."
038 [merchant world commodity]
039 (let [m (cond
040 (keyword? merchant)
041 (-> world :merchants merchant)
042 (map? merchant)
043 merchant)]
044 (quot
045 (- (:capacity m) (burden m world))
046 (-> world :commodities commodity :weight))))
047
048 (defn can-afford
049 "Return the number of units of this `commodity` which this `merchant`
050 can afford to buy in this `world`."
051 [merchant world commodity]
052 (let [m (cond
053 (keyword? merchant)
054 (-> world :merchants merchant)
055 (map? merchant)
056 merchant)
057 l (:location m)]
058 (quot
059 (:cash m)
060 (-> world :cities l :prices commodity))))
061
062 (defn add-stock
063 "Where `a` and `b` are both maps all of whose values are numbers, return
064 a map whose keys are a union of the keys of `a` and `b` and whose values
065 are the sums of their respective values."
066 [a b]
067 (reduce
068 merge
069 a
070 (map
071 #(hash-map % (+ (or (a %) 0) (or (b %) 0)))
072 (keys b))))
073
074 (defn add-known-prices
075 "Add the current prices at this `merchant`'s location in the `world`
076 to a new cacke of known prices, and return it."
077 [merchant world]
078 (let [m (cond
079 (keyword? merchant)
080 (-> world :merchants merchant)
081 (map? merchant)
082 merchant)
083 k (:known-prices m)
084 l (:location m)
085 d (:date world)
086 p (-> world :cities l :prices)]
087 (reduce
088 merge
089 k
090 (map
091 #(hash-map % (apply vector cons {:price (p %) :date d} (k %)))
092 (-> world :commodities keys)))))