Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
42a2792539
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -38,3 +38,15 @@ libopenal64.so
|
|||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
.calva/
|
||||
.lsp/
|
||||
|
||||
|
||||
*.so
|
||||
|
||||
docs/cloverage/codecov.json
|
||||
|
||||
docs/cloverage/coverage.xml
|
||||
|
||||
src/cc/journeyman/the_great_game/cloverage.clj
|
||||
|
|
|
@ -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 (ns cc.journeyman.the-great-game.buildings.module
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
002
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
003 "A module of a building; essentially something like a portacabin, which can be
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
004 assembled together with other modules to make a complete building.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
005
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
006 Modules need to include
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
007
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
008 1. Ground floor modules, having external doors;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
009 2. Craft modules -- workshops -- which will normally be ground floor (except
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
010 weavers) and may have the constraint that no upper floor module can cover them;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
011 3. Upper floor modules, having NO external doors (but linking internal doors);
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
012 4. Roof modules
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
013
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
014 **Role** must be one of:
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
015
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
016 1. `:primary` a ground floor main entrance module
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
017 2. `:secondary` a module which can be upper or ground floor
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
018 3. `:upper` a module which can only be on an upper floor, for example one
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
019 with a projecting gallery, balcony or overhang.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
020
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
021 Other values for `role` will emerge.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
022
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
023 **Exits** must be a sequence of keywords taken from the following list:
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
024
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
025 1. `:left` an exit in the centre of the left wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
026 2. `:left-front` an exit in the centre of the left half of the front wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
027 3. `:front` an exit in the centre of the front wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
028 4. `:right-front` an exit in the centre of the right half of the front wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
029 5. `:right` an exit in the centre of the right wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
030 6. `:right-back` an exit in the centre of the right half of the back wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
031 7. `:left-back` an exit in the centre of the back wall
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
032
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
033 A module placed on an upper floor must have no exit which opens beyond the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
034 footprint of the floor below - no doors into mid air! However, it is allowable
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
035 (and indeed is necessary) to allow doors into roof spaces if the adjacent
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
036 module on the same floor does not yet exist, since otherwise it would be
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
037 impossible to access a new room which might later be built there.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
038
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
039 **Load** must be a small integer indicating both the weight of the module and
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
040 the total amount of weight it can support. So for example a stone-built module
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
041 might have a `load` value of 4, a brick built one of 3, and a half-timbered one
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
042 of 2, and a tent of 0. This means a stone ground floor module could support one
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
043 further floor of stone or brick, or two further floors of half timbered
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
044 construction; while a brick built ground floor could support a single brick or
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
045 half-timbered upper floor but not a stone one, and a half-timbered ground floor
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
046 could only support a half timbered upper floor.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
047
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
048 There also needs to be an undercroft or platform module, such that the area of
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 the top of the platform is identical with the footprint of the building, and
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
050 the altitude of the top of the platform is equal to the altitude of the
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
051 terrain at the heighest corner of the building; so that the actual
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
052 building doesn't float in the air, and also so that none of the doors or windows
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
053 are partly underground.
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
054
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
055 Each module needs to wrap an actual 3d model created in Blender or whatever,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
056 and have a list of optional **textures** with which that model can be rendered.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
057 So an upper floor bedroom module might have the following renders:
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
058
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
059 1. Bare masonry - constrained to upland or plateau terrain, and to coastal culture
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
060 2. Painted masonry - constrained to upland or plateau terrain, and to coastal culture
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
061 3. Half-timbered - not available on plateau terrain
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
062 4. Weatherboarded - constrained to forest terrain
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
063 5. Brick - constrained to arable or arid terrain
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
064
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
065 of course these are only examples, and also, it's entirely possible to have
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
066 for example multiple different weatherboard renders for the same module.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
067 There needs to be a way of rendering what can be built above what: for
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
068 example, you can't have a masonry clad module over a half timbered one,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
069 but you can have a half-timbered one over a masonry one.")
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
070
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
071 (defrecord BuildingModule
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
072 [model
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
073 ^Double length
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
074 ^Double width
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
075 ^Double height
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
076 ^Integer load
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
077 ^clojure.lang.Keyword role
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
078 ^clojure.lang.IPersistentCollection textures
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
079 ^clojure.lang.IPersistentCollection exits
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
080 ]
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
081 )
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
|
@ -355,194 +355,104 @@
|
|||
<span class="blank" title="0 out of 0 forms covered">
|
||||
117
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
118 ;; TODO: So, modules need to contain
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
118
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
119 (defn building-family
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
119 ;;
|
||||
120 "A building family is essentially a collection of models of building modules
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
120 ;; 1. Ground floor modules, having external doors;
|
||||
121 which can be assembled to create buildings of a particular structural and
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
121 ;; 2. Craft modules -- workshops -- which will normally be ground floor (except
|
||||
122 architectural style."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
122 ;; weavers) and may have the constraint that no upper floor module can cover them;
|
||||
123 [terrain culture craft gene]
|
||||
</span><br/>
|
||||
<span class="partial" title="12 out of 13 forms covered">
|
||||
124 (let [candidates (filter #(and
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
125 ((:terrains %) terrain)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
126 ((:crafts %) craft)
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
127 ((:cultures %) culture))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
128 (vals *building-families*))]
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
129 (nth candidates (mod (Math/abs (.nextInt gene)) (count candidates)))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
130
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
131 (building-family :arable :coastal :baker (MersenneTwister. 5))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
132
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
133 (defn build!
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
123 ;; 3. Upper floor modules, having NO external doors (but linking internal doors);
|
||||
134 "Builds a building, and returns a data structure which represents it. In
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
124 ;; 4. Roof modules
|
||||
135 building the building, it adds a model of the building to the representation
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
125 ;;
|
||||
136 of the world, so it does have a side effect."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
126 ;; There also needs to be an undercroft or platform module, such that the area of
|
||||
137 [holding terrain culture craft size]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
138 (if (satisfies? ProtoHolding holding)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
139 (let [location (.building-origin holding)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
140 gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location))))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
141 family (building-family terrain culture craft gene)]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
142 (if
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 11 forms covered">
|
||||
143 (and (instance? ProtoLocation location) (:orientation location))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
127 ;; the top of the platform is identical with the footprint of the building, and
|
||||
144 :stuff
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
128 ;; the altitude of the top of the platform is equal to the altitude of the
|
||||
145 :nonsense
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
129 ;; terrain at the heighest corner of the building; so that the actual
|
||||
146 ))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
130 ;; building doesn't float in the air, and also so that none of the doors or windows
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
131 ;; are partly underground.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
132 ;;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
133 ;; Each module needs to wrap an actual 3d model created in Blender or whatever,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
134 ;; and have a list of optional textures with which that model can be rendered.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
135 ;; So an upper floor bedroom module might have the following renders:
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
136 ;;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
137 ;; 1. Bare masonry - constrained to upland or plateau terrain, and to coastal culture
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
138 ;; 2. Painted masonry - constrained to upland or plateau terrain, and to coastal culture
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
139 ;; 3. Half-timbered - not available on plateau terrain
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
140 ;; 4. Weatherboarded - constrained to forest terrain
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
141 ;; 5. Brick - constrained to arable or arid terrain
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
142 ;;
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
143 ;; of course these are only examples, and also, it's entirely possible to have
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
144 ;; for example multiple different weatherboard renders for the same module.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
145 ;; There needs to be a way of rendering what can be built above what: for
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
146 ;; example, you can't have a masonry clad module over a half timbered one,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
147 ;; but you can have a half-timbered one over a masonry one
|
||||
147 :froboz))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
148
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
149 (defn building-family
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
150 "A building family is essentially a collection of models of building modules
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
151 which can be assembled to create buildings of a particular structural and
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
152 architectural style."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
153 [terrain culture craft gene]
|
||||
</span><br/>
|
||||
<span class="partial" title="12 out of 13 forms covered">
|
||||
154 (let [candidates (filter #(and
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
155 ((:terrains %) terrain)
|
||||
</span><br/>
|
||||
<span class="covered" title="5 out of 5 forms covered">
|
||||
156 ((:crafts %) craft)
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
157 ((:cultures %) culture))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
158 (vals *building-families*))]
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
159 (nth candidates (mod (Math/abs (.nextInt gene)) (count candidates)))))
|
||||
149 ;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {}))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
160
|
||||
</span><br/>
|
||||
<span class="covered" title="7 out of 7 forms covered">
|
||||
161 (building-family :arable :coastal :baker (MersenneTwister. 5))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
162
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
163 (defn build!
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
164 "Builds a building, and returns a data structure which represents it. In
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
165 building the building, it adds a model of the building to the representation
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
166 of the world, so it does have a side effect."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
167 [holding terrain culture craft size]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
168 (if (satisfies? ProtoHolding holding)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
169 (let [location (.building-origin holding)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 7 forms covered">
|
||||
170 gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location))))
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 6 forms covered">
|
||||
171 family (building-family terrain culture craft gene)]
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
172 (if
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 11 forms covered">
|
||||
173 (and (instance? ProtoLocation location) (:orientation location))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
174 :stuff
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
175 :nonsense
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
176 ))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
177 :froboz))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
178
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
179 ;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {}))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
180
|
||||
150
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -139,11 +139,5 @@
|
|||
<span class="blank" title="0 out of 0 forms covered">
|
||||
045
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
046
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
047 ;; (OrientedLocation. 123.45 543.76 12.34 0.00 {})
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -37,22 +37,22 @@
|
|||
<span class="covered" title="1 out of 1 forms covered">
|
||||
011 (defn init []
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
<span class="not-covered" title="0 out of 9 forms covered">
|
||||
012 (let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
013 mat (unshaded-mat)]
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
<span class="not-covered" title="0 out of 11 forms covered">
|
||||
014 (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
<span class="not-covered" title="0 out of 8 forms covered">
|
||||
015 (set* cube :material mat)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
016 (add-to-root cube)
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
<span class="not-covered" title="0 out of 3 forms covered">
|
||||
017 {:cube cube}))
|
||||
</span><br/>
|
||||
<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">
|
||||
028 ;; We define the `app` var.
|
||||
</span><br/>
|
||||
<span class="partial" title="170 out of 215 forms covered">
|
||||
<span class="partial" title="115 out of 215 forms covered">
|
||||
029 (defsimpleapp app
|
||||
</span><br/>
|
||||
<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">
|
||||
036 :height 600}}
|
||||
</span><br/>
|
||||
<span class="partial" title="1 out of 2 forms covered">
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
037 :init init
|
||||
</span><br/>
|
||||
<span class="partial" title="1 out of 2 forms covered">
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
038 :update simple-update)
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
039
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
040 (start app)
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
040 ;; (start app)
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
041
|
||||
|
@ -145,11 +145,11 @@
|
|||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
047 ;; Let's increase its movement speed. Now, you fly faster :)
|
||||
</span><br/>
|
||||
<span class="covered" title="16 out of 16 forms covered">
|
||||
048 (run app
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
048 ;; (run app
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
049 (set* (fly-cam) :move-speed 15))
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 ;; (set* (fly-cam) :move-speed 15))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
050
|
||||
|
@ -160,14 +160,14 @@
|
|||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
052 ;; Updates the app
|
||||
</span><br/>
|
||||
<span class="covered" title="16 out of 16 forms covered">
|
||||
053 (run app
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
053 ;; (run app
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
054 (let [{:keys [cube]} (get-state)]
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
054 ;; (let [{:keys [cube]} (get-state)]
|
||||
</span><br/>
|
||||
<span class="covered" title="13 out of 13 forms covered">
|
||||
055 (set* cube :local-translation (add (get* cube :local-translation) 1 1 1))))
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
055 ;; (set* cube :local-translation (add (get* cube :local-translation) 1 1 1))))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
056
|
||||
|
@ -175,32 +175,32 @@
|
|||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
057 ;; Updates the app adding a second cube
|
||||
</span><br/>
|
||||
<span class="covered" title="16 out of 16 forms covered">
|
||||
058 (run app
|
||||
</span><br/>
|
||||
<span class="covered" title="9 out of 9 forms covered">
|
||||
059 (let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
060 mat (unshaded-mat)]
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
061 (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
|
||||
</span><br/>
|
||||
<span class="covered" title="22 out of 22 forms covered">
|
||||
062 (setc cube
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
063 :material mat
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
058 ;; (run app
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
064 :local-translation [-3 0 0])
|
||||
059 ;; (let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
065 (add-to-root cube)
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
060 ;; mat (unshaded-mat)]
|
||||
</span><br/>
|
||||
<span class="covered" title="4 out of 4 forms covered">
|
||||
066 (set-state :cube2 cube)))
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
061 ;; (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
062 ;; (setc cube
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
063 ;; :material mat
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
064 ;; :local-translation [-3 0 0])
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
065 ;; (add-to-root cube)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
066 ;; (set-state :cube2 cube)))
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
067
|
||||
|
@ -208,17 +208,17 @@
|
|||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
068 ;; We added the new cube, but it's not rotating. We need to update the simple-update fn.
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
069 (defn simple-update [tpf]
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
069 ;; (defn simple-update [tpf]
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
070 (let [{:keys [cube cube2]} (get-state)]
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
070 ;; (let [{:keys [cube cube2]} (get-state)]
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
071 (rotate cube 0 (* 2 tpf) 0)
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
071 ;; (rotate cube 0 (* 2 tpf) 0)
|
||||
</span><br/>
|
||||
<span class="covered" title="8 out of 8 forms covered">
|
||||
072 (rotate cube2 0 (* 2 tpf) 0)))
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
072 ;; (rotate cube2 0 (* 2 tpf) 0)))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -139,5 +139,53 @@
|
|||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
045 ;; (value-or-default nil :altitude 8)
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
046
|
||||
</span><br/>
|
||||
<span class="covered" title="1 out of 1 forms covered">
|
||||
047 (defn truthy?
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
048 "Returns `true` unless `val` is `nil`, `false` or an empty sequence.
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
049 Otherwise always 'false'; never any other value."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
050 [val]
|
||||
</span><br/>
|
||||
<span class="covered" title="11 out of 11 forms covered">
|
||||
051 (and (or val false) true))
|
||||
</span><br/>
|
||||
<span class="blank" title="0 out of 0 forms covered">
|
||||
052
|
||||
</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 inc-or-one
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
055 "If this `val` is a number, return that number incremented by one; otherwise,
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
056 return 1. TODO: should probably be in `utils`."
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
057 [val]
|
||||
</span><br/>
|
||||
<span class="covered" title="2 out of 2 forms covered">
|
||||
058 (if
|
||||
</span><br/>
|
||||
<span class="covered" title="3 out of 3 forms covered">
|
||||
059 (number? val)
|
||||
</span><br/>
|
||||
<span class="not-covered" title="0 out of 2 forms covered">
|
||||
060 (inc val)
|
||||
</span><br/>
|
||||
<span class="not-tracked" title="0 out of 0 forms covered">
|
||||
061 1))
|
||||
</span><br/>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -25,6 +25,17 @@
|
|||
<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>
|
||||
</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>
|
||||
<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%;
|
||||
|
@ -40,7 +51,7 @@
|
|||
style="width:19.35483870967742%;
|
||||
float:left;"> 6 </div></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>
|
||||
<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>
|
||||
<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%;
|
||||
float:left;"> 437 </div><div class="not-covered"
|
||||
style="width:31.07255520504732%;
|
||||
float:left;"> 197 </div></td>
|
||||
<td class="with-number">68.93 %</td>
|
||||
style="width:77.15582450832072%;
|
||||
float:left;"> 510 </div><div class="not-covered"
|
||||
style="width:22.844175491679273%;
|
||||
float:left;"> 151 </div></td>
|
||||
<td class="with-number">77.16 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:63.07692307692308%;
|
||||
float:left;"> 82 </div><div class="partial"
|
||||
style="width:7.6923076923076925%;
|
||||
float:left;"> 10 </div><div class="not-covered"
|
||||
style="width:29.23076923076923%;
|
||||
float:left;"> 38 </div></td>
|
||||
<td class="with-number">70.77 %</td>
|
||||
<td class="with-number">313</td><td class="with-number">36</td><td class="with-number">130</td>
|
||||
style="width:72.66187050359713%;
|
||||
float:left;"> 101 </div><div class="partial"
|
||||
style="width:5.755395683453237%;
|
||||
float:left;"> 8 </div><div class="not-covered"
|
||||
style="width:21.58273381294964%;
|
||||
float:left;"> 30 </div></td>
|
||||
<td class="with-number">78.42 %</td>
|
||||
<td class="with-number">345</td><td class="with-number">41</td><td class="with-number">139</td>
|
||||
</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"
|
||||
|
@ -102,7 +113,7 @@
|
|||
style="width:71.42857142857143%;
|
||||
float:left;"> 10 </div></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>
|
||||
<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>
|
||||
<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%;
|
||||
float:left;"> 463 </div><div class="not-covered"
|
||||
style="width:13.940520446096654%;
|
||||
float:left;"> 75 </div></td>
|
||||
<td class="with-number">86.06 %</td>
|
||||
style="width:56.92307692307692%;
|
||||
float:left;"> 222 </div><div class="not-covered"
|
||||
style="width:43.07692307692308%;
|
||||
float:left;"> 168 </div></td>
|
||||
<td class="with-number">56.92 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:80.0%;
|
||||
float:left;"> 28 </div><div class="partial"
|
||||
style="width:14.285714285714286%;
|
||||
float:left;"> 5 </div><div class="not-covered"
|
||||
style="width:5.714285714285714%;
|
||||
float:left;"> 2 </div></td>
|
||||
<td class="with-number">94.29 %</td>
|
||||
<td class="with-number">72</td><td class="with-number">12</td><td class="with-number">35</td>
|
||||
style="width:23.529411764705884%;
|
||||
float:left;"> 4 </div><div class="partial"
|
||||
style="width:17.647058823529413%;
|
||||
float:left;"> 3 </div><div class="not-covered"
|
||||
style="width:58.8235294117647%;
|
||||
float:left;"> 10 </div></td>
|
||||
<td class="with-number">41.18 %</td>
|
||||
<td class="with-number">72</td><td class="with-number">12</td><td class="with-number">17</td>
|
||||
</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"
|
||||
|
@ -247,18 +258,18 @@
|
|||
</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"
|
||||
style="width:84.33734939759036%;
|
||||
float:left;"> 70 </div><div class="not-covered"
|
||||
style="width:15.662650602409638%;
|
||||
float:left;"> 13 </div></td>
|
||||
<td class="with-number">84.34 %</td>
|
||||
style="width:85.4368932038835%;
|
||||
float:left;"> 88 </div><div class="not-covered"
|
||||
style="width:14.563106796116505%;
|
||||
float:left;"> 15 </div></td>
|
||||
<td class="with-number">85.44 %</td>
|
||||
<td class="with-bar"><div class="covered"
|
||||
style="width:95.23809523809524%;
|
||||
float:left;"> 20 </div><div class="not-covered"
|
||||
style="width:4.761904761904762%;
|
||||
float:left;"> 1 </div></td>
|
||||
<td class="with-number">95.24 %</td>
|
||||
<td class="with-number">45</td><td class="with-number">5</td><td class="with-number">21</td>
|
||||
style="width:92.5925925925926%;
|
||||
float:left;"> 25 </div><div class="not-covered"
|
||||
style="width:7.407407407407407%;
|
||||
float:left;"> 2 </div></td>
|
||||
<td class="with-number">92.59 %</td>
|
||||
<td class="with-number">61</td><td class="with-number">8</td><td class="with-number">27</td>
|
||||
</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"
|
||||
|
@ -350,9 +361,9 @@
|
|||
</tr>
|
||||
<tr><td>Totals:</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-number">61.78 %</td>
|
||||
<td class="with-number">61.63 %</td>
|
||||
</tr>
|
||||
</table>
|
||||
</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
23
project.clj
23
project.clj
|
@ -1,11 +1,18 @@
|
|||
(defproject journeyman-cc/the-great-game "0.1.2-SNAPSHOT"
|
||||
:cloverage {:output "docs/cloverage"}
|
||||
:codox {:metadata {:doc "**TODO**: write docs"
|
||||
:cloverage {:output "docs/cloverage"
|
||||
: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}
|
||||
:output-path "docs/codox"
|
||||
:source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"}
|
||||
: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"]
|
||||
[jme-clj "0.1.13"]
|
||||
;; [jme3-core "3.4.0-stable"]
|
||||
|
@ -16,12 +23,13 @@
|
|||
[org.clojure/algo.generic "0.1.3"]
|
||||
[org.clojure/clojure "1.10.3"]
|
||||
[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."
|
||||
: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-cloverage "1.1.1"]
|
||||
[lein-codox "0.10.7"]
|
||||
:plugins [[lein-cloverage "1.2.2"]
|
||||
[lein-codox "0.10.7-cloverage"]
|
||||
[lein-cucumber "1.0.2"]
|
||||
[lein-gorilla "0.4.0"]]
|
||||
|
||||
|
@ -38,5 +46,4 @@
|
|||
["change" "version" "leiningen.release/bump-version"]
|
||||
["vcs" "commit"]]
|
||||
|
||||
:url "https://github.com/simon-brooke/the-great-game"
|
||||
)
|
||||
:url "https://github.com/simon-brooke/the-great-game")
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
(ns cc.journeyman.the-great-game.gossip.news-items
|
||||
"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
|
||||
game world](The-spread-of-knowledge-in-a-large-game-world.html), q.v.;
|
||||
they've advanced a little beyond that and will doubtless
|
||||
|
@ -8,7 +17,7 @@
|
|||
|
||||
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;
|
||||
* `verb` - what it is that happened (key into `news-topics`);
|
||||
|
||||
|
@ -23,9 +32,9 @@
|
|||
proposition is offered. This is woefully inefficient. "
|
||||
(: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.utils :refer [inc-or-one truthy?]]
|
||||
[taoensso.timbre :as l]))
|
||||
|
||||
|
||||
(def news-topics
|
||||
"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
|
||||
|
@ -40,9 +49,7 @@
|
|||
action;
|
||||
* `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
|
||||
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
|
||||
interesting.
|
||||
|
||||
### Locations
|
||||
## Locations
|
||||
|
||||
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
|
||||
|
@ -66,12 +73,11 @@
|
|||
|
||||
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
|
||||
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
|
||||
:attack {:verb :attack :keys [:actor :other :location]}
|
||||
;; Deaths of characters may be interesting
|
||||
|
@ -95,7 +101,7 @@
|
|||
{:verb :sex}
|
||||
{:verb :sex :actor :other :other :actor}]}
|
||||
;; 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
|
||||
;; established sexual relationship.
|
||||
:sex {:verb :sex :keys [:actor :other :location]
|
||||
|
@ -110,6 +116,11 @@
|
|||
: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
|
||||
"Integer representation of how interesting this `character` is to this
|
||||
`gossip`.
|
||||
|
@ -118,8 +129,11 @@
|
|||
[gossip character]
|
||||
(count
|
||||
(concat
|
||||
(filter #(= (:actor % character)) (:knowledge gossip))
|
||||
(filter #(= (:other % character)) (:knowledge gossip)))))
|
||||
;; TODO: we ought also check the relationships of the gossip.
|
||||
;; Are relationships just propositions in the knowledge base?
|
||||
(filter #(= (:actor %) character) (:knowledge gossip))
|
||||
(filter #(= (:other %) character) (:knowledge gossip)))))
|
||||
|
||||
|
||||
(defn interesting-character?
|
||||
"Boolean representation of whether this `character` is interesting to this
|
||||
|
@ -135,10 +149,13 @@
|
|||
(and (map? location) (number? (:x location)) (number? (:y location)))
|
||||
(if-let [home (:home gossip)]
|
||||
(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
|
||||
]
|
||||
(if (> i 1) i 0))
|
||||
(if (>= i 1) i 0))
|
||||
0)
|
||||
(coll? location)
|
||||
(reduce
|
||||
|
@ -152,6 +169,7 @@
|
|||
#(some (fn [x] (= x location)) (:location %))
|
||||
(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])
|
||||
|
||||
(defn interesting-location?
|
||||
|
@ -169,6 +187,17 @@
|
|||
;; TODO: Not yet (really) implemented
|
||||
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?
|
||||
"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.
|
||||
|
@ -191,16 +220,14 @@
|
|||
learning that 'someone killed Sweet Daisy', but there is point in learning
|
||||
'someone killed Sweet Daisy _with poison_'."
|
||||
[new-item known-item]
|
||||
(if
|
||||
(truthy?
|
||||
(reduce
|
||||
#(and %1 %2)
|
||||
(map #(if
|
||||
(known-item %) ;; if known-item has this key
|
||||
(compatible-value? (new-item %) (known-item %))
|
||||
true)
|
||||
(remove #{:nth-hand :confidence :learned-from} (keys new-item))))
|
||||
true
|
||||
false))
|
||||
(remove #{:nth-hand :confidence :learned-from} (keys new-item))))))
|
||||
|
||||
(defn known-item?
|
||||
"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
|
||||
`:nth-hand`, `:confidence` and `:learned-from`."
|
||||
[gossip item]
|
||||
(if
|
||||
(truthy?
|
||||
(reduce
|
||||
#(or %1 %2)
|
||||
false
|
||||
(filter true? (map #(compatible-item? item %) (:knowledge gossip))))
|
||||
true
|
||||
false))
|
||||
(filter true? (map #(compatible-item? item %) (:knowledge gossip))))))
|
||||
|
||||
(defn interesting-item?
|
||||
"True if anything about this news `item` is interesting to this `gossip`."
|
||||
[gossip item]
|
||||
(and (not (known-item? gossip item))
|
||||
(interesting-verb? gossip item) ;; news is only interesting if the topic is.
|
||||
(or
|
||||
(interesting-character? gossip (:actor item))
|
||||
(interesting-character? gossip (:other item))
|
||||
|
@ -228,15 +254,6 @@
|
|||
(interesting-object? gossip (:object 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
|
||||
"Infer a new knowledge item from this `item`, following this `rule`."
|
||||
[item rule]
|
||||
|
@ -281,15 +298,9 @@
|
|||
location))]
|
||||
(when-not (empty? l) l)))
|
||||
|
||||
(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' (assoc
|
||||
(defn degrade-news-item
|
||||
[gossip item]
|
||||
(assoc
|
||||
item
|
||||
:nth-hand (inc-or-one (:nth-hand item))
|
||||
:time-stamp (if
|
||||
|
@ -302,7 +313,20 @@
|
|||
;; TODO: do something to degrade confidence in the item,
|
||||
;; probably as a function of the provider's confidence in
|
||||
;; 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
|
||||
gossip
|
||||
:knowledge
|
||||
|
@ -313,7 +337,7 @@
|
|||
(assoc
|
||||
g
|
||||
:knowledge
|
||||
(concat (:knowledge g) (make-all-inferences item)))
|
||||
(concat (:knowledge g) (make-all-inferences item')))
|
||||
g)))
|
||||
gossip))
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
:init init
|
||||
:update simple-update)
|
||||
|
||||
(start app)
|
||||
;; (start app)
|
||||
|
||||
;; Reinitialises the running 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.
|
||||
;; Let's increase its movement speed. Now, you fly faster :)
|
||||
(run app
|
||||
(set* (fly-cam) :move-speed 15))
|
||||
;; (run app
|
||||
;; (set* (fly-cam) :move-speed 15))
|
||||
|
||||
|
||||
;; Updates the app
|
||||
(run app
|
||||
(let [{:keys [cube]} (get-state)]
|
||||
(set* cube :local-translation (add (get* cube :local-translation) 1 1 1))))
|
||||
;; (run app
|
||||
;; (let [{:keys [cube]} (get-state)]
|
||||
;; (set* cube :local-translation (add (get* cube :local-translation) 1 1 1))))
|
||||
|
||||
;; Updates the app adding a second cube
|
||||
(run app
|
||||
(let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
mat (unshaded-mat)]
|
||||
(set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
|
||||
(setc cube
|
||||
:material mat
|
||||
:local-translation [-3 0 0])
|
||||
(add-to-root cube)
|
||||
(set-state :cube2 cube)))
|
||||
;; (run app
|
||||
;; (let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
;; mat (unshaded-mat)]
|
||||
;; (set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
|
||||
;; (setc cube
|
||||
;; :material mat
|
||||
;; :local-translation [-3 0 0])
|
||||
;; (add-to-root cube)
|
||||
;; (set-state :cube2 cube)))
|
||||
|
||||
;; We added the new cube, but it's not rotating. We need to update the simple-update fn.
|
||||
(defn simple-update [tpf]
|
||||
(let [{:keys [cube cube2]} (get-state)]
|
||||
(rotate cube 0 (* 2 tpf) 0)
|
||||
(rotate cube2 0 (* 2 tpf) 0)))
|
||||
;; (defn simple-update [tpf]
|
||||
;; (let [{:keys [cube cube2]} (get-state)]
|
||||
;; (rotate cube 0 (* 2 tpf) 0)
|
||||
;; (rotate cube2 0 (* 2 tpf) 0)))
|
||||
|
|
|
@ -43,3 +43,19 @@
|
|||
;; (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 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))
|
||||
|
|
|
@ -1,8 +1,49 @@
|
|||
(ns cc.journeyman.the-great-game.gossip.news-items-test
|
||||
(:require [clojure.test :refer [deftest is testing]]
|
||||
[cc.journeyman.the-great-game.gossip.news-items :refer
|
||||
[compatible-item? degrade-location infer interest-in-location interesting-location?
|
||||
learn-news-item make-all-inferences]]))
|
||||
[all-known-verbs compatible-item? degrade-location infer
|
||||
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
|
||||
(testing "Compatible item: items are identical"
|
||||
|
@ -128,17 +169,17 @@
|
|||
|
||||
(deftest inference-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}
|
||||
rule {:verb :marry :actor :other :other :actor}
|
||||
actual (infer item rule)]
|
||||
(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}
|
||||
rule {:verb :attack}
|
||||
actual (infer item rule)]
|
||||
(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}
|
||||
rule {:verb :sex :actor :other :other :actor}
|
||||
actual (infer item rule)]
|
||||
|
@ -149,15 +190,22 @@
|
|||
{:verb :attack, :actor :adam, :other :belinda, :location :test-home, :nth-hand 1}}
|
||||
;; dates will not be and cannot be expected to be equal
|
||||
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)))))
|
||||
|
||||
(deftest learn-tests
|
||||
(testing "Learning from an interesting news item."
|
||||
(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}]}
|
||||
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
|
||||
{:home [{0, 0} :test-home] :knowledge []}
|
||||
gossip
|
||||
{:verb :sex :actor :adam :other :belinda :location [:test-home]})]
|
||||
(is (= actual expected)))))
|
||||
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../gossip"
|
||||
"path": "../GreatGameTerrain"
|
||||
},
|
||||
{
|
||||
"path": "../walkmap"
|
||||
},
|
||||
{
|
||||
"path": "../genbuildings"
|
||||
},
|
||||
{
|
||||
"path": "../GreatGameTerrain"
|
||||
},
|
||||
{
|
||||
"path": "../jme-clj"
|
||||
},
|
||||
{
|
||||
"path": "../codox"
|
||||
},
|
||||
{
|
||||
"path": "../cloverage"
|
||||
},
|
||||
{
|
||||
"path": "../MicroWorld/mw-engine"
|
||||
},
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../test-graphs"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
"settings": {
|
||||
"java.configuration.updateBuildConfiguration": "automatic"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue