Added a strategy for running the whole simulation

This commit is contained in:
Simon Brooke 2019-05-15 00:20:43 +01:00
parent 530760ee02
commit 984feb850a
17 changed files with 310 additions and 30 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
<!DOCTYPE html PUBLIC ""
"">
<html><head><meta charset="UTF-8" /><title>Introduction to the-great-game</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">The-great-game</span> <span class="project-version">0.1.0-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>the-great-game</span></div></div></li><li class="depth-2 branch"><a href="the-great-game.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.merchants.markets.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>markets</span></div></a></li><li class="depth-3"><a href="the-great-game.merchants.merchants.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -83px;"><span class="top" style="height: 92px;"></span><span class="bottom"></span></span><span>utils</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.world.routes.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>routes</span></div></a></li><li class="depth-3"><a href="the-great-game.world.world.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#introduction-to-the-great-game" name="introduction-to-the-great-game"></a>Introduction to the-great-game</h1>
<html><head><meta charset="UTF-8" /><title>Introduction to the-great-game</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">The-great-game</span> <span class="project-version">0.1.0-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>the-great-game</span></div></div></li><li class="depth-2 branch"><a href="the-great-game.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gossip</span></div></div></li><li class="depth-3"><a href="the-great-game.gossip.gossip.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gossip</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree" style="top: -52px;"><span class="top" style="height: 61px;"></span><span class="bottom"></span></span><span>merchants</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.merchants.markets.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>markets</span></div></a></li><li class="depth-3"><a href="the-great-game.merchants.merchants.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -83px;"><span class="top" style="height: 92px;"></span><span class="bottom"></span></span><span>utils</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.world.routes.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>routes</span></div></a></li><li class="depth-3 branch"><a href="the-great-game.world.run.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>run</span></div></a></li><li class="depth-3"><a href="the-great-game.world.world.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#introduction-to-the-great-game" name="introduction-to-the-great-game"></a>Introduction to the-great-game</h1>
<h1><a href="#the-great-game" name="the-great-game"></a>The Great Game</h1>
<p>In this essay Im going to try to pull together a number of my architectural ideas about the Great Game which I know Im never actually going to build - because its vastly too big for any one person to build - into one overall vision.</p>
<p>So, firstly, how does one characterise this game?</p>

View file

