001 (ns cc.journeyman.the-great-game.world.world
002 "Access to data about the world")
003
004 ;;; The world has to work either as map or a database. Initially, and for
005 ;;; unit tests, I'll use a map; later, there will be a database. But the
006 ;;; API needs to be agnostic, so that heirarchies which interact with
007 ;;; `world` don't have to know which they've got - as far as they're concerned
008 ;;; it's just a handle.
009
010 (def default-world
011 "A basic world for testing concepts"
012 {:date 0 ;; the age of this world in game days
013 :cities
014 {:aberdeen
015 {:id :aberdeen
016 :supplies
017 ;; `supplies` is the quantity of each commodity added to the stock
018 ;; each game day. If the price in the market is lower than 1 (the
019 ;; cost of production of a unit) no goods will be added.
020 {:fish 10
021 :leather 5}
022 :demands
023 ;; `stock` is the quantity of each commodity in the market at any
024 ;; given time. It is adjusted for production and consumption at
025 ;; the end of each game day.
026 {:iron 1
027 :cloth 10
028 :whisky 10}
029 :port true
030 :prices
031 ;; `prices`: the current price (both buying and selling, for simplicity)
032 ;; of each commodity in the market. Updated each game day based on current
033 ;; stock.
034 {:cloth 1
035 :fish 1
036 :leather 1
037 :iron 1
038 :whisky 1}
039 :stock
040 ;; `stock` is the quantity of each commodity in the market at any
041 ;; given time. It is adjusted for production and consumption at
042 ;; the end of each game day.
043 {:cloth 0
044 :fish 0
045 :leather 0
046 :iron 0
047 :whisky 0}
048 :cash 100}
049 :buckie
050 {:id :buckie
051 :supplies
052 {:fish 20}
053 :demands
054 {:cloth 5
055 :leather 3
056 :whisky 5
057 :iron 1}
058 :port true
059 :prices {:cloth 1
060 :fish 1
061 :leather 1
062 :iron 1
063 :whisky 1}
064 :stock {:cloth 0
065 :fish 0
066 :leather 0
067 :iron 0
068 :whisky 0}
069 :cash 100}
070 :callander
071 {:id :callander
072 :supplies {:leather 20}
073 :demands
074 {:cloth 5
075 :fish 3
076 :whisky 5
077 :iron 1}
078 :prices {:cloth 1
079 :fish 1
080 :leather 1
081 :iron 1
082 :whisky 1}
083 :stock {:cloth 0
084 :fish 0
085 :leather 0
086 :iron 0
087 :whisky 0}
088 :cash 100}
089 :dundee {:id :dundee}
090 :edinburgh {:id :dundee}
091 :falkirk
092 {:id :falkirk
093 :supplies {:iron 10}
094 :demands
095 {:cloth 5
096 :leather 3
097 :whisky 5
098 :fish 10}
099 :port true
100 :prices {:cloth 1
101 :fish 1
102 :leather 1
103 :iron 1
104 :whisky 1}
105 :stock {:cloth 0
106 :fish 0
107 :leather 0
108 :iron 0
109 :whisky 0}
110 :cash 100}
111 :glasgow
112 {:id :glasgow
113 :supplies {:whisky 10}
114 :demands
115 {:cloth 5
116 :leather 3
117 :iron 5
118 :fish 10}
119 :port true
120 :prices {:cloth 1
121 :fish 1
122 :leather 1
123 :iron 1
124 :whisky 1}
125 :stock {:cloth 0
126 :fish 0
127 :leather 0
128 :iron 0
129 :whisky 0}
130 :cash 100}}
131 :merchants
132 {:archie {:id :archie
133 :home :aberdeen :location :aberdeen :cash 100 :capacity 10
134 :known-prices {}
135 :stock {}}
136 :belinda {:id :belinda
137 :home :buckie :location :buckie :cash 100 :capacity 10
138 :known-prices {}
139 :stock {}}
140 :callum {:id :callum
141 :home :callander :location :calander :cash 100 :capacity 10
142 :known-prices {}
143 :stock {}}
144 :deirdre {:id :deidre
145 :home :dundee :location :dundee :cash 100 :capacity 10
146 :known-prices {}
147 :stock {}}
148 :euan {:id :euan
149 :home :edinbirgh :location :edinburgh :cash 100 :capacity 10
150 :known-prices {}
151 :stock {}}
152 :fiona {:id :fiona
153 :home :falkirk :location :falkirk :cash 100 :capacity 10
154 :known-prices {}
155 :stock {}}}
156 :routes
157 ;; all routes can be traversed in either direction and are assumed to
158 ;; take the same amount of time.
159 [[:aberdeen :buckie]
160 [:aberdeen :dundee]
161 [:callander :glasgow]
162 [:dundee :callander]
163 [:dundee :edinburgh]
164 [:dundee :falkirk]
165 [:edinburgh :falkirk]
166 [:falkirk :glasgow]]
167 :commodities
168 ;; cost of commodities is expressed in person/days;
169 ;; weight in packhorse loads. Transport in this model
170 ;; is all overland; you don't take bulk cargoes overland
171 ;; in this period, it's too expensive.
172 {:cloth {:id :cloth :cost 1 :weight 0.25}
173 :fish {:id :fish :cost 1 :weight 1}
174 :leather {:id :leather :cost 1 :weight 0.5}
175 :whisky {:id :whisky :cost 1 :weight 0.1}
176 :iron {:id :iron :cost 1 :weight 10}}})
177
178 (defn actual-price
179 "Find the actual current price of this `commodity` in this `city` given
180 this `world`. **NOTE** that merchants can only know the actual prices in
181 the city in which they are currently located."
182 [world commodity city]
183 (-> world :cities city :prices commodity))
184
185 (defn run
186 "Return a world like this `world` with only the `:date` to this `date`
187 (or id `date` not supplied, the current value incremented by one). For
188 running other aspects of the simulation, see [[the-great-game.world.run]]."
189 ([world]
190 (run world (inc (or (:date world) 0))))
191 ([world date]
192 (assoc world :date date)))