Merge branch 'master' of github.com:simon-brooke/the-great-game
This commit is contained in:
commit
58589d2da4
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -2,13 +2,18 @@ pom.xml
|
|||
pom.xml.asc
|
||||
*.jar
|
||||
*.class
|
||||
*.log
|
||||
[0-9a-f]*-init.clj
|
||||
/lib/
|
||||
/classes/
|
||||
/target/
|
||||
/checkouts/
|
||||
/.clj-kondo/
|
||||
.eastwood
|
||||
.lein-deps-sum
|
||||
.lein-repl-history
|
||||
.lein-plugins/
|
||||
.lein-failures
|
||||
.nrepl-port
|
||||
.cpcache/
|
||||
*~
|
||||
|
|
BIN
doc/Population.ods
Normal file
BIN
doc/Population.ods
Normal file
Binary file not shown.
49
doc/economy.md
Normal file
49
doc/economy.md
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Game world economy
|
||||
|
||||
Broadly this essay extends ideas presented in [Populating a game world](https://blog.journeyman.cc/2013/07/populating-game-world.html), q.v.
|
||||
|
||||
## Primary producers
|
||||
|
||||
### Herdsfolk
|
||||
|
||||
Herdsfolk are nomadic; it's reasonable to think they'll bring their herds to market, rather than selling it lots of tiny markets. So in the spring, shepherds will visit specific towns at the edge of open land, to hold a shearing festival/carnevale; and that both shepherds and cattle herders will visit towns on the edge of open land to sell fatstock in the autumn.
|
||||
|
||||
### Miners
|
||||
|
||||
Miners mine. They're settled, but they're settled usually in specialist settlements at the location where the ore body is accessible, usually in mountenous territory. They'll consume a lot of food, so there will be a local market for foodstuffs encouraging local farming. Different mines obviously mine different ores, but, for example, lead and silver are frequently found together.
|
||||
|
||||
### Foresters
|
||||
|
||||
Foresters are more or less settled at the edge of forests, at locations from which timber can be moved by navigable water; again in specialist settlements. In addition to timber, foresters hunt and produce both meat and furs, so have less need for other food producers locally.
|
||||
|
||||
### Farmers
|
||||
|
||||
Farmers are settled. Farmers occupy standard runrig plots, but because they don't employ journeymen or apprentices, and don't have workshops, the plots are mostly open with little building. Most farmers are 'mixed farmers', producing cereals, meat, eggs and milk. Some will be more specialist. Farm produce, taken broadly to include orchardsfolk, include:
|
||||
|
||||
* meat
|
||||
* milk and milk products
|
||||
* hides
|
||||
* eggs
|
||||
* cereals
|
||||
* root vegetables, onions, etc
|
||||
* peas and beans
|
||||
* leaf vegetables
|
||||
* fruits
|
||||
* fibres: linen, hemp and silk (from silk-moths in mulberry orchards)
|
||||
* possibly other stuff I've forgotten.
|
||||
|
||||
Farmers are all basically subsistence farmers, farming first to feed their own household and selling only surplus in the market.
|
||||
|
||||
## Crafts
|
||||
|
||||
Crafts generally process primary goods into secondary goods - whether intermediate stages or final consumer items. Some elite 'crafts' deal with abstract primary goods like law and knowledge, and they may be seen as somewhat separate.
|
||||
|
||||
A master craftsperson occupies a standard runrig plot, much like a farmer's plot. Like a farmer, a poor master crafter household will cultivate part of the plot to produce food for the house - at least grow vegetables and keep hens. However, as the crafter takes on apprentices and journeymen - and gets richer - more buildings will be required as accommodation, workshop space and materials stores.
|
||||
|
||||
Generally, primary goods aren't transported over land - because overland transport is expensive, by the time they've been transported they're no longer low cost goods. So often the craftspeople who process primary produce into at least commodity intermediate forms will live close to the source of the primary goods.
|
||||
|
||||
So, for example, the town(s) where the shepherds hold their shearing fairs will tend to have a lot of weavers. While around mines there will be smelters producing ingots and bar stock to be marketed to smiths all over the place, there will also be smiths close to the mines producing commodity tools and weapons.
|
||||
|
||||
See the table in Populating a game world.
|
||||
|
||||
|
9
doc/modelling_trading_cost_and_risk.md
Normal file
9
doc/modelling_trading_cost_and_risk.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Modelling trading cost and risk
|
||||
|
||||
In a dynamic pre-firearms world with many small states and contested regions, trade is not going to be straightforward. Not only will different routes have different physical characteristics - more or less mountainous, more or fewer unbridged river crossings - they will also have different political characteristics: more of less taxed, more or less effectively policed.
|
||||
|
||||
Raids by outlaws are expected to be part of the game economy. News of raids are the sort of things which may propagate through the [[gossip]] system. So are changes in taxation regime. Obviously, knowledge items can affect merchants' trading strategy; in existing prototype code, individual merchants already each keep their own cache of known historical prices, and exchange historical price data with one another; and use this price data to select trades to make.
|
||||
|
||||
So: to what extent is it worth modelling the spread of knowledge of trade cost and risk?
|
||||
|
||||
Obviously the more we model, the more compute power modelling consumes. If the core objective is a Role Playing Games as currently understood, then there is no need to model very complex trade risk assessment behaviour.
|
66
doc/sandbox.md
Normal file
66
doc/sandbox.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Sandbox
|
||||
|
||||
Up to now I've been thinking of the Great Game as essentially an RPG with some sandbox-like elements; but I think it may be better to think of it as a sandbox game with some RPG like elements.
|
||||
|
||||
Why?
|
||||
|
||||
The core of the game is a world in which non-player characters have enough individual knowledge of the world and their immediate surroundings that they can sensibly answer questions like
|
||||
|
||||
* Where is the nearest craftsman of this craft?
|
||||
* What price can I expect to get for this item in the local market?
|
||||
* What news have you heard recently?
|
||||
* Where does this person from your village live?
|
||||
|
||||
and where there's a sufficiently sophisticated and robust economy simulation that buying goods in one market and selling them in another is viable.
|
||||
|
||||
The original BBC Micro space trading game Elite had very little more in terms of game mechanics than a sandbox with a means to navigate it and an economy simulation, which wasn't even nearly as sophisticated as the one I have working now. Yet that combination resulted in engaging game play.
|
||||
|
||||
## Main sandbox roles
|
||||
|
||||
The idea of a sandbox is that the player character should be able to do pretty much anything they like within the mechanics of the game. From that, it seems to me reasonable that the player ought to be able to do more or less everything a non-player character can do. But creating the game mechanics to make each additional task doable takes time and investment, so there's a need to prioritise.
|
||||
|
||||
So, as Elite did, I propose to make the first available sandbox roles
|
||||
|
||||
### Merchant
|
||||
|
||||
Someone who travels from city to city, buying goods cheap in one and selling them for more in another; and
|
||||
|
||||
### Outlaw
|
||||
|
||||
Someone who intercepts and steals from merchants (and may also attack outlying farms and villages)
|
||||
|
||||
## Second tier playable roles
|
||||
|
||||
The next tier of playable roles rotates around issues arising from the mercantile ecosystem.
|
||||
|
||||
### Aristocracy
|
||||
|
||||
Aristocrats are basically settled outlaws who seek to establish a monopoly on extracting taxes from inhabitants and travellers in a particular region by driving out all other outlaws. Within the comain of an aristocrat, you have to pay tax but you're reasonably safe from being attacked by other outlaws and losing everything. Aristocrats may also maintain and improve roads and bridges and do other things to boost the economy of their territory, may expant into adjoining territory with no current aristocratic control, and may wage war on other aristocrats.
|
||||
|
||||
An outlaw ought to be able to become an aristocrat, by dominating an ungoverned area or by defeating an existing aristocrat.
|
||||
|
||||
### Soldiery
|
||||
|
||||
Soldiers, like aristocrats, are basically on the same spectrum as outlaws. Outlaws may hire themselves out to merchants as caravan guards, or to aristocrats as soldiers. Soldiers or guards, falling on bad times, may revert to outlawry.
|
||||
|
||||
## Routine, Discretion and Playability
|
||||
|
||||
There's a term that's used in criticism of many computer games which is worth thinking about hard here: that term is 'farming'. 'Farming', in this sense, is doing something repetitive and dull to earn credits in a game. Generally this is not fun. What makes roles in a game-world fun is having individual discretion - the ability to choose between actions and strategies - and a lack of routine.
|
||||
|
||||
Most craft skills - especially in the learning phase - are not like this, and crafts which are sophisticated enough to be actually engaging are very hard to model in a game. Learning a craft is essentially, inherently, repetitive and dull, and if you take that repetition out of it you probably don't have enough left to yield the feeling of mastery which would reward success; so it doesn't seem to me that making craft roles playable should be a priority.
|
||||
|
||||
## Cruise control
|
||||
|
||||
One of the most enjoyable aspects of The Witcher 3 - still my go-to game for ideas I want to improve on - is simply travelling through the world. Although fast travel is possible I find I rarely use it, and a journey which takes fifteen minutes of real world wall clock time can be enjoyable in and of itself. This is, of course, a credit to the beautiful way the world is realised.
|
||||
|
||||
But nevertheless, in The Witcher 3, a decision was made to pack incident fairly densely - because players would find just travelling boring. This leads to a situation where peaceful villages exist two minutes travel from dangerous monsters or bandit camps, and the suspension of disbelief gets a little strained. Building a world big enough that a market simulation is believable means that for the individual, the travel time to a market where a particular desired good is likely to be cheaper becomes costly in itself. Otherwise, there's no arbitrage between markets and no ecological niche for a merchant to fill. The journey time from market to market has to be several in-game days.
|
||||
|
||||
An in-game day doesn't have to be as long as a wall clock day, and, indeed, typically isn't. But nevertheless, doing several game days of incident-free travel, even in beautiful scenery, is not going to be engaging - which implies a fast-travel mechanic.
|
||||
|
||||
I don't like fast travel, I find it a too-obvious breaking of immersion. Also, of course, one of the interesting things about a game in a merchant/outlaw ecosystem is the risk of interception on a journey. The Dragon Age series handled interrupted travel in 'fast travel' by randomly interacting the loading screen you get when moving from location to location in Dragon Age's patchwork worlds by dumping you into a tiny arena with enemies. That's really, really bad - there's no other way to say this. Everything about it shouts artifice.
|
||||
|
||||
So I'm thinking of a different mechanism: one I'm calling cruise control.
|
||||
|
||||
You set out on a task which will take a long time - such as a journey, but also such as any routine task. You're shown either a 'fast forward' of your character carrying out this task, or a series of cinematic 'shots along the way'. This depends, of course, on their being continuous renderable landscape between your departure and your destination, but there will be. This fast-forward proceeds at a substantially higher time gearing than normal game time - ten times as fast perhaps; we need it to, because as well as doing backgound scenery loading to move from one location to another, we're also simulating lots of non-player agents actions in parts of the world where the player currently isn't. So a 'jump cut' from one location to another isn't going to work anyway.
|
||||
|
||||
The player can interrupt 'fast forward' at any time. But also, the game itself may bring you out of fast forward when it anticipates that there may be action which requires decision - for example, when there are outlaws in the vicinity. And it will do this **before** the player's party is under immediate attack - the player will have time to take stock of the situation and prepare appropriately. Finally, this will take place in the full open world; the player will have the option to choose *not* to enter the narrow defile, for example, to ask local people (if there are any) for any news of outlaw activity, or, if they are available, to send forward scouts.
|
45
doc/sexual-dimorphism.md
Normal file
45
doc/sexual-dimorphism.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Sexual dimorphism
|
||||
|
||||
This essay is going to upset a lot of people, so let's start with a statement of what it is about: it is an attempt to describe the systematically different behaviours of men and women, in sufficient detail that this can be represented by agents in a game world. It's trying to allow as broad as possible a range of cultures to be represented, so when I'm talking about what I consider to be behaviours of particular cultures, I'll say that.
|
||||
|
||||
Of course, I'm writing this from the view point of an old white male. It's not possible to write about these things from a totally neutral viewpoint, and every one of us will have prejudices.
|
||||
|
||||
OK? Let's start.
|
||||
|
||||
When a man and a woman have sex, there's a non-zero chance that the woman will get pregnant. There's a zero chance that the male will get pregnant.
|
||||
|
||||
A woman can typically give birth to of the order of twelve children in the course of her life, and each childbirth involves a non-zero risk of death. If modelling the sort of bronze-age-to-late-medieval cultures I'm generally considering, there are no available reliable methods of contraception, although their may be, for example, known spermicidal or abortifacient spells or potions. If it's abortifacient, that's pretty unpleasant for the woman, too.
|
||||
|
||||
Children, especially when young, are very vulnerable and need protection. Children with good protection are much more likely to survive to adulthood. Raising children involves a fair amount of work.
|
||||
|
||||
For all sorts of reasons, some of which are clearly cultural but others of which are fundamental, it's much easier for men to walk away from responsibility for their children than it is for women. For example, considering a pre-modern world, women would always know for certain which children were theirs, and men would not.
|
||||
|
||||
For a woman, consequently, the best breeding strategy is to have sex only with men who will be 'good fathers', where there are three essential parameters to "good fathers":
|
||||
|
||||
1. Desirable genetic traits;
|
||||
2. Preparedness to stick around and share the work;
|
||||
3. Ability to provide and protect.
|
||||
|
||||
The essential trade-off in the traditional western marriage is that the man gets to have sex, and the woman gets to have protection for her progeny.
|
||||
|
||||
Another significant point is that women's ability to bear children ceases at a much younger age than men's ability to father them.
|
||||
|
||||
## Why have sex at all?
|
||||
|
||||
If a character has 'having children' - the **Ancestor** aspiration, in my typology - as their key aim, then they will want to have sex. But to have children in this sense is to have acknowledged children, so while a male character may be motivated to have multiple female partners, he will never the less have some degree of long term committment to them, and will want both to feel confident that the children are his and to be recognised by their father.
|
||||
|
||||
From the point of view of seeking to become an Ancestor, there is little benefit to the woman in having multiple partners, except in very harsh environments. It will be easier to give one partner confidence that all your children are his, and while a man can increase his number of potential progeny by having multiple wives, mistresses or other classes of long-term female sexual partners, a woman cannot.
|
||||
|
||||
## Why have children?
|
||||
|
||||
In modern Scotland, I have met a lot of women with a strong drive to have children for the sake of having children, where the best explanation they could give is that it's instinctual; it may be so. But beyond that, in many cultures children provide their (acknowledged) parents with care and security in their old age, may tend their graves and perform belief-related services after they die, and carry on their name and their stories into the future.
|
||||
|
||||
Not everyone wants to have children; in thinking about the driving aspirations of game characters, I view having children one of six potential key aspirations.
|
||||
|
||||
## Why else have sex?
|
||||
|
||||
Sex, done right, is an extremely pleasant pastime. Sex can also be used to create and maintain bonds of committment, to demonstrate social status, to defuse tense situations, and transactionally in many ways, both formal and informal.
|
||||
|
||||
For women, sex with other women carries with it no risk of pregnancy, so can be enjoyed or used for any of these purposes in very much the same way as it can by men; in other words, particularly for women, homosexual sex can be more lighthearted and carefree than heterosexual sex. To what extend our notions of homosexuality and heterosexuality are cultural I simply don't know. But because no children will result, a woman can afford to be more promiscuous with other women than she can with men.
|
||||
|
||||
## How does this impact on
|
|
@ -1 +0,0 @@
|
|||
theme: jekyll-theme-slate
|
40
docs/cloverage/coverage.css
Normal file
40
docs/cloverage/coverage.css
Normal file
|
@ -0,0 +1,40 @@
|
|||
.covered {
|
||||
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
||||
background-color: #558B55;
|
||||
}
|
||||
|
||||
.not-covered {
|
||||
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.partial {
|
||||
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.not-tracked {
|
||||
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
||||
}
|
||||
|
||||
.blank {
|
||||
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
td.with-bar {
|
||||
width: 250px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td.with-number {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
td.ns-name {
|
||||
min-width: 150px;
|
||||
padding-right: 25px;
|
||||
}
|
192
docs/cloverage/index.html
Normal file
192
docs/cloverage/index.html
Normal file
|
@ -0,0 +1,192 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="./coverage.css"/>
|
||||
<title>Coverage Summary</title>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<thead><tr>
|
||||
<td class="ns-name"> Namespace </td>
|
||||
<td class="with-bar"> Forms </td>
|
||||
<td class="with-number">Forms %</td>
|
||||
<td class="with-bar"> Lines </td>
|
||||
<td class="with-number">Lines %</td>
|
||||
<td class="with-number">Total</td><td class="with-number">Blank</td><td class="with-number">Instrumented</td>
|
||||
</tr></thead>
|
||||
<tr>
|
||||
<td><a href="the_great_game/core.clj.html">the-great-game.core</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:33.333333333333336%;
|
||||
float:left;"> 2 </div><div class="not-covered"
|
||||
style="width:66.66666666666667%;
|
||||
float:left;"> 4 </div></td>
|
||||
<td class="with-number">33.33 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:66.66666666666667%;
|
||||
float:left;"> 2 </div><div class="not-covered"
|
||||
style="width:33.333333333333336%;
|
||||
float:left;"> 1 </div></td>
|
||||
<td class="with-number">66.67 %</td>
|
||||
<td class="with-number">6</td><td class="with-number">1</td><td class="with-number">3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/gossip/gossip.clj.html">the-great-game.gossip.gossip</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:4.545454545454546%;
|
||||
float:left;"> 5 </div><div class="not-covered"
|
||||
style="width:95.45454545454545%;
|
||||
float:left;"> 105 </div></td>
|
||||
<td class="with-number">4.55 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:12.820512820512821%;
|
||||
float:left;"> 5 </div><div class="not-covered"
|
||||
style="width:87.17948717948718%;
|
||||
float:left;"> 34 </div></td>
|
||||
<td class="with-number">12.82 %</td>
|
||||
<td class="with-number">65</td><td class="with-number">5</td><td class="with-number">39</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/merchants/markets.clj.html">the-great-game.merchants.markets</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:75.11737089201878%;
|
||||
float:left;"> 160 </div><div class="not-covered"
|
||||
style="width:24.88262910798122%;
|
||||
float:left;"> 53 </div></td>
|
||||
<td class="with-number">75.12 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:56.81818181818182%;
|
||||
float:left;"> 25 </div><div class="partial"
|
||||
style="width:11.363636363636363%;
|
||||
float:left;"> 5 </div><div class="not-covered"
|
||||
style="width:31.818181818181817%;
|
||||
float:left;"> 14 </div></td>
|
||||
<td class="with-number">68.18 %</td>
|
||||
<td class="with-number">84</td><td class="with-number">8</td><td class="with-number">44</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/merchants/merchant_utils.clj.html">the-great-game.merchants.merchant-utils</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:46.017699115044245%;
|
||||
float:left;"> 104 </div><div class="not-covered"
|
||||
style="width:53.982300884955755%;
|
||||
float:left;"> 122 </div></td>
|
||||
<td class="with-number">46.02 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:54.09836065573771%;
|
||||
float:left;"> 33 </div><div class="partial"
|
||||
style="width:4.918032786885246%;
|
||||
float:left;"> 3 </div><div class="not-covered"
|
||||
style="width:40.98360655737705%;
|
||||
float:left;"> 25 </div></td>
|
||||
<td class="with-number">59.02 %</td>
|
||||
<td class="with-number">92</td><td class="with-number">7</td><td class="with-number">61</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/merchants/merchants.clj.html">the-great-game.merchants.merchants</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:2.816901408450704%;
|
||||
float:left;"> 2 </div><div class="not-covered"
|
||||
style="width:97.1830985915493%;
|
||||
float:left;"> 69 </div></td>
|
||||
<td class="with-number">2.82 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:12.5%;
|
||||
float:left;"> 2 </div><div class="not-covered"
|
||||
style="width:87.5%;
|
||||
float:left;"> 14 </div></td>
|
||||
<td class="with-number">12.50 %</td>
|
||||
<td class="with-number">28</td><td class="with-number">3</td><td class="with-number">16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/merchants/planning.clj.html">the-great-game.merchants.planning</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:88.88888888888889%;
|
||||
float:left;"> 264 </div><div class="not-covered"
|
||||
style="width:11.11111111111111%;
|
||||
float:left;"> 33 </div></td>
|
||||
<td class="with-number">88.89 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:83.52941176470588%;
|
||||
float:left;"> 71 </div><div class="partial"
|
||||
style="width:4.705882352941177%;
|
||||
float:left;"> 4 </div><div class="not-covered"
|
||||
style="width:11.764705882352942%;
|
||||
float:left;"> 10 </div></td>
|
||||
<td class="with-number">88.24 %</td>
|
||||
<td class="with-number">159</td><td class="with-number">11</td><td class="with-number">85</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/merchants/strategies/simple.clj.html">the-great-game.merchants.strategies.simple</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:0.8103727714748784%;
|
||||
float:left;"> 5 </div><div class="not-covered"
|
||||
style="width:99.18962722852513%;
|
||||
float:left;"> 612 </div></td>
|
||||
<td class="with-number">0.81 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:4.032258064516129%;
|
||||
float:left;"> 5 </div><div class="not-covered"
|
||||
style="width:95.96774193548387%;
|
||||
float:left;"> 119 </div></td>
|
||||
<td class="with-number">4.03 %</td>
|
||||
<td class="with-number">173</td><td class="with-number">6</td><td class="with-number">124</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/utils.clj.html">the-great-game.utils</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:100.0%;
|
||||
float:left;"> 72 </div></td>
|
||||
<td class="with-number">100.00 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:100.0%;
|
||||
float:left;"> 19 </div></td>
|
||||
<td class="with-number">100.00 %</td>
|
||||
<td class="with-number">35</td><td class="with-number">3</td><td class="with-number">19</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/world/routes.clj.html">the-great-game.world.routes</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:99.21875%;
|
||||
float:left;"> 127 </div><div class="not-covered"
|
||||
style="width:0.78125%;
|
||||
float:left;"> 1 </div></td>
|
||||
<td class="with-number">99.22 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:97.61904761904762%;
|
||||
float:left;"> 41 </div><div class="partial"
|
||||
style="width:2.380952380952381%;
|
||||
float:left;"> 1 </div></td>
|
||||
<td class="with-number">100.00 %</td>
|
||||
<td class="with-number">55</td><td class="with-number">2</td><td class="with-number">42</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/world/run.clj.html">the-great-game.world.run</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:4.918032786885246%;
|
||||
float:left;"> 3 </div><div class="not-covered"
|
||||
style="width:95.08196721311475%;
|
||||
float:left;"> 58 </div></td>
|
||||
<td class="with-number">4.92 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:15.0%;
|
||||
float:left;"> 3 </div><div class="not-covered"
|
||||
style="width:85.0%;
|
||||
float:left;"> 17 </div></td>
|
||||
<td class="with-number">15.00 %</td>
|
||||
<td class="with-number">39</td><td class="with-number">2</td><td class="with-number">20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="the_great_game/world/world.clj.html">the-great-game.world.world</a></td><td class="with-bar"><div class="covered"
|
||||
style="width:95.89041095890411%;
|
||||
float:left;"> 420 </div><div class="not-covered"
|
||||
style="width:4.109589041095891%;
|
||||
float:left;"> 18 </div></td>
|
||||
<td class="with-number">95.89 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:97.01492537313433%;
|
||||
float:left;"> 65 </div><div class="not-covered"
|
||||
style="width:2.985074626865672%;
|
||||
float:left;"> 2 </div></td>
|
||||
<td class="with-number">97.01 %</td>
|
||||
<td class="with-number">192</td><td class="with-number">4</td><td class="with-number">67</td>
|
||||
</tr>
|
||||
<tr><td>Totals:</td>
|
||||
<td class="with-bar"></td>
|
||||
<td class="with-number">51.99 %</td>
|
||||
<td class="with-bar"></td>
|
||||
<td class="with-number">54.62 %</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
26
docs/cloverage/the_great_game/core.clj.html
Normal file
26
docs/cloverage/the_great_game/core.clj.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../coverage.css"/> <title> the_great_game/core.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.core)
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
002
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
003 (defn foo
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 "I don't do a whole lot."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 [x]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
006 (println x "Hello, World!"))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
203
docs/cloverage/the_great_game/gossip/gossip.clj.html
Normal file
203
docs/cloverage/the_great_game/gossip/gossip.clj.html
Normal file
|
@ -0,0 +1,203 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/gossip/gossip.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.gossip.gossip
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Interchange of news events between agents agents"
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 (:require [the-great-game.utils :refer [deep-merge]]))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
004
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 ;; Note that habitual travellers are all gossip agents; specifically, at this
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 ;; stage, that means merchants. When merchants are moved we also need to
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 ;; update the location of the gossip with the same key.
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
008
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
009 (defn dialogue
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
010 "Dialogue between an `enquirer` and an `agent` in this `world`; returns a
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
011 map identical to `enquirer` except that its `:gossip` collection may have
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
012 additional entries."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
013 ;; TODO: not yet written, this is a stub.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
014 [enquirer respondent world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
015 enquirer)
|
||||
</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 gather-news
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
018 ([world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
019 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
020 deep-merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
021 world
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
022 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
023 #(gather-news world %)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
024 (keys (:gossips world)))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
025 ([world gossip]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
026 (let [g (cond (keyword? gossip)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
027 (-> world :gossips gossip)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
028 (map? gossip)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
029 gossip)]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
030 {:gossips
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
031 {(:id g)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
032 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
033 deep-merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
034 {}
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
035 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
036 #(dialogue g % world)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
037 (remove
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
038 #( = g %)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
039 (filter
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 8 forms covered">
|
||||
040 #(= (:location %) (:location g))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
041 (vals (:gossips world))))))}})))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
042
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
043 (defn move-gossip
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
044 "Return a world like this `world` but with this `gossip` moved to this
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
045 `new-location`. Many gossips are essentially shadow-records of agents of
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
046 other types, and the movement if the gossip should be controlled by the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
047 run function of the type of the record they shadow. The [[#run]] function
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
048 below does NOT call this function."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 [gossip world new-location]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
050 (let [id (cond
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
051 (map? gossip)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
052 (-> world :gossips gossip :id)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
053 (keyword? gossip)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
054 gossip)]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
055 (deep-merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
056 world
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
057 {:gossips
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
058 {id
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
059 {:location new-location}}})))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
060
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
061 (defn run
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
062 "Return a world like this `world`, with news items exchanged between gossip
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
063 agents."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
064 [world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
065 (gather-news world))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
260
docs/cloverage/the_great_game/merchants/markets.clj.html
Normal file
260
docs/cloverage/the_great_game/merchants/markets.clj.html
Normal file
|
@ -0,0 +1,260 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/merchants/markets.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.merchants.markets
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Adjusting quantities and prices in markets."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 (:require [taoensso.timbre :as l :refer [info error]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 [the-great-game.utils :refer [deep-merge]]))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
005
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
006 (defn new-price
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 "If `stock` is greater than the maximum of `supply` and `demand`, then
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 there is surplus and `old` price is too high, so shold be reduced. If
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
009 lower, then it is too low and should be increased."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
010 [old stock supply demand]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
011 (let
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
012 [delta (dec' (/ (max supply demand 1) (max stock 1)))
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
013 scaled (/ delta 100)]
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
014 (+ old scaled)))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
015
|
||||
</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 adjust-quantity-and-price
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
018 "Adjust the quantity of this `commodity` currently in stock in this `city`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 of this `world`. Return a fragmentary world which can be deep-merged into
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
020 this world."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
021 [world city commodity]
|
||||
</span><br/>
|
||||
<span class="partial" title="2 out of 4 forms covered">
|
||||
022 (let [c (cond
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
023 (keyword? city) (-> world :cities city)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
024 (map? city) city)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
025 id (:id c)
|
||||
</span><br/>
|
||||
<span class="partial" title="9 out of 10 forms covered">
|
||||
026 p (or (-> c :prices commodity) 0)
|
||||
</span><br/>
|
||||
<span class="covered" title="10 out of 10 forms covered">
|
||||
027 d (or (-> c :demands commodity) 0)
|
||||
</span><br/>
|
||||
<span class="partial" title="9 out of 10 forms covered">
|
||||
028 st (or (-> c :stock commodity) 0)
|
||||
</span><br/>
|
||||
<span class="partial" title="9 out of 10 forms covered">
|
||||
029 su (or (-> c :supplies commodity) 0)
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
030 decrement (min st d)
|
||||
</span><br/>
|
||||
<span class="partial" title="3 out of 6 forms covered">
|
||||
031 increment (cond
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
032 ;; if we've two turns' production of this commodity in
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
033 ;; stock, halt production
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
034 (> st (* su 2))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
035 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
036 ;; if it is profitable to produce this commodity, the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
037 ;; craftspeople of the city will do so.
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
038 (> p 1) su
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
039 ;; otherwise, if there isn't a turn's production in
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
040 ;; stock, top up the stock, so that there's something for
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
041 ;; incoming merchants to buy
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
042 (> su st)
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
043 (- su st)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
044 :else
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
045 0)
|
||||
</span><br/>
|
||||
<span class="covered" title="6 out of 6 forms covered">
|
||||
046 n (new-price p st su d)]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
047 (if
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
048 (not= p n)
|
||||
</span><br/>
|
||||
<span class="covered" title="26 out of 26 forms covered">
|
||||
049 (l/info "Price of" commodity "at" id "has changed from" (float p) "to" (float n)))
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
050 {:cities {id
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
051 {:stock
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
052 {commodity (+ (- st decrement) increment)}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
053 :prices
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
054 {commodity n}}}}))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
055
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
056
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
057 (defn update-markets
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
058 "Return a world like this `world`, with quantities and prices in markets
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
059 updated to reflect supply and demand. If `city` or `city` and `commodity`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
060 are specified, return a fragmentary world with only the changes for that
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
061 `city` (and `commodity` if specified) populated."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
062 ([world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
063 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
064 deep-merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
065 world
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
066 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
067 #(update-markets world %)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
068 (keys (:cities world)))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
069 ([world city]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
070 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
071 deep-merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
072 {}
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 8 forms covered">
|
||||
073 (map #(update-markets world city %)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
074 (keys (:commodities world)))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
075 ([world city commodity]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
076 (adjust-quantity-and-price world city commodity)))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
077
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
078
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
079 (defn run
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
080 "Return a world like this `world`, with quantities and prices in markets
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
081 updated to reflect supply and demand."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
082 [world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
083 (update-markets world))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
084
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
284
docs/cloverage/the_great_game/merchants/merchant_utils.clj.html
Normal file
284
docs/cloverage/the_great_game/merchants/merchant_utils.clj.html
Normal file
|
@ -0,0 +1,284 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/merchants/merchant_utils.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.merchants.merchant-utils
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Useful functions for doing low-level things with merchants.")
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
003
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
004 (defn expected-price
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 "Find the price anticipated, given this `world`, by this `merchant` for
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 this `commodity` in this `city`. If no information, assume 1.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 `merchant` should be passed as a map, `commodity` and `city` should be passed as keywords."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 [merchant commodity city]
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
009 (or
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
010 (:price
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
011 (last
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
012 (sort-by
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
013 :date
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
014 (-> merchant :known-prices city commodity))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
015 1))
|
||||
</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 burden
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
018 "The total weight of the current cargo carried by this `merchant` in this
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 `world`."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
020 [merchant world]
|
||||
</span><br/>
|
||||
<span class="partial" title="3 out of 4 forms covered">
|
||||
021 (let [m (cond
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
022 (keyword? merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
023 (-> world :merchants merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
024 (map? merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
025 merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
026 cargo (:stock m)]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
027 (reduce
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
028 +
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
029 0
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
030 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 12 forms covered">
|
||||
031 #(* (cargo %) (-> world :commodities % :weight))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
032 (keys cargo)))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
033
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
034
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
035 (defn can-carry
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
036 "Return the number of units of this `commodity` which this `merchant`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
037 can carry in this `world`, given their current burden."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
038 [merchant world commodity]
|
||||
</span><br/>
|
||||
<span class="partial" title="3 out of 4 forms covered">
|
||||
039 (let [m (cond
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
040 (keyword? merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
041 (-> world :merchants merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
042 (map? merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
043 merchant)]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
044 (quot
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
045 (- (:capacity m) (burden m world))
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
046 (-> world :commodities commodity :weight))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
047
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
048 (defn can-afford
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 "Return the number of units of this `commodity` which this `merchant`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
050 can afford to buy in this `world`."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
051 [merchant world commodity]
|
||||
</span><br/>
|
||||
<span class="partial" title="3 out of 4 forms covered">
|
||||
052 (let [m (cond
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
053 (keyword? merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
054 (-> world :merchants merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
055 (map? merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
056 merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
057 l (:location m)]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
058 (quot
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
059 (:cash m)
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
060 (-> world :cities l :prices commodity))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
061
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
062 (defn add-stock
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
063 "Where `a` and `b` are both maps all of whose values are numbers, return
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
064 a map whose keys are a union of the keys of `a` and `b` and whose values
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
065 are the sums of their respective values."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
066 [a b]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
067 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
068 merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
069 a
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
070 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 21 forms covered">
|
||||
071 #(hash-map % (+ (or (a %) 0) (or (b %) 0)))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
072 (keys b))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
073
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
074 (defn add-known-prices
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
075 "Add the current prices at this `merchant`'s location in the `world`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
076 to a new cacke of known prices, and return it."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
077 [merchant world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
078 (let [m (cond
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
079 (keyword? merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
080 (-> world :merchants merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
081 (map? merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
082 merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
083 k (:known-prices m)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
084 l (:location m)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
085 d (:date world)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
086 p (-> world :cities l :prices)]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
087 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
088 merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
089 k
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
090 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 17 forms covered">
|
||||
091 #(hash-map % (apply vector cons {:price (p %) :date d} (k %)))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
092 (-> world :commodities keys)))))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
92
docs/cloverage/the_great_game/merchants/merchants.clj.html
Normal file
92
docs/cloverage/the_great_game/merchants/merchants.clj.html
Normal file
|
@ -0,0 +1,92 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/merchants/merchants.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.merchants.merchants
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Trade planning for merchants, primarily."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 (:require [taoensso.timbre :as l :refer [info error spy]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 [the-great-game.utils :refer [deep-merge]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 [the-great-game.merchants.strategies.simple :refer [move-merchant]]))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
006
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
007
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
008 (defn run
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
009 "Return a partial world based on this `world`, but with each merchant moved."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
010 [world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
011 (try
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
012 (reduce
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
013 deep-merge
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
014 world
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
015 (map
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
016 #(try
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
017 (let [move-fn (or
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
018 (-> world :merchants % :move-fn)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 move-merchant)]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
020 (apply move-fn (list % world)))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
021 (catch Exception any
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 17 forms covered">
|
||||
022 (l/error any "Failure while moving merchant " %)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
023 {}))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
024 (keys (:merchants world))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
025 (catch Exception any
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 16 forms covered">
|
||||
026 (l/error any "Failure while moving merchants")
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
027 world)))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
028
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
485
docs/cloverage/the_great_game/merchants/planning.clj.html
Normal file
485
docs/cloverage/the_great_game/merchants/planning.clj.html
Normal file
|
@ -0,0 +1,485 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/merchants/planning.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.merchants.planning
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Trade planning for merchants, primarily. This follows a simple-minded
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 generate-and-test strategy and currently generates plans for all possible
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 routes from the current location. This may not scale. Also, routes do not
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 currently have cost or risk associated with them."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 (:require [the-great-game.utils :refer [deep-merge make-target-filter]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 [the-great-game.merchants.merchant-utils :refer :all]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 [the-great-game.world.routes :refer [find-route]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
009 [the-great-game.world.world :refer [actual-price default-world]]))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
010
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
011 (defn generate-trade-plans
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
012 "Generate all possible trade plans for this `merchant` and this `commodity`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
013 in this `world`.
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
014
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
015 Returned plans are maps with keys:
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
016
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
017 * :merchant - the id of the `merchant` for whom the plan was created;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
018 * :origin - the city from which the trade starts;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 * :destination - the city to which the trade is planned;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
020 * :commodity - the `commodity` to be carried;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
021 * :buy-price - the price at which that `commodity` can be bought;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
022 * :expected-price - the price at which the `merchant` anticipates
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
023 that `commodity` can be sold;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
024 * :distance - the number of stages in the planned journey
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
025 * :dist-to-home - the distance from `destination` to the `merchant`'s
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
026 home city."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
027 [merchant world commodity]
|
||||
</span><br/>
|
||||
<span class="partial" title="3 out of 4 forms covered">
|
||||
028 (let [m (cond
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
029 (keyword? merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
030 (-> world :merchants merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
031 (map? merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
032 merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
033 origin (:location m)]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
034 (map
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
035 #(hash-map
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
036 :merchant (:id m)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
037 :origin origin
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
038 :destination %
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
039 :commodity commodity
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
040 :buy-price (actual-price world commodity origin)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
041 :expected-price (expected-price
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
042 m
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
043 commodity
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
044 %)
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
045 :distance (count
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
046 (find-route world origin %))
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
047 :dist-to-home (count
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
048 (find-route
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
049 world
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
050 (:home m)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
051 %)))
|
||||
</span><br/>
|
||||
<span class="covered" title="12 out of 12 forms covered">
|
||||
052 (remove #(= % origin) (-> world :cities keys)))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
053
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
054 (defn nearest-with-targets
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
055 "Return the distance to the nearest destination among those of these
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
056 `plans` which match these `targets`. Plans are expected to be plans
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
057 as returned by `generate-trade-plans`, q.v.; `targets` are expected to be
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
058 as accepted by `make-target-filter`, q.v."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
059 [plans targets]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
060 (apply
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
061 min
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
062 (map
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
063 :distance
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
064 (filter
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
065 (make-target-filter targets)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
066 plans))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
067
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
068 (defn plan-trade
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
069 "Find the best destination in this `world` for this `commodity` given this
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
070 `merchant` and this `origin`. If two cities are anticipated to offer the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
071 same price, the nearer should be preferred; if two are equally distant, the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
072 ones nearer to the merchant's home should be preferred.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
073 `merchant` may be passed as a map or a keyword; `commodity` should be
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
074 passed as a keyword.
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
075
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
076 The returned plan is a map with keys:
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
077
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
078 * :merchant - the id of the `merchant` for whom the plan was created;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
079 * :origin - the city from which the trade starts;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
080 * :destination - the city to which the trade is planned;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
081 * :commodity - the `commodity` to be carried;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
082 * :buy-price - the price at which that `commodity` can be bought;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
083 * :expected-price - the price at which the `merchant` anticipates
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
084 that `commodity` can be sold;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
085 * :distance - the number of stages in the planned journey
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
086 * :dist-to-home - the distance from `destination` to the `merchant`'s
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
087 home city."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
088 [merchant world commodity]
|
||||
</span><br/>
|
||||
<span class="covered" title="6 out of 6 forms covered">
|
||||
089 (let [plans (generate-trade-plans merchant world commodity)
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
090 best-prices (filter
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
091 (make-target-filter
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
092 [[:expected-price
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
093 (apply
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
094 max
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
095 (filter number? (map :expected-price plans)))]])
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
096 plans)]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
097 (first
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
098 (sort-by
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
099 ;; all other things being equal, a merchant would prefer to end closer
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
100 ;; to home.
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
101 #(- 0 (:dist-to-home %))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
102 ;; a merchant will seek the best price, but won't go further than
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
103 ;; needed to get it.
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
104 (filter
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
105 (make-target-filter
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
106 [[:distance
|
||||
</span><br/>
|
||||
<span class="covered" title="10 out of 10 forms covered">
|
||||
107 (apply min (filter number? (map :distance best-prices)))]])
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
108 best-prices)))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
109
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
110 (defn augment-plan
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
111 "Augment this `plan` constructed in this `world` for this `merchant` with
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
112 the `:quantity` of goods which should be bought and the `:expected-profit`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
113 of the trade.
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
114
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
115 Returns the augmented plan."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
116 [merchant world plan]
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
117 (let [c (:commodity plan)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
118 o (:origin plan)
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
119 q (min
|
||||
</span><br/>
|
||||
<span class="partial" title="4 out of 5 forms covered">
|
||||
120 (or
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
121 (-> world :cities o :stock c)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
122 0)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
123 (can-carry merchant world c)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
124 (can-afford merchant world c))
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
125 p (* q (- (:expected-price plan) (:buy-price plan)))]
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
126 (assoc plan :quantity q :expected-profit p)))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
127
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
128 (defn select-cargo
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
129 "A `merchant`, in a given location in a `world`, will choose to buy a cargo
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
130 within the limit they are capable of carrying, which they can anticipate
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
131 selling for a profit at a destination."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
132 [merchant world]
|
||||
</span><br/>
|
||||
<span class="partial" title="2 out of 4 forms covered">
|
||||
133 (let [m (cond
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
134 (keyword? merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
135 (-> world :merchants merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
136 (map? merchant)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 1 forms covered">
|
||||
137 merchant)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
138 origin (:location m)
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
139 available (-> world :cities origin :stock)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
140 plans (map
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
141 #(augment-plan
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
142 m
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
143 world
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
144 (plan-trade m world %))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
145 (filter
|
||||
</span><br/>
|
||||
<span class="covered" title="10 out of 10 forms covered">
|
||||
146 #(let [q (-> world :cities origin :stock %)]
|
||||
</span><br/>
|
||||
<span class="partial" title="9 out of 10 forms covered">
|
||||
147 (and (number? q) (pos? q)))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
148 (keys available)))]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
149 (if
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
150 (not (empty? plans))
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
151 (first
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
152 (sort-by
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
153 #(- 0 (:dist-to-home %))
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
154 (filter
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
155 (make-target-filter
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
156 [[:expected-profit
|
||||
</span><br/>
|
||||
<span class="covered" title="10 out of 10 forms covered">
|
||||
157 (apply max (filter number? (map :expected-profit plans)))]])
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
158 plans))))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
159
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,527 @@
|
|||
<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 8 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 6 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 17 forms covered">
|
||||
047 {:stock (assoc (:stock market) c (- (-> market :stock c) q))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 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 8 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 4 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 12 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 6 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 6 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 6 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 17 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 3 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>
|
113
docs/cloverage/the_great_game/utils.clj.html
Normal file
113
docs/cloverage/the_great_game/utils.clj.html
Normal file
|
@ -0,0 +1,113 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../coverage.css"/> <title> the_great_game/utils.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.utils)
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
002
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
003 (defn cyclic?
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 "True if two or more elements of `route` are identical"
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 [route]
|
||||
</span><br/>
|
||||
<span class="covered" title="10 out of 10 forms covered">
|
||||
006 (not= (count route)(count (set route))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
007
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
008 (defn deep-merge
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
009 "Recursively merges maps. Stolen from
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
010 https://dnaeon.github.io/recursively-merging-maps-in-clojure/"
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
011 [& maps]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
012 (letfn [(m [& xs]
|
||||
</span><br/>
|
||||
<span class="covered" title="17 out of 17 forms covered">
|
||||
013 (if (some #(and (map? %) (not (record? %))) xs)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
014 (apply merge-with m xs)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
015 (last xs)))]
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
016 (reduce m maps)))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
017
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
018 (defn make-target-filter
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 "Construct a filter which, when applied to a list of maps,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
020 will pass those which match these `targets`, where each target
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
021 is a tuple [key value]."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
022 ;; TODO: this would probably be more elegant as a macro
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
023 [targets]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
024 (eval
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
025 (list
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
026 'fn
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
027 (vector 'm)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
028 (cons
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
029 'and
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
030 (map
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
031 #(list
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
032 '=
|
||||
</span><br/>
|
||||
<span class="covered" title="6 out of 6 forms covered">
|
||||
033 (list (first %) 'm)
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
034 (nth % 1))
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
035 targets)))))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
173
docs/cloverage/the_great_game/world/routes.clj.html
Normal file
173
docs/cloverage/the_great_game/world/routes.clj.html
Normal file
|
@ -0,0 +1,173 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/world/routes.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.world.routes
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Conceptual (plan level) routes, represented as tuples of location ids."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 (:require [the-great-game.utils :refer [cyclic?]]))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
004
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
005 (defn find-routes
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 "Find routes from among these `routes` from `from`; if `to` is supplied,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 to `to`, by breadth-first search."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 ([routes from]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
009 (map
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
010 (fn [to] (cons from to))
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
011 (remove
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
012 empty?
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
013 (map
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
014 (fn [route]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
015 (remove
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
016 #(= from %)
|
||||
</span><br/>
|
||||
<span class="covered" title="10 out of 10 forms covered">
|
||||
017 (if (some #(= % from) route) route)))
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
018 routes))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 ([routes from to]
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
020 (let [steps (find-routes routes from)
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
021 found (filter
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
022 (fn [step] (if (some #(= to %) step) step))
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
023 steps)]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
024 (if
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
025 (empty? found)
|
||||
</span><br/>
|
||||
<span class="covered" title="6 out of 6 forms covered">
|
||||
026 (find-routes routes from to steps)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
027 found)))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
028 ([routes from to steps]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
029 (if
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
030 (not (empty? steps))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
031 (let [paths (remove
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
032 cyclic?
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
033 (mapcat
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
034 (fn [path]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
035 (map
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
036 (fn [x] (concat path (rest x)))
|
||||
</span><br/>
|
||||
<span class="covered" title="6 out of 6 forms covered">
|
||||
037 (find-routes routes (last path))))
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
038 steps))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
039 found (filter
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
040 #(= (last %) to) paths)]
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
041 (if
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
042 (empty? found)
|
||||
</span><br/>
|
||||
<span class="covered" title="6 out of 6 forms covered">
|
||||
043 (find-routes routes from to paths)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
044 found)))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
045
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
046 (defn find-route
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
047 "Find a single route from `from` to `to` in this `world-or-routes`, which
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
048 may be either a world as defined in [[the-great-game.world.world]] or else
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 a sequence of tuples of keywords."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
050 [world-or-routes from to]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
051 (first
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
052 (find-routes
|
||||
</span><br/>
|
||||
<span class="partial" title="7 out of 8 forms covered">
|
||||
053 (or (:routes world-or-routes) world-or-routes)
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
054 from
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
055 to)))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
125
docs/cloverage/the_great_game/world/run.clj.html
Normal file
125
docs/cloverage/the_great_game/world/run.clj.html
Normal file
|
@ -0,0 +1,125 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/world/run.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.world.run
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Run the whole simulation"
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 (:require [environ.core :refer [env]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 [taoensso.timbre :as timbre]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 [taoensso.timbre.appenders.3rd-party.rotor :as rotor]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 [the-great-game.gossip.gossip :as g]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 [the-great-game.merchants.merchants :as m]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 [the-great-game.merchants.markets :as k]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
009 [the-great-game.world.world :as w]))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
010
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
011 (defn init
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
012 ([]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
013 (init {}))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
014 ([config]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
015 (timbre/merge-config!
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
016 {:appenders
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
017 {:rotor (rotor/rotor-appender
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
018 {:path "the-great-game.log"
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
019 :max-size (* 512 1024)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
020 :backlog 10})}
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 9 forms covered">
|
||||
021 :level (or
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
022 (:log-level config)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
023 (if (env :dev) :debug)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
024 :info)})))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
025
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
026 (defn run
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
027 "The pipeline to run the simulation each game day. Returns a world like
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
028 this world, with all the various active elements updated. The optional
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
029 `date` argument, if supplied, is set as the `:date` of the returned world."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
030 ([world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
031 (g/run
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
032 (m/run
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
033 (k/run
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
034 (w/run world)))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
035 ([world date]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
036 (g/run
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
037 (m/run
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
038 (k/run
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 4 forms covered">
|
||||
039 (w/run world date))))))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
584
docs/cloverage/the_great_game/world/world.clj.html
Normal file
584
docs/cloverage/the_great_game/world/world.clj.html
Normal file
|
@ -0,0 +1,584 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="../../coverage.css"/> <title> the_great_game/world/world.clj </title>
|
||||
</head>
|
||||
<body>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
001 (ns the-great-game.world.world
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
002 "Access to data about the world")
|
||||
</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 world has to work either as map or a database. Initially, and for
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005 ;;; unit tests, I'll use a map; later, there will be a database. But the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 ;;; API needs to be agnostic, so that heirarchies which interact with
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
007 ;;; `world` don't have to know which they've got - as far as they're concerned
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 ;;; it's just a handle.
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
009
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
010 (def default-world
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
011 "A basic world for testing concepts"
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
012 {:date 0 ;; the age of this world in game days
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
013 :cities
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
014 {:aberdeen
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
015 {:id :aberdeen
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
016 :supplies
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
017 ;; `supplies` is the quantity of each commodity added to the stock
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
018 ;; each game day. If the price in the market is lower than 1 (the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 ;; cost of production of a unit) no goods will be added.
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
020 {:fish 10
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
021 :leather 5}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
022 :demands
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
023 ;; `stock` is the quantity of each commodity in the market at any
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
024 ;; given time. It is adjusted for production and consumption at
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
025 ;; the end of each game day.
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
026 {:iron 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
027 :cloth 10
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
028 :whisky 10}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
029 :port true
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
030 :prices
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
031 ;; `prices`: the current price (both buying and selling, for simplicity)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
032 ;; of each commodity in the market. Updated each game day based on current
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
033 ;; stock.
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
034 {:cloth 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
035 :fish 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
036 :leather 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
037 :iron 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
038 :whisky 1}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
039 :stock
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
040 ;; `stock` is the quantity of each commodity in the market at any
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
041 ;; given time. It is adjusted for production and consumption at
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
042 ;; the end of each game day.
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
043 {:cloth 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
044 :fish 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
045 :leather 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
046 :iron 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
047 :whisky 0}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
048 :cash 100}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 :buckie
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
050 {:id :buckie
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
051 :supplies
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
052 {:fish 20}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
053 :demands
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
054 {:cloth 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
055 :leather 3
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
056 :whisky 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
057 :iron 1}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
058 :port true
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
059 :prices {:cloth 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
060 :fish 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
061 :leather 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
062 :iron 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
063 :whisky 1}
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
064 :stock {:cloth 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
065 :fish 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
066 :leather 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
067 :iron 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
068 :whisky 0}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
069 :cash 100}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
070 :callander
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
071 {:id :callander
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
072 :supplies {:leather 20}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
073 :demands
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
074 {:cloth 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
075 :fish 3
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
076 :whisky 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
077 :iron 1}
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
078 :prices {:cloth 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
079 :fish 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
080 :leather 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
081 :iron 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
082 :whisky 1}
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
083 :stock {:cloth 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
084 :fish 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
085 :leather 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
086 :iron 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
087 :whisky 0}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
088 :cash 100}
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
089 :dundee {:id :dundee}
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
090 :edinburgh {:id :dundee}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
091 :falkirk
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
092 {:id :falkirk
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
093 :supplies {:iron 10}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
094 :demands
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
095 {:cloth 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
096 :leather 3
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
097 :whisky 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
098 :fish 10}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
099 :port true
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
100 :prices {:cloth 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
101 :fish 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
102 :leather 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
103 :iron 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
104 :whisky 1}
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
105 :stock {:cloth 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
106 :fish 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
107 :leather 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
108 :iron 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
109 :whisky 0}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
110 :cash 100}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
111 :glasgow
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
112 {:id :glasgow
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
113 :supplies {:whisky 10}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
114 :demands
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
115 {:cloth 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
116 :leather 3
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
117 :iron 5
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
118 :fish 10}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
119 :port true
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
120 :prices {:cloth 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
121 :fish 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
122 :leather 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
123 :iron 1
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
124 :whisky 1}
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
125 :stock {:cloth 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
126 :fish 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
127 :leather 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
128 :iron 0
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
129 :whisky 0}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
130 :cash 100}}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
131 :merchants
|
||||
</span><br/>
|
||||
<span class="covered" title="20 out of 20 forms covered">
|
||||
132 {:archie {:id :archie
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
133 :home :aberdeen :location :aberdeen :cash 100 :capacity 10
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
134 :known-prices {}
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
135 :stock {}}
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
136 :belinda {:id :belinda
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
137 :home :buckie :location :buckie :cash 100 :capacity 10
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
138 :known-prices {}
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
139 :stock {}}
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
140 :callum {:id :callum
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
141 :home :callander :location :calander :cash 100 :capacity 10
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
142 :known-prices {}
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
143 :stock {}}
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
144 :deirdre {:id :deidre
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
145 :home :dundee :location :dundee :cash 100 :capacity 10
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
146 :known-prices {}
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
147 :stock {}}
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
148 :euan {:id :euan
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
149 :home :edinbirgh :location :edinburgh :cash 100 :capacity 10
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
150 :known-prices {}
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
151 :stock {}}
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
152 :fiona {:id :fiona
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
153 :home :falkirk :location :falkirk :cash 100 :capacity 10
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
154 :known-prices {}
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
155 :stock {}}}
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
156 :routes
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
157 ;; all routes can be traversed in either direction and are assumed to
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
158 ;; take the same amount of time.
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
159 [[:aberdeen :buckie]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
160 [:aberdeen :dundee]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
161 [:callander :glasgow]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
162 [:dundee :callander]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
163 [:dundee :edinburgh]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
164 [:dundee :falkirk]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
165 [:edinburgh :falkirk]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
166 [:falkirk :glasgow]]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
167 :commodities
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
168 ;; cost of commodities is expressed in person/days;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
169 ;; weight in packhorse loads. Transport in this model
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
170 ;; is all overland; you don't take bulk cargoes overland
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
171 ;; in this period, it's too expensive.
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
172 {:cloth {:id :cloth :cost 1 :weight 0.25}
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
173 :fish {:id :fish :cost 1 :weight 1}
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
174 :leather {:id :leather :cost 1 :weight 0.5}
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
175 :whisky {:id :whisky :cost 1 :weight 0.1}
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
176 :iron {:id :iron :cost 1 :weight 10}}})
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
177
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
178 (defn actual-price
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
179 "Find the actual current price of this `commodity` in this `city` given
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
180 this `world`. **NOTE** that merchants can only know the actual prices in
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
181 the city in which they are currently located."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
182 [world commodity city]
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
183 (-> world :cities city :prices commodity))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
184
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
185 (defn run
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
186 "Return a world like this `world` with only the `:date` to this `date`
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
187 (or id `date` not supplied, the current value incremented by one). For
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
188 running other aspects of the simulation, see [[the-great-game.world.run]]."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
189 ([world]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 13 forms covered">
|
||||
190 (run world (inc (or (:date world) 0))))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
191 ([world date]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 5 forms covered">
|
||||
192 (assoc world :date date)))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
33
docs/codox/economy.html
Normal file
33
docs/codox/economy.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html PUBLIC ""
|
||||
"">
|
||||
<html><head><meta charset="UTF-8" /><title>Game world economy</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</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="economy.html"><div class="inner"><span>Game world economy</span></div></a></li><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li><li class="depth-1 "><a href="modelling_trading_cost_and_risk.html"><div class="inner"><span>Modelling trading cost and risk</span></div></a></li><li class="depth-1 "><a href="sexual-dimorphism.html"><div class="inner"><span>Sexual dimorphism</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 branch"><a href="the-great-game.merchants.merchant-utils.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchant-utils</span></div></a></li><li class="depth-3 branch"><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-3 branch"><a href="the-great-game.merchants.planning.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>planning</span></div></a></li><li class="depth-3"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>strategies</span></div></div></li><li class="depth-4"><a href="the-great-game.merchants.strategies.simple.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simple</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -207px;"><span class="top" style="height: 216px;"></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="#game-world-economy" name="game-world-economy"></a>Game world economy</h1>
|
||||
<p>Broadly this essay extends ideas presented in <a href="https://blog.journeyman.cc/2013/07/populating-game-world.html">Populating a game world</a>, q.v.</p>
|
||||
<h2><a href="#primary-producers" name="primary-producers"></a>Primary producers</h2>
|
||||
<h3><a href="#herdsfolk" name="herdsfolk"></a>Herdsfolk</h3>
|
||||
<p>Herdsfolk are nomadic; it’s reasonable to think they’ll bring their herds to market, rather than selling it lots of tiny markets. So in the spring, shepherds will visit specific towns at the edge of open land, to hold a shearing festival/carnevale; and that both shepherds and cattle herders will visit towns on the edge of open land to sell fatstock in the autumn.</p>
|
||||
<h3><a href="#miners" name="miners"></a>Miners</h3>
|
||||
<p>Miners mine. They’re settled, but they’re settled usually in specialist settlements at the location where the ore body is accessible, usually in mountenous territory. They’ll consume a lot of food, so there will be a local market for foodstuffs encouraging local farming. Different mines obviously mine different ores, but, for example, lead and silver are frequently found together.</p>
|
||||
<h3><a href="#foresters" name="foresters"></a>Foresters</h3>
|
||||
<p>Foresters are more or less settled at the edge of forests, at locations from which timber can be moved by navigable water; again in specialist settlements. In addition to timber, foresters hunt and produce both meat and furs, so have less need for other food producers locally.</p>
|
||||
<h3><a href="#farmers" name="farmers"></a>Farmers</h3>
|
||||
<p>Farmers are settled. Farmers occupy standard runrig plots, but because they don’t employ journeymen or apprentices, and don’t have workshops, the plots are mostly open with little building. Most farmers are ‘mixed farmers’, producing cereals, meat, eggs and milk. Some will be more specialist. Farm produce, taken broadly to include orchardsfolk, include:</p>
|
||||
<ul>
|
||||
<li>meat</li>
|
||||
<li>milk and milk products</li>
|
||||
<li>hides</li>
|
||||
<li>eggs</li>
|
||||
<li>cereals</li>
|
||||
<li>root vegetables, onions, etc</li>
|
||||
<li>peas and beans</li>
|
||||
<li>leaf vegetables</li>
|
||||
<li>fruits</li>
|
||||
<li>fibres: linen, hemp and silk (from silk-moths in mulberry orchards)</li>
|
||||
<li>possibly other stuff I’ve forgotten.</li>
|
||||
</ul>
|
||||
<p>Farmers are all basically subsistence farmers, farming first to feed their own household and selling only surplus in the market.</p>
|
||||
<h2><a href="#crafts" name="crafts"></a>Crafts</h2>
|
||||
<p>Crafts generally process primary goods into secondary goods - whether intermediate stages or final consumer items. Some elite ‘crafts’ deal with abstract primary goods like law and knowledge, and they may be seen as somewhat separate.</p>
|
||||
<p>A master craftsperson occupies a standard runrig plot, much like a farmer’s plot. Like a farmer, a poor master crafter household will cultivate part of the plot to produce food for the house - at least grow vegetables and keep hens. However, as the crafter takes on apprentices and journeymen - and gets richer - more buildings will be required as accommodation, workshop space and materials stores.</p>
|
||||
<p>Generally, primary goods aren’t transported over land - because overland transport is expensive, by the time they’ve been transported they’re no longer low cost goods. So often the craftspeople who process primary produce into at least commodity intermediate forms will live close to the source of the primary goods.</p>
|
||||
<p>So, for example, the town(s) where the shepherds hold their shearing fairs will tend to have a lot of weavers. While around mines there will be smelters producing ingots and bar stock to be marketed to smiths all over the place, there will also be smiths close to the mines producing commodity tools and weapons.</p>
|
||||
<p>See the table in Populating a game world.</p></div></div></div></body></html>
|
3
docs/codox/index.html
Normal file
3
docs/codox/index.html
Normal file
File diff suppressed because one or more lines are too long
|
@ -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>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>
|
||||
<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</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="economy.html"><div class="inner"><span>Game world economy</span></div></a></li><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li><li class="depth-1 "><a href="modelling_trading_cost_and_risk.html"><div class="inner"><span>Modelling trading cost and risk</span></div></a></li><li class="depth-1 "><a href="sexual-dimorphism.html"><div class="inner"><span>Sexual dimorphism</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 branch"><a href="the-great-game.merchants.merchant-utils.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchant-utils</span></div></a></li><li class="depth-3 branch"><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-3 branch"><a href="the-great-game.merchants.planning.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>planning</span></div></a></li><li class="depth-3"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>strategies</span></div></div></li><li class="depth-4"><a href="the-great-game.merchants.strategies.simple.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simple</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -207px;"><span class="top" style="height: 216px;"></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 I’m going to try to pull together a number of my architectural ideas about the Great Game which I know I’m never actually going to build - because it’s vastly too big for any one person to build - into one overall vision.</p>
|
||||
<p>So, firstly, how does one characterise this game?</p>
|
7
docs/codox/modelling_trading_cost_and_risk.html
Normal file
7
docs/codox/modelling_trading_cost_and_risk.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html PUBLIC ""
|
||||
"">
|
||||
<html><head><meta charset="UTF-8" /><title>Modelling trading cost and risk</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</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="economy.html"><div class="inner"><span>Game world economy</span></div></a></li><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li><li class="depth-1 current"><a href="modelling_trading_cost_and_risk.html"><div class="inner"><span>Modelling trading cost and risk</span></div></a></li><li class="depth-1 "><a href="sexual-dimorphism.html"><div class="inner"><span>Sexual dimorphism</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 branch"><a href="the-great-game.merchants.merchant-utils.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchant-utils</span></div></a></li><li class="depth-3 branch"><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-3 branch"><a href="the-great-game.merchants.planning.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>planning</span></div></a></li><li class="depth-3"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>strategies</span></div></div></li><li class="depth-4"><a href="the-great-game.merchants.strategies.simple.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simple</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -207px;"><span class="top" style="height: 216px;"></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="#modelling-trading-cost-and-risk" name="modelling-trading-cost-and-risk"></a>Modelling trading cost and risk</h1>
|
||||
<p>In a dynamic pre-firearms world with many small states and contested regions, trade is not going to be straightforward. Not only will different routes have different physical characteristics - more or less mountainous, more or fewer unbridged river crossings - they will also have different political characteristics: more of less taxed, more or less effectively policed.</p>
|
||||
<p>Raids by outlaws are expected to be part of the game economy. News of raids are the sort of things which may propagate through the <a href="null">gossip</a> system. So are changes in taxation regime. Obviously, knowledge items can affect merchants’ trading strategy; in existing prototype code, individual merchants already each keep their own cache of known historical prices, and exchange historical price data with one another; and use this price data to select trades to make.</p>
|
||||
<p>So: to what extent is it worth modelling the spread of knowledge of trade cost and risk?</p>
|
||||
<p>Obviously the more we model, the more compute power modelling consumes. If the core objective is a Role Playing Games as currently understood, then there is no need to model very complex trade risk assessment behaviour.</p></div></div></div></body></html>
|
28
docs/codox/sexual-dimorphism.html
Normal file
28
docs/codox/sexual-dimorphism.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html PUBLIC ""
|
||||
"">
|
||||
<html><head><meta charset="UTF-8" /><title>Sexual dimorphism</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</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="economy.html"><div class="inner"><span>Game world economy</span></div></a></li><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to the-great-game</span></div></a></li><li class="depth-1 "><a href="modelling_trading_cost_and_risk.html"><div class="inner"><span>Modelling trading cost and risk</span></div></a></li><li class="depth-1 current"><a href="sexual-dimorphism.html"><div class="inner"><span>Sexual dimorphism</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 branch"><a href="the-great-game.merchants.merchant-utils.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>merchant-utils</span></div></a></li><li class="depth-3 branch"><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-3 branch"><a href="the-great-game.merchants.planning.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>planning</span></div></a></li><li class="depth-3"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>strategies</span></div></div></li><li class="depth-4"><a href="the-great-game.merchants.strategies.simple.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simple</span></div></a></li><li class="depth-2 branch"><a href="the-great-game.utils.html"><div class="inner"><span class="tree" style="top: -207px;"><span class="top" style="height: 216px;"></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="#sexual-dimorphism" name="sexual-dimorphism"></a>Sexual dimorphism</h1>
|
||||
<p>This essay is going to upset a lot of people, so let’s start with a statement of what it is about: it is an attempt to describe the systematically different behaviours of men and women, in sufficient detail that this can be represented by agents in a game world. It’s trying to allow as broad as possible a range of cultures to be represented, so when I’m talking about what I consider to be behaviours of particular cultures, I’ll say that.</p>
|
||||
<p>Of course, I’m writing this from the view point of an old white male. It’s not possible to write about these things from a totally neutral viewpoint, and every one of us will have prejudices.</p>
|
||||
<p>OK? Let’s start.</p>
|
||||
<p>When a man and a woman have sex, there’s a non-zero chance that the woman will get pregnant. There’s a zero chance that the male will get pregnant.</p>
|
||||
<p>A woman can typically give birth to of the order of twelve children in the course of her life, and each childbirth involves a non-zero risk of death. If modelling the sort of bronze-age-to-late-medieval cultures I’m generally considering, there are no available reliable methods of contraception, although their may be, for example, known spermicidal or abortifacient spells or potions. If it’s abortifacient, that’s pretty unpleasant for the woman, too.</p>
|
||||
<p>Children, especially when young, are very vulnerable and need protection. Children with good protection are much more likely to survive to adulthood. Raising children involves a fair amount of work.</p>
|
||||
<p>For all sorts of reasons, some of which are clearly cultural but others of which are fundamental, it’s much easier for men to walk away from responsibility for their children than it is for women. For example, considering a pre-modern world, women would always know for certain which children were theirs, and men would not.</p>
|
||||
<p>For a woman, consequently, the best breeding strategy is to have sex only with men who will be ‘good fathers’, where there are three essential parameters to “good fathers”:</p>
|
||||
<ol>
|
||||
<li>Desirable genetic traits;</li>
|
||||
<li>Preparedness to stick around and share the work;</li>
|
||||
<li>Ability to provide and protect.</li>
|
||||
</ol>
|
||||
<p>The essential trade-off in the traditional western marriage is that the man gets to have sex, and the woman gets to have protection for her progeny.</p>
|
||||
<p>Another significant point is that women’s ability to bear children ceases at a much younger age than men’s ability to father them.</p>
|
||||
<h2><a href="#why-have-sex-at-all-" name="why-have-sex-at-all-"></a>Why have sex at all?</h2>
|
||||
<p>If a character has ‘having children’ - the <strong>Ancestor</strong> aspiration, in my typology - as their key aim, then they will want to have sex. But to have children in this sense is to have acknowledged children, so while a male character may be motivated to have multiple female partners, he will never the less have some degree of long term committment to them, and will want both to feel confident that the children are his and to be recognised by their father.</p>
|
||||
<p>From the point of view of seeking to become an Ancestor, there is little benefit to the woman in having multiple partners, except in very harsh environments. It will be easier to give one partner confidence that all your children are his, and while a man can increase his number of potential progeny by having multiple wives, mistresses or other classes of long-term female sexual partners, a woman cannot.</p>
|
||||
<h2><a href="#why-have-children-" name="why-have-children-"></a>Why have children?</h2>
|
||||
<p>In modern Scotland, I have met a lot of women with a strong drive to have children for the sake of having children, where the best explanation they could give is that it’s instinctual; it may be so. But beyond that, in many cultures children provide their (acknowledged) parents with care and security in their old age, may tend their graves and perform belief-related services after they die, and carry on their name and their stories into the future.</p>
|
||||
<p>Not everyone wants to have children; in thinking about the driving aspirations of game characters, I view having children one of six potential key aspirations.</p>
|
||||
<h2><a href="#why-else-have-sex-" name="why-else-have-sex-"></a>Why else have sex?</h2>
|
||||
<p>Sex, done right, is an extremely pleasant pastime. Sex can also be used to create and maintain bonds of committment, to demonstrate social status, to defuse tense situations, and transactionally in many ways, both formal and informal.</p>
|
||||
<p>For women, sex with other women carries with it no risk of pregnancy, so can be enjoyed or used for any of these purposes in very much the same way as it can by men; in other words, particularly for women, homosexual sex can be more lighthearted and carefree than heterosexual sex. To what extend our notions of homosexuality and heterosexuality are cultural I simply don’t know. But because no children will result, a woman can afford to be more promiscuous with other women than she can with men.</p>
|
||||
<h2><a href="#how-does-this-impact-on" name="how-does-this-impact-on"></a>How does this impact on</h2></div></div></div></body></html>
|
3
docs/codox/the-great-game.core.html
Normal file
3
docs/codox/the-great-game.core.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.gossip.gossip.html
Normal file
3
docs/codox/the-great-game.gossip.gossip.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.merchants.markets.html
Normal file
3
docs/codox/the-great-game.merchants.markets.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.merchants.merchant-utils.html
Normal file
3
docs/codox/the-great-game.merchants.merchant-utils.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.merchants.merchants.html
Normal file
3
docs/codox/the-great-game.merchants.merchants.html
Normal file
File diff suppressed because one or more lines are too long
26
docs/codox/the-great-game.merchants.planning.html
Normal file
26
docs/codox/the-great-game.merchants.planning.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.utils.html
Normal file
3
docs/codox/the-great-game.utils.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.world.routes.html
Normal file
3
docs/codox/the-great-game.world.routes.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.world.run.html
Normal file
3
docs/codox/the-great-game.world.run.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/the-great-game.world.world.html
Normal file
3
docs/codox/the-great-game.world.world.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,3 +0,0 @@
|
|||
<!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>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 don’t 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
|
@ -1,3 +0,0 @@
|
|||
<!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
21
project.clj
21
project.clj
|
@ -1,13 +1,28 @@
|
|||
(defproject the-great-game "0.1.0-SNAPSHOT"
|
||||
(defproject the-great-game "0.1.1-SNAPSHOT"
|
||||
:cloverage {:output "docs/cloverage"}
|
||||
:codox {:metadata {:doc "**TODO**: write docs"
|
||||
:doc/format :markdown}
|
||||
:output-path "docs"
|
||||
:output-path "docs/codox"
|
||||
:source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"}
|
||||
:dependencies [[org.clojure/clojure "1.8.0"]
|
||||
[environ "1.1.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"}
|
||||
:plugins [[lein-codox "0.10.3"]]
|
||||
:plugins [[lein-cloverage "1.1.1"]
|
||||
[lein-codox "0.10.7"]]
|
||||
|
||||
:release-tasks [["vcs" "assert-committed"]
|
||||
["change" "version" "leiningen.release/bump-version" "release"]
|
||||
["vcs" "commit"]
|
||||
["vcs" "tag" "v." "--no-sign"]
|
||||
["clean"]
|
||||
["codox"]
|
||||
["cloverage"]
|
||||
["uberjar"]
|
||||
["change" "version" "leiningen.release/bump-version"]
|
||||
["vcs" "commit"]]
|
||||
|
||||
:url "https://github.com/simon-brooke/the-great-game"
|
||||
)
|
||||
|
|
|
@ -49,9 +49,9 @@
|
|||
[gossip world new-location]
|
||||
(let [id (cond
|
||||
(map? gossip)
|
||||
(:id (-> world :gossipe gossip)
|
||||
(-> world :gossips gossip :id)
|
||||
(keyword? gossip)
|
||||
gossip))]
|
||||
gossip)]
|
||||
(deep-merge
|
||||
world
|
||||
{:gossips
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
(ns the-great-game.merchants.markets
|
||||
"Adjusting quantities and prices in markets."
|
||||
(:require [taoensso.timbre :as l :refer [info error]]
|
||||
[the-great-game.utils :refer [deep-merge]]
|
||||
[the-great-game.world.world :refer [actual-price default-world]]))
|
||||
[the-great-game.utils :refer [deep-merge]]))
|
||||
|
||||
(defn new-price
|
||||
"If `stock` is greater than the maximum of `supply` and `demand`, then
|
||||
|
@ -30,19 +29,24 @@
|
|||
su (or (-> c :supplies commodity) 0)
|
||||
decrement (min st d)
|
||||
increment (cond
|
||||
;; if its profitable to produce this commodity, the craftspeople
|
||||
;; of the city will do so.
|
||||
;; if we've two turns' production of this commodity in
|
||||
;; stock, halt production
|
||||
(> st (* su 2))
|
||||
0
|
||||
;; if it is profitable to produce this commodity, the
|
||||
;; craftspeople of the city will do so.
|
||||
(> p 1) su
|
||||
;; otherwise, if there isn't a turn's production in stock, top up
|
||||
;; the stock, so that there's something for incoming merchants to
|
||||
;; buy
|
||||
;; otherwise, if there isn't a turn's production in
|
||||
;; stock, top up the stock, so that there's something for
|
||||
;; incoming merchants to buy
|
||||
(> su st)
|
||||
(- su st)
|
||||
true 0)
|
||||
:else
|
||||
0)
|
||||
n (new-price p st su d)]
|
||||
(if
|
||||
(not (= p n))
|
||||
(l/info "Price of " commodity " at " id " has changed from " (float p) " to " (float n)))
|
||||
(not= p n)
|
||||
(l/info "Price of" commodity "at" id "has changed from" (float p) "to" (float n)))
|
||||
{:cities {id
|
||||
{:stock
|
||||
{commodity (+ (- st decrement) increment)}
|
||||
|
|
92
src/the_great_game/merchants/merchant_utils.clj
Normal file
92
src/the_great_game/merchants/merchant_utils.clj
Normal file
|
@ -0,0 +1,92 @@
|
|||
(ns the-great-game.merchants.merchant-utils
|
||||
"Useful functions for doing low-level things with merchants.")
|
||||
|
||||
(defn expected-price
|
||||
"Find the price anticipated, given this `world`, by this `merchant` for
|
||||
this `commodity` in this `city`. If no information, assume 1.
|
||||
`merchant` should be passed as a map, `commodity` and `city` should be passed as keywords."
|
||||
[merchant commodity city]
|
||||
(or
|
||||
(:price
|
||||
(last
|
||||
(sort-by
|
||||
:date
|
||||
(-> merchant :known-prices city commodity))))
|
||||
1))
|
||||
|
||||
(defn burden
|
||||
"The total weight of the current cargo carried by this `merchant` in this
|
||||
`world`."
|
||||
[merchant world]
|
||||
(let [m (cond
|
||||
(keyword? merchant)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
cargo (:stock m)]
|
||||
(reduce
|
||||
+
|
||||
0
|
||||
(map
|
||||
#(* (cargo %) (-> world :commodities % :weight))
|
||||
(keys cargo)))))
|
||||
|
||||
|
||||
(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)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)]
|
||||
(quot
|
||||
(- (:capacity m) (burden m world))
|
||||
(-> 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)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
l (:location m)]
|
||||
(quot
|
||||
(:cash m)
|
||||
(-> world :cities l :prices commodity))))
|
||||
|
||||
(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)))))
|
|
@ -1,423 +1,12 @@
|
|||
(ns the-great-game.merchants.merchants
|
||||
"Trade planning for merchants, primarily."
|
||||
(:require [taoensso.timbre :as l :refer [info error]]
|
||||
(:require [taoensso.timbre :as l :refer [info error spy]]
|
||||
[the-great-game.utils :refer [deep-merge]]
|
||||
[the-great-game.gossip.gossip :refer [move-gossip]]
|
||||
[the-great-game.world.routes :refer [find-route]]
|
||||
[the-great-game.world.world :refer [actual-price default-world]]))
|
||||
[the-great-game.merchants.strategies.simple :refer [move-merchant]]))
|
||||
|
||||
|
||||
(defn expected-price
|
||||
"Find the price anticipated, given this `world`, by this `merchant` for
|
||||
this `commodity` in this `city`. If no information, assume 1.
|
||||
`merchant` should be passed as a map, `commodity` and `city` should be passed as keywords."
|
||||
[merchant commodity city]
|
||||
(or
|
||||
(:price
|
||||
(last
|
||||
(sort-by
|
||||
:date
|
||||
(-> merchant :known-prices city commodity))))
|
||||
1))
|
||||
|
||||
|
||||
(defn burden
|
||||
"The total weight of the current cargo carried by this `merchant` in this
|
||||
`world`."
|
||||
[merchant world]
|
||||
(let [m (cond
|
||||
(keyword? merchant)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
cargo (-> m :stock)]
|
||||
(reduce
|
||||
+
|
||||
0
|
||||
(map
|
||||
#(* (cargo %) (-> world :commodities % :weight))
|
||||
(keys cargo)))))
|
||||
|
||||
|
||||
(defn make-target-filter
|
||||
"Construct a filter which, when applied to a list of maps,
|
||||
will pass those which match these `targets`, where each target
|
||||
is a tuple [key value]."
|
||||
;; TODO: this would probably be more elegant as a macro
|
||||
[targets]
|
||||
(eval
|
||||
(list
|
||||
'fn
|
||||
(vector 'plan)
|
||||
(cons
|
||||
'and
|
||||
(map
|
||||
#(list
|
||||
'=
|
||||
(list (first %) 'plan)
|
||||
(nth % 1))
|
||||
targets)))))
|
||||
|
||||
|
||||
(defn generate-trade-plans
|
||||
"Generate all possible trade plans for this `merchant` and this `commodity`
|
||||
in this `world`.
|
||||
|
||||
Returned plans are maps with keys:
|
||||
|
||||
* :merchant - the id of the `merchant` for whom the plan was created;
|
||||
* :origin - the city from which the trade starts;
|
||||
* :destination - the city to which the trade is planned;
|
||||
* :commodity - the `commodity` to be carried;
|
||||
* :buy-price - the price at which that `commodity` can be bought;
|
||||
* :expected-price - the price at which the `merchant` anticipates
|
||||
that `commodity` can be sold;
|
||||
* :distance - the number of stages in the planned journey
|
||||
* :dist-to-home - the distance from `destination` to the `merchant`'s
|
||||
home city."
|
||||
[merchant world commodity]
|
||||
(let [m (cond
|
||||
(keyword? merchant)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
origin (-> m :location)]
|
||||
(map
|
||||
#(hash-map
|
||||
:merchant (-> m :id)
|
||||
:origin origin
|
||||
:destination %
|
||||
:commodity commodity
|
||||
:buy-price (actual-price world commodity origin)
|
||||
:expected-price (expected-price
|
||||
m
|
||||
commodity
|
||||
%)
|
||||
:distance (count
|
||||
(find-route world origin %))
|
||||
:dist-to-home (count
|
||||
(find-route
|
||||
world
|
||||
(:home m)
|
||||
%)))
|
||||
(remove #(= % origin) (keys (-> world :cities))))))
|
||||
|
||||
(defn nearest-with-targets
|
||||
"Return the distance to the nearest destination among those of these
|
||||
`plans` which match these `targets`. Plans are expected to be plans
|
||||
as returned by `generate-trade-plans`, q.v.; `targets` are expected to be
|
||||
as accepted by `make-target-filter`, q.v."
|
||||
[plans targets]
|
||||
(apply
|
||||
min
|
||||
(map
|
||||
:distance
|
||||
(filter
|
||||
(make-target-filter targets)
|
||||
plans))))
|
||||
|
||||
(defn plan-trade
|
||||
"Find the best destination in this `world` for this `commodity` given this
|
||||
`merchant` and this `origin`. If two cities are anticipated to offer the
|
||||
same price, the nearer should be preferred; if two are equally distant, the
|
||||
ones nearer to the merchant's home should be preferred.
|
||||
`merchant` may be passed as a map or a keyword; `commodity` should be
|
||||
passed as a keyword.
|
||||
|
||||
The returned plan is a map with keys:
|
||||
|
||||
* :merchant - the id of the `merchant` for whom the plan was created;
|
||||
* :origin - the city from which the trade starts;
|
||||
* :destination - the city to which the trade is planned;
|
||||
* :commodity - the `commodity` to be carried;
|
||||
* :buy-price - the price at which that `commodity` can be bought;
|
||||
* :expected-price - the price at which the `merchant` anticipates
|
||||
that `commodity` can be sold;
|
||||
* :distance - the number of stages in the planned journey
|
||||
* :dist-to-home - the distance from `destination` to the `merchant`'s
|
||||
home city."
|
||||
[merchant world commodity]
|
||||
(let [plans (generate-trade-plans merchant world commodity)
|
||||
best-prices (filter
|
||||
(make-target-filter
|
||||
[[:expected-price
|
||||
(apply
|
||||
max
|
||||
(filter number? (map :expected-price plans)))]])
|
||||
plans)]
|
||||
(first
|
||||
(sort-by
|
||||
;; all other things being equal, a merchant would prefer to end closer
|
||||
;; to home.
|
||||
#(- 0 (:dist-to-home %))
|
||||
;; a merchant will seek the best price, but won't go further than
|
||||
;; needed to get it.
|
||||
(filter
|
||||
(make-target-filter
|
||||
[[:distance
|
||||
(apply min (filter number? (map :distance best-prices)))]])
|
||||
best-prices)))))
|
||||
|
||||
|
||||
(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)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)]
|
||||
(quot
|
||||
(- (:capacity m) (burden m world))
|
||||
(-> 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)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
l (:location m)]
|
||||
(quot
|
||||
(-> m :cash)
|
||||
(-> world :cities l :prices commodity))))
|
||||
|
||||
(defn augment-plan
|
||||
"Augment this `plan` constructed in this `world` for this `merchant` with
|
||||
the `:quantity` of goods which should be bought and the `:expected-profit`
|
||||
of the trade.
|
||||
|
||||
Returns the augmented plan."
|
||||
[merchant world plan]
|
||||
(let [c (:commodity plan)
|
||||
o (:origin plan)
|
||||
q (min
|
||||
(or
|
||||
(-> world :cities o :stock c)
|
||||
0)
|
||||
(can-carry merchant world c)
|
||||
(can-afford merchant world c))
|
||||
p (* q (- (:expected-price plan) (:buy-price plan)))]
|
||||
(assoc plan :quantity q :expected-profit p)))
|
||||
|
||||
;; (-> default-world :cities :buckie :stock :iron)
|
||||
;; (burden :fiona default-world)
|
||||
;; (-> default-world :commodities :iron :weight)
|
||||
;; (quot 0 10)
|
||||
|
||||
(defn select-cargo
|
||||
"A `merchant`, in a given location in a `world`, will choose to buy a cargo
|
||||
within the limit they are capable of carrying, which they can anticipate
|
||||
selling for a profit at a destination."
|
||||
[merchant world]
|
||||
(let [m (cond
|
||||
(keyword? merchant)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
origin (-> m :location)
|
||||
available (-> world :cities origin :stock)
|
||||
plans (map
|
||||
#(augment-plan
|
||||
m
|
||||
world
|
||||
(plan-trade m world %))
|
||||
(filter
|
||||
#(let [q (-> world :cities origin :stock %)]
|
||||
(and (number? q) (> q 0)))
|
||||
(keys available)))]
|
||||
(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))
|
||||
(do
|
||||
(l/info "Merchant " id " remains at home in " location)
|
||||
{})
|
||||
;; 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)
|
||||
(merge
|
||||
{:merchants
|
||||
{id
|
||||
{:location next-location}}}
|
||||
(move-gossip id world 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 " has moved from " (:location m) " to " next-location)
|
||||
(cond
|
||||
;; if the merchant is at the destination of their current plan
|
||||
;; sell all cargo and repurchase.
|
||||
at-destination?
|
||||
(sell-and-buy merchant world plan)
|
||||
;; if they don't have a plan, seek to create one
|
||||
(nil? (:plan m))
|
||||
(plan-and-buy merchant world)
|
||||
;; otherwise, move one step towards their destination
|
||||
true
|
||||
(deep-merge
|
||||
{:merchants
|
||||
{id
|
||||
{:location next-location
|
||||
:known-prices (add-known-prices m world)}}}
|
||||
(move-gossip id world next-location)))))
|
||||
|
||||
(defn run
|
||||
"Return a world like this `world`, but with each merchant moved."
|
||||
"Return a partial world based on this `world`, but with each merchant moved."
|
||||
[world]
|
||||
(try
|
||||
(reduce
|
||||
|
@ -425,7 +14,10 @@
|
|||
world
|
||||
(map
|
||||
#(try
|
||||
(move-merchant % world)
|
||||
(let [move-fn (or
|
||||
(-> world :merchants % :move-fn)
|
||||
move-merchant)]
|
||||
(apply move-fn (list % world)))
|
||||
(catch Exception any
|
||||
(l/error any "Failure while moving merchant " %)
|
||||
{}))
|
||||
|
|
159
src/the_great_game/merchants/planning.clj
Normal file
159
src/the_great_game/merchants/planning.clj
Normal file
|
@ -0,0 +1,159 @@
|
|||
(ns the-great-game.merchants.planning
|
||||
"Trade planning for merchants, primarily. This follows a simple-minded
|
||||
generate-and-test strategy and currently generates plans for all possible
|
||||
routes from the current location. This may not scale. Also, routes do not
|
||||
currently have cost or risk associated with them."
|
||||
(:require [the-great-game.utils :refer [deep-merge make-target-filter]]
|
||||
[the-great-game.merchants.merchant-utils :refer :all]
|
||||
[the-great-game.world.routes :refer [find-route]]
|
||||
[the-great-game.world.world :refer [actual-price default-world]]))
|
||||
|
||||
(defn generate-trade-plans
|
||||
"Generate all possible trade plans for this `merchant` and this `commodity`
|
||||
in this `world`.
|
||||
|
||||
Returned plans are maps with keys:
|
||||
|
||||
* :merchant - the id of the `merchant` for whom the plan was created;
|
||||
* :origin - the city from which the trade starts;
|
||||
* :destination - the city to which the trade is planned;
|
||||
* :commodity - the `commodity` to be carried;
|
||||
* :buy-price - the price at which that `commodity` can be bought;
|
||||
* :expected-price - the price at which the `merchant` anticipates
|
||||
that `commodity` can be sold;
|
||||
* :distance - the number of stages in the planned journey
|
||||
* :dist-to-home - the distance from `destination` to the `merchant`'s
|
||||
home city."
|
||||
[merchant world commodity]
|
||||
(let [m (cond
|
||||
(keyword? merchant)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
origin (:location m)]
|
||||
(map
|
||||
#(hash-map
|
||||
:merchant (:id m)
|
||||
:origin origin
|
||||
:destination %
|
||||
:commodity commodity
|
||||
:buy-price (actual-price world commodity origin)
|
||||
:expected-price (expected-price
|
||||
m
|
||||
commodity
|
||||
%)
|
||||
:distance (count
|
||||
(find-route world origin %))
|
||||
:dist-to-home (count
|
||||
(find-route
|
||||
world
|
||||
(:home m)
|
||||
%)))
|
||||
(remove #(= % origin) (-> world :cities keys)))))
|
||||
|
||||
(defn nearest-with-targets
|
||||
"Return the distance to the nearest destination among those of these
|
||||
`plans` which match these `targets`. Plans are expected to be plans
|
||||
as returned by `generate-trade-plans`, q.v.; `targets` are expected to be
|
||||
as accepted by `make-target-filter`, q.v."
|
||||
[plans targets]
|
||||
(apply
|
||||
min
|
||||
(map
|
||||
:distance
|
||||
(filter
|
||||
(make-target-filter targets)
|
||||
plans))))
|
||||
|
||||
(defn plan-trade
|
||||
"Find the best destination in this `world` for this `commodity` given this
|
||||
`merchant` and this `origin`. If two cities are anticipated to offer the
|
||||
same price, the nearer should be preferred; if two are equally distant, the
|
||||
ones nearer to the merchant's home should be preferred.
|
||||
`merchant` may be passed as a map or a keyword; `commodity` should be
|
||||
passed as a keyword.
|
||||
|
||||
The returned plan is a map with keys:
|
||||
|
||||
* :merchant - the id of the `merchant` for whom the plan was created;
|
||||
* :origin - the city from which the trade starts;
|
||||
* :destination - the city to which the trade is planned;
|
||||
* :commodity - the `commodity` to be carried;
|
||||
* :buy-price - the price at which that `commodity` can be bought;
|
||||
* :expected-price - the price at which the `merchant` anticipates
|
||||
that `commodity` can be sold;
|
||||
* :distance - the number of stages in the planned journey
|
||||
* :dist-to-home - the distance from `destination` to the `merchant`'s
|
||||
home city."
|
||||
[merchant world commodity]
|
||||
(let [plans (generate-trade-plans merchant world commodity)
|
||||
best-prices (filter
|
||||
(make-target-filter
|
||||
[[:expected-price
|
||||
(apply
|
||||
max
|
||||
(filter number? (map :expected-price plans)))]])
|
||||
plans)]
|
||||
(first
|
||||
(sort-by
|
||||
;; all other things being equal, a merchant would prefer to end closer
|
||||
;; to home.
|
||||
#(- 0 (:dist-to-home %))
|
||||
;; a merchant will seek the best price, but won't go further than
|
||||
;; needed to get it.
|
||||
(filter
|
||||
(make-target-filter
|
||||
[[:distance
|
||||
(apply min (filter number? (map :distance best-prices)))]])
|
||||
best-prices)))))
|
||||
|
||||
(defn augment-plan
|
||||
"Augment this `plan` constructed in this `world` for this `merchant` with
|
||||
the `:quantity` of goods which should be bought and the `:expected-profit`
|
||||
of the trade.
|
||||
|
||||
Returns the augmented plan."
|
||||
[merchant world plan]
|
||||
(let [c (:commodity plan)
|
||||
o (:origin plan)
|
||||
q (min
|
||||
(or
|
||||
(-> world :cities o :stock c)
|
||||
0)
|
||||
(can-carry merchant world c)
|
||||
(can-afford merchant world c))
|
||||
p (* q (- (:expected-price plan) (:buy-price plan)))]
|
||||
(assoc plan :quantity q :expected-profit p)))
|
||||
|
||||
(defn select-cargo
|
||||
"A `merchant`, in a given location in a `world`, will choose to buy a cargo
|
||||
within the limit they are capable of carrying, which they can anticipate
|
||||
selling for a profit at a destination."
|
||||
[merchant world]
|
||||
(let [m (cond
|
||||
(keyword? merchant)
|
||||
(-> world :merchants merchant)
|
||||
(map? merchant)
|
||||
merchant)
|
||||
origin (:location m)
|
||||
available (-> world :cities origin :stock)
|
||||
plans (map
|
||||
#(augment-plan
|
||||
m
|
||||
world
|
||||
(plan-trade m world %))
|
||||
(filter
|
||||
#(let [q (-> world :cities origin :stock %)]
|
||||
(and (number? q) (pos? q)))
|
||||
(keys available)))]
|
||||
(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))))))
|
||||
|
173
src/the_great_game/merchants/strategies/simple.clj
Normal file
173
src/the_great_game/merchants/strategies/simple.clj
Normal file
|
@ -0,0 +1,173 @@
|
|||
(ns the-great-game.merchants.strategies.simple
|
||||
"Default trading strategy for merchants.
|
||||
|
||||
The simple strategy buys a single product in the local market if there is
|
||||
one which can be traded profitably, trades it to the chosen target market,
|
||||
and sells it there. If there is no commodity locally which can be traded
|
||||
profitably, moves towards home with no cargo. If at home and no commodity
|
||||
can be traded profitably, does not move."
|
||||
(:require [taoensso.timbre :as l :refer [info error spy]]
|
||||
[the-great-game.utils :refer [deep-merge]]
|
||||
[the-great-game.gossip.gossip :refer [move-gossip]]
|
||||
[the-great-game.merchants.planning :refer :all]
|
||||
[the-great-game.merchants.merchant-utils :refer
|
||||
[add-stock add-known-prices]]
|
||||
[the-great-game.world.routes :refer [find-route]]))
|
||||
|
||||
(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]
|
||||
(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)]
|
||||
(l/debug "plan-and-buy: merchant" id)
|
||||
(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 plan)
|
||||
{:merchants
|
||||
{id
|
||||
{:stock (add-stock (:stock m) {c q})
|
||||
:cash (- (:cash m) p)
|
||||
:known-prices (add-known-prices m world)
|
||||
:plan plan}}
|
||||
: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))
|
||||
(do
|
||||
(l/info "Merchant" id "remains at home in" location)
|
||||
{})
|
||||
;; else move towards home
|
||||
:else
|
||||
(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)
|
||||
(merge
|
||||
{:merchants
|
||||
{id
|
||||
{:location next-location}}}
|
||||
(move-gossip id world 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)))]
|
||||
(l/debug "re-plan: merchant" id)
|
||||
(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))))]
|
||||
(l/debug "sell-and-buy: merchant" id)
|
||||
(if
|
||||
(>= (:cash market) stock-value)
|
||||
(do
|
||||
(l/info "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`;
|
||||
return a (partial or full) world like this `world` but in which the
|
||||
merchant may have been moved ot updated."
|
||||
[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
|
||||
(find-route
|
||||
world
|
||||
(:location m)
|
||||
(:destination plan))
|
||||
1)
|
||||
(:location m))]
|
||||
(l/debug "move-merchant: merchant" id "at" (:location m)
|
||||
"destination" (-> m :plan :destination) "next" next-location
|
||||
"at destination" at-destination?)
|
||||
(cond
|
||||
;; if the merchant is at the destination of their current plan
|
||||
;; sell all cargo and repurchase.
|
||||
at-destination?
|
||||
(sell-and-buy merchant world)
|
||||
;; if they don't have a plan, seek to create one
|
||||
(nil? plan)
|
||||
(plan-and-buy merchant world)
|
||||
;; otherwise, move one step towards their destination
|
||||
(and next-location (not= next-location (:location m)))
|
||||
(do
|
||||
(l/info "Merchant " id " moving from " (:location m) " to " next-location)
|
||||
(deep-merge
|
||||
{:merchants
|
||||
{id
|
||||
{:location next-location
|
||||
:known-prices (add-known-prices m world)}}}
|
||||
(move-gossip id world next-location)))
|
||||
:else
|
||||
(do
|
||||
(l/info "Merchant" id "has plan but no next-location; currently at"
|
||||
(:location m) ", destination is" (:destination plan))
|
||||
world))))
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
(defn cyclic?
|
||||
"True if two or more elements of `route` are identical"
|
||||
[route]
|
||||
(not (= (count route)(count (set route)))))
|
||||
(not= (count route)(count (set route))))
|
||||
|
||||
(defn deep-merge
|
||||
"Recursively merges maps. Stolen from
|
||||
|
@ -15,3 +15,21 @@
|
|||
(last xs)))]
|
||||
(reduce m maps)))
|
||||
|
||||
(defn make-target-filter
|
||||
"Construct a filter which, when applied to a list of maps,
|
||||
will pass those which match these `targets`, where each target
|
||||
is a tuple [key value]."
|
||||
;; TODO: this would probably be more elegant as a macro
|
||||
[targets]
|
||||
(eval
|
||||
(list
|
||||
'fn
|
||||
(vector 'm)
|
||||
(cons
|
||||
'and
|
||||
(map
|
||||
#(list
|
||||
'=
|
||||
(list (first %) 'm)
|
||||
(nth % 1))
|
||||
targets)))))
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
(map
|
||||
(fn [to] (cons from to))
|
||||
(remove
|
||||
#(empty? %)
|
||||
empty?
|
||||
(map
|
||||
(fn [route]
|
||||
(filter
|
||||
#(not (= from %))
|
||||
(remove
|
||||
#(= from %)
|
||||
(if (some #(= % from) route) route)))
|
||||
routes))))
|
||||
([routes from to]
|
||||
|
@ -30,14 +30,12 @@
|
|||
(not (empty? steps))
|
||||
(let [paths (remove
|
||||
cyclic?
|
||||
(apply
|
||||
concat
|
||||
(map
|
||||
(mapcat
|
||||
(fn [path]
|
||||
(map
|
||||
(fn [x] (concat path (rest x)))
|
||||
(find-routes routes (last path))))
|
||||
steps)))
|
||||
steps))
|
||||
found (filter
|
||||
#(= (last %) to) paths)]
|
||||
(if
|
||||
|
|
|
@ -1,17 +1,39 @@
|
|||
(ns the-great-game.world.run
|
||||
"Run the whole simulation"
|
||||
(:require [taoensso.timbre :as log]
|
||||
(:require [environ.core :refer [env]]
|
||||
[taoensso.timbre :as timbre]
|
||||
[taoensso.timbre.appenders.3rd-party.rotor :as rotor]
|
||||
[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 init
|
||||
([]
|
||||
(init {}))
|
||||
([config]
|
||||
(timbre/merge-config!
|
||||
{:appenders
|
||||
{:rotor (rotor/rotor-appender
|
||||
{:path "the-great-game.log"
|
||||
:max-size (* 512 1024)
|
||||
:backlog 10})}
|
||||
:level (or
|
||||
(:log-level config)
|
||||
(if (env :dev) :debug)
|
||||
:info)})))
|
||||
|
||||
(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]
|
||||
this world, with all the various active elements updated. The optional
|
||||
`date` argument, if supplied, is set as the `:date` of the returned world."
|
||||
([world]
|
||||
(g/run
|
||||
(m/run
|
||||
(k/run
|
||||
(w/run world)))))
|
||||
([world date]
|
||||
(g/run
|
||||
(m/run
|
||||
(k/run
|
||||
(w/run world date))))))
|
||||
|
|
|
@ -183,8 +183,10 @@
|
|||
(-> 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]]."
|
||||
[world]
|
||||
(assoc world :date (inc (or (:date world) 0))))
|
||||
"Return a world like this `world` with only the `:date` to this `date`
|
||||
(or id `date` not supplied, the current value incremented by one). For
|
||||
running other aspects of the simulation, see [[the-great-game.world.run]]."
|
||||
([world]
|
||||
(run world (inc (or (:date world) 0))))
|
||||
([world date]
|
||||
(assoc world :date date)))
|
||||
|
|
24
test/the_great_game/merchants/merchant_utils_test.clj
Normal file
24
test/the_great_game/merchants/merchant_utils_test.clj
Normal file
|
@ -0,0 +1,24 @@
|
|||
(ns the-great-game.merchants.merchant-utils-test
|
||||
(:require [clojure.test :refer :all]
|
||||
[the-great-game.utils :refer [deep-merge]]
|
||||
[the-great-game.world.world :refer [default-world]]
|
||||
[the-great-game.merchants.merchant-utils :refer :all]))
|
||||
|
||||
(deftest expected-price-test
|
||||
(testing "Anticipated prices in markets"
|
||||
(let [world (deep-merge
|
||||
default-world
|
||||
{:merchants
|
||||
{:archie
|
||||
{:known-prices
|
||||
{:buckie
|
||||
{:iron
|
||||
[{:price 1.7 :date 1}
|
||||
{:price 2 :date 0}]}}}}})]
|
||||
(let [actual (expected-price (-> world :merchants :archie) :fish :edinburgh)
|
||||
expected 1] ;;
|
||||
(is (= actual expected) "if no information assume 1"))
|
||||
(let [actual (expected-price (-> world :merchants :archie) :iron :buckie)
|
||||
expected 1.7] ;;
|
||||
(is (= actual expected) "if information select the most recent")))))
|
||||
|
|
@ -1,26 +1,9 @@
|
|||
(ns the-great-game.merchants.merchants-test
|
||||
(ns the-great-game.merchants.planning-test
|
||||
(:require [clojure.test :refer :all]
|
||||
[the-great-game.utils :refer [deep-merge]]
|
||||
[the-great-game.world.world :refer [default-world]]
|
||||
[the-great-game.merchants.merchants :refer :all]))
|
||||
[the-great-game.merchants.planning :refer :all]))
|
||||
|
||||
(deftest expected-price-test
|
||||
(testing "Anticipated prices in markets"
|
||||
(let [world (deep-merge
|
||||
default-world
|
||||
{:merchants
|
||||
{:archie
|
||||
{:known-prices
|
||||
{:buckie
|
||||
{:iron
|
||||
[{:price 1.7 :date 1}
|
||||
{:price 2 :date 0}]}}}}})]
|
||||
(let [actual (expected-price (-> world :merchants :archie) :fish :edinburgh)
|
||||
expected 1] ;;
|
||||
(is (= actual expected) "if no information assume 1"))
|
||||
(let [actual (expected-price (-> world :merchants :archie) :iron :buckie)
|
||||
expected 1.7] ;;
|
||||
(is (= actual expected) "if information select the most recent")))))
|
||||
|
||||
(deftest plan-trade-test
|
||||
(testing "Lower level trade planning"
|
Loading…
Reference in a new issue