@ -1,3 +1,3 @@
<!DOCTYPE html PUBLIC ""
"">
<html><head><meta charset="UTF-8" /><title>the-great-game.core documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">The-great-game</span> <span class="project-version">0.1.0-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>the-great-game</span></div></div></li><li class="depth-2 branch current"><a href="the-great-game.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.merchants.markets.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>markets</span></div></a></li><li class="depth-3"><a href="the-great-game.merchants.merchants.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -83px;"><span class="top" style="height: 92px;"></span><span class="bottom"></span></span><span>utils</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.world.routes.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>routes</span></div></a></li><li class="depth-3"><a href="the-great-game.world.world.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="the-great-game.core.html#var-foo"><div class="inner"><span>foo</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">the-great-game.core</h1><div class="doc"><div class="markdown"><p><strong>TODO</strong>: write docs</p></div></div><div class="public anchor" id="var-foo"><h3>foo</h3><div class="usage"><code>(foo x)</code></div><div class="doc"><div class="markdown"><p>I dont do a whole lot.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/the-great-game/blob/master/src/the_great_game/core.clj#L3">view source</a></div></div></div></body></html>
<html><head><meta charset="UTF-8" /><title>the-great-game.core documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">The-great-game</span> <span class="project-version">0.1.0-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>the-great-game</span></div></div></li><li class="depth-2 branch current"><a href="the-great-game.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gossip</span></div></div></li><li class="depth-3"><a href="the-great-game.gossip.gossip.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gossip</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree" style="top: -52px;"><span class="top" style="height: 61px;"></span><span class="bottom"></span></span><span>merchants</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.merchants.markets.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>markets</span></div></a></li><li class="depth-3"><a href="the-great-game.merchants.merchants.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -83px;"><span class="top" style="height: 92px;"></span><span class="bottom"></span></span><span>utils</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.world.routes.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>routes</span></div></a></li><li class="depth-3 branch"><a href="the-great-game.world.run.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>run</span></div></a></li><li class="depth-3"><a href="the-great-game.world.world.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="the-great-game.core.html#var-foo"><div class="inner"><span>foo</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">the-great-game.core</h1><div class="doc"><div class="markdown"><p><strong>TODO</strong>: write docs</p></div></div><div class="public anchor" id="var-foo"><h3>foo</h3><div class="usage"><code>(foo x)</code></div><div class="doc"><div class="markdown"><p>I dont do a whole lot.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/the-great-game/blob/master/src/the_great_game/core.clj#L3">view source</a></div></div></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
<!DOCTYPE html PUBLIC ""
"">
<html><head><meta charset="UTF-8" /><title>the-great-game.world.run documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">The-great-game</span> <span class="project-version">0.1.0-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>the-great-game</span></div></div></li><li class="depth-2 branch"><a href="the-great-game.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gossip</span></div></div></li><li class="depth-3"><a href="the-great-game.gossip.gossip.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>gossip</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree" style="top: -52px;"><span class="top" style="height: 61px;"></span><span class="bottom"></span></span><span>merchants</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.merchants.markets.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>markets</span></div></a></li><li class="depth-3"><a href="the-great-game.merchants.merchants.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchants</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -83px;"><span class="top" style="height: 92px;"></span><span class="bottom"></span></span><span>utils</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></div></li><li class="depth-3 branch"><a href="the-great-game.world.routes.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>routes</span></div></a></li><li class="depth-3 branch current"><a href="the-great-game.world.run.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>run</span></div></a></li><li class="depth-3"><a href="the-great-game.world.world.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>world</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="the-great-game.world.run.html#var-run"><div class="inner"><span>run</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">the-great-game.world.run</h1><div class="doc"><div class="markdown"><p>Run the whole simulation</p></div></div><div class="public anchor" id="var-run"><h3>run</h3><div class="usage"><code>(run world)</code></div><div class="doc"><div class="markdown"><p>The pipeline to run the simulation each game day. Returns a world like this world, with all the various active elements updated.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/the-great-game/blob/master/src/the_great_game/world/run.clj#L10">view source</a></div></div></div></body></html>

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,8 @@
:doc/format :markdown}
:output-path "docs"
:source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"}
:dependencies [[org.clojure/clojure "1.8.0"]]
:dependencies [[org.clojure/clojure "1.8.0"]
[com.taoensso/timbre "4.10.0"]]
:description "Prototype code towards the great game I've been writing about for ten years, and know I will never finish."
:license {:name "GNU General Public License,version 2.0 or (at your option) any later version"
:url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}

View file

@ -0,0 +1,47 @@
(ns the-great-game.gossip.gossip
"Interchange of news events between agents agents"
(:require [the-great-game.utils :refer [deep-merge]]))
;; Note that habitual travellers are all gossip agents; specifically, at this
;; stage, that means merchants. When merchants are moved we also need to
;; update the location of the gossip with the same key.
(defn dialogue
"Dialogue between an `enquirer` and an `agent` in this `world`; returns a
map identical to `enquirer` except that its `:gossip` collection may have
additional entries."
;; TODO: not yet written, this is a stub.
[enquirer respondent world]
enquirer)
(defn gather-news
([world]
(reduce
deep-merge
world
(map
#(gather-news world %)
(keys (:gossips world)))))
([world gossip]
(let [g (cond (keyword? gossip)
(-> world :gossips gossip)
(map? gossip)
gossip)]
{:gossips
{(:id g)
(reduce
deep-merge
{}
(map
#(dialogue g % world)
(remove
#( = g %)
(filter
#(= (:location %) (:location g))
(vals (:gossips world))))))}})))
(defn run
"Return a world like this `world`, with news items exchanged between gossip
agents."
[world]
(gather-news world))

View file

