Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Simon Brooke 2021-12-08 12:46:48 +00:00
commit 42a2792539
60 changed files with 1460 additions and 1036 deletions

12
.gitignore vendored
View file

@ -38,3 +38,15 @@ libopenal64.so
.settings/ .settings/
.classpath .classpath
.project .project
.calva/
.lsp/
*.so
docs/cloverage/codecov.json
docs/cloverage/coverage.xml
src/cc/journeyman/the_great_game/cloverage.clj

View file

@ -0,0 +1,251 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="../../../../coverage.css"/> <title> cc/journeyman/the_great_game/buildings/module.clj </title>
</head>
<body>
<span class="covered" title="1 out of 1 forms covered">
001&nbsp;&nbsp;(ns&nbsp;cc.journeyman.the-great-game.buildings.module
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
002&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
003&nbsp;&nbsp;&nbsp;&nbsp;&quot;A&nbsp;module&nbsp;of&nbsp;a&nbsp;building;&nbsp;essentially&nbsp;something&nbsp;like&nbsp;a&nbsp;portacabin,&nbsp;which&nbsp;can&nbsp;be
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assembled&nbsp;together&nbsp;with&nbsp;other&nbsp;modules&nbsp;to&nbsp;make&nbsp;a&nbsp;complete&nbsp;building.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
005&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Modules&nbsp;need&nbsp;to&nbsp;include
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
007&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;Ground&nbsp;floor&nbsp;modules,&nbsp;having&nbsp;external&nbsp;doors;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
009&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;Craft&nbsp;modules&nbsp;--&nbsp;workshops&nbsp;--&nbsp;which&nbsp;will&nbsp;normally&nbsp;be&nbsp;ground&nbsp;floor&nbsp;(except
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;weavers)&nbsp;and&nbsp;may&nbsp;have&nbsp;the&nbsp;constraint&nbsp;that&nbsp;no&nbsp;upper&nbsp;floor&nbsp;module&nbsp;can&nbsp;cover&nbsp;them;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;Upper&nbsp;floor&nbsp;modules,&nbsp;having&nbsp;NO&nbsp;external&nbsp;doors&nbsp;(but&nbsp;linking&nbsp;internal&nbsp;doors);
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;Roof&nbsp;modules
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Role**&nbsp;must&nbsp;be&nbsp;one&nbsp;of:
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;`:primary`&nbsp;a&nbsp;ground&nbsp;floor&nbsp;main&nbsp;entrance&nbsp;module
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;`:secondary`&nbsp;a&nbsp;module&nbsp;which&nbsp;can&nbsp;be&nbsp;upper&nbsp;or&nbsp;ground&nbsp;floor
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;`:upper`&nbsp;a&nbsp;module&nbsp;which&nbsp;can&nbsp;only&nbsp;be&nbsp;on&nbsp;an&nbsp;upper&nbsp;floor,&nbsp;for&nbsp;example&nbsp;one
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;a&nbsp;projecting&nbsp;gallery,&nbsp;balcony&nbsp;or&nbsp;overhang.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
021&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Other&nbsp;values&nbsp;for&nbsp;`role`&nbsp;will&nbsp;emerge.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
022&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
023&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Exits**&nbsp;must&nbsp;be&nbsp;a&nbsp;sequence&nbsp;of&nbsp;keywords&nbsp;taken&nbsp;from&nbsp;the&nbsp;following&nbsp;list:
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
025&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;`:left`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;left&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
026&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;`:left-front`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;left&nbsp;half&nbsp;of&nbsp;the&nbsp;front&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
027&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;`:front`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;front&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;`:right-front`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;right&nbsp;half&nbsp;of&nbsp;the&nbsp;front&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
029&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.&nbsp;`:right`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;right&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6.&nbsp;`:right-back`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;right&nbsp;half&nbsp;of&nbsp;the&nbsp;back&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
031&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7.&nbsp;`:left-back`&nbsp;an&nbsp;exit&nbsp;in&nbsp;the&nbsp;centre&nbsp;of&nbsp;the&nbsp;back&nbsp;wall
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
032&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
033&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;module&nbsp;placed&nbsp;on&nbsp;an&nbsp;upper&nbsp;floor&nbsp;must&nbsp;have&nbsp;no&nbsp;exit&nbsp;which&nbsp;opens&nbsp;beyond&nbsp;the&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;footprint&nbsp;of&nbsp;the&nbsp;floor&nbsp;below&nbsp;-&nbsp;no&nbsp;doors&nbsp;into&nbsp;mid&nbsp;air!&nbsp;However,&nbsp;it&nbsp;is&nbsp;allowable&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
035&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;indeed&nbsp;is&nbsp;necessary)&nbsp;to&nbsp;allow&nbsp;doors&nbsp;into&nbsp;roof&nbsp;spaces&nbsp;if&nbsp;the&nbsp;adjacent
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module&nbsp;on&nbsp;the&nbsp;same&nbsp;floor&nbsp;does&nbsp;not&nbsp;yet&nbsp;exist,&nbsp;since&nbsp;otherwise&nbsp;it&nbsp;would&nbsp;be&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;impossible&nbsp;to&nbsp;access&nbsp;a&nbsp;new&nbsp;room&nbsp;which&nbsp;might&nbsp;later&nbsp;be&nbsp;built&nbsp;there.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
039&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Load**&nbsp;must&nbsp;be&nbsp;a&nbsp;small&nbsp;integer&nbsp;indicating&nbsp;both&nbsp;the&nbsp;weight&nbsp;of&nbsp;the&nbsp;module&nbsp;and&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;total&nbsp;amount&nbsp;of&nbsp;weight&nbsp;it&nbsp;can&nbsp;support.&nbsp;So&nbsp;for&nbsp;example&nbsp;a&nbsp;stone-built&nbsp;module
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
041&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;might&nbsp;have&nbsp;a&nbsp;`load`&nbsp;value&nbsp;of&nbsp;4,&nbsp;a&nbsp;brick&nbsp;built&nbsp;one&nbsp;of&nbsp;3,&nbsp;and&nbsp;a&nbsp;half-timbered&nbsp;one&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
042&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;2,&nbsp;and&nbsp;a&nbsp;tent&nbsp;of&nbsp;0.&nbsp;This&nbsp;means&nbsp;a&nbsp;stone&nbsp;ground&nbsp;floor&nbsp;module&nbsp;could&nbsp;support&nbsp;one&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
043&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;further&nbsp;floor&nbsp;of&nbsp;stone&nbsp;or&nbsp;brick,&nbsp;or&nbsp;two&nbsp;further&nbsp;floors&nbsp;of&nbsp;half&nbsp;timbered&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
044&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;construction;&nbsp;while&nbsp;a&nbsp;brick&nbsp;built&nbsp;ground&nbsp;floor&nbsp;could&nbsp;support&nbsp;a&nbsp;single&nbsp;brick&nbsp;or&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
045&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;half-timbered&nbsp;upper&nbsp;floor&nbsp;but&nbsp;not&nbsp;a&nbsp;stone&nbsp;one,&nbsp;and&nbsp;a&nbsp;half-timbered&nbsp;ground&nbsp;floor
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
046&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;could&nbsp;only&nbsp;support&nbsp;a&nbsp;half&nbsp;timbered&nbsp;upper&nbsp;floor.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
047&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
048&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;There&nbsp;also&nbsp;needs&nbsp;to&nbsp;be&nbsp;an&nbsp;undercroft&nbsp;or&nbsp;platform&nbsp;module,&nbsp;such&nbsp;that&nbsp;the&nbsp;area&nbsp;of&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
049&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;platform&nbsp;is&nbsp;identical&nbsp;with&nbsp;the&nbsp;footprint&nbsp;of&nbsp;the&nbsp;building,&nbsp;and&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
050&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;altitude&nbsp;of&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;platform&nbsp;is&nbsp;equal&nbsp;to&nbsp;the&nbsp;altitude&nbsp;of&nbsp;the&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
051&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;terrain&nbsp;at&nbsp;the&nbsp;heighest&nbsp;corner&nbsp;of&nbsp;the&nbsp;building;&nbsp;so&nbsp;that&nbsp;the&nbsp;actual&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
052&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;building&nbsp;doesn&#x27;t&nbsp;float&nbsp;in&nbsp;the&nbsp;air,&nbsp;and&nbsp;also&nbsp;so&nbsp;that&nbsp;none&nbsp;of&nbsp;the&nbsp;doors&nbsp;or&nbsp;windows
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
053&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are&nbsp;partly&nbsp;underground.
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
054&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Each&nbsp;module&nbsp;needs&nbsp;to&nbsp;wrap&nbsp;an&nbsp;actual&nbsp;3d&nbsp;model&nbsp;created&nbsp;in&nbsp;Blender&nbsp;or&nbsp;whatever,&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;have&nbsp;a&nbsp;list&nbsp;of&nbsp;optional&nbsp;**textures**&nbsp;with&nbsp;which&nbsp;that&nbsp;model&nbsp;can&nbsp;be&nbsp;rendered.&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;So&nbsp;an&nbsp;upper&nbsp;floor&nbsp;bedroom&nbsp;module&nbsp;might&nbsp;have&nbsp;the&nbsp;following&nbsp;renders:
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
058&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;Bare&nbsp;masonry&nbsp;-&nbsp;constrained&nbsp;to&nbsp;upland&nbsp;or&nbsp;plateau&nbsp;terrain,&nbsp;and&nbsp;to&nbsp;coastal&nbsp;culture
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;Painted&nbsp;masonry&nbsp;-&nbsp;constrained&nbsp;to&nbsp;upland&nbsp;or&nbsp;plateau&nbsp;terrain,&nbsp;and&nbsp;to&nbsp;coastal&nbsp;culture
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
061&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;Half-timbered&nbsp;-&nbsp;not&nbsp;available&nbsp;on&nbsp;plateau&nbsp;terrain
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;Weatherboarded&nbsp;-&nbsp;constrained&nbsp;to&nbsp;forest&nbsp;terrain
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
063&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.&nbsp;Brick&nbsp;-&nbsp;constrained&nbsp;to&nbsp;arable&nbsp;or&nbsp;arid&nbsp;terrain
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
064&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
065&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;course&nbsp;these&nbsp;are&nbsp;only&nbsp;examples,&nbsp;and&nbsp;also,&nbsp;it&#x27;s&nbsp;entirely&nbsp;possible&nbsp;to&nbsp;have
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;example&nbsp;multiple&nbsp;different&nbsp;weatherboard&nbsp;renders&nbsp;for&nbsp;the&nbsp;same&nbsp;module.&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
067&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;There&nbsp;needs&nbsp;to&nbsp;be&nbsp;a&nbsp;way&nbsp;of&nbsp;rendering&nbsp;what&nbsp;can&nbsp;be&nbsp;built&nbsp;above&nbsp;what:&nbsp;for
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;example,&nbsp;you&nbsp;can&#x27;t&nbsp;have&nbsp;a&nbsp;masonry&nbsp;clad&nbsp;module&nbsp;over&nbsp;a&nbsp;half&nbsp;timbered&nbsp;one,&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
069&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;but&nbsp;you&nbsp;can&nbsp;have&nbsp;a&nbsp;half-timbered&nbsp;one&nbsp;over&nbsp;a&nbsp;masonry&nbsp;one.&quot;)
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
070&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
071&nbsp;&nbsp;(defrecord&nbsp;BuildingModule
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
072&nbsp;&nbsp;&nbsp;&nbsp;[model
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
073&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^Double&nbsp;length
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
074&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^Double&nbsp;width
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
075&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^Double&nbsp;height
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
076&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^Integer&nbsp;load&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
077&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^clojure.lang.Keyword&nbsp;role
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
078&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^clojure.lang.IPersistentCollection&nbsp;textures
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
079&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^clojure.lang.IPersistentCollection&nbsp;exits
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
081&nbsp;&nbsp;&nbsp;&nbsp;)
</span><br/>
</body>
</html>

View file

@ -355,194 +355,104 @@
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
117&nbsp;&nbsp; 117&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
118&nbsp;&nbsp;;;&nbsp;TODO:&nbsp;So,&nbsp;modules&nbsp;need&nbsp;to&nbsp;contain 118&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
119&nbsp;&nbsp;(defn&nbsp;building-family
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
119&nbsp;&nbsp;;; 120&nbsp;&nbsp;&nbsp;&nbsp;&quot;A&nbsp;building&nbsp;family&nbsp;is&nbsp;essentially&nbsp;a&nbsp;collection&nbsp;of&nbsp;models&nbsp;of&nbsp;building&nbsp;modules
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
120&nbsp;&nbsp;;;&nbsp;1.&nbsp;Ground&nbsp;floor&nbsp;modules,&nbsp;having&nbsp;external&nbsp;doors; 121&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;which&nbsp;can&nbsp;be&nbsp;assembled&nbsp;to&nbsp;create&nbsp;buildings&nbsp;of&nbsp;a&nbsp;particular&nbsp;structural&nbsp;and
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
121&nbsp;&nbsp;;;&nbsp;2.&nbsp;Craft&nbsp;modules&nbsp;--&nbsp;workshops&nbsp;--&nbsp;which&nbsp;will&nbsp;normally&nbsp;be&nbsp;ground&nbsp;floor&nbsp;(except 122&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;architectural&nbsp;style.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
122&nbsp;&nbsp;;;&nbsp;weavers)&nbsp;and&nbsp;may&nbsp;have&nbsp;the&nbsp;constraint&nbsp;that&nbsp;no&nbsp;upper&nbsp;floor&nbsp;module&nbsp;can&nbsp;cover&nbsp;them; 123&nbsp;&nbsp;&nbsp;&nbsp;[terrain&nbsp;culture&nbsp;craft&nbsp;gene]
</span><br/>
<span class="partial" title="12 out of 13 forms covered">
124&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[candidates&nbsp;(filter&nbsp;#(and
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
125&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((:terrains&nbsp;%)&nbsp;terrain)
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((:crafts&nbsp;%)&nbsp;craft)
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
127&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((:cultures&nbsp;%)&nbsp;culture))
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
128&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vals&nbsp;*building-families*))]
</span><br/>
<span class="covered" title="8 out of 8 forms covered">
129&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(nth&nbsp;candidates&nbsp;(mod&nbsp;(Math&#x2F;abs&nbsp;(.nextInt&nbsp;gene))&nbsp;(count&nbsp;candidates)))))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
130&nbsp;&nbsp;
</span><br/>
<span class="covered" title="7 out of 7 forms covered">
131&nbsp;&nbsp;(building-family&nbsp;:arable&nbsp;:coastal&nbsp;:baker&nbsp;(MersenneTwister.&nbsp;5))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
132&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
133&nbsp;&nbsp;(defn&nbsp;build!&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
123&nbsp;&nbsp;;;&nbsp;3.&nbsp;Upper&nbsp;floor&nbsp;modules,&nbsp;having&nbsp;NO&nbsp;external&nbsp;doors&nbsp;(but&nbsp;linking&nbsp;internal&nbsp;doors); 134&nbsp;&nbsp;&nbsp;&nbsp;&quot;Builds&nbsp;a&nbsp;building,&nbsp;and&nbsp;returns&nbsp;a&nbsp;data&nbsp;structure&nbsp;which&nbsp;represents&nbsp;it.&nbsp;In&nbsp;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
124&nbsp;&nbsp;;;&nbsp;4.&nbsp;Roof&nbsp;modules 135&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;building&nbsp;the&nbsp;building,&nbsp;it&nbsp;adds&nbsp;a&nbsp;model&nbsp;of&nbsp;the&nbsp;building&nbsp;to&nbsp;the&nbsp;representation
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
125&nbsp;&nbsp;;;&nbsp; 136&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;the&nbsp;world,&nbsp;so&nbsp;it&nbsp;does&nbsp;have&nbsp;a&nbsp;side&nbsp;effect.&quot;
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
126&nbsp;&nbsp;;;&nbsp;There&nbsp;also&nbsp;needs&nbsp;to&nbsp;be&nbsp;an&nbsp;undercroft&nbsp;or&nbsp;platform&nbsp;module,&nbsp;such&nbsp;that&nbsp;the&nbsp;area&nbsp;of&nbsp; 137&nbsp;&nbsp;&nbsp;&nbsp;[holding&nbsp;terrain&nbsp;culture&nbsp;craft&nbsp;size]
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
138&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(satisfies?&nbsp;ProtoHolding&nbsp;holding)
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
139&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[location&nbsp;(.building-origin&nbsp;holding)
</span><br/>
<span class="not-covered" title="0 out of 7 forms covered">
140&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gene&nbsp;(MersenneTwister.&nbsp;(int&nbsp;(+&nbsp;(*&nbsp;(.easting&nbsp;location)&nbsp;1000000)&nbsp;(.northing&nbsp;location))))
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
141&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;family&nbsp;(building-family&nbsp;terrain&nbsp;culture&nbsp;craft&nbsp;gene)]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
142&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 11 forms covered">
143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;(instance?&nbsp;ProtoLocation&nbsp;location)&nbsp;(:orientation&nbsp;location))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
127&nbsp;&nbsp;;;&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;platform&nbsp;is&nbsp;identical&nbsp;with&nbsp;the&nbsp;footprint&nbsp;of&nbsp;the&nbsp;building,&nbsp;and&nbsp; 144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:stuff
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
128&nbsp;&nbsp;;;&nbsp;the&nbsp;altitude&nbsp;of&nbsp;the&nbsp;top&nbsp;of&nbsp;the&nbsp;platform&nbsp;is&nbsp;equal&nbsp;to&nbsp;the&nbsp;altitude&nbsp;of&nbsp;the&nbsp; 145&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:nonsense
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
129&nbsp;&nbsp;;;&nbsp;terrain&nbsp;at&nbsp;the&nbsp;heighest&nbsp;corner&nbsp;of&nbsp;the&nbsp;building;&nbsp;so&nbsp;that&nbsp;the&nbsp;actual&nbsp; 146&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
130&nbsp;&nbsp;;;&nbsp;building&nbsp;doesn&#x27;t&nbsp;float&nbsp;in&nbsp;the&nbsp;air,&nbsp;and&nbsp;also&nbsp;so&nbsp;that&nbsp;none&nbsp;of&nbsp;the&nbsp;doors&nbsp;or&nbsp;windows 147&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:froboz))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
131&nbsp;&nbsp;;;&nbsp;are&nbsp;partly&nbsp;underground.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
132&nbsp;&nbsp;;;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
133&nbsp;&nbsp;;;&nbsp;Each&nbsp;module&nbsp;needs&nbsp;to&nbsp;wrap&nbsp;an&nbsp;actual&nbsp;3d&nbsp;model&nbsp;created&nbsp;in&nbsp;Blender&nbsp;or&nbsp;whatever,&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
134&nbsp;&nbsp;;;&nbsp;and&nbsp;have&nbsp;a&nbsp;list&nbsp;of&nbsp;optional&nbsp;textures&nbsp;with&nbsp;which&nbsp;that&nbsp;model&nbsp;can&nbsp;be&nbsp;rendered.&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
135&nbsp;&nbsp;;;&nbsp;So&nbsp;an&nbsp;upper&nbsp;floor&nbsp;bedroom&nbsp;module&nbsp;might&nbsp;have&nbsp;the&nbsp;following&nbsp;renders:
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
136&nbsp;&nbsp;;;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
137&nbsp;&nbsp;;;&nbsp;1.&nbsp;Bare&nbsp;masonry&nbsp;-&nbsp;constrained&nbsp;to&nbsp;upland&nbsp;or&nbsp;plateau&nbsp;terrain,&nbsp;and&nbsp;to&nbsp;coastal&nbsp;culture
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
138&nbsp;&nbsp;;;&nbsp;2.&nbsp;Painted&nbsp;masonry&nbsp;-&nbsp;constrained&nbsp;to&nbsp;upland&nbsp;or&nbsp;plateau&nbsp;terrain,&nbsp;and&nbsp;to&nbsp;coastal&nbsp;culture
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
139&nbsp;&nbsp;;;&nbsp;3.&nbsp;Half-timbered&nbsp;-&nbsp;not&nbsp;available&nbsp;on&nbsp;plateau&nbsp;terrain
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
140&nbsp;&nbsp;;;&nbsp;4.&nbsp;Weatherboarded&nbsp;-&nbsp;constrained&nbsp;to&nbsp;forest&nbsp;terrain
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
141&nbsp;&nbsp;;;&nbsp;5.&nbsp;Brick&nbsp;-&nbsp;constrained&nbsp;to&nbsp;arable&nbsp;or&nbsp;arid&nbsp;terrain
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
142&nbsp;&nbsp;;;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
143&nbsp;&nbsp;;;&nbsp;of&nbsp;course&nbsp;these&nbsp;are&nbsp;only&nbsp;examples,&nbsp;and&nbsp;also,&nbsp;it&#x27;s&nbsp;entirely&nbsp;possible&nbsp;to&nbsp;have
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
144&nbsp;&nbsp;;;&nbsp;for&nbsp;example&nbsp;multiple&nbsp;different&nbsp;weatherboard&nbsp;renders&nbsp;for&nbsp;the&nbsp;same&nbsp;module.&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
145&nbsp;&nbsp;;;&nbsp;There&nbsp;needs&nbsp;to&nbsp;be&nbsp;a&nbsp;way&nbsp;of&nbsp;rendering&nbsp;what&nbsp;can&nbsp;be&nbsp;built&nbsp;above&nbsp;what:&nbsp;for
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
146&nbsp;&nbsp;;;&nbsp;example,&nbsp;you&nbsp;can&#x27;t&nbsp;have&nbsp;a&nbsp;masonry&nbsp;clad&nbsp;module&nbsp;over&nbsp;a&nbsp;half&nbsp;timbered&nbsp;one,&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
147&nbsp;&nbsp;;;&nbsp;but&nbsp;you&nbsp;can&nbsp;have&nbsp;a&nbsp;half-timbered&nbsp;one&nbsp;over&nbsp;a&nbsp;masonry&nbsp;one
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
148&nbsp;&nbsp; 148&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered">
149&nbsp;&nbsp;(defn&nbsp;building-family
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
150&nbsp;&nbsp;&nbsp;&nbsp;&quot;A&nbsp;building&nbsp;family&nbsp;is&nbsp;essentially&nbsp;a&nbsp;collection&nbsp;of&nbsp;models&nbsp;of&nbsp;building&nbsp;modules 149&nbsp;&nbsp;;;&nbsp;(def&nbsp;ol&nbsp;(cc.journeyman.the-great-game.location.location&#x2F;OrientedLocation.&nbsp;123.45&nbsp;543.76&nbsp;12.34&nbsp;0.00&nbsp;{}))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
151&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;which&nbsp;can&nbsp;be&nbsp;assembled&nbsp;to&nbsp;create&nbsp;buildings&nbsp;of&nbsp;a&nbsp;particular&nbsp;structural&nbsp;and
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
152&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;architectural&nbsp;style.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
153&nbsp;&nbsp;&nbsp;&nbsp;[terrain&nbsp;culture&nbsp;craft&nbsp;gene]
</span><br/>
<span class="partial" title="12 out of 13 forms covered">
154&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[candidates&nbsp;(filter&nbsp;#(and
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
155&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((:terrains&nbsp;%)&nbsp;terrain)
</span><br/>
<span class="covered" title="5 out of 5 forms covered">
156&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((:crafts&nbsp;%)&nbsp;craft)
</span><br/>
<span class="covered" title="4 out of 4 forms covered">
157&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((:cultures&nbsp;%)&nbsp;culture))
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
158&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(vals&nbsp;*building-families*))]
</span><br/>
<span class="covered" title="8 out of 8 forms covered">
159&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(nth&nbsp;candidates&nbsp;(mod&nbsp;(Math&#x2F;abs&nbsp;(.nextInt&nbsp;gene))&nbsp;(count&nbsp;candidates)))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
160&nbsp;&nbsp; 150&nbsp;&nbsp;
</span><br/>
<span class="covered" title="7 out of 7 forms covered">
161&nbsp;&nbsp;(building-family&nbsp;:arable&nbsp;:coastal&nbsp;:baker&nbsp;(MersenneTwister.&nbsp;5))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
162&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
163&nbsp;&nbsp;(defn&nbsp;build!&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
164&nbsp;&nbsp;&nbsp;&nbsp;&quot;Builds&nbsp;a&nbsp;building,&nbsp;and&nbsp;returns&nbsp;a&nbsp;data&nbsp;structure&nbsp;which&nbsp;represents&nbsp;it.&nbsp;In&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
165&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;building&nbsp;the&nbsp;building,&nbsp;it&nbsp;adds&nbsp;a&nbsp;model&nbsp;of&nbsp;the&nbsp;building&nbsp;to&nbsp;the&nbsp;representation
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
166&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;the&nbsp;world,&nbsp;so&nbsp;it&nbsp;does&nbsp;have&nbsp;a&nbsp;side&nbsp;effect.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
167&nbsp;&nbsp;&nbsp;&nbsp;[holding&nbsp;terrain&nbsp;culture&nbsp;craft&nbsp;size]
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
168&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;(satisfies?&nbsp;ProtoHolding&nbsp;holding)
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
169&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[location&nbsp;(.building-origin&nbsp;holding)
</span><br/>
<span class="not-covered" title="0 out of 7 forms covered">
170&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gene&nbsp;(MersenneTwister.&nbsp;(int&nbsp;(+&nbsp;(*&nbsp;(.easting&nbsp;location)&nbsp;1000000)&nbsp;(.northing&nbsp;location))))
</span><br/>
<span class="not-covered" title="0 out of 6 forms covered">
171&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;family&nbsp;(building-family&nbsp;terrain&nbsp;culture&nbsp;craft&nbsp;gene)]
</span><br/>
<span class="not-covered" title="0 out of 3 forms covered">
172&nbsp;&nbsp;&nbsp;&nbsp;(if&nbsp;
</span><br/>
<span class="not-covered" title="0 out of 11 forms covered">
173&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;(instance?&nbsp;ProtoLocation&nbsp;location)&nbsp;(:orientation&nbsp;location))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
174&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:stuff
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
175&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:nonsense
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
176&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
177&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:froboz))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
178&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
179&nbsp;&nbsp;;;&nbsp;(def&nbsp;ol&nbsp;(cc.journeyman.the-great-game.location.location&#x2F;OrientedLocation.&nbsp;123.45&nbsp;543.76&nbsp;12.34&nbsp;0.00&nbsp;{}))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
180&nbsp;&nbsp;
</span><br/> </span><br/>
</body> </body>
</html> </html>

View file

@ -139,11 +139,5 @@
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
045&nbsp;&nbsp; 045&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered">
046&nbsp;&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
047&nbsp;&nbsp;;;&nbsp;(OrientedLocation.&nbsp;123.45&nbsp;543.76&nbsp;12.34&nbsp;0.00&nbsp;{})
</span><br/>
</body> </body>
</html> </html>

View file

@ -37,22 +37,22 @@
<span class="covered" title="1 out of 1 forms covered"> <span class="covered" title="1 out of 1 forms covered">
011&nbsp;&nbsp;(defn&nbsp;init&nbsp;[] 011&nbsp;&nbsp;(defn&nbsp;init&nbsp;[]
</span><br/> </span><br/>
<span class="covered" title="9 out of 9 forms covered"> <span class="not-covered" title="0 out of 9 forms covered">
012&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[cube&nbsp;(geo&nbsp;&quot;jMonkey&nbsp;cube&quot;&nbsp;(box&nbsp;1&nbsp;1&nbsp;1)) 012&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[cube&nbsp;(geo&nbsp;&quot;jMonkey&nbsp;cube&quot;&nbsp;(box&nbsp;1&nbsp;1&nbsp;1))
</span><br/> </span><br/>
<span class="covered" title="2 out of 2 forms covered"> <span class="not-covered" title="0 out of 2 forms covered">
013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mat&nbsp;&nbsp;(unshaded-mat)] 013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mat&nbsp;&nbsp;(unshaded-mat)]
</span><br/> </span><br/>
<span class="covered" title="11 out of 11 forms covered"> <span class="not-covered" title="0 out of 11 forms covered">
014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;mat&nbsp;:texture&nbsp;&quot;ColorMap&quot;&nbsp;(load-texture&nbsp;&quot;textures&#x2F;Monkey.jpg&quot;)) 014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;mat&nbsp;:texture&nbsp;&quot;ColorMap&quot;&nbsp;(load-texture&nbsp;&quot;textures&#x2F;Monkey.jpg&quot;))
</span><br/> </span><br/>
<span class="covered" title="8 out of 8 forms covered"> <span class="not-covered" title="0 out of 8 forms covered">
015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;cube&nbsp;:material&nbsp;mat) 015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;cube&nbsp;:material&nbsp;mat)
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add-to-root&nbsp;cube) 016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add-to-root&nbsp;cube)
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-covered" title="0 out of 3 forms covered">
017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:cube&nbsp;cube})) 017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{:cube&nbsp;cube}))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
@ -88,7 +88,7 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
028&nbsp;&nbsp;;;&nbsp;We&nbsp;define&nbsp;the&nbsp;`app`&nbsp;var. 028&nbsp;&nbsp;;;&nbsp;We&nbsp;define&nbsp;the&nbsp;`app`&nbsp;var.
</span><br/> </span><br/>
<span class="partial" title="170 out of 215 forms covered"> <span class="partial" title="115 out of 215 forms covered">
029&nbsp;&nbsp;(defsimpleapp&nbsp;app 029&nbsp;&nbsp;(defsimpleapp&nbsp;app
</span><br/> </span><br/>
<span class="partial" title="36 out of 42 forms covered"> <span class="partial" title="36 out of 42 forms covered">
@ -112,17 +112,17 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:height&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;600}} 036&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:height&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;600}}
</span><br/> </span><br/>
<span class="partial" title="1 out of 2 forms covered"> <span class="not-covered" title="0 out of 2 forms covered">
037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:init&nbsp;init 037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:init&nbsp;init
</span><br/> </span><br/>
<span class="partial" title="1 out of 2 forms covered"> <span class="not-covered" title="0 out of 2 forms covered">
038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:update&nbsp;simple-update) 038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:update&nbsp;simple-update)
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
039&nbsp;&nbsp; 039&nbsp;&nbsp;
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
040&nbsp;&nbsp;(start&nbsp;app) 040&nbsp;&nbsp;;;&nbsp;(start&nbsp;app)
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
041&nbsp;&nbsp; 041&nbsp;&nbsp;
@ -145,11 +145,11 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
047&nbsp;&nbsp;&nbsp;;;&nbsp;Let&#x27;s&nbsp;increase&nbsp;its&nbsp;movement&nbsp;speed.&nbsp;Now,&nbsp;you&nbsp;fly&nbsp;faster&nbsp;:) 047&nbsp;&nbsp;&nbsp;;;&nbsp;Let&#x27;s&nbsp;increase&nbsp;its&nbsp;movement&nbsp;speed.&nbsp;Now,&nbsp;you&nbsp;fly&nbsp;faster&nbsp;:)
</span><br/> </span><br/>
<span class="covered" title="16 out of 16 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
048&nbsp;&nbsp;&nbsp;(run&nbsp;app 048&nbsp;&nbsp;&nbsp;;;&nbsp;(run&nbsp;app
</span><br/> </span><br/>
<span class="covered" title="9 out of 9 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
049&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;(fly-cam)&nbsp;:move-speed&nbsp;15)) 049&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;(fly-cam)&nbsp;:move-speed&nbsp;15))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
050&nbsp;&nbsp; 050&nbsp;&nbsp;
@ -160,14 +160,14 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
052&nbsp;&nbsp;&nbsp;;;&nbsp;Updates&nbsp;the&nbsp;app&nbsp; 052&nbsp;&nbsp;&nbsp;;;&nbsp;Updates&nbsp;the&nbsp;app&nbsp;
</span><br/> </span><br/>
<span class="covered" title="16 out of 16 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
053&nbsp;&nbsp;(run&nbsp;app 053&nbsp;&nbsp;;;&nbsp;(run&nbsp;app
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
054&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[{:keys&nbsp;[cube]}&nbsp;(get-state)] 054&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[{:keys&nbsp;[cube]}&nbsp;(get-state)]
</span><br/> </span><br/>
<span class="covered" title="13 out of 13 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
055&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;cube&nbsp;:local-translation&nbsp;(add&nbsp;(get*&nbsp;cube&nbsp;:local-translation)&nbsp;1&nbsp;1&nbsp;1)))) 055&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;cube&nbsp;:local-translation&nbsp;(add&nbsp;(get*&nbsp;cube&nbsp;:local-translation)&nbsp;1&nbsp;1&nbsp;1))))
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered"> <span class="blank" title="0 out of 0 forms covered">
056&nbsp;&nbsp; 056&nbsp;&nbsp;
@ -175,32 +175,32 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;Updates&nbsp;the&nbsp;app&nbsp;adding&nbsp;a&nbsp;second&nbsp;cube 057&nbsp;&nbsp;&nbsp;&nbsp;;;&nbsp;Updates&nbsp;the&nbsp;app&nbsp;adding&nbsp;a&nbsp;second&nbsp;cube
</span><br/> </span><br/>
<span class="covered" title="16 out of 16 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
058&nbsp;&nbsp;(run&nbsp;app 058&nbsp;&nbsp;;;&nbsp;(run&nbsp;app
</span><br/>
<span class="covered" title="9 out of 9 forms covered">
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[cube&nbsp;(geo&nbsp;&quot;jMonkey&nbsp;cube&quot;&nbsp;(box&nbsp;1&nbsp;1&nbsp;1))
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mat&nbsp;&nbsp;(unshaded-mat)]
</span><br/>
<span class="covered" title="11 out of 11 forms covered">
061&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;mat&nbsp;:texture&nbsp;&quot;ColorMap&quot;&nbsp;(load-texture&nbsp;&quot;textures&#x2F;Monkey.jpg&quot;))
</span><br/>
<span class="covered" title="22 out of 22 forms covered">
062&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(setc&nbsp;cube
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
063&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:material&nbsp;mat
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
064&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:local-translation&nbsp;[-3&nbsp;0&nbsp;0]) 059&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[cube&nbsp;(geo&nbsp;&quot;jMonkey&nbsp;cube&quot;&nbsp;(box&nbsp;1&nbsp;1&nbsp;1))
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
065&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add-to-root&nbsp;cube) 060&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mat&nbsp;&nbsp;(unshaded-mat)]
</span><br/> </span><br/>
<span class="covered" title="4 out of 4 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
066&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set-state&nbsp;:cube2&nbsp;cube))) 061&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set*&nbsp;mat&nbsp;:texture&nbsp;&quot;ColorMap&quot;&nbsp;(load-texture&nbsp;&quot;textures&#x2F;Monkey.jpg&quot;))
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
062&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(setc&nbsp;cube
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
063&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:material&nbsp;mat
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
064&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:local-translation&nbsp;[-3&nbsp;0&nbsp;0])
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
065&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(add-to-root&nbsp;cube)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
066&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set-state&nbsp;:cube2&nbsp;cube)))
</span><br/> </span><br/>
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
067&nbsp;&nbsp;&nbsp; 067&nbsp;&nbsp;&nbsp;
@ -208,17 +208,17 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
068&nbsp;&nbsp;&nbsp;;;&nbsp;We&nbsp;added&nbsp;the&nbsp;new&nbsp;cube,&nbsp;but&nbsp;it&#x27;s&nbsp;not&nbsp;rotating.&nbsp;We&nbsp;need&nbsp;to&nbsp;update&nbsp;the&nbsp;simple-update&nbsp;fn. 068&nbsp;&nbsp;&nbsp;;;&nbsp;We&nbsp;added&nbsp;the&nbsp;new&nbsp;cube,&nbsp;but&nbsp;it&#x27;s&nbsp;not&nbsp;rotating.&nbsp;We&nbsp;need&nbsp;to&nbsp;update&nbsp;the&nbsp;simple-update&nbsp;fn.
</span><br/> </span><br/>
<span class="covered" title="1 out of 1 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
069&nbsp;&nbsp;&nbsp;(defn&nbsp;simple-update&nbsp;[tpf] 069&nbsp;&nbsp;&nbsp;;;&nbsp;(defn&nbsp;simple-update&nbsp;[tpf]
</span><br/> </span><br/>
<span class="covered" title="3 out of 3 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;[{:keys&nbsp;[cube&nbsp;cube2]}&nbsp;(get-state)] 070&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;(let&nbsp;[{:keys&nbsp;[cube&nbsp;cube2]}&nbsp;(get-state)]
</span><br/> </span><br/>
<span class="covered" title="8 out of 8 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
071&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(rotate&nbsp;cube&nbsp;0&nbsp;(*&nbsp;2&nbsp;tpf)&nbsp;0) 071&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(rotate&nbsp;cube&nbsp;0&nbsp;(*&nbsp;2&nbsp;tpf)&nbsp;0)
</span><br/> </span><br/>
<span class="covered" title="8 out of 8 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
072&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(rotate&nbsp;cube2&nbsp;0&nbsp;(*&nbsp;2&nbsp;tpf)&nbsp;0))) 072&nbsp;&nbsp;&nbsp;;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(rotate&nbsp;cube2&nbsp;0&nbsp;(*&nbsp;2&nbsp;tpf)&nbsp;0)))
</span><br/> </span><br/>
</body> </body>
</html> </html>

