<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <link rel="stylesheet" href="../../../coverage.css"/> <title> the_great_game/merchants/strategies/simple.clj </title> </head> <body> <span class="covered" title="1 out of 1 forms covered"> 001 (ns the-great-game.merchants.strategies.simple </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 002 "Default trading strategy for merchants. </span><br/> <span class="blank" title="0 out of 0 forms covered"> 003 </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 004 The simple strategy buys a single product in the local market if there is </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 005 one which can be traded profitably, trades it to the chosen target market, </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 006 and sells it there. If there is no commodity locally which can be traded </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 007 profitably, moves towards home with no cargo. If at home and no commodity </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 008 can be traded profitably, does not move." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 009 (:require [taoensso.timbre :as l :refer [info error spy]] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 010 [the-great-game.utils :refer [deep-merge]] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 011 [the-great-game.gossip.gossip :refer [move-gossip]] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 012 [the-great-game.merchants.planning :refer :all] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 013 [the-great-game.merchants.merchant-utils :refer </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 014 [add-stock add-known-prices]] </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 015 [the-great-game.world.routes :refer [find-route]])) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 016 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 017 (defn plan-and-buy </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 018 "Return a world like this `world`, in which this `merchant` has planned </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 019 a new trade, and bought appropriate stock for it. If no profitable trade </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 020 can be planned, the merchant is simply moved towards their home." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 021 [merchant world] </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 022 (let [m (cond </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 023 (keyword? merchant) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 024 (-> world :merchants merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 025 (map? merchant) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 026 merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 027 id (:id m) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 028 location (:location m) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 029 market (-> world :cities location) </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 030 plan (select-cargo merchant world)] </span><br/> <span class="not-covered" title="0 out of 16 forms covered"> 031 (l/debug "plan-and-buy: merchant" id) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 032 (cond </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 033 (not (empty? plan)) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 034 (let </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 035 [c (:commodity plan) </span><br/> <span class="not-covered" title="0 out of 7 forms covered"> 036 p (* (:quantity plan) (:buy-price plan)) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 037 q (:quantity plan)] </span><br/> <span class="not-covered" title="0 out of 25 forms covered"> 038 (l/info "Merchant" id "bought" q "units of" c "at" location "for" p plan) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 039 {:merchants </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 040 {id </span><br/> <span class="not-covered" title="0 out of 13 forms covered"> 041 {:stock (add-stock (:stock m) {c q}) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 042 :cash (- (:cash m) p) </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 043 :known-prices (add-known-prices m world) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 044 :plan plan}} </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 045 :cities </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 046 {location </span><br/> <span class="not-covered" title="0 out of 16 forms covered"> 047 {:stock (assoc (:stock market) c (- (-> market :stock c) q)) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 048 :cash (+ (:cash market) p)}}}) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 049 ;; if no plan, then if at home stay put </span><br/> <span class="not-covered" title="0 out of 7 forms covered"> 050 (= (:location m) (:home m)) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 051 (do </span><br/> <span class="not-covered" title="0 out of 18 forms covered"> 052 (l/info "Merchant" id "remains at home in" location) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 053 {}) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 054 ;; else move towards home </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 055 :else </span><br/> <span class="not-covered" title="0 out of 8 forms covered"> 056 (let [route (find-route world location (:home m)) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 057 next-location (nth route 1)] </span><br/> <span class="not-covered" title="0 out of 20 forms covered"> 058 (l/info "No trade possible at" location "; merchant" id "moves to" next-location) </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 059 (merge </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 060 {:merchants </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 061 {id </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 062 {:location next-location}}} </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 063 (move-gossip id world next-location)))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 064 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 065 (defn re-plan </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 066 "Having failed to sell a cargo at current location, re-plan a route to </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 067 sell the current cargo. Returns a revised world." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 068 [merchant world] </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 069 (let [m (cond </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 070 (keyword? merchant) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 071 (-> world :merchants merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 072 (map? merchant) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 073 merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 074 id (:id m) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 075 location (:location m) </span><br/> <span class="not-covered" title="0 out of 13 forms covered"> 076 plan (augment-plan m world (plan-trade m world (-> m :plan :commodity)))] </span><br/> <span class="not-covered" title="0 out of 16 forms covered"> 077 (l/debug "re-plan: merchant" id) </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 078 (deep-merge </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 079 world </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 080 {:merchants </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 081 {id </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 082 {:plan plan}}}))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 083 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 084 (defn sell-and-buy </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 085 "Return a new world like this `world`, in which this `merchant` has sold </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 086 their current stock in their current location, and planned a new trade, and </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 087 bought appropriate stock for it." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 088 ;; TODO: this either sells the entire cargo, or, if the market can't afford </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 089 ;; it, none of it. And it does not cope with selling different commodities </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 090 ;; in different markets. </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 091 [merchant world] </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 092 (let [m (cond </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 093 (keyword? merchant) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 094 (-> world :merchants merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 095 (map? merchant) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 096 merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 097 id (:id m) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 098 location (:location m) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 099 market (-> world :cities location) </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 100 stock-value (reduce </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 101 + </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 102 (map </span><br/> <span class="not-covered" title="0 out of 11 forms covered"> 103 #(* (-> m :stock %) (-> market :prices m)) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 104 (keys (:stock m))))] </span><br/> <span class="not-covered" title="0 out of 16 forms covered"> 105 (l/debug "sell-and-buy: merchant" id) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 106 (if </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 107 (>= (:cash market) stock-value) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 108 (do </span><br/> <span class="not-covered" title="0 out of 24 forms covered"> 109 (l/info "Merchant" id "sells" (:stock m) "at" location "for" stock-value) </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 110 (plan-and-buy </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 111 merchant </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 112 (deep-merge </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 113 world </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 114 {:merchants </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 115 {id </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 116 {:stock {} </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 117 :cash (+ (:cash m) stock-value) </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 118 :known-prices (add-known-prices m world)}} </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 119 :cities </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 120 {location </span><br/> <span class="not-covered" title="0 out of 11 forms covered"> 121 {:stock (add-stock (:stock m) (:stock market)) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 122 :cash (- (:cash market) stock-value)}}}))) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 123 ;; else </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 124 (re-plan merchant world)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 125 </span><br/> <span class="covered" title="1 out of 1 forms covered"> 126 (defn move-merchant </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 127 "Handle general en route movement of this `merchant` in this `world`; </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 128 return a (partial or full) world like this `world` but in which the </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 129 merchant may have been moved ot updated." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 130 [merchant world] </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 131 (let [m (cond </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 132 (keyword? merchant) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 133 (-> world :merchants merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 134 (map? merchant) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 135 merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 136 id (:id m) </span><br/> <span class="not-covered" title="0 out of 16 forms covered"> 137 at-destination? (and (:plan m) (= (:location m) (-> m :plan :destination))) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 138 plan (:plan m) </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 139 next-location (if plan </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 140 (nth </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 141 (find-route </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 142 world </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 143 (:location m) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 144 (:destination plan)) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 145 1) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 146 (:location m))] </span><br/> <span class="not-covered" title="0 out of 23 forms covered"> 147 (l/debug "move-merchant: merchant" id "at" (:location m) </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 148 "destination" (-> m :plan :destination) "next" next-location </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 149 "at destination" at-destination?) </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 150 (cond </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 151 ;; if the merchant is at the destination of their current plan </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 152 ;; sell all cargo and repurchase. </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 153 at-destination? </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 154 (sell-and-buy merchant world) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 155 ;; if they don't have a plan, seek to create one </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> 156 (nil? plan) </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 157 (plan-and-buy merchant world) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 158 ;; otherwise, move one step towards their destination </span><br/> <span class="not-covered" title="0 out of 11 forms covered"> 159 (and next-location (not= next-location (:location m))) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 160 (do </span><br/> <span class="not-covered" title="0 out of 22 forms covered"> 161 (l/info "Merchant " id " moving from " (:location m) " to " next-location) </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 162 (deep-merge </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 163 {:merchants </span><br/> <span class="not-covered" title="0 out of 2 forms covered"> 164 {id </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 165 {:location next-location </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> 166 :known-prices (add-known-prices m world)}}} </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> 167 (move-gossip id world next-location))) </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> 168 :else </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 169 (do </span><br/> <span class="not-covered" title="0 out of 18 forms covered"> 170 (l/info "Merchant" id "has plan but no next-location; currently at" </span><br/> <span class="not-covered" title="0 out of 6 forms covered"> 171 (:location m) ", destination is" (:destination plan)) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> 172 world)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> 173 </span><br/> </body> </html>