@ -1,6 +1,8 @@
(ns the-great-game.merchants.merchants
"Trade planning for merchants, primarily."
(:require [the-great-game.world.routes :refer [find-routes]]
(:require [taoensso.timbre :as l :refer [info error]]
[the-great-game.utils :refer [deep-merge]]
[the-great-game.world.routes :refer [find-route]]
[the-great-game.world.world :refer [actual-price default-world]]))
@ -91,15 +93,12 @@
commodity
%)
:distance (count
(first
(find-routes (:routes world) origin %)))
(find-route world origin %))
:dist-to-home (count
(first
(find-routes
(:routes world)
(find-route
world
(:home m)
%)))
)
(remove #(= % origin) (keys (-> world :cities))))))
(defn nearest-with-targets
@ -160,6 +159,8 @@
(defn can-carry
"Return the number of units of this `commodity` which this `merchant`
can carry in this `world`, given their current burden."
[merchant world commodity]
(let [m (cond
(keyword? merchant)
@ -171,6 +172,8 @@
(-> world :commodities commodity :weight))))
(defn can-afford
"Return the number of units of this `commodity` which this `merchant`
can afford to buy in this `world`."
[merchant world commodity]
(let [m (cond
(keyword? merchant)
@ -226,12 +229,201 @@
#(let [q (-> world :cities origin :stock %)]
(and (number? q) (> q 0)))
(keys available)))]
(first
(sort-by
#(- 0 (:dist-to-home %))
(filter
(make-target-filter
[[:expected-profit
(apply max (filter number? (map :expected-profit plans)))]])
plans)))))
(if
(not (empty? plans))
(first
(sort-by
#(- 0 (:dist-to-home %))
(filter
(make-target-filter
[[:expected-profit
(apply max (filter number? (map :expected-profit plans)))]])
plans))))))
(defn add-stock
"Where `a` and `b` are both maps all of whose values are numbers, return
a map whose keys are a union of the keys of `a` and `b` and whose values
are the sums of their respective values."
[a b]
(reduce
merge
a
(map
#(hash-map % (+ (or (a %) 0) (or (b %) 0)))
(keys b))))
(defn add-known-prices
"Add the current prices at this `merchant`'s location in the `world`
to a new cacke of known prices, and return it."
[merchant world]
(let [m (cond
(keyword? merchant)
(-> world :merchants merchant)
(map? merchant)
merchant)
k (:known-prices m)
l (:location m)
d (:date world)
p (-> world :cities l :prices)]
(reduce
merge
k
(map
#(hash-map % (apply vector cons {:price (p %) :date d} (k %)))
(-> world :commodities keys)))))
;;; Right, from here on in we're actually moving things in the world, so
;;; functions generally return modified partial worlds.
(defn plan-and-buy
"Return a world like this `world`, in which this `merchant` has planned
a new trade, and bought appropriate stock for it. If no profitable trade
can be planned, the merchant is simply moved towards their home."
[merchant world]
(deep-merge
world
(let [m (cond
(keyword? merchant)
(-> world :merchants merchant)
(map? merchant)
merchant)
id (:id m)
location (:location m)
market (-> world :cities location)
plan (select-cargo merchant world)]
(cond
(not (empty? plan))
(let
[c (:commodity plan)
p (* (:quantity plan) (:buy-price plan))
q (:quantity plan)]
(l/info "Merchant " id " bought " q " units of " c " at " location " for " p)
{:merchants
{id
{:stock (add-stock (:stock m) {c q})
:cash (- (:cash m) p)
:known-prices (add-known-prices m world)}}
:cities
{location
{:stock (assoc (:stock market) c (- (-> market :stock c) q))
:cash (+ (:cash market) p)}}})
;; if no plan, then if at home stay put
(= (:location m) (:home m))
{}
;; else move towards home
true
(let [route (find-route world location (:home m))
next-location (nth route 1)]
(l/info "No trade possible at " location "; merchant " id " moves to " next-location)
{:merchants
{id
{:location next-location}}})))))
(defn re-plan
"Having failed to sell a cargo at current location, re-plan a route to
sell the current cargo. Returns a revised world."
[merchant world]
(let [m (cond
(keyword? merchant)
(-> world :merchants merchant)
(map? merchant)
merchant)
id (:id m)
location (:location m)
plan (augment-plan m world (plan-trade m world (-> m :plan :commodity)))]
(deep-merge
world
{:merchants
{id
{:plan plan}}})))
(defn sell-and-buy
"Return a new world like this `world`, in which this `merchant` has sold
their current stock in their current location, and planned a new trade, and
bought appropriate stock for it."
;; TODO: this either sells the entire cargo, or, if the market can't afford
;; it, none of it. And it does not cope with selling different commodities
;; in different markets.
[merchant world]
(let [m (cond
(keyword? merchant)
(-> world :merchants merchant)
(map? merchant)
merchant)
id (:id m)
location (:location m)
market (-> world :cities location)
stock-value (reduce
+
(map
#(* (-> m :stock %) (-> market :prices m))
(keys (:stock m))))]
(if
(>= (:cash market) stock-value)
(do
(l/info
(apply str (flatten (list "Merchant " id " sells " (:stock m) " at " location " for " stock-value))))
(plan-and-buy
merchant
(deep-merge
world
{:merchants
{id
{:stock {}
:cash (+ (:cash m) stock-value)
:known-prices (add-known-prices m world)}}
:cities
{location
{:stock (add-stock (:stock m) (:stock market))
:cash (- (:cash market) stock-value)}}})))
;; else
(re-plan merchant world))))
(defn move-merchant
"Handle general en route movement of this `merchant` in this `world`."
[merchant world]
(let [m (cond
(keyword? merchant)
(-> world :merchants merchant)
(map? merchant)
merchant)
id (:id m)
at-destination? (and (:plan m) (= (:location m) (-> m :plan :destination)))
plan (:plan m)
next-location (if plan
(nth 1 (find-route world (:location m) (:destination plan)))
(:location m))]
(l/info "Merchant " id " at " (:location m))
(cond at-destination?
(sell-and-buy merchant world plan)
(nil? (:plan m))
(plan-and-buy merchant world)
true
{:merchants
{id
{:id id
:location next-location
:known-prices (add-known-prices m world)}}})))
(defn run
"Return a world like this `world`, but with each merchant moved."
[world]
(try
(reduce
deep-merge
world
(map
#(try
(move-merchant % world)
(catch Exception any
(l/error any "Failure while moving merchant " %)
{}))
(keys (:merchants world))))
(catch Exception any
(l/error any "Failure while moving merchants")
world)))