View file

@ -139,5 +139,53 @@
<span class="not-tracked" title="0 out of 0 forms covered"> <span class="not-tracked" title="0 out of 0 forms covered">
045&nbsp;&nbsp;;;&nbsp;(value-or-default&nbsp;nil&nbsp;:altitude&nbsp;8) 045&nbsp;&nbsp;;;&nbsp;(value-or-default&nbsp;nil&nbsp;:altitude&nbsp;8)
</span><br/> </span><br/>
<span class="blank" title="0 out of 0 forms covered">
046&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
047&nbsp;&nbsp;(defn&nbsp;truthy?&nbsp;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
048&nbsp;&nbsp;&nbsp;&nbsp;&quot;Returns&nbsp;`true`&nbsp;unless&nbsp;`val`&nbsp;is&nbsp;`nil`,&nbsp;`false`&nbsp;or&nbsp;an&nbsp;empty&nbsp;sequence.
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
049&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Otherwise&nbsp;always&nbsp;&#x27;false&#x27;;&nbsp;never&nbsp;any&nbsp;other&nbsp;value.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
050&nbsp;&nbsp;&nbsp;&nbsp;[val]
</span><br/>
<span class="covered" title="11 out of 11 forms covered">
051&nbsp;&nbsp;&nbsp;&nbsp;(and&nbsp;(or&nbsp;val&nbsp;false)&nbsp;true))
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
052&nbsp;&nbsp;
</span><br/>
<span class="blank" title="0 out of 0 forms covered">
053&nbsp;&nbsp;
</span><br/>
<span class="covered" title="1 out of 1 forms covered">
054&nbsp;&nbsp;(defn&nbsp;inc-or-one
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
055&nbsp;&nbsp;&nbsp;&nbsp;&quot;If&nbsp;this&nbsp;`val`&nbsp;is&nbsp;a&nbsp;number,&nbsp;return&nbsp;that&nbsp;number&nbsp;incremented&nbsp;by&nbsp;one;&nbsp;otherwise,
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;1.&nbsp;TODO:&nbsp;should&nbsp;probably&nbsp;be&nbsp;in&nbsp;`utils`.&quot;
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
057&nbsp;&nbsp;&nbsp;&nbsp;[val]
</span><br/>
<span class="covered" title="2 out of 2 forms covered">
058&nbsp;&nbsp;&nbsp;&nbsp;(if
</span><br/>
<span class="covered" title="3 out of 3 forms covered">
059&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(number?&nbsp;val)
</span><br/>
<span class="not-covered" title="0 out of 2 forms covered">
060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(inc&nbsp;val)
</span><br/>
<span class="not-tracked" title="0 out of 0 forms covered">
061&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1))
</span><br/>
</body> </body>
</html> </html>