View file

@ -1,6 +1,5 @@
(ns the-great-game.utils)
(defn cyclic?
"True if two or more elements of `route` are identical"
[route]
@ -15,3 +14,4 @@
(apply merge-with m xs)
(last xs)))]
(reduce m maps)))

View file

@ -44,3 +44,14 @@
(empty? found)
(find-routes routes from to paths)
found)))))
(defn find-route
"Find a single route from `from` to `to` in this `world-or-routes`, which
may be either a world as defined in [[the-great-game.world.world]] or else
a sequence of tuples of keywords."
[world-or-routes from to]
(first
(find-routes
(or (:routes world-or-routes) world-or-routes)
from
to)))

View file

@ -0,0 +1,17 @@
(ns the-great-game.world.run
"Run the whole simulation"
(:require [taoensso.timbre :as log]
[the-great-game.gossip.gossip :as g]
[the-great-game.merchants.merchants :as m]
[the-great-game.merchants.markets :as k]
[the-great-game.world.world :as w]))
(defn run
"The pipeline to run the simulation each game day. Returns a world like
this world, with all the various active elements updated."
[world]
(g/run
(m/run
(k/run
(w/run world)))))

View file

@ -9,7 +9,8 @@
(def default-world
"A basic world for testing concepts"
{:cities
{:date 0 ;; the age of this world in game days
:cities
{:aberdeen
{:id :aberdeen
:supplies
@ -181,4 +182,9 @@
[world commodity city]
(-> world :cities city :prices commodity))
(defn run
"Return a world like this `world` with only the `:date` value updated
(incremented by one). For running other aspects of the simulation, see
[[the-great-game.world.run#var-run]]."
[world]
(assoc world :date (inc (or (:date world) 0))))