View file

@ -25,6 +25,17 @@
<td class="with-number">100.00 %</td> <td class="with-number">100.00 %</td>
<td class="with-number">45</td><td class="with-number">5</td><td class="with-number">3</td> <td class="with-number">45</td><td class="with-number">5</td><td class="with-number">3</td>
</tr> </tr>
<tr>
<td><a href="cc/journeyman/the_great_game/buildings/module.clj.html">cc.journeyman.the-great-game.buildings.module</a></td><td class="with-bar"><div class="covered"
style="width:100.0%;
float:left;"> 2 </div></td>
<td class="with-number">100.00 %</td>
<td class="with-bar"><div class="covered"
style="width:100.0%;
float:left;"> 2 </div></td>
<td class="with-number">100.00 %</td>
<td class="with-number">81</td><td class="with-number">6</td><td class="with-number">2</td>
</tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/buildings/rectangular.clj.html">cc.journeyman.the-great-game.buildings.rectangular</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/buildings/rectangular.clj.html">cc.journeyman.the-great-game.buildings.rectangular</a></td><td class="with-bar"><div class="covered"
style="width:74.64788732394366%; style="width:74.64788732394366%;
@ -40,7 +51,7 @@
style="width:19.35483870967742%; style="width:19.35483870967742%;
float:left;"> 6 </div></td> float:left;"> 6 </div></td>
<td class="with-number">80.65 %</td> <td class="with-number">80.65 %</td>
<td class="with-number">180</td><td class="with-number">25</td><td class="with-number">31</td> <td class="with-number">150</td><td class="with-number">25</td><td class="with-number">31</td>
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/gossip/gossip.clj.html">cc.journeyman.the-great-game.gossip.gossip</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/gossip/gossip.clj.html">cc.journeyman.the-great-game.gossip.gossip</a></td><td class="with-bar"><div class="covered"
@ -59,20 +70,20 @@
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/gossip/news_items.clj.html">cc.journeyman.the-great-game.gossip.news-items</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/gossip/news_items.clj.html">cc.journeyman.the-great-game.gossip.news-items</a></td><td class="with-bar"><div class="covered"
style="width:68.92744479495268%; style="width:77.15582450832072%;
float:left;"> 437 </div><div class="not-covered" float:left;"> 510 </div><div class="not-covered"
style="width:31.07255520504732%; style="width:22.844175491679273%;
float:left;"> 197 </div></td> float:left;"> 151 </div></td>
<td class="with-number">68.93 %</td> <td class="with-number">77.16 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:63.07692307692308%; style="width:72.66187050359713%;
float:left;"> 82 </div><div class="partial" float:left;"> 101 </div><div class="partial"
style="width:7.6923076923076925%; style="width:5.755395683453237%;
float:left;"> 10 </div><div class="not-covered" float:left;"> 8 </div><div class="not-covered"
style="width:29.23076923076923%; style="width:21.58273381294964%;
float:left;"> 38 </div></td> float:left;"> 30 </div></td>
<td class="with-number">70.77 %</td> <td class="with-number">78.42 %</td>
<td class="with-number">313</td><td class="with-number">36</td><td class="with-number">130</td> <td class="with-number">345</td><td class="with-number">41</td><td class="with-number">139</td>
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/holdings/holding.clj.html">cc.journeyman.the-great-game.holdings.holding</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/holdings/holding.clj.html">cc.journeyman.the-great-game.holdings.holding</a></td><td class="with-bar"><div class="covered"
@ -102,7 +113,7 @@
style="width:71.42857142857143%; style="width:71.42857142857143%;
float:left;"> 10 </div></td> float:left;"> 10 </div></td>
<td class="with-number">28.57 %</td> <td class="with-number">28.57 %</td>
<td class="with-number">47</td><td class="with-number">8</td><td class="with-number">14</td> <td class="with-number">45</td><td class="with-number">7</td><td class="with-number">14</td>
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/merchants/markets.clj.html">cc.journeyman.the-great-game.merchants.markets</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/merchants/markets.clj.html">cc.journeyman.the-great-game.merchants.markets</a></td><td class="with-bar"><div class="covered"
@ -213,20 +224,20 @@
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/playroom.clj.html">cc.journeyman.the-great-game.playroom</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/playroom.clj.html">cc.journeyman.the-great-game.playroom</a></td><td class="with-bar"><div class="covered"
style="width:86.05947955390334%; style="width:56.92307692307692%;
float:left;"> 463 </div><div class="not-covered" float:left;"> 222 </div><div class="not-covered"
style="width:13.940520446096654%; style="width:43.07692307692308%;
float:left;"> 75 </div></td> float:left;"> 168 </div></td>
<td class="with-number">86.06 %</td> <td class="with-number">56.92 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:80.0%; style="width:23.529411764705884%;
float:left;"> 28 </div><div class="partial" float:left;"> 4 </div><div class="partial"
style="width:14.285714285714286%; style="width:17.647058823529413%;
float:left;"> 5 </div><div class="not-covered" float:left;"> 3 </div><div class="not-covered"
style="width:5.714285714285714%; style="width:58.8235294117647%;
float:left;"> 2 </div></td> float:left;"> 10 </div></td>
<td class="with-number">94.29 %</td> <td class="with-number">41.18 %</td>
<td class="with-number">72</td><td class="with-number">12</td><td class="with-number">35</td> <td class="with-number">72</td><td class="with-number">12</td><td class="with-number">17</td>
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/time.clj.html">cc.journeyman.the-great-game.time</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/time.clj.html">cc.journeyman.the-great-game.time</a></td><td class="with-bar"><div class="covered"
@ -247,18 +258,18 @@
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/utils.clj.html">cc.journeyman.the-great-game.utils</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/utils.clj.html">cc.journeyman.the-great-game.utils</a></td><td class="with-bar"><div class="covered"
style="width:84.33734939759036%; style="width:85.4368932038835%;
float:left;"> 70 </div><div class="not-covered" float:left;"> 88 </div><div class="not-covered"
style="width:15.662650602409638%; style="width:14.563106796116505%;
float:left;"> 13 </div></td> float:left;"> 15 </div></td>
<td class="with-number">84.34 %</td> <td class="with-number">85.44 %</td>
<td class="with-bar"><div class="covered" <td class="with-bar"><div class="covered"
style="width:95.23809523809524%; style="width:92.5925925925926%;
float:left;"> 20 </div><div class="not-covered" float:left;"> 25 </div><div class="not-covered"
style="width:4.761904761904762%; style="width:7.407407407407407%;
float:left;"> 1 </div></td> float:left;"> 2 </div></td>
<td class="with-number">95.24 %</td> <td class="with-number">92.59 %</td>
<td class="with-number">45</td><td class="with-number">5</td><td class="with-number">21</td> <td class="with-number">61</td><td class="with-number">8</td><td class="with-number">27</td>
</tr> </tr>
<tr> <tr>
<td><a href="cc/journeyman/the_great_game/world/heightmap.clj.html">cc.journeyman.the-great-game.world.heightmap</a></td><td class="with-bar"><div class="covered" <td><a href="cc/journeyman/the_great_game/world/heightmap.clj.html">cc.journeyman.the-great-game.world.heightmap</a></td><td class="with-bar"><div class="covered"
@ -350,9 +361,9 @@
</tr> </tr>
<tr><td>Totals:</td> <tr><td>Totals:</td>
<td class="with-bar"></td> <td class="with-bar"></td>
<td class="with-number">61.00 %</td> <td class="with-number">58.91 %</td>
<td class="with-bar"></td> <td class="with-bar"></td>
<td class="with-number">61.78 %</td> <td class="with-number">61.63 %</td>
</tr> </tr>
</table> </table>
</body> </body>

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

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

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

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

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

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

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

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

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

File diff suppressed because one or more lines are too long

View file

@ -1,11 +1,18 @@
(defproject journeyman-cc/the-great-game "0.1.2-SNAPSHOT" (defproject journeyman-cc/the-great-game "0.1.2-SNAPSHOT"
:cloverage {:output "docs/cloverage"} :cloverage {:output "docs/cloverage"
:codox {:metadata {:doc "**TODO**: write docs" :codecov? true
:emma-xml? true}
:codox {:froboz.cloverage {:output "docs/cloverage"
:codecov? true
:html? true
:debug? true}
:metadata {:doc "**TODO**: write docs"
:doc/format :markdown} :doc/format :markdown}
:output-path "docs/codox" :output-path "docs/codox"
:source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"} :source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"}
:cucumber-feature-paths ["test/features/"] :cucumber-feature-paths ["test/features/"]
:dependencies [[com.taoensso/timbre "5.1.2"] :dependencies [;;[codox "0.10.7-cloverage"]
[com.taoensso/timbre "5.1.2"]
[environ "1.2.0"] [environ "1.2.0"]
[jme-clj "0.1.13"] [jme-clj "0.1.13"]
;; [jme3-core "3.4.0-stable"] ;; [jme3-core "3.4.0-stable"]
@ -16,12 +23,13 @@
[org.clojure/algo.generic "0.1.3"] [org.clojure/algo.generic "0.1.3"]
[org.clojure/clojure "1.10.3"] [org.clojure/clojure "1.10.3"]
[org.clojure/math.numeric-tower "0.0.4"] [org.clojure/math.numeric-tower "0.0.4"]
] [org.clojure/tools.namespace "1.0.0"]
[org.clojure/tools.reader "1.3.5"]]
:description "Prototype code towards the great game I've been writing about for ten years, and know I will never finish." :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" :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"} :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}
:plugins [[lein-cloverage "1.1.1"] :plugins [[lein-cloverage "1.2.2"]
[lein-codox "0.10.7"] [lein-codox "0.10.7-cloverage"]
[lein-cucumber "1.0.2"] [lein-cucumber "1.0.2"]
[lein-gorilla "0.4.0"]] [lein-gorilla "0.4.0"]]
@ -38,5 +46,4 @@
["change" "version" "leiningen.release/bump-version"] ["change" "version" "leiningen.release/bump-version"]
["vcs" "commit"]] ["vcs" "commit"]]
:url "https://github.com/simon-brooke/the-great-game" :url "https://github.com/simon-brooke/the-great-game")
)

View file

@ -1,6 +1,15 @@
(ns cc.journeyman.the-great-game.gossip.news-items (ns cc.journeyman.the-great-game.gossip.news-items
"Using news items (propositions) to transfer knowledge between gossip agents. "Using news items (propositions) to transfer knowledge between gossip agents.
## Status
What is here is essentially working. It's not, however, working with the
rich data objects which will be needed, and it's not yet nearly efficient
enough, but it allows knowledge to propagate through the world procedurally,
at a rate limited by the speed of movement of the gossip agents.
## Discussion
The ideas here are based on the essay [The spread of knowledge in a large The ideas here are based on the essay [The spread of knowledge in a large
game world](The-spread-of-knowledge-in-a-large-game-world.html), q.v.; game world](The-spread-of-knowledge-in-a-large-game-world.html), q.v.;
they've advanced a little beyond that and will doubtless they've advanced a little beyond that and will doubtless
@ -8,7 +17,7 @@
A news item is a map with the keys: A news item is a map with the keys:
* `date` - the date on which the reported event happened; * `date` - the date on which the reported event is claimed to have happened;
* `nth-hand` - the number of agents the news item has passed through; * `nth-hand` - the number of agents the news item has passed through;
* `verb` - what it is that happened (key into `news-topics`); * `verb` - what it is that happened (key into `news-topics`);
@ -23,9 +32,9 @@
proposition is offered. This is woefully inefficient. " proposition is offered. This is woefully inefficient. "
(:require [cc.journeyman.the-great-game.world.location :refer [distance-between]] (:require [cc.journeyman.the-great-game.world.location :refer [distance-between]]
[cc.journeyman.the-great-game.time :refer [game-time]] [cc.journeyman.the-great-game.time :refer [game-time]]
[cc.journeyman.the-great-game.utils :refer [inc-or-one truthy?]]
[taoensso.timbre :as l])) [taoensso.timbre :as l]))
(def news-topics (def news-topics
"Topics of interest to gossip agents. Topics are keyed in this map by "Topics of interest to gossip agents. Topics are keyed in this map by
their `verbs`. The `keys` associated with each topic are the extra pieces their `verbs`. The `keys` associated with each topic are the extra pieces
@ -40,9 +49,7 @@
action; action;
* `price` is special to buy/sell, but of significant interest to merchants. * `price` is special to buy/sell, but of significant interest to merchants.
## Notes ## Characters
### Characters
*TODO* but note that at most all the receiver can learn about a character *TODO* but note that at most all the receiver can learn about a character
from a news item is what the giver knows about that character, degraded by from a news item is what the giver knows about that character, degraded by
@ -56,7 +63,7 @@
as the receiver stores only that segment which the receiver finds as the receiver stores only that segment which the receiver finds
interesting. interesting.
### Locations ## Locations
A 'location' value is a list comprising at most the x/y coordinate location A 'location' value is a list comprising at most the x/y coordinate location
and the ids of the settlement and region (possibly hierarchically) that contain and the ids of the settlement and region (possibly hierarchically) that contain
@ -66,12 +73,11 @@
It is assumed that the `:home` of a character is a location in this sense. It is assumed that the `:home` of a character is a location in this sense.
### Inferences ## Inferences
If an agent learns that Adam has married Betty, they can infer that Betty has If an agent learns that Adam has married Betty, they can infer that Betty has
married Adam; if they learn that Charles killed Dorothy, that Dorothy has died. married Adam; if they learn that Charles killed Dorothy, that Dorothy has died.
I'm not convinced that my representation of inferences here is ideal. I'm not convinced that my representation of inferences here is ideal."
"
{;; A significant attack is interesting whether or not it leads to deaths {;; A significant attack is interesting whether or not it leads to deaths
:attack {:verb :attack :keys [:actor :other :location]} :attack {:verb :attack :keys [:actor :other :location]}
;; Deaths of characters may be interesting ;; Deaths of characters may be interesting
@ -95,7 +101,7 @@
{:verb :sex} {:verb :sex}
{:verb :sex :actor :other :other :actor}]} {:verb :sex :actor :other :other :actor}]}
;; Merchants, especially, are interested in prices in other markets ;; Merchants, especially, are interested in prices in other markets
:sell {:verb :sell :keys [:actor :other :object :location :price]} :sell {:verb :sell :keys [:actor :other :object :location :quantity :price]}
;; Sex can juicy gossip, although not normally if the participants are in an ;; Sex can juicy gossip, although not normally if the participants are in an
;; established sexual relationship. ;; established sexual relationship.
:sex {:verb :sex :keys [:actor :other :location] :sex {:verb :sex :keys [:actor :other :location]
@ -110,6 +116,11 @@
:inferences [{:verb :war :actor :other :other :actor}]}}) :inferences [{:verb :war :actor :other :other :actor}]}})
(def all-known-verbs
"All verbs currently known to the gossip system."
(set (keys news-topics)))
(defn interest-in-character (defn interest-in-character
"Integer representation of how interesting this `character` is to this "Integer representation of how interesting this `character` is to this
`gossip`. `gossip`.
@ -118,8 +129,11 @@
[gossip character] [gossip character]
(count (count
(concat (concat
(filter #(= (:actor % character)) (:knowledge gossip)) ;; TODO: we ought also check the relationships of the gossip.
(filter #(= (:other % character)) (:knowledge gossip))))) ;; Are relationships just propositions in the knowledge base?
(filter #(= (:actor %) character) (:knowledge gossip))
(filter #(= (:other %) character) (:knowledge gossip)))))
(defn interesting-character? (defn interesting-character?
"Boolean representation of whether this `character` is interesting to this "Boolean representation of whether this `character` is interesting to this
@ -135,10 +149,13 @@
(and (map? location) (number? (:x location)) (number? (:y location))) (and (map? location) (number? (:x location)) (number? (:y location)))
(if-let [home (:home gossip)] (if-let [home (:home gossip)]
(let [d (distance-between location home) (let [d (distance-between location home)
i (/ 10000 d) ;; 10000 at metre scale is 10km; interest should i (if
(zero? d) 1
(/ 10000 d))
;; 10000 at metre scale is 10km; interest should
;;fall off with distance from home, but possibly on a log scale ;;fall off with distance from home, but possibly on a log scale
] ]
(if (> i 1) i 0)) (if (>= i 1) i 0))
0) 0)
(coll? location) (coll? location)
(reduce (reduce
@ -152,6 +169,7 @@
#(some (fn [x] (= x location)) (:location %)) #(some (fn [x] (= x location)) (:location %))
(cons {:location (:home gossip)} (:knowledge gossip)))))) (cons {:location (:home gossip)} (:knowledge gossip))))))
;; (distance-between {:x 25 :y 37} {:x 25 :y 37})
;; (interest-in-location {:home [{0, 0} :test-home] :knowledge []} [:test-home]) ;; (interest-in-location {:home [{0, 0} :test-home] :knowledge []} [:test-home])
(defn interesting-location? (defn interesting-location?
@ -169,6 +187,17 @@
;; TODO: Not yet (really) implemented ;; TODO: Not yet (really) implemented
true) true)
(defn interesting-verb?
"Is this `verb` interesting to this `gossip`?"
[gossip verb]
(let [vs (:interesting-verbs gossip)]
(truthy?
(if (set? vs)
(vs verb)
false))))
;; (interesting-verb? {:interesting-verbs #{:kill :sell}} :sell)
(defn compatible-value? (defn compatible-value?
"True if `known-value` is the same as `new-value`, or, for each key present "True if `known-value` is the same as `new-value`, or, for each key present
in `new-value`, has the same value for that key. in `new-value`, has the same value for that key.
@ -191,16 +220,14 @@
learning that 'someone killed Sweet Daisy', but there is point in learning learning that 'someone killed Sweet Daisy', but there is point in learning
'someone killed Sweet Daisy _with poison_'." 'someone killed Sweet Daisy _with poison_'."
[new-item known-item] [new-item known-item]
(if (truthy?
(reduce (reduce
#(and %1 %2) #(and %1 %2)
(map #(if (map #(if
(known-item %) ;; if known-item has this key (known-item %) ;; if known-item has this key
(compatible-value? (new-item %) (known-item %)) (compatible-value? (new-item %) (known-item %))
true) true)
(remove #{:nth-hand :confidence :learned-from} (keys new-item)))) (remove #{:nth-hand :confidence :learned-from} (keys new-item))))))
true
false))
(defn known-item? (defn known-item?
"True if this news `item` is already known to this `gossip`. "True if this news `item` is already known to this `gossip`.
@ -209,18 +236,17 @@
the same _or more specific_ values for all the keys of this `item` except the same _or more specific_ values for all the keys of this `item` except
`:nth-hand`, `:confidence` and `:learned-from`." `:nth-hand`, `:confidence` and `:learned-from`."
[gossip item] [gossip item]
(if (truthy?
(reduce (reduce
#(or %1 %2) #(or %1 %2)
false false
(filter true? (map #(compatible-item? item %) (:knowledge gossip)))) (filter true? (map #(compatible-item? item %) (:knowledge gossip))))))
true
false))
(defn interesting-item? (defn interesting-item?
"True if anything about this news `item` is interesting to this `gossip`." "True if anything about this news `item` is interesting to this `gossip`."
[gossip item] [gossip item]
(and (not (known-item? gossip item)) (and (not (known-item? gossip item))
(interesting-verb? gossip item) ;; news is only interesting if the topic is.
(or (or
(interesting-character? gossip (:actor item)) (interesting-character? gossip (:actor item))
(interesting-character? gossip (:other item)) (interesting-character? gossip (:other item))
@ -228,15 +254,6 @@
(interesting-object? gossip (:object item)) (interesting-object? gossip (:object item))
(interesting-topic? gossip (:verb item))))) (interesting-topic? gossip (:verb item)))))
(defn inc-or-one
"If this `val` is a number, return that number incremented by one; otherwise,
return 1. TODO: should probably be in `utils`."
[val]
(if
(number? val)
(inc val)
1))
(defn infer (defn infer
"Infer a new knowledge item from this `item`, following this `rule`." "Infer a new knowledge item from this `item`, following this `rule`."
[item rule] [item rule]
@ -281,15 +298,9 @@
location))] location))]
(when-not (empty? l) l))) (when-not (empty? l) l)))
(defn learn-news-item (defn degrade-news-item
"Return a gossip like this `gossip`, which has learned this news `item` if [gossip item]
it is of interest to them." (assoc
([gossip item]
(learn-news-item gossip item true))
([gossip item follow-inferences?]
(if
(interesting-item? gossip item)
(let [item' (assoc
item item
:nth-hand (inc-or-one (:nth-hand item)) :nth-hand (inc-or-one (:nth-hand item))
:time-stamp (if :time-stamp (if
@ -302,7 +313,20 @@
;; TODO: do something to degrade confidence in the item, ;; TODO: do something to degrade confidence in the item,
;; probably as a function of the provider's confidence in ;; probably as a function of the provider's confidence in
;; the item and the gossip's trust in the provider ;; the item and the gossip's trust in the provider
) ))
;; (degrade-news-item {:home [{:x 25 :y 37} :auchencairn :scotland]}
;; {:verb :marry :actor :adam :other :belinda :location [{:x 25 :y 37} :auchencairn :scotland]})
(defn learn-news-item
"Return a gossip like this `gossip`, which has learned this news `item` if
it is of interest to them."
([gossip item]
(learn-news-item gossip item true))
([gossip item follow-inferences?]
(if
(interesting-item? gossip item)
(let [item' (degrade-news-item gossip item)
g (assoc g (assoc
gossip gossip
:knowledge :knowledge
@ -313,7 +337,7 @@
(assoc (assoc
g g
:knowledge :knowledge
(concat (:knowledge g) (make-all-inferences item))) (concat (:knowledge g) (make-all-inferences item')))
g))) g)))
gossip)) gossip))

View file

@ -37,7 +37,7 @@
:init init :init init
:update simple-update) :update simple-update)
(start app) ;; (start app)
;; Reinitialises the running app ;; Reinitialises the running app
;;(run app ;;(run app
@ -45,28 +45,28 @@
;; By default, there is a Fly Camera attached to the app that you can control with W, A, S and D keys. ;; By default, there is a Fly Camera attached to the app that you can control with W, A, S and D keys.
;; Let's increase its movement speed. Now, you fly faster :) ;; Let's increase its movement speed. Now, you fly faster :)
(run app ;; (run app
(set* (fly-cam) :move-speed 15)) ;; (set* (fly-cam) :move-speed 15))
;; Updates the app ;; Updates the app
(run app ;; (run app
(let [{:keys [cube]} (get-state)] ;; (let [{:keys [cube]} (get-state)]
(set* cube :local-translation (add (get* cube :local-translation) 1 1 1)))) ;; (set* cube :local-translation (add (get* cube :local-translation) 1 1 1))))
;; Updates the app adding a second cube ;; Updates the app adding a second cube
(run app ;; (run app
(let [cube (geo "jMonkey cube" (box 1 1 1)) ;; (let [cube (geo "jMonkey cube" (box 1 1 1))
mat (unshaded-mat)] ;; mat (unshaded-mat)]
(set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg")) ;; (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
(setc cube ;; (setc cube
:material mat ;; :material mat
:local-translation [-3 0 0]) ;; :local-translation [-3 0 0])
(add-to-root cube) ;; (add-to-root cube)
(set-state :cube2 cube))) ;; (set-state :cube2 cube)))
;; We added the new cube, but it's not rotating. We need to update the simple-update fn. ;; We added the new cube, but it's not rotating. We need to update the simple-update fn.
(defn simple-update [tpf] ;; (defn simple-update [tpf]
(let [{:keys [cube cube2]} (get-state)] ;; (let [{:keys [cube cube2]} (get-state)]
(rotate cube 0 (* 2 tpf) 0) ;; (rotate cube 0 (* 2 tpf) 0)
(rotate cube2 0 (* 2 tpf) 0))) ;; (rotate cube2 0 (* 2 tpf) 0)))

View file

@ -43,3 +43,19 @@
;; (value-or-default {:x 0 :y 0 :altitude 7} :altitude 8) ;; (value-or-default {:x 0 :y 0 :altitude 7} :altitude 8)
;; (value-or-default {:x 0 :y 0 :altitude 7} :alt 8) ;; (value-or-default {:x 0 :y 0 :altitude 7} :alt 8)
;; (value-or-default nil :altitude 8) ;; (value-or-default nil :altitude 8)
(defn truthy?
"Returns `true` unless `val` is `nil`, `false` or an empty sequence.
Otherwise always 'false'; never any other value."
[val]
(and (or val false) true))
(defn inc-or-one
"If this `val` is a number, return that number incremented by one; otherwise,
return 1. TODO: should probably be in `utils`."
[val]
(if
(number? val)
(inc val)
1))

View file

@ -1,8 +1,49 @@
(ns cc.journeyman.the-great-game.gossip.news-items-test (ns cc.journeyman.the-great-game.gossip.news-items-test
(:require [clojure.test :refer [deftest is testing]] (:require [clojure.test :refer [deftest is testing]]
[cc.journeyman.the-great-game.gossip.news-items :refer [cc.journeyman.the-great-game.gossip.news-items :refer
[compatible-item? degrade-location infer interest-in-location interesting-location? [all-known-verbs compatible-item? degrade-location infer
learn-news-item make-all-inferences]])) interest-in-character interesting-character? interest-in-location
interesting-location? learn-news-item make-all-inferences]]))
(deftest interesting-character-tests
(testing "To what degree characters are of interest to the gossip"
(let [expected 1
gossip {:home [{0, 0} :test-home]
:interesting-verbs all-known-verbs
;; already knows about adam
:knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]}
actual (interest-in-character
gossip
:adam)]
(is (= actual expected)))
(let [expected 0
gossip {:home [{0, 0} :test-home]
:interesting-verbs all-known-verbs
;; already knows about adam
:knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]}
actual (interest-in-character
gossip
:dorothy)]
(is (= actual expected))))
(testing "Whether characters are of interest to the gossip"
(let [expected true
gossip {:home [{0, 0} :test-home]
:interesting-verbs all-known-verbs
;; already knows about adam
:knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]}
actual (interesting-character?
gossip
:adam)]
(is (= actual expected)))
(let [expected false
gossip {:home [{0, 0} :test-home]
:interesting-verbs all-known-verbs
;; already knows about adam
:knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]}
actual (interesting-character?
gossip
:dorothy)]
(is (= actual expected)))))
(deftest compatible-item-test (deftest compatible-item-test
(testing "Compatible item: items are identical" (testing "Compatible item: items are identical"
@ -128,17 +169,17 @@
(deftest inference-tests (deftest inference-tests
(testing "Ability to infer new knowledge from news items: single rule tests" (testing "Ability to infer new knowledge from news items: single rule tests"
(let [expected {:verb :marry, :actor :belinda, :other :adam} (let [expected {:verb :marry, :actor :belinda, :other :adam, :nth-hand 1}
item {:verb :marry :actor :adam :other :belinda} item {:verb :marry :actor :adam :other :belinda}
rule {:verb :marry :actor :other :other :actor} rule {:verb :marry :actor :other :other :actor}
actual (infer item rule)] actual (infer item rule)]
(is (= actual expected))) (is (= actual expected)))
(let [expected {:verb :attack, :actor :adam, :other :belinda} (let [expected {:verb :attack, :actor :adam, :other :belinda, :nth-hand 1}
item {:verb :rape :actor :adam :other :belinda} item {:verb :rape :actor :adam :other :belinda}
rule {:verb :attack} rule {:verb :attack}
actual (infer item rule)] actual (infer item rule)]
(is (= actual expected))) (is (= actual expected)))
(let [expected {:verb :sex, :actor :belinda, :other :adam} (let [expected {:verb :sex, :actor :belinda, :other :adam, :nth-hand 1}
item {:verb :rape :actor :adam :other :belinda} item {:verb :rape :actor :adam :other :belinda}
rule {:verb :sex :actor :other :other :actor} rule {:verb :sex :actor :other :other :actor}
actual (infer item rule)] actual (infer item rule)]
@ -149,15 +190,22 @@
{:verb :attack, :actor :adam, :other :belinda, :location :test-home, :nth-hand 1}} {:verb :attack, :actor :adam, :other :belinda, :location :test-home, :nth-hand 1}}
;; dates will not be and cannot be expected to be equal ;; dates will not be and cannot be expected to be equal
actual (set (make-all-inferences actual (set (make-all-inferences
{:verb :rape :actor :adam :other :belinda :location :test-home :nth-hand 1}))] {:verb :rape :actor :adam :other :belinda :location :test-home}))]
(is (= actual expected))))) (is (= actual expected)))))
(deftest learn-tests (deftest learn-tests
(testing "Learning from an interesting news item." (testing "Learning from an interesting news item."
(let [expected {:home [{0 0} :test-home] (let [expected {:home [{0 0} :test-home]
:knowledge [{:verb :sex, :actor :adam, :other :belinda, :location [:test-home], :nth-hand 1} :interesting-verbs all-known-verbs
:knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}
{:verb :sex, :actor :adam, :other :belinda, :location [:test-home], :nth-hand 1}
{:verb :sex, :actor :belinda, :other :adam, :location [:test-home], :nth-hand 1}]} {:verb :sex, :actor :belinda, :other :adam, :location [:test-home], :nth-hand 1}]}
gossip {:home [{0, 0} :test-home]
:interesting-verbs all-known-verbs
;; already knows about adam
:knowledge [{:verb :sell :actor :adam :other :charles :object :wheat :quantity 10 :price 5 :location [:test-home]}]}
actual (learn-news-item actual (learn-news-item
{:home [{0, 0} :test-home] :knowledge []} gossip
{:verb :sex :actor :adam :other :belinda :location [:test-home]})] {:verb :sex :actor :adam :other :belinda :location [:test-home]})]
(is (= actual expected))))) (is (= actual expected)))))

View file

@ -1,26 +1,31 @@
{ {
"folders": [ "folders": [
{ {
"path": "." "path": "../GreatGameTerrain"
},
{
"path": "../gossip"
}, },
{ {
"path": "../walkmap" "path": "../walkmap"
}, },
{
"path": "../genbuildings"
},
{
"path": "../GreatGameTerrain"
},
{ {
"path": "../jme-clj" "path": "../jme-clj"
}, },
{
"path": "../codox"
},
{
"path": "../cloverage"
},
{ {
"path": "../MicroWorld/mw-engine" "path": "../MicroWorld/mw-engine"
},
{
"path": "."
},
{
"path": "../test-graphs"
} }
], ],
"settings": {} "settings": {
"java.configuration.updateBuildConfiguration": "automatic"
}
} }